[IMP] accounting v9. Yeeeeaah

This commit is contained in:
qdp-odoo
2015-05-05 17:28:04 +02:00
parent f09b118659
commit c04065abd8
974 changed files with 18601 additions and 189791 deletions
+7 -8
View File
@@ -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
+38 -114
View File
@@ -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,
}
+421 -3431
View File
File diff suppressed because it is too large Load Diff
+84 -87
View File
@@ -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
+41 -59
View File
@@ -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
File diff suppressed because it is too large Load Diff
-362
View File
@@ -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'
-20
View File
@@ -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>
-139
View File
@@ -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>
-56
View File
@@ -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>
File diff suppressed because it is too large Load Diff
+313
View File
@@ -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
-69
View File
@@ -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>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+524
View File
@@ -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
-22
View File
@@ -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)
-159
View File
@@ -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>
File diff suppressed because it is too large Load Diff
+892
View File
@@ -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')])
+80 -44
View File
@@ -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)
+76 -66
View File
@@ -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 &amp; 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>
+62 -41
View File
@@ -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')
+31 -122
View File
@@ -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})
-441
View File
@@ -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')
-
-22
View File
@@ -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
-289
View File
@@ -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"
-5
View File
@@ -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"
-174
View File
@@ -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'])
+223 -199
View File
@@ -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']
+56 -54
View File
@@ -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)
+1 -15
View File
@@ -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>
-136
View File
@@ -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), '&amp;',('date','&lt;=', time.strftime('%%Y-12-31')),('date','&gt;=',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>
+108 -84
View File
@@ -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
+75 -122
View File
@@ -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"
-215
View File
@@ -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
-288
View File
@@ -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 ''
-260
View File
@@ -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
+243 -366
View File
@@ -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
-44
View File
@@ -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
+13 -70
View File
@@ -3,7 +3,7 @@
<data noupdate="0">
<record id="group_account_invoice" model="res.groups">
<field name="name">Invoicing &amp; 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>
+17 -36
View File
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_product_product_account_user product.product.account.user product.model_product_product group_account_user 1 0 0 0
3 access_account_payment_term account.payment.term model_account_payment_term account.group_account_user 1 0 0 0
4 access_account_payment_term_line account.payment.term.line model_account_payment_term_line account.group_account_user 1 0 0 0
5 access_account_account_type_manager account.account.type model_account_account_type account.group_account_manager 1 1 1 1
6 access_account_account_type account.account.type model_account_account_type account.group_account_user 1 0 0 0
7 access_account_tax_internal_user account.tax internal user model_account_tax base.group_user 1 0 0 0
8 access_account_account_manager account.account model_account_account account.group_account_manager 1 1 1 1
9 access_account_account account.account model_account_account account.group_account_user 1 0 0 0
10 access_account_account_user account.account user model_account_account base.group_user 1 0 0 0
11 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
12 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
13 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
14 access_account_chart_template account.chart.template model_account_chart_template account.group_account_manager 1 1 1 1
15 access_account_tax_template account.tax.template model_account_tax_template account.group_account_manager 1 1 1 1
16 access_account_bank_statement account.bank.statement model_account_bank_statement account.group_account_user 1 1 1 1
24 access_account_invoice_tax_uinvoice account.invoice.tax model_account_invoice_tax account.group_account_invoice 1 1 1 1
25 access_account_move_uinvoice account.move model_account_move account.group_account_invoice 1 1 1 1
26 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
27 access_account_payment_term_manager account.payment.term model_account_payment_term account.group_account_manager 1 1 1 1
28 access_account_payment_term_line_manager account.payment.term.line model_account_payment_term_line account.group_account_manager 1 1 1 1
29 access_account_tax_manager account.tax model_account_tax account.group_account_manager 1 1 1 1
30 access_account_journal_manager account.journal model_account_journal account.group_account_manager 1 1 1 1
31 access_account_journal_user account.journal model_account_journal account.group_account_user 1 0 0 0
32 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
33 access_account_invoice_group_invoice account.invoice group invoice model_account_invoice account.group_account_invoice 1 1 1 1
34 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
35 access_res_currency_account_manager res.currency account manager base.model_res_currency group_account_manager 1 1 1 1
36 access_res_currency_rate_account_manager res.currency.rate account manager base.model_res_currency_rate group_account_manager 1 1 1 1
37 access_account_invoice_user account.invoice user model_account_invoice base.group_user 1 0 0 0
48 access_account_fiscal_position_template account.fiscal.position.template model_account_fiscal_position_template account.group_account_manager 1 1 1 1
49 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
50 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
51 access_temp_range access_account_invoice_report_user temp.range account.invoice.report_user model_temp_range model_account_invoice_report account.group_account_manager account.group_account_user 1 0 0 0
52 access_report_aged_receivable access_account_invoice_report report.aged.receivable account.invoice.report model_report_aged_receivable model_account_invoice_report 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
53 access_res_partner_group_account_manager res_partner group_account_manager model_res_partner account.group_account_manager 1 0 0 0
54 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
55 access_account_move_line_manager account.move.line manager model_account_move_line account.group_account_manager 1 0 0 0
56 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
57 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
58 access_account_analytic_line_invoice account.analytic.line invoice model_account_analytic_line account.group_account_invoice 1 1 1 1
59 access_account_invoice_line_accountant account.invoice.line accountant model_account_invoice_line account.group_account_user 1 0 0 0
60 access_account_account_invoice account.account invoice model_account_account account.group_account_invoice 1 1 0 1 0 1 0
61 access_account_analytic_accountant account.analytic.account accountant analytic.model_account_analytic_account account.group_account_user 1 1 1 1
62 access_account_account_type_invoice account.account.type invoice model_account_account_type account.group_account_invoice 1 1 0 1 0 1 0
access_report_account_receivable_invoice report.account.receivable.invoice model_report_account_receivable account.group_account_invoice 1 1 1 1
63 access_account_tax_sale_manager account.tax sale manager model_account_tax base.group_sale_salesman 1 0 0 0
64 access_account_journal_sale_manager account.journal sale manager model_account_journal base.group_sale_salesman 1 0 0 0
65 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
66 access_account_financial_report account.financial.report model_account_financial_report account.group_account_user 1 1 1 1
67 access_account_financial_report_invoice account.financial.report invoice model_account_financial_report account.group_account_invoice 1 0 0 0
68 access_account_statement_operation_template access_account_financial_report_line account.statement.operation.template account.financial.report.line model_account_statement_operation_template model_account_financial_report_line account.group_account_user 1 1 1 1
69 access_account_financial_report_line_invoice account.financial.report.line invoice model_account_financial_report_line account.group_account_invoice 1 0 0 0
70 access_account_account_tax account.account.tag model_account_account_tag account.group_account_user 1 0 0 0
71 access_account_account_tax_user account.account.tag model_account_account_tag account.group_account_invoice 1 0 0 0
72 access_account_operation_template account.operation.template model_account_operation_template account.group_account_user 1 1 1 1
73 access_account_partial_reconcile account.partial.reconcile model_account_partial_reconcile account.group_account_user 1 1 1 1
74 access_account_payment_method account.payment.method model_account_payment_method account.group_account_invoice 1 1 1 1
75 access_account_payment account.payment model_account_payment account.group_account_invoice 1 1 1 1
76 access_account_cashbox account.bank.statement.cashbox model_account_bank_statement_cashbox account.group_account_user 1 1 1 1
77 access_account_cashbox_line account.bank.statement.cashbox.line model_account_cashbox_line account.group_account_user 1 1 1 1
Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

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

+36 -88
View File
@@ -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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

+26
View File
@@ -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;
}
}
}
Binary file not shown.

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);
});
File diff suppressed because it is too large Load Diff
@@ -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",
File diff suppressed because it is too large Load Diff
@@ -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 &gt; 0">
<t t-esc="line.amount_str"/></t></td>
<td class="cell_credit"><t t-if="line.amount &lt; 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 &lt; 0"><t t-esc="line.amount_str"/></t></td>
<td class="cell_credit"><t t-if="line.amount &gt; 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)">&lt;</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)">&gt;</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 &lt; 0"><t t-esc="line.amount_str"/></t></td>
<td class="cell_credit"><t t-if="line.amount &gt; 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 &gt; 0">
<t t-esc="line.amount_str"/></t></td>
<td class="cell_credit"><t t-if="line.amount &lt; 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">&#xA0;(<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">&#xA0;(<t t-esc="line.amount_currency_str" />)</t>
</t></td></t>
-->
</t>
</templates>
+19 -40
View File
@@ -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
+21 -39
View File
@@ -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

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