[IMP] accounting v9. Yeeeeaah
@@ -21,18 +21,17 @@
|
||||
|
||||
import partner
|
||||
import account
|
||||
import installer
|
||||
import account_payment
|
||||
import account_invoice
|
||||
import account_bank_statement
|
||||
import account_bank
|
||||
import account_cash_statement
|
||||
import account_move_line
|
||||
import account_move
|
||||
import chart_template
|
||||
import account_analytic_line
|
||||
import account_financial_report
|
||||
import wizard
|
||||
import report
|
||||
import account_journal_dashboard
|
||||
import product
|
||||
import company
|
||||
import res_currency
|
||||
import edi
|
||||
import res_config
|
||||
|
||||
import wizard
|
||||
import report
|
||||
|
||||
@@ -19,140 +19,64 @@
|
||||
#
|
||||
##############################################################################
|
||||
{
|
||||
'name' : 'eInvoicing',
|
||||
'name' : 'Invoicing',
|
||||
'version' : '1.1',
|
||||
'author' : 'OpenERP SA',
|
||||
'category' : 'Accounting & Finance',
|
||||
'description' : """
|
||||
Accounting and Financial Management.
|
||||
====================================
|
||||
'summary': 'Send Invoices and Track Payments',
|
||||
'sequence': 4,
|
||||
'description': """
|
||||
Invoicing & Payments
|
||||
====================
|
||||
The specific and easy-to-use Invoicing system in Odoo allows you to keep track of your accounting, even when you are not an accountant. It provides an easy way to follow up on your suppliers and customers.
|
||||
|
||||
Financial and accounting module that covers:
|
||||
--------------------------------------------
|
||||
* General Accounting
|
||||
* Cost/Analytic accounting
|
||||
* Third party accounting
|
||||
* Taxes management
|
||||
* Budgets
|
||||
* Customer and Supplier Invoices
|
||||
* Bank statements
|
||||
* Reconciliation process by partner
|
||||
|
||||
Creates a dashboard for accountants that includes:
|
||||
--------------------------------------------------
|
||||
* List of Customer Invoices to Approve
|
||||
* Company Analysis
|
||||
* Graph of Treasury
|
||||
|
||||
Processes like maintaining general ledgers are done through the defined Financial Journals (entry move line or grouping is maintained through a journal)
|
||||
for a particular financial year and for preparation of vouchers there is a module named account_voucher.
|
||||
You could use this simplified accounting in case you work with an (external) account to keep your books, and you still want to keep track of payments. This module also offers you an easy method of registering payments, without having to encode complete abstracts of account.
|
||||
""",
|
||||
'category' : 'Accounting & Finance',
|
||||
'website': 'https://www.odoo.com/page/billing',
|
||||
'depends': ['base_setup', 'product', 'analytic', 'board', 'edi', 'report', 'web_tip'],
|
||||
'images' : ['images/accounts.jpeg','images/bank_statement.jpeg','images/cash_register.jpeg','images/chart_of_accounts.jpeg','images/customer_invoice.jpeg','images/journal_entries.jpeg'],
|
||||
'depends' : ['base_setup', 'product', 'analytic', 'board', 'report', 'web_tip'],
|
||||
'data': [
|
||||
'security/account_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'account_menuitem.xml',
|
||||
'report/account_invoice_report_view.xml',
|
||||
'report/account_entries_report_view.xml',
|
||||
'report/account_treasury_report_view.xml',
|
||||
'report/account_report_view.xml',
|
||||
'report/account_analytic_entries_report_view.xml',
|
||||
'wizard/account_move_bank_reconcile_view.xml',
|
||||
'wizard/account_use_model_view.xml',
|
||||
'account_installer.xml',
|
||||
'wizard/account_period_close_view.xml',
|
||||
'data/data_account_type.xml',
|
||||
'data/account_data.xml',
|
||||
'views/account_menuitem.xml',
|
||||
'views/account_payment_view.xml',
|
||||
'wizard/account_reconcile_view.xml',
|
||||
'wizard/account_unreconcile_view.xml',
|
||||
'wizard/account_statement_from_invoice_view.xml',
|
||||
'account_view.xml',
|
||||
'account_report.xml',
|
||||
'account_financial_report_data.xml',
|
||||
'wizard/account_report_common_view.xml',
|
||||
'views/account_view.xml',
|
||||
'views/account_report.xml',
|
||||
'wizard/account_invoice_refund_view.xml',
|
||||
'wizard/account_fiscalyear_close_state.xml',
|
||||
'wizard/account_chart_view.xml',
|
||||
'wizard/account_tax_chart_view.xml',
|
||||
'wizard/account_move_line_reconcile_select_view.xml',
|
||||
'wizard/account_open_closed_fiscalyear_view.xml',
|
||||
'wizard/account_move_line_unreconcile_select_view.xml',
|
||||
'wizard/account_vat_view.xml',
|
||||
'wizard/account_report_print_journal_view.xml',
|
||||
'wizard/account_report_general_journal_view.xml',
|
||||
'wizard/account_report_central_journal_view.xml',
|
||||
'wizard/account_subscription_generate_view.xml',
|
||||
'wizard/account_fiscalyear_close_view.xml',
|
||||
'wizard/account_state_open_view.xml',
|
||||
'wizard/account_journal_select_view.xml',
|
||||
'wizard/account_change_currency_view.xml',
|
||||
'wizard/account_move_reversal_view.xml',
|
||||
'wizard/account_validate_move_view.xml',
|
||||
'wizard/account_report_general_ledger_view.xml',
|
||||
'wizard/account_invoice_state_view.xml',
|
||||
'wizard/account_report_partner_balance_view.xml',
|
||||
'wizard/account_report_account_balance_view.xml',
|
||||
'wizard/account_report_aged_partner_balance_view.xml',
|
||||
'wizard/account_report_partner_ledger_view.xml',
|
||||
'wizard/account_reconcile_partner_process_view.xml',
|
||||
'wizard/account_automatic_reconcile_view.xml',
|
||||
'wizard/account_financial_report_view.xml',
|
||||
'wizard/account_log_followup_note_view.xml',
|
||||
'wizard/pos_box.xml',
|
||||
'account_end_fy.xml',
|
||||
'account_invoice_view.xml',
|
||||
'data/account_data.xml',
|
||||
'data/data_account_type.xml',
|
||||
'data/configurable_account_chart.xml',
|
||||
'account_invoice_workflow.xml',
|
||||
'partner_view.xml',
|
||||
'product_view.xml',
|
||||
'account_assert_test.xml',
|
||||
'account_analytic_view.xml',
|
||||
'company_view.xml',
|
||||
'edi/invoice_action_data.xml',
|
||||
'account_bank_view.xml',
|
||||
'res_config_view.xml',
|
||||
'account_tip_data.xml',
|
||||
'account_pre_install.yml',
|
||||
'views/report_vat.xml',
|
||||
'views/report_invoice.xml',
|
||||
'views/report_trialbalance.xml',
|
||||
'views/report_centraljournal.xml',
|
||||
'views/report_overdue.xml',
|
||||
'views/report_generaljournal.xml',
|
||||
'views/report_journal.xml',
|
||||
'views/report_salepurchasejournal.xml',
|
||||
'views/report_partnerbalance.xml',
|
||||
'views/report_agedpartnerbalance.xml',
|
||||
'views/report_partnerledger.xml',
|
||||
'views/report_partnerledgerother.xml',
|
||||
'views/report_financial.xml',
|
||||
'views/report_generalledger.xml',
|
||||
'views/account_end_fy.xml',
|
||||
'views/account_invoice_view.xml',
|
||||
'data/invoice_action_data.xml',
|
||||
'views/account_invoice_workflow.xml',
|
||||
'views/partner_view.xml',
|
||||
'views/product_view.xml',
|
||||
'views/account_analytic_view.xml',
|
||||
'views/company_view.xml',
|
||||
'views/account_bank_view.xml',
|
||||
'views/res_config_view.xml',
|
||||
'views/account_tip_data.xml',
|
||||
'views/account.xml',
|
||||
],
|
||||
'qweb' : [
|
||||
"static/src/xml/account_move_reconciliation.xml",
|
||||
"static/src/xml/account_move_line_quickadd.xml",
|
||||
"static/src/xml/account_bank_statement_reconciliation.xml",
|
||||
'views/report_invoice.xml',
|
||||
'report/account_invoice_report_view.xml',
|
||||
'views/account_journal_dashboard_view.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo/account_demo.xml',
|
||||
'demo/account_minimal.xml',
|
||||
'demo/account_invoice_demo.xml',
|
||||
'demo/account_bank_statement.xml',
|
||||
'account_unit_test.xml',
|
||||
],
|
||||
'test': [
|
||||
'test/account_test_users.yml',
|
||||
'test/account_customer_invoice.yml',
|
||||
'test/account_supplier_invoice.yml',
|
||||
'test/account_change_currency.yml',
|
||||
'test/chart_of_account.yml',
|
||||
'test/account_period_close.yml',
|
||||
'test/account_use_model.yml',
|
||||
'test/account_validate_account_move.yml',
|
||||
'test/test_edi_invoice.yml',
|
||||
'test/account_report.yml',
|
||||
'test/account_fiscalyear_close.yml', #last test, as it will definitively close the demo fiscalyear
|
||||
'qweb': [
|
||||
"static/src/xml/account_reconciliation.xml",
|
||||
"static/src/xml/account_payment.xml",
|
||||
"static/src/xml/account_report_backend.xml",
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
|
||||
@@ -1,80 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp import api, fields, models, _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class account_analytic_line(osv.osv):
|
||||
|
||||
class AccountAnalyticLine(models.Model):
|
||||
_inherit = 'account.analytic.line'
|
||||
_description = 'Analytic Line'
|
||||
_columns = {
|
||||
'product_uom_id': fields.many2one('product.uom', 'Unit of Measure'),
|
||||
'product_id': fields.many2one('product.product', 'Product'),
|
||||
'general_account_id': fields.many2one('account.account', 'Financial Account', required=True, ondelete='restrict'),
|
||||
'move_id': fields.many2one('account.move.line', 'Move Line', ondelete='cascade', select=True),
|
||||
'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal', required=True, ondelete='restrict', select=True),
|
||||
'code': fields.char('Code', size=8),
|
||||
'ref': fields.char('Ref.'),
|
||||
'currency_id': fields.related('move_id', 'currency_id', type='many2one', relation='res.currency', string='Account Currency', store=True, help="The related account currency if not equal to the company one.", readonly=True),
|
||||
'amount_currency': fields.related('move_id', 'amount_currency', type='float', string='Amount Currency', store=True, help="The amount expressed in the related account currency if not equal to the company one.", readonly=True),
|
||||
'partner_id': fields.related('account_id', 'partner_id', type='many2one', relation='res.partner', string='Partner', store=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=c),
|
||||
}
|
||||
_order = 'date desc'
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
if context is None:
|
||||
context = {}
|
||||
if context.get('from_date',False):
|
||||
args.append(['date', '>=', context['from_date']])
|
||||
if context.get('to_date',False):
|
||||
args.append(['date','<=', context['to_date']])
|
||||
return super(account_analytic_line, self).search(cr, uid, args, offset, limit,
|
||||
order, context=context, count=count)
|
||||
|
||||
def _check_company(self, cr, uid, ids, context=None):
|
||||
lines = self.browse(cr, uid, ids, context=context)
|
||||
for l in lines:
|
||||
if l.move_id and not l.account_id.company_id.id == l.move_id.account_id.company_id.id:
|
||||
return False
|
||||
return True
|
||||
product_uom_id = fields.Many2one('product.uom', string='Unit of Measure')
|
||||
product_id = fields.Many2one('product.product', string='Product')
|
||||
general_account_id = fields.Many2one('account.account', string='Financial Account', required=True, ondelete='restrict', domain=[('deprecated', '=', False)])
|
||||
move_id = fields.Many2one('account.move.line', string='Move Line', ondelete='cascade', index=True)
|
||||
journal_id = fields.Many2one('account.analytic.journal', string='Analytic Journal', required=True, ondelete='restrict', index=True)
|
||||
code = fields.Char(size=8)
|
||||
ref = fields.Char(string='Ref.')
|
||||
currency_id = fields.Many2one('res.currency', related='move_id.currency_id', string='Account Currency', store=True, help="The related account currency if not equal to the company one.", readonly=True)
|
||||
amount_currency = fields.Monetary(related='move_id.amount_currency', store=True, help="The amount expressed in the related account currency if not equal to the company one.", readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', related='account_id.partner_id', string='Partner', store=True)
|
||||
|
||||
# Compute the cost based on the price type define into company
|
||||
# property_valuation_price_type property
|
||||
@api.v7
|
||||
def on_change_unit_amount(self, cr, uid, id, prod_id, quantity, company_id,
|
||||
unit=False, journal_id=False, context=None):
|
||||
if context==None:
|
||||
context={}
|
||||
if context is None:
|
||||
context = {}
|
||||
if not journal_id:
|
||||
j_ids = self.pool.get('account.analytic.journal').search(cr, uid, [('type','=','purchase')])
|
||||
j_ids = self.pool.get('account.analytic.journal').search(cr, uid, [('type', '=', 'purchase')])
|
||||
journal_id = j_ids and j_ids[0] or False
|
||||
if not journal_id or not prod_id:
|
||||
return {}
|
||||
product_obj = self.pool.get('product.product')
|
||||
analytic_journal_obj =self.pool.get('account.analytic.journal')
|
||||
analytic_journal_obj = self.pool.get('account.analytic.journal')
|
||||
product_price_type_obj = self.pool.get('product.price.type')
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
j_id = analytic_journal_obj.browse(cr, uid, journal_id, context=context)
|
||||
@@ -94,8 +53,7 @@ class account_analytic_line(osv.osv):
|
||||
if not a:
|
||||
a = prod.categ_id.property_account_expense_categ.id
|
||||
if not a:
|
||||
raise UserError(
|
||||
_('There is no expense account defined ' \
|
||||
raise UserError(_('There is no expense account defined ' \
|
||||
'for this product: "%s" (id:%d).') % \
|
||||
(prod.name, prod.id,))
|
||||
else:
|
||||
@@ -103,19 +61,18 @@ class account_analytic_line(osv.osv):
|
||||
if not a:
|
||||
a = prod.categ_id.property_account_income_categ.id
|
||||
if not a:
|
||||
raise UserError(
|
||||
_('There is no income account defined ' \
|
||||
raise UserError(_('There is no income account defined ' \
|
||||
'for this product: "%s" (id:%d).') % \
|
||||
(prod.name, prod_id,))
|
||||
|
||||
flag = False
|
||||
# Compute based on pricetype
|
||||
product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','standard_price')], context=context)
|
||||
product_price_type_ids = product_price_type_obj.search(cr, uid, [('field', '=', 'standard_price')], context=context)
|
||||
pricetype = product_price_type_obj.browse(cr, uid, product_price_type_ids, context=context)[0]
|
||||
if journal_id:
|
||||
journal = analytic_journal_obj.browse(cr, uid, journal_id, context=context)
|
||||
if journal.type == 'sale':
|
||||
product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','list_price')], context=context)
|
||||
product_price_type_ids = product_price_type_obj.search(cr, uid, [('field', '=', 'list_price')], context=context)
|
||||
if product_price_type_ids:
|
||||
pricetype = product_price_type_obj.browse(cr, uid, product_price_type_ids, context=context)[0]
|
||||
# Take the company currency as the reference one
|
||||
@@ -127,9 +84,10 @@ class account_analytic_line(osv.osv):
|
||||
# to return a default price for those units
|
||||
ctx['uom'] = unit
|
||||
amount_unit = prod.price_get(pricetype.field, context=ctx)[prod.id]
|
||||
prec = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
|
||||
amount = amount_unit * quantity or 0.0
|
||||
result = round(amount, prec)
|
||||
cur_record = self.browse(cr, uid, id, context=context)
|
||||
currency = cur_record.exists() and cur_record.currency_id or prod.company_id.currency_id
|
||||
result = round(amount, currency.decimal_places)
|
||||
if not flag:
|
||||
result *= -1
|
||||
return {'value': {
|
||||
@@ -139,24 +97,63 @@ class account_analytic_line(osv.osv):
|
||||
}
|
||||
}
|
||||
|
||||
def view_header_get(self, cr, user, view_id, view_type, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
@api.v8
|
||||
@api.onchange('product_id', 'product_uom_id')
|
||||
def on_change_unit_amount(self):
|
||||
product_price_type_obj = self.env['product.price.type']
|
||||
|
||||
journal_id = self.journal_id
|
||||
if not journal_id:
|
||||
journal_id = self.env['account.analytic.journal'].search([('type', '=', 'purchase')], limit=1)
|
||||
if not journal_id or not self.product_id:
|
||||
return {}
|
||||
|
||||
result = 0.0
|
||||
if self.product_id:
|
||||
unit = self.product_uom_id.id
|
||||
if not self.product_uom_id or self.product_id.uom_id.category_id.id != self.product_uom_id.category_id.id:
|
||||
unit = self.product_id.uom_id.id
|
||||
if journal_id.type == 'purchase':
|
||||
if not self.product_uom_id or self.product_id.uom_po_id.category_id.id != self.product_uom_id.category_id.id:
|
||||
unit = self.product_id.uom_po_id.id
|
||||
if journal_id.type != 'sale':
|
||||
account = self.product_id.property_account_expense.id or self.product_id.categ_id.property_account_expense_categ.id
|
||||
if not account:
|
||||
raise UserError(_('There is no expense account defined ' \
|
||||
'for this product: "%s" (id:%d).') % \
|
||||
(self.product_id.name, self.product_id.id,))
|
||||
else:
|
||||
account = self.product_id.property_account_income.id or self.product_id.categ_id.property_account_income_categ.id
|
||||
if not account:
|
||||
raise UserError(_('There is no income account defined ' \
|
||||
'for this product: "%s" (id:%d).') % \
|
||||
(self.product_id.name, self.product_id.id,))
|
||||
|
||||
# Compute based on pricetype
|
||||
if journal_id.type == 'sale':
|
||||
pricetype = product_price_type_obj.search([('field', '=', 'list_price')], limit=1)
|
||||
else:
|
||||
pricetype = product_price_type_obj.search([('field', '=', 'standard_price')], limit=1)
|
||||
|
||||
ctx = dict(self._context or {})
|
||||
if unit:
|
||||
# price_get() will respect a 'uom' in its context, in order
|
||||
# to return a default price for those units
|
||||
ctx['uom'] = unit
|
||||
amount_unit = self.product_id.with_context(ctx).price_get(pricetype.field)[self.product_id.id]
|
||||
amount = amount_unit * self.unit_amount or 0.0
|
||||
result = round(amount, self.currency_id.decimal_places)
|
||||
if pricetype.field != 'list_price':
|
||||
result *= -1
|
||||
self.amount = result
|
||||
self.general_account_id = account
|
||||
self.product_uom_id = unit
|
||||
|
||||
@api.model
|
||||
def view_header_get(self, view_id, view_type):
|
||||
context = (self._context or {})
|
||||
header = False
|
||||
if context.get('account_id', False):
|
||||
# account_id in context may also be pointing to an account.account.id
|
||||
cr.execute('select name from account_analytic_account where id=%s', (context['account_id'],))
|
||||
res = cr.fetchone()
|
||||
if res:
|
||||
res = _('Entries: ')+ (res[0] or '')
|
||||
return res
|
||||
return False
|
||||
|
||||
|
||||
class res_partner(osv.osv):
|
||||
""" Inherits partner and adds contract information in the partner form """
|
||||
_inherit = 'res.partner'
|
||||
|
||||
_columns = {
|
||||
'contract_ids': fields.one2many('account.analytic.account', \
|
||||
'partner_id', 'Contracts', readonly=True),
|
||||
}
|
||||
analytic_account = self.env['account.analytic.account'].search([('id', '=', context['account_id'])], limit=1)
|
||||
header = _('Entries: ') + (analytic_account.name or '')
|
||||
return header
|
||||
@@ -1,99 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import fields, osv
|
||||
from openerp import api, fields, models, _
|
||||
|
||||
class bank(osv.osv):
|
||||
|
||||
class Bank(models.Model):
|
||||
_inherit = "res.partner.bank"
|
||||
_columns = {
|
||||
'journal_id': fields.many2one('account.journal', 'Account Journal', help="This journal will be created automatically for this bank account when you save the record"),
|
||||
'currency_id': fields.related('journal_id', 'currency', type="many2one", relation='res.currency', readonly=True,
|
||||
string="Currency", help="Currency of the related account journal."),
|
||||
}
|
||||
def create(self, cr, uid, data, context=None):
|
||||
result = super(bank, self).create(cr, uid, data, context=context)
|
||||
self.post_write(cr, uid, [result], context=context)
|
||||
|
||||
journal_id = fields.Many2one('account.journal', string='Account Journal',
|
||||
help="This journal will be created automatically for this bank account when you save the record")
|
||||
currency_id = fields.Many2one('res.currency', related='journal_id.currency_id', string='Currency',
|
||||
readonly=True, help="Currency of the related account journal.")
|
||||
|
||||
@api.model
|
||||
def create(self, data):
|
||||
result = super(Bank, self).create(data)
|
||||
result.post_write()
|
||||
return result
|
||||
|
||||
def write(self, cr, uid, ids, data, context=None):
|
||||
result = super(bank, self).write(cr, uid, ids, data, context=context)
|
||||
self.post_write(cr, uid, ids, context=context)
|
||||
@api.multi
|
||||
def write(self, data):
|
||||
result = super(Bank, self).write(data)
|
||||
self.post_write()
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def _prepare_name(self, bank):
|
||||
"Return the name to use when creating a bank journal"
|
||||
return (bank.bank_name or '') + ' ' + (bank.acc_number or '')
|
||||
|
||||
def _prepare_name_get(self, cr, uid, bank_dicts, context=None):
|
||||
@api.model
|
||||
def _prepare_name_get(self, bank_dicts):
|
||||
"""Add ability to have %(currency_name)s in the format_layout of res.partner.bank.type"""
|
||||
currency_ids = list(set(data['currency_id'][0] for data in bank_dicts if data.get('currency_id')))
|
||||
currencies = self.pool.get('res.currency').browse(cr, uid, currency_ids, context=context)
|
||||
currencies = self.env['res.currency'].browse(currency_ids)
|
||||
currency_name = dict((currency.id, currency.name) for currency in currencies)
|
||||
|
||||
for data in bank_dicts:
|
||||
data['currency_name'] = data.get('currency_id') and currency_name[data['currency_id'][0]] or ''
|
||||
return super(bank, self)._prepare_name_get(cr, uid, bank_dicts, context=context)
|
||||
return super(Bank, self)._prepare_name_get(bank_dicts)
|
||||
|
||||
def post_write(self, cr, uid, ids, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@api.multi
|
||||
def post_write(self):
|
||||
AccountObj = self.env['account.account']
|
||||
JournalObj = self.env['account.journal']
|
||||
|
||||
obj_acc = self.pool.get('account.account')
|
||||
obj_data = self.pool.get('ir.model.data')
|
||||
|
||||
for bank in self.browse(cr, uid, ids, context):
|
||||
if bank.company_id and not bank.journal_id:
|
||||
for bank in self:
|
||||
# Create a journal for the bank account if it belongs to the company.
|
||||
if bank.partner_id in self.env.user.company_ids.mapped('partner_id') and not bank.journal_id:
|
||||
# TODO: this code is duplicated; refactor using _prepare_bank_account() in chart_template.py
|
||||
# Find the code and parent of the bank account to create
|
||||
dig = 6
|
||||
current_num = 1
|
||||
ids = obj_acc.search(cr, uid, [('type','=','liquidity'), ('company_id', '=', bank.company_id.id), ('parent_id', '!=', False)], context=context)
|
||||
account = AccountObj.search([('internal_type', '=', 'liquidity'), ('company_id', '=', bank.company_id.id)], limit=1)
|
||||
# No liquidity account exists, no template available
|
||||
if not ids: continue
|
||||
if not account: continue
|
||||
|
||||
ref_acc_bank = obj_acc.browse(cr, uid, ids[0], context=context).parent_id
|
||||
ref_acc_bank = account
|
||||
while True:
|
||||
new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)), '0')) + str(current_num)
|
||||
ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', bank.company_id.id)])
|
||||
if not ids:
|
||||
account = AccountObj.search([('code', '=', new_code), ('company_id', '=', bank.company_id.id)], limit=1)
|
||||
if not account:
|
||||
break
|
||||
current_num += 1
|
||||
name = self._prepare_name(bank)
|
||||
acc = {
|
||||
'name': name,
|
||||
'code': new_code,
|
||||
'type': 'liquidity',
|
||||
'user_type': ref_acc_bank.user_type.id,
|
||||
'reconcile': False,
|
||||
'parent_id': ref_acc_bank.id,
|
||||
'company_id': bank.company_id.id,
|
||||
}
|
||||
acc_bank_id = obj_acc.create(cr,uid,acc,context=context)
|
||||
acc_bank = AccountObj.create(acc)
|
||||
|
||||
jour_obj = self.pool.get('account.journal')
|
||||
new_code = 1
|
||||
while True:
|
||||
code = _('BNK')+str(new_code)
|
||||
ids = jour_obj.search(cr, uid, [('code','=',code)], context=context)
|
||||
if not ids:
|
||||
account = JournalObj.search([('code', '=', code)], limit=1)
|
||||
if not account:
|
||||
break
|
||||
new_code += 1
|
||||
|
||||
@@ -104,10 +87,9 @@ class bank(osv.osv):
|
||||
'type': 'bank',
|
||||
'company_id': bank.company_id.id,
|
||||
'analytic_journal_id': False,
|
||||
'default_credit_account_id': acc_bank_id,
|
||||
'default_debit_account_id': acc_bank_id,
|
||||
'default_credit_account_id': acc_bank.id,
|
||||
'default_debit_account_id': acc_bank.id,
|
||||
}
|
||||
journal_id = jour_obj.create(cr, uid, vals_journal, context=context)
|
||||
|
||||
self.write(cr, uid, [bank.id], {'journal_id': journal_id}, context=context)
|
||||
bank.journal_id = JournalObj.create(vals_journal)
|
||||
return True
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
# encoding: utf-8
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 PC Solutions (<http://pcsol.be>). All Rights Reserved
|
||||
# $Id$
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import float_compare
|
||||
from openerp.tools.translate import _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.exceptions import UserError, AccessError
|
||||
|
||||
class account_cashbox_line(osv.osv):
|
||||
|
||||
""" Cash Box Details """
|
||||
|
||||
_name = 'account.cashbox.line'
|
||||
_description = 'CashBox Line'
|
||||
_rec_name = 'pieces'
|
||||
|
||||
def _sub_total(self, cr, uid, ids, name, arg, context=None):
|
||||
|
||||
""" Calculates Sub total
|
||||
@param name: Names of fields.
|
||||
@param arg: User defined arguments
|
||||
@return: Dictionary of values.
|
||||
"""
|
||||
res = {}
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
res[obj.id] = {
|
||||
'subtotal_opening' : obj.pieces * obj.number_opening,
|
||||
'subtotal_closing' : obj.pieces * obj.number_closing,
|
||||
}
|
||||
return res
|
||||
|
||||
def on_change_sub_opening(self, cr, uid, ids, pieces, number, *a):
|
||||
""" Compute the subtotal for the opening """
|
||||
return {'value' : {'subtotal_opening' : (pieces * number) or 0.0 }}
|
||||
|
||||
def on_change_sub_closing(self, cr, uid, ids, pieces, number, *a):
|
||||
""" Compute the subtotal for the closing """
|
||||
return {'value' : {'subtotal_closing' : (pieces * number) or 0.0 }}
|
||||
|
||||
_columns = {
|
||||
'pieces': fields.float('Unit of Currency', digits_compute=dp.get_precision('Account')),
|
||||
'number_opening' : fields.integer('Number of Units', help='Opening Unit Numbers'),
|
||||
'number_closing' : fields.integer('Number of Units', help='Closing Unit Numbers'),
|
||||
'subtotal_opening': fields.function(_sub_total, string='Opening Subtotal', type='float', digits_compute=dp.get_precision('Account'), multi='subtotal'),
|
||||
'subtotal_closing': fields.function(_sub_total, string='Closing Subtotal', type='float', digits_compute=dp.get_precision('Account'), multi='subtotal'),
|
||||
'bank_statement_id' : fields.many2one('account.bank.statement', string="Bank Statements", ondelete='cascade'),
|
||||
}
|
||||
|
||||
|
||||
class account_cash_statement(osv.osv):
|
||||
|
||||
_inherit = 'account.bank.statement'
|
||||
|
||||
def _update_balances(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Set starting and ending balances according to pieces count
|
||||
"""
|
||||
res = {}
|
||||
for statement in self.browse(cr, uid, ids, context=context):
|
||||
if (statement.journal_id.type not in ('cash',)):
|
||||
continue
|
||||
if not statement.journal_id.cash_control:
|
||||
prec = self.pool['decimal.precision'].precision_get(cr, uid, 'Account')
|
||||
if float_compare(statement.balance_end_real, statement.balance_end, precision_digits=prec):
|
||||
statement.write({'balance_end_real' : statement.balance_end})
|
||||
continue
|
||||
start = end = 0
|
||||
for line in statement.details_ids:
|
||||
start += line.subtotal_opening
|
||||
end += line.subtotal_closing
|
||||
data = {
|
||||
'balance_start': start,
|
||||
'balance_end_real': end,
|
||||
}
|
||||
res[statement.id] = data
|
||||
super(account_cash_statement, self).write(cr, uid, [statement.id], data, context=context)
|
||||
return res
|
||||
|
||||
def _get_sum_entry_encoding(self, cr, uid, ids, name, arg, context=None):
|
||||
|
||||
""" Find encoding total of statements "
|
||||
@param name: Names of fields.
|
||||
@param arg: User defined arguments
|
||||
@return: Dictionary of values.
|
||||
"""
|
||||
res = {}
|
||||
for statement in self.browse(cr, uid, ids, context=context):
|
||||
res[statement.id] = sum((line.amount for line in statement.line_ids), 0.0)
|
||||
return res
|
||||
|
||||
def _get_company(self, cr, uid, context=None):
|
||||
user_pool = self.pool.get('res.users')
|
||||
company_pool = self.pool.get('res.company')
|
||||
user = user_pool.browse(cr, uid, uid, context=context)
|
||||
company_id = user.company_id
|
||||
if not company_id:
|
||||
company_id = company_pool.search(cr, uid, [])
|
||||
return company_id and company_id[0] or False
|
||||
|
||||
def _get_statement_from_line(self, cr, uid, ids, context=None):
|
||||
result = {}
|
||||
for line in self.pool.get('account.bank.statement.line').browse(cr, uid, ids, context=context):
|
||||
result[line.statement_id.id] = True
|
||||
return result.keys()
|
||||
|
||||
def _compute_difference(self, cr, uid, ids, fieldnames, args, context=None):
|
||||
result = dict.fromkeys(ids, 0.0)
|
||||
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
result[obj.id] = obj.balance_end_real - obj.balance_end
|
||||
|
||||
return result
|
||||
|
||||
def _compute_last_closing_balance(self, cr, uid, ids, fieldnames, args, context=None):
|
||||
result = dict.fromkeys(ids, 0.0)
|
||||
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.state == 'draft':
|
||||
statement_ids = self.search(cr, uid,
|
||||
[('journal_id', '=', obj.journal_id.id),('state', '=', 'confirm')],
|
||||
order='create_date desc',
|
||||
limit=1,
|
||||
context=context
|
||||
)
|
||||
|
||||
if not statement_ids:
|
||||
continue
|
||||
else:
|
||||
st = self.browse(cr, uid, statement_ids[0], context=context)
|
||||
result[obj.id] = st.balance_end_real
|
||||
|
||||
return result
|
||||
|
||||
def onchange_journal_id(self, cr, uid, ids, journal_id, context=None):
|
||||
result = super(account_cash_statement, self).onchange_journal_id(cr, uid, ids, journal_id)
|
||||
|
||||
if not journal_id:
|
||||
return result
|
||||
|
||||
statement_ids = self.search(cr, uid,
|
||||
[('journal_id', '=', journal_id),('state', '=', 'confirm')],
|
||||
order='create_date desc',
|
||||
limit=1,
|
||||
context=context
|
||||
)
|
||||
|
||||
opening_details_ids = self._get_cash_open_box_lines(cr, uid, journal_id, context)
|
||||
if opening_details_ids:
|
||||
result['value']['opening_details_ids'] = opening_details_ids
|
||||
|
||||
if not statement_ids:
|
||||
return result
|
||||
|
||||
st = self.browse(cr, uid, statement_ids[0], context=context)
|
||||
result.setdefault('value', {}).update({'last_closing_balance' : st.balance_end_real})
|
||||
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'total_entry_encoding': fields.function(_get_sum_entry_encoding, string="Total Transactions",
|
||||
store = {
|
||||
'account.bank.statement': (lambda self, cr, uid, ids, context=None: ids, ['line_ids','move_line_ids'], 10),
|
||||
'account.bank.statement.line': (_get_statement_from_line, ['amount'], 10),
|
||||
},
|
||||
help="Total of cash transaction lines."),
|
||||
'closing_date': fields.datetime("Closed On"),
|
||||
'details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='CashBox Lines', copy=True),
|
||||
'opening_details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='Opening Cashbox Lines'),
|
||||
'closing_details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='Closing Cashbox Lines'),
|
||||
'user_id': fields.many2one('res.users', 'Responsible', required=False),
|
||||
'difference' : fields.function(_compute_difference, method=True, string="Difference", type="float", help="Difference between the theoretical closing balance and the real closing balance."),
|
||||
'last_closing_balance' : fields.function(_compute_last_closing_balance, method=True, string='Last Closing Balance', type='float'),
|
||||
}
|
||||
_defaults = {
|
||||
'state': 'draft',
|
||||
'date': lambda self, cr, uid, context={}: context.get('date', time.strftime("%Y-%m-%d %H:%M:%S")),
|
||||
'user_id': lambda self, cr, uid, context=None: uid,
|
||||
}
|
||||
|
||||
def _get_cash_open_box_lines(self, cr, uid, journal_id, context):
|
||||
details_ids = []
|
||||
if not journal_id:
|
||||
return details_ids
|
||||
journal = self.pool.get('account.journal').browse(cr, uid, journal_id, context=context)
|
||||
if journal and (journal.type == 'cash'):
|
||||
last_pieces = None
|
||||
|
||||
if journal.with_last_closing_balance == True:
|
||||
domain = [('journal_id', '=', journal.id),
|
||||
('state', '=', 'confirm')]
|
||||
last_bank_statement_ids = self.search(cr, uid, domain, limit=1, order='create_date desc', context=context)
|
||||
if last_bank_statement_ids:
|
||||
last_bank_statement = self.browse(cr, uid, last_bank_statement_ids[0], context=context)
|
||||
|
||||
last_pieces = dict(
|
||||
(line.pieces, line.number_closing) for line in last_bank_statement.details_ids
|
||||
)
|
||||
for value in journal.cashbox_line_ids:
|
||||
nested_values = {
|
||||
'number_closing' : 0,
|
||||
'number_opening' : last_pieces.get(value.pieces, 0) if isinstance(last_pieces, dict) else 0,
|
||||
'pieces' : value.pieces
|
||||
}
|
||||
details_ids.append([0, False, nested_values])
|
||||
return details_ids
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
journal_id = vals.get('journal_id')
|
||||
if journal_id and not vals.get('opening_details_ids'):
|
||||
vals['opening_details_ids'] = vals.get('opening_details_ids') or self._get_cash_open_box_lines(cr, uid, journal_id, context)
|
||||
res_id = super(account_cash_statement, self).create(cr, uid, vals, context=context)
|
||||
self._update_balances(cr, uid, [res_id], context)
|
||||
return res_id
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
"""
|
||||
Update redord(s) comes in {ids}, with new value comes as {vals}
|
||||
return True on success, False otherwise
|
||||
|
||||
@param cr: cursor to database
|
||||
@param user: id of current user
|
||||
@param ids: list of record ids to be update
|
||||
@param vals: dict of new values to be set
|
||||
@param context: context arguments, like lang, time zone
|
||||
|
||||
@return: True on success, False otherwise
|
||||
"""
|
||||
if vals.get('journal_id', False):
|
||||
cashbox_line_obj = self.pool.get('account.cashbox.line')
|
||||
cashbox_ids = cashbox_line_obj.search(cr, uid, [('bank_statement_id', 'in', ids)], context=context)
|
||||
cashbox_line_obj.unlink(cr, uid, cashbox_ids, context)
|
||||
res = super(account_cash_statement, self).write(cr, uid, ids, vals, context=context)
|
||||
self._update_balances(cr, uid, ids, context)
|
||||
return res
|
||||
|
||||
def _user_allow(self, cr, uid, statement_id, context=None):
|
||||
return True
|
||||
|
||||
def button_open(self, cr, uid, ids, context=None):
|
||||
""" Changes statement state to Running.
|
||||
@return: True
|
||||
"""
|
||||
obj_seq = self.pool.get('ir.sequence')
|
||||
if context is None:
|
||||
context = {}
|
||||
statement_pool = self.pool.get('account.bank.statement')
|
||||
for statement in statement_pool.browse(cr, uid, ids, context=context):
|
||||
vals = {}
|
||||
if not self._user_allow(cr, uid, statement.id, context=context):
|
||||
raise AccessError((_('You do not have rights to open this %s journal!') % (statement.journal_id.name, )))
|
||||
|
||||
if statement.name and statement.name == '/':
|
||||
c = {'ir_sequence_date': statement.period_id.date_start}
|
||||
if statement.journal_id.sequence_id:
|
||||
st_number = obj_seq.next_by_id(cr, uid, statement.journal_id.sequence_id.id, context=c)
|
||||
else:
|
||||
st_number = obj_seq.next_by_code(cr, uid, 'account.cash.statement', context=c)
|
||||
vals.update({
|
||||
'name': st_number
|
||||
})
|
||||
|
||||
vals.update({
|
||||
'state': 'open',
|
||||
})
|
||||
self.write(cr, uid, [statement.id], vals, context=context)
|
||||
return True
|
||||
|
||||
def statement_close(self, cr, uid, ids, journal_type='bank', context=None):
|
||||
if journal_type == 'bank':
|
||||
return super(account_cash_statement, self).statement_close(cr, uid, ids, journal_type, context)
|
||||
vals = {
|
||||
'state':'confirm',
|
||||
'closing_date': time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
}
|
||||
return self.write(cr, uid, ids, vals, context=context)
|
||||
|
||||
def check_status_condition(self, cr, uid, state, journal_type='bank'):
|
||||
if journal_type == 'bank':
|
||||
return super(account_cash_statement, self).check_status_condition(cr, uid, state, journal_type)
|
||||
return state=='open'
|
||||
|
||||
def button_confirm_cash(self, cr, uid, ids, context=None):
|
||||
absl_proxy = self.pool.get('account.bank.statement.line')
|
||||
|
||||
TABLES = ((_('Profit'), 'profit_account_id'), (_('Loss'), 'loss_account_id'),)
|
||||
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.difference == 0.0:
|
||||
continue
|
||||
elif obj.difference < 0.0:
|
||||
account = obj.journal_id.loss_account_id
|
||||
name = _('Loss')
|
||||
if not obj.journal_id.loss_account_id:
|
||||
raise UserError(_('There is no Loss Account on the journal %s.') % (obj.journal_id.name,))
|
||||
else: # obj.difference > 0.0
|
||||
account = obj.journal_id.profit_account_id
|
||||
name = _('Profit')
|
||||
if not obj.journal_id.profit_account_id:
|
||||
raise UserError(_('There is no Profit Account on the journal %s.') % (obj.journal_id.name,))
|
||||
|
||||
values = {
|
||||
'statement_id' : obj.id,
|
||||
'journal_id' : obj.journal_id.id,
|
||||
'account_id' : account.id,
|
||||
'amount' : obj.difference,
|
||||
'name' : name,
|
||||
}
|
||||
absl_proxy.create(cr, uid, values, context=context)
|
||||
|
||||
return super(account_cash_statement, self).button_confirm_bank(cr, uid, ids, context=context)
|
||||
|
||||
|
||||
class account_journal(osv.osv):
|
||||
_inherit = 'account.journal'
|
||||
|
||||
def _default_cashbox_line_ids(self, cr, uid, context=None):
|
||||
# Return a list of coins in Euros.
|
||||
result = [
|
||||
dict(pieces=value) for value in [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500]
|
||||
]
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'cashbox_line_ids' : fields.one2many('account.journal.cashbox.line', 'journal_id', 'CashBox', copy=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'cashbox_line_ids' : _default_cashbox_line_ids,
|
||||
}
|
||||
|
||||
|
||||
class account_journal_cashbox_line(osv.osv):
|
||||
_name = 'account.journal.cashbox.line'
|
||||
_rec_name = 'pieces'
|
||||
_columns = {
|
||||
'pieces': fields.float('Values', digits_compute=dp.get_precision('Account')),
|
||||
'journal_id' : fields.many2one('account.journal', 'Journal', required=True, select=1, ondelete="cascade"),
|
||||
}
|
||||
|
||||
_order = 'pieces asc'
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="action_account_period_tree" model="ir.actions.act_window">
|
||||
<field name="name">Close a Period</field>
|
||||
<field name="res_model">account.period</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_account_period_tree"/>
|
||||
<field name="context">{'search_default_draft': 1}</field>
|
||||
<field name="help">A period is a fiscal period of time during which accounting entries should be recorded for accounting related activities. Monthly period is the norm but depending on your countries or company needs, you could also have quarterly periods. Closing a period will make it impossible to record new accounting entries, all new entries should then be made on the following open period. Close a period when you do not want to record new entries and want to lock this period for tax related calculation.</field>
|
||||
</record>
|
||||
<menuitem
|
||||
action="action_account_period_tree"
|
||||
id="menu_action_account_period_close_tree"
|
||||
parent="account.menu_account_end_year_treatments"
|
||||
sequence="0"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,139 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from operator import itemgetter
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.tools.translate import _
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Account Financial Report
|
||||
# ---------------------------------------------------------
|
||||
|
||||
class account_financial_report(osv.osv):
|
||||
_name = "account.financial.report"
|
||||
_description = "Account Report"
|
||||
|
||||
def _get_level(self, cr, uid, ids, field_name, arg, context=None):
|
||||
'''Returns a dictionary with key=the ID of a record and value = the level of this
|
||||
record in the tree structure.'''
|
||||
res = {}
|
||||
for report in self.browse(cr, uid, ids, context=context):
|
||||
level = 0
|
||||
if report.parent_id:
|
||||
level = report.parent_id.level + 1
|
||||
res[report.id] = level
|
||||
return res
|
||||
|
||||
def _get_children_by_order(self, cr, uid, ids, context=None):
|
||||
'''returns a dictionary with the key= the ID of a record and value = all its children,
|
||||
computed recursively, and sorted by sequence. Ready for the printing'''
|
||||
res = []
|
||||
for id in ids:
|
||||
res.append(id)
|
||||
ids2 = self.search(cr, uid, [('parent_id', '=', id)], order='sequence ASC', context=context)
|
||||
res += self._get_children_by_order(cr, uid, ids2, context=context)
|
||||
return res
|
||||
|
||||
def _get_balance(self, cr, uid, ids, field_names, args, context=None):
|
||||
'''returns a dictionary with key=the ID of a record and value=the balance amount
|
||||
computed for this record. If the record is of type :
|
||||
'accounts' : it's the sum of the linked accounts
|
||||
'account_type' : it's the sum of leaf accoutns with such an account_type
|
||||
'account_report' : it's the amount of the related report
|
||||
'sum' : it's the sum of the children of this record (aka a 'view' record)'''
|
||||
account_obj = self.pool.get('account.account')
|
||||
res = {}
|
||||
for report in self.browse(cr, uid, ids, context=context):
|
||||
if report.id in res:
|
||||
continue
|
||||
res[report.id] = dict((fn, 0.0) for fn in field_names)
|
||||
if report.type == 'accounts':
|
||||
# it's the sum of the linked accounts
|
||||
for a in report.account_ids:
|
||||
for field in field_names:
|
||||
res[report.id][field] += getattr(a, field)
|
||||
elif report.type == 'account_type':
|
||||
# it's the sum the leaf accounts with such an account type
|
||||
report_types = [x.id for x in report.account_type_ids]
|
||||
account_ids = account_obj.search(cr, uid, [('user_type','in', report_types), ('type','!=','view')], context=context)
|
||||
for a in account_obj.browse(cr, uid, account_ids, context=context):
|
||||
for field in field_names:
|
||||
res[report.id][field] += getattr(a, field)
|
||||
elif report.type == 'account_report' and report.account_report_id:
|
||||
# it's the amount of the linked report
|
||||
res2 = self._get_balance(cr, uid, [report.account_report_id.id], field_names, False, context=context)
|
||||
for key, value in res2.items():
|
||||
for field in field_names:
|
||||
res[report.id][field] += value[field]
|
||||
elif report.type == 'sum':
|
||||
# it's the sum of the children of this account.report
|
||||
res2 = self._get_balance(cr, uid, [rec.id for rec in report.children_ids], field_names, False, context=context)
|
||||
for key, value in res2.items():
|
||||
for field in field_names:
|
||||
res[report.id][field] += value[field]
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Report Name', required=True, translate=True),
|
||||
'parent_id': fields.many2one('account.financial.report', 'Parent'),
|
||||
'children_ids': fields.one2many('account.financial.report', 'parent_id', 'Account Report'),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'balance': fields.function(_get_balance, string='Balance', multi='balance'),
|
||||
'debit': fields.function(_get_balance, string='Debit', multi='balance'),
|
||||
'credit': fields.function(_get_balance, string='Credit', multi="balance"),
|
||||
'level': fields.function(_get_level, string='Level', store=True, type='integer'),
|
||||
'type': fields.selection([
|
||||
('sum','View'),
|
||||
('accounts','Accounts'),
|
||||
('account_type','Account Type'),
|
||||
('account_report','Report Value'),
|
||||
],'Type'),
|
||||
'account_ids': fields.many2many('account.account', 'account_account_financial_report', 'report_line_id', 'account_id', 'Accounts'),
|
||||
'account_report_id': fields.many2one('account.financial.report', 'Report Value'),
|
||||
'account_type_ids': fields.many2many('account.account.type', 'account_account_financial_report_type', 'report_id', 'account_type_id', 'Account Types'),
|
||||
'sign': fields.selection([(-1, 'Reverse balance sign'), (1, 'Preserve balance sign')], 'Sign on Reports', required=True, help='For accounts that are typically more debited than credited and that you would like to print as negative amounts in your reports, you should reverse the sign of the balance; e.g.: Expense account. The same applies for accounts that are typically more credited than debited and that you would like to print as positive amounts in your reports; e.g.: Income account.'),
|
||||
'display_detail': fields.selection([
|
||||
('no_detail','No detail'),
|
||||
('detail_flat','Display children flat'),
|
||||
('detail_with_hierarchy','Display children with hierarchy')
|
||||
], 'Display details'),
|
||||
'style_overwrite': fields.selection([
|
||||
(0, 'Automatic formatting'),
|
||||
(1,'Main Title 1 (bold, underlined)'),
|
||||
(2,'Title 2 (bold)'),
|
||||
(3,'Title 3 (bold, smaller)'),
|
||||
(4,'Normal Text'),
|
||||
(5,'Italic Text (smaller)'),
|
||||
(6,'Smallest Text'),
|
||||
],'Financial Report Style', help="You can set up here the format you want this record to be displayed. If you leave the automatic formatting, it will be computed based on the financial reports hierarchy (auto-computed field 'level')."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'type': 'sum',
|
||||
'display_detail': 'detail_flat',
|
||||
'sign': 1,
|
||||
'style_overwrite': 0,
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<!--
|
||||
Financial Reports
|
||||
-->
|
||||
<record id="account_financial_report_profitandloss0" model="account.financial.report">
|
||||
<field name="name">Profit and Loss</field>
|
||||
<field name="sign" eval="-1" />
|
||||
<field name="type">sum</field>
|
||||
</record>
|
||||
<record id="account_financial_report_income0" model="account.financial.report">
|
||||
<field name="name">Income</field>
|
||||
<field name="sign" eval="-1" />
|
||||
<field name="parent_id" ref="account_financial_report_profitandloss0"/>
|
||||
<field name="display_detail">detail_with_hierarchy</field>
|
||||
<field name="type">account_type</field>
|
||||
</record>
|
||||
<record id="account_financial_report_expense0" model="account.financial.report">
|
||||
<field name="name">Expense</field>
|
||||
<field name="sign" eval="-1" />
|
||||
<field name="parent_id" ref="account_financial_report_profitandloss0"/>
|
||||
<field name="display_detail">detail_with_hierarchy</field>
|
||||
<field name="type">account_type</field>
|
||||
</record>
|
||||
|
||||
<record id="account_financial_report_balancesheet0" model="account.financial.report">
|
||||
<field name="name">Balance Sheet</field>
|
||||
<field name="type">sum</field>
|
||||
</record>
|
||||
<record id="account_financial_report_assets0" model="account.financial.report">
|
||||
<field name="name">Assets</field>
|
||||
<field name="parent_id" ref="account_financial_report_balancesheet0"/>
|
||||
<field name="display_detail">detail_with_hierarchy</field>
|
||||
<field name="type">account_type</field>
|
||||
</record>
|
||||
<record id="account_financial_report_liabilitysum0" model="account.financial.report">
|
||||
<field name="name">Liability</field>
|
||||
<field name="parent_id" ref="account_financial_report_balancesheet0"/>
|
||||
<field name="display_detail">no_detail</field>
|
||||
<field name="type">sum</field>
|
||||
</record>
|
||||
<record id="account_financial_report_liability0" model="account.financial.report">
|
||||
<field name="name">Liability</field>
|
||||
<field name="parent_id" ref="account_financial_report_liabilitysum0"/>
|
||||
<field name="display_detail">detail_with_hierarchy</field>
|
||||
<field name="type">account_type</field>
|
||||
</record>
|
||||
<record id="account_financial_report_profitloss_toreport0" model="account.financial.report">
|
||||
<field name="name">Profit (Loss) to report</field>
|
||||
<field name="parent_id" ref="account_financial_report_liabilitysum0"/>
|
||||
<field name="display_detail">no_detail</field>
|
||||
<field name="type">account_report</field>
|
||||
<field name="account_report_id" ref="account_financial_report_profitandloss0"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_account_configuration_installer" model="ir.ui.view">
|
||||
<field name="name">account.installer.form</field>
|
||||
<field name="model">account.installer</field>
|
||||
<field name="inherit_id" ref="base.res_config_installer"/>
|
||||
<field name="arch" type="xml">
|
||||
<form position="attributes">
|
||||
<attribute name="string">Accounting Application Configuration</attribute>
|
||||
</form>
|
||||
<footer position="replace">
|
||||
<footer>
|
||||
<button name="action_next" context="{'default_charts':charts}" type="object" string="Continue" class="oe_highlight"/>
|
||||
</footer>
|
||||
</footer>
|
||||
<separator string="title" position="replace">
|
||||
<p class="oe_grey">
|
||||
Select a configuration package to setup automatically your
|
||||
taxes and chart of accounts.
|
||||
</p>
|
||||
<group>
|
||||
<field name="charts" class="oe_inline"/>
|
||||
<field name="company_id" options="{'no_create': True}"/><!-- we assume that this wizard will be run only by administrators and as this field may cause problem if hidden (because of the default company of the user removed from the selection because already configured), we simply choosed to remove the group "multi company" of it -->
|
||||
</group>
|
||||
<group string="Configure your Fiscal Year" groups="account.group_account_user">
|
||||
<field name="has_default_company" invisible="1" />
|
||||
|
||||
<label for="date_start" string="Date Range"/>
|
||||
<div>
|
||||
<field name="date_start" on_change="on_change_start_date(date_start)" class="oe_inline"/> -
|
||||
<field name="date_stop" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="period"/>
|
||||
</group>
|
||||
</separator>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_account_configuration_installer" model="ir.actions.act_window">
|
||||
<field name="name">Configure Accounting Data</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.installer</field>
|
||||
<field name="view_id" ref="view_account_configuration_installer"/>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<record id="account_configuration_installer_todo" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_account_configuration_installer"/>
|
||||
<field name="sequence">3</field>
|
||||
<field name="type">automatic</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,313 @@
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from babel.dates import format_datetime, format_date
|
||||
|
||||
from openerp import models, api, _, fields
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
|
||||
from openerp.tools.misc import formatLang
|
||||
|
||||
class account_journal(models.Model):
|
||||
_inherit = "account.journal"
|
||||
|
||||
@api.one
|
||||
def _kanban_dashboard(self):
|
||||
self.kanban_dashboard = json.dumps(self.get_journal_dashboard_datas())
|
||||
|
||||
@api.one
|
||||
def _kanban_dashboard_graph(self):
|
||||
if (self.type in ['sale', 'purchase']):
|
||||
self.kanban_dashboard_graph = json.dumps(self.get_bar_graph_datas())
|
||||
elif (self.type in ['cash', 'bank']):
|
||||
self.kanban_dashboard_graph = json.dumps(self.get_line_graph_datas())
|
||||
|
||||
kanban_dashboard = fields.Text(compute='_kanban_dashboard')
|
||||
kanban_dashboard_graph = fields.Text(compute='_kanban_dashboard_graph')
|
||||
show_on_dashboard = fields.Boolean(string='Show journal on dashboard', help="Whether this journal should be displayed on the dashboard or not", default=True)
|
||||
|
||||
@api.multi
|
||||
def toggle_favorite(self):
|
||||
self.write({'show_on_dashboard': False if self.show_on_dashboard else True})
|
||||
return False
|
||||
|
||||
@api.multi
|
||||
def get_line_graph_datas(self):
|
||||
data = []
|
||||
today = datetime.today()
|
||||
last_month = today + timedelta(days=-30)
|
||||
bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids),('date', '>', last_month.strftime(DEFAULT_SERVER_DATE_FORMAT)),('date', '<=', today.strftime(DEFAULT_SERVER_DATE_FORMAT))], order="date asc")
|
||||
last_bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids),('date', '<=', last_month.strftime(DEFAULT_SERVER_DATE_FORMAT))], order="date desc", limit=1)
|
||||
start_balance = last_bank_stmt and last_bank_stmt[0].balance_end or 0
|
||||
locale = self._context.get('lang', 'en_US')
|
||||
show_date = last_month
|
||||
#get date in locale format
|
||||
name = format_date(show_date, 'd LLLL Y', locale=locale)
|
||||
short_name = format_date(show_date, 'd MMM', locale=locale)
|
||||
data.append({'x':short_name,'y':start_balance, 'name':name})
|
||||
|
||||
for stmt in bank_stmt:
|
||||
#fill the gap between last data and the new one
|
||||
number_day_to_add = (datetime.strptime(stmt.date, DEFAULT_SERVER_DATE_FORMAT) - show_date).days
|
||||
last_balance = data[len(data) - 1]['y']
|
||||
for day in range(0,number_day_to_add + 1):
|
||||
show_date = show_date + timedelta(days=1)
|
||||
#get date in locale format
|
||||
name = format_date(show_date, 'd LLLL Y', locale=locale)
|
||||
short_name = format_date(show_date, 'd MMM', locale=locale)
|
||||
data.append({'x': short_name, 'y':last_balance, 'name': name})
|
||||
#add new stmt value
|
||||
data[len(data) - 1]['y'] = stmt.balance_end
|
||||
|
||||
#continue the graph if the last statement isn't today
|
||||
if show_date != today:
|
||||
number_day_to_add = (today - show_date).days
|
||||
last_balance = data[len(data) - 1]['y']
|
||||
for day in range(0,number_day_to_add):
|
||||
show_date = show_date + timedelta(days=1)
|
||||
#get date in locale format
|
||||
name = format_date(show_date, 'd LLLL Y', locale=locale)
|
||||
short_name = format_date(show_date, 'd MMM', locale=locale)
|
||||
data.append({'x': short_name, 'y':last_balance, 'name': name})
|
||||
|
||||
return [{'values': data, 'color': '#ff7f0e', 'area': True}]
|
||||
|
||||
@api.multi
|
||||
def get_bar_graph_datas(self):
|
||||
data = []
|
||||
title = _('Invoices owed to you')
|
||||
if self.type == 'purchase':
|
||||
title = _('Bills you need to pay')
|
||||
today = datetime.today()
|
||||
data.append({'label': _('Past'), 'value':0.0, 'color': '#ff0000'})
|
||||
day_of_week = int(format_datetime(today, 'e', locale=self._context.get('lang', 'en_US')))
|
||||
first_day_of_week = today + timedelta(days=-day_of_week+1)
|
||||
for i in range(-1,4):
|
||||
if i==0:
|
||||
label = _('This Week')
|
||||
elif i==3:
|
||||
label = _('Future')
|
||||
else:
|
||||
start_week = first_day_of_week + timedelta(days=i*7)
|
||||
end_week = start_week + timedelta(days=6)
|
||||
if start_week.month == end_week.month:
|
||||
label = str(start_week.day) + '-' +str(end_week.day)+ ' ' + format_date(end_week, 'MMM', locale=self._context.get('lang', 'en_US'))
|
||||
else:
|
||||
label = format_date(start_week, 'd MMM', locale=self._context.get('lang', 'en_US'))+'-'+format_date(end_week, 'd MMM', locale=self._context.get('lang', 'en_US'))
|
||||
data.append({'label':label,'value':0.0, 'color': '#ff0000' if i<0 else '#ff7f0e'})
|
||||
for invoice in self.env['account.invoice'].search([('journal_id','=',self.id),('state', '=', 'open')]):
|
||||
if invoice.date_due < (first_day_of_week + timedelta(days=-7)).strftime(DEFAULT_SERVER_DATE_FORMAT):
|
||||
data[0]['value'] += invoice.residual_signed
|
||||
elif invoice.date_due < first_day_of_week.strftime(DEFAULT_SERVER_DATE_FORMAT):
|
||||
data[1]['value'] += invoice.residual_signed
|
||||
elif invoice.date_due >= (first_day_of_week + timedelta(days=21)).strftime(DEFAULT_SERVER_DATE_FORMAT):
|
||||
data[5]['value'] += invoice.residual_signed
|
||||
elif invoice.date_due >= (first_day_of_week + timedelta(days=14)).strftime(DEFAULT_SERVER_DATE_FORMAT):
|
||||
data[4]['value'] += invoice.residual_signed
|
||||
elif invoice.date_due >= (first_day_of_week + timedelta(days=7)).strftime(DEFAULT_SERVER_DATE_FORMAT):
|
||||
data[3]['value'] += invoice.residual_signed
|
||||
else:
|
||||
data[2]['value'] += invoice.residual_signed
|
||||
#postprocess to set graph color
|
||||
for bar in data:
|
||||
if bar['value'] == 0.0:
|
||||
bar['color'] = '#ffffff'
|
||||
return [{'values': data, 'title': title}]
|
||||
|
||||
@api.multi
|
||||
def get_journal_dashboard_datas(self):
|
||||
number_to_reconcile = last_balance = account_sum = 0
|
||||
ac_bnk_stmt = []
|
||||
number_draft = number_waiting = number_late = sum_draft = sum_waiting = sum_late = 0
|
||||
if self.type in ['bank', 'cash']:
|
||||
last_bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids)], order="date desc", limit=1)
|
||||
last_balance = last_bank_stmt and last_bank_stmt[0].balance_end or 0
|
||||
ac_bnk_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids),('state', '=', 'open')])
|
||||
for ac_bnk in ac_bnk_stmt:
|
||||
for line in ac_bnk.line_ids:
|
||||
if not line.journal_entry_ids:
|
||||
number_to_reconcile += 1
|
||||
account = [self.default_debit_account_id.id, self.default_credit_account_id.id]
|
||||
acm_lines = self.env['account.move.line'].search([('account_id', 'in', account)])
|
||||
account_sum = sum([line.balance for line in acm_lines]) or 0
|
||||
#TODO need to check if all invoices are in the same currency than the journal!!!!
|
||||
elif self.type in ['sale', 'purchase']:
|
||||
invoices = self.env['account.invoice'].search([('journal_id', 'in', self.ids), ('state', 'not in', ('paid', 'cancel'))])
|
||||
for invoice in invoices:
|
||||
if invoice.state in ['draft', 'proforma', 'proforma2']:
|
||||
number_draft += 1
|
||||
sum_draft += invoice.amount_total
|
||||
else:
|
||||
number_waiting += 1
|
||||
sum_waiting += invoice.residual
|
||||
if invoice.date_due < fields.Date.today():
|
||||
number_late += 1
|
||||
sum_late += invoice.residual
|
||||
|
||||
return {
|
||||
'number_to_reconcile': number_to_reconcile,
|
||||
'account_balance': formatLang(self.env, account_sum, currency_obj=self.currency_id or self.company_id.currency_id),
|
||||
'last_balance': formatLang(self.env, last_balance, currency_obj=self.currency_id or self.company_id.currency_id),
|
||||
'number_draft': number_draft,
|
||||
'number_waiting': number_waiting,
|
||||
'number_late': number_late,
|
||||
'sum_draft': formatLang(self.env, sum_draft, currency_obj=self.currency_id or self.company_id.currency_id),
|
||||
'sum_waiting': formatLang(self.env, sum_waiting, currency_obj=self.currency_id or self.company_id.currency_id),
|
||||
'sum_late': formatLang(self.env, sum_late, currency_obj=self.currency_id or self.company_id.currency_id),
|
||||
'currency_id': self.currency_id and self.currency_id.id or self.company_id.currency_id.id,
|
||||
'show_import': True if self.type in ['bank', 'cash'] and len(ac_bnk_stmt) == 0 and last_balance == 0 else False,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def action_create_new(self):
|
||||
ctx = self._context.copy()
|
||||
model = 'account.invoice'
|
||||
if self.type == 'sale':
|
||||
ctx.update({'journal_type': self.type, 'default_type': 'out_invoice', 'type': 'out_invoice', 'default_journal_id': self.id})
|
||||
if ctx.get('refund'):
|
||||
ctx.update({'default_type':'out_refund', 'type':'out_refund'})
|
||||
view_id = self.env.ref('account.invoice_form').id
|
||||
elif self.type == 'purchase':
|
||||
ctx.update({'journal_type': self.type, 'default_type': 'in_invoice', 'type': 'in_invoice', 'default_journal_id': self.id})
|
||||
if ctx.get('refund'):
|
||||
ctx.update({'default_type': 'in_refund', 'type': 'in_refund'})
|
||||
view_id = self.env.ref('account.invoice_supplier_form').id
|
||||
else:
|
||||
ctx.update({'default_journal_id': self.id})
|
||||
view_id = self.env.ref('account.view_move_form').id
|
||||
model = 'account.move'
|
||||
return {
|
||||
'name': _('Create invoice/bill'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': model,
|
||||
'view_id': view_id,
|
||||
'context': ctx,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def create_cash_bank(self):
|
||||
ctx = self._context.copy()
|
||||
ctx.update({'journal_id': self.id, 'default_journal_id': self.id, 'default_journal_type': 'cash'})
|
||||
return {
|
||||
'name': _('Create cash statement'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'account.bank.statement',
|
||||
'context': ctx,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def action_open_reconcile(self):
|
||||
if self.type in ['bank', 'cash']:
|
||||
# Open reconciliation view for bank statements belonging to this journal
|
||||
bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids)])
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'bank_statement_reconciliation_view',
|
||||
'context': {'statement_ids': bank_stmt.ids},
|
||||
}
|
||||
else:
|
||||
# Open reconciliation view for customers/suppliers
|
||||
action_context = {'show_mode_selector': False}
|
||||
if self.type == 'sale':
|
||||
action_context.update({'mode': 'customers'})
|
||||
elif self.type == 'purchase':
|
||||
action_context.update({'mode': 'suppliers'})
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'manual_reconciliation_view',
|
||||
'context': action_context,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def open_action(self):
|
||||
"""return action based on type for related journals"""
|
||||
action_name = self._context.get('action_name', False)
|
||||
if not action_name:
|
||||
if self.type == 'bank':
|
||||
action_name = 'action_bank_statement_tree'
|
||||
elif self.type == 'cash':
|
||||
action_name = 'action_view_bank_statement_tree'
|
||||
elif self.type == 'sale':
|
||||
action_name = 'action_invoice_tree1'
|
||||
elif self.type == 'purchase':
|
||||
action_name = 'action_invoice_tree2'
|
||||
else:
|
||||
action_name = 'action_move_journal_line'
|
||||
|
||||
_journal_invoice_type_map = {
|
||||
'sale': 'out_invoice',
|
||||
'purchase': 'in_invoice',
|
||||
'bank': 'bank',
|
||||
'cash': 'cash',
|
||||
'general': 'general',
|
||||
}
|
||||
invoice_type = _journal_invoice_type_map[self.type]
|
||||
|
||||
ctx = self._context.copy()
|
||||
ctx.update({
|
||||
'journal_type': self.type,
|
||||
'default_journal_id': self.id,
|
||||
'search_default_journal_id': self.id,
|
||||
'default_type': invoice_type,
|
||||
'type': invoice_type
|
||||
})
|
||||
ir_model_obj = self.pool['ir.model.data']
|
||||
model, action_id = ir_model_obj.get_object_reference(self._cr, self._uid, 'account', action_name)
|
||||
action = self.pool[model].read(self._cr, self._uid, action_id, context=self._context)
|
||||
action['context'] = ctx
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def open_spend_money(self):
|
||||
return self.open_payments_action('outbound')
|
||||
|
||||
@api.multi
|
||||
def open_collect_money(self):
|
||||
return self.open_payments_action('inbound')
|
||||
|
||||
@api.multi
|
||||
def open_transfer_money(self):
|
||||
return self.open_payments_action('transfer')
|
||||
|
||||
@api.multi
|
||||
def open_payments_action(self, payment_type):
|
||||
ctx = self._context.copy()
|
||||
ctx.update({
|
||||
'default_payment_type': payment_type,
|
||||
'default_journal_id': self.id
|
||||
})
|
||||
action_rec = self.env['ir.model.data'].xmlid_to_object('account.action_account_payments')
|
||||
if action_rec:
|
||||
action = action_rec.read([])[0]
|
||||
action['context'] = ctx
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def open_action_with_context(self):
|
||||
action_name = self.env.context.get('action_name', False)
|
||||
if not action_name:
|
||||
return False
|
||||
ctx = dict(self.env.context, default_journal_id=self.id)
|
||||
if ctx.get('search_default_journal', False):
|
||||
ctx.update(search_default_journal_id=self.id)
|
||||
ir_model_obj = self.pool['ir.model.data']
|
||||
model, action_id = ir_model_obj.get_object_reference(self._cr, self._uid, 'account', action_name)
|
||||
action = self.pool[model].read(self._cr, self._uid, action_id, context=self._context)
|
||||
action['context'] = ctx
|
||||
if ctx.get('use_domain', False):
|
||||
action['domain'] = ['|', ('journal_id', '=', self.id), ('journal_id', '=', False)]
|
||||
action['name'] += ' for journal '+self.name
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def import_statement(self):
|
||||
"""return action to import bank/cash statements. This button should be called only on journals with type =='bank'"""
|
||||
model = 'account.bank.statement'
|
||||
action_name = 'action_account_bank_statement_import'
|
||||
ir_model_obj = self.pool['ir.model.data']
|
||||
model, action_id = ir_model_obj.get_object_reference(self._cr, self._uid, 'account_bank_statement_import', action_name)
|
||||
action = self.pool[model].read(self._cr, self._uid, action_id, context=self._context)
|
||||
return action
|
||||
@@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Top menu item -->
|
||||
<menuitem name="Invoicing"
|
||||
id="menu_finance"
|
||||
groups="group_account_user,group_account_manager,group_account_invoice"
|
||||
icon="fa-usd"
|
||||
sequence="25"/>
|
||||
|
||||
<menuitem id="menu_finance_receivables" name="Customers" parent="menu_finance" sequence="2"/>
|
||||
<menuitem id="menu_finance_payables" name="Suppliers" parent="menu_finance" sequence="3"/>
|
||||
<menuitem id="menu_finance_bank_and_cash" name="Bank and Cash" parent="menu_finance" sequence="4"
|
||||
groups="group_account_user,group_account_manager"/>
|
||||
<menuitem id="menu_finance_periodical_processing" name="Periodic Processing" parent="menu_finance" sequence="13" groups="group_account_user,group_account_manager"/>
|
||||
<!-- This menu is used in account_code module -->
|
||||
<menuitem id="menu_account_pp_statements" name="Statements" parent="menu_finance_periodical_processing" sequence="12"/>
|
||||
<menuitem id="periodical_processing_journal_entries_validation" name="Draft Entries" parent="menu_finance_periodical_processing"/>
|
||||
<menuitem id="periodical_processing_reconciliation" name="Reconciliation" parent="menu_finance_periodical_processing"/>
|
||||
<menuitem id="periodical_processing_invoicing" name="Invoicing" parent="menu_finance_periodical_processing"/>
|
||||
<menuitem id="periodical_processing_bank_statements" name="Bank Statements" parent="menu_finance_periodical_processing"/>
|
||||
<menuitem id="menu_finance_charts" name="Charts" parent="menu_finance" groups="account.group_account_user" sequence="9"/>
|
||||
<menuitem id="menu_finance_reporting" name="Reports" parent="menu_finance" sequence="99"/>
|
||||
<menuitem id="menu_finance_reporting_budgets" name="Budgets" parent="menu_finance_reporting" groups="group_account_user" sequence="8"/>
|
||||
<menuitem id="menu_finance_reports" name="Reporting" parent="menu_finance" sequence="10" groups="group_account_user,group_account_manager"/>
|
||||
<menuitem id="menu_finance_legal_statement" name="Legal Reports" parent="menu_finance_reports"/>
|
||||
<menuitem id="menu_finance_management_belgian_reports" name="Belgian Reports" parent="menu_finance_reporting"/>
|
||||
<menuitem id="menu_finance_configuration" name="Configuration" parent="menu_finance" sequence="15" groups="group_account_manager"/>
|
||||
<menuitem id="menu_finance_accounting" name="Financial Accounting" parent="menu_finance_configuration" sequence="1"/>
|
||||
<menuitem id="menu_analytic_accounting" name="Analytic Accounting" parent="menu_finance_configuration" groups="analytic.group_analytic_accounting" sequence="5"/>
|
||||
|
||||
<menuitem id="menu_analytic" parent="menu_analytic_accounting" name="Accounts" groups="analytic.group_analytic_accounting"/>
|
||||
<menuitem id="menu_journals" sequence="3" name="Journals" parent="menu_finance_configuration" groups="group_account_manager"/>
|
||||
<menuitem id="menu_configuration_recurrent_entries" name="Reccuring Entries" parent="menu_finance_configuration" sequence="54"/>
|
||||
<menuitem id="menu_config_multi_currency" name="Multi-Currencies" parent="menu_finance_configuration" sequence="9" groups="base.group_multi_currency"/>
|
||||
|
||||
<menuitem id="base.menu_action_currency_form" name="Currencies" parent="menu_config_multi_currency" sequence="20" groups="base.group_no_one"/>
|
||||
<menuitem id="menu_finance_generic_reporting" name="Generic Reporting" parent="menu_finance_reports" sequence="100"/>
|
||||
<menuitem id="menu_finance_entries" name="Journal Entries" parent="menu_finance" sequence="6" groups="group_account_user,group_account_manager"/>
|
||||
|
||||
<menuitem id="account_account_menu" name="Accounts" parent="account.menu_finance_configuration" sequence="2"/>
|
||||
<menuitem id="menu_account_reports" name="Reports" parent="account.account_account_menu" sequence="4" />
|
||||
|
||||
<menuitem id="account.menu_finance_recurrent_entries" name="Recurring Entries"
|
||||
parent="menu_finance_periodical_processing" sequence="15"/>
|
||||
|
||||
<menuitem id="menu_account_end_year_treatments"
|
||||
name="End of Period" parent="menu_finance_periodical_processing"
|
||||
sequence="25"/>
|
||||
<menuitem id="menu_finance_periodical_processing_billing" name="Billing" parent="menu_finance_periodical_processing" sequence="35"/>
|
||||
|
||||
<menuitem id="next_id_22" name="Partners" parent="menu_finance_generic_reporting" sequence="1"/>
|
||||
<menuitem id="menu_multi_currency" name="Multi-Currencies" parent="menu_finance_generic_reporting" sequence="10" groups="base.group_multi_currency"/>
|
||||
|
||||
<menuitem
|
||||
parent="account.menu_finance_legal_statement"
|
||||
id="final_accounting_reports"
|
||||
name="Accounting Reports"/>
|
||||
|
||||
<menuitem
|
||||
parent="account.menu_finance_legal_statement"
|
||||
id="menu_journals_report"
|
||||
groups="group_account_user,group_account_manager"
|
||||
name="Journals"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -0,0 +1,524 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp import models, fields, api, _
|
||||
from openerp.exceptions import UserError, ValidationError
|
||||
|
||||
MAP_INVOICE_TYPE_PARTNER_TYPE = {
|
||||
'out_invoice': 'customer',
|
||||
'out_refund': 'customer',
|
||||
'in_invoice': 'supplier',
|
||||
'in_refund': 'supplier',
|
||||
}
|
||||
# Since invoice amounts are unsigned, this is how we know if money comes in or goes out
|
||||
MAP_INVOICE_TYPE_PAYMENT_SIGN = {
|
||||
'out_invoice': 1,
|
||||
'in_refund': 1,
|
||||
'in_invoice': -1,
|
||||
'out_refund': -1,
|
||||
}
|
||||
|
||||
class account_payment_method(models.Model):
|
||||
_name = "account.payment.method"
|
||||
_description = "Payment Methods"
|
||||
|
||||
name = fields.Char(required=True)
|
||||
code = fields.Char(required=True) # For internal identification
|
||||
payment_type = fields.Selection([('inbound', 'Inbound'), ('outbound', 'Outbound')], required=True)
|
||||
|
||||
|
||||
class account_abstract_payment(models.AbstractModel):
|
||||
_name = "account.abstract.payment"
|
||||
_description = "Contains the logic shared between models which allows to register payments"
|
||||
|
||||
payment_type = fields.Selection([('outbound', 'Send Money'), ('inbound', 'Receive Money')], default='outbound', required=True)
|
||||
payment_method = fields.Many2one('account.payment.method', string='Payment Method', required=True)
|
||||
|
||||
partner_type = fields.Selection([('customer', 'Customer'), ('supplier', 'Supplier')], default='supplier')
|
||||
partner_id = fields.Many2one('res.partner', string='Partner')
|
||||
|
||||
amount = fields.Monetary(string='Payment Amount', required=True)
|
||||
currency_id = fields.Many2one('res.currency', string='Currency', required=True, default=lambda self: self.env.user.company_id.currency_id)
|
||||
payment_date = fields.Date(string='Payment Date', default=fields.Date.context_today, required=True, copy=False)
|
||||
date = fields.Date(string='Accounting Date', copy=False, help="Keep empty to use the payment date.",)
|
||||
communication = fields.Char()
|
||||
journal_id = fields.Many2one('account.journal', string='Bank Journal', required=True, domain=[('type', 'in', ('bank', 'cash'))])
|
||||
company_id = fields.Many2one('res.company', related='journal_id.company_id', string='Company', readonly=True)
|
||||
|
||||
manual_payment_method_selected = fields.Boolean(compute='_compute_manual_payment_method_selected')
|
||||
hide_payment_method = fields.Boolean(compute='_compute_hide_payment_method', help="Technical field used to hide the payment method if the selected journal has only one available which is 'manual'")
|
||||
|
||||
@api.one
|
||||
@api.constrains('amount')
|
||||
def _check_amount(self):
|
||||
if not self.amount > 0.0:
|
||||
raise ValidationError('The payment amount must be strictly positive.')
|
||||
|
||||
@api.one
|
||||
@api.constrains('communication')
|
||||
def _check_communication(self):
|
||||
""" This method is to be overwritten by payment type modules. The method body would look like :
|
||||
if self.payment_method == self.env.ref('my_module.payment_method'):
|
||||
try:
|
||||
self.communication.decode('ascii')
|
||||
except UnicodeDecodeError:
|
||||
raise ValidationError(_t("The communication cannot contain any special character"))
|
||||
"""
|
||||
pass
|
||||
|
||||
@api.one
|
||||
@api.depends('payment_method')
|
||||
def _compute_manual_payment_method_selected(self):
|
||||
self.manual_payment_method_selected = self.payment_method.code == 'manual'
|
||||
|
||||
@api.one
|
||||
@api.depends('payment_type', 'journal_id')
|
||||
def _compute_hide_payment_method(self):
|
||||
if not self.journal_id:
|
||||
self.hide_payment_method = True
|
||||
return
|
||||
journal_payment_methods = self.payment_type == 'inbound' and self.journal_id.inbound_payment_methods or self.journal_id.outbound_payment_methods
|
||||
self.hide_payment_method = len(journal_payment_methods) == 1 and journal_payment_methods[0].code == 'manual'
|
||||
|
||||
@api.onchange('journal_id')
|
||||
def _onchange_journal(self):
|
||||
if self.journal_id:
|
||||
self.currency_id = self.journal_id.currency_id or self.company_id.currency_id
|
||||
# Set default payment method (we consider the first to be the default one)
|
||||
payment_methods = self.payment_type == 'inbound' and self.journal_id.inbound_payment_methods or self.journal_id.outbound_payment_methods
|
||||
self.payment_method = payment_methods and payment_methods[0] or False
|
||||
# Set payment method domain (restrict to methods enabled for the journal and to selected payment type)
|
||||
payment_type = self.payment_type in ('outbound', 'transfer') and 'outbound' or 'inbound'
|
||||
return {'domain': {'payment_method': [('payment_type', '=', payment_type), ('id', 'in', payment_methods.ids)]}}
|
||||
return {}
|
||||
|
||||
@api.onchange('currency_id')
|
||||
def _onchange_currency_id(self):
|
||||
self._set_total_invoices_amount()
|
||||
|
||||
@api.onchange('payment_date')
|
||||
def _onchange_date(self):
|
||||
self._set_total_invoices_amount()
|
||||
|
||||
def _get_invoices(self):
|
||||
""" Return the invoices of the payment. Must be overridden """
|
||||
raise NotImplementedError
|
||||
|
||||
def _compute_total_invoices_amount(self):
|
||||
""" Compute the sum of the residual of invoices, expressed in the payment currency """
|
||||
total = 0
|
||||
payment_currency = self.currency_id or self.journal_id.currency_id or self.journal_id.company_id.currency_id
|
||||
for inv in self._get_invoices():
|
||||
total += inv.residual_signed
|
||||
if self.company_id and self.company_id.currency_id != payment_currency:
|
||||
total = self.company_id.currency_id.with_context(date=self.payment_date).compute(total, payment_currency)
|
||||
return abs(total)
|
||||
|
||||
def _set_total_invoices_amount(self):
|
||||
""" Set self.amount = total residual of invoices, do nothing if the payment does not refer to invoices """
|
||||
if len(self._get_invoices()) != 0:
|
||||
self.amount = self._compute_total_invoices_amount()
|
||||
|
||||
|
||||
class account_register_payments(models.TransientModel):
|
||||
_name = "account.register.payments"
|
||||
_inherit = 'account.abstract.payment'
|
||||
_description = "Register payments on multiple invoices"
|
||||
|
||||
@api.onchange('payment_type')
|
||||
def _onchange_payment_type(self):
|
||||
if self.payment_type:
|
||||
return {'domain': {'payment_method': [('payment_type', '=', self.payment_type)]}}
|
||||
|
||||
def _get_invoices(self):
|
||||
return self.env['account.invoice'].browse(self._context.get('active_ids'))
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
rec = super(account_register_payments, self).default_get(fields)
|
||||
context = dict(self._context or {})
|
||||
active_model = context.get('active_model')
|
||||
active_ids = context.get('active_ids')
|
||||
|
||||
# Checks on context parameters
|
||||
if not active_model or not active_ids:
|
||||
raise UserError(_("Programmation error: wizard action executed without active_model or active_ids in context."))
|
||||
if active_model != 'account.invoice':
|
||||
raise UserError(_("Programmation error: the expected model for this action is 'account.invoice'. The provided one is '%d'." % active_model))
|
||||
|
||||
# Checks on received invoice records
|
||||
invoices = self.env[active_model].browse(active_ids)
|
||||
if any(invoice.state != 'open' for invoice in invoices):
|
||||
raise UserError(_("You can only register payments for open invoices"))
|
||||
if any(inv.partner_id != invoices[0].partner_id for inv in invoices):
|
||||
raise UserError(_("In order to pay multiple invoices at once, they must belong to the same partner."))
|
||||
if any(MAP_INVOICE_TYPE_PARTNER_TYPE[inv.type] != MAP_INVOICE_TYPE_PARTNER_TYPE[invoices[0].type] for inv in invoices):
|
||||
raise UserError(_("You cannot mix customer and supplier invoices in a single payment."))
|
||||
if any(inv.currency_id != invoices[0].currency_id for inv in invoices):
|
||||
raise UserError(_("In order to pay multiple invoices at once, they must use the same currency."))
|
||||
|
||||
total_amount = sum(inv.residual * MAP_INVOICE_TYPE_PAYMENT_SIGN[inv.type] for inv in invoices)
|
||||
rec.update({
|
||||
'amount': abs(total_amount),
|
||||
'currency_id': invoices[0].currency_id.id,
|
||||
'payment_type': total_amount > 0 and 'inbound' or 'outbound',
|
||||
'partner_id': invoices[0].partner_id.id,
|
||||
'partner_type': MAP_INVOICE_TYPE_PARTNER_TYPE[invoices[0].type],
|
||||
})
|
||||
return rec
|
||||
|
||||
@api.multi
|
||||
def create_payment(self):
|
||||
invoices = self._get_invoices()
|
||||
payment = self.env['account.payment'].create({
|
||||
'journal_id': self.journal_id.id,
|
||||
'payment_method': self.payment_method.id,
|
||||
'payment_date': self.payment_date,
|
||||
'date': self.date,
|
||||
'communication': self.communication,
|
||||
'invoice_ids': [(4, inv.id, None) for inv in invoices],
|
||||
'payment_type': self.payment_type,
|
||||
'amount': self._compute_total_invoices_amount(),
|
||||
'currency_id': self.currency_id.id,
|
||||
'partner_id': self.partner_id.id,
|
||||
'partner_type': self.partner_type,
|
||||
})
|
||||
payment.post()
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
class account_payment(models.Model):
|
||||
_name = "account.payment"
|
||||
_inherit = 'account.abstract.payment'
|
||||
_description = "Payments"
|
||||
_order = "payment_date desc, name desc"
|
||||
|
||||
@api.one
|
||||
@api.depends('invoice_ids')
|
||||
def _get_has_invoices(self):
|
||||
self.has_invoices = bool(self.invoice_ids)
|
||||
|
||||
@api.one
|
||||
@api.depends('invoice_ids', 'amount', 'date', 'currency_id')
|
||||
def _compute_payment_difference(self):
|
||||
if len(self.invoice_ids) == 0:
|
||||
return
|
||||
# A payment on multiple invoices must pay them entirely (and amount be readonly of course)
|
||||
if len(self.invoice_ids) != 1:
|
||||
self.payment_difference = 0
|
||||
else:
|
||||
self.payment_difference = self._compute_total_invoices_amount() - self.amount
|
||||
|
||||
name = fields.Char(readonly=True, copy=False)
|
||||
state = fields.Selection([('draft', 'Draft'), ('posted', 'Posted'), ('sent', 'Sent'), ('reconciled', 'Reconciled')], readonly=True, default='draft', copy=False, string="Status")
|
||||
|
||||
payment_type = fields.Selection(selection_add=[('transfer', 'Internal Transfer')])
|
||||
payment_reference = fields.Char(copy=False, readonly=True, help="Reference of the document used to issue this payment. Eg. check number, file name, etc.")
|
||||
|
||||
# Money flows from the journal_id's default_debit_account_id or default_credit_account_id to the destination_account_id
|
||||
destination_account_id = fields.Many2one('account.account', compute='_compute_destination_account_id', readonly=True)
|
||||
# For money transfer, money goes from journal_id to a transfer account, then from the transfer account to destination_journal_id
|
||||
destination_journal_id = fields.Many2one('account.journal', string='Transfer To', domain=[('type', 'in', ('bank', 'cash'))])
|
||||
|
||||
invoice_ids = fields.Many2many('account.invoice', 'account_invoice_payment_rel', 'payment_id', 'invoice_id', string="Invoices", copy=False, readonly=True)
|
||||
has_invoices = fields.Boolean(compute="_get_has_invoices", help="Technical field used for usablity purposes")
|
||||
payment_difference = fields.Float(compute='_compute_payment_difference', readonly=True)
|
||||
payment_difference_handling = fields.Selection([('open', 'Keep Open'), ('reconcile', 'Reconcile Payment Balance')], default='open', string="Payment Difference", copy=False)
|
||||
writeoff_account = fields.Many2one('account.account', string="Counterpart Account", domain=[('deprecated', '=', False)], copy=False)
|
||||
|
||||
# FIXME: ondelete='restrict' not working (eg. cancel a bank statement reconciliation with a payment)
|
||||
move_line_ids = fields.One2many('account.move.line', 'payment_id', readonly=True, copy=False, ondelete='restrict')
|
||||
|
||||
@api.one
|
||||
@api.depends('invoice_ids', 'payment_type', 'partner_type', 'partner_id')
|
||||
def _compute_destination_account_id(self):
|
||||
if self.invoice_ids:
|
||||
self.destination_account_id = self.invoice_ids[0].account_id.id
|
||||
elif self.payment_type == 'transfer':
|
||||
if not self.company_id.transfer_account_id.id:
|
||||
raise UserError(_('Transfer account not defined on the company.'))
|
||||
self.destination_account_id = self.company_id.transfer_account_id.id
|
||||
elif self.partner_id:
|
||||
if self.partner_type == 'customer':
|
||||
self.destination_account_id = self.partner_id.property_account_receivable.id
|
||||
else:
|
||||
self.destination_account_id = self.partner_id.property_account_payable.id
|
||||
|
||||
@api.onchange('partner_type')
|
||||
def _onchange_partner_type(self):
|
||||
# Set partner_id domain
|
||||
if self.partner_type:
|
||||
if getattr(self.partner_id, self.partner_type) is False:
|
||||
self.partner_id = False
|
||||
return {'domain': {'partner_id': [(self.partner_type, '=', True)]}}
|
||||
|
||||
@api.onchange('payment_type')
|
||||
def _onchange_payment_type(self):
|
||||
# Set default partner type for the payment type
|
||||
if self.payment_type == 'inbound':
|
||||
self.partner_type = 'customer'
|
||||
elif self.payment_type == 'outbound':
|
||||
self.partner_type = 'supplier'
|
||||
# Set payment method domain
|
||||
res = self._onchange_journal()
|
||||
if not res.get('domain', {}):
|
||||
res['domain'] = {}
|
||||
res['domain']['journal_id'] = self.payment_type == 'inbound' and [('at_least_one_inbound', '=', True)] or [('at_least_one_outbound', '=', True)]
|
||||
res['domain']['journal_id'].append(('type', 'in', ('bank', 'cash')))
|
||||
return res
|
||||
|
||||
@api.onchange('invoice_ids')
|
||||
def _onchange_invoice(self):
|
||||
if len(self.invoice_ids) == 1:
|
||||
self.communication = self.invoice_ids[0].reference
|
||||
self.currency_id = self.invoice_ids[0].currency_id
|
||||
self.payment_type = self.invoice_ids[0].type in ('out_invoice', 'in_refund') and 'inbound' or 'outbound'
|
||||
self.partner_type = MAP_INVOICE_TYPE_PARTNER_TYPE[self.invoice_ids[0].type]
|
||||
self.partner_id = self.invoice_ids[0].partner_id
|
||||
self._set_total_invoices_amount()
|
||||
|
||||
def _get_invoices(self):
|
||||
return self.invoice_ids
|
||||
|
||||
@api.multi
|
||||
def button_journal_entries(self):
|
||||
return {
|
||||
'name': _('Journal Items'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree',
|
||||
'res_model': 'account.move.line',
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
'domain': [('payment_id', 'in', self.ids)],
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def button_invoices(self):
|
||||
return {
|
||||
'name': _('Paid Invoices'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree',
|
||||
'res_model': 'account.invoice',
|
||||
'view_id': False,
|
||||
'type': 'ir.actions.act_window',
|
||||
'domain': [('id', 'in', [x.id for x in self.invoice_ids])],
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def button_dummy(self):
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def cancel(self):
|
||||
for rec in self:
|
||||
for move in rec.move_line_ids.mapped('move_id'):
|
||||
if rec.invoice_ids:
|
||||
move.line_ids.remove_move_reconcile()
|
||||
move.button_cancel()
|
||||
move.unlink()
|
||||
rec.state = 'draft'
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
if any(rec.state != 'draft' for rec in self):
|
||||
raise UserError(_("In order to delete a payment, it must first be canceled."))
|
||||
return super(account_payment, self).unlink()
|
||||
|
||||
@api.multi
|
||||
def post(self):
|
||||
""" Create the journal items for the payment and update the payment's state to 'posted'.
|
||||
A journal entry is created containing an item in the source liquidity account (selected journal's default_debit or default_credit)
|
||||
and another in the destination reconciliable account (see _compute_destination_account_id).
|
||||
If invoice_ids is not empty, there will be one reconciliable move line per invoice to reconcile with.
|
||||
If the payment is a transfer, a second journal entry is created in the destination journal to receive money from the transfer account.
|
||||
"""
|
||||
for rec in self:
|
||||
|
||||
if rec.state != 'draft':
|
||||
raise UserError(_("Only a draft payment can be posted. Trying to post a payment in state %s.") % rec.state)
|
||||
|
||||
if any(inv.state != 'open' for inv in rec.invoice_ids):
|
||||
raise ValidationError(_("The payment cannot be processed because an invoice of the payment is not open !"))
|
||||
|
||||
# Use the right sequence to set the name
|
||||
if rec.payment_type == 'transfer':
|
||||
sequence = rec.env.ref('account.sequence_payment_transfer')
|
||||
else:
|
||||
if rec.partner_type == 'customer':
|
||||
if rec.payment_type == 'inbound':
|
||||
sequence = rec.env.ref('account.sequence_payment_customer_invoice')
|
||||
if rec.payment_type == 'outbound':
|
||||
sequence = rec.env.ref('account.sequence_payment_customer_refund')
|
||||
if rec.partner_type == 'supplier':
|
||||
if rec.payment_type == 'inbound':
|
||||
sequence = rec.env.ref('account.sequence_payment_supplier_refund')
|
||||
if rec.payment_type == 'outbound':
|
||||
sequence = rec.env.ref('account.sequence_payment_supplier_invoice')
|
||||
rec.name = sequence.with_context(ir_sequence_date=rec.date or rec.payment_date).next_by_id()
|
||||
|
||||
# Create the journal entry
|
||||
amount = rec.amount * (rec.payment_type in ('outbound', 'transfer') and 1 or -1)
|
||||
move = rec._create_payment_entry(amount)
|
||||
|
||||
# In case of a transfer, the first journal entry created debited the source liquidity account and credited
|
||||
# the transfer account. Now we debit the transfer account and credit the destination liquidity account.
|
||||
if rec.payment_type == 'transfer':
|
||||
transfer_credit_aml = move.line_ids.filtered(lambda r: r.account_id == rec.company_id.transfer_account_id)
|
||||
transfer_debit_aml = rec._create_transfer_entry(amount)
|
||||
(transfer_credit_aml + transfer_debit_aml).reconcile()
|
||||
|
||||
rec.state = 'posted'
|
||||
|
||||
def _create_payment_entry(self, amount):
|
||||
""" Create a journal entry corresponding to a payment, if the payment references invoice(s) they are reconciled.
|
||||
Return the journal entry.
|
||||
"""
|
||||
aml_obj = self.env['account.move.line'].with_context(check_move_validity=False)
|
||||
invoice_id = len(self.invoice_ids) == 1 and self.invoice_ids[0] or False
|
||||
total_debit, total_credit, total_amount_currency = aml_obj.with_context(date=self.payment_date).compute_amount_fields(amount, self.currency_id, self.company_id.currency_id)
|
||||
|
||||
move = self.env['account.move'].create(self._get_move_vals())
|
||||
|
||||
if len(self.invoice_ids) > 1:
|
||||
total_amount = 0
|
||||
for invoice_id in self.invoice_ids:
|
||||
# Create a reconciliable journal item corresponding to the invoice
|
||||
inv_amount = -invoice_id.residual * MAP_INVOICE_TYPE_PAYMENT_SIGN[invoice_id.type]
|
||||
debit = inv_amount > 0 and inv_amount or 0
|
||||
credit = inv_amount < 0 and -inv_amount or 0
|
||||
amount_currency = self.currency_id != self.company_id.currency_id and self.company_id.currency_id.with_context(date=self.payment_date).compute(inv_amount, self.currency_id) or 0
|
||||
# Avoid unbalanced journal entry due to rounding error
|
||||
total_amount = total_amount + debit - credit
|
||||
counterpart_aml_dict = self._get_shared_move_line_vals(debit, credit, amount_currency, move.id, invoice_id)
|
||||
counterpart_aml_dict.update(self._get_counterpart_move_line_vals(invoice_id))
|
||||
counterpart_aml_dict.update({'currency_id': self.currency_id != self.company_id.currency_id and self.currency_id.id or False})
|
||||
counterpart_aml = aml_obj.create(counterpart_aml_dict)
|
||||
invoice_id.register_payment(counterpart_aml)
|
||||
total_debit = total_amount > 0 and total_amount or 0
|
||||
total_credit = total_amount < 0 and -total_amount or 0
|
||||
else:
|
||||
# Create reconciliable journal item
|
||||
counterpart_aml_dict = self._get_shared_move_line_vals(total_debit, total_credit, total_amount_currency, move.id, invoice_id)
|
||||
counterpart_aml_dict.update(self._get_counterpart_move_line_vals(invoice_id))
|
||||
counterpart_aml = aml_obj.create(counterpart_aml_dict)
|
||||
|
||||
# Reconcile it with the invoice if present
|
||||
if invoice_id:
|
||||
if self.payment_difference_handling == 'reconcile':
|
||||
invoice_id.register_payment(counterpart_aml, self.writeoff_account, self.journal_id)
|
||||
else:
|
||||
invoice_id.register_payment(counterpart_aml)
|
||||
|
||||
liquidity_aml_dict = self._get_shared_move_line_vals(total_credit, total_debit, -total_amount_currency, move.id, invoice_id)
|
||||
liquidity_aml_dict.update(self._get_liquidity_move_line_vals(-amount))
|
||||
aml_obj.create(liquidity_aml_dict)
|
||||
|
||||
move.post()
|
||||
return move
|
||||
|
||||
def _create_transfer_entry(self, amount):
|
||||
""" Create the journal entry corresponding to the 'incoming money' part of an internal transfer, return the reconciliable move line
|
||||
"""
|
||||
aml_obj = self.env['account.move.line'].with_context(check_move_validity=False)
|
||||
debit, credit, amount_currency = aml_obj.with_context(date=self.payment_date).compute_amount_fields(amount, self.currency_id, self.company_id.currency_id)
|
||||
amount_currency = self.destination_journal_id.currency_id and self.currency_id.with_context(date=self.payment_date).compute(amount, self.destination_journal_id.currency_id) or 0
|
||||
|
||||
dst_move = self.env['account.move'].create(self._get_move_vals(self.destination_journal_id))
|
||||
|
||||
dst_liquidity_aml_dict = self._get_shared_move_line_vals(debit, credit, amount_currency, dst_move.id)
|
||||
dst_liquidity_aml_dict.update({
|
||||
'name': _('Transfer from %s') % self.journal_id.name,
|
||||
'account_id': self.destination_journal_id.default_credit_account_id.id,
|
||||
'currency_id': self.destination_journal_id.currency_id.id,
|
||||
'payment_id': self.id,
|
||||
'journal_id': self.destination_journal_id.id})
|
||||
aml_obj.create(dst_liquidity_aml_dict)
|
||||
|
||||
transfer_debit_aml_dict = self._get_shared_move_line_vals(credit, debit, 0, dst_move.id)
|
||||
transfer_debit_aml_dict.update({
|
||||
'name': self.name,
|
||||
'payment_id': self.id,
|
||||
'account_id': self.company_id.transfer_account_id.id,
|
||||
'journal_id': self.destination_journal_id.id})
|
||||
if self.currency_id != self.company_id.currency_id:
|
||||
transfer_debit_aml_dict.update({
|
||||
'currency_id': self.currency_id.id,
|
||||
'amount_currency': -self.amount,
|
||||
})
|
||||
transfer_debit_aml = aml_obj.create(transfer_debit_aml_dict)
|
||||
dst_move.post()
|
||||
return transfer_debit_aml
|
||||
|
||||
def _get_move_vals(self, journal=None):
|
||||
""" Return dict to create the payment move
|
||||
"""
|
||||
journal = journal or self.journal_id
|
||||
if not journal.sequence_id:
|
||||
raise UserError(_('Configuration Error !'), _('The journal %s does not have a sequence, please specify one.') % journal.name)
|
||||
if not journal.sequence_id.active:
|
||||
raise UserError(_('Configuration Error !'), _('The sequence of journal %s is deactivated.') % journal.name)
|
||||
name = journal.with_context(ir_sequence_date=self.date).sequence_id.next_by_id()
|
||||
return {
|
||||
'name': name,
|
||||
'date': self.date or self.payment_date,
|
||||
'ref': self.communication or '',
|
||||
'company_id': self.company_id.id,
|
||||
'journal_id': journal.id,
|
||||
}
|
||||
|
||||
def _get_shared_move_line_vals(self, debit, credit, amount_currency, move_id, invoice_id=False):
|
||||
""" Returns values common to both move lines (except for debit, credit and amount_currency which are reversed)
|
||||
"""
|
||||
return {
|
||||
'partner_id': self.payment_type in ('inbound', 'outbound') and self.partner_id.commercial_partner_id.id or False,
|
||||
'invoice': invoice_id and invoice_id.id or False,
|
||||
'move_id': move_id,
|
||||
'debit': debit,
|
||||
'credit': credit,
|
||||
'amount_currency': amount_currency or False,
|
||||
}
|
||||
|
||||
def _get_counterpart_move_line_vals(self, invoice=False):
|
||||
if self.payment_type == 'transfer':
|
||||
name = self.name
|
||||
else:
|
||||
name = invoice and invoice.number + ': ' or ''
|
||||
if self.partner_type == 'customer':
|
||||
if self.payment_type == 'inbound':
|
||||
name += _("Customer Payment")
|
||||
elif self.payment_type == 'outbound':
|
||||
name += _("Customer Refund")
|
||||
elif self.partner_type == 'supplier':
|
||||
if self.payment_type == 'inbound':
|
||||
name += _("Supplier Refund")
|
||||
elif self.payment_type == 'outbound':
|
||||
name += _("Supplier Payment")
|
||||
return {
|
||||
'name': name,
|
||||
'account_id': self.destination_account_id.id,
|
||||
'journal_id': self.journal_id.id,
|
||||
'currency_id': self.currency_id != self.company_id.currency_id and self.currency_id.id or False,
|
||||
'payment_id': self.id,
|
||||
}
|
||||
|
||||
def _get_liquidity_move_line_vals(self, amount):
|
||||
name = self.name
|
||||
if self.payment_type == 'transfer':
|
||||
name = _('Transfer to %s') % self.destination_journal_id.name
|
||||
vals = {
|
||||
'name': name,
|
||||
'account_id': self.payment_type in ('outbound','transfer') and self.journal_id.default_debit_account_id.id or self.journal_id.default_credit_account_id.id,
|
||||
'payment_id': self.id,
|
||||
'journal_id': self.journal_id.id,
|
||||
'currency_id': self.currency_id != self.company_id.currency_id and self.currency_id.id or False,
|
||||
}
|
||||
|
||||
# If the journal has a currency specified, the journal item need to be expressed in this currency
|
||||
if self.journal_id.currency_id and self.currency_id != self.journal_id.currency_id:
|
||||
amount = self.currency_id.with_context(date=self.payment_date).compute(amount, self.journal_id.currency_id)
|
||||
debit, credit, amount_currency = self.env['account.move.line'].with_context(date=self.payment_date).compute_amount_fields(amount, self.journal_id.currency_id, self.company_id.currency_id)
|
||||
vals.update({
|
||||
'amount_currency': amount_currency,
|
||||
'currency_id': self.journal_id.currency_id.id,
|
||||
})
|
||||
|
||||
return vals
|
||||
@@ -1,22 +0,0 @@
|
||||
-
|
||||
I configure automatically if the country is set on the company, mainly for online offers.
|
||||
-
|
||||
!python {model: account.installer}: |
|
||||
modules = self.pool.get('ir.module.module')
|
||||
wizards = self.pool.get('ir.actions.todo')
|
||||
wiz = wizards.browse(cr, uid, ref('account.account_configuration_installer_todo'))
|
||||
part = self.pool.get('res.partner').browse(cr, uid, ref('base.main_partner'))
|
||||
# if we know the country and the wizard has not yet been executed, we do it
|
||||
if (part.country_id.id) and (part.country_id.code) and (wiz.state=='open'):
|
||||
mod = 'l10n_'+part.country_id.code.lower()
|
||||
ids = modules.search(cr, uid, [ ('name','=',mod) ], context=context)
|
||||
if ids:
|
||||
wizards.write(cr, uid, [ref('account.account_configuration_installer_todo')], {
|
||||
'state': 'done'
|
||||
})
|
||||
wiz_id = self.create(cr, uid, {
|
||||
'charts': mod
|
||||
})
|
||||
self.execute_simple(cr, uid, [wiz_id])
|
||||
modules.state_update(cr, uid, ids,
|
||||
'to install', ['uninstalled'], context=context)
|
||||
@@ -1,159 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<report
|
||||
auto="False"
|
||||
id="account_intracom"
|
||||
menu="False"
|
||||
model="account.move.line"
|
||||
name="account.intracom"
|
||||
string="IntraCom"
|
||||
/>
|
||||
|
||||
<!-- QWeb Reports -->
|
||||
<report
|
||||
id="action_report_vat"
|
||||
model="account.tax.code"
|
||||
report_type="qweb-pdf"
|
||||
string="Account tax"
|
||||
name="account.report_vat"
|
||||
file="account.report_vat"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="account_invoices"
|
||||
model="account.invoice"
|
||||
string="Invoices"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_invoice"
|
||||
file="account.report_invoice"
|
||||
attachment_use="True"
|
||||
attachment="(object.state in ('open','paid')) and ('INV'+(object.number or '').replace('/','')+'.pdf')"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_trial_balance"
|
||||
model="account.balance.report"
|
||||
string="Trial Balance"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_trialbalance"
|
||||
file="account.report_trialbalance"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_central_journal"
|
||||
model="account.journal.period"
|
||||
string="Central Journal"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_centraljournal"
|
||||
file="account.report_centraljournal"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_print_overdue"
|
||||
model="res.partner"
|
||||
report_type="qweb-pdf"
|
||||
string="Due Payments"
|
||||
name="account.report_overdue"
|
||||
file="account.report_overdue"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_general_journal"
|
||||
model="account.journal.period"
|
||||
string="General Journal"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_generaljournal"
|
||||
file="account.report_generaljournal"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_account_journal"
|
||||
model="account.journal.period"
|
||||
string="Journal"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_journal"
|
||||
file="account.report_journal"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_account_salepurchasejournal"
|
||||
model="account.journal.period"
|
||||
string="Journal"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_salepurchasejournal"
|
||||
file="account.report_salepurchasejournal"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_account_3rdparty_account_balance"
|
||||
model="account.account"
|
||||
string="Partner Balance"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_partnerbalance"
|
||||
file="account.report_partnerbalance"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_aged_partner_balance"
|
||||
model="res.partner"
|
||||
string="Aged Partner Balance"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_agedpartnerbalance"
|
||||
file="account.report_agedpartnerbalance"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_partner_ledger"
|
||||
model="res.partner"
|
||||
string="Partner Ledger"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_partnerledger"
|
||||
file="account.report_partnerledger"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_partner_ledger_other"
|
||||
model="res.partner"
|
||||
string="Partner Ledger"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_partnerledgerother"
|
||||
file="account.report_partnerledgerother"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_financial"
|
||||
model="account.financial.report"
|
||||
string="Financial report"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_financial"
|
||||
file="account.report_financial"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report
|
||||
id="action_report_general_ledger"
|
||||
model="account.report.general.ledger"
|
||||
string="General Ledger"
|
||||
report_type="qweb-pdf"
|
||||
name="account.report_generalledger"
|
||||
file="account.report_generalledger"
|
||||
menu="False"
|
||||
auto="False"
|
||||
/>
|
||||
|
||||
<!-- Menu items -->
|
||||
<menuitem
|
||||
id="menu_tax_report"
|
||||
name="Taxes"
|
||||
groups="group_account_user,group_account_manager"
|
||||
parent="account.menu_finance_generic_reporting"
|
||||
sequence="3"
|
||||
/>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,892 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import time
|
||||
import math
|
||||
|
||||
from openerp.osv import expression
|
||||
from openerp.tools.float_utils import float_round as round
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.exceptions import AccessError, UserError, ValidationError
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp import api, fields, models, _
|
||||
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Account Templates: Account, Tax, Tax Code and chart. + Wizard
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
|
||||
class AccountAccountTemplate(models.Model):
|
||||
_name = "account.account.template"
|
||||
_description = 'Templates for Accounts'
|
||||
_order = "code"
|
||||
|
||||
name = fields.Char(required=True, index=True)
|
||||
currency_id = fields.Many2one('res.currency', string='Secondary Currency', help="Forces all moves for this account to have this secondary currency.")
|
||||
code = fields.Char(size=64, required=True, index=True)
|
||||
user_type = fields.Many2one('account.account.type', string='Type', required=True,
|
||||
help="These types are defined according to your country. The type contains more information "\
|
||||
"about the account and its specificities.")
|
||||
reconcile = fields.Boolean(string='Allow Invoices & payments Matching', default=False,
|
||||
help="Check this option if you want the user to reconcile entries in this account.")
|
||||
note = fields.Text()
|
||||
tax_ids = fields.Many2many('account.tax.template', 'account_account_template_tax_rel', 'account_id', 'tax_id', string='Default Taxes')
|
||||
nocreate = fields.Boolean(string='Optional Create', default=False,
|
||||
help="If checked, the new chart of accounts will not contain this by default.")
|
||||
chart_template_id = fields.Many2one('account.chart.template', string='Chart Template',
|
||||
help="This optional field allow you to link an account template to a specific chart template that may differ from the one its root parent belongs to. This allow you "
|
||||
"to define chart templates that extend another and complete it with few new accounts (You don't need to define the whole structure that is common to both several times).")
|
||||
tag_ids = fields.Many2many('account.account.tag', 'account_account_template_account_tag', string='Account tag', help="Optional tags you may want to assign for custom reporting")
|
||||
|
||||
@api.multi
|
||||
@api.depends('name', 'code')
|
||||
def name_get(self):
|
||||
res = []
|
||||
for record in self:
|
||||
name = record.name
|
||||
if record.code:
|
||||
name = record.code + ' ' + name
|
||||
res.append((record.id, name))
|
||||
return res
|
||||
|
||||
|
||||
class AccountAddTmplWizard(models.TransientModel):
|
||||
"""Add one more account from the template.
|
||||
|
||||
With the 'nocreate' option, some accounts may not be created. Use this to add them later."""
|
||||
_name = 'account.addtmpl.wizard'
|
||||
|
||||
@api.model
|
||||
def _get_def_cparent(self):
|
||||
context = self._context or {}
|
||||
tmpl_obj = self.env['account.account.template']
|
||||
|
||||
tids = tmpl_obj.read([context['tmpl_ids']], ['parent_id'])
|
||||
if not tids or not tids[0]['parent_id']:
|
||||
return False
|
||||
ptids = tmpl_obj.read([tids[0]['parent_id'][0]], ['code'])
|
||||
account = False
|
||||
if not ptids or not ptids[0]['code']:
|
||||
raise UserError(_('There is no parent code for the template account.'))
|
||||
account = self.env['account.account'].search([('code', '=', ptids[0]['code'])], limit=1)
|
||||
return account
|
||||
|
||||
cparent_id = fields.Many2one('account.account', string='Parent target', default=lambda self: self._get_def_cparent(),
|
||||
help="Creates an account with the selected template under this existing parent.", required=True, domain=[('deprecated', '=', False)])
|
||||
|
||||
@api.multi
|
||||
def action_create(self):
|
||||
context = self._context or {}
|
||||
AccountObj = self.env['account.account']
|
||||
data = self.read()[0]
|
||||
company_id = AccountObj.read([data['cparent_id'][0]], ['company_id'])[0]['company_id'][0]
|
||||
account_template = self.env['account.account.template'].browse(context['tmpl_ids'])
|
||||
vals = {
|
||||
'name': account_template.name,
|
||||
'currency_id': account_template.currency_id and account_template.currency_id.id or False,
|
||||
'code': account_template.code,
|
||||
'user_type': account_template.user_type and account_template.user_type.id or False,
|
||||
'reconcile': account_template.reconcile,
|
||||
'note': account_template.note,
|
||||
'parent_id': data['cparent_id'][0],
|
||||
'company_id': company_id,
|
||||
}
|
||||
AccountObj.create(vals)
|
||||
return {'type': 'state', 'state': 'end'}
|
||||
|
||||
@api.multi
|
||||
def action_cancel(self):
|
||||
return {'type': 'state', 'state': 'end'}
|
||||
|
||||
|
||||
class AccountChartTemplate(models.Model):
|
||||
_name = "account.chart.template"
|
||||
_description = "Templates for Account Chart"
|
||||
|
||||
name = fields.Char(required=True)
|
||||
company_id = fields.Many2one('res.company', string='Company')
|
||||
parent_id = fields.Many2one('account.chart.template', string='Parent Chart Template')
|
||||
code_digits = fields.Integer(string='# of Digits', required=True, default=6, help="No. of Digits to use for account code")
|
||||
visible = fields.Boolean(string='Can be Visible?', default=True,
|
||||
help="Set this to False if you don't want this template to be used actively in the wizard that generate Chart of Accounts from "
|
||||
"templates, this is useful when you want to generate accounts of this template only when loading its child template.")
|
||||
currency_id = fields.Many2one('res.currency', string='Currency', required=True)
|
||||
use_anglo_saxon = fields.Boolean(string="Use Anglo-Saxon accounting", default=False)
|
||||
complete_tax_set = fields.Boolean(string='Complete Set of Taxes', default=True,
|
||||
help="This boolean helps you to choose if you want to propose to the user to encode the sale and purchase rates or choose from list "
|
||||
"of taxes. This last choice assumes that the set of tax defined on this template is complete")
|
||||
account_ids = fields.One2many('account.account.template', 'chart_template_id', string='Associated Account Templates')
|
||||
tax_template_ids = fields.One2many('account.tax.template', 'chart_template_id', string='Tax Template List',
|
||||
help='List of all the taxes that have to be installed by the wizard')
|
||||
bank_account_code_char = fields.Char(string='Code of the main bank account')
|
||||
transfer_account_id = fields.Many2one('account.account.template', string='Transfer Account', required=True,
|
||||
domain=lambda self: [('reconcile', '=', True), ('user_type.id', '=', self.env.ref('account.data_account_type_current_assets').id)],
|
||||
help="Intermediary account used when moving money from a liquidity account to another")
|
||||
income_currency_exchange_account_id = fields.Many2one('account.account.template',
|
||||
string="Gain Exchange Rate Account", domain=[('internal_type', '=', 'other'), ('deprecated', '=', False)])
|
||||
expense_currency_exchange_account_id = fields.Many2one('account.account.template',
|
||||
string="Loss Exchange Rate Account", domain=[('internal_type', '=', 'other'), ('deprecated', '=', False)])
|
||||
property_account_receivable = fields.Many2one('account.account.template', string='Receivable Account')
|
||||
property_account_payable = fields.Many2one('account.account.template', string='Payable Account')
|
||||
property_account_expense_categ = fields.Many2one('account.account.template', string='Expense Category Account')
|
||||
property_account_income_categ = fields.Many2one('account.account.template', string='Income Category Account')
|
||||
property_account_expense = fields.Many2one('account.account.template', string='Expense Account on Product Template')
|
||||
property_account_income = fields.Many2one('account.account.template', string='Income Account on Product Template')
|
||||
|
||||
@api.one
|
||||
def try_loading_for_current_company(self):
|
||||
self.ensure_one()
|
||||
company = self.env.user.company_id
|
||||
# If we don't have any chart of account on this company, install this chart of account
|
||||
if not company.chart_template_id:
|
||||
self.env['wizard.multi.charts.accounts'].create({
|
||||
'company_id': self.env.user.company_id.id,
|
||||
'chart_template_id': self.id,
|
||||
'code_digits': self.code_digits,
|
||||
'transfer_account_id': self.transfer_account_id.id,
|
||||
'currency_id': self.currency_id.id,
|
||||
'bank_account_code_char': self.bank_account_code_char,
|
||||
}).execute()
|
||||
|
||||
@api.multi
|
||||
def open_select_template_wizard(self):
|
||||
# Add action to open wizard to select between several templates
|
||||
if not self.company_id.chart_template_id:
|
||||
todo = self.env['ir.actions.todo']
|
||||
action_rec = self.env['ir.model.data'].xmlid_to_object('account.action_wizard_multi_chart')
|
||||
if action_rec:
|
||||
todo.create({'action_id': action_rec.id, 'name': _('Choose Accounting Template'), 'type': 'automatic'})
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def check_created_journals(self, vals_journal, company):
|
||||
"""
|
||||
This method used for checking journals already created or not. If not then create new journal.
|
||||
"""
|
||||
JournalObj = self.env['account.journal']
|
||||
rec_list = JournalObj.search([('name', '=', vals_journal['name']), ('company_id', '=', company.id)], limit=1)
|
||||
if not rec_list:
|
||||
journal = JournalObj.create(vals_journal)
|
||||
if vals_journal['type'] == 'general' and not company.currency_exchange_journal_id.id:
|
||||
company.write({'currency_exchange_journal_id': journal.id})
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def generate_journals(self, acc_template_ref, company, journals_dict=None):
|
||||
"""
|
||||
This method is used for creating journals.
|
||||
|
||||
:param chart_temp_id: Chart Template Id.
|
||||
:param acc_template_ref: Account templates reference.
|
||||
:param company_id: company_id selected from wizard.multi.charts.accounts.
|
||||
:returns: True
|
||||
"""
|
||||
for vals_journal in self._prepare_all_journals(acc_template_ref, company, journals_dict=journals_dict):
|
||||
self.check_created_journals(vals_journal, company)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _prepare_all_journals(self, acc_template_ref, company, journals_dict=None):
|
||||
def _get_analytic_journal(journal_type):
|
||||
# Get the analytic journal
|
||||
data = False
|
||||
try:
|
||||
if journal['type'] == 'sale':
|
||||
data = self.env.ref('account.analytic_journal_sale')
|
||||
elif journal['type'] == 'purchase':
|
||||
data = self.env.ref('account.exp')
|
||||
elif journal['type'] == 'general':
|
||||
pass
|
||||
except ValueError:
|
||||
pass
|
||||
return data and data.id or False
|
||||
|
||||
def _get_default_account(journal_vals, type='debit'):
|
||||
# Get the default accounts
|
||||
default_account = False
|
||||
if journal['type'] == 'sale':
|
||||
default_account = acc_template_ref.get(self.property_account_income_categ.id)
|
||||
elif journal['type'] == 'purchase':
|
||||
default_account = acc_template_ref.get(self.property_account_expense_categ.id)
|
||||
elif journal['type'] == 'general' and journal['name'] == _('Exchange Rate Journal'):
|
||||
if type=='credit':
|
||||
default_account = acc_template_ref.get(self.income_currency_exchange_account_id.id)
|
||||
else:
|
||||
default_account = acc_template_ref.get(self.expense_currency_exchange_account_id.id)
|
||||
return default_account
|
||||
|
||||
journals = [{'name': _('Customer Invoices'), 'type': 'sale', 'code': _('INV'), 'favorite': True},
|
||||
{'name': _('Supplier Bills'), 'type': 'purchase', 'code': _('EXJ'), 'favorite': True},
|
||||
{'name': _('Exchange Rate Journal'), 'type': 'general', 'code': _('EXCH'), 'favorite': False},
|
||||
{'name': _('Miscellaneous Journal'), 'type': 'general', 'code': _('MISC'), 'favorite': False},]
|
||||
if journals_dict != None:
|
||||
journals.extend(journals_dict)
|
||||
|
||||
self.ensure_one()
|
||||
journal_data = []
|
||||
for journal in journals:
|
||||
vals = {
|
||||
'type': journal['type'],
|
||||
'name': journal['name'],
|
||||
'code': journal['code'],
|
||||
'company_id': company.id,
|
||||
'analytic_journal_id': _get_analytic_journal(journal),
|
||||
'default_credit_account_id': _get_default_account(journal, 'credit'),
|
||||
'default_debit_account_id': _get_default_account(journal, 'debit'),
|
||||
'refund_sequence': True,
|
||||
'show_on_dashboard': journal['favorite'],
|
||||
}
|
||||
journal_data.append(vals)
|
||||
return journal_data
|
||||
|
||||
@api.multi
|
||||
def generate_properties(self, acc_template_ref, company):
|
||||
"""
|
||||
This method used for creating properties.
|
||||
|
||||
:param self: chart templates for which we need to create properties
|
||||
:param acc_template_ref: Mapping between ids of account templates and real accounts created from them
|
||||
:param company_id: company_id selected from wizard.multi.charts.accounts.
|
||||
:returns: True
|
||||
"""
|
||||
self.ensure_one()
|
||||
PropertyObj = self.env['ir.property']
|
||||
todo_list = [
|
||||
('property_account_receivable', 'res.partner', 'account.account'),
|
||||
('property_account_payable', 'res.partner', 'account.account'),
|
||||
('property_account_expense_categ', 'product.category', 'account.account'),
|
||||
('property_account_income_categ', 'product.category', 'account.account'),
|
||||
('property_account_expense', 'product.template', 'account.account'),
|
||||
('property_account_income', 'product.template', 'account.account'),
|
||||
]
|
||||
for record in todo_list:
|
||||
account = getattr(self, record[0])
|
||||
value = account and 'account.account,' + str(acc_template_ref[account.id]) or False
|
||||
if value:
|
||||
field = self.env['ir.model.fields'].search([('name', '=', record[0]), ('model', '=', record[1]), ('relation', '=', record[2])], limit=1)
|
||||
vals = {
|
||||
'name': record[0],
|
||||
'company_id': company.id,
|
||||
'fields_id': field.id,
|
||||
'value': value,
|
||||
}
|
||||
properties = PropertyObj.search([('name', '=', record[0]), ('company_id', '=', company.id)])
|
||||
if properties:
|
||||
#the property exist: modify it
|
||||
properties.write(vals)
|
||||
else:
|
||||
#create the property
|
||||
PropertyObj.create(vals)
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _install_template(self, company, code_digits=None, transfer_account_id=None, obj_wizard=None, acc_ref=None, taxes_ref=None):
|
||||
""" Recursively load the template objects and create the real objects from them.
|
||||
|
||||
:param company: company the wizard is running for
|
||||
:param code_digits: number of digits the accounts code should have in the COA
|
||||
:param transfer_account_id: reference to the account template that will be used as intermediary account for transfers between 2 liquidity accounts
|
||||
:param obj_wizard: the current wizard for generating the COA from the templates
|
||||
:param acc_ref: Mapping between ids of account templates and real accounts created from them
|
||||
:param taxes_ref: Mapping between ids of tax templates and real taxes created from them
|
||||
:returns: tuple with a dictionary containing
|
||||
* the mapping between the account template ids and the ids of the real accounts that have been generated
|
||||
from them, as first item,
|
||||
* a similar dictionary for mapping the tax templates and taxes, as second item,
|
||||
:rtype: tuple(dict, dict, dict)
|
||||
"""
|
||||
self.ensure_one()
|
||||
if acc_ref is None:
|
||||
acc_ref = {}
|
||||
if taxes_ref is None:
|
||||
taxes_ref = {}
|
||||
if self.parent_id:
|
||||
tmp1, tmp2 = self.parent_id._install_template(company, code_digits=code_digits, transfer_account_id=transfer_account_id, acc_ref=acc_ref, taxes_ref=taxes_ref)
|
||||
acc_ref.update(tmp1)
|
||||
taxes_ref.update(tmp2)
|
||||
tmp1, tmp2 = self._load_template(company, code_digits=code_digits, transfer_account_id=transfer_account_id, account_ref=acc_ref, taxes_ref=taxes_ref)
|
||||
acc_ref.update(tmp1)
|
||||
taxes_ref.update(tmp2)
|
||||
return acc_ref, taxes_ref
|
||||
|
||||
@api.multi
|
||||
def _load_template(self, company, code_digits=None, transfer_account_id=None, account_ref=None, taxes_ref=None):
|
||||
""" Generate all the objects from the templates
|
||||
|
||||
:param company: company the wizard is running for
|
||||
:param code_digits: number of digits the accounts code should have in the COA
|
||||
:param transfer_account_id: reference to the account template that will be used as intermediary account for transfers between 2 liquidity accounts
|
||||
:param acc_ref: Mapping between ids of account templates and real accounts created from them
|
||||
:param taxes_ref: Mapping between ids of tax templates and real taxes created from them
|
||||
:returns: tuple with a dictionary containing
|
||||
* the mapping between the account template ids and the ids of the real accounts that have been generated
|
||||
from them, as first item,
|
||||
* a similar dictionary for mapping the tax templates and taxes, as second item,
|
||||
:rtype: tuple(dict, dict, dict)
|
||||
"""
|
||||
self.ensure_one()
|
||||
if account_ref is None:
|
||||
account_ref = {}
|
||||
if taxes_ref is None:
|
||||
taxes_ref = {}
|
||||
if not code_digits:
|
||||
code_digits = self.code_digits
|
||||
if not transfer_account_id:
|
||||
transfer_account_id = self.transfer_account_id
|
||||
AccountTaxObj = self.env['account.tax']
|
||||
|
||||
# Generate taxes from templates.
|
||||
generated_tax_res = self.tax_template_ids._generate_tax(company)
|
||||
taxes_ref.update(generated_tax_res['tax_template_to_tax'])
|
||||
|
||||
# Generating Accounts from templates.
|
||||
account_template_ref = self.generate_account(taxes_ref, account_ref, code_digits, company)
|
||||
account_ref.update(account_template_ref)
|
||||
|
||||
# writing account values after creation of accounts
|
||||
company.transfer_account_id = account_template_ref[transfer_account_id.id]
|
||||
for key, value in generated_tax_res['account_dict'].items():
|
||||
if value['refund_account_id'] or value['account_id']:
|
||||
AccountTaxObj.browse(key).write({
|
||||
'refund_account_id': account_ref.get(value['refund_account_id'], False),
|
||||
'account_id': account_ref.get(value['account_id'], False),
|
||||
})
|
||||
|
||||
# Create Journals
|
||||
self.generate_journals(account_ref, company)
|
||||
|
||||
# generate properties function
|
||||
self.generate_properties(account_ref, company)
|
||||
|
||||
# Generate Fiscal Position , Fiscal Position Accounts and Fiscal Position Taxes from templates
|
||||
self.generate_fiscal_position(taxes_ref, account_ref, company)
|
||||
|
||||
return account_ref, taxes_ref
|
||||
|
||||
@api.multi
|
||||
def generate_account(self, tax_template_ref, acc_template_ref, code_digits, company):
|
||||
""" This method for generating accounts from templates.
|
||||
|
||||
:param tax_template_ref: Taxes templates reference for write taxes_id in account_account.
|
||||
:param acc_template_ref: dictionary with the mappping between the account templates and the real accounts.
|
||||
:param code_digits: number of digits got from wizard.multi.charts.accounts, this is use for account code.
|
||||
:param company_id: company_id selected from wizard.multi.charts.accounts.
|
||||
:returns: return acc_template_ref for reference purpose.
|
||||
:rtype: dict
|
||||
"""
|
||||
self.ensure_one()
|
||||
account_tmpl_obj = self.env['account.account.template']
|
||||
acc_template = account_tmpl_obj.search([('nocreate', '!=', True), ('chart_template_id', '=', self.id)], order='id')
|
||||
for account_template in acc_template:
|
||||
tax_ids = []
|
||||
for tax in account_template.tax_ids:
|
||||
tax_ids.append(tax_template_ref[tax.id])
|
||||
|
||||
code_main = account_template.code and len(account_template.code) or 0
|
||||
code_acc = account_template.code or ''
|
||||
if code_main > 0 and code_main <= code_digits:
|
||||
code_acc = str(code_acc) + (str('0'*(code_digits-code_main)))
|
||||
vals = {
|
||||
'name': account_template.name,
|
||||
'currency_id': account_template.currency_id and account_template.currency_id.id or False,
|
||||
'code': code_acc,
|
||||
'user_type': account_template.user_type and account_template.user_type.id or False,
|
||||
'reconcile': account_template.reconcile,
|
||||
'note': account_template.note,
|
||||
'tax_ids': [(6, 0, tax_ids)],
|
||||
'company_id': company.id,
|
||||
'tag_ids': [(6, 0, [t.id for t in account_template.tag_ids])],
|
||||
}
|
||||
new_account = self.env['account.account'].create(vals)
|
||||
acc_template_ref[account_template.id] = new_account.id
|
||||
return acc_template_ref
|
||||
|
||||
@api.multi
|
||||
def generate_fiscal_position(self, tax_template_ref, acc_template_ref, company):
|
||||
""" This method generate Fiscal Position, Fiscal Position Accounts and Fiscal Position Taxes from templates.
|
||||
|
||||
:param chart_temp_id: Chart Template Id.
|
||||
:param taxes_ids: Taxes templates reference for generating account.fiscal.position.tax.
|
||||
:param acc_template_ref: Account templates reference for generating account.fiscal.position.account.
|
||||
:param company_id: company_id selected from wizard.multi.charts.accounts.
|
||||
:returns: True
|
||||
"""
|
||||
self.ensure_one()
|
||||
positions = self.env['account.fiscal.position.template'].search([('chart_template_id', '=', self.id)])
|
||||
for position in positions:
|
||||
new_fp = self.env['account.fiscal.position'].create({'company_id': company.id, 'name': position.name, 'note': position.note})
|
||||
for tax in position.tax_ids:
|
||||
self.env['account.fiscal.position.tax'].create({
|
||||
'tax_src_id': tax_template_ref[tax.tax_src_id.id],
|
||||
'tax_dest_id': tax.tax_dest_id and tax_template_ref[tax.tax_dest_id.id] or False,
|
||||
'position_id': new_fp.id
|
||||
})
|
||||
for acc in position.account_ids:
|
||||
self.env['account.fiscal.position.account'].create({
|
||||
'account_src_id': acc_template_ref[acc.account_src_id.id],
|
||||
'account_dest_id': acc_template_ref[acc.account_dest_id.id],
|
||||
'position_id': new_fp.id
|
||||
})
|
||||
return True
|
||||
|
||||
|
||||
class AccountTaxTemplate(models.Model):
|
||||
_name = 'account.tax.template'
|
||||
_description = 'Templates for Taxes'
|
||||
_order = 'id'
|
||||
|
||||
chart_template_id = fields.Many2one('account.chart.template', string='Chart Template', required=True)
|
||||
|
||||
name = fields.Char(string='Tax Name', required=True, translate=True)
|
||||
type_tax_use = fields.Selection([('sale', 'Sales'), ('purchase', 'Purchases'), ('none', 'None')], string='Tax Scope', required=True, default="sale",
|
||||
help="Determines where the tax is selectable. Note : 'None' means a tax can't be used by itself, however it can still be used in a group.")
|
||||
amount_type = fields.Selection(default='percent', string="Tax Computation", required=True,
|
||||
selection=[('group', 'Group of Taxes'), ('fixed', 'Fixed'), ('percent', 'Percentage of Price'), ('division', 'Percentage of Price Tax Included')])
|
||||
active = fields.Boolean(default=True, help="Set active to false to hide the tax without removing it.")
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.user.company_id)
|
||||
children_tax_ids = fields.Many2many('account.tax.template', 'account_tax_template_filiation_rel', 'parent_tax', 'child_tax', string='Children Taxes')
|
||||
sequence = fields.Integer(required=True, default=1,
|
||||
help="The sequence field is used to define order in which the tax lines are applied.")
|
||||
amount = fields.Float(required=True, digits=(16, 3))
|
||||
account_id = fields.Many2one('account.account.template', string='Tax Account', ondelete='restrict',
|
||||
help="Account that will be set on invoice tax lines for invoices. Leave empty to use the expense account.", oldname='account_collected_id')
|
||||
refund_account_id = fields.Many2one('account.account.template', string='Tax Account on Refunds', ondelete='restrict',
|
||||
help="Account that will be set on invoice tax lines for refunds. Leave empty to use the expense account.", oldname='account_paid_id')
|
||||
description = fields.Char(string='Display on Invoices')
|
||||
price_include = fields.Boolean(string='Included in Price', default=False,
|
||||
help="Check this if the price you use on the product and invoices includes this tax.")
|
||||
include_base_amount = fields.Boolean(string='Affect Subsequent Taxes', default=False,
|
||||
help="If set, taxes which are computed after this one will be computed based on the price tax included.")
|
||||
analytic = fields.Boolean(string="Analytic Cost", help="If set, the amount computed by this tax will be assigned to the same analytic account as the invoice line (if any)")
|
||||
tag_ids = fields.Many2many('account.account.tag', string='Account tag', help="Optional tags you may want to assign for custom reporting")
|
||||
|
||||
_sql_constraints = [
|
||||
('name_company_uniq', 'unique(name, company_id)', 'Tax names must be unique !'),
|
||||
]
|
||||
|
||||
@api.multi
|
||||
@api.depends('name', 'description')
|
||||
def name_get(self):
|
||||
res = []
|
||||
for record in self:
|
||||
name = record.description and record.description or record.name
|
||||
res.append((record.id, name))
|
||||
return res
|
||||
|
||||
def _get_tax_vals(self, company):
|
||||
""" This method generates a dictionnary of all the values for the tax that will be created.
|
||||
"""
|
||||
self.ensure_one()
|
||||
return {
|
||||
'name': self.name,
|
||||
'type_tax_use': self.type_tax_use,
|
||||
'amount_type': self.amount_type,
|
||||
'active': self.active,
|
||||
'company_id': company.id,
|
||||
'sequence': self.sequence,
|
||||
'amount': self.amount,
|
||||
'description': self.description,
|
||||
'price_include': self.price_include,
|
||||
'include_base_amount': self.include_base_amount,
|
||||
'analytic': self.analytic,
|
||||
'tag_ids': [(6, 0, [t.id for t in self.tag_ids])],
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def _generate_tax(self, company):
|
||||
""" This method generate taxes from templates.
|
||||
|
||||
:param company: the company for which the taxes should be created from templates in self
|
||||
:returns: {
|
||||
'tax_template_to_tax': mapping between tax template and the newly generated taxes corresponding,
|
||||
'account_dict': dictionary containing a to-do list with all the accounts to assign on new taxes
|
||||
}
|
||||
"""
|
||||
todo_dict = {}
|
||||
tax_template_to_tax = {}
|
||||
for tax in self:
|
||||
# Compute children tax ids
|
||||
children_ids = []
|
||||
for child_tax in tax.children_tax_ids:
|
||||
if tax_template_to_tax.get(child_tax.id):
|
||||
children_ids.append(tax_template_to_tax[child_tax.id])
|
||||
vals_tax = tax._get_tax_vals(company)
|
||||
vals_tax['children_tax_ids'] = children_ids and [(6, 0, children_ids)] or []
|
||||
new_tax = self.env['account.tax'].create(vals_tax)
|
||||
tax_template_to_tax[tax.id] = new_tax.id
|
||||
# Since the accounts have not been created yet, we have to wait before filling these fields
|
||||
todo_dict[new_tax.id] = {
|
||||
'account_id': tax.account_id.id,
|
||||
'refund_account_id': tax.refund_account_id.id,
|
||||
}
|
||||
|
||||
return {
|
||||
'tax_template_to_tax': tax_template_to_tax,
|
||||
'account_dict': todo_dict
|
||||
}
|
||||
|
||||
|
||||
# Fiscal Position Templates
|
||||
|
||||
class AccountFiscalPositionTemplate(models.Model):
|
||||
_name = 'account.fiscal.position.template'
|
||||
_description = 'Template for Fiscal Position'
|
||||
|
||||
name = fields.Char(string='Fiscal Position Template', required=True)
|
||||
chart_template_id = fields.Many2one('account.chart.template', string='Chart Template', required=True)
|
||||
account_ids = fields.One2many('account.fiscal.position.account.template', 'position_id', string='Account Mapping')
|
||||
tax_ids = fields.One2many('account.fiscal.position.tax.template', 'position_id', string='Tax Mapping')
|
||||
note = fields.Text(string='Notes')
|
||||
|
||||
|
||||
class AccountFiscalPositionTaxTemplate(models.Model):
|
||||
_name = 'account.fiscal.position.tax.template'
|
||||
_description = 'Template Tax Fiscal Position'
|
||||
_rec_name = 'position_id'
|
||||
|
||||
position_id = fields.Many2one('account.fiscal.position.template', string='Fiscal Position', required=True, ondelete='cascade')
|
||||
tax_src_id = fields.Many2one('account.tax.template', string='Tax Source', required=True)
|
||||
tax_dest_id = fields.Many2one('account.tax.template', string='Replacement Tax')
|
||||
|
||||
|
||||
class AccountFiscalPositionAccountTemplate(models.Model):
|
||||
_name = 'account.fiscal.position.account.template'
|
||||
_description = 'Template Account Fiscal Mapping'
|
||||
_rec_name = 'position_id'
|
||||
|
||||
position_id = fields.Many2one('account.fiscal.position.template', string='Fiscal Mapping', required=True, ondelete='cascade')
|
||||
account_src_id = fields.Many2one('account.account.template', string='Account Source', required=True)
|
||||
account_dest_id = fields.Many2one('account.account.template', string='Account Destination', required=True)
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Account generation from template wizards
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
class WizardMultiChartsAccounts(models.TransientModel):
|
||||
"""
|
||||
Create a new account chart for a company.
|
||||
Wizards ask for:
|
||||
* a company
|
||||
* an account chart template
|
||||
* a number of digits for formatting code of non-view accounts
|
||||
* a list of bank accounts owned by the company
|
||||
Then, the wizard:
|
||||
* generates all accounts from the template and assigns them to the right company
|
||||
* generates all taxes and tax codes, changing account assignations
|
||||
* generates all accounting properties and assigns them correctly
|
||||
"""
|
||||
|
||||
_name = 'wizard.multi.charts.accounts'
|
||||
_inherit = 'res.config'
|
||||
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True)
|
||||
currency_id = fields.Many2one('res.currency', string='Currency', help="Currency as per company's country.", required=True)
|
||||
only_one_chart_template = fields.Boolean(string='Only One Chart Template Available')
|
||||
chart_template_id = fields.Many2one('account.chart.template', string='Chart Template', required=True)
|
||||
bank_accounts_id = fields.One2many('account.bank.accounts.wizard', 'bank_account_id', string='Cash and Banks', required=True)
|
||||
bank_account_code_char = fields.Char('Bank Accounts Code')
|
||||
code_digits = fields.Integer(string='# of Digits', required=True, help="No. of Digits to use for account code")
|
||||
sale_tax = fields.Many2one('account.tax.template', string='Default Sales Tax')
|
||||
purchase_tax = fields.Many2one('account.tax.template', string='Default Purchase Tax')
|
||||
sale_tax_rate = fields.Float(string='Sales Tax(%)')
|
||||
use_anglo_saxon = fields.Boolean(string='Use Anglo-Saxon Accounting', related='chart_template_id.use_anglo_saxon')
|
||||
transfer_account_id = fields.Many2one('account.account.template', required=True, string='Transfer Account',
|
||||
domain=lambda self: [('reconcile', '=', True), ('user_type.id', '=', self.env.ref('account.data_account_type_current_assets').id)],
|
||||
help="Intermediary account used when moving money from a liquidity account to another")
|
||||
purchase_tax_rate = fields.Float(string='Purchase Tax(%)')
|
||||
complete_tax_set = fields.Boolean('Complete Set of Taxes',
|
||||
help="This boolean helps you to choose if you want to propose to the user to encode the sales and purchase rates or use "
|
||||
"the usual m2o fields. This last choice assumes that the set of tax defined for the chosen template is complete")
|
||||
|
||||
@api.model
|
||||
def _get_chart_parent_ids(self, chart_template):
|
||||
""" Returns the IDs of all ancestor charts, including the chart itself.
|
||||
(inverse of child_of operator)
|
||||
|
||||
:param browse_record chart_template: the account.chart.template record
|
||||
:return: the IDS of all ancestor charts, including the chart itself.
|
||||
"""
|
||||
result = [chart_template.id]
|
||||
while chart_template.parent_id:
|
||||
chart_template = chart_template.parent_id
|
||||
result.append(chart_template.id)
|
||||
return result
|
||||
|
||||
@api.onchange('sale_tax_rate')
|
||||
def onchange_tax_rate(self):
|
||||
self.purchase_tax_rate = self.sale_tax_rate or False
|
||||
|
||||
@api.onchange('chart_template_id')
|
||||
def onchange_chart_template_id(self):
|
||||
res = {}
|
||||
tax_templ_obj = self.env['account.tax.template']
|
||||
if self.chart_template_id:
|
||||
currency_id = self.chart_template_id.currency_id and self.chart_template_id.currency_id.id or self.env.user.company_id.currency_id.id
|
||||
self.complete_tax_set = self.chart_template_id.complete_tax_set
|
||||
self.currency_id = currency_id
|
||||
if self.chart_template_id.complete_tax_set:
|
||||
# default tax is given by the lowest sequence. For same sequence we will take the latest created as it will be the case for tax created while isntalling the generic chart of account
|
||||
chart_ids = self._get_chart_parent_ids(self.chart_template_id)
|
||||
base_tax_domain = [('chart_template_id', 'in', chart_ids)]
|
||||
sale_tax_domain = base_tax_domain + [('type_tax_use', '=', 'sale')]
|
||||
purchase_tax_domain = base_tax_domain + [('type_tax_use', '=', 'purchase')]
|
||||
sale_tax = tax_templ_obj.search(sale_tax_domain, order="sequence, id desc", limit=1)
|
||||
purchase_tax = tax_templ_obj.search(purchase_tax_domain, order="sequence, id desc", limit=1)
|
||||
self.sale_tax = sale_tax.id
|
||||
self.purchase_tax = purchase_tax.id
|
||||
res.setdefault('domain', {})
|
||||
res['domain']['sale_tax'] = repr(sale_tax_domain)
|
||||
res['domain']['purchase_tax'] = repr(purchase_tax_domain)
|
||||
if self.chart_template_id.transfer_account_id:
|
||||
self.transfer_account_id = self.chart_template_id.transfer_account_id.id
|
||||
if self.chart_template_id.code_digits:
|
||||
self.code_digits = self.chart_template_id.code_digits
|
||||
if self.chart_template_id.bank_account_code_char:
|
||||
self.bank_account_code_char = self.chart_template_id.bank_account_code_char
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
context = self._context or {}
|
||||
res = super(WizardMultiChartsAccounts, self).default_get(fields)
|
||||
tax_templ_obj = self.env['account.tax.template']
|
||||
account_chart_template = self.env['account.chart.template']
|
||||
|
||||
if 'bank_accounts_id' in fields:
|
||||
res.update({'bank_accounts_id': [{'acc_name': _('Cash'), 'account_type': 'cash'}, {'acc_name': _('Bank'), 'account_type': 'bank'}]})
|
||||
if 'company_id' in fields:
|
||||
res.update({'company_id': self.env.user.company_id.id})
|
||||
if 'currency_id' in fields:
|
||||
company_id = res.get('company_id') or False
|
||||
if company_id:
|
||||
company = self.env['res.company'].browse(company_id)
|
||||
currency_id = company.on_change_country(company.country_id.id)['value']['currency_id']
|
||||
res.update({'currency_id': currency_id})
|
||||
|
||||
chart_templates = account_chart_template.search([('visible', '=', True)])
|
||||
if chart_templates:
|
||||
#in order to set default chart which was last created set max of ids.
|
||||
chart_id = max(chart_templates.ids)
|
||||
if context.get("default_charts"):
|
||||
model_data = self.env['ir.model.data'].search_read([('model', '=', 'account.chart.template'), ('module', '=', context.get("default_charts"))], ['res_id'])
|
||||
if model_data:
|
||||
chart_id = model_data[0]['res_id']
|
||||
chart = account_chart_template.browse(chart_id)
|
||||
chart_hierarchy_ids = self._get_chart_parent_ids(chart)
|
||||
if 'chart_template_id' in fields:
|
||||
res.update({'only_one_chart_template': len(chart_templates) == 1,
|
||||
'chart_template_id': chart_id})
|
||||
if 'sale_tax' in fields:
|
||||
sale_tax = tax_templ_obj.search([('chart_template_id', 'in', chart_hierarchy_ids),
|
||||
('type_tax_use', '=', 'sale')], limit=1, order='sequence')
|
||||
res.update({'sale_tax': sale_tax and sale_tax.id or False})
|
||||
if 'purchase_tax' in fields:
|
||||
purchase_tax = tax_templ_obj.search([('chart_template_id', 'in', chart_hierarchy_ids),
|
||||
('type_tax_use', '=', 'purchase')], limit=1, order='sequence')
|
||||
res.update({'purchase_tax': purchase_tax and purchase_tax.id or False})
|
||||
res.update({
|
||||
'purchase_tax_rate': 15.0,
|
||||
'sale_tax_rate': 15.0,
|
||||
})
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
|
||||
context = self._context or {}
|
||||
res = super(WizardMultiChartsAccounts, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=False)
|
||||
cmp_select = []
|
||||
CompanyObj = self.env['res.company']
|
||||
|
||||
companies = CompanyObj.search([])
|
||||
#display in the widget selection of companies, only the companies that haven't been configured yet (but don't care about the demo chart of accounts)
|
||||
self._cr.execute("SELECT company_id FROM account_account WHERE deprecated = 'f' AND name != 'Chart For Automated Tests' AND name NOT LIKE '%(test)'")
|
||||
configured_cmp = [r[0] for r in self._cr.fetchall()]
|
||||
unconfigured_cmp = list(set(companies.ids) - set(configured_cmp))
|
||||
for field in res['fields']:
|
||||
if field == 'company_id':
|
||||
res['fields'][field]['domain'] = [('id', 'in', unconfigured_cmp)]
|
||||
res['fields'][field]['selection'] = [('', '')]
|
||||
if unconfigured_cmp:
|
||||
cmp_select = [(line.id, line.name) for line in CompanyObj.browse(unconfigured_cmp)]
|
||||
res['fields'][field]['selection'] = cmp_select
|
||||
return res
|
||||
|
||||
@api.one
|
||||
def _create_tax_templates_from_rates(self, company_id):
|
||||
'''
|
||||
This function checks if the chosen chart template is configured as containing a full set of taxes, and if
|
||||
it's not the case, it creates the templates for account.tax object accordingly to the provided sale/purchase rates.
|
||||
Then it saves the new tax templates as default taxes to use for this chart template.
|
||||
|
||||
:param company_id: id of the company for wich the wizard is running
|
||||
:return: True
|
||||
'''
|
||||
obj_tax_temp = self.env['account.tax.template']
|
||||
all_parents = self._get_chart_parent_ids(self.chart_template_id)
|
||||
# create tax templates from purchase_tax_rate and sale_tax_rate fields
|
||||
if not self.chart_template_id.complete_tax_set:
|
||||
value = self.sale_tax_rate
|
||||
ref_taxs = obj_tax_temp.search([('type_tax_use', '=', 'sale'), ('chart_template_id', 'in', all_parents)], order="sequence, id desc", limit=1)
|
||||
ref_taxs.write({'amount': value, 'name': _('Tax %.2f%%') % value})
|
||||
value = self.purchase_tax_rate
|
||||
ref_taxs = obj_tax_temp.search([('type_tax_use', '=', 'purchase'), ('chart_template_id', 'in', all_parents)], order="sequence, id desc", limit=1)
|
||||
ref_taxs.write({'amount': value, 'name': _('Purchase Tax %.2f%%') % value})
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def execute(self):
|
||||
'''
|
||||
This function is called at the confirmation of the wizard to generate the COA from the templates. It will read
|
||||
all the provided information to create the accounts, the banks, the journals, the taxes, the
|
||||
accounting properties... accordingly for the chosen company.
|
||||
'''
|
||||
if self._uid != self.sudo()._uid and not self.env.user.has_group('base.group_erp_manager'):
|
||||
raise AccessError(_("Only administrators can change the settings"))
|
||||
ir_values_obj = self.env['ir.values']
|
||||
company = self.company_id
|
||||
self.company_id.write({'currency_id': self.currency_id.id,
|
||||
'accounts_code_digits': self.code_digits,
|
||||
'anglo_saxon_accounting': self.use_anglo_saxon,
|
||||
'bank_account_code_char': self.bank_account_code_char,
|
||||
'chart_template_id': self.chart_template_id.id})
|
||||
|
||||
# When we install the CoA of first company, set the currency to price types and pricelists
|
||||
if company.id == 1:
|
||||
for reference in ['product.list_price', 'product.standard_price', 'product.list0', 'purchase.list0']:
|
||||
try:
|
||||
tmp2 = self.env.ref(reference).write({'currency_id': self.currency_id.id})
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# If the floats for sale/purchase rates have been filled, create templates from them
|
||||
self._create_tax_templates_from_rates(company.id)
|
||||
|
||||
# Install all the templates objects and generate the real objects
|
||||
|
||||
acc_template_ref, taxes_ref = self.chart_template_id._install_template(company, code_digits=self.code_digits, transfer_account_id=self.transfer_account_id)
|
||||
|
||||
# write values of default taxes for product as super user
|
||||
if self.sale_tax and taxes_ref:
|
||||
ir_values_obj.sudo().set_default('product.template', "taxes_id", [taxes_ref[self.sale_tax.id]], for_all_users=True, company_id=company.id)
|
||||
if self.purchase_tax and taxes_ref:
|
||||
ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [taxes_ref[self.purchase_tax.id]], for_all_users=True, company_id=company.id)
|
||||
|
||||
# Create Bank journals
|
||||
self._create_bank_journals_from_o2m(company, acc_template_ref)
|
||||
return {}
|
||||
|
||||
@api.model
|
||||
def _prepare_bank_journal(self, company, line, default_account_id):
|
||||
'''
|
||||
This function prepares the value to use for the creation of a bank journal created through the wizard of
|
||||
generating COA from templates.
|
||||
|
||||
:param line: dictionary containing the values encoded by the user related to his bank account
|
||||
:param default_account_id: id of the default debit.credit account created before for this journal.
|
||||
:param company_id: id of the company for which the wizard is running
|
||||
:return: mapping of field names and values
|
||||
:rtype: dict
|
||||
'''
|
||||
# we need to loop to find next number for journal code
|
||||
for num in xrange(1, 100):
|
||||
# journal_code has a maximal size of 5, hence we can enforce the boundary num < 100
|
||||
journal_code = line['account_type'] == 'cash' and 'CSH' or 'BNK'
|
||||
journal_code += str(num)
|
||||
journal = self.env['account.journal'].search([('code', '=', journal_code), ('company_id', '=', company.id)], limit=1)
|
||||
if not journal:
|
||||
break
|
||||
else:
|
||||
raise UserError(_('Cannot generate an unused journal code.'))
|
||||
|
||||
return {
|
||||
'name': line['acc_name'],
|
||||
'code': journal_code,
|
||||
'type': line['account_type'],
|
||||
'company_id': company.id,
|
||||
'analytic_journal_id': False,
|
||||
'currency_id': line['currency_id'] or False,
|
||||
'default_credit_account_id': default_account_id,
|
||||
'default_debit_account_id': default_account_id,
|
||||
'show_on_dashboard': True,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _prepare_bank_account(self, company, line):
|
||||
'''
|
||||
This function prepares the value to use for the creation of the default debit and credit accounts of a
|
||||
bank journal created through the wizard of generating COA from templates.
|
||||
|
||||
:param company: company for which the wizard is running
|
||||
:param line: dictionary containing the values encoded by the user related to his bank account
|
||||
:return: mapping of field names and values
|
||||
:rtype: dict
|
||||
'''
|
||||
|
||||
# Seek the next available number for the account code
|
||||
code_digits = company.accounts_code_digits or 0
|
||||
bank_account_code_char = company.bank_account_code_char or ''
|
||||
for num in xrange(1, 100):
|
||||
new_code = str(bank_account_code_char.ljust(code_digits - 1, '0')) + str(num)
|
||||
rec = self.env['account.account'].search([('code', '=', new_code), ('company_id', '=', company.id)], limit=1)
|
||||
if not rec:
|
||||
break
|
||||
else:
|
||||
raise UserError(_('Cannot generate an unused account code.'))
|
||||
|
||||
liquidity_type = self.env.ref('account.data_account_type_liquidity')
|
||||
|
||||
return {
|
||||
'name': line['acc_name'],
|
||||
'currency_id': line['currency_id'] or False,
|
||||
'code': new_code,
|
||||
'user_type': liquidity_type and liquidity_type.id or False,
|
||||
'company_id': company.id,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def _create_bank_journals_from_o2m(self, company, acc_template_ref):
|
||||
'''
|
||||
This function creates bank journals and its accounts for each line encoded in the field bank_accounts_id of the
|
||||
wizard.
|
||||
|
||||
:param company_id: the id of the company for which the wizard is running.
|
||||
:param acc_template_ref: the dictionary containing the mapping between the ids of account templates and the ids
|
||||
of the accounts that have been generated from them.
|
||||
:return: True
|
||||
'''
|
||||
self.ensure_one()
|
||||
# Build a list with all the data to process
|
||||
journal_data = []
|
||||
if self.bank_accounts_id:
|
||||
for acc in self.bank_accounts_id:
|
||||
vals = {
|
||||
'acc_name': acc.acc_name,
|
||||
'account_type': acc.account_type,
|
||||
'currency_id': acc.currency_id.id,
|
||||
}
|
||||
journal_data.append(vals)
|
||||
ref_acc_bank = self.bank_account_code_char
|
||||
if journal_data and not ref_acc_bank:
|
||||
raise UserError(_('You have to set a code for the bank account defined on the selected chart of accounts.'))
|
||||
company.write({'bank_account_code_char': ref_acc_bank})
|
||||
|
||||
for line in journal_data:
|
||||
# Create the default debit/credit accounts for this bank journal
|
||||
vals = self._prepare_bank_account(company, line)
|
||||
default_account = self.env['account.account'].create(vals)
|
||||
|
||||
#create the bank journal
|
||||
vals_journal = self._prepare_bank_journal(company, line, default_account.id)
|
||||
self.env['account.journal'].create(vals_journal)
|
||||
return True
|
||||
|
||||
|
||||
class AccountBankAccountsWizard(models.TransientModel):
|
||||
_name = 'account.bank.accounts.wizard'
|
||||
|
||||
acc_name = fields.Char(string='Account Name.', required=True)
|
||||
bank_account_id = fields.Many2one('wizard.multi.charts.accounts', string='Bank Account', required=True, ondelete='cascade')
|
||||
currency_id = fields.Many2one('res.currency', string='Secondary Currency',
|
||||
help="Forces all moves for this account to have this secondary currency.")
|
||||
account_type = fields.Selection([('cash', 'Cash'), ('bank', 'Bank')])
|
||||
@@ -1,51 +1,87 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp import fields, models, api, _
|
||||
from datetime import timedelta
|
||||
|
||||
class res_company(osv.osv):
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
_columns = {
|
||||
'expects_chart_of_accounts': fields.boolean('Expects a Chart of Accounts'),
|
||||
'bank_account_code_char': fields.char('Code of the main bank account'),
|
||||
'accounts_code_digits': fields.integer('Number of digits in an account code'),
|
||||
'tax_calculation_rounding_method': fields.selection([
|
||||
('round_per_line', 'Round per Line'),
|
||||
('round_globally', 'Round Globally'),
|
||||
], 'Tax Calculation Rounding Method',
|
||||
help="If you select 'Round per Line' : for each tax, the tax amount will first be computed and rounded for each PO/SO/invoice line and then these rounded amounts will be summed, leading to the total amount for that tax. If you select 'Round Globally': for each tax, the tax amount will be computed for each PO/SO/invoice line, then these amounts will be summed and eventually this total tax amount will be rounded. If you sell with tax included, you should choose 'Round per line' because you certainly want the sum of your tax-included line subtotals to be equal to the total amount with taxes."),
|
||||
'paypal_account': fields.char("Paypal Account", size=128, help="Paypal username (usually email) for receiving online payments."),
|
||||
'overdue_msg': fields.text('Overdue Payments Message', translate=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'expects_chart_of_accounts': True,
|
||||
'tax_calculation_rounding_method': 'round_per_line',
|
||||
'accounts_code_digits': 6,
|
||||
'overdue_msg': '''Dear Sir/Madam,
|
||||
#TODO check all the options/fields are in the views (settings + company form view)
|
||||
#TODO: add a cash_register_code_char for allowing cash journals' accounts having a different numbering than bank journals' accounts.
|
||||
fiscalyear_last_day = fields.Integer(default=31, required=True)
|
||||
fiscalyear_last_month = fields.Selection([(1, 'January'), (2, 'February'), (3, 'March'), (4, 'April'), (5, 'May'), (6, 'June'), (7, 'July'), (8, 'August'), (9, 'September'), (10, 'October'), (11, 'November'), (12, 'December')], default=12, required=True)
|
||||
period_lock_date = fields.Date(help="Only users with the 'Adviser' role can edit accounts prior to and inclusive of this date")
|
||||
fiscalyear_lock_date = fields.Date(string="Fiscal Year lock date", help="No users, including Advisers, can edit accounts prior to and inclusive of this date")
|
||||
transfer_account_id = fields.Many2one('account.account',
|
||||
domain=lambda self: [('reconcile', '=', True), ('user_type.id', '=', self.env.ref('account.data_account_type_current_assets').id), ('deprecated', '=', False)], string="Transfer Account", help="Intermediary account used when moving money from a liquidity account to another")
|
||||
expects_chart_of_accounts = fields.Boolean(string='Expects a Chart of Accounts', default=True)
|
||||
chart_template_id = fields.Many2one('account.chart.template', help='The chart template for the company (if any)')
|
||||
bank_account_code_char = fields.Char(string='Code of the main bank account')
|
||||
accounts_code_digits = fields.Integer(string='Number of digits in an account code')
|
||||
tax_calculation_rounding_method = fields.Selection([
|
||||
('round_per_line', 'Round per Line'),
|
||||
('round_globally', 'Round Globally'),
|
||||
], default='round_per_line', string='Tax Calculation Rounding Method',
|
||||
help="If you select 'Round per Line' : for each tax, the tax amount will first be computed and rounded for each PO/SO/invoice line and then these rounded amounts will be summed, leading to the total amount for that tax. If you select 'Round Globally': for each tax, the tax amount will be computed for each PO/SO/invoice line, then these amounts will be summed and eventually this total tax amount will be rounded. If you sell with tax included, you should choose 'Round per line' because you certainly want the sum of your tax-included line subtotals to be equal to the total amount with taxes.")
|
||||
paypal_account = fields.Char(string='Paypal Account', size=128, help="Paypal username (usually email) for receiving online payments.")
|
||||
currency_exchange_journal_id = fields.Many2one('account.journal', string="Currency Adjustments Journal", domain=[('type', '=', 'general')])
|
||||
income_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_credit_account_id',
|
||||
string="Gain Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]")
|
||||
expense_currency_exchange_account_id = fields.Many2one('account.account', related='currency_exchange_journal_id.default_debit_account_id',
|
||||
string="Loss Exchange Rate Account", domain="[('internal_type', '=', 'other'), ('deprecated', '=', False), ('company_id', '=', id)]")
|
||||
anglo_saxon_accounting = fields.Boolean(string="Use anglo-saxon accounting")
|
||||
|
||||
Our records indicate that some payments on your account are still due. Please find details below.
|
||||
If the amount has already been paid, please disregard this notice. Otherwise, please forward us the total amount stated below.
|
||||
If you have any queries regarding your account, Please contact us.
|
||||
@api.multi
|
||||
def _create_bank_account_and_journal(self, account_number, currency_id=None):
|
||||
""" Create a journal and its account """
|
||||
MultiChartsAccounts = self.env['wizard.multi.charts.accounts']
|
||||
|
||||
Thank you in advance for your cooperation.
|
||||
Best Regards,'''
|
||||
}
|
||||
if currency_id is None:
|
||||
currency_id = self.currency_id.id
|
||||
|
||||
vals_account = {'currency_id': currency_id, 'acc_name': account_number, 'account_type': 'bank'}
|
||||
vals_account = MultiChartsAccounts._prepare_bank_account(self, vals_account)
|
||||
account_id = self.env['account.account'].create(vals_account).id
|
||||
|
||||
vals_journal = {'currency_id': currency_id, 'acc_name': _('Bank') + ' ' + account_number, 'account_type': 'bank'}
|
||||
vals_journal = MultiChartsAccounts._prepare_bank_journal(self, vals_journal, account_id)
|
||||
return self.env['account.journal'].create(vals_journal).id
|
||||
|
||||
@api.multi
|
||||
def compute_fiscalyear_dates(self, date):
|
||||
""" Computes the start and end dates of the fiscalyear where the given 'date' belongs to
|
||||
@param date: a datetime object
|
||||
@returns: a dictionary with date_from and date_to
|
||||
"""
|
||||
self = self[0]
|
||||
last_month = self.fiscalyear_last_month
|
||||
last_day = self.fiscalyear_last_day
|
||||
if (date.month < last_month or (date.month == last_month and date.date <= last_day)):
|
||||
date = date.replace(month=last_month, day=last_day)
|
||||
else:
|
||||
date = date.replace(month=last_month, day=last_day, year=date.year + 1)
|
||||
date_to = date
|
||||
date_from = date + timedelta(days=1)
|
||||
date_from = date_from.replace(year=date_from.year - 1)
|
||||
return {'date_from': date_from, 'date_to': date_to}
|
||||
|
||||
def get_new_account_code(self, code, old_prefix, new_prefix, digits):
|
||||
new_prefix_length = len(new_prefix)
|
||||
number = str(int(code[len(old_prefix):]))
|
||||
code = new_prefix + str('0' * (digits - new_prefix_length - len(number))) + number
|
||||
return code
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
# Repercute the change on accounts
|
||||
if values.get('bank_account_code_char', False) or values.get('accounts_code_digits', False):
|
||||
bank_code = values.get('bank_account_code_char', False) or self.bank_account_code_char
|
||||
digits = values.get('accounts_code_digits', False) or self.accounts_code_digits
|
||||
|
||||
accounts = self.env['account.account'].search([('code', 'like', self.bank_account_code_char), ('internal_type', '=', 'liquidity'),
|
||||
('company_id', '=', self.id)], order='code asc')
|
||||
for account in accounts:
|
||||
if account.code.startswith(self.bank_account_code_char):
|
||||
account.write({'code': self.get_new_account_code(account.code, self.bank_account_code_char, bank_code, digits)})
|
||||
return super(ResCompany, self).write(values)
|
||||
|
||||
@@ -2,6 +2,22 @@
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- TAGS FOR CASH FLOW STATEMENT -->
|
||||
|
||||
<record id="account_tag_operating" model="account.account.tag">
|
||||
<field name="name">Operating Activities</field>
|
||||
<field name="applicability">accounts</field>
|
||||
</record>
|
||||
<record id="account_tag_financing" model="account.account.tag">
|
||||
<field name="name">Financing Activities</field>
|
||||
<field name="applicability">accounts</field>
|
||||
</record>
|
||||
<record id="account_tag_investing" model="account.account.tag">
|
||||
<field name="name">Investing & Extraordinary Activities</field>
|
||||
<field name="applicability">accounts</field>
|
||||
</record>
|
||||
|
||||
<!-- Analytic journals -->
|
||||
<record id="analytic_journal_sale" model="account.analytic.journal">
|
||||
<field name="code">SAL</field>
|
||||
<field name="name">Sales</field>
|
||||
@@ -58,56 +74,6 @@
|
||||
<field eval="account_payment_term_net" name="payment_id"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Account Journal Sequences
|
||||
-->
|
||||
|
||||
<record id="sequence_sale_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Sales Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">SAJ/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_refund_sales_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Sales Credit Note Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">SCNJ/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_purchase_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Expenses Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">EXJ/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_refund_purchase_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Expenses Credit Notes Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">ECNJ/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_bank_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Bank Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">BNK/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_check_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Checks Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">CHK/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_cash_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Cash Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">CSH/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_opening_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Opening Entries Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">OPEJ/%(year)s/</field>
|
||||
</record>
|
||||
<record id="sequence_miscellaneous_journal" model="ir.sequence">
|
||||
<field name="name">Account Default Miscellaneous Journal</field>
|
||||
<field eval="3" name="padding"/>
|
||||
<field name="prefix">MISJ/%(year)s/</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Account Statement Sequences
|
||||
-->
|
||||
@@ -118,22 +84,6 @@
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
|
||||
<record id="sequence_statement" model="ir.sequence">
|
||||
<field name="name">Account Bank Statement</field>
|
||||
<field name="code">account.bank.statement</field>
|
||||
<field name="prefix">St. %(month)s/%(day)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
|
||||
<record id="cash_sequence_statement" model="ir.sequence">
|
||||
<field name="name">Account Cash Statement</field>
|
||||
<field name="code">account.cash.statement</field>
|
||||
<field name="prefix">Cr. %(month)s/%(day)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
</record>
|
||||
<!--
|
||||
Invoice requests (deprecated)
|
||||
-->
|
||||
@@ -162,5 +112,65 @@
|
||||
<field name="hidden" eval="True"/>
|
||||
<field name="description">Invoice Created</field>
|
||||
</record>
|
||||
|
||||
<!-- Payment methods -->
|
||||
<record id="account_payment_method_manual_in" model="account.payment.method">
|
||||
<field name="name">Manual</field>
|
||||
<field name="code">manual</field>
|
||||
<field name="payment_type">inbound</field>
|
||||
</record>
|
||||
<record id="account_payment_method_manual_out" model="account.payment.method">
|
||||
<field name="name">Manual</field>
|
||||
<field name="code">manual</field>
|
||||
<field name="payment_type">outbound</field>
|
||||
</record>
|
||||
|
||||
<!-- Payment sequences -->
|
||||
<record id="sequence_payment_customer_invoice" model="ir.sequence">
|
||||
<field name="name">Payments customer invoices sequence</field>
|
||||
<field name="code">account.payment.customer.invoice</field>
|
||||
<field name="prefix">CUST.IN/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="True" name="use_date_range"/>
|
||||
<field name="padding">4</field>
|
||||
</record>
|
||||
<record id="sequence_payment_customer_refund" model="ir.sequence">
|
||||
<field name="name">Payments customer refunds sequence</field>
|
||||
<field name="code">account.payment.customer.refund</field>
|
||||
<field name="prefix">CUST.OUT/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="True" name="use_date_range"/>
|
||||
<field name="padding">4</field>
|
||||
</record>
|
||||
<record id="sequence_payment_supplier_invoice" model="ir.sequence">
|
||||
<field name="name">Payments supplier invoices sequence</field>
|
||||
<field name="code">account.payment.supplier.invoice</field>
|
||||
<field name="prefix">SUPP.OUT/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="True" name="use_date_range"/>
|
||||
<field name="padding">4</field>
|
||||
</record>
|
||||
<record id="sequence_payment_supplier_refund" model="ir.sequence">
|
||||
<field name="name">Payments supplier refunds sequence</field>
|
||||
<field name="code">account.payment.supplier.refund</field>
|
||||
<field name="prefix">SUPP.IN/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="True" name="use_date_range"/>
|
||||
<field name="padding">4</field>
|
||||
</record>
|
||||
<record id="sequence_payment_transfer" model="ir.sequence">
|
||||
<field name="name">Payments transfer sequence</field>
|
||||
<field name="code">account.payment.transfer</field>
|
||||
<field name="prefix">TRANS/%(year)s/</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="True" name="use_date_range"/>
|
||||
<field name="padding">4</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,557 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<!-- Types -->
|
||||
<record model="account.account.type" id="account_type_income_view1">
|
||||
<field name="name">Income View</field>
|
||||
<field name="code">view</field>
|
||||
<field name="report_type">income</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="account_type_expense_view1">
|
||||
<field name="name">Expense View</field>
|
||||
<field name="code">expense</field>
|
||||
<field name="report_type">expense</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="account_type_asset_view1">
|
||||
<field name="name">Asset View</field>
|
||||
<field name="code">asset</field>
|
||||
<field name="report_type">asset</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="account_type_liability_view1">
|
||||
<field name="name">Liability View</field>
|
||||
<field name="code">liability</field>
|
||||
<field name="report_type">liability</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="conf_account_type_tax">
|
||||
<field name="name">Tax</field>
|
||||
<field name="code">tax</field>
|
||||
<field name="close_method">unreconciled</field>
|
||||
<field name="report_type">expense</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="conf_account_type_equity">
|
||||
<field name="name">Equity</field>
|
||||
<field name="code">equity</field>
|
||||
<field name="close_method">balance</field>
|
||||
<field name="report_type">liability</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="conf_account_type_chk">
|
||||
<field name="name">Check</field>
|
||||
<field name="code">check</field>
|
||||
<field name="close_method">balance</field>
|
||||
<field name="report_type">asset</field>
|
||||
</record>
|
||||
|
||||
<!-- Account Templates-->
|
||||
<record id="conf_chart0" model="account.account.template">
|
||||
<field name="code">0</field>
|
||||
<field name="name">Configurable Account Chart</field>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_view"/>
|
||||
</record>
|
||||
|
||||
<!-- Balance Sheet -->
|
||||
|
||||
<record id="conf_bal" model="account.account.template">
|
||||
<field name="code">1</field>
|
||||
<field name="name">Balance Sheet</field>
|
||||
<field ref="conf_chart0" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_view"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_fas" model="account.account.template">
|
||||
<field name="code">10</field>
|
||||
<field name="name">Fixed Assets</field>
|
||||
<field ref="conf_bal" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_asset_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_xfa" model="account.account.template">
|
||||
<field name="code">100</field>
|
||||
<field name="name">Fixed Asset Account</field>
|
||||
<field ref="conf_fas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="account_type_asset_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_nca" model="account.account.template">
|
||||
<field name="code">11</field>
|
||||
<field name="name">Net Current Assets</field>
|
||||
<field ref="conf_bal" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_asset_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_cas" model="account.account.template">
|
||||
<field name="code">110</field>
|
||||
<field name="name">Current Assets</field>
|
||||
<field ref="conf_nca" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_asset_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_stk" model="account.account.template">
|
||||
<field name="code">1101</field>
|
||||
<field name="name">Purchased Stocks</field>
|
||||
<field ref="conf_cas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_a_recv" model="account.account.template">
|
||||
<field name="code">1102</field>
|
||||
<field name="name">Debtors</field>
|
||||
<field ref="conf_cas" name="parent_id"/>
|
||||
<field name="type">receivable</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="user_type" ref="data_account_type_receivable"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_ova" model="account.account.template">
|
||||
<field name="code">1103</field>
|
||||
<field name="name">Tax Paid</field>
|
||||
<field ref="conf_cas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_bnk" model="account.account.template">
|
||||
<field name="code">1104</field>
|
||||
<field name="name">Bank Current Account</field>
|
||||
<field ref="conf_cas" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_asset_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_o_income" model="account.account.template">
|
||||
<field name="code">1106</field>
|
||||
<field name="name">Opening Income Account</field>
|
||||
<field ref="conf_cas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_income"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_cli" model="account.account.template">
|
||||
<field name="code">12</field>
|
||||
<field name="name">Current Liabilities</field>
|
||||
<field ref="conf_bal" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_liability_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_a_pay" model="account.account.template">
|
||||
<field name="code">120</field>
|
||||
<field name="name">Creditors</field>
|
||||
<field ref="conf_cli" name="parent_id"/>
|
||||
<field name="type">payable</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="user_type" ref="data_account_type_payable"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_iva" model="account.account.template">
|
||||
<field name="code">121</field>
|
||||
<field name="name">Tax Received</field>
|
||||
<field ref="conf_cli" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_liability"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_a_reserve_and_surplus" model="account.account.template">
|
||||
<field name="code">122</field>
|
||||
<field name="name">Reserve and Profit/Loss Account</field>
|
||||
<field ref="conf_cli" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="user_type" ref="data_account_type_liability"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_o_expense" model="account.account.template">
|
||||
<field name="code">123</field>
|
||||
<field name="name">Opening Expense Account</field>
|
||||
<field ref="conf_cli" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<!-- Profit and Loss -->
|
||||
|
||||
<record id="conf_gpf" model="account.account.template">
|
||||
<field name="code">2</field>
|
||||
<field name="name">Profit and Loss</field>
|
||||
<field ref="conf_chart0" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_view"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_rev" model="account.account.template">
|
||||
<field name="code">20</field>
|
||||
<field name="name">Revenue</field>
|
||||
<field ref="conf_gpf" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_income_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_a_sale" model="account.account.template">
|
||||
<field name="code">200</field>
|
||||
<field name="name">Product Sales</field>
|
||||
<field ref="conf_rev" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_income"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_cos" model="account.account.template">
|
||||
<field name="code">21</field>
|
||||
<field name="name">Cost of Sales</field>
|
||||
<field ref="conf_gpf" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_income_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_cog" model="account.account.template">
|
||||
<field name="code">210</field>
|
||||
<field name="name">Cost of Goods Sold</field>
|
||||
<field ref="conf_cos" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_ovr" model="account.account.template">
|
||||
<field name="code">22</field>
|
||||
<field name="name">Overheads</field>
|
||||
<field ref="conf_gpf" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="account_type_expense_view1"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_a_expense" model="account.account.template">
|
||||
<field name="code">220</field>
|
||||
<field name="name">Expenses</field>
|
||||
<field ref="conf_ovr" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_a_salary_expense" model="account.account.template">
|
||||
<field name="code">221</field>
|
||||
<field name="name">Salary Expenses</field>
|
||||
<field ref="conf_ovr" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<!-- Taxes -->
|
||||
<!-- TAX Code Definitions -->
|
||||
|
||||
<!-- Invoiced TAX -->
|
||||
|
||||
<record id="tax_code_chart_root" model="account.tax.code.template">
|
||||
<field name="name">Plan Fees </field>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_balance_net" model="account.tax.code.template">
|
||||
<field name="name">Tax Balance to Pay</field>
|
||||
<field name="parent_id" ref="tax_code_chart_root"/>
|
||||
</record>
|
||||
|
||||
<!-- Input TAX -->
|
||||
<record id="tax_code_input" model="account.tax.code.template">
|
||||
<field name="name">Tax Received</field>
|
||||
<field name="parent_id" ref="tax_code_balance_net"/>
|
||||
<field eval="-1" name="sign"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_input_S" model="account.tax.code.template">
|
||||
<field name="name">Tax Received Rate S (15%)</field>
|
||||
<field name="parent_id" ref="tax_code_input"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_input_R" model="account.tax.code.template">
|
||||
<field name="name">Tax Received Rate R (5%)</field>
|
||||
<field name="parent_id" ref="tax_code_input"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_input_X" model="account.tax.code.template">
|
||||
<field name="name">Tax Received Rate X (Exempt)</field>
|
||||
<field name="parent_id" ref="tax_code_input"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_input_O" model="account.tax.code.template">
|
||||
<field name="name">Tax Received Rate O (Out of scope)</field>
|
||||
<field name="parent_id" ref="tax_code_input"/>
|
||||
</record>
|
||||
|
||||
<!-- Output TAX -->
|
||||
|
||||
<record id="tax_code_output" model="account.tax.code.template">
|
||||
<field name="name">Tax Paid</field>
|
||||
<field name="parent_id" ref="tax_code_balance_net"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_output_S" model="account.tax.code.template">
|
||||
<field name="name">Tax Paid Rate S (15%)</field>
|
||||
<field name="parent_id" ref="tax_code_output"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_output_R" model="account.tax.code.template">
|
||||
<field name="name">Tax Paid Rate R (5%)</field>
|
||||
<field name="parent_id" ref="tax_code_output"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_output_X" model="account.tax.code.template">
|
||||
<field name="name">Tax Paid Rate X (Exempt)</field>
|
||||
<field name="parent_id" ref="tax_code_output"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_output_O" model="account.tax.code.template">
|
||||
<field name="name">Tax Paid Rate O (Out of scope)</field>
|
||||
<field name="parent_id" ref="tax_code_output"/>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Invoiced Base of TAX -->
|
||||
|
||||
<!-- Purchases -->
|
||||
|
||||
<record id="tax_code_base_net" model="account.tax.code.template">
|
||||
<field name="name">Tax Bases</field>
|
||||
<field name="parent_id" ref="tax_code_chart_root"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_base_purchases" model="account.tax.code.template">
|
||||
<field name="name">Taxable Purchases Base</field>
|
||||
<field name="parent_id" ref="tax_code_base_net"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_purch_S" model="account.tax.code.template">
|
||||
<field name="name">Taxable Purchases Rated S (15%)</field>
|
||||
<field name="parent_id" ref="tax_code_base_purchases"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_purch_R" model="account.tax.code.template">
|
||||
<field name="name">Taxable Purchases Rated R (5%)</field>
|
||||
<field name="parent_id" ref="tax_code_base_purchases"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_purch_X" model="account.tax.code.template">
|
||||
<field name="name">Taxable Purchases Type X (Exempt)</field>
|
||||
<field name="parent_id" ref="tax_code_base_purchases"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_purch_O" model="account.tax.code.template">
|
||||
<field name="name">Taxable Purchases Type O (Out of scope)</field>
|
||||
<field name="parent_id" ref="tax_code_base_purchases"/>
|
||||
</record>
|
||||
|
||||
<!-- Sales -->
|
||||
|
||||
<record id="tax_code_base_sales" model="account.tax.code.template">
|
||||
<field name="name">Base of Taxable Sales</field>
|
||||
<field name="parent_id" ref="tax_code_base_net"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_sales_S" model="account.tax.code.template">
|
||||
<field name="name">Taxable Sales Rated S (15%)</field>
|
||||
<field name="parent_id" ref="tax_code_base_sales"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_sales_R" model="account.tax.code.template">
|
||||
<field name="name">Taxable Sales Rated R (5%)</field>
|
||||
<field name="parent_id" ref="tax_code_base_sales"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_sales_X" model="account.tax.code.template">
|
||||
<field name="name">Taxable Sales Type X (Exempt)</field>
|
||||
<field name="parent_id" ref="tax_code_base_sales"/>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_sales_O" model="account.tax.code.template">
|
||||
<field name="name">Taxable Sales Type O (Out of scope)</field>
|
||||
<field name="parent_id" ref="tax_code_base_sales"/>
|
||||
</record>
|
||||
|
||||
<record id="configurable_chart_template" model="account.chart.template">
|
||||
<field name="name">Configurable Account Chart Template</field>
|
||||
<field name="account_root_id" ref="conf_chart0"/>
|
||||
<field name="tax_code_root_id" ref="tax_code_chart_root"/>
|
||||
<field name="bank_account_view_id" ref="conf_bnk"/>
|
||||
<field name="property_account_receivable" ref="conf_a_recv"/>
|
||||
<field name="property_account_payable" ref="conf_a_pay"/>
|
||||
<field name="property_account_expense_categ" ref="conf_a_expense"/>
|
||||
<field name="property_account_income_categ" ref="conf_a_sale"/>
|
||||
<field name="property_account_income_opening" ref="conf_o_income"/>
|
||||
<field name="property_account_expense_opening" ref="conf_o_expense"/>
|
||||
<field name="complete_tax_set" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- VAT Codes -->
|
||||
<!-- Purchases + Output VAT -->
|
||||
|
||||
<record id="otaxs" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">OTAX S</field>
|
||||
<field eval="0.15" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_ova"/>
|
||||
<field name="account_paid_id" ref="conf_ova"/>
|
||||
<field name="base_code_id" ref="tax_code_purch_S"/>
|
||||
<field name="tax_code_id" ref="tax_code_output_S"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_purch_S"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_output_S"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
</record>
|
||||
|
||||
<record id="otaxr" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">OTAX R</field>
|
||||
<field eval="0.05" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_ova"/>
|
||||
<field name="account_paid_id" ref="conf_ova"/>
|
||||
<field name="base_code_id" ref="tax_code_purch_R"/>
|
||||
<field name="tax_code_id" ref="tax_code_output_R"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_purch_R"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_output_R"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
</record>
|
||||
|
||||
<record id="otaxx" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">OTAX X</field>
|
||||
<field eval="0.0" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_ova"/>
|
||||
<field name="account_paid_id" ref="conf_ova"/>
|
||||
<field name="base_code_id" ref="tax_code_purch_X"/>
|
||||
<field name="tax_code_id" ref="tax_code_output_X"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_purch_X"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_output_X"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
</record>
|
||||
|
||||
<record id="otaxo" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">OTAX O</field>
|
||||
<field eval="0.0" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_ova"/>
|
||||
<field name="account_paid_id" ref="conf_ova"/>
|
||||
<field name="base_code_id" ref="tax_code_purch_O"/>
|
||||
<field name="tax_code_id" ref="tax_code_output_O"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_purch_O"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_output_O"/>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
</record>
|
||||
|
||||
<!-- Sales + Input VAT -->
|
||||
|
||||
<record id="itaxs" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">ITAX S</field>
|
||||
<field eval="0.15" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_iva"/>
|
||||
<field name="account_paid_id" ref="conf_iva"/>
|
||||
<field name="base_code_id" ref="tax_code_sales_S"/>
|
||||
<field name="tax_code_id" ref="tax_code_input_S"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_sales_S"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_input_S"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
</record>
|
||||
|
||||
<record id="itaxr" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">ITAX R</field>
|
||||
<field eval="0.05" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_iva"/>
|
||||
<field name="account_paid_id" ref="conf_iva"/>
|
||||
<field name="base_code_id" ref="tax_code_sales_R"/>
|
||||
<field name="tax_code_id" ref="tax_code_input_R"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_sales_R"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_input_R"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
</record>
|
||||
|
||||
<record id="itaxx" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">ITAX X</field>
|
||||
<field eval="0.0" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_iva"/>
|
||||
<field name="account_paid_id" ref="conf_iva"/>
|
||||
<field name="base_code_id" ref="tax_code_sales_X"/>
|
||||
<field name="tax_code_id" ref="tax_code_input_X"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_sales_X"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_input_X"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
</record>
|
||||
|
||||
<record id="itaxo" model="account.tax.template">
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
<field name="name">ITAX O</field>
|
||||
<field eval="0.0" name="amount"/>
|
||||
<field name="type">percent</field>
|
||||
<field name="account_collected_id" ref="conf_iva"/>
|
||||
<field name="account_paid_id" ref="conf_iva"/>
|
||||
<field name="base_code_id" ref="tax_code_sales_O"/>
|
||||
<field name="tax_code_id" ref="tax_code_input_O"/>
|
||||
<field name="ref_base_code_id" ref="tax_code_sales_O"/>
|
||||
<field name="ref_tax_code_id" ref="tax_code_input_O"/>
|
||||
<field name="type_tax_use">sale</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = -->
|
||||
<!-- Fiscal Mapping Templates -->
|
||||
<!-- = = = = = = = = = = = = = = = -->
|
||||
|
||||
|
||||
<record id="fiscal_position_normal_taxes_template1" model="account.fiscal.position.template">
|
||||
<field name="name">Normal Taxes</field>
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_exempt_template2" model="account.fiscal.position.template">
|
||||
<field name="name">Tax Exempt</field>
|
||||
<field name="chart_template_id" ref="configurable_chart_template"/>
|
||||
</record>
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = -->
|
||||
<!-- Fiscal Position Tax Templates -->
|
||||
<!-- = = = = = = = = = = = = = = = -->
|
||||
|
||||
|
||||
<record id="fiscal_position_normal_taxes" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_normal_taxes_template1"/>
|
||||
<field name="tax_src_id" ref="itaxs"/>
|
||||
<field name="tax_dest_id" ref="otaxs"/>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_position_tax_exempt" model="account.fiscal.position.tax.template">
|
||||
<field name="position_id" ref="fiscal_position_tax_exempt_template2"/>
|
||||
<field name="tax_src_id" ref="itaxx"/>
|
||||
<field name="tax_dest_id" ref="otaxx"/>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Assigned Default Taxes For Different Account -->
|
||||
|
||||
<record id="conf_a_sale" model="account.account.template">
|
||||
<field name="tax_ids" eval="[(6,0,[ref('itaxs')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="conf_a_expense" model="account.account.template">
|
||||
<field name="tax_ids" eval="[(6,0,[ref('otaxs')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="action_wizard_multi_chart_todo" model="ir.actions.todo">
|
||||
<field name="name">Set Your Accounting Options</field>
|
||||
<field name="action_id" ref="account.action_wizard_multi_chart"/>
|
||||
<field name="type">automatic</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,58 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record model="account.account.type" id="data_account_type_view">
|
||||
<field name="name">Root/View</field>
|
||||
<field name="code">view</field>
|
||||
<field name="close_method">none</field>
|
||||
</record>
|
||||
<!-- account.account.type -->
|
||||
<record model="account.account.type" id="data_account_type_receivable">
|
||||
<field name="name">Receivable</field>
|
||||
<field name="code">receivable</field>
|
||||
<field name="close_method">unreconciled</field>
|
||||
<field name="report_type">asset</field>
|
||||
<field name="type">receivable</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_payable">
|
||||
<field name="name">Payable</field>
|
||||
<field name="code">payable</field>
|
||||
<field name="close_method">unreconciled</field>
|
||||
<field name="report_type">liability</field>
|
||||
<field name="type">payable</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_bank">
|
||||
<field name="name">Bank</field>
|
||||
<field name="code">bank</field>
|
||||
<field name="close_method">balance</field>
|
||||
<field name="report_type">asset</field>
|
||||
<record model="account.account.type" id="data_account_type_liquidity">
|
||||
<field name="name">Bank and Cash</field>
|
||||
<field name="type">liquidity</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_cash">
|
||||
<field name="name">Cash</field>
|
||||
<field name="code">cash</field>
|
||||
<field name="close_method">balance</field>
|
||||
<field name="report_type">asset</field>
|
||||
<record model="account.account.type" id="data_account_type_current_assets">
|
||||
<field name="name">Current Assets</field>
|
||||
<field name="type">other</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_asset">
|
||||
<field name="name">Asset</field>
|
||||
<field name="code">asset</field>
|
||||
<field name="close_method">balance</field>
|
||||
<field name="report_type">asset</field>
|
||||
<record model="account.account.type" id="data_account_type_non_current_assets">
|
||||
<field name="name">Non-current Assets</field>
|
||||
<field name="type">other</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_liability">
|
||||
<field name="name">Liability</field>
|
||||
<field name="code">liability</field>
|
||||
<field name="close_method">balance</field>
|
||||
<field name="report_type">liability</field>
|
||||
<record model="account.account.type" id="data_account_type_prepayments">
|
||||
<field name="name">Prepayments</field>
|
||||
<field name="type">other</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_income">
|
||||
<field name="name">Income</field>
|
||||
<field name="code">income</field>
|
||||
<field name="close_method">none</field>
|
||||
<field name="report_type">income</field>
|
||||
<record model="account.account.type" id="data_account_type_fixed_assets">
|
||||
<field name="name">Fixed Assets</field>
|
||||
<field name="type">other</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_expense">
|
||||
<field name="name">Expense</field>
|
||||
<field name="code">expense</field>
|
||||
<field name="close_method">none</field>
|
||||
<field name="report_type">expense</field>
|
||||
<record model="account.account.type" id="data_account_type_current_liabilities">
|
||||
<field name="name">Current Liabilities</field>
|
||||
<field name="type">other</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_non_current_liabilities">
|
||||
<field name="name">Non-current Liabilities</field>
|
||||
<field name="type">other</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_equity">
|
||||
<field name="name">Equity</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_unaffected_earnings">
|
||||
<field name="name">Current Year Earnings</field>
|
||||
<field name="include_initial_balance" eval="True"/>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_other_income">
|
||||
<field name="name">Other Income</field>
|
||||
<field name="type">other</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_revenue">
|
||||
<field name="name">Revenue</field>
|
||||
<field name="type">other</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_depreciation">
|
||||
<field name="name">Depreciation</field>
|
||||
<field name="type">other</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_expenses">
|
||||
<field name="name">Expenses</field>
|
||||
<field name="type">other</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="data_account_type_direct_costs">
|
||||
<field name="name">Direct Costs</field>
|
||||
<field name="type">other</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
<?xml version="1.0" ?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- EDI related Email Templates menu -->
|
||||
<record model="ir.actions.act_window" id="action_email_templates">
|
||||
<field name="name">Email Templates</field>
|
||||
<field name="res_model">mail.template</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
<field name="view_id" ref="mail.email_template_tree" />
|
||||
<field name="search_view_id" ref="mail.view_email_template_search"/>
|
||||
<field name="context">{'search_default_model_id':'account.invoice'}</field>
|
||||
<field name="context" eval="{'search_default_model_id': ref('account.model_account_invoice')}"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<!-- Mail template are declared in a NOUPDATE block
|
||||
so users can freely customize/delete them -->
|
||||
@@ -30,9 +17,7 @@
|
||||
<field name="lang">${object.partner_id.lang}</field>
|
||||
<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: #FFF; ">
|
||||
|
||||
<p>Hello ${object.partner_id.name},</p>
|
||||
|
||||
<p>A new invoice is available for you: </p>
|
||||
|
||||
<p style="border-left: 1px solid #8e0000; margin-left: 30px;">
|
||||
@@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- A bank statement -->
|
||||
<record id="demo_bank_statement_1" model="account.bank.statement">
|
||||
<field name="journal_id" ref="account.bank_journal"/>
|
||||
<field name="period_id" ref="account.period_5"/>
|
||||
<field name="date" eval="time.strftime('%Y')+'-01-01'"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="name">BNK/2014/001</field>
|
||||
<field name="balance_end" eval="2040.0"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="balance_start" eval="0.0"/>
|
||||
<field name="balance_end_real" eval="3707.58"/>
|
||||
</record>
|
||||
<record id="demo_bank_statement_line_1" model="account.bank.statement.line">
|
||||
<field name="ref"></field>
|
||||
<field name="statement_id" ref="demo_bank_statement_1"/>
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="name">First 2000 € of SAJ/2014/001</field>
|
||||
<field name="journal_id" ref="account.bank_journal"/>
|
||||
<field name="amount" eval="2000.0"/>
|
||||
<field name="date" eval="time.strftime('%Y')+'-01-01'"/>
|
||||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
</record>
|
||||
<record id="demo_bank_statement_line_2" model="account.bank.statement.line">
|
||||
<field name="ref"></field>
|
||||
<field name="statement_id" ref="demo_bank_statement_1"/>
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="name">SAJ/2014/002</field>
|
||||
<field name="journal_id" ref="account.bank_journal"/>
|
||||
<field name="amount" eval="650.0"/>
|
||||
<field name="date" eval="time.strftime('%Y')+'-01-01'"/>
|
||||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
</record>
|
||||
<record id="demo_bank_statement_line_3" model="account.bank.statement.line">
|
||||
<field name="ref"></field>
|
||||
<field name="statement_id" ref="demo_bank_statement_1"/>
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="name">Bank fees</field>
|
||||
<field name="journal_id" ref="account.bank_journal"/>
|
||||
<field name="amount" eval="32.58"/>
|
||||
<field name="date" eval="time.strftime('%Y')+'-01-01'"/>
|
||||
</record>
|
||||
<record id="demo_bank_statement_line_4" model="account.bank.statement.line">
|
||||
<field name="ref"></field>
|
||||
<field name="statement_id" ref="demo_bank_statement_1"/>
|
||||
<field name="sequence" eval="4"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="name">SAJ/2014/003 and SAJ/2014/004</field>
|
||||
<field name="journal_id" ref="account.bank_journal"/>
|
||||
<field name="amount" eval="1025.0"/>
|
||||
<field name="date" eval="time.strftime('%Y')+'-01-01'"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
</record>
|
||||
|
||||
<!-- Statement operation templates -->
|
||||
<record id="statement_operation_template_1" model="account.statement.operation.template">
|
||||
<field name="name">Discount For Early Payment</field>
|
||||
<field name="account_id" ref="a_expense"></field>
|
||||
<field name="label">Discount</field>
|
||||
<field name="amount_type">percentage_of_total</field>
|
||||
<field name="amount">-7</field>
|
||||
</record>
|
||||
<record id="statement_operation_template_2" model="account.statement.operation.template">
|
||||
<field name="name">Bank Fees</field>
|
||||
<field name="account_id" ref="a_expense"></field>
|
||||
<field name="label">Bank Fees</field>
|
||||
<field name="amount_type">percentage_of_balance</field>
|
||||
<field name="amount">100.0</field>
|
||||
</record>
|
||||
<record id="statement_operation_template_3" model="account.statement.operation.template">
|
||||
<field name="name">Profit / Loss</field>
|
||||
<field name="account_id" ref="a_sale"></field>
|
||||
<field name="label">Profit / Loss</field>
|
||||
<field name="amount_type">percentage_of_balance</field>
|
||||
<field name="amount">100.0</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,75 @@
|
||||
-
|
||||
Create demo bank statement
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
journal_id = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'bank')])
|
||||
import time
|
||||
if journal_id:
|
||||
journal_id = journal_id[0]
|
||||
vals = {
|
||||
'journal_id': journal_id,
|
||||
'date': time.strftime('%Y')+'-01-01',
|
||||
'name': "BNK/2014/001",
|
||||
'balance_end_real': '8998.2',
|
||||
'company_id': ref('base.main_company'),
|
||||
'balance_start': 5103.0
|
||||
}
|
||||
self._update(cr, uid, 'account.bank.statement', 'account', vals, 'demo_bank_statement_1')
|
||||
vals = {
|
||||
'ref': '',
|
||||
'statement_id': ref('account.demo_bank_statement_1'),
|
||||
'sequence': 1,
|
||||
'company_id': ref('base.main_company'),
|
||||
'name': "SAJ/2014/002 and SAJ/2014/003",
|
||||
'journal_id': journal_id,
|
||||
'amount': 1175.0,
|
||||
'date': time.strftime('%Y')+'-01-01',
|
||||
'partner_id': ref('base.res_partner_2'),
|
||||
}
|
||||
self._update(cr, uid, 'account.bank.statement.line', 'account', vals, 'demo_bank_statement_line_1')
|
||||
vals = {
|
||||
'ref': '',
|
||||
'statement_id': ref('account.demo_bank_statement_1'),
|
||||
'sequence': 2,
|
||||
'company_id': ref('base.main_company'),
|
||||
'name': "Bank fees",
|
||||
'journal_id': journal_id,
|
||||
'amount': -32.58,
|
||||
'date': time.strftime('%Y')+'-01-01',
|
||||
}
|
||||
self._update(cr, uid, 'account.bank.statement.line', 'account', vals, 'demo_bank_statement_line_2')
|
||||
vals = {
|
||||
'ref': '',
|
||||
'statement_id': ref('account.demo_bank_statement_1'),
|
||||
'sequence': 3,
|
||||
'company_id': ref('base.main_company'),
|
||||
'name': "Prepayment",
|
||||
'journal_id': journal_id,
|
||||
'amount': 650.0,
|
||||
'date': time.strftime('%Y')+'-01-01',
|
||||
'partner_id': ref('base.res_partner_9'),
|
||||
}
|
||||
self._update(cr, uid, 'account.bank.statement.line', 'account', vals, 'demo_bank_statement_line_3')
|
||||
vals = {
|
||||
'ref': '',
|
||||
'statement_id': ref('account.demo_bank_statement_1'),
|
||||
'sequence': 4,
|
||||
'company_id': ref('base.main_company'),
|
||||
'name': "First 2000 € of SAJ/2014/001",
|
||||
'journal_id': journal_id,
|
||||
'amount': 2000.0,
|
||||
'date': time.strftime('%Y')+'-01-01',
|
||||
'partner_id': ref('base.res_partner_9'),
|
||||
}
|
||||
self._update(cr, uid, 'account.bank.statement.line', 'account', vals, 'demo_bank_statement_line_4')
|
||||
vals = {
|
||||
'ref': '',
|
||||
'statement_id': ref('account.demo_bank_statement_1'),
|
||||
'sequence': 5,
|
||||
'company_id': ref('base.main_company'),
|
||||
'name': "Last Year Interests",
|
||||
'journal_id': journal_id,
|
||||
'amount': 102.78,
|
||||
'date': time.strftime('%Y')+'-01-01',
|
||||
}
|
||||
self._update(cr, uid, 'account.bank.statement.line', 'account', vals, 'demo_bank_statement_line_5')
|
||||
@@ -2,129 +2,23 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!--
|
||||
Fiscal year
|
||||
-->
|
||||
|
||||
<record id="data_fiscalyear" model="account.fiscalyear">
|
||||
<field eval="'Fiscal Year X '+time.strftime('%Y')" name="name"/>
|
||||
<field eval="'FY'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="time.strftime('%Y')+'-01-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-12-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<!-- TAGS FOR RETRIEVING THE DEMO ACCOUNTS -->
|
||||
|
||||
<record id="demo_capital_account" model="account.account.tag">
|
||||
<field name="name">Demo Capital Account</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Fiscal Periods
|
||||
-->
|
||||
|
||||
<record id="period_0" model="account.period">
|
||||
<field eval="'00/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X Opening Period '+time.strftime('%Y')" name="name"/>
|
||||
<field eval="True" name="special"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-01-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-01-01'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<record id="demo_stock_account" model="account.account.tag">
|
||||
<field name="name">Demo Stock Account</field>
|
||||
</record>
|
||||
<record id="period_1" model="account.period">
|
||||
<field eval="'01/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 01/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-01-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-01-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<record id="demo_sale_of_land_account" model="account.account.tag">
|
||||
<field name="name">Demo Sale of Land Account</field>
|
||||
</record>
|
||||
<record id="period_2" model="account.period">
|
||||
<field eval="'02/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 02/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-02-01'" name="date_start"/>
|
||||
<!-- for the last day of February, we have to compute the day before March 1st -->
|
||||
<field eval="(DateTime.today().replace(month=3, day=1) - timedelta(days=1)).strftime('%Y-%m-%d')" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<record id="demo_ceo_wages_account" model="account.account.tag">
|
||||
<field name="name">Demo CEO Wages Account</field>
|
||||
</record>
|
||||
<record id="period_3" model="account.period">
|
||||
<field eval="'03/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 03/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-03-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-03-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<record id="demo_coffee_machine_account" model="account.account.tag">
|
||||
<field name="name">Demo Coffe Machine Account</field>
|
||||
</record>
|
||||
<record id="period_4" model="account.period">
|
||||
<field eval="'04/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 04/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-04-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-04-30'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_5" model="account.period">
|
||||
<field eval="'05/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 05/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-05-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-05-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_6" model="account.period">
|
||||
<field eval="'06/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 06/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-06-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-06-30'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_7" model="account.period">
|
||||
<field eval="'07/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 07/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-07-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-07-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_8" model="account.period">
|
||||
<field eval="'08/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 08/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-08-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-08-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_9" model="account.period">
|
||||
<field eval="'09/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 09/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-09-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-09-30'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_10" model="account.period">
|
||||
<field eval="'10/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 10/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-10-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-10-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_11" model="account.period">
|
||||
<field eval="'11/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 11/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-11-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-11-30'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="period_12" model="account.period">
|
||||
<field eval="'12/'+time.strftime('%Y')" name="code"/>
|
||||
<field eval="'X 12/'+time.strftime('%Y')" name="name"/>
|
||||
<field name="fiscalyear_id" ref="data_fiscalyear"/>
|
||||
<field eval="time.strftime('%Y')+'-12-01'" name="date_start"/>
|
||||
<field eval="time.strftime('%Y')+'-12-31'" name="date_stop"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
|
||||
<!-- Payment Term -->
|
||||
|
||||
<record id="account_payment_term" model="account.payment.term">
|
||||
@@ -143,8 +37,8 @@
|
||||
<field name="note">30% Advance End 30 Days</field>
|
||||
</record>
|
||||
<record id="account_payment_term_line_advance1" model="account.payment.term.line">
|
||||
<field name="value">procent</field>
|
||||
<field eval="30.00" name="value_amount"/>
|
||||
<field name="value">percent</field>
|
||||
<field eval="0.300000" name="value_amount"/>
|
||||
<field eval="0" name="days"/>
|
||||
<field eval="0" name="days2"/>
|
||||
<field eval="account_payment_term_advance" name="payment_id"/>
|
||||
@@ -162,18 +56,33 @@
|
||||
|
||||
<!-- Add payment term on some demo partners -->
|
||||
<record id="base.res_partner_2" model="res.partner">
|
||||
<field name="property_payment_term" ref="account_payment_term_net"/>
|
||||
<field name="property_payment_term" ref="account.account_payment_term_net"/>
|
||||
</record>
|
||||
<record id="base.res_partner_12" model="res.partner">
|
||||
<field name="property_payment_term" ref="account_payment_term"/>
|
||||
<field name="property_supplier_payment_term" ref="account_payment_term"/>
|
||||
</record>
|
||||
<record id="base.res_partner_4" model="res.partner">
|
||||
<field name="property_supplier_payment_term" ref="account_payment_term_net"/>
|
||||
<field name="property_supplier_payment_term" ref="account.account_payment_term_net"/>
|
||||
</record>
|
||||
<record id="base.res_partner_1" model="res.partner">
|
||||
<field name="property_supplier_payment_term" ref="account_payment_term"/>
|
||||
</record>
|
||||
<!--
|
||||
<record id="account.credit_account" model="account.account">
|
||||
<field name="name">Bank Account</field>
|
||||
<field name="user_type" ref="account.data_account_type_liquidity"/>
|
||||
<field name="code">Testbank</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<record id="account.bank_journal" model="account.journal">
|
||||
<field name="name">Bank Journal</field>
|
||||
<field name="code">TBNK</field>
|
||||
<field name="type">bank</field>
|
||||
<field name="default_credit_account_id" ref="account.credit_account"/>
|
||||
<field name="default_debit_account_id" ref="account.credit_account"/>
|
||||
</record> -->
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record id="demo_invoice_0" model="account.invoice">
|
||||
<field name="date_due" eval="time.strftime('%Y')+'-01-30'"/>
|
||||
<field name="payment_term" ref="account.account_payment_term"/>
|
||||
<field name="journal_id" ref="account.expenses_journal"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="reference_type">none</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="type">in_invoice</field>
|
||||
<field name="account_id" ref="account.a_pay"/>
|
||||
<field eval="0" name="reconciled"/>
|
||||
<field name="date_invoice" eval="time.strftime('%Y')+'-01-01'"/>
|
||||
<field eval="14.0" name="amount_untaxed"/>
|
||||
<field eval="14.0" name="amount_total"/>
|
||||
<field name="partner_id" ref="base.res_partner_17"/>
|
||||
</record>
|
||||
<record id="demo_invoice_0_line_rpanrearpanelshe0" model="account.invoice.line">
|
||||
<field name="invoice_id" ref="demo_invoice_0"/>
|
||||
<field name="account_id" ref="account.a_expense"/>
|
||||
<field name="uos_id" ref="product.product_uom_unit"/>
|
||||
<field name="price_unit" eval="10.0" />
|
||||
<field name="price_subtotal" eval="10.0" />
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="invoice_line_tax_id" eval="[(6,0,[])]"/>
|
||||
<field name="product_id" ref="product.product_product_39"/>
|
||||
<field name="quantity" eval="1.0" />
|
||||
<field name="partner_id" ref="base.res_partner_16"/>
|
||||
<field name="name">Toner Cartridge</field>
|
||||
</record>
|
||||
<record id="demo_invoice_0_line_rckrackcm0" model="account.invoice.line">
|
||||
<field name="invoice_id" ref="demo_invoice_0"/>
|
||||
<field name="account_id" ref="account.a_expense"/>
|
||||
<field name="uos_id" ref="product.product_uom_unit"/>
|
||||
<field name="price_unit" eval="4.0"/>
|
||||
<field name="price_subtotal" eval="4.0"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="invoice_line_tax_id" eval="[(6,0,[])]"/>
|
||||
<field name="product_id" ref="product.product_product_43"/>
|
||||
<field name="quantity" eval="1.0" />
|
||||
<field name="partner_id" ref="base.res_partner_17"/>
|
||||
<field name="name">Zed+ Antivirus</field>
|
||||
</record>
|
||||
|
||||
<!-- Some customer invoices used to show the reconciliation process on the bank statement -->
|
||||
<record id="invoice_1" model="account.invoice">
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="journal_id" ref="account.sales_journal"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="type">out_invoice</field>
|
||||
<field name="account_id" ref="a_recv"/>
|
||||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
</record>
|
||||
<record id="invoice_1_line_1" model="account.invoice.line">
|
||||
<field name="name">Dell Inspiron Laptop without OS</field>
|
||||
<field name="product_id" ref="product.product_product_49"/>
|
||||
<field name="invoice_id" ref="invoice_1"/>
|
||||
<field name="price_unit">642</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<record id="invoice_1_line_2" model="account.invoice.line">
|
||||
<field name="name">Linutop</field>
|
||||
<field name="product_id" ref="product.product_product_50"/>
|
||||
<field name="invoice_id" ref="invoice_1"/>
|
||||
<field name="price_unit">280</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<workflow action="invoice_open" model="account.invoice" ref="invoice_1"/>
|
||||
|
||||
<record id="invoice_2" model="account.invoice">
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="journal_id" ref="account.sales_journal"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="type">out_invoice</field>
|
||||
<field name="account_id" ref="a_recv"/>
|
||||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
<field eval="time.strftime('%Y-%m') + '-01'" name="date_invoice"/>
|
||||
</record>
|
||||
<record id="invoice_2_line_1" model="account.invoice.line">
|
||||
<field name="name">8-port Switch</field>
|
||||
<field name="product_id" ref="product.product_product_51"/>
|
||||
<field name="invoice_id" ref="invoice_2"/>
|
||||
<field name="price_unit">50</field>
|
||||
<field name="quantity">3</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<record id="invoice_2_line_2" model="account.invoice.line">
|
||||
<field name="name">30m RJ45 wire</field>
|
||||
<field name="product_id" ref="product.product_product_52"/>
|
||||
<field name="invoice_id" ref="invoice_2"/>
|
||||
<field name="price_unit">25</field>
|
||||
<field name="quantity">20</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<workflow action="invoice_open" model="account.invoice" ref="invoice_2"/>
|
||||
|
||||
<record id="invoice_3" model="account.invoice">
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="journal_id" ref="account.sales_journal"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="type">out_invoice</field>
|
||||
<field name="account_id" ref="a_recv"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field eval="time.strftime('%Y-%m') + '-08'" name="date_invoice"/>
|
||||
</record>
|
||||
<record id="invoice_3_line_1" model="account.invoice.line">
|
||||
<field name="name">TypeMatrix Dvorak Keyboard</field>
|
||||
<field name="product_id" ref="product.product_product_53"/>
|
||||
<field name="invoice_id" ref="invoice_3"/>
|
||||
<field name="price_unit">90</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<record id="invoice_3_line_2" model="account.invoice.line">
|
||||
<field name="name">Ergonomic Mouse</field>
|
||||
<field name="product_id" ref="product.product_product_54"/>
|
||||
<field name="invoice_id" ref="invoice_3"/>
|
||||
<field name="price_unit">15</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<workflow action="invoice_open" model="account.invoice" ref="invoice_3"/>
|
||||
|
||||
<record id="invoice_4" model="account.invoice">
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="journal_id" ref="account.sales_journal"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="type">out_invoice</field>
|
||||
<field name="account_id" ref="a_recv"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field eval="time.strftime('%Y-%m') + '-15'" name="date_invoice"/>
|
||||
</record>
|
||||
<record id="invoice_4_line_1" model="account.invoice.line">
|
||||
<field name="name">Desktop Computer Table</field>
|
||||
<field name="product_id" ref="product.product_product_55"/>
|
||||
<field name="invoice_id" ref="invoice_4"/>
|
||||
<field name="price_unit">80</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<record id="invoice_4_line_2" model="account.invoice.line">
|
||||
<field name="name">Desktop Lamp</field>
|
||||
<field name="product_id" ref="product.product_product_56"/>
|
||||
<field name="invoice_id" ref="invoice_4"/>
|
||||
<field name="price_unit">20</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<workflow action="invoice_open" model="account.invoice" ref="invoice_4"/>
|
||||
|
||||
<record id="invoice_5" model="account.invoice">
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="journal_id" ref="account.sales_journal"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="type">out_invoice</field>
|
||||
<field name="account_id" ref="a_recv"/>
|
||||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
<field eval="time.strftime('%Y-%m') + '-08'" name="date_invoice"/>
|
||||
</record>
|
||||
<record id="invoice_5_line_1" model="account.invoice.line">
|
||||
<field name="name">TypeMatrix Dvorak Keyboard</field>
|
||||
<field name="product_id" ref="product.product_product_53"/>
|
||||
<field name="invoice_id" ref="invoice_5"/>
|
||||
<field name="price_unit">90</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<record id="invoice_5_line_2" model="account.invoice.line">
|
||||
<field name="name">Ergonomic Mouse</field>
|
||||
<field name="product_id" ref="product.product_product_54"/>
|
||||
<field name="invoice_id" ref="invoice_5"/>
|
||||
<field name="price_unit">15</field>
|
||||
<field name="quantity">5</field>
|
||||
<field name="account_id" ref="a_sale"/>
|
||||
</record>
|
||||
<workflow action="invoice_open" model="account.invoice" ref="invoice_5"/>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,195 @@
|
||||
-
|
||||
Set the context for customer invoices because the 'type' field is readonly in invoice form views, so it value won't be considered by the yaml import
|
||||
-
|
||||
!record {model: account.invoice, id: demo_invoice_1}:
|
||||
company_id: base.main_company
|
||||
partner_id: base.res_partner_9
|
||||
currency_id: base.EUR
|
||||
user_id: base.user_demo
|
||||
reference_type: none
|
||||
payment_term_id: account.account_payment_term
|
||||
type: 'out_invoice'
|
||||
date_invoice: !eval time.strftime('%Y')+'-01-01'
|
||||
invoice_line_ids:
|
||||
- name: 'Dell Inspiron Laptop without OS'
|
||||
product_id: product.product_product_49
|
||||
price_unit: 642.0
|
||||
quantity: 5
|
||||
- name: 'Linutop'
|
||||
product_id: product.product_product_50
|
||||
price_unit: 280.0
|
||||
quantity: 5.0
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: demo_invoice_1}
|
||||
-
|
||||
!record {model: account.invoice, id: demo_invoice_2}:
|
||||
company_id: base.main_company
|
||||
partner_id: base.res_partner_2
|
||||
currency_id: base.EUR
|
||||
type: 'out_invoice'
|
||||
date_invoice: !eval time.strftime('%Y')+'-01-08'
|
||||
invoice_line_ids:
|
||||
- name: '8-port Switch'
|
||||
product_id: product.product_product_51
|
||||
price_unit: 50.0
|
||||
quantity: 3
|
||||
- name: '30m RJ45 wire'
|
||||
product_id: product.product_product_52
|
||||
price_unit: 25
|
||||
quantity: 20
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: demo_invoice_2}
|
||||
-
|
||||
!record {model: account.invoice, id: demo_invoice_3}:
|
||||
company_id: base.main_company
|
||||
partner_id: base.res_partner_2
|
||||
currency_id: base.EUR
|
||||
type: 'out_invoice'
|
||||
date_invoice: !eval time.strftime('%Y-%m')+'-08'
|
||||
invoice_line_ids:
|
||||
- name: 'TypeMatrix Dvorak Keyboard'
|
||||
product_id: product.product_product_53
|
||||
price_unit: 90.0
|
||||
quantity: 5
|
||||
- name: 'Ergonomic Mouse'
|
||||
product_id: product.product_product_54
|
||||
price_unit: 15.0
|
||||
quantity: 5.0
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: demo_invoice_3}
|
||||
-
|
||||
!record {model: account.invoice, id: demo_invoice_invest_sale}:
|
||||
company_id: base.main_company
|
||||
partner_id: base.res_partner_5
|
||||
currency_id: base.EUR
|
||||
type: 'out_invoice'
|
||||
date_invoice: !eval time.strftime('%Y-%m')+'-08'
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('tag_ids', 'in', [ref('account.demo_sale_of_land_account')])])
|
||||
line_vals = {
|
||||
'invoice_id': ref('demo_invoice_invest_sale'),
|
||||
'name': "Land located at '50.635336,4.863298'",
|
||||
'price_unit': 210600,
|
||||
}
|
||||
if account_id:
|
||||
line_vals['account_id'] = account_id[0]
|
||||
tax_id = self.pool.get('account.tax').search(cr, uid, [('type_tax_use', '=', 'sale'), ('amount', '>', 0)])
|
||||
if tax_id:
|
||||
line_vals['invoice_line_tax_ids'] = [(6, 0, [tax_id[0]])]
|
||||
self._update(cr, uid, 'account.invoice.line', 'account', line_vals, 'sale_of_land_line')
|
||||
self.pool.get('account.invoice')._onchange_invoice_line_ids(cr, uid, [ref('demo_invoice_invest_sale')])
|
||||
self.pool.get('account.invoice').signal_workflow(cr, uid, [ref('demo_invoice_invest_sale')], 'invoice_open')
|
||||
-
|
||||
Set the context for supplier bills because the 'type' field is readonly in invoice form views, so it value won't be considered by the yaml import
|
||||
-
|
||||
!context
|
||||
type: 'in_invoice'
|
||||
-
|
||||
!record {model: account.invoice, id: demo_invoice_0}:
|
||||
company_id: base.main_company
|
||||
partner_id: base.res_partner_17
|
||||
currency_id: base.EUR
|
||||
user_id: base.user_demo
|
||||
reference_type: none
|
||||
payment_term_id: account.account_payment_term
|
||||
type: 'in_invoice'
|
||||
date_invoice: !eval time.strftime('%Y')+'-01-01'
|
||||
invoice_line_ids:
|
||||
- name: 'Toner Cartridge'
|
||||
price_unit: 10.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_39
|
||||
uos_id: product.product_uom_unit
|
||||
- name: 'Zed+ Antivirus'
|
||||
price_unit: 4.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_43
|
||||
uos_id: product.product_uom_unit
|
||||
-
|
||||
!record {model: account.invoice, id: demo_invoice_january_wages}:
|
||||
company_id: base.main_company
|
||||
partner_id: base.res_partner_17
|
||||
currency_id: base.EUR
|
||||
type: 'in_invoice'
|
||||
date_invoice: !eval time.strftime('%Y')+'-01-01'
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
line_vals = {
|
||||
'invoice_id': ref('demo_invoice_january_wages'),
|
||||
'name': "CEO wages",
|
||||
'price_unit': 10000,
|
||||
}
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('tag_ids', 'in', [ref('account.demo_ceo_wages_account')])])
|
||||
if not account_id:
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_expenses'))])
|
||||
if account_id:
|
||||
line_vals['account_id'] = account_id[0]
|
||||
self._update(cr, uid, 'account.invoice.line', 'account', line_vals, 'ceo_wages_line')
|
||||
self.pool.get('account.invoice').signal_workflow(cr, uid, [ref('demo_invoice_january_wages')], 'invoice_open')
|
||||
-
|
||||
!record {model: account.invoice, id: demo_invoice_equipment_purchase}:
|
||||
company_id: base.main_company
|
||||
partner_id: base.res_partner_6
|
||||
currency_id: base.EUR
|
||||
type: 'in_invoice'
|
||||
date_invoice: !eval time.strftime('%Y')+'-01-15'
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
line_vals = {
|
||||
'invoice_id': ref('demo_invoice_equipment_purchase'),
|
||||
'name': "Coffee Machine with huge 'employee\'s performances boosting perk'",
|
||||
'price_unit': 4999.99,
|
||||
}
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('tag_ids', 'in', [ref('account.demo_coffee_machine_account')])])
|
||||
if not account_id:
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_expenses'))])
|
||||
if account_id:
|
||||
line_vals['account_id'] = account_id[0]
|
||||
tax_id = self.pool.get('account.tax').search(cr, uid, [('type_tax_use', '=', 'purchase'), ('amount', '>', 0)])
|
||||
if tax_id:
|
||||
line_vals['invoice_line_tax_ids'] = [(6, 0, [tax_id[0]])]
|
||||
self._update(cr, uid, 'account.invoice.line', 'account', line_vals, 'coffee_machine_line')
|
||||
self.pool.get('account.invoice')._onchange_invoice_line_ids(cr, uid, [ref('demo_invoice_equipment_purchase')])
|
||||
self.pool.get('account.invoice').signal_workflow(cr, uid, [ref('demo_invoice_equipment_purchase')], 'invoice_open')
|
||||
-
|
||||
!python {model: account.bank.statement.line} : |
|
||||
account_ids = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_revenue')), ('tag_ids', 'in', [ref('account.account_tag_financing')])])
|
||||
line = self.browse(cr, uid, ref('account.demo_bank_statement_line_5'))
|
||||
if not line.journal_entry_ids and account_ids:
|
||||
line.write({'account_id': account_ids[0]})
|
||||
line.fast_counterpart_creation()
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
vals = {
|
||||
'company_id': ref('base.main_company'),
|
||||
'journal_id': self.pool.get('account.journal').search(cr, uid, [('type', '=', 'general')])[0],
|
||||
'date': datetime.now().replace(day=1,month=1) - relativedelta(days=1),
|
||||
'ref': 'Company Creation',
|
||||
}
|
||||
self._update(cr, uid, 'account.move', 'account', vals, 'demo_opening_move')
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
bank_journal_id = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'bank')])[0]
|
||||
if bank_journal_id:
|
||||
bank_account_id = self.pool.get('account.journal').browse(cr, uid, bank_journal_id).default_debit_account_id.id
|
||||
fixed_asset_account_ids = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_fixed_assets'))])
|
||||
equity_account_ids = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_equity')), ('tag_ids', 'in', [ref('account.demo_capital_account')])])
|
||||
if bank_account_id and fixed_asset_account_ids and equity_account_ids:
|
||||
self._update(cr, uid, 'account.move.line', 'account', {
|
||||
'move_id': ref('account.demo_opening_move'),
|
||||
'name': 'Opening Entry',
|
||||
'debit': 5103,
|
||||
'account_id': bank_account_id}, 'opening_line_1', context={'check_move_validity': False})
|
||||
self._update(cr, uid, 'account.move.line', 'account', {
|
||||
'move_id': ref('account.demo_opening_move'),
|
||||
'name': 'Opening Entry',
|
||||
'debit': 13447,
|
||||
'account_id': fixed_asset_account_ids[0]}, 'opening_line_2', context={'check_move_validity': False})
|
||||
self._update(cr, uid, 'account.move.line', 'account', {
|
||||
'move_id': ref('account.demo_opening_move'),
|
||||
'name': 'Opening Entry',
|
||||
'credit': 18550,
|
||||
'account_id': equity_account_ids[0]}, 'opening_line_3', context={'check_move_validity': False})
|
||||
@@ -1,441 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record id="base.main_company" model="res.company">
|
||||
<field name="bank_account_code_char">X1100</field>
|
||||
<field name="accounts_code_digits">7</field>
|
||||
</record>
|
||||
<!--
|
||||
Account Type
|
||||
-->
|
||||
|
||||
<record id="account_type_cash_equity" model="account.account.type">
|
||||
<field name="name">Equity</field>
|
||||
<field name="code">equity</field>
|
||||
<field name="close_method">balance</field>
|
||||
<field name="report_type">liability</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Chart of Accounts
|
||||
-->
|
||||
|
||||
<record id="chart0" model="account.account">
|
||||
<field name="code">X0</field>
|
||||
<field name="name">Chart For Automated Tests</field>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_view"/>
|
||||
</record>
|
||||
|
||||
<!-- Balance Sheet -->
|
||||
|
||||
<record id="bal" model="account.account">
|
||||
<field name="code">X1</field>
|
||||
<field name="name">Balance Sheet - (test)</field>
|
||||
<field ref="chart0" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_view"/>
|
||||
</record>
|
||||
|
||||
<record model="account.account" id="assets_view">
|
||||
<field name="name">Assets - (test)</field>
|
||||
<field name="code">X10</field>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
<field name="reconcile" eval="False"/>
|
||||
<field name="parent_id" ref="bal"/>
|
||||
</record>
|
||||
|
||||
<record id="fas" model="account.account">
|
||||
<field name="code">X100</field>
|
||||
<field name="name">Fixed Assets - (test)</field>
|
||||
<field ref="assets_view" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="xfa" model="account.account">
|
||||
<field name="code">X1000</field>
|
||||
<field name="name">Fixed Asset Account - (test)</field>
|
||||
<field ref="fas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="nca" model="account.account">
|
||||
<field name="code">X101</field>
|
||||
<field name="name">Net Current Assets - (test)</field>
|
||||
<field ref="assets_view" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="cas" model="account.account">
|
||||
<field name="code">X1100</field>
|
||||
<field name="name">Current Assets - (test)</field>
|
||||
<field ref="nca" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="stk" model="account.account">
|
||||
<field name="code">X11001</field>
|
||||
<field name="name">Purchased Stocks - (test)</field>
|
||||
<field ref="cas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="a_recv" model="account.account">
|
||||
<field name="code">X11002</field>
|
||||
<field name="name">Debtors - (test)</field>
|
||||
<field ref="cas" name="parent_id"/>
|
||||
<field name="type">receivable</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="user_type" ref="data_account_type_receivable"/>
|
||||
</record>
|
||||
|
||||
<record id="ova" model="account.account">
|
||||
<field name="code">X11003</field>
|
||||
<field name="name">Output VAT - (test)</field>
|
||||
<field ref="cas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="bnk" model="account.account">
|
||||
<field name="code">X11004</field>
|
||||
<field name="name">Bank Current Account - (test)</field>
|
||||
<field ref="cas" name="parent_id"/>
|
||||
<field name="type">liquidity</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="cash" model="account.account">
|
||||
<field name="code">X11005</field>
|
||||
<field name="name">Cash - (test)</field>
|
||||
<field ref="cas" name="parent_id"/>
|
||||
<field name="type">liquidity</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
</record>
|
||||
|
||||
<record id="o_income" model="account.account">
|
||||
<field name="code">X11006</field>
|
||||
<field name="name">Opening Income - (test)</field>
|
||||
<field ref="cas" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_income"/>
|
||||
</record>
|
||||
<record id="usd_bnk" model="account.account">
|
||||
<field name="code">X11007</field>
|
||||
<field name="name">USD Bank Account - (test)</field>
|
||||
<field ref="cas" name="parent_id"/>
|
||||
<field name="type">liquidity</field>
|
||||
<field name="user_type" ref="data_account_type_asset"/>
|
||||
<field name="currency_id" ref="base.USD"/>
|
||||
</record>
|
||||
|
||||
<record model="account.account" id="liabilities_view">
|
||||
<field name="name">Liabilities - (test)</field>
|
||||
<field name="code">X11</field>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_liability"/>
|
||||
<field name="reconcile" eval="False"/>
|
||||
<field name="parent_id" ref="bal"/>
|
||||
</record>
|
||||
|
||||
<record id="cli" model="account.account">
|
||||
<field name="code">X110</field>
|
||||
<field name="name">Current Liabilities - (test)</field>
|
||||
<field ref="liabilities_view" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_liability"/>
|
||||
</record>
|
||||
|
||||
<record id="a_pay" model="account.account">
|
||||
<field name="code">X1111</field>
|
||||
<field name="name">Creditors - (test)</field>
|
||||
<field ref="cli" name="parent_id"/>
|
||||
<field name="type">payable</field>
|
||||
<field eval="True" name="reconcile"/>
|
||||
<field name="user_type" ref="data_account_type_payable"/>
|
||||
</record>
|
||||
|
||||
<record id="iva" model="account.account">
|
||||
<field name="code">X1112</field>
|
||||
<field name="name">Input VAT - (test)</field>
|
||||
<field ref="cli" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_liability"/>
|
||||
</record>
|
||||
|
||||
<record id="rsa" model="account.account">
|
||||
<field name="code">X1113</field>
|
||||
<field name="name">Reserve and Profit/Loss - (test)</field>
|
||||
<field ref="cli" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_liability"/>
|
||||
</record>
|
||||
|
||||
<record id="o_expense" model="account.account">
|
||||
<field name="code">X1114</field>
|
||||
<field name="name">Opening Expense - (test)</field>
|
||||
<field ref="cli" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<!-- Profit and Loss -->
|
||||
|
||||
<record id="gpf" model="account.account">
|
||||
<field name="code">X2</field>
|
||||
<field name="name">Profit and Loss - (test)</field>
|
||||
<field ref="chart0" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_view"/>
|
||||
</record>
|
||||
|
||||
<record model="account.account" id="income_view">
|
||||
<field name="name">Income - (test)</field>
|
||||
<field name="code">X20</field>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_income"/>
|
||||
<field name="reconcile" eval="False"/>
|
||||
<field name="parent_id" ref="gpf"/>
|
||||
</record>
|
||||
|
||||
<record model="account.account" id="income_fx_income">
|
||||
<field name="name">Foreign Exchange Gain - (test)</field>
|
||||
<field name="code">X201</field>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_income"/>
|
||||
<field name="reconcile" eval="False"/>
|
||||
<field name="parent_id" ref="income_view"/>
|
||||
</record>
|
||||
|
||||
<record id="rev" model="account.account">
|
||||
<field name="code">X200</field>
|
||||
<field name="name">Revenue - (test)</field>
|
||||
<field ref="income_view" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_income"/>
|
||||
</record>
|
||||
|
||||
<record id="a_sale" model="account.account">
|
||||
<field name="code">X2001</field>
|
||||
<field name="name">Product Sales - (test)</field>
|
||||
<field ref="rev" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_income"/>
|
||||
</record>
|
||||
|
||||
<record model="account.account" id="expense_view">
|
||||
<field name="name">Expense - (test)</field>
|
||||
<field name="code">X21</field>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
<field name="reconcile" eval="False"/>
|
||||
<field name="parent_id" ref="gpf"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="cos" model="account.account">
|
||||
<field name="code">X210</field>
|
||||
<field name="name">Cost of Sales - (test)</field>
|
||||
<field ref="expense_view" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<record id="cog" model="account.account">
|
||||
<field name="code">X2100</field>
|
||||
<field name="name">Cost of Goods Sold - (test)</field>
|
||||
<field ref="cos" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<record id="ovr" model="account.account">
|
||||
<field name="code">X211</field>
|
||||
<field name="name">Overheads - (test)</field>
|
||||
<field ref="expense_view" name="parent_id"/>
|
||||
<field name="type">view</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<record id="a_expense" model="account.account">
|
||||
<field name="code">X2110</field>
|
||||
<field name="name">Expenses - (test)</field>
|
||||
<field ref="ovr" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<record model="account.account" id="income_fx_expense">
|
||||
<field name="name">Foreign Exchange Loss - (test)</field>
|
||||
<field name="code">X2111</field>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
<field name="reconcile" eval="False"/>
|
||||
<field name="parent_id" ref="ovr"/>
|
||||
</record>
|
||||
|
||||
<record id="a_salary_expense" model="account.account">
|
||||
<field name="code">X2112</field>
|
||||
<field name="name">Salary Expenses - (test)</field>
|
||||
<field ref="ovr" name="parent_id"/>
|
||||
<field name="type">other</field>
|
||||
<field name="user_type" ref="data_account_type_expense"/>
|
||||
</record>
|
||||
|
||||
<!-- Properties -->
|
||||
<record forcecreate="True" id="property_account_receivable" model="ir.property">
|
||||
<field name="name">property_account_receivable</field>
|
||||
<field name="fields_id" search="[('model','=','res.partner'),('name','=','property_account_receivable')]"/>
|
||||
<field eval="'account.account,'+str(a_recv)" name="value"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record forcecreate="True" id="property_account_payable" model="ir.property">
|
||||
<field name="name">property_account_payable</field>
|
||||
<field name="fields_id" search="[('model','=','res.partner'),('name','=','property_account_payable')]"/>
|
||||
<field eval="'account.account,'+str(a_pay)" name="value"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record forcecreate="True" id="property_account_position" model="ir.property">
|
||||
<field name="name">property_account_position</field>
|
||||
<field name="fields_id" search="[('model','=','res.partner'),('name','=','property_account_position')]"/>
|
||||
<field eval="False" name="value"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Account Journal
|
||||
-->
|
||||
|
||||
<record id="sales_journal" model="account.journal">
|
||||
<field name="name">Sales Journal - (test)</field>
|
||||
<field name="code">TSAJ</field>
|
||||
<field name="type">sale</field>
|
||||
<field name="sequence_id" ref="sequence_sale_journal"/>
|
||||
<field name="default_credit_account_id" ref="a_sale"/>
|
||||
<field name="default_debit_account_id" ref="a_sale"/>
|
||||
<field name="analytic_journal_id" ref="analytic.cose_journal_sale"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
<record id="refund_sales_journal" model="account.journal">
|
||||
<field name="name">Sales Credit Note Journal - (test)</field>
|
||||
<field name="code">TSCNJ</field>
|
||||
<field name="type">sale_refund</field>
|
||||
<field name="sequence_id" ref="sequence_refund_sales_journal"/>
|
||||
<field name="default_credit_account_id" ref="a_sale"/>
|
||||
<field name="default_debit_account_id" ref="a_sale"/>
|
||||
<field name="analytic_journal_id" ref="analytic.cose_journal_sale"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
|
||||
<record id="expenses_journal" model="account.journal">
|
||||
<field name="name">Expenses Journal - (test)</field>
|
||||
<field name="code">TEXJ</field>
|
||||
<field name="type">purchase</field>
|
||||
<field name="sequence_id" ref="sequence_purchase_journal"/>
|
||||
<field name="default_debit_account_id" ref="a_expense"/>
|
||||
<field name="default_credit_account_id" ref="a_expense"/>
|
||||
<field name="analytic_journal_id" ref="exp"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
<record id="refund_expenses_journal" model="account.journal">
|
||||
<field name="name">Expenses Credit Notes Journal - (test)</field>
|
||||
<field name="code">TECNJ</field>
|
||||
<field name="type">purchase_refund</field>
|
||||
<field name="sequence_id" ref="sequence_refund_purchase_journal"/>
|
||||
<field name="default_debit_account_id" ref="a_expense"/>
|
||||
<field name="default_credit_account_id" ref="a_expense"/>
|
||||
<field name="analytic_journal_id" ref="exp"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
|
||||
<record id="bank_journal" model="account.journal">
|
||||
<field name="name">Bank Journal - (test)</field>
|
||||
<field name="code">TBNK</field>
|
||||
<field name="type">bank</field>
|
||||
<field name="sequence_id" ref="sequence_bank_journal"/>
|
||||
<field name="default_debit_account_id" ref="bnk"/>
|
||||
<field name="default_credit_account_id" ref="bnk"/>
|
||||
<field name="analytic_journal_id" ref="analytic.sit"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
<record id="check_journal" model="account.journal">
|
||||
<field name="name">Checks Journal - (test)</field>
|
||||
<field name="code">TCHK</field>
|
||||
<field name="type">bank</field>
|
||||
<field name="sequence_id" ref="sequence_check_journal"/>
|
||||
<field name="default_debit_account_id" ref="cash"/>
|
||||
<field name="default_credit_account_id" ref="cash"/>
|
||||
<field name="analytic_journal_id" ref="analytic.sit"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
<record id="cash_journal" model="account.journal">
|
||||
<field name="name">Cash Journal - (test)</field>
|
||||
<field name="code">TCSH</field>
|
||||
<field name="type">cash</field>
|
||||
<field name="profit_account_id" ref="rsa" />
|
||||
<field name="loss_account_id" ref="rsa" />
|
||||
<field name="internal_account_id" ref="rsa" />
|
||||
<field name="with_last_closing_balance" eval="True" />
|
||||
<!--
|
||||
Usually, cash payment methods requires a control at opening and closing.
|
||||
Bot for demo data, it's better to avoid the control step so that people
|
||||
that test Odoo arrive directly in the touchscreen UI.
|
||||
-->
|
||||
<field name="cash_control" eval="False"/>
|
||||
<field name="sequence_id" ref="sequence_cash_journal"/>
|
||||
<field name="default_debit_account_id" ref="cash"/>
|
||||
<field name="default_credit_account_id" ref="cash"/>
|
||||
<field name="analytic_journal_id" ref="analytic.sit"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
<record id="miscellaneous_journal" model="account.journal">
|
||||
<field name="name">Miscellaneous Journal - (test)</field>
|
||||
<field name="code">TMIS</field>
|
||||
<field name="type">general</field>
|
||||
<field name="sequence_id" ref="sequence_miscellaneous_journal"/>
|
||||
<field name="analytic_journal_id" ref="analytic.sit"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
<record id="opening_journal" model="account.journal">
|
||||
<field name="name">Opening Entries Journal - (test)</field>
|
||||
<field name="code">TOEJ</field>
|
||||
<field name="type">situation</field>
|
||||
<field name="sequence_id" ref="sequence_opening_journal"/>
|
||||
<field name="default_debit_account_id" ref="o_income"/>
|
||||
<field name="default_credit_account_id" ref="o_expense"/>
|
||||
<field eval="True" name="centralisation"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
</record>
|
||||
|
||||
<record id="bank_journal_usd" model="account.journal">
|
||||
<field name="name">USD Bank Journal - (test)</field>
|
||||
<field name="code">TUBK</field>
|
||||
<field name="type">bank</field>
|
||||
<field name="default_debit_account_id" ref="usd_bnk"/>
|
||||
<field name="default_credit_account_id" ref="usd_bnk"/>
|
||||
<field name="currency" ref="base.USD"/>
|
||||
</record>
|
||||
<!--
|
||||
Product income and expense accounts, default parameters
|
||||
-->
|
||||
|
||||
<record id="property_account_expense_categ" model="ir.property">
|
||||
<field name="name">property_account_expense_categ</field>
|
||||
<field name="fields_id" search="[('model','=','product.category'),('name','=','property_account_expense_categ')]"/>
|
||||
<field eval="'account.account,'+str(ref('account.a_expense'))" name="value"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
<record id="property_account_income_categ" model="ir.property">
|
||||
<field name="name">property_account_income_categ</field>
|
||||
<field name="fields_id" search="[('model','=','product.category'),('name','=','property_account_income_categ')]"/>
|
||||
<field eval="'account.account,'+str(ref('account.a_sale'))" model="account.account" name="value"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,37 @@
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_expenses')), ('tag_ids', '=', ref('account_tag_operating'))])
|
||||
vals = {
|
||||
'name': "Discount For Early Payment",
|
||||
'label': 'Discount',
|
||||
'amount_type': 'percentage',
|
||||
'amount': -7,
|
||||
}
|
||||
if account_id:
|
||||
vals['account_id'] = account_id[0]
|
||||
self._update(cr, uid, 'account.operation.template', 'account', vals, 'statement_operation_template_1')
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_expenses')), ('tag_ids', '=', ref('account_tag_operating'))])
|
||||
vals = {
|
||||
'name': "Bank Fees",
|
||||
'label': 'Bank Fees',
|
||||
'amount_type': 'percentage',
|
||||
'amount': 100.0,
|
||||
}
|
||||
if account_id:
|
||||
vals['account_id'] = account_id[0]
|
||||
self._update(cr, uid, 'account.operation.template', 'account', vals, 'statement_operation_template_2')
|
||||
-
|
||||
!python {model: ir.model.data} : |
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type', '=', ref('account.data_account_type_revenue')), ('tag_ids', '=', ref('account_tag_operating'))])
|
||||
vals = {
|
||||
'name': "Profit / Loss",
|
||||
'label': 'Profit / Loss',
|
||||
'amount_type': 'percentage',
|
||||
'amount': 100.0,
|
||||
}
|
||||
if account_id:
|
||||
vals['account_id'] = account_id[0]
|
||||
self._update(cr, uid, 'account.operation.template', 'account', vals, 'statement_operation_template_3')
|
||||
-
|
||||
@@ -1,22 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2011 OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import invoice
|
||||
@@ -1,289 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (c) 2011-2012 OpenERP S.A. <http://openerp.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.addons.edi import EDIMixin
|
||||
|
||||
from werkzeug import url_encode
|
||||
|
||||
INVOICE_LINE_EDI_STRUCT = {
|
||||
'name': True,
|
||||
'origin': True,
|
||||
'uos_id': True,
|
||||
'product_id': True,
|
||||
'price_unit': True,
|
||||
'quantity': True,
|
||||
'discount': True,
|
||||
|
||||
# fields used for web preview only - discarded on import
|
||||
'price_subtotal': True,
|
||||
}
|
||||
|
||||
INVOICE_TAX_LINE_EDI_STRUCT = {
|
||||
'name': True,
|
||||
'base': True,
|
||||
'amount': True,
|
||||
'manual': True,
|
||||
'sequence': True,
|
||||
'base_amount': True,
|
||||
'tax_amount': True,
|
||||
}
|
||||
|
||||
INVOICE_EDI_STRUCT = {
|
||||
'name': True,
|
||||
'origin': True,
|
||||
'company_id': True, # -> to be changed into partner
|
||||
'type': True, # -> reversed at import
|
||||
'internal_number': True, # -> reference at import
|
||||
'comment': True,
|
||||
'date_invoice': True,
|
||||
'date_due': True,
|
||||
'partner_id': True,
|
||||
'payment_term': True,
|
||||
#custom: currency_id
|
||||
'invoice_line': INVOICE_LINE_EDI_STRUCT,
|
||||
'tax_line': INVOICE_TAX_LINE_EDI_STRUCT,
|
||||
|
||||
# fields used for web preview only - discarded on import
|
||||
#custom: 'partner_ref'
|
||||
'amount_total': True,
|
||||
'amount_untaxed': True,
|
||||
'amount_tax': True,
|
||||
}
|
||||
|
||||
class account_invoice(osv.osv, EDIMixin):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
def edi_export(self, cr, uid, records, edi_struct=None, context=None):
|
||||
"""Exports a supplier or customer invoice"""
|
||||
edi_struct = dict(edi_struct or INVOICE_EDI_STRUCT)
|
||||
res_company = self.pool.get('res.company')
|
||||
res_partner = self.pool.get('res.partner')
|
||||
edi_doc_list = []
|
||||
for invoice in records:
|
||||
# generate the main report
|
||||
self._edi_generate_report_attachment(cr, uid, invoice, context=context)
|
||||
edi_doc = super(account_invoice,self).edi_export(cr, uid, [invoice], edi_struct, context)[0]
|
||||
edi_doc.update({
|
||||
'company_address': res_company.edi_export_address(cr, uid, invoice.company_id, context=context),
|
||||
'company_paypal_account': invoice.company_id.paypal_account,
|
||||
'partner_address': res_partner.edi_export(cr, uid, [invoice.partner_id], context=context)[0],
|
||||
'currency': self.pool.get('res.currency').edi_export(cr, uid, [invoice.currency_id], context=context)[0],
|
||||
'partner_ref': invoice.reference or False,
|
||||
})
|
||||
edi_doc_list.append(edi_doc)
|
||||
return edi_doc_list
|
||||
|
||||
def _edi_tax_account(self, cr, uid, invoice_type='out_invoice', context=None):
|
||||
#TODO/FIXME: should select proper Tax Account
|
||||
account_pool = self.pool.get('account.account')
|
||||
account_ids = account_pool.search(cr, uid, [('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')])
|
||||
tax_account = False
|
||||
if account_ids:
|
||||
tax_account = account_pool.browse(cr, uid, account_ids[0])
|
||||
return tax_account
|
||||
|
||||
def _edi_invoice_account(self, cr, uid, partner_id, invoice_type, context=None):
|
||||
res_partner = self.pool.get('res.partner')
|
||||
partner = res_partner.browse(cr, uid, partner_id, context=context)
|
||||
if invoice_type in ('out_invoice', 'out_refund'):
|
||||
invoice_account = partner.property_account_receivable
|
||||
else:
|
||||
invoice_account = partner.property_account_payable
|
||||
return invoice_account
|
||||
|
||||
def _edi_product_account(self, cr, uid, product_id, invoice_type, context=None):
|
||||
product_pool = self.pool.get('product.product')
|
||||
product = product_pool.browse(cr, uid, product_id, context=context)
|
||||
if invoice_type in ('out_invoice','out_refund'):
|
||||
account = product.property_account_income or product.categ_id.property_account_income_categ
|
||||
else:
|
||||
account = product.property_account_expense or product.categ_id.property_account_expense_categ
|
||||
return account
|
||||
|
||||
def _edi_import_company(self, cr, uid, edi_document, context=None):
|
||||
# TODO: for multi-company setups, we currently import the document in the
|
||||
# user's current company, but we should perhaps foresee a way to select
|
||||
# the desired company among the user's allowed companies
|
||||
|
||||
self._edi_requires_attributes(('company_id','company_address','type'), edi_document)
|
||||
res_partner = self.pool.get('res.partner')
|
||||
|
||||
xid, company_name = edi_document.pop('company_id')
|
||||
# Retrofit address info into a unified partner info (changed in v7 - used to keep them separate)
|
||||
company_address_edi = edi_document.pop('company_address')
|
||||
company_address_edi['name'] = company_name
|
||||
company_address_edi['is_company'] = True
|
||||
company_address_edi['__import_model'] = 'res.partner'
|
||||
company_address_edi['__id'] = xid # override address ID, as of v7 they should be the same anyway
|
||||
if company_address_edi.get('logo'):
|
||||
company_address_edi['image'] = company_address_edi.pop('logo')
|
||||
|
||||
invoice_type = edi_document['type']
|
||||
if invoice_type.startswith('out_'):
|
||||
company_address_edi['customer'] = True
|
||||
else:
|
||||
company_address_edi['supplier'] = True
|
||||
partner_id = res_partner.edi_import(cr, uid, company_address_edi, context=context)
|
||||
|
||||
# modify edi_document to refer to new partner
|
||||
partner = res_partner.browse(cr, uid, partner_id, context=context)
|
||||
partner_edi_m2o = self.edi_m2o(cr, uid, partner, context=context)
|
||||
edi_document['partner_id'] = partner_edi_m2o
|
||||
edi_document.pop('partner_address', None) # ignored, that's supposed to be our own address!
|
||||
|
||||
return partner_id
|
||||
|
||||
def edi_import(self, cr, uid, edi_document, context=None):
|
||||
""" During import, invoices will import the company that is provided in the invoice as
|
||||
a new partner (e.g. supplier company for a customer invoice will be come a supplier
|
||||
record for the new invoice.
|
||||
Summary of tasks that need to be done:
|
||||
- import company as a new partner, if type==in then supplier=1, else customer=1
|
||||
- partner_id field is modified to point to the new partner
|
||||
- company_address data used to add address to new partner
|
||||
- change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund'
|
||||
- reference: should contain the value of the 'internal_number'
|
||||
- reference_type: 'none'
|
||||
- internal number: reset to False, auto-generated
|
||||
- journal_id: should be selected based on type: simply put the 'type'
|
||||
in the context when calling create(), will be selected correctly
|
||||
- payment_term: if set, create a default one based on name...
|
||||
- for invoice lines, the account_id value should be taken from the
|
||||
product's default, i.e. from the default category, as it will not
|
||||
be provided.
|
||||
- for tax lines, we disconnect from the invoice.line, so all tax lines
|
||||
will be of type 'manual', and default accounts should be picked based
|
||||
on the tax config of the DB where it is imported.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
self._edi_requires_attributes(('company_id','company_address','type','invoice_line','currency'), edi_document)
|
||||
|
||||
# extract currency info
|
||||
res_currency = self.pool.get('res.currency')
|
||||
currency_info = edi_document.pop('currency')
|
||||
currency_id = res_currency.edi_import(cr, uid, currency_info, context=context)
|
||||
currency = res_currency.browse(cr, uid, currency_id)
|
||||
edi_document['currency_id'] = self.edi_m2o(cr, uid, currency, context=context)
|
||||
|
||||
# change type: out_invoice'<->'in_invoice','out_refund'<->'in_refund'
|
||||
invoice_type = edi_document['type']
|
||||
invoice_type = invoice_type.startswith('in_') and invoice_type.replace('in_','out_') or invoice_type.replace('out_','in_')
|
||||
edi_document['type'] = invoice_type
|
||||
|
||||
# import company as a new partner
|
||||
partner_id = self._edi_import_company(cr, uid, edi_document, context=context)
|
||||
|
||||
# Set Account
|
||||
invoice_account = self._edi_invoice_account(cr, uid, partner_id, invoice_type, context=context)
|
||||
edi_document['account_id'] = invoice_account and self.edi_m2o(cr, uid, invoice_account, context=context) or False
|
||||
|
||||
# reference: should contain the value of the 'internal_number'
|
||||
edi_document['reference'] = edi_document.get('internal_number', False)
|
||||
# reference_type: 'none'
|
||||
edi_document['reference_type'] = 'none'
|
||||
|
||||
# internal number: reset to False, auto-generated
|
||||
edi_document['internal_number'] = False
|
||||
|
||||
# discard web preview fields, if present
|
||||
edi_document.pop('partner_ref', None)
|
||||
|
||||
# journal_id: should be selected based on type: simply put the 'type' in the context when calling create(), will be selected correctly
|
||||
context = dict(context, type=invoice_type)
|
||||
|
||||
# for invoice lines, the account_id value should be taken from the product's default, i.e. from the default category, as it will not be provided.
|
||||
for edi_invoice_line in edi_document['invoice_line']:
|
||||
product_info = edi_invoice_line['product_id']
|
||||
product_id = self.edi_import_relation(cr, uid, 'product.product', product_info[1],
|
||||
product_info[0], context=context)
|
||||
account = self._edi_product_account(cr, uid, product_id, invoice_type, context=context)
|
||||
# TODO: could be improved with fiscal positions perhaps
|
||||
# account = fpos_obj.map_account(cr, uid, fiscal_position_id, account.id)
|
||||
edi_invoice_line['account_id'] = self.edi_m2o(cr, uid, account, context=context) if account else False
|
||||
|
||||
# discard web preview fields, if present
|
||||
edi_invoice_line.pop('price_subtotal', None)
|
||||
|
||||
# for tax lines, we disconnect from the invoice.line, so all tax lines will be of type 'manual', and default accounts should be picked based
|
||||
# on the tax config of the DB where it is imported.
|
||||
tax_account = self._edi_tax_account(cr, uid, context=context)
|
||||
tax_account_info = self.edi_m2o(cr, uid, tax_account, context=context)
|
||||
for edi_tax_line in edi_document.get('tax_line', []):
|
||||
edi_tax_line['account_id'] = tax_account_info
|
||||
edi_tax_line['manual'] = True
|
||||
|
||||
return super(account_invoice,self).edi_import(cr, uid, edi_document, context=context)
|
||||
|
||||
|
||||
def _edi_record_display_action(self, cr, uid, id, context=None):
|
||||
"""Returns an appropriate action definition dict for displaying
|
||||
the record with ID ``rec_id``.
|
||||
|
||||
:param int id: database ID of record to display
|
||||
:return: action definition dict
|
||||
"""
|
||||
action = super(account_invoice,self)._edi_record_display_action(cr, uid, id, context=context)
|
||||
try:
|
||||
invoice = self.browse(cr, uid, id, context=context)
|
||||
if 'out_' in invoice.type:
|
||||
view_ext_id = 'invoice_form'
|
||||
journal_type = 'sale'
|
||||
else:
|
||||
view_ext_id = 'invoice_supplier_form'
|
||||
journal_type = 'purchase'
|
||||
ctx = "{'type': '%s', 'journal_type': '%s'}" % (invoice.type, journal_type)
|
||||
action.update(context=ctx)
|
||||
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', view_ext_id)[1]
|
||||
action.update(views=[(view_id,'form'), (False, 'tree')])
|
||||
except ValueError:
|
||||
# ignore if views are missing
|
||||
pass
|
||||
return action
|
||||
|
||||
def _edi_paypal_url(self, cr, uid, ids, field, arg, context=None):
|
||||
res = dict.fromkeys(ids, False)
|
||||
for inv in self.browse(cr, uid, ids, context=context):
|
||||
if inv.type == 'out_invoice' and inv.company_id.paypal_account:
|
||||
params = {
|
||||
"cmd": "_xclick",
|
||||
"business": inv.company_id.paypal_account,
|
||||
"item_name": "%s Invoice %s" % (inv.company_id.name, inv.number or ''),
|
||||
"invoice": inv.number,
|
||||
"amount": inv.residual,
|
||||
"currency_code": inv.currency_id.name,
|
||||
"button_subtype": "services",
|
||||
"no_note": "1",
|
||||
"bn": "OpenERP_Invoice_PayNow_" + inv.currency_id.name,
|
||||
}
|
||||
res[inv.id] = "https://www.paypal.com/cgi-bin/webscr?" + url_encode(params)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'paypal_url': fields.function(_edi_paypal_url, type='char', string='Paypal Url'),
|
||||
}
|
||||
|
||||
|
||||
class account_invoice_line(osv.osv, EDIMixin):
|
||||
_inherit='account.invoice.line'
|
||||
|
||||
class account_invoice_tax(osv.osv, EDIMixin):
|
||||
_inherit = "account.invoice.tax"
|
||||
@@ -2697,11 +2697,6 @@ msgstr ""
|
||||
msgid "Company Analysis"
|
||||
msgstr ""
|
||||
|
||||
#. module: account
|
||||
#: field:account.account,company_currency_id:0
|
||||
msgid "Company Currency"
|
||||
msgstr ""
|
||||
|
||||
#. module: account
|
||||
#: field:account.config.settings,has_chart_of_accounts:0
|
||||
msgid "Company has a chart of accounts"
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import logging
|
||||
from operator import itemgetter
|
||||
import time
|
||||
import urllib2
|
||||
import urlparse
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json # noqa
|
||||
|
||||
from openerp.release import serie
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class account_installer(osv.osv_memory):
|
||||
_name = 'account.installer'
|
||||
_inherit = 'res.config.installer'
|
||||
|
||||
def _get_charts(self, cr, uid, context=None):
|
||||
modules = self.pool.get('ir.module.module')
|
||||
|
||||
# try get the list on apps server
|
||||
try:
|
||||
apps_server = self.pool.get('ir.module.module').get_apps_server(cr, uid, context=context)
|
||||
|
||||
up = urlparse.urlparse(apps_server)
|
||||
url = '{0.scheme}://{0.netloc}/apps/charts?serie={1}'.format(up, serie)
|
||||
|
||||
j = urllib2.urlopen(url, timeout=3).read()
|
||||
apps_charts = json.loads(j)
|
||||
|
||||
charts = dict(apps_charts)
|
||||
except Exception:
|
||||
charts = dict()
|
||||
|
||||
# Looking for the module with the 'Account Charts' category
|
||||
category_name, category_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'module_category_localization_account_charts')
|
||||
ids = modules.search(cr, uid, [('category_id', '=', category_id)], context=context)
|
||||
if ids:
|
||||
charts.update((m.name, m.shortdesc) for m in modules.browse(cr, uid, ids, context=context))
|
||||
|
||||
charts = sorted(charts.items(), key=itemgetter(1))
|
||||
charts.insert(0, ('configurable', _('Custom')))
|
||||
return charts
|
||||
|
||||
_columns = {
|
||||
# Accounting
|
||||
'charts': fields.selection(_get_charts, 'Accounting Package',
|
||||
required=True,
|
||||
help="Installs localized accounting charts to match as closely as "
|
||||
"possible the accounting needs of your company based on your "
|
||||
"country."),
|
||||
'date_start': fields.date('Start Date', required=True),
|
||||
'date_stop': fields.date('End Date', required=True),
|
||||
'period': fields.selection([('month', 'Monthly'), ('3months', '3 Monthly')], 'Periods', required=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'has_default_company': fields.boolean('Has Default Company', readonly=True),
|
||||
}
|
||||
|
||||
def _default_company(self, cr, uid, context=None):
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
return user.company_id and user.company_id.id or False
|
||||
|
||||
def _default_has_default_company(self, cr, uid, context=None):
|
||||
count = self.pool.get('res.company').search_count(cr, uid, [], context=context)
|
||||
return bool(count == 1)
|
||||
|
||||
_defaults = {
|
||||
'date_start': lambda *a: time.strftime('%Y-01-01'),
|
||||
'date_stop': lambda *a: time.strftime('%Y-12-31'),
|
||||
'period': 'month',
|
||||
'company_id': _default_company,
|
||||
'has_default_company': _default_has_default_company,
|
||||
'charts': 'configurable'
|
||||
}
|
||||
|
||||
def get_unconfigured_cmp(self, cr, uid, context=None):
|
||||
""" get the list of companies that have not been configured yet
|
||||
but don't care about the demo chart of accounts """
|
||||
company_ids = self.pool.get('res.company').search(cr, uid, [], context=context)
|
||||
cr.execute("SELECT company_id FROM account_account WHERE active = 't' AND account_account.parent_id IS NULL AND name != %s", ("Chart For Automated Tests",))
|
||||
configured_cmp = [r[0] for r in cr.fetchall()]
|
||||
return list(set(company_ids)-set(configured_cmp))
|
||||
|
||||
def check_unconfigured_cmp(self, cr, uid, context=None):
|
||||
""" check if there are still unconfigured companies """
|
||||
if not self.get_unconfigured_cmp(cr, uid, context=context):
|
||||
raise UserError(_("There is currently no company without chart of account. The wizard will therefore not be executed."))
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
if context is None: context = {}
|
||||
res = super(account_installer, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=False)
|
||||
cmp_select = []
|
||||
# display in the widget selection only the companies that haven't been configured yet
|
||||
unconfigured_cmp = self.get_unconfigured_cmp(cr, uid, context=context)
|
||||
for field in res['fields']:
|
||||
if field == 'company_id':
|
||||
res['fields'][field]['domain'] = [('id', 'in', unconfigured_cmp)]
|
||||
res['fields'][field]['selection'] = [('', '')]
|
||||
if unconfigured_cmp:
|
||||
cmp_select = [(line.id, line.name) for line in self.pool.get('res.company').browse(cr, uid, unconfigured_cmp)]
|
||||
res['fields'][field]['selection'] = cmp_select
|
||||
return res
|
||||
|
||||
def on_change_start_date(self, cr, uid, id, start_date=False):
|
||||
if start_date:
|
||||
start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
|
||||
end_date = (start_date + relativedelta(months=12)) - relativedelta(days=1)
|
||||
return {'value': {'date_stop': end_date.strftime('%Y-%m-%d')}}
|
||||
return {}
|
||||
|
||||
def execute(self, cr, uid, ids, context=None):
|
||||
self.execute_simple(cr, uid, ids, context)
|
||||
return super(account_installer, self).execute(cr, uid, ids, context=context)
|
||||
|
||||
def execute_simple(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
fy_obj = self.pool.get('account.fiscalyear')
|
||||
for res in self.read(cr, uid, ids, context=context):
|
||||
if 'date_start' in res and 'date_stop' in res:
|
||||
f_ids = fy_obj.search(cr, uid, [('date_start', '<=', res['date_start']), ('date_stop', '>=', res['date_stop']), ('company_id', '=', res['company_id'][0])], context=context)
|
||||
if not f_ids:
|
||||
name = code = res['date_start'][:4]
|
||||
if int(name) != int(res['date_stop'][:4]):
|
||||
name = res['date_start'][:4] + '-' + res['date_stop'][:4]
|
||||
code = res['date_start'][2:4] + '-' + res['date_stop'][2:4]
|
||||
vals = {
|
||||
'name': name,
|
||||
'code': code,
|
||||
'date_start': res['date_start'],
|
||||
'date_stop': res['date_stop'],
|
||||
'company_id': res['company_id'][0]
|
||||
}
|
||||
fiscal_id = fy_obj.create(cr, uid, vals, context=context)
|
||||
if res['period'] == 'month':
|
||||
fy_obj.create_period(cr, uid, [fiscal_id])
|
||||
elif res['period'] == '3months':
|
||||
fy_obj.create_period3(cr, uid, [fiscal_id])
|
||||
|
||||
def modules_to_install(self, cr, uid, ids, context=None):
|
||||
modules = super(account_installer, self).modules_to_install(
|
||||
cr, uid, ids, context=context)
|
||||
chart = self.read(cr, uid, ids, ['charts'],
|
||||
context=context)[0]['charts']
|
||||
_logger.debug('Installing chart of accounts %s', chart)
|
||||
return (modules | set([chart])) - set(['has_default_company', 'configurable'])
|
||||
@@ -1,61 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from operator import itemgetter
|
||||
import time
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp import api
|
||||
from openerp import api, fields, models, _
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from datetime import datetime, timedelta
|
||||
from openerp.tools.misc import formatLang
|
||||
|
||||
class account_fiscal_position(osv.osv):
|
||||
|
||||
class AccountFiscalPosition(models.Model):
|
||||
_name = 'account.fiscal.position'
|
||||
_description = 'Fiscal Position'
|
||||
_order = 'sequence'
|
||||
_columns = {
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'name': fields.char('Fiscal Position', required=True),
|
||||
'active': fields.boolean('Active', help="By unchecking the active field, you may hide a fiscal position without deleting it."),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'account_ids': fields.one2many('account.fiscal.position.account', 'position_id', 'Account Mapping', copy=True),
|
||||
'tax_ids': fields.one2many('account.fiscal.position.tax', 'position_id', 'Tax Mapping', copy=True),
|
||||
'note': fields.text('Notes'),
|
||||
'auto_apply': fields.boolean('Automatic', help="Apply automatically this fiscal position if the conditions match."),
|
||||
'vat_required': fields.boolean('VAT required', help="Apply only if partner has a VAT number."),
|
||||
'country_id': fields.many2one('res.country', 'Country', help="Apply when the shipping or invoicing country matches. Takes precedence over positions matching on a country group."),
|
||||
'country_group_id': fields.many2one('res.country.group', 'Country Group', help="Apply when the shipping or invoicing country is in this country group, and no position matches the country directly."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'active': True,
|
||||
}
|
||||
sequence = fields.Integer()
|
||||
name = fields.Char(string='Fiscal Position', required=True)
|
||||
active = fields.Boolean(default=True,
|
||||
help="By unchecking the active field, you may hide a fiscal position without deleting it.")
|
||||
company_id = fields.Many2one('res.company', string='Company')
|
||||
account_ids = fields.One2many('account.fiscal.position.account', 'position_id', string='Account Mapping', copy=True)
|
||||
tax_ids = fields.One2many('account.fiscal.position.tax', 'position_id', string='Tax Mapping', copy=True)
|
||||
note = fields.Text('Notes')
|
||||
auto_apply = fields.Boolean(string='Automatic', help="Apply automatically this fiscal position.")
|
||||
vat_required = fields.Boolean(string='VAT required', help="Apply only if partner has a VAT number.")
|
||||
country_id = fields.Many2one('res.country', string='Countries',
|
||||
help="Apply only if delivery or invoicing country match.")
|
||||
country_group_id = fields.Many2one('res.country.group', string='Country Group',
|
||||
help="Apply only if delivery or invocing country match the group.")
|
||||
|
||||
def _check_country(self, cr, uid, ids, context=None):
|
||||
obj = self.browse(cr, uid, ids[0], context=context)
|
||||
if obj.country_id and obj.country_group_id:
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_country, 'You can not select a country and a group of countries', ['country_id', 'country_group_id']),
|
||||
]
|
||||
@api.one
|
||||
@api.constrains('country_id', 'country_group_id')
|
||||
def _check_country(self):
|
||||
if self.country_id and self.country_group_id:
|
||||
raise UserError(_('You can not select a country and a group of countries.'))
|
||||
|
||||
@api.v7
|
||||
def map_tax(self, cr, uid, fposition_id, taxes, context=None):
|
||||
@@ -70,7 +49,7 @@ class account_fiscal_position(osv.osv):
|
||||
if tax.tax_src_id.id == t.id:
|
||||
if tax.tax_dest_id:
|
||||
result.add(tax.tax_dest_id.id)
|
||||
ok=True
|
||||
ok = True
|
||||
if not ok:
|
||||
result.add(t.id)
|
||||
return list(result)
|
||||
@@ -106,12 +85,25 @@ class account_fiscal_position(osv.osv):
|
||||
return pos.account_dest_id
|
||||
return account
|
||||
|
||||
def get_fiscal_position(self, cr, uid, company_id, partner_id, delivery_id=None, context=None):
|
||||
@api.v8
|
||||
def map_accounts(self, accounts):
|
||||
""" Receive a dictionary having accounts in values and try to replace those accounts accordingly to the fiscal position.
|
||||
"""
|
||||
ref_dict = {}
|
||||
for line in self.account_ids:
|
||||
ref_dict[line.account_src_id] = line.account_dest_id
|
||||
for key, acc in accounts.items():
|
||||
if acc in ref_dict:
|
||||
accounts[key] = ref_dict[acc]
|
||||
return accounts
|
||||
|
||||
@api.model
|
||||
def get_fiscal_position(self, partner_id, delivery_id=None):
|
||||
if not partner_id:
|
||||
return False
|
||||
# This can be easily overriden to apply more complex fiscal rules
|
||||
part_obj = self.pool['res.partner']
|
||||
partner = part_obj.browse(cr, uid, partner_id, context=context)
|
||||
PartnerObj = self.env['res.partner']
|
||||
partner = PartnerObj.browse(partner_id)
|
||||
|
||||
# partner manually set fiscal position always win
|
||||
if partner.property_account_position:
|
||||
@@ -119,7 +111,7 @@ class account_fiscal_position(osv.osv):
|
||||
|
||||
# if no delivery use invocing
|
||||
if delivery_id:
|
||||
delivery = part_obj.browse(cr, uid, delivery_id, context=context)
|
||||
delivery = PartnerObj.browse(delivery_id)
|
||||
else:
|
||||
delivery = partner
|
||||
|
||||
@@ -130,28 +122,29 @@ class account_fiscal_position(osv.osv):
|
||||
|
||||
for domain in domains:
|
||||
if delivery.country_id.id:
|
||||
fiscal_position_ids = self.search(cr, uid, domain + [('country_id', '=', delivery.country_id.id)], context=context, limit=1)
|
||||
if fiscal_position_ids:
|
||||
return fiscal_position_ids[0]
|
||||
fiscal_position = self.search(domain + [('country_id', '=', delivery.country_id.id)], limit=1)
|
||||
if fiscal_position:
|
||||
return fiscal_position.id
|
||||
|
||||
fiscal_position_ids = self.search(cr, uid, domain + [('country_group_id.country_ids', '=', delivery.country_id.id)], context=context, limit=1)
|
||||
if fiscal_position_ids:
|
||||
return fiscal_position_ids[0]
|
||||
fiscal_position = self.search(domain + [('country_group_id.country_ids', '=', delivery.country_id.id)], limit=1)
|
||||
if fiscal_position:
|
||||
return fiscal_position.id
|
||||
|
||||
fiscal_position_ids = self.search(cr, uid, domain + [('country_id', '=', None), ('country_group_id', '=', None)], context=context, limit=1)
|
||||
if fiscal_position_ids:
|
||||
return fiscal_position_ids[0]
|
||||
fiscal_position = self.search(domain + [('country_id', '=', None), ('country_group_id', '=', None)], limit=1)
|
||||
if fiscal_position:
|
||||
return fiscal_position.id
|
||||
return False
|
||||
|
||||
class account_fiscal_position_tax(osv.osv):
|
||||
|
||||
class AccountFiscalPositionTax(models.Model):
|
||||
_name = 'account.fiscal.position.tax'
|
||||
_description = 'Taxes Fiscal Position'
|
||||
_rec_name = 'position_id'
|
||||
_columns = {
|
||||
'position_id': fields.many2one('account.fiscal.position', 'Fiscal Position', required=True, ondelete='cascade'),
|
||||
'tax_src_id': fields.many2one('account.tax', 'Tax Source', required=True),
|
||||
'tax_dest_id': fields.many2one('account.tax', 'Replacement Tax')
|
||||
}
|
||||
|
||||
position_id = fields.Many2one('account.fiscal.position', string='Fiscal Position',
|
||||
required=True, ondelete='cascade')
|
||||
tax_src_id = fields.Many2one('account.tax', string='Tax Source', required=True)
|
||||
tax_dest_id = fields.Many2one('account.tax', string='Replacement Tax')
|
||||
|
||||
_sql_constraints = [
|
||||
('tax_src_dest_uniq',
|
||||
@@ -160,15 +153,17 @@ class account_fiscal_position_tax(osv.osv):
|
||||
]
|
||||
|
||||
|
||||
class account_fiscal_position_account(osv.osv):
|
||||
class AccountFiscalPositionAccount(models.Model):
|
||||
_name = 'account.fiscal.position.account'
|
||||
_description = 'Accounts Fiscal Position'
|
||||
_rec_name = 'position_id'
|
||||
_columns = {
|
||||
'position_id': fields.many2one('account.fiscal.position', 'Fiscal Position', required=True, ondelete='cascade'),
|
||||
'account_src_id': fields.many2one('account.account', 'Account Source', domain=[('type','<>','view')], required=True),
|
||||
'account_dest_id': fields.many2one('account.account', 'Account Destination', domain=[('type','<>','view')], required=True)
|
||||
}
|
||||
|
||||
position_id = fields.Many2one('account.fiscal.position', string='Fiscal Position',
|
||||
required=True, ondelete='cascade')
|
||||
account_src_id = fields.Many2one('account.account', string='Account Source',
|
||||
domain=[('deprecated', '=', False)], required=True)
|
||||
account_dest_id = fields.Many2one('account.account', string='Account Destination',
|
||||
domain=[('deprecated', '=', False)], required=True)
|
||||
|
||||
_sql_constraints = [
|
||||
('account_src_dest_uniq',
|
||||
@@ -177,43 +172,42 @@ class account_fiscal_position_account(osv.osv):
|
||||
]
|
||||
|
||||
|
||||
class res_partner(osv.osv):
|
||||
class ResPartner(models.Model):
|
||||
_name = 'res.partner'
|
||||
_inherit = 'res.partner'
|
||||
_description = 'Partner'
|
||||
|
||||
def _credit_debit_get(self, cr, uid, ids, field_names, arg, context=None):
|
||||
ctx = context.copy()
|
||||
ctx['all_fiscalyear'] = True
|
||||
query = self.pool.get('account.move.line')._query_get(cr, uid, context=ctx)
|
||||
cr.execute("""SELECT l.partner_id, a.type, SUM(l.debit-l.credit)
|
||||
@api.multi
|
||||
def _credit_debit_get(self):
|
||||
where_clause, where_params = self.env['account.move.line']._query_get()
|
||||
where_params = [tuple(self.ids)] + where_params
|
||||
self._cr.execute("""SELECT l.partner_id, act.type, SUM(l.debit-l.credit)
|
||||
FROM account_move_line l
|
||||
LEFT JOIN account_account a ON (l.account_id=a.id)
|
||||
WHERE a.type IN ('receivable','payable')
|
||||
LEFT JOIN account_account_type act ON (a.user_type=act.id)
|
||||
WHERE act.type IN ('receivable','payable')
|
||||
AND l.partner_id IN %s
|
||||
AND l.reconcile_id IS NULL
|
||||
AND """ + query + """
|
||||
GROUP BY l.partner_id, a.type
|
||||
""",
|
||||
(tuple(ids),))
|
||||
maps = {'receivable':'credit', 'payable':'debit' }
|
||||
res = {}
|
||||
for id in ids:
|
||||
res[id] = {}.fromkeys(field_names, 0)
|
||||
for pid,type,val in cr.fetchall():
|
||||
if val is None: val=0
|
||||
res[pid][maps[type]] = (type=='receivable') and val or -val
|
||||
return res
|
||||
AND l.reconciled IS FALSE
|
||||
""" + where_clause + """
|
||||
GROUP BY l.partner_id, act.type
|
||||
""", where_params)
|
||||
for pid, type, val in self._cr.fetchall():
|
||||
partner = self.browse(pid)
|
||||
if type == 'receivable':
|
||||
partner.credit = val
|
||||
elif type == 'payable':
|
||||
partner.debit = -val
|
||||
|
||||
def _asset_difference_search(self, cr, uid, obj, name, type, args, context=None):
|
||||
@api.multi
|
||||
def _asset_difference_search(self, type, args):
|
||||
if not args:
|
||||
return []
|
||||
having_values = tuple(map(itemgetter(2), args))
|
||||
where = ' AND '.join(
|
||||
map(lambda x: '(SUM(bal2) %(operator)s %%s)' % {
|
||||
'operator':x[1]},args))
|
||||
query = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
|
||||
cr.execute(('SELECT pid AS partner_id, SUM(bal2) FROM ' \
|
||||
query = self.env['account.move.line']._query_get()
|
||||
self._cr.execute(('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 ' \
|
||||
@@ -221,121 +215,151 @@ class res_partner(osv.osv):
|
||||
'WHERE account_id IN ' \
|
||||
'(SELECT id FROM account_account '\
|
||||
'WHERE type=%s AND active) ' \
|
||||
'AND reconcile_id IS NULL ' \
|
||||
'AND reconciled IS FALSE ' \
|
||||
'AND '+query+') AS l ' \
|
||||
'RIGHT JOIN res_partner p ' \
|
||||
'ON p.id = partner_id ) AS pl ' \
|
||||
'GROUP BY pid HAVING ' + where),
|
||||
'GROUP BY pid HAVING ' + where),
|
||||
(type,) + having_values)
|
||||
res = cr.fetchall()
|
||||
res = self._cr.fetchall()
|
||||
if not res:
|
||||
return [('id','=','0')]
|
||||
return [('id','in',map(itemgetter(0), res))]
|
||||
return [('id', '=', '0')]
|
||||
return [('id', 'in', map(itemgetter(0), res))]
|
||||
|
||||
def _credit_search(self, cr, uid, obj, name, args, context=None):
|
||||
return self._asset_difference_search(cr, uid, obj, name, 'receivable', args, context=context)
|
||||
@api.multi
|
||||
def _credit_search(self, args):
|
||||
return self._asset_difference_search('receivable', args)
|
||||
|
||||
def _debit_search(self, cr, uid, obj, name, args, context=None):
|
||||
return self._asset_difference_search(cr, uid, obj, name, 'payable', args, context=context)
|
||||
@api.multi
|
||||
def _debit_search(self, args):
|
||||
return self._asset_difference_search('payable', args)
|
||||
|
||||
def _invoice_total(self, cr, uid, ids, field_name, arg, context=None):
|
||||
result = {}
|
||||
account_invoice_report = self.pool.get('account.invoice.report')
|
||||
for partner in self.browse(cr, uid, ids, context=context):
|
||||
domain = [('partner_id', 'child_of', partner.id), ('state', 'not in', ['draft', 'cancel'])]
|
||||
invoice_ids = account_invoice_report.search(cr, uid, domain, context=context)
|
||||
invoices = account_invoice_report.browse(cr, uid, invoice_ids, context=context)
|
||||
result[partner.id] = sum(inv.user_currency_price_total for inv in invoices)
|
||||
return result
|
||||
@api.multi
|
||||
def _invoice_total(self):
|
||||
account_invoice_report = self.env['account.invoice.report']
|
||||
if not self.ids:
|
||||
self.total_invoiced = 0.0
|
||||
return True
|
||||
for partner in self:
|
||||
invoices = account_invoice_report.search([('partner_id', 'child_of', partner.id), ('state', 'not in', ['draft', 'cancel'])])
|
||||
partner.total_invoiced = sum(inv.user_currency_price_total for inv in invoices)
|
||||
|
||||
def _journal_item_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||
MoveLine = self.pool('account.move.line')
|
||||
AnalyticAccount = self.pool('account.analytic.account')
|
||||
results = {}
|
||||
for partner_id in ids:
|
||||
results[partner_id] = {}
|
||||
if 'contracts_count' in field_name:
|
||||
results[partner_id]['contracts_count'] = AnalyticAccount.search_count(cr, uid, [('partner_id', '=', partner_id)], context=context)
|
||||
if 'journal_item_count' in field_name:
|
||||
results[partner_id]['journal_item_count'] = MoveLine.search_count(cr, uid, [('partner_id', 'child_of', partner_id)], context=context)
|
||||
return results
|
||||
@api.multi
|
||||
def _journal_item_count(self):
|
||||
for partner in self:
|
||||
partner.journal_item_count = self.env['account.move.line'].search_count([('partner_id', '=', partner.id)])
|
||||
partner.contracts_count = self.env['account.analytic.account'].search_count([('partner_id', '=', partner.id)])
|
||||
|
||||
def has_something_to_reconcile(self, cr, uid, partner_id, context=None):
|
||||
'''
|
||||
at least a debit, a credit and a line older than the last reconciliation date of the partner
|
||||
'''
|
||||
cr.execute('''
|
||||
SELECT l.partner_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit
|
||||
FROM account_move_line l
|
||||
RIGHT JOIN account_account a ON (a.id = l.account_id)
|
||||
RIGHT JOIN res_partner p ON (l.partner_id = p.id)
|
||||
WHERE a.reconcile IS TRUE
|
||||
AND p.id = %s
|
||||
AND l.reconcile_id IS NULL
|
||||
AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date)
|
||||
AND l.state <> 'draft'
|
||||
GROUP BY l.partner_id''', (partner_id,))
|
||||
res = cr.dictfetchone()
|
||||
if res:
|
||||
return bool(res['debit'] and res['credit'])
|
||||
return False
|
||||
@api.multi
|
||||
def _compute_issued_total(self):
|
||||
""" Returns the issued total as will be displayed on partner view """
|
||||
today = fields.Date.context_today(self)
|
||||
for partner in self:
|
||||
domain = partner.get_followup_lines_domain(today, overdue_only=True)
|
||||
issued_total = 0
|
||||
for aml in self.env['account.move.line'].search(domain):
|
||||
issued_total += aml.amount_residual
|
||||
partner.issued_total = formatLang(self.env, issued_total, currency_obj=self.env.user.company_id.currency_id)
|
||||
|
||||
def mark_as_reconciled(self, cr, uid, ids, context=None):
|
||||
return self.write(cr, uid, ids, {'last_reconciliation_date': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
|
||||
@api.one
|
||||
def _compute_has_unreconciled_entries(self):
|
||||
# Avoid useless work if has_unreconciled_entries is not relevant for this partner
|
||||
if not self.active or not self.is_company and self.parent_id:
|
||||
return
|
||||
self.env.cr.execute(
|
||||
""" SELECT 1 FROM(
|
||||
SELECT
|
||||
p.last_time_entries_checked AS last_time_entries_checked,
|
||||
MAX(l.write_date) AS max_date
|
||||
FROM
|
||||
account_move_line l
|
||||
RIGHT JOIN account_account a ON (a.id = l.account_id)
|
||||
RIGHT JOIN res_partner p ON (l.partner_id = p.id)
|
||||
WHERE
|
||||
p.id = %s
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM account_move_line l
|
||||
WHERE l.account_id = a.id
|
||||
AND l.partner_id = p.id
|
||||
AND l.amount_residual > 0
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM account_move_line l
|
||||
WHERE l.account_id = a.id
|
||||
AND l.partner_id = p.id
|
||||
AND l.amount_residual < 0
|
||||
)
|
||||
GROUP BY p.last_time_entries_checked
|
||||
) as s
|
||||
WHERE (last_time_entries_checked IS NULL OR max_date > last_time_entries_checked)
|
||||
""" % (self.id,))
|
||||
self.has_unreconciled_entries = self.env.cr.rowcount == 1
|
||||
|
||||
_columns = {
|
||||
'vat_subjected': fields.boolean('VAT Legal Statement', help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement."),
|
||||
'credit': fields.function(_credit_debit_get,
|
||||
fnct_search=_credit_search, string='Total Receivable', multi='dc', help="Total amount this customer owes you."),
|
||||
'debit': fields.function(_credit_debit_get, fnct_search=_debit_search, string='Total Payable', multi='dc', help="Total amount you have to pay to this supplier."),
|
||||
'debit_limit': fields.float('Payable Limit'),
|
||||
'total_invoiced': fields.function(_invoice_total, string="Total Invoiced", type='float', groups='account.group_account_invoice'),
|
||||
@api.multi
|
||||
def mark_as_reconciled(self):
|
||||
return self.write({'last_time_entries_checked': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)})
|
||||
|
||||
'contracts_count': fields.function(_journal_item_count, string="Contracts", type='integer', multi="invoice_journal"),
|
||||
'journal_item_count': fields.function(_journal_item_count, string="Journal Items", type="integer", multi="invoice_journal"),
|
||||
'property_account_payable': fields.property(
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Account Payable",
|
||||
domain="[('type', '=', 'payable')]",
|
||||
help="This account will be used instead of the default one as the payable account for the current partner",
|
||||
required=True),
|
||||
'property_account_receivable': fields.property(
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Account Receivable",
|
||||
domain="[('type', '=', 'receivable')]",
|
||||
help="This account will be used instead of the default one as the receivable account for the current partner",
|
||||
required=True),
|
||||
'property_account_position': fields.property(
|
||||
type='many2one',
|
||||
relation='account.fiscal.position',
|
||||
string="Fiscal Position",
|
||||
help="The fiscal position will determine taxes and accounts used for the partner.",
|
||||
),
|
||||
'property_payment_term': fields.property(
|
||||
type='many2one',
|
||||
relation='account.payment.term',
|
||||
string ='Customer Payment Term',
|
||||
help="This payment term will be used instead of the default one for sale orders and customer invoices"),
|
||||
'property_supplier_payment_term': fields.property(
|
||||
type='many2one',
|
||||
relation='account.payment.term',
|
||||
string ='Supplier Payment Term',
|
||||
help="This payment term will be used instead of the default one for purchase orders and supplier invoices"),
|
||||
'ref_companies': fields.one2many('res.company', 'partner_id',
|
||||
'Companies that refers to partner'),
|
||||
'last_reconciliation_date': fields.datetime(
|
||||
'Latest Full Reconciliation Date', copy=False,
|
||||
help='Date on which the partner accounting entries were fully reconciled last time. '
|
||||
'It differs from the last date where a reconciliation has been made for this partner, '
|
||||
'as here we depict the fact that nothing more was to be reconciled at this date. '
|
||||
'This can be achieved in 2 different ways: either the last unreconciled debit/credit '
|
||||
'entry of this partner was reconciled, either the user pressed the button '
|
||||
'"Nothing more to reconcile" during the manual reconciliation process.')
|
||||
}
|
||||
@api.one
|
||||
def _get_company_currency(self):
|
||||
if self.company_id:
|
||||
self.currency_id = self.company_id.currency_id
|
||||
else:
|
||||
self.currency_id = self.env.user.company_id.currency_id
|
||||
|
||||
def _commercial_fields(self, cr, uid, context=None):
|
||||
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + \
|
||||
vat_subjected = fields.Boolean('VAT Legal Statement',
|
||||
help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement.")
|
||||
credit = fields.Monetary(compute='_credit_debit_get', search=_credit_search,
|
||||
string='Total Receivable', help="Total amount this customer owes you.")
|
||||
debit = fields.Monetary(compute='_credit_debit_get', search=_debit_search, string='Total Payable',
|
||||
help="Total amount you have to pay to this supplier.")
|
||||
debit_limit = fields.Monetary('Payable Limit')
|
||||
total_invoiced = fields.Monetary(compute='_invoice_total', string="Total Invoiced",
|
||||
groups='account.group_account_invoice')
|
||||
currency_id = fields.Many2one('res.currency', compute='_get_company_currency', store=True, readonly=True,
|
||||
help='Utility field to express amount currency')
|
||||
|
||||
contracts_count = fields.Integer(compute='_journal_item_count', string="Contracts", type='integer')
|
||||
journal_item_count = fields.Integer(compute='_journal_item_count', string="Journal Items", type="integer")
|
||||
issued_total = fields.Char(compute='_compute_issued_total', string="Journal Items")
|
||||
property_account_payable = fields.Many2one('account.account', company_dependent=True,
|
||||
string="Account Payable",
|
||||
domain="[('internal_type', '=', 'payable'), ('deprecated', '=', False)]",
|
||||
help="This account will be used instead of the default one as the payable account for the current partner",
|
||||
required=True)
|
||||
property_account_receivable = fields.Many2one('account.account', company_dependent=True,
|
||||
string="Account Receivable",
|
||||
domain="[('internal_type', '=', 'receivable'), ('deprecated', '=', False)]",
|
||||
help="This account will be used instead of the default one as the receivable account for the current partner",
|
||||
required=True)
|
||||
property_account_position = fields.Many2one('account.fiscal.position', company_dependent=True,
|
||||
string="Fiscal Position",
|
||||
help="The fiscal position will determine taxes and accounts used for the partner.")
|
||||
property_payment_term = fields.Many2one('account.payment.term', company_dependent=True,
|
||||
string ='Customer Payment Term',
|
||||
help="This payment term will be used instead of the default one for sale orders and customer invoices")
|
||||
property_supplier_payment_term = fields.Many2one('account.payment.term', company_dependent=True,
|
||||
string ='Supplier Payment Term',
|
||||
help="This payment term will be used instead of the default one for purchase orders and supplier bills")
|
||||
ref_companies = fields.One2many('res.company', 'partner_id',
|
||||
string='Companies that refers to partner')
|
||||
has_unreconciled_entries = fields.Boolean(compute='_compute_has_unreconciled_entries',
|
||||
help="The partner has at least one unreconciled debit and credit since last time the invoices & payments matching was performed.")
|
||||
last_time_entries_checked = fields.Datetime(oldname='last_reconciliation_date',
|
||||
string='Latest Invoices & Payments Matching Date', readonly=True, copy=False,
|
||||
help='Last time the invoices & payments matching was performed for this partner. '
|
||||
'It is set either if there\'s not at least an unreconciled debit and an unreconciled credit '
|
||||
'or if you click the "Done" button.')
|
||||
invoice_ids = fields.One2many('account.invoice', 'partner_id', string='Invoices', readonly=True, copy=False)
|
||||
contract_ids = fields.One2many('account.analytic.account', 'partner_id', string='Contracts', readonly=True)
|
||||
|
||||
def _find_accounting_partner(self, partner):
|
||||
''' Find the partner for which the accounting entries will be created '''
|
||||
return partner.commercial_partner_id
|
||||
|
||||
@api.model
|
||||
def _commercial_fields(self):
|
||||
return super(ResPartner, self)._commercial_fields() + \
|
||||
['debit_limit', 'property_account_payable', 'property_account_receivable', 'property_account_position',
|
||||
'property_payment_term', 'property_supplier_payment_term', 'last_reconciliation_date']
|
||||
'property_payment_term', 'property_supplier_payment_term', 'last_time_entries_checked']
|
||||
|
||||
@@ -1,64 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp import api, fields, models, _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class product_category(osv.osv):
|
||||
|
||||
class ProductCategory(models.Model):
|
||||
_inherit = "product.category"
|
||||
_columns = {
|
||||
'property_account_income_categ': fields.property(
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Income Account",
|
||||
help="This account will be used for invoices to value sales."),
|
||||
'property_account_expense_categ': fields.property(
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Expense Account",
|
||||
help="This account will be used for invoices to value expenses."),
|
||||
}
|
||||
|
||||
property_account_income_categ = fields.Many2one('account.account', company_dependent=True,
|
||||
string="Income Account",
|
||||
domain=[('deprecated', '=', False)],
|
||||
help="This account will be used for invoices to value sales.")
|
||||
property_account_expense_categ = fields.Many2one('account.account', company_dependent=True,
|
||||
string="Expense Account",
|
||||
domain=[('deprecated', '=', False)],
|
||||
help="This account will be used for invoices to value expenses.")
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Products
|
||||
#----------------------------------------------------------
|
||||
|
||||
class product_template(osv.osv):
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = "product.template"
|
||||
_columns = {
|
||||
'taxes_id': fields.many2many('account.tax', 'product_taxes_rel',
|
||||
'prod_id', 'tax_id', 'Customer Taxes',
|
||||
domain=[('parent_id','=',False),('type_tax_use','in',['sale','all'])]),
|
||||
'supplier_taxes_id': fields.many2many('account.tax',
|
||||
'product_supplier_taxes_rel', 'prod_id', 'tax_id',
|
||||
'Supplier Taxes', domain=[('parent_id', '=', False),('type_tax_use','in',['purchase','all'])]),
|
||||
'property_account_income': fields.property(
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Income Account",
|
||||
help="This account will be used for invoices instead of the default one to value sales for the current product."),
|
||||
'property_account_expense': fields.property(
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Expense Account",
|
||||
help="This account will be used for invoices instead of the default one to value expenses for the current product."),
|
||||
}
|
||||
|
||||
taxes_id = fields.Many2many('account.tax', 'product_taxes_rel', 'prod_id', 'tax_id', string='Customer Taxes',
|
||||
domain=[('type_tax_use', '=', 'sale')])
|
||||
supplier_taxes_id = fields.Many2many('account.tax', 'product_supplier_taxes_rel', 'prod_id', 'tax_id', string='Supplier Taxes',
|
||||
domain=[('type_tax_use', '=', 'purchase')])
|
||||
property_account_income = fields.Many2one('account.account', company_dependent=True,
|
||||
string="Income Account",
|
||||
domain=[('deprecated', '=', False)],
|
||||
help="This account will be used for invoices instead of the default one to value sales for the current product.")
|
||||
property_account_expense = fields.Many2one('account.account', company_dependent=True,
|
||||
string="Expense Account",
|
||||
domain=[('deprecated', '=', False)],
|
||||
help="This account will be used for invoices instead of the default one to value expenses for the current product.")
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
#TODO: really? i don't see the reason we'd need that constraint..
|
||||
check = self.ids and 'uom_po_id' in vals
|
||||
if check:
|
||||
self._cr.execute("SELECT id, uom_po_id FROM product_template WHERE id IN %s", [tuple(self.ids)])
|
||||
uoms = dict(self._cr.fetchall())
|
||||
res = super(ProductTemplate, self).write(vals)
|
||||
if check:
|
||||
self._cr.execute("SELECT id, uom_po_id FROM product_template WHERE id IN %s", [tuple(self.ids)])
|
||||
if dict(self._cr.fetchall()) != uoms:
|
||||
products = self.env['product.product'].search([('product_tmpl_id', 'in', self.ids)])
|
||||
if self.env['account.move.line'].search_count([('product_id', 'in', products.ids)]):
|
||||
raise UserError(_('You can not change the unit of measure of a product that has been already used in an account journal item. If you need to change the unit of measure, you may deactivate this product.'))
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _get_product_accounts(self):
|
||||
return {
|
||||
'income': self.property_account_income or self.categ_id.property_account_income_categ,
|
||||
'expense': self.property_account_expense or self.categ_id.property_account_expense_categ
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def get_product_accounts(self, fiscal_pos=None):
|
||||
accounts = self._get_product_accounts()
|
||||
if not fiscal_pos:
|
||||
fiscal_pos = self.env['account.fiscal.position']
|
||||
return fiscal_pos.map_accounts(accounts)
|
||||
|
||||
@@ -19,19 +19,5 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import account_central_journal
|
||||
import account_general_journal
|
||||
import account_journal
|
||||
import account_balance
|
||||
import account_partner_balance
|
||||
import account_general_ledger
|
||||
import account_partner_ledger
|
||||
import account_print_overdue
|
||||
import account_aged_partner_balance
|
||||
import report_vat
|
||||
import account_invoice_report
|
||||
import account_report
|
||||
import account_entries_report
|
||||
import account_analytic_entries_report
|
||||
import account_treasury_report
|
||||
import account_financial_report
|
||||
import account_invoice_report
|
||||
|
||||
@@ -1,407 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
|
||||
|
||||
class aged_trial_report(report_sxw.rml_parse, common_report_header):
|
||||
|
||||
def __init__(self, cr, uid, name, context):
|
||||
super(aged_trial_report, self).__init__(cr, uid, name, context=context)
|
||||
self.total_account = []
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'get_lines_with_out_partner': self._get_lines_with_out_partner,
|
||||
'get_lines': self._get_lines,
|
||||
'get_total': self._get_total,
|
||||
'get_direction': self._get_direction,
|
||||
'get_for_period': self._get_for_period,
|
||||
'get_company': self._get_company,
|
||||
'get_currency': self._get_currency,
|
||||
'get_partners':self._get_partners,
|
||||
'get_account': self._get_account,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_target_move': self._get_target_move,
|
||||
})
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
obj_move = self.pool.get('account.move.line')
|
||||
ctx = data['form'].get('used_context', {})
|
||||
ctx.update({'fiscalyear': False, 'all_fiscalyear': True})
|
||||
self.query = obj_move._query_get(self.cr, self.uid, obj='l', context=ctx)
|
||||
self.direction_selection = data['form'].get('direction_selection', 'past')
|
||||
self.target_move = data['form'].get('target_move', 'all')
|
||||
self.date_from = data['form'].get('date_from', time.strftime('%Y-%m-%d'))
|
||||
if (data['form']['result_selection'] == 'customer' ):
|
||||
self.ACCOUNT_TYPE = ['receivable']
|
||||
elif (data['form']['result_selection'] == 'supplier'):
|
||||
self.ACCOUNT_TYPE = ['payable']
|
||||
else:
|
||||
self.ACCOUNT_TYPE = ['payable','receivable']
|
||||
return super(aged_trial_report, self).set_context(objects, data, ids, report_type=report_type)
|
||||
|
||||
def _get_lines(self, form):
|
||||
res = []
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
self.cr.execute('SELECT DISTINCT res_partner.id AS id,\
|
||||
res_partner.name AS name \
|
||||
FROM res_partner,account_move_line AS l, account_account, account_move am\
|
||||
WHERE (l.account_id=account_account.id) \
|
||||
AND (l.move_id=am.id) \
|
||||
AND (am.state IN %s)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND account_account.active\
|
||||
AND ((l.reconcile_id IS NULL)\
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND (l.partner_id=res_partner.id)\
|
||||
AND (l.date <= %s)\
|
||||
AND ' + self.query + ' \
|
||||
ORDER BY res_partner.name', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from,))
|
||||
partners = self.cr.dictfetchall()
|
||||
## mise a 0 du total
|
||||
for i in range(7):
|
||||
self.total_account.append(0)
|
||||
#
|
||||
# Build a string like (1,2,3) for easy use in SQL query
|
||||
partner_ids = [x['id'] for x in partners]
|
||||
if not partner_ids:
|
||||
return []
|
||||
# This dictionary will store the debit-credit for all partners, using partner_id as key.
|
||||
|
||||
totals = {}
|
||||
self.cr.execute('SELECT l.partner_id, SUM(l.debit-l.credit) \
|
||||
FROM account_move_line AS l, account_account, account_move am \
|
||||
WHERE (l.account_id = account_account.id) AND (l.move_id=am.id) \
|
||||
AND (am.state IN %s)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND (l.partner_id IN %s)\
|
||||
AND ((l.reconcile_id IS NULL)\
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND ' + self.query + '\
|
||||
AND account_account.active\
|
||||
AND (l.date <= %s)\
|
||||
GROUP BY l.partner_id ', (tuple(move_state), tuple(self.ACCOUNT_TYPE), tuple(partner_ids), self.date_from, self.date_from,))
|
||||
t = self.cr.fetchall()
|
||||
for i in t:
|
||||
totals[i[0]] = i[1]
|
||||
|
||||
# This dictionary will store the future or past of all partners
|
||||
future_past = {}
|
||||
if self.direction_selection == 'future':
|
||||
self.cr.execute('SELECT l.partner_id, SUM(l.debit-l.credit) \
|
||||
FROM account_move_line AS l, account_account, account_move am \
|
||||
WHERE (l.account_id=account_account.id) AND (l.move_id=am.id) \
|
||||
AND (am.state IN %s)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND (COALESCE(l.date_maturity, l.date) < %s)\
|
||||
AND (l.partner_id IN %s)\
|
||||
AND ((l.reconcile_id IS NULL)\
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND '+ self.query + '\
|
||||
AND account_account.active\
|
||||
AND (l.date <= %s)\
|
||||
GROUP BY l.partner_id', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, tuple(partner_ids),self.date_from, self.date_from,))
|
||||
t = self.cr.fetchall()
|
||||
for i in t:
|
||||
future_past[i[0]] = i[1]
|
||||
elif self.direction_selection == 'past': # Using elif so people could extend without this breaking
|
||||
self.cr.execute('SELECT l.partner_id, SUM(l.debit-l.credit) \
|
||||
FROM account_move_line AS l, account_account, account_move am \
|
||||
WHERE (l.account_id=account_account.id) AND (l.move_id=am.id)\
|
||||
AND (am.state IN %s)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND (COALESCE(l.date_maturity,l.date) > %s)\
|
||||
AND (l.partner_id IN %s)\
|
||||
AND ((l.reconcile_id IS NULL)\
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND '+ self.query + '\
|
||||
AND account_account.active\
|
||||
AND (l.date <= %s)\
|
||||
GROUP BY l.partner_id', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, tuple(partner_ids), self.date_from, self.date_from,))
|
||||
t = self.cr.fetchall()
|
||||
for i in t:
|
||||
future_past[i[0]] = i[1]
|
||||
|
||||
# Use one query per period and store results in history (a list variable)
|
||||
# Each history will contain: history[1] = {'<partner_id>': <partner_debit-credit>}
|
||||
history = []
|
||||
for i in range(5):
|
||||
args_list = (tuple(move_state), tuple(self.ACCOUNT_TYPE), tuple(partner_ids),self.date_from,)
|
||||
dates_query = '(COALESCE(l.date_maturity,l.date)'
|
||||
if form[str(i)]['start'] and form[str(i)]['stop']:
|
||||
dates_query += ' BETWEEN %s AND %s)'
|
||||
args_list += (form[str(i)]['start'], form[str(i)]['stop'])
|
||||
elif form[str(i)]['start']:
|
||||
dates_query += ' >= %s)'
|
||||
args_list += (form[str(i)]['start'],)
|
||||
else:
|
||||
dates_query += ' <= %s)'
|
||||
args_list += (form[str(i)]['stop'],)
|
||||
args_list += (self.date_from,)
|
||||
self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit), l.reconcile_partial_id
|
||||
FROM account_move_line AS l, account_account, account_move am
|
||||
WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)
|
||||
AND (am.state IN %s)
|
||||
AND (account_account.type IN %s)
|
||||
AND (l.partner_id IN %s)
|
||||
AND ((l.reconcile_id IS NULL)
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))
|
||||
AND ''' + self.query + '''
|
||||
AND account_account.active
|
||||
AND ''' + dates_query + '''
|
||||
AND (l.date <= %s)
|
||||
GROUP BY l.partner_id, l.reconcile_partial_id''', args_list)
|
||||
partners_partial = self.cr.fetchall()
|
||||
partners_amount = dict((i[0],0) for i in partners_partial)
|
||||
for partner_info in partners_partial:
|
||||
if partner_info[2]:
|
||||
# in case of partial reconciliation, we want to keep the left amount in the oldest period
|
||||
self.cr.execute('''SELECT MIN(COALESCE(date_maturity,date)) FROM account_move_line WHERE reconcile_partial_id = %s''', (partner_info[2],))
|
||||
date = self.cr.fetchall()
|
||||
partial = False
|
||||
if 'BETWEEN' in dates_query:
|
||||
partial = date and args_list[-3] <= date[0][0] <= args_list[-2]
|
||||
elif '>=' in dates_query:
|
||||
partial = date and date[0][0] >= form[str(i)]['start']
|
||||
else:
|
||||
partial = date and date[0][0] <= form[str(i)]['stop']
|
||||
if partial:
|
||||
# partial reconcilation
|
||||
limit_date = 'COALESCE(l.date_maturity,l.date) %s %%s' % '<=' if self.direction_selection == 'past' else '>='
|
||||
self.cr.execute('''SELECT SUM(l.debit-l.credit)
|
||||
FROM account_move_line AS l, account_move AS am
|
||||
WHERE l.move_id = am.id AND am.state in %s
|
||||
AND l.reconcile_partial_id = %s
|
||||
AND ''' + limit_date, (tuple(move_state), partner_info[2], self.date_from))
|
||||
unreconciled_amount = self.cr.fetchall()
|
||||
partners_amount[partner_info[0]] += unreconciled_amount[0][0]
|
||||
else:
|
||||
partners_amount[partner_info[0]] += partner_info[1]
|
||||
history.append(partners_amount)
|
||||
|
||||
for partner in partners:
|
||||
values = {}
|
||||
## If choise selection is in the future
|
||||
if self.direction_selection == 'future':
|
||||
# Query here is replaced by one query which gets the all the partners their 'before' value
|
||||
before = False
|
||||
if future_past.has_key(partner['id']):
|
||||
before = [ future_past[partner['id']] ]
|
||||
self.total_account[6] = self.total_account[6] + (before and before[0] or 0.0)
|
||||
values['direction'] = before and before[0] or 0.0
|
||||
elif self.direction_selection == 'past': # Changed this so people could in the future create new direction_selections
|
||||
# Query here is replaced by one query which gets the all the partners their 'after' value
|
||||
after = False
|
||||
if future_past.has_key(partner['id']): # Making sure this partner actually was found by the query
|
||||
after = [ future_past[partner['id']] ]
|
||||
|
||||
self.total_account[6] = self.total_account[6] + (after and after[0] or 0.0)
|
||||
values['direction'] = after and after[0] or 0.0
|
||||
|
||||
for i in range(5):
|
||||
during = False
|
||||
if history[i].has_key(partner['id']):
|
||||
during = [ history[i][partner['id']] ]
|
||||
# Ajout du compteur
|
||||
self.total_account[(i)] = self.total_account[(i)] + (during and during[0] or 0)
|
||||
values[str(i)] = during and during[0] or 0.0
|
||||
total = False
|
||||
if totals.has_key( partner['id'] ):
|
||||
total = [ totals[partner['id']] ]
|
||||
values['total'] = total and total[0] or 0.0
|
||||
## Add for total
|
||||
self.total_account[(i+1)] = self.total_account[(i+1)] + (total and total[0] or 0.0)
|
||||
values['name'] = partner['name']
|
||||
|
||||
res.append(values)
|
||||
|
||||
total = 0.0
|
||||
totals = {}
|
||||
for r in res:
|
||||
total += float(r['total'] or 0.0)
|
||||
for i in range(5)+['direction']:
|
||||
totals.setdefault(str(i), 0.0)
|
||||
totals[str(i)] += float(r[str(i)] or 0.0)
|
||||
return res
|
||||
|
||||
def _get_lines_with_out_partner(self, form):
|
||||
res = []
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
## mise a 0 du total
|
||||
for i in range(7):
|
||||
self.total_account.append(0)
|
||||
totals = {}
|
||||
self.cr.execute('SELECT SUM(l.debit-l.credit) \
|
||||
FROM account_move_line AS l, account_account, account_move am \
|
||||
WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)\
|
||||
AND (am.state IN %s)\
|
||||
AND (l.partner_id IS NULL)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND ((l.reconcile_id IS NULL) \
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND ' + self.query + '\
|
||||
AND (l.date <= %s)\
|
||||
AND account_account.active ',(tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from,))
|
||||
t = self.cr.fetchall()
|
||||
for i in t:
|
||||
totals['Unknown Partner'] = i[0]
|
||||
future_past = {}
|
||||
if self.direction_selection == 'future':
|
||||
self.cr.execute('SELECT SUM(l.debit-l.credit) \
|
||||
FROM account_move_line AS l, account_account, account_move am\
|
||||
WHERE (l.account_id=account_account.id) AND (l.move_id=am.id)\
|
||||
AND (am.state IN %s)\
|
||||
AND (l.partner_id IS NULL)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND (COALESCE(l.date_maturity, l.date) < %s)\
|
||||
AND ((l.reconcile_id IS NULL)\
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND '+ self.query + '\
|
||||
AND account_account.active ', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from))
|
||||
t = self.cr.fetchall()
|
||||
for i in t:
|
||||
future_past['Unknown Partner'] = i[0]
|
||||
elif self.direction_selection == 'past': # Using elif so people could extend without this breaking
|
||||
self.cr.execute('SELECT SUM(l.debit-l.credit) \
|
||||
FROM account_move_line AS l, account_account, account_move am \
|
||||
WHERE (l.account_id=account_account.id) AND (l.move_id=am.id)\
|
||||
AND (am.state IN %s)\
|
||||
AND (l.partner_id IS NULL)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND (COALESCE(l.date_maturity,l.date) > %s)\
|
||||
AND ((l.reconcile_id IS NULL)\
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND '+ self.query + '\
|
||||
AND account_account.active ', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from))
|
||||
t = self.cr.fetchall()
|
||||
for i in t:
|
||||
future_past['Unknown Partner'] = i[0]
|
||||
history = []
|
||||
|
||||
for i in range(5):
|
||||
args_list = (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from,)
|
||||
dates_query = '(COALESCE(l.date_maturity,l.date)'
|
||||
if form[str(i)]['start'] and form[str(i)]['stop']:
|
||||
dates_query += ' BETWEEN %s AND %s)'
|
||||
args_list += (form[str(i)]['start'], form[str(i)]['stop'])
|
||||
elif form[str(i)]['start']:
|
||||
dates_query += ' > %s)'
|
||||
args_list += (form[str(i)]['start'],)
|
||||
else:
|
||||
dates_query += ' < %s)'
|
||||
args_list += (form[str(i)]['stop'],)
|
||||
args_list += (self.date_from,)
|
||||
self.cr.execute('SELECT SUM(l.debit-l.credit)\
|
||||
FROM account_move_line AS l, account_account, account_move am \
|
||||
WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)\
|
||||
AND (am.state IN %s)\
|
||||
AND (account_account.type IN %s)\
|
||||
AND (l.partner_id IS NULL)\
|
||||
AND ((l.reconcile_id IS NULL)\
|
||||
OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
|
||||
AND '+ self.query + '\
|
||||
AND account_account.active\
|
||||
AND ' + dates_query + '\
|
||||
AND (l.date <= %s)\
|
||||
GROUP BY l.partner_id', args_list)
|
||||
t = self.cr.fetchall()
|
||||
d = {}
|
||||
for i in t:
|
||||
d['Unknown Partner'] = i[0]
|
||||
history.append(d)
|
||||
|
||||
values = {}
|
||||
if self.direction_selection == 'future':
|
||||
before = False
|
||||
if future_past.has_key('Unknown Partner'):
|
||||
before = [ future_past['Unknown Partner'] ]
|
||||
self.total_account[6] = self.total_account[6] + (before and before[0] or 0.0)
|
||||
values['direction'] = before and before[0] or 0.0
|
||||
elif self.direction_selection == 'past':
|
||||
after = False
|
||||
if future_past.has_key('Unknown Partner'):
|
||||
after = [ future_past['Unknown Partner'] ]
|
||||
self.total_account[6] = self.total_account[6] + (after and after[0] or 0.0)
|
||||
values['direction'] = after and after[0] or 0.0
|
||||
|
||||
for i in range(5):
|
||||
during = False
|
||||
if history[i].has_key('Unknown Partner'):
|
||||
during = [ history[i]['Unknown Partner'] ]
|
||||
self.total_account[(i)] = self.total_account[(i)] + (during and during[0] or 0)
|
||||
values[str(i)] = during and during[0] or 0.0
|
||||
|
||||
total = False
|
||||
if totals.has_key( 'Unknown Partner' ):
|
||||
total = [ totals['Unknown Partner'] ]
|
||||
values['total'] = total and total[0] or 0.0
|
||||
## Add for total
|
||||
self.total_account[(i+1)] = self.total_account[(i+1)] + (total and total[0] or 0.0)
|
||||
values['name'] = 'Unknown Partner'
|
||||
|
||||
if values['total']:
|
||||
res.append(values)
|
||||
|
||||
total = 0.0
|
||||
totals = {}
|
||||
for r in res:
|
||||
total += float(r['total'] or 0.0)
|
||||
for i in range(5)+['direction']:
|
||||
totals.setdefault(str(i), 0.0)
|
||||
totals[str(i)] += float(r[str(i)] or 0.0)
|
||||
return res
|
||||
|
||||
def _get_total(self,pos):
|
||||
period = self.total_account[int(pos)]
|
||||
return period or 0.0
|
||||
|
||||
def _get_direction(self,pos):
|
||||
period = self.total_account[int(pos)]
|
||||
return period or 0.0
|
||||
|
||||
def _get_for_period(self,pos):
|
||||
period = self.total_account[int(pos)]
|
||||
return period or 0.0
|
||||
|
||||
def _get_partners(self,data):
|
||||
# TODO: deprecated, to remove in trunk
|
||||
if data['form']['result_selection'] == 'customer':
|
||||
return self._translate('Receivable Accounts')
|
||||
elif data['form']['result_selection'] == 'supplier':
|
||||
return self._translate('Payable Accounts')
|
||||
elif data['form']['result_selection'] == 'customer_supplier':
|
||||
return self._translate('Receivable and Payable Accounts')
|
||||
return ''
|
||||
|
||||
|
||||
class report_agedpartnerbalance(osv.AbstractModel):
|
||||
_name = 'report.account.report_agedpartnerbalance'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_agedpartnerbalance'
|
||||
_wrapped_report_class = aged_trial_report
|
||||
@@ -1,75 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import tools
|
||||
from openerp.osv import fields,osv
|
||||
|
||||
class analytic_entries_report(osv.osv):
|
||||
_name = "analytic.entries.report"
|
||||
_description = "Analytic Entries Statistics"
|
||||
_auto = False
|
||||
_columns = {
|
||||
'date': fields.date('Date', readonly=True),
|
||||
'user_id': fields.many2one('res.users', 'User',readonly=True),
|
||||
'name': fields.char('Description', size=64, readonly=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', required=True),
|
||||
'account_id': fields.many2one('account.analytic.account', 'Analytic Account', required=False),
|
||||
'general_account_id': fields.many2one('account.account', 'Financial Account', required=True),
|
||||
'journal_id': fields.many2one('account.analytic.journal', 'Journal', required=True),
|
||||
'move_id': fields.many2one('account.move.line', 'Move', required=True),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True),
|
||||
'product_uom_id': fields.many2one('product.uom', 'Product Unit of Measure', required=True),
|
||||
'amount': fields.float('Amount', readonly=True),
|
||||
'unit_amount': fields.integer('Unit Amount', readonly=True),
|
||||
'nbr': fields.integer('# Entries', readonly=True), # TDE FIXME master: rename into nbr_entries
|
||||
}
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'analytic_entries_report')
|
||||
cr.execute("""
|
||||
create or replace view analytic_entries_report as (
|
||||
select
|
||||
min(a.id) as id,
|
||||
count(distinct a.id) as nbr,
|
||||
a.date as date,
|
||||
a.user_id as user_id,
|
||||
a.name as name,
|
||||
analytic.partner_id as partner_id,
|
||||
a.company_id as company_id,
|
||||
a.currency_id as currency_id,
|
||||
a.account_id as account_id,
|
||||
a.general_account_id as general_account_id,
|
||||
a.journal_id as journal_id,
|
||||
a.move_id as move_id,
|
||||
a.product_id as product_id,
|
||||
a.product_uom_id as product_uom_id,
|
||||
sum(a.amount) as amount,
|
||||
sum(a.unit_amount) as unit_amount
|
||||
from
|
||||
account_analytic_line a, account_analytic_account analytic
|
||||
where analytic.id = a.account_id
|
||||
group by
|
||||
a.date, a.user_id,a.name,analytic.partner_id,a.company_id,a.currency_id,
|
||||
a.account_id,a.general_account_id,a.journal_id,
|
||||
a.move_id,a.product_id,a.product_uom_id
|
||||
)
|
||||
""")
|
||||
@@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_analytic_entries_report_search" model="ir.ui.view">
|
||||
<field name="name">analytic.entries.report.search</field>
|
||||
<field name="model">analytic.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Analytic Entries Analysis">
|
||||
<field name="date"/>
|
||||
<filter string="My Entries" domain="[('user_id','=',uid)]" help="My Entries"/>
|
||||
<field name="account_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="product_id" />
|
||||
<field name="user_id"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Partner" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Analytic Account" name="Account" context="{'group_by':'account_id'}" groups="analytic.group_analytic_accounting"/>
|
||||
<filter string="Financial Account" context="{'group_by':'general_account_id'}"/>
|
||||
<filter string="Journal" context="{'group_by':'journal_id'}"/>
|
||||
<filter string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator/>
|
||||
<filter string="Month" name="Month" context="{'group_by':'date:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_analytic_entries_pivot" model="ir.ui.view">
|
||||
<field name="name">account.analytic.entries.pivot</field>
|
||||
<field name="model">analytic.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Analytic Entries Analysis" disable_linking="True">
|
||||
<field name="account_id" type="row"/>
|
||||
<field name="date" interval="month" type="col"/>
|
||||
<field name="nbr" type="measure"/>
|
||||
<field name="unit_amount" type="measure"/>
|
||||
<field name="amount" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_analytic_entries_graph" model="ir.ui.view">
|
||||
<field name="name">account.analytic.entries.graph</field>
|
||||
<field name="model">analytic.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Analytic Entries Analysis">
|
||||
<field name="account_id"/>
|
||||
<field name="date" interval="month"/>
|
||||
<field name="amount" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_analytic_entries_report" model="ir.actions.act_window">
|
||||
<field name="name">Analytic Entries Analysis</field>
|
||||
<field name="res_model">analytic.entries.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="search_view_id" ref="view_analytic_entries_report_search"/>
|
||||
<field name="context">{'search_default_Account':1}</field>
|
||||
<field name="help">From this view, have an analysis of your different analytic entries following the analytic account you defined matching your business need. Use the tool search to analyse information about analytic entries generated in the system.</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_analytic_entries_report"
|
||||
id="menu_action_analytic_entries_report"
|
||||
groups="analytic.group_analytic_accounting"
|
||||
parent="account.menu_finance_reporting" sequence="4"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,136 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
|
||||
from openerp.osv import osv
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
|
||||
|
||||
class account_balance(report_sxw.rml_parse, common_report_header):
|
||||
_name = 'report.account.account.balance'
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
super(account_balance, self).__init__(cr, uid, name, context=context)
|
||||
self.sum_debit = 0.00
|
||||
self.sum_credit = 0.00
|
||||
self.date_lst = []
|
||||
self.date_lst_string = ''
|
||||
self.result_acc = []
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'lines': self.lines,
|
||||
'sum_debit': self._sum_debit,
|
||||
'sum_credit': self._sum_credit,
|
||||
'get_fiscalyear':self._get_fiscalyear,
|
||||
'get_filter': self._get_filter,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period ,
|
||||
'get_account': self._get_account,
|
||||
'get_journal': self._get_journal,
|
||||
'get_start_date':self._get_start_date,
|
||||
'get_end_date':self._get_end_date,
|
||||
'get_target_move': self._get_target_move,
|
||||
})
|
||||
self.context = context
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
new_ids = ids
|
||||
if (data['model'] == 'ir.ui.menu'):
|
||||
new_ids = 'chart_account_id' in data['form'] and [data['form']['chart_account_id']] or []
|
||||
objects = self.pool.get('account.account').browse(self.cr, self.uid, new_ids)
|
||||
return super(account_balance, self).set_context(objects, data, new_ids, report_type=report_type)
|
||||
|
||||
def _get_account(self, data):
|
||||
if data['model']=='account.account':
|
||||
return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['id']).company_id.name
|
||||
return super(account_balance ,self)._get_account(data)
|
||||
|
||||
def lines(self, form, ids=None, done=None):
|
||||
def _process_child(accounts, disp_acc, parent):
|
||||
account_rec = [acct for acct in accounts if acct['id']==parent][0]
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
acc_id = self.pool.get('account.account').browse(self.cr, self.uid, account_rec['id'])
|
||||
currency = acc_id.currency_id and acc_id.currency_id or acc_id.company_id.currency_id
|
||||
res = {
|
||||
'id': account_rec['id'],
|
||||
'type': account_rec['type'],
|
||||
'code': account_rec['code'],
|
||||
'name': account_rec['name'],
|
||||
'level': account_rec['level'],
|
||||
'debit': account_rec['debit'],
|
||||
'credit': account_rec['credit'],
|
||||
'balance': account_rec['balance'],
|
||||
'parent_id': account_rec['parent_id'],
|
||||
'bal_type': '',
|
||||
}
|
||||
self.sum_debit += account_rec['debit']
|
||||
self.sum_credit += account_rec['credit']
|
||||
if disp_acc == 'movement':
|
||||
if not currency_obj.is_zero(self.cr, self.uid, currency, res['credit']) or not currency_obj.is_zero(self.cr, self.uid, currency, res['debit']) or not currency_obj.is_zero(self.cr, self.uid, currency, res['balance']):
|
||||
self.result_acc.append(res)
|
||||
elif disp_acc == 'not_zero':
|
||||
if not currency_obj.is_zero(self.cr, self.uid, currency, res['balance']):
|
||||
self.result_acc.append(res)
|
||||
else:
|
||||
self.result_acc.append(res)
|
||||
if account_rec['child_id']:
|
||||
for child in account_rec['child_id']:
|
||||
_process_child(accounts,disp_acc,child)
|
||||
|
||||
obj_account = self.pool.get('account.account')
|
||||
if not ids:
|
||||
ids = self.ids
|
||||
if not ids:
|
||||
return []
|
||||
if not done:
|
||||
done={}
|
||||
|
||||
ctx = self.context.copy()
|
||||
|
||||
ctx['fiscalyear'] = form['fiscalyear_id']
|
||||
if form['filter'] == 'filter_period':
|
||||
ctx['period_from'] = form['period_from']
|
||||
ctx['period_to'] = form['period_to']
|
||||
elif form['filter'] == 'filter_date':
|
||||
ctx['date_from'] = form['date_from']
|
||||
ctx['date_to'] = form['date_to']
|
||||
ctx['state'] = form['target_move']
|
||||
parents = ids
|
||||
child_ids = obj_account._get_children_and_consol(self.cr, self.uid, ids, ctx)
|
||||
if child_ids:
|
||||
ids = child_ids
|
||||
accounts = obj_account.read(self.cr, self.uid, ids, ['type','code','name','debit','credit','balance','parent_id','level','child_id'], ctx)
|
||||
|
||||
for parent in parents:
|
||||
if parent in done:
|
||||
continue
|
||||
done[parent] = 1
|
||||
_process_child(accounts,form['display_account'],parent)
|
||||
return self.result_acc
|
||||
|
||||
|
||||
class report_trialbalance(osv.AbstractModel):
|
||||
_name = 'report.account.report_trialbalance'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_trialbalance'
|
||||
_wrapped_report_class = account_balance
|
||||
@@ -1,114 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
#
|
||||
# Use period and Journal for selection or resources
|
||||
#
|
||||
|
||||
|
||||
class journal_print(report_sxw.rml_parse, common_report_header):
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
super(journal_print, self).__init__(cr, uid, name, context=context)
|
||||
self.period_ids = []
|
||||
self.journal_ids = []
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'lines': self.lines,
|
||||
'sum_debit': self._sum_debit,
|
||||
'sum_credit': self._sum_credit,
|
||||
'get_filter': self._get_filter,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_account': self._get_account,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_sortby': self._get_sortby,
|
||||
'get_start_date':self._get_start_date,
|
||||
'get_end_date':self._get_end_date,
|
||||
'display_currency':self._display_currency,
|
||||
'get_target_move': self._get_target_move,
|
||||
})
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
obj_move = self.pool.get('account.move.line')
|
||||
new_ids = ids
|
||||
self.query_get_clause = ''
|
||||
self.target_move = data['form'].get('target_move', 'all')
|
||||
if (data['model'] == 'ir.ui.menu'):
|
||||
new_ids = 'active_ids' in data['form'] and data['form']['active_ids'] or []
|
||||
self.query_get_clause = 'AND '
|
||||
self.query_get_clause += obj_move._query_get(self.cr, self.uid, obj='l', context=data['form'].get('used_context', {}))
|
||||
objects = self.pool.get('account.journal.period').browse(self.cr, self.uid, new_ids)
|
||||
if new_ids:
|
||||
self.cr.execute('SELECT period_id, journal_id FROM account_journal_period WHERE id IN %s', (tuple(new_ids),))
|
||||
res = self.cr.fetchall()
|
||||
self.period_ids, self.journal_ids = zip(*res)
|
||||
return super(journal_print, self).set_context(objects, data, ids, report_type=report_type)
|
||||
|
||||
def lines(self, period_id, journal_id):
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
self.cr.execute('SELECT a.currency_id, a.code, a.name, c.symbol AS currency_code, l.currency_id, l.amount_currency, SUM(debit) AS debit, SUM(credit) AS credit \
|
||||
from account_move_line l \
|
||||
LEFT JOIN account_move am ON (l.move_id=am.id) \
|
||||
LEFT JOIN account_account a ON (l.account_id=a.id) \
|
||||
LEFT JOIN res_currency c on (l.currency_id=c.id) WHERE am.state IN %s AND l.period_id=%s AND l.journal_id=%s '+self.query_get_clause+' GROUP BY a.id, a.code, a.name,l.amount_currency,c.symbol, a.currency_id,l.currency_id', (tuple(move_state), period_id, journal_id))
|
||||
return self.cr.dictfetchall()
|
||||
|
||||
def _set_get_account_currency_code(self, account_id):
|
||||
self.cr.execute("SELECT c.symbol as code "\
|
||||
"FROM res_currency c,account_account as ac "\
|
||||
"WHERE ac.id = %s AND ac.currency_id = c.id"%(account_id))
|
||||
result = self.cr.fetchone()
|
||||
if result:
|
||||
self.account_currency = result[0]
|
||||
else:
|
||||
self.account_currency = False
|
||||
|
||||
def _get_account(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return self.pool.get('account.journal.period').browse(self.cr, self.uid, data['id']).company_id.name
|
||||
return super(journal_print,self)._get_account(data)
|
||||
|
||||
def _get_fiscalyear(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return self.pool.get('account.journal.period').browse(self.cr, self.uid, data['id']).fiscalyear_id.name
|
||||
return super(journal_print,self)._get_fiscalyear(data)
|
||||
|
||||
def _display_currency(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return True
|
||||
return data['form']['amount_currency']
|
||||
|
||||
|
||||
class report_agedpartnerbalance(osv.AbstractModel):
|
||||
_name = 'report.account.report_centraljournal'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_centraljournal'
|
||||
_wrapped_report_class = journal_print
|
||||
@@ -1,145 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import tools
|
||||
from openerp.osv import fields,osv
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
class account_entries_report(osv.osv):
|
||||
_name = "account.entries.report"
|
||||
_description = "Journal Items Analysis"
|
||||
_auto = False
|
||||
_rec_name = 'date'
|
||||
_columns = {
|
||||
'date': fields.date('Effective Date', readonly=True), # TDE FIXME master: rename into date_effective
|
||||
'date_created': fields.date('Date Created', readonly=True),
|
||||
'date_maturity': fields.date('Date Maturity', readonly=True),
|
||||
'ref': fields.char('Reference', readonly=True),
|
||||
'nbr': fields.integer('# of Items', readonly=True),
|
||||
'debit': fields.float('Debit', readonly=True),
|
||||
'credit': fields.float('Credit', readonly=True),
|
||||
'balance': fields.float('Balance', readonly=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
'amount_currency': fields.float('Amount Currency', digits_compute=dp.get_precision('Account'), readonly=True),
|
||||
'period_id': fields.many2one('account.period', 'Period', readonly=True),
|
||||
'account_id': fields.many2one('account.account', 'Account', readonly=True),
|
||||
'journal_id': fields.many2one('account.journal', 'Journal', readonly=True),
|
||||
'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year', readonly=True),
|
||||
'product_id': fields.many2one('product.product', 'Product', readonly=True),
|
||||
'product_uom_id': fields.many2one('product.uom', 'Product Unit of Measure', readonly=True),
|
||||
'move_state': fields.selection([('draft','Unposted'), ('posted','Posted')], 'Status', readonly=True),
|
||||
'move_line_state': fields.selection([('draft','Unbalanced'), ('valid','Valid')], 'State of Move Line', readonly=True),
|
||||
'reconcile_id': fields.many2one('account.move.reconcile', 'Reconciliation number', readonly=True),
|
||||
'partner_id': fields.many2one('res.partner','Partner', readonly=True),
|
||||
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True),
|
||||
'quantity': fields.float('Products Quantity', digits=(16,2), readonly=True), # TDE FIXME master: rename into product_quantity
|
||||
'user_type': fields.many2one('account.account.type', 'Account Type', readonly=True),
|
||||
'type': fields.selection([
|
||||
('receivable', 'Receivable'),
|
||||
('payable', 'Payable'),
|
||||
('cash', 'Cash'),
|
||||
('view', 'View'),
|
||||
('consolidation', 'Consolidation'),
|
||||
('other', 'Regular'),
|
||||
('closed', 'Closed'),
|
||||
], 'Internal Type', readonly=True, help="This type is used to differentiate types with "\
|
||||
"special effects in Odoo: view can not have entries, consolidation are accounts that "\
|
||||
"can have children accounts for multi-company consolidations, payable/receivable are for "\
|
||||
"partners accounts (for debit/credit computations), closed for depreciated accounts."),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
}
|
||||
|
||||
_order = 'date desc'
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
||||
context=None, count=False):
|
||||
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
||||
period_obj = self.pool.get('account.period')
|
||||
for arg in args:
|
||||
if arg[0] == 'period_id' and arg[2] == 'current_period':
|
||||
current_period = period_obj.find(cr, uid, context=context)[0]
|
||||
args.append(['period_id','in',[current_period]])
|
||||
break
|
||||
elif arg[0] == 'period_id' and arg[2] == 'current_year':
|
||||
current_year = fiscalyear_obj.find(cr, uid)
|
||||
ids = fiscalyear_obj.read(cr, uid, [current_year], ['period_ids'])[0]['period_ids']
|
||||
args.append(['period_id','in',ids])
|
||||
for a in [['period_id','in','current_year'], ['period_id','in','current_period']]:
|
||||
if a in args:
|
||||
args.remove(a)
|
||||
return super(account_entries_report, self).search(cr, uid, args=args, offset=offset, limit=limit, order=order,
|
||||
context=context, count=count)
|
||||
|
||||
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False,lazy=True):
|
||||
if context is None:
|
||||
context = {}
|
||||
fiscalyear_obj = self.pool.get('account.fiscalyear')
|
||||
period_obj = self.pool.get('account.period')
|
||||
if context.get('period', False) == 'current_period':
|
||||
current_period = period_obj.find(cr, uid, context=context)[0]
|
||||
domain.append(['period_id','in',[current_period]])
|
||||
elif context.get('year', False) == 'current_year':
|
||||
current_year = fiscalyear_obj.find(cr, uid)
|
||||
ids = fiscalyear_obj.read(cr, uid, [current_year], ['period_ids'])[0]['period_ids']
|
||||
domain.append(['period_id','in',ids])
|
||||
else:
|
||||
domain = domain
|
||||
return super(account_entries_report, self).read_group(cr, uid, domain, fields, groupby, offset, limit, context, orderby,lazy)
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'account_entries_report')
|
||||
cr.execute("""
|
||||
create or replace view account_entries_report as (
|
||||
select
|
||||
l.id as id,
|
||||
am.date as date,
|
||||
l.date_maturity as date_maturity,
|
||||
l.date_created as date_created,
|
||||
am.ref as ref,
|
||||
am.state as move_state,
|
||||
l.state as move_line_state,
|
||||
l.reconcile_id as reconcile_id,
|
||||
l.partner_id as partner_id,
|
||||
l.product_id as product_id,
|
||||
l.product_uom_id as product_uom_id,
|
||||
am.company_id as company_id,
|
||||
am.journal_id as journal_id,
|
||||
p.fiscalyear_id as fiscalyear_id,
|
||||
am.period_id as period_id,
|
||||
l.account_id as account_id,
|
||||
l.analytic_account_id as analytic_account_id,
|
||||
a.type as type,
|
||||
a.user_type as user_type,
|
||||
1 as nbr,
|
||||
l.quantity as quantity,
|
||||
l.currency_id as currency_id,
|
||||
l.amount_currency as amount_currency,
|
||||
l.debit as debit,
|
||||
l.credit as credit,
|
||||
l.debit-l.credit as balance
|
||||
from
|
||||
account_move_line l
|
||||
left join account_account a on (l.account_id = a.id)
|
||||
left join account_move am on (am.id=l.move_id)
|
||||
left join account_period p on (am.period_id=p.id)
|
||||
where l.state != 'draft'
|
||||
)
|
||||
""")
|
||||
@@ -1,122 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_account_entries_report_tree" model="ir.ui.view">
|
||||
<field name="name">account.entries.report.tree</field>
|
||||
<field name="model">account.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="blue:move_state == 'draft';black:move_state == 'posted'" create="false" string="Entries Analysis">
|
||||
<field name="date" invisible="1"/>
|
||||
<field name="date_created" invisible="1"/>
|
||||
<field name="date_maturity" invisible="1"/>
|
||||
<field name="ref" invisible="1"/>
|
||||
<field name="nbr" sum="# of Entries "/>
|
||||
<field name="quantity" sum="# of Products Qty " invisible="not context.get('quantity_visible', False)"/>
|
||||
<field name="amount_currency" invisible="not context.get('amount_currency_visible', False)"/>
|
||||
<field name="currency_id" invisible="not context.get('currency_id_visible', False)"/>
|
||||
<field name="debit"/>
|
||||
<field name="credit"/>
|
||||
<field name="balance"/>
|
||||
<field name="move_state" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="product_id" invisible="1"/>
|
||||
<field name="product_uom_id" invisible="1"/>
|
||||
<field name="company_id" invisible="1" groups="base.group_multi_company"/>
|
||||
<field name="journal_id" invisible="1"/>
|
||||
<field name="account_id" invisible="1"/>
|
||||
<field name="fiscalyear_id" invisible="1"/>
|
||||
<field name="period_id" invisible="1"/>
|
||||
<field name="user_type" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_entries_report_pivot" model="ir.ui.view">
|
||||
<field name="name">account.entries.report.pivot</field>
|
||||
<field name="model">account.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Entries Analysis" disable_linking="True">
|
||||
<field name="user_type" type="row"/>
|
||||
<field name="period_id" type="col"/>
|
||||
<field name="debit" type="measure"/>
|
||||
<field name="credit" type="measure"/>
|
||||
<field name="balance" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_entries_report_graph" model="ir.ui.view">
|
||||
<field name="name">account.entries.report.graph</field>
|
||||
<field name="model">account.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Entries Analysis">
|
||||
<field name="user_type"/>
|
||||
<field name="period_id"/>
|
||||
<field name="balance" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_company_analysis_tree" model="ir.ui.view">
|
||||
<field name="name">account.company.analysis.tree</field>
|
||||
<field name="model">account.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Company Analysis" >
|
||||
<field name="user_type"/>
|
||||
<field name="debit" />
|
||||
<field name="credit" />
|
||||
<field name="balance" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_entries_report_search" model="ir.ui.view">
|
||||
<field name="name">account.entries.report.search</field>
|
||||
<field name="model">account.entries.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Entries Analysis">
|
||||
<field name="date"/>
|
||||
<field name="date_created"/>
|
||||
<field name="date_maturity"/>
|
||||
<filter string="This F.Year" name="thisyear" domain="['|', ('date', '=', False), '&',('date','<=', time.strftime('%%Y-12-31')),('date','>=',time.strftime('%%Y-01-01'))]" help="Journal Entries with period in current year"/>
|
||||
<filter string="This Period" name="period" context="{'period':'current_period'}" help="Journal Entries with period in current period"/>
|
||||
<separator/>
|
||||
<filter string="Unposted" domain="[('move_state','=','draft')]" help = "entries"/>
|
||||
<filter string="Posted" domain="[('move_state','=','posted')]" help = "Posted entries"/>
|
||||
<separator/>
|
||||
<filter string="Unreconciled" domain="[('reconcile_id','=',False), ('account_id.reconcile','=',True)]" help = "Unreconciled entries"/>
|
||||
<filter string="Reconciled" domain="[('reconcile_id','!=',False)]" help = "Reconciled entries"/>
|
||||
<field name="account_id"/>
|
||||
<field name="journal_id"/>
|
||||
<field name="period_id"/>
|
||||
<group expand="0" string="Extended Filters...">
|
||||
<field name="fiscalyear_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Partner" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Journal" name="group_journal" context="{'group_by':'journal_id'}"/>
|
||||
<filter string="Acc.Type" context="{'group_by':'user_type'}" name="usertype"/>
|
||||
<filter string="Int.Type" context="{'group_by':'type'}"/>
|
||||
<filter string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator/>
|
||||
<filter string="Entries Month" context="{'group_by':'date:month'}" help="Entries Date by Month"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_account_entries_report_all" model="ir.actions.act_window">
|
||||
<field name="name">Entries Analysis</field>
|
||||
<field name="res_model">account.entries.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="search_view_id" ref="view_account_entries_report_search"/>
|
||||
<field name="view_id"></field> <!-- force empty -->
|
||||
<field name="context">{'group_by':[], 'search_default_usertype':1, 'search_default_thisyear':1, 'group_by_no_leaf':1}</field>
|
||||
<field name="help">From this view, have an analysis of your different financial accounts. The document shows your debit and credit taking in consideration some criteria you can choose by using the search tool.</field>
|
||||
</record>
|
||||
<menuitem action="action_account_entries_report_all" id="menu_action_account_entries_report_all"
|
||||
parent="account.menu_finance_reporting"
|
||||
groups="group_account_manager"
|
||||
sequence="2"/>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -19,97 +20,120 @@
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from operator import itemgetter
|
||||
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
from openerp.osv import fields, osv
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import osv
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Account Financial Report
|
||||
# ---------------------------------------------------------
|
||||
|
||||
class report_account_common(report_sxw.rml_parse, common_report_header):
|
||||
class account_financial_report(osv.osv):
|
||||
_name = "account.financial.report"
|
||||
_description = "Account Report"
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
super(report_account_common, self).__init__(cr, uid, name, context=context)
|
||||
self.localcontext.update( {
|
||||
'get_lines': self.get_lines,
|
||||
'time': time,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_account': self._get_account,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_filter': self._get_filter,
|
||||
'get_start_date':self._get_start_date,
|
||||
'get_end_date':self._get_end_date,
|
||||
'get_target_move': self._get_target_move,
|
||||
})
|
||||
self.context = context
|
||||
def _get_level(self, cr, uid, ids, field_name, arg, context=None):
|
||||
'''Returns a dictionary with key=the ID of a record and value = the level of this
|
||||
record in the tree structure.'''
|
||||
res = {}
|
||||
for report in self.browse(cr, uid, ids, context=context):
|
||||
level = 0
|
||||
if report.parent_id:
|
||||
level = report.parent_id.level + 1
|
||||
res[report.id] = level
|
||||
return res
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
new_ids = ids
|
||||
if (data['model'] == 'ir.ui.menu'):
|
||||
new_ids = 'chart_account_id' in data['form'] and [data['form']['chart_account_id']] or []
|
||||
objects = self.pool.get('account.account').browse(self.cr, self.uid, new_ids)
|
||||
return super(report_account_common, self).set_context(objects, data, new_ids, report_type=report_type)
|
||||
def _get_children_by_order(self, cr, uid, ids, context=None):
|
||||
'''returns a dictionary with the key= the ID of a record and value = all its children,
|
||||
computed recursively, and sorted by sequence. Ready for the printing'''
|
||||
res = []
|
||||
for id in ids:
|
||||
res.append(id)
|
||||
ids2 = self.search(cr, uid, [('parent_id', '=', id)], order='sequence ASC', context=context)
|
||||
res += self._get_children_by_order(cr, uid, ids2, context=context)
|
||||
return res
|
||||
|
||||
def get_lines(self, data):
|
||||
lines = []
|
||||
def _get_balance(self, cr, uid, ids, field_names, args, context=None):
|
||||
'''returns a dictionary with key=the ID of a record and value=the balance amount
|
||||
computed for this record. If the record is of type :
|
||||
'accounts' : it's the sum of the linked accounts
|
||||
'account_type' : it's the sum of leaf accoutns with such an account_type
|
||||
'account_report' : it's the amount of the related report
|
||||
'sum' : it's the sum of the children of this record (aka a 'view' record)'''
|
||||
account_obj = self.pool.get('account.account')
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
ids2 = self.pool.get('account.financial.report')._get_children_by_order(self.cr, self.uid, [data['form']['account_report_id'][0]], context=data['form']['used_context'])
|
||||
for report in self.pool.get('account.financial.report').browse(self.cr, self.uid, ids2, context=data['form']['used_context']):
|
||||
vals = {
|
||||
'name': report.name,
|
||||
'balance': report.balance * report.sign or 0.0,
|
||||
'type': 'report',
|
||||
'level': bool(report.style_overwrite) and report.style_overwrite or report.level,
|
||||
'account_type': report.type =='sum' and 'view' or False, #used to underline the financial report balances
|
||||
}
|
||||
if data['form']['debit_credit']:
|
||||
vals['debit'] = report.debit
|
||||
vals['credit'] = report.credit
|
||||
if data['form']['enable_filter']:
|
||||
vals['balance_cmp'] = self.pool.get('account.financial.report').browse(self.cr, self.uid, report.id, context=data['form']['comparison_context']).balance * report.sign or 0.0
|
||||
lines.append(vals)
|
||||
account_ids = []
|
||||
if report.display_detail == 'no_detail':
|
||||
#the rest of the loop is used to display the details of the financial report, so it's not needed here.
|
||||
res = {}
|
||||
for report in self.browse(cr, uid, ids, context=context):
|
||||
if report.id in res:
|
||||
continue
|
||||
if report.type == 'accounts' and report.account_ids:
|
||||
account_ids = account_obj._get_children_and_consol(self.cr, self.uid, [x.id for x in report.account_ids])
|
||||
elif report.type == 'account_type' and report.account_type_ids:
|
||||
account_ids = account_obj.search(self.cr, self.uid, [('user_type','in', [x.id for x in report.account_type_ids])])
|
||||
if account_ids:
|
||||
for account in account_obj.browse(self.cr, self.uid, account_ids, context=data['form']['used_context']):
|
||||
#if there are accounts to display, we add them to the lines with a level equals to their level in
|
||||
#the COA + 1 (to avoid having them with a too low level that would conflicts with the level of data
|
||||
#financial reports for Assets, liabilities...)
|
||||
if report.display_detail == 'detail_flat' and account.type == 'view':
|
||||
continue
|
||||
flag = False
|
||||
vals = {
|
||||
'name': account.code + ' ' + account.name,
|
||||
'balance': account.balance != 0 and account.balance * report.sign or account.balance,
|
||||
'type': 'account',
|
||||
'level': report.display_detail == 'detail_with_hierarchy' and min(account.level + 1,6) or 6, #account.level + 1
|
||||
'account_type': account.type,
|
||||
}
|
||||
res[report.id] = dict((fn, 0.0) for fn in field_names)
|
||||
if report.type == 'accounts':
|
||||
# it's the sum of the linked accounts
|
||||
for a in report.account_ids:
|
||||
for field in field_names:
|
||||
res[report.id][field] += getattr(a, field)
|
||||
elif report.type == 'account_type':
|
||||
# it's the sum the leaf accounts with such an account type
|
||||
report_types = [x.id for x in report.account_type_ids]
|
||||
account_ids = account_obj.search(cr, uid, [('user_type','in', report_types), ('type','!=','view')], context=context)
|
||||
for a in account_obj.browse(cr, uid, account_ids, context=context):
|
||||
for field in field_names:
|
||||
res[report.id][field] += getattr(a, field)
|
||||
elif report.type == 'account_report' and report.account_report_id:
|
||||
# it's the amount of the linked report
|
||||
res2 = self._get_balance(cr, uid, [report.account_report_id.id], field_names, False, context=context)
|
||||
for key, value in res2.items():
|
||||
for field in field_names:
|
||||
res[report.id][field] += value[field]
|
||||
elif report.type == 'sum':
|
||||
# it's the sum of the children of this account.report
|
||||
res2 = self._get_balance(cr, uid, [rec.id for rec in report.children_ids], field_names, False, context=context)
|
||||
for key, value in res2.items():
|
||||
for field in field_names:
|
||||
res[report.id][field] += value[field]
|
||||
return res
|
||||
|
||||
if data['form']['debit_credit']:
|
||||
vals['debit'] = account.debit
|
||||
vals['credit'] = account.credit
|
||||
if not currency_obj.is_zero(self.cr, self.uid, account.company_id.currency_id, vals['balance']):
|
||||
flag = True
|
||||
if data['form']['enable_filter']:
|
||||
vals['balance_cmp'] = account_obj.browse(self.cr, self.uid, account.id, context=data['form']['comparison_context']).balance * report.sign or 0.0
|
||||
if not currency_obj.is_zero(self.cr, self.uid, account.company_id.currency_id, vals['balance_cmp']):
|
||||
flag = True
|
||||
if flag:
|
||||
lines.append(vals)
|
||||
return lines
|
||||
_columns = {
|
||||
'name': fields.char('Report Name', required=True, translate=True),
|
||||
'parent_id': fields.many2one('account.financial.report', 'Parent'),
|
||||
'children_ids': fields.one2many('account.financial.report', 'parent_id', 'Account Report'),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'balance': fields.function(_get_balance, string='Balance', multi='balance'),
|
||||
'debit': fields.function(_get_balance, string='Debit', multi='balance'),
|
||||
'credit': fields.function(_get_balance, string='Credit', multi="balance"),
|
||||
'level': fields.function(_get_level, string='Level', store=True, type='integer'),
|
||||
'type': fields.selection([
|
||||
('sum','View'),
|
||||
('accounts','Accounts'),
|
||||
('account_type','Account Type'),
|
||||
('account_report','Report Value'),
|
||||
],'Type'),
|
||||
'account_ids': fields.many2many('account.account', 'account_account_financial_report', 'report_line_id', 'account_id', 'Accounts'),
|
||||
'account_report_id': fields.many2one('account.financial.report', 'Report Value'),
|
||||
'account_type_ids': fields.many2many('account.account.type', 'account_account_financial_report_type', 'report_id', 'account_type_id', 'Account Types'),
|
||||
'sign': fields.selection([(-1, 'Reverse balance sign'), (1, 'Preserve balance sign')], 'Sign on Reports', required=True, help='For accounts that are typically more debited than credited and that you would like to print as negative amounts in your reports, you should reverse the sign of the balance; e.g.: Expense account. The same applies for accounts that are typically more credited than debited and that you would like to print as positive amounts in your reports; e.g.: Income account.'),
|
||||
'display_detail': fields.selection([
|
||||
('no_detail','No detail'),
|
||||
('detail_flat','Display children flat'),
|
||||
('detail_with_hierarchy','Display children with hierarchy')
|
||||
], 'Display details'),
|
||||
'style_overwrite': fields.selection([
|
||||
(0, 'Automatic formatting'),
|
||||
(1,'Main Title 1 (bold, underlined)'),
|
||||
(2,'Title 2 (bold)'),
|
||||
(3,'Title 3 (bold, smaller)'),
|
||||
(4,'Normal Text'),
|
||||
(5,'Italic Text (smaller)'),
|
||||
(6,'Smallest Text'),
|
||||
],'Financial Report Style', help="You can set up here the format you want this record to be displayed. If you leave the automatic formatting, it will be computed based on the financial reports hierarchy (auto-computed field 'level')."),
|
||||
}
|
||||
|
||||
|
||||
class report_financial(osv.AbstractModel):
|
||||
_name = 'report.account.report_financial'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_financial'
|
||||
_wrapped_report_class = report_account_common
|
||||
_defaults = {
|
||||
'type': 'sum',
|
||||
'display_detail': 'detail_flat',
|
||||
'sign': 1,
|
||||
'style_overwrite': 0,
|
||||
}
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
|
||||
|
||||
class journal_print(report_sxw.rml_parse, common_report_header):
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
super(journal_print, self).__init__(cr, uid, name, context=context)
|
||||
self.period_ids = []
|
||||
self.journal_ids = []
|
||||
self.localcontext.update( {
|
||||
'time': time,
|
||||
'lines': self.lines,
|
||||
'periods': self.periods,
|
||||
'sum_debit_period': self._sum_debit_period,
|
||||
'sum_credit_period': self._sum_credit_period,
|
||||
'sum_debit': self._sum_debit,
|
||||
'sum_credit': self._sum_credit,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_account': self._get_account,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_sortby': self._get_sortby,
|
||||
'get_filter': self._get_filter,
|
||||
'get_journal': self._get_journal,
|
||||
'get_start_date':self._get_start_date,
|
||||
'get_end_date':self._get_end_date,
|
||||
'display_currency':self._display_currency,
|
||||
'get_target_move': self._get_target_move,
|
||||
})
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
obj_move = self.pool.get('account.move.line')
|
||||
new_ids = ids
|
||||
self.query_get_clause = ''
|
||||
self.target_move = data['form'].get('target_move', 'all')
|
||||
if (data['model'] == 'ir.ui.menu'):
|
||||
new_ids = 'active_ids' in data['form'] and data['form']['active_ids'] or []
|
||||
self.query_get_clause = 'AND '
|
||||
self.query_get_clause += obj_move._query_get(self.cr, self.uid, obj='l', context=data['form'].get('used_context', {}))
|
||||
objects = self.pool.get('account.journal.period').browse(self.cr, self.uid, new_ids)
|
||||
if new_ids:
|
||||
self.cr.execute('SELECT period_id, journal_id FROM account_journal_period WHERE id IN %s', (tuple(new_ids),))
|
||||
res = self.cr.fetchall()
|
||||
self.period_ids, self.journal_ids = zip(*res)
|
||||
return super(journal_print, self).set_context(objects, data, ids, report_type=report_type)
|
||||
|
||||
# returns a list of period objs
|
||||
def periods(self, journal_period_objs):
|
||||
dic = {}
|
||||
def filter_unique(o):
|
||||
key = o.period_id.id
|
||||
res = key in dic
|
||||
if not res:
|
||||
dic[key] = True
|
||||
return not res
|
||||
filtered_objs = filter(filter_unique, journal_period_objs)
|
||||
return map(lambda x: x.period_id, filtered_objs)
|
||||
|
||||
def lines(self, period_id):
|
||||
if not self.journal_ids:
|
||||
return []
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
self.cr.execute('SELECT j.code, j.name, l.amount_currency,c.symbol AS currency_code,l.currency_id, '
|
||||
'SUM(l.debit) AS debit, SUM(l.credit) AS credit '
|
||||
'FROM account_move_line l '
|
||||
'LEFT JOIN account_move am ON (l.move_id=am.id) '
|
||||
'LEFT JOIN account_journal j ON (l.journal_id=j.id) '
|
||||
'LEFT JOIN res_currency c on (l.currency_id=c.id)'
|
||||
'WHERE am.state IN %s AND l.period_id=%s AND l.journal_id IN %s ' + self.query_get_clause + ' '
|
||||
'GROUP BY j.id, j.code, j.name, l.amount_currency, c.symbol, l.currency_id ',
|
||||
(tuple(move_state), period_id, tuple(self.journal_ids)))
|
||||
return self.cr.dictfetchall()
|
||||
|
||||
def _set_get_account_currency_code(self, account_id):
|
||||
self.cr.execute("SELECT c.symbol AS code "\
|
||||
"FROM res_currency c, account_account AS ac "\
|
||||
"WHERE ac.id = %s AND ac.currency_id = c.id" % (account_id))
|
||||
result = self.cr.fetchone()
|
||||
if result:
|
||||
self.account_currency = result[0]
|
||||
else:
|
||||
self.account_currency = False
|
||||
|
||||
def _get_account(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return self.pool.get('account.journal.period').browse(self.cr, self.uid, data['id']).company_id.name
|
||||
return super(journal_print, self)._get_account(data)
|
||||
|
||||
def _get_fiscalyear(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return self.pool.get('account.journal.period').browse(self.cr, self.uid, data['id']).fiscalyear_id.name
|
||||
return super(journal_print, self)._get_fiscalyear(data)
|
||||
|
||||
def _display_currency(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return True
|
||||
return data['form']['amount_currency']
|
||||
|
||||
def _sum_debit_period(self, period_id, journal_id=False):
|
||||
if journal_id:
|
||||
journals = [journal_id]
|
||||
else:
|
||||
journals = self.journal_ids
|
||||
if not journals:
|
||||
return 0.0
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
self.cr.execute('SELECT SUM(l.debit) FROM account_move_line l '
|
||||
'LEFT JOIN account_move am ON (l.move_id=am.id) '
|
||||
'WHERE am.state IN %s AND l.period_id=%s AND l.journal_id IN %s ' + self.query_get_clause + ' ' \
|
||||
'AND l.state<>\'draft\'',
|
||||
(tuple(move_state), period_id, tuple(journals)))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def _sum_credit_period(self, period_id, journal_id=None):
|
||||
if journal_id:
|
||||
journals = [journal_id]
|
||||
else:
|
||||
journals = self.journal_ids
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
if not journals:
|
||||
return 0.0
|
||||
self.cr.execute('SELECT SUM(l.credit) FROM account_move_line l '
|
||||
'LEFT JOIN account_move am ON (l.move_id=am.id) '
|
||||
'WHERE am.state IN %s AND l.period_id=%s AND l.journal_id IN %s '+ self.query_get_clause + ' ' \
|
||||
'AND l.state<>\'draft\'',
|
||||
(tuple(move_state), period_id, tuple(journals)))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
|
||||
class report_generaljournal(osv.AbstractModel):
|
||||
_name = 'report.account.report_generaljournal'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_generaljournal'
|
||||
_wrapped_report_class = journal_print
|
||||
@@ -1,314 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2005-2006 CamptoCamp
|
||||
# Copyright (c) 2006-2010 OpenERP S.A
|
||||
#
|
||||
# WARNING: This program as such is intended to be used by professional
|
||||
# programmers who take the whole responsibility of assessing all potential
|
||||
# consequences resulting from its eventual inadequacies and bugs
|
||||
# End users who are looking for a ready-to-use solution with commercial
|
||||
# guarantees and support are strongly advised to contract a Free Software
|
||||
# Service Company
|
||||
#
|
||||
# This program is Free Software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
|
||||
|
||||
class general_ledger(report_sxw.rml_parse, common_report_header):
|
||||
_name = 'report.account.general.ledger'
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
new_ids = ids
|
||||
obj_move = self.pool.get('account.move.line')
|
||||
self.sortby = data['form'].get('sortby', 'sort_date')
|
||||
self.query = obj_move._query_get(self.cr, self.uid, obj='l', context=data['form'].get('used_context',{}))
|
||||
ctx2 = data['form'].get('used_context',{}).copy()
|
||||
self.init_balance = data['form'].get('initial_balance', True)
|
||||
if self.init_balance:
|
||||
ctx2.update({'initial_bal': True})
|
||||
self.init_query = obj_move._query_get(self.cr, self.uid, obj='l', context=ctx2)
|
||||
self.display_account = data['form']['display_account']
|
||||
self.target_move = data['form'].get('target_move', 'all')
|
||||
ctx = self.context.copy()
|
||||
ctx['fiscalyear'] = data['form']['fiscalyear_id']
|
||||
if data['form']['filter'] == 'filter_period':
|
||||
ctx['periods'] = data['form']['periods']
|
||||
elif data['form']['filter'] == 'filter_date':
|
||||
ctx['date_from'] = data['form']['date_from']
|
||||
ctx['date_to'] = data['form']['date_to']
|
||||
ctx['state'] = data['form']['target_move']
|
||||
self.context.update(ctx)
|
||||
if (data['model'] == 'ir.ui.menu'):
|
||||
new_ids = [data['form']['chart_account_id']]
|
||||
objects = self.pool.get('account.account').browse(self.cr, self.uid, new_ids)
|
||||
return super(general_ledger, self).set_context(objects, data, new_ids, report_type=report_type)
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
super(general_ledger, self).__init__(cr, uid, name, context=context)
|
||||
self.query = ""
|
||||
self.tot_currency = 0.0
|
||||
self.period_sql = ""
|
||||
self.sold_accounts = {}
|
||||
self.sortby = 'sort_date'
|
||||
self.localcontext.update( {
|
||||
'time': time,
|
||||
'lines': self.lines,
|
||||
'sum_debit_account': self._sum_debit_account,
|
||||
'sum_credit_account': self._sum_credit_account,
|
||||
'sum_balance_account': self._sum_balance_account,
|
||||
'sum_currency_amount_account': self._sum_currency_amount_account,
|
||||
'get_children_accounts': self.get_children_accounts,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_journal': self._get_journal,
|
||||
'get_account': self._get_account,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_filter': self._get_filter,
|
||||
'get_sortby': self._get_sortby,
|
||||
'get_start_date':self._get_start_date,
|
||||
'get_end_date':self._get_end_date,
|
||||
'get_target_move': self._get_target_move,
|
||||
})
|
||||
self.context = context
|
||||
|
||||
def _sum_currency_amount_account(self, account):
|
||||
self.cr.execute('SELECT sum(l.amount_currency) AS tot_currency \
|
||||
FROM account_move_line l \
|
||||
WHERE l.account_id = %s AND %s' %(account.id, self.query))
|
||||
sum_currency = self.cr.fetchone()[0] or 0.0
|
||||
if self.init_balance:
|
||||
self.cr.execute('SELECT sum(l.amount_currency) AS tot_currency \
|
||||
FROM account_move_line l \
|
||||
WHERE l.account_id = %s AND %s '%(account.id, self.init_query))
|
||||
sum_currency += self.cr.fetchone()[0] or 0.0
|
||||
return sum_currency
|
||||
|
||||
def get_children_accounts(self, account):
|
||||
res = []
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
ids_acc = self.pool.get('account.account')._get_children_and_consol(self.cr, self.uid, account.id)
|
||||
currency = account.currency_id and account.currency_id or account.company_id.currency_id
|
||||
for child_account in self.pool.get('account.account').browse(self.cr, self.uid, ids_acc, context=self.context):
|
||||
sql = """
|
||||
SELECT count(id)
|
||||
FROM account_move_line AS l
|
||||
WHERE %s AND l.account_id = %%s
|
||||
""" % (self.query)
|
||||
self.cr.execute(sql, (child_account.id,))
|
||||
num_entry = self.cr.fetchone()[0] or 0
|
||||
sold_account = self._sum_balance_account(child_account)
|
||||
self.sold_accounts[child_account.id] = sold_account
|
||||
if self.display_account == 'movement':
|
||||
if child_account.type != 'view' and num_entry <> 0:
|
||||
res.append(child_account)
|
||||
elif self.display_account == 'not_zero':
|
||||
if child_account.type != 'view' and num_entry <> 0:
|
||||
if not currency_obj.is_zero(self.cr, self.uid, currency, sold_account):
|
||||
res.append(child_account)
|
||||
else:
|
||||
res.append(child_account)
|
||||
if not res:
|
||||
return [account]
|
||||
return res
|
||||
|
||||
def lines(self, account):
|
||||
""" Return all the account_move_line of account with their account code counterparts """
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted', '']
|
||||
# First compute all counterpart strings for every move_id where this account appear.
|
||||
# Currently, the counterpart info is used only in landscape mode
|
||||
sql = """
|
||||
SELECT m1.move_id,
|
||||
array_to_string(ARRAY(SELECT DISTINCT a.code
|
||||
FROM account_move_line m2
|
||||
LEFT JOIN account_account a ON (m2.account_id=a.id)
|
||||
WHERE m2.move_id = m1.move_id
|
||||
AND m2.account_id<>%%s), ', ') AS counterpart
|
||||
FROM (SELECT move_id
|
||||
FROM account_move_line l
|
||||
LEFT JOIN account_move am ON (am.id = l.move_id)
|
||||
WHERE am.state IN %s and %s AND l.account_id = %%s GROUP BY move_id) m1
|
||||
"""% (tuple(move_state), self.query)
|
||||
self.cr.execute(sql, (account.id, account.id))
|
||||
counterpart_res = self.cr.dictfetchall()
|
||||
counterpart_accounts = {}
|
||||
for i in counterpart_res:
|
||||
counterpart_accounts[i['move_id']] = i['counterpart']
|
||||
del counterpart_res
|
||||
|
||||
# Then select all account_move_line of this account
|
||||
if self.sortby == 'sort_journal_partner':
|
||||
sql_sort='j.code, p.name, l.move_id'
|
||||
else:
|
||||
sql_sort='l.date, l.move_id'
|
||||
sql = """
|
||||
SELECT l.id AS lid, l.date AS ldate, j.code AS lcode, l.currency_id,l.amount_currency,l.ref AS lref, l.name AS lname, COALESCE(l.debit,0) AS debit, COALESCE(l.credit,0) AS credit, l.period_id AS lperiod_id, l.partner_id AS lpartner_id,
|
||||
m.name AS move_name, m.id AS mmove_id,per.code as period_code,
|
||||
c.symbol AS currency_code,
|
||||
i.id AS invoice_id, i.type AS invoice_type, i.number AS invoice_number,
|
||||
p.name AS partner_name
|
||||
FROM account_move_line l
|
||||
JOIN account_move m on (l.move_id=m.id)
|
||||
LEFT JOIN res_currency c on (l.currency_id=c.id)
|
||||
LEFT JOIN res_partner p on (l.partner_id=p.id)
|
||||
LEFT JOIN account_invoice i on (m.id =i.move_id)
|
||||
LEFT JOIN account_period per on (per.id=l.period_id)
|
||||
JOIN account_journal j on (l.journal_id=j.id)
|
||||
WHERE %s AND m.state IN %s AND l.account_id = %%s ORDER by %s
|
||||
""" %(self.query, tuple(move_state), sql_sort)
|
||||
self.cr.execute(sql, (account.id,))
|
||||
res_lines = self.cr.dictfetchall()
|
||||
res_init = []
|
||||
if res_lines and self.init_balance:
|
||||
#FIXME: replace the label of lname with a string translatable
|
||||
sql = """
|
||||
SELECT 0 AS lid, '' AS ldate, '' AS lcode, COALESCE(SUM(l.amount_currency),0.0) AS amount_currency, '' AS lref, 'Initial Balance' AS lname, COALESCE(SUM(l.debit),0.0) AS debit, COALESCE(SUM(l.credit),0.0) AS credit, '' AS lperiod_id, '' AS lpartner_id,
|
||||
'' AS move_name, '' AS mmove_id, '' AS period_code,
|
||||
'' AS currency_code,
|
||||
NULL AS currency_id,
|
||||
'' AS invoice_id, '' AS invoice_type, '' AS invoice_number,
|
||||
'' AS partner_name
|
||||
FROM account_move_line l
|
||||
LEFT JOIN account_move m on (l.move_id=m.id)
|
||||
LEFT JOIN res_currency c on (l.currency_id=c.id)
|
||||
LEFT JOIN res_partner p on (l.partner_id=p.id)
|
||||
LEFT JOIN account_invoice i on (m.id =i.move_id)
|
||||
JOIN account_journal j on (l.journal_id=j.id)
|
||||
WHERE %s AND m.state IN %s AND l.account_id = %%s
|
||||
""" %(self.init_query, tuple(move_state))
|
||||
self.cr.execute(sql, (account.id,))
|
||||
res_init = self.cr.dictfetchall()
|
||||
res = res_init + res_lines
|
||||
account_sum = 0.0
|
||||
for l in res:
|
||||
l['move'] = l['move_name'] != '/' and l['move_name'] or ('*'+str(l['mmove_id']))
|
||||
l['partner'] = l['partner_name'] or ''
|
||||
account_sum += l['debit'] - l['credit']
|
||||
l['progress'] = account_sum
|
||||
l['line_corresp'] = l['mmove_id'] == '' and ' ' or counterpart_accounts[l['mmove_id']].replace(', ',',')
|
||||
# Modification of amount Currency
|
||||
if l['credit'] > 0:
|
||||
if l['amount_currency'] != None:
|
||||
l['amount_currency'] = abs(l['amount_currency']) * -1
|
||||
if l['amount_currency'] != None:
|
||||
self.tot_currency = self.tot_currency + l['amount_currency']
|
||||
return res
|
||||
|
||||
def _sum_debit_account(self, account):
|
||||
if account.type == 'view':
|
||||
return account.debit
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted','']
|
||||
self.cr.execute('SELECT sum(debit) \
|
||||
FROM account_move_line l \
|
||||
JOIN account_move am ON (am.id = l.move_id) \
|
||||
WHERE (l.account_id = %s) \
|
||||
AND (am.state IN %s) \
|
||||
AND '+ self.query +' '
|
||||
,(account.id, tuple(move_state)))
|
||||
sum_debit = self.cr.fetchone()[0] or 0.0
|
||||
if self.init_balance:
|
||||
self.cr.execute('SELECT sum(debit) \
|
||||
FROM account_move_line l \
|
||||
JOIN account_move am ON (am.id = l.move_id) \
|
||||
WHERE (l.account_id = %s) \
|
||||
AND (am.state IN %s) \
|
||||
AND '+ self.init_query +' '
|
||||
,(account.id, tuple(move_state)))
|
||||
# Add initial balance to the result
|
||||
sum_debit += self.cr.fetchone()[0] or 0.0
|
||||
return sum_debit
|
||||
|
||||
def _sum_credit_account(self, account):
|
||||
if account.type == 'view':
|
||||
return account.credit
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted','']
|
||||
self.cr.execute('SELECT sum(credit) \
|
||||
FROM account_move_line l \
|
||||
JOIN account_move am ON (am.id = l.move_id) \
|
||||
WHERE (l.account_id = %s) \
|
||||
AND (am.state IN %s) \
|
||||
AND '+ self.query +' '
|
||||
,(account.id, tuple(move_state)))
|
||||
sum_credit = self.cr.fetchone()[0] or 0.0
|
||||
if self.init_balance:
|
||||
self.cr.execute('SELECT sum(credit) \
|
||||
FROM account_move_line l \
|
||||
JOIN account_move am ON (am.id = l.move_id) \
|
||||
WHERE (l.account_id = %s) \
|
||||
AND (am.state IN %s) \
|
||||
AND '+ self.init_query +' '
|
||||
,(account.id, tuple(move_state)))
|
||||
# Add initial balance to the result
|
||||
sum_credit += self.cr.fetchone()[0] or 0.0
|
||||
return sum_credit
|
||||
|
||||
def _sum_balance_account(self, account):
|
||||
if account.type == 'view':
|
||||
return account.balance
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted','']
|
||||
self.cr.execute('SELECT (sum(debit) - sum(credit)) as tot_balance \
|
||||
FROM account_move_line l \
|
||||
JOIN account_move am ON (am.id = l.move_id) \
|
||||
WHERE (l.account_id = %s) \
|
||||
AND (am.state IN %s) \
|
||||
AND '+ self.query +' '
|
||||
,(account.id, tuple(move_state)))
|
||||
sum_balance = self.cr.fetchone()[0] or 0.0
|
||||
if self.init_balance:
|
||||
self.cr.execute('SELECT (sum(debit) - sum(credit)) as tot_balance \
|
||||
FROM account_move_line l \
|
||||
JOIN account_move am ON (am.id = l.move_id) \
|
||||
WHERE (l.account_id = %s) \
|
||||
AND (am.state IN %s) \
|
||||
AND '+ self.init_query +' '
|
||||
,(account.id, tuple(move_state)))
|
||||
# Add initial balance to the result
|
||||
sum_balance += self.cr.fetchone()[0] or 0.0
|
||||
return sum_balance
|
||||
|
||||
def _get_account(self, data):
|
||||
if data['model'] == 'account.account':
|
||||
return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['id']).company_id.name
|
||||
return super(general_ledger ,self)._get_account(data)
|
||||
|
||||
def _get_sortby(self, data):
|
||||
if self.sortby == 'sort_date':
|
||||
return self._translate('Date')
|
||||
elif self.sortby == 'sort_journal_partner':
|
||||
return self._translate('Journal & Partner')
|
||||
return self._translate('Date')
|
||||
|
||||
|
||||
class report_generalledger(osv.AbstractModel):
|
||||
_name = 'report.account.report_generalledger'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_generalledger'
|
||||
_wrapped_report_class = general_ledger
|
||||
@@ -1,117 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import tools
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.osv import fields,osv
|
||||
from openerp import models, fields, api
|
||||
|
||||
class account_invoice_report(osv.osv):
|
||||
|
||||
class AccountInvoiceReport(models.Model):
|
||||
_name = "account.invoice.report"
|
||||
_description = "Invoices Statistics"
|
||||
_auto = False
|
||||
_rec_name = 'date'
|
||||
|
||||
def _compute_amounts_in_user_currency(self, cr, uid, ids, field_names, args, context=None):
|
||||
@api.multi
|
||||
@api.depends('currency_id', 'date', 'price_total', 'price_average', 'residual')
|
||||
def _compute_amounts_in_user_currency(self):
|
||||
"""Compute the amounts in the currency of the user
|
||||
"""
|
||||
if context is None:
|
||||
context={}
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
currency_rate_obj = self.pool.get('res.currency.rate')
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
user_currency_id = user.company_id.currency_id.id
|
||||
currency_rate_id = currency_rate_obj.search(
|
||||
cr, uid, [
|
||||
('rate', '=', 1),
|
||||
'|',
|
||||
('currency_id.company_id', '=', user.company_id.id),
|
||||
('currency_id.company_id', '=', False)
|
||||
], limit=1, context=context)[0]
|
||||
base_currency_id = currency_rate_obj.browse(cr, uid, currency_rate_id, context=context).currency_id.id
|
||||
res = {}
|
||||
context = dict(self._context or {})
|
||||
user_currency_id = self.env.user.company_id.currency_id
|
||||
currency_rate_id = self.env['res.currency.rate'].search([
|
||||
('rate', '=', 1),
|
||||
'|', ('company_id', '=', self.env.user.company_id.id), ('company_id', '=', False)], limit=1)
|
||||
base_currency_id = currency_rate_id.currency_id
|
||||
ctx = context.copy()
|
||||
for item in self.browse(cr, uid, ids, context=context):
|
||||
ctx['date'] = item.date
|
||||
price_total = currency_obj.compute(cr, uid, base_currency_id, user_currency_id, item.price_total, context=ctx)
|
||||
price_average = currency_obj.compute(cr, uid, base_currency_id, user_currency_id, item.price_average, context=ctx)
|
||||
residual = currency_obj.compute(cr, uid, base_currency_id, user_currency_id, item.residual, context=ctx)
|
||||
res[item.id] = {
|
||||
'user_currency_price_total': price_total,
|
||||
'user_currency_price_average': price_average,
|
||||
'user_currency_residual': residual,
|
||||
}
|
||||
return res
|
||||
for record in self:
|
||||
ctx['date'] = record.date
|
||||
record.user_currency_price_total = base_currency_id.with_context(ctx).compute(record.price_total, user_currency_id)
|
||||
record.user_currency_price_average = base_currency_id.with_context(ctx).compute(record.price_average, user_currency_id)
|
||||
record.user_currency_residual = base_currency_id.with_context(ctx).compute(record.residual, user_currency_id)
|
||||
|
||||
date = fields.Date(readonly=True)
|
||||
product_id = fields.Many2one('product.product', string='Product', readonly=True)
|
||||
product_qty = fields.Float(string='Product Quantity', readonly=True)
|
||||
uom_name = fields.Char(string='Reference Unit of Measure', readonly=True)
|
||||
payment_term_id = fields.Many2one('account.payment.term', string='Payment Term', oldname='payment_term', readonly=True)
|
||||
fiscal_position_id = fields.Many2one('account.fiscal.position', oldname='fiscal_position', string='Fiscal Position', readonly=True)
|
||||
currency_id = fields.Many2one('res.currency', string='Currency', readonly=True)
|
||||
categ_id = fields.Many2one('product.category', string='Product Category', readonly=True)
|
||||
journal_id = fields.Many2one('account.journal', string='Journal', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Partner', readonly=True)
|
||||
commercial_partner_id = fields.Many2one('res.partner', string='Partner Company', help="Commercial Entity")
|
||||
company_id = fields.Many2one('res.company', string='Company', readonly=True)
|
||||
user_id = fields.Many2one('res.users', string='Salesperson', readonly=True)
|
||||
price_total = fields.Float(string='Total Without Tax', readonly=True)
|
||||
user_currency_price_total = fields.Float(string="Total Without Tax", compute='_compute_amounts_in_user_currency', digits=0)
|
||||
price_average = fields.Float(string='Average Price', readonly=True, group_operator="avg")
|
||||
user_currency_price_average = fields.Float(string="Average Price", compute='_compute_amounts_in_user_currency', digits=0)
|
||||
currency_rate = fields.Float(string='Currency Rate', readonly=True)
|
||||
nbr = fields.Integer(string='# of Invoices', readonly=True) # TDE FIXME master: rename into nbr_lines
|
||||
type = fields.Selection([
|
||||
('out_invoice', 'Customer Invoice'),
|
||||
('in_invoice', 'Supplier Bill'),
|
||||
('out_refund', 'Customer Refund'),
|
||||
('in_refund', 'Supplier Refund'),
|
||||
], readonly=True)
|
||||
state = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
('proforma', 'Pro-forma'),
|
||||
('proforma2', 'Pro-forma'),
|
||||
('open', 'Open'),
|
||||
('paid', 'Done'),
|
||||
('cancel', 'Cancelled')
|
||||
], string='Invoice Status', readonly=True)
|
||||
date_due = fields.Date(string='Due Date', readonly=True)
|
||||
account_id = fields.Many2one('account.account', string='Account', readonly=True, domain=[('deprecated', '=', False)])
|
||||
account_line_id = fields.Many2one('account.account', string='Account Line', readonly=True, domain=[('deprecated', '=', False)])
|
||||
partner_bank_id = fields.Many2one('res.partner.bank', string='Bank Account', readonly=True)
|
||||
residual = fields.Float(string='Total Residual', readonly=True)
|
||||
user_currency_residual = fields.Float(string="Total Residual", compute='_compute_amounts_in_user_currency', digits=0)
|
||||
country_id = fields.Many2one('res.country', string='Country of the Partner Company')
|
||||
|
||||
_columns = {
|
||||
'date': fields.date('Date', readonly=True),
|
||||
'product_id': fields.many2one('product.product', 'Product', readonly=True),
|
||||
'product_qty':fields.float('Product Quantity', readonly=True),
|
||||
'uom_name': fields.char('Reference Unit of Measure', size=128, readonly=True),
|
||||
'payment_term': fields.many2one('account.payment.term', 'Payment Term', readonly=True),
|
||||
'period_id': fields.many2one('account.period', 'Force Period', domain=[('state','<>','done')], readonly=True),
|
||||
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
'categ_id': fields.many2one('product.category','Product Category', readonly=True),
|
||||
'journal_id': fields.many2one('account.journal', 'Journal', readonly=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
|
||||
'commercial_partner_id': fields.many2one('res.partner', 'Partner Company', help="Commercial Entity"),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True),
|
||||
'price_total': fields.float('Total Without Tax', readonly=True),
|
||||
'user_currency_price_total': fields.function(_compute_amounts_in_user_currency, string="Total Without Tax", type='float', digits_compute=dp.get_precision('Account'), multi="_compute_amounts"),
|
||||
'price_average': fields.float('Average Price', readonly=True, group_operator="avg"),
|
||||
'user_currency_price_average': fields.function(_compute_amounts_in_user_currency, string="Average Price", type='float', digits_compute=dp.get_precision('Account'), multi="_compute_amounts"),
|
||||
'currency_rate': fields.float('Currency Rate', readonly=True),
|
||||
'nbr': fields.integer('# of Invoices', readonly=True), # TDE FIXME master: rename into nbr_lines
|
||||
'type': fields.selection([
|
||||
('out_invoice','Customer Invoice'),
|
||||
('in_invoice','Supplier Invoice'),
|
||||
('out_refund','Customer Refund'),
|
||||
('in_refund','Supplier Refund'),
|
||||
],'Type', readonly=True),
|
||||
'state': fields.selection([
|
||||
('draft','Draft'),
|
||||
('proforma','Pro-forma'),
|
||||
('proforma2','Pro-forma'),
|
||||
('open','Open'),
|
||||
('paid','Done'),
|
||||
('cancel','Cancelled')
|
||||
], 'Invoice Status', readonly=True),
|
||||
'date_due': fields.date('Due Date', readonly=True),
|
||||
'account_id': fields.many2one('account.account', 'Account',readonly=True),
|
||||
'account_line_id': fields.many2one('account.account', 'Account Line',readonly=True),
|
||||
'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account',readonly=True),
|
||||
'residual': fields.float('Total Residual', readonly=True),
|
||||
'user_currency_residual': fields.function(_compute_amounts_in_user_currency, string="Total Residual", type='float', digits_compute=dp.get_precision('Account'), multi="_compute_amounts"),
|
||||
'country_id': fields.many2one('res.country', 'Country of the Partner Company'),
|
||||
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True),
|
||||
}
|
||||
_order = 'date desc'
|
||||
|
||||
_depends = {
|
||||
'account.invoice': [
|
||||
'account_id', 'amount_total', 'commercial_partner_id', 'company_id',
|
||||
'currency_id', 'date_due', 'date_invoice', 'fiscal_position',
|
||||
'journal_id', 'partner_bank_id', 'partner_id', 'payment_term',
|
||||
'period_id', 'residual', 'state', 'type', 'user_id',
|
||||
'account_id', 'amount_total_signed', 'commercial_partner_id', 'company_id',
|
||||
'currency_id', 'date_due', 'date_invoice', 'fiscal_position_id',
|
||||
'journal_id', 'partner_bank_id', 'partner_id', 'payment_term_id',
|
||||
'residual', 'state', 'type', 'user_id',
|
||||
],
|
||||
'account.invoice.line': [
|
||||
'account_id', 'invoice_id', 'price_subtotal', 'product_id',
|
||||
@@ -127,11 +92,11 @@ class account_invoice_report(osv.osv):
|
||||
def _select(self):
|
||||
select_str = """
|
||||
SELECT sub.id, sub.date, sub.product_id, sub.partner_id, sub.country_id, sub.account_analytic_id,
|
||||
sub.payment_term, sub.period_id, sub.uom_name, sub.currency_id, sub.journal_id,
|
||||
sub.fiscal_position, sub.user_id, sub.company_id, sub.nbr, sub.type, sub.state,
|
||||
sub.payment_term_id, sub.uom_name, sub.currency_id, sub.journal_id,
|
||||
sub.fiscal_position_id, sub.user_id, sub.company_id, sub.nbr, sub.type, sub.state,
|
||||
sub.categ_id, sub.date_due, sub.account_id, sub.account_line_id, sub.partner_bank_id,
|
||||
sub.product_qty, sub.price_total / cr.rate as price_total, sub.price_average /cr.rate as price_average,
|
||||
cr.rate as currency_rate, sub.residual / cr.rate as residual, sub.commercial_partner_id as commercial_partner_id
|
||||
sub.product_qty, sub.price_total as price_total, sub.price_average as price_average,
|
||||
cr.rate as currency_rate, sub.residual as residual, sub.commercial_partner_id as commercial_partner_id
|
||||
"""
|
||||
return select_str
|
||||
|
||||
@@ -139,9 +104,9 @@ class account_invoice_report(osv.osv):
|
||||
select_str = """
|
||||
SELECT min(ail.id) AS id,
|
||||
ai.date_invoice AS date,
|
||||
ail.product_id, ai.partner_id, ai.payment_term, ai.period_id, ail.account_analytic_id,
|
||||
ail.product_id, ai.partner_id, ai.payment_term_id, ail.account_analytic_id,
|
||||
u2.name AS uom_name,
|
||||
ai.currency_id, ai.journal_id, ai.fiscal_position, ai.user_id, ai.company_id,
|
||||
ai.currency_id, ai.journal_id, ai.fiscal_position_id, ai.user_id, ai.company_id,
|
||||
count(ail.*) AS nbr,
|
||||
ai.type, ai.state, pt.categ_id, ai.date_due, ai.account_id, ail.account_id AS account_line_id,
|
||||
ai.partner_bank_id,
|
||||
@@ -150,16 +115,8 @@ class account_invoice_report(osv.osv):
|
||||
THEN (- ail.quantity) / u.factor * u2.factor
|
||||
ELSE ail.quantity / u.factor * u2.factor
|
||||
END) AS product_qty,
|
||||
SUM(CASE
|
||||
WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text])
|
||||
THEN - ail.price_subtotal
|
||||
ELSE ail.price_subtotal
|
||||
END) AS price_total,
|
||||
CASE
|
||||
WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text])
|
||||
THEN SUM(- ail.price_subtotal)
|
||||
ELSE SUM(ail.price_subtotal)
|
||||
END / CASE
|
||||
SUM(ail.price_subtotal_signed) AS price_total,
|
||||
SUM(ail.price_subtotal_signed) / CASE
|
||||
WHEN SUM(ail.quantity / u.factor * u2.factor) <> 0::numeric
|
||||
THEN CASE
|
||||
WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text])
|
||||
@@ -168,11 +125,7 @@ class account_invoice_report(osv.osv):
|
||||
END
|
||||
ELSE 1::numeric
|
||||
END AS price_average,
|
||||
CASE
|
||||
WHEN ai.type::text = ANY (ARRAY['out_refund'::character varying::text, 'in_invoice'::character varying::text])
|
||||
THEN - ai.residual
|
||||
ELSE ai.residual
|
||||
END / (SELECT count(*) FROM account_invoice_line l where invoice_id = ai.id) *
|
||||
ai.residual_signed / (SELECT count(*) FROM account_invoice_line l where invoice_id = ai.id) *
|
||||
count(*) AS residual,
|
||||
ai.commercial_partner_id as commercial_partner_id,
|
||||
partner.country_id
|
||||
@@ -194,10 +147,10 @@ class account_invoice_report(osv.osv):
|
||||
def _group_by(self):
|
||||
group_by_str = """
|
||||
GROUP BY ail.product_id, ail.account_analytic_id, ai.date_invoice, ai.id,
|
||||
ai.partner_id, ai.payment_term, ai.period_id, u2.name, u2.id, ai.currency_id, ai.journal_id,
|
||||
ai.fiscal_position, ai.user_id, ai.company_id, ai.type, ai.state, pt.categ_id,
|
||||
ai.date_due, ai.account_id, ail.account_id, ai.partner_bank_id, ai.residual,
|
||||
ai.amount_total, ai.commercial_partner_id, partner.country_id
|
||||
ai.partner_id, ai.payment_term_id, u2.name, u2.id, ai.currency_id, ai.journal_id,
|
||||
ai.fiscal_position_id, ai.user_id, ai.company_id, ai.type, ai.state, pt.categ_id,
|
||||
ai.date_due, ai.account_id, ail.account_id, ai.partner_bank_id, ai.residual_signed,
|
||||
ai.amount_total_signed, ai.commercial_partner_id, partner.country_id
|
||||
"""
|
||||
return group_by_str
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Invoices Analysis" disable_linking="True">
|
||||
<field name="categ_id" type="row"/>
|
||||
<field name="period_id" type="col"/>
|
||||
<field name="date" type="col"/>
|
||||
<field name="price_total" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
@@ -19,7 +19,6 @@
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Invoices Analysis">
|
||||
<field name="categ_id"/>
|
||||
<field name="period_id"/>
|
||||
<field name="price_total" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
@@ -75,7 +74,7 @@
|
||||
<filter string="Invoiced" name="current" domain="[('state','not in', ('draft','cancel','proforma','proforma2'))]"/>
|
||||
<separator/>
|
||||
<filter string="Customer" name="customer" domain="['|', ('type','=','out_invoice'),('type','=','out_refund')]"/>
|
||||
<filter string="Supplier" domain="['|', ('type','=','in_invoice'),('type','=','in_refund')]"/>
|
||||
<filter string="Supplier" name="supplier" domain="['|', ('type','=','in_invoice'),('type','=','in_refund')]"/>
|
||||
<separator/>
|
||||
<filter string="Invoice" domain="['|', ('type','=','out_invoice'),('type','=','in_invoice')]"/>
|
||||
<filter string="Refund" domain="['|', ('type','=','out_refund'),('type','=','in_refund')]"/>
|
||||
@@ -90,13 +89,22 @@
|
||||
<filter string="Status" context="{'group_by':'state'}"/>
|
||||
<filter string="Company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Period" context="{'group_by':'period_id'}"/>
|
||||
<filter string="Date" context="{'group_by':'date'}"/>
|
||||
<filter string="Due Month" context="{'group_by':'date_due:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_account_invoice_report_all_supp" model="ir.actions.act_window">
|
||||
<field name="name">Invoices Analysis</field>
|
||||
<field name="res_model">account.invoice.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="context">{'search_default_current':1, 'search_default_supplier':1, 'group_by':[], 'group_by_no_leaf':1, 'search_default_year': 1}</field>
|
||||
<field name="search_view_id" ref="view_account_invoice_report_search"/>
|
||||
<field name="help">From this report, you can have an overview of the amount invoiced from your suppliers. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs.</field>
|
||||
</record>
|
||||
<record id="action_account_invoice_report_all" model="ir.actions.act_window">
|
||||
<field name="name">Invoices Analysis</field>
|
||||
<field name="res_model">account.invoice.report</field>
|
||||
@@ -104,10 +112,10 @@
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="context">{'search_default_current':1, 'search_default_customer':1, 'group_by':[], 'group_by_no_leaf':1, 'search_default_year': 1}</field>
|
||||
<field name="search_view_id" ref="view_account_invoice_report_search"/>
|
||||
<field name="help">From this report, you can have an overview of the amount invoiced to your customer. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs.</field>
|
||||
<field name="help">From this report, you can have an overview of the amount invoiced to your customers. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs.</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_account_invoice_report_all" id="menu_action_account_invoice_report_all" parent="account.menu_finance_reporting" sequence="0"/>
|
||||
<menuitem action="action_account_invoice_report_all" id="menu_action_account_invoice_report_all" parent="account.menu_finance_reports" sequence="0"/>
|
||||
|
||||
<act_window
|
||||
id="act_account_invoice_partner_relation"
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
|
||||
|
||||
class journal_print(report_sxw.rml_parse, common_report_header):
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
super(journal_print, self).__init__(cr, uid, name, context=context)
|
||||
self.context = context
|
||||
self.period_ids = []
|
||||
self.last_move_id = False
|
||||
self.journal_ids = []
|
||||
self.sort_selection = 'am.name'
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'lines': self.lines,
|
||||
'sum_debit': self._sum_debit,
|
||||
'sum_credit': self._sum_credit,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_account': self._get_account,
|
||||
'get_filter': self._get_filter,
|
||||
'get_start_date': self._get_start_date,
|
||||
'get_end_date': self._get_end_date,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'display_currency':self._display_currency,
|
||||
'get_sortby': self._get_sortby,
|
||||
'get_target_move': self._get_target_move,
|
||||
'check_last_move_id': self.check_last_move_id,
|
||||
'set_last_move_id': self.set_last_move_id,
|
||||
'tax_codes': self.tax_codes,
|
||||
'sum_vat': self._sum_vat,
|
||||
})
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
obj_move = self.pool.get('account.move.line')
|
||||
new_ids = ids
|
||||
self.query_get_clause = ''
|
||||
self.target_move = data['form'].get('target_move', 'all')
|
||||
if (data['model'] == 'ir.ui.menu'):
|
||||
self.period_ids = tuple(data['form']['periods'])
|
||||
self.journal_ids = tuple(data['form']['journal_ids'])
|
||||
new_ids = data['form'].get('active_ids', [])
|
||||
self.query_get_clause = 'AND '
|
||||
self.query_get_clause += obj_move._query_get(self.cr, self.uid, obj='l', context=data['form'].get('used_context', {}))
|
||||
self.sort_selection = data['form'].get('sort_selection', 'date')
|
||||
objects = self.pool.get('account.journal.period').browse(self.cr, self.uid, new_ids)
|
||||
elif new_ids:
|
||||
#in case of direct access from account.journal.period object, we need to set the journal_ids and periods_ids
|
||||
self.cr.execute('SELECT period_id, journal_id FROM account_journal_period WHERE id IN %s', (tuple(new_ids),))
|
||||
res = self.cr.fetchall()
|
||||
self.period_ids, self.journal_ids = zip(*res)
|
||||
return super(journal_print, self).set_context(objects, data, ids, report_type=report_type)
|
||||
|
||||
def set_last_move_id(self, move_id):
|
||||
self.last_move_id = move_id
|
||||
|
||||
def check_last_move_id(self, move_id):
|
||||
'''
|
||||
return True if we need to draw a gray line above this line, used to separate moves
|
||||
'''
|
||||
if self.last_move_id:
|
||||
return not(self.last_move_id == move_id)
|
||||
return False
|
||||
|
||||
def tax_codes(self, period_id, journal_id):
|
||||
ids_journal_period = self.pool.get('account.journal.period').search(self.cr, self.uid,
|
||||
[('journal_id', '=', journal_id), ('period_id', '=', period_id)])
|
||||
self.cr.execute(
|
||||
'select distinct tax_code_id from account_move_line ' \
|
||||
'where period_id=%s and journal_id=%s and tax_code_id is not null and state<>\'draft\'',
|
||||
(period_id, journal_id)
|
||||
)
|
||||
ids = map(lambda x: x[0], self.cr.fetchall())
|
||||
tax_code_ids = []
|
||||
if ids:
|
||||
self.cr.execute('select id from account_tax_code where id in %s order by code', (tuple(ids),))
|
||||
tax_code_ids = map(lambda x: x[0], self.cr.fetchall())
|
||||
tax_codes = self.pool.get('account.tax.code').browse(self.cr, self.uid, tax_code_ids)
|
||||
return tax_codes
|
||||
|
||||
def _sum_vat(self, period_id, journal_id, tax_code_id):
|
||||
self.cr.execute('select sum(tax_amount) from account_move_line where ' \
|
||||
'period_id=%s and journal_id=%s and tax_code_id=%s and state<>\'draft\'',
|
||||
(period_id, journal_id, tax_code_id))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def _sum_debit(self, period_id=False, journal_id=False):
|
||||
if journal_id and isinstance(journal_id, int):
|
||||
journal_id = [journal_id]
|
||||
if period_id and isinstance(period_id, int):
|
||||
period_id = [period_id]
|
||||
if not journal_id:
|
||||
journal_id = self.journal_ids
|
||||
if not period_id:
|
||||
period_id = self.period_ids
|
||||
if not (period_id and journal_id):
|
||||
return 0.0
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
self.cr.execute('SELECT SUM(debit) FROM account_move_line l, account_move am '
|
||||
'WHERE l.move_id=am.id AND am.state IN %s AND l.period_id IN %s AND l.journal_id IN %s ' + self.query_get_clause + ' ',
|
||||
(tuple(move_state), tuple(period_id), tuple(journal_id)))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def _sum_credit(self, period_id=False, journal_id=False):
|
||||
if journal_id and isinstance(journal_id, int):
|
||||
journal_id = [journal_id]
|
||||
if period_id and isinstance(period_id, int):
|
||||
period_id = [period_id]
|
||||
if not journal_id:
|
||||
journal_id = self.journal_ids
|
||||
if not period_id:
|
||||
period_id = self.period_ids
|
||||
if not (period_id and journal_id):
|
||||
return 0.0
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
self.cr.execute('SELECT SUM(l.credit) FROM account_move_line l, account_move am '
|
||||
'WHERE l.move_id=am.id AND am.state IN %s AND l.period_id IN %s AND l.journal_id IN %s '+ self.query_get_clause+'',
|
||||
(tuple(move_state), tuple(period_id), tuple(journal_id)))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def lines(self, period_id, journal_id=False):
|
||||
if not journal_id:
|
||||
journal_id = self.journal_ids
|
||||
else:
|
||||
journal_id = [journal_id]
|
||||
obj_mline = self.pool.get('account.move.line')
|
||||
self.cr.execute('update account_journal_period set state=%s where journal_id IN %s and period_id=%s and state=%s', ('printed', self.journal_ids, period_id, 'draft'))
|
||||
self.pool.get('account.journal.period').invalidate_cache(self.cr, self.uid, ['state'], context=self.context)
|
||||
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
self.cr.execute('SELECT l.id FROM account_move_line l, account_move am WHERE l.move_id=am.id AND am.state IN %s AND l.period_id=%s AND l.journal_id IN %s ' + self.query_get_clause + ' ORDER BY '+ self.sort_selection + ', l.move_id',(tuple(move_state), period_id, tuple(journal_id) ))
|
||||
ids = map(lambda x: x[0], self.cr.fetchall())
|
||||
return obj_mline.browse(self.cr, self.uid, ids)
|
||||
|
||||
def _set_get_account_currency_code(self, account_id):
|
||||
self.cr.execute("SELECT c.symbol AS code "\
|
||||
"FROM res_currency c,account_account AS ac "\
|
||||
"WHERE ac.id = %s AND ac.currency_id = c.id" % (account_id))
|
||||
result = self.cr.fetchone()
|
||||
if result:
|
||||
self.account_currency = result[0]
|
||||
else:
|
||||
self.account_currency = False
|
||||
|
||||
def _get_fiscalyear(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return self.pool.get('account.journal.period').browse(self.cr, self.uid, data['id']).fiscalyear_id.name
|
||||
return super(journal_print, self)._get_fiscalyear(data)
|
||||
|
||||
def _get_account(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return self.pool.get('account.journal.period').browse(self.cr, self.uid, data['id']).company_id.name
|
||||
return super(journal_print, self)._get_account(data)
|
||||
|
||||
def _display_currency(self, data):
|
||||
if data['model'] == 'account.journal.period':
|
||||
return True
|
||||
return data['form']['amount_currency']
|
||||
|
||||
def _get_sortby(self, data):
|
||||
# TODO: deprecated, to remove in trunk
|
||||
if self.sort_selection == 'date':
|
||||
return self._translate('Date')
|
||||
elif self.sort_selection == 'ref':
|
||||
return self._translate('Reference Number')
|
||||
return self._translate('Date')
|
||||
|
||||
|
||||
class report_journal(osv.AbstractModel):
|
||||
_name = 'report.account.report_journal'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_journal'
|
||||
_wrapped_report_class = journal_print
|
||||
|
||||
|
||||
class report_salepurchasejournal(osv.AbstractModel):
|
||||
_name = 'report.account.report_salepurchasejournal'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_salepurchasejournal'
|
||||
_wrapped_report_class = journal_print
|
||||
@@ -1,263 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
|
||||
|
||||
class partner_balance(report_sxw.rml_parse, common_report_header):
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
super(partner_balance, self).__init__(cr, uid, name, context=context)
|
||||
self.account_ids = []
|
||||
self.localcontext.update( {
|
||||
'time': time,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_journal': self._get_journal,
|
||||
'get_filter': self._get_filter,
|
||||
'get_account': self._get_account,
|
||||
'get_start_date':self._get_start_date,
|
||||
'get_end_date':self._get_end_date,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_partners':self._get_partners,
|
||||
'get_target_move': self._get_target_move,
|
||||
})
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
self.display_partner = data['form'].get('display_partner', 'non-zero_balance')
|
||||
obj_move = self.pool.get('account.move.line')
|
||||
self.query = obj_move._query_get(self.cr, self.uid, obj='l', context=data['form'].get('used_context', {}))
|
||||
self.result_selection = data['form'].get('result_selection')
|
||||
self.target_move = data['form'].get('target_move', 'all')
|
||||
|
||||
if (self.result_selection == 'customer' ):
|
||||
self.ACCOUNT_TYPE = ('receivable',)
|
||||
elif (self.result_selection == 'supplier'):
|
||||
self.ACCOUNT_TYPE = ('payable',)
|
||||
else:
|
||||
self.ACCOUNT_TYPE = ('payable', 'receivable')
|
||||
|
||||
self.cr.execute("SELECT a.id " \
|
||||
"FROM account_account a " \
|
||||
"LEFT JOIN account_account_type t " \
|
||||
"ON (a.type = t.code) " \
|
||||
"WHERE a.type IN %s " \
|
||||
"AND a.active", (self.ACCOUNT_TYPE,))
|
||||
self.account_ids = [a for (a,) in self.cr.fetchall()]
|
||||
res = super(partner_balance, self).set_context(objects, data, ids, report_type=report_type)
|
||||
lines = self.lines()
|
||||
sum_debit = sum_credit = sum_litige = 0
|
||||
for line in filter(lambda x: x['type'] == 3, lines):
|
||||
sum_debit += line['debit'] or 0
|
||||
sum_credit += line['credit'] or 0
|
||||
sum_litige += line['enlitige'] or 0
|
||||
self.localcontext.update({
|
||||
'lines': lambda: lines,
|
||||
'sum_debit': lambda: sum_debit,
|
||||
'sum_credit': lambda: sum_credit,
|
||||
'sum_litige': lambda: sum_litige,
|
||||
})
|
||||
return res
|
||||
|
||||
def lines(self):
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
full_account = []
|
||||
self.cr.execute(
|
||||
"SELECT p.ref,l.account_id,ac.name AS account_name,ac.code AS code,p.name, sum(debit) AS debit, sum(credit) AS credit, " \
|
||||
"CASE WHEN sum(debit) > sum(credit) " \
|
||||
"THEN sum(debit) - sum(credit) " \
|
||||
"ELSE 0 " \
|
||||
"END AS sdebit, " \
|
||||
"CASE WHEN sum(debit) < sum(credit) " \
|
||||
"THEN sum(credit) - sum(debit) " \
|
||||
"ELSE 0 " \
|
||||
"END AS scredit, " \
|
||||
"(SELECT sum(debit-credit) " \
|
||||
"FROM account_move_line l " \
|
||||
"WHERE partner_id = p.id " \
|
||||
"AND " + self.query + " " \
|
||||
"AND blocked = TRUE " \
|
||||
") AS enlitige " \
|
||||
"FROM account_move_line l LEFT JOIN res_partner p ON (l.partner_id=p.id) " \
|
||||
"JOIN account_account ac ON (l.account_id = ac.id)" \
|
||||
"JOIN account_move am ON (am.id = l.move_id)" \
|
||||
"WHERE ac.type IN %s " \
|
||||
"AND am.state IN %s " \
|
||||
"AND " + self.query + "" \
|
||||
"GROUP BY p.id, p.ref, p.name,l.account_id,ac.name,ac.code " \
|
||||
"ORDER BY l.account_id,p.name",
|
||||
(self.ACCOUNT_TYPE, tuple(move_state)))
|
||||
res = self.cr.dictfetchall()
|
||||
|
||||
|
||||
if self.display_partner == 'non-zero_balance':
|
||||
full_account = [r for r in res if r['sdebit'] > 0 or r['scredit'] > 0]
|
||||
else:
|
||||
full_account = [r for r in res]
|
||||
|
||||
for rec in full_account:
|
||||
if not rec.get('name', False):
|
||||
rec.update({'name': _('Unknown Partner')})
|
||||
|
||||
## We will now compute Total
|
||||
subtotal_row = self._add_subtotal(full_account)
|
||||
return subtotal_row
|
||||
|
||||
def _add_subtotal(self, cleanarray):
|
||||
i = 0
|
||||
completearray = []
|
||||
tot_debit = 0.0
|
||||
tot_credit = 0.0
|
||||
tot_scredit = 0.0
|
||||
tot_sdebit = 0.0
|
||||
tot_enlitige = 0.0
|
||||
for r in cleanarray:
|
||||
# For the first element we always add the line
|
||||
# type = 1 is the line is the first of the account
|
||||
# type = 2 is an other line of the account
|
||||
if i==0:
|
||||
# We add the first as the header
|
||||
#
|
||||
##
|
||||
new_header = {}
|
||||
new_header['ref'] = ''
|
||||
new_header['name'] = r['account_name']
|
||||
new_header['code'] = r['code']
|
||||
new_header['debit'] = r['debit']
|
||||
new_header['credit'] = r['credit']
|
||||
new_header['scredit'] = tot_scredit
|
||||
new_header['sdebit'] = tot_sdebit
|
||||
new_header['enlitige'] = tot_enlitige
|
||||
new_header['balance'] = r['debit'] - r['credit']
|
||||
new_header['type'] = 3
|
||||
##
|
||||
completearray.append(new_header)
|
||||
#
|
||||
r['type'] = 1
|
||||
r['balance'] = float(r['sdebit']) - float(r['scredit'])
|
||||
|
||||
completearray.append(r)
|
||||
#
|
||||
tot_debit = r['debit']
|
||||
tot_credit = r['credit']
|
||||
tot_scredit = r['scredit']
|
||||
tot_sdebit = r['sdebit']
|
||||
tot_enlitige = (r['enlitige'] or 0.0)
|
||||
#
|
||||
else:
|
||||
if cleanarray[i]['account_id'] <> cleanarray[i-1]['account_id']:
|
||||
|
||||
new_header['debit'] = tot_debit
|
||||
new_header['credit'] = tot_credit
|
||||
new_header['scredit'] = tot_scredit
|
||||
new_header['sdebit'] = tot_sdebit
|
||||
new_header['enlitige'] = tot_enlitige
|
||||
new_header['balance'] = float(tot_sdebit) - float(tot_scredit)
|
||||
new_header['type'] = 3
|
||||
# we reset the counter
|
||||
tot_debit = r['debit']
|
||||
tot_credit = r['credit']
|
||||
tot_scredit = r['scredit']
|
||||
tot_sdebit = r['sdebit']
|
||||
tot_enlitige = (r['enlitige'] or 0.0)
|
||||
#
|
||||
##
|
||||
new_header = {}
|
||||
new_header['ref'] = ''
|
||||
new_header['name'] = r['account_name']
|
||||
new_header['code'] = r['code']
|
||||
new_header['debit'] = tot_debit
|
||||
new_header['credit'] = tot_credit
|
||||
new_header['scredit'] = tot_scredit
|
||||
new_header['sdebit'] = tot_sdebit
|
||||
new_header['enlitige'] = tot_enlitige
|
||||
new_header['balance'] = float(tot_sdebit) - float(tot_scredit)
|
||||
new_header['type'] = 3
|
||||
##get_fiscalyear
|
||||
##
|
||||
|
||||
completearray.append(new_header)
|
||||
##
|
||||
#
|
||||
r['type'] = 1
|
||||
#
|
||||
r['balance'] = float(r['sdebit']) - float(r['scredit'])
|
||||
|
||||
completearray.append(r)
|
||||
|
||||
if cleanarray[i]['account_id'] == cleanarray[i-1]['account_id']:
|
||||
# we reset the counter
|
||||
|
||||
new_header['debit'] = tot_debit
|
||||
new_header['credit'] = tot_credit
|
||||
new_header['scredit'] = tot_scredit
|
||||
new_header['sdebit'] = tot_sdebit
|
||||
new_header['enlitige'] = tot_enlitige
|
||||
new_header['balance'] = float(tot_sdebit) - float(tot_scredit)
|
||||
new_header['type'] = 3
|
||||
|
||||
tot_debit = tot_debit + r['debit']
|
||||
tot_credit = tot_credit + r['credit']
|
||||
tot_scredit = tot_scredit + r['scredit']
|
||||
tot_sdebit = tot_sdebit + r['sdebit']
|
||||
tot_enlitige = tot_enlitige + (r['enlitige'] or 0.0)
|
||||
|
||||
new_header['debit'] = tot_debit
|
||||
new_header['credit'] = tot_credit
|
||||
new_header['scredit'] = tot_scredit
|
||||
new_header['sdebit'] = tot_sdebit
|
||||
new_header['enlitige'] = tot_enlitige
|
||||
new_header['balance'] = float(tot_sdebit) - float(tot_scredit)
|
||||
|
||||
#
|
||||
r['type'] = 2
|
||||
#
|
||||
r['balance'] = float(r['sdebit']) - float(r['scredit'])
|
||||
#
|
||||
|
||||
completearray.append(r)
|
||||
|
||||
i = i + 1
|
||||
return completearray
|
||||
|
||||
def _get_partners(self):
|
||||
|
||||
if self.result_selection == 'customer':
|
||||
return _('Receivable Accounts')
|
||||
elif self.result_selection == 'supplier':
|
||||
return _('Payable Accounts')
|
||||
elif self.result_selection == 'customer_supplier':
|
||||
return _('Receivable and Payable Accounts')
|
||||
return ''
|
||||
|
||||
|
||||
class report_partnerbalance(osv.AbstractModel):
|
||||
_name = 'report.account.report_partnerbalance'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_partnerbalance'
|
||||
_wrapped_report_class = partner_balance
|
||||
@@ -1,320 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
from openerp import SUPERUSER_ID
|
||||
|
||||
class third_party_ledger(report_sxw.rml_parse, common_report_header):
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
super(third_party_ledger, self).__init__(cr, uid, name, context=context)
|
||||
self.init_bal_sum = 0.0
|
||||
self.amount_currency = {}
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'lines': self.lines,
|
||||
'sum_debit_partner': self._sum_debit_partner,
|
||||
'sum_credit_partner': self._sum_credit_partner,
|
||||
'get_currency': self._get_currency,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_account': self._get_account,
|
||||
'get_filter': self._get_filter,
|
||||
'get_start_date': self._get_start_date,
|
||||
'get_end_date': self._get_end_date,
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_journal': self._get_journal,
|
||||
'get_partners':self._get_partners,
|
||||
'get_intial_balance':self._get_intial_balance,
|
||||
'display_initial_balance':self._display_initial_balance,
|
||||
'display_currency':self._display_currency,
|
||||
'get_target_move': self._get_target_move,
|
||||
'amount_currency': self.amount_currency,
|
||||
})
|
||||
|
||||
def _get_filter(self, data):
|
||||
if data['form']['filter'] == 'unreconciled':
|
||||
return _('Unreconciled Entries')
|
||||
return super(third_party_ledger, self)._get_filter(data)
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
obj_move = self.pool.get('account.move.line')
|
||||
obj_partner = self.pool.get('res.partner')
|
||||
self.query = obj_move._query_get(self.cr, self.uid, obj='l', context=data['form'].get('used_context', {}))
|
||||
ctx2 = data['form'].get('used_context',{}).copy()
|
||||
self.initial_balance = data['form'].get('initial_balance', True)
|
||||
if self.initial_balance:
|
||||
ctx2.update({'initial_bal': True})
|
||||
self.init_query = obj_move._query_get(self.cr, self.uid, obj='l', context=ctx2)
|
||||
self.reconcil = True
|
||||
if data['form']['filter'] == 'unreconciled':
|
||||
self.reconcil = False
|
||||
self.result_selection = data['form'].get('result_selection', 'customer')
|
||||
if data['form'].get('amount_currency'):
|
||||
self.amount_currency['currency'] = True
|
||||
else:
|
||||
self.amount_currency.pop('currency', False)
|
||||
self.target_move = data['form'].get('target_move', 'all')
|
||||
PARTNER_REQUEST = ''
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
if self.result_selection == 'supplier':
|
||||
self.ACCOUNT_TYPE = ['payable']
|
||||
elif self.result_selection == 'customer':
|
||||
self.ACCOUNT_TYPE = ['receivable']
|
||||
else:
|
||||
self.ACCOUNT_TYPE = ['payable','receivable']
|
||||
|
||||
self.cr.execute(
|
||||
"SELECT a.id " \
|
||||
"FROM account_account a " \
|
||||
"LEFT JOIN account_account_type t " \
|
||||
"ON (a.type=t.code) " \
|
||||
'WHERE a.type IN %s' \
|
||||
"AND a.active", (tuple(self.ACCOUNT_TYPE), ))
|
||||
self.account_ids = [a for (a,) in self.cr.fetchall()]
|
||||
params = [tuple(move_state), tuple(self.account_ids)]
|
||||
#if we print from the partners, add a clause on active_ids
|
||||
if (data['model'] == 'res.partner') and ids:
|
||||
PARTNER_REQUEST = "AND l.partner_id IN %s"
|
||||
params += [tuple(ids)]
|
||||
reconcile = "" if self.reconcil else "AND l.reconcile_id IS NULL "
|
||||
self.cr.execute(
|
||||
"SELECT DISTINCT l.partner_id " \
|
||||
"FROM account_move_line AS l, account_account AS account, " \
|
||||
" account_move AS am " \
|
||||
"WHERE l.partner_id IS NOT NULL " \
|
||||
"AND l.account_id = account.id " \
|
||||
"AND am.id = l.move_id " \
|
||||
"AND am.state IN %s"
|
||||
"AND " + self.query +" " \
|
||||
"AND l.account_id IN %s " \
|
||||
" " + PARTNER_REQUEST + " " \
|
||||
"AND account.active " + reconcile + " ", params)
|
||||
self.partner_ids = [res['partner_id'] for res in self.cr.dictfetchall()]
|
||||
objects = obj_partner.browse(self.cr, SUPERUSER_ID, self.partner_ids)
|
||||
objects = sorted(objects, key=lambda x: (x.ref, x.name))
|
||||
return super(third_party_ledger, self).set_context(objects, data, self.partner_ids, report_type)
|
||||
|
||||
def lines(self, partner):
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
full_account = []
|
||||
if self.reconcil:
|
||||
RECONCILE_TAG = " "
|
||||
else:
|
||||
RECONCILE_TAG = "AND l.reconcile_id IS NULL"
|
||||
self.cr.execute(
|
||||
"SELECT l.id, l.date, j.code, acc.code as a_code, acc.name as a_name, l.ref, m.name as move_name, l.name, l.debit, l.credit, l.amount_currency,l.currency_id, c.symbol AS currency_code " \
|
||||
"FROM account_move_line l " \
|
||||
"LEFT JOIN account_journal j " \
|
||||
"ON (l.journal_id = j.id) " \
|
||||
"LEFT JOIN account_account acc " \
|
||||
"ON (l.account_id = acc.id) " \
|
||||
"LEFT JOIN res_currency c ON (l.currency_id=c.id)" \
|
||||
"LEFT JOIN account_move m ON (m.id=l.move_id)" \
|
||||
"WHERE l.partner_id = %s " \
|
||||
"AND l.account_id IN %s AND " + self.query +" " \
|
||||
"AND m.state IN %s " \
|
||||
" " + RECONCILE_TAG + " "\
|
||||
"ORDER BY l.date",
|
||||
(partner.id, tuple(self.account_ids), tuple(move_state)))
|
||||
res = self.cr.dictfetchall()
|
||||
sum = 0.0
|
||||
if self.initial_balance:
|
||||
sum = self.init_bal_sum
|
||||
for r in res:
|
||||
sum += r['debit'] - r['credit']
|
||||
r['progress'] = sum
|
||||
full_account.append(r)
|
||||
return full_account
|
||||
|
||||
def _get_intial_balance(self, partner):
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
if self.reconcil:
|
||||
RECONCILE_TAG = " "
|
||||
else:
|
||||
RECONCILE_TAG = "AND l.reconcile_id IS NULL"
|
||||
self.cr.execute(
|
||||
"SELECT COALESCE(SUM(l.debit),0.0), COALESCE(SUM(l.credit),0.0), COALESCE(sum(debit-credit), 0.0) " \
|
||||
"FROM account_move_line AS l, " \
|
||||
"account_move AS m "
|
||||
"WHERE l.partner_id = %s " \
|
||||
"AND m.id = l.move_id " \
|
||||
"AND m.state IN %s "
|
||||
"AND account_id IN %s" \
|
||||
" " + RECONCILE_TAG + " "\
|
||||
"AND " + self.init_query + " ",
|
||||
(partner.id, tuple(move_state), tuple(self.account_ids)))
|
||||
res = self.cr.fetchall()
|
||||
self.init_bal_sum = res[0][2]
|
||||
return res
|
||||
|
||||
def _sum_debit_partner(self, partner):
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
result_tmp = 0.0
|
||||
result_init = 0.0
|
||||
if self.reconcil:
|
||||
RECONCILE_TAG = " "
|
||||
else:
|
||||
RECONCILE_TAG = "AND reconcile_id IS NULL"
|
||||
if self.initial_balance:
|
||||
self.cr.execute(
|
||||
"SELECT sum(debit) " \
|
||||
"FROM account_move_line AS l, " \
|
||||
"account_move AS m "
|
||||
"WHERE l.partner_id = %s" \
|
||||
"AND m.id = l.move_id " \
|
||||
"AND m.state IN %s "
|
||||
"AND account_id IN %s" \
|
||||
" " + RECONCILE_TAG + " " \
|
||||
"AND " + self.init_query + " ",
|
||||
(partner.id, tuple(move_state), tuple(self.account_ids)))
|
||||
contemp = self.cr.fetchone()
|
||||
if contemp != None:
|
||||
result_init = contemp[0] or 0.0
|
||||
else:
|
||||
result_init = result_tmp + 0.0
|
||||
|
||||
self.cr.execute(
|
||||
"SELECT sum(debit) " \
|
||||
"FROM account_move_line AS l, " \
|
||||
"account_move AS m "
|
||||
"WHERE l.partner_id = %s " \
|
||||
"AND m.id = l.move_id " \
|
||||
"AND m.state IN %s "
|
||||
"AND account_id IN %s" \
|
||||
" " + RECONCILE_TAG + " " \
|
||||
"AND " + self.query + " ",
|
||||
(partner.id, tuple(move_state), tuple(self.account_ids),))
|
||||
|
||||
contemp = self.cr.fetchone()
|
||||
if contemp != None:
|
||||
result_tmp = contemp[0] or 0.0
|
||||
else:
|
||||
result_tmp = result_tmp + 0.0
|
||||
|
||||
return result_tmp + result_init
|
||||
|
||||
def _sum_credit_partner(self, partner):
|
||||
move_state = ['draft','posted']
|
||||
if self.target_move == 'posted':
|
||||
move_state = ['posted']
|
||||
|
||||
result_tmp = 0.0
|
||||
result_init = 0.0
|
||||
if self.reconcil:
|
||||
RECONCILE_TAG = " "
|
||||
else:
|
||||
RECONCILE_TAG = "AND reconcile_id IS NULL"
|
||||
if self.initial_balance:
|
||||
self.cr.execute(
|
||||
"SELECT sum(credit) " \
|
||||
"FROM account_move_line AS l, " \
|
||||
"account_move AS m "
|
||||
"WHERE l.partner_id = %s" \
|
||||
"AND m.id = l.move_id " \
|
||||
"AND m.state IN %s "
|
||||
"AND account_id IN %s" \
|
||||
" " + RECONCILE_TAG + " " \
|
||||
"AND " + self.init_query + " ",
|
||||
(partner.id, tuple(move_state), tuple(self.account_ids)))
|
||||
contemp = self.cr.fetchone()
|
||||
if contemp != None:
|
||||
result_init = contemp[0] or 0.0
|
||||
else:
|
||||
result_init = result_tmp + 0.0
|
||||
|
||||
self.cr.execute(
|
||||
"SELECT sum(credit) " \
|
||||
"FROM account_move_line AS l, " \
|
||||
"account_move AS m "
|
||||
"WHERE l.partner_id=%s " \
|
||||
"AND m.id = l.move_id " \
|
||||
"AND m.state IN %s "
|
||||
"AND account_id IN %s" \
|
||||
" " + RECONCILE_TAG + " " \
|
||||
"AND " + self.query + " ",
|
||||
(partner.id, tuple(move_state), tuple(self.account_ids),))
|
||||
|
||||
contemp = self.cr.fetchone()
|
||||
if contemp != None:
|
||||
result_tmp = contemp[0] or 0.0
|
||||
else:
|
||||
result_tmp = result_tmp + 0.0
|
||||
return result_tmp + result_init
|
||||
|
||||
def _get_partners(self):
|
||||
# TODO: deprecated, to remove in trunk
|
||||
if self.result_selection == 'customer':
|
||||
return _('Receivable Accounts')
|
||||
elif self.result_selection == 'supplier':
|
||||
return _('Payable Accounts')
|
||||
elif self.result_selection == 'customer_supplier':
|
||||
return _('Receivable and Payable Accounts')
|
||||
return ''
|
||||
|
||||
def _sum_currency_amount_account(self, account, form):
|
||||
self._set_get_account_currency_code(account.id)
|
||||
self.cr.execute("SELECT sum(aml.amount_currency) FROM account_move_line as aml,res_currency as rc WHERE aml.currency_id = rc.id AND aml.account_id= %s ", (account.id,))
|
||||
total = self.cr.fetchone()
|
||||
if self.account_currency:
|
||||
return_field = str(total[0]) + self.account_currency
|
||||
return return_field
|
||||
else:
|
||||
currency_total = self.tot_currency = 0.0
|
||||
return currency_total
|
||||
|
||||
def _display_initial_balance(self, data):
|
||||
if self.initial_balance:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _display_currency(self, data):
|
||||
if self.amount_currency:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class report_partnerledger(osv.AbstractModel):
|
||||
_name = 'report.account.report_partnerledger'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_partnerledger'
|
||||
_wrapped_report_class = third_party_ledger
|
||||
|
||||
|
||||
class report_partnerledgerother(osv.AbstractModel):
|
||||
_name = 'report.account.report_partnerledgerother'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_partnerledgerother'
|
||||
_wrapped_report_class = third_party_ledger
|
||||
@@ -1,90 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
|
||||
from openerp.report import report_sxw
|
||||
from openerp.osv import osv
|
||||
|
||||
|
||||
class Overdue(report_sxw.rml_parse):
|
||||
def __init__(self, cr, uid, name, context):
|
||||
super(Overdue, self).__init__(cr, uid, name, context=context)
|
||||
ids = context.get('active_ids')
|
||||
partner_obj = self.pool['res.partner']
|
||||
docs = partner_obj.browse(cr, uid, ids, context)
|
||||
|
||||
due = {}
|
||||
paid = {}
|
||||
mat = {}
|
||||
|
||||
for partner in docs:
|
||||
due[partner.id] = reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['debit'] or 0) or (y['account_id']['type'] == 'payable' and y['credit'] * -1 or 0)), self._lines_get(partner), 0)
|
||||
paid[partner.id] = reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), self._lines_get(partner), 0)
|
||||
mat[partner.id] = reduce(lambda x, y: x + (y['debit'] - y['credit']), filter(lambda x: x['date_maturity'] < time.strftime('%Y-%m-%d'), self._lines_get(partner)), 0)
|
||||
|
||||
addresses = self.pool['res.partner']._address_display(cr, uid, ids, None, None)
|
||||
self.localcontext.update({
|
||||
'docs': docs,
|
||||
'time': time,
|
||||
'getLines': self._lines_get,
|
||||
'tel_get': self._tel_get,
|
||||
'message': self._message,
|
||||
'due': due,
|
||||
'paid': paid,
|
||||
'mat': mat,
|
||||
'addresses': addresses
|
||||
})
|
||||
self.context = context
|
||||
|
||||
def _tel_get(self,partner):
|
||||
if not partner:
|
||||
return False
|
||||
res_partner = self.pool['res.partner']
|
||||
addresses = res_partner.address_get(self.cr, self.uid, [partner.id], ['invoice'])
|
||||
adr_id = addresses and addresses['invoice'] or False
|
||||
if adr_id:
|
||||
adr=res_partner.read(self.cr, self.uid, [adr_id])[0]
|
||||
return adr['phone']
|
||||
else:
|
||||
return partner.phone or False
|
||||
return False
|
||||
|
||||
def _lines_get(self, partner):
|
||||
moveline_obj = self.pool['account.move.line']
|
||||
movelines = moveline_obj.search(self.cr, self.uid,
|
||||
[('partner_id', '=', partner.id),
|
||||
('account_id.type', 'in', ['receivable', 'payable']),
|
||||
('state', '<>', 'draft'), ('reconcile_id', '=', False)])
|
||||
movelines = moveline_obj.browse(self.cr, self.uid, movelines)
|
||||
return movelines
|
||||
|
||||
def _message(self, obj, company):
|
||||
company_pool = self.pool['res.company']
|
||||
message = company_pool.browse(self.cr, self.uid, company.id, {'lang':obj.lang}).overdue_msg
|
||||
return message.split('\n')
|
||||
|
||||
|
||||
class report_overdue(osv.AbstractModel):
|
||||
_name = 'report.account.report_overdue'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_overdue'
|
||||
_wrapped_report_class = Overdue
|
||||
@@ -1,288 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from openerp import tools
|
||||
from openerp.osv import fields,osv
|
||||
|
||||
def _code_get(self, cr, uid, context=None):
|
||||
acc_type_obj = self.pool.get('account.account.type')
|
||||
ids = acc_type_obj.search(cr, uid, [])
|
||||
res = acc_type_obj.read(cr, uid, ids, ['code', 'name'], context)
|
||||
return [(r['code'], r['name']) for r in res]
|
||||
|
||||
|
||||
class report_account_receivable(osv.osv):
|
||||
_name = "report.account.receivable"
|
||||
_description = "Receivable accounts"
|
||||
_auto = False
|
||||
_columns = {
|
||||
'name': fields.char('Week of Year', size=7, readonly=True),
|
||||
'type': fields.selection(_code_get, 'Account Type', required=True),
|
||||
'balance':fields.float('Balance', readonly=True),
|
||||
'debit':fields.float('Debit', readonly=True),
|
||||
'credit':fields.float('Credit', readonly=True),
|
||||
}
|
||||
_order = 'name desc'
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'report_account_receivable')
|
||||
cr.execute("""
|
||||
create or replace view report_account_receivable as (
|
||||
select
|
||||
min(l.id) as id,
|
||||
to_char(date,'YYYY:IW') as name,
|
||||
sum(l.debit-l.credit) as balance,
|
||||
sum(l.debit) as debit,
|
||||
sum(l.credit) as credit,
|
||||
a.type
|
||||
from
|
||||
account_move_line l
|
||||
left join
|
||||
account_account a on (l.account_id=a.id)
|
||||
where
|
||||
l.state <> 'draft'
|
||||
group by
|
||||
to_char(date,'YYYY:IW'), a.type
|
||||
)""")
|
||||
|
||||
#a.type in ('receivable','payable')
|
||||
class temp_range(osv.osv):
|
||||
_name = 'temp.range'
|
||||
_description = 'A Temporary table used for Dashboard view'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Range')
|
||||
}
|
||||
|
||||
|
||||
class report_aged_receivable(osv.osv):
|
||||
_name = "report.aged.receivable"
|
||||
_description = "Aged Receivable Till Today"
|
||||
_auto = False
|
||||
|
||||
def __init__(self, pool, cr):
|
||||
super(report_aged_receivable, self).__init__(pool, cr)
|
||||
self.called = False
|
||||
|
||||
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
""" To call the init() method timely
|
||||
"""
|
||||
if context is None:context = {}
|
||||
if not self.called:
|
||||
self._init(cr, user)
|
||||
self.called = True # To make sure that init doesn't get called multiple times
|
||||
|
||||
res = super(report_aged_receivable, self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
|
||||
return res
|
||||
|
||||
def _calc_bal(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
for period in self.read(cr, uid, ids, ['name'], context=context):
|
||||
date1,date2 = period['name'].split(' to ')
|
||||
cr.execute("SELECT SUM(credit-debit) FROM account_move_line AS line, account_account as ac \
|
||||
WHERE (line.account_id=ac.id) AND ac.type='receivable' \
|
||||
AND (COALESCE(line.date,date) BETWEEN %s AND %s) \
|
||||
AND (reconcile_id IS NULL) AND ac.active",(str(date2),str(date1),))
|
||||
amount = cr.fetchone()
|
||||
amount = amount[0] or 0.00
|
||||
res[period['id']] = amount
|
||||
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Month Range', size=24, readonly=True),
|
||||
'balance': fields.function(_calc_bal, string='Balance', readonly=True),
|
||||
}
|
||||
|
||||
def init(self, cr):
|
||||
return self._init(cr, 1)
|
||||
|
||||
def _init(self, cr, uid):
|
||||
""" This view will be used in dashboard
|
||||
The reason writing this code here is, we need to check date range from today to first date of fiscal year.
|
||||
"""
|
||||
pool_obj_fy = self.pool['account.fiscalyear']
|
||||
current_date = datetime.date.today()
|
||||
fy_id = pool_obj_fy.find(cr, uid, exception=False)
|
||||
names = []
|
||||
|
||||
def add(names, start_on, stop_on):
|
||||
names.append(start_on.strftime("%Y-%m-%d") + ' to ' + stop_on.strftime('%Y-%m-%d'))
|
||||
return names
|
||||
|
||||
if fy_id:
|
||||
fiscal_year = pool_obj_fy.browse(cr, uid, fy_id)
|
||||
fy_start_date = datetime.datetime.strptime(fiscal_year.date_start, '%Y-%m-%d').date()
|
||||
last_month_date = current_date - relativedelta(months=1)
|
||||
|
||||
while (last_month_date > fy_start_date):
|
||||
add(names, current_date, last_month_date)
|
||||
current_date = last_month_date - relativedelta(days=1)
|
||||
last_month_date = current_date - relativedelta(months=1)
|
||||
|
||||
add(names, current_date, fy_start_date)
|
||||
cr.execute('delete from temp_range')
|
||||
|
||||
for name in names:
|
||||
self.pool['temp.range'].create(cr, uid, {'name':name})
|
||||
|
||||
cr.execute("""
|
||||
create or replace view report_aged_receivable as (
|
||||
select id,name from temp_range
|
||||
)""")
|
||||
|
||||
|
||||
class report_invoice_created(osv.osv):
|
||||
_name = "report.invoice.created"
|
||||
_description = "Report of Invoices Created within Last 15 days"
|
||||
_auto = False
|
||||
_columns = {
|
||||
'name': fields.char('Description', readonly=True),
|
||||
'type': fields.selection([
|
||||
('out_invoice','Customer Invoice'),
|
||||
('in_invoice','Supplier Invoice'),
|
||||
('out_refund','Customer Refund'),
|
||||
('in_refund','Supplier Refund'),
|
||||
],'Type', readonly=True),
|
||||
'number': fields.char('Invoice Number', readonly=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
|
||||
'amount_untaxed': fields.float('Untaxed', readonly=True),
|
||||
'amount_total': fields.float('Total', readonly=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
'date_invoice': fields.date('Invoice Date', readonly=True),
|
||||
'date_due': fields.date('Due Date', readonly=True),
|
||||
'residual': fields.float('Residual', readonly=True),
|
||||
'state': fields.selection([
|
||||
('draft','Draft'),
|
||||
('proforma','Pro-forma'),
|
||||
('proforma2','Pro-forma'),
|
||||
('open','Open'),
|
||||
('paid','Done'),
|
||||
('cancel','Cancelled')
|
||||
],'Status', readonly=True),
|
||||
'origin': fields.char('Source Document', readonly=True, help="Reference of the document that generated this invoice report."),
|
||||
'create_date': fields.datetime('Create Date', readonly=True)
|
||||
}
|
||||
_order = 'create_date'
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'report_invoice_created')
|
||||
cr.execute("""create or replace view report_invoice_created as (
|
||||
select
|
||||
inv.id as id, inv.name as name, inv.type as type,
|
||||
inv.number as number, inv.partner_id as partner_id,
|
||||
inv.amount_untaxed as amount_untaxed,
|
||||
inv.amount_total as amount_total, inv.currency_id as currency_id,
|
||||
inv.date_invoice as date_invoice, inv.date_due as date_due,
|
||||
inv.residual as residual, inv.state as state,
|
||||
inv.origin as origin, inv.create_date as create_date
|
||||
from
|
||||
account_invoice inv
|
||||
where
|
||||
(to_date(to_char(inv.create_date, 'YYYY-MM-dd'),'YYYY-MM-dd') <= CURRENT_DATE)
|
||||
AND
|
||||
(to_date(to_char(inv.create_date, 'YYYY-MM-dd'),'YYYY-MM-dd') > (CURRENT_DATE-15))
|
||||
)""")
|
||||
|
||||
class report_account_type_sales(osv.osv):
|
||||
_name = "report.account_type.sales"
|
||||
_description = "Report of the Sales by Account Type"
|
||||
_auto = False
|
||||
_columns = {
|
||||
'name': fields.char('Year', required=False, readonly=True),
|
||||
'period_id': fields.many2one('account.period', 'Force Period', readonly=True),
|
||||
'product_id': fields.many2one('product.product', 'Product', readonly=True),
|
||||
'quantity': fields.float('Quantity', readonly=True),
|
||||
'user_type': fields.many2one('account.account.type', 'Account Type', readonly=True),
|
||||
'amount_total': fields.float('Total', readonly=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'),
|
||||
('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')], 'Month', readonly=True),
|
||||
}
|
||||
_order = 'name desc,amount_total desc'
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'report_account_type_sales')
|
||||
cr.execute("""create or replace view report_account_type_sales as (
|
||||
select
|
||||
min(inv_line.id) as id,
|
||||
to_char(inv.date_invoice, 'YYYY') as name,
|
||||
to_char(inv.date_invoice,'MM') as month,
|
||||
sum(inv_line.price_subtotal) as amount_total,
|
||||
inv.currency_id as currency_id,
|
||||
inv.period_id,
|
||||
inv_line.product_id,
|
||||
sum(inv_line.quantity) as quantity,
|
||||
account.user_type
|
||||
from
|
||||
account_invoice_line inv_line
|
||||
inner join account_invoice inv on inv.id = inv_line.invoice_id
|
||||
inner join account_account account on account.id = inv_line.account_id
|
||||
where
|
||||
inv.state in ('open','paid')
|
||||
group by
|
||||
to_char(inv.date_invoice, 'YYYY'),to_char(inv.date_invoice,'MM'),inv.currency_id, inv.period_id, inv_line.product_id, account.user_type
|
||||
)""")
|
||||
|
||||
|
||||
class report_account_sales(osv.osv):
|
||||
_name = "report.account.sales"
|
||||
_description = "Report of the Sales by Account"
|
||||
_auto = False
|
||||
_columns = {
|
||||
'name': fields.char('Year', required=False, readonly=True, select=True),
|
||||
'period_id': fields.many2one('account.period', 'Force Period', readonly=True),
|
||||
'product_id': fields.many2one('product.product', 'Product', readonly=True),
|
||||
'quantity': fields.float('Quantity', readonly=True),
|
||||
'account_id': fields.many2one('account.account', 'Account', readonly=True),
|
||||
'amount_total': fields.float('Total', readonly=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'),
|
||||
('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')], 'Month', readonly=True),
|
||||
}
|
||||
_order = 'name desc'
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'report_account_sales')
|
||||
cr.execute("""create or replace view report_account_sales as (
|
||||
select
|
||||
min(inv_line.id) as id,
|
||||
to_char(inv.date_invoice, 'YYYY') as name,
|
||||
to_char(inv.date_invoice,'MM') as month,
|
||||
sum(inv_line.price_subtotal) as amount_total,
|
||||
inv.currency_id as currency_id,
|
||||
inv.period_id,
|
||||
inv_line.product_id,
|
||||
sum(inv_line.quantity) as quantity,
|
||||
account.id as account_id
|
||||
from
|
||||
account_invoice_line inv_line
|
||||
inner join account_invoice inv on inv.id = inv_line.invoice_id
|
||||
inner join account_account account on account.id = inv_line.account_id
|
||||
where
|
||||
inv.state in ('open','paid')
|
||||
group by
|
||||
to_char(inv.date_invoice, 'YYYY'),to_char(inv.date_invoice,'MM'),inv.currency_id, inv.period_id, inv_line.product_id, account.id
|
||||
)""")
|
||||
@@ -1,219 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Balance by account type -->
|
||||
|
||||
<record id="view_crm_case_user_graph" model="ir.ui.view">
|
||||
<field name="name">report.account.receivable.graph</field>
|
||||
<field name="model">report.account.receivable</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Accounts by Type" type="bar">
|
||||
<field name="name"/>
|
||||
<field name="balance" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_crm_case_user_tree" model="ir.ui.view">
|
||||
<field name="name">report.account.receivable.tree</field>
|
||||
<field name="model">report.account.receivable</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Accounts by Type">
|
||||
<field name="name"/>
|
||||
<field name="type"/>
|
||||
<field name="balance"/>
|
||||
<field name="debit"/>
|
||||
<field name="credit"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_crm_case_user_form" model="ir.ui.view">
|
||||
<field name="name">report.account.receivable.form</field>
|
||||
<field name="model">report.account.receivable</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Accounts by Type">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="type"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_account_receivable_graph" model="ir.actions.act_window">
|
||||
<field name="name">Balance by Type of Account</field>
|
||||
<field name="res_model">report.account.receivable</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
</record>
|
||||
|
||||
<!-- Report for Aged Receivable -->
|
||||
|
||||
<record id="view_aged_recv_graph" model="ir.ui.view">
|
||||
<field name="name">report.aged.receivable.graph</field>
|
||||
<field name="model">report.aged.receivable</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Aged Receivable" type="bar">
|
||||
<field name="name"/>
|
||||
<field name="balance" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_aged_recv_tree" model="ir.ui.view">
|
||||
<field name="name">report.aged.receivable.tree</field>
|
||||
<field name="model">report.aged.receivable</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Aged Receivable">
|
||||
<field name="name"/>
|
||||
<field name="balance"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_aged_receivable_graph" model="ir.actions.act_window">
|
||||
<field name="name">Aged Receivable</field>
|
||||
<field name="res_model">report.aged.receivable</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,tree</field>
|
||||
</record>
|
||||
|
||||
<!-- Created Invoice for random activities of service dashboard -->
|
||||
|
||||
<record id="board_view_created_invoice" model="ir.ui.view">
|
||||
<field name="name">report.invoice.created.tree</field>
|
||||
<field name="model">report.invoice.created</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="blue:state == 'draft';black:state in ('proforma','proforma2','open');gray:state in('paid','cancel') " string="Invoices">
|
||||
<field name="create_date"/>
|
||||
<field name="name"/>
|
||||
<field name="type"/>
|
||||
<field name="number"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="amount_untaxed" sum="Untaxed Amount"/>
|
||||
<field name="amount_total" sum="Total Amount"/>
|
||||
<field name="currency_id"/>
|
||||
<field name="date_invoice"/>
|
||||
<field name="date_due"/>
|
||||
<field name="residual"/>
|
||||
<field name="state"/>
|
||||
<field name="origin"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_created_invoice_dashboard" model="ir.actions.act_window">
|
||||
<field name="name">Invoices Created Within Past 15 Days</field>
|
||||
<field name="res_model">report.invoice.created</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="board_view_created_invoice"/>
|
||||
</record>
|
||||
|
||||
<record id="view_report_account_sales_tree" model="ir.ui.view">
|
||||
<field name="name">report.account.sales.tree</field>
|
||||
<field name="model">report.account.sales</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Sales by Account">
|
||||
<field name="name"/>
|
||||
<field name="month"/>
|
||||
<field name="product_id"/>
|
||||
<field name="account_id"/>
|
||||
<field name="quantity"/>
|
||||
<field name="amount_total"/>
|
||||
<field name="currency_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_report_account_sales_graph" model="ir.ui.view">
|
||||
<field name="name">report.account.sales.graph</field>
|
||||
<field name="model">report.account.sales</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Sales by Account" type="pie">
|
||||
<field name="account_id"/>
|
||||
<field name="amount_total"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_report_account_sales_search" model="ir.ui.view">
|
||||
<field name="name">report.account.sales.search</field>
|
||||
<field name="model">report.account.sales</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Sales by Account">
|
||||
<field name="name" string="Year"/>
|
||||
<field name="month"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_account_sales_tree_all" model="ir.actions.act_window">
|
||||
<field name="name">Sales by Account</field>
|
||||
<field name="res_model">report.account.sales</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,tree</field>
|
||||
<field name="search_view_id" ref="view_report_account_sales_search"/>
|
||||
</record>
|
||||
|
||||
<record id="view_report_account_type_sales_tree" model="ir.ui.view">
|
||||
<field name="name">report.account_type.sales.tree</field>
|
||||
<field name="model">report.account_type.sales</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Sales by Account Type">
|
||||
<field name="name"/>
|
||||
<field name="month"/>
|
||||
<field name="period_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="user_type"/>
|
||||
<field name="quantity"/>
|
||||
<field name="amount_total"/>
|
||||
<field name="currency_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_report_account_type_sales_form" model="ir.ui.view">
|
||||
<field name="name">report.account_type.sales.form</field>
|
||||
<field name="model">report.account_type.sales</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Sales by Account Type">
|
||||
<field name="name"/>
|
||||
<field name="month"/>
|
||||
<field name="product_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_report_account_type_sales_graph" model="ir.ui.view">
|
||||
<field name="name">report.account_type.sales.graph</field>
|
||||
<field name="model">report.account_type.sales</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Sales by Account" type="pie">
|
||||
<field name="user_type"/>
|
||||
<field name="amount_total"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_report_account_type_sales_search" model="ir.ui.view">
|
||||
<field name="name">report.account_type.sales.search</field>
|
||||
<field name="model">report.account_type.sales</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Sales by Account">
|
||||
<field name="name" string="Year"/>
|
||||
<field name="month"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_account_type_sales_tree_all" model="ir.actions.act_window">
|
||||
<field name="name">Sales by Account Type</field>
|
||||
<field name="res_model">report.account_type.sales</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,tree</field>
|
||||
<field name="search_view_id" ref="view_report_account_type_sales_search"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,80 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import tools
|
||||
from openerp.osv import fields,osv
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
class account_treasury_report(osv.osv):
|
||||
_name = "account.treasury.report"
|
||||
_description = "Treasury Analysis"
|
||||
_auto = False
|
||||
|
||||
def _compute_balances(self, cr, uid, ids, field_names, arg=None, context=None,
|
||||
query='', query_params=()):
|
||||
all_treasury_lines = self.search(cr, uid, [], context=context)
|
||||
all_companies = self.pool.get('res.company').search(cr, uid, [], context=context)
|
||||
current_sum = dict((company, 0.0) for company in all_companies)
|
||||
res = dict((id, dict((fn, 0.0) for fn in field_names)) for id in all_treasury_lines)
|
||||
for record in self.browse(cr, uid, all_treasury_lines, context=context):
|
||||
res[record.id]['starting_balance'] = current_sum[record.company_id.id]
|
||||
current_sum[record.company_id.id] += record.balance
|
||||
res[record.id]['ending_balance'] = current_sum[record.company_id.id]
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscalyear', readonly=True),
|
||||
'period_id': fields.many2one('account.period', 'Period', readonly=True),
|
||||
'debit': fields.float('Debit', readonly=True),
|
||||
'credit': fields.float('Credit', readonly=True),
|
||||
'balance': fields.float('Balance', readonly=True),
|
||||
'date': fields.date('Beginning of Period Date', readonly=True),
|
||||
'starting_balance': fields.function(_compute_balances, digits_compute=dp.get_precision('Account'), string='Starting Balance', multi='balance'),
|
||||
'ending_balance': fields.function(_compute_balances, digits_compute=dp.get_precision('Account'), string='Ending Balance', multi='balance'),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
}
|
||||
|
||||
_order = 'date asc'
|
||||
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'account_treasury_report')
|
||||
cr.execute("""
|
||||
create or replace view account_treasury_report as (
|
||||
select
|
||||
p.id as id,
|
||||
p.fiscalyear_id as fiscalyear_id,
|
||||
p.id as period_id,
|
||||
sum(l.debit) as debit,
|
||||
sum(l.credit) as credit,
|
||||
sum(l.debit-l.credit) as balance,
|
||||
p.date_start as date,
|
||||
am.company_id as company_id
|
||||
from
|
||||
account_move_line l
|
||||
left join account_account a on (l.account_id = a.id)
|
||||
left join account_move am on (am.id=l.move_id)
|
||||
left join account_period p on (am.period_id=p.id)
|
||||
where l.state != 'draft'
|
||||
and a.type = 'liquidity'
|
||||
group by p.id, p.fiscalyear_id, p.date_start, am.company_id
|
||||
)
|
||||
""")
|
||||
@@ -1,72 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_account_treasury_report_tree" model="ir.ui.view">
|
||||
<field name="name">account.treasury.report.tree</field>
|
||||
<field name="model">account.treasury.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Treasury Analysis" create="false">
|
||||
<field name="date" invisible="1"/>
|
||||
<field name="fiscalyear_id"/>
|
||||
<field name="period_id"/>
|
||||
<field name="debit"/>
|
||||
<field name="credit"/>
|
||||
<field name="balance"/>
|
||||
<field name="starting_balance"/>
|
||||
<field name="ending_balance"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_treasury_report_pivot" model="ir.ui.view">
|
||||
<field name="name">account.treasury.report.pivot</field>
|
||||
<field name="model">account.treasury.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Treasury Analysis" disable_linking="True">
|
||||
<field name="period_id"/>
|
||||
<field name="debit" type="measure"/>
|
||||
<field name="credit" type="measure"/>
|
||||
<field name="balance" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_treasury_report_graph" model="ir.ui.view">
|
||||
<field name="name">account.treasury.report.graph</field>
|
||||
<field name="model">account.treasury.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Treasury Analysis">
|
||||
<field name="period_id" type="row"/>
|
||||
<field name="balance" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_treasury_report_search" model="ir.ui.view">
|
||||
<field name="name">account.treasury.report.search</field>
|
||||
<field name="model">account.treasury.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Treasury Analysis">
|
||||
<field name="fiscalyear_id"/>
|
||||
<field name="period_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Month" context="{'group_by':'date:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_account_treasury_report_all" model="ir.actions.act_window">
|
||||
<field name="name">Treasury Analysis</field>
|
||||
<field name="res_model">account.treasury.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
<field name="search_view_id" ref="view_account_treasury_report_search"/>
|
||||
<field name="view_id"></field> <!-- force empty -->
|
||||
<field name="context">{}</field> <!-- force empty -->
|
||||
<field name="help">From this view, have an analysis of your treasury. It sums the balance of every accounting entries made on liquidity accounts per period.</field>
|
||||
</record>
|
||||
<menuitem action="action_account_treasury_report_all" id="menu_action_account_treasury_report_all"
|
||||
parent="account.menu_finance_reporting"
|
||||
groups="group_account_manager"
|
||||
sequence="2"/>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,141 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tools.translate import _
|
||||
|
||||
# Mixin to use with rml_parse, so self.pool will be defined.
|
||||
class common_report_header(object):
|
||||
|
||||
def _sum_debit(self, period_id=False, journal_id=False):
|
||||
if journal_id and isinstance(journal_id, int):
|
||||
journal_id = [journal_id]
|
||||
if period_id and isinstance(period_id, int):
|
||||
period_id = [period_id]
|
||||
if not journal_id:
|
||||
journal_id = self.journal_ids
|
||||
if not period_id:
|
||||
period_id = self.period_ids
|
||||
if not (period_id and journal_id):
|
||||
return 0.0
|
||||
self.cr.execute('SELECT SUM(debit) FROM account_move_line l '
|
||||
'WHERE period_id IN %s AND journal_id IN %s ' + self.query_get_clause + ' ',
|
||||
(tuple(period_id), tuple(journal_id)))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def _sum_credit(self, period_id=False, journal_id=False):
|
||||
if journal_id and isinstance(journal_id, int):
|
||||
journal_id = [journal_id]
|
||||
if period_id and isinstance(period_id, int):
|
||||
period_id = [period_id]
|
||||
if not journal_id:
|
||||
journal_id = self.journal_ids
|
||||
if not period_id:
|
||||
period_id = self.period_ids
|
||||
if not (period_id and journal_id):
|
||||
return 0.0
|
||||
self.cr.execute('SELECT SUM(credit) FROM account_move_line l '
|
||||
'WHERE period_id IN %s AND journal_id IN %s '+ self.query_get_clause+'',
|
||||
(tuple(period_id), tuple(journal_id)))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def _get_start_date(self, data):
|
||||
if data.get('form', False) and data['form'].get('date_from', False):
|
||||
return data['form']['date_from']
|
||||
return ''
|
||||
|
||||
def _get_target_move(self, data):
|
||||
if data.get('form', False) and data['form'].get('target_move', False):
|
||||
if data['form']['target_move'] == 'all':
|
||||
return _('All Entries')
|
||||
return _('All Posted Entries')
|
||||
return ''
|
||||
|
||||
def _get_end_date(self, data):
|
||||
if data.get('form', False) and data['form'].get('date_to', False):
|
||||
return data['form']['date_to']
|
||||
return ''
|
||||
|
||||
def get_start_period(self, data):
|
||||
if data.get('form', False) and data['form'].get('period_from', False):
|
||||
return self.pool.get('account.period').browse(self.cr,self.uid,data['form']['period_from']).name
|
||||
return ''
|
||||
|
||||
def get_end_period(self, data):
|
||||
if data.get('form', False) and data['form'].get('period_to', False):
|
||||
return self.pool.get('account.period').browse(self.cr, self.uid, data['form']['period_to']).name
|
||||
return ''
|
||||
|
||||
def _get_account(self, data):
|
||||
if data.get('form', False) and data['form'].get('chart_account_id', False):
|
||||
return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['chart_account_id']).name
|
||||
return ''
|
||||
|
||||
def _get_sortby(self, data):
|
||||
raise (_('Error!'), _('Not implemented.'))
|
||||
|
||||
def _get_filter(self, data):
|
||||
if data.get('form', False) and data['form'].get('filter', False):
|
||||
if data['form']['filter'] == 'filter_date':
|
||||
return self._translate('Date')
|
||||
elif data['form']['filter'] == 'filter_period':
|
||||
return self._translate('Periods')
|
||||
return self._translate('No Filters')
|
||||
|
||||
def _sum_debit_period(self, period_id, journal_id=None):
|
||||
journals = journal_id or self.journal_ids
|
||||
if not journals:
|
||||
return 0.0
|
||||
self.cr.execute('SELECT SUM(debit) FROM account_move_line l '
|
||||
'WHERE period_id=%s AND journal_id IN %s '+ self.query_get_clause +'',
|
||||
(period_id, tuple(journals)))
|
||||
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def _sum_credit_period(self, period_id, journal_id=None):
|
||||
journals = journal_id or self.journal_ids
|
||||
if not journals:
|
||||
return 0.0
|
||||
self.cr.execute('SELECT SUM(credit) FROM account_move_line l '
|
||||
'WHERE period_id=%s AND journal_id IN %s ' + self.query_get_clause +' ',
|
||||
(period_id, tuple(journals)))
|
||||
return self.cr.fetchone()[0] or 0.0
|
||||
|
||||
def _get_fiscalyear(self, data):
|
||||
if data.get('form', False) and data['form'].get('fiscalyear_id', False):
|
||||
return self.pool.get('account.fiscalyear').browse(self.cr, self.uid, data['form']['fiscalyear_id']).name
|
||||
return ''
|
||||
|
||||
def _get_company(self, data):
|
||||
if data.get('form', False) and data['form'].get('chart_account_id', False):
|
||||
return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['chart_account_id']).company_id.name
|
||||
return ''
|
||||
|
||||
def _get_journal(self, data):
|
||||
codes = []
|
||||
if data.get('form', False) and data['form'].get('journal_ids', False):
|
||||
self.cr.execute('select code from account_journal where id IN %s',(tuple(data['form']['journal_ids']),))
|
||||
codes = [x for x, in self.cr.fetchall()]
|
||||
return codes
|
||||
|
||||
def _get_currency(self, data):
|
||||
if data.get('form', False) and data['form'].get('chart_account_id', False):
|
||||
return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['chart_account_id']).company_id.currency_id.symbol
|
||||
return ''
|
||||
@@ -1,260 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from functools import partial
|
||||
from openerp.osv import osv
|
||||
from openerp.report import report_sxw
|
||||
from common_report_header import common_report_header
|
||||
|
||||
|
||||
class tax_report(report_sxw.rml_parse, common_report_header):
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
new_ids = ids
|
||||
res = {}
|
||||
if not data:
|
||||
company_id = self.pool['res.users'].browse(self.cr, self.uid, self.uid).company_id.id
|
||||
data = {
|
||||
'form': {
|
||||
'based_on': 'invoices',
|
||||
'company_id': company_id,
|
||||
'display_detail': False,
|
||||
}
|
||||
}
|
||||
self.period_ids = []
|
||||
period_obj = self.pool.get('account.period')
|
||||
self.display_detail = data['form']['display_detail']
|
||||
res['periods'] = ''
|
||||
res['fiscalyear'] = data['form'].get('fiscalyear_id', False)
|
||||
|
||||
if data['form'].get('period_from', False) and data['form'].get('period_to', False):
|
||||
self.period_ids = period_obj.build_ctx_periods(self.cr, self.uid, data['form']['period_from'], data['form']['period_to'])
|
||||
periods_l = period_obj.read(self.cr, self.uid, self.period_ids, ['name'])
|
||||
for period in periods_l:
|
||||
if res['periods'] == '':
|
||||
res['periods'] = period['name']
|
||||
else:
|
||||
res['periods'] += ", "+ period['name']
|
||||
return super(tax_report, self).set_context(objects, data, new_ids, report_type=report_type)
|
||||
|
||||
def __init__(self, cr, uid, name, context=None):
|
||||
super(tax_report, self).__init__(cr, uid, name, context=context)
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'get_codes': self._get_codes,
|
||||
'get_general': self._get_general,
|
||||
'get_currency': self._get_currency,
|
||||
'get_lines': partial(self._get_lines, context=context),
|
||||
'get_fiscalyear': self._get_fiscalyear,
|
||||
'get_account': self._get_account,
|
||||
'get_start_period': self.get_start_period,
|
||||
'get_end_period': self.get_end_period,
|
||||
'get_basedon': self._get_basedon,
|
||||
})
|
||||
|
||||
def _get_basedon(self, form):
|
||||
return form['form']['based_on']
|
||||
|
||||
def _get_lines(self, based_on, company_id=False, parent=False, level=0, context=None):
|
||||
period_list = self.period_ids
|
||||
res = self._get_codes(based_on, company_id, parent, level, period_list, context=context)
|
||||
if period_list:
|
||||
res = self._add_codes(based_on, res, period_list, context=context)
|
||||
else:
|
||||
self.cr.execute ("select id from account_fiscalyear")
|
||||
fy = self.cr.fetchall()
|
||||
self.cr.execute ("select id from account_period where fiscalyear_id = %s",(fy[0][0],))
|
||||
periods = self.cr.fetchall()
|
||||
for p in periods:
|
||||
period_list.append(p[0])
|
||||
res = self._add_codes(based_on, res, period_list, context=context)
|
||||
|
||||
i = 0
|
||||
top_result = []
|
||||
while i < len(res):
|
||||
res_dict = { 'code': res[i][1]['code'],
|
||||
'name': res[i][1]['name'],
|
||||
'debit': 0,
|
||||
'credit': 0,
|
||||
'tax_amount': res[i][1]['sum_period'],
|
||||
'type': 1,
|
||||
'level': res[i][0],
|
||||
'pos': 0
|
||||
}
|
||||
|
||||
top_result.append(res_dict)
|
||||
res_general = self._get_general(res[i][1]['id'], period_list, company_id, based_on, context=context)
|
||||
ind_general = 0
|
||||
while ind_general < len(res_general):
|
||||
res_general[ind_general]['type'] = 2
|
||||
res_general[ind_general]['pos'] = 0
|
||||
res_general[ind_general]['level'] = res_dict['level']
|
||||
top_result.append(res_general[ind_general])
|
||||
ind_general+=1
|
||||
i+=1
|
||||
return top_result
|
||||
|
||||
def _get_general(self, tax_code_id, period_list, company_id, based_on, context=None):
|
||||
if not self.display_detail:
|
||||
return []
|
||||
res = []
|
||||
obj_account = self.pool.get('account.account')
|
||||
periods_ids = tuple(period_list)
|
||||
if based_on == 'payments':
|
||||
self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \
|
||||
SUM(line.debit) AS debit, \
|
||||
SUM(line.credit) AS credit, \
|
||||
COUNT(*) AS count, \
|
||||
account.id AS account_id, \
|
||||
account.name AS name, \
|
||||
account.code AS code \
|
||||
FROM account_move_line AS line, \
|
||||
account_account AS account, \
|
||||
account_move AS move \
|
||||
LEFT JOIN account_invoice invoice ON \
|
||||
(invoice.move_id = move.id) \
|
||||
WHERE line.state<>%s \
|
||||
AND line.tax_code_id = %s \
|
||||
AND line.account_id = account.id \
|
||||
AND account.company_id = %s \
|
||||
AND move.id = line.move_id \
|
||||
AND line.period_id IN %s \
|
||||
AND ((invoice.state = %s) \
|
||||
OR (invoice.id IS NULL)) \
|
||||
GROUP BY account.id,account.name,account.code', ('draft', tax_code_id,
|
||||
company_id, periods_ids, 'paid',))
|
||||
|
||||
else:
|
||||
self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \
|
||||
SUM(line.debit) AS debit, \
|
||||
SUM(line.credit) AS credit, \
|
||||
COUNT(*) AS count, \
|
||||
account.id AS account_id, \
|
||||
account.name AS name, \
|
||||
account.code AS code \
|
||||
FROM account_move_line AS line, \
|
||||
account_account AS account \
|
||||
WHERE line.state <> %s \
|
||||
AND line.tax_code_id = %s \
|
||||
AND line.account_id = account.id \
|
||||
AND account.company_id = %s \
|
||||
AND line.period_id IN %s\
|
||||
AND account.active \
|
||||
GROUP BY account.id,account.name,account.code', ('draft', tax_code_id,
|
||||
company_id, periods_ids,))
|
||||
res = self.cr.dictfetchall()
|
||||
|
||||
i = 0
|
||||
while i<len(res):
|
||||
res[i]['account'] = obj_account.browse(self.cr, self.uid, res[i]['account_id'], context=context)
|
||||
i+=1
|
||||
return res
|
||||
|
||||
def _get_codes(self, based_on, company_id, parent=False, level=0, period_list=None, context=None):
|
||||
obj_tc = self.pool.get('account.tax.code')
|
||||
ids = obj_tc.search(self.cr, self.uid, [('parent_id','=',parent),('company_id','=',company_id)], context=context)
|
||||
|
||||
res = []
|
||||
for code in obj_tc.browse(self.cr, self.uid, ids, {'based_on': based_on}):
|
||||
res.append(('.'*2*level, code))
|
||||
|
||||
res += self._get_codes(based_on, company_id, code.id, level+1, context=context)
|
||||
return res
|
||||
|
||||
def _add_codes(self, based_on, account_list=None, period_list=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
if account_list is None:
|
||||
account_list = []
|
||||
if period_list is None:
|
||||
period_list = []
|
||||
res = []
|
||||
obj_tc = self.pool.get('account.tax.code')
|
||||
for account in account_list:
|
||||
ids = obj_tc.search(self.cr, self.uid, [('id','=', account[1].id)], context=context)
|
||||
code = {}
|
||||
for period_ind in period_list:
|
||||
context2 = dict(context, period_id=period_ind, based_on=based_on)
|
||||
record = obj_tc.browse(self.cr, self.uid, ids, context=context2)[0]
|
||||
if not code:
|
||||
code = {
|
||||
'id': record.id,
|
||||
'name': record.name,
|
||||
'code': record.code,
|
||||
'sequence': record.sequence,
|
||||
'sum_period': 0,
|
||||
}
|
||||
code['sum_period'] += record.sum_period
|
||||
|
||||
res.append((account[0], code))
|
||||
return res
|
||||
|
||||
def _get_currency(self, form, context=None):
|
||||
return self.pool.get('res.company').browse(self.cr, self.uid, form['company_id'], context=context).currency_id.name
|
||||
|
||||
def sort_result(self, accounts, context=None):
|
||||
# On boucle sur notre rapport
|
||||
result_accounts = []
|
||||
ind=0
|
||||
old_level=0
|
||||
while ind<len(accounts):
|
||||
#
|
||||
account_elem = accounts[ind]
|
||||
#
|
||||
|
||||
#
|
||||
# we will now check if the level is lower than the previous level, in this case we will make a subtotal
|
||||
if (account_elem['level'] < old_level):
|
||||
bcl_current_level = old_level
|
||||
bcl_rup_ind = ind - 1
|
||||
|
||||
while (bcl_current_level >= int(accounts[bcl_rup_ind]['level']) and bcl_rup_ind >= 0 ):
|
||||
res_tot = { 'code': accounts[bcl_rup_ind]['code'],
|
||||
'name': '',
|
||||
'debit': 0,
|
||||
'credit': 0,
|
||||
'tax_amount': accounts[bcl_rup_ind]['tax_amount'],
|
||||
'type': accounts[bcl_rup_ind]['type'],
|
||||
'level': 0,
|
||||
'pos': 0
|
||||
}
|
||||
|
||||
if res_tot['type'] == 1:
|
||||
# on change le type pour afficher le total
|
||||
res_tot['type'] = 2
|
||||
result_accounts.append(res_tot)
|
||||
bcl_current_level = accounts[bcl_rup_ind]['level']
|
||||
bcl_rup_ind -= 1
|
||||
|
||||
old_level = account_elem['level']
|
||||
result_accounts.append(account_elem)
|
||||
ind+=1
|
||||
|
||||
return result_accounts
|
||||
|
||||
|
||||
class report_vat(osv.AbstractModel):
|
||||
_name = 'report.account.report_vat'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'account.report_vat'
|
||||
_wrapped_report_class = tax_report
|
||||
@@ -1,23 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import datetime
|
||||
@@ -26,380 +7,276 @@ from dateutil.relativedelta import relativedelta
|
||||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import fields, osv
|
||||
from openerp import api, fields, models, _
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
class account_config_settings(osv.osv_memory):
|
||||
|
||||
class AccountConfigSettings(models.TransientModel):
|
||||
_name = 'account.config.settings'
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
_columns = {
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'has_default_company': fields.boolean('Has default company', readonly=True),
|
||||
'expects_chart_of_accounts': fields.related('company_id', 'expects_chart_of_accounts', type='boolean',
|
||||
string='This company has its own chart of accounts',
|
||||
help="""Check this box if this company is a legal entity."""),
|
||||
'currency_id': fields.related('company_id', 'currency_id', type='many2one', relation='res.currency', required=True,
|
||||
string='Default company currency', help="Main currency of the company."),
|
||||
'paypal_account': fields.related('company_id', 'paypal_account', type='char', size=128,
|
||||
string='Paypal account', help="Paypal account (email) for receiving online payments (credit card, etc.) If you set a paypal account, the customer will be able to pay your invoices or quotations with a button \"Pay with Paypal\" in automated emails or through the Odoo portal."),
|
||||
'company_footer': fields.related('company_id', 'rml_footer', type='text', readonly=True,
|
||||
string='Bank accounts footer preview', help="Bank accounts as printed in the footer of each printed document"),
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True,
|
||||
default=lambda self: self.env.user.company_id)
|
||||
has_default_company = fields.Boolean(readonly=True,
|
||||
default=lambda self: self._default_has_default_company())
|
||||
expects_chart_of_accounts = fields.Boolean(related='company_id.expects_chart_of_accounts',
|
||||
string='This company has its own chart of accounts',
|
||||
help='Check this box if this company is a legal entity.')
|
||||
currency_id = fields.Many2one('res.currency', related='company_id.currency_id', required=True,
|
||||
string='Default company currency', help="Main currency of the company.")
|
||||
paypal_account = fields.Char(related='company_id.paypal_account', size=128, string='Paypal account',
|
||||
help="""Paypal account (email) for receiving online payments (credit card, etc.)
|
||||
If you set a paypal account, the customer will be able to pay your invoices or quotations
|
||||
with a button \"Pay with Paypal\" in automated emails or through the Odoo portal.""")
|
||||
company_footer = fields.Text(related='company_id.rml_footer', string='Bank accounts footer preview',
|
||||
readonly=True, help="Bank accounts as printed in the footer of each printed document")
|
||||
|
||||
'has_chart_of_accounts': fields.boolean('Company has a chart of accounts'),
|
||||
'chart_template_id': fields.many2one('account.chart.template', 'Template', domain="[('visible','=', True)]"),
|
||||
'code_digits': fields.integer('# of Digits', help="No. of digits to use for account code"),
|
||||
'tax_calculation_rounding_method': fields.related('company_id',
|
||||
'tax_calculation_rounding_method', type='selection', selection=[
|
||||
('round_per_line', 'Round calculation of taxes per line'),
|
||||
('round_globally', 'Round globally calculation of taxes '),
|
||||
], string='Tax calculation rounding method',
|
||||
help="If you select 'Round per line' : for each tax, the tax amount will first be computed and rounded for each PO/SO/invoice line and then these rounded amounts will be summed, leading to the total amount for that tax. If you select 'Round globally': for each tax, the tax amount will be computed for each PO/SO/invoice line, then these amounts will be summed and eventually this total tax amount will be rounded. If you sell with tax included, you should choose 'Round per line' because you certainly want the sum of your tax-included line subtotals to be equal to the total amount with taxes."),
|
||||
'sale_tax': fields.many2one("account.tax.template", "Default sale tax"),
|
||||
'purchase_tax': fields.many2one("account.tax.template", "Default purchase tax"),
|
||||
'sale_tax_rate': fields.float('Sales tax (%)'),
|
||||
'purchase_tax_rate': fields.float('Purchase tax (%)'),
|
||||
'complete_tax_set': fields.boolean('Complete set of taxes', help='This boolean helps you to choose if you want to propose to the user to encode the sales and purchase rates or use the usual m2o fields. This last choice assumes that the set of tax defined for the chosen template is complete'),
|
||||
has_chart_of_accounts = fields.Boolean(string='Company has a chart of accounts')
|
||||
chart_template_id = fields.Many2one('account.chart.template', string='Template',
|
||||
domain="[('visible','=', True)]")
|
||||
use_anglo_saxon = fields.Boolean(string='Use Anglo-Saxon Accounting', related='company_id.anglo_saxon_accounting')
|
||||
code_digits = fields.Integer(string='# of Digits', related='company_id.accounts_code_digits', help="No. of digits to use for account code")
|
||||
tax_calculation_rounding_method = fields.Selection(
|
||||
[
|
||||
('round_per_line', 'Round calculation of taxes per line'),
|
||||
('round_globally', 'Round globally calculation of taxes '),
|
||||
], related='company_id.tax_calculation_rounding_method', string='Tax calculation rounding method',
|
||||
help="""If you select 'Round per line' : for each tax, the tax amount will first be
|
||||
computed and rounded for each PO/SO/invoice line and then these rounded amounts will be summed,
|
||||
leading to the total amount for that tax. If you select 'Round globally': for each tax,
|
||||
the tax amount will be computed for each PO/SO/invoice line, then these amounts will be
|
||||
summed and eventually this total tax amount will be rounded. If you sell with tax included,
|
||||
you should choose 'Round per line' because you certainly want the sum of your tax-included line
|
||||
subtotals to be equal to the total amount with taxes.""")
|
||||
sale_tax = fields.Many2one('account.tax.template', string='Default sale tax')
|
||||
purchase_tax = fields.Many2one('account.tax.template', string='Default purchase tax')
|
||||
sale_tax_rate = fields.Float(string='Sales tax (%)')
|
||||
purchase_tax_rate = fields.Float(string='Purchase tax (%)')
|
||||
bank_account_code_char = fields.Char(string='Bank Accounts Code', related='company_id.bank_account_code_char', help='Define the code for the bank account')
|
||||
transfer_account_id = fields.Many2one('account.account',
|
||||
related='company_id.transfer_account_id',
|
||||
domain=lambda self: [('reconcile', '=', True), ('user_type.id', '=', self.env.ref('account.data_account_type_current_assets').id)],
|
||||
help="Intermediary account used when moving money from a liquidity account to another")
|
||||
complete_tax_set = fields.Boolean(string='Complete set of taxes',
|
||||
help='''This boolean helps you to choose if you want to propose to the user to encode
|
||||
the sales and purchase rates or use the usual m2o fields. This last choice assumes that
|
||||
the set of tax defined for the chosen template is complete''')
|
||||
|
||||
'has_fiscal_year': fields.boolean('Company has a fiscal year'),
|
||||
'date_start': fields.date('Start date', required=True),
|
||||
'date_stop': fields.date('End date', required=True),
|
||||
'period': fields.selection([('month', 'Monthly'), ('3months','3 Monthly')], 'Periods', required=True),
|
||||
fiscalyear_last_day = fields.Integer(related='company_id.fiscalyear_last_day', default=31)
|
||||
fiscalyear_last_month = fields.Selection([(1, 'January'), (2, 'February'), (3, 'March'), (4, 'April'), (5, 'May'), (6, 'June'), (7, 'July'), (8, 'August'), (9, 'September'), (10, 'October'), (11, 'November'), (12, 'December')], related='company_id.fiscalyear_last_month', default=12)
|
||||
period_lock_date = fields.Date(related='company_id.period_lock_date', help="Only users with the 'Adviser' role can edit accounts prior to and inclusive of this date")
|
||||
fiscalyear_lock_date = fields.Date(string="Fiscal Year lock date", related='company_id.fiscalyear_lock_date', help="No users, including Advisers, can edit accounts prior to and inclusive of this date")
|
||||
sale_journal_id = fields.Many2one('account.journal', string='Sale journal')
|
||||
sale_sequence_prefix = fields.Char(related='sale_journal_id.sequence_id.prefix', string='Invoice sequence')
|
||||
sale_sequence_next = fields.Integer(related='sale_journal_id.sequence_id.number_next',
|
||||
string='Next invoice number')
|
||||
purchase_journal_id = fields.Many2one('account.journal', string='Purchase journal')
|
||||
purchase_sequence_prefix = fields.Char(related='purchase_journal_id.sequence_id.prefix',
|
||||
string='Supplier bill sequence')
|
||||
purchase_sequence_next = fields.Integer(related='purchase_journal_id.sequence_id.number_next',
|
||||
string='Next supplier bill number')
|
||||
|
||||
'sale_journal_id': fields.many2one('account.journal', 'Sale journal'),
|
||||
'sale_sequence_prefix': fields.related('sale_journal_id', 'sequence_id', 'prefix', type='char', string='Invoice sequence'),
|
||||
'sale_sequence_next': fields.related('sale_journal_id', 'sequence_id', 'number_next', type='integer', string='Next invoice number'),
|
||||
'sale_refund_journal_id': fields.many2one('account.journal', 'Sale refund journal'),
|
||||
'sale_refund_sequence_prefix': fields.related('sale_refund_journal_id', 'sequence_id', 'prefix', type='char', string='Credit note sequence'),
|
||||
'sale_refund_sequence_next': fields.related('sale_refund_journal_id', 'sequence_id', 'number_next', type='integer', string='Next credit note number'),
|
||||
'purchase_journal_id': fields.many2one('account.journal', 'Purchase journal'),
|
||||
'purchase_sequence_prefix': fields.related('purchase_journal_id', 'sequence_id', 'prefix', type='char', string='Supplier invoice sequence'),
|
||||
'purchase_sequence_next': fields.related('purchase_journal_id', 'sequence_id', 'number_next', type='integer', string='Next supplier invoice number'),
|
||||
'purchase_refund_journal_id': fields.many2one('account.journal', 'Purchase refund journal'),
|
||||
'purchase_refund_sequence_prefix': fields.related('purchase_refund_journal_id', 'sequence_id', 'prefix', type='char', string='Supplier credit note sequence'),
|
||||
'purchase_refund_sequence_next': fields.related('purchase_refund_journal_id', 'sequence_id', 'number_next', type='integer', string='Next supplier credit note number'),
|
||||
module_account_check_writing = fields.Boolean(string='Pay your suppliers by check',
|
||||
help='This allows you to check writing and printing.\n'
|
||||
'-This installs the module account_check_writing.')
|
||||
module_account_accountant = fields.Boolean(string='Full accounting features: journals, legal statements, chart of accounts, etc.',
|
||||
help="""If you do not check this box, you will be able to do invoicing & payments,
|
||||
but not accounting (Journal Items, Chart of Accounts, ...)""")
|
||||
module_account_asset = fields.Boolean(string='Assets management',
|
||||
help='This allows you to manage the assets owned by a company or a person.\n'
|
||||
'It keeps track of the depreciation occurred on those assets, and creates account move for those depreciation lines.\n'
|
||||
'-This installs the module account_asset. If you do not check this box, you will be able to do invoicing & payments, '
|
||||
'but not accounting (Journal Items, Chart of Accounts, ...)')
|
||||
module_account_budget = fields.Boolean(string='Budget management',
|
||||
help='This allows accountants to manage analytic and crossovered budgets. '
|
||||
'Once the master budgets and the budgets are defined, '
|
||||
'the project managers can set the planned amount on each analytic account.\n'
|
||||
'-This installs the module account_budget.')
|
||||
module_account_voucher = fields.Boolean(string='Manage customer payments',
|
||||
help='This includes all the basic requirements of voucher entries for bank, cash, sales, purchase, expense, contra, etc.\n'
|
||||
'-This installs the module account_voucher.')
|
||||
module_account_followup = fields.Boolean(string='Manage customer payment follow-ups',
|
||||
help='This allows to automate letters for unpaid invoices, with multi-level recalls.\n'
|
||||
'-This installs the module account_followup.')
|
||||
module_product_email_template = fields.Boolean(string='Send products tools and information at the invoice confirmation',
|
||||
help='With this module, link your products to a template to send complete information and tools to your customer.\n'
|
||||
'For instance when invoicing a training, the training agenda and materials will automatically be send to your customers.')
|
||||
module_account_bank_statement_import_ofx = fields.Boolean(string='Import of Bank Statements in .OFX Format',
|
||||
help='Get your bank statements from you bank and import them in Odoo in .OFX format.\n'
|
||||
'-that installs the module account_bank_statement_import.')
|
||||
module_account_bank_statement_import_qif = fields.Boolean(string='Import of Bank Statements in .QIF Format.',
|
||||
help='Get your bank statements from you bank and import them in Odoo in .QIF format.\n'
|
||||
'-that installs the module account_bank_statement_import_qif.')
|
||||
group_proforma_invoices = fields.Boolean(string='Allow pro-forma invoices',
|
||||
implied_group='account.group_proforma_invoices',
|
||||
help="Allows you to put invoices in pro-forma state.")
|
||||
default_sale_tax = fields.Many2one('account.tax', help="This sale tax will be assigned by default on new products.")
|
||||
default_purchase_tax = fields.Many2one('account.tax', help="This purchase tax will be assigned by default on new products.")
|
||||
group_multi_currency = fields.Boolean(string='Allow multi currencies',
|
||||
implied_group='base.group_multi_currency',
|
||||
help="Allows you multi currency environment")
|
||||
group_analytic_accounting = fields.Boolean(string='Analytic accounting',
|
||||
implied_group='analytic.group_analytic_accounting',
|
||||
help="Allows you to use the analytic accounting.")
|
||||
group_check_supplier_invoice_total = fields.Boolean(string='Check the total of supplier bills',
|
||||
implied_group="account.group_supplier_inv_check_total")
|
||||
currency_exchange_journal_id = fields.Many2one('account.journal',
|
||||
related='company_id.currency_exchange_journal_id',
|
||||
string="Rate Difference Journal",)
|
||||
income_currency_exchange_account_id = fields.Many2one('account.account',
|
||||
related='company_id.income_currency_exchange_account_id',
|
||||
string="Gain Exchange Rate Account",
|
||||
domain=lambda self: [('internal_type', '=', 'other'), ('company_id', '=', self.company_id.id), ('deprecated', '=', False)])
|
||||
expense_currency_exchange_account_id = fields.Many2one('account.account',
|
||||
related='company_id.expense_currency_exchange_account_id',
|
||||
string="Loss Exchange Rate Account",
|
||||
domain=lambda self: [('internal_type', '=', 'other'), ('company_id', '=', self.company_id.id), ('deprecated', '=', False)])
|
||||
|
||||
'module_account_check_writing': fields.boolean('Pay your suppliers by check',
|
||||
help='This allows you to check writing and printing.\n'
|
||||
'-This installs the module account_check_writing.'),
|
||||
'module_account_accountant': fields.boolean('Full accounting features: journals, legal statements, chart of accounts, etc.',
|
||||
help="""If you do not check this box, you will be able to do invoicing & payments, but not accounting (Journal Items, Chart of Accounts, ...)"""),
|
||||
'module_account_asset': fields.boolean('Assets management',
|
||||
help='This allows you to manage the assets owned by a company or a person.\n'
|
||||
'It keeps track of the depreciation occurred on those assets, and creates account move for those depreciation lines.\n'
|
||||
'-This installs the module account_asset. If you do not check this box, you will be able to do invoicing & payments, '
|
||||
'but not accounting (Journal Items, Chart of Accounts, ...)'),
|
||||
'module_account_budget': fields.boolean('Budget management',
|
||||
help='This allows accountants to manage analytic and crossovered budgets. '
|
||||
'Once the master budgets and the budgets are defined, '
|
||||
'the project managers can set the planned amount on each analytic account.\n'
|
||||
'-This installs the module account_budget.'),
|
||||
'module_account_payment': fields.boolean('Manage payment orders',
|
||||
help='This allows you to create and manage your payment orders, with purposes to \n'
|
||||
'* serve as base for an easy plug-in of various automated payment mechanisms, and \n'
|
||||
'* provide a more efficient way to manage invoice payments.\n'
|
||||
'-This installs the module account_payment.' ),
|
||||
'module_account_voucher': fields.boolean('Manage customer payments',
|
||||
help='This includes all the basic requirements of voucher entries for bank, cash, sales, purchase, expense, contra, etc.\n'
|
||||
'-This installs the module account_voucher.'),
|
||||
'module_account_followup': fields.boolean('Manage customer payment follow-ups',
|
||||
help='This allows to automate letters for unpaid invoices, with multi-level recalls.\n'
|
||||
'-This installs the module account_followup.'),
|
||||
'module_product_email_template': fields.boolean('Send products tools and information at the invoice confirmation',
|
||||
help='With this module, link your products to a template to send complete information and tools to your customer.\n'
|
||||
'For instance when invoicing a training, the training agenda and materials will automatically be send to your customers.'),
|
||||
'module_account_bank_statement_import_ofx': fields.boolean('Import of Bank Statements in .OFX Format',
|
||||
help='Get your bank statements from you bank and import them in Odoo in .OFX format.\n'
|
||||
'-that installs the module account_bank_statement_import.'),
|
||||
'module_account_bank_statement_import_qif': fields.boolean('Import of Bank Statements in .QIF Format.',
|
||||
help='Get your bank statements from you bank and import them in Odoo in .QIF format.\n'
|
||||
'-that installs the module account_bank_statement_import_qif.'),
|
||||
'group_proforma_invoices': fields.boolean('Allow pro-forma invoices',
|
||||
implied_group='account.group_proforma_invoices',
|
||||
help="Allows you to put invoices in pro-forma state."),
|
||||
'default_sale_tax': fields.many2one('account.tax', 'Default sale tax',
|
||||
help="This sale tax will be assigned by default on new products."),
|
||||
'default_purchase_tax': fields.many2one('account.tax', 'Default purchase tax',
|
||||
help="This purchase tax will be assigned by default on new products."),
|
||||
'decimal_precision': fields.integer('Decimal precision on journal entries',
|
||||
help="""As an example, a decimal precision of 2 will allow journal entries like: 9.99 EUR, whereas a decimal precision of 4 will allow journal entries like: 0.0231 EUR."""),
|
||||
'group_multi_currency': fields.boolean('Allow multi currencies',
|
||||
implied_group='base.group_multi_currency',
|
||||
help="Allows you multi currency environment"),
|
||||
'group_analytic_accounting': fields.boolean('Analytic accounting',
|
||||
implied_group='analytic.group_analytic_accounting',
|
||||
help="Allows you to use the analytic accounting."),
|
||||
'group_check_supplier_invoice_total': fields.boolean('Check the total of supplier invoices',
|
||||
implied_group="account.group_supplier_inv_check_total"),
|
||||
'income_currency_exchange_account_id': fields.related(
|
||||
'company_id', 'income_currency_exchange_account_id',
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Gain Exchange Rate Account",
|
||||
domain="[('type', '=', 'other'), ('company_id', '=', company_id)]]"),
|
||||
'expense_currency_exchange_account_id': fields.related(
|
||||
'company_id', 'expense_currency_exchange_account_id',
|
||||
type="many2one",
|
||||
relation='account.account',
|
||||
string="Loss Exchange Rate Account",
|
||||
domain="[('type', '=', 'other'), ('company_id', '=', company_id)]]"),
|
||||
}
|
||||
|
||||
def _check_account_gain(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.income_currency_exchange_account_id.company_id and obj.company_id != obj.income_currency_exchange_account_id.company_id:
|
||||
@api.multi
|
||||
@api.constrains('income_currency_exchange_account_id', 'expense_currency_exchange_account_id')
|
||||
def _check_account_gain_loss(self):
|
||||
for element in self:
|
||||
if element.income_currency_exchange_account_id.company_id and element.company_id != element.income_currency_exchange_account_id.company_id:
|
||||
return False
|
||||
if element.expense_currency_exchange_account_id.company_id and element.company_id != element.expense_currency_exchange_account_id.company_id:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _check_account_loss(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.expense_currency_exchange_account_id.company_id and obj.company_id != obj.expense_currency_exchange_account_id.company_id:
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_account_gain, 'The company of the gain exchange rate account must be the same than the company selected.', ['income_currency_exchange_account_id']),
|
||||
(_check_account_loss, 'The company of the loss exchange rate account must be the same than the company selected.', ['expense_currency_exchange_account_id']),
|
||||
]
|
||||
|
||||
def _default_company(self, cr, uid, context=None):
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
return user.company_id.id
|
||||
|
||||
def _default_has_default_company(self, cr, uid, context=None):
|
||||
count = self.pool.get('res.company').search_count(cr, uid, [], context=context)
|
||||
@api.model
|
||||
def _default_has_default_company(self):
|
||||
count = self.env['res.company'].search_count([])
|
||||
return bool(count == 1)
|
||||
|
||||
def _get_default_fiscalyear_data(self, cr, uid, company_id, context=None):
|
||||
"""Compute default period, starting and ending date for fiscalyear
|
||||
- if in a fiscal year, use its period, starting and ending date
|
||||
- if past fiscal year, use its period, and new dates [ending date of the latest +1 day ; ending date of the latest +1 year]
|
||||
- if no fiscal year, use monthly, 1st jan, 31th dec of this year
|
||||
:return: (date_start, date_stop, period) at format DEFAULT_SERVER_DATETIME_FORMAT
|
||||
"""
|
||||
fiscalyear_ids = self.pool.get('account.fiscalyear').search(cr, uid,
|
||||
[('date_start', '<=', time.strftime(DF)), ('date_stop', '>=', time.strftime(DF)),
|
||||
('company_id', '=', company_id)])
|
||||
if fiscalyear_ids:
|
||||
# is in a current fiscal year, use this one
|
||||
fiscalyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_ids[0], context=context)
|
||||
if len(fiscalyear.period_ids) == 5: # 4 periods of 3 months + opening period
|
||||
period = '3months'
|
||||
else:
|
||||
period = 'month'
|
||||
return (fiscalyear.date_start, fiscalyear.date_stop, period)
|
||||
else:
|
||||
past_fiscalyear_ids = self.pool.get('account.fiscalyear').search(cr, uid,
|
||||
[('date_stop', '<=', time.strftime(DF)), ('company_id', '=', company_id)])
|
||||
if past_fiscalyear_ids:
|
||||
# use the latest fiscal, sorted by (start_date, id)
|
||||
latest_year = self.pool.get('account.fiscalyear').browse(cr, uid, past_fiscalyear_ids[-1], context=context)
|
||||
latest_stop = datetime.datetime.strptime(latest_year.date_stop, DF)
|
||||
if len(latest_year.period_ids) == 5:
|
||||
period = '3months'
|
||||
else:
|
||||
period = 'month'
|
||||
return ((latest_stop+datetime.timedelta(days=1)).strftime(DF), latest_stop.replace(year=latest_stop.year+1).strftime(DF), period)
|
||||
else:
|
||||
return (time.strftime('%Y-01-01'), time.strftime('%Y-12-31'), 'month')
|
||||
|
||||
_defaults = {
|
||||
'company_id': _default_company,
|
||||
'has_default_company': _default_has_default_company,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
id = super(account_config_settings, self).create(cr, uid, values, context)
|
||||
# Hack: to avoid some nasty bug, related fields are not written upon record creation.
|
||||
# Hence we write on those fields here.
|
||||
vals = {}
|
||||
for fname, field in self._columns.iteritems():
|
||||
if isinstance(field, fields.related) and fname in values:
|
||||
vals[fname] = values[fname]
|
||||
self.write(cr, uid, [id], vals, context)
|
||||
return id
|
||||
|
||||
def onchange_company_id(self, cr, uid, ids, company_id, context=None):
|
||||
@api.onchange('company_id')
|
||||
def onchange_company_id(self):
|
||||
# update related fields
|
||||
values = {}
|
||||
values['currency_id'] = False
|
||||
if company_id:
|
||||
company = self.pool.get('res.company').browse(cr, uid, company_id, context=context)
|
||||
has_chart_of_accounts = company_id not in self.pool.get('account.installer').get_unconfigured_cmp(cr, uid)
|
||||
fiscalyear_count = self.pool.get('account.fiscalyear').search_count(cr, uid,
|
||||
[('date_start', '<=', time.strftime('%Y-%m-%d')), ('date_stop', '>=', time.strftime('%Y-%m-%d')),
|
||||
('company_id', '=', company_id)])
|
||||
date_start, date_stop, period = self._get_default_fiscalyear_data(cr, uid, company_id, context=context)
|
||||
values = {
|
||||
'expects_chart_of_accounts': company.expects_chart_of_accounts,
|
||||
'currency_id': company.currency_id.id,
|
||||
'paypal_account': company.paypal_account,
|
||||
'company_footer': company.rml_footer,
|
||||
'has_chart_of_accounts': has_chart_of_accounts,
|
||||
'has_fiscal_year': bool(fiscalyear_count),
|
||||
'chart_template_id': False,
|
||||
'tax_calculation_rounding_method': company.tax_calculation_rounding_method,
|
||||
'date_start': date_start,
|
||||
'date_stop': date_stop,
|
||||
'period': period,
|
||||
}
|
||||
self.currency_id = False
|
||||
if self.company_id:
|
||||
company = self.company_id
|
||||
self.chart_template_id = company.chart_template_id
|
||||
self.has_chart_of_accounts = len(company.chart_template_id) > 0 or False
|
||||
self.expects_chart_of_accounts = company.expects_chart_of_accounts
|
||||
self.currency_id = company.currency_id
|
||||
self.transfer_account_id = company.transfer_account_id
|
||||
self.paypal_account = company.paypal_account
|
||||
self.company_footer = company.rml_footer
|
||||
self.tax_calculation_rounding_method = company.tax_calculation_rounding_method
|
||||
self.bank_account_code_char = company.bank_account_code_char
|
||||
self.code_digits = company.accounts_code_digits
|
||||
|
||||
# update journals and sequences
|
||||
for journal_type in ('sale', 'sale_refund', 'purchase', 'purchase_refund'):
|
||||
for suffix in ('_journal_id', '_sequence_prefix', '_sequence_next'):
|
||||
values[journal_type + suffix] = False
|
||||
journal_obj = self.pool.get('account.journal')
|
||||
journal_ids = journal_obj.search(cr, uid, [('company_id', '=', company_id)])
|
||||
for journal in journal_obj.browse(cr, uid, journal_ids):
|
||||
if journal.type in ('sale', 'sale_refund', 'purchase', 'purchase_refund'):
|
||||
values.update({
|
||||
journal.type + '_journal_id': journal.id,
|
||||
journal.type + '_sequence_prefix': journal.sequence_id.prefix,
|
||||
journal.type + '_sequence_next': journal.sequence_id.number_next,
|
||||
})
|
||||
self.purchase_journal_id = self.purchase_sequence_prefix = self.purchase_sequence_next = False
|
||||
self.sale_journal_id = self.sale_sequence_prefix = self.sale_sequence_next = False
|
||||
journals = self.env['account.journal'].search([('company_id', '=', self.company_id.id)])
|
||||
for journal in journals:
|
||||
if journal.type == 'purchase':
|
||||
self.purchase_journal_id = journal
|
||||
self.purchase_sequence_prefix = journal.sequence_id.prefix
|
||||
self.purchase_sequence_next = journal.sequence_id.number_next
|
||||
elif journal.type == 'sale':
|
||||
self.sale_journal_id = journal
|
||||
self.sale_sequence_prefix = journal.sequence_id.prefix
|
||||
self.sale_sequence_next = journal.sequence_id.number_next
|
||||
# update taxes
|
||||
ir_values = self.pool.get('ir.values')
|
||||
taxes_id = ir_values.get_default(cr, uid, 'product.template', 'taxes_id', company_id=company_id)
|
||||
supplier_taxes_id = ir_values.get_default(cr, uid, 'product.template', 'supplier_taxes_id', company_id=company_id)
|
||||
values.update({
|
||||
'default_sale_tax': isinstance(taxes_id, list) and taxes_id[0] or taxes_id,
|
||||
'default_purchase_tax': isinstance(supplier_taxes_id, list) and supplier_taxes_id[0] or supplier_taxes_id,
|
||||
})
|
||||
ir_values = self.env['ir.values']
|
||||
taxes_id = ir_values.get_default('product.template', 'taxes_id', company_id = self.company_id.id)
|
||||
supplier_taxes_id = ir_values.get_default('product.template', 'supplier_taxes_id', company_id = self.company_id.id)
|
||||
self.default_sale_tax = isinstance(taxes_id, list) and taxes_id[0] or taxes_id
|
||||
self.default_purchase_tax = isinstance(supplier_taxes_id, list) and supplier_taxes_id[0] or supplier_taxes_id
|
||||
|
||||
# update gain/loss exchange rate accounts
|
||||
values.update({
|
||||
'income_currency_exchange_account_id': company.income_currency_exchange_account_id and company.income_currency_exchange_account_id.id or False,
|
||||
'expense_currency_exchange_account_id': company.expense_currency_exchange_account_id and company.expense_currency_exchange_account_id.id or False
|
||||
})
|
||||
|
||||
return {'value': values}
|
||||
|
||||
def onchange_chart_template_id(self, cr, uid, ids, chart_template_id, context=None):
|
||||
tax_templ_obj = self.pool.get('account.tax.template')
|
||||
res = {'value': {
|
||||
'complete_tax_set': False, 'sale_tax': False, 'purchase_tax': False,
|
||||
'sale_tax_rate': 15, 'purchase_tax_rate': 15,
|
||||
}}
|
||||
if chart_template_id:
|
||||
# update complete_tax_set, sale_tax and purchase_tax
|
||||
chart_template = self.pool.get('account.chart.template').browse(cr, uid, chart_template_id, context=context)
|
||||
res['value'].update({'complete_tax_set': chart_template.complete_tax_set})
|
||||
if chart_template.complete_tax_set:
|
||||
# default tax is given by the lowest sequence. For same sequence we will take the latest created as it will be the case for tax created while isntalling the generic chart of account
|
||||
sale_tax_ids = tax_templ_obj.search(cr, uid,
|
||||
[("chart_template_id", "=", chart_template_id), ('type_tax_use', 'in', ('sale','all'))],
|
||||
order="sequence, id desc")
|
||||
purchase_tax_ids = tax_templ_obj.search(cr, uid,
|
||||
[("chart_template_id", "=", chart_template_id), ('type_tax_use', 'in', ('purchase','all'))],
|
||||
order="sequence, id desc")
|
||||
res['value']['sale_tax'] = sale_tax_ids and sale_tax_ids[0] or False
|
||||
res['value']['purchase_tax'] = purchase_tax_ids and purchase_tax_ids[0] or False
|
||||
if chart_template.code_digits:
|
||||
res['value']['code_digits'] = chart_template.code_digits
|
||||
return res
|
||||
|
||||
def onchange_tax_rate(self, cr, uid, ids, rate, context=None):
|
||||
return {'value': {'purchase_tax_rate': rate or False}}
|
||||
|
||||
def onchange_multi_currency(self, cr, uid, ids, group_multi_currency, context=None):
|
||||
res = {}
|
||||
if not group_multi_currency:
|
||||
res['value'] = {'income_currency_exchange_account_id': False, 'expense_currency_exchange_account_id': False}
|
||||
return res
|
||||
|
||||
def set_group_multi_currency(self, cr, uid, ids, context=None):
|
||||
ir_model = self.pool['ir.model.data']
|
||||
group_user = ir_model.get_object(cr, uid, 'base', 'group_user', context)
|
||||
group_product = ir_model.get_object(cr, uid, 'product', 'group_sale_pricelist', context)
|
||||
for config_obj in self.browse(cr, uid, ids, context=context):
|
||||
if config_obj.group_multi_currency:
|
||||
group_user.write({'implied_ids': [(4, group_product.id)]})
|
||||
return True
|
||||
|
||||
def onchange_start_date(self, cr, uid, id, start_date):
|
||||
if start_date:
|
||||
start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
|
||||
end_date = (start_date + relativedelta(months=12)) - relativedelta(days=1)
|
||||
return {'value': {'date_stop': end_date.strftime('%Y-%m-%d')}}
|
||||
self.income_currency_exchange_account_id = company.income_currency_exchange_account_id
|
||||
self.expense_currency_exchange_account_id = company.expense_currency_exchange_account_id
|
||||
return {}
|
||||
|
||||
def open_company_form(self, cr, uid, ids, context=None):
|
||||
config = self.browse(cr, uid, ids[0], context)
|
||||
@api.onchange('chart_template_id')
|
||||
def onchange_chart_template_id(self):
|
||||
tax_templ_obj = self.env['account.tax.template']
|
||||
self.complete_tax_set = self.sale_tax = self.purchase_tax = False
|
||||
self.sale_tax_rate = self.purchase_tax_rate = 15
|
||||
if self.chart_template_id and not self.has_chart_of_accounts:
|
||||
# update complete_tax_set, sale_tax and purchase_tax
|
||||
self.complete_tax_set = self.chart_template_id.complete_tax_set
|
||||
if self.chart_template_id.complete_tax_set:
|
||||
ir_values_obj = self.env['ir.values']
|
||||
# default tax is given by the lowest sequence. For same sequence we will take the latest created as it will be the case for tax created while isntalling the generic chart of account
|
||||
sale_tax = tax_templ_obj.search(
|
||||
[('chart_template_id', '=', self.chart_template_id.id), ('type_tax_use', '=', 'sale')], limit=1,
|
||||
order="sequence, id desc")
|
||||
purchase_tax = tax_templ_obj.search(
|
||||
[('chart_template_id', '=', self.chart_template_id.id), ('type_tax_use', '=', 'purchase')], limit=1,
|
||||
order="sequence, id desc")
|
||||
self.sale_tax = sale_tax
|
||||
self.purchase_tax = purchase_tax
|
||||
if self.chart_template_id.code_digits:
|
||||
self.code_digits = self.chart_template_id.code_digits
|
||||
if self.chart_template_id.transfer_account_id:
|
||||
self.transfer_account_id = self.chart_template_id.transfer_account_id.id
|
||||
if self.chart_template_id.bank_account_code_char:
|
||||
self.bank_account_code_char = self.chart_template_id.bank_account_code_char
|
||||
return {}
|
||||
|
||||
@api.onchange('sale_tax_rate')
|
||||
def onchange_tax_rate(self):
|
||||
self.purchase_tax_rate = self.sale_tax_rate or False
|
||||
|
||||
@api.onchange('group_multi_currency')
|
||||
def onchange_multi_currency(self):
|
||||
if not self.group_multi_currency:
|
||||
self.income_currency_exchange_account_id = False
|
||||
self.expense_currency_exchange_account_id = False
|
||||
|
||||
@api.multi
|
||||
def set_group_multi_currency(self):
|
||||
ir_model = self.env['ir.model.data']
|
||||
group_user = ir_model.get_object('base', 'group_user')
|
||||
group_product = ir_model.get_object('product', 'group_sale_pricelist')
|
||||
if self.group_multi_currency:
|
||||
group_user.write({'implied_ids': [(4, group_product.id)]})
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def open_company_form(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Configure your Company',
|
||||
'res_model': 'res.company',
|
||||
'res_id': config.company_id.id,
|
||||
'res_id': self.company_id.id,
|
||||
'view_mode': 'form',
|
||||
}
|
||||
|
||||
def set_default_taxes(self, cr, uid, ids, context=None):
|
||||
""" set default sale and purchase taxes for products """
|
||||
if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'):
|
||||
raise openerp.exceptions.AccessError(_("Only administrators can change the settings"))
|
||||
ir_values = self.pool.get('ir.values')
|
||||
config = self.browse(cr, uid, ids[0], context)
|
||||
ir_values.set_default(cr, SUPERUSER_ID, 'product.template', 'taxes_id',
|
||||
config.default_sale_tax and [config.default_sale_tax.id] or False, company_id=config.company_id.id)
|
||||
ir_values.set_default(cr, SUPERUSER_ID, 'product.template', 'supplier_taxes_id',
|
||||
config.default_purchase_tax and [config.default_purchase_tax.id] or False, company_id=config.company_id.id)
|
||||
@api.multi
|
||||
def set_product_taxes(self):
|
||||
""" Set the product taxes if they have changed """
|
||||
ir_values_obj = self.env['ir.values']
|
||||
if self.default_sale_tax:
|
||||
ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax.id], for_all_users=True, company_id=self.company_id.id)
|
||||
if self.default_purchase_tax:
|
||||
ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax.id], for_all_users=True, company_id=self.company_id.id)
|
||||
|
||||
def set_chart_of_accounts(self, cr, uid, ids, context=None):
|
||||
@api.multi
|
||||
def set_chart_of_accounts(self):
|
||||
""" install a chart of accounts for the given company (if required) """
|
||||
config = self.browse(cr, uid, ids[0], context)
|
||||
if config.chart_template_id:
|
||||
assert config.expects_chart_of_accounts and not config.has_chart_of_accounts
|
||||
wizard = self.pool.get('wizard.multi.charts.accounts')
|
||||
wizard_id = wizard.create(cr, uid, {
|
||||
'company_id': config.company_id.id,
|
||||
'chart_template_id': config.chart_template_id.id,
|
||||
'code_digits': config.code_digits or 6,
|
||||
'sale_tax': config.sale_tax.id,
|
||||
'purchase_tax': config.purchase_tax.id,
|
||||
'sale_tax_rate': config.sale_tax_rate,
|
||||
'purchase_tax_rate': config.purchase_tax_rate,
|
||||
'complete_tax_set': config.complete_tax_set,
|
||||
'currency_id': config.currency_id.id,
|
||||
}, context)
|
||||
wizard.execute(cr, uid, [wizard_id], context)
|
||||
if self.chart_template_id and not self.has_chart_of_accounts and self.expects_chart_of_accounts:
|
||||
if self.company_id.chart_template_id and self.chart_template_id != self.company_id.chart_template_id:
|
||||
raise UserError(_('You can not change a company chart of account once it has been installed'))
|
||||
wizard = self.env['wizard.multi.charts.accounts'].create({
|
||||
'company_id': self.company_id.id,
|
||||
'chart_template_id': self.chart_template_id.id,
|
||||
'transfer_account_id': self.transfer_account_id.id,
|
||||
'code_digits': self.code_digits or 6,
|
||||
'sale_tax': self.sale_tax.id,
|
||||
'purchase_tax': self.purchase_tax.id,
|
||||
'sale_tax_rate': self.sale_tax_rate,
|
||||
'purchase_tax_rate': self.purchase_tax_rate,
|
||||
'complete_tax_set': self.complete_tax_set,
|
||||
'currency_id': self.currency_id.id,
|
||||
'bank_account_code_char': self.bank_account_code_char,
|
||||
})
|
||||
wizard.execute()
|
||||
|
||||
def set_fiscalyear(self, cr, uid, ids, context=None):
|
||||
""" create a fiscal year for the given company (if necessary) """
|
||||
config = self.browse(cr, uid, ids[0], context)
|
||||
if config.has_chart_of_accounts or config.chart_template_id:
|
||||
fiscalyear = self.pool.get('account.fiscalyear')
|
||||
fiscalyear_count = fiscalyear.search_count(cr, uid,
|
||||
[('date_start', '<=', config.date_start), ('date_stop', '>=', config.date_stop),
|
||||
('company_id', '=', config.company_id.id)],
|
||||
context=context)
|
||||
if not fiscalyear_count:
|
||||
name = code = config.date_start[:4]
|
||||
if int(name) != int(config.date_stop[:4]):
|
||||
name = config.date_start[:4] +'-'+ config.date_stop[:4]
|
||||
code = config.date_start[2:4] +'-'+ config.date_stop[2:4]
|
||||
vals = {
|
||||
'name': name,
|
||||
'code': code,
|
||||
'date_start': config.date_start,
|
||||
'date_stop': config.date_stop,
|
||||
'company_id': config.company_id.id,
|
||||
}
|
||||
fiscalyear_id = fiscalyear.create(cr, uid, vals, context=context)
|
||||
if config.period == 'month':
|
||||
fiscalyear.create_period(cr, uid, [fiscalyear_id])
|
||||
elif config.period == '3months':
|
||||
fiscalyear.create_period3(cr, uid, [fiscalyear_id])
|
||||
|
||||
def get_default_dp(self, cr, uid, fields, context=None):
|
||||
dp = self.pool.get('ir.model.data').get_object(cr, uid, 'product','decimal_account')
|
||||
return {'decimal_precision': dp.digits}
|
||||
|
||||
def set_default_dp(self, cr, uid, ids, context=None):
|
||||
config = self.browse(cr, uid, ids[0], context)
|
||||
dp = self.pool.get('ir.model.data').get_object(cr, uid, 'product','decimal_account')
|
||||
dp.write({'digits': config.decimal_precision})
|
||||
|
||||
def onchange_analytic_accounting(self, cr, uid, ids, analytic_accounting, context=None):
|
||||
if analytic_accounting:
|
||||
return {'value': {
|
||||
'module_account_accountant': True,
|
||||
}}
|
||||
return {}
|
||||
@api.onchange('group_analytic_accounting')
|
||||
def onchange_analytic_accounting(self):
|
||||
if self.group_analytic_accounting:
|
||||
self.module_account_accountant = True
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2010 OpenERP s.a. (<http://www.openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import osv
|
||||
|
||||
"""Inherit res.currency to handle accounting date values when converting currencies"""
|
||||
|
||||
class res_currency_account(osv.osv):
|
||||
_inherit = "res.currency"
|
||||
|
||||
def _get_conversion_rate(self, cr, uid, from_currency, to_currency, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
rate = super(res_currency_account, self)._get_conversion_rate(cr, uid, from_currency, to_currency, context=context)
|
||||
#process the case where the account doesn't work with an outgoing currency rate method 'at date' but 'average'
|
||||
account = context.get('res.currency.compute.account')
|
||||
account_invert = context.get('res.currency.compute.account_invert')
|
||||
if account and account.currency_mode == 'average' and account.currency_id:
|
||||
query = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
|
||||
cr.execute('select sum(debit-credit),sum(amount_currency) from account_move_line l ' \
|
||||
'where l.currency_id=%s and l.account_id=%s and '+query, (account.currency_id.id,account.id,))
|
||||
tot1,tot2 = cr.fetchone()
|
||||
if tot2 and not account_invert:
|
||||
rate = float(tot1)/float(tot2)
|
||||
elif tot1 and account_invert:
|
||||
rate = float(tot2)/float(tot1)
|
||||
return rate
|
||||
@@ -3,7 +3,7 @@
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="group_account_invoice" model="res.groups">
|
||||
<field name="name">Invoicing & Payments</field>
|
||||
<field name="name">Billing</field>
|
||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
@@ -16,7 +16,7 @@
|
||||
</record>
|
||||
|
||||
<record id="group_account_manager" model="res.groups">
|
||||
<field name="name">Financial Manager</field>
|
||||
<field name="name">Adviser</field>
|
||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||
<field name="implied_ids" eval="[(4, ref('group_account_user'))]"/>
|
||||
</record>
|
||||
@@ -27,7 +27,7 @@
|
||||
</record>
|
||||
|
||||
<record id="group_supplier_inv_check_total" model="res.groups">
|
||||
<field name="name">Check Total on supplier invoices</field>
|
||||
<field name="name">Check Total on supplier bills</field>
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
</data>
|
||||
@@ -47,14 +47,6 @@
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="journal_period_comp_rule" model="ir.rule">
|
||||
<field name="name">Journal Period</field>
|
||||
<field name="model_id" ref="model_account_journal_period"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="journal_comp_rule" model="ir.rule">
|
||||
<field name="name">Journal multi-company</field>
|
||||
<field name="model_id" ref="model_account_journal"/>
|
||||
@@ -62,20 +54,6 @@
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="period_comp_rule" model="ir.rule">
|
||||
<field name="name">Period multi-company</field>
|
||||
<field name="model_id" ref="model_account_period"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="fiscal_year_comp_rule" model="ir.rule">
|
||||
<field name="name">Fiscal year multi-company</field>
|
||||
<field name="model_id" ref="model_account_fiscalyear"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="account_comp_rule" model="ir.rule">
|
||||
<field name="name">Account multi-company</field>
|
||||
<field name="model_id" ref="model_account_account"/>
|
||||
@@ -90,13 +68,6 @@
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="tax_code_comp_rule" model="ir.rule">
|
||||
<field name="name">Tax code multi-company</field>
|
||||
<field name="model_id" ref="model_account_tax_code"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_comp_rule" model="ir.rule">
|
||||
<field name="name">Invoice multi-company</field>
|
||||
<field name="model_id" ref="model_account_invoice"/>
|
||||
@@ -104,27 +75,6 @@
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_analysis_comp_rule" model="ir.rule">
|
||||
<field name="name">Invoice Analysis multi-company</field>
|
||||
<field name="model_id" ref="model_account_invoice_report"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="entry_analysis_comp_rule" model="ir.rule">
|
||||
<field name="name">Entries Analysis multi-company</field>
|
||||
<field name="model_id" ref="model_account_entries_report"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="analytic_entry_analysis_comp_rule" model="ir.rule">
|
||||
<field name="name">Analytic Entries Analysis multi-company</field>
|
||||
<field name="model_id" ref="model_analytic_entries_report"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="account_fiscal_position_comp_rule" model="ir.rule">
|
||||
<field name="name">Account fiscal Mapping company rule</field>
|
||||
<field name="model_id" ref="model_account_fiscal_position"/>
|
||||
@@ -132,20 +82,6 @@
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="account_model_comp_rule" model="ir.rule">
|
||||
<field name="name">Account model company rule</field>
|
||||
<field name="model_id" ref="model_account_model"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="account_subscription_line_comp_rule" model="ir.rule">
|
||||
<field name="name">Account subscription line company rule</field>
|
||||
<field name="model_id" ref="model_account_subscription_line"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('subscription_id.model_id.company_id','=',False),('subscription_id.model_id.company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="account_invoice_line_comp_rule">
|
||||
<field name="name">Invoice Line company rule</field>
|
||||
<field name="model_id" ref="model_account_invoice_line"/>
|
||||
@@ -167,9 +103,16 @@
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="account_statement_operation_template_comp_rule">
|
||||
<field name="name">Account statement operation template company rule</field>
|
||||
<field name="model_id" ref="model_account_statement_operation_template"/>
|
||||
<record model="ir.rule" id="account_operation_template_comp_rule">
|
||||
<field name="name">Account operation template company rule</field>
|
||||
<field name="model_id" ref="model_account_operation_template"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="account_payment_comp_rule">
|
||||
<field name="name">Account payment company rule</field>
|
||||
<field name="model_id" ref="model_account_payment"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
@@ -2,22 +2,15 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_product_product_account_user,product.product.account.user,product.model_product_product,group_account_user,1,0,0,0
|
||||
access_account_payment_term,account.payment.term,model_account_payment_term,account.group_account_user,1,0,0,0
|
||||
access_account_payment_term_line,account.payment.term.line,model_account_payment_term_line,account.group_account_user,1,0,0,0
|
||||
access_account_account_type_manager,account.account.type,model_account_account_type,account.group_account_manager,1,1,1,1
|
||||
access_account_account_type,account.account.type,model_account_account_type,account.group_account_user,1,0,0,0
|
||||
access_account_tax_internal_user,account.tax internal user,model_account_tax,base.group_user,1,0,0,0
|
||||
access_account_account_manager,account.account,model_account_account,account.group_account_manager,1,1,1,1
|
||||
access_account_account,account.account,model_account_account,account.group_account_user,1,0,0,0
|
||||
access_account_account_user,account.account user,model_account_account,base.group_user,1,0,0,0
|
||||
access_account_account_partner_manager,account.account partner manager,model_account_account,base.group_partner_manager,1,0,0,0
|
||||
access_account_journal_period_manager,account.journal.period manager,model_account_journal_period,account.group_account_manager,1,0,0,0
|
||||
access_account_tax_code,account.tax.code,model_account_tax_code,account.group_account_invoice,1,0,0,0
|
||||
access_account_tax,account.tax,model_account_tax,account.group_account_invoice,1,0,0,0
|
||||
access_account_model,account.model,model_account_model,account.group_account_user,1,1,1,1
|
||||
access_account_model_line,account.model.line,model_account_model_line,account.group_account_user,1,1,1,1
|
||||
access_account_subscription,account.subscription,model_account_subscription,account.group_account_user,1,1,1,1
|
||||
access_account_subscription_line,account.subscription.line,model_account_subscription_line,account.group_account_user,1,1,1,1
|
||||
access_account_subscription_manager,account.subscription manager,model_account_subscription,account.group_account_manager,1,0,0,0
|
||||
access_account_subscription_line_manager,account.subscription.line manager,model_account_subscription_line,account.group_account_manager,1,0,0,0
|
||||
access_account_account_template,account.account.template,model_account_account_template,account.group_account_manager,1,1,1,1
|
||||
access_account_tax_code_template,account.tax.code.template,model_account_tax_code_template,account.group_account_manager,1,1,1,1
|
||||
access_account_chart_template,account.chart.template,model_account_chart_template,account.group_account_manager,1,1,1,1
|
||||
access_account_tax_template,account.tax.template,model_account_tax_template,account.group_account_manager,1,1,1,1
|
||||
access_account_bank_statement,account.bank.statement,model_account_bank_statement,account.group_account_user,1,1,1,1
|
||||
@@ -31,21 +24,14 @@ access_account_invoice_line_uinvoice,account.invoice.line,model_account_invoice_
|
||||
access_account_invoice_tax_uinvoice,account.invoice.tax,model_account_invoice_tax,account.group_account_invoice,1,1,1,1
|
||||
access_account_move_uinvoice,account.move,model_account_move,account.group_account_invoice,1,1,1,1
|
||||
access_account_move_line_uinvoice,account.move.line invoice,model_account_move_line,account.group_account_invoice,1,1,1,1
|
||||
access_account_move_reconcile_uinvoice,account.move.reconcile,model_account_move_reconcile,account.group_account_invoice,1,1,1,1
|
||||
access_account_journal_period_uinvoice,account.journal.period,model_account_journal_period,account.group_account_invoice,1,1,1,1
|
||||
access_account_payment_term_manager,account.payment.term,model_account_payment_term,account.group_account_manager,1,1,1,1
|
||||
access_account_payment_term_line_manager,account.payment.term.line,model_account_payment_term_line,account.group_account_manager,1,1,1,1
|
||||
access_account_tax_manager,account.tax,model_account_tax,account.group_account_manager,1,1,1,1
|
||||
access_account_journal_manager,account.journal,model_account_journal,account.group_account_manager,1,1,1,1
|
||||
access_account_journal_user,account.journal,model_account_journal,account.group_account_user,1,0,0,0
|
||||
access_account_journal_invoice,account.journal invoice,model_account_journal,account.group_account_invoice,1,0,0,0
|
||||
access_account_period_manager,account.period,model_account_period,account.group_account_manager,1,1,1,1
|
||||
access_account_period_invoice,account.period invoice,model_account_period,account.group_account_invoice,1,0,0,0
|
||||
access_account_invoice_group_invoice,account.invoice group invoice,model_account_invoice,account.group_account_invoice,1,1,1,1
|
||||
access_account_analytic_journal_manager,account.analytic.journal,analytic.model_account_analytic_journal,account.group_account_manager,1,1,1,1
|
||||
access_account_fiscalyear,account.fiscalyear,model_account_fiscalyear,account.group_account_manager,1,1,1,1
|
||||
access_account_fiscalyear_invoice,account.fiscalyear.invoice,model_account_fiscalyear,account.group_account_invoice,1,0,0,0
|
||||
access_account_fiscalyear_partner_manager,account.fiscalyear.partnermanager,model_account_fiscalyear,base.group_partner_manager,1,0,0,0
|
||||
access_account_fiscalyear_employee,account.fiscalyear employee,model_account_fiscalyear,base.group_user,1,0,0,0
|
||||
access_res_currency_account_manager,res.currency account manager,base.model_res_currency,group_account_manager,1,1,1,1
|
||||
access_res_currency_rate_account_manager,res.currency.rate account manager,base.model_res_currency_rate,group_account_manager,1,1,1,1
|
||||
access_account_invoice_user,account.invoice user,model_account_invoice,base.group_user,1,0,0,0
|
||||
@@ -62,35 +48,30 @@ access_account_fiscal_position_account,account.fiscal.position all,model_account
|
||||
access_account_fiscal_position_template,account.fiscal.position.template,model_account_fiscal_position_template,account.group_account_manager,1,1,1,1
|
||||
access_account_fiscal_position_tax_template,account.fiscal.position.tax.template,model_account_fiscal_position_tax_template,account.group_account_manager,1,1,1,1
|
||||
access_account_fiscal_position_account_template,account.fiscal.position.account.template,model_account_fiscal_position_account_template,account.group_account_manager,1,1,1,1
|
||||
access_temp_range,temp.range,model_temp_range,account.group_account_manager,1,0,0,0
|
||||
access_report_aged_receivable,report.aged.receivable,model_report_aged_receivable,account.group_account_manager,1,1,1,1
|
||||
access_report_invoice_created,report.invoice.created,model_report_invoice_created,account.group_account_manager,1,1,1,1
|
||||
access_report_account_type_sales,report.account_type.sales,model_report_account_type_sales,account.group_account_manager,1,1,1,1
|
||||
access_report_account_sales,report.account.sales,model_report_account_sales,account.group_account_manager,1,1,1,1
|
||||
access_account_invoice_report,account.invoice.report,model_account_invoice_report,account.group_account_invoice,1,0,0,0
|
||||
access_account_invoice_report_user,account.invoice.report_user,model_account_invoice_report,account.group_account_user,1,0,0,0
|
||||
access_account_invoice_report,account.invoice.report,model_account_invoice_report,account.group_account_manager,1,1,1,1
|
||||
access_res_partner_group_account_manager,res_partner group_account_manager,model_res_partner,account.group_account_manager,1,0,0,0
|
||||
access_account_invoice_accountant,account.invoice accountant,model_account_invoice,account.group_account_user,1,0,0,0
|
||||
access_account_tax_code_accountant,account.tax.code accountant,model_account_tax_code,account.group_account_user,1,1,1,1
|
||||
access_account_move_line_manager,account.move.line manager,model_account_move_line,account.group_account_manager,1,0,0,0
|
||||
access_account_move_manager,account.move manager,model_account_move,account.group_account_manager,1,0,0,0
|
||||
access_account_entries_report_manager,account.entries.report,model_account_entries_report,account.group_account_manager,1,1,1,1
|
||||
access_account_entries_report_invoice,account.entries.report,model_account_entries_report,account.group_account_invoice,1,0,0,0
|
||||
access_account_entries_report_employee,account.entries.report employee,model_account_entries_report,base.group_user,1,0,0,0
|
||||
access_analytic_entries_report_manager,analytic.entries.report,model_analytic_entries_report,account.group_account_manager,1,0,0,0
|
||||
access_account_cashbox_line,account.cashbox.line,model_account_cashbox_line,account.group_account_user,1,1,1,1
|
||||
access_account_journal_cashbox_line,account.journal.cashbox.line,model_account_journal_cashbox_line,account.group_account_user,1,1,1,0
|
||||
access_account_invoice_tax_accountant,account.invoice.tax accountant,model_account_invoice_tax,account.group_account_user,1,0,0,0
|
||||
access_account_move_reconcile_manager,account.move.reconcile manager,model_account_move_reconcile,account.group_account_manager,1,0,0,0
|
||||
access_account_analytic_line_invoice,account.analytic.line invoice,model_account_analytic_line,account.group_account_invoice,1,1,1,1
|
||||
access_account_invoice_line_accountant,account.invoice.line accountant,model_account_invoice_line,account.group_account_user,1,0,0,0
|
||||
access_account_account_invoice,account.account invoice,model_account_account,account.group_account_invoice,1,1,1,1
|
||||
access_account_account_invoice,account.account invoice,model_account_account,account.group_account_invoice,1,0,0,0
|
||||
access_account_analytic_accountant,account.analytic.account accountant,analytic.model_account_analytic_account,account.group_account_user,1,1,1,1
|
||||
access_account_account_type_invoice,account.account.type invoice,model_account_account_type,account.group_account_invoice,1,1,1,1
|
||||
access_report_account_receivable_invoice,report.account.receivable.invoice,model_report_account_receivable,account.group_account_invoice,1,1,1,1
|
||||
access_account_account_type_invoice,account.account.type invoice,model_account_account_type,account.group_account_invoice,1,0,0,0
|
||||
access_account_tax_sale_manager,account.tax sale manager,model_account_tax,base.group_sale_salesman,1,0,0,0
|
||||
access_account_journal_sale_manager,account.journal sale manager,model_account_journal,base.group_sale_salesman,1,0,0,0
|
||||
access_account_invoice_tax_sale_manager,account.invoice.tax sale manager,model_account_invoice_tax,base.group_sale_salesman,1,0,0,0
|
||||
access_account_treasury_report_manager,account.treasury.report.manager,model_account_treasury_report,account.group_account_manager,1,0,0,0
|
||||
access_account_financial_report,account.financial.report,model_account_financial_report,account.group_account_user,1,1,1,1
|
||||
access_account_financial_report_invoice,account.financial.report invoice,model_account_financial_report,account.group_account_invoice,1,0,0,0
|
||||
access_account_statement_operation_template,account.statement.operation.template,model_account_statement_operation_template,account.group_account_user,1,1,1,1
|
||||
access_account_financial_report_line,account.financial.report.line,model_account_financial_report_line,account.group_account_user,1,1,1,1
|
||||
access_account_financial_report_line_invoice,account.financial.report.line invoice,model_account_financial_report_line,account.group_account_invoice,1,0,0,0
|
||||
access_account_account_tax,account.account.tag,model_account_account_tag,account.group_account_user,1,0,0,0
|
||||
access_account_account_tax_user,account.account.tag,model_account_account_tag,account.group_account_invoice,1,0,0,0
|
||||
access_account_operation_template,account.operation.template,model_account_operation_template,account.group_account_user,1,1,1,1
|
||||
access_account_partial_reconcile,account.partial.reconcile,model_account_partial_reconcile,account.group_account_user,1,1,1,1
|
||||
access_account_payment_method,account.payment.method,model_account_payment_method,account.group_account_invoice,1,1,1,1
|
||||
access_account_payment,account.payment,model_account_payment,account.group_account_invoice,1,1,1,1
|
||||
access_account_cashbox,account.bank.statement.cashbox,model_account_bank_statement_cashbox,account.group_account_user,1,1,1,1
|
||||
access_account_cashbox_line,account.bank.statement.cashbox.line,model_account_cashbox_line,account.group_account_user,1,1,1,1
|
||||
|
||||
|
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
@@ -1,7 +1,7 @@
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h2 class="oe_slogan">Accounting Made Easy</h2>
|
||||
<h3 class="oe_slogan">Beautiful, easy, full featured</h3>
|
||||
<h2 class="oe_slogan">Invoicing Made Easy</h2>
|
||||
<h3 class="oe_slogan">Send professional invoices & get paid online</h3>
|
||||
<div class="oe_span6">
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<a href="https://www.openerp.com/saas_master/demo?lang=en_US&module=account">
|
||||
@@ -12,53 +12,58 @@
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
By far the most beautiful and full featured accounting software. Odoo Accounting allows a better way to collaborate with your accountants, your customers and control your suppliers.</p>
|
||||
<p>
|
||||
Activate features on demand, from integrated analytic accounting to budget, assets and multiple companies consolidation.
|
||||
Create and send professional looking invoices & get paid
|
||||
online. It automatically integrates with other apps to bill
|
||||
automatically based on your activities.
|
||||
</p>
|
||||
<div class="oe_centeralign oe_websiteonly">
|
||||
<a href="http://www.openerp.com/start?app=account" class="oe_button oe_big oe_tacky">Start your <span class="oe_emph">free</span> trial</a>
|
||||
<a href="http://www.openerp.com/start?app=account_voucher" class="oe_button oe_big oe_tacky">Start your <span class="oe_emph">free</span> trial</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<h2 class="oe_slogan">Send Invoices With No Effort</h2>
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">A Smart User Interface</h2>
|
||||
<div class="oe_span6">
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Record transactions in a few clicks and easily manage all financial activities
|
||||
in one place. Odoo's user interface is designed with productivity in mind.
|
||||
Send invoices directly to your clients in just a click. The
|
||||
invoice is automatically attached to the email as a PDF file.
|
||||
</p>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_01.png">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_03.png">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="oe_container">
|
||||
<h2 class="oe_slogan">Get Paid Faster</h2>
|
||||
<h3 class="oe_slogan">Electronic invoicing and automated follow-ups</h3>
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">A Better Way To Work – Together</h2>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_02.png">
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Share access to your latest business numbers with your team and your accountant – so everyone is up to speed. From work, home or on the go.
|
||||
Get paid online with paypal or other payment processing service. Get rid of
|
||||
the stress of having to constantly remind your debtors. Simply set-up and
|
||||
automate follow-ups to get paid quickly.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">Connect Your Bank Accounts</h2>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Import your bank statements and reconcile them in just a few clicks. Prepare payment orders based on your supplier invoices and payment terms.
|
||||
Import your bank statements and reconcile them in just a few clicks. Prepare
|
||||
payment orders based on your supplier invoices and payment terms.
|
||||
</p>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
@@ -69,15 +74,15 @@ Import your bank statements and reconcile them in just a few clicks. Prepare pay
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<h2 class="oe_slogan">Get Paid Faster</h2>
|
||||
<h3 class="oe_slogan">Electronic invoicing and automated follow-ups</h3>
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">Analyse Your Sales & Costs</h2>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_03.png">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_06.png">
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Create and send professional invoices & get paid online. Get rid of the stress of having to constantly remind your debtors. Simply set-up and automate follow-ups to get paid quickly.
|
||||
Get direct access to key information with dynamic and customizable dashboards.
|
||||
Analyse your invoicing by product, customer, salesperson, etc.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,75 +90,16 @@ Create and send professional invoices & get paid online. Get rid of the stre
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">Sales Integration</h2>
|
||||
<h2 class="oe_slogan">Integration With Other Apps</h2>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Automatically create invoices from sales orders, delivery orders or base them on time and material. Re-invoice expenses on projects to your customer in just a few clicks.
|
||||
Bill automatically based on sales orders, delivery orders, contracts or on time and
|
||||
material. Define recurrencies to produce recurring invoice automatically.
|
||||
</p>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_04.png">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row">
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_05.png">
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<h2 class="oe_slogan">Purchase Integration</h2>
|
||||
<p class='oe_mt32'>
|
||||
Control supplier invocies based on purchase orders. Get real-time inventory valuation reports automatically posted in your accounts.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">Multi-Level Analytic Accounting</h2>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Integrate your analytic accounting operations with timesheets, projects, invoices, expenses, etc. No need to record transactions, all analytic entries are posted automatically following your business rules.
|
||||
</p>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="account_sc_06.png">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">Everything you need to grow</h2>
|
||||
<div class="oe_span6">
|
||||
<img src="account_illu_02.png">
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Manage your assets, track expenses, control budgets, multi-level analytic accounting; Odoo has all the features you need to sustain all your business activities.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">Scale With Your Organization</h2>
|
||||
<h3 class="oe_slogan">Used by very small to very large organizations</h3>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Odoo supports multiple currencies, multiple users with different access rights, multiple companies with real time consolidation and unlimited analytic plans.
|
||||
</p>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<img class="oe_picture oe_screenshot" src="account_illu_03.png">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -166,20 +112,20 @@ Odoo supports multiple currencies, multiple users with different access rights,
|
||||
<div class="oe_span6">
|
||||
<div class="oe_quote">
|
||||
<q>
|
||||
Odoo Accounting is a great way to record all business transactions
|
||||
right when they happen. Awesome and cost-effective!
|
||||
Odoo allowed us to automate sending 10.000 invoices per month.
|
||||
</q>
|
||||
<cite class="oe_cite oe_clearfix oe_ml64">
|
||||
<div class="oe_author">Wolfgang Taferner</div>
|
||||
<div class="oe_job"><a href="http://tapo-it.at/en/" target="_blank">Tapo</a>, Austria.</div>
|
||||
<cite class="oe_cite oe_clearfix">
|
||||
<img class="oe_photo" src="bazile.png">
|
||||
<div class="oe_author">Yves Morel</div>
|
||||
<div class="oe_job">Director of <a href="http://www.bazile.fr" target="_blank">Bazile Telecom</a>.</div>
|
||||
</cite>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<div class="oe_quote">
|
||||
<q>
|
||||
We have found accounting module of Odoo to be user
|
||||
friendly and highly customizable. It proved to be an accounting gem.
|
||||
We have found invoicing module of Odoo to be user
|
||||
friendly and highly customizable.
|
||||
</q>
|
||||
<cite class="oe_cite oe_clearfix">
|
||||
<img class="oe_photo" src="testimonial_sunil.jpg">
|
||||
@@ -190,3 +136,5 @@ Odoo supports multiple currencies, multiple users with different access rights,
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="oe_container oe_separator">
|
||||
</section>
|
||||
|
||||
|
Before Width: | Height: | Size: 120 KiB |
@@ -0,0 +1,26 @@
|
||||
.openerp div.oe_account_help {
|
||||
background : #D6EBFF;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
border: 3px solid #C1D4E6;
|
||||
}
|
||||
|
||||
.openerp p.oe_account_font_help{
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
margin: 0px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.openerp p.oe_account_font_content{
|
||||
margin-left: 30px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.openerp p.oe_account_font_title{
|
||||
margin-top: 7px;
|
||||
font-size: 15px;
|
||||
font-style: italic;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
@@ -1,334 +0,0 @@
|
||||
.openerp .oe_bank_statement_reconciliation {
|
||||
font-size: 12px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
/* icons */ }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_form_sheetbg {
|
||||
padding-top: 0; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_form_sheetbg .oe_form_sheet {
|
||||
position: relative;
|
||||
padding: 20px 15px 20px 15px;
|
||||
border-top: 0;
|
||||
height: 100%; }
|
||||
.openerp .oe_bank_statement_reconciliation h1 input, .openerp .oe_bank_statement_reconciliation h2 input {
|
||||
height: auto !important; }
|
||||
.openerp .oe_bank_statement_reconciliation h1 {
|
||||
width: 48%;
|
||||
padding: 0 0 0 15px;
|
||||
margin: 0 0 25px 0;
|
||||
float: left;
|
||||
font-size: 2em;
|
||||
height: 1.5em; }
|
||||
.openerp .oe_bank_statement_reconciliation .statement_name span {
|
||||
line-height: 1.5em;
|
||||
cursor: pointer; }
|
||||
.openerp .oe_bank_statement_reconciliation .change_statement_name_container {
|
||||
display: none;
|
||||
width: 95%; }
|
||||
.openerp .oe_bank_statement_reconciliation .change_statement_name_container td:first-child, .openerp .oe_bank_statement_reconciliation .change_statement_name_container td:first-child > input {
|
||||
width: 99%; }
|
||||
.openerp .oe_bank_statement_reconciliation .change_statement_name_container td:last-child {
|
||||
width: 1%;
|
||||
padding-left: 3px; }
|
||||
.openerp .oe_bank_statement_reconciliation .change_statement_name_container td:last-child button {
|
||||
height: 100%;
|
||||
box-sizing: content-box; }
|
||||
.openerp .oe_bank_statement_reconciliation h2 {
|
||||
font-size: 1.8em; }
|
||||
.openerp .oe_bank_statement_reconciliation .progress {
|
||||
width: 49%;
|
||||
margin: 10px 15px 0 0;
|
||||
float: right;
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
.openerp .oe_bank_statement_reconciliation .progress .progress-text {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
z-index: 10;
|
||||
text-shadow: -1px -1px 0 #f5f5f5, 1px -1px 0 #f5f5f5, -1px 1px 0 #f5f5f5, 1px 1px 0 #f5f5f5; }
|
||||
.openerp .oe_bank_statement_reconciliation .show_more_container {
|
||||
text-align: center; }
|
||||
.openerp .oe_bank_statement_reconciliation .show_more_container .show_more {
|
||||
display: none; }
|
||||
.openerp .oe_bank_statement_reconciliation .notification_area {
|
||||
margin: 0 15px; }
|
||||
.openerp .oe_bank_statement_reconciliation .notification_area .fa {
|
||||
font-size: 20px;
|
||||
margin-left: 7px;
|
||||
line-height: 14px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
.openerp .oe_bank_statement_reconciliation .interface_options {
|
||||
margin-bottom: 25px;
|
||||
padding-left: 15px; }
|
||||
.openerp .oe_bank_statement_reconciliation .interface_options .oe_radio_input {
|
||||
border: none;
|
||||
display: inline; }
|
||||
.openerp .oe_bank_statement_reconciliation .protip {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
bottom: 7px;
|
||||
right: 15px;
|
||||
text-align: right;
|
||||
color: #bbb; }
|
||||
.openerp .oe_bank_statement_reconciliation .done_message {
|
||||
width: 100%;
|
||||
padding: 0 20%;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 50px; }
|
||||
.openerp .oe_bank_statement_reconciliation .done_message h2 {
|
||||
margin-bottom: 30px; }
|
||||
.openerp .oe_bank_statement_reconciliation .done_message h2 .congrats_icon {
|
||||
float: right;
|
||||
font-size: 2em;
|
||||
position: relative;
|
||||
top: -0.25em; }
|
||||
.openerp .oe_bank_statement_reconciliation .done_message .achievements {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
position: relative; }
|
||||
.openerp .oe_bank_statement_reconciliation .done_message .achievements .achievement {
|
||||
font-size: 4em;
|
||||
margin: 0 0.3em;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.2); }
|
||||
.openerp .oe_bank_statement_reconciliation .done_message .achievements .achievement i {
|
||||
font-size: 0.5em;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -0.55em;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center; }
|
||||
.openerp .oe_bank_statement_reconciliation .done_message .action_buttons {
|
||||
text-align: center; }
|
||||
.openerp .oe_bank_statement_reconciliation .glyphicon {
|
||||
font-size: 12px !important; }
|
||||
.openerp .oe_bank_statement_reconciliation .glyphicon.line_info_button {
|
||||
color: #ccc !important; }
|
||||
.openerp .oe_bank_statement_reconciliation .accounting_view .glyphicon-add-remove:before {
|
||||
content: "\2212"; }
|
||||
.openerp .oe_bank_statement_reconciliation .match .glyphicon-add-remove:before {
|
||||
content: "\2b"; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line {
|
||||
margin-bottom: 30px;
|
||||
/* gap between accounting_view and action view */
|
||||
/* popover */
|
||||
/* arrays of move lines */
|
||||
/* Partie infos */
|
||||
/* Match view */
|
||||
/* Action create */ }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line table {
|
||||
width: 100%; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .toggle_match, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .toggle_create {
|
||||
-webkit-transition-property: -webkit-transform;
|
||||
-moz-transition-property: -moz-transform;
|
||||
-ms-transition-property: -ms-transform;
|
||||
-o-transition-property: -o-transform;
|
||||
transition-property: transform;
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
-webkit-transition-duration: 300ms;
|
||||
-moz-transition-duration: 300ms;
|
||||
-ms-transition-duration: 300ms;
|
||||
-o-transition-duration: 300ms;
|
||||
transition-duration: 300ms; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .visible_toggle, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line[data-mode="match"] .toggle_match, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line[data-mode="create"] .toggle_create {
|
||||
visibility: visible !important;
|
||||
-webkit-transform: rotate(90deg);
|
||||
-moz-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
-o-transform: rotate(90deg);
|
||||
transform: rotate(90deg); }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .partner_name .change_partner {
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
margin: 0 10px 0 5px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .partner_name:hover .change_partner {
|
||||
display: inline; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .change_partner_container {
|
||||
width: 200px;
|
||||
display: none;
|
||||
position: relative !important; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line[data-mode="inactive"] .initial_line > td {
|
||||
background-color: #f8f8f8 !important; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_match:not(.no_partner) .initial_line {
|
||||
cursor: default !important; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_match:not(.no_partner) .initial_line .line_info_button {
|
||||
cursor: pointer; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line.no_match:not(.no_partner) .toggle_match {
|
||||
visibility: hidden !important; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line > table > tbody > tr:nth-child(1) > td table {
|
||||
margin-bottom: 10px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line table.details td:first-child {
|
||||
padding-right: 10px;
|
||||
font-weight: bold; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line table.details tr.one_line_info td {
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
color: #44c; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table {
|
||||
width: 100%; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tbody tr, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tbody tr {
|
||||
cursor: pointer; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tbody tr.created_line, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tbody tr.created_line {
|
||||
cursor: default !important; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tbody tr.created_line .line_remove_button, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tbody tr.created_line .line_remove_button {
|
||||
cursor: pointer; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.already_reconciled, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr.already_reconciled {
|
||||
color: #44c; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td {
|
||||
padding: 1px 8px;
|
||||
vertical-align: middle; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_action, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_info_popover, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_action, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_info_popover {
|
||||
width: 15px;
|
||||
padding: 0; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_action, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_action {
|
||||
text-align: left; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_account_code, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_account_code {
|
||||
width: 80px;
|
||||
padding-left: 3px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_due_date, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_due_date {
|
||||
width: 100px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_debit, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_debit {
|
||||
text-align: right;
|
||||
width: 15%; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_credit, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_credit {
|
||||
width: 15%;
|
||||
text-align: right;
|
||||
padding-right: 3px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_info_popover, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table td.cell_info_popover {
|
||||
text-align: right; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.line_open_balance, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr.line_open_balance {
|
||||
color: #bbb; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr .glyphicon:not(.line_info_button), .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr .glyphicon:not(.line_info_button) {
|
||||
visibility: hidden;
|
||||
color: #555; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr:hover .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr:focus .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr.active .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr:hover .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr:focus .glyphicon, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr.active .glyphicon {
|
||||
visibility: visible; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr .do_partial_reconcile_button, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr .do_partial_reconcile_button {
|
||||
color: #f0ad4e;
|
||||
padding-right: 5px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view tr .undo_partial_reconcile_button, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match table tr .undo_partial_reconcile_button {
|
||||
color: #555;
|
||||
padding-right: 5px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view {
|
||||
border-collapse: separate; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view .initial_line > td {
|
||||
border-top: 1px solid #bbb;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 5px;
|
||||
background-color: #f0f0f0;
|
||||
-webkit-transition-property: background-color;
|
||||
-moz-transition-property: background-color;
|
||||
-ms-transition-property: background-color;
|
||||
transition-property: background-color;
|
||||
-webkit-transition-duration: 300ms;
|
||||
-moz-transition-duration: 300ms;
|
||||
-ms-transition-duration: 300ms;
|
||||
-o-transition-duration: 300ms;
|
||||
transition-duration: 300ms; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view .initial_line > td.cell_action, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view .initial_line > td.cell_info_popover {
|
||||
border-top: none;
|
||||
background: white !important;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 3px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption {
|
||||
text-align: left;
|
||||
height: 26px;
|
||||
margin: 0 15px 4px 15px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption .partner_name {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption .tip_reconciliation_not_balanced {
|
||||
float: right;
|
||||
padding-right: 7px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption button {
|
||||
float: right;
|
||||
position: relative;
|
||||
top: -4px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption button:disabled {
|
||||
opacity: 0.5; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption > span, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption > input {
|
||||
position: relative;
|
||||
top: 7px;
|
||||
/* meh */ }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_credit {
|
||||
border-left: 1px solid #000; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match {
|
||||
display: none; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls {
|
||||
padding: 0 0 5px 18px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .filter {
|
||||
width: 240px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_left, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_right {
|
||||
display: inline-block;
|
||||
cursor: pointer; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_left {
|
||||
margin-right: 10px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_left.disabled, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls .pager_control_right.disabled {
|
||||
color: #ddd;
|
||||
cursor: default; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .show_more {
|
||||
display: inline-block;
|
||||
margin-left: 18px;
|
||||
margin-top: 5px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create {
|
||||
display: none;
|
||||
margin: 0 15px;
|
||||
border: 1px solid #d5d5d5;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
overflow: auto; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .quick_add {
|
||||
margin-bottom: 10px;
|
||||
clear: both; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .quick_add:empty {
|
||||
display: none; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .quick_add:empty {
|
||||
display: none; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table {
|
||||
width: 49%;
|
||||
height: 26px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table:nth-child(2n+1) {
|
||||
float: left;
|
||||
clear: left; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table:nth-child(2n) {
|
||||
float: right;
|
||||
clear: right; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table th {
|
||||
font-weight: bold;
|
||||
line-height: 26px;
|
||||
padding-right: 8px;
|
||||
min-width: 100px;
|
||||
border-right: 1px solid #ddd;
|
||||
white-space: nowrap;
|
||||
width: 1%; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table td {
|
||||
width: 99%;
|
||||
padding-left: 8px; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table input, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table select {
|
||||
width: 100%; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table.add_line_container:nth-child(2n+1) {
|
||||
width: 98%;
|
||||
float: none;
|
||||
margin: auto; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table.add_line_container td {
|
||||
text-align: center; }
|
||||
.openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .create .oe_form > table.add_line_container .add_line {
|
||||
line-height: 26px; }
|
||||
@@ -0,0 +1,38 @@
|
||||
.dashboard_journal_code {
|
||||
font-size: 10px;
|
||||
}
|
||||
.dashboard-right-separator {
|
||||
border-right-style: solid;
|
||||
border-right-width: thin;
|
||||
border-right-color: darkgray;
|
||||
}
|
||||
.dashboard-header-dropdown {
|
||||
margin-top: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.dashboard-journal-head {
|
||||
min-height: 60px;
|
||||
}
|
||||
.journal-dashboard-text-right {
|
||||
text-align: right !important;
|
||||
/*font-size: 10px;*/
|
||||
}
|
||||
.dashboard-dropdown {
|
||||
color: black !important;
|
||||
/*padding: 3px 25px;*/
|
||||
width: 400px;
|
||||
}
|
||||
.dashboard-star {
|
||||
font-size: 12px !important;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.dashboard-dropdown table td {
|
||||
border-top: none !important;
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
.dashboard-kanban-graph {
|
||||
height: 75px;
|
||||
}
|
||||
.oe_empty_dashboard_info_row {
|
||||
height: 84px;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
.openerp .oe_vm_switch_tree_account_move_line_quickadd:after {
|
||||
padding: 2px;
|
||||
content: "i";
|
||||
}
|
||||
|
||||
.oe-vm-switch-tree_account_move_line_quickadd:before {
|
||||
content: "";
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
.openerp .oe_account_reconciliation {
|
||||
border-bottom: 1px solid #CACACA;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.openerp .oe_account_reconciliation button {
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.openerp .oe_account_reconciliation>div {
|
||||
display: table;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.openerp .oe_account_reconciliation>div>div {
|
||||
display: table-cell;
|
||||
width: 50%:
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
.openerp .oe_reconciliation {
|
||||
font-size: 12px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
/* icons */ }
|
||||
.openerp .oe_reconciliation .oe_form_sheetbg {
|
||||
padding-top: 0; }
|
||||
.openerp .oe_reconciliation .oe_form_sheetbg .oe_form_sheet {
|
||||
position: relative;
|
||||
padding: 20px 15px 20px 15px;
|
||||
border-top: 0;
|
||||
height: 100%; }
|
||||
.openerp .oe_reconciliation .clearer {
|
||||
clear: both; }
|
||||
.openerp .oe_reconciliation .oe_view_nocontent {
|
||||
max-width: none; }
|
||||
.openerp .oe_reconciliation .oe_view_nocontent > p {
|
||||
padding: 0 10%; }
|
||||
.openerp .oe_reconciliation h1 input, .openerp .oe_reconciliation h2 input {
|
||||
height: auto !important; }
|
||||
.openerp .oe_reconciliation h1 {
|
||||
width: 48%;
|
||||
padding: 0 0 0 15px;
|
||||
margin: 0 0 25px 0;
|
||||
float: left;
|
||||
font-size: 2em;
|
||||
height: 1.5em; }
|
||||
.openerp .oe_reconciliation .statement_name span {
|
||||
line-height: 1.5em;
|
||||
cursor: pointer; }
|
||||
.openerp .oe_reconciliation .change_statement_name_container {
|
||||
display: none;
|
||||
width: 95%; }
|
||||
.openerp .oe_reconciliation .change_statement_name_container td:first-child, .openerp .oe_reconciliation .change_statement_name_container td:first-child > input {
|
||||
width: 99%; }
|
||||
.openerp .oe_reconciliation .change_statement_name_container td:last-child {
|
||||
width: 1%;
|
||||
padding-left: 3px; }
|
||||
.openerp .oe_reconciliation .change_statement_name_container td:last-child button {
|
||||
height: 100%;
|
||||
box-sizing: content-box; }
|
||||
.openerp .oe_reconciliation h2 {
|
||||
font-size: 1.8em; }
|
||||
.openerp .oe_reconciliation .progress {
|
||||
width: 49%;
|
||||
margin: 10px 15px 0 0;
|
||||
float: right;
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
.openerp .oe_reconciliation .progress .progress-text {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
z-index: 10;
|
||||
text-shadow: -1px -1px 0 #f5f5f5, 1px -1px 0 #f5f5f5, -1px 1px 0 #f5f5f5, 1px 1px 0 #f5f5f5; }
|
||||
.openerp .oe_reconciliation .show_more_container {
|
||||
text-align: center; }
|
||||
.openerp .oe_reconciliation .show_more_container .show_more {
|
||||
display: none; }
|
||||
.openerp .oe_reconciliation .notification_area {
|
||||
margin: 0 15px; }
|
||||
.openerp .oe_reconciliation .notification_area .fa {
|
||||
font-size: 20px;
|
||||
margin-left: 7px;
|
||||
line-height: 14px;
|
||||
position: relative;
|
||||
top: 3px; }
|
||||
.openerp .oe_reconciliation .interface_options {
|
||||
margin-bottom: 25px;
|
||||
padding-left: 15px; }
|
||||
.openerp .oe_reconciliation .interface_options .oe_radio_input {
|
||||
border: none;
|
||||
display: inline; }
|
||||
.openerp .oe_reconciliation .protip {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
bottom: 7px;
|
||||
right: 15px;
|
||||
text-align: right;
|
||||
color: #bbb; }
|
||||
.openerp .oe_reconciliation .done_message {
|
||||
width: 100%;
|
||||
padding: 0 20%;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 50px; }
|
||||
.openerp .oe_reconciliation .done_message h2 {
|
||||
margin-bottom: 30px; }
|
||||
.openerp .oe_reconciliation .done_message h2 .congrats_icon {
|
||||
float: right;
|
||||
font-size: 2em;
|
||||
position: relative;
|
||||
top: -0.25em; }
|
||||
.openerp .oe_reconciliation .done_message .achievements {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
position: relative; }
|
||||
.openerp .oe_reconciliation .done_message .achievements .achievement {
|
||||
font-size: 4em;
|
||||
margin: 0 0.3em;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.2); }
|
||||
.openerp .oe_reconciliation .done_message .achievements .achievement i {
|
||||
font-size: 0.5em;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -0.55em;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center; }
|
||||
.openerp .oe_reconciliation .done_message .action_buttons {
|
||||
text-align: center; }
|
||||
.openerp .oe_reconciliation .glyphicon {
|
||||
font-size: 12px !important; }
|
||||
.openerp .oe_reconciliation .glyphicon.line_info_button {
|
||||
color: #ccc !important; }
|
||||
.openerp .oe_reconciliation .accounting_view .glyphicon-add-remove:before {
|
||||
content: "\2212"; }
|
||||
.openerp .oe_reconciliation .match .glyphicon-add-remove:before {
|
||||
content: "\2b"; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line {
|
||||
margin-bottom: 30px;
|
||||
/* gap between accounting_view and action view */
|
||||
/* popover */
|
||||
/* arrays of move lines */
|
||||
/* Partie infos */
|
||||
/* Match view */
|
||||
/* Action create */ }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line table {
|
||||
width: 100%; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .toggle_match, .openerp .oe_reconciliation .oe_reconciliation_line .toggle_create {
|
||||
-webkit-transition-property: -webkit-transform;
|
||||
-moz-transition-property: -moz-transform;
|
||||
-ms-transition-property: -ms-transform;
|
||||
-o-transition-property: -o-transform;
|
||||
transition-property: transform;
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
-webkit-transition-duration: 300ms;
|
||||
-moz-transition-duration: 300ms;
|
||||
-ms-transition-duration: 300ms;
|
||||
-o-transition-duration: 300ms;
|
||||
transition-duration: 300ms; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .visible_toggle, .openerp .oe_reconciliation .oe_reconciliation_line[data-mode="match"] .toggle_match, .openerp .oe_reconciliation .oe_reconciliation_line[data-mode="create"] .toggle_create, .openerp .oe_reconciliation .oe_reconciliation_line[data-mode="create"].no_partner .toggle_match {
|
||||
visibility: visible !important;
|
||||
-webkit-transform: rotate(90deg);
|
||||
-moz-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
-o-transform: rotate(90deg);
|
||||
transform: rotate(90deg); }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .partner_name .change_partner {
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
margin: 0 10px 0 5px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .partner_name:hover .change_partner {
|
||||
display: inline; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .change_partner_container {
|
||||
width: 200px;
|
||||
display: none;
|
||||
position: relative !important; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line[data-mode="inactive"] .initial_line > td {
|
||||
background-color: #f8f8f8 !important; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line.no_match:not(.no_partner) .initial_line {
|
||||
cursor: default !important; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line.no_match:not(.no_partner) .initial_line .line_info_button {
|
||||
cursor: pointer; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line.no_match:not(.no_partner) .toggle_match {
|
||||
visibility: hidden !important; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line > table > tbody > tr:nth-child(1) > td table {
|
||||
margin-bottom: 10px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line table.details td:first-child {
|
||||
padding-right: 10px;
|
||||
font-weight: bold; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line table.details tr.one_line_info td {
|
||||
padding-top: 10px;
|
||||
text-align: center;
|
||||
color: #44c; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view, .openerp .oe_reconciliation .oe_reconciliation_line .match table {
|
||||
width: 100%; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tbody tr, .openerp .oe_reconciliation .oe_reconciliation_line .match table tbody tr {
|
||||
cursor: pointer; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr.already_reconciled, .openerp .oe_reconciliation .oe_reconciliation_line .match table tr.already_reconciled {
|
||||
color: #44c; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td, .openerp .oe_reconciliation .oe_reconciliation_line .match table td {
|
||||
padding: 1px 8px;
|
||||
vertical-align: middle; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_action, .openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_info_popover, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_action, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_info_popover {
|
||||
width: 15px;
|
||||
padding: 0; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_action, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_action {
|
||||
text-align: left; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_account_code, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_account_code {
|
||||
width: 80px;
|
||||
padding-left: 3px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_due_date, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_due_date {
|
||||
width: 100px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_debit, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_debit {
|
||||
text-align: right;
|
||||
width: 15%; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_credit, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_credit {
|
||||
width: 15%;
|
||||
text-align: right;
|
||||
padding-right: 3px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_info_popover, .openerp .oe_reconciliation .oe_reconciliation_line .match table td.cell_info_popover {
|
||||
text-align: right; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr.line_open_balance, .openerp .oe_reconciliation .oe_reconciliation_line .match table tr.line_open_balance {
|
||||
color: #bbb; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr .glyphicon:not(.line_info_button), .openerp .oe_reconciliation .oe_reconciliation_line .match table tr .glyphicon:not(.line_info_button) {
|
||||
visibility: hidden;
|
||||
color: #555; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr:hover .glyphicon, .openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr:focus .glyphicon, .openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr.active .glyphicon, .openerp .oe_reconciliation .oe_reconciliation_line .match table tr:hover .glyphicon, .openerp .oe_reconciliation .oe_reconciliation_line .match table tr:focus .glyphicon, .openerp .oe_reconciliation .oe_reconciliation_line .match table tr.active .glyphicon {
|
||||
visibility: visible; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr .do_partial_reconcile_button, .openerp .oe_reconciliation .oe_reconciliation_line .match table tr .do_partial_reconcile_button {
|
||||
color: #f0ad4e;
|
||||
padding-right: 5px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view tr .undo_partial_reconcile_button, .openerp .oe_reconciliation .oe_reconciliation_line .match table tr .undo_partial_reconcile_button {
|
||||
color: #555;
|
||||
padding-right: 5px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view {
|
||||
border-collapse: separate; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view .initial_line > td {
|
||||
border-top: 1px solid #bbb;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 5px;
|
||||
background-color: #f0f0f0;
|
||||
-webkit-transition-property: background-color;
|
||||
-moz-transition-property: background-color;
|
||||
-ms-transition-property: background-color;
|
||||
transition-property: background-color;
|
||||
-webkit-transition-duration: 300ms;
|
||||
-moz-transition-duration: 300ms;
|
||||
-ms-transition-duration: 300ms;
|
||||
-o-transition-duration: 300ms;
|
||||
transition-duration: 300ms; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view .initial_line > td.cell_action, .openerp .oe_reconciliation .oe_reconciliation_line .accounting_view .initial_line > td.cell_info_popover {
|
||||
border-top: none;
|
||||
background: white !important;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 3px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view caption {
|
||||
text-align: left;
|
||||
height: 26px;
|
||||
margin: 0 15px 4px 15px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view caption .partner_name {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view caption .tip_reconciliation_not_balanced {
|
||||
float: right;
|
||||
padding-right: 7px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view caption button {
|
||||
float: right;
|
||||
position: relative;
|
||||
top: -4px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view caption button:disabled {
|
||||
opacity: 0.5; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view caption > span, .openerp .oe_reconciliation .oe_reconciliation_line .accounting_view caption > input {
|
||||
position: relative;
|
||||
top: 7px;
|
||||
/* meh */ }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .accounting_view td.cell_credit {
|
||||
border-left: 1px solid #000; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .match {
|
||||
display: none;
|
||||
padding: 1px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .match .match_controls {
|
||||
padding: 0 0 5px 18px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .match .match_controls .filter {
|
||||
width: 240px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .match .match_controls .pager_control_left, .openerp .oe_reconciliation .oe_reconciliation_line .match .match_controls .pager_control_right {
|
||||
display: inline-block;
|
||||
cursor: pointer; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .match .match_controls .pager_control_left {
|
||||
margin-right: 10px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .match .match_controls .pager_control_left.disabled, .openerp .oe_reconciliation .oe_reconciliation_line .match .match_controls .pager_control_right.disabled {
|
||||
color: #ddd;
|
||||
cursor: default; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .match .show_more {
|
||||
display: inline-block;
|
||||
margin-left: 18px;
|
||||
margin-top: 5px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create {
|
||||
display: none;
|
||||
margin: 0 15px;
|
||||
border: 1px solid #d5d5d5;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
overflow: auto; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .quick_add {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
clear: both; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .quick_add:empty {
|
||||
display: none; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .quick_add .presets_config {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 100; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .quick_add .presets_config .dropdown-menu {
|
||||
font-size: 1em; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .quick_add:hover .presets_config, .openerp .oe_reconciliation .oe_reconciliation_line .create .quick_add .presets_config.open {
|
||||
display: inline; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table {
|
||||
width: 49%;
|
||||
height: 26px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table:nth-child(2n+1) {
|
||||
float: left;
|
||||
clear: left; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table:nth-child(2n) {
|
||||
float: right;
|
||||
clear: right; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table th {
|
||||
font-weight: bold;
|
||||
line-height: 26px;
|
||||
padding-right: 8px;
|
||||
min-width: 100px;
|
||||
border-right: 1px solid #ddd;
|
||||
white-space: nowrap;
|
||||
width: 1%; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table td {
|
||||
width: 99%;
|
||||
padding-left: 8px; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table input, .openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table select {
|
||||
width: 100%; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table.add_line_container:nth-child(2n+1) {
|
||||
width: 98%;
|
||||
float: none;
|
||||
margin: auto; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table.add_line_container td {
|
||||
text-align: center; }
|
||||
.openerp .oe_reconciliation .oe_reconciliation_line .create .oe_form > table.add_line_container .add_line {
|
||||
line-height: 26px; }
|
||||
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .button_reconcile {
|
||||
float: right;
|
||||
position: relative;
|
||||
top: 1.1em; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead {
|
||||
background: none; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead td {
|
||||
vertical-align: bottom !important; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead td:nth-child(2) {
|
||||
padding-left: 0; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead .cell_item_name {
|
||||
display: inline-block;
|
||||
min-width: 135px; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead .cell_last_time_entries_checked {
|
||||
font-weight: normal;
|
||||
display: inline-block; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead .cell_item_name + .cell_last_time_entries_checked {
|
||||
padding-left: 20px; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead .cell_title_account_code {
|
||||
text-align: center; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead tr:first-child td {
|
||||
border-bottom: 1px solid #bbb; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead tr:first-child td.cell_action, .openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead tr:first-child td.cell_info_popover {
|
||||
border-bottom: none; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view thead tr:first-child td.cell_title_account_code {
|
||||
border-bottom: 1px solid #000 !important; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view .filler_line td {
|
||||
height: 22px;
|
||||
cursor: default !important; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line .accounting_view tbody.tbody_matched_lines tr:first-child td {
|
||||
padding-top: 4px; }
|
||||
.openerp .oe_manual_reconciliation .oe_manual_reconciliation_line td.cell_due_date {
|
||||
padding-left: 3px !important; }
|
||||
@@ -8,7 +8,7 @@ $infoColor: #44c;
|
||||
$aestetic_animation_speed: 300ms;
|
||||
|
||||
|
||||
.openerp .oe_bank_statement_reconciliation {
|
||||
.openerp .oe_reconciliation {
|
||||
font-size: 12px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
@@ -30,6 +30,25 @@ $aestetic_animation_speed: 300ms;
|
||||
}
|
||||
}
|
||||
|
||||
// For future ⌨ navigation
|
||||
// *[tabindex='0']:focus {
|
||||
// outline: 1px solid #888;
|
||||
// outline-offset: 2px;
|
||||
// outline-color: invert;
|
||||
// }
|
||||
|
||||
.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.oe_view_nocontent {
|
||||
max-width: none;
|
||||
|
||||
> p {
|
||||
padding: 0 10%;
|
||||
}
|
||||
}
|
||||
|
||||
h1 input, h2 input {
|
||||
height: auto !important;
|
||||
}
|
||||
@@ -192,8 +211,8 @@ $aestetic_animation_speed: 300ms;
|
||||
content: "\2b";
|
||||
}
|
||||
|
||||
// bankStatementReconciliationLine widget
|
||||
.oe_bank_statement_reconciliation_line {
|
||||
// reconciliationLine widget
|
||||
.oe_reconciliation_line {
|
||||
margin-bottom: 30px;
|
||||
|
||||
table {
|
||||
@@ -256,6 +275,12 @@ $aestetic_animation_speed: 300ms;
|
||||
.toggle_create {
|
||||
@extend .visible_toggle;
|
||||
}
|
||||
|
||||
&.no_partner {
|
||||
.toggle_match {
|
||||
@extend .visible_toggle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[data-mode="inactive"] {
|
||||
@@ -442,7 +467,7 @@ $aestetic_animation_speed: 300ms;
|
||||
/* Match view */
|
||||
.match {
|
||||
display: none;
|
||||
|
||||
padding: 1px;
|
||||
.match_controls {
|
||||
padding: 0 0 5px ($actionColWidth+$mainTableBordersPadding);
|
||||
|
||||
@@ -483,15 +508,29 @@ $aestetic_animation_speed: 300ms;
|
||||
overflow: auto;
|
||||
|
||||
.quick_add {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
clear: both;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.quick_add:empty {
|
||||
display: none;
|
||||
|
||||
.presets_config {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
|
||||
.dropdown-menu {
|
||||
font-size: 1em; // Since there's no dropdown-menu-sm class in bootstrap
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .presets_config, .presets_config.open {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.oe_form > table {
|
||||
@@ -539,3 +578,70 @@ $aestetic_animation_speed: 300ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.openerp .oe_manual_reconciliation {
|
||||
.oe_manual_reconciliation_line {
|
||||
.button_reconcile {
|
||||
float: right;
|
||||
position: relative;
|
||||
top: 1.1em;
|
||||
}
|
||||
|
||||
.accounting_view {
|
||||
thead {
|
||||
background: none;
|
||||
|
||||
td {
|
||||
vertical-align: bottom !important;
|
||||
}
|
||||
|
||||
td:nth-child(2) {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.cell_item_name {
|
||||
display: inline-block;
|
||||
min-width: 135px;
|
||||
}
|
||||
|
||||
.cell_last_time_entries_checked {
|
||||
font-weight: normal;
|
||||
display: inline-block;
|
||||
}
|
||||
.cell_item_name + .cell_last_time_entries_checked {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.cell_title_account_code {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tr:first-child td {
|
||||
border-bottom: $lightBorder;
|
||||
|
||||
&.cell_action, &.cell_info_popover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.cell_title_account_code {
|
||||
border-bottom: 1px solid #000 !important;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.filler_line td {
|
||||
height: 22px;
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
tbody.tbody_matched_lines tr:first-child td {
|
||||
padding-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
td.cell_due_date {
|
||||
padding-left: $mainTableBordersPadding !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,98 @@
|
||||
odoo.define('journal_dashboard', function (require) {
|
||||
'use strict';
|
||||
|
||||
var kanban_common = require('web_kanban.common');
|
||||
|
||||
var JournalDashboardGraph = kanban_common.AbstractField.extend({
|
||||
start: function() {
|
||||
var self = this;
|
||||
self.graph_type = self.$node.attr('graph_type')
|
||||
self.display_graph(JSON.parse(self.field.raw_value));
|
||||
},
|
||||
display_graph : function(data) {
|
||||
var self = this;
|
||||
nv.addGraph(function () {
|
||||
self.$el.append('<svg style="height:75px; overflow:visible;">');
|
||||
var type = self.graph_type
|
||||
switch(type) {
|
||||
case "line":
|
||||
var chart = nv.models.lineChart();
|
||||
chart.dispatch.on('tooltipShow', function(){console.log(arguments);})
|
||||
chart.options({
|
||||
x: function(d,u) { return u},
|
||||
width: self.$el.find('svg').width(),
|
||||
height: self.$el.find('svg').height(),
|
||||
margin: {'left': 15, 'right':10, 'top':10, 'bottom': 20},
|
||||
showYAxis: false,
|
||||
showLegend: false,
|
||||
tooltips: true,
|
||||
tooltipContent: function(key, x, y, e, graph) {
|
||||
var header = "";
|
||||
$.each(e.series.values, function(k,v){
|
||||
if (v.x === x){
|
||||
header = v.name;
|
||||
}
|
||||
});
|
||||
return '<h3>' + header + '</h3> <p> Balance ' + y + '</p>'},
|
||||
});
|
||||
chart.xAxis
|
||||
.tickFormat(function(d) {
|
||||
var label = '';
|
||||
$.each(data, function(el){
|
||||
if (data[el].values[d] && data[el].values[d].x){
|
||||
label = data[el].values[d].x;
|
||||
}
|
||||
});
|
||||
return label;
|
||||
})
|
||||
.showMaxMin(false);
|
||||
break;
|
||||
case "bar":
|
||||
var bar_color = [];
|
||||
$.each(data[0].values, function(k,v){
|
||||
bar_color.push(v.color);
|
||||
})
|
||||
var chart = nv.models.discreteBarChart()
|
||||
.x(function(d) { return d.label })
|
||||
.y(function(d) { return d.value })
|
||||
.width(self.$el.find('svg').width())
|
||||
.height(self.$el.find('svg').height())
|
||||
.showValues(false)
|
||||
.showYAxis(false)
|
||||
.color(bar_color)
|
||||
.margin({'left': 15, 'right':10, 'top':10, 'bottom': 25})
|
||||
.tooltips(true);
|
||||
chart.xAxis.axisLabel(data[0].title);
|
||||
chart.yAxis.tickFormat(d3.format(',.2f'));
|
||||
break;
|
||||
}
|
||||
self.svg = self.$el.find('svg')[0];
|
||||
d3.select(self.svg)
|
||||
.datum(data)
|
||||
.transition().duration(1200)
|
||||
.call(chart);
|
||||
nv.utils.windowResize(function() { d3.select(self.svg).call(chart.width(self.$el.find('svg').width()).height(self.$el.find('svg').height())); self.postprocess(); });
|
||||
|
||||
});
|
||||
//ugly, need to do something else
|
||||
setTimeout(function(){self.postprocess();},2000);
|
||||
|
||||
|
||||
},
|
||||
postprocess: function(){
|
||||
var low_rect = $(this.svg).find('rect').filter(function(){return $(this).attr('height') < 1.0 })
|
||||
low_rect.attr('height', 1);
|
||||
},
|
||||
});
|
||||
|
||||
var JournalDashboard = kanban_common.AbstractField.extend({
|
||||
start: function(){
|
||||
//used to set 2 dashboard per line
|
||||
this.$el.parents('.oe_kanban_record').addClass('col-md-6');
|
||||
},
|
||||
});
|
||||
|
||||
kanban_common.registry.add('dashboard_graph', JournalDashboardGraph);
|
||||
kanban_common.registry.add('dashboard_journal', JournalDashboard);
|
||||
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
odoo.define('account.payment', function (require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var form_common = require('web.form_common');
|
||||
var formats = require('web.formats');
|
||||
var Model = require('web.Model');
|
||||
|
||||
var QWeb = core.qweb;
|
||||
|
||||
var ShowPaymentLineWidget = form_common.AbstractField.extend({
|
||||
render_value: function() {
|
||||
var self = this;
|
||||
var info = JSON.parse(this.get('value'));
|
||||
var invoice_id = info.invoice_id;
|
||||
if (info !== false) {
|
||||
_.each(info.content, function(k,v){
|
||||
k.amount = formats.format_value(k.amount, {type: "float", digits: k.digits});
|
||||
if (k.date){
|
||||
k.date = formats.format_value(k.date, {type: "date"});
|
||||
}
|
||||
});
|
||||
this.$el.html(QWeb.render('ShowPaymentInfo', {
|
||||
'lines': info.content,
|
||||
'outstanding': info.outstanding,
|
||||
'title': info.title
|
||||
}));
|
||||
this.$('.outstanding_credit_assign').click(function(){
|
||||
var id = $(this).data('id') || false;
|
||||
new Model("account.invoice")
|
||||
.call("assign_outstanding_credit", [invoice_id, id])
|
||||
.then(function (result) {
|
||||
self.view.reload();
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.$el.html('');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
core.form_widget_registry.add('payment', ShowPaymentLineWidget);
|
||||
|
||||
});
|
||||
@@ -11,7 +11,6 @@ Tour.register({
|
||||
name: _t("Reconcile the demo bank statement"),
|
||||
path: '/web',
|
||||
mode: 'test',
|
||||
// TODO : identify menu by data-menu attr or text node ?
|
||||
steps: [
|
||||
// Go to the first statement reconciliation
|
||||
{
|
||||
@@ -31,7 +30,7 @@ Tour.register({
|
||||
element: '.oe_form_container header button:contains("Reconcile")',
|
||||
},
|
||||
|
||||
|
||||
|
||||
// Check mutual exclusion of move lines
|
||||
{
|
||||
title: "set second reconciliation in match mode",
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="bank_statement_nothing_to_reconcile">
|
||||
<div class="oe_form_sheetbg"><div class="oe_form_sheet oe_form_sheet_width">
|
||||
<div class="notification_area"></div>
|
||||
<div class="oe_view_nocontent"><p>
|
||||
<b>Good Job!</b> Bank statements are fully reconciled.</p>
|
||||
<p>This page displays all the bank transactions that are to be reconciled and provides with a neat interface to do so.</p>
|
||||
</div>
|
||||
</div></div>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation">
|
||||
<div class="oe_form_sheetbg"><div class="oe_form_sheet oe_form_sheet_width">
|
||||
<t t-if="single_statement">
|
||||
<h1 class="statement_name">
|
||||
<span><t t-esc="title"/></span>
|
||||
<table class="change_statement_name_container oe_form"><tr>
|
||||
<td><input class="change_statement_name_field" type="text"/></td>
|
||||
<td><button class="change_statement_name_button btn btn-primary btn-sm">OK</button></td>
|
||||
</tr></table>
|
||||
</h1>
|
||||
</t>
|
||||
<t t-if="!single_statement">
|
||||
<h1><t t-esc="title"/></h1>
|
||||
</t>
|
||||
<div class="progress progress-striped">
|
||||
<div class="progress-text"><span class="valuenow">0</span> / <span class="valuemax"><t t-esc="total_lines"/></span></div>
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" t-att-aria-valuemax="total_lines" style="width: 0%;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_clear"></div>
|
||||
<div class="notification_area"></div>
|
||||
<div class="reconciliation_lines_container"></div>
|
||||
<div class="show_more_container"><button class="show_more">Show more... (<span class="num_items_remaining"></span> remaining)</button></div>
|
||||
<p class='protip'>Tip : Hit ctrl-enter to validate the whole sheet.</p>
|
||||
</div></div>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_done_message">
|
||||
<div class='done_message'>
|
||||
<h2><t t-raw="title" /></h2>
|
||||
<p>It took you <strong><t t-esc="time_taken" /></strong> to reconcile <strong><t t-esc="transactions_done" /> transactions.<br/></strong> That's on average <t t-esc="sec_per_item" /> seconds per transaction.</p>
|
||||
<t t-if="done_with_ctrl_enter !== 0">
|
||||
<p>You validated <t t-esc="done_with_ctrl_enter" /> reconciliations with the ctrl-enter shortcut.</p>
|
||||
</t>
|
||||
<p class='achievements'>
|
||||
<t t-foreach="achievements" t-as="achievement">
|
||||
<i class='fa fa-certificate achievement' t-att-data-title='achievement.title' t-att-data-content='achievement.desc'><i t-att-class="'fa '+achievement.icon"></i></i>
|
||||
</t>
|
||||
</p>
|
||||
<p class="action_buttons">
|
||||
<t t-if="single_statement or multiple_statements">
|
||||
<button class="button_back_to_statement btn btn-default btn-sm">Back to statements list</button>
|
||||
<button class="button_close_statement btn btn-primary btn-sm">Close the statement<t t-if="multiple_statements">s</t></button>
|
||||
</t>
|
||||
</p>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_notification">
|
||||
<div t-att-class="'notification alert-dismissible alert alert-' + type" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true" class="glyphicon glyphicon-remove"></span><span class="sr-only">Close</span></button>
|
||||
<t t-esc="message" />
|
||||
<t t-if="details !== undefined">
|
||||
<i class="fa fa-external-link" rel="do_action" href="javascript:void(0)"
|
||||
t-att-data-action_nam="details.name"
|
||||
t-att-data-model="details.model"
|
||||
t-att-data-ids="details.ids"/>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_line">
|
||||
<table t-att-data-mode="mode">
|
||||
<tr>
|
||||
<td>
|
||||
<table class="accounting_view">
|
||||
<caption>
|
||||
<button class="button_ok btn btn-default btn-sm"></button>
|
||||
<span class="tip_reconciliation_not_balanced">You must balance the reconciliation</span>
|
||||
<span t-if="! line.has_no_partner" class="partner_name">
|
||||
<t t-esc="line.partner_name"/>
|
||||
<span class="change_partner glyphicon glyphicon-pencil"></span>
|
||||
</span>
|
||||
<div class="change_partner_container oe_form"></div>
|
||||
</caption>
|
||||
<tbody class="tbody_initial_line">
|
||||
<tr class="initial_line">
|
||||
<td class="cell_action"><span class="toggle_match glyphicon glyphicon-cog"></span></td>
|
||||
<td class="cell_account_code"><t t-esc="line.account_code"/></td>
|
||||
<td class="cell_due_date"><t t-esc="line.date"/></td>
|
||||
<td class="cell_label">
|
||||
<t t-if="line.name" t-esc="line.name"/>
|
||||
<t t-if="line.ref"> : <t t-esc="line.ref" /></t>
|
||||
<t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t></td>
|
||||
<td class="cell_debit"><t t-if="line.amount > 0">
|
||||
<t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_credit"><t t-if="line.amount < 0">
|
||||
<t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_info_popover"><span class="line_info_button glyphicon glyphicon-info-sign" t-att-data-content="line.q_popover"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody class="tbody_matched_lines"></tbody>
|
||||
<tbody class="tbody_created_lines"></tbody>
|
||||
<tbody class="tbody_open_balance"></tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="action_pane match">
|
||||
<div class="match_controls">
|
||||
<input type="text" class="filter" placeholder="Filter" value="" />
|
||||
<span class="pager_control_right pull-right glyphicon glyphicon-chevron-right"></span>
|
||||
<span class="pager_control_left pull-right glyphicon glyphicon-chevron-left"></span>
|
||||
</div>
|
||||
<table></table>
|
||||
</div>
|
||||
|
||||
<div class="action_pane create">
|
||||
<!-- NB : I use a .quick_add:empty selector. whitespace characters being a node, there shall be none -->
|
||||
<div class="quick_add btn-group btn-group-sm"><t t-foreach="presets" t-as="preset"><button type='button' class='btn btn-default preset' t-att-data-presetid="preset.id"><t t-esc="preset.name"/></button></t></div>
|
||||
<div class="oe_form create_form">
|
||||
<!-- here come some form_create_field -->
|
||||
<table class="create_field add_line_container"><tr><td><a href="javascript:void(0)" class="add_line">New</a></td></tr></table>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="filter_no_match">
|
||||
<tr><td style='text-align: center;'>No result matching '<t t-esc="filter_str" />'</td></tr>
|
||||
</t>
|
||||
|
||||
<t t-name="form_create_field">
|
||||
<table t-att-class='"create_field create_"+id'><tr>
|
||||
<th><t t-esc="label"/></th>
|
||||
<td class="create_account_container" t-att-class='"create_"+id+"_container"'></td>
|
||||
</tr></table>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_line_details">
|
||||
<table class='details'>
|
||||
<tr><td>Date</td><td><t t-esc="line.date"/></td></tr>
|
||||
<tr t-if="line.partner_name"><td>Partner</td><td><t t-esc="line.partner_name"/></td></tr>
|
||||
<tr t-if="line.ref"><td>Transaction</td><td><t t-esc="line.ref"/></td></tr>
|
||||
<tr><td>Description</td><td><t t-esc="line.name"/></td></tr>
|
||||
<tr><td>Amount</td><td><t t-esc="line.amount_str"/><t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t></td></tr>
|
||||
<tr><td>Account</td><td><t t-esc="line.account_code"/> <t t-esc="line.account_name"/></td></tr>
|
||||
<tr t-if="line.note"><td>Note</td><td><t t-esc="line.note"/></td></tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_move_line">
|
||||
<tr t-att-class="'mv_line'+(line.already_paid ? ' already_reconciled' : '')" t-att-data-lineid="line.id" t-att-data-selected="selected">
|
||||
<td class="cell_action"><span class="glyphicon glyphicon-add-remove"></span></td>
|
||||
<td class="cell_account_code" t-if="line.account_code"><t t-esc="line.account_code"/></td>
|
||||
<td class="cell_due_date"><t t-esc="line.q_due_date"/></td>
|
||||
<td class="cell_label js_qlabel"><t t-esc="line.q_label"/></td>
|
||||
<td class="cell_debit"><t t-if="line.debit !== 0"><t t-if="line.propose_partial_reconcile" t-call="icon_do_partial_reconciliation"></t><t t-if="line.partial_reconcile" t-call="icon_undo_partial_reconciliation"></t><t t-esc="line.debit_str"/></t></td>
|
||||
<td class="cell_credit"><t t-if="line.credit !== 0"><t t-if="line.propose_partial_reconcile"><t t-call="icon_do_partial_reconciliation" /></t><t t-if="line.partial_reconcile"><t t-call="icon_undo_partial_reconciliation" /></t><t t-esc="line.credit_str"/></t></td>
|
||||
<td class="cell_info_popover"><span class="line_info_button glyphicon glyphicon-info-sign" t-att-data-content="line.q_popover"></span></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="icon_do_partial_reconciliation"><i class="do_partial_reconcile_button fa fa-exclamation-triangle" data-content="Click to register a partial payment and keep the invoice open. Otherwise it does a full reconciliation."></i></t>
|
||||
|
||||
<t t-name="icon_undo_partial_reconciliation"><i class="undo_partial_reconcile_button fa fa-exclamation-triangle" data-content="Undo the partial reconciliation."></i></t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_move_line_details">
|
||||
<table class='details'>
|
||||
<tr t-if="line.account_code"><td>Account</td><td><t t-esc="line.account_code"/> <t t-esc="line.account_name"/></td></tr>
|
||||
<tr><td>Journal</td><td><t t-esc="line.journal_name"/></td></tr>
|
||||
<tr><td>Period</td><td><t t-esc="line.period_name"/></td></tr>
|
||||
<tr><td>Date</td><td><t t-esc="line.date"/></td></tr>
|
||||
<tr><td>Due Date</td><td><t t-esc="line.q_due_date"/></td></tr>
|
||||
<t t-if="line.is_partially_reconciled">
|
||||
<tr><td>Total</td><td>
|
||||
<t t-esc="line.total_amount_str"/><t t-if="line.total_amount_currency_str"> (<t t-esc="line.total_amount_currency_str"/>)</t>
|
||||
</td></tr>
|
||||
</t>
|
||||
<tr><td><t t-if="line.is_partially_reconciled">Residual</t><t t-if="! line.is_partially_reconciled">Amount</t></td><td>
|
||||
<t t-if="line.debit !== 0" t-esc="line.debit_str"/><t t-if="line.credit !== 0" t-esc="line.credit_str"/>
|
||||
<t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t>
|
||||
</td></tr>
|
||||
<tr class="one_line_info" t-if='line.already_paid'>
|
||||
<td colspan="2">This payment is registered but not reconciled.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_created_line">
|
||||
<tr class="created_line" t-att-data-lineid="line.id">
|
||||
<td class="cell_action"><t t-if="! line.no_remove_action"><span class="glyphicon glyphicon-remove"></span></t></td>
|
||||
<td class="cell_account_code"><t t-esc="line.account_num"/></td>
|
||||
<td class="cell_due_date"></td>
|
||||
<td class="cell_label"><t t-esc="line.label"/></td>
|
||||
<td class="cell_debit"><t t-if="line.amount < 0"><t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_credit"><t t-if="line.amount > 0"><t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_info_popover"></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_line_open_balance">
|
||||
<tr class="line_open_balance">
|
||||
<td class="cell_action"><span class="toggle_create glyphicon glyphicon-play"></span></td>
|
||||
<td class="cell_account_code"><t t-esc="account_code"/></td>
|
||||
<td class="cell_due_date"></td>
|
||||
<td class="cell_label">Open balance</td>
|
||||
<td class="cell_debit"><t t-esc="debit"/></td>
|
||||
<td class="cell_credit"><t t-esc="credit"/></td>
|
||||
<td class="cell_info_popover"></td>
|
||||
</tr>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="AccountMoveLineQuickAdd">
|
||||
<div class="oe_account_quickadd ui-toolbar" style="margin-bottom:0px;">
|
||||
<div class="oe_form_dropdown_section">
|
||||
<h4>Period :</h4>
|
||||
<select class="oe_account_select_period">
|
||||
|
||||
</select>
|
||||
</div>
|
||||
<div class="oe_form_dropdown_section">
|
||||
<h4>Journal :</h4>
|
||||
<select class="oe_account_select_journal" >
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="AccountReconciliation">
|
||||
<t t-if="widget.current_partner === null">
|
||||
<div class="oe_view_nocontent">
|
||||
<p>
|
||||
Good job!
|
||||
</p><p>
|
||||
There is nothing to reconcile. All invoices and payments
|
||||
have been reconciled, your partner balance is clean.
|
||||
</p>
|
||||
</div>
|
||||
</t>
|
||||
<div class="oe_account_reconciliation">
|
||||
<t t-if="widget.current_partner !== null">
|
||||
<div>
|
||||
<div>
|
||||
<button class="oe_account_recon_previous oe_button" href="javascript:void(0)"><</button>
|
||||
<t t-esc="'' + widget.partners[widget.current_partner][1] + ' (' + (widget.current_partner + 1) + '/' + widget.partners.length + ')'"/>
|
||||
<button class="oe_account_recon_next oe_button" href="javascript:void(0)">></button>
|
||||
</div>
|
||||
<div>
|
||||
Latest Manual Reconciliation Processed: <t t-esc="widget.last_reconciliation_date" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button class="oe_account_recon_reconcile oe_button oe_highlight" href="javascript:void(0)"
|
||||
disabled="">Reconcile</button>
|
||||
<button class="oe_account_recom_mark_as_reconciled oe_button" href="javascript:void(0)">Nothing more to reconcile</button>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="ShowPaymentInfo">
|
||||
<div>
|
||||
<t t-if="outstanding">
|
||||
<div>
|
||||
<strong class="pull-left" id="outstanding"><t t-esc="title"></t></strong>
|
||||
</div>
|
||||
</t>
|
||||
<table style="width:100%;">
|
||||
<t t-foreach="lines" t-as="line">
|
||||
<tr>
|
||||
<t t-if="outstanding">
|
||||
<td>
|
||||
<a title="assign to invoice" class="oe_form_field outstanding_credit_assign" t-att-data-id="line.id">Add</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="oe_form_field"><t t-esc="line.ref"></t></span>
|
||||
</td>
|
||||
</t>
|
||||
<t t-if="!outstanding">
|
||||
<td>
|
||||
<i class="oe_form_field text-right" t-att-title="line.name + '\n'+ line.ref">Paid on <t t-esc="line.date"></t></i>
|
||||
</td>
|
||||
</t>
|
||||
<td style="text-align:right;">
|
||||
<span class="oe_form_field oe_form_field_float oe_form_field_monetary">
|
||||
<t t-if="line.position === 'before'">
|
||||
<t t-esc="line.currency"/>
|
||||
</t>
|
||||
<t t-esc="line.amount"></t>
|
||||
<t t-if="line.position === 'after'">
|
||||
<t t-esc="line.currency"/>
|
||||
</t>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -0,0 +1,365 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<!-- abstract or shared templates -->
|
||||
|
||||
<t t-name="reconciliation">
|
||||
<div class="oe_form_sheetbg"><div class="oe_form_sheet oe_form_sheet_width">
|
||||
<h1><t t-esc="title"/></h1>
|
||||
<div t-if="! hide_progress" class="progress progress-striped">
|
||||
<div class="progress-text"><span class="valuenow">0</span> / <span class="valuemax"><t t-esc="total_lines"/></span></div>
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" t-att-aria-valuemax="total_lines" style="width: 0%;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_clear"></div>
|
||||
<div class="notification_area"></div>
|
||||
<div class="interface_options oe_form"></div>
|
||||
<div class="reconciliation_lines_container"></div>
|
||||
<div class="show_more_container"><button class="show_more btn btn-default btn-sm">Show more... (<span class="num_items_remaining"></span> remaining)</button></div>
|
||||
<p class='protip'>Tip : Hit ctrl-enter to reconcile all the balanced items in the sheet.</p>
|
||||
</div></div>
|
||||
</t>
|
||||
|
||||
<t t-name="nothing_to_reconcile">
|
||||
<div class="oe_form_sheetbg"><div class="oe_form_sheet oe_form_sheet_width">
|
||||
<div class="notification_area"></div>
|
||||
<div class="oe_view_nocontent"></div>
|
||||
</div></div>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_done_message">
|
||||
<div class='done_message'>
|
||||
<h2><t t-raw="title" /></h2>
|
||||
<p class="action_buttons"></p>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_notification">
|
||||
<div t-att-class="'notification alert-dismissible alert alert-' + type" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true" class="glyphicon glyphicon-remove"></span><span class="sr-only">Close</span></button>
|
||||
<t t-esc="message" />
|
||||
<t t-if="details !== undefined">
|
||||
<a class="fa fa-external-link" rel="do_action" href="javascript:void(0)"
|
||||
t-att-data-action_nam="details.name"
|
||||
t-att-data-model="details.model"
|
||||
t-att-data-ids="details.ids">
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_line">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<table class="accounting_view">
|
||||
<caption></caption>
|
||||
<tbody class="tbody_matched_lines"></tbody>
|
||||
<tbody class="tbody_created_lines"></tbody>
|
||||
<tbody class="tbody_open_balance"></tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="action_pane match">
|
||||
<div class="match_controls">
|
||||
<input type="text" class="filter" placeholder="Filter" value="" />
|
||||
<span class="pager_control_right pull-right glyphicon glyphicon-chevron-right"></span>
|
||||
<span class="pager_control_left pull-right glyphicon glyphicon-chevron-left"></span>
|
||||
</div>
|
||||
<table></table>
|
||||
</div>
|
||||
<div class="action_pane create">
|
||||
<div class="quick_add" t-att-style="(!presets ? 'display: none' : undefined)">
|
||||
<div class="btn-group btn-group-sm presets_container"><t t-raw="presets" /></div>
|
||||
<div class="dropdown presets_config">
|
||||
<a data-toggle="dropdown" href="#"><span class="glyphicon glyphicon-cog"></span></a>
|
||||
<ul class="dropdown-menu dropdown-menu-right" role="menu" aria-labelledby="Presets config">
|
||||
<li><a class="presets_config_create" href="#">New preset</a></li>
|
||||
<li><a class="presets_config_edit" href="#">Modify presets</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_form create_form">
|
||||
<!-- here come some form_create_field -->
|
||||
<table class="create_field add_line_container"><tr><td><a href="javascript:void(0)" class="add_line"><i class="fa fa-plus-circle"></i> New Operation</a></td></tr></table>
|
||||
<div class='clearer'></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="preset_button">
|
||||
<button type='button' class='btn btn-default preset' t-att-data-presetid="id">
|
||||
<t t-esc="name"/>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
<t t-name="presets_dropdown">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
More <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<t t-foreach="presets" t-as="preset">
|
||||
<li><a href="javascript:void(0)" class='preset' t-att-data-presetid="preset.id"><t t-esc="preset.name"/></a></li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="form_create_field">
|
||||
<table t-att-class='"create_field create_"+id'><tr>
|
||||
<th><t t-esc="label"/></th>
|
||||
<td class="create_account_container" t-att-class='"create_"+id+"_container"'></td>
|
||||
</tr></table>
|
||||
</t>
|
||||
|
||||
<t t-name="filter_no_match">
|
||||
<tr><td style='text-align: center;'>No result matching '<t t-esc="filter_str" />'</td></tr>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_move_line">
|
||||
<tr t-att-class="'mv_line'+(line.already_paid ? ' already_reconciled' : '')" t-att-data-lineid="line.id" t-att-data-selected="selected">
|
||||
<td class="cell_action"><span class="glyphicon glyphicon-add-remove"></span></td>
|
||||
<td class="cell_account_code" t-if="line.account_code"><t t-esc="line.account_code"/></td>
|
||||
<td class="cell_due_date"><t t-esc="line.q_due_date"/></td>
|
||||
<td class="cell_label"><t t-esc="line.q_label"/></td>
|
||||
<td class="cell_debit"><t t-if="line.debit !== 0"><t t-if="line.propose_partial_reconcile" t-call="icon_do_partial_reconciliation"></t><t t-if="line.partial_reconcile" t-call="icon_undo_partial_reconciliation"></t><t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_credit"><t t-if="line.credit !== 0"><t t-if="line.propose_partial_reconcile"><t t-call="icon_do_partial_reconciliation" /></t><t t-if="line.partial_reconcile"><t t-call="icon_undo_partial_reconciliation" /></t><t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_info_popover"><span class="line_info_button glyphicon glyphicon-info-sign" t-att-data-content="line.q_popover"></span></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_move_line_details">
|
||||
<table class='details'>
|
||||
<tr t-if="line.account_code"><td>Account</td><td><t t-esc="line.account_code"/> <t t-esc="line.account_name"/></td></tr>
|
||||
<tr><td>Journal</td><td><t t-esc="line.journal_name"/></td></tr>
|
||||
<tr><td>Date</td><td><t t-esc="line.date"/></td></tr>
|
||||
<tr><td>Due Date</td><td><t t-esc="line.q_due_date"/></td></tr>
|
||||
<t t-if="line.is_partially_reconciled">
|
||||
<tr><td>Total</td><td>
|
||||
<t t-esc="line.total_amount_str"/><t t-if="line.total_amount_currency_str"> (<t t-esc="line.total_amount_currency_str"/>)</t>
|
||||
</td></tr>
|
||||
</t>
|
||||
<tr><td><t t-if="line.is_partially_reconciled">Residual</t><t t-if="! line.is_partially_reconciled">Amount</t></td><td>
|
||||
<t t-esc="line.amount_str"/><t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t>
|
||||
</td></tr>
|
||||
<tr class="one_line_info" t-if='line.already_paid'>
|
||||
<td colspan="2">This payment is registered but not reconciled.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_created_line">
|
||||
<tr class="created_line" tabindex="0" t-att-data-lineid="line.id">
|
||||
<td class="cell_action"><t t-if="! line.no_remove_action"><span class="line_remove_button glyphicon glyphicon-remove"></span></t></td>
|
||||
<td class="cell_account_code"><t t-esc="line.account_num"/></td>
|
||||
<td class="cell_due_date"></td>
|
||||
<td class="cell_label"><t t-esc="line.label"/></td>
|
||||
<td class="cell_debit"><t t-if="line.amount < 0"><t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_credit"><t t-if="line.amount > 0"><t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_info_popover"></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="reconciliation_line_open_balance">
|
||||
<tr class="line_open_balance" tabindex="0">
|
||||
<td class="cell_action"><span class="toggle_create glyphicon glyphicon-play"></span></td>
|
||||
<td class="cell_account_code"><t t-if="account_code" t-esc="account_code"/></td>
|
||||
<td class="cell_due_date"></td>
|
||||
<td class="cell_label"><t t-esc="label" /></td>
|
||||
<td class="cell_debit"><t t-esc="debit"/></td>
|
||||
<td class="cell_credit"><t t-esc="credit"/></td>
|
||||
<td class="cell_info_popover"></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
|
||||
<!-- bank statement reconciliation -->
|
||||
|
||||
<t t-name="bank_statement_reconciliation" t-extend="reconciliation">
|
||||
<t t-jquery="h1" t-operation="replace">
|
||||
<t t-if="single_statement">
|
||||
<h1 class="statement_name">
|
||||
<span><t t-esc="title"/></span>
|
||||
<table class="change_statement_name_container oe_form"><tr>
|
||||
<td><input class="change_statement_name_field" type="text"/></td>
|
||||
<td><button class="change_statement_name_button btn btn-primary btn-sm">OK</button></td>
|
||||
</tr></table>
|
||||
</h1>
|
||||
</t>
|
||||
<t t-if="!single_statement">
|
||||
<h1><t t-esc="title"/></h1>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_nothing_to_reconcile" t-extend="nothing_to_reconcile">
|
||||
<t t-jquery=".oe_view_nocontent" t-operation="inner">
|
||||
<p><b>Good Job!</b> Bank statements are fully reconciled.</p>
|
||||
<p>This page displays all the bank transactions that are to be reconciled and provides with a neat interface to do so.</p>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_done_message" t-extend="reconciliation_done_message">
|
||||
<t t-jquery="h2" t-operation="after">
|
||||
<t t-if="! all_was_auto_reconciled">
|
||||
<p>It took you <strong><t t-esc="time_taken" /></strong> to reconcile <strong><t t-esc="transactions_done" /> transactions.<br/></strong> That's on average <t t-esc="sec_per_item" /> seconds per transaction.</p>
|
||||
<t t-if="done_with_ctrl_enter !== 0">
|
||||
<p>You validated <t t-esc="done_with_ctrl_enter" /> reconciliations with the ctrl-enter shortcut.</p>
|
||||
</t>
|
||||
<p class='achievements'>
|
||||
<t t-foreach="achievements" t-as="achievement">
|
||||
<i class='fa fa-certificate achievement' t-att-data-title='achievement.title' t-att-data-content='achievement.desc'><i t-att-class="'fa '+achievement.icon"></i></i>
|
||||
</t>
|
||||
</p>
|
||||
</t>
|
||||
</t>
|
||||
<t t-jquery=".action_buttons" t-operation="inner">
|
||||
<t t-if="single_statement or multiple_statements">
|
||||
<button class="button_back_to_statement btn btn-default btn-sm">Go to bank statements</button>
|
||||
<button class="button_close_statement btn btn-primary btn-sm">Close the statement<t t-if="multiple_statements">s</t></button>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_line" t-extend="reconciliation_line">
|
||||
<t t-jquery=".accounting_view caption" t-operation="inner">
|
||||
<button class="button_ok btn btn-default btn-sm"></button>
|
||||
<span class="tip_reconciliation_not_balanced">Select a partner or choose a counterpart</span>
|
||||
<span t-if="! line.has_no_partner" class="partner_name">
|
||||
<t t-esc="line.partner_name"/>
|
||||
<span class="change_partner glyphicon glyphicon-remove"></span>
|
||||
</span>
|
||||
<div class="change_partner_container oe_form"></div>
|
||||
</t>
|
||||
<t t-jquery=".accounting_view caption" t-operation="after">
|
||||
<tbody class="tbody_initial_line">
|
||||
<tr class="initial_line" tabindex="0">
|
||||
<td class="cell_action"><span class="toggle_match glyphicon glyphicon-cog"></span></td>
|
||||
<td class="cell_account_code"><t t-esc="line.account_code"/></td>
|
||||
<td class="cell_due_date"><t t-esc="line.date"/></td>
|
||||
<td class="cell_label"><t t-if="line.name" t-esc="line.name"/>
|
||||
<t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t></td>
|
||||
<td class="cell_debit"><t t-if="line.amount > 0">
|
||||
<t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_credit"><t t-if="line.amount < 0">
|
||||
<t t-esc="line.amount_str"/></t></td>
|
||||
<td class="cell_info_popover"><span class="line_info_button glyphicon glyphicon-info-sign" t-att-data-content="line.q_popover"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_statement_line_details">
|
||||
<table class='details'>
|
||||
<tr><td>Date</td><td><t t-esc="line.date"/></td></tr>
|
||||
<tr t-if="line.partner_name"><td>Partner</td><td><t t-esc="line.partner_name"/></td></tr>
|
||||
<tr t-if="line.ref"><td>Transaction</td><td><t t-esc="line.ref"/></td></tr>
|
||||
<tr><td>Description</td><td><t t-esc="line.name"/></td></tr>
|
||||
<tr><td>Amount</td><td><t t-esc="line.amount_str"/><t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str"/>)</t></td></tr>
|
||||
<tr><td>Account</td><td><t t-esc="line.account_code"/> <t t-esc="line.account_name"/></td></tr>
|
||||
<tr t-if="line.note"><td>Note</td><td><t t-esc="line.note"/></td></tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="icon_do_partial_reconciliation"><i class="do_partial_reconcile_button fa fa-exclamation-triangle" data-content="This move's amount is higher than the transaction's amount. Click to register a partial payment and keep the payment balance open."></i></t>
|
||||
|
||||
<t t-name="icon_undo_partial_reconciliation"><i class="undo_partial_reconcile_button fa fa-exclamation-triangle" data-content="Undo the partial reconciliation."></i></t>
|
||||
|
||||
<t t-name="bank_statement_reconciliation_move_line_details" t-extend="reconciliation_move_line_details">
|
||||
<t t-jquery=".details" t-operation="append">
|
||||
<tr class="one_line_info" t-if='line.is_reconciled'>
|
||||
<td colspan="2">This item is already reconciled</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- manual reconciliation -->
|
||||
|
||||
<t t-name="show_mode_selector_option">
|
||||
<div>
|
||||
<span class="oe_radio_input"><input type="radio" name="modeselektor" t-att-val="value" t-attf-id="mode_{{value}}" t-att-checked="(mode === value ? true : undefined)" /></span>
|
||||
<label t-attf-for="mode_{{value}}"><t t-esc="title"/></label>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="manual_reconciliation" t-extend="reconciliation">
|
||||
<t t-jquery=".interface_options" t-operation="append">
|
||||
<table t-if="show_mode_selector" border="0" cellpadding="0" cellspacing="0" class="oe_form_group"><tbody>
|
||||
<tr class="oe_form_group_row">
|
||||
<td class="oe_form_group_cell oe_form_group_cell_label" colspan="1">
|
||||
<label for="oe-field-input-5" class="oe_form_label oe_align_right">Show</label>
|
||||
</td>
|
||||
<td class="oe_form_group_cell" colspan="1" width="99%">
|
||||
<span class="oe_form_field oe_form_field_radio oe_vertical oe_form_required">
|
||||
<span>
|
||||
<t t-if="display_mode_customers" t-call="show_mode_selector_option"><t t-set="value">customers</t><t t-set="title">Customers</t></t>
|
||||
<t t-if="display_mode_suppliers" t-call="show_mode_selector_option"><t t-set="value">suppliers</t><t t-set="title">Suppliers</t></t>
|
||||
<t t-if="display_mode_others" t-call="show_mode_selector_option"><t t-set="value">others</t><t t-set="title">OtherAccounts</t></t>
|
||||
<t t-call="show_mode_selector_option"><t t-set="value">all</t><t t-set="title">All</t></t>
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="manual_reconciliation_nothing_to_reconcile" t-extend="nothing_to_reconcile">
|
||||
<t t-jquery=".oe_view_nocontent" t-operation="inner">
|
||||
<p><b>Good Job!</b> There is nothing to reconcile.</p>
|
||||
<p>All invoices and payments have been matched, your accounts' balances are clean.</p>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="manual_reconciliation_done_message">
|
||||
<div class='done_message'>
|
||||
<p><b>Good Job!</b> There is nothing to reconcile.</p>
|
||||
<p>All invoices and payments have been matched, your accounts' balances are clean.</p>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="manual_reconciliation_line" t-extend="reconciliation_line">
|
||||
<t t-jquery=".accounting_view" t-operation="before">
|
||||
<button class="button_reconcile btn btn-default btn-sm">Reconcile</button>
|
||||
</t>
|
||||
<t t-jquery=".accounting_view caption" t-operation="replace">
|
||||
<thead><tr>
|
||||
<td class="cell_action"></td>
|
||||
<td class="cell-title" colspan="2">
|
||||
<span class="cell_item_name"><t t-if="data.partner_name" t-esc="data.partner_name" /><t t-if="data.partner_name === undefined" t-esc="data.account_code" /></span>
|
||||
<span class="cell_last_time_entries_checked" t-if="data.last_time_entries_checked">Last Reconciliation : <t t-esc="data.last_time_entries_checked" /></span>
|
||||
</td>
|
||||
<td class="cell_title_account_code" colspan="2"><t t-esc="data.account_code" /></td>
|
||||
<td class="cell_info_popover"></td>
|
||||
</tr></thead>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="manual_reconciliation_line_open_balance" t-extend="reconciliation_line_open_balance">
|
||||
<t t-jquery=".cell_account_code" t-operation="replace"></t>
|
||||
</t>
|
||||
|
||||
<t t-name="manual_reconciliation_created_line" t-extend="reconciliation_created_line">
|
||||
<t t-jquery=".cell_account_code" t-operation="replace"></t>
|
||||
</t>
|
||||
|
||||
<t t-name="manual_reconciliation_move_line" t-extend="reconciliation_move_line">
|
||||
<t t-jquery=".cell_account_code" t-operation="replace"></t>
|
||||
<!--
|
||||
<t t-jquery=".cell_debit" t-operation="replace"><td class="cell_debit"><t t-if="line.debit !== 0"><t t-esc="line.amount_str"/>
|
||||
<t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str" />)</t>
|
||||
</t></td></t>
|
||||
<t t-jquery=".cell_credit" t-operation="replace"><td class="cell_credit"><t t-if="line.credit !== 0"><t t-esc="line.amount_str"/>
|
||||
<t t-if="line.amount_currency_str"> (<t t-esc="line.amount_currency_str" />)</t>
|
||||
</t></td></t>
|
||||
-->
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -1,3 +1,13 @@
|
||||
-
|
||||
!context
|
||||
journal_type: 'bank'
|
||||
-
|
||||
We create a new bank with the company as partner in order to be sure to have at least one bank journal
|
||||
-
|
||||
!record {model: res.partner.bank, id: test_bank}:
|
||||
acc_number: BE123456789
|
||||
bank_name: BNP Test bank
|
||||
partner_id: base.main_partner
|
||||
-
|
||||
In order to test Bank Statement feature of account I create a bank statement line and confirm it and check it's move created
|
||||
-
|
||||
@@ -5,8 +15,8 @@
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
import time
|
||||
journal = self._default_journal_id(cr, uid, {'lang': u'en_US', 'tz': False, 'active_model': 'ir.ui.menu',
|
||||
'journal_type': 'bank', 'period_id': time.strftime('%m'), 'active_ids': [ref('menu_bank_statement_tree')], 'active_id': ref('menu_bank_statement_tree')})
|
||||
journal = self._default_journal(cr, uid, {'lang': u'en_US', 'tz': False, 'active_model': 'ir.ui.menu',
|
||||
'journal_type': 'bank', 'date': time.strftime("%Y/%m/%d")})
|
||||
assert journal, 'Journal has not been selected'
|
||||
-
|
||||
I create a bank statement with Opening and Closing balance 0.
|
||||
@@ -15,34 +25,24 @@
|
||||
balance_end_real: 0.0
|
||||
balance_start: 0.0
|
||||
date: !eval time.strftime('%Y-%m-%d')
|
||||
journal_id: account.bank_journal
|
||||
-
|
||||
I create bank statement line
|
||||
company_id: base.main_company
|
||||
-
|
||||
!python {model: account.bank.statement.line}: |
|
||||
partner = self.onchange_partner_id(cr, uid, [], ref('base.res_partner_4'), context=None)
|
||||
import time
|
||||
account_id = self.pool.get('account.account').search(cr, uid, [('user_type.type', '=', 'liquidity'), ('currency_id', '=', False)])[0]
|
||||
vals = {
|
||||
'account_id': partner['value']['account_id'],
|
||||
'amount': 1000.0,
|
||||
'amount': 1000,
|
||||
'date': time.strftime('%Y-%m-%d'),
|
||||
'partner_id': ref('base.res_partner_4'),
|
||||
'name': 'EXT001',
|
||||
'statement_id': ref('account_bank_statement_0'),
|
||||
'name': 'EXT001'
|
||||
}
|
||||
vals.update(partner.get('value',{}))
|
||||
line_id = self.create(cr, uid, vals)
|
||||
assert line_id, "Account bank statement line has not been created"
|
||||
-
|
||||
I compute bank statement using Compute button
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
self.button_dummy(cr, uid, [ref("account_bank_statement_0")])
|
||||
|
||||
self.create(cr, uid, vals)
|
||||
-
|
||||
I modify the bank statement and set the Closing Balance.
|
||||
-
|
||||
!record {model: account.bank.statement, id: account_bank_statement_0}:
|
||||
balance_end_real: 1000.0
|
||||
|
||||
-
|
||||
I confirm the bank statement using Confirm button
|
||||
-
|
||||
@@ -53,24 +53,3 @@
|
||||
-
|
||||
!assert {model: account.bank.statement, id: account_bank_statement_0}:
|
||||
- state == 'confirm'
|
||||
|
||||
-
|
||||
I check that move lines created for bank statement and move state is Posted
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
bank_data = self.browse(cr, uid, ref("account_bank_statement_0"))
|
||||
assert bank_data.move_line_ids, "Move lines not created for bank statement"
|
||||
for line in bank_data.move_line_ids:
|
||||
assert line.move_id.state == 'posted', "Move state is not posted"
|
||||
-
|
||||
Then I cancel Bank Statements and verifies that it raises a warning
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
from openerp.osv import osv
|
||||
try:
|
||||
self.button_cancel(cr, uid, [ref("account_bank_statement_0")])
|
||||
assert False, "An exception should have been raised, the journal should not let us cancel moves!"
|
||||
except osv.except_osv:
|
||||
# exception was raised as expected, as the journal does not allow cancelling moves
|
||||
pass
|
||||
|
||||
@@ -1,63 +1,46 @@
|
||||
-
|
||||
TODO: improve this test and add the use of cashbox lines to set the ending balance and use of the confirmation wizard
|
||||
-
|
||||
In order to test Cash statement I create a Cash statement and confirm it and check its move created
|
||||
-
|
||||
!record {model: account.bank.statement, id: account_bank_statement_1}:
|
||||
!record {model: account.cash.statement, id: account_cash_statement_1, view: False}:
|
||||
date: !eval time.strftime('%Y-%m-%d')
|
||||
journal_id: account.cash_journal
|
||||
name: /
|
||||
period_id: account.period_10
|
||||
user_id: base.user_root
|
||||
starting_details_ids:
|
||||
- pieces: 10.0
|
||||
number: 2
|
||||
subtotal: 20.0
|
||||
- pieces: 100.0
|
||||
number: 1
|
||||
subtotal: 100.0
|
||||
balance_start: 120.0
|
||||
balance_end: 120.0
|
||||
-
|
||||
I check that Initially bank statement is in the "Draft" state
|
||||
I check that Initially cash statement is in the "Draft" state
|
||||
-
|
||||
!assert {model: account.bank.statement, id: account_bank_statement_1}:
|
||||
!assert {model: account.cash.statement, id: account_cash_statement_1}:
|
||||
- state == 'draft'
|
||||
|
||||
-
|
||||
I clicked on Open CashBox button to open the cashbox
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
self.button_open(cr, uid, [ref("account_bank_statement_1")], {"lang": "en_US", "tz": False, "active_model": "account.bank.statement", "active_ids": [ref("account_bank_statement_1")], "active_id": ref("account_bank_statement_1"), })
|
||||
|
||||
!python {model: account.cash.statement, id: account_cash_statement_1}: |
|
||||
context = {"lang": "en_US", "tz": False,
|
||||
"active_model": "account.cash.statement",
|
||||
"active_ids": [ref("account_cash_statement_1")],
|
||||
"active_id": ref("account_cash_statement_1"), }
|
||||
self.with_context(context).button_open()
|
||||
-
|
||||
I check that now bank statement is in the "Open" state
|
||||
I check that now cash statement is in the "Open" state
|
||||
-
|
||||
!assert {model: account.bank.statement, id: account_bank_statement_1}:
|
||||
!assert {model: account.cash.statement, id: account_cash_statement_1}:
|
||||
- state == 'open'
|
||||
|
||||
-
|
||||
I enter values in Closing balance before close the cashbox
|
||||
-
|
||||
!record {model: account.bank.statement, id: account_bank_statement_1}:
|
||||
!record {model: account.cash.statement, id: account_cash_statement_1, view: False}:
|
||||
line_ids:
|
||||
- account_id: account.a_recv
|
||||
amount: 1000.0
|
||||
- amount: 1000.0
|
||||
date: !eval time.strftime('%Y-%m-%d')
|
||||
name: test
|
||||
partner_id: base.res_partner_4
|
||||
sequence: 0.0
|
||||
type: general
|
||||
account_id: account.credit_account
|
||||
balance_end: 1120.0
|
||||
ending_details_ids:
|
||||
- pieces: 10.0
|
||||
number: 2
|
||||
subtotal: 20.0
|
||||
- pieces: 100.0
|
||||
number: 1
|
||||
subtotal: 100.0
|
||||
- pieces: 500.0
|
||||
number: 2
|
||||
subtotal: 1000.0
|
||||
|
||||
-
|
||||
I clicked on Close CashBox button to close the cashbox
|
||||
-
|
||||
@@ -71,11 +54,10 @@
|
||||
- state == 'confirm'
|
||||
|
||||
-
|
||||
I check that move lines created for bank statement and move state is Posted
|
||||
I check that move lines created for cash statement and move state is Posted
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
bank_data = self.browse(cr, uid, ref("account_bank_statement_1"))
|
||||
assert bank_data.move_line_ids, "Move lines not created for bank statement"
|
||||
for line in bank_data.move_line_ids:
|
||||
!python {model: account.cash.statement, id: account_cash_statement_1}: |
|
||||
move_line_obj = self.env['account.move.line']
|
||||
assert self.move_line_ids, "Move lines not created for cash statement"
|
||||
for line in self.move_line_ids:
|
||||
assert line.move_id.state == 'posted', "Move state is not posted"
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
-
|
||||
In order to test change currency wizard I create an invoice with currency "EUR" and change it to "USD" using the wizard
|
||||
-
|
||||
!record {model: account.invoice, id: account_invoice_currency}:
|
||||
account_id: account.a_recv
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PCSC234] PC Assemble SC234'
|
||||
price_unit: 450.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_3
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.sales_journal
|
||||
partner_id: base.res_partner_12
|
||||
reference_type: none
|
||||
|
||||
-
|
||||
I check that Initially customer invoice is in the draft state
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_currency, string: Customer Invoice is in Draft state}:
|
||||
- state == 'draft'
|
||||
-
|
||||
Now I select USD as new currency
|
||||
-
|
||||
!record {model: account.change.currency, id: account_change_currency_0}:
|
||||
currency_id: base.USD
|
||||
-
|
||||
I clicked on Change Currency button to change the currency
|
||||
-
|
||||
!python {model: account.change.currency}: |
|
||||
self.view_init(cr, uid, [ref("account_change_currency_0")], {"lang": 'en_US',
|
||||
"active_model": "account.invoice", "tz": False, "active_ids":
|
||||
[ref("account_invoice_currency")], "type": "out_invoice", "active_id": ref("account_invoice_currency"),
|
||||
})
|
||||
self.change_currency(cr, uid, [ref("account_change_currency_0")], {"lang": 'en_US',
|
||||
"active_model": "account.invoice", "tz": False, "active_ids":
|
||||
[ref("account_invoice_currency")], "type": "out_invoice", "active_id": ref("account_invoice_currency"),
|
||||
})
|
||||
-
|
||||
I change the state of invoice to proforma2 by clicking PRO-FORMA button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_proforma2, ref: account_invoice_currency}
|
||||
-
|
||||
I check that now customer invoice is in the "proforma2" state
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_currency}:
|
||||
- state == 'proforma2'
|
||||
-
|
||||
I can't change the currency of invoice when it is not in draft state so I change the state to cancel
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_cancel, ref: account_invoice_currency}
|
||||
-
|
||||
I change the state to "Draft"
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
self.action_cancel_draft(cr, uid, [ref("account_invoice_currency")], {"lang": 'en_US',
|
||||
"tz": False, "active_model": "ir.ui.menu", "active_ids": [ref("account.menu_action_invoice_tree1")],
|
||||
"type": "out_invoice", "active_id": ref("account.menu_action_invoice_tree1"),
|
||||
})
|
||||
-
|
||||
I change the currency.
|
||||
-
|
||||
!record {model: account.change.currency, id: account_change_currency_0}:
|
||||
currency_id: base.USD
|
||||
-
|
||||
I clicked on Change Currency button to change the currency
|
||||
-
|
||||
!python {model: account.change.currency}: |
|
||||
self.change_currency(cr, uid, [ref("account_change_currency_0")], {"lang": 'en_US',
|
||||
"active_model": "account.invoice", "tz": False, "active_ids":
|
||||
[ref("account_invoice_currency")], "type": "out_invoice", "active_id": ref("account_invoice_currency"),
|
||||
})
|
||||
-
|
||||
I check that the currency is changed successfully
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_currency, string: Currency changed from EUR to USD}:
|
||||
- currency_id.id == ref("base.USD")
|
||||
@@ -1,120 +0,0 @@
|
||||
-
|
||||
In order to test account invoice I create a new customer invoice
|
||||
-
|
||||
I will create bank detail with using manager access rights because account manager can only create bank details.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_account_manager'
|
||||
-
|
||||
!record {model: res.partner.bank, id: res_partner_bank_0}:
|
||||
state: bank
|
||||
company_id: base.main_company
|
||||
partner_id: base.main_partner
|
||||
acc_number: 123456789
|
||||
footer: True
|
||||
bank: base.res_bank_1
|
||||
bank_name: Reserve
|
||||
-
|
||||
Test with that user which have rights to make Invoicing and payment and who is accountant.
|
||||
-
|
||||
!context
|
||||
uid: 'res_users_account_user'
|
||||
-
|
||||
I create a customer invoice
|
||||
-
|
||||
!record {model: account.invoice, id: account_invoice_customer0, view: invoice_form}:
|
||||
payment_term: account.account_payment_term_advance
|
||||
partner_bank_id: res_partner_bank_0
|
||||
journal_id: account.sales_journal
|
||||
partner_id: base.res_partner_3
|
||||
reference_type: none
|
||||
name: 'Test Customer Invoice'
|
||||
invoice_line:
|
||||
- product_id: product.product_product_5
|
||||
quantity: 10.0
|
||||
-
|
||||
I manually assign tax on invoice
|
||||
-
|
||||
!python {model: account.invoice.tax}: |
|
||||
amt = self.amount_change(cr, uid, [], 50.0, ref('base.EUR'), ref('base.main_company'), False)
|
||||
base_amt = self.base_change(cr, uid, [], 9000.0, ref('base.EUR'), ref('base.main_company'), False)
|
||||
invoice_tax_line = {
|
||||
'name': 'Test Tax for Customer Invoice',
|
||||
'manual': 1,
|
||||
'base': base_amt['value']['base_amount'],
|
||||
'amount': amt['value']['tax_amount'],
|
||||
'account_id': ref('account.ova'),
|
||||
'invoice_id': ref("account_invoice_customer0"),
|
||||
}
|
||||
tax = self.create(cr, uid, invoice_tax_line)
|
||||
assert tax, "Tax has not been assigned correctly"
|
||||
|
||||
-
|
||||
I check that Initially customer invoice is in the "Draft" state
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_customer0}:
|
||||
- state == 'draft'
|
||||
-
|
||||
I change the state of invoice to "Proforma2" by clicking PRO-FORMA button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_proforma2, ref: account_invoice_customer0}
|
||||
-
|
||||
I check that the invoice state is now "Proforma2"
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_customer0}:
|
||||
- state == 'proforma2'
|
||||
-
|
||||
I check that there is no move attached to the invoice
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
acc_id=self.browse(cr, uid, ref("account_invoice_customer0"))
|
||||
assert (not acc_id.move_id), "Move falsely created at pro-forma"
|
||||
-
|
||||
I create invoice by clicking on Create button
|
||||
-
|
||||
!workflow {model: account.invoice, action: invoice_open, ref: account_invoice_customer0}
|
||||
-
|
||||
I check that the invoice state is "Open"
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_customer0}:
|
||||
- state == 'open'
|
||||
|
||||
-
|
||||
I check that now there is a move attached to the invoice
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
acc_id=self.browse(cr, uid, ref("account_invoice_customer0"))
|
||||
assert acc_id.move_id, "Move not created for open invoice"
|
||||
-
|
||||
I pay the Invoice
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
import time
|
||||
pay = self.pay_and_reconcile(cr, uid, [ref('account_invoice_customer0')],
|
||||
9050.0, ref('cash'), ref('account.period_10'),
|
||||
ref('bank_journal'), ref('cash'),
|
||||
ref('account.period_10'), ref('bank_journal'),
|
||||
name='Payment for test customer invoice')
|
||||
assert (pay == True), "Incorrect Payment"
|
||||
-
|
||||
I verify that invoice is now in Paid state
|
||||
-
|
||||
!python {model: account.invoice}: |
|
||||
inv = self.browse(cr, uid, ref("account_invoice_customer0"))
|
||||
assert (inv.state == 'paid'), "Invoice is not in Paid state"
|
||||
-
|
||||
I refund the invoice Using Refund Button
|
||||
-
|
||||
!record {model: account.invoice.refund, id: account_invoice_refund_0}:
|
||||
description: Refund To China Export
|
||||
period: account.period_5
|
||||
filter_refund: refund
|
||||
-
|
||||
I clicked on refund button
|
||||
-
|
||||
!python {model: account.invoice.refund}: |
|
||||
self.invoice_refund(cr, uid, [ref("account_invoice_refund_0")], {"lang": 'en_US', "tz": False, "active_model": "account.invoice", "active_ids": [ref("account.account_invoice_customer0")], "type": "out_invoice", "active_id": ref("account.account_invoice_customer0"), })
|
||||
-
|
||||
I checked that a new entry with state "Draft" created in account move line
|
||||
|
||||
|
||||