diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 43aaa2f58c1..a380a69dc03 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -99,7 +99,6 @@ for a particular financial year and for preparation of vouchers there is a modul 'project/wizard/project_account_analytic_line_view.xml', 'account_end_fy.xml', 'account_invoice_view.xml', - 'partner_view.xml', 'data/account_data.xml', 'data/data_account_type.xml', 'data/configurable_account_chart.xml', @@ -112,6 +111,7 @@ for a particular financial year and for preparation of vouchers there is a modul 'project/wizard/account_analytic_journal_report_view.xml', 'project/wizard/account_analytic_cost_ledger_for_journal_report_view.xml', 'project/wizard/account_analytic_chart_view.xml', + 'partner_view.xml', 'product_view.xml', 'account_assert_test.xml', 'process/statement_process.xml', diff --git a/addons/account/account.py b/addons/account/account.py index 3959799f1bb..33b52b643ed 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -648,10 +648,10 @@ class account_account(osv.osv): if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]): #Check for 'Closed' type if old_type == 'closed' and new_type !='closed': - raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type as it contains journal items!")) + raise osv.except_osv(_('Warning!'), _("You cannot change the type of account from 'Closed' to any other type as it contains journal items!")) # Forbid to change an account type for restricted_groups as it contains journal items (or if one of its children does) if (new_type in restricted_groups): - raise osv.except_osv(_('Warning !'), _("You cannot change the type of account to '%s' type as it contains journal items!") % (new_type,)) + raise osv.except_osv(_('Warning!'), _("You cannot change the type of account to '%s' type as it contains journal items!") % (new_type,)) return True @@ -719,7 +719,7 @@ class account_journal(osv.osv): 'user_id': fields.many2one('res.users', 'User', help="The user responsible for this journal"), 'groups_id': fields.many2many('res.groups', 'account_journal_group_rel', 'journal_id', 'group_id', 'Groups'), 'currency': fields.many2one('res.currency', 'Currency', help='The currency used to enter statement'), - 'entry_posted': fields.boolean('Skip \'Draft\' State for Manual Entries', help='Check this box if you don\'t want new journal entries to pass through the \'draft\' state and instead goes directly to the \'posted state\' without any manual validation. \nNote that journal entries that are automatically created by the system are always skipping that state.'), + 'entry_posted': fields.boolean('Autopost Created Moves', help='Check this box to automatically post entries of this journal. Note that legally, some entries may be automatically posted when the source document is validated (Invoices), whatever the status of this field.'), 'company_id': fields.many2one('res.company', 'Company', required=True, select=1, help="Company related to this journal"), 'allow_date':fields.boolean('Check Date in Period', help= 'If set to True then do not accept the entry if the entry date is not into the period dates'), @@ -1015,14 +1015,14 @@ class account_period(osv.osv): if not result: result = self.search(cr, uid, args, context=context) if not result: - raise osv.except_osv(_('Error !'), _('There is no period defined for this date: %s.\nPlease create one.')%dt) + raise osv.except_osv(_('Error!'), _('There is no period defined for this date: %s.\nPlease create one.')%dt) return result def action_draft(self, cr, uid, ids, *args): mode = 'draft' for period in self.browse(cr, uid, ids): if period.fiscalyear_id.state == 'done': - raise osv.except_osv(_('Warning !'), _('You can not re-open a period which belongs to closed fiscal year')) + raise osv.except_osv(_('Warning!'), _('You can not re-open a period which belongs to closed fiscal year')) cr.execute('update account_journal_period set state=%s where period_id in %s', (mode, tuple(ids),)) cr.execute('update account_period set state=%s where id in %s', (mode, tuple(ids),)) return True @@ -1034,9 +1034,15 @@ class account_period(osv.osv): context = {} ids = [] if name: - ids = self.search(cr, user, [('code','ilike',name)]+ args, limit=limit) + ids = self.search(cr, user, + [('code', 'ilike', name)] + args, + limit=limit, + context=context) if not ids: - ids = self.search(cr, user, [('name',operator,name)]+ args, limit=limit) + ids = self.search(cr, user, + [('name', operator, name)] + args, + limit=limit, + context=context) return self.name_get(cr, user, ids, context=context) def write(self, cr, uid, ids, vals, context=None): @@ -1059,10 +1065,14 @@ class account_period(osv.osv): raise osv.except_osv(_('Error!'), _('You should choose the periods that belong to the same company.')) if period_date_start > period_date_stop: raise osv.except_osv(_('Error!'), _('Start period should precede then end period.')) + + # /!\ We do not include a criterion on the company_id field below, to allow producing consolidated reports + # on multiple companies. It will only work when start/end periods are selected and no fiscal year is chosen. + #for period from = january, we want to exclude the opening period (but it has same date_from, so we have to check if period_from is special or not to include that clause or not in the search). if period_from.special: - return self.search(cr, uid, [('date_start', '>=', period_date_start), ('date_stop', '<=', period_date_stop), ('company_id', '=', company1_id)]) - return self.search(cr, uid, [('date_start', '>=', period_date_start), ('date_stop', '<=', period_date_stop), ('company_id', '=', company1_id), ('special', '=', False)]) + return self.search(cr, uid, [('date_start', '>=', period_date_start), ('date_stop', '<=', period_date_stop)]) + return self.search(cr, uid, [('date_start', '>=', period_date_start), ('date_stop', '<=', period_date_stop), ('special', '=', False)]) class account_journal_period(osv.osv): @@ -1670,7 +1680,7 @@ class account_move_reconcile(osv.osv): elif reconcile.line_partial_ids: first_partner = reconcile.line_partial_ids[0].partner_id.id move_lines = reconcile.line_partial_ids - if any([line.partner_id.id != first_partner for line in move_lines]): + if any([(line.account_id.type in ('receivable', 'payable') and line.partner_id.id != first_partner) for line in move_lines]): return False return True @@ -1854,6 +1864,12 @@ class account_tax_code(osv.osv): _order = 'code' +def get_precision_tax(): + def change_digit_tax(cr): + res = openerp.registry(cr.dbname)['decimal.precision'].precision_get(cr, SUPERUSER_ID, 'Account') + return (16, res+3) + return change_digit_tax + class account_tax(osv.osv): """ A tax object. @@ -1874,12 +1890,6 @@ class account_tax(osv.osv): default.update({'name': name + _(' (Copy)')}) return super(account_tax, self).copy_data(cr, uid, id, default=default, context=context) - def get_precision_tax(): - def change_digit_tax(cr): - res = openerp.registry(cr.dbname)['decimal.precision'].precision_get(cr, SUPERUSER_ID, 'Account') - return (16, res+2) - return change_digit_tax - _name = 'account.tax' _description = 'Tax' _columns = { @@ -2307,7 +2317,7 @@ class account_model(osv.osv): try: entry['name'] = model.name%{'year': move_date.strftime('%Y'), 'month': move_date.strftime('%m'), 'date': move_date.strftime('%Y-%m')} except: - raise osv.except_osv(_('Wrong model !'), _('You have a wrong expression "%(...)s" in your model !')) + raise osv.except_osv(_('Wrong Model!'), _('You have a wrong expression "%(...)s" in your model!')) move_id = account_move_obj.create(cr, uid, { 'ref': entry['name'], 'period_id': period_id, @@ -2319,7 +2329,7 @@ class account_model(osv.osv): analytic_account_id = False if line.analytic_account_id: if not model.journal_id.analytic_journal_id: - raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (model.journal_id.name,)) + raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (model.journal_id.name,)) analytic_account_id = line.analytic_account_id.id val = { 'move_id': move_id, @@ -2795,7 +2805,7 @@ class account_tax_template(osv.osv): 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True), 'name': fields.char('Tax Name', size=64, required=True), 'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the taxes lines from lower sequences to higher ones. The order is important if you have a tax that has several tax children. In this case, the evaluation order is important."), - 'amount': fields.float('Amount', required=True, digits=(14,4), help="For Tax Type percent enter % ratio between 0-1."), + 'amount': fields.float('Amount', required=True, digits_compute=get_precision_tax(), help="For Tax Type percent enter % ratio between 0-1."), 'type': fields.selection( [('percent','Percent'), ('fixed','Fixed'), ('none','None'), ('code','Python Code'), ('balance','Balance')], 'Tax Type', required=True), 'applicable_type': fields.selection( [('true','True'), ('code','Python Code')], 'Applicable Type', required=True, help="If not applicable (computed through a Python code), the tax won't appear on the invoice."), 'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."), diff --git a/addons/account/account_bank.py b/addons/account/account_bank.py index 44411cd637a..acb0e640a7a 100644 --- a/addons/account/account_bank.py +++ b/addons/account/account_bank.py @@ -65,12 +65,11 @@ class bank(osv.osv): # Find the code and parent of the bank account to create dig = 6 current_num = 1 - ids = obj_acc.search(cr, uid, [('type','=','liquidity'), ('company_id', '=', bank.company_id.id)], context=context) + ids = obj_acc.search(cr, uid, [('type','=','liquidity'), ('company_id', '=', bank.company_id.id), ('parent_id', '!=', False)], context=context) # No liquidity account exists, no template available if not ids: continue - ref_acc_bank_temp = obj_acc.browse(cr, uid, ids[0], context=context) - ref_acc_bank = ref_acc_bank_temp.parent_id + ref_acc_bank = obj_acc.browse(cr, uid, ids[0], context=context).parent_id while True: new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)), '0')) + str(current_num) ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', bank.company_id.id)]) @@ -82,7 +81,7 @@ class bank(osv.osv): 'name': name, 'code': new_code, 'type': 'liquidity', - 'user_type': ref_acc_bank_temp.user_type.id, + 'user_type': ref_acc_bank.user_type.id, 'reconcile': False, 'parent_id': ref_acc_bank.id, 'company_id': bank.company_id.id, diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 023765d73f0..8a15321b9c6 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -420,7 +420,7 @@ class account_bank_statement(osv.osv): for st_line in st.line_ids: if st_line.analytic_account_id: if not st.journal_id.analytic_journal_id: - raise osv.except_osv(_('No Analytic Journal !'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,)) + raise osv.except_osv(_('No Analytic Journal!'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,)) if not st_line.amount: continue st_line_number = self.get_next_st_line_number(cr, uid, st_number, st_line, context) diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py index 40f0ca80738..8e3e250d41c 100644 --- a/addons/account/account_cash_statement.py +++ b/addons/account/account_cash_statement.py @@ -252,7 +252,7 @@ class account_cash_statement(osv.osv): for statement in statement_pool.browse(cr, uid, ids, context=context): vals = {} if not self._user_allow(cr, uid, statement.id, context=context): - raise osv.except_osv(_('Error!'), (_('You do not have rights to open this %s journal !') % (statement.journal_id.name, ))) + raise osv.except_osv(_('Error!'), (_('You do not have rights to open this %s journal!') % (statement.journal_id.name, ))) if statement.name and statement.name == '/': c = {'fiscalyear_id': statement.period_id.fiscalyear_id.id} diff --git a/addons/account/account_financial_report_data.xml b/addons/account/account_financial_report_data.xml index 6410a5e887c..e8ff33151c3 100644 --- a/addons/account/account_financial_report_data.xml +++ b/addons/account/account_financial_report_data.xml @@ -6,16 +6,19 @@ --> Profit and Loss + sum Income + detail_with_hierarchy account_type Expense + detail_with_hierarchy account_type diff --git a/addons/account/account_installer.xml b/addons/account/account_installer.xml index 58e824a6250..b03babc63ac 100644 --- a/addons/account/account_installer.xml +++ b/addons/account/account_installer.xml @@ -20,10 +20,11 @@

+ - + diff --git a/addons/account_followup/i18n/ru.po b/addons/account_followup/i18n/ru.po index f6cb2cf0412..b57c8e4315e 100644 --- a/addons/account_followup/i18n/ru.po +++ b/addons/account_followup/i18n/ru.po @@ -7,14 +7,14 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0dev\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2011-11-11 15:21+0000\n" -"Last-Translator: Fabien (Open ERP) \n" +"PO-Revision-Date: 2013-05-31 10:28+0000\n" +"Last-Translator: Chertykov Denis \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-03-16 05:11+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-06-01 05:16+0000\n" +"X-Generator: Launchpad (build 16660)\n" #. module: account_followup #: model:email.template,subject:account_followup.email_template_account_followup_default @@ -22,7 +22,7 @@ msgstr "" #: model:email.template,subject:account_followup.email_template_account_followup_level1 #: model:email.template,subject:account_followup.email_template_account_followup_level2 msgid "${user.company_id.name} Payment Reminder" -msgstr "" +msgstr "${user.company_id.name} напоминание о платеже" #. module: account_followup #: help:res.partner,latest_followup_level_id:0 @@ -43,12 +43,12 @@ msgstr "Дальнейшие действия" #. module: account_followup #: view:account_followup.followup.line:0 msgid "%(date)s" -msgstr "" +msgstr "%(date)s" #. module: account_followup #: field:res.partner,payment_next_action_date:0 msgid "Next Action Date" -msgstr "" +msgstr "Дата следующего действия" #. module: account_followup #: view:account_followup.followup.line:0 @@ -64,7 +64,7 @@ msgstr "" #. module: account_followup #: view:res.partner:0 msgid "⇾ Mark as Done" -msgstr "" +msgstr "⇾ отметить как сделанное" #. module: account_followup #: field:account_followup.followup.line,manual_action_note:0 @@ -94,7 +94,7 @@ msgstr "Тема эл.письма" #. module: account_followup #: view:account_followup.followup.line:0 msgid "%(user_signature)s" -msgstr "" +msgstr "%(user_signature)s" #. module: account_followup #: view:account_followup.followup.line:0 @@ -109,19 +109,19 @@ msgstr "" #. module: account_followup #: field:account_followup.print,email_body:0 msgid "Email Body" -msgstr "" +msgstr "Тело эл. письма" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_account_followup_print msgid "Send Follow-Ups" -msgstr "" +msgstr "Послать напоминания" #. module: account_followup #: report:account_followup.followup.print:0 #: code:addons/account_followup/account_followup.py:263 #, python-format msgid "Amount" -msgstr "" +msgstr "Сумма" #. module: account_followup #: help:res.partner,payment_next_action:0 @@ -133,7 +133,7 @@ msgstr "" #. module: account_followup #: view:res.partner:0 msgid "No Responsible" -msgstr "" +msgstr "Нет ответственного" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line2 @@ -209,17 +209,17 @@ msgstr "Всего по дебету" #. module: account_followup #: field:res.partner,payment_next_action:0 msgid "Next Action" -msgstr "" +msgstr "Следующее действие" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": Partner Name" -msgstr "" +msgstr ": Название партнера" #. module: account_followup #: field:account_followup.followup.line,manual_action_responsible_id:0 msgid "Assign a Responsible" -msgstr "" +msgstr "Назначить ответственного" #. module: account_followup #: view:account_followup.followup:0 @@ -305,7 +305,7 @@ msgstr "" #. module: account_followup #: view:account_followup.followup.line:0 msgid "%(partner_name)s" -msgstr "" +msgstr "%(partner_name)s" #. module: account_followup #: model:email.template,body_html:account_followup.email_template_account_followup_level1 @@ -377,7 +377,7 @@ msgstr "Определяет порядок вывода списка напом #: code:addons/account_followup/wizard/account_followup_print.py:166 #, python-format msgid " will be sent" -msgstr "" +msgstr " будет отправлен" #. module: account_followup #: view:account_followup.followup.line:0 @@ -388,7 +388,7 @@ msgstr "" #: view:account_followup.followup.line:0 #: field:account_followup.followup.line,send_letter:0 msgid "Send a Letter" -msgstr "" +msgstr "Отправить письмо" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_account_followup_definition_form @@ -466,7 +466,7 @@ msgstr "Напечатанное сообщение" #: code:addons/account_followup/wizard/account_followup_print.py:155 #, python-format msgid "Anybody" -msgstr "" +msgstr "Кто угодно" #. module: account_followup #: help:account_followup.followup.line,send_email:0 @@ -528,7 +528,7 @@ msgstr "" #. module: account_followup #: view:res.partner:0 msgid "Search Partner" -msgstr "" +msgstr "Поиск партнера" #. module: account_followup #: model:ir.ui.menu,name:account_followup.account_followup_print_menu @@ -554,7 +554,7 @@ msgstr "" #. module: account_followup #: view:account_followup.print:0 msgid "or" -msgstr "" +msgstr "или" #. module: account_followup #: view:res.partner:0 diff --git a/addons/account_followup/report/account_followup_report.xml b/addons/account_followup/report/account_followup_report.xml index 6fee6a77ac1..b7c38e89f5e 100644 --- a/addons/account_followup/report/account_followup_report.xml +++ b/addons/account_followup/report/account_followup_report.xml @@ -6,7 +6,7 @@ account_followup.stat.tree account_followup.stat - + diff --git a/addons/account_followup/security/account_followup_security.xml b/addons/account_followup/security/account_followup_security.xml index 1586403d701..69c9a44a1b9 100644 --- a/addons/account_followup/security/account_followup_security.xml +++ b/addons/account_followup/security/account_followup_security.xml @@ -4,7 +4,7 @@ Account Follow-up multi company rule - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] diff --git a/addons/account_followup/security/ir.model.access.csv b/addons/account_followup/security/ir.model.access.csv index 8774015efc6..591cc347563 100644 --- a/addons/account_followup/security/ir.model.access.csv +++ b/addons/account_followup/security/ir.model.access.csv @@ -3,5 +3,5 @@ access_account_followup_followup_line,account_followup.followup.line,model_accou access_account_followup_followup_line_manager,account_followup.followup.line.manager,model_account_followup_followup_line,account.group_account_manager,1,1,1,1 access_account_followup_followup_accountant,account_followup.followup user,model_account_followup_followup,account.group_account_invoice,1,0,0,0 access_account_followup_followup_manager,account_followup.followup.manager,model_account_followup_followup,account.group_account_manager,1,1,1,1 -access_account_followup_stat_invoice,account_followup.stat.invoice,model_account_followup_stat,account.group_account_invoice,1,1,1,1 -access_account_followup_stat_by_partner_manager,account_followup.stat.by.partner,model_account_followup_stat_by_partner,account.group_account_user,1,1,1,1 +access_account_followup_stat_invoice,account_followup.stat.invoice,model_account_followup_stat,account.group_account_invoice,1,1,0,0 +access_account_followup_stat_by_partner_manager,account_followup.stat.by.partner,model_account_followup_stat_by_partner,account.group_account_user,1,1,0,0 diff --git a/addons/account_payment/security/account_payment_security.xml b/addons/account_payment/security/account_payment_security.xml index 4bca00eaa6d..fbe29699e86 100644 --- a/addons/account_payment/security/account_payment_security.xml +++ b/addons/account_payment/security/account_payment_security.xml @@ -15,21 +15,21 @@ Payment Mode company rule - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] Payment order multi company rule - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] Payment line multi company rule - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] diff --git a/addons/account_payment/wizard/account_payment_order.py b/addons/account_payment/wizard/account_payment_order.py index 08d36c45eff..de9c47ec005 100644 --- a/addons/account_payment/wizard/account_payment_order.py +++ b/addons/account_payment/wizard/account_payment_order.py @@ -23,6 +23,7 @@ import time from lxml import etree from openerp.osv import fields, osv +from openerp.tools.translate import _ class payment_order_create(osv.osv_memory): """ @@ -87,6 +88,7 @@ class payment_order_create(osv.osv_memory): 'order_id': payment.id, 'partner_id': line.partner_id and line.partner_id.id or False, 'communication': line.ref or '/', + 'state': line.invoice and line.invoice.reference_type != 'none' and 'structured' or 'normal', 'date': date_to_pay, 'currency': (line.invoice and line.invoice.currency_id.id) or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id, }, context=context) @@ -108,7 +110,7 @@ class payment_order_create(osv.osv_memory): context.update({'line_ids': line_ids}) model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_create_payment_order_lines')], context=context) resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] - return {'name': ('Entrie Lines'), + return {'name': _('Entry Lines'), 'context': context, 'view_type': 'form', 'view_mode': 'form', diff --git a/addons/account_test/account_test.py b/addons/account_test/account_test.py index 98e27380837..cc60108bf20 100644 --- a/addons/account_test/account_test.py +++ b/addons/account_test/account_test.py @@ -24,7 +24,7 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ############################################################################## diff --git a/addons/account_test/i18n/ru.po b/addons/account_test/i18n/ru.po new file mode 100644 index 00000000000..d36d83d2e99 --- /dev/null +++ b/addons/account_test/i18n/ru.po @@ -0,0 +1,241 @@ +# Russian translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-06-05 07:09+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Russian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-06-06 05:21+0000\n" +"X-Generator: Launchpad (build 16667)\n" + +#. module: account_test +#: view:accounting.assert.test:0 +msgid "" +"Code should always set a variable named `result` with the result of your " +"test, that can be a list or\n" +"a dictionary. If `result` is an empty list, it means that the test was " +"succesful. Otherwise it will\n" +"try to translate and print what is inside `result`.\n" +"\n" +"If the result of your test is a dictionary, you can set a variable named " +"`column_order` to choose in\n" +"what order you want to print `result`'s content.\n" +"\n" +"Should you need them, you can also use the following variables into your " +"code:\n" +" * cr: cursor to the database\n" +" * uid: ID of the current user\n" +"\n" +"In any ways, the code must be legal python statements with correct " +"indentation (if needed).\n" +"\n" +"Example: \n" +" sql = '''SELECT id, name, ref, date\n" +" FROM account_move_line \n" +" WHERE account_id IN (SELECT id FROM account_account WHERE type " +"= 'view')\n" +" '''\n" +" cr.execute(sql)\n" +" result = cr.dictfetchall()" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_02 +msgid "Test 2: Opening a fiscal year" +msgstr "Проверка 2: Открытие фискального года" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_05 +msgid "" +"Check that reconciled invoice for Sales/Purchases has reconciled entries for " +"Payable and Receivable Accounts" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_03 +msgid "" +"Check if movement lines are balanced and have the same date and period" +msgstr "" + +#. module: account_test +#: field:accounting.assert.test,name:0 +msgid "Test Name" +msgstr "" + +#. module: account_test +#: report:account.test.assert.print:0 +msgid "Accouting tests on" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_01 +msgid "Test 1: General balance" +msgstr "Проверка 1: Общий баланс" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_06 +msgid "Check that paid/reconciled invoices are not in 'Open' state" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_05_2 +msgid "" +"Check that reconciled account moves, that define Payable and Receivable " +"accounts, are belonging to reconciled invoices" +msgstr "" + +#. module: account_test +#: view:accounting.assert.test:0 +msgid "Tests" +msgstr "Проверки" + +#. module: account_test +#: field:accounting.assert.test,desc:0 +msgid "Test Description" +msgstr "Описание проверки" + +#. module: account_test +#: view:accounting.assert.test:0 +msgid "Description" +msgstr "Описание" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_06_1 +msgid "Check that there's no move for any account with « View » account type" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_08 +msgid "Test 9 : Accounts and partners on account moves" +msgstr "" + +#. module: account_test +#: model:ir.actions.act_window,name:account_test.action_accounting_assert +#: model:ir.actions.report.xml,name:account_test.account_assert_test_report +#: model:ir.ui.menu,name:account_test.menu_action_license +msgid "Accounting Tests" +msgstr "" + +#. module: account_test +#: code:addons/account_test/report/account_test_report.py:74 +#, python-format +msgid "The test was passed successfully" +msgstr "Проверка прошла успешно" + +#. module: account_test +#: field:accounting.assert.test,active:0 +msgid "Active" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_06 +msgid "Test 6 : Invoices status" +msgstr "" + +#. module: account_test +#: model:ir.model,name:account_test.model_accounting_assert_test +msgid "accounting.assert.test" +msgstr "accounting.assert.test" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_05 +msgid "" +"Test 5.1 : Payable and Receivable accountant lines of reconciled invoices" +msgstr "" + +#. module: account_test +#: field:accounting.assert.test,code_exec:0 +msgid "Python code" +msgstr "Код на Python" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_07 +msgid "" +"Check on bank statement that the Closing Balance = Starting Balance + sum of " +"statement lines" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_07 +msgid "Test 8 : Closing balance on bank statements" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_03 +msgid "Test 3: Movement lines" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_05_2 +msgid "Test 5.2 : Reconcilied invoices and Payable/Receivable accounts" +msgstr "" + +#. module: account_test +#: view:accounting.assert.test:0 +msgid "Expression" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_04 +msgid "Test 4: Totally reconciled mouvements" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_04 +msgid "Check if the totally reconciled movements are balanced" +msgstr "" + +#. module: account_test +#: field:accounting.assert.test,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_02 +msgid "" +"Check if the balance of the new opened fiscal year matches with last year's " +"balance" +msgstr "" + +#. module: account_test +#: view:accounting.assert.test:0 +msgid "Python Code" +msgstr "Код на Python" + +#. module: account_test +#: model:ir.actions.act_window,help:account_test.action_accounting_assert +msgid "" +"

\n" +" Click to create Accounting Test.\n" +"

\n" +" " +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_01 +msgid "Check the balance: Debit sum = Credit sum" +msgstr "Проверяет баланс: сумма дебита = сумма кредита" + +#. module: account_test +#: model:accounting.assert.test,desc:account_test.account_test_08 +msgid "Check that general accounts and partners on account moves are active" +msgstr "" + +#. module: account_test +#: model:accounting.assert.test,name:account_test.account_test_06_1 +msgid "Test 7: « View  » account type" +msgstr "" + +#. module: account_test +#: view:accounting.assert.test:0 +msgid "Code Help" +msgstr "" diff --git a/addons/account_voucher/__openerp__.py b/addons/account_voucher/__openerp__.py index 345c3378aa0..a043b15a518 100644 --- a/addons/account_voucher/__openerp__.py +++ b/addons/account_voucher/__openerp__.py @@ -67,6 +67,7 @@ This module manages: 'test/sales_payment.yml', 'test/account_voucher_report.yml', 'test/case1_usd_usd.yml', + 'test/case1_usd_usd_payment_rate.yml', 'test/case2_usd_eur_debtor_in_eur.yml', 'test/case2_usd_eur_debtor_in_usd.yml', 'test/case3_eur_eur.yml', diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index b176c3b8fd9..81eb76ff3a8 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -26,6 +26,19 @@ from openerp.osv import fields, osv import openerp.addons.decimal_precision as dp from openerp.tools.translate import _ from openerp.tools import float_compare +from openerp.report import report_sxw + +class res_currency(osv.osv): + _inherit = "res.currency" + + def _get_current_rate(self, cr, uid, ids, name, arg, context=None): + if context is None: + context = {} + res = super(res_currency, self)._get_current_rate(cr, uid, ids, name, arg, context=context) + if context.get('voucher_special_currency') in ids and context.get('voucher_special_currency_rate'): + res[context.get('voucher_special_currency')] = context.get('voucher_special_currency_rate') + return res + class res_company(osv.osv): _inherit = "res.company" @@ -153,7 +166,7 @@ class account_voucher(osv.osv): journal = journal_pool.browse(cr, uid, journal_id, context=context) if journal.currency: return journal.currency.id - return False + return self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id def _get_partner(self, cr, uid, context=None): if context is None: context = {} @@ -222,26 +235,26 @@ class account_voucher(osv.osv): def onchange_line_ids(self, cr, uid, ids, line_dr_ids, line_cr_ids, amount, voucher_currency, type, context=None): context = context or {} if not line_dr_ids and not line_cr_ids: - return {'value':{}} + return {'value':{'writeoff_amount': 0.0}} line_osv = self.pool.get("account.voucher.line") line_dr_ids = resolve_o2m_operations(cr, uid, line_osv, line_dr_ids, ['amount'], context) line_cr_ids = resolve_o2m_operations(cr, uid, line_osv, line_cr_ids, ['amount'], context) - #compute the field is_multi_currency that is used to hide/display options linked to secondary currency on the voucher is_multi_currency = False - if voucher_currency: - # if the voucher currency is not False, it means it is different than the company currency and we need to display the options - is_multi_currency = True - else: - #loop on the voucher lines to see if one of these has a secondary currency. If yes, we need to define the options - for voucher_line in line_dr_ids+line_cr_ids: - company_currency = False - company_currency = voucher_line.get('move_line_id', False) and self.pool.get('account.move.line').browse(cr, uid, voucher_line.get('move_line_id'), context=context).company_id.currency_id.id - if voucher_line.get('currency_id', company_currency) != company_currency: - is_multi_currency = True - break + #loop on the voucher lines to see if one of these has a secondary currency. If yes, we need to see the options + for voucher_line in line_dr_ids+line_cr_ids: + line_id = voucher_line.get('id') and self.pool.get('account.voucher.line').browse(cr, uid, voucher_line['id'], context=context).move_line_id.id or voucher_line.get('move_line_id') + if line_id and self.pool.get('account.move.line').browse(cr, uid, line_id, context=context).currency_id: + is_multi_currency = True + break return {'value': {'writeoff_amount': self._compute_writeoff_amount(cr, uid, line_dr_ids, line_cr_ids, amount, type), 'is_multi_currency': is_multi_currency}} + def _get_journal_currency(self, cr, uid, ids, name, args, context=None): + res = {} + for voucher in self.browse(cr, uid, ids, context=context): + res[voucher.id] = voucher.journal_id.currency and voucher.journal_id.currency.id or voucher.company_id.currency_id.id + return res + def _get_writeoff_amount(self, cr, uid, ids, name, args, context=None): if not ids: return {} currency_obj = self.pool.get('res.currency') @@ -258,20 +271,48 @@ class account_voucher(osv.osv): return res def _paid_amount_in_company_currency(self, cr, uid, ids, name, args, context=None): - if not ids: return {} + if context is None: + context = {} + res = {} + ctx = context.copy() + for v in self.browse(cr, uid, ids, context=context): + ctx.update({'date': v.date}) + #make a new call to browse in order to have the right date in the context, to get the right currency rate + voucher = self.browse(cr, uid, v.id, context=ctx) + ctx.update({ + 'voucher_special_currency': voucher.payment_rate_currency_id and voucher.payment_rate_currency_id.id or False, + 'voucher_special_currency_rate': voucher.currency_id.rate * voucher.payment_rate,}) + res[voucher.id] = self.pool.get('res.currency').compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, voucher.amount, context=ctx) + return res + + def _get_currency_help_label(self, cr, uid, currency_id, payment_rate, payment_rate_currency_id, context=None): + """ + This function builds a string to help the users to understand the behavior of the payment rate fields they can specify on the voucher. + This string is only used to improve the usability in the voucher form view and has no other effect. + + :param currency_id: the voucher currency + :type currency_id: integer + :param payment_rate: the value of the payment_rate field of the voucher + :type payment_rate: float + :param payment_rate_currency_id: the value of the payment_rate_currency_id field of the voucher + :type payment_rate_currency_id: integer + :return: translated string giving a tip on what's the effect of the current payment rate specified + :rtype: str + """ + rml_parser = report_sxw.rml_parse(cr, uid, 'currency_help_label', context=context) + currency_pool = self.pool.get('res.currency') + currency_str = payment_rate_str = '' + if currency_id: + currency_str = rml_parser.formatLang(1, currency_obj=currency_pool.browse(cr, uid, currency_id, context=context)) + if payment_rate_currency_id: + payment_rate_str = rml_parser.formatLang(payment_rate, currency_obj=currency_pool.browse(cr, uid, payment_rate_currency_id, context=context)) + currency_help_label = _('At the operation date, the exchange rate was\n%s = %s') % (currency_str, payment_rate_str) + return currency_help_label + + def _fnct_currency_help_label(self, cr, uid, ids, name, args, context=None): res = {} - rate = 1.0 for voucher in self.browse(cr, uid, ids, context=context): - if voucher.currency_id: - if voucher.company_id.currency_id.id == voucher.payment_rate_currency_id.id: - rate = 1 / voucher.payment_rate - else: - ctx = context.copy() - ctx.update({'date': voucher.date}) - voucher_rate = self.browse(cr, uid, voucher.id, context=ctx).currency_id.rate - company_currency_rate = voucher.company_id.currency_id.rate - rate = voucher_rate * company_currency_rate - res[voucher.id] = voucher.amount / rate + res[voucher.id] = self._get_currency_help_label(cr, uid, voucher.currency_id.id, voucher.payment_rate, voucher.payment_rate_currency_id.id, context=context) return res _name = 'account.voucher' @@ -304,8 +345,7 @@ class account_voucher(osv.osv): domain=[('type','=','dr')], context={'default_type':'dr'}, readonly=True, states={'draft':[('readonly',False)]}), 'period_id': fields.many2one('account.period', 'Period', required=True, readonly=True, states={'draft':[('readonly',False)]}), 'narration':fields.text('Notes', readonly=True, states={'draft':[('readonly',False)]}), -# 'currency_id':fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}), - 'currency_id': fields.related('journal_id','currency', type='many2one', relation='res.currency', string='Currency', readonly=True), + 'currency_id': fields.function(_get_journal_currency, type='many2one', relation='res.currency', string='Currency', readonly=True, required=True), 'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, states={'draft':[('readonly',False)]}), 'state':fields.selection( [('draft','Draft'), @@ -346,6 +386,7 @@ class account_voucher(osv.osv): help='The specific rate that will be used, in this voucher, between the selected currency (in \'Payment Rate Currency\' field) and the voucher currency.'), 'paid_amount_in_company_currency': fields.function(_paid_amount_in_company_currency, string='Paid Amount in Company Currency', type='float', readonly=True), 'is_multi_currency': fields.boolean('Multi Currency Voucher', help='Fields with internal purpose only that depicts if the voucher is a multi currency one or not'), + 'currency_help_label': fields.function(_fnct_currency_help_label, type='text', string="Helping Sentence", help="This sentence helps you to know how to specify the payment rate by giving you the direct effect it has"), } _defaults = { 'active': True, @@ -422,6 +463,8 @@ class account_voucher(osv.osv): partner_pool = self.pool.get('res.partner') position_pool = self.pool.get('account.fiscal.position') line_pool = self.pool.get('account.voucher.line') + if not line_ids: + line_ids = [] res = { 'tax_amount': False, 'amount': False, @@ -516,23 +559,26 @@ class account_voucher(osv.osv): return default def onchange_rate(self, cr, uid, ids, rate, amount, currency_id, payment_rate_currency_id, company_id, context=None): - res = {'value': {'paid_amount_in_company_currency': amount}} - company_currency = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id - if rate and amount and currency_id:# and currency_id == payment_rate_currency_id: - voucher_rate = self.pool.get('res.currency').browse(cr, uid, currency_id, context).rate - if company_currency.id == payment_rate_currency_id: - company_rate = rate - else: - company_rate = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id.rate - res['value']['paid_amount_in_company_currency'] = amount / voucher_rate * company_rate + res = {'value': {'paid_amount_in_company_currency': amount, 'currency_help_label': self._get_currency_help_label(cr, uid, currency_id, rate, payment_rate_currency_id, context=context)}} + if rate and amount and currency_id: + company_currency = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id + #context should contain the date, the payment currency and the payment rate specified on the voucher + amount_in_company_currency = self.pool.get('res.currency').compute(cr, uid, currency_id, company_currency.id, amount, context=context) + res['value']['paid_amount_in_company_currency'] = amount_in_company_currency return res def onchange_amount(self, cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date, payment_rate_currency_id, company_id, context=None): if context is None: context = {} - res = self.recompute_voucher_lines(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context=context) ctx = context.copy() ctx.update({'date': date}) + #read the voucher rate with the right date in the context + currency_id = currency_id or self.pool.get('res.company').browse(cr, uid, company_id, context=ctx).currency_id.id + voucher_rate = self.pool.get('res.currency').read(cr, uid, currency_id, ['rate'], context=ctx)['rate'] + ctx.update({ + 'voucher_special_currency': payment_rate_currency_id, + 'voucher_special_currency_rate': rate * voucher_rate}) + res = self.recompute_voucher_lines(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context=ctx) vals = self.onchange_rate(cr, uid, ids, rate, amount, currency_id, payment_rate_currency_id, company_id, context=ctx) for key in vals.keys(): res[key].update(vals[key]) @@ -546,6 +592,7 @@ class account_voucher(osv.osv): journal = self.pool.get('account.journal').browse(cr, uid, journal_id, context=context) company_id = journal.company_id.id payment_rate = 1.0 + currency_id = currency_id or journal.company_id.currency_id.id payment_rate_currency_id = currency_id ctx = context.copy() ctx.update({'date': date}) @@ -561,24 +608,62 @@ class account_voucher(osv.osv): # is not in the voucher currency payment_rate_currency_id = voucher_line['currency_id'] tmp = currency_obj.browse(cr, uid, payment_rate_currency_id, context=ctx).rate - voucher_currency_id = currency_id or journal.company_id.currency_id.id - payment_rate = tmp / currency_obj.browse(cr, uid, voucher_currency_id, context=ctx).rate + payment_rate = tmp / currency_obj.browse(cr, uid, currency_id, context=ctx).rate break + vals['value'].update({ + 'payment_rate': payment_rate, + 'currency_id': currency_id, + 'payment_rate_currency_id': payment_rate_currency_id + }) + #read the voucher rate with the right date in the context + voucher_rate = self.pool.get('res.currency').read(cr, uid, currency_id, ['rate'], context=ctx)['rate'] + ctx.update({ + 'voucher_special_currency_rate': payment_rate * voucher_rate, + 'voucher_special_currency': payment_rate_currency_id}) res = self.onchange_rate(cr, uid, ids, payment_rate, amount, currency_id, payment_rate_currency_id, company_id, context=ctx) for key in res.keys(): vals[key].update(res[key]) - vals['value'].update({'payment_rate': payment_rate}) - if payment_rate_currency_id: - vals['value'].update({'payment_rate_currency_id': payment_rate_currency_id}) return vals + def basic_onchange_partner(self, cr, uid, ids, partner_id, journal_id, ttype, context=None): + partner_pool = self.pool.get('res.partner') + journal_pool = self.pool.get('account.journal') + res = {'value': {'account_id': False}} + if not partner_id or not journal_id: + return res + + journal = journal_pool.browse(cr, uid, journal_id, context=context) + partner = partner_pool.browse(cr, uid, partner_id, context=context) + account_id = False + if journal.type in ('sale','sale_refund'): + account_id = partner.property_account_receivable.id + elif journal.type in ('purchase', 'purchase_refund','expense'): + account_id = partner.property_account_payable.id + else: + account_id = journal.default_credit_account_id.id or journal.default_debit_account_id.id + + res['value']['account_id'] = account_id + return res + def onchange_partner_id(self, cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context=None): if not journal_id: return {} - res = self.recompute_voucher_lines(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context=context) - vals = self.recompute_payment_rate(cr, uid, ids, res, currency_id, date, ttype, journal_id, amount, context=context) + if context is None: + context = {} + #TODO: comment me and use me directly in the sales/purchases views + res = self.basic_onchange_partner(cr, uid, ids, partner_id, journal_id, ttype, context=context) + if ttype in ['sale', 'purchase']: + return res + ctx = context.copy() + # not passing the payment_rate currency and the payment_rate in the context but it's ok because they are reset in recompute_payment_rate + ctx.update({'date': date}) + vals = self.recompute_voucher_lines(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context=ctx) + vals2 = self.recompute_payment_rate(cr, uid, ids, vals, currency_id, date, ttype, journal_id, amount, context=context) for key in vals.keys(): res[key].update(vals[key]) + for key in vals2.keys(): + res[key].update(vals2[key]) + #TODO: can probably be removed now #TODO: onchange_partner_id() should not returns [pre_line, line_dr_ids, payment_rate...] for type sale, and not # [pre_line, line_cr_ids, payment_rate...] for type purchase. # We should definitively split account.voucher object in two and make distinct on_change functions. In the @@ -621,8 +706,6 @@ class account_voucher(osv.osv): if context is None: context = {} context_multi_currency = context.copy() - if date: - context_multi_currency.update({'date': date}) currency_pool = self.pool.get('res.currency') move_line_pool = self.pool.get('account.move.line') @@ -646,18 +729,6 @@ class account_voucher(osv.osv): journal = journal_pool.browse(cr, uid, journal_id, context=context) partner = partner_pool.browse(cr, uid, partner_id, context=context) currency_id = currency_id or journal.company_id.currency_id.id - account_id = False - if journal.type in ('sale','sale_refund'): - account_id = partner.property_account_receivable.id - elif journal.type in ('purchase', 'purchase_refund','expense'): - account_id = partner.property_account_payable.id - else: - account_id = journal.default_credit_account_id.id or journal.default_debit_account_id.id - - default['value']['account_id'] = account_id - - if journal.type not in ('cash', 'bank'): - return default total_credit = 0.0 total_debit = 0.0 @@ -715,12 +786,13 @@ class account_voucher(osv.osv): if _remove_noise_in_o2m(): continue - if line.currency_id and currency_id==line.currency_id.id: + if line.currency_id and currency_id == line.currency_id.id: amount_original = abs(line.amount_currency) amount_unreconciled = abs(line.amount_residual_currency) else: - amount_original = currency_pool.compute(cr, uid, company_currency, currency_id, line.credit or line.debit or 0.0) - amount_unreconciled = currency_pool.compute(cr, uid, company_currency, currency_id, abs(line.amount_residual)) + #always use the amount booked in the company currency as the basis of the conversion into the voucher currency + amount_original = currency_pool.compute(cr, uid, company_currency, currency_id, line.credit or line.debit or 0.0, context=context_multi_currency) + amount_unreconciled = currency_pool.compute(cr, uid, company_currency, currency_id, abs(line.amount_residual), context=context_multi_currency) line_currency_id = line.currency_id and line.currency_id.id or company_currency rs = { 'name':line.move_id.name, @@ -766,10 +838,15 @@ class account_voucher(osv.osv): if context is None: context = {} res = {'value': {}} - #set the default payment rate of the voucher and compute the paid amount in company currency - if currency_id and currency_id == payment_rate_currency_id: + if currency_id: + #set the default payment rate of the voucher and compute the paid amount in company currency ctx = context.copy() ctx.update({'date': date}) + #read the voucher rate with the right date in the context + voucher_rate = self.pool.get('res.currency').read(cr, uid, currency_id, ['rate'], context=ctx)['rate'] + ctx.update({ + 'voucher_special_currency_rate': payment_rate * voucher_rate, + 'voucher_special_currency': payment_rate_currency_id}) vals = self.onchange_rate(cr, uid, ids, payment_rate, amount, currency_id, payment_rate_currency_id, company_id, context=ctx) for key in vals.keys(): res[key].update(vals[key]) @@ -789,7 +866,8 @@ class account_voucher(osv.osv): period_pool = self.pool.get('account.period') currency_obj = self.pool.get('res.currency') ctx = context.copy() - ctx.update({'company_id': company_id}) + ctx.update({'company_id': company_id, 'account_period_prefer_normal': True}) + voucher_currency_id = currency_id or self.pool.get('res.company').browse(cr, uid, company_id, context=ctx).currency_id.id pids = period_pool.find(cr, uid, date, context=ctx) if pids: res['value'].update({'period_id':pids[0]}) @@ -798,9 +876,8 @@ class account_voucher(osv.osv): payment_rate = 1.0 if payment_rate_currency_id != currency_id: tmp = currency_obj.browse(cr, uid, payment_rate_currency_id, context=ctx).rate - voucher_currency_id = currency_id or self.pool.get('res.company').browse(cr, uid, company_id, context=ctx).currency_id.id payment_rate = tmp / currency_obj.browse(cr, uid, voucher_currency_id, context=ctx).rate - vals = self.onchange_payment_rate_currency(cr, uid, ids, currency_id, payment_rate, payment_rate_currency_id, date, amount, company_id, context=context) + vals = self.onchange_payment_rate_currency(cr, uid, ids, voucher_currency_id, payment_rate, payment_rate_currency_id, date, amount, company_id, context=context) vals['value'].update({'payment_rate': payment_rate}) for key in vals.keys(): res[key].update(vals[key]) @@ -823,7 +900,15 @@ class account_voucher(osv.osv): currency_id = False if journal.currency: currency_id = journal.currency.id + else: + currency_id = journal.company_id.currency_id.id vals['value'].update({'currency_id': currency_id}) + #in case we want to register the payment directly from an invoice, it's confusing to allow to switch the journal + #without seeing that the amount is expressed in the journal currency, and not in the invoice currency. So to avoid + #this common mistake, we simply reset the amount to 0 if the currency is not the invoice currency. + if context.get('payment_expected_currency') and currency_id != context.get('payment_expected_currency'): + vals['value']['amount'] = 0 + amount = 0 res = self.onchange_partner_id(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context) for key in res.keys(): vals[key].update(res[key]) @@ -905,8 +990,8 @@ class account_voucher(osv.osv): current_currency = self._get_current_currency(cr, uid, voucher_id, context) if current_currency <> company_currency: context_multi_currency = context.copy() - voucher_brw = self.pool.get('account.voucher').browse(cr, uid, voucher_id, context) - context_multi_currency.update({'date': voucher_brw.date}) + voucher = self.pool.get('account.voucher').browse(cr, uid, voucher_id, context) + context_multi_currency.update({'date': voucher.date}) return context_multi_currency return context @@ -921,33 +1006,33 @@ class account_voucher(osv.osv): :return: mapping between fieldname and value of account move line to create :rtype: dict ''' - voucher_brw = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context) + voucher = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context) debit = credit = 0.0 # TODO: is there any other alternative then the voucher type ?? # ANSWER: We can have payment and receipt "In Advance". # TODO: Make this logic available. # -for sale, purchase we have but for the payment and receipt we do not have as based on the bank/cash journal we can not know its payment or receipt - if voucher_brw.type in ('purchase', 'payment'): - credit = voucher_brw.paid_amount_in_company_currency - elif voucher_brw.type in ('sale', 'receipt'): - debit = voucher_brw.paid_amount_in_company_currency + if voucher.type in ('purchase', 'payment'): + credit = voucher.paid_amount_in_company_currency + elif voucher.type in ('sale', 'receipt'): + debit = voucher.paid_amount_in_company_currency if debit < 0: credit = -debit; debit = 0.0 if credit < 0: debit = -credit; credit = 0.0 sign = debit - credit < 0 and -1 or 1 #set the first line of the voucher move_line = { - 'name': voucher_brw.name or '/', + 'name': voucher.name or '/', 'debit': debit, 'credit': credit, - 'account_id': voucher_brw.account_id.id, + 'account_id': voucher.account_id.id, 'move_id': move_id, - 'journal_id': voucher_brw.journal_id.id, - 'period_id': voucher_brw.period_id.id, - 'partner_id': voucher_brw.partner_id.id, + 'journal_id': voucher.journal_id.id, + 'period_id': voucher.period_id.id, + 'partner_id': voucher.partner_id.id, 'currency_id': company_currency <> current_currency and current_currency or False, - 'amount_currency': company_currency <> current_currency and sign * voucher_brw.amount or 0.0, - 'date': voucher_brw.date, - 'date_maturity': voucher_brw.date_due + 'amount_currency': company_currency <> current_currency and sign * voucher.amount or 0.0, + 'date': voucher.date, + 'date_maturity': voucher.date_due } return move_line @@ -960,31 +1045,31 @@ class account_voucher(osv.osv): :rtype: dict ''' seq_obj = self.pool.get('ir.sequence') - voucher_brw = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context) - if voucher_brw.number: - name = voucher_brw.number - elif voucher_brw.journal_id.sequence_id: - if not voucher_brw.journal_id.sequence_id.active: + voucher = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context) + if voucher.number: + name = voucher.number + elif voucher.journal_id.sequence_id: + if not voucher.journal_id.sequence_id.active: raise osv.except_osv(_('Configuration Error !'), _('Please activate the sequence of selected journal !')) c = dict(context) - c.update({'fiscalyear_id': voucher_brw.period_id.fiscalyear_id.id}) - name = seq_obj.next_by_id(cr, uid, voucher_brw.journal_id.sequence_id.id, context=c) + c.update({'fiscalyear_id': voucher.period_id.fiscalyear_id.id}) + name = seq_obj.next_by_id(cr, uid, voucher.journal_id.sequence_id.id, context=c) else: raise osv.except_osv(_('Error!'), _('Please define a sequence on the journal.')) - if not voucher_brw.reference: + if not voucher.reference: ref = name.replace('/','') else: - ref = voucher_brw.reference + ref = voucher.reference move = { 'name': name, - 'journal_id': voucher_brw.journal_id.id, - 'narration': voucher_brw.narration, - 'date': voucher_brw.date, + 'journal_id': voucher.journal_id.id, + 'narration': voucher.narration, + 'date': voucher.date, 'ref': ref, - 'period_id': voucher_brw.period_id.id, + 'period_id': voucher.period_id.id, } return move @@ -1011,7 +1096,10 @@ class account_voucher(osv.osv): raise osv.except_osv(_('Insufficient Configuration!'),_("You should configure the 'Gain Exchange Rate Account' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates.")) # Even if the amount_currency is never filled, we need to pass the foreign currency because otherwise # the receivable/payable account may have a secondary currency, which render this field mandatory - account_currency_id = company_currency <> current_currency and current_currency or False + if line.account_id.currency_id: + account_currency_id = line.account_id.currency_id.id + else: + account_currency_id = company_currency <> current_currency and current_currency or False move_line = { 'journal_id': line.voucher_id.journal_id.id, 'period_id': line.voucher_id.period_id.id, @@ -1054,16 +1142,11 @@ class account_voucher(osv.osv): :return: the amount in the currency of the voucher's company :rtype: float ''' + if context is None: + context = {} currency_obj = self.pool.get('res.currency') voucher = self.browse(cr, uid, voucher_id, context=context) - res = amount - if voucher.payment_rate_currency_id.id == voucher.company_id.currency_id.id: - # the rate specified on the voucher is for the company currency - res = currency_obj.round(cr, uid, voucher.company_id.currency_id, (amount * voucher.payment_rate)) - else: - # the rate specified on the voucher is not relevant, we use all the rates in the system - res = currency_obj.compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=context) - return res + return currency_obj.compute(cr, uid, voucher.currency_id.id, voucher.company_id.currency_id.id, amount, context=context) def voucher_move_line_create(self, cr, uid, voucher_id, line_total, move_id, company_currency, current_currency, context=None): ''' @@ -1087,39 +1170,45 @@ class account_voucher(osv.osv): tot_line = line_total rec_lst_ids = [] - voucher_brw = self.pool.get('account.voucher').browse(cr, uid, voucher_id, context) + date = self.read(cr, uid, voucher_id, ['date'], context=context)['date'] ctx = context.copy() - ctx.update({'date': voucher_brw.date}) + ctx.update({'date': date}) + voucher = self.pool.get('account.voucher').browse(cr, uid, voucher_id, context=ctx) + voucher_currency = voucher.journal_id.currency or voucher.company_id.currency_id + ctx.update({ + 'voucher_special_currency_rate': voucher_currency.rate * voucher.payment_rate , + 'voucher_special_currency': voucher.payment_rate_currency_id and voucher.payment_rate_currency_id.id or False,}) prec = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') - for line in voucher_brw.line_ids: + for line in voucher.line_ids: #create one move line per voucher line where amount is not 0.0 # AND (second part of the clause) only if the original move line was not having debit = credit = 0 (which is a legal value) if not line.amount and not (line.move_line_id and not float_compare(line.move_line_id.debit, line.move_line_id.credit, precision_rounding=prec) and not float_compare(line.move_line_id.debit, 0.0, precision_rounding=prec)): continue # convert the amount set on the voucher line into the currency of the voucher's company - amount = self._convert_amount(cr, uid, line.untax_amount or line.amount, voucher_brw.id, context=ctx) + # this calls res_curreny.compute() with the right context, so that it will take either the rate on the voucher if it is relevant or will use the default behaviour + amount = self._convert_amount(cr, uid, line.untax_amount or line.amount, voucher.id, context=ctx) # if the amount encoded in voucher is equal to the amount unreconciled, we need to compute the # currency rate difference if line.amount == line.amount_unreconciled: if not line.move_line_id: raise osv.except_osv(_('Wrong voucher line'),_("The invoice you are willing to pay is not valid anymore.")) - sign = voucher_brw.type in ('payment', 'purchase') and -1 or 1 + sign = voucher.type in ('payment', 'purchase') and -1 or 1 currency_rate_difference = sign * (line.move_line_id.amount_residual - amount) else: currency_rate_difference = 0.0 move_line = { - 'journal_id': voucher_brw.journal_id.id, - 'period_id': voucher_brw.period_id.id, + 'journal_id': voucher.journal_id.id, + 'period_id': voucher.period_id.id, 'name': line.name or '/', 'account_id': line.account_id.id, 'move_id': move_id, - 'partner_id': voucher_brw.partner_id.id, + 'partner_id': voucher.partner_id.id, 'currency_id': line.move_line_id and (company_currency <> line.move_line_id.currency_id.id and line.move_line_id.currency_id.id) or False, 'analytic_account_id': line.account_analytic_id and line.account_analytic_id.id or False, 'quantity': 1, 'credit': 0.0, 'debit': 0.0, - 'date': voucher_brw.date + 'date': voucher.date } if amount < 0: amount = -amount @@ -1135,9 +1224,9 @@ class account_voucher(osv.osv): tot_line -= amount move_line['credit'] = amount - if voucher_brw.tax_id and voucher_brw.type in ('sale', 'purchase'): + if voucher.tax_id and voucher.type in ('sale', 'purchase'): move_line.update({ - 'account_tax_id': voucher_brw.tax_id.id, + 'account_tax_id': voucher.tax_id.id, }) if move_line.get('account_tax_id', False): @@ -1149,7 +1238,6 @@ class account_voucher(osv.osv): foreign_currency_diff = 0.0 amount_currency = False if line.move_line_id: - voucher_currency = voucher_brw.currency_id and voucher_brw.currency_id.id or voucher_brw.journal_id.company_id.currency_id.id # We want to set it on the account move line as soon as the original line had a foreign currency if line.move_line_id.currency_id and line.move_line_id.currency_id.id != company_currency: # we compute the amount in that foreign currency. @@ -1157,22 +1245,19 @@ class account_voucher(osv.osv): # if the voucher and the voucher line share the same currency, there is no computation to do sign = (move_line['debit'] - move_line['credit']) < 0 and -1 or 1 amount_currency = sign * (line.amount) - elif line.move_line_id.currency_id.id == voucher_brw.payment_rate_currency_id.id: - # if the rate is specified on the voucher, we must use it - voucher_rate = currency_obj.browse(cr, uid, voucher_currency, context=ctx).rate - amount_currency = (move_line['debit'] - move_line['credit']) * voucher_brw.payment_rate * voucher_rate else: - # otherwise we use the rates of the system (giving the voucher date in the context) + # if the rate is specified on the voucher, it will be used thanks to the special keys in the context + # otherwise we use the rates of the system amount_currency = currency_obj.compute(cr, uid, company_currency, line.move_line_id.currency_id.id, move_line['debit']-move_line['credit'], context=ctx) - if line.amount == line.amount_unreconciled and line.move_line_id.currency_id.id == voucher_currency: - sign = voucher_brw.type in ('payment', 'purchase') and -1 or 1 + if line.amount == line.amount_unreconciled: + sign = voucher.type in ('payment', 'purchase') and -1 or 1 foreign_currency_diff = sign * line.move_line_id.amount_residual_currency + amount_currency move_line['amount_currency'] = amount_currency voucher_line = move_line_obj.create(cr, uid, move_line) rec_ids = [voucher_line, line.move_line_id.id] - if not currency_obj.is_zero(cr, uid, voucher_brw.company_id.currency_id, currency_rate_difference): + if not currency_obj.is_zero(cr, uid, voucher.company_id.currency_id, currency_rate_difference): # Change difference entry in company currency exch_lines = self._get_exchange_lines(cr, uid, line, move_id, currency_rate_difference, company_currency, current_currency, context=context) new_id = move_line_obj.create(cr, uid, exch_lines[0],context) @@ -1219,32 +1304,32 @@ class account_voucher(osv.osv): currency_obj = self.pool.get('res.currency') move_line = {} - voucher_brw = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context) - current_currency_obj = voucher_brw.currency_id or voucher_brw.journal_id.company_id.currency_id + voucher = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context) + current_currency_obj = voucher.currency_id or voucher.journal_id.company_id.currency_id if not currency_obj.is_zero(cr, uid, current_currency_obj, line_total): diff = line_total account_id = False write_off_name = '' - if voucher_brw.payment_option == 'with_writeoff': - account_id = voucher_brw.writeoff_acc_id.id - write_off_name = voucher_brw.comment - elif voucher_brw.type in ('sale', 'receipt'): - account_id = voucher_brw.partner_id.property_account_receivable.id + if voucher.payment_option == 'with_writeoff': + account_id = voucher.writeoff_acc_id.id + write_off_name = voucher.comment + elif voucher.type in ('sale', 'receipt'): + account_id = voucher.partner_id.property_account_receivable.id else: - account_id = voucher_brw.partner_id.property_account_payable.id - sign = voucher_brw.type == 'payment' and -1 or 1 + account_id = voucher.partner_id.property_account_payable.id + sign = voucher.type == 'payment' and -1 or 1 move_line = { 'name': write_off_name or name, 'account_id': account_id, 'move_id': move_id, - 'partner_id': voucher_brw.partner_id.id, - 'date': voucher_brw.date, + 'partner_id': voucher.partner_id.id, + 'date': voucher.date, 'credit': diff > 0 and diff or 0.0, 'debit': diff < 0 and -diff or 0.0, - 'amount_currency': company_currency <> current_currency and (sign * -1 * voucher_brw.writeoff_amount) or False, + 'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or False, 'currency_id': company_currency <> current_currency and current_currency or False, - 'analytic_account_id': voucher_brw.analytic_id and voucher_brw.analytic_id.id or False, + 'analytic_account_id': voucher.analytic_id and voucher.analytic_id.id or False, } return move_line @@ -1345,13 +1430,17 @@ class account_voucher_line(osv.osv): _order = "move_line_id" # If the payment is in the same currency than the invoice, we keep the same amount - # Otherwise, we compute from company currency to payment currency + # Otherwise, we compute from invoice currency to payment currency def _compute_balance(self, cr, uid, ids, name, args, context=None): currency_pool = self.pool.get('res.currency') rs_data = {} for line in self.browse(cr, uid, ids, context=context): ctx = context.copy() ctx.update({'date': line.voucher_id.date}) + voucher_rate = self.pool.get('res.currency').read(cr, uid, line.voucher_id.currency_id.id, ['rate'], context=ctx)['rate'] + ctx.update({ + 'voucher_special_currency': line.voucher_id.payment_rate_currency_id and line.voucher_id.payment_rate_currency_id.id or False, + 'voucher_special_currency_rate': line.voucher_id.payment_rate * voucher_rate}) res = {} company_currency = line.voucher_id.journal_id.company_id.currency_id.id voucher_currency = line.voucher_id.currency_id and line.voucher_id.currency_id.id or company_currency @@ -1361,13 +1450,11 @@ class account_voucher_line(osv.osv): res['amount_original'] = 0.0 res['amount_unreconciled'] = 0.0 elif move_line.currency_id and voucher_currency==move_line.currency_id.id: - res['amount_original'] = currency_pool.compute(cr, uid, move_line.currency_id.id, voucher_currency, abs(move_line.amount_currency), context=ctx) - res['amount_unreconciled'] = currency_pool.compute(cr, uid, move_line.currency_id and move_line.currency_id.id or company_currency, voucher_currency, abs(move_line.amount_residual_currency), context=ctx) - elif move_line and move_line.credit > 0: - res['amount_original'] = currency_pool.compute(cr, uid, company_currency, voucher_currency, move_line.credit, context=ctx) - res['amount_unreconciled'] = currency_pool.compute(cr, uid, company_currency, voucher_currency, abs(move_line.amount_residual), context=ctx) + res['amount_original'] = abs(move_line.amount_currency) + res['amount_unreconciled'] = abs(move_line.amount_residual_currency) else: - res['amount_original'] = currency_pool.compute(cr, uid, company_currency, voucher_currency, move_line.debit, context=ctx) + #always use the amount booked in the company currency as the basis of the conversion into the voucher currency + res['amount_original'] = currency_pool.compute(cr, uid, company_currency, voucher_currency, move_line.credit or move_line.debit or 0.0, context=ctx) res['amount_unreconciled'] = currency_pool.compute(cr, uid, company_currency, voucher_currency, abs(move_line.amount_residual), context=ctx) rs_data[line.id] = res @@ -1535,7 +1622,7 @@ class account_bank_statement(osv.osv): for bk_st in self.browse(cr, uid, ids, context=context): if vals.get('journal_id') and bk_st.line_ids: if any([x.voucher_id and True or False for x in bk_st.line_ids]): - raise osv.except_osv(_('Unable to change journal !'), _('You can not change the journal as you already reconciled some statement lines!')) + raise osv.except_osv(_('Unable to Change Journal!'), _('You can not change the journal as you already reconciled some statement lines!')) return super(account_bank_statement, self).write(cr, uid, ids, vals, context=context) diff --git a/addons/account_voucher/i18n/nl_BE.po b/addons/account_voucher/i18n/nl_BE.po index 0cdc8cd8399..04366df488e 100644 --- a/addons/account_voucher/i18n/nl_BE.po +++ b/addons/account_voucher/i18n/nl_BE.po @@ -7,14 +7,14 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-21 17:04+0000\n" -"PO-Revision-Date: 2012-12-19 18:04+0000\n" +"PO-Revision-Date: 2013-07-10 09:54+0000\n" "Last-Translator: Els Van Vossel (Agaplan) \n" "Language-Team: Els Van Vossel\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-03-16 05:33+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-07-11 05:17+0000\n" +"X-Generator: Launchpad (build 16696)\n" "Language: nl\n" #. module: account_voucher @@ -28,7 +28,7 @@ msgid "account.config.settings" msgstr "account.config.settings" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:369 +#: code:addons/account_voucher/account_voucher.py:417 #, python-format msgid "Write-Off" msgstr "Afschrijving" @@ -132,12 +132,14 @@ msgid "Voucher Statistics" msgstr "Boekingsstatistieken" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1547 +#: code:addons/account_voucher/account_voucher.py:1641 #, python-format msgid "" "You can not change the journal as you already reconciled some statement " "lines!" msgstr "" +"U kunt het journaal niet veranderen, omdat er al uittreksellijnen zijn " +"afgepunt." #. module: account_voucher #: view:account.voucher:0 @@ -148,7 +150,7 @@ msgstr "Goedkeuren" #: model:ir.actions.act_window,name:account_voucher.action_vendor_payment #: model:ir.ui.menu,name:account_voucher.menu_action_vendor_payment msgid "Supplier Payments" -msgstr "" +msgstr "Leveranciersbetalingen" #. module: account_voucher #: model:ir.actions.act_window,help:account_voucher.action_purchase_receipt @@ -223,7 +225,7 @@ msgstr "Berichten" #: model:ir.actions.act_window,name:account_voucher.action_purchase_receipt #: model:ir.ui.menu,name:account_voucher.menu_action_purchase_receipt msgid "Purchase Receipts" -msgstr "" +msgstr "Aankoopbewijzen" #. module: account_voucher #: field:account.voucher.line,move_line_id:0 @@ -231,8 +233,8 @@ msgid "Journal Item" msgstr "Boekingslijn" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:508 -#: code:addons/account_voucher/account_voucher.py:981 +#: code:addons/account_voucher/account_voucher.py:558 +#: code:addons/account_voucher/account_voucher.py:1073 #, python-format msgid "Error!" msgstr "Fout" @@ -259,7 +261,7 @@ msgid "Cancelled" msgstr "Geannuleerd" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1153 +#: code:addons/account_voucher/account_voucher.py:1249 #, python-format msgid "" "You have to configure account base code and account tax code on the '%s' tax!" @@ -311,7 +313,7 @@ msgid "Tax" msgstr "Btw" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:879 +#: code:addons/account_voucher/account_voucher.py:971 #, python-format msgid "Invalid Action!" msgstr "Ongeldige actie" @@ -364,10 +366,10 @@ msgid "Import Invoices" msgstr "Facturen importeren" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1112 +#: code:addons/account_voucher/account_voucher.py:1208 #, python-format msgid "Wrong voucher line" -msgstr "" +msgstr "Verkeerde betalingsregel" #. module: account_voucher #: selection:account.voucher,pay_now:0 @@ -383,7 +385,7 @@ msgid "Receipt" msgstr "Reçu" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1018 +#: code:addons/account_voucher/account_voucher.py:1110 #, python-format msgid "" "You should configure the 'Gain Exchange Rate Account' in the accounting " @@ -407,7 +409,7 @@ msgstr "Periode" #. module: account_voucher #: view:account.voucher:0 -#: code:addons/account_voucher/account_voucher.py:211 +#: code:addons/account_voucher/account_voucher.py:231 #, python-format msgid "Supplier" msgstr "Leverancier" @@ -428,10 +430,10 @@ msgid "Debit" msgstr "Debet" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1547 +#: code:addons/account_voucher/account_voucher.py:1641 #, python-format msgid "Unable to change journal !" -msgstr "" +msgstr "Het dagboek kan niet worden gewijzigd" #. module: account_voucher #: view:sale.receipt.report:0 @@ -467,6 +469,12 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Klik hier als u een nieuwe leveranciersbetaling wilt maken.\n" +"

\n" +" Met OpenERP kunt u betalingen aan leveranciers opvolgen.\n" +"

\n" +" " #. module: account_voucher #: view:account.voucher:0 @@ -534,7 +542,7 @@ msgid "Pay Invoice" msgstr "Factuur betalen" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1153 +#: code:addons/account_voucher/account_voucher.py:1249 #, python-format msgid "No Account Base Code and Account Tax Code!" msgstr "Geen rekening voor basisvak en btw-vak" @@ -588,15 +596,15 @@ msgid "To Review" msgstr "Te controleren" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1025 -#: code:addons/account_voucher/account_voucher.py:1039 -#: code:addons/account_voucher/account_voucher.py:1194 +#: code:addons/account_voucher/account_voucher.py:1120 +#: code:addons/account_voucher/account_voucher.py:1134 +#: code:addons/account_voucher/account_voucher.py:1286 #, python-format msgid "change" msgstr "wijzigen" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1014 +#: code:addons/account_voucher/account_voucher.py:1106 #, python-format msgid "" "You should configure the 'Loss Exchange Rate Account' in the accounting " @@ -654,6 +662,7 @@ msgstr "Maand" #. module: account_voucher #: field:account.voucher,currency_id:0 #: field:account.voucher.line,currency_id:0 +#: model:ir.model,name:account_voucher.model_res_currency #: field:sale.receipt.report,currency_id:0 msgid "Currency" msgstr "Munt" @@ -697,7 +706,7 @@ msgid "Reconcile Payment Balance" msgstr "Betalingssaldo afpunten" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:975 +#: code:addons/account_voucher/account_voucher.py:1067 #, python-format msgid "Configuration Error !" msgstr "Configuratiefout" @@ -745,7 +754,7 @@ msgstr "Augustus" #. module: account_voucher #: view:account.voucher:0 msgid "Validate Payment" -msgstr "" +msgstr "Betaling bevestigen" #. module: account_voucher #: help:account.voucher,audit:0 @@ -762,7 +771,7 @@ msgid "October" msgstr "Oktober" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:976 +#: code:addons/account_voucher/account_voucher.py:1068 #, python-format msgid "Please activate the sequence of selected journal !" msgstr "Gelieve de nummering van het gekozen journaal te activeren." @@ -786,7 +795,7 @@ msgstr "Betaald" #: model:ir.actions.act_window,name:account_voucher.action_sale_receipt #: model:ir.ui.menu,name:account_voucher.menu_action_sale_receipt msgid "Sales Receipts" -msgstr "" +msgstr "Verkoopbewijzen" #. module: account_voucher #: field:account.voucher,message_is_follower:0 @@ -834,7 +843,7 @@ msgstr "Onmiddellijk betalen" #. module: account_voucher #: field:account.voucher.line,type:0 msgid "Dr/Cr" -msgstr "" +msgstr "Db/Cr" #. module: account_voucher #: field:account.voucher,pre_line:0 @@ -842,10 +851,10 @@ msgid "Previous Payments ?" msgstr "Vorige betalingen?" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1112 +#: code:addons/account_voucher/account_voucher.py:1208 #, python-format msgid "The invoice you are willing to pay is not valid anymore." -msgstr "" +msgstr "De factuur die u wilt betalen, is niet meer geldig." #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -874,7 +883,7 @@ msgid "Active" msgstr "Actief" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:982 +#: code:addons/account_voucher/account_voucher.py:1074 #, python-format msgid "Please define a sequence on the journal." msgstr "Gelieve een reeks in te stellen voor het journaal." @@ -884,7 +893,7 @@ msgstr "Gelieve een reeks in te stellen voor het journaal." #: model:ir.actions.act_window,name:account_voucher.action_vendor_receipt #: model:ir.ui.menu,name:account_voucher.menu_action_vendor_receipt msgid "Customer Payments" -msgstr "" +msgstr "Klantenbetalingen" #. module: account_voucher #: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all @@ -938,7 +947,7 @@ msgstr "Nummer" #. module: account_voucher #: selection:account.voucher.line,type:0 msgid "Credit" -msgstr "" +msgstr "Credit" #. module: account_voucher #: model:ir.model,name:account_voucher.model_account_bank_statement @@ -1002,7 +1011,7 @@ msgid "Journal Items" msgstr "Boekingslijnen" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:508 +#: code:addons/account_voucher/account_voucher.py:558 #, python-format msgid "Please define default credit/debit accounts on the journal \"%s\"." msgstr "Stel een standaard debet-/creditrekening in voor journaal \"%s\"." @@ -1219,7 +1228,7 @@ msgstr "" "Het bedrag van het reçu moet gelijk zijn aan het bedrag op de uittreksellijn." #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:879 +#: code:addons/account_voucher/account_voucher.py:971 #, python-format msgid "Cannot delete voucher(s) which are already opened or paid." msgstr "Een openstaand of betaald reçu kan niet meer worden verwijderd." @@ -1279,11 +1288,11 @@ msgstr "Openstaand saldo" #. module: account_voucher #: model:mail.message.subtype,description:account_voucher.mt_voucher_state_change msgid "Status changed" -msgstr "" +msgstr "Status vgewijzigd" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1014 -#: code:addons/account_voucher/account_voucher.py:1018 +#: code:addons/account_voucher/account_voucher.py:1106 +#: code:addons/account_voucher/account_voucher.py:1110 #, python-format msgid "Insufficient Configuration!" msgstr "Niet volledig geconfigureerd" diff --git a/addons/account_voucher/i18n/ru.po b/addons/account_voucher/i18n/ru.po index 63cad344ed0..16e03d424ef 100644 --- a/addons/account_voucher/i18n/ru.po +++ b/addons/account_voucher/i18n/ru.po @@ -7,27 +7,27 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0dev\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-21 17:04+0000\n" -"PO-Revision-Date: 2012-05-10 17:46+0000\n" +"PO-Revision-Date: 2013-06-13 11:30+0000\n" "Last-Translator: Chertykov Denis \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-03-16 05:33+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-06-14 05:38+0000\n" +"X-Generator: Launchpad (build 16667)\n" #. module: account_voucher #: field:account.bank.statement.line,voucher_id:0 msgid "Reconciliation" -msgstr "" +msgstr "Сверка" #. module: account_voucher #: model:ir.model,name:account_voucher.model_account_config_settings msgid "account.config.settings" -msgstr "" +msgstr "account.config.settings" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:369 +#: code:addons/account_voucher/account_voucher.py:417 #, python-format msgid "Write-Off" msgstr "Списание" @@ -45,7 +45,7 @@ msgstr "Общая сумма" #. module: account_voucher #: view:account.voucher:0 msgid "Open Customer Journal Entries" -msgstr "" +msgstr "Открыть записи журнала по заказчику" #. module: account_voucher #: view:account.voucher:0 @@ -63,7 +63,7 @@ msgstr "" #. module: account_voucher #: view:account.voucher:0 msgid "(Update)" -msgstr "" +msgstr "(Обновить)" #. module: account_voucher #: view:account.voucher:0 @@ -90,7 +90,7 @@ msgstr "Март" #. module: account_voucher #: field:account.voucher,message_unread:0 msgid "Unread Messages" -msgstr "" +msgstr "Непрочитанные" #. module: account_voucher #: view:account.voucher:0 @@ -115,13 +115,13 @@ msgstr "Номер транзакции." #. module: account_voucher #: view:sale.receipt.report:0 msgid "Group by year of Invoice Date" -msgstr "" +msgstr "Группировать по году в дате счета" #. module: account_voucher #: view:sale.receipt.report:0 #: field:sale.receipt.report,user_id:0 msgid "Salesperson" -msgstr "" +msgstr "Продавец" #. module: account_voucher #: view:account.voucher:0 @@ -129,12 +129,14 @@ msgid "Voucher Statistics" msgstr "" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1547 +#: code:addons/account_voucher/account_voucher.py:1641 #, python-format msgid "" "You can not change the journal as you already reconciled some statement " "lines!" msgstr "" +"Вы не можете изменить журнал, так как вы уже сверили некоторые позиции " +"документа!" #. module: account_voucher #: view:account.voucher:0 @@ -145,7 +147,7 @@ msgstr "Утвердить" #: model:ir.actions.act_window,name:account_voucher.action_vendor_payment #: model:ir.ui.menu,name:account_voucher.menu_action_vendor_payment msgid "Supplier Payments" -msgstr "" +msgstr "Оплаты поставщикам" #. module: account_voucher #: model:ir.actions.act_window,help:account_voucher.action_purchase_receipt @@ -167,7 +169,7 @@ msgstr "Искать ваучеры" #. module: account_voucher #: field:account.voucher,writeoff_acc_id:0 msgid "Counterpart Account" -msgstr "" +msgstr "Корреспондирующий счет" #. module: account_voucher #: field:account.voucher,account_id:0 @@ -189,7 +191,7 @@ msgstr "OK" #. module: account_voucher #: field:account.voucher.line,reconcile:0 msgid "Full Reconcile" -msgstr "" +msgstr "Полная сверка" #. module: account_voucher #: field:account.voucher,date_due:0 @@ -207,7 +209,7 @@ msgstr "Примечания" #. module: account_voucher #: field:account.voucher,message_ids:0 msgid "Messages" -msgstr "" +msgstr "Сообщения" #. module: account_voucher #: model:ir.actions.act_window,name:account_voucher.action_purchase_receipt @@ -221,11 +223,11 @@ msgid "Journal Item" msgstr "Элемент журнала" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:508 -#: code:addons/account_voucher/account_voucher.py:981 +#: code:addons/account_voucher/account_voucher.py:558 +#: code:addons/account_voucher/account_voucher.py:1073 #, python-format msgid "Error!" -msgstr "" +msgstr "Ошибка!" #. module: account_voucher #: field:account.voucher.line,amount:0 @@ -235,7 +237,7 @@ msgstr "Суммма" #. module: account_voucher #: view:account.voucher:0 msgid "Payment Options" -msgstr "" +msgstr "Варианты оплаты" #. module: account_voucher #: view:account.voucher:0 @@ -249,11 +251,13 @@ msgid "Cancelled" msgstr "Отменено" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1153 +#: code:addons/account_voucher/account_voucher.py:1249 #, python-format msgid "" "You have to configure account base code and account tax code on the '%s' tax!" msgstr "" +"Вы должны настроить код базового счета и код налогового счета для налога " +"'%s'!" #. module: account_voucher #: model:ir.actions.act_window,help:account_voucher.action_sale_receipt @@ -271,7 +275,7 @@ msgstr "" #. module: account_voucher #: help:account.voucher,message_unread:0 msgid "If checked new messages require your attention." -msgstr "" +msgstr "Если отмечено, новые сообщения требуют вашего внимания." #. module: account_voucher #: model:ir.model,name:account_voucher.model_account_bank_statement_line @@ -291,15 +295,15 @@ msgid "Tax" msgstr "Налог" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:879 +#: code:addons/account_voucher/account_voucher.py:971 #, python-format msgid "Invalid Action!" -msgstr "" +msgstr "Неверное действие!" #. module: account_voucher #: field:account.voucher,comment:0 msgid "Counterpart Comment" -msgstr "" +msgstr "Корреспондирующий коментарий" #. module: account_voucher #: field:account.voucher.line,account_analytic_id:0 @@ -312,6 +316,8 @@ msgid "" "Holds the Chatter summary (number of messages, ...). This summary is " "directly in html format in order to be inserted in kanban views." msgstr "" +"Содержит сводку по Чаттеру (количество сообщений,...). Эта сводка в формате " +"html для возможности использования в канбан виде" #. module: account_voucher #: view:account.voucher:0 @@ -326,7 +332,7 @@ msgstr "Информация о платеже" #. module: account_voucher #: view:account.voucher:0 msgid "(update)" -msgstr "" +msgstr "(обновить)" #. module: account_voucher #: view:account.voucher:0 @@ -342,7 +348,7 @@ msgid "Import Invoices" msgstr "Импорт счетов" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1112 +#: code:addons/account_voucher/account_voucher.py:1208 #, python-format msgid "Wrong voucher line" msgstr "" @@ -361,7 +367,7 @@ msgid "Receipt" msgstr "Приход" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1018 +#: code:addons/account_voucher/account_voucher.py:1110 #, python-format msgid "" "You should configure the 'Gain Exchange Rate Account' in the accounting " @@ -382,7 +388,7 @@ msgstr "Период" #. module: account_voucher #: view:account.voucher:0 -#: code:addons/account_voucher/account_voucher.py:211 +#: code:addons/account_voucher/account_voucher.py:231 #, python-format msgid "Supplier" msgstr "Поставщик" @@ -395,7 +401,7 @@ msgstr "Ваучер поставщика" #. module: account_voucher #: field:account.voucher,message_follower_ids:0 msgid "Followers" -msgstr "" +msgstr "Подписчики" #. module: account_voucher #: selection:account.voucher.line,type:0 @@ -403,10 +409,10 @@ msgid "Debit" msgstr "Дебет" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1547 +#: code:addons/account_voucher/account_voucher.py:1641 #, python-format msgid "Unable to change journal !" -msgstr "" +msgstr "Невозможно изменить журнал!" #. module: account_voucher #: view:sale.receipt.report:0 @@ -446,7 +452,7 @@ msgstr "" #. module: account_voucher #: view:account.voucher:0 msgid "Open Supplier Journal Entries" -msgstr "" +msgstr "Открыть журнал проводок по поставщику" #. module: account_voucher #: model:ir.actions.act_window,name:account_voucher.action_review_voucher_list @@ -461,7 +467,7 @@ msgstr "Памятка" #. module: account_voucher #: view:account.voucher:0 msgid "Are you sure to unreconcile and cancel this record ?" -msgstr "" +msgstr "Вы уверены, что надо отменить сверку и саму запись ?" #. module: account_voucher #: field:account.voucher,is_multi_currency:0 @@ -494,13 +500,13 @@ msgstr "" #. module: account_voucher #: field:account.voucher,writeoff_amount:0 msgid "Difference Amount" -msgstr "" +msgstr "Сумма разницы" #. module: account_voucher #: view:sale.receipt.report:0 #: field:sale.receipt.report,due_delay:0 msgid "Avg. Due Delay" -msgstr "" +msgstr "Средн. задержка" #. module: account_voucher #: code:addons/account_voucher/invoice.py:34 @@ -509,7 +515,7 @@ msgid "Pay Invoice" msgstr "Оплата счета" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1153 +#: code:addons/account_voucher/account_voucher.py:1249 #, python-format msgid "No Account Base Code and Account Tax Code!" msgstr "" @@ -554,7 +560,7 @@ msgstr "Оплаченная сумма" #. module: account_voucher #: field:account.voucher,payment_option:0 msgid "Payment Difference" -msgstr "" +msgstr "Оплата разницы" #. module: account_voucher #: view:account.voucher:0 @@ -563,15 +569,15 @@ msgid "To Review" msgstr "Для проверки" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1025 -#: code:addons/account_voucher/account_voucher.py:1039 -#: code:addons/account_voucher/account_voucher.py:1194 +#: code:addons/account_voucher/account_voucher.py:1120 +#: code:addons/account_voucher/account_voucher.py:1134 +#: code:addons/account_voucher/account_voucher.py:1286 #, python-format msgid "change" -msgstr "" +msgstr "изменить" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1014 +#: code:addons/account_voucher/account_voucher.py:1106 #, python-format msgid "" "You should configure the 'Loss Exchange Rate Account' in the accounting " @@ -599,7 +605,7 @@ msgstr "" #. module: account_voucher #: view:account.invoice:0 msgid "Register Payment" -msgstr "" +msgstr "Регистрация оплаты" #. module: account_voucher #: field:account.statement.from.invoice.lines,line_ids:0 @@ -614,7 +620,7 @@ msgstr "декабрём" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Group by month of Invoice Date" -msgstr "" +msgstr "Группировать по месяцу даты счета" #. module: account_voucher #: view:sale.receipt.report:0 @@ -625,6 +631,7 @@ msgstr "Месяц" #. module: account_voucher #: field:account.voucher,currency_id:0 #: field:account.voucher.line,currency_id:0 +#: model:ir.model,name:account_voucher.model_res_currency #: field:sale.receipt.report,currency_id:0 msgid "Currency" msgstr "Валюта" @@ -647,7 +654,7 @@ msgstr "" #. module: account_voucher #: view:account.voucher:0 msgid "Are you sure to unreconcile this record?" -msgstr "" +msgstr "Вы уверены в отмене сверки" #. module: account_voucher #: field:account.voucher,company_id:0 @@ -665,13 +672,13 @@ msgstr "" #. module: account_voucher #: selection:account.voucher,payment_option:0 msgid "Reconcile Payment Balance" -msgstr "" +msgstr "Сверка платежного баланса" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:975 +#: code:addons/account_voucher/account_voucher.py:1067 #, python-format msgid "Configuration Error !" -msgstr "" +msgstr "Ошибка конфигурации !" #. module: account_voucher #: view:account.voucher:0 @@ -695,18 +702,18 @@ msgstr "" #: field:account.voucher,state:0 #: view:sale.receipt.report:0 msgid "Status" -msgstr "" +msgstr "Статус" #. module: account_voucher #: view:account.voucher:0 msgid "Allocation" -msgstr "" +msgstr "Распределение" #. module: account_voucher #: view:account.statement.from.invoice.lines:0 #: view:account.voucher:0 msgid "or" -msgstr "" +msgstr "или" #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -716,7 +723,7 @@ msgstr "Август" #. module: account_voucher #: view:account.voucher:0 msgid "Validate Payment" -msgstr "" +msgstr "Утвердить оплату" #. module: account_voucher #: help:account.voucher,audit:0 @@ -724,6 +731,8 @@ msgid "" "Check this box if you are unsure of that journal entry and if you want to " "note it as 'to be reviewed' by an accounting expert." msgstr "" +"Отметьте, если вы не уверены в этой проводке журнала и хотите отметить её " +"\"для проверки\" опытному бухгалтеру." #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -731,10 +740,10 @@ msgid "October" msgstr "Октябрь" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:976 +#: code:addons/account_voucher/account_voucher.py:1068 #, python-format msgid "Please activate the sequence of selected journal !" -msgstr "" +msgstr "Пожалуйста, включите нумерацию выбранного журнала!" #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -749,7 +758,7 @@ msgstr "" #. module: account_voucher #: field:account.voucher,paid:0 msgid "Paid" -msgstr "" +msgstr "Оплачено" #. module: account_voucher #: model:ir.actions.act_window,name:account_voucher.action_sale_receipt @@ -760,7 +769,7 @@ msgstr "" #. module: account_voucher #: field:account.voucher,message_is_follower:0 msgid "Is a Follower" -msgstr "" +msgstr "Подписан" #. module: account_voucher #: field:account.voucher,analytic_id:0 @@ -787,7 +796,7 @@ msgstr "Расширенные фильтры..." #. module: account_voucher #: field:account.voucher,paid_amount_in_company_currency:0 msgid "Paid Amount in Company Currency" -msgstr "" +msgstr "Оплаченная сумма в валюте компании" #. module: account_voucher #: field:account.bank.statement.line,amount_reconciled:0 @@ -811,10 +820,10 @@ msgid "Previous Payments ?" msgstr "Предыдущие платежи ?" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1112 +#: code:addons/account_voucher/account_voucher.py:1208 #, python-format msgid "The invoice you are willing to pay is not valid anymore." -msgstr "" +msgstr "Счет, который вы готовы платить, уже не актуален ." #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -830,30 +839,30 @@ msgstr "Журнал ваучеров" #. module: account_voucher #: model:ir.model,name:account_voucher.model_res_company msgid "Companies" -msgstr "" +msgstr "Компании" #. module: account_voucher #: field:account.voucher,message_summary:0 msgid "Summary" -msgstr "" +msgstr "Итог" #. module: account_voucher #: field:account.voucher,active:0 msgid "Active" -msgstr "" +msgstr "Активно" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:982 +#: code:addons/account_voucher/account_voucher.py:1074 #, python-format msgid "Please define a sequence on the journal." -msgstr "" +msgstr "Пожалуйста, определите нумерацию журнала." #. module: account_voucher #: model:ir.actions.act_window,name:account_voucher.act_pay_voucher #: model:ir.actions.act_window,name:account_voucher.action_vendor_receipt #: model:ir.ui.menu,name:account_voucher.menu_action_vendor_receipt msgid "Customer Payments" -msgstr "" +msgstr "Платежи заказчиков" #. module: account_voucher #: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all @@ -865,7 +874,7 @@ msgstr "" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Group by Invoice Date" -msgstr "" +msgstr "Группировать по дате счета" #. module: account_voucher #: view:account.voucher:0 @@ -971,7 +980,7 @@ msgid "Journal Items" msgstr "Элементы журнала" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:508 +#: code:addons/account_voucher/account_voucher.py:558 #, python-format msgid "Please define default credit/debit accounts on the journal \"%s\"." msgstr "" @@ -1180,7 +1189,7 @@ msgid "" msgstr "" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:879 +#: code:addons/account_voucher/account_voucher.py:971 #, python-format msgid "Cannot delete voucher(s) which are already opened or paid." msgstr "" @@ -1243,8 +1252,8 @@ msgid "Status changed" msgstr "" #. module: account_voucher -#: code:addons/account_voucher/account_voucher.py:1014 -#: code:addons/account_voucher/account_voucher.py:1018 +#: code:addons/account_voucher/account_voucher.py:1106 +#: code:addons/account_voucher/account_voucher.py:1110 #, python-format msgid "Insufficient Configuration!" msgstr "" diff --git a/addons/account_voucher/invoice.py b/addons/account_voucher/invoice.py index 03a3e5fab67..c11f9d532e9 100644 --- a/addons/account_voucher/invoice.py +++ b/addons/account_voucher/invoice.py @@ -41,6 +41,7 @@ class invoice(osv.osv): 'target': 'new', 'domain': '[]', 'context': { + 'payment_expected_currency': inv.currency_id.id, 'default_partner_id': self.pool.get('res.partner')._find_accounting_partner(inv.partner_id).id, 'default_amount': inv.type in ('out_refund', 'in_refund') and -inv.residual or inv.residual, 'default_reference': inv.name, diff --git a/addons/account_voucher/security/account_voucher_security.xml b/addons/account_voucher/security/account_voucher_security.xml index 04540fd8aa0..daa5934b256 100644 --- a/addons/account_voucher/security/account_voucher_security.xml +++ b/addons/account_voucher/security/account_voucher_security.xml @@ -3,13 +3,13 @@ Voucher multi-company - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] Voucher Line multi-company - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] diff --git a/addons/account_voucher/static/description/account_illu_01.png b/addons/account_voucher/static/description/account_illu_01.png new file mode 100644 index 00000000000..2e0dbf4aac2 Binary files /dev/null and b/addons/account_voucher/static/description/account_illu_01.png differ diff --git a/addons/account_voucher/static/description/account_sc_00.png b/addons/account_voucher/static/description/account_sc_00.png new file mode 100644 index 00000000000..63332b46575 Binary files /dev/null and b/addons/account_voucher/static/description/account_sc_00.png differ diff --git a/addons/account_voucher/static/description/account_sc_02.png b/addons/account_voucher/static/description/account_sc_02.png new file mode 100644 index 00000000000..709e444ba0d Binary files /dev/null and b/addons/account_voucher/static/description/account_sc_02.png differ diff --git a/addons/account_voucher/static/description/account_sc_03.png b/addons/account_voucher/static/description/account_sc_03.png new file mode 100644 index 00000000000..a3e3afc34c0 Binary files /dev/null and b/addons/account_voucher/static/description/account_sc_03.png differ diff --git a/addons/account_voucher/static/description/account_sc_04.png b/addons/account_voucher/static/description/account_sc_04.png new file mode 100644 index 00000000000..458c8280c26 Binary files /dev/null and b/addons/account_voucher/static/description/account_sc_04.png differ diff --git a/addons/account_voucher/static/description/account_sc_06.png b/addons/account_voucher/static/description/account_sc_06.png new file mode 100644 index 00000000000..9605506c6a5 Binary files /dev/null and b/addons/account_voucher/static/description/account_sc_06.png differ diff --git a/addons/account_voucher/static/description/bazile.png b/addons/account_voucher/static/description/bazile.png new file mode 100644 index 00000000000..30f37e70b4a Binary files /dev/null and b/addons/account_voucher/static/description/bazile.png differ diff --git a/addons/account_voucher/static/src/img/icon.png b/addons/account_voucher/static/description/icon.png similarity index 100% rename from addons/account_voucher/static/src/img/icon.png rename to addons/account_voucher/static/description/icon.png diff --git a/addons/account_voucher/static/description/index.html b/addons/account_voucher/static/description/index.html new file mode 100644 index 00000000000..a363291f12e --- /dev/null +++ b/addons/account_voucher/static/description/index.html @@ -0,0 +1,140 @@ +
+
+

Invoicing Made Easy

+

Send professional invoices & get paid online

+
+
+ + Online Demo + + +
+
+
+

+ Create and send professional looking invoices & get paid + online. It automatically integrates with other apps to bill + automatically based on your activities. +

+ +
+
+
+ +
+

Send Invoices With No Effort

+
+
+

+ Send invoices directly to your clients in just a click. The + invoice is automatically attached to the email as a PDF file. +

+
+
+ +
+
+
+ + +
+

Get Paid Faster

+

Electronic invoicing and automated follow-ups

+
+
+ +
+
+

+Get paid online with paypal or other payment processing service. Get rid of +the stress of having to constantly remind your debtors. Simply set-up and +automate follow-ups to get paid quickly. +

+
+
+
+ + +
+
+

Connect Your Bank Accounts

+
+

+Import your bank statements and reconcile them in just a few clicks. Prepare +payment orders based on your supplier invoices and payment terms. +

+
+
+ +
+ +
+
+ +
+
+

Analyse Your Sales & Costs

+
+ +
+
+

+Get direct access to key information with dynamic and customizable dashboards. +Analyse your invoicing by product, customer, salesperson, etc. +

+
+
+
+ +
+
+

Integration With Other Apps

+
+

+Bill automatically based on sales orders, delivery orders, contracts or on time and +material. Define recurrencies to produce recurring invoice automatically. +

+
+
+ +
+
+
+ +
+
+
+

Many companies already enjoy it

+

Hear what they have to say !

+
+
+
+ + OpenERP allowed us to automate sending 10.000 invoices per month. + + + +
Yves Morel
+
Director of Bazile Telecom.
+
+
+
+
+
+ + We have found invoicing module of OpenERP to be user + friendly and highly customizable. + + + +
Col. Sunil Prem.
+ +
+
+
+
+
+
+
diff --git a/addons/account_voucher/static/description/testimonial_sunil.jpg b/addons/account_voucher/static/description/testimonial_sunil.jpg new file mode 100644 index 00000000000..f2ad6929a2b Binary files /dev/null and b/addons/account_voucher/static/description/testimonial_sunil.jpg differ diff --git a/addons/account_voucher/test/account_voucher.yml b/addons/account_voucher/test/account_voucher.yml index c9270dc695c..2cd612affc7 100644 --- a/addons/account_voucher/test/account_voucher.yml +++ b/addons/account_voucher/test/account_voucher.yml @@ -6,7 +6,7 @@ account_id: account.cash amount: 1000.0 company_id: base.main_company - journal_id: account.bank_journal + journal_id: account.sales_journal name: Voucher for Axelor narration: Basic Pc line_cr_ids: diff --git a/addons/account_voucher/test/case1_usd_usd_payment_rate.yml b/addons/account_voucher/test/case1_usd_usd_payment_rate.yml new file mode 100644 index 00000000000..037fc1497ec --- /dev/null +++ b/addons/account_voucher/test/case1_usd_usd_payment_rate.yml @@ -0,0 +1,247 @@ +- + In order to check the Account_voucher module with multi-currency in OpenERP, + I create 2 Invoices in USD and make 1 Payment in USD based on the currency rating given by the bank which is slightly different that the one encoded in OpenERP +- + I set the income and expense currency accounts on the main company +- + !python {model: res.company}: | + from datetime import datetime + vals = { + 'income_currency_exchange_account_id': ref('account.o_expense'), + 'expense_currency_exchange_account_id': ref('account.o_expense')} + self.write(cr, uid, ref('base.main_company'), vals) +- + I create currency USD in OpenERP for January of 1.333333 Rate +- + !python {model: res.currency.rate}: | + from datetime import datetime + curr_id = self.pool.get('res.currency').search(cr, uid, [('name', '=', 'USD')])[0] + date = '%s-01-01' %(datetime.now().year) + ids = self.search(cr, uid, [('currency_id','=',curr_id), ('name', '=', date)]) + self.write(cr, uid, ids, {'rate': 1.333333}) +- + I create currency USD in OpenERP for February of 1.250000 Rate +- + !record {model: res.currency.rate, id: feb_usd}: + currency_id: base.USD + name: !eval "'%s-02-01' %(datetime.now().year)" + rate: 1.250000 + +- + I create currency USD in OpenERP for March of 1.111111 Rate +- + !record {model: res.currency.rate, id: mar_usd}: + currency_id: base.USD + name: !eval "'%s-03-01' %(datetime.now().year)" + rate: 1.111111 + +- + I create currency USD in OpenERP for April of 1.052632 Rate +- + !record {model: res.currency.rate, id: apr_usd}: + currency_id: base.USD + name: !eval "'%s-04-01' %(datetime.now().year)" + rate: 1.052632 + +- + I create a cash account with currency USD +- + !record {model: account.account, id: account_cash_usd_id}: + currency_id: base.USD + name: "cash account in usd" + code: "Xcash usd" + type: 'liquidity' + user_type: "account.data_account_type_cash" + +- + I create a bank journal with USD as currency +- + !record {model: account.journal, id: bank_journal_USD}: + name: Bank Journal(USD) + code: BUSD + type: bank + analytic_journal_id: account.sit + sequence_id: account.sequence_bank_journal + default_debit_account_id: account_cash_usd_id + default_credit_account_id: account_cash_usd_id + currency: base.USD + company_id: base.main_company + +- + I create a new partner Kate Mc Kay +- + !record {model: res.partner, id: res_partner_mc_kay}: + name: "Mc Kay Kate" + property_account_receivable: account.a_recv + property_account_payable: account.a_pay +- + I create the first invoice on 1st January for 200 USD +- + !record {model: account.invoice, id: account_invoice_jan_payment_rate}: + account_id: account.a_recv + company_id: base.main_company + currency_id: base.USD + date_invoice: !eval "'%s-01-01' %(datetime.now().year)" + period_id: account.period_1 + invoice_line: + - account_id: account.a_sale + name: '[PCSC234] PC Assemble SC234' + price_unit: 200.0 + quantity: 1.0 + product_id: product.product_product_3 + uos_id: product.product_uom_unit + journal_id: account.sales_journal + partner_id: res_partner_mc_kay + reference_type: none +- + I Validate invoice by clicking on Validate button +- + !workflow {model: account.invoice, action: invoice_open, ref: account_invoice_jan_payment_rate} +- + I check that first invoice move is correct for debtor account (debit - credit == 150.0) +- + !python {model: account.invoice}: | + invoice_id = self.browse(cr, uid, ref("account_invoice_jan_payment_rate")) + assert invoice_id.move_id, "Move not created for open invoice" + move_line_obj = self.pool.get('account.move.line') + move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)]) + move_line = move_line_obj.browse(cr, uid, move_lines[0]) + assert (move_line.debit - move_line.credit == 150.0), "Invoice move is not correct for debtors account" +- + I create the second invoice on 1st February for 100 USD +- + !record {model: account.invoice, id: account_invoice_feb_payment_rate}: + account_id: account.a_recv + company_id: base.main_company + currency_id: base.USD + date_invoice: !eval "'%s-02-01' %(datetime.now().year)" + period_id: account.period_2 + invoice_line: + - account_id: account.a_sale + name: '[PCSC234] PC Assemble SC234' + price_unit: 100.0 + quantity: 1.0 + product_id: product.product_product_3 + uos_id: product.product_uom_unit + journal_id: account.sales_journal + partner_id: res_partner_mc_kay + reference_type: none +- + I Validate invoice by clicking on Validate button +- + !workflow {model: account.invoice, action: invoice_open, ref: account_invoice_feb_payment_rate} +- + I check that second invoice move is correct for debtor account (debit - credit == 80) +- + !python {model: account.invoice}: | + invoice_id = self.browse(cr, uid, ref("account_invoice_feb_payment_rate")) + assert invoice_id.move_id, "Move not created for open invoice" + move_line_obj = self.pool.get('account.move.line') + move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)]) + move_line = move_line_obj.browse(cr, uid, move_lines[0]) + assert (move_line.debit - move_line.credit == 80), "Invoice move is not correct for debtors account" + +- + I set the context that will be used for the encoding of all the vouchers of this file +- + !context + 'type': 'receipt' +- + On the first March, I create the first voucher of payment with values 240 USD, journal USD, and specifying that $1 = 0.8€ +- + !record {model: account.voucher, id: account_voucher_1_case1_payment_rate, view: view_vendor_receipt_form}: + account_id: account.cash + amount: 240.0 + company_id: base.main_company + journal_id: bank_journal_USD + name: 'Payment: Case 1 USD/USD payment rate' + partner_id: res_partner_mc_kay + period_id: account.period_3 + date: !eval time.strftime("%Y-03-01") + payment_option: 'with_writeoff' + writeoff_acc_id: account.a_expense + comment: 'Write Off' + payment_rate: 0.8 + payment_rate_currency_id: base.EUR + +- + I fill amounts 180 for the invoice of 200$ and 70 for the invoice of 100$> +- + !python {model: account.voucher}: | + vals = {} + voucher_id = self.browse(cr, uid, ref('account_voucher_1_case1_payment_rate')) + data = [] + for item in voucher_id.line_cr_ids: + if item.amount_unreconciled == 200.00: + data += [(item.id, 180.0)] + else: + data += [(item.id, 70.0)] + for line_id, amount in data: + self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount}) + assert (voucher_id.state=='draft'), "Voucher is not in draft state" +- + I check that writeoff amount computed is -10.0 +- + !python {model: account.voucher}: | + voucher = ref('account_voucher_1_case1_payment_rate') + voucher_id = self.browse(cr, uid, voucher) + assert (voucher_id.writeoff_amount == -10.0), "Writeoff amount is not -10.0" +- + I confirm the voucher +- + !python {model: account.voucher}: | + voucher = ref('account_voucher_1_case1_payment_rate') + self.signal_proforma_voucher(cr, uid, [voucher]) +- + I check that the move of my first voucher is valid +- + !python {model: account.voucher}: | + voucher = ref('account_voucher_1_case1_payment_rate') + voucher_id = self.browse(cr, uid, voucher) + move_line_obj = self.pool.get('account.move.line') + move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)]) + for move_line in move_line_obj.browse(cr, uid, move_lines): + assert move_line.state == 'valid', "Voucher move is not valid" +- + I check that my debtor account is correct +- + I check that the debtor account has 2 new lines with -180 and -70 as amount_currency columns and that their credit columns are respectively 144 and 56 +- + I check that my write-off is correct. 8 debit and 10 amount_currency +- + !python {model: account.voucher}: | + voucher = ref('account_voucher_1_case1_payment_rate') + voucher_id = self.browse(cr, uid, voucher) + move_line_obj = self.pool.get('account.move.line') + move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)]) + for move_line in move_line_obj.browse(cr, uid, move_lines): + if move_line.amount_currency == -180.00: + assert move_line.credit == 144.00, "Debtor account has wrong entry." + elif move_line.amount_currency == -70.00: + assert move_line.credit == 56.00, "Debtor account has wrong entry." + elif move_line.amount_currency == 10.00: + assert move_line.debit == 8.00, "Writeoff amount is wrong: Got a debit of %s (expected 8,00€)" % (move_line.debit) + elif move_line.amount_currency == 240.00: + assert move_line.debit == 192.00, "Bank entry is wrong." + else: + assert False, "Unrecognized journal entry" +- + I check the residual amount of Invoice1, should be 20 in amount_currency and 6 in amount_residual +- + !python {model: account.invoice}: | + invoice_id = self.browse(cr, uid, ref("account_invoice_jan_payment_rate")) + move_line_obj = self.pool.get('account.move.line') + move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) + move_line = move_line_obj.browse(cr, uid, move_lines[0]) + assert (move_line.amount_residual == 6.0) , "Residual amount is not correct for first Invoice" + assert (move_line.amount_residual_currency == 20.0) , "Residual amount in currency is not correct for first Invoice" +- + I check the residual amuont of Invoice2, should be 30 in residual currency and 24 in amount_residual +- + !python {model: account.invoice}: | + invoice_id = self.browse(cr, uid, ref("account_invoice_feb_payment_rate")) + move_line_obj = self.pool.get('account.move.line') + move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) + move_line = move_line_obj.browse(cr, uid, move_lines[0]) + assert (move_line.amount_residual == 24.0) , "Residual amount is not correct for second Invoice" + assert (move_line.amount_residual_currency == 30.0) , "Residual amount in currency is not correct for second Invoice" diff --git a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml index 02dd82f5c14..f523e312933 100644 --- a/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml +++ b/addons/account_voucher/test/case2_usd_eur_debtor_in_eur.yml @@ -201,7 +201,7 @@ move_line_obj = self.pool.get('account.move.line') move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)]) move_line = move_line_obj.browse(cr, uid, move_lines[0]) - assert (move_line.amount_residual_currency == 55.56 and move_line.amount_residual == 20) , "Residual amount is not correct for first Invoice" + assert (move_line.amount_residual_currency == 55.56 and move_line.amount_residual == 20) , "Residual amount is not correct for first Invoice. Got %s USD (%s EUR)" %(move_line.amount_residual_currency, move_line.amount_residual) - I check the residual amuont of Invoice2, should be 22.22 in residual currency and 10 in amount_residual - diff --git a/addons/account_voucher/test/case4_cad_chf.yml b/addons/account_voucher/test/case4_cad_chf.yml index a0ef13d96aa..90c36e371bf 100644 --- a/addons/account_voucher/test/case4_cad_chf.yml +++ b/addons/account_voucher/test/case4_cad_chf.yml @@ -161,7 +161,7 @@ - I check that the debtor account has 1 new line with -298.78 as amount_currency columns and 149.39 of credit and currency is CAD. - - I check that my currency rate difference is correct. 0 in debit with no amount_currency + I check that my currency rate difference is correct. 0 in debit with 98.78 CAD as amount_currency - I check that my writeoff is correct. 11.05 credit and -13.26 amount_currency - @@ -176,7 +176,8 @@ elif move_line.amount_currency == -298.78: assert move_line.credit == 149.39, "Debtor account has wrong entry." elif move_line.debit == 0.00 and move_line.credit == 0.00: - assert move_line.amount_currency == 0.00, "Incorrect Currency Difference." + assert move_line.amount_currency == 98.78, "Incorrect Currency Difference, got %s as amount_currency (expected 98.78)." % (move_line.amount_currency) + assert move_line.currency_id.id == ref('base.CAD'), "Incorrect Currency Difference, got %s (expected 'CAD')" % (move_line.currency_id.name) elif move_line.credit == 10.61: assert move_line.amount_currency == -13.26, "Writeoff amount is wrong." else: diff --git a/addons/account_voucher/test/case_eur_usd.yml b/addons/account_voucher/test/case_eur_usd.yml index 94f0c718980..8dce677fd9a 100644 --- a/addons/account_voucher/test/case_eur_usd.yml +++ b/addons/account_voucher/test/case_eur_usd.yml @@ -41,7 +41,7 @@ currency: base.USD company_id: base.main_company - - I create an invoice + On the first of January, I create an invoice of 1000€ - !record {model: account.invoice, id: account_invoice_eur_usd}: account_id: account.a_recv @@ -79,7 +79,7 @@ !context 'type': 'receipt' - - I create the voucher of payment with values 1350 USD, journal USD, + On the first of February, I create the voucher of payment with values 1350 USD, journal USD, - !record {model: account.voucher, id: account_voucher_eur_usd_case, view: view_vendor_receipt_form}: account_id: account.cash diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 109c2f9aec9..dea94d59f4e 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -46,6 +46,9 @@
+ + + account.voucher.payment.low.priority.form account.voucher @@ -107,7 +110,7 @@ - + @@ -119,6 +122,7 @@ + account.voucher.payment.form account.voucher @@ -157,7 +161,7 @@ + account.voucher.receipt.form account.voucher @@ -467,10 +482,14 @@ - + - - + diff --git a/addons/account_voucher/voucher_sales_purchase_view.xml b/addons/account_voucher/voucher_sales_purchase_view.xml index 6a84a09d5e6..dc732129803 100644 --- a/addons/account_voucher/voucher_sales_purchase_view.xml +++ b/addons/account_voucher/voucher_sales_purchase_view.xml @@ -145,6 +145,13 @@ + + + + + + +
@@ -237,6 +244,7 @@ on_change="onchange_journal(journal_id, line_dr_ids, tax_id, partner_id, date, amount, type, company_id, context)" groups="account.group_account_user"/> + diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index ac298713b04..df852181709 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -33,9 +33,9 @@ class account_analytic_account(osv.osv): _description = 'Analytic Account' _track = { 'state': { - 'analytic.mt_account_pending': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'pending', - 'analytic.mt_account_closed': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'close', - 'analytic.mt_account_opened': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'open', + 'analytic.mt_account_pending': lambda self, cr, uid, obj, ctx=None: obj.state == 'pending', + 'analytic.mt_account_closed': lambda self, cr, uid, obj, ctx=None: obj.state == 'close', + 'analytic.mt_account_opened': lambda self, cr, uid, obj, ctx=None: obj.state == 'open', }, } @@ -157,7 +157,7 @@ class account_analytic_account(osv.osv): for account in self.browse(cr, uid, ids, context=context): if account.company_id: if account.company_id.currency_id.id != value: - raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really usefull for consolidation purposes of several companies charts with different currencies, for example.")) + raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really useful for consolidation purposes of several companies charts with different currencies, for example.")) if value: return cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id, )) diff --git a/addons/analytic/i18n/lt.po b/addons/analytic/i18n/lt.po new file mode 100644 index 00000000000..d9073313307 --- /dev/null +++ b/addons/analytic/i18n/lt.po @@ -0,0 +1,388 @@ +# Lithuanian translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-04-29 15:10+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Lithuanian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-30 05:29+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: analytic +#: field:account.analytic.account,child_ids:0 +msgid "Child Accounts" +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,state:0 +msgid "In Progress" +msgstr "" + +#. module: analytic +#: code:addons/analytic/analytic.py:229 +#, python-format +msgid "Contract: " +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,state:0 +msgid "Template" +msgstr "" + +#. module: analytic +#: view:account.analytic.account:0 +msgid "End Date" +msgstr "" + +#. module: analytic +#: help:account.analytic.line,unit_amount:0 +msgid "Specifies the amount of quantity to count." +msgstr "" + +#. module: analytic +#: field:account.analytic.account,debit:0 +msgid "Debit" +msgstr "" + +#. module: analytic +#: help:account.analytic.account,type:0 +msgid "" +"If you select the View Type, it means you won't allow to create journal " +"entries using that account.\n" +"The type 'Analytic account' stands for usual accounts that you only want to " +"use in accounting.\n" +"If you select Contract or Project, it offers you the possibility to manage " +"the validity and the invoicing options for this account.\n" +"The special type 'Template of Contract' allows you to define a template with " +"default data that you can reuse easily." +msgstr "" + +#. module: analytic +#: view:account.analytic.account:0 +msgid "" +"Once the end date of the contract is\n" +" passed or the maximum number of " +"service\n" +" units (e.g. support contract) is\n" +" reached, the account manager is " +"notified \n" +" by email to renew the contract with " +"the\n" +" customer." +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,type:0 +msgid "Contract or Project" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,name:0 +msgid "Account/Contract Name" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,manager_id:0 +msgid "Account Manager" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,state:0 +msgid "Closed" +msgstr "" + +#. module: analytic +#: model:mail.message.subtype,name:analytic.mt_account_pending +msgid "Contract to Renew" +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,state:0 +msgid "New" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,user_id:0 +msgid "Project Manager" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,state:0 +msgid "Status" +msgstr "" + +#. module: analytic +#: code:addons/analytic/analytic.py:271 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: analytic +#: model:ir.model,name:analytic.model_account_analytic_line +msgid "Analytic Line" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,description:0 +#: field:account.analytic.line,name:0 +msgid "Description" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: analytic +#: constraint:account.analytic.account:0 +msgid "Error! You cannot create recursive analytic accounts." +msgstr "" + +#. module: analytic +#: field:account.analytic.account,company_id:0 +#: field:account.analytic.line,company_id:0 +msgid "Company" +msgstr "" + +#. module: analytic +#: view:account.analytic.account:0 +msgid "Renewal" +msgstr "" + +#. module: analytic +#: help:account.analytic.account,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: analytic +#: model:mail.message.subtype,description:analytic.mt_account_opened +msgid "Stage opened" +msgstr "" + +#. module: analytic +#: help:account.analytic.account,quantity_max:0 +msgid "" +"Sets the higher limit of time to work on the contract, based on the " +"timesheet. (for instance, number of hours in a limited support contract.)" +msgstr "" + +#. module: analytic +#: code:addons/analytic/analytic.py:160 +#, python-format +msgid "" +"If you set a company, the currency selected has to be the same as it's " +"currency. \n" +"You can remove the company belonging, and thus change the currency, only on " +"analytic account of type 'view'. This can be really usefull for " +"consolidation purposes of several companies charts with different " +"currencies, for example." +msgstr "" + +#. module: analytic +#: field:account.analytic.account,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: analytic +#: field:account.analytic.line,user_id:0 +msgid "User" +msgstr "" + +#. module: analytic +#: model:mail.message.subtype,description:analytic.mt_account_pending +msgid "Contract pending" +msgstr "" + +#. module: analytic +#: field:account.analytic.line,date:0 +msgid "Date" +msgstr "" + +#. module: analytic +#: model:mail.message.subtype,name:analytic.mt_account_closed +msgid "Contract Finished" +msgstr "" + +#. module: analytic +#: view:account.analytic.account:0 +msgid "Terms and Conditions" +msgstr "" + +#. module: analytic +#: help:account.analytic.line,amount:0 +msgid "" +"Calculated by multiplying the quantity and the price given in the Product's " +"cost price. Always expressed in the company main currency." +msgstr "" + +#. module: analytic +#: field:account.analytic.account,partner_id:0 +msgid "Customer" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,child_complete_ids:0 +msgid "Account Hierarchy" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,parent_id:0 +msgid "Parent Analytic Account" +msgstr "" + +#. module: analytic +#: view:account.analytic.account:0 +msgid "Contract Information" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,template_id:0 +#: selection:account.analytic.account,type:0 +msgid "Template of Contract" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,quantity_max:0 +msgid "Prepaid Service Units" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,credit:0 +msgid "Credit" +msgstr "" + +#. module: analytic +#: model:mail.message.subtype,name:analytic.mt_account_opened +msgid "Contract Opened" +msgstr "" + +#. module: analytic +#: model:mail.message.subtype,description:analytic.mt_account_closed +msgid "Contract closed" +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,state:0 +msgid "Cancelled" +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,type:0 +msgid "Analytic View" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,balance:0 +msgid "Balance" +msgstr "" + +#. module: analytic +#: help:account.analytic.account,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: analytic +#: selection:account.analytic.account,state:0 +msgid "To Renew" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,quantity:0 +#: field:account.analytic.line,unit_amount:0 +msgid "Quantity" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,date:0 +msgid "Date End" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,code:0 +msgid "Reference" +msgstr "" + +#. module: analytic +#: code:addons/analytic/analytic.py:160 +#, python-format +msgid "Error!" +msgstr "" + +#. module: analytic +#: model:res.groups,name:analytic.group_analytic_accounting +msgid "Analytic Accounting" +msgstr "" + +#. module: analytic +#: field:account.analytic.line,amount:0 +msgid "Amount" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,complete_name:0 +msgid "Full Account Name" +msgstr "" + +#. module: analytic +#: view:account.analytic.account:0 +#: selection:account.analytic.account,type:0 +#: field:account.analytic.line,account_id:0 +#: model:ir.model,name:analytic.model_account_analytic_account +msgid "Analytic Account" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,currency_id:0 +msgid "Currency" +msgstr "" + +#. module: analytic +#: help:account.analytic.account,message_summary:0 +msgid "" +"Holds the Chatter summary (number of messages, ...). This summary is " +"directly in html format in order to be inserted in kanban views." +msgstr "" + +#. module: analytic +#: field:account.analytic.account,type:0 +msgid "Type of Account" +msgstr "" + +#. module: analytic +#: field:account.analytic.account,date_start:0 +msgid "Start Date" +msgstr "" + +#. module: analytic +#: constraint:account.analytic.line:0 +msgid "You cannot create analytic line on view account." +msgstr "" + +#. module: analytic +#: field:account.analytic.account,line_ids:0 +msgid "Analytic Entries" +msgstr "" diff --git a/addons/analytic/security/analytic_security.xml b/addons/analytic/security/analytic_security.xml index 70688275de2..bf103ca8988 100644 --- a/addons/analytic/security/analytic_security.xml +++ b/addons/analytic/security/analytic_security.xml @@ -4,14 +4,14 @@ Analytic multi company rule - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] Analytic line multi company rule - + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] diff --git a/addons/analytic_user_function/analytic_user_function.py b/addons/analytic_user_function/analytic_user_function.py index 0573292c1f6..1adefb2d59d 100644 --- a/addons/analytic_user_function/analytic_user_function.py +++ b/addons/analytic_user_function/analytic_user_function.py @@ -104,7 +104,7 @@ class hr_analytic_timesheet(osv.osv): a = r.product_id.categ_id.property_account_expense_categ.id if not a: raise osv.except_osv(_('Error!'), - _('There is no expense account define ' \ + _('There is no expense account defined ' \ 'for this product: "%s" (id:%d)') % \ (r.product_id.name, r.product_id.id,)) # Compute based on pricetype @@ -133,7 +133,7 @@ class hr_analytic_timesheet(osv.osv): a = r.product_id.categ_id.property_account_expense_categ.id if not a: raise osv.except_osv(_('Error!'), - _('There is no expense account define ' \ + _('There is no expense account defined ' \ 'for this product: "%s" (id:%d)') % \ (r.product_id.name, r.product_id.id,)) # Compute based on pricetype diff --git a/addons/anonymization/anonymization.py b/addons/anonymization/anonymization.py index 025f1f79f70..c82afde103f 100644 --- a/addons/anonymization/anonymization.py +++ b/addons/anonymization/anonymization.py @@ -86,11 +86,11 @@ class ir_model_fields_anonymization(osv.osv): if context.get('manual'): global_state = self._get_global_state(cr, uid, context=context) if global_state == 'anonymized': - raise osv.except_osv('Error !', "The database is currently anonymized, you cannot create, modify or delete fields.") + raise osv.except_osv('Error!', "The database is currently anonymized, you cannot create, modify or delete fields.") elif global_state == 'unstable': msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \ " while some fields are not anonymized. You should try to solve this problem before trying to create, write or delete fields.") - raise osv.except_osv('Error !', msg) + raise osv.except_osv('Error!', msg) return True @@ -357,7 +357,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory): else: msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \ " while some fields are not anonymized. You should try to solve this problem before trying to do anything else.") - raise osv.except_osv('Error !', msg) + raise osv.except_osv('Error!', msg) res['arch'] = etree.tostring(eview) @@ -521,11 +521,11 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory): # check that all the defined fields are in the 'anonymized' state state = ir_model_fields_anonymization_model._get_global_state(cr, uid, context=context) if state == 'clear': - raise osv.except_osv_('Error !', "The database is not currently anonymized, you cannot reverse the anonymization.") + raise osv.except_osv_('Error!', "The database is not currently anonymized, you cannot reverse the anonymization.") elif state == 'unstable': msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \ " while some fields are not anonymized. You should try to solve this problem before trying to do anything.") - raise osv.except_osv('Error !', msg) + raise osv.except_osv('Error!', msg) wizards = self.browse(cr, uid, ids, context=context) for wizard in wizards: @@ -543,6 +543,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory): fixes = group(fixes, ('model_name', 'field_name')) for line in data: + queries = [] table_name = self.pool[line['model_id']]._table if line['model_id'] in self.pool else None # check if custom sql exists: diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 3f7ef2f3f0c..35a06871696 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -7,7 +7,8 @@ from werkzeug.exceptions import BadRequest import openerp from openerp import SUPERUSER_ID -import openerp.addons.web.http as oeweb +import openerp.addons.web.http as http +from openerp.addons.web.http import request from openerp.addons.web.controllers.main import db_monodb, set_cookie_and_redirect, login_and_redirect from openerp.modules.registry import RegistryManager @@ -18,7 +19,7 @@ _logger = logging.getLogger(__name__) #---------------------------------------------------------- def fragment_to_query_string(func): @functools.wraps(func) - def wrapper(self, req, **kw): + def wrapper(self, **kw): if not kw: return """""" - return func(self, req, **kw) + return func(self, **kw) return wrapper #---------------------------------------------------------- # Controller #---------------------------------------------------------- -class OAuthController(oeweb.Controller): - _cp_path = '/auth_oauth' +class OAuthController(http.Controller): - @oeweb.jsonrequest - def list_providers(self, req, dbname): + @http.route('/auth_oauth/list_providers', type='json', auth='none') + def list_providers(self, dbname): try: registry = RegistryManager.get(dbname) with registry.cursor() as cr: @@ -51,9 +51,9 @@ class OAuthController(oeweb.Controller): l = [] return l - @oeweb.httprequest + @http.route('/auth_oauth/signin', type='http', auth='none') @fragment_to_query_string - def signin(self, req, **kw): + def signin(self, **kw): state = simplejson.loads(kw['state']) dbname = state['d'] provider = state['p'] @@ -71,7 +71,7 @@ class OAuthController(oeweb.Controller): url = '/#action=%s' % action elif menu: url = '/#menu_id=%s' % menu - return login_and_redirect(req, *credentials, redirect_url=url) + return login_and_redirect(*credentials, redirect_url=url) except AttributeError: # auth_signup is not installed _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,)) @@ -88,21 +88,24 @@ class OAuthController(oeweb.Controller): _logger.exception("OAuth2: %s" % str(e)) url = "/#action=login&oauth_error=2" - return set_cookie_and_redirect(req, url) + return set_cookie_and_redirect(url) - @oeweb.httprequest - def oea(self, req, **kw): + @http.route('/auth_oauth/oea', type='http', auth='none') + def oea(self, **kw): """login user via OpenERP Account provider""" dbname = kw.pop('db', None) if not dbname: - dbname = db_monodb(req) + dbname = db_monodb() if not dbname: return BadRequest() registry = RegistryManager.get(dbname) with registry.cursor() as cr: IMD = registry['ir.model.data'] - model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp') + try: + model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp') + except ValueError: + return set_cookie_and_redirect('/?db=%s' % dbname) assert model == 'auth.oauth.provider' state = { @@ -112,6 +115,6 @@ class OAuthController(oeweb.Controller): } kw['state'] = simplejson.dumps(state) - return self.signin(req, **kw) + return self.signin(**kw) # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.eot b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.eot old mode 100755 new mode 100644 diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.svg b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.svg old mode 100755 new mode 100644 diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf old mode 100755 new mode 100644 diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff old mode 100755 new mode 100644 diff --git a/addons/auth_oauth_signup/i18n/vi.po b/addons/auth_oauth_signup/i18n/vi.po new file mode 100644 index 00000000000..bdc3eff5b8d --- /dev/null +++ b/addons/auth_oauth_signup/i18n/vi.po @@ -0,0 +1,23 @@ +# Vietnamese translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-06-27 06:49+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Vietnamese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-06-28 05:42+0000\n" +"X-Generator: Launchpad (build 16681)\n" + +#. module: auth_oauth_signup +#: model:ir.model,name:auth_oauth_signup.model_res_users +msgid "Users" +msgstr "Người dùng" diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py index 1fcc34c82a0..a4ef1bfa07b 100644 --- a/addons/auth_openid/controllers/main.py +++ b/addons/auth_openid/controllers/main.py @@ -38,6 +38,8 @@ import openerp from openerp import SUPERUSER_ID from openerp.modules.registry import RegistryManager from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect +import openerp.addons.web.http as http +from openerp.addons.web.http import request from .. import utils @@ -88,20 +90,19 @@ class GoogleAppsAwareConsumer(consumer.GenericConsumer): return super(GoogleAppsAwareConsumer, self).complete(message, endpoint, return_to) -class OpenIDController(openerp.addons.web.http.Controller): - _cp_path = '/auth_openid/login' +class OpenIDController(http.Controller): _store = filestore.FileOpenIDStore(_storedir) _REQUIRED_ATTRIBUTES = ['email'] _OPTIONAL_ATTRIBUTES = 'nickname fullname postcode country language timezone'.split() - def _add_extensions(self, request): - """Add extensions to the request""" + def _add_extensions(self, oidrequest): + """Add extensions to the oidrequest""" sreg_request = sreg.SRegRequest(required=self._REQUIRED_ATTRIBUTES, optional=self._OPTIONAL_ATTRIBUTES) - request.addExtension(sreg_request) + oidrequest.addExtension(sreg_request) ax_request = ax.FetchRequest() for alias in self._REQUIRED_ATTRIBUTES: @@ -111,7 +112,7 @@ class OpenIDController(openerp.addons.web.http.Controller): uri = utils.SREG2AX[alias] ax_request.add(ax.AttrInfo(uri, required=False, alias=alias)) - request.addExtension(ax_request) + oidrequest.addExtension(ax_request) def _get_attributes_from_success_response(self, success_response): attrs = {} @@ -133,58 +134,58 @@ class OpenIDController(openerp.addons.web.http.Controller): attrs[attr] = value return attrs - def _get_realm(self, req): - return req.httprequest.host_url + def _get_realm(self): + return request.httprequest.host_url - @openerp.addons.web.http.httprequest - def verify_direct(self, req, db, url): - result = self._verify(req, db, url) + @http.route('/auth_openid/login/verify_direct', type='http', auth='none') + def verify_direct(self, db, url): + result = self._verify(db, url) if 'error' in result: return werkzeug.exceptions.BadRequest(result['error']) if result['action'] == 'redirect': return werkzeug.utils.redirect(result['value']) return result['value'] - @openerp.addons.web.http.jsonrequest - def verify(self, req, db, url): - return self._verify(req, db, url) + @http.route('/auth_openid/login/verify', type='json', auth='none') + def verify(self, db, url): + return self._verify(db, url) - def _verify(self, req, db, url): - redirect_to = werkzeug.urls.Href(req.httprequest.host_url + 'auth_openid/login/process')(session_id=req.session_id) - realm = self._get_realm(req) + def _verify(self, db, url): + redirect_to = werkzeug.urls.Href(request.httprequest.host_url + 'auth_openid/login/process')(session_id=request.session_id) + realm = self._get_realm() session = dict(dbname=db, openid_url=url) # TODO add origin page ? oidconsumer = consumer.Consumer(session, self._store) try: - request = oidconsumer.begin(url) + oidrequest = oidconsumer.begin(url) except consumer.DiscoveryFailure, exc: fetch_error_string = 'Error in discovery: %s' % (str(exc[0]),) return {'error': fetch_error_string, 'title': 'OpenID Error'} - if request is None: + if oidrequest is None: return {'error': 'No OpenID services found', 'title': 'OpenID Error'} - req.session.openid_session = session - self._add_extensions(request) + request.session.openid_session = session + self._add_extensions(oidrequest) - if request.shouldSendRedirect(): - redirect_url = request.redirectURL(realm, redirect_to) - return {'action': 'redirect', 'value': redirect_url, 'session_id': req.session_id} + if oidrequest.shouldSendRedirect(): + redirect_url = oidrequest.redirectURL(realm, redirect_to) + return {'action': 'redirect', 'value': redirect_url, 'session_id': request.session_id} else: - form_html = request.htmlMarkup(realm, redirect_to) - return {'action': 'post', 'value': form_html, 'session_id': req.session_id} + form_html = oidrequest.htmlMarkup(realm, redirect_to) + return {'action': 'post', 'value': form_html, 'session_id': request.session_id} - @openerp.addons.web.http.httprequest - def process(self, req, **kw): - session = getattr(req.session, 'openid_session', None) + @http.route('/auth_openid/login/process', type='http', auth='none') + def process(self, **kw): + session = getattr(request.session, 'openid_session', None) if not session: - return set_cookie_and_redirect(req, '/') + return set_cookie_and_redirect('/') oidconsumer = consumer.Consumer(session, self._store, consumer_class=GoogleAppsAwareConsumer) - query = req.httprequest.args - info = oidconsumer.complete(query, req.httprequest.base_url) + query = request.httprequest.args + info = oidconsumer.complete(query, request.httprequest.base_url) display_identifier = info.getDisplayIdentifier() session['status'] = info.status @@ -225,7 +226,7 @@ class OpenIDController(openerp.addons.web.http.Controller): # TODO fill empty fields with the ones from sreg/ax cr.commit() - return login_and_redirect(req, dbname, login, key) + return login_and_redirect(dbname, login, key) session['message'] = 'This OpenID identifier is not associated to any active users' @@ -241,11 +242,11 @@ class OpenIDController(openerp.addons.web.http.Controller): # information in a log. session['message'] = 'Verification failed.' - return set_cookie_and_redirect(req, '/#action=login&loginerror=1') + return set_cookie_and_redirect('/#action=login&loginerror=1') - @openerp.addons.web.http.jsonrequest - def status(self, req): - session = getattr(req.session, 'openid_session', {}) + @http.route('/auth_openid/login/status', type='json', auth='none') + def status(self): + session = getattr(request.session, 'openid_session', {}) return {'status': session.get('status'), 'message': session.get('message')} diff --git a/addons/auth_openid/i18n/ru.po b/addons/auth_openid/i18n/ru.po index 6041300fe60..68b36626056 100644 --- a/addons/auth_openid/i18n/ru.po +++ b/addons/auth_openid/i18n/ru.po @@ -8,21 +8,21 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2013-03-23 11:37+0000\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2013-05-28 06:19+0000\n" +"Last-Translator: Глория Хрусталёва \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-03-24 04:45+0000\n" -"X-Generator: Launchpad (build 16540)\n" +"X-Launchpad-Export-Date: 2013-05-29 05:37+0000\n" +"X-Generator: Launchpad (build 16640)\n" #. module: auth_openid #. openerp-web #: code:addons/auth_openid/static/src/xml/auth_openid.xml:24 #, python-format msgid "Username" -msgstr "" +msgstr "Имя пользователя" #. module: auth_openid #. openerp-web @@ -30,7 +30,7 @@ msgstr "" #: view:res.users:0 #, python-format msgid "OpenID" -msgstr "" +msgstr "OpenID" #. module: auth_openid #. openerp-web @@ -46,14 +46,14 @@ msgstr "" #: code:addons/auth_openid/static/src/xml/auth_openid.xml:10 #, python-format msgid "Google" -msgstr "" +msgstr "Google" #. module: auth_openid #. openerp-web #: code:addons/auth_openid/static/src/xml/auth_openid.xml:11 #, python-format msgid "Launchpad" -msgstr "" +msgstr "Launchpad" #. module: auth_openid #: help:res.users,openid_email:0 @@ -82,7 +82,7 @@ msgstr "" #: code:addons/auth_openid/static/src/xml/auth_openid.xml:8 #, python-format msgid "Password" -msgstr "" +msgstr "Пароль" #. module: auth_openid #. openerp-web @@ -94,4 +94,4 @@ msgstr "" #. module: auth_openid #: model:ir.model,name:auth_openid.model_res_users msgid "Users" -msgstr "" +msgstr "Пользователи" diff --git a/addons/auth_openid/i18n/vi.po b/addons/auth_openid/i18n/vi.po new file mode 100644 index 00000000000..d1040420132 --- /dev/null +++ b/addons/auth_openid/i18n/vi.po @@ -0,0 +1,97 @@ +# Vietnamese translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-06-27 16:29+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Vietnamese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-06-28 05:42+0000\n" +"X-Generator: Launchpad (build 16681)\n" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:24 +#, python-format +msgid "Username" +msgstr "Tên đăng nhập" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:12 +#: view:res.users:0 +#, python-format +msgid "OpenID" +msgstr "OpenID" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:30 +#: field:res.users,openid_url:0 +#, python-format +msgid "OpenID URL" +msgstr "Đường dẫn OpenID" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:9 +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:10 +#, python-format +msgid "Google" +msgstr "Google" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:11 +#, python-format +msgid "Launchpad" +msgstr "Launchpad" + +#. module: auth_openid +#: help:res.users,openid_email:0 +msgid "Used for disambiguation in case of a shared OpenID URL" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:18 +#, python-format +msgid "Google Apps Domain" +msgstr "" + +#. module: auth_openid +#: field:res.users,openid_email:0 +msgid "OpenID Email" +msgstr "OpenID Email" + +#. module: auth_openid +#: field:res.users,openid_key:0 +msgid "OpenID Key" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:8 +#, python-format +msgid "Password" +msgstr "Mật khẩu" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:10 +#, python-format +msgid "Google Apps" +msgstr "" + +#. module: auth_openid +#: model:ir.model,name:auth_openid.model_res_users +msgid "Users" +msgstr "Người dùng" diff --git a/addons/auth_openid/res_users.py b/addons/auth_openid/res_users.py index 47e119f2a1e..897dea07982 100644 --- a/addons/auth_openid/res_users.py +++ b/addons/auth_openid/res_users.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python ############################################################################## # # OpenERP, Open Source Management Solution diff --git a/addons/auth_openid/utils.py b/addons/auth_openid/utils.py index 806198f99c2..0474e23fe4b 100644 --- a/addons/auth_openid/utils.py +++ b/addons/auth_openid/utils.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python ############################################################################## # # OpenERP, Open Source Management Solution diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 924e1546862..e42dc64151f 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -23,14 +23,15 @@ import logging import openerp from openerp.modules.registry import RegistryManager from ..res_users import SignupError +import openerp.addons.web.http as http +from openerp.addons.web.http import request _logger = logging.getLogger(__name__) -class Controller(openerp.addons.web.http.Controller): - _cp_path = '/auth_signup' +class Controller(http.Controller): - @openerp.addons.web.http.jsonrequest - def get_config(self, req, dbname): + @http.route('/auth_signup/get_config', type='json', auth="none") + def get_config(self, dbname): """ retrieve the module config (which features are enabled) for the login page """ registry = RegistryManager.get(dbname) with registry.cursor() as cr: @@ -41,8 +42,8 @@ class Controller(openerp.addons.web.http.Controller): } return config - @openerp.addons.web.http.jsonrequest - def retrieve(self, req, dbname, token): + @http.route('/auth_signup/retrieve', type='json', auth="none") + def retrieve(self, dbname, token): """ retrieve the user info (name, login or email) corresponding to a signup token """ registry = RegistryManager.get(dbname) with registry.cursor() as cr: @@ -50,23 +51,23 @@ class Controller(openerp.addons.web.http.Controller): user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token) return user_info - @openerp.addons.web.http.jsonrequest - def signup(self, req, dbname, token, **values): + @http.route('/auth_signup/signup', type='json', auth="none") + def signup(self, dbname, token, **values): """ sign up a user (new or existing)""" try: - self._signup_with_values(req, dbname, token, values) + self._signup_with_values(dbname, token, values) except SignupError, e: return {'error': openerp.tools.exception_to_unicode(e)} return {} - def _signup_with_values(self, req, dbname, token, values): + def _signup_with_values(self, dbname, token, values): registry = RegistryManager.get(dbname) with registry.cursor() as cr: res_users = registry.get('res.users') res_users.signup(cr, openerp.SUPERUSER_ID, values, token) - @openerp.addons.web.http.jsonrequest - def reset_password(self, req, dbname, login): + @http.route('/auth_signup/reset_password', type='json', auth="none") + def reset_password(self, dbname, login): """ retrieve user, and perform reset password """ registry = RegistryManager.get(dbname) with registry.cursor() as cr: diff --git a/addons/auth_signup/i18n/lt.po b/addons/auth_signup/i18n/lt.po new file mode 100644 index 00000000000..7ae419856e6 --- /dev/null +++ b/addons/auth_signup/i18n/lt.po @@ -0,0 +1,279 @@ +# Lithuanian translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-04-29 15:13+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Lithuanian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-30 05:29+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: auth_signup +#: field:res.partner,signup_type:0 +msgid "Signup Token Type" +msgstr "" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_uninvited:0 +msgid "Allow external users to sign up" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:16 +#, python-format +msgid "Confirm Password" +msgstr "" + +#. module: auth_signup +#: help:base.config.settings,auth_signup_uninvited:0 +msgid "If unchecked, only invited users may sign up." +msgstr "" + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_base_config_settings +msgid "base.config.settings" +msgstr "" + +#. module: auth_signup +#: code:addons/auth_signup/res_users.py:265 +#, python-format +msgid "Cannot send email: user has no email address." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:24 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:28 +#, python-format +msgid "Reset password" +msgstr "" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_template_user_id:0 +msgid "Template user for new users created through signup" +msgstr "" + +#. module: auth_signup +#: model:email.template,subject:auth_signup.reset_password_email +msgid "Password reset" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:117 +#, python-format +msgid "Please enter a password and confirm it." +msgstr "" + +#. module: auth_signup +#: view:res.users:0 +msgid "Send an email to the user to (re)set their password." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:23 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:26 +#, python-format +msgid "Sign Up" +msgstr "" + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "New" +msgstr "" + +#. module: auth_signup +#: code:addons/auth_signup/res_users.py:258 +#, python-format +msgid "Mail sent to:" +msgstr "" + +#. module: auth_signup +#: field:res.users,state:0 +msgid "Status" +msgstr "" + +#. module: auth_signup +#: model:email.template,body_html:auth_signup.reset_password_email +msgid "" +"\n" +"

A password reset was requested for the OpenERP account linked to this " +"email.

\n" +"\n" +"

You may change your password by following this link.

\n" +"\n" +"

Note: If you do not expect this, you can safely ignore this email.

" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:111 +#, python-format +msgid "Please enter a name." +msgstr "" + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_res_users +msgid "Users" +msgstr "" + +#. module: auth_signup +#: field:res.partner,signup_url:0 +msgid "Signup URL" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:114 +#, python-format +msgid "Please enter a username." +msgstr "" + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "Active" +msgstr "" + +#. module: auth_signup +#: code:addons/auth_signup/res_users.py:269 +#, python-format +msgid "" +"Cannot send email: no outgoing email server configured.\n" +"You can configure it under Settings/General Settings." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:12 +#, python-format +msgid "Username" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:8 +#, python-format +msgid "Name" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:170 +#, python-format +msgid "Please enter a username or email address." +msgstr "" + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "Resetting Password" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:13 +#, python-format +msgid "Username (Email)" +msgstr "" + +#. module: auth_signup +#: field:res.partner,signup_expiration:0 +msgid "Signup Expiration" +msgstr "" + +#. module: auth_signup +#: help:base.config.settings,auth_signup_reset_password:0 +msgid "This allows users to trigger a password reset from the Login page." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:22 +#, python-format +msgid "Log in" +msgstr "" + +#. module: auth_signup +#: field:res.partner,signup_valid:0 +msgid "Signup Token is Valid" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:108 +#: code:addons/auth_signup/static/src/js/auth_signup.js:111 +#: code:addons/auth_signup/static/src/js/auth_signup.js:114 +#: code:addons/auth_signup/static/src/js/auth_signup.js:117 +#: code:addons/auth_signup/static/src/js/auth_signup.js:120 +#: code:addons/auth_signup/static/src/js/auth_signup.js:167 +#: code:addons/auth_signup/static/src/js/auth_signup.js:170 +#, python-format +msgid "Login" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:94 +#, python-format +msgid "Invalid signup token" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:120 +#, python-format +msgid "Passwords do not match; please retype them." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:108 +#: code:addons/auth_signup/static/src/js/auth_signup.js:167 +#, python-format +msgid "No database selected !" +msgstr "" + +#. module: auth_signup +#: view:res.users:0 +msgid "Reset Password" +msgstr "" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_reset_password:0 +msgid "Enable password reset from Login page" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:27 +#, python-format +msgid "Back to Login" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:22 +#, python-format +msgid "Sign up" +msgstr "" + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_res_partner +msgid "Partner" +msgstr "" + +#. module: auth_signup +#: field:res.partner,signup_token:0 +msgid "Signup Token" +msgstr "" diff --git a/addons/auth_signup/i18n/ru.po b/addons/auth_signup/i18n/ru.po index bddc6cde1ba..639a1e9bc3c 100644 --- a/addons/auth_signup/i18n/ru.po +++ b/addons/auth_signup/i18n/ru.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2012-12-11 06:59+0000\n" -"Last-Translator: FULL NAME \n" +"PO-Revision-Date: 2013-05-27 12:12+0000\n" +"Last-Translator: Глория Хрусталёва \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-03-16 05:52+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-05-28 05:17+0000\n" +"X-Generator: Launchpad (build 16640)\n" #. module: auth_signup #: field:res.partner,signup_type:0 @@ -25,25 +25,25 @@ msgstr "" #. module: auth_signup #: field:base.config.settings,auth_signup_uninvited:0 msgid "Allow external users to sign up" -msgstr "" +msgstr "Разрешить регистрацию внешним пользователям" #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/xml/auth_signup.xml:16 #, python-format msgid "Confirm Password" -msgstr "" +msgstr "Подтвердите пароль" #. module: auth_signup #: help:base.config.settings,auth_signup_uninvited:0 msgid "If unchecked, only invited users may sign up." msgstr "" -"Если отмечено, только приглашенные пользователи могут зарегистрироваться" +"Если не отмечено, только приглашенные пользователи могут зарегистрироваться" #. module: auth_signup #: model:ir.model,name:auth_signup.model_base_config_settings msgid "base.config.settings" -msgstr "" +msgstr "base.config.settings" #. module: auth_signup #: code:addons/auth_signup/res_users.py:265 @@ -57,17 +57,17 @@ msgstr "Невозможно отправить письмо: у пользов #: code:addons/auth_signup/static/src/xml/auth_signup.xml:28 #, python-format msgid "Reset password" -msgstr "" +msgstr "Сброс пароля" #. module: auth_signup #: field:base.config.settings,auth_signup_template_user_id:0 msgid "Template user for new users created through signup" -msgstr "" +msgstr "Шаблон новых пользователей, созданных в процессе регистрации" #. module: auth_signup #: model:email.template,subject:auth_signup.reset_password_email msgid "Password reset" -msgstr "" +msgstr "Сброс пароля" #. module: auth_signup #. openerp-web @@ -88,12 +88,12 @@ msgstr "" #: code:addons/auth_signup/static/src/xml/auth_signup.xml:26 #, python-format msgid "Sign Up" -msgstr "" +msgstr "Регистрация" #. module: auth_signup #: selection:res.users,state:0 msgid "New" -msgstr "" +msgstr "Новый" #. module: auth_signup #: code:addons/auth_signup/res_users.py:258 @@ -104,7 +104,7 @@ msgstr "" #. module: auth_signup #: field:res.users,state:0 msgid "Status" -msgstr "" +msgstr "Статус" #. module: auth_signup #: model:email.template,body_html:auth_signup.reset_password_email @@ -118,18 +118,27 @@ msgid "" "\n" "

Note: If you do not expect this, you can safely ignore this email.

" msgstr "" +"\n" +"

Был запрошен сброс пароля для аккаунта OpenERP связанного с этим адресом " +"эл.почты

\n" +"\n" +"

Вы можете сменить пароль, проследовав по ссылке.

\n" +"\n" +"

Примечание: если вы не запрашивали сброс пароля, просто проигнорируйте " +"данное письмо

" #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/js/auth_signup.js:111 #, python-format msgid "Please enter a name." -msgstr "" +msgstr "Пожалуйста, введите имя" #. module: auth_signup #: model:ir.model,name:auth_signup.model_res_users msgid "Users" -msgstr "" +msgstr "Пользователи" #. module: auth_signup #: field:res.partner,signup_url:0 @@ -146,7 +155,7 @@ msgstr "Пожалуйста, введите имя пользователя." #. module: auth_signup #: selection:res.users,state:0 msgid "Active" -msgstr "" +msgstr "Активен" #. module: auth_signup #: code:addons/auth_signup/res_users.py:269 @@ -155,39 +164,41 @@ msgid "" "Cannot send email: no outgoing email server configured.\n" "You can configure it under Settings/General Settings." msgstr "" +"Невозможно отправить email: не настроены сервера исходящей почты.\n" +"Вы можете настроить их в меню Настройки/Общие настройки" #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/xml/auth_signup.xml:12 #, python-format msgid "Username" -msgstr "" +msgstr "Имя пользователя" #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/xml/auth_signup.xml:8 #, python-format msgid "Name" -msgstr "" +msgstr "Имя" #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/js/auth_signup.js:170 #, python-format msgid "Please enter a username or email address." -msgstr "" +msgstr "Пожалуйста, введите имя пользователя или адрес эл. почты." #. module: auth_signup #: selection:res.users,state:0 msgid "Resetting Password" -msgstr "" +msgstr "Переустановка пароля" #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/xml/auth_signup.xml:13 #, python-format msgid "Username (Email)" -msgstr "" +msgstr "Имя пользователя (Email)" #. module: auth_signup #: field:res.partner,signup_expiration:0 @@ -198,13 +209,15 @@ msgstr "" #: help:base.config.settings,auth_signup_reset_password:0 msgid "This allows users to trigger a password reset from the Login page." msgstr "" +"Это позволяет пользователям запросить сброс пароля со страницы входа в " +"систему." #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/xml/auth_signup.xml:22 #, python-format msgid "Log in" -msgstr "" +msgstr "Вход" #. module: auth_signup #: field:res.partner,signup_valid:0 @@ -222,7 +235,7 @@ msgstr "" #: code:addons/auth_signup/static/src/js/auth_signup.js:170 #, python-format msgid "Login" -msgstr "" +msgstr "Вход" #. module: auth_signup #. openerp-web @@ -236,7 +249,7 @@ msgstr "" #: code:addons/auth_signup/static/src/js/auth_signup.js:120 #, python-format msgid "Passwords do not match; please retype them." -msgstr "" +msgstr "Пароли не совпадают; пожалуйста, введите их заново." #. module: auth_signup #. openerp-web @@ -244,7 +257,7 @@ msgstr "" #: code:addons/auth_signup/static/src/js/auth_signup.js:167 #, python-format msgid "No database selected !" -msgstr "" +msgstr "Не выбрана база данных!" #. module: auth_signup #: view:res.users:0 @@ -254,14 +267,14 @@ msgstr "" #. module: auth_signup #: field:base.config.settings,auth_signup_reset_password:0 msgid "Enable password reset from Login page" -msgstr "" +msgstr "Включить сброс пароля со страницы входа" #. module: auth_signup #. openerp-web #: code:addons/auth_signup/static/src/xml/auth_signup.xml:27 #, python-format msgid "Back to Login" -msgstr "" +msgstr "Вернуться к странице входа" #. module: auth_signup #. openerp-web @@ -273,7 +286,7 @@ msgstr "" #. module: auth_signup #: model:ir.model,name:auth_signup.model_res_partner msgid "Partner" -msgstr "" +msgstr "Партнер" #. module: auth_signup #: field:res.partner,signup_token:0 diff --git a/addons/auth_signup/i18n/vi.po b/addons/auth_signup/i18n/vi.po new file mode 100644 index 00000000000..a79bbcb7bb4 --- /dev/null +++ b/addons/auth_signup/i18n/vi.po @@ -0,0 +1,288 @@ +# Vietnamese translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-06-27 06:52+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Vietnamese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-06-28 05:42+0000\n" +"X-Generator: Launchpad (build 16681)\n" + +#. module: auth_signup +#: field:res.partner,signup_type:0 +msgid "Signup Token Type" +msgstr "Loại mã đăng ký" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_uninvited:0 +msgid "Allow external users to sign up" +msgstr "Cho phép người dùng bên ngoài đăng ký." + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:19 +#, python-format +msgid "Confirm Password" +msgstr "Xác nhận mật khẩu" + +#. module: auth_signup +#: help:base.config.settings,auth_signup_uninvited:0 +msgid "If unchecked, only invited users may sign up." +msgstr "Nếu không chọn, chỉ những người được mời mới được đăng ký." + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_base_config_settings +msgid "base.config.settings" +msgstr "" + +#. module: auth_signup +#: code:addons/auth_signup/res_users.py:266 +#, python-format +msgid "Cannot send email: user has no email address." +msgstr "Không thể gửi email: người dùng không có địa chỉ email" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:27 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:31 +#, python-format +msgid "Reset password" +msgstr "Đặt lại mật khẩu" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_template_user_id:0 +msgid "Template user for new users created through signup" +msgstr "Mẫu người dùng sử dụng khi đăng ký" + +#. module: auth_signup +#: model:email.template,subject:auth_signup.reset_password_email +msgid "Password reset" +msgstr "Quên mật khẩu" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:120 +#, python-format +msgid "Please enter a password and confirm it." +msgstr "Vui lòng nhập mật khẩu và xác nhận nó" + +#. module: auth_signup +#: view:res.users:0 +msgid "Send an email to the user to (re)set their password." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:26 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:29 +#, python-format +msgid "Sign Up" +msgstr "" + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "New" +msgstr "" + +#. module: auth_signup +#: code:addons/auth_signup/res_users.py:258 +#, python-format +msgid "Mail sent to:" +msgstr "" + +#. module: auth_signup +#: field:res.users,state:0 +msgid "Status" +msgstr "Trạng thái" + +#. module: auth_signup +#: model:email.template,body_html:auth_signup.reset_password_email +msgid "" +"\n" +"

A password reset was requested for the OpenERP account linked to this " +"email.

\n" +"\n" +"

You may change your password by following this link.

\n" +"\n" +"

Note: If you do not expect this, you can safely ignore this email.

" +msgstr "" +"\n" +"\\n\n" +"

Bạn có một yêu cầu reset mật khẩu từ tài khoản OpenERPA gắn với email " +"này.

\\n\n" +"\\n\n" +"

Bạn có thể thay đổi mật khẩu thông qua đường dẫn này.

\\n\n" +"\\n\n" +"

Lưu ý: Nếu đây không phải chủ ý của bạn. Bạn có thể bỏ qua email này.

" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:114 +#, python-format +msgid "Please enter a name." +msgstr "Xin nhập tên." + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_res_users +msgid "Users" +msgstr "Người dùng" + +#. module: auth_signup +#: field:res.partner,signup_url:0 +msgid "Signup URL" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:117 +#, python-format +msgid "Please enter a username." +msgstr "" + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "Active" +msgstr "" + +#. module: auth_signup +#: code:addons/auth_signup/res_users.py:270 +#, python-format +msgid "" +"Cannot send email: no outgoing email server configured.\n" +"You can configure it under Settings/General Settings." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:12 +#, python-format +msgid "Username" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:8 +#, python-format +msgid "Name" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:173 +#, python-format +msgid "Please enter a username or email address." +msgstr "" + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "Resetting Password" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:13 +#, python-format +msgid "Username (Email)" +msgstr "" + +#. module: auth_signup +#: field:res.partner,signup_expiration:0 +msgid "Signup Expiration" +msgstr "" + +#. module: auth_signup +#: help:base.config.settings,auth_signup_reset_password:0 +msgid "This allows users to trigger a password reset from the Login page." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:25 +#, python-format +msgid "Log in" +msgstr "" + +#. module: auth_signup +#: field:res.partner,signup_valid:0 +msgid "Signup Token is Valid" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:111 +#: code:addons/auth_signup/static/src/js/auth_signup.js:114 +#: code:addons/auth_signup/static/src/js/auth_signup.js:117 +#: code:addons/auth_signup/static/src/js/auth_signup.js:120 +#: code:addons/auth_signup/static/src/js/auth_signup.js:123 +#: code:addons/auth_signup/static/src/js/auth_signup.js:170 +#: code:addons/auth_signup/static/src/js/auth_signup.js:173 +#, python-format +msgid "Login" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:97 +#, python-format +msgid "Invalid signup token" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:123 +#, python-format +msgid "Passwords do not match; please retype them." +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:111 +#: code:addons/auth_signup/static/src/js/auth_signup.js:170 +#, python-format +msgid "No database selected !" +msgstr "" + +#. module: auth_signup +#: view:res.users:0 +msgid "Reset Password" +msgstr "" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_reset_password:0 +msgid "Enable password reset from Login page" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:30 +#, python-format +msgid "Back to Login" +msgstr "" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:22 +#, python-format +msgid "Sign up" +msgstr "" + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_res_partner +msgid "Partner" +msgstr "" + +#. module: auth_signup +#: field:res.partner,signup_token:0 +msgid "Signup Token" +msgstr "" diff --git a/addons/auth_signup/i18n/zh_CN.po b/addons/auth_signup/i18n/zh_CN.po index aa8d9f952c1..497b872997f 100644 --- a/addons/auth_signup/i18n/zh_CN.po +++ b/addons/auth_signup/i18n/zh_CN.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2013-04-16 04:33+0000\n" -"Last-Translator: Key \n" +"PO-Revision-Date: 2013-07-02 08:11+0000\n" +"Last-Translator: DWXXX \n" "Language-Team: Chinese (Simplified) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-04-17 05:15+0000\n" -"X-Generator: Launchpad (build 16567)\n" +"X-Launchpad-Export-Date: 2013-07-03 05:14+0000\n" +"X-Generator: Launchpad (build 16692)\n" #. module: auth_signup #: field:res.partner,signup_type:0 @@ -29,7 +29,7 @@ msgstr "允许外部用户登录" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/xml/auth_signup.xml:16 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:19 #, python-format msgid "Confirm Password" msgstr "确认密码" @@ -37,7 +37,7 @@ msgstr "确认密码" #. module: auth_signup #: help:base.config.settings,auth_signup_uninvited:0 msgid "If unchecked, only invited users may sign up." -msgstr "" +msgstr "如果不勾选,只有被邀请用户才能注册。" #. module: auth_signup #: model:ir.model,name:auth_signup.model_base_config_settings @@ -45,15 +45,15 @@ msgid "base.config.settings" msgstr "base.config.settings" #. module: auth_signup -#: code:addons/auth_signup/res_users.py:265 +#: code:addons/auth_signup/res_users.py:266 #, python-format msgid "Cannot send email: user has no email address." -msgstr "" +msgstr "无法发送邮件:用户邮件地址为空。" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/xml/auth_signup.xml:24 -#: code:addons/auth_signup/static/src/xml/auth_signup.xml:28 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:27 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:31 #, python-format msgid "Reset password" msgstr "重设密码" @@ -70,7 +70,7 @@ msgstr "重置密码" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:117 +#: code:addons/auth_signup/static/src/js/auth_signup.js:120 #, python-format msgid "Please enter a password and confirm it." msgstr "请输入密码并确认。" @@ -78,12 +78,12 @@ msgstr "请输入密码并确认。" #. module: auth_signup #: view:res.users:0 msgid "Send an email to the user to (re)set their password." -msgstr "" +msgstr "向用户发送重置密码邮件。" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/xml/auth_signup.xml:23 #: code:addons/auth_signup/static/src/xml/auth_signup.xml:26 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:29 #, python-format msgid "Sign Up" msgstr "注册" @@ -119,10 +119,10 @@ msgstr "" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:111 +#: code:addons/auth_signup/static/src/js/auth_signup.js:114 #, python-format msgid "Please enter a name." -msgstr "" +msgstr "请输入名字" #. module: auth_signup #: model:ir.model,name:auth_signup.model_res_users @@ -136,10 +136,10 @@ msgstr "注册 URL" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:114 +#: code:addons/auth_signup/static/src/js/auth_signup.js:117 #, python-format msgid "Please enter a username." -msgstr "" +msgstr "请输入您的用户名" #. module: auth_signup #: selection:res.users,state:0 @@ -147,7 +147,7 @@ msgid "Active" msgstr "启用" #. module: auth_signup -#: code:addons/auth_signup/res_users.py:269 +#: code:addons/auth_signup/res_users.py:270 #, python-format msgid "" "Cannot send email: no outgoing email server configured.\n" @@ -170,10 +170,10 @@ msgstr "姓名" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:170 +#: code:addons/auth_signup/static/src/js/auth_signup.js:173 #, python-format msgid "Please enter a username or email address." -msgstr "" +msgstr "请输入用户名和邮件地址" #. module: auth_signup #: selection:res.users,state:0 @@ -199,7 +199,7 @@ msgstr "" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/xml/auth_signup.xml:22 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:25 #, python-format msgid "Log in" msgstr "登录" @@ -211,35 +211,35 @@ msgstr "注册令牌( Token )是有效的" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:108 #: code:addons/auth_signup/static/src/js/auth_signup.js:111 #: code:addons/auth_signup/static/src/js/auth_signup.js:114 #: code:addons/auth_signup/static/src/js/auth_signup.js:117 #: code:addons/auth_signup/static/src/js/auth_signup.js:120 -#: code:addons/auth_signup/static/src/js/auth_signup.js:167 +#: code:addons/auth_signup/static/src/js/auth_signup.js:123 #: code:addons/auth_signup/static/src/js/auth_signup.js:170 +#: code:addons/auth_signup/static/src/js/auth_signup.js:173 #, python-format msgid "Login" msgstr "" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:94 +#: code:addons/auth_signup/static/src/js/auth_signup.js:97 #, python-format msgid "Invalid signup token" msgstr "" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:120 +#: code:addons/auth_signup/static/src/js/auth_signup.js:123 #, python-format msgid "Passwords do not match; please retype them." msgstr "" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/js/auth_signup.js:108 -#: code:addons/auth_signup/static/src/js/auth_signup.js:167 +#: code:addons/auth_signup/static/src/js/auth_signup.js:111 +#: code:addons/auth_signup/static/src/js/auth_signup.js:170 #, python-format msgid "No database selected !" msgstr "" @@ -256,7 +256,7 @@ msgstr "" #. module: auth_signup #. openerp-web -#: code:addons/auth_signup/static/src/xml/auth_signup.xml:27 +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:30 #, python-format msgid "Back to Login" msgstr "返回登录页面" @@ -266,12 +266,12 @@ msgstr "返回登录页面" #: code:addons/auth_signup/static/src/xml/auth_signup.xml:22 #, python-format msgid "Sign up" -msgstr "" +msgstr "注册" #. module: auth_signup #: model:ir.model,name:auth_signup.model_res_partner msgid "Partner" -msgstr "业务伙伴" +msgstr "合作伙伴" #. module: auth_signup #: field:res.partner,signup_token:0 diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index f4a985280ac..891837f8813 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -23,6 +23,7 @@ import random from urllib import urlencode from urlparse import urljoin +from openerp.addons.base.ir.ir_mail_server import MailDeliveryException from openerp.osv import osv, fields from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT from openerp.tools.safe_eval import safe_eval @@ -55,19 +56,22 @@ class res_partner(osv.Model): def _get_signup_url_for_action(self, cr, uid, ids, action='login', view_type=None, menu_id=None, res_id=None, model=None, context=None): """ generate a signup url for the given partner ids and action, possibly overriding the url state components (menu_id, id, view_type) """ + if context is None: + context= {} res = dict.fromkeys(ids, False) base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') for partner in self.browse(cr, uid, ids, context): # when required, make sure the partner has a valid signup token - if context and context.get('signup_valid') and not partner.user_ids: + if context.get('signup_valid') and not partner.user_ids: self.signup_prepare(cr, uid, [partner.id], context=context) partner.refresh() # the parameters to encode for the query and fragment part of url query = {'db': cr.dbname} - fragment = {'action': action, 'type': partner.signup_type} + signup_type = context.get('signup_force_type_in_url', partner.signup_type or '') + fragment = {'action': action, 'type': signup_type} - if partner.signup_token: + if partner.signup_token and signup_type: fragment['token'] = partner.signup_token elif partner.user_ids: fragment['db'] = cr.dbname @@ -103,6 +107,9 @@ class res_partner(osv.Model): def action_signup_prepare(self, cr, uid, ids, context=None): return self.signup_prepare(cr, uid, ids, context=context) + def signup_cancel(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'signup_token': False, 'signup_type': False, 'signup_expiration': False}, context=context) + def signup_prepare(self, cr, uid, ids, signup_type="signup", expiration=False, context=None): """ generate a new token for the partners with the given validity, if necessary :param expiration: the expiration datetime of the token (string, optional) @@ -202,7 +209,7 @@ class res_users(osv.Model): }) if partner.company_id: values['company_id'] = partner.company_id.id - values['company_ids'] = [(6,0,[partner.company_id.id])] + values['company_ids'] = [(6, 0, [partner.company_id.id])] self._signup_create_user(cr, uid, values, context=context) else: # no token, sign up an external user @@ -259,25 +266,26 @@ class res_users(osv.Model): pass if not bool(template): template = self.pool.get('ir.model.data').get_object(cr, uid, 'auth_signup', 'reset_password_email') - mail_obj = self.pool.get('mail.mail') assert template._name == 'email.template' for user in self.browse(cr, uid, ids, context): if not user.email: raise osv.except_osv(_("Cannot send email: user has no email address."), user.name) - mail_id = self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, True, context=context) - mail_state = mail_obj.read(cr, uid, mail_id, ['state'], context=context) - - if mail_state and mail_state['state'] == 'exception': - raise self.pool.get('res.config.settings').get_config_warning(cr, _("Cannot send email: no outgoing email server configured.\nYou can configure it under %(menu:base_setup.menu_general_configuration)s."), context) - else: - return True + try: + self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, force_send=True, raise_exception=True, context=context) + except Exception: + raise def create(self, cr, uid, values, context=None): + if context is None: + context = {} # overridden to automatically invite user to sign up user_id = super(res_users, self).create(cr, uid, values, context=context) user = self.browse(cr, uid, user_id, context=context) - if context and context.get('reset_password') and user.email: - ctx = dict(context, create_user=True) - self.action_reset_password(cr, uid, [user.id], context=ctx) + if user.email and not context.get('no_reset_password'): + context.update({'create_user': True}) + try: + self.action_reset_password(cr, uid, [user.id], context=context) + except MailDeliveryException: + self.pool.get('res.partner').signup_cancel(cr, uid, [user.partner_id.id], context=context) return user_id diff --git a/addons/auth_signup/res_users_view.xml b/addons/auth_signup/res_users_view.xml index 28f66eb101d..60c419db737 100644 --- a/addons/auth_signup/res_users_view.xml +++ b/addons/auth_signup/res_users_view.xml @@ -31,9 +31,11 @@
+ +
diff --git a/addons/base_status/base_state.py b/addons/base_status/base_state.py index b856bbd74ad..3fe59ecbd21 100644 --- a/addons/base_status/base_state.py +++ b/addons/base_status/base_state.py @@ -104,7 +104,7 @@ class base_state(object): if parent_id.change_responsible and parent_id.user_id: data['user_id'] = parent_id.user_id.id else: - raise osv.except_osv(_('Error !'), _('You can not escalate, you are already at the top level regarding your sales-team category.')) + raise osv.except_osv(_('Error!'), _('You can not escalate, you are already at the top level regarding your sales-team category.')) self.write(cr, uid, [case.id], data, context=context) case.case_escalate_send_note(parent_id, context=context) return True diff --git a/addons/base_status/i18n/lt.po b/addons/base_status/i18n/lt.po new file mode 100644 index 00000000000..cdaf9b0db37 --- /dev/null +++ b/addons/base_status/i18n/lt.po @@ -0,0 +1,76 @@ +# Lithuanian translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-04-29 15:17+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Lithuanian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-30 05:29+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "Error !" +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:166 +#, python-format +msgid "%s has been opened." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:199 +#, python-format +msgid "%s has been renewed." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "Error!" +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "" +"You can not escalate, you are already at the top level regarding your sales-" +"team category." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:193 +#, python-format +msgid "%s is now pending." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:187 +#, python-format +msgid "%s has been canceled." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "" +"You are already at the top level of your sales-team category.\n" +"Therefore you cannot escalate furthermore." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:181 +#, python-format +msgid "%s has been closed." +msgstr "" diff --git a/addons/base_status/i18n/ru.po b/addons/base_status/i18n/ru.po index 546f2772af3..2dab7ceaf31 100644 --- a/addons/base_status/i18n/ru.po +++ b/addons/base_status/i18n/ru.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2012-12-28 10:04+0000\n" +"PO-Revision-Date: 2013-06-05 07:16+0000\n" "Last-Translator: Chertykov Denis \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-03-16 05:52+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-06-06 05:21+0000\n" +"X-Generator: Launchpad (build 16667)\n" #. module: base_status #: code:addons/base_status/base_state.py:107 @@ -27,13 +27,13 @@ msgstr "Ошибка !" #: code:addons/base_status/base_state.py:166 #, python-format msgid "%s has been opened." -msgstr "" +msgstr "%s было открыто." #. module: base_status #: code:addons/base_status/base_state.py:199 #, python-format msgid "%s has been renewed." -msgstr "" +msgstr "%s было обновлено." #. module: base_status #: code:addons/base_status/base_stage.py:210 @@ -55,13 +55,13 @@ msgstr "" #: code:addons/base_status/base_state.py:193 #, python-format msgid "%s is now pending." -msgstr "" +msgstr "%s сейчас в ожидании." #. module: base_status #: code:addons/base_status/base_state.py:187 #, python-format msgid "%s has been canceled." -msgstr "" +msgstr "%s было отменено." #. module: base_status #: code:addons/base_status/base_stage.py:210 @@ -70,9 +70,11 @@ msgid "" "You are already at the top level of your sales-team category.\n" "Therefore you cannot escalate furthermore." msgstr "" +"Вы уже на высшем уровне категории вашей команды продаж.\n" +"Поэтому вы не можете обострить." #. module: base_status #: code:addons/base_status/base_state.py:181 #, python-format msgid "%s has been closed." -msgstr "" +msgstr "%s было закрыто." diff --git a/addons/base_status/i18n/sv.po b/addons/base_status/i18n/sv.po new file mode 100644 index 00000000000..eb1b42e6a53 --- /dev/null +++ b/addons/base_status/i18n/sv.po @@ -0,0 +1,79 @@ +# Swedish translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-07-08 15:10+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Swedish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-07-09 05:16+0000\n" +"X-Generator: Launchpad (build 16696)\n" + +#. module: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "Error !" +msgstr "Fel !" + +#. module: base_status +#: code:addons/base_status/base_state.py:166 +#, python-format +msgid "%s has been opened." +msgstr "%s har öppnats." + +#. module: base_status +#: code:addons/base_status/base_state.py:199 +#, python-format +msgid "%s has been renewed." +msgstr "%s har förnyats." + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "Error!" +msgstr "Fel!" + +#. module: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "" +"You can not escalate, you are already at the top level regarding your sales-" +"team category." +msgstr "" +"Du kan inte eskalera längre, du har nått toppen för denna säljlags-kategori." + +#. module: base_status +#: code:addons/base_status/base_state.py:193 +#, python-format +msgid "%s is now pending." +msgstr "%s är nu pågående." + +#. module: base_status +#: code:addons/base_status/base_state.py:187 +#, python-format +msgid "%s has been canceled." +msgstr "%s har avbrutits." + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "" +"You are already at the top level of your sales-team category.\n" +"Therefore you cannot escalate furthermore." +msgstr "" +"Du har nått översta nivån för din säljlagskategori.\n" +"Det går därför inte att eskalera ytterligare." + +#. module: base_status +#: code:addons/base_status/base_state.py:181 +#, python-format +msgid "%s has been closed." +msgstr "%s har stängts." diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py index e7501334997..52db18b7307 100644 --- a/addons/base_vat/base_vat.py +++ b/addons/base_vat/base_vat.py @@ -83,6 +83,8 @@ class res_partner(osv.osv): Check the VAT number depending of the country. http://sima-pc.com/nif.php ''' + if not ustr(country_code).encode('utf-8').isalpha(): + return False check_func_name = 'check_vat_' + country_code check_func = getattr(self, check_func_name, None) or \ getattr(vatnumber, check_func_name, None) diff --git a/addons/board/__openerp__.py b/addons/board/__openerp__.py index e699e091176..87771b2f518 100644 --- a/addons/board/__openerp__.py +++ b/addons/board/__openerp__.py @@ -31,7 +31,7 @@ Lets the user create a custom dashboard. Allows users to create custom dashboard. """, 'author': 'OpenERP SA', - 'depends': ['base'], + 'depends': ['base', 'web'], 'data': [ 'security/ir.model.access.csv', 'board_view.xml', diff --git a/addons/board/static/src/js/dashboard.js b/addons/board/static/src/js/dashboard.js index 3489b686e1b..4f50d2281fe 100644 --- a/addons/board/static/src/js/dashboard.js +++ b/addons/board/static/src/js/dashboard.js @@ -344,7 +344,7 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({ }, load_data:function(){ var board = new instance.web.Model('board.board'); - return board.call('list'); + return board.call('list', [board.context()]); }, _x:function() { if (!instance.webclient) { return $.Deferred().reject(); } diff --git a/addons/claim_from_delivery/i18n/ru.po b/addons/claim_from_delivery/i18n/ru.po index 253e824d1e2..ffcf8fc2781 100644 --- a/addons/claim_from_delivery/i18n/ru.po +++ b/addons/claim_from_delivery/i18n/ru.po @@ -8,29 +8,29 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2010-09-30 06:47+0000\n" +"PO-Revision-Date: 2013-06-05 07:11+0000\n" "Last-Translator: Chertykov Denis \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-03-16 05:41+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-06-06 05:21+0000\n" +"X-Generator: Launchpad (build 16667)\n" #. module: claim_from_delivery #: view:stock.picking.out:0 msgid "Claims" -msgstr "" +msgstr "Рекламации" #. module: claim_from_delivery #: model:res.request.link,name:claim_from_delivery.request_link_claim_from_delivery msgid "Delivery Order" -msgstr "" +msgstr "Заказ доставки" #. module: claim_from_delivery #: model:ir.actions.act_window,name:claim_from_delivery.action_claim_from_delivery msgid "Claim From Delivery" -msgstr "" +msgstr "Рекламация по доставке" #~ msgid "Claim from delivery" #~ msgstr "Претензия из доставки" diff --git a/addons/claim_from_delivery/i18n/vi.po b/addons/claim_from_delivery/i18n/vi.po new file mode 100644 index 00000000000..f308bafb1ea --- /dev/null +++ b/addons/claim_from_delivery/i18n/vi.po @@ -0,0 +1,33 @@ +# Vietnamese translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-06-30 16:10+0000\n" +"Last-Translator: Hung Tran \n" +"Language-Team: Vietnamese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-07-01 05:14+0000\n" +"X-Generator: Launchpad (build 16692)\n" + +#. module: claim_from_delivery +#: view:stock.picking.out:0 +msgid "Claims" +msgstr "Các khiếu nại" + +#. module: claim_from_delivery +#: model:res.request.link,name:claim_from_delivery.request_link_claim_from_delivery +msgid "Delivery Order" +msgstr "" + +#. module: claim_from_delivery +#: model:ir.actions.act_window,name:claim_from_delivery.action_claim_from_delivery +msgid "Claim From Delivery" +msgstr "" diff --git a/addons/contacts/i18n/ko.po b/addons/contacts/i18n/ko.po new file mode 100644 index 00000000000..19e46f9e0b0 --- /dev/null +++ b/addons/contacts/i18n/ko.po @@ -0,0 +1,37 @@ +# Korean translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-06-28 09:32+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Korean \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-06-30 05:56+0000\n" +"X-Generator: Launchpad (build 16692)\n" + +#. module: contacts +#: model:ir.actions.act_window,help:contacts.action_contacts +msgid "" +"

\n" +" Click to add a contact in your address book.\n" +"

\n" +" OpenERP helps you easily track all activities related to\n" +" a customer; discussions, history of business opportunities,\n" +" documents, etc.\n" +"

\n" +" " +msgstr "" + +#. module: contacts +#: model:ir.actions.act_window,name:contacts.action_contacts +#: model:ir.ui.menu,name:contacts.menu_contacts +msgid "Contacts" +msgstr "연락처" diff --git a/addons/contacts/i18n/th.po b/addons/contacts/i18n/th.po new file mode 100644 index 00000000000..a75ecac2237 --- /dev/null +++ b/addons/contacts/i18n/th.po @@ -0,0 +1,37 @@ +# Thai translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-05-15 07:10+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Thai \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-05-16 05:12+0000\n" +"X-Generator: Launchpad (build 16626)\n" + +#. module: contacts +#: model:ir.actions.act_window,help:contacts.action_contacts +msgid "" +"

\n" +" Click to add a contact in your address book.\n" +"

\n" +" OpenERP helps you easily track all activities related to\n" +" a customer; discussions, history of business opportunities,\n" +" documents, etc.\n" +"

\n" +" " +msgstr "" + +#. module: contacts +#: model:ir.actions.act_window,name:contacts.action_contacts +#: model:ir.ui.menu,name:contacts.menu_contacts +msgid "Contacts" +msgstr "" diff --git a/addons/contacts/i18n/vi.po b/addons/contacts/i18n/vi.po new file mode 100644 index 00000000000..d404d947fe2 --- /dev/null +++ b/addons/contacts/i18n/vi.po @@ -0,0 +1,45 @@ +# Vietnamese translation for openobject-addons +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-06-27 16:47+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Vietnamese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-06-28 05:42+0000\n" +"X-Generator: Launchpad (build 16681)\n" + +#. module: contacts +#: model:ir.actions.act_window,help:contacts.action_contacts +msgid "" +"

\n" +" Click to add a contact in your address book.\n" +"

\n" +" OpenERP helps you easily track all activities related to\n" +" a customer; discussions, history of business opportunities,\n" +" documents, etc.\n" +"

\n" +" " +msgstr "" +"

\n" +" Nhấn để thêm liên lạc vào sổ địa chỉ.\n" +"

\n" +" OpenERP giúp bạn theo dõi các hoạt động liên quan tới\n" +" một khách hàng; thảo luận, lịch sử cơ hội kinh doanh,\n" +" tài liệu v.v....\n" +"

\n" +" " + +#. module: contacts +#: model:ir.actions.act_window,name:contacts.action_contacts +#: model:ir.ui.menu,name:contacts.menu_contacts +msgid "Contacts" +msgstr "Liên hệ" diff --git a/addons/contacts/static/src/img/icon.png b/addons/contacts/static/description/icon.png similarity index 100% rename from addons/contacts/static/src/img/icon.png rename to addons/contacts/static/description/icon.png diff --git a/addons/crm/__init__.py b/addons/crm/__init__.py index d78fb09eae7..4e3a704d5f3 100644 --- a/addons/crm/__init__.py +++ b/addons/crm/__init__.py @@ -28,6 +28,7 @@ import report import wizard import res_partner import res_config +import base_partner_merge # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 072624a7d98..e7ab7df27ea 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -81,8 +81,6 @@ Dashboard for CRM will include: 'crm_lead_view.xml', 'crm_lead_menu.xml', - 'crm_case_section_view.xml', - 'crm_meeting_menu.xml', 'crm_phonecall_view.xml', @@ -97,6 +95,9 @@ Dashboard for CRM will include: 'board_crm_view.xml', 'res_config_view.xml', + 'base_partner_merge_view.xml', + + 'crm_case_section_view.xml', ], 'demo': [ 'crm_demo.xml', @@ -120,7 +121,8 @@ Dashboard for CRM will include: 'static/src/css/crm.css' ], 'js': [ - 'static/src/js/crm.js' + 'static/lib/sparkline/jquery.sparkline.js', + 'static/src/js/crm_case_section.js', ], 'installable': True, 'application': True, diff --git a/addons/crm/base_partner_merge.py b/addons/crm/base_partner_merge.py new file mode 100644 index 00000000000..42e1ab7c7ec --- /dev/null +++ b/addons/crm/base_partner_merge.py @@ -0,0 +1,769 @@ +#!/usr/bin/env python +from __future__ import absolute_import +from email.utils import parseaddr +import functools +import htmlentitydefs +import itertools +import logging +import operator +import re +from ast import literal_eval +from openerp.tools import mute_logger + +# Validation Library https://pypi.python.org/pypi/validate_email/1.1 +from .validate_email import validate_email + +import openerp +from openerp.osv import osv, orm +from openerp.osv import fields +from openerp.osv.orm import browse_record +from openerp.tools.translate import _ + +pattern = re.compile("&(\w+?);") + +_logger = logging.getLogger('base.partner.merge') + + +# http://www.php2python.com/wiki/function.html-entity-decode/ +def html_entity_decode_char(m, defs=htmlentitydefs.entitydefs): + try: + return defs[m.group(1)] + except KeyError: + return m.group(0) + + +def html_entity_decode(string): + return pattern.sub(html_entity_decode_char, string) + + +def sanitize_email(email): + assert isinstance(email, basestring) and email + + result = re.subn(r';|/|:', ',', + html_entity_decode(email or ''))[0].split(',') + + emails = [parseaddr(email)[1] + for item in result + for email in item.split()] + + return [email.lower() + for email in emails + if validate_email(email)] + + +def is_integer_list(ids): + return all(isinstance(i, (int, long)) for i in ids) + + +class ResPartner(osv.Model): + _inherit = 'res.partner' + + _columns = { + 'id': fields.integer('Id', readonly=True), + 'create_date': fields.datetime('Create Date', readonly=True), + } + +class MergePartnerLine(osv.TransientModel): + _name = 'base.partner.merge.line' + + _columns = { + 'wizard_id': fields.many2one('base.partner.merge.automatic.wizard', + 'Wizard'), + 'min_id': fields.integer('MinID'), + 'aggr_ids': fields.char('Ids', required=True), + } + + _order = 'min_id asc' + + +class MergePartnerAutomatic(osv.TransientModel): + """ + The idea behind this wizard is to create a list of potential partners to + merge. We use two objects, the first one is the wizard for the end-user. + And the second will contain the partner list to merge. + """ + _name = 'base.partner.merge.automatic.wizard' + + _columns = { + # Group by + 'group_by_email': fields.boolean('Email'), + 'group_by_name': fields.boolean('Name'), + 'group_by_is_company': fields.boolean('Is Company'), + 'group_by_vat': fields.boolean('VAT'), + 'group_by_parent_id': fields.boolean('Parent Company'), + + 'state': fields.selection([('option', 'Option'), + ('selection', 'Selection'), + ('finished', 'Finished')], + 'State', + readonly=True, + required=True), + 'number_group': fields.integer("Group of Contacts", readonly=True), + 'current_line_id': fields.many2one('base.partner.merge.line', 'Current Line'), + 'line_ids': fields.one2many('base.partner.merge.line', 'wizard_id', 'Lines'), + 'partner_ids': fields.many2many('res.partner', string='Contacts'), + 'dst_partner_id': fields.many2one('res.partner', string='Destination Contact'), + + 'exclude_contact': fields.boolean('A user associated to the contact'), + 'exclude_journal_item': fields.boolean('Journal Items associated to the contact'), + 'maximum_group': fields.integer("Maximum of Group of Contacts"), + } + + def default_get(self, cr, uid, fields, context=None): + if context is None: + context = {} + res = super(MergePartnerAutomatic, self).default_get(cr, uid, fields, context) + if context.get('active_model') == 'res.partner' and context.get('active_ids'): + partner_ids = context['active_ids'] + res['state'] = 'selection' + res['partner_ids'] = partner_ids + res['dst_partner_id'] = self._get_ordered_partner(cr, uid, partner_ids, context=context)[-1].id + return res + + _defaults = { + 'state': 'option' + } + + def get_fk_on(self, cr, table): + q = """ SELECT cl1.relname as table, + att1.attname as column + FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, + pg_attribute as att1, pg_attribute as att2 + WHERE con.conrelid = cl1.oid + AND con.confrelid = cl2.oid + AND array_lower(con.conkey, 1) = 1 + AND con.conkey[1] = att1.attnum + AND att1.attrelid = cl1.oid + AND cl2.relname = %s + AND att2.attname = 'id' + AND array_lower(con.confkey, 1) = 1 + AND con.confkey[1] = att2.attnum + AND att2.attrelid = cl2.oid + AND con.contype = 'f' + """ + return cr.execute(q, (table,)) + + def _update_foreign_keys(self, cr, uid, src_partners, dst_partner, context=None): + _logger.debug('_update_foreign_keys for dst_partner: %s for src_partners: %r', dst_partner.id, list(map(operator.attrgetter('id'), src_partners))) + + # find the many2one relation to a partner + proxy = self.pool.get('res.partner') + self.get_fk_on(cr, 'res_partner') + + # ignore two tables + + for table, column in cr.fetchall(): + if 'base_partner_merge_' in table: + continue + partner_ids = tuple(map(int, src_partners)) + + query = "SELECT column_name FROM information_schema.columns WHERE table_name LIKE '%s'" % (table) + cr.execute(query, ()) + columns = [] + for data in cr.fetchall(): + if data[0] != column: + columns.append(data[0]) + + query_dic = { + 'table': table, + 'column': column, + 'value': columns[0], + } + if len(columns) <= 1: + # unique key treated + query = """ + UPDATE "%(table)s" as ___tu + SET %(column)s = %%s + WHERE + %(column)s = %%s AND + NOT EXISTS ( + SELECT 1 + FROM "%(table)s" as ___tw + WHERE + %(column)s = %%s AND + ___tu.%(value)s = ___tw.%(value)s + )""" % query_dic + for partner_id in partner_ids: + cr.execute(query, (dst_partner.id, partner_id, dst_partner.id)) + else: + cr.execute("SAVEPOINT recursive_partner_savepoint") + try: + query = 'UPDATE "%(table)s" SET %(column)s = %%s WHERE %(column)s IN %%s' % query_dic + cr.execute(query, (dst_partner.id, partner_ids,)) + + if column == proxy._parent_name and table == 'res_partner': + query = """ + WITH RECURSIVE cycle(id, parent_id) AS ( + SELECT id, parent_id FROM res_partner + UNION + SELECT cycle.id, res_partner.parent_id + FROM res_partner, cycle + WHERE res_partner.id = cycle.parent_id AND + cycle.id != cycle.parent_id + ) + SELECT id FROM cycle WHERE id = parent_id AND id = %s + """ + cr.execute(query, (dst_partner.id,)) + if cr.fetchall(): + cr.execute("ROLLBACK TO SAVEPOINT recursive_partner_savepoint") + finally: + cr.execute("RELEASE SAVEPOINT recursive_partner_savepoint") + + def _update_reference_fields(self, cr, uid, src_partners, dst_partner, context=None): + _logger.debug('_update_reference_fields for dst_partner: %s for src_partners: %r', dst_partner.id, list(map(operator.attrgetter('id'), src_partners))) + + def update_records(model, src, field_model='model', field_id='res_id', context=None): + proxy = self.pool.get(model) + if proxy is None: + return + domain = [(field_model, '=', 'res.partner'), (field_id, '=', src.id)] + ids = proxy.search(cr, openerp.SUPERUSER_ID, domain, context=context) + return proxy.write(cr, openerp.SUPERUSER_ID, ids, {field_id: dst_partner.id}, context=context) + + update_records = functools.partial(update_records, context=context) + + for partner in src_partners: + update_records('base.calendar', src=partner, field_model='model_id.model') + update_records('ir.attachment', src=partner, field_model='res_model') + update_records('mail.followers', src=partner, field_model='res_model') + update_records('mail.message', src=partner) + update_records('marketing.campaign.workitem', src=partner, field_model='object_id.model') + update_records('ir.model.data', src=partner) + + proxy = self.pool['ir.model.fields'] + domain = [('ttype', '=', 'reference')] + record_ids = proxy.search(cr, openerp.SUPERUSER_ID, domain, context=context) + + for record in proxy.browse(cr, openerp.SUPERUSER_ID, record_ids, context=context): + proxy_model = self.pool[record.model] + + field_type = proxy_model._columns.get(record.name).__class__._type + + if field_type == 'function': + continue + + for partner in src_partners: + domain = [ + (record.name, '=', 'res.partner,%d' % partner.id) + ] + model_ids = proxy_model.search(cr, openerp.SUPERUSER_ID, domain, context=context) + values = { + record.name: 'res.partner,%d' % dst_partner.id, + } + proxy_model.write(cr, openerp.SUPERUSER_ID, model_ids, values, context=context) + + def _update_values(self, cr, uid, src_partners, dst_partner, context=None): + _logger.debug('_update_values for dst_partner: %s for src_partners: %r', dst_partner.id, list(map(operator.attrgetter('id'), src_partners))) + + columns = dst_partner._columns + def write_serializer(column, item): + if isinstance(item, browse_record): + return item.id + else: + return item + + values = dict() + for column, field in columns.iteritems(): + if field._type not in ('many2many', 'one2many') and not isinstance(field, fields.function): + for item in itertools.chain(src_partners, [dst_partner]): + if item[column]: + values[column] = write_serializer(column, item[column]) + + values.pop('id', None) + parent_id = values.pop('parent_id', None) + dst_partner.write(values) + if parent_id and parent_id != dst_partner.id: + try: + dst_partner.write({'parent_id': parent_id}) + except (osv.except_osv, orm.except_orm): + _logger.info('Skip recursive partner hierarchies for parent_id %s of partner: %s', parent_id, dst_partner.id) + + @mute_logger('openerp.osv.expression', 'openerp.osv.orm') + def _merge(self, cr, uid, partner_ids, dst_partner=None, context=None): + proxy = self.pool.get('res.partner') + + partner_ids = proxy.exists(cr, uid, list(partner_ids), context=context) + if len(partner_ids) < 2: + return + + if len(partner_ids) > 3: + raise osv.except_osv(_('Error'), _("For safety reasons, you cannot merge more than 3 contacts together. You can re-open the wizard several times if needed.")) + + if openerp.SUPERUSER_ID != uid and len(set(partner.email for partner in proxy.browse(cr, uid, partner_ids, context=context))) > 1: + raise osv.except_osv(_('Error'), _("All contacts must have the same email. Only the Administrator can merge contacts with different emails.")) + + if dst_partner and dst_partner.id in partner_ids: + src_partners = proxy.browse(cr, uid, [id for id in partner_ids if id != dst_partner.id], context=context) + else: + ordered_partners = self._get_ordered_partner(cr, uid, partner_ids, context) + dst_partner = ordered_partners[-1] + src_partners = ordered_partners[:-1] + _logger.info("dst_partner: %s", dst_partner.id) + + if openerp.SUPERUSER_ID != uid and self._model_is_installed(cr, uid, 'account.move.line', context=context) and \ + self.pool.get('account.move.line').search(cr, openerp.SUPERUSER_ID, [('partner_id', 'in', [partner.id for partner in src_partners])], context=context): + raise osv.except_osv(_('Error'), _("Only the destination contact may be linked to existing Journal Items. Please ask the Administrator if you need to merge several contacts linked to existing Journal Items.")) + + call_it = lambda function: function(cr, uid, src_partners, dst_partner, + context=context) + + call_it(self._update_foreign_keys) + call_it(self._update_reference_fields) + call_it(self._update_values) + + _logger.info('(uid = %s) merged the partners %r with %s', uid, list(map(operator.attrgetter('id'), src_partners)), dst_partner.id) + dst_partner.message_post(body='%s %s'%(_("Merged with the following partners:"), ", ".join('%s<%s>(ID %s)' % (p.name, p.email or 'n/a', p.id) for p in src_partners))) + + for partner in src_partners: + partner.unlink() + + def clean_emails(self, cr, uid, context=None): + """ + Clean the email address of the partner, if there is an email field with + a mimum of two addresses, the system will create a new partner, with the + information of the previous one and will copy the new cleaned email into + the email field. + """ + if context is None: + context = {} + + proxy_model = self.pool['ir.model.fields'] + field_ids = proxy_model.search(cr, uid, [('model', '=', 'res.partner'), + ('ttype', 'like', '%2many')], + context=context) + fields = proxy_model.read(cr, uid, field_ids, context=context) + reset_fields = dict((field['name'], []) for field in fields) + + proxy_partner = self.pool['res.partner'] + context['active_test'] = False + ids = proxy_partner.search(cr, uid, [], context=context) + + fields = ['name', 'var' 'partner_id' 'is_company', 'email'] + partners = proxy_partner.read(cr, uid, ids, fields, context=context) + + partners.sort(key=operator.itemgetter('id')) + partners_len = len(partners) + + _logger.info('partner_len: %r', partners_len) + + for idx, partner in enumerate(partners): + if not partner['email']: + continue + + percent = (idx / float(partners_len)) * 100.0 + _logger.info('idx: %r', idx) + _logger.info('percent: %r', percent) + try: + emails = sanitize_email(partner['email']) + head, tail = emails[:1], emails[1:] + email = head[0] if head else False + + proxy_partner.write(cr, uid, [partner['id']], + {'email': email}, context=context) + + for email in tail: + values = dict(reset_fields, email=email) + proxy_partner.copy(cr, uid, partner['id'], values, + context=context) + + except Exception: + _logger.exception("There is a problem with this partner: %r", partner) + raise + return True + + def close_cb(self, cr, uid, ids, context=None): + return {'type': 'ir.actions.act_window_close'} + + def _generate_query(self, fields, maximum_group=100): + group_fields = ', '.join(fields) + + filters = [] + for field in fields: + if field in ['email', 'name']: + filters.append((field, 'IS NOT', 'NULL')) + + criteria = ' AND '.join('%s %s %s' % (field, operator, value) + for field, operator, value in filters) + + text = [ + "SELECT min(id), array_agg(id)", + "FROM res_partner", + ] + + if criteria: + text.append('WHERE %s' % criteria) + + text.extend([ + "GROUP BY %s" % group_fields, + "HAVING COUNT(*) >= 2", + "ORDER BY min(id)", + ]) + + if maximum_group: + text.extend([ + "LIMIT %s" % maximum_group, + ]) + + return ' '.join(text) + + def _compute_selected_groupby(self, this): + group_by_str = 'group_by_' + group_by_len = len(group_by_str) + + fields = [ + key[group_by_len:] + for key in self._columns.keys() + if key.startswith(group_by_str) + ] + + groups = [ + field + for field in fields + if getattr(this, '%s%s' % (group_by_str, field), False) + ] + + if not groups: + raise osv.except_osv(_('Error'), + _("You have to specify a filter for your selection")) + + return groups + + def next_cb(self, cr, uid, ids, context=None): + """ + Don't compute any thing + """ + context = dict(context or {}, active_test=False) + this = self.browse(cr, uid, ids[0], context=context) + if this.current_line_id: + this.current_line_id.unlink() + return self._next_screen(cr, uid, this, context) + + def _get_ordered_partner(self, cr, uid, partner_ids, context=None): + partners = self.pool.get('res.partner').browse(cr, uid, list(partner_ids), context=context) + ordered_partners = sorted(sorted(partners, + key=operator.attrgetter('create_date'), reverse=True), + key=operator.attrgetter('active'), reverse=True) + return ordered_partners + + def _next_screen(self, cr, uid, this, context=None): + this.refresh() + values = {} + if this.line_ids: + # in this case, we try to find the next record. + current_line = this.line_ids[0] + current_partner_ids = literal_eval(current_line.aggr_ids) + values.update({ + 'current_line_id': current_line.id, + 'partner_ids': [(6, 0, current_partner_ids)], + 'dst_partner_id': self._get_ordered_partner(cr, uid, current_partner_ids, context)[-1].id, + 'state': 'selection', + }) + else: + values.update({ + 'current_line_id': False, + 'partner_ids': [], + 'state': 'finished', + }) + + this.write(values) + + return { + 'type': 'ir.actions.act_window', + 'res_model': this._name, + 'res_id': this.id, + 'view_mode': 'form', + 'target': 'new', + } + + def _model_is_installed(self, cr, uid, model, context=None): + proxy = self.pool.get('ir.model') + domain = [('model', '=', model)] + return proxy.search_count(cr, uid, domain, context=context) > 0 + + def _partner_use_in(self, cr, uid, aggr_ids, models, context=None): + """ + Check if there is no occurence of this group of partner in the selected + model + """ + for model, field in models.iteritems(): + proxy = self.pool.get(model) + domain = [(field, 'in', aggr_ids)] + if proxy.search_count(cr, uid, domain, context=context): + return True + return False + + def compute_models(self, cr, uid, ids, context=None): + """ + Compute the different models needed by the system if you want to exclude + some partners. + """ + assert is_integer_list(ids) + + this = self.browse(cr, uid, ids[0], context=context) + + models = {} + if this.exclude_contact: + models['res.users'] = 'partner_id' + + if self._model_is_installed(cr, uid, 'account.move.line', context=context) and this.exclude_journal_item: + models['account.move.line'] = 'partner_id' + + return models + + def _process_query(self, cr, uid, ids, query, context=None): + """ + Execute the select request and write the result in this wizard + """ + proxy = self.pool.get('base.partner.merge.line') + this = self.browse(cr, uid, ids[0], context=context) + models = self.compute_models(cr, uid, ids, context=context) + cr.execute(query) + + counter = 0 + for min_id, aggr_ids in cr.fetchall(): + if models and self._partner_use_in(cr, uid, aggr_ids, models, context=context): + continue + values = { + 'wizard_id': this.id, + 'min_id': min_id, + 'aggr_ids': aggr_ids, + } + + proxy.create(cr, uid, values, context=context) + counter += 1 + + values = { + 'state': 'selection', + 'number_group': counter, + } + + this.write(values) + + _logger.info("counter: %s", counter) + + def start_process_cb(self, cr, uid, ids, context=None): + """ + Start the process. + * Compute the selected groups (with duplication) + * If the user has selected the 'exclude_XXX' fields, avoid the partners. + """ + assert is_integer_list(ids) + + context = dict(context or {}, active_test=False) + this = self.browse(cr, uid, ids[0], context=context) + groups = self._compute_selected_groupby(this) + query = self._generate_query(groups, this.maximum_group) + self._process_query(cr, uid, ids, query, context=context) + + return self._next_screen(cr, uid, this, context) + + def automatic_process_cb(self, cr, uid, ids, context=None): + assert is_integer_list(ids) + this = self.browse(cr, uid, ids[0], context=context) + this.start_process_cb() + this.refresh() + + for line in this.line_ids: + partner_ids = literal_eval(line.aggr_ids) + self._merge(cr, uid, partner_ids, context=context) + line.unlink() + cr.commit() + + this.write({'state': 'finished'}) + return { + 'type': 'ir.actions.act_window', + 'res_model': this._name, + 'res_id': this.id, + 'view_mode': 'form', + 'target': 'new', + } + + def parent_migration_process_cb(self, cr, uid, ids, context=None): + assert is_integer_list(ids) + + context = dict(context or {}, active_test=False) + this = self.browse(cr, uid, ids[0], context=context) + + query = """ + SELECT + min(p1.id), + array_agg(DISTINCT p1.id) + FROM + res_partner as p1 + INNER join + res_partner as p2 + ON + p1.email = p2.email AND + p1.name = p2.name AND + (p1.parent_id = p2.id OR p1.id = p2.parent_id) + WHERE + p2.id IS NOT NULL + GROUP BY + p1.email, + p1.name, + CASE WHEN p1.parent_id = p2.id THEN p2.id + ELSE p1.id + END + HAVING COUNT(*) >= 2 + ORDER BY + min(p1.id) + """ + + self._process_query(cr, uid, ids, query, context=context) + + for line in this.line_ids: + partner_ids = literal_eval(line.aggr_ids) + self._merge(cr, uid, partner_ids, context=context) + line.unlink() + cr.commit() + + this.write({'state': 'finished'}) + + cr.execute(""" + UPDATE + res_partner + SET + is_company = NULL, + parent_id = NULL + WHERE + parent_id = id + """) + + return { + 'type': 'ir.actions.act_window', + 'res_model': this._name, + 'res_id': this.id, + 'view_mode': 'form', + 'target': 'new', + } + + def update_all_process_cb(self, cr, uid, ids, context=None): + assert is_integer_list(ids) + + # WITH RECURSIVE cycle(id, parent_id) AS ( + # SELECT id, parent_id FROM res_partner + # UNION + # SELECT cycle.id, res_partner.parent_id + # FROM res_partner, cycle + # WHERE res_partner.id = cycle.parent_id AND + # cycle.id != cycle.parent_id + # ) + # UPDATE res_partner + # SET parent_id = NULL + # WHERE id in (SELECT id FROM cycle WHERE id = parent_id); + + this = self.browse(cr, uid, ids[0], context=context) + + self.parent_migration_process_cb(cr, uid, ids, context=None) + + list_merge = [ + {'group_by_vat': True, 'group_by_email': True, 'group_by_name': True}, + # {'group_by_name': True, 'group_by_is_company': True, 'group_by_parent_id': True}, + # {'group_by_email': True, 'group_by_is_company': True, 'group_by_parent_id': True}, + # {'group_by_name': True, 'group_by_vat': True, 'group_by_is_company': True, 'exclude_journal_item': True}, + # {'group_by_email': True, 'group_by_vat': True, 'group_by_is_company': True, 'exclude_journal_item': True}, + # {'group_by_email': True, 'group_by_is_company': True, 'exclude_contact': True, 'exclude_journal_item': True}, + # {'group_by_name': True, 'group_by_is_company': True, 'exclude_contact': True, 'exclude_journal_item': True} + ] + + for merge_value in list_merge: + id = self.create(cr, uid, merge_value, context=context) + self.automatic_process_cb(cr, uid, [id], context=context) + + cr.execute(""" + UPDATE + res_partner + SET + is_company = NULL + WHERE + parent_id IS NOT NULL AND + is_company IS NOT NULL + """) + + # cr.execute(""" + # UPDATE + # res_partner as p1 + # SET + # is_company = NULL, + # parent_id = ( + # SELECT p2.id + # FROM res_partner as p2 + # WHERE p2.email = p1.email AND + # p2.parent_id != p2.id + # LIMIT 1 + # ) + # WHERE + # p1.parent_id = p1.id + # """) + + return self._next_screen(cr, uid, this, context) + + def merge_cb(self, cr, uid, ids, context=None): + assert is_integer_list(ids) + + context = dict(context or {}, active_test=False) + this = self.browse(cr, uid, ids[0], context=context) + + partner_ids = set(map(int, this.partner_ids)) + if not partner_ids: + this.write({'state': 'finished'}) + return { + 'type': 'ir.actions.act_window', + 'res_model': this._name, + 'res_id': this.id, + 'view_mode': 'form', + 'target': 'new', + } + + self._merge(cr, uid, partner_ids, this.dst_partner_id, context=context) + + if this.current_line_id: + this.current_line_id.unlink() + + return self._next_screen(cr, uid, this, context) + + def auto_set_parent_id(self, cr, uid, ids, context=None): + assert is_integer_list(ids) + + # select partner who have one least invoice + partner_treated = ['@gmail.com'] + cr.execute(""" SELECT p.id, p.email + FROM res_partner as p + LEFT JOIN account_invoice as a + ON p.id = a.partner_id AND a.state in ('open','paid') + WHERE p.grade_id is NOT NULL + GROUP BY p.id + ORDER BY COUNT(a.id) DESC + """) + re_email = re.compile(r".*@") + for id, email in cr.fetchall(): + # check email domain + email = re_email.sub("@", email or "") + if not email or email in partner_treated: + continue + partner_treated.append(email) + + # don't update the partners if they are more of one who have invoice + cr.execute(""" SELECT * + FROM res_partner as p + WHERE p.id != %s AND p.email LIKE '%%%s' AND + EXISTS (SELECT * FROM account_invoice as a WHERE p.id = a.partner_id AND a.state in ('open','paid')) + """ % (id, email)) + + if len(cr.fetchall()) > 1: + _logger.info("%s MORE OF ONE COMPANY", email) + continue + + # to display changed values + cr.execute(""" SELECT id,email + FROM res_partner + WHERE parent_id != %s AND id != %s AND email LIKE '%%%s' + """ % (id, id, email)) + _logger.info("%r", cr.fetchall()) + + # upgrade + cr.execute(""" UPDATE res_partner + SET parent_id = %s + WHERE id != %s AND email LIKE '%%%s' + """ % (id, id, email)) + return False diff --git a/addons/crm/base_partner_merge_view.xml b/addons/crm/base_partner_merge_view.xml new file mode 100644 index 00000000000..8ce0b5fd99f --- /dev/null +++ b/addons/crm/base_partner_merge_view.xml @@ -0,0 +1,123 @@ + + + + + + + + Deduplicate Contacts + base.partner.merge.automatic.wizard + form + form + new + {'active_test': False} + + + + + + base.partner.merge.automatic.wizard.form + base.partner.merge.automatic.wizard + +
+
+
+ + +

There is no more contacts to merge for this request...

+ + + ' % i for i in manifest_list(req, None, 'js')) - css = "\n ".join('' % i for i in manifest_list(req, None, 'css')) + @http.route('/pos/app', type='http', auth='admin') + def app(self): + js = "\n ".join('' % i for i in manifest_list('js',db=request.db)) + css = "\n ".join('' % i for i in manifest_list('css',db=request.db)) - cookie = req.httprequest.cookies.get("instance0|session_id") + cookie = request.httprequest.cookies.get("instance0|session_id") session_id = cookie.replace("%22","") - template = html_template.replace(', 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:04+0000\n" +"PO-Revision-Date: 2013-06-09 16:04+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Hebrew \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-06-11 05:40+0000\n" +"X-Generator: Launchpad (build 16667)\n" + +#. module: point_of_sale +#: field:report.transaction.pos,product_nb:0 +msgid "Product Nb." +msgstr "מס' מוצר" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_trans_pos_tree_today +msgid "Sales by day" +msgstr "מחיר לפי יום" + +#. module: point_of_sale +#: model:ir.actions.act_window,help:point_of_sale.pos_category_action +msgid "" +"

\n" +" Click to define a new category.\n" +"

\n" +" Categories are used to browse your products through the\n" +" touchscreen interface.\n" +"

\n" +" If you put a photo on the category, the layout of the\n" +" touchscreen interface will automatically. We suggest not to " +"put\n" +" a photo on categories for small (1024x768) screens.\n" +"

\n" +" " +msgstr "" +"

\n" +" לחץ כדי להגדיר קטגוריה חדש.\n" +"

\n" +" קטגרויות נועדו לכך שתוכל לנווט במוצרים שלך\n" +" באמצעות מסך המגע.\n" +"

\n" +" במידה ותבחר תמונה עבור הקטגוריה תראה אותה בקטלוג\n" +" מוצרים בתוך הקופה שלך. אנו מציעים לא להשתמש בתמונות\n" +" עבור מסכים קטנים כגון 1024X768.\n" +"

\n" +" " + +#. module: point_of_sale +#: view:pos.receipt:0 +msgid "Print the Receipt of the Sale" +msgstr "הדפס קבלה עבור המכירה" + +#. module: point_of_sale +#: field:pos.session,cash_register_balance_end:0 +msgid "Computed Balance" +msgstr "יתרה מחושבת" + +#. module: point_of_sale +#: view:pos.session:0 +#: view:report.pos.order:0 +msgid "Today" +msgstr "נוכחי" + +#. module: point_of_sale +#: field:pos.config,iface_electronic_scale:0 +msgid "Electronic Scale Interface" +msgstr "ממשק משקל דיגיטלי" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.plain_water +msgid "Plain Water" +msgstr "מיים רגילים" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.poire_conference_product_template +msgid "Conference pears" +msgstr "אגסים" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:398 +#, python-format +msgid "ã" +msgstr "ã" + +#. module: point_of_sale +#: field:pos.config,journal_id:0 +#: field:pos.order,sale_journal:0 +msgid "Sale Journal" +msgstr "יומן מכירות" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.spa_2l_product_template +msgid "Spa Reine 2L" +msgstr "ספא רני 2 ליטר" + +#. module: point_of_sale +#: model:ir.actions.report.xml,name:point_of_sale.pos_lines_detail +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Details of Sales" +msgstr "פרטי מכירות" + +#. module: point_of_sale +#: constraint:pos.config:0 +msgid "You cannot have two cash controls in one Point Of Sale !" +msgstr "לא ניתן לשייך שתי בקרי מזומן לקופה רושמת אחת!" + +#. module: point_of_sale +#: field:pos.payment.report.user,user_id:0 +#: field:pos.sale.user,user_id:0 +#: field:pos.sales.user.today,user_id:0 +#: view:report.pos.order:0 +#: field:report.pos.order,user_id:0 +msgid "Salesperson" +msgstr "איש מכירות" + +#. module: point_of_sale +#: view:report.pos.order:0 +#: field:report.pos.order,day:0 +msgid "Day" +msgstr "יום" + +#. module: point_of_sale +#: field:report.sales.by.margin.pos,product_name:0 +#: field:report.sales.by.margin.pos.month,product_name:0 +msgid "Product Name" +msgstr "שם המוצר" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.pamplemousse_rouge_pamplemousse_product_template +msgid "Red grapefruit" +msgstr "אשכולית אדומה" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:1373 +#, python-format +msgid "Assign a Custom EAN" +msgstr "שייך מספר סידורי מותאם אישית" + +#. module: point_of_sale +#: view:pos.session.opening:0 +msgid "" +"You may have to control your cash amount in your cash register, before\n" +" being able to start selling through the " +"touchscreen interface." +msgstr "" +"יתכן ותצתרך לעשות ספירת מזומנים, לפני\n" +" שתוכל להתחיל למכור באמצעות קופה רושמת." + +#. module: point_of_sale +#: report:account.statement:0 +#: field:pos.box.entries,amount:0 +#: report:pos.invoice:0 +#: field:pos.make.payment,amount:0 +#: report:pos.user.product:0 +#: field:report.transaction.pos,amount:0 +msgid "Amount" +msgstr "סכום" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_pos_box_out +#: view:pos.session:0 +msgid "Take Money Out" +msgstr "הוצא את הכסף" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:105 +#, python-format +msgid "not used" +msgstr "לא בשימוש" + +#. module: point_of_sale +#: field:pos.config,iface_vkeyboard:0 +msgid "Virtual KeyBoard Interface" +msgstr "ממשק מקלדת וירטואלית" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:96 +#, python-format +msgid "+/-" +msgstr "+/-" + +#. module: point_of_sale +#: field:pos.ean_wizard,ean13_pattern:0 +msgid "Reference" +msgstr "ייחוס" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:1066 +#: code:addons/point_of_sale/point_of_sale.py:1083 +#: report:pos.invoice:0 +#: report:pos.lines:0 +#, python-format +msgid "Tax" +msgstr "מס" + +#. module: point_of_sale +#: report:pos.user.product:0 +msgid "Starting Date" +msgstr "תאריך התחלה" + +#. module: point_of_sale +#: constraint:pos.session:0 +msgid "You cannot create two active sessions with the same responsible!" +msgstr "אתה לא יכול ליצור שני מפגשים פעילים עם אותו אחראי!" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:473 +#, python-format +msgid "Weighting" +msgstr "שוקל" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.fenouil_fenouil_product_template +msgid "Fennel" +msgstr "שומר" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:472 +#, python-format +msgid "Help needed" +msgstr "צריך עזרה" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:760 +#, python-format +msgid "Configuration Error!" +msgstr "שגיאת הגדרות!" + +#. module: point_of_sale +#: report:account.statement:0 +#: model:ir.model,name:point_of_sale.model_res_partner +#: field:report.pos.order,partner_id:0 +msgid "Partner" +msgstr "שותף" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "Closing Cash Control" +msgstr "סגירת קופת מזומנים" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Total of the day" +msgstr "סה\"כ ליום" + +#. module: point_of_sale +#: view:report.pos.order:0 +#: field:report.pos.order,average_price:0 +msgid "Average Price" +msgstr "מחיר ממוצע" + +#. module: point_of_sale +#: view:pos.order:0 +msgid "Accounting Information" +msgstr "פרטי חשבון" + +#. module: point_of_sale +#: field:pos.session.opening,show_config:0 +msgid "Show Config" +msgstr "הצג הגדרות" + +#. module: point_of_sale +#: report:pos.lines:0 +msgid "Disc. (%)" +msgstr "תיאור (%)" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Total discount" +msgstr "סה\"כ הנחה" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:441 +#, python-format +msgid "Debug Window" +msgstr "חלון ניפוי שגיאות" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:241 +#: code:addons/point_of_sale/static/src/xml/pos.xml:613 +#, python-format +msgid "Change:" +msgstr "עודף:" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_regular_2l_product_template +msgid "Coca-Cola Regular 2L" +msgstr "קוקה קולה רגילה 2 ליטר" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_trans_pos_tree_month +msgid "Sales by month" +msgstr "מכירות לפי חודש" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.soda_orange +msgid "Orange" +msgstr "תפוז" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_report_sales_by_user_pos_today +#: view:report.sales.by.user.pos:0 +#: view:report.sales.by.user.pos.month:0 +msgid "Sales by User" +msgstr "מכירות למשתמש" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Disc.(%)" +msgstr "תיאור (%)" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:1031 +#, python-format +msgid "Please define income account for this product: \"%s\" (id:%d)." +msgstr "אנה הגדר חשבון הכנסות עבור מוצר זה: \"%s\" (id:%d)" + +#. module: point_of_sale +#: view:report.pos.order:0 +#: field:report.pos.order,price_total:0 +msgid "Total Price" +msgstr "סה\"כ מחיר" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.leffe_brune_33cl_product_template +msgid "Leffe Brune 33cl" +msgstr "לף קהה 330 מ\"ל" + +#. module: point_of_sale +#: help:pos.config,iface_self_checkout:0 +msgid "" +"Check this if this point of sale should open by default in a self checkout " +"mode. If unchecked, OpenERP uses the normal cashier mode by default." +msgstr "" +"סמן כאן במידה וקופה זה תומכת ברכישה אצמעית. במידה ולא סומן, OpenERP יגדיר " +"קופה רגילה כברירת מחדל." + +#. module: point_of_sale +#: model:ir.actions.report.xml,name:point_of_sale.pos_sales_user +#: report:pos.sales.user:0 +msgid "Sales Report" +msgstr "דוח מכירות" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.beverage +msgid "Beverages" +msgstr "משקאות" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_pos_session_opening +#: model:ir.ui.menu,name:point_of_sale.menu_pos_session_opening +msgid "Your Session" +msgstr "חשבון מכירות שלך" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.stella_50cl_product_template +msgid "Stella Artois 50cl" +msgstr "סטלה ארטוס 0.5 ליטר" + +#. module: point_of_sale +#: view:pos.details:0 +msgid "Dates" +msgstr "תאריכים" + +#. module: point_of_sale +#: field:pos.category,parent_id:0 +msgid "Parent Category" +msgstr "קטגוריית אב" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:482 +#, python-format +msgid "Open Cashbox" +msgstr "פתח מגירה" + +#. module: point_of_sale +#: view:pos.session.opening:0 +msgid "Select your Point of Sale" +msgstr "אנה בחר את הקופה שלך" + +#. module: point_of_sale +#: field:report.sales.by.margin.pos,total:0 +#: field:report.sales.by.margin.pos.month,total:0 +msgid "Margin" +msgstr "שוליים" + +#. module: point_of_sale +#: field:pos.discount,discount:0 +#: field:pos.order.line,discount:0 +msgid "Discount (%)" +msgstr "הנחה (%)" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.oetker_speciale_product_template +msgid "Dr. Oetker Ristorante Speciale" +msgstr "דר. אוייטקר מומחה מסעדנות" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:480 +#, python-format +msgid "Payment Request" +msgstr "בקשת תשלום" + +#. module: point_of_sale +#: field:product.product,to_weight:0 +msgid "To Weight" +msgstr "עבור משקל" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:476 +#, python-format +msgid "Hardware Events" +msgstr "איורעי חומרה" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:301 +#, python-format +msgid "You should assign a Point of Sale to your session." +msgstr "הינך חייב לבחור קופה לחשבון המכירות שלך" + +#. module: point_of_sale +#: view:pos.order.line:0 +msgid "Total qty" +msgstr "כמות כוללת" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.fanta_orange_33cl_product_template +msgid "Fanta Orange 33cl" +msgstr "פאנטה תופזים 330 מ\"ל" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:423 +#, python-format +msgid "" +"Please set your profit and loss accounts on your payment method '%s'. This " +"will allow OpenERP to post the difference of %.2f in your ending balance. To " +"close this session, you can update the 'Closing Cash Control' to avoid any " +"difference." +msgstr "" +"אנה בחר חשבון הרווח וההפסד שלך עבור שיתת תשלום '%s'. זה יאפשר לOpenERP להזין " +"הפרשי %.2f בתוך חשבון הסופי שלך. על מנת לסגור חשבון מכירות זה, אתה יכול " +"לעדכן את 'סיגרת קופת מזומנים' על מנת לא לגרום להפרשים." + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:315 +#: code:addons/point_of_sale/point_of_sale.py:514 +#, python-format +msgid "error!" +msgstr "שגיא!" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_report_sales_by_user_pos_month +msgid "Sales by User Monthly" +msgstr "מכירות חודשיות לפי משתמש" + +#. module: point_of_sale +#: help:pos.session,cash_register_difference:0 +msgid "" +"Difference between the counted cash control at the closing and the computed " +"balance." +msgstr "הפרשים בין ספירה ידנית לספירה ממוחשבת." + +#. module: point_of_sale +#: view:pos.session.opening:0 +msgid ") is \"" +msgstr ") הוא \"" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.Onions_product_template +msgid "Onions" +msgstr "בצלים" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "Validate & Open Session" +msgstr "אמת ופתח יומן מכירות" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:99 +#: selection:pos.session,state:0 +#: selection:pos.session.opening,pos_state:0 +#, python-format +msgid "In Progress" +msgstr "בתהליך" + +#. module: point_of_sale +#: view:pos.session:0 +#: field:pos.session,opening_details_ids:0 +msgid "Opening Cash Control" +msgstr "פתח קופת מזומנים" + +#. module: point_of_sale +#: help:res.users,ean13:0 +msgid "BarCode" +msgstr "ברקוד" + +#. module: point_of_sale +#: help:pos.category,image_medium:0 +msgid "" +"Medium-sized image of the category. It is automatically resized as a " +"128x128px image, with aspect ratio preserved. Use this field in form views " +"or some kanban views." +msgstr "" +"תמונה בגודל בינוני עבור קטגוריה זו. התמונות יוקטנו אוטומטית לגודל 128X128 " +"פיקסל, תוך כדי שמירה על יחס התמונה." + +#. module: point_of_sale +#: view:pos.session.opening:0 +msgid "Open Session" +msgstr "פתח הפעלה" + +#. module: point_of_sale +#: model:ir.ui.menu,name:point_of_sale.menu_point_of_sale +msgid "Daily Operations" +msgstr "פעולות יומיות" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:42 +#, python-format +msgid "Google Chrome" +msgstr "גוגל כרום" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.sparkling_water +msgid "Sparkling Water" +msgstr "מים מוגזים" + +#. module: point_of_sale +#: view:account.bank.statement:0 +msgid "Search Cash Statements" +msgstr "חיפוש דוחות מזומנים" + +#. module: point_of_sale +#: view:account.bank.statement:0 +#: field:pos.config,state:0 +#: view:pos.order:0 +#: field:pos.order,state:0 +#: report:pos.sales.user:0 +#: report:pos.sales.user.today:0 +#: field:pos.session,state:0 +#: field:pos.session.opening,pos_state_str:0 +#: field:report.pos.order,state:0 +msgid "Status" +msgstr "סטטוס" + +#. module: point_of_sale +#: selection:report.pos.order,month:0 +msgid "August" +msgstr "אוגוסט" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.pepsi_max_lemon_33cl_product_template +msgid "Pepsi Max Cool Lemon 33cl" +msgstr "פפסי מקס בטעם לימון 330 מ\"ל" + +#. module: point_of_sale +#: selection:report.pos.order,month:0 +msgid "June" +msgstr "יוני" + +#. module: point_of_sale +#: view:pos.order.line:0 +msgid "POS Order line" +msgstr "שורת הזמנה בקופה" + +#. module: point_of_sale +#: view:pos.config:0 +msgid "Point of Sale Configuration" +msgstr "הגדרות קופה רושמת" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:359 +#, python-format +msgid "Your order has to be validated by a cashier." +msgstr "הזמנת חייבת לעבור עימות על ידי קופאי" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.fanta_orange_50cl_product_template +msgid "Fanta Orange 50cl" +msgstr "פנטה תפוזים 0.5 ליטר" + +#. module: point_of_sale +#: field:pos.category,child_id:0 +msgid "Children Categories" +msgstr "קטגוריות ילדים" + +#. module: point_of_sale +#: model:ir.actions.act_window,help:point_of_sale.action_pos_session +msgid "" +"

\n" +" Click to start a new session.\n" +"

\n" +" A session is a period of time, usually one day, during " +"which\n" +" you sell through the point of sale. The user has to check " +"the\n" +" currencies in your cash registers at the beginning and the " +"end\n" +" of each session.\n" +"

\n" +" Note that you should better to use the menu Your " +"Session\n" +" to quickly open a new session.\n" +"

\n" +" " +msgstr "" +"

\n" +" לחץ כאן על מנת לפתוח יומן מכירות חדש.\n" +"

\n" +" יומן מכירות הינה תקופת עבודה בקופה, בדרך כלל\n" +" יום מכירות אחד, באה הינך מוכר באמצעות הקופה.\n" +" משתמש חייב לבחור מטבעה בכל תחילת וסוף יום.\n" +"

\n" +" שים לב, עדיף שתשתמש ב יומן מכירות שלך\n" +" על מנת לפתוח במהירות יומן מכירות.\n" +"

\n" +" " + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:888 +#, python-format +msgid "Customer Invoice" +msgstr "חשבונית לקוח" + +#. module: point_of_sale +#: view:pos.session.opening:0 +msgid "" +"You can continue sales from the touchscreen interface by clicking on \"Start " +"Selling\" or close the cash register session." +msgstr "" +"הינך יכול להמשיך את המכירות שלך על ידי לחיצה על \"התחל למכור\" או לסגור את " +"יומן המכירות הנוכחי." + +#. module: point_of_sale +#: report:account.statement:0 +#: report:all.closed.cashbox.of.the.day:0 +#: field:pos.session,stop_at:0 +msgid "Closing Date" +msgstr "תריך סגירה" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "Opening Cashbox Lines" +msgstr "שורת פתיחה של קופת מזומנים" + +#. module: point_of_sale +#: selection:report.pos.order,month:0 +msgid "October" +msgstr "אוקטובר" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_1l_product_template +msgid "Coca-Cola Light 1L" +msgstr "קוקה קולה דיאט 1 ליטר" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Summary" +msgstr "סיכום" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lays_naturel_45g_product_template +msgid "Lays Natural 45g" +msgstr "לייס בטעם טבעי 45 גר'" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.chaudfontaine_50cl_product_template +msgid "Chaudfontaine 50cl" +msgstr "Chaudfontaine 50 מ\"ל" + +#. module: point_of_sale +#: report:pos.invoice:0 +#: report:pos.lines:0 +#: field:pos.order.line,qty:0 +#: field:report.sales.by.user.pos,qty:0 +#: field:report.sales.by.user.pos.month,qty:0 +msgid "Quantity" +msgstr "כמות" + +#. module: point_of_sale +#: field:pos.order.line,name:0 +msgid "Line No" +msgstr "שורה מס'" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:453 +#, python-format +msgid "Set Weight" +msgstr "קבע משקל" + +#. module: point_of_sale +#: view:account.bank.statement:0 +msgid "Period" +msgstr "תקופה" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Net Total:" +msgstr "סה\"כ נטו:" + +#. module: point_of_sale +#: model:ir.actions.client,name:point_of_sale.action_client_pos_menu +msgid "Open POS Menu" +msgstr "פתח תפריט קופה" + +#. module: point_of_sale +#: report:pos.details_summary:0 +msgid "Mode of Payment" +msgstr "צורת תשלום" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_confirm +msgid "Post POS Journal Entries" +msgstr "הזן ערך לתוך יומן" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:457 +#, python-format +msgid "Barcode Scanner" +msgstr "סורק ברקודים" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.pomme_granny_smith_product_template +msgid "Granny Smith apples" +msgstr "תפוחי ספתה טובה" + +#. module: point_of_sale +#: help:product.product,expense_pdt:0 +msgid "" +"Check if, this is a product you can use to take cash from a statement for " +"the point of sale backend, example: money lost, transfer to bank, etc." +msgstr "" +"סמן כאן במידה ומוצר זה יכול להשתמש ביתרה מיוחדת כגון: חוב אבוד, העבורת לבנק " +"וכו'." + +#. module: point_of_sale +#: view:report.pos.order:0 +#: field:report.pos.order,total_discount:0 +msgid "Total Discount" +msgstr "סה\"כ הנחה" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:39 +#, python-format +msgid "" +"The Point of Sale is not supported by Microsoft Internet Explorer. Please " +"use\n" +" a modern browser like" +msgstr "" +"קופה רושמת זו אינה תומכת באינטרנט אקספלורר, אנה השתמש בדפדפן\n" +" מודרני יותר על מנת להשתמש בקופה רושמת." + +#. module: point_of_sale +#: view:pos.session.opening:0 +msgid "Click to start a session." +msgstr "הקלק על מנת לפתוח יומן מכירות" + +#. module: point_of_sale +#: view:pos.details:0 +#: view:pos.payment.report:0 +#: view:pos.payment.report.user:0 +#: view:pos.sale.user:0 +msgid "Print Report" +msgstr "הדפס דוח" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.oetker_bolognese_product_template +msgid "Dr. Oetker Ristorante Bolognese" +msgstr "" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.pizza +msgid "Pizza" +msgstr "פיצה" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "= Theoretical Balance" +msgstr "= יתרה טאורטית" + +#. module: point_of_sale +#: code:addons/point_of_sale/wizard/pos_return.py:85 +#: code:addons/point_of_sale/wizard/pos_return.py:240 +#, python-format +msgid "Add Product" +msgstr "הוסף מוצר" + +#. module: point_of_sale +#: field:pos.config,name:0 +msgid "Point of Sale Name" +msgstr "שם קופה רושמת" + +#. module: point_of_sale +#: field:report.transaction.pos,invoice_am:0 +msgid "Invoice Amount" +msgstr "סכום חשבונית" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.coke +msgid "Coke" +msgstr "קוקה קולה" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Tel. :" +msgstr "טל:" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:254 +#: model:ir.actions.act_window,name:point_of_sale.action_report_pos_receipt +#, python-format +msgid "Receipt" +msgstr "קבלה" + +#. module: point_of_sale +#: field:report.sales.by.margin.pos,net_margin_per_qty:0 +#: field:report.sales.by.margin.pos.month,net_margin_per_qty:0 +msgid "Net margin per Qty" +msgstr "רווח נקי לכמות" + +#. module: point_of_sale +#: view:pos.confirm:0 +msgid "Post All Orders" +msgstr "פרסם את כל ההזמנות" + +#. module: point_of_sale +#: report:account.statement:0 +#: report:all.closed.cashbox.of.the.day:0 +#: field:pos.session,cash_register_balance_end_real:0 +msgid "Ending Balance" +msgstr "יתרה סופית" + +#. module: point_of_sale +#: code:addons/point_of_sale/wizard/pos_box_out.py:89 +#, python-format +msgid "please check that account is set to %s." +msgstr "אנה בדוק שחשבון זה מקושר ל %s." + +#. module: point_of_sale +#: help:pos.category,image:0 +msgid "" +"This field holds the image used as image for the cateogry, limited to " +"1024x1024px." +msgstr "" +"בשדה זה נמצאת תמונה של קטגוריה, מוגבל לגודל מקסימאלי 1024X1024 פיקסלים." + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.pepsi_max_50cl_product_template +msgid "Pepsi Max 50cl" +msgstr "פפסי מאקס 50 מ\"ל" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.san_pellegrino_1l_product_template +msgid "San Pellegrino 1L" +msgstr "סאן פלגרינו 1 ליטר" + +#. module: point_of_sale +#: code:addons/point_of_sale/wizard/pos_open_statement.py:49 +#, python-format +msgid "" +"You have to define which payment method must be available in the point of " +"sale by reusing existing bank and cash through \"Accounting / Configuration " +"/ Journals / Journals\". Select a journal and check the field \"PoS Payment " +"Method\" from the \"Point of Sale\" tab. You can also create new payment " +"methods directly from menu \"PoS Backend / Configuration / Payment Methods\"." +msgstr "" +"הינך חייב לבחור בצורת תשלום שתהיה זמינה בקופה על ידי שימוש בחשבון בנק קיים " +"דרך : \"חשבונות\\ הגדרות\\ יומנים\\ יומים\". בחר יומן זמין וסמן בשורת \"צורת " +"תשלום עבור קופה רושמת\". אתה יכול ליצור צורת תשלום חדשה ישירות מתוך התפריט : " +"\"הגדרות\\ צורות תשלום\"." + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.rouges_noyau_fruits +msgid "Berries" +msgstr "פירות יער" + +#. module: point_of_sale +#: view:pos.ean_wizard:0 +msgid "Ean13 Generator" +msgstr "מחולל EAN 13" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.spa_1l_product_template +msgid "Spa Reine 1L" +msgstr "" + +#. module: point_of_sale +#: constraint:res.partner:0 +#: constraint:res.users:0 +msgid "Error: Invalid ean code" +msgstr "שגיאה : קוד EAN אינו תקין" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.legumes_racine +msgid "Root vegetables" +msgstr "ירקות שורש" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.act_pos_open_statement +#: model:ir.model,name:point_of_sale.model_pos_open_statement +#: view:pos.open.statement:0 +msgid "Open Statements" +msgstr "פתח דוחות" + +#. module: point_of_sale +#: field:pos.details,date_end:0 +#: field:pos.sale.user,date_end:0 +msgid "Date End" +msgstr "תאריך סיום" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.pomme_jonagold_product_template +msgid "Jonagold apples" +msgstr "" + +#. module: point_of_sale +#: view:account.bank.statement:0 +#: report:account.statement:0 +#: report:all.closed.cashbox.of.the.day:0 +#: model:ir.model,name:point_of_sale.model_account_journal +#: field:report.pos.order,journal_id:0 +msgid "Journal" +msgstr "יומן" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "Statements" +msgstr "דוחות" + +#. module: point_of_sale +#: report:pos.details:0 +msgid "Sales total(Revenue)" +msgstr "סה\"כ מכירות (רווחים)" + +#. module: point_of_sale +#: help:pos.config,group_by:0 +msgid "" +"Check this if you want to group the Journal Items by Product while closing a " +"Session" +msgstr "" +"סמן כאן במידה והינך רוצה לשלב פרטי יומן על ידי מוצרים בזמן סגירת יומן מכירות" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Total paid" +msgstr "שולם סה\"כ" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_session_opening +msgid "pos.session.opening" +msgstr "" + +#. module: point_of_sale +#: view:res.users:0 +msgid "Edit EAN" +msgstr "ערוך EAN" + +#. module: point_of_sale +#: code:addons/point_of_sale/wizard/pos_open_statement.py:80 +#, python-format +msgid "List of Cash Registers" +msgstr "רשימת קופות מזומן" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.maes_50cl_product_template +msgid "Maes 50cl" +msgstr "" + +#. module: point_of_sale +#: view:report.pos.order:0 +msgid "Not Invoiced" +msgstr "ללא חשבונית" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lays_pickles_250g_product_template +msgid "250g Lays Pickels" +msgstr "" + +#. module: point_of_sale +#: field:pos.session.opening,pos_session_id:0 +msgid "PoS Session" +msgstr "יומן מכירות" + +#. module: point_of_sale +#: selection:report.pos.order,month:0 +msgid "March" +msgstr "מרץ" + +#. module: point_of_sale +#: model:ir.actions.report.xml,name:point_of_sale.pos_users_product_re +#: report:pos.user.product:0 +msgid "User's Product" +msgstr "מוצרי משתמש" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:1173 +#, python-format +msgid "" +"You have to select a pricelist in the sale form !\n" +"Please set one before choosing a product." +msgstr "" +"הינך חייב לבחור מחירון עבור מכירה זו!\n" +"אנה בחר אחד לפני בחירת המוצר." + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.fanta_orange_2l_product_template +msgid "Fanta Orange 2L" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.perrier_1l_product_template +msgid "Perrier 1L" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.spa_33cl_product_template +msgid "Spa Reine 33cl" +msgstr "" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_discount +msgid "Add a Global Discount" +msgstr "הוסף הנחה כוללת" + +#. module: point_of_sale +#: view:pos.config:0 +msgid "Journals" +msgstr "יומנים" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.oetker_prosciutto_product_template +msgid "Dr. Oetker Ristorante Prosciutto" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lays_light_paprika_170g_product_template +#: model:product.template,name:point_of_sale.lays_paprika_170g_product_template +msgid "Lays Light Paprika 170g" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_lemon_50cl_product_template +msgid "Coca-Cola Light Lemon 50cl" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/point_of_sale.py:520 +#: code:addons/point_of_sale/static/src/xml/pos.xml:689 +#: code:addons/point_of_sale/static/src/xml/pos.xml:744 +#, python-format +msgid "return" +msgstr "חזרה" + +#. module: point_of_sale +#: view:product.product:0 +msgid "Set a Custom EAN" +msgstr "בחר מספר EAN מותאם אישית" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:235 +#, python-format +msgid "Remaining:" +msgstr "נותרו:" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.legumes +msgid "Fresh vegetables" +msgstr "ירקות טריים" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "tab of the" +msgstr "לשונית של" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:478 +#, python-format +msgid "Scan Item Success" +msgstr "סירקת המוצר הושלמה" + +#. module: point_of_sale +#: report:account.statement:0 +#: report:all.closed.cashbox.of.the.day:0 +#: field:pos.session,cash_register_balance_start:0 +msgid "Starting Balance" +msgstr "יתרת התחלה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lays_naturel_oven_150g_product_template +msgid "Oven Baked Lays Natural 150g" +msgstr "" + +#. module: point_of_sale +#: sql_constraint:pos.session:0 +msgid "The name of this POS Session must be unique !" +msgstr "שם יומן מכירות זה חייב להיות ייחודי !" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "Opening Subtotal" +msgstr "יתרת פתיחה" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "payment method." +msgstr "צורת תשלום." + +#. module: point_of_sale +#: view:pos.order:0 +msgid "Re-Print" +msgstr "הדפס מחדש" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.chimay_bleu_75cl_product_template +msgid "Chimay Bleu 75cl" +msgstr "" + +#. module: point_of_sale +#: report:pos.payment.report.user:0 +msgid "Payment By User" +msgstr "תשלומים ללקוח" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:215 +#: code:addons/point_of_sale/static/src/xml/pos.xml:285 +#: code:addons/point_of_sale/wizard/pos_payment.py:79 +#: model:ir.actions.act_window,name:point_of_sale.action_pos_payment +#: report:pos.details:0 +#: view:pos.order:0 +#, python-format +msgid "Payment" +msgstr "תשלום" + +#. module: point_of_sale +#: view:report.pos.order:0 +#: field:report.pos.order,nbr:0 +msgid "# of Lines" +msgstr "# שורות" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:89 +#, python-format +msgid "Disc" +msgstr "הנחה" + +#. module: point_of_sale +#: view:pos.order:0 +msgid "(update)" +msgstr "(עדכן)" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.ijsboerke_vanille_2,5l_product_template +msgid "IJsboerke Vanilla 2.5L" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_report_pos_details +#: model:ir.ui.menu,name:point_of_sale.menu_pos_details +msgid "Sale Details" +msgstr "פרטי מכירה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.evian_2l_product_template +msgid "2L Evian" +msgstr "" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:373 +#: code:addons/point_of_sale/point_of_sale.py:474 +#: code:addons/point_of_sale/wizard/pos_session_opening.py:33 +#, python-format +msgid "Start Point Of Sale" +msgstr "התחלה יומן מכירות" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.pils +msgid "Pils" +msgstr "כדורים" + +#. module: point_of_sale +#: help:pos.session,cash_register_balance_end_real:0 +msgid "Computed using the cash control lines" +msgstr "מחושב לפי שורות קופה" + +#. module: point_of_sale +#: report:all.closed.cashbox.of.the.day:0 +msgid "St.Name" +msgstr "רחוב" + +#. module: point_of_sale +#: report:pos.details_summary:0 +msgid "Sales total" +msgstr "סה\"כ מכירות" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:741 +#, python-format +msgid "ABC" +msgstr "ABC" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.ijsboerke_dame_blanche_2,5l_product_template +msgid "IJsboerke 2.5L White Lady" +msgstr "" + +#. module: point_of_sale +#: field:pos.order,lines:0 +msgid "Order Lines" +msgstr "שורות הזמנה" + +#. module: point_of_sale +#: view:report.transaction.pos:0 +msgid "Total Transaction" +msgstr "סה\"כ עסקה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.chaudfontaine_petillante_50cl_product_template +msgid "Chaudfontaine Petillante 50cl" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:485 +#, python-format +msgid "Read Weighting Scale" +msgstr "קראה משקל דיגיטלי" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:426 +#, python-format +msgid "0.00 €" +msgstr "0.00 ₪" + +#. module: point_of_sale +#: field:pos.order.line,create_date:0 +msgid "Creation Date" +msgstr "תאריך יצירה" + +#. module: point_of_sale +#: model:ir.actions.report.xml,name:point_of_sale.pos_sales_user_today +msgid "Today's Sales" +msgstr "מכירות להיום" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:264 +#: code:addons/point_of_sale/static/src/xml/pos.xml:324 +#, python-format +msgid "Welcome" +msgstr "ברוכים הבאים" + +#. module: point_of_sale +#: code:addons/point_of_sale/wizard/pos_box_entries.py:46 +#, python-format +msgid "" +"You do not have any open cash register. You must create a payment method or " +"open a cash register." +msgstr "" +"לא נמצאו קופות מזומנים. הינך חייב ליצור שיתת תשלום או לפתוח קופת מזומנים." + +#. module: point_of_sale +#: view:report.sales.by.margin.pos:0 +#: view:report.sales.by.margin.pos.month:0 +#: view:report.sales.by.user.pos:0 +#: view:report.sales.by.user.pos.month:0 +#: view:report.transaction.pos:0 +msgid "POS " +msgstr "קופה " + +#. module: point_of_sale +#: report:account.statement:0 +#: report:pos.user.product:0 +msgid "Total :" +msgstr "סה\"כ:" + +#. module: point_of_sale +#: view:report.pos.order:0 +msgid "My Sales" +msgstr "המכירות שלי" + +#. module: point_of_sale +#: view:pos.config:0 +msgid "Set to Deprecated" +msgstr "הגדר לחסרי ערך" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.limon_product_template +msgid "Stringers" +msgstr "סטרינגרים" + +#. module: point_of_sale +#: field:pos.order,pricelist_id:0 +msgid "Pricelist" +msgstr "מחירון" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Total invoiced" +msgstr "סה\"כ עם חשבונית" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_category +#: field:product.product,pos_categ_id:0 +msgid "Point of Sale Category" +msgstr "קטגוריית קופה" + +#. module: point_of_sale +#: view:report.pos.order:0 +#: field:report.pos.order,product_qty:0 +msgid "# of Qty" +msgstr "# כמות" + +#. module: point_of_sale +#: help:pos.config,sequence_id:0 +msgid "" +"This sequence is automatically created by OpenERP but you can change it to " +"customize the reference numbers of your orders." +msgstr "" +"רצף זה נוצר באופן אוטומטי על ידי OpenERP אבל אתה יכול לשנות את זה כדי להתאים " +"אישית את התייחסות למספרים של ההזמנות שלך." + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:324 +#, python-format +msgid "Choose your type of receipt:" +msgstr "בחר את סוג הקבלה שלך:" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_report_sales_by_margin_pos_month +msgid "Sales by margin monthly" +msgstr "מכירות לפי מרווח חודשי" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.poivron_jaunes_product_template +msgid "Yellow Peppers" +msgstr "" + +#. module: point_of_sale +#: view:pos.order:0 +#: field:pos.order,date_order:0 +#: field:report.sales.by.margin.pos,date_order:0 +#: field:report.sales.by.margin.pos.month,date_order:0 +#: field:report.sales.by.user.pos,date_order:0 +#: field:report.sales.by.user.pos.month,date_order:0 +msgid "Order Date" +msgstr "תאריך הזמנה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.stella_33cl_product_template +msgid "Stella Artois 33cl" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lays_naturel_300g_product_template +msgid "Lays Natural XXL 300g" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:479 +#, python-format +msgid "Scan Item Unrecognized" +msgstr "סרוק פריט ללא קטגוריה" + +#. module: point_of_sale +#: report:all.closed.cashbox.of.the.day:0 +msgid "Today's Closed Cashbox" +msgstr "דוח מזומנים להיום" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:920 +#, python-format +msgid "Selected orders do not have the same session!" +msgstr "הזמנות שנבחרו לא בוצעו באותו יומן מכירות!" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Draft Invoice" +msgstr "חשבונית ברירת מחדל" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lays_paprika_oven_150g_product_template +msgid "Oven Baked Lays Paprika 150g" +msgstr "" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Fiscal Position Remark :" +msgstr "הערת מצב פיסקלי:" + +#. module: point_of_sale +#: selection:report.pos.order,month:0 +msgid "September" +msgstr "ספטמבר" + +#. module: point_of_sale +#: report:account.statement:0 +#: report:all.closed.cashbox.of.the.day:0 +#: field:pos.session,start_at:0 +msgid "Opening Date" +msgstr "תאריך פתיחה" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_pos_session +#: model:ir.ui.menu,name:point_of_sale.menu_pos_session_all +msgid "All Sessions" +msgstr "כל היומנים" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:663 +#, python-format +msgid "tab" +msgstr "לשונית" + +#. module: point_of_sale +#: report:pos.lines:0 +msgid "Taxes :" +msgstr "מיסים:" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:271 +#, python-format +msgid "Thank you for shopping with us." +msgstr "תודה על כך שעשיתה קניות אתנו." + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_2l_product_template +msgid "Coca-Cola Light 2L" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.oetker_funghi_product_template +msgid "Dr. Oetker Ristorante Funghi" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.pos_category_action +#: model:ir.ui.menu,name:point_of_sale.menu_pos_category +msgid "Product Categories" +msgstr "קטגוריות מוצרים" + +#. module: point_of_sale +#: help:pos.config,journal_id:0 +msgid "Accounting journal used to post sales entries." +msgstr "יומן מכירות להזנת מכירות." + +#. module: point_of_sale +#: field:report.transaction.pos,disc:0 +msgid "Disc." +msgstr "תיאור" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:467 +#, python-format +msgid "Invalid Ean" +msgstr "EAN שגוי" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lindemans_kriek_37,5cl_product_template +msgid "Lindemans Kriek 37.5cl" +msgstr "" + +#. module: point_of_sale +#: view:pos.config:0 +msgid "Point of Sale Config" +msgstr "הגדרות קופה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_zero_33cl_product_template +msgid "Coca-Cola Zero 33cl" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:405 +#, python-format +msgid "ä" +msgstr "ä" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "VAT :" +msgstr "" + +#. module: point_of_sale +#: view:pos.order.line:0 +msgid "POS Order lines" +msgstr "שורות הזמנה לקופה" + +#. module: point_of_sale +#: view:pos.receipt:0 +msgid "Receipt :" +msgstr "קבלה:" + +#. module: point_of_sale +#: field:account.bank.statement,pos_session_id:0 +#: field:account.bank.statement.line,pos_statement_id:0 +#: field:pos.order,amount_return:0 +#: field:pos.session.opening,pos_session_name:0 +#: field:pos.session.opening,pos_session_username:0 +msgid "unknown" +msgstr "לא ידוע" + +#. module: point_of_sale +#: field:product.product,income_pdt:0 +msgid "Point of Sale Cash In" +msgstr "כניסת מזומנים לקופה" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:590 +#, python-format +msgid "Tax:" +msgstr "מע\"מ:" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "+ Transactions" +msgstr "+ עסקאות" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_pos_discount +#: view:pos.discount:0 +msgid "Apply Discount" +msgstr "עדכן הנחה" + +#. module: point_of_sale +#: report:account.statement:0 +#: report:all.closed.cashbox.of.the.day:0 +#: field:pos.box.entries,user_id:0 +#: report:pos.sales.user:0 +#: report:pos.sales.user.today:0 +#: view:pos.session:0 +#: report:pos.user.product:0 +#: field:report.sales.by.margin.pos,user_id:0 +#: field:report.sales.by.margin.pos.month,user_id:0 +#: field:report.sales.by.user.pos,user_id:0 +#: field:report.sales.by.user.pos.month,user_id:0 +#: field:report.transaction.pos,user_id:0 +#: model:res.groups,name:point_of_sale.group_pos_user +msgid "User" +msgstr "משתמש/ת" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:194 +#, python-format +msgid "Kg" +msgstr "ק\"ג" + +#. module: point_of_sale +#: field:product.product,available_in_pos:0 +msgid "Available in the Point of Sale" +msgstr "זמין בקופה" + +#. module: point_of_sale +#: selection:pos.config,state:0 +msgid "Deprecated" +msgstr "מומלץ לשימוש" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_decaf_33cl_product_template +msgid "Coca-Cola Light 33cl Decaf" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:338 +#, python-format +msgid "The scanned product was not recognized" +msgstr "מוצר נסרק אינו מזוהה" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_report_transaction_pos +msgid "transaction for the pos" +msgstr "עסקאות לקופה" + +#. module: point_of_sale +#: report:pos.details:0 +#: field:report.transaction.pos,date_create:0 +msgid "Date" +msgstr "תאריך" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_box_entries +msgid "Pos Box Entries" +msgstr "תנועות קופה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.boon_framboise_37,5cl_product_template +msgid "Boon Framboise 37.5cl" +msgstr "" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_config +msgid "pos.config" +msgstr "" + +#. module: point_of_sale +#: view:pos.ean_wizard:0 +msgid "" +"Enter a reference, it will be converted\n" +" automatically to a valid EAN number." +msgstr "" +"הזן מספק, הוא יומר אוטומטית\n" +" לקוד EAN חוקי לשימוש." + +#. module: point_of_sale +#: field:product.product,expense_pdt:0 +msgid "Point of Sale Cash Out" +msgstr "מכירות במזומן" + +#. module: point_of_sale +#: selection:report.pos.order,month:0 +msgid "November" +msgstr "נובמבר" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:267 +#, python-format +msgid "Please scan an item or your member card" +msgstr "אנה סרוק מוצר או כרטיס חבר מועדון" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.poivron_verts_product_template +msgid "Green Peppers" +msgstr "פלפלים ירוקים" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.timmermans_faro_37,5cl_product_template +msgid "Timmermans Faro 37.5cl" +msgstr "" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:410 +#, python-format +msgid "" +"Your ending balance is too different from the theorical cash closing (%.2f), " +"the maximum allowed is: %.2f. You can contact your manager to force it." +msgstr "" +"בסיגרת הקופה נמצאה הבדל של (%.2f), כאשר המקסימום המותר הינו %.2f. אנה צור " +"קשר עם אחראי משמרת." + +#. module: point_of_sale +#: view:pos.session:0 +msgid "Validate Closing & Post Entries" +msgstr "אמת סגירה ותנועות קופה" + +#. module: point_of_sale +#: field:report.transaction.pos,no_trans:0 +msgid "Number of Transaction" +msgstr "מספר עסקאות" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:759 +#, python-format +msgid "" +"There is no receivable account defined to make payment for the partner: " +"\"%s\" (id:%d)." +msgstr "לא נמצא חשבון אשר יכול לקבל כספים עבור שותף : \"%s\" (id:%d)." + +#. module: point_of_sale +#: view:pos.config:0 +#: selection:pos.config,state:0 +msgid "Inactive" +msgstr "לא פעיל" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:313 +#: view:pos.confirm:0 +#: view:pos.details:0 +#: view:pos.discount:0 +#: view:pos.ean_wizard:0 +#: view:pos.make.payment:0 +#: view:pos.open.statement:0 +#: view:pos.payment.report:0 +#: view:pos.payment.report.user:0 +#: view:pos.receipt:0 +#: view:pos.sale.user:0 +#, python-format +msgid "Cancel" +msgstr "ביטול" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:296 +#, python-format +msgid "Please put your product on the scale" +msgstr "אנה מקם את המוצר שלך על משקל דיגיטלי" + +#. module: point_of_sale +#: model:ir.actions.report.xml,name:point_of_sale.pos_details_summary +msgid "Sales (summary)" +msgstr "מכירות (סה\"כ)" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.nectarine_product_template +msgid "Peach" +msgstr "אפרסק" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.timmermans_kriek_37,5cl_product_template +msgid "Timmermans Kriek 37.5cl" +msgstr "" + +#. module: point_of_sale +#: field:pos.config,sequence_id:0 +msgid "Order IDs Sequence" +msgstr "רצף מספרי הזמנות" + +#. module: point_of_sale +#: report:pos.invoice:0 +#: report:pos.lines:0 +#: field:pos.order.line,price_unit:0 +#: report:pos.payment.report.user:0 +msgid "Unit Price" +msgstr "מחיר ליחידה" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:190 +#, python-format +msgid "Product Weighting" +msgstr "משקל המוצר" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:704 +#: code:addons/point_of_sale/static/src/xml/pos.xml:746 +#, python-format +msgid "close" +msgstr "סגור" + +#. module: point_of_sale +#: model:ir.actions.report.xml,name:point_of_sale.report_user_label +msgid "User Labels" +msgstr "תוויות משתמש" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_order_line +msgid "Lines of Point of Sale" +msgstr "שורות קופה" + +#. module: point_of_sale +#: view:pos.order:0 +#: view:report.transaction.pos:0 +msgid "Amount total" +msgstr "סכום כולל" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "End of Session" +msgstr "סוף ההפעלה" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_new_bank_statement_all_tree +#: view:pos.session:0 +msgid "Cash Registers" +msgstr "קופות מזומן" + +#. module: point_of_sale +#: help:pos.session,cash_register_balance_end:0 +msgid "Computed with the initial cash control and the sum of all payments." +msgstr "מחושב עם שליטה הראשונית במזומן והסכום של כל התשלומים." + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:474 +#, python-format +msgid "In Transaction" +msgstr "בעסקה" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.food +msgid "Food" +msgstr "מזון" + +#. module: point_of_sale +#: field:pos.box.entries,ref:0 +msgid "Ref" +msgstr "הפניה" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:94 +#: report:pos.details:0 +#: report:pos.invoice:0 +#: report:pos.lines:0 +#, python-format +msgid "Price" +msgstr "מחיר" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_33cl_product_template +msgid "Coca-Cola Light 33cl" +msgstr "" + +#. module: point_of_sale +#: view:report.sales.by.margin.pos:0 +#: view:report.sales.by.margin.pos.month:0 +#: view:report.sales.by.user.pos:0 +#: view:report.sales.by.user.pos.month:0 +#: view:report.transaction.pos:0 +msgid "POS" +msgstr "קופה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_regular_33cl_product_template +msgid "Coca-Cola Regular 33cl" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:325 +#, python-format +msgid "Ticket" +msgstr "פנייה" + +#. module: point_of_sale +#: field:pos.session,cash_register_difference:0 +msgid "Difference" +msgstr "הפרש" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:549 +#, python-format +msgid "Unable to Delete !" +msgstr "לא ניתן למחיקה!" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.autres_agrumes +msgid "Other Citrus" +msgstr "" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Start Period" +msgstr "תקופת הדוח" + +#. module: point_of_sale +#: report:account.statement:0 +#: field:pos.category,complete_name:0 +#: field:pos.category,name:0 +#: report:pos.sales.user:0 +#: report:pos.sales.user.today:0 +msgid "Name" +msgstr "שם" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.spa_gazeuse_33cl_product_template +msgid "Spa Barisart 33cl" +msgstr "" + +#. module: point_of_sale +#: view:pos.confirm:0 +msgid "" +"Generate all sale journal entries for non invoiced orders linked to a closed " +"cash register or statement." +msgstr "חולל את כל המכירות להם לא הונפקה חשבונית אשר קשורים לקופה זו." + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.unreferenced_product_product_template +msgid "Unreferenced Products" +msgstr "מוצרים מנותקים מ" + +#. module: point_of_sale +#: view:pos.ean_wizard:0 +msgid "Apply" +msgstr "החל" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:288 +#, python-format +msgid "" +"Please insert your card in the reader and follow the instructions to " +"complete\n" +" your purchase" +msgstr "" +"אנה הכנס את הכרטיס שלך לתוך קורא הכרטיסיפ ועקוב אחר ההוראות להשלמת\n" +" " +" הקניה שלך" + +#. module: point_of_sale +#: help:product.product,income_pdt:0 +msgid "" +"Check if, this is a product you can use to put cash into a statement for the " +"point of sale backend." +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.ijsboerke_moka_2,5l_product_template +msgid "IJsboerke Mocha 2.5L" +msgstr "" + +#. module: point_of_sale +#: field:pos.session,cash_control:0 +msgid "Has Cash Control" +msgstr "יש קופת מזומן" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_report_pos_order_all +#: model:ir.ui.menu,name:point_of_sale.menu_report_pos_order_all +msgid "Orders Analysis" +msgstr "ניתוח הזמנות" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:563 +#, python-format +msgid "User:" +msgstr "משתמש:" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:316 +#, python-format +msgid "" +"Unable to open the session. You have to assign a sale journal to your point " +"of sale." +msgstr "לא ניתן לפתוח יומן מכירות. הינך חייב לקשר יומן לקופה." + +#. module: point_of_sale +#: view:report.pos.order:0 +msgid "POS ordered created during current year" +msgstr "זמנות קופה שנוצרו במהלך השנה הנוכחית" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.peche_product_template +msgid "Fishing" +msgstr "דייג" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +#: report:pos.lines:0 +#: report:pos.payment.report.user:0 +#: report:pos.sales.user:0 +#: report:pos.sales.user.today:0 +#: report:pos.user.product:0 +msgid "Print Date" +msgstr "תאריך הדפסה" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.poireaux_poireaux_product_template +msgid "Leeks" +msgstr "כרישה" + +#. module: point_of_sale +#: help:pos.category,sequence:0 +msgid "" +"Gives the sequence order when displaying a list of product categories." +msgstr "נותן את סדר הרצף בעת הצגת רשימה של קטגוריות מוצר." + +#. module: point_of_sale +#: view:account.bank.statement:0 +#: view:pos.order:0 +#: view:pos.session:0 +#: view:report.pos.order:0 +msgid "Group By..." +msgstr "מקובץ על ידי ..." + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:564 +#, python-format +msgid "Shop:" +msgstr "חנות:" + +#. module: point_of_sale +#: field:account.journal,self_checkout_payment_method:0 +msgid "Self Checkout Payment Method" +msgstr "צורות תשלום ברכישה עצמית" + +#. module: point_of_sale +#: view:pos.order:0 +msgid "POS Orders" +msgstr "הזמנות קופה" + +#. module: point_of_sale +#: model:ir.actions.report.xml,name:point_of_sale.all_closed_cashbox_of_the_day +msgid "All Closed CashBox" +msgstr "כל קופות מזומן סגורות" + +#. module: point_of_sale +#: field:pos.details,user_ids:0 +msgid "Salespeople" +msgstr "אנשי מכירות" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:777 +#: code:addons/point_of_sale/wizard/pos_box_entries.py:118 +#: code:addons/point_of_sale/wizard/pos_box_out.py:91 +#, python-format +msgid "You have to open at least one cashbox." +msgstr "" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:1172 +#, python-format +msgid "No Pricelist !" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.poivron_rouges_product_template +msgid "Red Pepper" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:677 +#, python-format +msgid "caps lock" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.grisette_cerise_25cl_product_template +msgid "Grisette Cherry 25cl" +msgstr "" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Base" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:702 +#: code:addons/point_of_sale/static/src/xml/pos.xml:742 +#, python-format +msgid " " +msgstr "" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.categ_others +msgid "Others" +msgstr "" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.autres_legumes_frais +msgid "Other fresh vegetables" +msgstr "" + +#. module: point_of_sale +#: code:addons/point_of_sale/wizard/pos_open_statement.py:49 +#, python-format +msgid "No Cash Register Defined !" +msgstr "" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:515 +#, python-format +msgid "" +"No cash statement found for this session. Unable to record returned cash." +msgstr "" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.oignons_ail_echalotes +msgid "Onions / Garlic / Shallots" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.evian_50cl_product_template +msgid "Evian 50cl" +msgstr "" + +#. module: point_of_sale +#: view:pos.order:0 +msgid "Notes" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_lemon_2l_product_template +msgid "Coca-Cola Light Lemon 2L" +msgstr "" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.invoice:0 +#: field:pos.order,amount_tax:0 +msgid "Taxes" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_pos_order_line +#: model:ir.actions.act_window,name:point_of_sale.action_pos_order_line_day +#: model:ir.actions.act_window,name:point_of_sale.action_pos_order_line_form +msgid "Sale line" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:741 +#, python-format +msgid "123" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.product_normal_action +#: model:ir.ui.menu,name:point_of_sale.menu_point_of_sale_product +#: model:ir.ui.menu,name:point_of_sale.menu_pos_products +#: view:pos.order:0 +msgid "Products" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.oetker_4formaggi_product_template +msgid "Dr. Oetker Ristorante Quattro Formaggi" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.croky_naturel_45g_product_template +msgid "Croky Natural 45g" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.tomate_en_grappe_product_template +msgid "In Cluster Tomatoes" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.client,name:point_of_sale.action_pos_pos +msgid "Start Point of Sale" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:84 +#: report:pos.details:0 +#: report:pos.payment.report.user:0 +#: report:pos.user.product:0 +#: field:report.sales.by.margin.pos,qty:0 +#: field:report.sales.by.margin.pos.month,qty:0 +#, python-format +msgid "Qty" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_zero_1l_product_template +msgid "Coca-Cola Zero 1L" +msgstr "" + +#. module: point_of_sale +#: report:pos.sales.user:0 +#: report:pos.sales.user.today:0 +#: field:report.pos.order,date:0 +msgid "Date Order" +msgstr "" + +#. module: point_of_sale +#: view:pos.order:0 +msgid "Point of Sale Orders" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.spa_et_fruit_50cl_product_template +msgid "Spa Fruit and Orange 50cl" +msgstr "" + +#. module: point_of_sale +#: view:pos.config:0 +#: field:pos.config,journal_ids:0 +#: field:pos.session,journal_ids:0 +msgid "Available Payment Methods" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.act_window,help:point_of_sale.product_normal_action +msgid "" +"

\n" +" Click to add a new product.\n" +"

\n" +" You must define a product for everything you sell through\n" +" the point of sale interface.\n" +"

\n" +" Do not forget to set the price and the point of sale " +"category\n" +" in which it should appear. If a product has no point of " +"sale\n" +" category, you can not sell it through the point of sale\n" +" interface.\n" +"

\n" +" " +msgstr "" + +#. module: point_of_sale +#: view:pos.order:0 +msgid "Extra Info" +msgstr "" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Fax :" +msgstr "" + +#. module: point_of_sale +#: view:pos.session:0 +msgid "Point of Sale Session" +msgstr "" + +#. module: point_of_sale +#: report:account.statement:0 +#: model:ir.actions.report.xml,name:point_of_sale.account_statement +msgid "Statement" +msgstr "" + +#. module: point_of_sale +#: report:pos.invoice:0 +msgid "Source" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:461 +#, python-format +msgid "Admin Badge" +msgstr "" + +#. module: point_of_sale +#: field:pos.make.payment,journal_id:0 +msgid "Payment Mode" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.lays_paprika_45g_product_template +msgid "Lays Paprika 45g" +msgstr "" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_account_bank_statement +#: field:pos.session,statement_ids:0 +msgid "Bank Statement" +msgstr "" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:101 +#: selection:pos.session,state:0 +#: selection:pos.session.opening,pos_state:0 +#, python-format +msgid "Closed & Posted" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_report_pos_sale_user +#: model:ir.model,name:point_of_sale.model_pos_sale_user +#: view:pos.payment.report.user:0 +msgid "Sale by User" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:562 +#, python-format +msgid "Phone:" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.evian_1l_product_template +msgid "Evian 1L" +msgstr "" + +#. module: point_of_sale +#: model:pos.category,name:point_of_sale.water +msgid "Water" +msgstr "" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_ean_wizard +msgid "pos.ean_wizard" +msgstr "" + +#. module: point_of_sale +#: selection:report.pos.order,month:0 +msgid "July" +msgstr "" + +#. module: point_of_sale +#: model:ir.actions.act_window,name:point_of_sale.action_pos_config_pos +#: model:ir.ui.menu,name:point_of_sale.menu_pos_config_pos +#: view:pos.session:0 +msgid "Point of Sales" +msgstr "" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "Qty of product" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.pomme_golden_perlim_product_template +msgid "Golden Apples Perlim" +msgstr "" + +#. module: point_of_sale +#: code:addons/point_of_sale/point_of_sale.py:100 +#: selection:pos.session,state:0 +#: selection:pos.session.opening,pos_state:0 +#, python-format +msgid "Closing Control" +msgstr "" + +#. module: point_of_sale +#: field:report.pos.order,delay_validation:0 +msgid "Delay Validation" +msgstr "" + +#. module: point_of_sale +#: field:pos.order,nb_print:0 +msgid "Number of Print" +msgstr "" + +#. module: point_of_sale +#: model:ir.model,name:point_of_sale.model_pos_make_payment +msgid "Point of Sale Payment" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_50cl_product_template +msgid "Coca-Cola Light 50cl" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:466 +#, python-format +msgid "Unknown Product" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:36 +#, python-format +msgid "" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.jupiler_50cl_product_template +msgid "Jupiler 50cl" +msgstr "" + +#. module: point_of_sale +#: report:pos.details:0 +#: report:pos.details_summary:0 +msgid "End Period" +msgstr "" + +#. module: point_of_sale +#: model:product.template,name:point_of_sale.coca_light_lemon_33cl_product_template +msgid "Coca-Cola Light Lemon 33cl" +msgstr "" + +#. module: point_of_sale +#. openerp-web +#: code:addons/point_of_sale/static/src/xml/pos.xml:33 +#, python-format +msgid " diff --git a/addons/point_of_sale/report/pos_receipt.rml b/addons/point_of_sale/report/pos_receipt.rml index 0802114bb48..02b8a5b1a1a 100644 --- a/addons/point_of_sale/report/pos_receipt.rml +++ b/addons/point_of_sale/report/pos_receipt.rml @@ -75,7 +75,7 @@ [[ address and display_address(address)]] Tel : [[ address and address.phone ]] User : [[ o.user_id.name ]] - Shop : [[ o.shop_id.name ]] + Warehouse : [[ o.warehouse_id.name ]] Date : [[ o.date_order ]] diff --git a/addons/point_of_sale/res_partner.py b/addons/point_of_sale/res_partner.py index 81a0f6083be..d7969b0e21a 100644 --- a/addons/point_of_sale/res_partner.py +++ b/addons/point_of_sale/res_partner.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python import math diff --git a/addons/point_of_sale/res_users.py b/addons/point_of_sale/res_users.py index 05e49a5545d..ed2c6fae598 100644 --- a/addons/point_of_sale/res_users.py +++ b/addons/point_of_sale/res_users.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python import math diff --git a/addons/point_of_sale/security/ir.model.access.csv b/addons/point_of_sale/security/ir.model.access.csv index 1d2c22053fb..b278c48e1f2 100644 --- a/addons/point_of_sale/security/ir.model.access.csv +++ b/addons/point_of_sale/security/ir.model.access.csv @@ -8,7 +8,7 @@ access_account_journal_pos_user,account.journal pos_user,account.model_account_j access_account_move_pos_user,account.move pos_user,account.model_account_move,group_pos_user,1,1,1,0 access_account_account_pos_user,account.account pos_user,account.model_account_account,group_pos_user,1,0,0,0 access_stock_picking_pos_user,stock.picking pos_user,stock.model_stock_picking,group_pos_user,1,1,1,1 -access_sale_shop_pos_user,sale.shop pos_user,sale.model_sale_shop,group_pos_user,1,0,0,0 +access_stock_warehouse_pos_user,stock.warehouse pos_user,stock.model_stock_warehouse,group_pos_user,1,0,0,0 access_pos_order_stock_worker,pos.order stock_worker,model_pos_order,stock.group_stock_user,1,0,0,0 access_stock_move_pos_user,stock.move pos_user,stock.model_stock_move,group_pos_user,1,1,1,1 access_report_sales_by_user_pos,report.sales.by.user.pos,model_report_sales_by_user_pos,group_pos_user,1,0,0,0 diff --git a/addons/point_of_sale/static/src/img/icon.png b/addons/point_of_sale/static/description/icon.png similarity index 100% rename from addons/point_of_sale/static/src/img/icon.png rename to addons/point_of_sale/static/description/icon.png diff --git a/addons/point_of_sale/static/description/index.html b/addons/point_of_sale/static/description/index.html new file mode 100644 index 00000000000..7f1b7a5c097 --- /dev/null +++ b/addons/point_of_sale/static/description/index.html @@ -0,0 +1,244 @@ +
+
+
+

A very friendly Point of Sale

+

Set up in a minute, Sell in seconds

+
+
+
+ + + + +
+
+
+

+ OpenERP's Point of Sale introduces a super clean interface with no installation required + that runs online and offline on modern hardwares. +

+

+ It's full integration with the company inventory and accounting, gives you real time statistics and + consolidations amongst all shops without the hassle of integrating several applications. +

+ +
+
+
+ +
+
+
+

Work with the hardware you already have

+

Desktops, laptops, tablets, it runs on everything

+
+
+ +
+
+

In your web browser

+

+ OpenERP's POS is a web application that can run on any device that can + display websites with little to no setup required. +

+
+
+

Touchscreen or Keyboard ?

+

+ The Point of Sale works perfectly on any kind of touch enabled device, whether it's + multi-touch tablets like an iPad or keyboardless resistive touchscreen terminals. +

+
+
+

Scales and Printers

+

+ Barcode scanners and printers are supported out of the box with no setup required. + Scales, cashboxes, and other peripherals can be used with the + proxy API. +

+
+
+
+ +
+
+ +

Online and Offline

+

OpenERP's POS stays reliable even if your connection isn't

+ +
+
+ +
+
+
+

+ Deploy new stores with just an internet connection: + no installation, no specific hardware required. It works with any + iPad, Tablet PC, laptop or industrial POS machine. +

+ While an internet connection is required to start the Point of Sale, + it will stay operational even after a complete disconnection. +

+
+
+
+ +
+
+ +
+ Download our free E-book +
+ +
+
+

A super clean user interface

+

The point of sale software retailers love to use

+
+
+
+ +

Simple and beautifull

+

+ Say goodbye to ugly, outdated POS software and enjoy the OpenERP + web interface designed for modern retailer. +

+
+
+ +

Designed for Productivity

+

+ Whether it's for a restaurant or a shop, you can activate the multiple + tickets in parallel to not make your customers wait. +

+
+
+ +

Blasting fast search

+

+ Scan products, browse through hyerarchical categories, or get quick + information about products with the blasting fast filter accross + all your products. +

+
+
+
+ +
+
+

Integrated Inventory Management

+
+ +
+
+

+ Consolidate all your sales channel in real time: stores, ecommerce, sales teams. + Get real time control of the inventory and accurate forecasts to manage procurements. +

+

+ A full warehouse management system at your fingertips: get information + about products availabilities, trigger procurement requests, etc. +

+
+
+
+ +
+
+

Deliver in-store customer services

+

Repairs, warantees, deliveries, etc.

+
+

+ Give your shopper a strong experience by integrating in-store + customer services. Handle reparations, track warantees, follow + customer claims, plan delivery orders, etc. +

+
+
+ +
+
+
+ +
+
+

Invoicing & Accounting Integration

+
+ +
+
+

+ Produce customer invoices in just a few clicks. Control sales and + cash in real time and use OpenERP's powerful reporting to make + smarter decisions to improve your store's efficiency. +

+ No more hassle of having to integrate softwares: get all your sales + and inventory operations automatically posted in your G/L. +

+
+
+
+ +
+
+

Self-checkout Interface

+
+

+ Reduce costs by limitting the number of required cashiers. + The self-checkout mode allows customers to scan products and pay by + themselves with a dedicated and super easy user interface. +

+

+ Use lights and sounds to control the checkout distantly. +

+
+
+ +
+
+
+ + +
+
+

Unified Data Amongst All Shops

+

Sync products, prices, customers with no effort

+
+ +
+
+

+ Get new products, pricing strategies and promotions applied automatically to + selected stores. Work on a unified customer base. No complex interface is + required to pilot a global strategy amongst all your stores. +

+

+ With OpenERP as a backend, you have a system proven to be perfectly + suitable for small stores or large multinationals. +

+
+
+
+ +
+
+

Know your customers - in store and out

+
+

+ Successful brands integrates all their customer relationship accross all their + channels to develop accurate customer profile and communicate with shoppers + as they make buying decisions, in store or online. +

+

+ With OpenERP, you get a 360° customer view, including cross-channel sales, + interaction history, profiles, and more. +

+
+
+ +
+
+
diff --git a/addons/point_of_sale/static/description/pos_checkout.jpg b/addons/point_of_sale/static/description/pos_checkout.jpg new file mode 100644 index 00000000000..d87e5b8499d Binary files /dev/null and b/addons/point_of_sale/static/description/pos_checkout.jpg differ diff --git a/addons/point_of_sale/static/description/pos_customer_form.png b/addons/point_of_sale/static/description/pos_customer_form.png new file mode 100644 index 00000000000..4e89d43c4c3 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_customer_form.png differ diff --git a/addons/point_of_sale/static/description/pos_customers.png b/addons/point_of_sale/static/description/pos_customers.png new file mode 100644 index 00000000000..6448074c3d9 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_customers.png differ diff --git a/addons/point_of_sale/static/description/pos_devices.png b/addons/point_of_sale/static/description/pos_devices.png new file mode 100644 index 00000000000..a021a87bfac Binary files /dev/null and b/addons/point_of_sale/static/description/pos_devices.png differ diff --git a/addons/point_of_sale/static/description/pos_invoice.png b/addons/point_of_sale/static/description/pos_invoice.png new file mode 100644 index 00000000000..aae4f6d38a5 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_invoice.png differ diff --git a/addons/point_of_sale/static/description/pos_offline.png b/addons/point_of_sale/static/description/pos_offline.png new file mode 100644 index 00000000000..764cda88e87 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_offline.png differ diff --git a/addons/point_of_sale/static/description/pos_product_form.png b/addons/point_of_sale/static/description/pos_product_form.png new file mode 100644 index 00000000000..a25c85b6496 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_product_form.png differ diff --git a/addons/point_of_sale/static/description/pos_products.png b/addons/point_of_sale/static/description/pos_products.png new file mode 100644 index 00000000000..cbfd054d72e Binary files /dev/null and b/addons/point_of_sale/static/description/pos_products.png differ diff --git a/addons/point_of_sale/static/description/pos_sc_01.jpg b/addons/point_of_sale/static/description/pos_sc_01.jpg new file mode 100644 index 00000000000..8fc97e00672 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_sc_01.jpg differ diff --git a/addons/point_of_sale/static/description/pos_sc_02.jpg b/addons/point_of_sale/static/description/pos_sc_02.jpg new file mode 100644 index 00000000000..d26e0504933 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_sc_02.jpg differ diff --git a/addons/point_of_sale/static/description/pos_sc_03.jpg b/addons/point_of_sale/static/description/pos_sc_03.jpg new file mode 100644 index 00000000000..8eb7e312791 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_sc_03.jpg differ diff --git a/addons/point_of_sale/static/description/pos_ui_01.png b/addons/point_of_sale/static/description/pos_ui_01.png new file mode 100644 index 00000000000..1725f91d6f2 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_ui_01.png differ diff --git a/addons/point_of_sale/static/description/pos_ui_02.png b/addons/point_of_sale/static/description/pos_ui_02.png new file mode 100644 index 00000000000..aa0eb51c0f1 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_ui_02.png differ diff --git a/addons/point_of_sale/static/description/pos_ui_03.png b/addons/point_of_sale/static/description/pos_ui_03.png new file mode 100644 index 00000000000..f25f2a49c00 Binary files /dev/null and b/addons/point_of_sale/static/description/pos_ui_03.png differ diff --git a/addons/point_of_sale/static/lib/mousewheel/jquery.mousewheel-3.0.6.js b/addons/point_of_sale/static/lib/mousewheel/jquery.mousewheel-3.0.6.js old mode 100755 new mode 100644 diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index d9a4d6d00a9..e328054aa28 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -291,10 +291,15 @@ display: inline-block; text-align: center; vertical-align: top; + width: 205px; + max-height: 232px; + overflow-y: auto; + overflow-x: hidden; } .point-of-sale #paypad button { height: 50px; - width: 208px; + display: block; + width: 100%; margin: 0px -6px 4px -2px; font-weight: bold; vertical-align: middle; @@ -302,6 +307,17 @@ border-top: 1px solid #efefef; font-size: 14px; } +.point-of-sale #paypad button, .point-of-sale #numpad button, .point-of-sale .popup button{ + position: relative; + top: 0; + -webkit-transition: top 150ms linear; + -moz-transition: top 150ms linear; + -ms-transition: top 150ms linear; + transition: top 150ms linear; +} +.point-of-sale #paypad button:active, .point-of-sale #numpad button:active, .point-of-sale .popup button:active{ + top:3px; +} .point-of-sale #paypad button:hover, .point-of-sale #numpad button:hover, .point-of-sale #numpad .selected-mode, .point-of-sale .popup button:hover { border: none; color: white; diff --git a/addons/point_of_sale/static/src/img/icons/png48/invoice.png b/addons/point_of_sale/static/src/img/icons/png48/invoice.png new file mode 100644 index 00000000000..e65d2ec5a67 Binary files /dev/null and b/addons/point_of_sale/static/src/img/icons/png48/invoice.png differ diff --git a/addons/point_of_sale/static/src/js/db.js b/addons/point_of_sale/static/src/js/db.js index a79b111b5c5..d16ba5a53dd 100644 --- a/addons/point_of_sale/static/src/js/db.js +++ b/addons/point_of_sale/static/src/js/db.js @@ -204,8 +204,8 @@ function openerp_pos_db(instance, module){ this.packagings_by_product_id[pack.product_id[0]] = []; } this.packagings_by_product_id[pack.product_id[0]].push(pack); - if(pack.ean13){ - this.packagings_by_ean13[pack.ean13] = pack; + if(pack.ean){ + this.packagings_by_ean13[pack.ean] = pack; } } }, @@ -267,11 +267,21 @@ function openerp_pos_db(instance, module){ return results; }, add_order: function(order){ - var last_id = this.load('last_order_id',0); + var order_id = order.uid; var orders = this.load('orders',[]); - orders.push({id: last_id + 1, data: order}); - this.save('last_order_id',last_id+1); + + // if the order was already stored, we overwrite its data + for(var i = 0, len = orders.length; i < len; i++){ + if(orders[i].id === order_id){ + orders[i].data = order; + this.save('orders',orders); + return order_id; + } + } + + orders.push({id: order_id, data: order}); this.save('orders',orders); + return order_id; }, remove_order: function(order_id){ var orders = this.load('orders',[]); @@ -283,5 +293,14 @@ function openerp_pos_db(instance, module){ get_orders: function(){ return this.load('orders',[]); }, + get_order: function(order_id){ + var orders = this.get_orders(); + for(var i = 0, len = orders.length; i < len; i++){ + if(orders[i].id === order_id){ + return orders[i]; + } + } + return undefined; + }, }); } diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 98ba49c8856..8375377b31c 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -104,7 +104,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal return self.fetch('res.currency',['symbol','position','rounding','accuracy'],[['id','=',self.get('company').currency_id[0]]]); }).then(function(currencies){ - console.log('Currency:',currencies[0]); self.set('currency',currencies[0]); return self.fetch('product.uom', null, null); @@ -142,10 +141,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal return self.fetch( 'pos.config', - ['name','journal_ids','shop_id','journal_id', + ['name','journal_ids','warehouse_id','journal_id','pricelist_id', 'iface_self_checkout', 'iface_led', 'iface_cashdrawer', 'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan', 'iface_vkeyboard', - 'iface_print_via_proxy','iface_cashdrawer','state','sequence_id','session_ids'], + 'iface_print_via_proxy','iface_cashdrawer','iface_invoicing','state','sequence_id','session_ids'], [['id','=', self.get('pos_session').config_id[0]]] ); }).then(function(configs){ @@ -156,8 +155,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal self.iface_vkeyboard = !!pos_config.iface_vkeyboard; self.iface_self_checkout = !!pos_config.iface_self_checkout; self.iface_cashdrawer = !!pos_config.iface_cashdrawer; + self.iface_invoicing = !!pos_config.iface_invoicing; - return self.fetch('sale.shop',[],[['id','=',pos_config.shop_id[0]]]); + return self.fetch('stock.warehouse',[],[['id','=',pos_config.warehouse_id[0]]]); }).then(function(shops){ self.set('shop',shops[0]); @@ -174,7 +174,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal ['name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description'], [['sale_ok','=',true],['available_in_pos','=',true]], - {pricelist: self.get('shop').pricelist_id[0]} // context for price + {pricelist: self.get('pos_config').pricelist_id[0]} // context for price ); }).then(function(products){ self.db.add_products(products); @@ -240,12 +240,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal } }, - // saves the order locally and try to send it to the backend. 'record' is a bizzarely defined JSON version of the Order - push_order: function(record) { - this.db.add_order(record); - this.flush(); - }, - //creates a new empty order and sets it as the current order add_new_order: function(){ var order = new module.Order({pos:this}); @@ -253,45 +247,161 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.set('selectedOrder', order); }, + // saves the order locally and try to send it to the backend. + // it returns a deferred that succeeds after having tried to send the order and all the other pending orders. + push_order: function(order) { + var self = this; + var order_id = this.db.add_order(order.export_as_JSON()); + var pushed = new $.Deferred(); + + this.set('nbr_pending_operations',self.db.get_orders().length); + + this.flush_mutex.exec(function(){ + var flushed = self._flush_all_orders(); + + flushed.always(function(){ + pushed.resolve(); + }); + + return flushed; + }); + return pushed; + }, + + // saves the order locally and try to send it to the backend and make an invoice + // returns a deferred that succeeds when the order has been posted and successfully generated + // an invoice. This method can fail in various ways: + // error-no-client: the order must have an associated partner_id. You can retry to make an invoice once + // this error is solved + // error-transfer: there was a connection error during the transfer. You can retry to make the invoice once + // the network connection is up + + push_and_invoice_order: function(order){ + var self = this; + var invoiced = new $.Deferred(); + + if(!order.get_client()){ + invoiced.reject('error-no-client'); + return invoiced; + } + + var order_id = this.db.add_order(order.export_as_JSON()); + + this.set('nbr_pending_operations',self.db.get_orders().length); + + this.flush_mutex.exec(function(){ + var done = new $.Deferred(); // holds the mutex + + // send the order to the server + // we have a 30 seconds timeout on this push. + // FIXME: if the server takes more than 30 seconds to accept the order, + // the client will believe it wasn't successfully sent, and very bad + // things will happen as a duplicate will be sent next time + // so we must make sure the server detects and ignores duplicated orders + + var transfer = self._flush_order(order_id, {timeout:30000, to_invoice:true}); + + transfer.fail(function(){ + invoiced.reject('error-transfer'); + done.reject(); + }); + + // on success, get the order id generated by the server + transfer.pipe(function(order_server_id){ + // generate the pdf and download it + self.pos_widget.do_action('point_of_sale.pos_invoice_report',{additional_context:{ + active_ids:order_server_id, + }}); + invoiced.resolve(); + done.resolve(); + }); + + return done; + + }); + + return invoiced; + }, + // attemps to send all pending orders ( stored in the pos_db ) to the server, // and remove the successfully sent ones from the db once // it has been confirmed that they have been sent correctly. flush: function() { - //TODO make the mutex work - //this makes sure only one _int_flush is called at the same time - /* - return this.flush_mutex.exec(_.bind(function() { - return this._flush(0); - }, this)); - */ - this._flush(0); + var self = this; + var flushed = new $.Deferred(); + + this.flush_mutex.exec(function(){ + var done = new $.Deferred(); + + self._flush_all_orders() + .done( function(){ flushed.resolve();}) + .fail( function(){ flushed.reject(); }) + .always(function(){ done.resolve(); }); + + return done; + }); + + return flushed; }, - // attempts to send an order of index 'index' in the list of order to send. The index - // is used to skip orders that failed. do not call this method outside the mutex provided - // by flush() - _flush: function(index){ + + // attempts to send the locally stored order of id 'order_id' + // the sending is asynchronous and can take some time to decide if it is successful or not + // it is therefore important to only call this method from inside a mutex + // this method returns a deferred indicating wether the sending was successful or not + // there is a timeout parameter which is set to 2 seconds by default. + _flush_order: function(order_id, options){ + var self = this; + options = options || {}; + timeout = typeof options.timeout === 'number' ? options.timeout : 5000; + + var order = this.db.get_order(order_id); + order.to_invoice = options.to_invoice || false; + + if(!order){ + // flushing a non existing order always fails + return (new $.Deferred()).reject(); + } + + // we try to send the order. shadow prevents a spinner if it takes too long. (unless we are sending an invoice, + // then we want to notify the user that we are waiting on something ) + var rpc = (new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{shadow: !options.to_invoice, timeout:timeout}); + + rpc.fail(function(unused,event){ + // prevent an error popup creation by the rpc failure + // we want the failure to be silent as we send the orders in the background + event.preventDefault(); + console.error('Failed to send order:',order); + }); + + rpc.done(function(){ + self.db.remove_order(order_id); + self.set('nbr_pending_operations',self.db.get_orders().length); + }); + + return rpc; + }, + + // attempts to send all the locally stored orders. As with _flush_order, it should only be + // called from within a mutex. + // this method returns a deferred that always succeeds when all orders have been tried to be sent, + // even if none of them could actually be sent. + _flush_all_orders: function(){ var self = this; var orders = this.db.get_orders(); - self.set('nbr_pending_operations',orders.length); + var tried_all = new $.Deferred(); - var order = orders[index]; - if(!order){ - return; + function rec_flush(index){ + if(index < orders.length){ + self._flush_order(orders[index].id).always(function(){ + rec_flush(index+1); + }) + }else{ + tried_all.resolve(); + } } - //try to push an order to the server - // shadow : true is to prevent a spinner to appear in case of timeout - (new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{ shadow:true }) - .fail(function(unused, event){ - //don't show error popup if it fails - event.preventDefault(); - console.error('Failed to send order:',order); - self._flush(index+1); - }) - .done(function(){ - //remove from db if success - self.db.remove_order(order.id); - self._flush(index); - }); + rec_flush(0); + + return tried_all; }, scan_product: function(parsed_ean){ @@ -323,7 +433,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal module.Product = Backbone.Model.extend({ get_image_url: function(){ - return instance.session.url('/web/binary/image', {model: 'product.product', field: 'image', id: this.get('id')}); + return instance.session.url('/web/binary/image', {model: 'product.product', field: 'image_medium', id: this.get('id')}); }, }); @@ -590,11 +700,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal module.Order = Backbone.Model.extend({ initialize: function(attributes){ Backbone.Model.prototype.initialize.apply(this, arguments); + this.uid = this.generateUniqueId(); this.set({ creationDate: new Date(), orderLines: new module.OrderlineCollection(), paymentLines: new module.PaymentlineCollection(), - name: "Order " + this.generateUniqueId(), + name: "Order " + this.uid, client: null, }); this.pos = attributes.pos; @@ -770,7 +881,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal currency: this.pos.get('currency'), }; }, - exportAsJSON: function() { + export_as_JSON: function() { var orderLines, paymentLines; orderLines = []; (this.get('orderLines')).each(_.bind( function(item) { @@ -789,8 +900,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal lines: orderLines, statement_ids: paymentLines, pos_session_id: this.pos.get('pos_session').id, - partner_id: this.pos.get('client') ? this.pos.get('client').id : undefined, + partner_id: this.get_client() ? this.get_client().id : false, user_id: this.pos.get('cashier') ? this.pos.get('cashier').id : this.pos.get('user').id, + uid: this.uid, }; }, getSelectedLine: function(){ diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 0bd399428ed..e0a8ba4b71c 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -16,7 +16,8 @@ // hide()s function openerp_pos_screens(instance, module){ //module is instance.point_of_sale - var QWeb = instance.web.qweb; + var QWeb = instance.web.qweb, + _t = instance.web._t; module.ScreenSelector = instance.web.Class.extend({ init: function(options){ @@ -264,7 +265,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // we add the help button by default. we do this because the buttons are cleared on each refresh so that // the button stay local to each screen this.pos_widget.left_action_bar.add_new_button({ - label: 'help', + label: _t('Help'), icon: '/point_of_sale/static/src/img/icons/png48/help.png', click: function(){ self.help_button_action(); }, }); @@ -433,6 +434,14 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa template:'ErrorNegativePricePopupWidget', }); + module.ErrorNoClientPopupWidget = module.ErrorPopupWidget.extend({ + template: 'ErrorNoClientPopupWidget', + }); + + module.ErrorInvoiceTransferPopupWidget = module.ErrorPopupWidget.extend({ + template: 'ErrorInvoiceTransferPopupWidget', + }); + module.ScaleInviteScreenWidget = module.ScreenWidget.extend({ template:'ScaleInviteScreenWidget', @@ -451,10 +460,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa clearInterval(this.intervalID); self.pos_widget.screen_selector.set_current_screen(self.next_screen); } - },500); + },100); this.add_action_button({ - label: 'back', + label: _t('Back'), icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png', click: function(){ clearInterval(this.intervalID); @@ -483,7 +492,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.add_action_button({ - label: 'back', + label: _t('Back'), icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png', click: function(){ self.pos_widget.screen_selector.set_current_screen(self.previous_screen); @@ -491,7 +500,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }); this.validate_button = this.add_action_button({ - label: 'Validate', + label: _t('Validate'), icon: '/point_of_sale/static/src/img/icons/png48/validate.png', click: function(){ self.order_product(); @@ -506,7 +515,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa self.weight = weight; self.renderElement(); } - },200); + },100); }, renderElement: function(){ var self = this; @@ -639,7 +648,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa var cashregister = selfCheckoutRegisters[0] || self.pos.get('cashRegisters').models[0]; currentOrder.addPaymentLine(cashregister); - self.pos.push_order(currentOrder.exportAsJSON()) + self.pos.push_order(currentOrder) currentOrder.destroy(); self.pos.proxy.transaction_end(); self.pos_widget.screen_selector.set_current_screen(self.next_screen); @@ -674,7 +683,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa } this.add_action_button({ - label: 'back', + label: _t('Back'), icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png', click: function(){ self.queue.schedule(self.cancel); @@ -714,7 +723,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa var self = this; this.add_action_button({ - label: 'help', + label: _t('Help'), icon: '/point_of_sale/static/src/img/icons/png48/help.png', click: function(){ $('.goodbye-message').css({opacity:1}).hide(); @@ -768,7 +777,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa if(this.pos_widget.screen_selector.current_mode === 'client'){ this.add_action_button({ - label: 'pay', + label: _t('Pay'), icon: '/point_of_sale/static/src/img/icons/png48/go-next.png', click: function(){ self.pos_widget.screen_selector.set_current_screen(self.client_next_screen); @@ -807,19 +816,42 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this._super(); var self = this; - this.add_action_button({ - label: 'Print', + var print_button = this.add_action_button({ + label: _t('Print'), icon: '/point_of_sale/static/src/img/icons/png48/printer.png', click: function(){ self.print(); }, }); - this.add_action_button({ - label: 'Next Order', + var finish_button = this.add_action_button({ + label: _t('Next Order'), icon: '/point_of_sale/static/src/img/icons/png48/go-next.png', click: function() { self.finishOrder(); }, }); window.print(); + + // THIS IS THE HACK OF THE CENTURY + // + // The problem is that in chrome the print() is asynchronous and doesn't + // execute until all rpc are finished. So it conflicts with the rpc used + // to send the orders to the backend, and the user is able to go to the next + // screen before the printing dialog is opened. The problem is that what's + // printed is whatever is in the page when the dialog is opened and not when it's called, + // and so you end up printing the product list instead of the receipt... + // + // Fixing this would need a re-architecturing + // of the code to postpone sending of orders after printing. + // + // But since the print dialog also blocks the other asynchronous calls, the + // button enabling in the setTimeout() is blocked until the printing dialog is + // closed. But the timeout has to be big enough or else it doesn't work + // 2 seconds is the same as the default timeout for sending orders and so the dialog + // should have appeared before the timeout... so yeah that's not ultra reliable. + + finish_button.set_disabled(true); + setTimeout(function(){ + finish_button.set_disabled(false); + }, 2000); }, print: function() { window.print(); @@ -869,22 +901,33 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.set_numpad_state(this.pos_widget.numpad.state); - this.back_button = this.add_action_button({ - label: 'Back', + this.add_action_button({ + label: _t('Back'), icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png', click: function(){ self.pos_widget.screen_selector.set_current_screen(self.back_screen); }, }); - - this.validate_button = this.add_action_button({ - label: 'Validate', + + this.add_action_button({ + label: _t('Validate'), name: 'validation', icon: '/point_of_sale/static/src/img/icons/png48/validate.png', click: function(){ self.validateCurrentOrder(); }, }); + + if(this.pos.iface_invoicing){ + this.add_action_button({ + label: 'Invoice', + name: 'invoice', + icon: '/point_of_sale/static/src/img/icons/png48/invoice.png', + click: function(){ + self.validateCurrentOrder({invoice: true}); + }, + }); + } this.updatePaymentSummary(); this.line_refocus(); @@ -897,15 +940,44 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa back: function() { this.pos_widget.screen_selector.set_current_screen(self.back_screen); }, - validateCurrentOrder: function() { + validateCurrentOrder: function(options) { + var self = this; + options = options || {}; + var currentOrder = this.pos.get('selectedOrder'); - this.pos.push_order(currentOrder.exportAsJSON()) - if(this.pos.iface_print_via_proxy){ - this.pos.proxy.print_receipt(currentOrder.export_for_printing()); - this.pos.get('selectedOrder').destroy(); //finish order and go back to scan screen + + if(options.invoice){ + // deactivate the validation button while we try to send the order + this.pos_widget.action_bar.set_button_disabled('validation',true); + this.pos_widget.action_bar.set_button_disabled('invoice',true); + + var invoiced = this.pos.push_and_invoice_order(currentOrder); + + invoiced.fail(function(error){ + if(error === 'error-no-client'){ + self.pos_widget.screen_selector.show_popup('error-no-client'); + }else{ + self.pos_widget.screen_selector.show_popup('error-invoice-transfer'); + } + self.pos_widget.action_bar.set_button_disabled('validation',false); + self.pos_widget.action_bar.set_button_disabled('invoice',false); + }); + + invoiced.done(function(){ + self.pos_widget.action_bar.set_button_disabled('validation',false); + self.pos_widget.action_bar.set_button_disabled('invoice',false); + self.pos.get('selectedOrder').destroy(); + }); + }else{ - this.pos_widget.screen_selector.set_current_screen(this.next_screen); + this.pos.push_order(currentOrder) + if(this.pos.iface_print_via_proxy){ + this.pos.proxy.print_receipt(currentOrder.export_for_printing()); + this.pos.get('selectedOrder').destroy(); //finish order and go back to scan screen + }else{ + this.pos_widget.screen_selector.set_current_screen(this.next_screen); + } } }, bindPaymentLineEvents: function() { @@ -984,6 +1056,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa if(this.pos_widget.action_bar){ this.pos_widget.action_bar.set_button_disabled('validation', remaining > 0.000001); + this.pos_widget.action_bar.set_button_disabled('invoice', remaining > 0.000001); } }, set_numpad_state: function(numpadState) { diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index cec48dbe72f..911d8cd321b 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -1,5 +1,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sale - var QWeb = instance.web.qweb; + var QWeb = instance.web.qweb, + _t = instance.web._t; // The ImageCache is used to hide the latency of the application cache on-disk access in chrome // that causes annoying flickering on product pictures. Why the hell a simple access to @@ -319,6 +320,14 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.payment_line.set_amount(amount); } }, + checkAmount: function(e){ + if (e.which !== 0 && e.charCode !== 0) { + if(isNaN(String.fromCharCode(e.charCode))){ + return (String.fromCharCode(e.charCode) === "." && e.currentTarget.value.toString().split(".").length < 2)?true:false; + } + } + return true + }, changedAmount: function() { if (this.amount !== this.payment_line.get_amount()){ this.renderElement(); @@ -328,7 +337,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var self = this; this.name = this.payment_line.get_cashregister().get('journal_id')[1]; this._super(); - this.$('input').keyup(function(event){ + this.$('input').keypress(_.bind(this.checkAmount, this)) + .keyup(function(event){ self.changeAmount(event); }); this.$('.delete-payment-line').click(function() { @@ -498,7 +508,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, get_image_url: function(category){ - return instance.session.url('/web/binary/image', {model: 'pos.category', field: 'image', id: category.id}); + return instance.session.url('/web/binary/image', {model: 'pos.category', field: 'image_medium', id: category.id}); }, renderElement: function(){ @@ -828,6 +838,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa instance.web.blockUI(); this.pos = new module.PosModel(this.session); + this.pos.pos_widget = this; this.pos_widget = this; //So that pos_widget's childs have pos_widget set automatically this.numpad_visible = true; @@ -942,6 +953,12 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.error_negative_price_popup = new module.ErrorNegativePricePopupWidget(this, {}); this.error_negative_price_popup.appendTo($('.point-of-sale')); + this.error_no_client_popup = new module.ErrorNoClientPopupWidget(this, {}); + this.error_no_client_popup.appendTo($('.point-of-sale')); + + this.error_invoice_transfer_popup = new module.ErrorInvoiceTransferPopupWidget(this, {}); + this.error_invoice_transfer_popup.appendTo($('.point-of-sale')); + // -------- Misc --------- this.notification = new module.SynchNotificationWidget(this,{}); @@ -971,13 +988,13 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.onscreen_keyboard.appendTo($(".point-of-sale #content")); this.close_button = new module.HeaderButtonWidget(this,{ - label:'Close', + label: _t('Close'), action: function(){ self.try_close(); }, }); this.close_button.appendTo(this.$('#rightheader')); this.client_button = new module.HeaderButtonWidget(this,{ - label:'Self-Checkout', + label: _t('Self-Checkout'), action: function(){ self.screen_selector.set_user_mode('client'); }, }); this.client_button.appendTo(this.$('#rightheader')); @@ -1003,6 +1020,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa 'error-session': this.error_session_popup, 'error-negative-price': this.error_negative_price_popup, 'choose-receipt': this.choose_receipt_popup, + 'error-no-client': this.error_no_client_popup, + 'error-invoice-transfer': this.error_invoice_transfer_popup, }, default_client_screen: 'welcome', default_cashier_screen: 'products', diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 3da76ec12d8..e28ea1c06b0 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -336,11 +336,11 @@ - @@ -361,6 +361,33 @@ + + + + + + + +