diff --git a/.travis.yml b/.travis.yml index e2d1c7b3c..f88850658 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,27 +1,33 @@ +# Config file .travis.yml + language: python + python: - "2.7" +env: + - VERSION="8.0" ODOO_REPO="odoo/odoo" EXCLUDE="account_constraints,account_partner_required,async_move_line_importer" + - VERSION="8.0" ODOO_REPO="odoo/odoo" INCLUDE="account_constraints" + - VERSION="8.0" ODOO_REPO="odoo/odoo" INCLUDE="account_partner_required" + - VERSION="8.0" ODOO_REPO="odoo/odoo" INCLUDE="async_move_line_importer" + + - VERSION="8.0" ODOO_REPO="OCA/OCB" EXCLUDE="account_constraints, account_partner_required,async_move_line_importer" + - VERSION="8.0" ODOO_REPO="OCA/OCB" INCLUDE="account_constraints" + - VERSION="8.0" ODOO_REPO="OCA/OCB" INCLUDE="account_partner_required" + - VERSION="8.0" ODOO_REPO="odoo/odoo" INCLUDE="async_move_line_importer" + virtualenv: system_site_packages: true -before_install: - - git clone https://github.com/nbessi/maintainer-quality-tools.git $HOME/maintainer-quality-tools -b consolidated - - git clone https://github.com/OCA/connector $HOME/connector -b 7.0 - -env: - - PATH=$HOME/maintainer-quality-tools/travis:$PATH - -services: - - postgresql - install: - - $HOME/maintainer-quality-tools/travis/travis_install_nightly 7.0 - - pip install coveralls flake8 + - git clone https://github.com/oca/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools + - git clone https://github.com/OCA/connector $HOME/connector -b ${VERSION} + - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} + - travis_install_nightly ${VERSION} script: - - travis_run_flake8 steps - - travis_run_tests_encapsulated 7.0 account $HOME/connector + # - travis_run_flake8 + - travis_run_tests after_success: coveralls diff --git a/README.md b/README.md index 6108669d4..1792f9547 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +[![Build Status](https://travis-ci.org/OCA/account-financial-tools.svg?branch=8.0)](https://travis-ci.org/OCA/account-financial-tools) +[![Coverage Status](https://coveralls.io/repos/OCA/account-financial-tools/badge.png?branch=8.0)](https://coveralls.io/r/OCA/account-financial-tools?branch=8.0) + Account financial Tools for Odoo/OpenERP ======================================== diff --git a/__unported__/account_cancel_invoice_check_payment_order/__openerp__.py b/__unported__/account_cancel_invoice_check_payment_order/__openerp__.py index f91f59a10..bc5f01c38 100644 --- a/__unported__/account_cancel_invoice_check_payment_order/__openerp__.py +++ b/__unported__/account_cancel_invoice_check_payment_order/__openerp__.py @@ -30,6 +30,6 @@ payment order. """, 'website': 'http://www.camptocamp.com', 'data': [], - 'installable': True, + 'installable': False, 'active': False, } diff --git a/__unported__/account_cancel_invoice_check_voucher/__openerp__.py b/__unported__/account_cancel_invoice_check_voucher/__openerp__.py index e43b73c3b..ac6d904ab 100644 --- a/__unported__/account_cancel_invoice_check_voucher/__openerp__.py +++ b/__unported__/account_cancel_invoice_check_voucher/__openerp__.py @@ -30,7 +30,7 @@ Constraint forbidding to cancel an invoice already imported in bank statement with a voucher. """, 'website': 'http://www.camptocamp.com', - 'date' : [], + 'date': [], 'installable': False, 'active': False, } diff --git a/__unported__/account_cancel_invoice_check_voucher/account_invoice.py b/__unported__/account_cancel_invoice_check_voucher/account_invoice.py index 6d6749e10..7ec3b4cc4 100644 --- a/__unported__/account_cancel_invoice_check_voucher/account_invoice.py +++ b/__unported__/account_cancel_invoice_check_voucher/account_invoice.py @@ -32,26 +32,33 @@ class account_invoice(orm.Model): invoices = self.read(cr, uid, ids, ['move_id', 'payment_ids']) for invoice in invoices: if invoice['move_id']: - # This invoice have a move line, we search move_line concerned by this move - cr.execute("""SELECT abs.name AS statement_name, - abs.date AS statement_date, - absl.name - FROM account_bank_statement_line AS absl - INNER JOIN account_bank_statement AS abs - ON absl.statement_id = abs.id - WHERE EXISTS (SELECT 1 - FROM account_voucher_line JOIN account_move_line ON - (account_voucher_line.move_line_id = account_move_line.id) - WHERE voucher_id=absl.voucher_id - AND account_move_line.move_id = %s )""", - (invoice['move_id'][0],)) + # This invoice have a move line, we search move_line concerned + # by this move + cr.execute( + """ + SELECT abs.name AS statement_name, + abs.date AS statement_date, + absl.name + FROM account_bank_statement_line AS absl + INNER JOIN account_bank_statement AS abs + ON absl.statement_id = abs.id + WHERE EXISTS (SELECT 1 + FROM account_voucher_line JOIN account_move_line ON + (account_voucher_line.move_line_id = account_move_line.id) + WHERE voucher_id=absl.voucher_id + AND account_move_line.move_id = %s ) + """, + (invoice['move_id'][0],) + ) statement_lines = cr.dictfetchone() if statement_lines: raise osv.except_osv( _('Error!'), - _('Invoice already imported in bank statment (%s) at %s on line %s' + _('Invoice already imported in bank statment (%s) ' + 'at %s on line %s' % (statement_lines['statement_name'], statement_lines['statement_date'], statement_lines['name'],))) - return super(account_invoice, self).action_cancel(cr, uid, ids, context=context) + return super(account_invoice, self).action_cancel(cr, uid, ids, + context=context) diff --git a/__unported__/account_chart_update/__openerp__.py b/__unported__/account_chart_update/__openerp__.py index e7948d978..8d49d9c85 100644 --- a/__unported__/account_chart_update/__openerp__.py +++ b/__unported__/account_chart_update/__openerp__.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) -# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L.(http://www.pexego.es) # Copyright (c) 2013 Joaquin Gutierrez (http://www.gutierrezweb.es) # Pedro Manuel Baeza # $Id$ diff --git a/__unported__/account_chart_update/wizard/wizard_chart_update.py b/__unported__/account_chart_update/wizard/wizard_chart_update.py index 8a2f19b18..b0b6d31d1 100644 --- a/__unported__/account_chart_update/wizard/wizard_chart_update.py +++ b/__unported__/account_chart_update/wizard/wizard_chart_update.py @@ -2,7 +2,7 @@ ############################################################################## # # Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) -# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L.(http://www.pexego.es) # @authors: Jordi Esteve (Zikzakmedia), Borja López Soilán (Pexego) # # This program is free software: you can redistribute it and/or modify @@ -32,7 +32,8 @@ def _reopen(self, res_id, model): 'res_id': res_id, 'res_model': self._name, 'target': 'new', - # save original model in context, because selecting the list of available + # save original model in context, + # because selecting the list of available # templates requires a model in context 'context': { 'default_model': model, @@ -118,8 +119,10 @@ class wizard_update_charts_accounts(orm.TransientModel): _get_lang_selection_options, 'Language', size=5, - help="For records searched by name (taxes, tax codes, fiscal positions), " - "the template name will be matched against the record name on this language." + help="For records searched by name " + "(taxes, tax codes, fiscal positions), " + "the template name will be matched against the record " + "name on this language." ), 'update_tax_code': fields.boolean( 'Update tax codes', @@ -132,11 +135,13 @@ class wizard_update_charts_accounts(orm.TransientModel): ), 'update_account': fields.boolean( 'Update accounts', - help="Existing accounts are updated. Accounts are searched by code." + help="Existing accounts are updated. " + "Accounts are searched by code." ), 'update_fiscal_position': fields.boolean( 'Update fiscal positions', - help="Existing fiscal positions are updated. Fiscal positions are searched by name." + help="Existing fiscal positions are updated. " + "Fiscal positions are searched by name." ), 'update_children_accounts_parent': fields.boolean( "Update children accounts parent", @@ -163,18 +168,32 @@ class wizard_update_charts_accounts(orm.TransientModel): 'Taxes', ondelete='cascade' ), - 'account_ids': fields.one2many('wizard.update.charts.accounts.account', - 'update_chart_wizard_id', 'Accounts', ondelete='cascade'), - 'fiscal_position_ids': fields.one2many('wizard.update.charts.accounts.fiscal.position', - 'update_chart_wizard_id', 'Fiscal positions', ondelete='cascade'), + 'account_ids': fields.one2many( + 'wizard.update.charts.accounts.account', + 'update_chart_wizard_id', + 'Accounts', + ondelete='cascade' + ), + 'fiscal_position_ids': fields.one2many( + 'wizard.update.charts.accounts.fiscal.position', + 'update_chart_wizard_id', + 'Fiscal positions', + ondelete='cascade' + ), 'new_tax_codes': fields.integer('New tax codes', readonly=True), 'new_taxes': fields.integer('New taxes', readonly=True), 'new_accounts': fields.integer('New accounts', readonly=True), 'new_fps': fields.integer('New fiscal positions', readonly=True), - 'updated_tax_codes': fields.integer('Updated tax codes', readonly=True), + 'updated_tax_codes': fields.integer( + 'Updated tax codes', + readonly=True + ), 'updated_taxes': fields.integer('Updated taxes', readonly=True), 'updated_accounts': fields.integer('Updated accounts', readonly=True), - 'updated_fps': fields.integer('Updated fiscal positions', readonly=True), + 'updated_fps': fields.integer( + 'Updated fiscal positions', + readonly=True + ), 'log': fields.text('Messages and Errors', readonly=True) } @@ -262,8 +281,9 @@ class wizard_update_charts_accounts(orm.TransientModel): _defaults = { 'state': 'init', - 'company_id': lambda self, cr, uid, context: self.pool.get('res.users').browse( - cr, uid, [uid], context)[0].company_id.id, + 'company_id': lambda self, cr, uid, context: + self.pool.get('res.users').browse( + cr, uid, [uid], context)[0].company_id.id, 'chart_template_id': _get_chart, 'update_tax_code': True, 'update_tax': True, @@ -271,7 +291,8 @@ class wizard_update_charts_accounts(orm.TransientModel): 'update_fiscal_position': True, 'update_children_accounts_parent': True, 'continue_on_errors': False, - 'lang': lambda self, cr, uid, context: context and context.get('lang') or None, + 'lang': lambda self, cr, uid, context: + context and context.get('lang') or None, } def onchange_company_id(self, cr, uid, ids, company_id, context=None): @@ -280,7 +301,8 @@ class wizard_update_charts_accounts(orm.TransientModel): """ res = { 'value': { - 'code_digits': self._get_code_digits(cr, uid, context=context, company_id=company_id), + 'code_digits': self._get_code_digits( + cr, uid, context=context, company_id=company_id), } } return res @@ -378,7 +400,8 @@ class wizard_update_charts_accounts(orm.TransientModel): acc_templ_mapping[acc_templ.id] = acc_ids and acc_ids[0] or False return acc_templ_mapping[acc_templ.id] - def _map_fp_template(self, cr, uid, wizard, fp_templ_mapping, fp_template, context=None): + def _map_fp_template(self, cr, uid, wizard, fp_templ_mapping, + fp_template, context=None): """ Adds a fiscal position template -> fiscal position id to the mapping. """ @@ -562,7 +585,9 @@ class wizard_update_charts_accounts(orm.TransientModel): for delay_vals_wiz in delay_wiz_tax: wiz_taxes_obj.create(cr, uid, delay_vals_wiz, context) - return {'new': new_taxes, 'updated': updated_taxes, 'mapping': tax_templ_mapping} + return {'new': new_taxes, + 'updated': updated_taxes, + 'mapping': tax_templ_mapping} def _find_accounts(self, cr, uid, wizard, context=None): """ @@ -614,7 +639,8 @@ class wizard_update_charts_accounts(orm.TransientModel): modified = False notes = "" account = acc_obj.browse(cr, uid, account_id, context=context) - if account.name != acc_templ.name and account.name != wizard.company_id.name: + if (account.name != acc_templ.name and + account.name != wizard.company_id.name): notes += _("The name is different.\n") modified = True if account.type != acc_templ.type: @@ -689,14 +715,18 @@ class wizard_update_charts_accounts(orm.TransientModel): if fp_templ.tax_ids and fp.tax_ids: for fp_tax_templ in fp_templ.tax_ids: found = False - tax_src_id = self._map_tax_template(cr, uid, wizard, - tax_templ_mapping, - fp_tax_templ.tax_src_id, - context=None) - tax_dest_id = self._map_tax_template(cr, uid, wizard, - tax_templ_mapping, - fp_tax_templ.tax_dest_id, - context=None) + tax_src_id = self._map_tax_template( + cr, uid, wizard, + tax_templ_mapping, + fp_tax_templ.tax_src_id, + context=None + ) + tax_dest_id = self._map_tax_template( + cr, uid, wizard, + tax_templ_mapping, + fp_tax_templ.tax_dest_id, + context=None + ) for fp_tax in fp.tax_ids: if fp_tax.tax_src_id.id == tax_src_id: if not fp_tax.tax_dest_id: @@ -708,12 +738,18 @@ class wizard_update_charts_accounts(orm.TransientModel): found = True break if not found: - notes += _("Tax mapping not found on the fiscal position instance: %s -> %s.\n") % ( + msg = (fp_tax_templ.tax_dest_id and + fp_tax_templ.tax_dest_id.name or + _('None')) + notes += _("Tax mapping not found on the fiscal " + "position instance: %s -> %s.\n") % ( fp_tax_templ.tax_src_id.name, - fp_tax_templ.tax_dest_id and fp_tax_templ.tax_dest_id.name or _('None')) + msg + ) modified = True elif fp_templ.tax_ids and not fp.tax_ids: - notes += _("The template has taxes the fiscal position instance does not.\n") + notes += _("The template has taxes the fiscal " + "position instance does not.\n") modified = True # Check fiscal position accounts for changes if fp_templ.account_ids and fp.account_ids: @@ -751,7 +787,9 @@ class wizard_update_charts_accounts(orm.TransientModel): 'update_fiscal_position_id': fp_id, 'notes': notes, }, context=context) - return {'new': new_fps, 'updated': updated_fps, 'mapping': fp_templ_mapping} + return {'new': new_fps, + 'updated': updated_fps, + 'mapping': fp_templ_mapping} def action_find_records(self, cr, uid, ids, context=None): """ @@ -822,12 +860,13 @@ class wizard_update_charts_accounts(orm.TransientModel): tax_code_template.parent_id, context=context) # Values + p_id = tax_code_template.parent_id.id vals = { 'name': tax_code_name, 'code': tax_code_template.code, 'info': tax_code_template.info, 'parent_id': (tax_code_template.parent_id and - tax_code_template_mapping.get(tax_code_template.parent_id.id)), + tax_code_template_mapping.get(p_id)), 'company_id': wizard.company_id.id, 'sign': tax_code_template.sign, } @@ -847,16 +886,19 @@ class wizard_update_charts_accounts(orm.TransientModel): updated_tax_codes += 1 modified = True else: - tax_code_id = wiz_tax_code.update_tax_code_id and wiz_tax_code.update_tax_code_id.id + tax_code_id = (wiz_tax_code.update_tax_code_id and + wiz_tax_code.update_tax_code_id.id) modified = False # Store the tax codes on the map tax_code_template_mapping[tax_code_template.id] = tax_code_id if modified: # Detect errors + p_id = tax_code_template.parent_id.id if (tax_code_template.parent_id and - not tax_code_template_mapping.get(tax_code_template.parent_id.id)): + not tax_code_template_mapping.get(p_id)): log.add( - _("Tax code %s: The parent tax code %s can not be set.\n") % ( + _("Tax code %s: The parent tax code %s " + "can not be set.\n") % ( tax_code_name, tax_code_template.parent_id.name), True ) @@ -866,7 +908,8 @@ class wizard_update_charts_accounts(orm.TransientModel): 'mapping': tax_code_template_mapping } - def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context=None): + def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, + context=None): """ Search for, and load, tax templates to create/update. """ @@ -887,7 +930,8 @@ class wizard_update_charts_accounts(orm.TransientModel): tax_template.ref_base_code_id, tax_template.ref_tax_code_id ] - for tax_code_template in [tmpl for tmpl in tax_code_templates_to_find if tmpl]: + for tax_code_template in \ + [tmpl for tmpl in tax_code_templates_to_find if tmpl]: self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template, context=context) @@ -899,21 +943,35 @@ class wizard_update_charts_accounts(orm.TransientModel): 'type': tax_template.type, 'applicable_type': tax_template.applicable_type, 'domain': tax_template.domain, - 'parent_id': tax_template.parent_id and tax_template_mapping.get(tax_template.parent_id.id), + 'parent_id': ( + tax_template.parent_id and + tax_template_mapping.get(tax_template.parent_id.id) + ), 'child_depend': tax_template.child_depend, 'python_compute': tax_template.python_compute, 'python_compute_inv': tax_template.python_compute_inv, 'python_applicable': tax_template.python_applicable, - 'base_code_id': (tax_template.base_code_id and - tax_code_template_mapping.get(tax_template.base_code_id.id)), - 'tax_code_id': (tax_template.tax_code_id and - tax_code_template_mapping.get(tax_template.tax_code_id.id)), + 'base_code_id': ( + tax_template.base_code_id and + tax_code_template_mapping.get(tax_template.base_code_id.id) + ), + 'tax_code_id': ( + tax_template.tax_code_id and + tax_code_template_mapping.get(tax_template.tax_code_id.id) + ), 'base_sign': tax_template.base_sign, 'tax_sign': tax_template.tax_sign, - 'ref_base_code_id': (tax_template.ref_base_code_id and - tax_code_template_mapping.get(tax_template.ref_base_code_id.id)), - 'ref_tax_code_id': (tax_template.ref_tax_code_id and - tax_code_template_mapping.get(tax_template.ref_tax_code_id.id)), + 'ref_base_code_id': ( + tax_template.ref_base_code_id and + tax_code_template_mapping.get( + tax_template.ref_base_code_id.id + ) + ), + 'ref_tax_code_id': ( + tax_template.ref_tax_code_id and + tax_code_template_mapping.get( + tax_template.ref_tax_code_id.id) + ), 'ref_base_sign': tax_template.ref_base_sign, 'ref_tax_sign': tax_template.ref_tax_sign, 'include_base_amount': tax_template.include_base_amount, @@ -943,41 +1001,63 @@ class wizard_update_charts_accounts(orm.TransientModel): if modified: # Add to the dict of taxes waiting for accounts. taxes_pending_for_accounts[tax_id] = { - 'account_collected_id': (tax_template.account_collected_id and - tax_template.account_collected_id.id or False), - 'account_paid_id': (tax_template.account_paid_id and - tax_template.account_paid_id.id or False), + 'account_collected_id': ( + tax_template.account_collected_id and + tax_template.account_collected_id.id or False + ), + 'account_paid_id': ( + tax_template.account_paid_id and + tax_template.account_paid_id.id or False + ), } # Detect errors - if tax_template.parent_id and not tax_template_mapping.get(tax_template.parent_id.id): + if (tax_template.parent_id and not + tax_template_mapping.get(tax_template.parent_id.id)): log.add( _("Tax %s: The parent tax %s can not be set.\n") % ( tax_template.name, tax_template.parent_id.name), True ) - if tax_template.base_code_id and not tax_code_template_mapping.get(tax_template.base_code_id.id): + if (tax_template.base_code_id and not + tax_code_template_mapping.get( + tax_template.base_code_id.id + )): log.add( - _("Tax %s: The tax code for the base %s can not be set.\n") % ( + _("Tax %s: The tax code for the base %s " + "can not be set.\n") % ( tax_template.name, tax_template.base_code_id.name), True ) - if tax_template.tax_code_id and not tax_code_template_mapping.get(tax_template.tax_code_id.id): + if (tax_template.tax_code_id and not + tax_code_template_mapping.get( + tax_template.tax_code_id.id)): log.add( - _("Tax %s: The tax code for the tax %s can not be set.\n") % ( - tax_template.name, tax_template.tax_code_id.name), + _("Tax %s: The tax code for the tax %s " + "can not be set.\n") % ( + tax_template.name, tax_template.tax_code_id.name + ), True ) if (tax_template.ref_base_code_id and - not tax_code_template_mapping.get(tax_template.ref_base_code_id.id)): + not tax_code_template_mapping.get( + tax_template.ref_base_code_id.id)): log.add( - _("Tax %s: The tax code for the base refund %s can not be set.\n") % ( - tax_template.name, tax_template.ref_base_code_id.name), + _("Tax %s: The tax code for the base refund %s " + "can not be set.\n") % ( + tax_template.name, + tax_template.ref_base_code_id.name + ), True ) - if tax_template.ref_tax_code_id and not tax_code_template_mapping.get(tax_template.ref_tax_code_id.id): + if (tax_template.ref_tax_code_id and not + tax_code_template_mapping.get( + tax_template.ref_tax_code_id.id)): log.add( - _("Tax %s: The tax code for the tax refund %s can not be set.\n") % ( - tax_template.name, tax_template.ref_tax_code_id.name), + _("Tax %s: The tax code for the tax refund %s" + " can not be set.\n") % ( + tax_template.name, + tax_template.ref_tax_code_id.name + ), True ) return { @@ -987,7 +1067,8 @@ class wizard_update_charts_accounts(orm.TransientModel): 'pending': taxes_pending_for_accounts } - def _update_children_accounts_parent(self, cr, uid, wizard, log, parent_account_id, context=None): + def _update_children_accounts_parent(self, cr, uid, wizard, + log, parent_account_id, context=None): """ Updates the parent_id of accounts that seem to be children of the given account (accounts that start with the same code and are brothers @@ -1010,24 +1091,30 @@ class wizard_update_charts_accounts(orm.TransientModel): if children_ids: try: - account_account.write(cr, uid, children_ids, {'parent_id': parent_account.id}, context=context) + account_account.write(cr, uid, children_ids, + {'parent_id': parent_account.id}, + context=context) except orm.except_orm, ex: log.add( - _("Exception setting the parent of account %s children: %s - %s.\n") % ( - parent_account.code, ex.name, ex.value), + _("Exception setting the parent of " + "account %s children: %s - %s.\n") % ( + parent_account.code, ex.name, ex.value + ), True ) return True - def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=None): + def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, + context=None): """ Search for, and load, account templates to create/update. """ accounts = self.pool.get('account.account') root_account_id = wizard.chart_template_id.account_root_id.id - # Disable the parent_store computing on account_account during the batch - # processing, we will force _parent_store_compute afterwards. + # Disable the parent_store computing on account_account + # during the batch processing, + # we will force _parent_store_compute afterwards. self.pool._init = True new_accounts = 0 updated_accounts = 0 @@ -1035,7 +1122,10 @@ class wizard_update_charts_accounts(orm.TransientModel): for wiz_account in wizard.account_ids: account_template = wiz_account.account_id # Ensure the parent account template is on the map. - self._map_account_template(cr, uid, wizard, account_template_mapping, account_template.parent_id, context) + self._map_account_template(cr, uid, wizard, + account_template_mapping, + account_template.parent_id, + context) # Ensure the related tax templates are on the map. for tax_template in account_template.tax_ids: self._map_tax_template(cr, uid, wizard, tax_template_mapping, @@ -1052,17 +1142,27 @@ class wizard_update_charts_accounts(orm.TransientModel): code = '%s%s' % ( code, '0' * (wizard.code_digits - len(code))) # Values + p_id = account_template.parent_id.id vals = { - 'name': (root_account_id == account_template.id) and wizard.company_id.name or account_template.name, - 'currency_id': account_template.currency_id and account_template.currency_id.id or False, + 'name': ((root_account_id == account_template.id) and + wizard.company_id.name or + account_template.name), + 'currency_id': (account_template.currency_id and + account_template.currency_id.id or + False), 'code': code, 'type': account_template.type, - 'user_type': account_template.user_type and account_template.user_type.id or False, + 'user_type': (account_template.user_type and + account_template.user_type.id or + False), 'reconcile': account_template.reconcile, 'shortcut': account_template.shortcut, 'note': account_template.note, - 'parent_id': (account_template.parent_id - and account_template_mapping.get(account_template.parent_id.id) or False), + 'parent_id': ( + account_template.parent_id + and account_template_mapping.get(p_id) or + False + ), 'tax_ids': [(6, 0, tax_ids)], 'company_id': wizard.company_id.id, } @@ -1090,15 +1190,20 @@ class wizard_update_charts_accounts(orm.TransientModel): log.add(_("Exception writing account %s: %s - %s.\n") % (code, ex.name, ex.value), True) else: - account_id = wiz_account.update_account_id and wiz_account.update_account_id.id + account_id = (wiz_account.update_account_id and + wiz_account.update_account_id.id) # Store the account on the map account_template_mapping[account_template.id] = account_id if modified: # Detect errors - if account_template.parent_id and not account_template_mapping.get(account_template.parent_id.id): + if (account_template.parent_id and not + account_template_mapping.get( + account_template.parent_id.id)): log.add( - _("Account %s: The parent account %s can not be set.\n") % ( - code, account_template.parent_id.code), + _("Account %s: The parent account %s " + "can not be set.\n") % ( + code, account_template.parent_id.code + ), True ) # Set this account as the parent of the accounts that seem to @@ -1142,25 +1247,40 @@ class wizard_update_charts_accounts(orm.TransientModel): if (acc_templ_mapping.get(value['account_collected_id']) and acc_templ_mapping.get(value['account_paid_id'])): vals = { - 'account_collected_id': acc_templ_mapping[value['account_collected_id']], - 'account_paid_id': acc_templ_mapping[value['account_paid_id']], + 'account_collected_id': acc_templ_mapping[ + value['account_collected_id'] + ], + 'account_paid_id': acc_templ_mapping[ + value['account_paid_id'] + ], } taxes.write(cr, uid, [key], vals) else: tax = taxes.browse(cr, uid, key) - if not acc_templ_mapping.get(value['account_collected_id']): - log.add(_("Tax %s: The collected account can not be set.\n") % (tax.name), True) + val = value['account_collected_id'] + if not acc_templ_mapping.get(val): + log.add( + _("Tax %s: The collected account " + "can not be set.\n") % ( + tax.name + ), + True + ) if not acc_templ_mapping.get(value['account_paid_id']): log.add(_("Tax %s: The paid account can not be set.\n") % (tax.name), True) - def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, acc_templ_mapping, context=None): + def _update_fiscal_positions(self, cr, uid, wizard, log, + tax_template_mapping, + acc_templ_mapping, context=None): """ Search for, and load, fiscal position templates to create/update. """ fiscalpositions = self.pool.get('account.fiscal.position') fiscalpositions_taxes = self.pool.get('account.fiscal.position.tax') - fiscalpositions_account = self.pool.get('account.fiscal.position.account') + fiscalpositions_account = self.pool.get( + 'account.fiscal.position.account' + ) new_fps = 0 updated_fps = 0 @@ -1178,7 +1298,8 @@ class wizard_update_charts_accounts(orm.TransientModel): fp_id = fiscalpositions.create(cr, uid, vals_fp) new_fps += 1 modified = True - elif wizard.update_fiscal_position and wiz_fp.update_fiscal_position_id: + elif (wizard.update_fiscal_position and + wiz_fp.update_fiscal_position_id): # Update the given fiscal position (remove the tax and account # mappings, that will be regenerated later) fp_id = wiz_fp.update_fiscal_position_id.id @@ -1193,33 +1314,47 @@ class wizard_update_charts_accounts(orm.TransientModel): cr, uid, [('position_id', '=', fp_id)]) fiscalpositions_account.unlink(cr, uid, fp_account_ids) else: - fp_id = wiz_fp.update_fiscal_position_id and wiz_fp.update_fiscal_position_id.id + fp_id = (wiz_fp.update_fiscal_position_id and + wiz_fp.update_fiscal_position_id.id) if modified: # (Re)create the tax mappings for fp_tax in fp_template.tax_ids: # Ensure the related tax templates are on the map. - self._map_tax_template(cr, uid, wizard, tax_template_mapping, fp_tax.tax_src_id, context) + self._map_tax_template(cr, uid, wizard, + tax_template_mapping, + fp_tax.tax_src_id, context) if fp_tax.tax_dest_id: - self._map_tax_template(cr, uid, wizard, tax_template_mapping, fp_tax.tax_dest_id, context) + self._map_tax_template(cr, uid, wizard, + tax_template_mapping, + fp_tax.tax_dest_id, context) # Create the fp tax mapping vals_tax = { - 'tax_src_id': tax_template_mapping.get(fp_tax.tax_src_id.id), - 'tax_dest_id': fp_tax.tax_dest_id and tax_template_mapping.get(fp_tax.tax_dest_id.id), + 'tax_src_id': tax_template_mapping.get( + fp_tax.tax_src_id.id + ), + 'tax_dest_id': (fp_tax.tax_dest_id and + tax_template_mapping.get( + fp_tax.tax_dest_id.id)), 'position_id': fp_id, } fiscalpositions_taxes.create(cr, uid, vals_tax) # Check for errors if not tax_template_mapping.get(fp_tax.tax_src_id.id): log.add( - _("Fiscal position %s: The source tax %s can not be set.\n") % ( - fp_template.name, fp_tax.tax_src_id.code), + _("Fiscal position %s: The source tax %s " + "can not be set.\n") % ( + fp_template.name, fp_tax.tax_src_id.code + ), True ) - if fp_tax.tax_dest_id and not tax_template_mapping.get(fp_tax.tax_dest_id.id): + if fp_tax.tax_dest_id and not tax_template_mapping.get( + fp_tax.tax_dest_id.id): log.add( - _("Fiscal position %s: The destination tax %s can not be set.\n") % ( - fp_template.name, fp_tax.tax_dest_id.name), + _("Fiscal position %s: The destination" + "tax %s can not be set.\n") % ( + fp_template.name, fp_tax.tax_dest_id.name + ), True ) # (Re)create the account mappings @@ -1236,23 +1371,37 @@ class wizard_update_charts_accounts(orm.TransientModel): context=context) # Create the fp account mapping vals_account = { - 'account_src_id': acc_templ_mapping.get(fp_account.account_src_id.id), - 'account_dest_id': (fp_account.account_dest_id and - acc_templ_mapping.get(fp_account.account_dest_id.id)), + 'account_src_id': acc_templ_mapping.get( + fp_account.account_src_id.id + ), + 'account_dest_id': ( + fp_account.account_dest_id and + acc_templ_mapping.get( + fp_account.account_dest_id.id + ) + ), 'position_id': fp_id, } fiscalpositions_account.create(cr, uid, vals_account) # Check for errors if not acc_templ_mapping.get(fp_account.account_src_id.id): log.add( - _("Fiscal position %s: The source account %s can not be set.\n") % ( - fp_template.name, fp_account.account_src_id.code), + _("Fiscal position %s: The source account %s " + "can not be set.\n") % ( + fp_template.name, + fp_account.account_src_id.code + ), True ) - if fp_account.account_dest_id and not acc_templ_mapping.get(fp_account.account_dest_id.id): + if (fp_account.account_dest_id and not + acc_templ_mapping.get( + fp_account.account_dest_id.id)): log.add( - _("Fiscal position %s: The destination account %s can not be set.\n") % ( - fp_template.name, fp_account.account_dest_id.code), + _("Fiscal position %s: The destination account %s " + "can not be set.\n") % ( + fp_template.name, + fp_account.account_dest_id.code + ), True ) @@ -1363,15 +1512,28 @@ class wizard_update_charts_accounts_tax(orm.TransientModel): """ _name = 'wizard.update.charts.accounts.tax' _columns = { - 'tax_id': fields.many2one('account.tax.template', 'Tax template', required=True, ondelete='set null'), + 'tax_id': fields.many2one( + 'account.tax.template', + 'Tax template', + required=True, + ondelete='set null' + ), 'update_chart_wizard_id': fields.many2one( - 'wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'wizard.update.charts.accounts', + 'Update chart wizard', + required=True, + ondelete='cascade' + ), 'type': fields.selection([ ('new', 'New template'), ('updated', 'Updated template'), ], 'Type'), 'update_tax_id': fields.many2one( - 'account.tax', 'Tax to update', required=False, ondelete='set null'), + 'account.tax', + 'Tax to update', + required=False, + ondelete='set null' + ), 'notes': fields.text('Notes'), } diff --git a/__unported__/account_compute_tax_amount/__openerp__.py b/__unported__/account_compute_tax_amount/__openerp__.py index 1b137397e..a07bf4463 100644 --- a/__unported__/account_compute_tax_amount/__openerp__.py +++ b/__unported__/account_compute_tax_amount/__openerp__.py @@ -25,7 +25,7 @@ "author": "Camptocamp", "description": """Recompute tax_amount to avoid sign problem""", 'website': 'http://www.camptocamp.com', - 'data' : [], + 'data': [], 'installable': False, 'active': False, } diff --git a/__unported__/account_compute_tax_amount/account_move_line.py b/__unported__/account_compute_tax_amount/account_move_line.py index fe8b5b49b..1bd6809a0 100644 --- a/__unported__/account_compute_tax_amount/account_move_line.py +++ b/__unported__/account_compute_tax_amount/account_move_line.py @@ -30,14 +30,16 @@ class account_move_line(orm.Model): # We set the tax_amount invisible, because we recompute it in every case. _columns = { - 'tax_amount': fields.float('Tax/Base Amount', - digits_compute=dp.get_precision('Account'), - invisible=True, - select=True, - help="If the Tax account is a tax code account, " - "this field will contain the taxed amount. " - "If the tax account is base tax code, " - "this field will contain the basic amount (without tax)."), + 'tax_amount': fields.float( + 'Tax/Base Amount', + digits_compute=dp.get_precision('Account'), + invisible=True, + select=True, + help="If the Tax account is a tax code account, " + "this field will contain the taxed amount. " + "If the tax account is base tax code, " + "this field will contain the basic amount (without tax)." + ), } def create(self, cr, uid, vals, context=None, check=True): @@ -55,11 +57,14 @@ class account_move_line(orm.Model): context=context) return result - def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True): - result = super(account_move_line, self).write(cr, uid, ids, vals, - context=context, - check=check, - update_check=update_check) + def write(self, cr, uid, ids, vals, context=None, check=True, + update_check=True): + result = super(account_move_line, self).write( + cr, uid, ids, vals, + context=context, + check=check, + update_check=update_check + ) if result: if ('debit' in vals) or ('credit' in vals): move_lines = self.read(cr, uid, ids, diff --git a/__unported__/account_constraints/__openerp__.py b/__unported__/account_constraints/__openerp__.py index 26381bba8..c5ab4d7f8 100644 --- a/__unported__/account_constraints/__openerp__.py +++ b/__unported__/account_constraints/__openerp__.py @@ -51,8 +51,8 @@ Summary of constraints are: invoice or a bank statement, no matter what the status of the move (draft, validated or posted). This is useful in a standard context but even more if you're using `account_default_draft_move`. This way you ensure - that the user cannot make mistakes even in draft state, he must pass through the - parent object to make his modification. + that the user cannot make mistakes even in draft state, he must pass + through the parent object to make his modification. Contributors * Stéphane Bidoul diff --git a/__unported__/account_constraints/account_constraints.py b/__unported__/account_constraints/account_constraints.py index ad33829bb..09203a432 100644 --- a/__unported__/account_constraints/account_constraints.py +++ b/__unported__/account_constraints/account_constraints.py @@ -62,9 +62,12 @@ class AccountMoveLine(orm.Model): _inherit = 'account.move.line' def _authorized_reconcile(self, vals): - """ Check if only reconcile_id and/or reconcile_partial_id are altered. We - cannot change other vals, but we should be able to write or unlink those field - (e.g. when you want to manually unreconcile an entry generated by an invoice). + """ Check if only reconcile_id and/or reconcile_partial_id are altered. + We cannot change other vals, but we should be able to write or unlink + those field. + e.g. when you want to manually unreconcile an entry + generated by an invoice + """ if not vals: return False @@ -72,7 +75,8 @@ class AccountMoveLine(orm.Model): write_keys = set(vals) return rec_keys.issuperset(write_keys) - def _check_invoice_related_move(self, cr, uid, ids, vals=None, context=None): + def _check_invoice_related_move(self, cr, uid, ids, vals=None, + context=None): for line in self.browse(cr, uid, ids, context=context): if line.invoice: if self._authorized_reconcile(vals): @@ -81,11 +85,14 @@ class AccountMoveLine(orm.Model): (line.invoice.name, line.invoice.id)) raise osv.except_osv( _('Error'), - _('You cannot do this on an entry generated by an invoice. You must ' - 'change the related invoice directly.\n%s.') % err_msg) + _('You cannot do this on an entry generated ' + 'by an invoice. You must change the related ' + 'invoice directly.\n%s.') % err_msg + ) return True - def _check_statement_related_move(self, cr, uid, ids, vals=None, context=None): + def _check_statement_related_move(self, cr, uid, ids, vals=None, + context=None): for line in self.browse(cr, uid, ids, context=context): if line.statement_id: if self._authorized_reconcile(vals): @@ -94,8 +101,10 @@ class AccountMoveLine(orm.Model): (line.statement_id.name, line.statement_id.id)) raise osv.except_osv( _('Error'), - _('You cannot do this on an entry generated by a bank statement. ' - 'You must change the related bank statement directly.\n%s.') % err_msg) + _('You cannot do this on an entry generated ' + 'by a bank statement. You must change the related' + 'bank statement directly.\n%s.') % err_msg + ) return True def unlink(self, cr, uid, ids, context=None, check=True): @@ -103,7 +112,8 @@ class AccountMoveLine(orm.Model): - Is the move related to an invoice - Is the move related to a bank statement - - Is other values than reconcile_partial_id and/or reconcile_id modified + - Is other values than reconcile_partial_id and/or + reconcile_id modified In that case, we forbid the move to be deleted even if draft. We should never delete directly a move line related or generated by @@ -115,14 +125,18 @@ class AccountMoveLine(orm.Model): if not context.get('from_parent_object', False): self._check_invoice_related_move(cr, uid, ids, context=context) self._check_statement_related_move(cr, uid, ids, context=context) - return super(AccountMoveLine, self).unlink(cr, uid, ids, context=context, check=check) + return super(AccountMoveLine, self).unlink(cr, uid, ids, + context=context, + check=check) - def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True): + def write(self, cr, uid, ids, vals, context=None, check=True, + update_check=True): """ Add the following checks: - Is the move related to an invoice - Is the move related to a bank statement - - Is other values than reconcile_partial_id and/or reconcile_id modified + - Is other values than reconcile_partial_id and/or + reconcile_id modified In that case, we forbid the move to be modified even if draft. We should never update directly a move line related or generated @@ -132,8 +146,10 @@ class AccountMoveLine(orm.Model): if context is None: context = {} if not context.get('from_parent_object', False): - self._check_invoice_related_move(cr, uid, ids, vals, context=context) - self._check_statement_related_move(cr, uid, ids, vals, context=context) + self._check_invoice_related_move(cr, uid, ids, vals, + context=context) + self._check_statement_related_move(cr, uid, ids, vals, + context=context) return super(AccountMoveLine, self).write( cr, uid, ids, vals, context=context, check=check, update_check=update_check @@ -194,7 +210,8 @@ class AccountInvoice(orm.Model): else: context = context.copy() context['from_parent_object'] = True - return super(AccountInvoice, self).action_cancel(cr, uid, ids, context=context) + return super(AccountInvoice, self).action_cancel(cr, uid, ids, + context=context) def action_move_create(self, cr, uid, ids, context=None): """Override the method to add the key 'from_parent_object' in @@ -204,7 +221,8 @@ class AccountInvoice(orm.Model): else: context = context.copy() context['from_parent_object'] = True - return super(AccountInvoice, self).action_move_create(cr, uid, ids, context=context) + return super(AccountInvoice, self).action_move_create(cr, uid, ids, + context=context) class AccountBankStatement(orm.Model): @@ -220,9 +238,11 @@ class AccountBankStatement(orm.Model): else: context = context.copy() context['from_parent_object'] = True - return super(AccountBankStatement, self).button_cancel(cr, uid, ids, context=context) + return super(AccountBankStatement, self).button_cancel(cr, uid, ids, + context=context) - def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, + def create_move_from_st_line(self, cr, uid, st_line_id, + company_currency_id, st_line_number, context=None): """Add the from_parent_object key in context in order to be able to post the move. diff --git a/__unported__/account_credit_control/line.py b/__unported__/account_credit_control/line.py index 10bfea0f7..964878fa4 100644 --- a/__unported__/account_credit_control/line.py +++ b/__unported__/account_credit_control/line.py @@ -44,7 +44,8 @@ class CreditControlLine(orm.Model): required=True, select=True ), - # maturity date of related move line we do not use a related field in order to + # maturity date of related move line we do not use + # a related field in order to # allow manual changes 'date_due': fields.date( 'Due date', @@ -196,7 +197,8 @@ class CreditControlLine(orm.Model): data['date_due'] = move_line.date_maturity data['state'] = 'draft' data['channel'] = level.channel - data['invoice_id'] = move_line.invoice.id if move_line.invoice else False + data['invoice_id'] = (move_line.invoice.id if + move_line.invoice else False) data['partner_id'] = move_line.partner_id.id data['amount_due'] = (move_line.amount_currency or move_line.debit or move_line.credit) @@ -282,7 +284,9 @@ class CreditControlLine(orm.Model): if line.state != 'draft': raise orm.except_orm( _('Error !'), - _('You are not allowed to delete a credit control line that ' - 'is not in draft state.')) + _('You are not allowed to delete a credit control ' + 'line that is not in draft state.') + ) - return super(CreditControlLine, self).unlink(cr, uid, ids, context=context) + return super(CreditControlLine, self).unlink(cr, uid, ids, + context=context) diff --git a/__unported__/account_credit_control/policy.py b/__unported__/account_credit_control/policy.py index 287d58a75..53214a838 100644 --- a/__unported__/account_credit_control/policy.py +++ b/__unported__/account_credit_control/policy.py @@ -63,7 +63,8 @@ class CreditControlPolicy(orm.Model): 'active': True, } - def _move_lines_domain(self, cr, uid, policy, controlling_date, context=None): + def _move_lines_domain(self, cr, uid, policy, controlling_date, + context=None): """Build the default domain for searching move lines""" account_ids = [a.id for a in policy.account_ids] return [('account_id', 'in', account_ids), @@ -74,8 +75,8 @@ class CreditControlPolicy(orm.Model): def _due_move_lines(self, cr, uid, policy, controlling_date, context=None): """ Get the due move lines for the policy of the company. - The set of ids will be reduced and extended according to the specific policies - defined on partners and invoices. + The set of ids will be reduced and extended according + to the specific policies defined on partners and invoices. Do not use direct SQL in order to respect security rules. @@ -88,7 +89,8 @@ class CreditControlPolicy(orm.Model): return set() domain_line = self._move_lines_domain(cr, uid, policy, - controlling_date, context=context) + controlling_date, + context=context) return set(move_l_obj.search(cr, uid, domain_line, context=context)) def _move_lines_subset(self, cr, uid, policy, controlling_date, @@ -131,7 +133,8 @@ class CreditControlPolicy(orm.Model): if add_obj_ids: domain = list(default_domain) domain.append((move_relation_field, 'in', add_obj_ids)) - to_add_ids = set(move_l_obj.search(cr, uid, domain, context=context)) + to_add_ids = set(move_l_obj.search(cr, uid, domain, + context=context)) # The lines which are linked to another policy do not have to be # included in the run for this policy. @@ -143,10 +146,12 @@ class CreditControlPolicy(orm.Model): if neg_obj_ids: domain = list(default_domain) domain.append((move_relation_field, 'in', neg_obj_ids)) - to_remove_ids = set(move_l_obj.search(cr, uid, domain, context=context)) + to_remove_ids = set(move_l_obj.search(cr, uid, domain, + context=context)) return to_add_ids, to_remove_ids - def _get_partner_related_lines(self, cr, uid, policy, controlling_date, context=None): + def _get_partner_related_lines(self, cr, uid, policy, controlling_date, + context=None): """ Get the move lines for a policy related to a partner. :param browse_record policy: policy @@ -158,9 +163,11 @@ class CreditControlPolicy(orm.Model): the process """ return self._move_lines_subset(cr, uid, policy, controlling_date, - 'res.partner', 'partner_id', context=context) + 'res.partner', 'partner_id', + context=context) - def _get_invoice_related_lines(self, cr, uid, policy, controlling_date, context=None): + def _get_invoice_related_lines(self, cr, uid, policy, controlling_date, + context=None): """ Get the move lines for a policy related to an invoice. :param browse_record policy: policy @@ -172,10 +179,13 @@ class CreditControlPolicy(orm.Model): the process """ return self._move_lines_subset(cr, uid, policy, controlling_date, - 'account.invoice', 'invoice', context=context) + 'account.invoice', 'invoice', + context=context) - def _get_move_lines_to_process(self, cr, uid, policy_id, controlling_date, context=None): - """Build a list of move lines ids to include in a run for a policy at a given date. + def _get_move_lines_to_process(self, cr, uid, policy_id, controlling_date, + context=None): + """Build a list of move lines ids to include in a run + for a policy at a given date. :param int/long policy: id of the policy :param str controlling_date: date of credit control @@ -189,7 +199,8 @@ class CreditControlPolicy(orm.Model): policy = self.browse(cr, uid, policy_id, context=context) # there is a priority between the lines, depicted by the calls below # warning, side effect method called on lines - lines = self._due_move_lines(cr, uid, policy, controlling_date, context=context) + lines = self._due_move_lines(cr, uid, policy, controlling_date, + context=context) add_ids, remove_ids = self._get_partner_related_lines(cr, uid, policy, controlling_date, context=context) @@ -234,8 +245,11 @@ class CreditControlPolicy(orm.Model): if policy not in allowed: allowed_names = u"\n".join(x.name for x in allowed) raise orm.except_orm( - _('You can only use a policy set on account %s') % account.name, - _("Please choose one of the following policies:\n %s") % allowed_names) + _('You can only use a policy set on ' + 'account %s') % account.name, + _("Please choose one of the following " + "policies:\n %s") % allowed_names + ) return True @@ -253,19 +267,24 @@ class CreditControlPolicyLevel(orm.Model): translate=True), 'level': fields.integer('Level', required=True), - 'computation_mode': fields.selection([('net_days', 'Due Date'), - ('end_of_month', 'Due Date, End Of Month'), - ('previous_date', 'Previous Reminder')], - 'Compute Mode', - required=True), + 'computation_mode': fields.selection( + [('net_days', 'Due Date'), + ('end_of_month', 'Due Date, End Of Month'), + ('previous_date', 'Previous Reminder')], + 'Compute Mode', + required=True + ), 'delay_days': fields.integer('Delay (in days)', required='True'), - 'email_template_id': fields.many2one('email.template', 'Email Template', + 'email_template_id': fields.many2one('email.template', + 'Email Template', required=True), 'channel': fields.selection([('letter', 'Letter'), ('email', 'Email')], 'Channel', required=True), - 'custom_text': fields.text('Custom Message', required=True, translate=True), + 'custom_text': fields.text('Custom Message', + required=True, + translate=True), 'custom_mail_text': fields.text('Custom Mail Message', required=True, translate=True), @@ -281,7 +300,8 @@ class CreditControlPolicyLevel(orm.Model): cr, uid, [('policy_id', '=', level.policy_id.id)], order='level asc', limit=1, context=context) - smallest_level = self.browse(cr, uid, smallest_level_id[0], context) + smallest_level = self.browse(cr, uid, smallest_level_id[0], + context) if smallest_level.computation_mode == 'previous_date': return False return True @@ -316,16 +336,20 @@ class CreditControlPolicyLevel(orm.Model): # ----- sql time related methods --------- def _net_days_get_boundary(self): - return " (mv_line.date_maturity + %(delay)s)::date <= date(%(controlling_date)s)" + return " (mv_line.date_maturity + %(delay)s)::date <= " + "date(%(controlling_date)s)" def _end_of_month_get_boundary(self): - return ("(date_trunc('MONTH', (mv_line.date_maturity + %(delay)s))+INTERVAL '1 MONTH - 1 day')::date" + return ("(date_trunc('MONTH', (mv_line.date_maturity + %(delay)s))+" + "INTERVAL '1 MONTH - 1 day')::date" "<= date(%(controlling_date)s)") def _previous_date_get_boundary(self): return "(cr_line.date + %(delay)s)::date <= date(%(controlling_date)s)" - def _get_sql_date_boundary_for_computation_mode(self, cr, uid, level, controlling_date, context=None): + def _get_sql_date_boundary_for_computation_mode(self, cr, uid, level, + controlling_date, + context=None): """Return a where clauses statement for the given controlling date and computation mode of the level""" fname = "_%s_get_boundary" % (level.computation_mode,) @@ -333,12 +357,15 @@ class CreditControlPolicyLevel(orm.Model): fnc = getattr(self, fname) return fnc() else: - raise NotImplementedError(_('Can not get function for computation mode: ' - '%s is not implemented') % (fname,)) + raise NotImplementedError( + _('Can not get function for computation mode: ' + '%s is not implemented') % (fname,) + ) # ----------------------------------------- - def _get_first_level_move_line_ids(self, cr, uid, level, controlling_date, lines, context=None): + def _get_first_level_move_line_ids(self, cr, uid, level, controlling_date, + lines, context=None): """Retrieve all the move lines that are linked to a first level. We use Raw SQL for performance. Security rule where applied in policy object when the first set of lines were retrieved""" @@ -358,8 +385,10 @@ class CreditControlPolicyLevel(orm.Model): " AND state NOT IN ('draft', 'ignored'))" " AND (mv_line.debit IS NOT NULL AND mv_line.debit != 0.0)\n") sql += " AND" - sql += self._get_sql_date_boundary_for_computation_mode(cr, uid, level, - controlling_date, context) + sql += self._get_sql_date_boundary_for_computation_mode( + cr, uid, level, + controlling_date, context + ) data_dict = {'controlling_date': controlling_date, 'line_ids': tuple(lines), 'delay': level.delay_days} @@ -369,7 +398,8 @@ class CreditControlPolicyLevel(orm.Model): level_lines.update([x[0] for x in res]) return level_lines - def _get_other_level_move_line_ids(self, cr, uid, level, controlling_date, lines, context=None): + def _get_other_level_move_line_ids(self, cr, uid, level, controlling_date, + lines, context=None): """ Retrieve the move lines for other levels than first level. """ level_lines = set() @@ -379,11 +409,12 @@ class CreditControlPolicyLevel(orm.Model): " FROM account_move_line mv_line\n" " JOIN credit_control_line cr_line\n" " ON (mv_line.id = cr_line.move_line_id)\n" - " WHERE cr_line.id = (SELECT credit_control_line.id FROM credit_control_line\n" - " WHERE credit_control_line.move_line_id = mv_line.id\n" - " AND state != 'ignored'" - " AND NOT manually_overridden" - " ORDER BY credit_control_line.level desc limit 1)\n" + " WHERE cr_line.id = (SELECT credit_control_line.id " + " FROM credit_control_line\n" + " WHERE credit_control_line.move_line_id = mv_line.id\n" + " AND state != 'ignored'" + " AND NOT manually_overridden" + " ORDER BY credit_control_line.level desc limit 1)\n" " AND cr_line.level = %(previous_level)s\n" " AND (mv_line.debit IS NOT NULL AND mv_line.debit != 0.0)\n" # lines from a previous level with a draft or ignored state @@ -393,10 +424,15 @@ class CreditControlPolicyLevel(orm.Model): " AND cr_line.state NOT IN ('draft', 'ignored')\n" " AND mv_line.id in %(line_ids)s\n") sql += " AND " - sql += self._get_sql_date_boundary_for_computation_mode(cr, uid, level, - controlling_date, context) - previous_level_id = self._previous_level(cr, uid, level, context=context) - previous_level = self.browse(cr, uid, previous_level_id, context=context) + sql += self._get_sql_date_boundary_for_computation_mode( + cr, uid, level, + controlling_date, + context + ) + previous_level_id = self._previous_level(cr, uid, level, + context=context) + previous_level = self.browse(cr, uid, previous_level_id, + context=context) data_dict = {'controlling_date': controlling_date, 'line_ids': tuple(lines), 'delay': level.delay_days, @@ -409,7 +445,8 @@ class CreditControlPolicyLevel(orm.Model): level_lines.update([x[0] for x in res]) return level_lines - def get_level_lines(self, cr, uid, level_id, controlling_date, lines, context=None): + def get_level_lines(self, cr, uid, level_id, controlling_date, lines, + context=None): """get all move lines in entry lines that match the current level""" assert not (isinstance(level_id, list) and len(level_id) > 1), \ "level_id: only one id expected" diff --git a/__unported__/account_credit_control/report/credit_control_summary.py b/__unported__/account_credit_control/report/credit_control_summary.py index 31c387258..ffbc65116 100644 --- a/__unported__/account_credit_control/report/credit_control_summary.py +++ b/__unported__/account_credit_control/report/credit_control_summary.py @@ -25,7 +25,8 @@ from openerp.report import report_sxw class CreditSummaryReport(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): - super(CreditSummaryReport, self).__init__(cr, uid, name, context=context) + super(CreditSummaryReport, self).__init__(cr, uid, name, + context=context) self.localcontext.update({ 'time': time, 'cr': cr, diff --git a/__unported__/account_credit_control/run.py b/__unported__/account_credit_control/run.py index 288f42c0d..fd32be1dc 100644 --- a/__unported__/account_credit_control/run.py +++ b/__unported__/account_credit_control/run.py @@ -76,13 +76,17 @@ class CreditControlRun(orm.Model): cr, uid, id, default=default, context=context) def _get_policies(self, cr, uid, context=None): - return self.pool['credit.control.policy'].search(cr, uid, [], context=context) + return self.pool['credit.control.policy'].search(cr, uid, [], + context=context) _defaults = {'state': 'draft', 'policy_ids': _get_policies} def _check_run_date(self, cr, uid, ids, controlling_date, context=None): - """Ensure that there is no credit line in the future using controlling_date""" + """Ensure that there is no credit line in the future + using controlling_date + + """ run_obj = self.pool['credit.control.run'] runs = run_obj.search(cr, uid, [('date', '>', controlling_date)], order='date DESC', limit=1, context=context) @@ -126,25 +130,38 @@ class CreditControlRun(orm.Model): for policy in policies: if policy.do_nothing: continue - lines = policy._get_move_lines_to_process(run.date, context=context) - manual_lines = policy._lines_different_policy(lines, context=context) + lines = policy._get_move_lines_to_process(run.date, + context=context) + manual_lines = policy._lines_different_policy(lines, + context=context) lines.difference_update(manual_lines) manually_managed_lines.update(manual_lines) policy_generated_ids = [] if lines: - # policy levels are sorted by level so iteration is in the correct order + # policy levels are sorted by level + # so iteration is in the correct order for level in reversed(policy.level_ids): - level_lines = level.get_level_lines(run.date, lines, context=context) - policy_generated_ids += cr_line_obj.create_or_update_from_mv_lines( - cr, uid, [], list(level_lines), level.id, run.date, context=context) + level_lines = level.get_level_lines(run.date, lines, + context=context) + policy_generated_ids += \ + cr_line_obj.create_or_update_from_mv_lines( + cr, uid, + [], + list(level_lines), + level.id, + run.date, + context=context + ) generated_ids.extend(policy_generated_ids) if policy_generated_ids: report += _("Policy \"%s\" has generated %d Credit Control Lines.\n") % \ (policy.name, len(policy_generated_ids)) credit_line_ids += policy_generated_ids else: - report += _("Policy \"%s\" has not generated any Credit Control Lines.\n" % - policy.name) + report += _( + "Policy \"%s\" has not generated any " + "Credit Control Lines.\n" % policy.name + ) vals = {'state': 'done', 'report': report, @@ -162,7 +179,8 @@ class CreditControlRun(orm.Model): cr.execute('SELECT id FROM credit_control_run' ' LIMIT 1 FOR UPDATE NOWAIT') except Exception: - # In case of exception openerp will do a rollback for us and free the lock + # In case of exception openerp will do a rollback + # for us and free the lock raise orm.except_orm(_('Error'), _('A credit control run is already running' ' in background, please try later.')) diff --git a/__unported__/account_credit_control/scenarios/features/steps/account_credit_control.py b/__unported__/account_credit_control/scenarios/features/steps/account_credit_control.py index f8718e7c0..5ec7fd3ce 100644 --- a/__unported__/account_credit_control/scenarios/features/steps/account_credit_control.py +++ b/__unported__/account_credit_control/scenarios/features/steps/account_credit_control.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +# flake8: noqa import time from behave import given, when from support import model diff --git a/__unported__/account_credit_control/scenarios/features/steps/account_credit_control_changer.py b/__unported__/account_credit_control/scenarios/features/steps/account_credit_control_changer.py index 0597438b6..ce9d944d7 100644 --- a/__unported__/account_credit_control/scenarios/features/steps/account_credit_control_changer.py +++ b/__unported__/account_credit_control/scenarios/features/steps/account_credit_control_changer.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# flake8: noqa @given(u'I change level for invoice "{invoice_name}" to "{level_name}" of policy "{policy_name}"') def impl(ctx, invoice_name, level_name, policy_name): invoice = model('account.invoice').get([('number', '=', invoice_name)]) diff --git a/__unported__/account_credit_control/scenarios/features/steps/account_voucher.py b/__unported__/account_credit_control/scenarios/features/steps/account_voucher.py index f89ce5721..a73c78fef 100644 --- a/__unported__/account_credit_control/scenarios/features/steps/account_voucher.py +++ b/__unported__/account_credit_control/scenarios/features/steps/account_voucher.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +# flake8: noqa from support import * import datetime diff --git a/__unported__/account_credit_control/wizard/credit_control_communication.py b/__unported__/account_credit_control/wizard/credit_control_communication.py index ba0320337..a32e9df5f 100644 --- a/__unported__/account_credit_control/wizard/credit_control_communication.py +++ b/__unported__/account_credit_control/wizard/credit_control_communication.py @@ -27,34 +27,57 @@ logger = logging.getLogger('credit.control.line.mailing') class CreditCommunication(TransientModel): """Shell class used to provide a base model to email template and reporting. - Il use this approche in version 7 a browse record will exist even if not saved""" + Il use this approche in version 7 a browse record + will exist even if not saved + + """ _name = "credit.control.communication" _description = "credit control communication" _rec_name = 'partner_id' - _columns = {'partner_id': fields.many2one('res.partner', 'Partner', required=True), + _columns = { + 'partner_id': fields.many2one( + 'res.partner', + 'Partner', + required=True + ), - 'current_policy_level': fields.many2one('credit.control.policy.level', - 'Level', required=True), + 'current_policy_level': fields.many2one( + 'credit.control.policy.level', + 'Level', + required=True + ), - 'credit_control_line_ids': fields.many2many('credit.control.line', - rel='comm_credit_rel', - string='Credit Lines'), + 'credit_control_line_ids': fields.many2many( + 'credit.control.line', + rel='comm_credit_rel', + string='Credit Lines' + ), - 'company_id': fields.many2one('res.company', 'Company', - required=True), + 'company_id': fields.many2one( + 'res.company', + 'Company', + required=True + ), - 'user_id': fields.many2one('res.users', 'User')} + 'user_id': fields.many2one('res.users', 'User') + } + + def _get_comp(self, cr, uid, context=None): + self.pool.get('res.company')._company_default_get( + cr, uid, + 'credit.control.policy', + context=context + ) _defaults = { - 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get( - cr, uid, 'credit.control.policy', context=c), + 'company_id': _get_comp, 'user_id': lambda s, cr, uid, c: uid } def get_email(self, cr, uid, com_id, context=None): """Return a valid email for customer""" if isinstance(com_id, list): - assert len(com_id) == 1, "get_email only support one id as parameter" + assert len(com_id) == 1, "get_email only support one id as param." com_id = com_id[0] form = self.browse(cr, uid, com_id, context=context) contact = form.get_contact_address() @@ -70,7 +93,8 @@ class CreditCommunication(TransientModel): add_id = add_ids.get('invoice', add_ids.get('default', False)) return pmod.browse(cr, uid, add_id, context) - def _get_credit_lines(self, cr, uid, line_ids, partner_id, level_id, context=None): + def _get_credit_lines(self, cr, uid, line_ids, partner_id, level_id, + context=None): """Return credit lines related to a partner and a policy level""" cr_line_obj = self.pool.get('credit.control.line') cr_l_ids = cr_line_obj.search(cr, @@ -81,19 +105,25 @@ class CreditCommunication(TransientModel): context=context) return cr_l_ids - def _generate_comm_from_credit_line_ids(self, cr, uid, line_ids, context=None): + def _generate_comm_from_credit_line_ids(self, cr, uid, line_ids, + context=None): """Aggregate credit control line by partner, level, and currency It also generate a communication object per aggregation. """ if not line_ids: return [] comms = [] - sql = ("SELECT distinct partner_id, policy_level_id, " - " credit_control_line.currency_id, credit_control_policy_level.level" - " FROM credit_control_line JOIN credit_control_policy_level " - " ON (credit_control_line.policy_level_id = credit_control_policy_level.id)" - " WHERE credit_control_line.id in %s" - " ORDER by credit_control_policy_level.level, credit_control_line.currency_id") + sql = ( + "SELECT distinct partner_id, policy_level_id, " + " credit_control_line.currency_id, " + " credit_control_policy_level.level" + " FROM credit_control_line JOIN credit_control_policy_level " + " ON (credit_control_line.policy_level_id = " + " credit_control_policy_level.id)" + " WHERE credit_control_line.id in %s" + " ORDER by credit_control_policy_level.level, " + " credit_control_line.currency_id" + ) cr.execute(sql, (tuple(line_ids),)) res = cr.dictfetchall() @@ -140,13 +170,15 @@ class CreditCommunication(TransientModel): email_values['body_html'] = email_values['body'] email_values['type'] = 'email' - email_id = email_message_obj.create(cr, uid, email_values, context=context) + email_id = email_message_obj.create(cr, uid, email_values, + context=context) state = 'sent' # The mail will not be send, however it will be in the pool, in an - # error state. So we create it, link it with the credit control line - # and put this latter in a `email_error` state we not that we have a - # problem with the email + # error state. So we create it, link it with + # the credit control line + # and put this latter in a `email_error` state we not that we have + # a problem with the email if any(not email_values.get(field) for field in essential_fields): state = 'email_error' @@ -168,7 +200,10 @@ class CreditCommunication(TransientModel): 'res_id': email_id, 'type': 'binary', } - att_ids.append(att_obj.create(cr, uid, data_attach, context=context)) + att_ids.append( + att_obj.create(cr, uid, data_attach, + context=context) + ) email_message_obj.write(cr, uid, [email_id], {'attachment_ids': [(6, 0, att_ids)]}, context=context) @@ -176,7 +211,10 @@ class CreditCommunication(TransientModel): return email_ids def _generate_report(self, cr, uid, comms, context=None): - """Will generate a report by inserting mako template of related policy template""" + """Will generate a report by inserting mako template + of related policy template + + """ service = netsvc.LocalService('report.credit_control_summary') ids = [x.id for x in comms] result, format = service.create(cr, uid, ids, {}, {}) diff --git a/__unported__/account_credit_control/wizard/credit_control_emailer.py b/__unported__/account_credit_control/wizard/credit_control_emailer.py index b0992de5b..17528ce71 100644 --- a/__unported__/account_credit_control/wizard/credit_control_emailer.py +++ b/__unported__/account_credit_control/wizard/credit_control_emailer.py @@ -47,7 +47,9 @@ class CreditControlEmailer(orm.TransientModel): 'line_ids': fields.many2many( 'credit.control.line', string='Credit Control Lines', - domain="[('state', '=', 'to_be_sent'), ('channel', '=', 'email')]"), + domain=[('state', '=', 'to_be_sent'), + ('channel', '=', 'email')] + ), } _defaults = { @@ -71,7 +73,10 @@ class CreditControlEmailer(orm.TransientModel): form = self.browse(cr, uid, wiz_id, context) if not form.line_ids: - raise orm.except_orm(_('Error'), _('No credit control lines selected.')) + raise orm.except_orm( + _('Error'), + _('No credit control lines selected.') + ) line_ids = [l.id for l in form.line_ids] filtered_ids = self._filter_line_ids( diff --git a/__unported__/account_credit_control/wizard/credit_control_marker.py b/__unported__/account_credit_control/wizard/credit_control_marker.py index 46e5db1ba..525ba930e 100644 --- a/__unported__/account_credit_control/wizard/credit_control_marker.py +++ b/__unported__/account_credit_control/wizard/credit_control_marker.py @@ -69,7 +69,9 @@ class CreditControlMarker(orm.TransientModel): line_obj = self.pool.get('credit.control.line') if not state: raise ValueError(_('state can not be empty')) - line_obj.write(cr, uid, filtered_ids, {'state': state}, context=context) + line_obj.write(cr, uid, filtered_ids, + {'state': state}, + context=context) return filtered_ids def mark_lines(self, cr, uid, wiz_id, context=None): @@ -82,7 +84,10 @@ class CreditControlMarker(orm.TransientModel): form = self.browse(cr, uid, wiz_id, context) if not form.line_ids: - raise orm.except_orm(_('Error'), _('No credit control lines selected.')) + raise orm.except_orm( + _('Error'), + _('No credit control lines selected.') + ) line_ids = [l.id for l in form.line_ids] @@ -90,7 +95,8 @@ class CreditControlMarker(orm.TransientModel): if not filtered_ids: raise orm.except_orm( _('Information'), - _('No lines will be changed. All the selected lines are already done.') + _('No lines will be changed. ' + 'All the selected lines are already done.') ) self._mark_lines(cr, uid, filtered_ids, form.name, context) diff --git a/__unported__/account_credit_control/wizard/credit_control_printer.py b/__unported__/account_credit_control/wizard/credit_control_printer.py index 028f18e1c..7eb900611 100644 --- a/__unported__/account_credit_control/wizard/credit_control_printer.py +++ b/__unported__/account_credit_control/wizard/credit_control_printer.py @@ -41,8 +41,10 @@ class CreditControlPrinter(orm.TransientModel): return res _columns = { - 'mark_as_sent': fields.boolean('Mark letter lines as sent', - help="Only letter lines will be marked."), + 'mark_as_sent': fields.boolean( + 'Mark letter lines as sent', + help="Only letter lines will be marked." + ), 'report_file': fields.binary('Generated Report', readonly=True), 'report_name': fields.char('Report name'), 'state': fields.char('state', size=32), @@ -90,10 +92,12 @@ class CreditControlPrinter(orm.TransientModel): comms = comm_obj._generate_comm_from_credit_line_ids(cr, uid, line_ids, context=context) - report_file = comm_obj._generate_report(cr, uid, comms, context=context) + report_file = comm_obj._generate_report(cr, uid, comms, + context=context) form.write({'report_file': base64.b64encode(report_file), - 'report_name': 'credit_control_esr_bvr_%s.pdf' % fields.datetime.now(), + 'report_name': ('credit_control_esr_bvr_%s.pdf' % + fields.datetime.now()), 'state': 'done'}) if form.mark_as_sent: diff --git a/__unported__/account_credit_control_dunning_fees/model/dunning.py b/__unported__/account_credit_control_dunning_fees/model/dunning.py index b0a75cdd2..5213b4f20 100644 --- a/__unported__/account_credit_control_dunning_fees/model/dunning.py +++ b/__unported__/account_credit_control_dunning_fees/model/dunning.py @@ -41,17 +41,20 @@ class FeesComputer(orm.BaseModel): def _get_compute_fun(self, level_fees_type): """Retrieve function of class that should compute the fees based on type - :param level_fee_type: type exisiting in model `credit.control.policy.level` + :param level_fee_type: type exisiting in model + `credit.control.policy.level` for field dunning_fees_type - :returns: a function of class :class:`FeesComputer` with following signature + :returns: a function of class :class:`FeesComputer` + with following signature self, cr, uid, credit_line (record), context """ if level_fees_type == 'fixed': return self.compute_fixed_fees else: - raise NotImplementedError('fees type %s is not supported' % level_fees_type) + raise NotImplementedError('fees type %s is not supported' % + level_fees_type) def _compute_fees(self, cr, uid, credit_line_ids, context=None): """Compute fees for `credit_line_ids` parameter @@ -68,7 +71,8 @@ class FeesComputer(orm.BaseModel): if not credit_line_ids: return credit_line_ids c_model = self.pool['credit.control.line'] - credit_lines = c_model.browse(cr, uid, credit_line_ids, context=context) + credit_lines = c_model.browse(cr, uid, credit_line_ids, + context=context) for credit in credit_lines: # if there is no dependence between generated credit lines # this could be threaded diff --git a/__unported__/account_credit_control_dunning_fees/model/run.py b/__unported__/account_credit_control_dunning_fees/model/run.py index 537c5b0b8..cba74e73d 100644 --- a/__unported__/account_credit_control_dunning_fees/model/run.py +++ b/__unported__/account_credit_control_dunning_fees/model/run.py @@ -28,12 +28,12 @@ class credit_control_run(orm.Model): def _generate_credit_lines(self, cr, uid, run_id, context=None): """Override method to add fees computation""" - credit_line_ids = super(credit_control_run, self)._generate_credit_lines( - cr, - uid, - run_id, - context=context - ) + credit_line_ids = super(credit_control_run, + self)._generate_credit_lines( + cr, + uid, + run_id, + context=context) fees_model = self.pool['credit.control.dunning.fees.computer'] fees_model._compute_fees(cr, uid, credit_line_ids, context=context) return credit_line_ids diff --git a/__unported__/account_credit_control_dunning_fees/tests/test_fees_generation.py b/__unported__/account_credit_control_dunning_fees/tests/test_fees_generation.py index 0d7037a9a..b685aea61 100644 --- a/__unported__/account_credit_control_dunning_fees/tests/test_fees_generation.py +++ b/__unported__/account_credit_control_dunning_fees/tests/test_fees_generation.py @@ -51,7 +51,9 @@ class FixedFeesTester(test_common.TransactionCase): self.usd_level.dunning_fixed_amount = 5.0 self.usd_level.dunning_currency_id = self.usd self.usd_level.dunning_type = 'fixed' - self.dunning_model = self.registry('credit.control.dunning.fees.computer') + self.dunning_model = self.registry( + 'credit.control.dunning.fees.computer' + ) def test_type_getter(self): """Test that correct compute function is returned for "fixed" type""" diff --git a/__unported__/account_default_draft_move/account.py b/__unported__/account_default_draft_move/account.py index 8c3201224..b73275ca0 100644 --- a/__unported__/account_default_draft_move/account.py +++ b/__unported__/account_default_draft_move/account.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # -# Author Vincent Renaville/Joel Grand-Guillaume. Copyright 2012 Camptocamp SA +# Author Vincent Renaville/Joel Grand-Guillaume. +# Copyright 2012 Camptocamp SA # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -26,11 +27,13 @@ class AccountInvoice(orm.Model): def action_move_create(self, cr, uid, ids, context=None): """Set move line in draft state after creating them.""" - res = super(AccountInvoice, self).action_move_create(cr, uid, ids, context=context) + res = super(AccountInvoice, self).action_move_create(cr, uid, ids, + context=context) move_obj = self.pool.get('account.move') for inv in self.browse(cr, uid, ids, context=context): if inv.move_id: - move_obj.write(cr, uid, [inv.move_id.id], {'state': 'draft'}, context=context) + move_obj.write(cr, uid, [inv.move_id.id], {'state': 'draft'}, + context=context) return res @@ -38,8 +41,11 @@ class AccountMove(orm.Model): _inherit = 'account.move' def button_cancel(self, cr, uid, ids, context=None): - """ We rewrite function button_cancel, to allow invoice or bank statement with linked draft moved - to be canceled """ + """ We rewrite function button_cancel, to allow invoice or bank + statement with linked draft moved + to be canceled + + """ for line in self.browse(cr, uid, ids, context=context): if line.state == 'draft': continue @@ -48,12 +54,11 @@ class AccountMove(orm.Model): raise osv.except_osv( _('Error!'), _('You cannot modify a posted entry of this journal.' - 'First you should set the journal to allow cancelling entries.') + 'First you should set the journal ' + 'to allow cancelling entries.') ) if ids: cr.execute('UPDATE account_move ' 'SET state=%s ' 'WHERE id IN %s', ('draft', tuple(ids),)) return True - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/__unported__/account_default_draft_move/account_bank_statement.py b/__unported__/account_default_draft_move/account_bank_statement.py index f1b822f65..5a966ed81 100644 --- a/__unported__/account_default_draft_move/account_bank_statement.py +++ b/__unported__/account_default_draft_move/account_bank_statement.py @@ -23,7 +23,8 @@ from openerp.osv import orm class AccountBankStatement(orm.Model): _inherit = "account.bank.statement" - def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, + def create_move_from_st_line(self, cr, uid, + st_line_id, company_currency_id, st_line_number, context=None): move_ids = super(AccountBankStatement, self).create_move_from_st_line( cr, uid, st_line_id, company_currency_id, @@ -35,7 +36,8 @@ class AccountBankStatement(orm.Model): voucher_obj = self.pool.get('account.voucher') st_line = bank_st_line_obj.browse(cr, uid, st_line_id, context=context) if st_line.voucher_id: - v = voucher_obj.browse(cr, uid, st_line.voucher_id.id, context=context) + v = voucher_obj.browse(cr, uid, st_line.voucher_id.id, + context=context) move_ids = v.move_id.id if not isinstance(move_ids, (tuple, list)): diff --git a/__unported__/account_fiscal_position_vat_check/__openerp__.py b/__unported__/account_fiscal_position_vat_check/__openerp__.py index 756633230..bc7c3c852 100644 --- a/__unported__/account_fiscal_position_vat_check/__openerp__.py +++ b/__unported__/account_fiscal_position_vat_check/__openerp__.py @@ -32,17 +32,25 @@ Check that the Customer has a VAT number on invoice validation ============================================================== This module adds an option **Customer must have VAT** on fiscal positions. -When a user tries to validate a customer invoice or refund with a fiscal position +When a user tries to validate a customer invoice or refund +with a fiscal position that have this option, OpenERP will check that the customer has a VAT number. -If it doesn't, OpenERP will block the validation of the invoice and display an error message. +If it doesn't, OpenERP will block the validation of the invoice +and display an error message. -In the European Union (EU), when an EU company sends an invoice to another EU company in another country, +In the European Union (EU), when an EU company sends an invoice to +another EU company in another country, -it can invoice without VAT (most of the time) but the VAT number of the customer must be displayed on the invoice. +it can invoice without VAT (most of the time) but the VAT number of the +customer must be displayed on the invoice. -This module also displays a warning when a user sets a fiscal position with the option - **Customer must have VAT** on a customer and this customer doesn't have a VAT number in OpenERP yet. +This module also displays a warning when a user sets +a fiscal position with the option + +**Customer must have VAT** + + on a customer and this customer doesn't have a VAT number in OpenERP yet. Please contact Alexis de Lattre from Akretion for any help or question about this module. @@ -57,7 +65,7 @@ Please contact Alexis de Lattre from Akretion 'images': [ 'images/fiscal_position_form.jpg', 'images/vat_check_invoice_validation.jpg', - ], + ], 'installable': False, 'active': False, 'application': True, diff --git a/__unported__/account_fiscal_position_vat_check/account_invoice.py b/__unported__/account_fiscal_position_vat_check/account_invoice.py index dc1bc54da..c3a77a471 100644 --- a/__unported__/account_fiscal_position_vat_check/account_invoice.py +++ b/__unported__/account_fiscal_position_vat_check/account_invoice.py @@ -30,7 +30,8 @@ class account_fiscal_position(orm.Model): _columns = { 'customer_must_have_vat': fields.boolean( 'Customer Must Have VAT number', - help="If enabled, OpenERP will check that the customer has a VAT number " + help="If enabled, OpenERP will check " + "that the customer has a VAT number " "when the user validates a customer invoice/refund." ), } @@ -53,9 +54,11 @@ class account_invoice(orm.Model): type_label = _('a Customer Refund') raise orm.except_orm( _('Missing VAT number:'), - _("You are trying to validate %s with the fiscal position '%s' " + _("You are trying to validate %s " + "with the fiscal position '%s' " "that require the customer to have a VAT number. " - "But the Customer '%s' doesn't have a VAT number in OpenERP." + "But the Customer '%s' doesn't " + "have a VAT number in OpenERP." "Please add the VAT number of this Customer in OpenERP " " and try to validate again.") % (type_label, invoice.fiscal_position.name, diff --git a/__unported__/account_fiscal_position_vat_check/partner.py b/__unported__/account_fiscal_position_vat_check/partner.py index dcac18e98..c4bc8f722 100644 --- a/__unported__/account_fiscal_position_vat_check/partner.py +++ b/__unported__/account_fiscal_position_vat_check/partner.py @@ -27,7 +27,8 @@ from openerp.tools.translate import _ class res_partner(orm.Model): _inherit = 'res.partner' - def fiscal_position_change(self, cr, uid, ids, account_position, vat, customer): + def fiscal_position_change(self, cr, uid, ids, account_position, + vat, customer): '''Warning is the fiscal position requires a vat number and the partner doesn't have one yet''' if account_position and customer and not vat: @@ -40,7 +41,8 @@ class res_partner(orm.Model): 'message': _( "You have set the fiscal position '%s' " "that require the customer to have a VAT number. " - "You should add the VAT number of this customer in OpenERP." + "You should add the VAT number of this customer" + " in OpenERP." ) % fp['name'] } } diff --git a/__unported__/account_invoice_currency/__init__.py b/__unported__/account_invoice_currency/__init__.py index 8e877eba3..f6bc9890c 100644 --- a/__unported__/account_invoice_currency/__init__.py +++ b/__unported__/account_invoice_currency/__init__.py @@ -1,22 +1,21 @@ # -*- coding: utf-8 -*- ############################################################################## # -# Copyright (C) 2004-2011 Zikzakmedia S.L. (http://zikzakmedia.com) All Rights Reserved. +# Copyright (C) 2004-2011 Zikzakmedia S.L. (http://zikzakmedia.com) +# All Rights Reserved. # -# 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 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. +# 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 . +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . # ############################################################################## - - -import invoice +from . import invoice diff --git a/__unported__/account_invoice_currency/__openerp__.py b/__unported__/account_invoice_currency/__openerp__.py index cf20b2802..740b039e6 100644 --- a/__unported__/account_invoice_currency/__openerp__.py +++ b/__unported__/account_invoice_currency/__openerp__.py @@ -1,23 +1,23 @@ # -*- coding: utf-8 -*- ############################################################################## # -# OpenERP - Account invoice currency -# Copyright (C) 2004-2011 Zikzakmedia S.L. (http://zikzakmedia.com) All Rights Reserved. -# Jordi Esteve -# Copyright (c) 2013 Joaquin Gutierrez (http://www.gutierrezweb.es) +# OpenERP - Account invoice currency +# Copyright (C) 2004-2011 Zikzakmedia S.L. (http://zikzakmedia.com) +# Jordi Esteve +# Copyright (c) 2013 Joaquin Gutierrez (http://www.gutierrezweb.es) # -# 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 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. +# 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 . +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . # ############################################################################## @@ -32,7 +32,8 @@ This Module adds functional fields to show invoice in the company currency ========================================================================== -Amount Untaxed, Amount Tax and Amount Total invoice fields in the company currency. +Amount Untaxed, Amount Tax and Amount Total invoice +fields in the company currency. These fields are shown in "Other information" tab in invoice form. """, 'license': "AGPL-3", @@ -43,5 +44,3 @@ These fields are shown in "Other information" tab in invoice form. 'installable': False, 'active': False, } - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/__unported__/account_invoice_currency/invoice.py b/__unported__/account_invoice_currency/invoice.py index 3b6954fe5..bd6c431f4 100644 --- a/__unported__/account_invoice_currency/invoice.py +++ b/__unported__/account_invoice_currency/invoice.py @@ -1,22 +1,22 @@ # -*- coding: utf-8 -*- ############################################################################## # -# Copyright (C) 2004-2011 -# Pexego Sistemas Informáticos. (http://pexego.es) All Rights Reserved -# Zikzakmedia S.L. (http://zikzakmedia.com) All Rights Reserved. +# Copyright (C) 2004-2011 +# Pexego Sistemas Informáticos. (http://pexego.es) All Rights Reserved +# Zikzakmedia S.L. (http://zikzakmedia.com) All Rights Reserved. # -# 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 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. +# 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 . +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . # ############################################################################## @@ -63,7 +63,8 @@ class account_invoice(orm.Model): 'cc_amount_total': 0.0, } - # It could be computed only in open or paid invoices with a generated account move + # It could be computed only in open or paid invoices with a + # generated account move if invoice.move_id: # Accounts to compute amount_untaxed line_account = [] @@ -74,20 +75,28 @@ class account_invoice(orm.Model): # Accounts to compute amount_tax tax_account = [] for line in invoice.tax_line: - if line.account_id.id not in tax_account and line.amount != 0: + if (line.account_id.id not in tax_account and + line.amount != 0): tax_account.append(line.account_id.id) - # The company currency amounts are the debit-credit amounts in the account moves + # The company currency amounts are the debit-credit + # amounts in the account moves for line in invoice.move_id.line_id: if line.account_id.id in line_account: - res[invoice.id]['cc_amount_untaxed'] += line.debit - line.credit + amt = line.debit - line.credit + res[invoice.id]['cc_amount_untaxed'] += amt if line.account_id.id in tax_account: - res[invoice.id]['cc_amount_tax'] += line.debit - line.credit + amt = line.debit - line.credit + res[invoice.id]['cc_amount_tax'] += amt if invoice.type in ('out_invoice', 'in_refund'): - res[invoice.id]['cc_amount_untaxed'] = -res[invoice.id]['cc_amount_untaxed'] - res[invoice.id]['cc_amount_tax'] = -res[invoice.id]['cc_amount_tax'] - res[invoice.id]['cc_amount_total'] = (res[invoice.id]['cc_amount_tax'] + - res[invoice.id]['cc_amount_untaxed']) + res[invoice.id]['cc_amount_untaxed'] = \ + -res[invoice.id]['cc_amount_untaxed'] + res[invoice.id]['cc_amount_tax'] = \ + -res[invoice.id]['cc_amount_tax'] + res[invoice.id]['cc_amount_total'] = ( + res[invoice.id]['cc_amount_tax'] + + res[invoice.id]['cc_amount_untaxed'] + ) return res _columns = { @@ -97,15 +106,20 @@ class account_invoice(orm.Model): digits_compute=dp.get_precision('Account'), string='Company Cur. Untaxed', help="Invoice untaxed amount in the company currency" - "(useful when invoice currency is different from company currency).", + "(useful when invoice currency is different " + "from company currency).", store={ - 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line', - 'currency_id', - 'move_id'], 20), + 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, + ['invoice_line', + 'currency_id', + 'move_id'], + 20), 'account.invoice.tax': (_get_invoice_tax2, None, 20), - 'account.invoice.line': (_get_invoice_line2, ['price_unit', - 'invoice_line_tax_id', - 'quantity', 'discount'], 20), + 'account.invoice.line': (_get_invoice_line2, + ['price_unit', + 'invoice_line_tax_id', + 'quantity', 'discount'], + 20), }, multi='cc_all' ), @@ -116,15 +130,20 @@ class account_invoice(orm.Model): digits_compute=dp.get_precision('Account'), string='Company Cur. Tax', help="Invoice tax amount in the company currency " - "(useful when invoice currency is different from company currency).", + "(useful when invoice currency is different " + "from company currency).", store={ - 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line', - 'currency_id', - 'move_id'], 20), + 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, + ['invoice_line', + 'currency_id', + 'move_id'], + 20), 'account.invoice.tax': (_get_invoice_tax2, None, 20), - 'account.invoice.line': (_get_invoice_line2, ['price_unit', - 'invoice_line_tax_id', - 'quantity', 'discount'], 20), + 'account.invoice.line': (_get_invoice_line2, + ['price_unit', + 'invoice_line_tax_id', + 'quantity', 'discount'], + 20), }, multi='cc_all' ), @@ -135,15 +154,20 @@ class account_invoice(orm.Model): digits_compute=dp.get_precision('Account'), string='Company Cur. Total', help="Invoice total amount in the company currency " - "(useful when invoice currency is different from company currency).", + "(useful when invoice currency is different from " + "company currency).", store={ - 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line', - 'currency_id', - 'move_id'], 20), + 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, + ['invoice_line', + 'currency_id', + 'move_id'], + 20), 'account.invoice.tax': (_get_invoice_tax2, None, 20), - 'account.invoice.line': (_get_invoice_line2, ['price_unit', - 'invoice_line_tax_id', - 'quantity', 'discount'], 20), + 'account.invoice.line': (_get_invoice_line2, + ['price_unit', + 'invoice_line_tax_id', + 'quantity', 'discount'], + 20), }, multi='cc_all'), } diff --git a/__unported__/account_journal_always_check_date/__openerp__.py b/__unported__/account_journal_always_check_date/__openerp__.py index 3c77a2ad2..b4d131dfc 100644 --- a/__unported__/account_journal_always_check_date/__openerp__.py +++ b/__unported__/account_journal_always_check_date/__openerp__.py @@ -39,9 +39,11 @@ This module: * prevent users from deactivating the 'Check Date in Period' option. -So this module is an additionnal security for countries where, on an account move, the date must be inside the period. +So this module is an additionnal security for countries where, on an account +move, the date must be inside the period. -Please contact Alexis de Lattre from Akretion for any help or question about this module. +Please contact Alexis de Lattre from Akretion +for any help or question about this module. """, 'author': 'Akretion', 'website': 'http://www.akretion.com', diff --git a/__unported__/account_move_line_no_default_search/__openerp__.py b/__unported__/account_move_line_no_default_search/__openerp__.py index 71e01f556..cc762affe 100644 --- a/__unported__/account_move_line_no_default_search/__openerp__.py +++ b/__unported__/account_move_line_no_default_search/__openerp__.py @@ -32,8 +32,7 @@ This module leaves the search view extension for move lines intact, but disables the default search values for the dropdowns so that you do not have to disable these before entering your own search queries. -.. image:: /account_move_line_no_default_search/static/src/img/move_line_search_view.png - +..image:: /account_move_line_no_default_search/static/src/img/sample.png """, 'website': 'http://therp.nl', 'depends': ['account'], diff --git a/__unported__/account_move_line_no_default_search/static/src/img/move_line_search_view.png b/__unported__/account_move_line_no_default_search/static/src/img/sample.png similarity index 100% rename from __unported__/account_move_line_no_default_search/static/src/img/move_line_search_view.png rename to __unported__/account_move_line_no_default_search/static/src/img/sample.png diff --git a/__unported__/account_move_line_search_extension/account_view.xml b/__unported__/account_move_line_search_extension/account_view.xml index 4dcbe197a..de3c19586 100644 --- a/__unported__/account_move_line_search_extension/account_view.xml +++ b/__unported__/account_move_line_search_extension/account_view.xml @@ -12,11 +12,11 @@ - + diff --git a/__unported__/account_move_template/__openerp__.py b/__unported__/account_move_template/__openerp__.py index 2dbcafa74..b60e00ab5 100644 --- a/__unported__/account_move_template/__openerp__.py +++ b/__unported__/account_move_template/__openerp__.py @@ -27,9 +27,15 @@ Templates for Journal Entries User can configure journal entries templates, useful for recurring entries. -The amount of each template line can be computed (through python code) or kept as user input. -If user input, when using the template, user has to fill the amount of every input lines. -The journal entry form allows lo load, through a wizard, the template to use and the amounts to fill. + +The amount of each template line can be computed (through python code) +or kept as user input. + +If user input, when using the template, user has to fill +the amount of every input lines. + +The journal entry form allows lo load, through a wizard, +the template to use and the amounts to fill. """, 'author': 'Agile Business Group', diff --git a/__unported__/account_move_template/account_document_template.py b/__unported__/account_move_template/account_document_template.py index 18f03df51..1d740af1d 100644 --- a/__unported__/account_move_template/account_document_template.py +++ b/__unported__/account_move_template/account_document_template.py @@ -51,21 +51,27 @@ class account_document_template(orm.Model): def _generate_empty_lines(self, cr, uid, template_id): lines = {} - for template_line in self.browse(cr, uid, template_id).template_line_ids: + t_lines = self.browse(cr, uid, template_id).template_line_ids + for template_line in t_lines: lines[template_line.sequence] = None return lines def lines(self, line_number): if self._computed_lines[line_number] is not None: return self._computed_lines[line_number] - line = self._get_template_line(self._cr, self._uid, self._current_template_id, line_number) + line = self._get_template_line(self._cr, + self._uid, + self._current_template_id, + line_number) if re.match('L\( *' + str(line_number) + ' *\)', line.python_code): raise orm.except_orm( _('Error'), _('Line %s can\'t refer to itself') % str(line_number) ) try: - self._computed_lines[line_number] = eval(line.python_code.replace('L', 'self.lines')) + self._computed_lines[line_number] = eval( + line.python_code.replace('L', 'self.lines') + ) except KeyError: raise orm.except_orm( _('Error'), @@ -74,12 +80,14 @@ class account_document_template(orm.Model): def compute_lines(self, cr, uid, template_id, input_lines): # input_lines: dictionary in the form {line_number: line_amount} - # returns all the lines (included input lines) in the form {line_number: line_amount} + # returns all the lines (included input lines) + # in the form {line_number: line_amount} template = self.browse(cr, uid, template_id) if len(input_lines) != self._input_lines(cr, uid, template): raise orm.except_orm( _('Error'), - _('Inconsistency between input lines and filled lines for template %s') % template.name + _('Inconsistency between input lines and ' + 'filled lines for template %s') % template.name ) self._current_template_id = template.id self._cr = cr @@ -106,6 +114,10 @@ class account_document_template_line(orm.Model): _columns = { 'name': fields.char('Name', size=64, required=True), 'sequence': fields.integer('Sequence', required=True), - 'type': fields.selection([('computed', 'Computed'), ('input', 'User input')], 'Type', required=True), + 'type': fields.selection( + [('computed', 'Computed'), ('input', 'User input')], + 'Type', + required=True + ), 'python_code': fields.text('Python Code'), } diff --git a/__unported__/account_move_template/account_move_template.py b/__unported__/account_move_template/account_move_template.py index 36c606754..e39864fff 100644 --- a/__unported__/account_move_template/account_move_template.py +++ b/__unported__/account_move_template/account_move_template.py @@ -28,23 +28,40 @@ class account_move_template(orm.Model): _name = 'account.move.template' _columns = { - 'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True), - 'template_line_ids': fields.one2many('account.move.template.line', 'template_id', 'Template Lines'), + 'company_id': fields.many2one( + 'res.company', + 'Company', + required=True, + change_default=True + ), + 'template_line_ids': fields.one2many( + 'account.move.template.line', + 'template_id', + 'Template Lines' + ), 'cross_journals': fields.boolean('Cross-Journals'), - 'transitory_acc_id': fields.many2one('account.account', 'Transitory account', required=False), - } - - _defaults = { - 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get( - cr, uid, 'account.move.template', context=c + 'transitory_acc_id': fields.many2one( + 'account.account', + 'Transitory account', + required=False ), } + def _get_default(self, cr, uid, context=None): + self.pool.get('res.company')._company_default_get( + cr, uid, 'account.move.template', context=context + ) + _defaults = { + 'company_id': _get_default + } + def _check_different_journal(self, cr, uid, ids, context=None): - # Check that the journal on these lines are different/same in the case of cross journals/single journal + # Check that the journal on these lines are different/same in the case + # of cross journals/single journal journal_ids = [] all_journal_ids = [] - move_template = self.pool.get('account.move.template').browse(cr, uid, ids)[0] + move_template = self.pool.get('account.move.template').browse( + cr, uid, ids)[0] if not move_template.template_line_ids: return True for template_line in move_template.template_line_ids: @@ -59,7 +76,8 @@ class account_move_template(orm.Model): _constraints = [ (_check_different_journal, 'If the template is "cross-journals", the Journals must be different,' - 'if the template does not "cross-journals" the Journals must be the same!', + 'if the template does not "cross-journals" ' + 'the Journals must be the same!', ['journal_id']) ] @@ -69,16 +87,28 @@ class account_move_template_line(orm.Model): _inherit = 'account.document.template.line' _columns = { - 'journal_id': fields.many2one('account.journal', 'Journal', required=True), - 'account_id': fields.many2one('account.account', 'Account', - required=True, ondelete="cascade"), + 'journal_id': fields.many2one( + 'account.journal', + 'Journal', + required=True + ), + 'account_id': fields.many2one( + 'account.account', + 'Account', + required=True, + ondelete="cascade" + ), 'move_line_type': fields.selection( [('cr', 'Credit'), ('dr', 'Debit')], 'Move Line Type', required=True ), - 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', ondelete="cascade"), + 'analytic_account_id': fields.many2one( + 'account.analytic.account', + 'Analytic Account', + ondelete="cascade" + ), 'template_id': fields.many2one('account.move.template', 'Template'), 'account_tax_id': fields.many2one('account.tax', 'Tax'), } diff --git a/__unported__/account_move_template/wizard/select_template.py b/__unported__/account_move_template/wizard/select_template.py index 539067932..a074c6bfa 100644 --- a/__unported__/account_move_template/wizard/select_template.py +++ b/__unported__/account_move_template/wizard/select_template.py @@ -86,7 +86,8 @@ class wizard_select_template(orm.TransientModel): return self.load_template(cr, uid, ids) wizard.write({'state': 'template_selected'}) - view_rec = model_data_obj.get_object_reference(cr, uid, 'account_move_template', 'wizard_select_template') + view_rec = model_data_obj.get_object_reference( + cr, uid, 'account_move_template', 'wizard_select_template') view_id = view_rec and view_rec[1] or False return { @@ -106,7 +107,10 @@ class wizard_select_template(orm.TransientModel): wizard = self.browse(cr, uid, ids, context=context)[0] if not template_obj.check_zero_lines(cr, uid, wizard): - raise orm.except_orm(_('Error !'), _('At least one amount has to be non-zero!')) + raise orm.except_orm( + _('Error !'), + _('At least one amount has to be non-zero!') + ) input_lines = {} for template_line in wizard.line_ids: @@ -114,10 +118,14 @@ class wizard_select_template(orm.TransientModel): period_id = account_period_obj.find(cr, uid, context=context) if not period_id: - raise orm.except_orm(_('No period found !'), _('Unable to find a valid period !')) + raise orm.except_orm( + _('No period found !'), + _('Unable to find a valid period !') + ) period_id = period_id[0] - computed_lines = template_obj.compute_lines(cr, uid, wizard.template_id.id, input_lines) + computed_lines = template_obj.compute_lines( + cr, uid, wizard.template_id.id, input_lines) moves = {} for line in wizard.template_id.template_line_ids: @@ -171,14 +179,16 @@ class wizard_select_template(orm.TransientModel): }) return move_id - def _make_move_line(self, cr, uid, line, computed_lines, move_id, period_id, partner_id): + def _make_move_line(self, cr, uid, line, computed_lines, + move_id, period_id, partner_id): account_move_line_obj = self.pool.get('account.move.line') analytic_account_id = False if line.analytic_account_id: if not line.journal_id.analytic_journal_id: raise orm.except_orm( _('No Analytic Journal !'), - _("You have to dfine an analytic journal on the '%s' journal!") + _("You have to define an analytic " + "journal on the '%s' journal!") % (line.journal_id.name,) ) @@ -212,7 +222,8 @@ class wizard_select_template(orm.TransientModel): if not line.journal_id.analytic_journal_id: raise orm.except_orm( _('No Analytic Journal !'), - _("You have to define an analytic journal on the '%s' journal!") + _("You have to define an analytic journal " + "on the '%s' journal!") % (line.template_id.journal_id.name,) ) analytic_account_id = line.analytic_account_id.id @@ -238,10 +249,16 @@ class wizard_select_template_line(orm.TransientModel): _description = 'Template Lines' _name = "wizard.select.move.template.line" _columns = { - 'template_id': fields.many2one('wizard.select.move.template', 'Template'), + 'template_id': fields.many2one('wizard.select.move.template', + 'Template'), 'sequence': fields.integer('Number', required=True), 'name': fields.char('Name', size=64, required=True, readonly=True), - 'account_id': fields.many2one('account.account', 'Account', required=True, readonly=True), + 'account_id': fields.many2one( + 'account.account', + 'Account', + required=True, + readonly=True + ), 'move_line_type': fields.selection( [('cr', 'Credit'), ('dr', 'Debit')], diff --git a/__unported__/account_move_validation_improvement/__openerp__.py b/__unported__/account_move_validation_improvement/__openerp__.py index 56a674907..a996fe406 100644 --- a/__unported__/account_move_validation_improvement/__openerp__.py +++ b/__unported__/account_move_validation_improvement/__openerp__.py @@ -28,7 +28,7 @@ but extending it to multiple periods and multiple journals. It replaces the base one defined in addons/account/wizard. """, 'website': 'http://www.camptocamp.com', - 'data' : ['wizard/account_validate_move_view.xml'], + 'data': ['wizard/account_validate_move_view.xml'], 'installable': False, 'active': False, } diff --git a/__unported__/account_partner_required/tests/test_account_partner_required.py b/__unported__/account_partner_required/tests/test_account_partner_required.py index 824df11bb..a9134537e 100644 --- a/__unported__/account_partner_required/tests/test_account_partner_required.py +++ b/__unported__/account_partner_required/tests/test_account_partner_required.py @@ -54,12 +54,16 @@ class test_account_partner_required(common.TransactionCase): 'account_id': self.ref('account.a_sale')}) move_line_id = self.move_line_obj.create( self.cr, self.uid, - {'move_id': move_id, - 'name': '/', - 'debit': amount, - 'credit': 0, - 'account_id': self.ref('account.a_recv'), - 'partner_id': self.ref('base.res_partner_1') if with_partner else False}) + { + 'move_id': move_id, + 'name': '/', + 'debit': amount, + 'credit': 0, + 'account_id': self.ref('account.a_recv'), + 'partner_id': self.ref('base.res_partner_1') if + with_partner else False + } + ) return move_line_id def _set_partner_policy(self, policy, aref='account.a_recv'): @@ -116,6 +120,12 @@ class test_account_partner_required(common.TransactionCase): self.move_line_obj.write(self.cr, self.uid, line_id, {'account_id': self.ref('account.a_pay')}) # change account to a_pay with policy always with partner -> ok - self.move_line_obj.write(self.cr, self.uid, line_id, - {'account_id': self.ref('account.a_pay'), - 'partner_id': self.ref('base.res_partner_1')}) + self.move_line_obj.write( + self.cr, + self.uid, + line_id, + { + 'account_id': self.ref('account.a_pay'), + 'partner_id': self.ref('base.res_partner_1') + } + ) diff --git a/__unported__/account_renumber/__openerp__.py b/__unported__/account_renumber/__openerp__.py index 41ff080fd..17b207447 100644 --- a/__unported__/account_renumber/__openerp__.py +++ b/__unported__/account_renumber/__openerp__.py @@ -3,7 +3,8 @@ # # OpenERP - Account renumber wizard # Copyright (C) 2009 Pexego Sistemas Informáticos. All Rights Reserved -# Copyright (c) 2013 Servicios Tecnológicos Avanzados (http://www.serviciosbaeza.com) +# Copyright (c) 2013 Servicios Tecnológicos Avanzados +# (http://www.serviciosbaeza.com) # Pedro Manuel Baeza # Copyright (c) 2013 Joaquin Gutierrez (http://www.gutierrezweb.es) # $Id$ @@ -31,17 +32,19 @@ 'category': "Enterprise Specific Modules", 'contributors': ['Pedro M. Baeza', 'Joaquín Gutierrez'], 'description': """ -This module adds a wizard to renumber account moves by date only for admin users. -================================================================================= +This module adds a wizard to renumber account moves by date only for admin. +=========================================================================== The wizard, that will be added to the "End of Year Treatments", let's you select one or more journals and fiscal periods, set a starting number; and then renumber all the posted moves from those journals and periods sorted by date. -It will recreate the sequence number of each account move using their journal sequence so: +It will recreate the sequence number of each account move +using their journal sequence so: - Sequences per journal are supported. - - Sequences with prefixes and sufixes based on the move date are also supported. + - Sequences with prefixes and sufixes based on the move + date are also supported. """, "license": "AGPL-3", "depends": [ diff --git a/__unported__/account_renumber/test/create_moves.py b/__unported__/account_renumber/test/create_moves.py index 30b58c34a..93d1e9664 100644 --- a/__unported__/account_renumber/test/create_moves.py +++ b/__unported__/account_renumber/test/create_moves.py @@ -89,7 +89,9 @@ def create_lots_of_account_moves(dbname, user, passwd, howmany): 'name': 'Test_l2'}) ], 'period_id': 1, - 'date': '2009-01-%s' % ((i % 31) or 1), + 'date': '2009-01-%s' % ( + (i % 31) or 1 + ), 'partner_id': False, 'to_check': 0 }, @@ -97,7 +99,8 @@ def create_lots_of_account_moves(dbname, user, passwd, howmany): # Validate the move object_facade.execute(dbname, user_id, passwd, - u'account.move', 'button_validate', [move_id], {}) + u'account.move', 'button_validate', + [move_id], {}) # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ @@ -105,7 +108,8 @@ def create_lots_of_account_moves(dbname, user, passwd, howmany): if __name__ == "__main__": if len(sys.argv) < 5: - logger.info(u"Usage: %s " % sys.argv[0]) + logger.info(u"Usage: %s " % + sys.argv[0]) else: create_lots_of_account_moves( sys.argv[1], sys.argv[2], sys.argv[3], int(sys.argv[4])) diff --git a/__unported__/account_renumber/wizard/wizard_renumber.py b/__unported__/account_renumber/wizard/wizard_renumber.py index 8b917f0a1..78ca23b99 100644 --- a/__unported__/account_renumber/wizard/wizard_renumber.py +++ b/__unported__/account_renumber/wizard/wizard_renumber.py @@ -42,7 +42,8 @@ class wizard_renumber(orm.TransientModel): help='Fiscal periods to renumber', string="Periods", ondelete='null'), 'number_next': fields.integer('First Number', required=True, - help="Journal sequences will start counting on this number"), + help="Journal sequences will start " + "counting on this number"), 'state': fields.selection([('init', 'Initial'), ('renumber', 'Renumbering')], readonly=True) } @@ -112,9 +113,11 @@ class wizard_renumber(orm.TransientModel): sequences_seen.append(sequence_id) # Generate (using our own get_id) and write the new move number c = {'fiscalyear_id': move.period_id.fiscalyear_id.id} - new_name = sequence_obj.next_by_id(cr, uid, - move.journal_id.sequence_id.id, - context=c) + new_name = sequence_obj.next_by_id( + cr, uid, + move.journal_id.sequence_id.id, + context=c + ) # Note: We can't just do a # "move_obj.write(cr, uid, [move.id], {'name': new_name})" # cause it might raise a diff --git a/__unported__/account_reversal/__openerp__.py b/__unported__/account_reversal/__openerp__.py index 033dfd1f6..8736a1ec2 100644 --- a/__unported__/account_reversal/__openerp__.py +++ b/__unported__/account_reversal/__openerp__.py @@ -48,7 +48,7 @@ during the Akretion-Camptocamp code sprint of June 2011. 'data': [ 'account_view.xml', 'wizard/account_move_reverse_view.xml' - ], + ], 'installable': False, 'active': False, } diff --git a/__unported__/account_tax_analysis/account_tax_analysis.py b/__unported__/account_tax_analysis/account_tax_analysis.py index e5368d975..a8a05b679 100644 --- a/__unported__/account_tax_analysis/account_tax_analysis.py +++ b/__unported__/account_tax_analysis/account_tax_analysis.py @@ -26,9 +26,11 @@ class account_tax_declaration_analysis(orm.TransientModel): _description = 'Account Vat Declaration' _columns = { 'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscalyear', - help='Fiscalyear to look on', required=True), + help='Fiscalyear to look on', + required=True), - 'period_list': fields.many2many('account.period', 'account_tax_period_rel', + 'period_list': fields.many2many('account.period', + 'account_tax_period_rel', 'tax_analysis', 'period_id', 'Period _list', required=True), } diff --git a/__unported__/account_tax_update/model/update_tax_config.py b/__unported__/account_tax_update/model/update_tax_config.py index 5c3238127..d202a4f33 100644 --- a/__unported__/account_tax_update/model/update_tax_config.py +++ b/__unported__/account_tax_update/model/update_tax_config.py @@ -171,51 +171,81 @@ class UpdateTaxConfig(orm.Model): cp_ref_tax_code_id = False if config.duplicate_tax_code: if line.source_tax_id.base_code_id: - cp_base_code_id = tax_code_pool.copy(cr, uid, - line.source_tax_id.base_code_id.id) - rename_old = '[%s] %s' % (config.name, - line.source_tax_id.base_code_id.name) + cp_base_code_id = tax_code_pool.copy( + cr, uid, + line.source_tax_id.base_code_id.id + ) + rename_old = '[%s] %s' % ( + config.name, + line.source_tax_id.base_code_id.name + ) tax_code_pool.write(cr, uid, line.source_tax_id.base_code_id.id, {'name': rename_old}) if line.source_tax_id.tax_code_id: - cp_tax_code_id = tax_code_pool.copy(cr, uid, - line.source_tax_id.tax_code_id.id) - rename_old = '[%s] %s' % (config.name, - line.source_tax_id.tax_code_id.name) + cp_tax_code_id = tax_code_pool.copy( + cr, uid, + line.source_tax_id.tax_code_id.id + ) + rename_old = '[%s] %s' % ( + config.name, + line.source_tax_id.tax_code_id.name + ) tax_code_pool.write(cr, uid, line.source_tax_id.tax_code_id.id, {'name': rename_old}) if line.source_tax_id.ref_base_code_id: # Check if with have the same tax code for base_code_id - if line.source_tax_id.ref_base_code_id.id == line.source_tax_id.base_code_id.id: + if (line.source_tax_id.ref_base_code_id.id == + line.source_tax_id.base_code_id.id): cp_ref_base_code_id = cp_base_code_id else: - cp_ref_base_code_id = tax_code_pool.copy(cr, uid, - line.source_tax_id.ref_base_code_id.id) - rename_old = '[%s] %s' % (config.name, - line.source_tax_id.ref_base_code_id.name) - tax_code_pool.write(cr, uid, - line.source_tax_id.ref_base_code_id.id, - {'name': rename_old}) + cp_ref_base_code_id = tax_code_pool.copy( + cr, uid, + line.source_tax_id.ref_base_code_id.id + ) + rename_old = '[%s] %s' % ( + config.name, + line.source_tax_id.ref_base_code_id.name + ) + tax_code_pool.write( + cr, uid, + line.source_tax_id.ref_base_code_id.id, + {'name': rename_old} + ) if line.source_tax_id.ref_tax_code_id: - if line.source_tax_id.ref_tax_code_id.id == line.source_tax_id.tax_code_id.id: + if (line.source_tax_id.ref_tax_code_id.id == + line.source_tax_id.tax_code_id.id): cp_ref_tax_code_id = cp_tax_code_id else: - cp_ref_tax_code_id = tax_code_pool.copy(cr, uid, - line.source_tax_id.ref_tax_code_id.id) - rename_old = '[%s] %s' % (config.name, - line.source_tax_id.ref_tax_code_id.name) - tax_code_pool.write(cr, uid, - line.source_tax_id.ref_tax_code_id.id, - {'name': rename_old}) + cp_ref_tax_code_id = tax_code_pool.copy( + cr, uid, + line.source_tax_id.ref_tax_code_id.id + ) + rename_old = '[%s] %s' % ( + config.name, + line.source_tax_id.ref_tax_code_id.name + ) + tax_code_pool.write( + cr, uid, + line.source_tax_id.ref_tax_code_id.id, + {'name': rename_old} + ) else: - cp_base_code_id = line.source_tax_id.base_code_id and line.source_tax_id.base_code_id.id or False - cp_ref_base_code_id = (line.source_tax_id.ref_base_code_id and - line.source_tax_id.ref_base_code_id.id or False) - cp_tax_code_id = line.source_tax_id.tax_code_id and line.source_tax_id.tax_code_id.id or False + cp_base_code_id = (line.source_tax_id.base_code_id and + line.source_tax_id.base_code_id.id or + False) + cp_ref_base_code_id = ( + line.source_tax_id.ref_base_code_id and + line.source_tax_id.ref_base_code_id.id or + False + ) + cp_tax_code_id = (line.source_tax_id.tax_code_id and + line.source_tax_id.tax_code_id.id or + False) cp_ref_tax_code_id = (line.source_tax_id.ref_tax_code_id and - line.source_tax_id.ref_tax_code_id.id or False) + line.source_tax_id.ref_tax_code_id.id or + False) target_tax_id = tax_pool.copy( cr, uid, line.source_tax_id.id, @@ -352,7 +382,8 @@ class UpdateTaxConfig(orm.Model): if model: for field_name, column in model._columns.items(): log += update_defaults(model_name, field_name, column) - for field_name, field_tuple in model._inherit_fields.iteritems(): + for field_name, field_tuple in \ + model._inherit_fields.iteritems(): if len(field_tuple) >= 3: column = field_tuple[2] log += update_defaults(model_name, field_name, column) diff --git a/__unported__/async_move_line_importer/__openerp__.py b/__unported__/async_move_line_importer/__openerp__.py index b392253a4..b76a6ab19 100644 --- a/__unported__/async_move_line_importer/__openerp__.py +++ b/__unported__/async_move_line_importer/__openerp__.py @@ -42,7 +42,8 @@ not support all CSV canvas. - AA lines will only be created when moves are posted. - Tax lines computation will be skipped until the move are posted. -This option should be used with caution and preferably in conjunction with provided canvas in tests/data +This option should be used with caution and preferably in conjunction with +provided canvas in tests/data Then simply press import file button. The process will be run in background and you will be able to continue your work. diff --git a/__unported__/async_move_line_importer/model/account.py b/__unported__/async_move_line_importer/model/account.py index 36273d362..530109f61 100644 --- a/__unported__/async_move_line_importer/model/account.py +++ b/__unported__/async_move_line_importer/model/account.py @@ -126,7 +126,8 @@ class account_move_line(orm.Model): context = {} if context.get('async_bypass_create'): return self._bypass_create(cr, uid, vals, context=context) - return super(account_move_line, self).create(cr, uid, vals, context=context) + return super(account_move_line, self).create(cr, uid, vals, + context=context) def _bypass_create(self, cr, uid, vals, context=None): """Create entries using cursor directly diff --git a/__unported__/async_move_line_importer/model/move_line_importer.py b/__unported__/async_move_line_importer/model/move_line_importer.py index f515bf8fe..03370acc2 100644 --- a/__unported__/async_move_line_importer/model/move_line_importer.py +++ b/__unported__/async_move_line_importer/model/move_line_importer.py @@ -53,7 +53,8 @@ class move_line_importer(orm.Model): if default is None: default = {} default.update(state='draft', report=False) - return super(move_line_importer, self).copy(cr, uid, id, default=default, + return super(move_line_importer, self).copy(cr, uid, id, + default=default, context=context) def track_success(sef, cr, uid, obj, context=None): @@ -71,39 +72,58 @@ class move_line_importer(orm.Model): }, } - _columns = {'name': fields.datetime('Name', - required=True, - readonly=True), - 'state': fields.selection([('draft', 'New'), - ('running', 'Running'), - ('done', 'Success'), - ('error', 'Error')], - readonly=True, - string='Status'), - 'report': fields.text('Report', - readonly=True), - 'file': fields.binary('File', - required=True), - 'delimiter': fields.selection([(',', ','), (';', ';'), ('|', '|')], - string="CSV delimiter", - required=True), - 'company_id': fields.many2one('res.company', - 'Company'), - 'bypass_orm': fields.boolean('Fast import (use with caution)', - help="When enabled import will be faster but" - " it will not use orm and may" - " not support all CSV canvas. \n" - "Entry posted option will be skipped. \n" - "AA lines will only be created when" - " moves are posted. \n" - "Tax lines computation will be skipped. \n" - "This option should be used with caution" - " and in conjonction with provided canvas."), - } + _columns = { + 'name': fields.datetime( + 'Name', + required=True, + readonly=True + ), + 'state': fields.selection( + [('draft', 'New'), + ('running', 'Running'), + ('done', 'Success'), + ('error', 'Error')], + readonly=True, + string='Status' + ), + 'report': fields.text( + 'Report', + readonly=True + ), + 'file': fields.binary( + 'File', + required=True + ), + 'delimiter': fields.selection( + [(',', ','), (';', ';'), ('|', '|')], + string="CSV delimiter", + required=True + ), + 'company_id': fields.many2one( + 'res.company', + 'Company' + ), + 'bypass_orm': fields.boolean( + 'Fast import (use with caution)', + help="When enabled import will be faster but" + " it will not use orm and may" + " not support all CSV canvas. \n" + "Entry posted option will be skipped. \n" + "AA lines will only be created when" + " moves are posted. \n" + "Tax lines computation will be skipped. \n" + "This option should be used with caution" + " and in conjonction with provided canvas." + ), + } - def _get_current_company(self, cr, uid, context=None, model="move.line.importer"): - return self.pool.get('res.company')._company_default_get(cr, uid, model, - context=context) + def _get_current_company(self, cr, uid, context=None, + model="move.line.importer"): + return self.pool.get('res.company')._company_default_get( + cr, uid, + model, + context=context + ) _defaults = {'state': 'draft', 'name': fields.datetime.now(), @@ -143,9 +163,11 @@ class move_line_importer(orm.Model): try: data = csv.reader(csv_file, delimiter=str(delimiter)) except csv.Error as error: - raise orm.except_orm(_('CSV file is malformed'), - _("Maybe you have not choose correct separator \n" - "the error detail is : \n %s") % repr(error)) + raise orm.except_orm( + _('CSV file is malformed'), + _("Maybe you have not choose correct separator \n" + "the error detail is : \n %s") % repr(error) + ) head = data.next() head = [x.replace(' ', '') for x in head] # Generator does not work with orm.BaseModel.load @@ -162,13 +184,16 @@ class move_line_importer(orm.Model): res = [] for msg in messages: rows = msg.get('rows', {}) - res.append(_("%s. -- Field: %s -- rows %s to %s") % (msg.get('message', 'N/A'), - msg.get('field', 'N/A'), - rows.get('from', 'N/A'), - rows.get('to', 'N/A'))) + res.append(_("%s. -- Field: %s -- rows %s to %s") % ( + msg.get('message', 'N/A'), + msg.get('field', 'N/A'), + rows.get('from', 'N/A'), + rows.get('to', 'N/A')) + ) return "\n \n".join(res) - def _manage_load_results(self, cr, uid, imp_id, result, _do_commit=True, context=None): + def _manage_load_results(self, cr, uid, imp_id, result, _do_commit=True, + context=None): """Manage the BaseModel.load function output and store exception. Will generate success/failure report and store it into report field. @@ -176,8 +201,10 @@ class move_line_importer(orm.Model): Savepoints. :param imp_id: current importer id - :param result: BaseModel.laod return {ids: list(int)|False, messages: [Message]} - :param _do_commit: toggle commit management only used for testing purpose only + :param result: BaseModel.load returns + {ids: list(int)|False, messages: [Message]} + :param _do_commit: toggle commit management only used + for testing purpose only :returns: current importer id """ @@ -216,15 +243,23 @@ class move_line_importer(orm.Model): local_cr.commit() # We handle concurrent error troubles except psycopg2.OperationalError as pg_exc: - _logger.error('Can not write report. System will retry %s time(s)' % max_tries) - if pg_exc.pg_code in orm.PG_CONCURRENCY_ERRORS_TO_RETRY and max_tries >= 0: + _logger.error( + "Can not write report. " + "System will retry %s time(s)" % max_tries + ) + if (pg_exc.pg_code in orm.PG_CONCURRENCY_ERRORS_TO_RETRY and + max_tries >= 0): local_cr.rollback() local_cr.close() remaining_try = max_tries - 1 - self._write_report(cr, uid, imp_id, cr, _do_commit=_do_commit, - max_tries=remaining_try, context=context) + self._write_report(cr, uid, imp_id, cr, + _do_commit=_do_commit, + max_tries=remaining_try, + context=context) else: - _logger.exception('Can not log report - Operational update error') + _logger.exception( + 'Can not log report - Operational update error' + ) raise except Exception: _logger.exception('Can not log report') @@ -234,10 +269,13 @@ class move_line_importer(orm.Model): if not local_cr.closed: local_cr.close() else: - self.write(cr, uid, [imp_id], {'state': state, 'report': msg}, context=context) + self.write(cr, uid, [imp_id], + {'state': state, 'report': msg}, + context=context) return imp_id - def _load_data(self, cr, uid, imp_id, head, data, _do_commit=True, context=None): + def _load_data(self, cr, uid, imp_id, head, data, _do_commit=True, + context=None): """Function that does the load of parsed CSV file. If will log exception and susccess into the report fields. @@ -245,13 +283,15 @@ class move_line_importer(orm.Model): :param imp_id: current importer id :param head: CSV file head (list of header) :param data: CSV file content (list of data list) - :param _do_commit: toggle commit management only used for testing purpose only + :param _do_commit: toggle commit management + only used for testing purpose only :returns: current importer id """ state = msg = None try: - res = self.pool['account.move'].load(cr, uid, head, data, context=context) + res = self.pool['account.move'].load(cr, uid, head, data, + context=context) r_id, state, msg = self._manage_load_results(cr, uid, imp_id, res, _do_commit=_do_commit, context=context) @@ -285,8 +325,10 @@ class move_line_importer(orm.Model): """ for th in threading.enumerate(): if th.getName() == 'async_move_line_import_%s' % imp_id: - raise orm.except_orm(_('An import of this file is already running'), - _('Please try latter')) + raise orm.except_orm( + _('An import of this file is already running'), + _('Please try latter') + ) def _check_permissions(self, cr, uid, context=None): """Ensure that user is allowed to create move / move line""" @@ -295,7 +337,8 @@ class move_line_importer(orm.Model): move_obj.check_access_rule(cr, uid, [], 'create') move_obj.check_access_rights(cr, uid, 'create', raise_exception=True) move_line_obj.check_access_rule(cr, uid, [], 'create') - move_line_obj.check_access_rights(cr, uid, 'create', raise_exception=True) + move_line_obj.check_access_rights(cr, uid, 'create', + raise_exception=True) def import_file(self, cr, uid, imp_id, context=None): """ Will do an asynchronous load of a CSV file. diff --git a/__unported__/async_move_line_importer/tests/test_async_import.py b/__unported__/async_move_line_importer/tests/test_async_import.py index e0c477899..308c56d81 100644 --- a/__unported__/async_move_line_importer/tests/test_async_import.py +++ b/__unported__/async_move_line_importer/tests/test_async_import.py @@ -48,22 +48,29 @@ class TestMoveLineImporter(test_common.SingleTransactionCase): def test_01_one_line_without_orm_bypass(self): """Test one line import without bypassing orm""" cr, uid = self.cr, self.uid - importer_id = self.importer_model.create(cr, uid, - {'file': self.get_file('one_move.csv'), - 'delimiter': ';'}) + importer_id = self.importer_model.create( + cr, uid, + {'file': self.get_file('one_move.csv'), + 'delimiter': ';'} + ) importer = self.importer_model.browse(cr, uid, importer_id) self.assertTrue(importer.company_id, 'Not default company set') self.assertFalse(importer.bypass_orm, 'Bypass orm must not be active') self.assertEqual(importer.state, 'draft') head, data = self.importer_model._parse_csv(cr, uid, importer.id) - self.importer_model._load_data(cr, uid, importer.id, head, data, _do_commit=False, context={}) + self.importer_model._load_data( + cr, uid, importer.id, head, data, _do_commit=False, context={}) importer = self.importer_model.browse(cr, uid, importer_id) self.assertEquals(importer.state, 'done', 'Exception %s during import' % importer.report) - created_move_ids = self.move_model.search(cr, uid, [('ref', '=', 'éöüàè_test_1')]) + created_move_ids = self.move_model.search( + cr, uid, + [('ref', '=', 'éöüàè_test_1')] + ) self.assertTrue(created_move_ids, 'No move imported') created_move = self.move_model.browse(cr, uid, created_move_ids[0]) - self.assertTrue(len(created_move.line_id) == 3, 'Wrong number of move line imported') + self.assertTrue(len(created_move.line_id) == 3, + 'Wrong number of move line imported') debit = credit = 0.0 for line in created_move.line_id: debit += line.debit if line.debit else 0.0 @@ -75,10 +82,12 @@ class TestMoveLineImporter(test_common.SingleTransactionCase): def test_02_one_line_using_orm_bypass(self): """Test one line import using orm bypass""" cr, uid = self.cr, self.uid - importer_id = self.importer_model.create(cr, uid, - {'file': self.get_file('one_move2.csv'), - 'delimiter': ';', - 'bypass_orm': True}) + importer_id = self.importer_model.create( + cr, uid, + {'file': self.get_file('one_move2.csv'), + 'delimiter': ';', + 'bypass_orm': True} + ) importer = self.importer_model.browse(cr, uid, importer_id) self.assertTrue(importer.company_id, 'Not default company set') self.assertTrue(importer.bypass_orm, 'Bypass orm must be active') @@ -91,10 +100,12 @@ class TestMoveLineImporter(test_common.SingleTransactionCase): importer = self.importer_model.browse(cr, uid, importer_id) self.assertEquals(importer.state, 'done', 'Exception %s during import' % importer.report) - created_move_ids = self.move_model.search(cr, uid, [('ref', '=', 'test_2')]) + created_move_ids = self.move_model.search(cr, uid, + [('ref', '=', 'test_2')]) self.assertTrue(created_move_ids, 'No move imported') created_move = self.move_model.browse(cr, uid, created_move_ids[0]) - self.assertTrue(len(created_move.line_id) == 3, 'Wrong number of move line imported') + self.assertTrue(len(created_move.line_id) == 3, + 'Wrong number of move line imported') debit = credit = 0.0 for line in created_move.line_id: debit += line.debit if line.debit else 0.0 @@ -106,17 +117,22 @@ class TestMoveLineImporter(test_common.SingleTransactionCase): def test_03_one_line_failing(self): """Test one line import with faulty CSV file""" cr, uid = self.cr, self.uid - importer_id = self.importer_model.create(cr, uid, - {'file': self.get_file('faulty_moves.csv'), - 'delimiter': ';'}) + importer_id = self.importer_model.create( + cr, uid, + {'file': self.get_file('faulty_moves.csv'), + 'delimiter': ';'} + ) importer = self.importer_model.browse(cr, uid, importer_id) self.assertTrue(importer.company_id, 'Not default company set') self.assertFalse(importer.bypass_orm, 'Bypass orm must not be active') self.assertEqual(importer.state, 'draft') head, data = self.importer_model._parse_csv(cr, uid, importer.id) - self.importer_model._load_data(cr, uid, importer.id, head, data, _do_commit=False, context={}) + self.importer_model._load_data(cr, uid, importer.id, head, data, + _do_commit=False, context={}) importer = self.importer_model.browse(cr, uid, importer_id) self.assertEquals(importer.state, 'error', 'No exception %s during import' % importer.report) - created_move_ids = self.move_model.search(cr, uid, [('ref', '=', 'test_3')]) - self.assertFalse(created_move_ids, 'Move was imported but it should not be the case') + created_move_ids = self.move_model.search(cr, uid, + [('ref', '=', 'test_3')]) + self.assertFalse(created_move_ids, + 'Move was imported but it should not be the case') diff --git a/__unported__/currency_rate_date_check/__openerp__.py b/__unported__/currency_rate_date_check/__openerp__.py index 9527afff6..87aad9aef 100644 --- a/__unported__/currency_rate_date_check/__openerp__.py +++ b/__unported__/currency_rate_date_check/__openerp__.py @@ -32,10 +32,12 @@ Currency Rate Date Check ======================== This module adds a check on dates when doing currency conversion in OpenERP. -It checks that the currency rate used to make the conversion is not more than N days away +It checks that the currency rate used to make the conversion +is not more than N days away from the date of the amount to convert. -The maximum number of days of the interval can be configured on the company form. +The maximum number of days of the interval can be +configured on the company form. Please contact Alexis de Lattre from Akretion for any help or question about this module. @@ -47,7 +49,7 @@ for any help or question about this module. 'images': [ 'images/date_check_error_popup.jpg', 'images/date_check_company_config.jpg', - ], + ], 'installable': False, 'active': False, } diff --git a/__unported__/currency_rate_date_check/company.py b/__unported__/currency_rate_date_check/company.py index afd3ebc94..d6881f9d7 100644 --- a/__unported__/currency_rate_date_check/company.py +++ b/__unported__/currency_rate_date_check/company.py @@ -29,8 +29,10 @@ class res_company(orm.Model): _columns = { 'currency_rate_max_delta': fields.integer( 'Max Time Delta in Days for Currency Rates', - help="This is the maximum interval in days between the date associated " - "with the amount to convert and the date of the nearest currency " + help="This is the maximum interval in days between " + "the date associated " + "with the amount to convert and the date " + "of the nearest currency " "rate available in OpenERP."), } @@ -41,5 +43,6 @@ class res_company(orm.Model): _sql_constraints = [ ('currency_rate_max_delta_positive', 'CHECK (currency_rate_max_delta >= 0)', - "The value of the field 'Max Time Delta in Days for Currency Rates' must be positive or 0."), + "The value of the field 'Max Time Delta in Days for Currency Rates' " + "must be positive or 0."), ] diff --git a/__unported__/currency_rate_date_check/currency_rate_date_check.py b/__unported__/currency_rate_date_check/currency_rate_date_check.py index ae91883a7..73cb041f3 100644 --- a/__unported__/currency_rate_date_check/currency_rate_date_check.py +++ b/__unported__/currency_rate_date_check/currency_rate_date_check.py @@ -26,27 +26,36 @@ from openerp.tools.translate import _ # Here are some explainations about the design of this module. # In server/openerp/addons/base/res/res_currency.py : -# compute() -> _get_conversion_rate() -> _current_rate() -> _current_rate_computation() +# compute() -> _get_conversion_rate() +# -> _current_rate() -> _current_rate_computation() # The date used for the rate is the one in the context -# compute() adds currency_rate_type_from and currency_rate_type_to to the context +# compute() adds currency_rate_type_from +# and currency_rate_type_to to the context # _get_conversion_rate() adds currency_rate_type_id to context ; # its value is currency_rate_type_to ; -# if it doesn't exist it's currency_rate_type_from ; if it doesn't exist either it's False +# if it doesn't exist it's currency_rate_type_from ; +# if it doesn't exist either it's False # It already contains raise "No rate found for currency ... at the date ..." -# _current_rate() reads currency_rate_type_id from context and uses it in the SQL request -# This is the function used for the definition of the field.function 'rate' on res_currency +# _current_rate() reads currency_rate_type_id +# from context and uses it in the SQL request +# This is the function used for the definition of +# the field.function 'rate' on res_currency # Which one of the 3 functions should we inherit ? Good question... -# It's probably better to inherit the lowest level function, i.e. _current_rate_computation() -# Advantage : by inheriting the lowest level function, we can be sure that the check -# always apply, even for scenarios where we read the field "rate" of the obj currency +# It's probably better to inherit the lowest level function, +# i.e. _current_rate_computation() +# Advantage : by inheriting the lowest level function, +# we can be sure that the check +# always apply, even for scenarios where we +# read the field "rate" of the obj currency # => that's the solution I implement in the code below class res_currency(orm.Model): _inherit = 'res.currency' - def _current_rate_computation(self, cr, uid, ids, name, arg, raise_on_no_rate, context=None): + def _current_rate_computation(self, cr, uid, ids, name, arg, + raise_on_no_rate, context=None): if context is None: context = {} # We only do the check if there is an explicit date in the context and @@ -55,16 +64,18 @@ class res_currency(orm.Model): not context.get('disable_rate_date_check'): for currency_id in ids: # We could get the company from the currency, but it's not a - # 'required' field, so we should probably continue to get it from - # the user, shouldn't we ? - user = self.pool['res.users'].browse(cr, uid, uid, context=context) + # 'required' field, so we should probably continue to get it + # from the user, shouldn't we ? + user = self.pool['res.users'].browse(cr, uid, uid, + context=context) # if it's the company currency, don't do anything # (there is just one old rate at 1.0) if user.company_id.currency_id.id == currency_id: continue else: # now we do the real work ! - date = context.get('date', datetime.today().strftime('%Y-%m-%d')) + date = context.get('date', + datetime.today().strftime('%Y-%m-%d')) date_datetime = datetime.strptime(date, '%Y-%m-%d') rate_obj = self.pool['res.currency.rate'] selected_rate = rate_obj.search(cr, uid, [ @@ -75,17 +86,26 @@ class res_currency(orm.Model): if not selected_rate: continue - rate_date = rate_obj.read(cr, uid, selected_rate[0], ['name'], context=context)['name'] - rate_date_datetime = datetime.strptime(rate_date, '%Y-%m-%d') + rate_date = rate_obj.read(cr, uid, selected_rate[0], + ['name'], + context=context)['name'] + rate_date_datetime = datetime.strptime(rate_date, + '%Y-%m-%d') max_delta = user.company_id.currency_rate_max_delta if (date_datetime - rate_date_datetime).days > max_delta: - currency_name = self.read(cr, uid, currency_id, ['name'], context=context)['name'] + currency_name = self.read(cr, uid, + currency_id, + ['name'], + context=context)['name'] raise orm.except_orm( _('Error'), _('You are requesting a rate conversion on %s for ' - 'currency %s but the nearest rate before that date is ' - 'dated %s and the maximum currency rate time delta for ' - 'your company is %s days') % (date, currency_name, rate_date, max_delta) + 'currency %s but the nearest ' + 'rate before that date is ' + 'dated %s and the maximum currency ' + 'rate time delta for ' + 'your company is %s days') % ( + date, currency_name, rate_date, max_delta) ) # Now we call the regular function from the "base" module return super(res_currency, self)._current_rate_computation( diff --git a/__unported__/currency_rate_update/__openerp__.py b/__unported__/currency_rate_update/__openerp__.py index 1a9c49fd8..6d7ba3bf9 100644 --- a/__unported__/currency_rate_update/__openerp__.py +++ b/__unported__/currency_rate_update/__openerp__.py @@ -3,8 +3,9 @@ # # Copyright (c) 2008 Camtocamp SA # @author JB Aubort, Nicolas Bessi, Joel Grand-Guillaume -# European Central Bank and Polish National Bank invented by Grzegorz Grzelak -# Ported to OpenERP 7.0 by Lorenzo Battistini +# European Central Bank and Polish National Bank by Grzegorz Grzelak +# Ported to OpenERP 7.0 by Lorenzo Battistini +# # Banxico implemented by Agustin Cruz openpyme.mx # # This program is free software: you can redistribute it and/or modify @@ -35,7 +36,8 @@ The module is able to use 4 different sources: Updated daily, source in CHF. 2. European Central Bank (ported by Grzegorz Grzelak) - The reference rates are based on the regular daily concertation procedure between + The reference rates are based on the regular + daily concertation procedure between central banks within and outside the European System of Central Banks, which normally takes place at 2.15 p.m. (14:15) ECB time. Source in EUR. http://www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html @@ -43,10 +45,12 @@ The module is able to use 4 different sources: 3. Yahoo Finance Updated daily -4. Polish National Bank (Narodowy Bank Polski) (contribution by Grzegorz Grzelak) +4. Polish National Bank (Narodowy Bank Polski) + (contribution by Grzegorz Grzelak) Takes official rates from www.nbp.pl. Adds rate table symbol in log. - You should check when rates should apply to bookkeeping. If next day you should - change the update hour in schedule settings because in OpenERP they apply from + You should check when rates should apply to bookkeeping. + If next day you should change the update hour in schedule settings + because in OpenERP they apply from date of update (date - no hours). 5. Banxico for USD & MXN (created by Agustín Cruz) @@ -60,7 +64,8 @@ The update can be set under the company form. You can set for each services which currency you want to update. The logs of the update are visible under the service note. You can active or deactivate the update. -The module uses internal ir_cron feature from OpenERP, so the job is launched once +The module uses internal ir_cron feature from OpenERP, +so the job is launched once the server starts if the 'first execute date' is before the current day. The module supports multi-company currency in two ways: @@ -71,7 +76,8 @@ The module supports multi-company currency in two ways: A function field lets you know your currency configuration. -If in multi-company mode, the base currency will be the first company's currency +If in multi-company mode, the base currency will +be the first company's currency found in database. Thanks to main contributors: Grzegorz Grzelak, Alexis de Lattre diff --git a/__unported__/currency_rate_update/company.py b/__unported__/currency_rate_update/company.py index 808691eae..606a15f50 100644 --- a/__unported__/currency_rate_update/company.py +++ b/__unported__/currency_rate_update/company.py @@ -69,7 +69,8 @@ class res_company(orm.Model): compagnies = self.search(cr, uid, []) activate_cron = 'f' if not value: - # this statement is here beacaus we do no want to save in case of error + # this statement is here beacaus we do no want to save # + # in case of error self.write(cr, uid, id, {'auto_currency_up': value}) for comp in compagnies: if self.browse(cr, uid, comp).auto_currency_up: @@ -84,17 +85,19 @@ class res_company(orm.Model): else: for comp in compagnies: if comp != id and not enable: - if self.browse(cr, uid, comp).multi_company_currency_enable: + current = self.browse(cr, uid, comp) + if current.multi_company_currency_enable: # We ensure taht we did not have write a true value self.write(cr, uid, id, {'auto_currency_up': False}) + msg = ('You can not activate auto currency' + 'update on more thant one company with this ' + 'multi company configuration') return { 'value': {'auto_currency_up': False}, 'warning': { 'title': "Warning", - 'message': 'You can not activate auto currency ' - 'update on more thant one company with this ' - 'multi company configuration' + 'message': msg, } } self.write(cr, uid, id, {'auto_currency_up': value}) diff --git a/__unported__/currency_rate_update/currency_rate_update.py b/__unported__/currency_rate_update/currency_rate_update.py index 4f9bc8808..6a32653cf 100644 --- a/__unported__/currency_rate_update/currency_rate_update.py +++ b/__unported__/currency_rate_update/currency_rate_update.py @@ -3,17 +3,20 @@ # # Copyright (c) 2009 Camptocamp SA # @source JBA and AWST inpiration -# @contributor Grzegorz Grzelak (grzegorz.grzelak@birdglobe.com), Joel Grand-Guillaume +# @contributor Grzegorz Grzelak (grzegorz.grzelak@birdglobe.com), +# Joel Grand-Guillaume # Copyright (c) 2010 Alexis de Lattre (alexis@via.ecp.fr) # - ported XML-based webservices (Admin.ch, ECB, PL NBP) to new XML lib # - rates given by ECB webservice is now correct even when main_cur <> EUR -# - rates given by PL_NBP webservice is now correct even when main_cur <> PLN -# - if company_currency <> CHF, you can now update CHF via Admin.ch webservice +# - rates given by PL_NBP webs. is now correct even when main_cur <> PLN +# - if company_currency <> CHF, you can now update CHF via Admin.ch # (same for EUR with ECB webservice and PLN with NBP webservice) # For more details, see Launchpad bug #645263 -# - mecanism to check if rates given by the webservice are "fresh" enough to be -# written in OpenERP ('max_delta_days' parameter for each currency update service) -# Ported to OpenERP 7.0 by Lorenzo Battistini +# - mecanism to check if rates given by the webservice are "fresh" +# enough to be written in OpenERP +# ('max_delta_days' parameter for each currency update service) +# Ported to OpenERP 7.0 by Lorenzo Battistini +# # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -37,6 +40,8 @@ import logging import time from datetime import datetime, timedelta +from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT from openerp.osv import fields, osv, orm from openerp.tools.translate import _ @@ -56,11 +61,15 @@ class Currency_rate_update_service(osv.Model): ('Admin_ch_getter', 'Admin.ch'), ('ECB_getter', 'European Central Bank'), ('Yahoo_getter', 'Yahoo Finance '), - ('PL_NBP_getter', 'Narodowy Bank Polski'), # Added for polish rates - ('Banxico_getter', 'Banco de México'), # Added for mexican rates - # Bank of Canada is using RSS-CB http://www.cbwiki.net/wiki/index.php/Specification_1.1 : - # This RSS format is used by other national banks (Thailand, Malaysia, Mexico...) - ('CA_BOC_getter', 'Bank of Canada - noon rates'), # Added for canadian rates + # Added for polish rates + ('PL_NBP_getter', 'Narodowy Bank Polski'), + # Added for mexican rates + ('Banxico_getter', 'Banco de México'), + # Bank of Canada is using RSS-CB + # http://www.cbwiki.net/wiki/index.php/Specification_1.1 + # This RSS format is used by other national banks + # (Thailand, Malaysia, Mexico...) + ('CA_BOC_getter', 'Bank of Canada - noon rates'), ], "Webservice to use", required=True @@ -119,13 +128,14 @@ class Currency_rate_update(osv.Model): _name = "currency.rate.update" _description = "Currency Rate Update" # Dict that represent a cron object + nextcall_time = datetime.today() + timedelta(days=1) + nextcall = nextcall_time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) cron = { 'active': False, 'priority': 1, 'interval_number': 1, 'interval_type': 'weeks', - 'nextcall': time.strftime("%Y-%m-%d %H:%M:%S", - datetime.today() + timedelta(days=1)).timetuple(), + 'nextcall': nextcall, 'numbercall': -1, 'doall': True, 'model': 'currency.rate.update', @@ -159,7 +169,9 @@ class Currency_rate_update(osv.Model): cron_id = int(cron_id[0]) except Exception: _logger.info('warning cron not found one will be created') - pass # Ignore if the cron is missing cause we are going to create it in db + # Ignore if the cron is missing cause we are + # going to create it in db + pass if not cron_id: self.cron['name'] = _('Currency Rate Update') cron_id = cron_obj.create(cr, uid, self.cron, context) @@ -213,13 +225,14 @@ class Currency_rate_update(osv.Model): # We initalize the class that will handle the request # and return a dict of rate getter = factory.register(service.service) - curr_to_fetch = map(lambda x: x.name, service.currency_to_update) + curr_to_fetch = map(lambda x: x.name, + service.currency_to_update) res, log_info = getter.get_updated_currency( curr_to_fetch, main_curr, service.max_delta_days ) - rate_name = time.strftime('%Y-%m-%d') + rate_name = time.strftime(DEFAULT_SERVER_DATE_FORMAT) for curr in service.currency_to_update: if curr.name == main_curr: continue @@ -242,16 +255,22 @@ class Currency_rate_update(osv.Model): ) # Show the most recent note at the top - msg = "%s \n%s currency updated. %s" % \ - (log_info or '', - datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S'), - note) + msg = "%s \n%s currency updated. %s" % ( + log_info or '', + datetime.today().strftime( + DEFAULT_SERVER_DATETIME_FORMAT + ), + note + ) service.write({'note': msg}) except Exception as exc: - error_msg = "\n%s ERROR : %s %s" %\ - (datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S'), - repr(exc), - note) + error_msg = "\n%s ERROR : %s %s" % ( + datetime.today().strftime( + DEFAULT_SERVER_DATETIME_FORMAT + ), + repr(exc), + note + ) _logger.info(repr(exc)) service.write({'note': error_msg}) @@ -321,40 +340,31 @@ class Curreny_getter_interface(object): log_info = " " supported_currency_array = [ - 'AFN', 'ALL', 'DZD', 'USD', 'USD', 'USD', 'EUR', 'AOA', 'XCD', 'XCD', 'ARS', - 'AMD', 'AWG', 'AUD', 'EUR', 'AZN', 'EUR', 'BSD', 'BHD', 'EUR', 'BDT', 'BBD', - 'XCD', 'BYR', 'EUR', 'BZD', 'XOF', 'BMD', 'BTN', 'INR', 'BOB', 'ANG', 'BAM', - 'BWP', 'NOK', 'BRL', 'GBP', 'USD', 'USD', 'BND', 'BGN', 'XOF', 'MMK', 'BIF', - 'XOF', 'USD', 'KHR', 'XAF', 'CAD', 'EUR', 'CVE', 'KYD', 'XAF', 'XAF', 'CLP', - 'CNY', 'AUD', 'AUD', 'COP', 'XAF', 'KMF', 'XPF', 'XAF', 'CDF', 'NZD', 'CRC', - 'HRK', 'CUP', 'ANG', 'EUR', 'CYP', 'CZK', 'DKK', 'DJF', 'XCD', 'DOP', 'EUR', - 'XCD', 'IDR', 'USD', 'EGP', 'EUR', 'SVC', 'USD', 'GBP', 'XAF', 'ETB', 'ERN', - 'EEK', 'ETB', 'EUR', 'FKP', 'DKK', 'FJD', 'EUR', 'EUR', 'EUR', 'XPF', 'XPF', - 'EUR', 'XPF', 'XAF', 'GMD', 'GEL', 'EUR', 'GHS', 'GIP', 'XAU', 'GBP', 'EUR', - 'DKK', 'XCD', 'XCD', 'EUR', 'USD', 'GTQ', 'GGP', 'GNF', 'XOF', 'GYD', 'HTG', - 'USD', 'AUD', 'BAM', 'EUR', 'EUR', 'HNL', 'HKD', 'HUF', 'ISK', 'INR', 'IDR', - 'XDR', 'IRR', 'IQD', 'EUR', 'IMP', 'ILS', 'EUR', 'JMD', 'NOK', 'JPY', 'JEP', - 'JOD', 'KZT', 'AUD', 'KES', 'AUD', 'KPW', 'KRW', 'KWD', 'KGS', 'LAK', 'LVL', - 'LBP', 'LSL', 'ZAR', 'LRD', 'LYD', 'CHF', 'LTL', 'EUR', 'MOP', 'MKD', 'MGA', - 'EUR', 'MWK', 'MYR', 'MVR', 'XOF', 'EUR', 'MTL', 'FKP', 'USD', 'USD', 'EUR', - 'MRO', 'MUR', 'EUR', 'AUD', 'MXN', 'USD', 'USD', 'EUR', 'MDL', 'EUR', 'MNT', - 'EUR', 'XCD', 'MAD', 'MZN', 'MMK', 'NAD', 'ZAR', 'AUD', 'NPR', 'ANG', 'EUR', - 'XCD', 'XPF', 'NZD', 'NIO', 'XOF', 'NGN', 'NZD', 'AUD', 'USD', 'NOK', 'OMR', - 'PKR', 'USD', 'XPD', 'PAB', 'USD', 'PGK', 'PYG', 'PEN', 'PHP', 'NZD', 'XPT', - 'PLN', 'EUR', 'STD', 'USD', 'QAR', 'EUR', 'RON', 'RUB', 'RWF', 'STD', 'ANG', - 'MAD', 'XCD', 'SHP', 'XCD', 'XCD', 'EUR', 'XCD', 'EUR', 'USD', 'WST', 'EUR', - 'SAR', 'SPL', 'XOF', 'RSD', 'SCR', 'SLL', 'XAG', 'SGD', 'ANG', 'ANG', 'EUR', - 'EUR', 'SBD', 'SOS', 'ZAR', 'GBP', 'GBP', 'EUR', 'XDR', 'LKR', 'SDG', 'SRD', - 'NOK', 'SZL', 'SEK', 'CHF', 'SYP', 'TWD', 'RUB', 'TJS', 'TZS', 'THB', 'IDR', - 'TTD', 'XOF', 'NZD', 'TOP', 'TTD', 'TND', 'TRY', 'TMM', 'USD', 'TVD', 'UGX', - 'UAH', 'AED', 'GBP', 'USD', 'USD', 'UYU', 'USD', 'UZS', 'VUV', 'EUR', 'VEB', - 'VEF', 'VND', 'USD', 'USD', 'USD', 'XPF', 'MAD', 'YER', 'ZMK', 'ZWD' + 'AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', + 'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BRL', + 'BSD', 'BTN', 'BWP', 'BYR', 'BZD', 'CAD', 'CDF', 'CHF', 'CLP', 'CNY', + 'COP', 'CRC', 'CUP', 'CVE', 'CYP', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', + 'EEK', 'EGP', 'ERN', 'ETB', 'EUR', 'FJD', 'FKP', 'GBP', 'GEL', 'GGP', + 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', + 'HUF', 'IDR', 'ILS', 'IMP', 'INR', 'IQD', 'IRR', 'ISK', 'JEP', 'JMD', + 'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', + 'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LTL', 'LVL', 'LYD', 'MAD', + 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP', 'MRO', 'MTL', 'MUR', 'MVR', + 'MWK', 'MXN', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', + 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', + 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDG', 'SEK', 'SGD', 'SHP', + 'SLL', 'SOS', 'SPL', 'SRD', 'STD', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', + 'TMM', 'TND', 'TOP', 'TRY', 'TTD', 'TVD', 'TWD', 'TZS', 'UAH', 'UGX', + 'USD', 'UYU', 'UZS', 'VEB', 'VEF', 'VND', 'VUV', 'WST', 'XAF', 'XAG', + 'XAU', 'XCD', 'XDR', 'XOF', 'XPD', 'XPF', 'XPT', 'YER', 'ZAR', 'ZMK', + 'ZWD' ] # Updated currency this arry will contain the final result updated_currency = {} - def get_updated_currency(self, currency_array, main_currency, max_delta_days): + def get_updated_currency(self, currency_array, main_currency, + max_delta_days): """Interface method that will retrieve the currency This function has to be reinplemented in child """ @@ -397,23 +407,26 @@ class Curreny_getter_interface(object): ) # We always have a warning when rate_date != today - rate_date_str = datetime.strftime(rate_date, '%Y-%m-%d') - if rate_date_str != datetime.strftime(datetime.today(), '%Y-%m-%d'): + rate_date_str = datetime.strftime(rate_date, + DEFAULT_SERVER_DATE_FORMAT) + if rate_date.date() != datetime.today().date(): msg = "The rate timestamp (%s) is not today's date" self.log_info = ("WARNING : %s %s") % (msg, rate_date_str) _logger.warning(msg, rate_date_str) -# Yahoo ######################################################################## +# Yahoo ####################################################################### class Yahoo_getter(Curreny_getter_interface): """Implementation of Currency_getter_factory interface for Yahoo finance service """ - def get_updated_currency(self, currency_array, main_currency, max_delta_days): + def get_updated_currency(self, currency_array, main_currency, + max_delta_days): """implementation of abstract method of curreny_getter_interface""" self.validate_cur(main_currency) - url = 'http://download.finance.yahoo.com/d/quotes.txt?s="%s"=X&f=sl1c1abg' + url = ('http://download.finance.yahoo.com/d/' + 'quotes.txt?s="%s"=X&f=sl1c1abg') if main_currency in currency_array: currency_array.remove(main_currency) for curr in currency_array: @@ -438,15 +451,23 @@ class Admin_ch_getter(Curreny_getter_interface): def rate_retrieve(self, dom, ns, curr): """Parse a dom node to retrieve currencies data""" res = {} - xpath_rate_currency = "/def:wechselkurse/def:devise[@code='%s']/def:kurs/text()" % (curr.lower()) - xpath_rate_ref = "/def:wechselkurse/def:devise[@code='%s']/def:waehrung/text()" % (curr.lower()) - res['rate_currency'] = float(dom.xpath(xpath_rate_currency, namespaces=ns)[0]) - res['rate_ref'] = float((dom.xpath(xpath_rate_ref, namespaces=ns)[0]).split(' ')[0]) + xpath_rate_currency = ("/def:wechselkurse/def:devise[@code='%s']/" + "def:kurs/text()") % (curr.lower()) + xpath_rate_ref = ("/def:wechselkurse/def:devise[@code='%s']/" + "def:waehrung/text()") % (curr.lower()) + res['rate_currency'] = float( + dom.xpath(xpath_rate_currency, namespaces=ns)[0] + ) + res['rate_ref'] = float( + (dom.xpath(xpath_rate_ref, namespaces=ns)[0]).split(' ')[0] + ) return res - def get_updated_currency(self, currency_array, main_currency, max_delta_days): + def get_updated_currency(self, currency_array, main_currency, + max_delta_days): """Implementation of abstract method of Curreny_getter_interface""" - url = 'http://www.afd.admin.ch/publicdb/newdb/mwst_kurse/wechselkurse.php' + url = ('http://www.afd.admin.ch/publicdb/newdb/' + 'mwst_kurse/wechselkurse.php') # We do not want to update the main currency if main_currency in currency_array: currency_array.remove(main_currency) @@ -456,21 +477,36 @@ class Admin_ch_getter(Curreny_getter_interface): rawfile = self.get_url(url) dom = etree.fromstring(rawfile) _logger.debug("Admin.ch sent a valid XML file") - adminch_ns = {'def': 'http://www.afd.admin.ch/publicdb/newdb/mwst_kurse'} - rate_date = dom.xpath('/def:wechselkurse/def:datum/text()', namespaces=adminch_ns)[0] - rate_date_datetime = datetime.strptime(rate_date, '%Y-%m-%d') + adminch_ns = { + 'def': 'http://www.afd.admin.ch/publicdb/newdb/mwst_kurse' + } + rate_date = dom.xpath( + '/def:wechselkurse/def:datum/text()', + namespaces=adminch_ns + ) + rate_date = rate_date[0] + rate_date_datetime = datetime.strptime(rate_date, + DEFAULT_SERVER_DATE_FORMAT) self.check_rate_date(rate_date_datetime, max_delta_days) # we dynamically update supported currencies - self.supported_currency_array = dom.xpath("/def:wechselkurse/def:devise/@code", namespaces=adminch_ns) - self.supported_currency_array = [x.upper() for x in self.supported_currency_array] + self.supported_currency_array = dom.xpath( + "/def:wechselkurse/def:devise/@code", + namespaces=adminch_ns + ) + self.supported_currency_array = [x.upper() for x + in self.supported_currency_array] self.supported_currency_array.append('CHF') - _logger.debug("Supported currencies = " + str(self.supported_currency_array)) + _logger.debug( + "Supported currencies = " + str(self.supported_currency_array) + ) self.validate_cur(main_currency) if main_currency != 'CHF': main_curr_data = self.rate_retrieve(dom, adminch_ns, main_currency) # 1 MAIN_CURRENCY = main_rate CHF - main_rate = main_curr_data['rate_currency'] / main_curr_data['rate_ref'] + rate_curr = main_curr_data['rate_currency'] + rate_ref = main_curr_data['rate_ref'] + main_rate = rate_curr / rate_ref for curr in currency_array: self.validate_cur(curr) if curr == 'CHF': @@ -481,7 +517,8 @@ class Admin_ch_getter(Curreny_getter_interface): if main_currency == 'CHF': rate = curr_data['rate_ref'] / curr_data['rate_currency'] else: - rate = main_rate * curr_data['rate_ref'] / curr_data['rate_currency'] + rate = (main_rate * curr_data['rate_ref'] / + curr_data['rate_currency']) self.updated_currency[curr] = rate _logger.debug( "Rate retrieved : 1 %s = %s %s" % (main_currency, rate, curr) @@ -501,17 +538,21 @@ class ECB_getter(Curreny_getter_interface): """ res = {} - xpath_curr_rate = "/gesmes:Envelope/def:Cube/def:Cube/def:Cube[@currency='%s']/@rate" % (curr.upper()) - res['rate_currency'] = float(dom.xpath(xpath_curr_rate, namespaces=ns)[0]) + xpath_curr_rate = ("/gesmes:Envelope/def:Cube/def:Cube/" + "def:Cube[@currency='%s']/@rate") % (curr.upper()) + res['rate_currency'] = float( + dom.xpath(xpath_curr_rate, namespaces=ns)[0] + ) return res - def get_updated_currency(self, currency_array, main_currency, max_delta_days): + def get_updated_currency(self, currency_array, main_currency, + max_delta_days): """implementation of abstract method of Curreny_getter_interface""" url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml' # Important : as explained on the ECB web site, the currencies are # at the beginning of the afternoon ; so, until 3 p.m. Paris time # the currency rates are the ones of trading day N-1 - # see http://www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html + # http://www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html # We do not want to update the main currency if main_currency in currency_array: @@ -528,13 +569,17 @@ class ECB_getter(Curreny_getter_interface): } rate_date = dom.xpath('/gesmes:Envelope/def:Cube/def:Cube/@time', namespaces=ecb_ns)[0] - rate_date_datetime = datetime.strptime(rate_date, '%Y-%m-%d') + rate_date_datetime = datetime.strptime(rate_date, + DEFAULT_SERVER_DATE_FORMAT) self.check_rate_date(rate_date_datetime, max_delta_days) # We dynamically update supported currencies - self.supported_currency_array = dom.xpath("/gesmes:Envelope/def:Cube/def:Cube/def:Cube/@currency", - namespaces=ecb_ns) + self.supported_currency_array = dom.xpath( + "/gesmes:Envelope/def:Cube/def:Cube/def:Cube/@currency", + namespaces=ecb_ns + ) self.supported_currency_array.append('EUR') - _logger.debug("Supported currencies = %s " % self.supported_currency_array) + _logger.debug("Supported currencies = %s " % + self.supported_currency_array) self.validate_cur(main_currency) if main_currency != 'EUR': main_curr_data = self.rate_retrieve(dom, ecb_ns, main_currency) @@ -547,9 +592,12 @@ class ECB_getter(Curreny_getter_interface): if main_currency == 'EUR': rate = curr_data['rate_currency'] else: - rate = curr_data['rate_currency'] / main_curr_data['rate_currency'] + rate = (curr_data['rate_currency'] / + main_curr_data['rate_currency']) self.updated_currency[curr] = rate - _logger.debug("Rate retrieved : 1 %s = %s %s" % (main_currency, rate, curr)) + _logger.debug( + "Rate retrieved : 1 %s = %s %s" % (main_currency, rate, curr) + ) return self.updated_currency, self.log_info @@ -564,13 +612,18 @@ class PL_NBP_getter(Curreny_getter_interface): """ Parse a dom node to retrieve currencies data""" res = {} - xpath_rate_currency = "/tabela_kursow/pozycja[kod_waluty='%s']/kurs_sredni/text()" % (curr.upper()) - xpath_rate_ref = "/tabela_kursow/pozycja[kod_waluty='%s']/przelicznik/text()" % (curr.upper()) - res['rate_currency'] = float(dom.xpath(xpath_rate_currency, namespaces=ns)[0].replace(',', '.')) + xpath_rate_currency = ("/tabela_kursow/pozycja[kod_waluty='%s']/" + "kurs_sredni/text()") % (curr.upper()) + xpath_rate_ref = ("/tabela_kursow/pozycja[kod_waluty='%s']/" + "przelicznik/text()") % (curr.upper()) + res['rate_currency'] = float( + dom.xpath(xpath_rate_currency, namespaces=ns)[0].replace(',', '.') + ) res['rate_ref'] = float(dom.xpath(xpath_rate_ref, namespaces=ns)[0]) return res - def get_updated_currency(self, currency_array, main_currency, max_delta_days): + def get_updated_currency(self, currency_array, main_currency, + max_delta_days): """implementation of abstract method of Curreny_getter_interface""" # LastA.xml is always the most recent one url = 'http://www.nbp.pl/kursy/xml/LastA.xml' @@ -584,18 +637,25 @@ class PL_NBP_getter(Curreny_getter_interface): dom = etree.fromstring(rawfile) ns = {} # Cool, there are no namespaces ! _logger.debug("NBP.pl sent a valid XML file") - rate_date = dom.xpath('/tabela_kursow/data_publikacji/text()', namespaces=ns)[0] - rate_date_datetime = datetime.strptime(rate_date, '%Y-%m-%d') + rate_date = dom.xpath('/tabela_kursow/data_publikacji/text()', + namespaces=ns)[0] + rate_date_datetime = datetime.strptime(rate_date, + DEFAULT_SERVER_DATE_FORMAT) self.check_rate_date(rate_date_datetime, max_delta_days) # We dynamically update supported currencies - self.supported_currency_array = dom.xpath('/tabela_kursow/pozycja/kod_waluty/text()', namespaces=ns) + self.supported_currency_array = dom.xpath( + '/tabela_kursow/pozycja/kod_waluty/text()', + namespaces=ns + ) self.supported_currency_array.append('PLN') - _logger.debug("Supported currencies = %s" % self.supported_currency_array) + _logger.debug("Supported currencies = %s" % + self.supported_currency_array) self.validate_cur(main_currency) if main_currency != 'PLN': main_curr_data = self.rate_retrieve(dom, ns, main_currency) # 1 MAIN_CURRENCY = main_rate PLN - main_rate = main_curr_data['rate_currency'] / main_curr_data['rate_ref'] + main_rate = (main_curr_data['rate_currency'] / + main_curr_data['rate_ref']) for curr in currency_array: self.validate_cur(curr) if curr == 'PLN': @@ -606,9 +666,11 @@ class PL_NBP_getter(Curreny_getter_interface): if main_currency == 'PLN': rate = curr_data['rate_ref'] / curr_data['rate_currency'] else: - rate = main_rate * curr_data['rate_ref'] / curr_data['rate_currency'] + rate = (main_rate * curr_data['rate_ref'] / + curr_data['rate_currency']) self.updated_currency[curr] = rate - _logger.debug("Rate retrieved : %s = %s %s" % (main_currency, rate, curr)) + _logger.debug("Rate retrieved : %s = %s %s" % + (main_currency, rate, curr)) return self.updated_currency, self.log_info @@ -623,7 +685,8 @@ class Banxico_getter(Curreny_getter_interface): """ Get currency exchange from Banxico.xml and proccess it TODO: Get correct data from xml instead of process string """ - url = 'http://www.banxico.org.mx/rsscb/rss?BMXC_canal=pagos&BMXC_idioma=es' + url = ('http://www.banxico.org.mx/rsscb/rss?' + 'BMXC_canal=pagos&BMXC_idioma=es') from xml.dom.minidom import parse from StringIO import StringIO @@ -640,7 +703,8 @@ class Banxico_getter(Curreny_getter_interface): return float(rate) - def get_updated_currency(self, currency_array, main_currency, max_delta_days=1): + def get_updated_currency(self, currency_array, main_currency, + max_delta_days=1): """implementation of abstract method of Curreny_getter_interface""" logger = logging.getLogger(__name__) # we do not want to update the main currency @@ -662,7 +726,8 @@ class Banxico_getter(Curreny_getter_interface): continue self.updated_currency[curr] = rate - logger.debug("Rate retrieved : %s = %s %s" % (main_currency, rate, curr)) + logger.debug("Rate retrieved : %s = %s %s" % + (main_currency, rate, curr)) # CA BOC ##### Bank of Canada ############################################# @@ -672,11 +737,13 @@ class CA_BOC_getter(Curreny_getter_interface): """ - def get_updated_currency(self, currency_array, main_currency, max_delta_days): + def get_updated_currency(self, currency_array, main_currency, + max_delta_days): """implementation of abstract method of Curreny_getter_interface""" # as of Jan 2014 BOC is publishing noon rates for about 60 currencies - url = 'http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_%s.xml' + url = ('http://www.bankofcanada.ca/stats/assets/' + 'rates_rss/noon/en_%s.xml') # closing rates are available as well (please note there are only 12 # currencies reported): # http://www.bankofcanada.ca/stats/assets/rates_rss/closing/en_%s.xml @@ -718,11 +785,15 @@ class CA_BOC_getter(Curreny_getter_interface): .astimezone(pytz.utc).replace(tzinfo=None) self.check_rate_date(rate_date_datetime, max_delta_days) self.updated_currency[curr] = rate - _logger.debug("BOC Rate retrieved : %s = %s %s" % (main_currency, rate, curr)) + _logger.debug("BOC Rate retrieved : %s = %s %s" % + (main_currency, rate, curr)) else: - _logger.error("Exchange data format error for Bank of Canada -\ - %s. Please check provider data format and/or source code." % curr) - raise osv.except_osv('Error !', 'Exchange data format error for\ - Bank of Canada - %s !' % str(curr)) + _logger.error( + "Exchange data format error for Bank of Canada -" + "%s. Please check provider data format " + "and/or source code." % curr) + raise osv.except_osv('Error !', + 'Exchange data format error for\ + Bank of Canada - %s !' % str(curr)) return self.updated_currency, self.log_info diff --git a/account_balance_line/__init__.py b/account_balance_line/__init__.py new file mode 100644 index 000000000..373e5a269 --- /dev/null +++ b/account_balance_line/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Vincent Renaville (Camptocamp) +# Copyright 2010-2014 Camptocamp SA +# +# 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 . +# +############################################################################## +from . import account_move_line diff --git a/account_balance_line/__openerp__.py b/account_balance_line/__openerp__.py new file mode 100644 index 000000000..91e780676 --- /dev/null +++ b/account_balance_line/__openerp__.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Vincent Renaville (Camptocamp) +# Copyright 2010-2014 Camptocamp SA +# +# 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 . +# +############################################################################## +{'name': 'Balance on lines', + 'summary': 'Display balance totals in move line view', + 'version': '1.1', + 'author': 'Camptocamp', + 'maintainter': 'Camptocamp', + 'category': 'Accounting', + 'depends': ['account'], + 'description': """ +Balance for a line +================== + +Add a balance total for grouped lines in move line view. + +Balance field will only be shown when move lines are grouped by account +or filtered by account. + +Contributors +------------ + +* Vincent revaville +* Yannick Vaucher +""", + 'website': 'http://www.camptocamp.com', + 'data': ['account_move_line_view.xml'], + 'tests': [], + 'installable': True, + 'auto_install': False, + 'license': 'AGPL-3', + 'application': False, + } diff --git a/account_balance_line/account_move_line.py b/account_balance_line/account_move_line.py new file mode 100644 index 000000000..e6c77260e --- /dev/null +++ b/account_balance_line/account_move_line.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Vincent Renaville (Camptocamp) +# Copyright 2010-2014 Camptocamp SA +# +# 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 . +# +############################################################################## +from openerp.osv import orm, fields + + +class account_move_line(orm.Model): + _inherit = "account.move.line" + + def _line_balance(self, cr, uid, ids, field, arg, context=None): + res = {} + move_lines = self.read(cr, uid, ids, + ['debit', 'credit'], + context=context) + + for line in move_lines: + res[line['id']] = line['debit'] - line['credit'] + return res + + _columns = { + 'line_balance': fields.function( + _line_balance, method=True, + string='Balance', + store=True), + } diff --git a/account_balance_line/account_move_line_view.xml b/account_balance_line/account_move_line_view.xml new file mode 100644 index 000000000..22be69ccb --- /dev/null +++ b/account_balance_line/account_move_line_view.xml @@ -0,0 +1,30 @@ + + + + + + Journal Items add visibilty for balance + account.move.line + + + + {'invisible_balance': False} + + + {'group_by': 'account_id', 'invisible_balance': False} + + + + + + account_move_line_balance_custom + account.move.line + + + + + + + + + diff --git a/account_balance_line/i18n/account_balance_line.pot b/account_balance_line/i18n/account_balance_line.pot new file mode 100644 index 000000000..4330edce5 --- /dev/null +++ b/account_balance_line/i18n/account_balance_line.pot @@ -0,0 +1,53 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_balance_line +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-20 14:11+0000\n" +"PO-Revision-Date: 2014-06-20 14:11+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "Account" +msgstr "" + +#. module: account_balance_line +#: model:ir.model,name:account_balance_line.model_account_move_line +msgid "Entry lines" +msgstr "" + +#. module: account_balance_line +#: code:_description:0 +#, python-format +msgid "Journal Items" +msgstr "" + +#. module: account_balance_line +#: field:account.move.line,line_balance:0 +msgid "Balance" +msgstr "" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "Total Balance" +msgstr "" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "{'group_by': 'account_id', 'invisible_balance': False}" +msgstr "" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "{'invisible_balance': False}" +msgstr "" + diff --git a/account_balance_line/i18n/fr.po b/account_balance_line/i18n/fr.po new file mode 100644 index 000000000..31f766975 --- /dev/null +++ b/account_balance_line/i18n/fr.po @@ -0,0 +1,53 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_balance_line +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-06-20 14:11+0000\n" +"PO-Revision-Date: 2014-06-20 14:11+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "Account" +msgstr "Compte" + +#. module: account_balance_line +#: model:ir.model,name:account_balance_line.model_account_move_line +msgid "Entry lines" +msgstr "Lignes d'écriture" + +#. module: account_balance_line +#: code:_description:0 +#, python-format +msgid "Journal Items" +msgstr "Écritures comptables" + +#. module: account_balance_line +#: field:account.move.line,line_balance:0 +msgid "Balance" +msgstr "Balance" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "Total Balance" +msgstr "Balance Totale" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "{'group_by': 'account_id', 'invisible_balance': False}" +msgstr "" + +#. module: account_balance_line +#: view:account.move.line:0 +msgid "{'invisible_balance': False}" +msgstr "" + diff --git a/account_journal_period_close/__init__.py b/account_journal_period_close/__init__.py new file mode 100644 index 000000000..dcf937772 --- /dev/null +++ b/account_journal_period_close/__init__.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# 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 contact a Free Software +# Service Company. +# +# 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 . +# +# + +from . import model +from . import tests diff --git a/account_journal_period_close/__openerp__.py b/account_journal_period_close/__openerp__.py new file mode 100644 index 000000000..ab9b61686 --- /dev/null +++ b/account_journal_period_close/__openerp__.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# 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 contact a Free Software +# Service Company. +# +# 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 . +# +# + +{ + "name": "Account Journal Period Close", + "version": "1.0", + "author": "ACSONE SA/NV", + "maintainer": "ACSONE SA/NV", + "website": "http://www.acsone.eu", + "images": [], + "category": "Accounting", + "depends": [ + "account"], + "description": """ +Close period per journal +======================== + +This module allows fine grained control of period closing. +Each journal can be closed independently for any period +(using buttons on the fiscal period view). + +A common use case is letting accountants close the sale +and purchase journals when the VAT declaration is done for +a given period, while leaving the miscellaneous journal open. + +From a technical standpoint, the module leverages the +account.journal.period model that is present in Odoo core. +""", + "data": ['view/account_view.xml'], + "demo": [], + "test": [], + "licence": "AGPL-3", + "installable": True, + "auto_install": False, + "application": True, +} diff --git a/account_journal_period_close/model/__init__.py b/account_journal_period_close/model/__init__.py new file mode 100644 index 000000000..123722270 --- /dev/null +++ b/account_journal_period_close/model/__init__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# 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 contact a Free Software +# Service Company. +# +# 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 . +# +# +from . import account diff --git a/account_journal_period_close/model/account.py b/account_journal_period_close/model/account.py new file mode 100644 index 000000000..ecaa924d4 --- /dev/null +++ b/account_journal_period_close/model/account.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# 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 contact a Free Software +# Service Company. +# +# 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 . +# +# + +from openerp.osv import orm, fields +from openerp.tools.translate import _ + + +class account_period(orm.Model): + _inherit = 'account.period' + _columns = { + 'journal_period_ids': fields.one2many('account.journal.period', + 'period_id', 'Journal states'), + } + + +class account_journal_period(orm.Model): + _inherit = 'account.journal.period' + _order = "type,name" + _columns = { + 'type': fields.related('journal_id', 'type', type='char', + relation='account.journal', + string='Journal Type', + store=True, readonly=True) + } + + def _check(self, cr, uid, ids, context=None): + return True + + def action_draft(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'state': 'draft'}) + + def action_done(self, cr, uid, ids, context=None): + for journal_period in self.browse(cr, uid, ids, context=context): + draft_move_ids = self.pool.get('account.move')\ + .search(cr, uid, [('period_id', '=', + journal_period.period_id.id), + ('state', '=', "draft"), + ('journal_id', '=', + journal_period.journal_id.id)], + context=context) + if draft_move_ids: + raise orm.except_orm(_('Invalid Action!'), + _('In order to close a journal,' + ' you must first post related' + ' journal entries.')) + return self.write(cr, uid, ids, {'state': 'done'}) + + def create(self, cr, uid, values, context=None): + if 'name' not in values: + if values.get('period_id') and values.get('journal_id'): + journal = self.pool.get('account.journal')\ + .browse(cr, uid, values['journal_id'], context=context) + period = self.pool.get('account.period')\ + .browse(cr, uid, values['period_id'], context=context) + values.update({'name': (journal.code or journal.name)+':' + + (period.name or '')}), + return super(account_journal_period, self).create(cr, + uid, + values, + context=context) diff --git a/account_journal_period_close/tests/__init__.py b/account_journal_period_close/tests/__init__.py new file mode 100644 index 000000000..d503a5aa8 --- /dev/null +++ b/account_journal_period_close/tests/__init__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# 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 contact a Free Software +# Service Company. +# +# 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 . +# +# + +from . import test_account_journal_period_close diff --git a/account_journal_period_close/tests/test_account_journal_period_close.py b/account_journal_period_close/tests/test_account_journal_period_close.py new file mode 100644 index 000000000..ed175a425 --- /dev/null +++ b/account_journal_period_close/tests/test_account_journal_period_close.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- +# +# +# Authors: Adrien Peiffer +# Copyright (c) 2014 Acsone SA/NV (http://www.acsone.eu) +# All Rights Reserved +# +# 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 contact a Free Software +# Service Company. +# +# 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 . +# +# + +import openerp.tests.common as common +from openerp.osv import orm +from datetime import datetime + +DB = common.DB +ADMIN_USER_ID = common.ADMIN_USER_ID + + +def get_simple_account_move_values(self, period_id, journal_id): + sale_product_account_id = self.ref('account.a_sale') + cash_account_id = self.ref('account.cash') + partner_id = self.ref('base.res_partner_2') + year = datetime.now().strftime('%Y') + return {'partner_id': partner_id, + 'period_id': period_id, + 'date': year + '-01-01', + 'journal_id': journal_id, + 'line_id': [(0, 0, {'name': 'test', + 'account_id': cash_account_id, + 'debit': 50.0, + }), + (0, 0, {'name': 'test_conterpart', + 'account_id': sale_product_account_id, + 'credit': 50.0, + }) + ] + } + + +def close_period(self, period_id, context=None): + close_period_wizard_id =\ + self.registry('account.period.close').create(self.cr, + self.uid, + {'sure': True + }, + context=context) + context.update({'active_ids': [period_id]}) + self.registry('account.period.close')\ + .data_save(self.cr, + self.uid, + [close_period_wizard_id], + context=context) + + +def create_journal_period(self, period_id, journal_id, context): + jour_per_obj = self.registry('account.journal.period') + journal_period_id = jour_per_obj.create(self.cr, + self.uid, + {'period_id': period_id, + 'journal_id': journal_id, + }, + context=context) + return journal_period_id + + +def journal_period_done(self, journal_period_id, context): + jour_per_obj = self.registry('account.journal.period') + jour_per_obj.action_done(self.cr, + self.uid, + [journal_period_id], + context=context) + + +def journal_period_draft(self, journal_period_id, context): + jour_per_obj = self.registry('account.journal.period') + jour_per_obj.action_draft(self.cr, + self.uid, + [journal_period_id], + context=context) + + +class TestAccountConstraintChronology(common.TransactionCase): + + def setUp(self): + super(TestAccountConstraintChronology, self).setUp() + + def test_close_period_open_journal(self): + context = {} + journal_id = self.ref('account.sales_journal') + period_id = self.ref('account.period_1') + close_period(self, period_id, context) + journal_period_id = create_journal_period(self, + period_id, + journal_id, + context) + journal_period_draft(self, journal_period_id, context) + self.registry('account.move')\ + .create(self.cr, + self.uid, + get_simple_account_move_values(self, + period_id, + journal_id), + context=context) + # Here, no exception should be raised because the journal's state is + # draft although the period is closed + + def test_open_period_close_journal(self): + context = {} + journal_id = self.ref('account.sales_journal') + period_id = self.ref('account.period_1') + journal_period_id = create_journal_period(self, + period_id, + journal_id, + context) + journal_period_done(self, journal_period_id, context) + move_values = get_simple_account_move_values(self, + period_id, + journal_id) + # I check if the exception is correctly raised at create of an account + # move which is linked with a closed journal + self.assertRaises(orm.except_orm, + self.registry('account.move').create, + self.cr, self.uid, move_values, context=context) + + def test_change_journal_on_move(self): + context = {} + journal_id = self.ref('account.sales_journal') + journal_cash_id = self.ref('account.cash_journal') + period_id = self.ref('account.period_1') + journal_period_id = create_journal_period(self, + period_id, + journal_id, + context) + journal_period_done(self, journal_period_id, context) + move_values = get_simple_account_move_values(self, + period_id, + journal_cash_id) + self.registry('account.move').create(self.cr, + self.uid, + move_values, + context=context) + # Standard of Odoo doesn't check account_journal_period at write on + # account_move + # issue on Odoo github : #1633 + + # I check if the exception is correctly raised + """self.assertRaises(orm.except_orm, + self.registry('account.move').write, + self.cr, self.uid, [move_id], + {'journal_id': journal_id}, context=context)""" + + def test_draft_move_close_journal(self): + context = {} + + jour_per_obj = self.registry('account.journal.period') + journal_id = self.ref('account.sales_journal') + period_id = self.ref('account.period_1') + move_values = get_simple_account_move_values(self, + period_id, + journal_id) + self.registry('account.move').create(self.cr, + self.uid, + move_values, + context=context) + journal_period_ids =\ + jour_per_obj.search(self.cr, + self.uid, + [('period_id', '=', period_id), + ('journal_id', '=', journal_id), + ], + context=context) + # I check if the exception is correctly raised at closing journal that + # contains some draft account move + self.assertRaises(orm.except_orm, + jour_per_obj.action_done, + self.cr, self.uid, journal_period_ids, + context=context) diff --git a/account_journal_period_close/view/account_view.xml b/account_journal_period_close/view/account_view.xml new file mode 100644 index 000000000..199ed0f4f --- /dev/null +++ b/account_journal_period_close/view/account_view.xml @@ -0,0 +1,33 @@ + + + + + account.period.form + (account_journal_period_close) + account.period + + + + + + + + + + +