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 1a44e480e03..a68c1de0939 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -132,7 +132,6 @@ class account_payment_term_line(osv.osv): (_check_percent, 'Percentages for Payment Term Line must be between 0 and 1, Example: 0.02 for 2%.', ['value_amount']), ] -account_payment_term_line() class account_account_type(osv.osv): _name = "account.account.type" @@ -198,7 +197,6 @@ class account_account_type(osv.osv): } _order = "code" -account_account_type() def _code_get(self, cr, uid, context=None): acc_type_obj = self.pool.get('account.account.type') @@ -212,7 +210,6 @@ def _code_get(self, cr, uid, context=None): class account_tax(osv.osv): _name = 'account.tax' -account_tax() class account_account(osv.osv): _order = "parent_left" @@ -651,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 @@ -697,7 +694,6 @@ class account_account(osv.osv): self._check_moves(cr, uid, ids, "unlink", context=context) return super(account_account, self).unlink(cr, uid, ids, context=context) -account_account() class account_journal(osv.osv): _name = "account.journal" @@ -849,7 +845,6 @@ class account_journal(osv.osv): return self.name_get(cr, user, ids, context=context) -account_journal() class account_fiscalyear(osv.osv): _name = "account.fiscalyear" @@ -945,7 +940,6 @@ class account_fiscalyear(osv.osv): ids = self.search(cr, user, [('name', operator, name)]+ args, limit=limit) return self.name_get(cr, user, ids, context=context) -account_fiscalyear() class account_period(osv.osv): _name = "account.period" @@ -1007,8 +1001,7 @@ class account_period(osv.osv): def find(self, cr, uid, dt=None, context=None): if context is None: context = {} if not dt: - dt = fields.date.context_today(self,cr,uid,context=context) -#CHECKME: shouldn't we check the state of the period? + dt = fields.date.context_today(self, cr, uid, context=context) args = [('date_start', '<=' ,dt), ('date_stop', '>=', dt)] if context.get('company_id', False): args.append(('company_id', '=', context['company_id'])) @@ -1016,20 +1009,20 @@ class account_period(osv.osv): company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id args.append(('company_id', '=', company_id)) result = [] - if context.get('account_period_prefer_normal'): + if context.get('account_period_prefer_normal', True): # look for non-special periods first, and fallback to all if no result is found result = self.search(cr, uid, args + [('special', '=', False)], context=context) 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 @@ -1041,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): @@ -1066,12 +1065,15 @@ 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)]) -account_period() class account_journal_period(osv.osv): _name = "account.journal.period" @@ -1128,7 +1130,6 @@ class account_journal_period(osv.osv): } _order = "period_id" -account_journal_period() class account_fiscalyear(osv.osv): _inherit = "account.fiscalyear" @@ -1145,7 +1146,6 @@ class account_fiscalyear(osv.osv): }) return super(account_fiscalyear, self).copy(cr, uid, id, default=default, context=context) -account_fiscalyear() #---------------------------------------------------------- # Entries #---------------------------------------------------------- @@ -1223,7 +1223,7 @@ class account_move(osv.osv): return res def _get_period(self, cr, uid, context=None): - ctx = dict(context or {}, account_period_prefer_normal=True) + ctx = dict(context or {}) period_ids = self.pool.get('account.period').find(cr, uid, context=ctx) return period_ids[0] @@ -1384,6 +1384,7 @@ class account_move(osv.osv): 'ref':False, 'balance':False, 'account_tax_id':False, + 'statement_id': False, }) if 'journal_id' in vals and vals.get('journal_id', False): @@ -1420,6 +1421,7 @@ class account_move(osv.osv): context = {} if context is None else context.copy() default.update({ 'state':'draft', + 'ref': False, 'name':'/', }) context.update({ @@ -1641,7 +1643,6 @@ class account_move(osv.osv): valid_moves = [move.id for move in valid_moves] return len(valid_moves) > 0 and valid_moves or False -account_move() class account_move_reconcile(osv.osv): _name = "account.move.reconcile" @@ -1679,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 @@ -1715,7 +1716,6 @@ class account_move_reconcile(osv.osv): result.append((r.id,r.name)) return result -account_move_reconcile() #---------------------------------------------------------- # Tax @@ -1795,7 +1795,7 @@ class account_tax_code(osv.osv): if context.get('period_id', False): period_id = context['period_id'] else: - period_id = self.pool.get('account.period').find(cr, uid) + period_id = self.pool.get('account.period').find(cr, uid, context=context) if not period_id: return dict.fromkeys(ids, 0.0) period_id = period_id[0] @@ -1863,7 +1863,12 @@ class account_tax_code(osv.osv): ] _order = 'code' -account_tax_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): """ @@ -1885,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 = { @@ -2271,7 +2270,6 @@ class account_tax(osv.osv): total += r['amount'] return res -account_tax() # --------------------------------------------------------- # Account Entries Models @@ -2319,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, @@ -2331,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, @@ -2383,7 +2381,6 @@ class account_model(osv.osv): return {'value': {'company_id': company_id}} -account_model() class account_model_line(osv.osv): _name = "account.model.line" @@ -2407,7 +2404,6 @@ class account_model_line(osv.osv): ('credit_debit1', 'CHECK (credit*debit=0)', 'Wrong credit or debit value in model, they must be positive!'), ('credit_debit2', 'CHECK (credit+debit>=0)', 'Wrong credit or debit value in model, they must be positive!'), ] -account_model_line() # --------------------------------------------------------- # Account Subscription @@ -2481,7 +2477,6 @@ class account_subscription(osv.osv): self.write(cr, uid, ids, {'state':'running'}) return True -account_subscription() class account_subscription_line(osv.osv): _name = "account.subscription.line" @@ -2510,7 +2505,6 @@ class account_subscription_line(osv.osv): _rec_name = 'date' -account_subscription_line() # --------------------------------------------------------------- # Account Templates: Account, Tax, Tax Code and chart. + Wizard @@ -2518,7 +2512,6 @@ account_subscription_line() class account_tax_template(osv.osv): _name = 'account.tax.template' -account_tax_template() class account_account_template(osv.osv): _order = "code" @@ -2646,7 +2639,6 @@ class account_account_template(osv.osv): obj_acc._parent_store_compute(cr) return acc_template_ref -account_account_template() class account_add_tmpl_wizard(osv.osv_memory): """Add one more account from the template. @@ -2700,7 +2692,6 @@ class account_add_tmpl_wizard(osv.osv_memory): def action_cancel(self, cr, uid, ids, context=None): return { 'type': 'state', 'state': 'end' } -account_add_tmpl_wizard() class account_tax_code_template(osv.osv): @@ -2772,7 +2763,6 @@ class account_tax_code_template(osv.osv): (_check_recursion, 'Error!\nYou cannot create recursive Tax Codes.', ['parent_id']) ] _order = 'code,name' -account_tax_code_template() class account_chart_template(osv.osv): @@ -2805,7 +2795,6 @@ class account_chart_template(osv.osv): 'complete_tax_set': True, } -account_chart_template() class account_tax_template(osv.osv): @@ -2816,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."), @@ -2935,7 +2924,6 @@ class account_tax_template(osv.osv): res.update({'tax_template_to_tax': tax_template_to_tax, 'account_dict': todo_dict}) return res -account_tax_template() # Fiscal Position Templates @@ -2983,7 +2971,6 @@ class account_fiscal_position_template(osv.osv): }) return True -account_fiscal_position_template() class account_fiscal_position_tax_template(osv.osv): _name = 'account.fiscal.position.tax.template' @@ -2996,7 +2983,6 @@ class account_fiscal_position_tax_template(osv.osv): 'tax_dest_id': fields.many2one('account.tax.template', 'Replacement Tax') } -account_fiscal_position_tax_template() class account_fiscal_position_account_template(osv.osv): _name = 'account.fiscal.position.account.template' @@ -3008,7 +2994,6 @@ class account_fiscal_position_account_template(osv.osv): 'account_dest_id': fields.many2one('account.account.template', 'Account Destination', domain=[('type','<>','view')], required=True) } -account_fiscal_position_account_template() # --------------------------------------------------------- # Account generation from template wizards @@ -3401,7 +3386,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): try: tmp2 = obj_data.get_object_reference(cr, uid, *ref) if tmp2: - self.pool.get(tmp2[0]).write(cr, uid, tmp2[1], { + self.pool[tmp2[0]].write(cr, uid, tmp2[1], { 'currency_id': obj_wizard.currency_id.id }) except ValueError, e: @@ -3548,7 +3533,6 @@ class wizard_multi_charts_accounts(osv.osv_memory): current_num += 1 return True -wizard_multi_charts_accounts() class account_bank_accounts_wizard(osv.osv_memory): _name='account.bank.accounts.wizard' @@ -3560,6 +3544,5 @@ class account_bank_accounts_wizard(osv.osv_memory): 'account_type': fields.selection([('cash','Cash'), ('check','Check'), ('bank','Bank')], 'Account Type', size=32), } -account_bank_accounts_wizard() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index f3617106f28..e141f33b9d1 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -143,7 +143,6 @@ class account_analytic_line(osv.osv): return res return False -account_analytic_line() class res_partner(osv.osv): """ Inherits partner and adds contract information in the partner form """ @@ -154,6 +153,5 @@ class res_partner(osv.osv): 'partner_id', 'Contracts', readonly=True), } -res_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 8e1a5dd26c6..8a15321b9c6 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -61,7 +61,7 @@ class account_bank_statement(osv.osv): return res def _get_period(self, cr, uid, context=None): - periods = self.pool.get('account.period').find(cr, uid,context=context) + periods = self.pool.get('account.period').find(cr, uid, context=context) if periods: return periods[0] return False @@ -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) @@ -500,7 +500,6 @@ class account_bank_statement(osv.osv): 'context':ctx, } -account_bank_statement() class account_bank_statement_line(osv.osv): @@ -576,6 +575,5 @@ class account_bank_statement_line(osv.osv): 'type': 'general', } -account_bank_statement_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py index 86d3b0d24de..8e3e250d41c 100644 --- a/addons/account/account_cash_statement.py +++ b/addons/account/account_cash_statement.py @@ -66,7 +66,6 @@ class account_cashbox_line(osv.osv): 'bank_statement_id' : fields.many2one('account.bank.statement', ondelete='cascade'), } -account_cashbox_line() class account_cash_statement(osv.osv): @@ -253,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} @@ -316,7 +315,6 @@ class account_cash_statement(osv.osv): return self.write(cr, uid, ids, {'closing_date': time.strftime("%Y-%m-%d %H:%M:%S")}, context=context) -account_cash_statement() class account_journal(osv.osv): _inherit = 'account.journal' @@ -336,7 +334,6 @@ class account_journal(osv.osv): 'cashbox_line_ids' : _default_cashbox_line_ids, } -account_journal() class account_journal_cashbox_line(osv.osv): _name = 'account.journal.cashbox.line' @@ -348,6 +345,5 @@ class account_journal_cashbox_line(osv.osv): _order = 'pieces asc' -account_journal_cashbox_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account_financial_report.py b/addons/account/account_financial_report.py index e8b58f61882..0c2e5845b89 100644 --- a/addons/account/account_financial_report.py +++ b/addons/account/account_financial_report.py @@ -138,6 +138,5 @@ class account_financial_report(osv.osv): 'style_overwrite': 0, } -account_financial_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: 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/nl_BE.po b/addons/account_followup/i18n/nl_BE.po index 1a92e60dfc9..64a73d776ef 100644 --- a/addons/account_followup/i18n/nl_BE.po +++ b/addons/account_followup/i18n/nl_BE.po @@ -1,20 +1,21 @@ # Translation of OpenERP Server. # This file contains the translation of the following modules: -# * account_followup -# +# * account_followup +# Els Van Vossel , 2013. msgid "" 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:05+0000\n" -"PO-Revision-Date: 2010-12-17 09:57+0000\n" -"Last-Translator: Niels Huylebroeck \n" -"Language-Team: \n" +"PO-Revision-Date: 2013-04-15 23:02+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:11+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-17 05:15+0000\n" +"X-Generator: Launchpad (build 16567)\n" +"Language: nl\n" #. module: account_followup #: model:email.template,subject:account_followup.email_template_account_followup_default @@ -22,12 +23,12 @@ 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} Aanmaning" #. module: account_followup #: help:res.partner,latest_followup_level_id:0 msgid "The maximum follow-up level" -msgstr "" +msgstr "Het maximale aanmaningsniveau" #. module: account_followup #: view:account_followup.stat:0 @@ -43,33 +44,33 @@ msgstr "Aanmanen" #. 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 "Volgende actiedatum" #. module: account_followup #: view:account_followup.followup.line:0 #: field:account_followup.followup.line,manual_action:0 msgid "Manual Action" -msgstr "" +msgstr "Manuele actie" #. module: account_followup #: field:account_followup.sending.results,needprinting:0 msgid "Needs Printing" -msgstr "" +msgstr "Moet worden afgedrukt" #. module: account_followup #: view:res.partner:0 msgid "⇾ Mark as Done" -msgstr "" +msgstr "⇾ Als Gedaan markeren" #. module: account_followup #: field:account_followup.followup.line,manual_action_note:0 msgid "Action To Do" -msgstr "" +msgstr "Uit te voeren actie" #. module: account_followup #: field:account_followup.followup,company_id:0 @@ -89,39 +90,39 @@ msgstr "Factuurdatum" #. module: account_followup #: field:account_followup.print,email_subject:0 msgid "Email Subject" -msgstr "E-mail onderwerp" +msgstr "E-mailonderwerp" #. 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 msgid "days overdue, do the following actions:" -msgstr "" +msgstr "dagen vervallen, voer volgende acties uit:" #. module: account_followup #: view:account_followup.followup.line:0 msgid "Follow-up Steps" -msgstr "" +msgstr "Aanmaningsstappen" #. module: account_followup #: field:account_followup.print,email_body:0 msgid "Email Body" -msgstr "" +msgstr "E-mailbericht" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_account_followup_print msgid "Send Follow-Ups" -msgstr "" +msgstr "Aanmaningen versturen" #. module: account_followup #: report:account_followup.followup.print:0 #: code:addons/account_followup/account_followup.py:263 #, python-format msgid "Amount" -msgstr "" +msgstr "Bedrag" #. module: account_followup #: help:res.partner,payment_next_action:0 @@ -129,11 +130,14 @@ msgid "" "This is the next action to be taken. It will automatically be set when the " "partner gets a follow-up level that requires a manual action. " msgstr "" +"Dit is de volgende actie die moet worden ondernomen. Deze wordt automatisch " +"ingesteld als de relatie een aanmaningsniveau bereikt waarvoor een manuele " +"actie is vereist. " #. module: account_followup #: view:res.partner:0 msgid "No Responsible" -msgstr "" +msgstr "Niemand verantwoordelijk" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line2 @@ -158,6 +162,24 @@ msgid "" "\n" "Best Regards,\n" msgstr "" +"\n" +"Beste %(partner_name)s,\n" +"\n" +"Het spijt ons te moeten vaststellen dat, ondanks een eerdere aanmaning, u " +"nog steeds een openstaand saldo hebt.\n" +"\n" +"Wij verzoeken u dringend het openstaande saldo te betalen. Bij gebrek aan " +"betaling, zijn wij genoodzaakt de verdere levering van goederen en diensten " +"stop te zetten.\n" +"Gelieve de betalingen uit te voeren binnen de 8 dagen.\n" +"\n" +"Als er een probleem is rond de betaling waarvan wij niet op de hoogte zijn, " +"kunt u steeds contact opnemen met onze boekhouding, zodat dit snel kan " +"worden opgelost.\n" +"\n" +"Hierna vindt u een overzicht van de vervallen documenten.\n" +"\n" +"Hoogachtend,\n" #. module: account_followup #: model:email.template,body_html:account_followup.email_template_account_followup_level0 @@ -195,6 +217,38 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +"\n" +"

Beste ${object.name},

\n" +"

\n" +" Volgens onze informatie, heeft u nog een openstaand saldo. Wij verzoeken " +"u het nodige te doen om deze betaling binnen de 8 dagen over te schrijven op " +"onze rekening.\n" +"\n" +"Indien uw betaling deze e-mail heeft gekruist, mag u dit bericht als " +"onbestaand beschouwen. Neem gerust contact op met onze boekhouding mocht u " +"nog vragen hebben.\n" +"\n" +"

\n" +"
\n" +"Met vriendelijke groeten,\n" +"
\n" +"
\n" +"${user.name}\n" +"\n" +"
\n" +"
\n" +"\n" +"\n" +"${object.get_followup_table_html() | safe}\n" +"\n" +"
\n" +"\n" +"
\n" +" " #. module: account_followup #: view:account_followup.stat.by.partner:0 @@ -209,17 +263,17 @@ msgstr "Totaal debet" #. module: account_followup #: field:res.partner,payment_next_action:0 msgid "Next Action" -msgstr "" +msgstr "Volgende actie" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": Partner Name" -msgstr "" +msgstr "Relatienaam" #. module: account_followup #: field:account_followup.followup.line,manual_action_responsible_id:0 msgid "Assign a Responsible" -msgstr "" +msgstr "Duid iemand aan die verantwoordelijk is" #. module: account_followup #: view:account_followup.followup:0 @@ -231,7 +285,7 @@ msgstr "Aanmaning" #. module: account_followup #: report:account_followup.followup.print:0 msgid "VAT:" -msgstr "BTW:" +msgstr "Btw:" #. module: account_followup #: view:account_followup.stat:0 @@ -255,11 +309,24 @@ msgid "" " same customer, the actions of the most \n" " overdue invoice will be executed." msgstr "" +"Om klanten aan te manen tot betaling, kunt u\n" +" verschillende acties instellen in functie van de " +"grootte\n" +" van het openstaand bedrag. Deze acties worden " +"samengevoegd\n" +" in aanmaningsniveaus die worden aangesproken als de\n" +" vervaldatum van een factuur een ingesteld aantal " +"dagen\n" +" overschrijdt. Als de klant ook andere openstaande " +"facturen heeft,\n" +" worden de acties uitgevoerd in functie van het " +"langst \n" +" openstaande document." #. module: account_followup #: report:account_followup.followup.print:0 msgid "Date :" -msgstr "Datum :" +msgstr "Datum:" #. module: account_followup #: field:account_followup.print,partner_ids:0 @@ -269,43 +336,43 @@ msgstr "Relaties" #. module: account_followup #: sql_constraint:account_followup.followup:0 msgid "Only one follow-up per company is allowed" -msgstr "" +msgstr "Per bedrijf is maar een aanmaningsniveau toegelaten." #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:254 #, python-format msgid "Invoices Reminder" -msgstr "Facturen aanmaning" +msgstr "Aanmaning facturen" #. module: account_followup #: help:account_followup.followup.line,send_letter:0 msgid "When processing, it will print a letter" -msgstr "" +msgstr "Bij verwerking wordt een brief gemaakt" #. module: account_followup #: field:res.partner,payment_earliest_due_date:0 msgid "Worst Due Date" -msgstr "" +msgstr "Slechtste vervaldatum" #. module: account_followup #: view:account_followup.stat:0 msgid "Not Litigation" -msgstr "" +msgstr "Geen betwisting" #. module: account_followup #: view:account_followup.print:0 msgid "Send emails and generate letters" -msgstr "" +msgstr "Verstuur e-mails en maak brieven" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_customer_followup msgid "Manual Follow-Ups" -msgstr "" +msgstr "Manuele aanmaningen" #. 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 @@ -347,6 +414,42 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +" \n" +"

Beste ${object.name},

\n" +"

\n" +" Het spijt ons te moeten vaststellen dat, ondanks een eerdere aanmaning, " +"u nog steeds een openstaand saldo hebt.\n" +"Wij verzoeken u dringend het openstaande saldo te betalen. Bij gebrek aan " +"betaling, zijn wij genoodzaakt de verdere levering van goederen en diensten " +"stop te zetten.\n" +"Gelieve de betalingen uit te voeren binnen de 8 dagen.\n" +"\n" +"Als er een probleem is rond de betaling waarvan wij niet op de hoogte zijn, " +"kunt u steeds contact opnemen met onze boekhouding, zodat dit snel kan " +"worden opgelost.\n" +"\n" +"Hierna vindt u een overzicht van de vervallen documenten.\n" +"

\n" +"
\n" +"Hoogachtend,\n" +" \n" +"
\n" +"
\n" +"${user.name}\n" +" \n" +"
\n" +"
\n" +"\n" +"${object.get_followup_table_html() | safe}\n" +"\n" +"
\n" +"\n" +"
\n" +" " #. module: account_followup #: field:account_followup.stat,debit:0 @@ -356,49 +459,49 @@ msgstr "Debet" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_stat msgid "Follow-up Statistics" -msgstr "" +msgstr "Aanmaningsstatistieken" #. module: account_followup #: view:res.partner:0 msgid "Send Overdue Email" -msgstr "" +msgstr "Aanmaningsmail sturen" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_followup_line msgid "Follow-up Criteria" -msgstr "" +msgstr "Aanmaningscriteria" #. module: account_followup #: help:account_followup.followup.line,sequence:0 msgid "Gives the sequence order when displaying a list of follow-up lines." -msgstr "Bepaalt de volgorde bij het afbeelden van de aanmaningregels" +msgstr "Bepaalt de volgorde bij het weergeven van de aanmaningslijnen." #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:166 #, python-format msgid " will be sent" -msgstr "" +msgstr " wordt verstuurd" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": User's Company Name" -msgstr "" +msgstr "Bedrijfsnaam van gebruiker" #. module: account_followup #: view:account_followup.followup.line:0 #: field:account_followup.followup.line,send_letter:0 msgid "Send a Letter" -msgstr "" +msgstr "Brief sturen" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_account_followup_definition_form msgid "Payment Follow-ups" -msgstr "" +msgstr "Aanmaningen" #. module: account_followup #: field:account_followup.followup.line,delay:0 msgid "Due Days" -msgstr "" +msgstr "Dagen vervallen" #. module: account_followup #: field:account.move.line,followup_line_id:0 @@ -414,48 +517,48 @@ msgstr "Laatste aanmaning" #. module: account_followup #: model:ir.ui.menu,name:account_followup.menu_manual_reconcile_followup msgid "Reconcile Invoices & Payments" -msgstr "" +msgstr "Facturen en betalingen afpunten" #. module: account_followup #: model:ir.ui.menu,name:account_followup.account_followup_s msgid "Do Manual Follow-Ups" -msgstr "" +msgstr "Manuele aanmaningen uitvoeren" #. module: account_followup #: report:account_followup.followup.print:0 msgid "Li." -msgstr "" +msgstr "Bt." #. module: account_followup #: field:account_followup.print,email_conf:0 msgid "Send Email Confirmation" -msgstr "" +msgstr "Bevestiging per e-mail sturen" #. module: account_followup #: view:account_followup.stat:0 msgid "Follow-up Entries with period in current year" -msgstr "" +msgstr "Aanmaningen met periode in huidig jaar" #. module: account_followup #: field:account_followup.stat.by.partner,date_followup:0 msgid "Latest follow-up" -msgstr "" +msgstr "Laatste aanmaning" #. module: account_followup #: field:account_followup.print,partner_lang:0 msgid "Send Email in Partner Language" -msgstr "Stuur email-bericht in taal relatie" +msgstr "Stuur e-mail in taal relatie" #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:169 #, python-format msgid " email(s) sent" -msgstr "" +msgstr " e-mail(s) verstuurd" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_print msgid "Print Follow-up & Send Mail to Customers" -msgstr "" +msgstr "Aanmaningen afdrukken & mail sturen naar klanten" #. module: account_followup #: field:account_followup.followup.line,description:0 @@ -466,12 +569,12 @@ msgstr "Afgedrukt bericht" #: code:addons/account_followup/wizard/account_followup_print.py:155 #, python-format msgid "Anybody" -msgstr "" +msgstr "Iedereen" #. module: account_followup #: help:account_followup.followup.line,send_email:0 msgid "When processing, it will send an email" -msgstr "" +msgstr "Bij verwerking wordt een e-mail verstuurd" #. module: account_followup #: view:account_followup.stat.by.partner:0 @@ -481,7 +584,7 @@ msgstr "Relatie voor aanmaning" #. module: account_followup #: view:res.partner:0 msgid "Print Overdue Payments" -msgstr "" +msgstr "Vervallen documenten afdrukken" #. module: account_followup #: field:account_followup.followup.line,followup_id:0 @@ -494,11 +597,13 @@ msgstr "Aanmaningen" #, python-format msgid "Email not sent because of email address of partner not filled in" msgstr "" +"E-mail is niet verstuurd, omdat er voor de relatie geen e-mailadres is " +"ingevuld." #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_followup msgid "Account Follow-up" -msgstr "" +msgstr "Aanmaningen" #. module: account_followup #: help:res.partner,payment_responsible_id:0 @@ -506,11 +611,13 @@ msgid "" "Optionally you can assign a user to this field, which will make him " "responsible for the action." msgstr "" +"U kunt eventueel een gebruiker toewijzen aan dit veld. Dit betekent dat hij " +"verantwoordelijk is voor deze actie." #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_sending_results msgid "Results from the sending of the different letters and emails" -msgstr "" +msgstr "Resultaten van het versturen van brieven en e-mails" #. module: account_followup #: constraint:account_followup.followup.line:0 @@ -518,43 +625,45 @@ msgid "" "Your description is invalid, use the right legend or %% if you want to use " "the percent character." msgstr "" +"Uw beschrijving is niet geldig. Gebruik de juiste parameter of %% als u het " +"percentageteken wilt gebruiken." #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:172 #, python-format msgid " manual action(s) assigned:" -msgstr "" +msgstr " manuele actie(s) toegewezen" #. module: account_followup #: view:res.partner:0 msgid "Search Partner" -msgstr "" +msgstr "Relatie zoeken" #. module: account_followup #: model:ir.ui.menu,name:account_followup.account_followup_print_menu msgid "Send Letters and Emails" -msgstr "" +msgstr "Brieven en e-mails sturen" #. module: account_followup #: view:account_followup.followup:0 msgid "Search Follow-up" -msgstr "" +msgstr "Aanmaningen zoeken" #. module: account_followup #: view:res.partner:0 msgid "Account Move line" -msgstr "" +msgstr "Boeking" #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:237 #, python-format msgid "Send Letters and Emails: Actions Summary" -msgstr "" +msgstr "Brieven en e-mails sturen: overzicht acties" #. module: account_followup #: view:account_followup.print:0 msgid "or" -msgstr "" +msgstr "of" #. module: account_followup #: view:res.partner:0 @@ -562,21 +671,23 @@ msgid "" "If not specified by the latest follow-up level, it will send from the " "default email template" msgstr "" +"Indien dit niet is ingesteld via de laatste aanmaning, dan wordt de " +"standaard e-mailsjabloon gebruikt." #. module: account_followup #: sql_constraint:account_followup.followup.line:0 msgid "Days of the follow-up levels must be different" -msgstr "" +msgstr "De dagen moeten verschillen per aanmaningsniveau." #. module: account_followup #: view:res.partner:0 msgid "Click to mark the action as done." -msgstr "" +msgstr "Klik om de actie als Gedaan te markeren." #. module: account_followup #: model:ir.ui.menu,name:account_followup.menu_action_followup_stat_follow msgid "Follow-Ups Analysis" -msgstr "" +msgstr "Aanmaningsanalyse" #. module: account_followup #: help:res.partner,payment_next_action_date:0 @@ -586,11 +697,15 @@ msgid "" "action. Can be practical to set manually e.g. to see if he keeps his " "promises." msgstr "" +"Dit is als er manuele opvolging nodig is. De datum wordt ingesteld op de " +"huidige datum als de relatie een aanmaningsniveau bereikt waarvoor een " +"manuele handeling nodig is. Kan handig zijn om dit als manueel in te " +"stellen, vb. om na te gaan of beloften worden nagekomen." #. module: account_followup #: view:res.partner:0 msgid "Print overdue payments report independent of follow-up line" -msgstr "" +msgstr "Aanmaningen afdrukken onafgezien van de aanmaningslijn." #. module: account_followup #: help:account_followup.print,date:0 @@ -609,7 +724,7 @@ msgstr "Verzenddatum aanmaning" #: view:res.partner:0 #: field:res.partner,payment_responsible_id:0 msgid "Follow-up Responsible" -msgstr "" +msgstr "Verantwoordelijk voor aanmaning" #. module: account_followup #: model:email.template,body_html:account_followup.email_template_account_followup_level2 @@ -646,16 +761,48 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +" \n" +"

Beste ${object.name},

\n" +"

\n" +" Ondanks het feit dat wij u meerdere aanmaningen hebben gestuurd, is uw " +"openstaand saldo nog steeds niet betaald.\n" +"Indien de betaling ervan niet binnen de 8 dagen op onze rekening staat, " +"schakelen wij een advocaat in om het verschuldigde saldo bij u te innen. U " +"ontvangt hierover geen verdere communicatie.\n" +"Wij gaan ervan uit dat deze stap niet nodig zal zijn. De details van de " +"openstaande betalingen vindt u hierna.\n" +"Aarzel niet contact op te nemen met onze boekhouding als u nog vragen " +"heeft.\n" +"

\n" +"
\n" +"Hoogachtend,\n" +"
\n" +"
\n" +"${user.name}\n" +"
\n" +"
\n" +"\n" +"\n" +"${object.get_followup_table_html() | safe}\n" +"\n" +"
\n" +"\n" +"
\n" +" " #. module: account_followup #: report:account_followup.followup.print:0 msgid "Document : Customer account statement" -msgstr "" +msgstr "Document: Rekeninguittreksel" #. module: account_followup #: model:ir.ui.menu,name:account_followup.account_followup_menu msgid "Follow-up Levels" -msgstr "" +msgstr "Aanmaningsniveaus" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line4 @@ -678,11 +825,27 @@ msgid "" "Best Regards,\n" " " msgstr "" +"\n" +"Beste %(partner_name)s,\n" +"\n" +"Ondanks meerdere aanmaningen, merken wij dat uw saldo nog steeds openstaat.\n" +"\n" +"Indien het openstaande saldo niet binnen 8 dagen op onze rekening is gestort " +", zullen wij een advocaat inschakelen. Wij sturen in dat verband geen " +"bericht meer.\n" +"\n" +"Wij gaan ervan uit dat deze actie niet nodig zal zijn. Details van de " +"openstaande documenten vindt u hierbij.\n" +"\n" +"Aarzel niet contact op te nemen met de boekhouding als u nog vragen heeft.\n" +"\n" +"Hoogachtend,\n" +" " #. module: account_followup #: field:res.partner,payment_amount_due:0 msgid "Amount Due" -msgstr "" +msgstr "Vervallen bedrag" #. module: account_followup #: field:account.move.line,followup_date:0 @@ -692,19 +855,19 @@ msgstr "Laatste aanmaning" #. module: account_followup #: view:account_followup.sending.results:0 msgid "Download Letters" -msgstr "" +msgstr "Brieven downloaden" #. module: account_followup #: field:account_followup.print,company_id:0 #: field:res.partner,unreconciled_aml_ids:0 msgid "unknown" -msgstr "" +msgstr "onbekend" #. module: account_followup #: code:addons/account_followup/account_followup.py:314 #, python-format msgid "Printed overdue payments report" -msgstr "" +msgstr "Afgedrukt aanmaningsrapport" #. module: account_followup #: help:account_followup.followup.line,manual_action:0 @@ -712,6 +875,7 @@ msgid "" "When processing, it will set the manual action to be taken for that " "customer. " msgstr "" +"Bij verwerking zal de manuele actie voor die klant worden ingesteld. " #. module: account_followup #: view:res.partner:0 @@ -721,18 +885,25 @@ msgid "" " order to exclude it from the next follow-up " "actions." msgstr "" +"Hieronder vindt u een overzicht van de transacties voor deze\n" +" klant. U kunt \"Stuur geen aanmaning\" kiezen " +"om\n" +" de factuur uit te sluiten van volgende " +"aanmaningsacties." #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:171 #, python-format msgid " email(s) should have been sent, but " -msgstr "" +msgstr " e-mail(s) zouden moeten zijn verstuurd, maar " #. module: account_followup #: help:account_followup.print,test_print:0 msgid "" "Check if you want to print follow-ups without changing follow-ups level." msgstr "" +"Schakel dit veld in als u aanmaningen wilt afdrukken zonder het niveau te " +"veranderen." #. module: account_followup #: model:ir.model,name:account_followup.model_account_move_line @@ -742,23 +913,23 @@ msgstr "Boekingen" #. module: account_followup #: report:account_followup.followup.print:0 msgid "Total:" -msgstr "" +msgstr "Totaal:" #. module: account_followup #: field:account_followup.followup.line,email_template_id:0 msgid "Email Template" -msgstr "" +msgstr "E-mailsjabloon" #. module: account_followup #: field:account_followup.print,summary:0 msgid "Summary" -msgstr "" +msgstr "Overzicht" #. module: account_followup #: view:account_followup.followup.line:0 #: field:account_followup.followup.line,send_email:0 msgid "Send an Email" -msgstr "" +msgstr "E-mail versturen" #. module: account_followup #: field:account_followup.stat,credit:0 @@ -768,7 +939,7 @@ msgstr "Krediet" #. module: account_followup #: field:res.partner,payment_amount_overdue:0 msgid "Amount Overdue" -msgstr "" +msgstr "Vervallen bedrag" #. module: account_followup #: help:res.partner,latest_followup_level_id_without_lit:0 @@ -776,12 +947,14 @@ msgid "" "The maximum follow-up level without taking into account the account move " "lines with litigation" msgstr "" +"Het maximale aanmaningsniveau, zonder rekening te houden met boekingen die " +"worden betwist." #. module: account_followup #: view:account_followup.stat:0 #: field:res.partner,latest_followup_date:0 msgid "Latest Follow-up Date" -msgstr "" +msgstr "Datum laatste aanmaning" #. module: account_followup #: model:email.template,body_html:account_followup.email_template_account_followup_default @@ -814,6 +987,33 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +" \n" +"

Beste ${object.name},

\n" +"

\n" +" Volgens onze administratie hebben wij het onderstaande bedrag nog niet " +"ontvangen. Wij verzoeken\n" +"u het verschuldigde bedrag uiterlijk binnen 8 dagen over te maken.\n" +"Indien dit schrijven uw betaling heeft gekruist, kunt u deze herinnering als " +"niet verzonden beschouwen.\n" +"Voor meer info kunt u steeds contact opnemen met onze boekhouding.\n" +"

\n" +"
\n" +"Hoogachtend,\n" +"
\n" +"
\n" +"${user.name}\n" +"
\n" +"
\n" +"\n" +"${object.get_followup_table_html() | safe}\n" +"\n" +"
\n" +"
\n" +" " #. module: account_followup #: field:account.move.line,result:0 @@ -826,17 +1026,17 @@ msgstr "Saldo" #. module: account_followup #: help:res.partner,payment_note:0 msgid "Payment Note" -msgstr "" +msgstr "Betalingsbewijs" #. module: account_followup #: view:res.partner:0 msgid "My Follow-ups" -msgstr "" +msgstr "Mijn aanmaningen" #. module: account_followup #: view:account_followup.followup.line:0 msgid "%(company_name)s" -msgstr "" +msgstr "%(company_name)s" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line1 @@ -854,28 +1054,40 @@ msgid "" "\n" "Best Regards,\n" msgstr "" +"\n" +"Beste %(partner_name)s,\n" +"\n" +"Volgens onze administratie hebben wij het onderstaande bedrag nog niet " +"ontvangen. Wij verzoeken u het verschuldigde bedrag binnen 8 dagen over te " +"maken.\n" +"\n" +"Indien dit schrijven uw betaling heeft gekruist, kunt u deze herinnering als " +"niet verzonden beschouwen.\n" +"Voor meer info kunt u steeds contact opnemen met onze boekhouding.\n" +"\n" +"Hoogachtend,\n" #. module: account_followup #: field:account_followup.stat,date_move_last:0 #: field:account_followup.stat.by.partner,date_move_last:0 msgid "Last move" -msgstr "" +msgstr "Laatste boeking" #. module: account_followup #: field:account_followup.stat,period_id:0 msgid "Period" -msgstr "" +msgstr "Periode" #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:228 #, python-format msgid "%s partners have no credits and as such the action is cleared" -msgstr "" +msgstr "%s relaties hebben geen schulden en de actie wordt gewist" #. module: account_followup #: model:ir.actions.report.xml,name:account_followup.account_followup_followup_report msgid "Follow-up Report" -msgstr "" +msgstr "Aanmaningsrapport" #. module: account_followup #: view:res.partner:0 @@ -883,48 +1095,50 @@ msgid "" ", the latest payment follow-up\n" " was:" msgstr "" +", het laatste aanmaningsniveau\n" +" was:" #. module: account_followup #: view:account_followup.print:0 msgid "Cancel" -msgstr "" +msgstr "Annuleren" #. module: account_followup #: view:account_followup.sending.results:0 msgid "Close" -msgstr "" +msgstr "Afsluiten" #. module: account_followup #: view:account_followup.stat:0 msgid "Litigation" -msgstr "" +msgstr "Betwist" #. module: account_followup #: field:account_followup.stat.by.partner,max_followup_id:0 msgid "Max Follow Up Level" -msgstr "" +msgstr "Max. aanmaningsniveau" #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:171 #, python-format msgid " had unknown email address(es)" -msgstr "" +msgstr " had een onbekend e-mailadres" #. module: account_followup #: view:res.partner:0 msgid "Responsible" -msgstr "" +msgstr "Verantwoordelijke" #. module: account_followup #: model:ir.ui.menu,name:account_followup.menu_finance_followup #: view:res.partner:0 msgid "Payment Follow-up" -msgstr "" +msgstr "Aanmaningen" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": Current Date" -msgstr "" +msgstr ": Huidige datum" #. module: account_followup #: view:account_followup.print:0 @@ -933,16 +1147,19 @@ msgid "" " set the manual actions per customer, according to " "the follow-up levels defined." msgstr "" +"Met deze actie stuurt u aanmaningsmails, kunt u brieven afdrukken en\n" +" manuele acties instellen per klant, in functie van " +"de ingestelde aanmaningsniveaus." #. module: account_followup #: field:account_followup.followup.line,name:0 msgid "Follow-Up Action" -msgstr "" +msgstr "Aanmaningsactie" #. module: account_followup #: view:account_followup.stat:0 msgid "Including journal entries marked as a litigation" -msgstr "" +msgstr "Inclusief betwiste boekingen" #. module: account_followup #: report:account_followup.followup.print:0 @@ -955,7 +1172,7 @@ msgstr "Omschrijving" #. module: account_followup #: view:account_followup.sending.results:0 msgid "Summary of actions" -msgstr "" +msgstr "Overzicht van acties" #. module: account_followup #: report:account_followup.followup.print:0 @@ -965,17 +1182,17 @@ msgstr "Ref" #. module: account_followup #: view:account_followup.followup.line:0 msgid "After" -msgstr "" +msgstr "Na" #. module: account_followup #: view:account_followup.stat:0 msgid "This Fiscal year" -msgstr "" +msgstr "Dit boekjaar" #. module: account_followup #: field:res.partner,latest_followup_level_id_without_lit:0 msgid "Latest Follow-up Level without litigation" -msgstr "" +msgstr "Laatste aanmaningsniveau met betwisting" #. module: account_followup #: model:ir.actions.act_window,help:account_followup.action_account_manual_reconcile_receivable @@ -985,16 +1202,20 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Geen boekingen gevonden.\n" +"

\n" +" " #. module: account_followup #: view:account.move.line:0 msgid "Partner entries" -msgstr "" +msgstr "Relatieboekingen" #. module: account_followup #: view:account_followup.stat:0 msgid "Follow-up lines" -msgstr "" +msgstr "Aanmaningsregels" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line3 @@ -1015,6 +1236,21 @@ msgid "" "\n" "Best Regards,\n" msgstr "" +"\n" +"Beste %(partner_name)s,\n" +"\n" +"Ondanks eerdere aanmaningen, heeft u nog steeds een openstaand saldo.\n" +"\n" +"Als uw betaling binnen de 8 dagen opnieuw uitblijft, zijn wij genoodzaakt de " +"vordering definitief uit handen te geven.\n" +"\n" +"Wij vertrouwen erop dat u het niet zover zult laten komen. Details van hety " +"openstaande saldo vindt u hierna.\n" +"\n" +"Indien u nog vragen heeft, kunt u steeds contact opnemen met onze " +"boekhouding.\n" +"\n" +"Hoogachtend,\n" #. module: account_followup #: help:account_followup.print,partner_lang:0 @@ -1022,6 +1258,8 @@ msgid "" "Do not change message text, if you want to send email in partner language, " "or configure from company" msgstr "" +"Wijzig de tekst niet als u de e-mail in de taal van de relatie wilt sturen, " +"of stel de tekst in op firma." #. module: account_followup #: view:account_followup.followup.line:0 @@ -1034,12 +1272,18 @@ msgid "" "installed\n" " using to top right icon." msgstr "" +"Schrijf hier de inleiding van uw brief,\n" +" in functie van het aanmaningsniveau. U kunt\n" +" de volgende parameters in de tekst gebruiken. " +"Vergeet\n" +" niet all geïnstalleerde talen te vertalen via " +"het pictogram in de rechterbovenhoek." #. module: account_followup #: view:account_followup.stat:0 #: model:ir.actions.act_window,name:account_followup.action_followup_stat msgid "Follow-ups Sent" -msgstr "" +msgstr "Verstuurde aanmaningen" #. module: account_followup #: field:account_followup.followup,name:0 @@ -1049,34 +1293,34 @@ msgstr "Naam:" #. module: account_followup #: field:res.partner,latest_followup_level_id:0 msgid "Latest Follow-up Level" -msgstr "" +msgstr "Laatste aanmaningsniveau" #. module: account_followup #: field:account_followup.stat,date_move:0 #: field:account_followup.stat.by.partner,date_move:0 msgid "First move" -msgstr "" +msgstr "Eerste boeking" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_stat_by_partner msgid "Follow-up Statistics by Partner" -msgstr "" +msgstr "Aanmaningsstatistieken per relatie" #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:172 #, python-format msgid " letter(s) in report" -msgstr "" +msgstr " brieven in rapport" #. module: account_followup #: view:res.partner:0 msgid "Partners with Overdue Credits" -msgstr "" +msgstr "Klanten met openstaande facturen" #. module: account_followup #: view:res.partner:0 msgid "Customer Followup" -msgstr "" +msgstr "Aanmaningen" #. module: account_followup #: model:ir.actions.act_window,help:account_followup.action_account_followup_definition_form @@ -1092,42 +1336,52 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Klik als u de aanmaningsniveaus wilt instellen met de " +"daaraan gekoppelde acties.\n" +"

\n" +" Per stap kunt u de acties opgeven en ook de dagen vervallen. " +"U kunt\n" +" brieven en e-mailsjablonen maken om specifieke berichten " +"naar de klant te sturen.\n" +"

\n" +" " #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:166 #, python-format msgid "Follow-up letter of " -msgstr "" +msgstr "Aanmaningsbrief van " #. module: account_followup #: view:res.partner:0 msgid "The" -msgstr "" +msgstr "De" #. module: account_followup #: view:account_followup.print:0 msgid "Send follow-ups" -msgstr "" +msgstr "Aanmaningen versturen" #. module: account_followup #: view:account.move.line:0 msgid "Total credit" -msgstr "" +msgstr "Totaal credit" #. module: account_followup #: field:account_followup.followup.line,sequence:0 msgid "Sequence" -msgstr "" +msgstr "Volgorde" #. module: account_followup #: view:res.partner:0 msgid "Follow-ups To Do" -msgstr "" +msgstr "Te versturen aanmaningen" #. module: account_followup #: report:account_followup.followup.print:0 msgid "Customer Ref :" -msgstr "" +msgstr "Klantenref.:" #. module: account_followup #: report:account_followup.followup.print:0 @@ -1141,26 +1395,30 @@ msgid "" "the reminder. Could be negative if you want to send a polite alert " "beforehand." msgstr "" +"Het aantal dagen dat de vervaldatum van de factuur moet zijn overschreden " +"voordat een aanmaning wordt verstuurd. Kan negatief zijn als u vooraf een " +"vriendelijk bericht wilt sturen." #. module: account_followup #: help:res.partner,latest_followup_date:0 msgid "Latest date that the follow-up level of the partner was changed" msgstr "" +"Laatste datum waarop het aanmaningsniveau van de relatie is gewijzigd." #. module: account_followup #: field:account_followup.print,test_print:0 msgid "Test Print" -msgstr "" +msgstr "Testafdruk" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": User Name" -msgstr "" +msgstr ": Gberuikersnaam" #. module: account_followup #: view:res.partner:0 msgid "Accounting" -msgstr "" +msgstr "Boekhouding" #. module: account_followup #: field:account_followup.stat,blocked:0 @@ -1170,7 +1428,7 @@ msgstr "Geblokkeerd" #. module: account_followup #: field:res.partner,payment_note:0 msgid "Customer Payment Promise" -msgstr "" +msgstr "Betalingsbelofte klant" #~ msgid "All payable entries" #~ msgstr "Alle crediteuren" 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.py b/addons/account_followup/report/account_followup_report.py index 9ca8d3c2332..8d120cb88ba 100644 --- a/addons/account_followup/report/account_followup_report.py +++ b/addons/account_followup/report/account_followup_report.py @@ -91,6 +91,5 @@ class account_followup_stat(osv.osv): GROUP BY l.id, l.partner_id, l.company_id, l.blocked, l.period_id )""") -account_followup_stat() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: 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/wizard/account_followup_print.py b/addons/account_followup/wizard/account_followup_print.py index 37b4300b03f..c14b5c071f6 100644 --- a/addons/account_followup/wizard/account_followup_print.py +++ b/addons/account_followup/wizard/account_followup_print.py @@ -72,7 +72,6 @@ class account_followup_stat_by_partner(osv.osv): GROUP BY l.partner_id, l.company_id )""") #Blocked is to take into account litigation -account_followup_stat_by_partner() class account_followup_sending_results(osv.osv_memory): @@ -106,7 +105,6 @@ class account_followup_sending_results(osv.osv_memory): 'description':_get_description, } -account_followup_sending_results() class account_followup_print(osv.osv_memory): @@ -315,6 +313,5 @@ class account_followup_print(osv.osv_memory): to_update[str(id)]= {'level': fups[followup_line_id][1], 'partner_id': stat_line_id} return {'partner_ids': partner_list, 'to_update': to_update} -account_followup_print() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/account_invoice.py b/addons/account_payment/account_invoice.py index bcce77a54ce..8fa98780c83 100644 --- a/addons/account_payment/account_invoice.py +++ b/addons/account_payment/account_invoice.py @@ -42,6 +42,5 @@ class Invoice(osv.osv): raise osv.except_osv(_('Error!'), _("You cannot cancel an invoice which has already been imported in a payment order. Remove it from the following payment order : %s."%(payment_order_name))) return super(Invoice, self).action_cancel(cr, uid, ids, context=context) -Invoice() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/account_move_line.py b/addons/account_payment/account_move_line.py index c601d9e8da3..266876db95f 100644 --- a/addons/account_payment/account_move_line.py +++ b/addons/account_payment/account_move_line.py @@ -57,6 +57,5 @@ class account_move_line(osv.osv): raise osv.except_osv(_('Error!'), _('There is no partner defined on the entry line.')) return line2bank -account_move_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/account_payment.py b/addons/account_payment/account_payment.py index 2b0fe1271d2..dc001e2e2a3 100644 --- a/addons/account_payment/account_payment.py +++ b/addons/account_payment/account_payment.py @@ -62,7 +62,6 @@ class payment_mode(osv.osv): return {'value': result} -payment_mode() class payment_order(osv.osv): _name = 'payment.order' @@ -170,7 +169,6 @@ class payment_order(osv.osv): payment_line_obj.write(cr, uid, payment_line_ids, {'date': False}, context=context) return super(payment_order, self).write(cr, uid, ids, vals, context=context) -payment_order() class payment_line(osv.osv): _name = 'payment.line' @@ -417,6 +415,5 @@ class payment_line(osv.osv): res['communication2']['states']['normal'] = [('readonly', False)] return res -payment_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/report/order.rml b/addons/account_payment/report/order.rml index ca2315d81b1..02675baf0b2 100644 --- a/addons/account_payment/report/order.rml +++ b/addons/account_payment/report/order.rml @@ -253,10 +253,10 @@ [[ get_invoice_name(line.ml_inv_ref.id) or '-' ]] - [[line.date=='False' and '-' or formatLang(line.date,date=True) ]] + [[not line.date and '-' or formatLang(line.date,date=True) ]] - [[ formatLang(line.amount or '-', currency_obj=line.company_currency) ]] + [[ formatLang(line.amount or 0.0, currency_obj=line.company_currency) ]] [[ formatLang(line.amount_currency, currency_obj=line.currency) ]] 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 4bd969726fe..03e25dfbc45 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): """ @@ -108,7 +109,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', @@ -118,6 +119,5 @@ class payment_order_create(osv.osv_memory): 'target': 'new', } -payment_order_create() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/wizard/account_payment_pay.py b/addons/account_payment/wizard/account_payment_pay.py index 03ff46125f5..5e2dc652068 100644 --- a/addons/account_payment/wizard/account_payment_pay.py +++ b/addons/account_payment/wizard/account_payment_pay.py @@ -54,6 +54,5 @@ class account_payment_make_payment(osv.osv_memory): # id = obj_model.read(cr, uid, [result], ['res_id'])[0]['res_id'] # return obj_act.read(cr, uid, [id])[0] -account_payment_make_payment() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/wizard/account_payment_populate_statement.py b/addons/account_payment/wizard/account_payment_populate_statement.py index edd47065e3a..92b1b1452f5 100644 --- a/addons/account_payment/wizard/account_payment_populate_statement.py +++ b/addons/account_payment/wizard/account_payment_populate_statement.py @@ -118,6 +118,5 @@ class account_payment_populate_statement(osv.osv_memory): line_obj.write(cr, uid, [line.id], {'bank_statement_line_id': st_line_id}) return {'type': 'ir.actions.act_window_close'} -account_payment_populate_statement() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_sequence/account_sequence.py b/addons/account_sequence/account_sequence.py index 5b344600599..3b8b2335068 100644 --- a/addons/account_sequence/account_sequence.py +++ b/addons/account_sequence/account_sequence.py @@ -40,7 +40,6 @@ class account_move(osv.osv): self.write(cr, uid, [move.id], {'internal_sequence_number': seq_no}) return res -account_move() class account_journal(osv.osv): _inherit = "account.journal" @@ -49,7 +48,6 @@ class account_journal(osv.osv): 'internal_sequence_id': fields.many2one('ir.sequence', 'Internal Sequence', help="This sequence will be used to maintain the internal number for the journal entries related to this journal."), } -account_journal() class account_move_line(osv.osv): _inherit = "account.move.line" @@ -58,6 +56,5 @@ class account_move_line(osv.osv): 'internal_sequence_number': fields.related('move_id','internal_sequence_number', type='char', relation='account.move', help='Internal Sequence Number', string='Internal Number'), } -account_move_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_sequence/account_sequence_installer.py b/addons/account_sequence/account_sequence_installer.py index e800bbad7ee..91316a61962 100644 --- a/addons/account_sequence/account_sequence_installer.py +++ b/addons/account_sequence/account_sequence_installer.py @@ -79,6 +79,5 @@ class account_sequence_installer(osv.osv_memory): ir_values_obj.set(cr, uid, key='default', key2=False, name='internal_sequence_id', models =[('account.journal', False)], value=ir_seq) return res -account_sequence_installer() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_test/account_test.py b/addons/account_test/account_test.py index da7bb8e308d..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 # ############################################################################## @@ -56,5 +56,4 @@ class accounting_assert_test(osv.osv): 'sequence': 10, } -accounting_assert_test() 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 c6f754ed18f..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" @@ -40,7 +53,6 @@ class res_company(osv.osv): domain="[('type', '=', 'other')]",), } -res_company() class account_config_settings(osv.osv_memory): _inherit = 'account.config.settings' @@ -85,7 +97,7 @@ class account_voucher(osv.osv): if context is None: context = {} if context.get('period_id', False): return context.get('period_id') - periods = self.pool.get('account.period').find(cr, uid) + periods = self.pool.get('account.period').find(cr, uid, context=context) return periods and periods[0] or False def _make_journal_search(self, cr, uid, ttype, context=None): @@ -154,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 = {} @@ -223,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') @@ -259,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' @@ -305,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'), @@ -347,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, @@ -423,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, @@ -517,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]) @@ -547,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}) @@ -562,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 @@ -622,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') @@ -647,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 @@ -716,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, @@ -767,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]) @@ -790,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]}) @@ -799,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]) @@ -824,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]) @@ -906,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 @@ -922,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 @@ -961,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 @@ -1012,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, @@ -1055,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): ''' @@ -1088,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 @@ -1136,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): @@ -1150,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. @@ -1158,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) @@ -1220,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 @@ -1346,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 @@ -1362,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 @@ -1488,7 +1574,6 @@ class account_voucher_line(osv.osv): 'type':ttype }) return values -account_voucher_line() class account_bank_statement(osv.osv): _inherit = 'account.bank.statement' @@ -1537,10 +1622,9 @@ 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) -account_bank_statement() class account_bank_statement_line(osv.osv): _inherit = 'account.bank.statement.line' @@ -1594,7 +1678,6 @@ class account_bank_statement_line(osv.osv): voucher_obj.unlink(cr, uid, unlink_ids, context=context) return super(account_bank_statement_line, self).unlink(cr, uid, ids, context=context) -account_bank_statement_line() def resolve_o2m_operations(cr, uid, target_osv, operations, fields, context): results = [] diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index f429480f656..4674d62b6a0 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -129,7 +129,7 @@ - + diff --git a/addons/account_voucher/html/account_illu_01.png b/addons/account_voucher/html/account_illu_01.png new file mode 100644 index 00000000000..2e0dbf4aac2 Binary files /dev/null and b/addons/account_voucher/html/account_illu_01.png differ diff --git a/addons/account_voucher/html/account_sc_00.png b/addons/account_voucher/html/account_sc_00.png new file mode 100644 index 00000000000..63332b46575 Binary files /dev/null and b/addons/account_voucher/html/account_sc_00.png differ diff --git a/addons/account_voucher/html/account_sc_02.png b/addons/account_voucher/html/account_sc_02.png new file mode 100644 index 00000000000..709e444ba0d Binary files /dev/null and b/addons/account_voucher/html/account_sc_02.png differ diff --git a/addons/account_voucher/html/account_sc_03.png b/addons/account_voucher/html/account_sc_03.png new file mode 100644 index 00000000000..a3e3afc34c0 Binary files /dev/null and b/addons/account_voucher/html/account_sc_03.png differ diff --git a/addons/account_voucher/html/account_sc_04.png b/addons/account_voucher/html/account_sc_04.png new file mode 100644 index 00000000000..458c8280c26 Binary files /dev/null and b/addons/account_voucher/html/account_sc_04.png differ diff --git a/addons/account_voucher/html/account_sc_06.png b/addons/account_voucher/html/account_sc_06.png new file mode 100644 index 00000000000..9605506c6a5 Binary files /dev/null and b/addons/account_voucher/html/account_sc_06.png differ diff --git a/addons/account_voucher/html/bazile.png b/addons/account_voucher/html/bazile.png new file mode 100644 index 00000000000..30f37e70b4a Binary files /dev/null and b/addons/account_voucher/html/bazile.png differ diff --git a/addons/account_voucher/html/index.html b/addons/account_voucher/html/index.html new file mode 100644 index 00000000000..d59c110dde5 --- /dev/null +++ b/addons/account_voucher/html/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/html/testimonial_sunil.jpg b/addons/account_voucher/html/testimonial_sunil.jpg new file mode 100644 index 00000000000..f2ad6929a2b Binary files /dev/null and b/addons/account_voucher/html/testimonial_sunil.jpg differ diff --git a/addons/account_voucher/i18n/nl_BE.po b/addons/account_voucher/i18n/nl_BE.po index 0cdc8cd8399..a58e655aec6 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-04-26 16:01+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-04-27 05:44+0000\n" +"X-Generator: Launchpad (build 16580)\n" "Language: nl\n" #. module: account_voucher @@ -138,6 +138,8 @@ 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 @@ -431,7 +433,7 @@ msgstr "Debet" #: code:addons/account_voucher/account_voucher.py:1547 #, python-format msgid "Unable to change journal !" -msgstr "" +msgstr "Het dagboek kan niet worden gewijzigd" #. module: account_voucher #: view:sale.receipt.report:0 @@ -745,7 +747,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 @@ -786,7 +788,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 +836,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 @@ -845,7 +847,7 @@ msgstr "Vorige betalingen?" #: code:addons/account_voucher/account_voucher.py:1112 #, 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 @@ -884,7 +886,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 +940,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 @@ -1279,7 +1281,7 @@ 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 diff --git a/addons/account_voucher/i18n/ru.po b/addons/account_voucher/i18n/ru.po index 63cad344ed0..ef38a07e478 100644 --- a/addons/account_voucher/i18n/ru.po +++ b/addons/account_voucher/i18n/ru.po @@ -7,24 +7,24 @@ 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-05-29 13:17+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-05-30 05:45+0000\n" +"X-Generator: Launchpad (build 16652)\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 @@ -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 @@ -135,6 +135,8 @@ 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 @@ -225,7 +227,7 @@ msgstr "Элемент журнала" #: code:addons/account_voucher/account_voucher.py:981 #, 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 @@ -254,6 +256,8 @@ msgstr "Отменено" 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 @@ -294,12 +298,12 @@ msgstr "Налог" #: code:addons/account_voucher/account_voucher.py:879 #, 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 @@ -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 @@ -406,7 +412,7 @@ msgstr "Дебет" #: code:addons/account_voucher/account_voucher.py:1547 #, 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 @@ -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 @@ -568,7 +574,7 @@ msgstr "Для проверки" #: code:addons/account_voucher/account_voucher.py:1194 #, python-format msgid "change" -msgstr "" +msgstr "изменить" #. module: account_voucher #: code:addons/account_voucher/account_voucher.py:1014 @@ -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 @@ -647,7 +653,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 +671,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 #, python-format msgid "Configuration Error !" -msgstr "" +msgstr "Ошибка конфигурации !" #. module: account_voucher #: view:account.voucher:0 @@ -695,18 +701,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 +722,7 @@ msgstr "Август" #. module: account_voucher #: view:account.voucher:0 msgid "Validate Payment" -msgstr "" +msgstr "Утвердить оплату" #. module: account_voucher #: help:account.voucher,audit:0 @@ -724,6 +730,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 @@ -734,7 +742,7 @@ msgstr "Октябрь" #: code:addons/account_voucher/account_voucher.py:976 #, python-format msgid "Please activate the sequence of selected journal !" -msgstr "" +msgstr "Пожалуйста, включите нумерацию выбранного журнала!" #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -749,7 +757,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 +768,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 +795,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 @@ -814,7 +822,7 @@ msgstr "Предыдущие платежи ?" #: code:addons/account_voucher/account_voucher.py:1112 #, 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 +838,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 #, 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 +873,7 @@ msgstr "" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Group by Invoice Date" -msgstr "" +msgstr "Группировать по дате счета" #. module: account_voucher #: view:account.voucher:0 diff --git a/addons/account_voucher/invoice.py b/addons/account_voucher/invoice.py index c0584ddbd52..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, @@ -52,6 +53,5 @@ class invoice(osv.osv): } } -invoice() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/report/account_voucher_sales_receipt.py b/addons/account_voucher/report/account_voucher_sales_receipt.py index 2ab76c252f5..246cd8b47e8 100644 --- a/addons/account_voucher/report/account_voucher_sales_receipt.py +++ b/addons/account_voucher/report/account_voucher_sales_receipt.py @@ -126,6 +126,5 @@ class sale_receipt_report(osv.osv): ) """) -sale_receipt_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: 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/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 de873c9195c..dea94d59f4e 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -11,7 +11,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -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 05b783dd339..dc732129803 100644 --- a/addons/account_voucher/voucher_sales_purchase_view.xml +++ b/addons/account_voucher/voucher_sales_purchase_view.xml @@ -10,7 +10,7 @@ - + @@ -32,7 +32,7 @@ - + @@ -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/account_voucher/wizard/account_statement_from_invoice.py b/addons/account_voucher/wizard/account_statement_from_invoice.py index fce251df175..de5121a819b 100644 --- a/addons/account_voucher/wizard/account_statement_from_invoice.py +++ b/addons/account_voucher/wizard/account_statement_from_invoice.py @@ -123,6 +123,5 @@ class account_statement_from_invoice_lines(osv.osv_memory): }, context=context) return {'type': 'ir.actions.act_window_close'} -account_statement_from_invoice_lines() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index 42651acb0c6..ce79c4d5ffb 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -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, )) @@ -171,9 +171,9 @@ class account_analytic_account(osv.osv): return result _columns = { - 'name': fields.char('Account/Contract Name', size=128, required=True), + 'name': fields.char('Account/Contract Name', size=128, required=True, track_visibility='onchange'), 'complete_name': fields.function(_get_full_name, type='char', string='Full Name'), - 'code': fields.char('Reference', select=True), + 'code': fields.char('Reference', select=True, track_visibility='onchange'), 'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Contract')], 'Type of Account', required=True, help="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"\ @@ -191,10 +191,10 @@ class account_analytic_account(osv.osv): 'quantity': fields.function(_debit_credit_bal_qtty, type='float', string='Quantity', multi='debit_credit_bal_qtty'), 'quantity_max': fields.float('Prepaid Service Units', help='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.)'), 'partner_id': fields.many2one('res.partner', 'Customer'), - 'user_id': fields.many2one('res.users', 'Project Manager'), - 'manager_id': fields.many2one('res.users', 'Account Manager'), + 'user_id': fields.many2one('res.users', 'Project Manager', track_visibility='onchange'), + 'manager_id': fields.many2one('res.users', 'Account Manager', track_visibility='onchange'), 'date_start': fields.date('Start Date'), - 'date': fields.date('End Date', select=True), + 'date': fields.date('End Date', select=True, track_visibility='onchange'), 'company_id': fields.many2one('res.company', 'Company', required=False), #not required because we want to allow different companies to use the same chart of account, except for leaf accounts. 'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'),('pending','To Renew'),('close','Closed'),('cancelled', 'Cancelled')], 'Status', required=True, track_visibility='onchange'), 'currency_id': fields.function(_currency, fnct_inv=_set_company_currency, #the currency_id field is readonly except if it's a view account and if there is no company 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_contract_hr_expense/analytic_contract_hr_expense.py b/addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py index 8b10381434d..a1bf43714ce 100644 --- a/addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py +++ b/addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py @@ -152,6 +152,5 @@ class account_analytic_account(osv.osv): 'nodestroy': True, } -account_analytic_account() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/analytic_contract_hr_expense/i18n/nl_BE.po b/addons/analytic_contract_hr_expense/i18n/nl_BE.po new file mode 100644 index 00000000000..4bc0cc559e5 --- /dev/null +++ b/addons/analytic_contract_hr_expense/i18n/nl_BE.po @@ -0,0 +1,72 @@ +# Dutch (Belgium) 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-15 16:33+0000\n" +"Last-Translator: Els Van Vossel (Agaplan) \n" +"Language-Team: Dutch (Belgium) \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-16 04:37+0000\n" +"X-Generator: Launchpad (build 16564)\n" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "or view" +msgstr "of bekijk" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "Nothing to invoice, create" +msgstr "Niets te factureren, aanmaken" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "expenses" +msgstr "onkosten" + +#. module: analytic_contract_hr_expense +#: model:ir.model,name:analytic_contract_hr_expense.model_account_analytic_account +msgid "Analytic Account" +msgstr "Analytische rekening" + +#. module: analytic_contract_hr_expense +#: code:addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py:129 +#, python-format +msgid "Expenses to Invoice of %s" +msgstr "Te factureren onkosten van %s" + +#. module: analytic_contract_hr_expense +#: code:addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py:121 +#, python-format +msgid "Expenses of %s" +msgstr "Onkosten van %s" + +#. module: analytic_contract_hr_expense +#: field:account.analytic.account,expense_invoiced:0 +#: field:account.analytic.account,expense_to_invoice:0 +#: field:account.analytic.account,remaining_expense:0 +msgid "unknown" +msgstr "onbekend" + +#. module: analytic_contract_hr_expense +#: field:account.analytic.account,est_expenses:0 +msgid "Estimation of Expenses to Invoice" +msgstr "Te verwachten te factureren onkosten" + +#. module: analytic_contract_hr_expense +#: field:account.analytic.account,charge_expenses:0 +msgid "Charge Expenses" +msgstr "Onkosten doorrekenen" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "⇒ Invoice" +msgstr "⇒ Factuur" 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 de46e2e8d03..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) @@ -411,7 +411,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory): model_name = field.model_id.model field_name = field.field_id.name field_type = field.field_id.ttype - table_name = self.pool.get(model_name)._table + table_name = self.pool[model_name]._table # get the current value sql = "select id, %s from %s" % (field_name, table_name) @@ -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,7 +543,8 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory): fixes = group(fixes, ('model_name', 'field_name')) for line in data: - table_name = self.pool.get(line['model_id'])._table if self.pool.get(line['model_id']) else None + queries = [] + table_name = self.pool[line['model_id']]._table if line['model_id'] in self.pool else None # check if custom sql exists: key = (line['model_id'], line['field_id']) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 811c5387697..159baf3a9e7 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -70,8 +70,7 @@ class audittrail_rule(osv.osv): obj_model = self.pool.get('ir.model.data') #start Loop for thisrule in self.browse(cr, uid, ids): - obj = self.pool.get(thisrule.object_id.model) - if not obj: + if thisrule.object_id.model not in self.pool: raise osv.except_osv( _('WARNING: audittrail is not part of the pool'), _('Change audittrail depends -- Setting rule as DRAFT')) @@ -131,7 +130,7 @@ class audittrail_log(osv.osv): model_object = resname.object_id res_id = resname.res_id if model_object and res_id: - model_pool = self.pool.get(model_object.model) + model_pool = self.pool[model_object.model] res = model_pool.read(cr, uid, res_id, ['name']) data[resname.id] = res['name'] else: @@ -190,7 +189,7 @@ def get_value_text(cr, uid, pool, resource_pool, method, field, value): field_obj = (resource_pool._all_columns.get(field)).column if field_obj._type in ('one2many','many2many'): - data = pool.get(field_obj._obj).name_get(cr, uid, value) + data = pool[field_obj._obj].name_get(cr, uid, value) #return the modifications on x2many fields as a list of names res = map(lambda x:x[1], data) elif field_obj._type == 'many2one': @@ -212,7 +211,7 @@ def create_log_line(cr, uid, log_id, model, lines=None): if lines is None: lines = [] pool = openerp.registry(cr.dbname) - obj_pool = pool.get(model.model) + obj_pool = pool[model.model] model_pool = pool.get('ir.model') field_pool = pool.get('ir.model.fields') log_line_pool = pool.get('audittrail.log.line') @@ -251,7 +250,7 @@ def log_fct(cr, uid_orig, model, method, fct_src, *args, **kw): @return: Returns result as per method of Object proxy """ pool = openerp.registry(cr.dbname) - resource_pool = pool.get(model) + resource_pool = pool[model] model_pool = pool.get('ir.model') model_ids = model_pool.search(cr, SUPERUSER_ID, [('model', '=', model)]) model_id = model_ids and model_ids[0] or False @@ -321,7 +320,7 @@ def get_data(cr, uid, pool, res_ids, model, method): } """ data = {} - resource_pool = pool.get(model.model) + resource_pool = pool[model.model] # read all the fields of the given resources in super admin mode for resource in resource_pool.read(cr, SUPERUSER_ID, res_ids): values = {} @@ -390,7 +389,7 @@ def prepare_audittrail_log_line(cr, uid, pool, model, resource_id, method, old_v key: [] } # loop on all the fields - for field_name, field_definition in pool.get(model.model)._all_columns.items(): + for field_name, field_definition in pool[model.model]._all_columns.items(): if field_name in ('__last_update', 'id'): continue #if the field_list param is given, skip all the fields not in that list @@ -457,7 +456,7 @@ def process_data(cr, uid, pool, res_ids, model, method, old_values=None, new_val # if at least one modification has been found for model_id, resource_id in lines: - name = pool.get(model.model).name_get(cr, uid, [resource_id])[0][1] + name = pool[model.model].name_get(cr, uid, [resource_id])[0][1] vals = { 'method': method, 'object_id': model_id, diff --git a/addons/audittrail/wizard/audittrail_view_log.py b/addons/audittrail/wizard/audittrail_view_log.py index d06da281933..4385970f8d9 100644 --- a/addons/audittrail/wizard/audittrail_view_log.py +++ b/addons/audittrail/wizard/audittrail_view_log.py @@ -61,6 +61,5 @@ class audittrail_view_log(osv.osv_memory): #End Loop return result -audittrail_view_log() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_crypt/i18n/lt.po b/addons/auth_crypt/i18n/lt.po new file mode 100644 index 00000000000..03f0bd5249f --- /dev/null +++ b/addons/auth_crypt/i18n/lt.po @@ -0,0 +1,28 @@ +# 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-24 18:24+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-25 05:20+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: auth_crypt +#: field:res.users,password_crypt:0 +msgid "Encrypted Password" +msgstr "Užšifruotas slaptažodis" + +#. module: auth_crypt +#: model:ir.model,name:auth_crypt.model_res_users +msgid "Users" +msgstr "Naudotojai" diff --git a/addons/auth_crypt/i18n/nl_BE.po b/addons/auth_crypt/i18n/nl_BE.po index b9477ece5dc..abb65c8700f 100644 --- a/addons/auth_crypt/i18n/nl_BE.po +++ b/addons/auth_crypt/i18n/nl_BE.po @@ -1,42 +1,28 @@ # Dutch (Belgium) translation for openobject-addons -# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 # This file is distributed under the same license as the openobject-addons package. -# FIRST AUTHOR , 2012. +# FIRST AUTHOR , 2013. # msgid "" msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2012-12-03 16:03+0000\n" -"PO-Revision-Date: 2012-07-26 17:52+0000\n" -"Last-Translator: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-04-15 16:02+0000\n" +"Last-Translator: Els Van Vossel (Agaplan) \n" "Language-Team: Dutch (Belgium) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-12-04 05:53+0000\n" -"X-Generator: Launchpad (build 16335)\n" +"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n" +"X-Generator: Launchpad (build 16564)\n" -#. module: base_crypt -#: model:ir.model,name:base_crypt.model_res_users +#. module: auth_crypt +#: field:res.users,password_crypt:0 +msgid "Encrypted Password" +msgstr "Geëncrypteerd wachtwoord" + +#. module: auth_crypt +#: model:ir.model,name:auth_crypt.model_res_users msgid "Users" -msgstr "" - -#~ msgid "You can not have two users with the same login !" -#~ msgstr "U kunt geen twee gebruikers met dezelfde login maken." - -#, python-format -#~ msgid "Please specify the password !" -#~ msgstr "Gelieve een wachtwoord op te geven" - -#~ msgid "The chosen company is not in the allowed companies for this user" -#~ msgstr "" -#~ "De gekozen firma behoort niet tot de toegelaten bedrijven voor deze " -#~ "gebruiker." - -#~ msgid "res.users" -#~ msgstr "res.users" - -#, python-format -#~ msgid "Error" -#~ msgstr "Fout" +msgstr "Gebruikers" diff --git a/addons/auth_ldap/users_ldap.py b/addons/auth_ldap/users_ldap.py index e8778449da5..8e7128ca91e 100644 --- a/addons/auth_ldap/users_ldap.py +++ b/addons/auth_ldap/users_ldap.py @@ -227,7 +227,6 @@ class CompanyLDAP(osv.osv): 'create_user': True, } -CompanyLDAP() class res_company(osv.osv): @@ -236,7 +235,6 @@ class res_company(osv.osv): 'ldaps': fields.one2many( 'res.company.ldap', 'company', 'LDAP Parameters'), } -res_company() class users(osv.osv): @@ -282,5 +280,4 @@ class users(osv.osv): cr.close() raise openerp.exceptions.AccessDenied() -users() # vim:expandtab:smartindent: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/lt.po b/addons/auth_oauth_signup/i18n/lt.po new file mode 100644 index 00000000000..27fb83e6a4f --- /dev/null +++ b/addons/auth_oauth_signup/i18n/lt.po @@ -0,0 +1,23 @@ +# 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-24 18:21+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-25 05:20+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: auth_oauth_signup +#: model:ir.model,name:auth_oauth_signup.model_res_users +msgid "Users" +msgstr "Naudotojai" diff --git a/addons/auth_oauth_signup/i18n/nl_BE.po b/addons/auth_oauth_signup/i18n/nl_BE.po new file mode 100644 index 00000000000..04d5034d029 --- /dev/null +++ b/addons/auth_oauth_signup/i18n/nl_BE.po @@ -0,0 +1,23 @@ +# Dutch (Belgium) 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-15 16:01+0000\n" +"Last-Translator: Els Van Vossel (Agaplan) \n" +"Language-Team: Dutch (Belgium) \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-16 04:37+0000\n" +"X-Generator: Launchpad (build 16564)\n" + +#. module: auth_oauth_signup +#: model:ir.model,name:auth_oauth_signup.model_res_users +msgid "Users" +msgstr "Gebruikers" 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/res_users.py b/addons/auth_openid/res_users.py index feea2d8d396..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 @@ -91,7 +90,6 @@ class res_users(osv.osv): raise self._uid_cache.setdefault(db, {})[uid] = passwd -res_users() 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/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/zh_CN.po b/addons/auth_signup/i18n/zh_CN.po index 333dd1be2dc..aa8d9f952c1 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: 2012-12-04 20:16+0000\n" -"Last-Translator: 盈通 ccdos \n" +"PO-Revision-Date: 2013-04-16 04:33+0000\n" +"Last-Translator: Key \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-03-16 05:52+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-17 05:15+0000\n" +"X-Generator: Launchpad (build 16567)\n" #. module: auth_signup #: field:res.partner,signup_type:0 @@ -73,7 +73,7 @@ msgstr "重置密码" #: code:addons/auth_signup/static/src/js/auth_signup.js:117 #, python-format msgid "Please enter a password and confirm it." -msgstr "" +msgstr "请输入密码并确认。" #. module: auth_signup #: view:res.users:0 diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index b5383e41775..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) @@ -200,6 +207,9 @@ class res_users(osv.Model): 'partner_id': partner.id, 'email': values.get('email') or values.get('login'), }) + if partner.company_id: + values['company_id'] = 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 @@ -256,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 @@
@@ -229,7 +231,7 @@ - + @@ -327,22 +329,22 @@ - + - + - + + help="Leads that are assigned to any sales teams I am member of" groups="base.group_multi_salesteams"/> - + @@ -361,7 +363,7 @@ - + @@ -428,9 +430,9 @@
- - - - + - - +
diff --git a/addons/crm/res_partner.py b/addons/crm/res_partner.py index 2fdccda2e06..f25b1303c02 100644 --- a/addons/crm/res_partner.py +++ b/addons/crm/res_partner.py @@ -92,7 +92,6 @@ class res_partner(osv.osv): }, context=context) opportunity_ids[partner_id] = opportunity_id return opportunity_ids -res_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 00a071fa954..dd6c50dbaba 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -10,7 +10,7 @@ - + @@ -30,8 +30,11 @@ crm.lead kanban,tree,form,graph,calendar [('type','=','opportunity')] - {'search_default_partner_id': active_id, - 'stage_type': 'opportunity', 'default_type': 'opportunity'} + { + 'search_default_partner_id': active_id, + 'stage_type': 'opportunity', + 'default_type': 'opportunity' + } diff --git a/addons/crm/security/crm_security.xml b/addons/crm/security/crm_security.xml index 2c34252209c..34137dc0fac 100644 --- a/addons/crm/security/crm_security.xml +++ b/addons/crm/security/crm_security.xml @@ -22,6 +22,19 @@ + + + Do Not Use Sales Teams + + + + + + + + Manage Sales Teams + + Manage Fund Raising diff --git a/addons/crm/security/ir.model.access.csv b/addons/crm/security/ir.model.access.csv index 52648c8e347..cadb8c24550 100644 --- a/addons/crm/security/ir.model.access.csv +++ b/addons/crm/security/ir.model.access.csv @@ -12,7 +12,7 @@ access_crm_phonecall_manager,crm.phonecall.manager,model_crm_phonecall,base.grou access_crm_case_categ,crm.case.categ,model_crm_case_categ,base.group_user,1,0,0,0 access_crm_lead,crm.lead,model_crm_lead,base.group_sale_salesman,1,1,1,0 access_crm_phonecall,crm.phonecall,model_crm_phonecall,base.group_sale_salesman,1,1,1,0 -access_crm_case_section_user,crm.case.section.user,model_crm_case_section,base.group_sale_salesman,1,1,1,0 +access_crm_case_section_user,crm.case.section.user,model_crm_case_section,base.group_sale_salesman,1,0,0,0 access_crm_case_section_manager,crm.case.section.manager,model_crm_case_section,base.group_sale_manager,1,1,1,1 access_crm_case_stage,crm.case.stage,model_crm_case_stage,,1,0,0,0 access_crm_case_stage_manager,crm.case.stage,model_crm_case_stage,base.group_sale_manager,1,1,1,1 @@ -35,3 +35,5 @@ access_crm_lead_partner_manager,crm.lead.partner.manager,model_crm_lead,base.gro access_crm_phonecall_partner_manager,crm.phonecall.partner.manager,model_crm_phonecall,base.group_partner_manager,1,1,1,1 access_crm_payment_mode_user,crm.payment.mode,model_crm_payment_mode,base.group_sale_salesman,1,0,0,0 access_crm_payment_mode,crm.payment.mode,model_crm_payment_mode,base.group_sale_manager,1,1,1,1 +access_base_partner_merge_line_manager,base_partner_merge_line.manager,model_base_partner_merge_line,base.group_system,1,1,1,1 +access_base_partner_merge_manager,base_partner_merge.manager,model_base_partner_merge_automatic_wizard,base.group_system,1,1,1,1 diff --git a/addons/crm/static/lib/sparkline/jquery.sparkline.js b/addons/crm/static/lib/sparkline/jquery.sparkline.js new file mode 100644 index 00000000000..c003923e03b --- /dev/null +++ b/addons/crm/static/lib/sparkline/jquery.sparkline.js @@ -0,0 +1,3047 @@ +/** +* +* jquery.sparkline.js +* +* v2.1.1 +* (c) Splunk, Inc +* Contact: Gareth Watts (gareth@splunk.com) +* http://omnipotent.net/jquery.sparkline/ +* +* Generates inline sparkline charts from data supplied either to the method +* or inline in HTML +* +* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas tag +* (Firefox 2.0+, Safari, Opera, etc) +* +* License: New BSD License +* +* Copyright (c) 2012, Splunk Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* * Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* * Neither the name of Splunk Inc nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +* Usage: +* $(selector).sparkline(values, options) +* +* If values is undefined or set to 'html' then the data values are read from the specified tag: +*

Sparkline: 1,4,6,6,8,5,3,5

+* $('.sparkline').sparkline(); +* There must be no spaces in the enclosed data set +* +* Otherwise values must be an array of numbers or null values +*

Sparkline: This text replaced if the browser is compatible

+* $('#sparkline1').sparkline([1,4,6,6,8,5,3,5]) +* $('#sparkline2').sparkline([1,4,6,null,null,5,3,5]) +* +* Values can also be specified in an HTML comment, or as a values attribute: +*

Sparkline:

+*

Sparkline:

+* $('.sparkline').sparkline(); +* +* For line charts, x values can also be specified: +*

Sparkline: 1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5

+* $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ]) +* +* By default, options should be passed in as teh second argument to the sparkline function: +* $('.sparkline').sparkline([1,2,3,4], {type: 'bar'}) +* +* Options can also be set by passing them on the tag itself. This feature is disabled by default though +* as there's a slight performance overhead: +* $('.sparkline').sparkline([1,2,3,4], {enableTagOptions: true}) +*

Sparkline: loading

+* Prefix all options supplied as tag attribute with "spark" (configurable by setting tagOptionPrefix) +* +* Supported options: +* lineColor - Color of the line used for the chart +* fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart +* width - Width of the chart - Defaults to 3 times the number of values in pixels +* height - Height of the chart - Defaults to the height of the containing element +* chartRangeMin - Specify the minimum value to use for the Y range of the chart - Defaults to the minimum value supplied +* chartRangeMax - Specify the maximum value to use for the Y range of the chart - Defaults to the maximum value supplied +* chartRangeClip - Clip out of range values to the max/min specified by chartRangeMin and chartRangeMax +* chartRangeMinX - Specify the minimum value to use for the X range of the chart - Defaults to the minimum value supplied +* chartRangeMaxX - Specify the maximum value to use for the X range of the chart - Defaults to the maximum value supplied +* composite - If true then don't erase any existing chart attached to the tag, but draw +* another chart over the top - Note that width and height are ignored if an +* existing chart is detected. +* tagValuesAttribute - Name of tag attribute to check for data values - Defaults to 'values' +* enableTagOptions - Whether to check tags for sparkline options +* tagOptionPrefix - Prefix used for options supplied as tag attributes - Defaults to 'spark' +* disableHiddenCheck - If set to true, then the plugin will assume that charts will never be drawn into a +* hidden dom element, avoding a browser reflow +* disableInteraction - If set to true then all mouseover/click interaction behaviour will be disabled, +* making the plugin perform much like it did in 1.x +* disableTooltips - If set to true then tooltips will be disabled - Defaults to false (tooltips enabled) +* disableHighlight - If set to true then highlighting of selected chart elements on mouseover will be disabled +* defaults to false (highlights enabled) +* highlightLighten - Factor to lighten/darken highlighted chart values by - Defaults to 1.4 for a 40% increase +* tooltipContainer - Specify which DOM element the tooltip should be rendered into - defaults to document.body +* tooltipClassname - Optional CSS classname to apply to tooltips - If not specified then a default style will be applied +* tooltipOffsetX - How many pixels away from the mouse pointer to render the tooltip on the X axis +* tooltipOffsetY - How many pixels away from the mouse pointer to render the tooltip on the r axis +* tooltipFormatter - Optional callback that allows you to override the HTML displayed in the tooltip +* callback is given arguments of (sparkline, options, fields) +* tooltipChartTitle - If specified then the tooltip uses the string specified by this setting as a title +* tooltipFormat - A format string or SPFormat object (or an array thereof for multiple entries) +* to control the format of the tooltip +* tooltipPrefix - A string to prepend to each field displayed in a tooltip +* tooltipSuffix - A string to append to each field displayed in a tooltip +* tooltipSkipNull - If true then null values will not have a tooltip displayed (defaults to true) +* tooltipValueLookups - An object or range map to map field values to tooltip strings +* (eg. to map -1 to "Lost", 0 to "Draw", and 1 to "Win") +* numberFormatter - Optional callback for formatting numbers in tooltips +* numberDigitGroupSep - Character to use for group separator in numbers "1,234" - Defaults to "," +* numberDecimalMark - Character to use for the decimal point when formatting numbers - Defaults to "." +* numberDigitGroupCount - Number of digits between group separator - Defaults to 3 +* +* There are 7 types of sparkline, selected by supplying a "type" option of 'line' (default), +* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box' +* line - Line chart. Options: +* spotColor - Set to '' to not end each line in a circular spot +* minSpotColor - If set, color of spot at minimum value +* maxSpotColor - If set, color of spot at maximum value +* spotRadius - Radius in pixels +* lineWidth - Width of line in pixels +* normalRangeMin +* normalRangeMax - If set draws a filled horizontal bar between these two values marking the "normal" +* or expected range of values +* normalRangeColor - Color to use for the above bar +* drawNormalOnTop - Draw the normal range above the chart fill color if true +* defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart +* highlightSpotColor - The color to use for drawing a highlight spot on mouseover - Set to null to disable +* highlightLineColor - The color to use for drawing a highlight line on mouseover - Set to null to disable +* valueSpots - Specify which points to draw spots on, and in which color. Accepts a range map +* +* bar - Bar chart. Options: +* barColor - Color of bars for postive values +* negBarColor - Color of bars for negative values +* zeroColor - Color of bars with zero values +* nullColor - Color of bars with null values - Defaults to omitting the bar entirely +* barWidth - Width of bars in pixels +* colorMap - Optional mappnig of values to colors to override the *BarColor values above +* can be an Array of values to control the color of individual bars or a range map +* to specify colors for individual ranges of values +* barSpacing - Gap between bars in pixels +* zeroAxis - Centers the y-axis around zero if true +* +* tristate - Charts values of win (>0), lose (<0) or draw (=0) +* posBarColor - Color of win values +* negBarColor - Color of lose values +* zeroBarColor - Color of draw values +* barWidth - Width of bars in pixels +* barSpacing - Gap between bars in pixels +* colorMap - Optional mappnig of values to colors to override the *BarColor values above +* can be an Array of values to control the color of individual bars or a range map +* to specify colors for individual ranges of values +* +* discrete - Options: +* lineHeight - Height of each line in pixels - Defaults to 30% of the graph height +* thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor +* thresholdColor +* +* bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ... +* options: +* targetColor - The color of the vertical target marker +* targetWidth - The width of the target marker in pixels +* performanceColor - The color of the performance measure horizontal bar +* rangeColors - Colors to use for each qualitative range background color +* +* pie - Pie chart. Options: +* sliceColors - An array of colors to use for pie slices +* offset - Angle in degrees to offset the first slice - Try -90 or +90 +* borderWidth - Width of border to draw around the pie chart, in pixels - Defaults to 0 (no border) +* borderColor - Color to use for the pie chart border - Defaults to #000 +* +* box - Box plot. Options: +* raw - Set to true to supply pre-computed plot points as values +* values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier +* When set to false you can supply any number of values and the box plot will +* be computed for you. Default is false. +* showOutliers - Set to true (default) to display outliers as circles +* outlierIQR - Interquartile range used to determine outliers. Default 1.5 +* boxLineColor - Outline color of the box +* boxFillColor - Fill color for the box +* whiskerColor - Line color used for whiskers +* outlierLineColor - Outline color of outlier circles +* outlierFillColor - Fill color of the outlier circles +* spotRadius - Radius of outlier circles +* medianColor - Line color of the median line +* target - Draw a target cross hair at the supplied value (default undefined) +* +* +* +* Examples: +* $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false }); +* $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 }); +* $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }): +* $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' }); +* $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' }); +* $('#pie').sparkline([1,1,2], { type:'pie' }); +*/ + +/*jslint regexp: true, browser: true, jquery: true, white: true, nomen: false, plusplus: false, maxerr: 500, indent: 4 */ + +(function(factory) { + if(typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } + else { + factory(jQuery); + } +} +(function($) { + 'use strict'; + + var UNSET_OPTION = {}, + getDefaults, createClass, SPFormat, clipval, quartile, normalizeValue, normalizeValues, + remove, isNumber, all, sum, addCSS, ensureArray, formatNumber, RangeMap, + MouseHandler, Tooltip, barHighlightMixin, + line, bar, tristate, discrete, bullet, pie, box, defaultStyles, initStyles, + VShape, VCanvas_base, VCanvas_canvas, VCanvas_vml, pending, shapeCount = 0; + + /** + * Default configuration settings + */ + getDefaults = function () { + return { + // Settings common to most/all chart types + common: { + type: 'line', + lineColor: '#00f', + fillColor: '#cdf', + defaultPixelsPerValue: 3, + width: 'auto', + height: 'auto', + composite: false, + tagValuesAttribute: 'values', + tagOptionsPrefix: 'spark', + enableTagOptions: false, + enableHighlight: true, + highlightLighten: 1.4, + tooltipSkipNull: true, + tooltipPrefix: '', + tooltipSuffix: '', + disableHiddenCheck: false, + numberFormatter: false, + numberDigitGroupCount: 3, + numberDigitGroupSep: ',', + numberDecimalMark: '.', + disableTooltips: false, + disableInteraction: false + }, + // Defaults for line charts + line: { + spotColor: '#f80', + highlightSpotColor: '#5f5', + highlightLineColor: '#f22', + spotRadius: 1.5, + minSpotColor: '#f80', + maxSpotColor: '#f80', + lineWidth: 1, + normalRangeMin: undefined, + normalRangeMax: undefined, + normalRangeColor: '#ccc', + drawNormalOnTop: false, + chartRangeMin: undefined, + chartRangeMax: undefined, + chartRangeMinX: undefined, + chartRangeMaxX: undefined, + tooltipFormat: new SPFormat('● {{prefix}}{{y}}{{suffix}}') + }, + // Defaults for bar charts + bar: { + barColor: '#3366cc', + negBarColor: '#f44', + stackedBarColor: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#66aa00', + '#dd4477', '#0099c6', '#990099'], + zeroColor: undefined, + nullColor: undefined, + zeroAxis: true, + barWidth: 4, + barSpacing: 1, + chartRangeMax: undefined, + chartRangeMin: undefined, + chartRangeClip: false, + colorMap: undefined, + tooltipFormat: new SPFormat('● {{prefix}}{{value}}{{suffix}}') + }, + // Defaults for tristate charts + tristate: { + barWidth: 4, + barSpacing: 1, + posBarColor: '#6f6', + negBarColor: '#f44', + zeroBarColor: '#999', + colorMap: {}, + tooltipFormat: new SPFormat('● {{value:map}}'), + tooltipValueLookups: { map: { '-1': 'Loss', '0': 'Draw', '1': 'Win' } } + }, + // Defaults for discrete charts + discrete: { + lineHeight: 'auto', + thresholdColor: undefined, + thresholdValue: 0, + chartRangeMax: undefined, + chartRangeMin: undefined, + chartRangeClip: false, + tooltipFormat: new SPFormat('{{prefix}}{{value}}{{suffix}}') + }, + // Defaults for bullet charts + bullet: { + targetColor: '#f33', + targetWidth: 3, // width of the target bar in pixels + performanceColor: '#33f', + rangeColors: ['#d3dafe', '#a8b6ff', '#7f94ff'], + base: undefined, // set this to a number to change the base start number + tooltipFormat: new SPFormat('{{fieldkey:fields}} - {{value}}'), + tooltipValueLookups: { fields: {r: 'Range', p: 'Performance', t: 'Target'} } + }, + // Defaults for pie charts + pie: { + offset: 0, + sliceColors: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#66aa00', + '#dd4477', '#0099c6', '#990099'], + borderWidth: 0, + borderColor: '#000', + tooltipFormat: new SPFormat('● {{value}} ({{percent.1}}%)') + }, + // Defaults for box plots + box: { + raw: false, + boxLineColor: '#000', + boxFillColor: '#cdf', + whiskerColor: '#000', + outlierLineColor: '#333', + outlierFillColor: '#fff', + medianColor: '#f00', + showOutliers: true, + outlierIQR: 1.5, + spotRadius: 1.5, + target: undefined, + targetColor: '#4a2', + chartRangeMax: undefined, + chartRangeMin: undefined, + tooltipFormat: new SPFormat('{{field:fields}}: {{value}}'), + tooltipFormatFieldlistKey: 'field', + tooltipValueLookups: { fields: { lq: 'Lower Quartile', med: 'Median', + uq: 'Upper Quartile', lo: 'Left Outlier', ro: 'Right Outlier', + lw: 'Left Whisker', rw: 'Right Whisker'} } + } + }; + }; + + // You can have tooltips use a css class other than jqstooltip by specifying tooltipClassname + defaultStyles = '.jqstooltip { ' + + 'position: absolute;' + + 'left: 0px;' + + 'top: 0px;' + + 'visibility: hidden;' + + 'background: rgb(0, 0, 0) transparent;' + + 'background-color: rgba(0,0,0,0.6);' + + 'filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);' + + '-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";' + + 'color: white;' + + 'font: 10px arial, san serif;' + + 'text-align: left;' + + 'white-space: nowrap;' + + 'padding: 5px;' + + 'border: 1px solid white;' + + 'z-index: 10000;' + + '}' + + '.jqsfield { ' + + 'color: white;' + + 'font: 10px arial, san serif;' + + 'text-align: left;' + + '}'; + + /** + * Utilities + */ + + createClass = function (/* [baseclass, [mixin, ...]], definition */) { + var Class, args; + Class = function () { + this.init.apply(this, arguments); + }; + if (arguments.length > 1) { + if (arguments[0]) { + Class.prototype = $.extend(new arguments[0](), arguments[arguments.length - 1]); + Class._super = arguments[0].prototype; + } else { + Class.prototype = arguments[arguments.length - 1]; + } + if (arguments.length > 2) { + args = Array.prototype.slice.call(arguments, 1, -1); + args.unshift(Class.prototype); + $.extend.apply($, args); + } + } else { + Class.prototype = arguments[0]; + } + Class.prototype.cls = Class; + return Class; + }; + + /** + * Wraps a format string for tooltips + * {{x}} + * {{x.2} + * {{x:months}} + */ + $.SPFormatClass = SPFormat = createClass({ + fre: /\{\{([\w.]+?)(:(.+?))?\}\}/g, + precre: /(\w+)\.(\d+)/, + + init: function (format, fclass) { + this.format = format; + this.fclass = fclass; + }, + + render: function (fieldset, lookups, options) { + var self = this, + fields = fieldset, + match, token, lookupkey, fieldvalue, prec; + return this.format.replace(this.fre, function () { + var lookup; + token = arguments[1]; + lookupkey = arguments[3]; + match = self.precre.exec(token); + if (match) { + prec = match[2]; + token = match[1]; + } else { + prec = false; + } + fieldvalue = fields[token]; + if (fieldvalue === undefined) { + return ''; + } + if (lookupkey && lookups && lookups[lookupkey]) { + lookup = lookups[lookupkey]; + if (lookup.get) { // RangeMap + return lookups[lookupkey].get(fieldvalue) || fieldvalue; + } else { + return lookups[lookupkey][fieldvalue] || fieldvalue; + } + } + if (isNumber(fieldvalue)) { + if (options.get('numberFormatter')) { + fieldvalue = options.get('numberFormatter')(fieldvalue); + } else { + fieldvalue = formatNumber(fieldvalue, prec, + options.get('numberDigitGroupCount'), + options.get('numberDigitGroupSep'), + options.get('numberDecimalMark')); + } + } + return fieldvalue; + }); + } + }); + + // convience method to avoid needing the new operator + $.spformat = function(format, fclass) { + return new SPFormat(format, fclass); + }; + + clipval = function (val, min, max) { + if (val < min) { + return min; + } + if (val > max) { + return max; + } + return val; + }; + + quartile = function (values, q) { + var vl; + if (q === 2) { + vl = Math.floor(values.length / 2); + return values.length % 2 ? values[vl] : (values[vl-1] + values[vl]) / 2; + } else { + if (values.length % 2 ) { // odd + vl = (values.length * q + q) / 4; + return vl % 1 ? (values[Math.floor(vl)] + values[Math.floor(vl) - 1]) / 2 : values[vl-1]; + } else { //even + vl = (values.length * q + 2) / 4; + return vl % 1 ? (values[Math.floor(vl)] + values[Math.floor(vl) - 1]) / 2 : values[vl-1]; + + } + } + }; + + normalizeValue = function (val) { + var nf; + switch (val) { + case 'undefined': + val = undefined; + break; + case 'null': + val = null; + break; + case 'true': + val = true; + break; + case 'false': + val = false; + break; + default: + nf = parseFloat(val); + if (val == nf) { + val = nf; + } + } + return val; + }; + + normalizeValues = function (vals) { + var i, result = []; + for (i = vals.length; i--;) { + result[i] = normalizeValue(vals[i]); + } + return result; + }; + + remove = function (vals, filter) { + var i, vl, result = []; + for (i = 0, vl = vals.length; i < vl; i++) { + if (vals[i] !== filter) { + result.push(vals[i]); + } + } + return result; + }; + + isNumber = function (num) { + return !isNaN(parseFloat(num)) && isFinite(num); + }; + + formatNumber = function (num, prec, groupsize, groupsep, decsep) { + var p, i; + num = (prec === false ? parseFloat(num).toString() : num.toFixed(prec)).split(''); + p = (p = $.inArray('.', num)) < 0 ? num.length : p; + if (p < num.length) { + num[p] = decsep; + } + for (i = p - groupsize; i > 0; i -= groupsize) { + num.splice(i, 0, groupsep); + } + return num.join(''); + }; + + // determine if all values of an array match a value + // returns true if the array is empty + all = function (val, arr, ignoreNull) { + var i; + for (i = arr.length; i--; ) { + if (ignoreNull && arr[i] === null) continue; + if (arr[i] !== val) { + return false; + } + } + return true; + }; + + // sums the numeric values in an array, ignoring other values + sum = function (vals) { + var total = 0, i; + for (i = vals.length; i--;) { + total += typeof vals[i] === 'number' ? vals[i] : 0; + } + return total; + }; + + ensureArray = function (val) { + return $.isArray(val) ? val : [val]; + }; + + // http://paulirish.com/2008/bookmarklet-inject-new-css-rules/ + addCSS = function(css) { + var tag; + //if ('\v' == 'v') /* ie only */ { + if (document.createStyleSheet) { + document.createStyleSheet().cssText = css; + } else { + tag = document.createElement('style'); + tag.type = 'text/css'; + document.getElementsByTagName('head')[0].appendChild(tag); + tag[(typeof document.body.style.WebkitAppearance == 'string') /* webkit only */ ? 'innerText' : 'innerHTML'] = css; + } + }; + + // Provide a cross-browser interface to a few simple drawing primitives + $.fn.simpledraw = function (width, height, useExisting, interact) { + var target, mhandler; + if (useExisting && (target = this.data('_jqs_vcanvas'))) { + return target; + } + if (width === undefined) { + width = $(this).innerWidth(); + } + if (height === undefined) { + height = $(this).innerHeight(); + } + if ($.fn.sparkline.hasCanvas) { + target = new VCanvas_canvas(width, height, this, interact); + } else if ($.fn.sparkline.hasVML) { + target = new VCanvas_vml(width, height, this); + } else { + return false; + } + mhandler = $(this).data('_jqs_mhandler'); + if (mhandler) { + mhandler.registerCanvas(target); + } + return target; + }; + + $.fn.cleardraw = function () { + var target = this.data('_jqs_vcanvas'); + if (target) { + target.reset(); + } + }; + + $.RangeMapClass = RangeMap = createClass({ + init: function (map) { + var key, range, rangelist = []; + for (key in map) { + if (map.hasOwnProperty(key) && typeof key === 'string' && key.indexOf(':') > -1) { + range = key.split(':'); + range[0] = range[0].length === 0 ? -Infinity : parseFloat(range[0]); + range[1] = range[1].length === 0 ? Infinity : parseFloat(range[1]); + range[2] = map[key]; + rangelist.push(range); + } + } + this.map = map; + this.rangelist = rangelist || false; + }, + + get: function (value) { + var rangelist = this.rangelist, + i, range, result; + if ((result = this.map[value]) !== undefined) { + return result; + } + if (rangelist) { + for (i = rangelist.length; i--;) { + range = rangelist[i]; + if (range[0] <= value && range[1] >= value) { + return range[2]; + } + } + } + return undefined; + } + }); + + // Convenience function + $.range_map = function(map) { + return new RangeMap(map); + }; + + MouseHandler = createClass({ + init: function (el, options) { + var $el = $(el); + this.$el = $el; + this.options = options; + this.currentPageX = 0; + this.currentPageY = 0; + this.el = el; + this.splist = []; + this.tooltip = null; + this.over = false; + this.displayTooltips = !options.get('disableTooltips'); + this.highlightEnabled = !options.get('disableHighlight'); + }, + + registerSparkline: function (sp) { + this.splist.push(sp); + if (this.over) { + this.updateDisplay(); + } + }, + + registerCanvas: function (canvas) { + var $canvas = $(canvas.canvas); + this.canvas = canvas; + this.$canvas = $canvas; + $canvas.mouseenter($.proxy(this.mouseenter, this)); + $canvas.mouseleave($.proxy(this.mouseleave, this)); + $canvas.click($.proxy(this.mouseclick, this)); + }, + + reset: function (removeTooltip) { + this.splist = []; + if (this.tooltip && removeTooltip) { + this.tooltip.remove(); + this.tooltip = undefined; + } + }, + + mouseclick: function (e) { + var clickEvent = $.Event('sparklineClick'); + clickEvent.originalEvent = e; + clickEvent.sparklines = this.splist; + this.$el.trigger(clickEvent); + }, + + mouseenter: function (e) { + $(document.body).unbind('mousemove.jqs'); + $(document.body).bind('mousemove.jqs', $.proxy(this.mousemove, this)); + this.over = true; + this.currentPageX = e.pageX; + this.currentPageY = e.pageY; + this.currentEl = e.target; + if (!this.tooltip && this.displayTooltips) { + this.tooltip = new Tooltip(this.options); + this.tooltip.updatePosition(e.pageX, e.pageY); + } + this.updateDisplay(); + }, + + mouseleave: function () { + $(document.body).unbind('mousemove.jqs'); + var splist = this.splist, + spcount = splist.length, + needsRefresh = false, + sp, i; + this.over = false; + this.currentEl = null; + + if (this.tooltip) { + this.tooltip.remove(); + this.tooltip = null; + } + + for (i = 0; i < spcount; i++) { + sp = splist[i]; + if (sp.clearRegionHighlight()) { + needsRefresh = true; + } + } + + if (needsRefresh) { + this.canvas.render(); + } + }, + + mousemove: function (e) { + this.currentPageX = e.pageX; + this.currentPageY = e.pageY; + this.currentEl = e.target; + if (this.tooltip) { + this.tooltip.updatePosition(e.pageX, e.pageY); + } + this.updateDisplay(); + }, + + updateDisplay: function () { + var splist = this.splist, + spcount = splist.length, + needsRefresh = false, + offset = this.$canvas.offset(), + localX = this.currentPageX - offset.left, + localY = this.currentPageY - offset.top, + tooltiphtml, sp, i, result, changeEvent; + if (!this.over) { + return; + } + for (i = 0; i < spcount; i++) { + sp = splist[i]; + result = sp.setRegionHighlight(this.currentEl, localX, localY); + if (result) { + needsRefresh = true; + } + } + if (needsRefresh) { + changeEvent = $.Event('sparklineRegionChange'); + changeEvent.sparklines = this.splist; + this.$el.trigger(changeEvent); + if (this.tooltip) { + tooltiphtml = ''; + for (i = 0; i < spcount; i++) { + sp = splist[i]; + tooltiphtml += sp.getCurrentRegionTooltip(); + } + this.tooltip.setContent(tooltiphtml); + } + if (!this.disableHighlight) { + this.canvas.render(); + } + } + if (result === null) { + this.mouseleave(); + } + } + }); + + + Tooltip = createClass({ + sizeStyle: 'position: static !important;' + + 'display: block !important;' + + 'visibility: hidden !important;' + + 'float: left !important;', + + init: function (options) { + var tooltipClassname = options.get('tooltipClassname', 'jqstooltip'), + sizetipStyle = this.sizeStyle, + offset; + this.container = options.get('tooltipContainer') || document.body; + this.tooltipOffsetX = options.get('tooltipOffsetX', 10); + this.tooltipOffsetY = options.get('tooltipOffsetY', 12); + // remove any previous lingering tooltip + $('#jqssizetip').remove(); + $('#jqstooltip').remove(); + this.sizetip = $('
', { + id: 'jqssizetip', + style: sizetipStyle, + 'class': tooltipClassname + }); + this.tooltip = $('
', { + id: 'jqstooltip', + 'class': tooltipClassname + }).appendTo(this.container); + // account for the container's location + offset = this.tooltip.offset(); + this.offsetLeft = offset.left; + this.offsetTop = offset.top; + this.hidden = true; + $(window).unbind('resize.jqs scroll.jqs'); + $(window).bind('resize.jqs scroll.jqs', $.proxy(this.updateWindowDims, this)); + this.updateWindowDims(); + }, + + updateWindowDims: function () { + this.scrollTop = $(window).scrollTop(); + this.scrollLeft = $(window).scrollLeft(); + this.scrollRight = this.scrollLeft + $(window).width(); + this.updatePosition(); + }, + + getSize: function (content) { + this.sizetip.html(content).appendTo(this.container); + this.width = this.sizetip.width() + 1; + this.height = this.sizetip.height(); + this.sizetip.remove(); + }, + + setContent: function (content) { + if (!content) { + this.tooltip.css('visibility', 'hidden'); + this.hidden = true; + return; + } + this.getSize(content); + this.tooltip.html(content) + .css({ + 'width': this.width, + 'height': this.height, + 'visibility': 'visible' + }); + if (this.hidden) { + this.hidden = false; + this.updatePosition(); + } + }, + + updatePosition: function (x, y) { + if (x === undefined) { + if (this.mousex === undefined) { + return; + } + x = this.mousex - this.offsetLeft; + y = this.mousey - this.offsetTop; + + } else { + this.mousex = x = x - this.offsetLeft; + this.mousey = y = y - this.offsetTop; + } + if (!this.height || !this.width || this.hidden) { + return; + } + + y -= this.height + this.tooltipOffsetY; + x += this.tooltipOffsetX; + + if (y < this.scrollTop) { + y = this.scrollTop; + } + if (x < this.scrollLeft) { + x = this.scrollLeft; + } else if (x + this.width > this.scrollRight) { + x = this.scrollRight - this.width; + } + + this.tooltip.css({ + 'left': x, + 'top': y + }); + }, + + remove: function () { + this.tooltip.remove(); + this.sizetip.remove(); + this.sizetip = this.tooltip = undefined; + $(window).unbind('resize.jqs scroll.jqs'); + } + }); + + initStyles = function() { + addCSS(defaultStyles); + }; + + $(initStyles); + + pending = []; + $.fn.sparkline = function (userValues, userOptions) { + return this.each(function () { + var options = new $.fn.sparkline.options(this, userOptions), + $this = $(this), + render, i; + render = function () { + var values, width, height, tmp, mhandler, sp, vals; + if (userValues === 'html' || userValues === undefined) { + vals = this.getAttribute(options.get('tagValuesAttribute')); + if (vals === undefined || vals === null) { + vals = $this.html(); + } + values = vals.replace(/(^\s*\s*$)|\s+/g, '').split(','); + } else { + values = userValues; + } + + width = options.get('width') === 'auto' ? values.length * options.get('defaultPixelsPerValue') : options.get('width'); + if (options.get('height') === 'auto') { + if (!options.get('composite') || !$.data(this, '_jqs_vcanvas')) { + // must be a better way to get the line height + tmp = document.createElement('span'); + tmp.innerHTML = 'a'; + $this.html(tmp); + height = $(tmp).innerHeight() || $(tmp).height(); + $(tmp).remove(); + tmp = null; + } + } else { + height = options.get('height'); + } + + if (!options.get('disableInteraction')) { + mhandler = $.data(this, '_jqs_mhandler'); + if (!mhandler) { + mhandler = new MouseHandler(this, options); + $.data(this, '_jqs_mhandler', mhandler); + } else if (!options.get('composite')) { + mhandler.reset(); + } + } else { + mhandler = false; + } + + if (options.get('composite') && !$.data(this, '_jqs_vcanvas')) { + if (!$.data(this, '_jqs_errnotify')) { + alert('Attempted to attach a composite sparkline to an element with no existing sparkline'); + $.data(this, '_jqs_errnotify', true); + } + return; + } + + sp = new $.fn.sparkline[options.get('type')](this, values, options, width, height); + + sp.render(); + + if (mhandler) { + mhandler.registerSparkline(sp); + } + }; + // jQuery 1.3.0 completely changed the meaning of :hidden :-/ + if (($(this).html() && !options.get('disableHiddenCheck') && $(this).is(':hidden')) || ($.fn.jquery < '1.3.0' && $(this).parents().is(':hidden')) || !$(this).parents('body').length) { + if (!options.get('composite') && $.data(this, '_jqs_pending')) { + // remove any existing references to the element + for (i = pending.length; i; i--) { + if (pending[i - 1][0] == this) { + pending.splice(i - 1, 1); + } + } + } + pending.push([this, render]); + $.data(this, '_jqs_pending', true); + } else { + render.call(this); + } + }); + }; + + $.fn.sparkline.defaults = getDefaults(); + + + $.sparkline_display_visible = function () { + var el, i, pl; + var done = []; + for (i = 0, pl = pending.length; i < pl; i++) { + el = pending[i][0]; + if ($(el).is(':visible') && !$(el).parents().is(':hidden')) { + pending[i][1].call(el); + $.data(pending[i][0], '_jqs_pending', false); + done.push(i); + } else if (!$(el).closest('html').length && !$.data(el, '_jqs_pending')) { + // element has been inserted and removed from the DOM + // If it was not yet inserted into the dom then the .data request + // will return true. + // removing from the dom causes the data to be removed. + $.data(pending[i][0], '_jqs_pending', false); + done.push(i); + } + } + for (i = done.length; i; i--) { + pending.splice(done[i - 1], 1); + } + }; + + + /** + * User option handler + */ + $.fn.sparkline.options = createClass({ + init: function (tag, userOptions) { + var extendedOptions, defaults, base, tagOptionType; + this.userOptions = userOptions = userOptions || {}; + this.tag = tag; + this.tagValCache = {}; + defaults = $.fn.sparkline.defaults; + base = defaults.common; + this.tagOptionsPrefix = userOptions.enableTagOptions && (userOptions.tagOptionsPrefix || base.tagOptionsPrefix); + + tagOptionType = this.getTagSetting('type'); + if (tagOptionType === UNSET_OPTION) { + extendedOptions = defaults[userOptions.type || base.type]; + } else { + extendedOptions = defaults[tagOptionType]; + } + this.mergedOptions = $.extend({}, base, extendedOptions, userOptions); + }, + + + getTagSetting: function (key) { + var prefix = this.tagOptionsPrefix, + val, i, pairs, keyval; + if (prefix === false || prefix === undefined) { + return UNSET_OPTION; + } + if (this.tagValCache.hasOwnProperty(key)) { + val = this.tagValCache.key; + } else { + val = this.tag.getAttribute(prefix + key); + if (val === undefined || val === null) { + val = UNSET_OPTION; + } else if (val.substr(0, 1) === '[') { + val = val.substr(1, val.length - 2).split(','); + for (i = val.length; i--;) { + val[i] = normalizeValue(val[i].replace(/(^\s*)|(\s*$)/g, '')); + } + } else if (val.substr(0, 1) === '{') { + pairs = val.substr(1, val.length - 2).split(','); + val = {}; + for (i = pairs.length; i--;) { + keyval = pairs[i].split(':', 2); + val[keyval[0].replace(/(^\s*)|(\s*$)/g, '')] = normalizeValue(keyval[1].replace(/(^\s*)|(\s*$)/g, '')); + } + } else { + val = normalizeValue(val); + } + this.tagValCache.key = val; + } + return val; + }, + + get: function (key, defaultval) { + var tagOption = this.getTagSetting(key), + result; + if (tagOption !== UNSET_OPTION) { + return tagOption; + } + return (result = this.mergedOptions[key]) === undefined ? defaultval : result; + } + }); + + + $.fn.sparkline._base = createClass({ + disabled: false, + + init: function (el, values, options, width, height) { + this.el = el; + this.$el = $(el); + this.values = values; + this.options = options; + this.width = width; + this.height = height; + this.currentRegion = undefined; + }, + + /** + * Setup the canvas + */ + initTarget: function () { + var interactive = !this.options.get('disableInteraction'); + if (!(this.target = this.$el.simpledraw(this.width, this.height, this.options.get('composite'), interactive))) { + this.disabled = true; + } else { + this.canvasWidth = this.target.pixelWidth; + this.canvasHeight = this.target.pixelHeight; + } + }, + + /** + * Actually render the chart to the canvas + */ + render: function () { + if (this.disabled) { + this.el.innerHTML = ''; + return false; + } + return true; + }, + + /** + * Return a region id for a given x/y co-ordinate + */ + getRegion: function (x, y) { + }, + + /** + * Highlight an item based on the moused-over x,y co-ordinate + */ + setRegionHighlight: function (el, x, y) { + var currentRegion = this.currentRegion, + highlightEnabled = !this.options.get('disableHighlight'), + newRegion; + if (x > this.canvasWidth || y > this.canvasHeight || x < 0 || y < 0) { + return null; + } + newRegion = this.getRegion(el, x, y); + if (currentRegion !== newRegion) { + if (currentRegion !== undefined && highlightEnabled) { + this.removeHighlight(); + } + this.currentRegion = newRegion; + if (newRegion !== undefined && highlightEnabled) { + this.renderHighlight(); + } + return true; + } + return false; + }, + + /** + * Reset any currently highlighted item + */ + clearRegionHighlight: function () { + if (this.currentRegion !== undefined) { + this.removeHighlight(); + this.currentRegion = undefined; + return true; + } + return false; + }, + + renderHighlight: function () { + this.changeHighlight(true); + }, + + removeHighlight: function () { + this.changeHighlight(false); + }, + + changeHighlight: function (highlight) {}, + + /** + * Fetch the HTML to display as a tooltip + */ + getCurrentRegionTooltip: function () { + var options = this.options, + header = '', + entries = [], + fields, formats, formatlen, fclass, text, i, + showFields, showFieldsKey, newFields, fv, + formatter, format, fieldlen, j; + if (this.currentRegion === undefined) { + return ''; + } + fields = this.getCurrentRegionFields(); + formatter = options.get('tooltipFormatter'); + if (formatter) { + return formatter(this, options, fields); + } + if (options.get('tooltipChartTitle')) { + header += '
' + options.get('tooltipChartTitle') + '
\n'; + } + formats = this.options.get('tooltipFormat'); + if (!formats) { + return ''; + } + if (!$.isArray(formats)) { + formats = [formats]; + } + if (!$.isArray(fields)) { + fields = [fields]; + } + showFields = this.options.get('tooltipFormatFieldlist'); + showFieldsKey = this.options.get('tooltipFormatFieldlistKey'); + if (showFields && showFieldsKey) { + // user-selected ordering of fields + newFields = []; + for (i = fields.length; i--;) { + fv = fields[i][showFieldsKey]; + if ((j = $.inArray(fv, showFields)) != -1) { + newFields[j] = fields[i]; + } + } + fields = newFields; + } + formatlen = formats.length; + fieldlen = fields.length; + for (i = 0; i < formatlen; i++) { + format = formats[i]; + if (typeof format === 'string') { + format = new SPFormat(format); + } + fclass = format.fclass || 'jqsfield'; + for (j = 0; j < fieldlen; j++) { + if (!fields[j].isNull || !options.get('tooltipSkipNull')) { + $.extend(fields[j], { + prefix: options.get('tooltipPrefix'), + suffix: options.get('tooltipSuffix') + }); + text = format.render(fields[j], options.get('tooltipValueLookups'), options); + entries.push('
' + text + '
'); + } + } + } + if (entries.length) { + return header + entries.join('\n'); + } + return ''; + }, + + getCurrentRegionFields: function () {}, + + calcHighlightColor: function (color, options) { + var highlightColor = options.get('highlightColor'), + lighten = options.get('highlightLighten'), + parse, mult, rgbnew, i; + if (highlightColor) { + return highlightColor; + } + if (lighten) { + // extract RGB values + parse = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(color) || /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(color); + if (parse) { + rgbnew = []; + mult = color.length === 4 ? 16 : 1; + for (i = 0; i < 3; i++) { + rgbnew[i] = clipval(Math.round(parseInt(parse[i + 1], 16) * mult * lighten), 0, 255); + } + return 'rgb(' + rgbnew.join(',') + ')'; + } + + } + return color; + } + + }); + + barHighlightMixin = { + changeHighlight: function (highlight) { + var currentRegion = this.currentRegion, + target = this.target, + shapeids = this.regionShapes[currentRegion], + newShapes; + // will be null if the region value was null + if (shapeids) { + newShapes = this.renderRegion(currentRegion, highlight); + if ($.isArray(newShapes) || $.isArray(shapeids)) { + target.replaceWithShapes(shapeids, newShapes); + this.regionShapes[currentRegion] = $.map(newShapes, function (newShape) { + return newShape.id; + }); + } else { + target.replaceWithShape(shapeids, newShapes); + this.regionShapes[currentRegion] = newShapes.id; + } + } + }, + + render: function () { + var values = this.values, + target = this.target, + regionShapes = this.regionShapes, + shapes, ids, i, j; + + if (!this.cls._super.render.call(this)) { + return; + } + for (i = values.length; i--;) { + shapes = this.renderRegion(i); + if (shapes) { + if ($.isArray(shapes)) { + ids = []; + for (j = shapes.length; j--;) { + shapes[j].append(); + ids.push(shapes[j].id); + } + regionShapes[i] = ids; + } else { + shapes.append(); + regionShapes[i] = shapes.id; // store just the shapeid + } + } else { + // null value + regionShapes[i] = null; + } + } + target.render(); + } + }; + + /** + * Line charts + */ + $.fn.sparkline.line = line = createClass($.fn.sparkline._base, { + type: 'line', + + init: function (el, values, options, width, height) { + line._super.init.call(this, el, values, options, width, height); + this.vertices = []; + this.regionMap = []; + this.xvalues = []; + this.yvalues = []; + this.yminmax = []; + this.hightlightSpotId = null; + this.lastShapeId = null; + this.initTarget(); + }, + + getRegion: function (el, x, y) { + var i, + regionMap = this.regionMap; // maps regions to value positions + for (i = regionMap.length; i--;) { + if (regionMap[i] !== null && x >= regionMap[i][0] && x <= regionMap[i][1]) { + return regionMap[i][2]; + } + } + return undefined; + }, + + getCurrentRegionFields: function () { + var currentRegion = this.currentRegion; + return { + isNull: this.yvalues[currentRegion] === null, + x: this.xvalues[currentRegion], + y: this.yvalues[currentRegion], + color: this.options.get('lineColor'), + fillColor: this.options.get('fillColor'), + offset: currentRegion + }; + }, + + renderHighlight: function () { + var currentRegion = this.currentRegion, + target = this.target, + vertex = this.vertices[currentRegion], + options = this.options, + spotRadius = options.get('spotRadius'), + highlightSpotColor = options.get('highlightSpotColor'), + highlightLineColor = options.get('highlightLineColor'), + highlightSpot, highlightLine; + + if (!vertex) { + return; + } + if (spotRadius && highlightSpotColor) { + highlightSpot = target.drawCircle(vertex[0], vertex[1], + spotRadius, undefined, highlightSpotColor); + this.highlightSpotId = highlightSpot.id; + target.insertAfterShape(this.lastShapeId, highlightSpot); + } + if (highlightLineColor) { + highlightLine = target.drawLine(vertex[0], this.canvasTop, vertex[0], + this.canvasTop + this.canvasHeight, highlightLineColor); + this.highlightLineId = highlightLine.id; + target.insertAfterShape(this.lastShapeId, highlightLine); + } + }, + + removeHighlight: function () { + var target = this.target; + if (this.highlightSpotId) { + target.removeShapeId(this.highlightSpotId); + this.highlightSpotId = null; + } + if (this.highlightLineId) { + target.removeShapeId(this.highlightLineId); + this.highlightLineId = null; + } + }, + + scanValues: function () { + var values = this.values, + valcount = values.length, + xvalues = this.xvalues, + yvalues = this.yvalues, + yminmax = this.yminmax, + i, val, isStr, isArray, sp; + for (i = 0; i < valcount; i++) { + val = values[i]; + isStr = typeof(values[i]) === 'string'; + isArray = typeof(values[i]) === 'object' && values[i] instanceof Array; + sp = isStr && values[i].split(':'); + if (isStr && sp.length === 2) { // x:y + xvalues.push(Number(sp[0])); + yvalues.push(Number(sp[1])); + yminmax.push(Number(sp[1])); + } else if (isArray) { + xvalues.push(val[0]); + yvalues.push(val[1]); + yminmax.push(val[1]); + } else { + xvalues.push(i); + if (values[i] === null || values[i] === 'null') { + yvalues.push(null); + } else { + yvalues.push(Number(val)); + yminmax.push(Number(val)); + } + } + } + if (this.options.get('xvalues')) { + xvalues = this.options.get('xvalues'); + } + + this.maxy = this.maxyorg = Math.max.apply(Math, yminmax); + this.miny = this.minyorg = Math.min.apply(Math, yminmax); + + this.maxx = Math.max.apply(Math, xvalues); + this.minx = Math.min.apply(Math, xvalues); + + this.xvalues = xvalues; + this.yvalues = yvalues; + this.yminmax = yminmax; + + }, + + processRangeOptions: function () { + var options = this.options, + normalRangeMin = options.get('normalRangeMin'), + normalRangeMax = options.get('normalRangeMax'); + + if (normalRangeMin !== undefined) { + if (normalRangeMin < this.miny) { + this.miny = normalRangeMin; + } + if (normalRangeMax > this.maxy) { + this.maxy = normalRangeMax; + } + } + if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < this.miny)) { + this.miny = options.get('chartRangeMin'); + } + if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > this.maxy)) { + this.maxy = options.get('chartRangeMax'); + } + if (options.get('chartRangeMinX') !== undefined && (options.get('chartRangeClipX') || options.get('chartRangeMinX') < this.minx)) { + this.minx = options.get('chartRangeMinX'); + } + if (options.get('chartRangeMaxX') !== undefined && (options.get('chartRangeClipX') || options.get('chartRangeMaxX') > this.maxx)) { + this.maxx = options.get('chartRangeMaxX'); + } + + }, + + drawNormalRange: function (canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey) { + var normalRangeMin = this.options.get('normalRangeMin'), + normalRangeMax = this.options.get('normalRangeMax'), + ytop = canvasTop + Math.round(canvasHeight - (canvasHeight * ((normalRangeMax - this.miny) / rangey))), + height = Math.round((canvasHeight * (normalRangeMax - normalRangeMin)) / rangey); + this.target.drawRect(canvasLeft, ytop, canvasWidth, height, undefined, this.options.get('normalRangeColor')).append(); + }, + + render: function () { + var options = this.options, + target = this.target, + canvasWidth = this.canvasWidth, + canvasHeight = this.canvasHeight, + vertices = this.vertices, + spotRadius = options.get('spotRadius'), + regionMap = this.regionMap, + rangex, rangey, yvallast, + canvasTop, canvasLeft, + vertex, path, paths, x, y, xnext, xpos, xposnext, + last, next, yvalcount, lineShapes, fillShapes, plen, + valueSpots, hlSpotsEnabled, color, xvalues, yvalues, i; + + if (!line._super.render.call(this)) { + return; + } + + this.scanValues(); + this.processRangeOptions(); + + xvalues = this.xvalues; + yvalues = this.yvalues; + + if (!this.yminmax.length || this.yvalues.length < 2) { + // empty or all null valuess + return; + } + + canvasTop = canvasLeft = 0; + + rangex = this.maxx - this.minx === 0 ? 1 : this.maxx - this.minx; + rangey = this.maxy - this.miny === 0 ? 1 : this.maxy - this.miny; + yvallast = this.yvalues.length - 1; + + if (spotRadius && (canvasWidth < (spotRadius * 4) || canvasHeight < (spotRadius * 4))) { + spotRadius = 0; + } + if (spotRadius) { + // adjust the canvas size as required so that spots will fit + hlSpotsEnabled = options.get('highlightSpotColor') && !options.get('disableInteraction'); + if (hlSpotsEnabled || options.get('minSpotColor') || (options.get('spotColor') && yvalues[yvallast] === this.miny)) { + canvasHeight -= Math.ceil(spotRadius); + } + if (hlSpotsEnabled || options.get('maxSpotColor') || (options.get('spotColor') && yvalues[yvallast] === this.maxy)) { + canvasHeight -= Math.ceil(spotRadius); + canvasTop += Math.ceil(spotRadius); + } + if (hlSpotsEnabled || + ((options.get('minSpotColor') || options.get('maxSpotColor')) && (yvalues[0] === this.miny || yvalues[0] === this.maxy))) { + canvasLeft += Math.ceil(spotRadius); + canvasWidth -= Math.ceil(spotRadius); + } + if (hlSpotsEnabled || options.get('spotColor') || + (options.get('minSpotColor') || options.get('maxSpotColor') && + (yvalues[yvallast] === this.miny || yvalues[yvallast] === this.maxy))) { + canvasWidth -= Math.ceil(spotRadius); + } + } + + + canvasHeight--; + + if (options.get('normalRangeMin') !== undefined && !options.get('drawNormalOnTop')) { + this.drawNormalRange(canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey); + } + + path = []; + paths = [path]; + last = next = null; + yvalcount = yvalues.length; + for (i = 0; i < yvalcount; i++) { + x = xvalues[i]; + xnext = xvalues[i + 1]; + y = yvalues[i]; + xpos = canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex)); + xposnext = i < yvalcount - 1 ? canvasLeft + Math.round((xnext - this.minx) * (canvasWidth / rangex)) : canvasWidth; + next = xpos + ((xposnext - xpos) / 2); + regionMap[i] = [last || 0, next, i]; + last = next; + if (y === null) { + if (i) { + if (yvalues[i - 1] !== null) { + path = []; + paths.push(path); + } + vertices.push(null); + } + } else { + if (y < this.miny) { + y = this.miny; + } + if (y > this.maxy) { + y = this.maxy; + } + if (!path.length) { + // previous value was null + path.push([xpos, canvasTop + canvasHeight]); + } + vertex = [xpos, canvasTop + Math.round(canvasHeight - (canvasHeight * ((y - this.miny) / rangey)))]; + path.push(vertex); + vertices.push(vertex); + } + } + + lineShapes = []; + fillShapes = []; + plen = paths.length; + for (i = 0; i < plen; i++) { + path = paths[i]; + if (path.length) { + if (options.get('fillColor')) { + path.push([path[path.length - 1][0], (canvasTop + canvasHeight)]); + fillShapes.push(path.slice(0)); + path.pop(); + } + // if there's only a single point in this path, then we want to display it + // as a vertical line which means we keep path[0] as is + if (path.length > 2) { + // else we want the first value + path[0] = [path[0][0], path[1][1]]; + } + lineShapes.push(path); + } + } + + // draw the fill first, then optionally the normal range, then the line on top of that + plen = fillShapes.length; + for (i = 0; i < plen; i++) { + target.drawShape(fillShapes[i], + options.get('fillColor'), options.get('fillColor')).append(); + } + + if (options.get('normalRangeMin') !== undefined && options.get('drawNormalOnTop')) { + this.drawNormalRange(canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey); + } + + plen = lineShapes.length; + for (i = 0; i < plen; i++) { + target.drawShape(lineShapes[i], options.get('lineColor'), undefined, + options.get('lineWidth')).append(); + } + + if (spotRadius && options.get('valueSpots')) { + valueSpots = options.get('valueSpots'); + if (valueSpots.get === undefined) { + valueSpots = new RangeMap(valueSpots); + } + for (i = 0; i < yvalcount; i++) { + color = valueSpots.get(yvalues[i]); + if (color) { + target.drawCircle(canvasLeft + Math.round((xvalues[i] - this.minx) * (canvasWidth / rangex)), + canvasTop + Math.round(canvasHeight - (canvasHeight * ((yvalues[i] - this.miny) / rangey))), + spotRadius, undefined, + color).append(); + } + } + + } + if (spotRadius && options.get('spotColor') && yvalues[yvallast] !== null) { + target.drawCircle(canvasLeft + Math.round((xvalues[xvalues.length - 1] - this.minx) * (canvasWidth / rangex)), + canvasTop + Math.round(canvasHeight - (canvasHeight * ((yvalues[yvallast] - this.miny) / rangey))), + spotRadius, undefined, + options.get('spotColor')).append(); + } + if (this.maxy !== this.minyorg) { + if (spotRadius && options.get('minSpotColor')) { + x = xvalues[$.inArray(this.minyorg, yvalues)]; + target.drawCircle(canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex)), + canvasTop + Math.round(canvasHeight - (canvasHeight * ((this.minyorg - this.miny) / rangey))), + spotRadius, undefined, + options.get('minSpotColor')).append(); + } + if (spotRadius && options.get('maxSpotColor')) { + x = xvalues[$.inArray(this.maxyorg, yvalues)]; + target.drawCircle(canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex)), + canvasTop + Math.round(canvasHeight - (canvasHeight * ((this.maxyorg - this.miny) / rangey))), + spotRadius, undefined, + options.get('maxSpotColor')).append(); + } + } + + this.lastShapeId = target.getLastShapeId(); + this.canvasTop = canvasTop; + target.render(); + } + }); + + /** + * Bar charts + */ + $.fn.sparkline.bar = bar = createClass($.fn.sparkline._base, barHighlightMixin, { + type: 'bar', + + init: function (el, values, options, width, height) { + var barWidth = parseInt(options.get('barWidth'), 10), + barSpacing = parseInt(options.get('barSpacing'), 10), + chartRangeMin = options.get('chartRangeMin'), + chartRangeMax = options.get('chartRangeMax'), + chartRangeClip = options.get('chartRangeClip'), + stackMin = Infinity, + stackMax = -Infinity, + isStackString, groupMin, groupMax, stackRanges, + numValues, i, vlen, range, zeroAxis, xaxisOffset, min, max, clipMin, clipMax, + stacked, vlist, j, slen, svals, val, yoffset, yMaxCalc, canvasHeightEf; + bar._super.init.call(this, el, values, options, width, height); + + // scan values to determine whether to stack bars + for (i = 0, vlen = values.length; i < vlen; i++) { + val = values[i]; + isStackString = typeof(val) === 'string' && val.indexOf(':') > -1; + if (isStackString || $.isArray(val)) { + stacked = true; + if (isStackString) { + val = values[i] = normalizeValues(val.split(':')); + } + val = remove(val, null); // min/max will treat null as zero + groupMin = Math.min.apply(Math, val); + groupMax = Math.max.apply(Math, val); + if (groupMin < stackMin) { + stackMin = groupMin; + } + if (groupMax > stackMax) { + stackMax = groupMax; + } + } + } + + this.stacked = stacked; + this.regionShapes = {}; + this.barWidth = barWidth; + this.barSpacing = barSpacing; + this.totalBarWidth = barWidth + barSpacing; + this.width = width = (values.length * barWidth) + ((values.length - 1) * barSpacing); + + this.initTarget(); + + if (chartRangeClip) { + clipMin = chartRangeMin === undefined ? -Infinity : chartRangeMin; + clipMax = chartRangeMax === undefined ? Infinity : chartRangeMax; + } + + numValues = []; + stackRanges = stacked ? [] : numValues; + var stackTotals = []; + var stackRangesNeg = []; + for (i = 0, vlen = values.length; i < vlen; i++) { + if (stacked) { + vlist = values[i]; + values[i] = svals = []; + stackTotals[i] = 0; + stackRanges[i] = stackRangesNeg[i] = 0; + for (j = 0, slen = vlist.length; j < slen; j++) { + val = svals[j] = chartRangeClip ? clipval(vlist[j], clipMin, clipMax) : vlist[j]; + if (val !== null) { + if (val > 0) { + stackTotals[i] += val; + } + if (stackMin < 0 && stackMax > 0) { + if (val < 0) { + stackRangesNeg[i] += Math.abs(val); + } else { + stackRanges[i] += val; + } + } else { + stackRanges[i] += Math.abs(val - (val < 0 ? stackMax : stackMin)); + } + numValues.push(val); + } + } + } else { + val = chartRangeClip ? clipval(values[i], clipMin, clipMax) : values[i]; + val = values[i] = normalizeValue(val); + if (val !== null) { + numValues.push(val); + } + } + } + this.max = max = Math.max.apply(Math, numValues); + this.min = min = Math.min.apply(Math, numValues); + this.stackMax = stackMax = stacked ? Math.max.apply(Math, stackTotals) : max; + this.stackMin = stackMin = stacked ? Math.min.apply(Math, numValues) : min; + + if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < min)) { + min = options.get('chartRangeMin'); + } + if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > max)) { + max = options.get('chartRangeMax'); + } + + this.zeroAxis = zeroAxis = options.get('zeroAxis', true); + if (min <= 0 && max >= 0 && zeroAxis) { + xaxisOffset = 0; + } else if (zeroAxis == false) { + xaxisOffset = min; + } else if (min > 0) { + xaxisOffset = min; + } else { + xaxisOffset = max; + } + this.xaxisOffset = xaxisOffset; + + range = stacked ? (Math.max.apply(Math, stackRanges) + Math.max.apply(Math, stackRangesNeg)) : max - min; + + // as we plot zero/min values a single pixel line, we add a pixel to all other + // values - Reduce the effective canvas size to suit + this.canvasHeightEf = (zeroAxis && min < 0) ? this.canvasHeight - 2 : this.canvasHeight - 1; + + if (min < xaxisOffset) { + yMaxCalc = (stacked && max >= 0) ? stackMax : max; + yoffset = (yMaxCalc - xaxisOffset) / range * this.canvasHeight; + if (yoffset !== Math.ceil(yoffset)) { + this.canvasHeightEf -= 2; + yoffset = Math.ceil(yoffset); + } + } else { + yoffset = this.canvasHeight; + } + this.yoffset = yoffset; + + if ($.isArray(options.get('colorMap'))) { + this.colorMapByIndex = options.get('colorMap'); + this.colorMapByValue = null; + } else { + this.colorMapByIndex = null; + this.colorMapByValue = options.get('colorMap'); + if (this.colorMapByValue && this.colorMapByValue.get === undefined) { + this.colorMapByValue = new RangeMap(this.colorMapByValue); + } + } + + this.range = range; + }, + + getRegion: function (el, x, y) { + var result = Math.floor(x / this.totalBarWidth); + return (result < 0 || result >= this.values.length) ? undefined : result; + }, + + getCurrentRegionFields: function () { + var currentRegion = this.currentRegion, + values = ensureArray(this.values[currentRegion]), + result = [], + value, i; + for (i = values.length; i--;) { + value = values[i]; + result.push({ + isNull: value === null, + value: value, + color: this.calcColor(i, value, currentRegion), + offset: currentRegion + }); + } + return result; + }, + + calcColor: function (stacknum, value, valuenum) { + var colorMapByIndex = this.colorMapByIndex, + colorMapByValue = this.colorMapByValue, + options = this.options, + color, newColor; + if (this.stacked) { + color = options.get('stackedBarColor'); + } else { + color = (value < 0) ? options.get('negBarColor') : options.get('barColor'); + } + if (value === 0 && options.get('zeroColor') !== undefined) { + color = options.get('zeroColor'); + } + if (colorMapByValue && (newColor = colorMapByValue.get(value))) { + color = newColor; + } else if (colorMapByIndex && colorMapByIndex.length > valuenum) { + color = colorMapByIndex[valuenum]; + } + return $.isArray(color) ? color[stacknum % color.length] : color; + }, + + /** + * Render bar(s) for a region + */ + renderRegion: function (valuenum, highlight) { + var vals = this.values[valuenum], + options = this.options, + xaxisOffset = this.xaxisOffset, + result = [], + range = this.range, + stacked = this.stacked, + target = this.target, + x = valuenum * this.totalBarWidth, + canvasHeightEf = this.canvasHeightEf, + yoffset = this.yoffset, + y, height, color, isNull, yoffsetNeg, i, valcount, val, minPlotted, allMin; + + vals = $.isArray(vals) ? vals : [vals]; + valcount = vals.length; + val = vals[0]; + isNull = all(null, vals); + allMin = all(xaxisOffset, vals, true); + + if (isNull) { + if (options.get('nullColor')) { + color = highlight ? options.get('nullColor') : this.calcHighlightColor(options.get('nullColor'), options); + y = (yoffset > 0) ? yoffset - 1 : yoffset; + return target.drawRect(x, y, this.barWidth - 1, 0, color, color); + } else { + return undefined; + } + } + yoffsetNeg = yoffset; + for (i = 0; i < valcount; i++) { + val = vals[i]; + + if (stacked && val === xaxisOffset) { + if (!allMin || minPlotted) { + continue; + } + minPlotted = true; + } + + if (range > 0) { + height = Math.floor(canvasHeightEf * ((Math.abs(val - xaxisOffset) / range))) + 1; + } else { + height = 1; + } + if (val < xaxisOffset || (val === xaxisOffset && yoffset === 0)) { + y = yoffsetNeg; + yoffsetNeg += height; + } else { + y = yoffset - height; + yoffset -= height; + } + color = this.calcColor(i, val, valuenum); + if (highlight) { + color = this.calcHighlightColor(color, options); + } + result.push(target.drawRect(x, y, this.barWidth - 1, height - 1, color, color)); + } + if (result.length === 1) { + return result[0]; + } + return result; + } + }); + + /** + * Tristate charts + */ + $.fn.sparkline.tristate = tristate = createClass($.fn.sparkline._base, barHighlightMixin, { + type: 'tristate', + + init: function (el, values, options, width, height) { + var barWidth = parseInt(options.get('barWidth'), 10), + barSpacing = parseInt(options.get('barSpacing'), 10); + tristate._super.init.call(this, el, values, options, width, height); + + this.regionShapes = {}; + this.barWidth = barWidth; + this.barSpacing = barSpacing; + this.totalBarWidth = barWidth + barSpacing; + this.values = $.map(values, Number); + this.width = width = (values.length * barWidth) + ((values.length - 1) * barSpacing); + + if ($.isArray(options.get('colorMap'))) { + this.colorMapByIndex = options.get('colorMap'); + this.colorMapByValue = null; + } else { + this.colorMapByIndex = null; + this.colorMapByValue = options.get('colorMap'); + if (this.colorMapByValue && this.colorMapByValue.get === undefined) { + this.colorMapByValue = new RangeMap(this.colorMapByValue); + } + } + this.initTarget(); + }, + + getRegion: function (el, x, y) { + return Math.floor(x / this.totalBarWidth); + }, + + getCurrentRegionFields: function () { + var currentRegion = this.currentRegion; + return { + isNull: this.values[currentRegion] === undefined, + value: this.values[currentRegion], + color: this.calcColor(this.values[currentRegion], currentRegion), + offset: currentRegion + }; + }, + + calcColor: function (value, valuenum) { + var values = this.values, + options = this.options, + colorMapByIndex = this.colorMapByIndex, + colorMapByValue = this.colorMapByValue, + color, newColor; + + if (colorMapByValue && (newColor = colorMapByValue.get(value))) { + color = newColor; + } else if (colorMapByIndex && colorMapByIndex.length > valuenum) { + color = colorMapByIndex[valuenum]; + } else if (values[valuenum] < 0) { + color = options.get('negBarColor'); + } else if (values[valuenum] > 0) { + color = options.get('posBarColor'); + } else { + color = options.get('zeroBarColor'); + } + return color; + }, + + renderRegion: function (valuenum, highlight) { + var values = this.values, + options = this.options, + target = this.target, + canvasHeight, height, halfHeight, + x, y, color; + + canvasHeight = target.pixelHeight; + halfHeight = Math.round(canvasHeight / 2); + + x = valuenum * this.totalBarWidth; + if (values[valuenum] < 0) { + y = halfHeight; + height = halfHeight - 1; + } else if (values[valuenum] > 0) { + y = 0; + height = halfHeight - 1; + } else { + y = halfHeight - 1; + height = 2; + } + color = this.calcColor(values[valuenum], valuenum); + if (color === null) { + return; + } + if (highlight) { + color = this.calcHighlightColor(color, options); + } + return target.drawRect(x, y, this.barWidth - 1, height - 1, color, color); + } + }); + + /** + * Discrete charts + */ + $.fn.sparkline.discrete = discrete = createClass($.fn.sparkline._base, barHighlightMixin, { + type: 'discrete', + + init: function (el, values, options, width, height) { + discrete._super.init.call(this, el, values, options, width, height); + + this.regionShapes = {}; + this.values = values = $.map(values, Number); + this.min = Math.min.apply(Math, values); + this.max = Math.max.apply(Math, values); + this.range = this.max - this.min; + this.width = width = options.get('width') === 'auto' ? values.length * 2 : this.width; + this.interval = Math.floor(width / values.length); + this.itemWidth = width / values.length; + if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < this.min)) { + this.min = options.get('chartRangeMin'); + } + if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > this.max)) { + this.max = options.get('chartRangeMax'); + } + this.initTarget(); + if (this.target) { + this.lineHeight = options.get('lineHeight') === 'auto' ? Math.round(this.canvasHeight * 0.3) : options.get('lineHeight'); + } + }, + + getRegion: function (el, x, y) { + return Math.floor(x / this.itemWidth); + }, + + getCurrentRegionFields: function () { + var currentRegion = this.currentRegion; + return { + isNull: this.values[currentRegion] === undefined, + value: this.values[currentRegion], + offset: currentRegion + }; + }, + + renderRegion: function (valuenum, highlight) { + var values = this.values, + options = this.options, + min = this.min, + max = this.max, + range = this.range, + interval = this.interval, + target = this.target, + canvasHeight = this.canvasHeight, + lineHeight = this.lineHeight, + pheight = canvasHeight - lineHeight, + ytop, val, color, x; + + val = clipval(values[valuenum], min, max); + x = valuenum * interval; + ytop = Math.round(pheight - pheight * ((val - min) / range)); + color = (options.get('thresholdColor') && val < options.get('thresholdValue')) ? options.get('thresholdColor') : options.get('lineColor'); + if (highlight) { + color = this.calcHighlightColor(color, options); + } + return target.drawLine(x, ytop, x, ytop + lineHeight, color); + } + }); + + /** + * Bullet charts + */ + $.fn.sparkline.bullet = bullet = createClass($.fn.sparkline._base, { + type: 'bullet', + + init: function (el, values, options, width, height) { + var min, max, vals; + bullet._super.init.call(this, el, values, options, width, height); + + // values: target, performance, range1, range2, range3 + this.values = values = normalizeValues(values); + // target or performance could be null + vals = values.slice(); + vals[0] = vals[0] === null ? vals[2] : vals[0]; + vals[1] = values[1] === null ? vals[2] : vals[1]; + min = Math.min.apply(Math, values); + max = Math.max.apply(Math, values); + if (options.get('base') === undefined) { + min = min < 0 ? min : 0; + } else { + min = options.get('base'); + } + this.min = min; + this.max = max; + this.range = max - min; + this.shapes = {}; + this.valueShapes = {}; + this.regiondata = {}; + this.width = width = options.get('width') === 'auto' ? '4.0em' : width; + this.target = this.$el.simpledraw(width, height, options.get('composite')); + if (!values.length) { + this.disabled = true; + } + this.initTarget(); + }, + + getRegion: function (el, x, y) { + var shapeid = this.target.getShapeAt(el, x, y); + return (shapeid !== undefined && this.shapes[shapeid] !== undefined) ? this.shapes[shapeid] : undefined; + }, + + getCurrentRegionFields: function () { + var currentRegion = this.currentRegion; + return { + fieldkey: currentRegion.substr(0, 1), + value: this.values[currentRegion.substr(1)], + region: currentRegion + }; + }, + + changeHighlight: function (highlight) { + var currentRegion = this.currentRegion, + shapeid = this.valueShapes[currentRegion], + shape; + delete this.shapes[shapeid]; + switch (currentRegion.substr(0, 1)) { + case 'r': + shape = this.renderRange(currentRegion.substr(1), highlight); + break; + case 'p': + shape = this.renderPerformance(highlight); + break; + case 't': + shape = this.renderTarget(highlight); + break; + } + this.valueShapes[currentRegion] = shape.id; + this.shapes[shape.id] = currentRegion; + this.target.replaceWithShape(shapeid, shape); + }, + + renderRange: function (rn, highlight) { + var rangeval = this.values[rn], + rangewidth = Math.round(this.canvasWidth * ((rangeval - this.min) / this.range)), + color = this.options.get('rangeColors')[rn - 2]; + if (highlight) { + color = this.calcHighlightColor(color, this.options); + } + return this.target.drawRect(0, 0, rangewidth - 1, this.canvasHeight - 1, color, color); + }, + + renderPerformance: function (highlight) { + var perfval = this.values[1], + perfwidth = Math.round(this.canvasWidth * ((perfval - this.min) / this.range)), + color = this.options.get('performanceColor'); + if (highlight) { + color = this.calcHighlightColor(color, this.options); + } + return this.target.drawRect(0, Math.round(this.canvasHeight * 0.3), perfwidth - 1, + Math.round(this.canvasHeight * 0.4) - 1, color, color); + }, + + renderTarget: function (highlight) { + var targetval = this.values[0], + x = Math.round(this.canvasWidth * ((targetval - this.min) / this.range) - (this.options.get('targetWidth') / 2)), + targettop = Math.round(this.canvasHeight * 0.10), + targetheight = this.canvasHeight - (targettop * 2), + color = this.options.get('targetColor'); + if (highlight) { + color = this.calcHighlightColor(color, this.options); + } + return this.target.drawRect(x, targettop, this.options.get('targetWidth') - 1, targetheight - 1, color, color); + }, + + render: function () { + var vlen = this.values.length, + target = this.target, + i, shape; + if (!bullet._super.render.call(this)) { + return; + } + for (i = 2; i < vlen; i++) { + shape = this.renderRange(i).append(); + this.shapes[shape.id] = 'r' + i; + this.valueShapes['r' + i] = shape.id; + } + if (this.values[1] !== null) { + shape = this.renderPerformance().append(); + this.shapes[shape.id] = 'p1'; + this.valueShapes.p1 = shape.id; + } + if (this.values[0] !== null) { + shape = this.renderTarget().append(); + this.shapes[shape.id] = 't0'; + this.valueShapes.t0 = shape.id; + } + target.render(); + } + }); + + /** + * Pie charts + */ + $.fn.sparkline.pie = pie = createClass($.fn.sparkline._base, { + type: 'pie', + + init: function (el, values, options, width, height) { + var total = 0, i; + + pie._super.init.call(this, el, values, options, width, height); + + this.shapes = {}; // map shape ids to value offsets + this.valueShapes = {}; // maps value offsets to shape ids + this.values = values = $.map(values, Number); + + if (options.get('width') === 'auto') { + this.width = this.height; + } + + if (values.length > 0) { + for (i = values.length; i--;) { + total += values[i]; + } + } + this.total = total; + this.initTarget(); + this.radius = Math.floor(Math.min(this.canvasWidth, this.canvasHeight) / 2); + }, + + getRegion: function (el, x, y) { + var shapeid = this.target.getShapeAt(el, x, y); + return (shapeid !== undefined && this.shapes[shapeid] !== undefined) ? this.shapes[shapeid] : undefined; + }, + + getCurrentRegionFields: function () { + var currentRegion = this.currentRegion; + return { + isNull: this.values[currentRegion] === undefined, + value: this.values[currentRegion], + percent: this.values[currentRegion] / this.total * 100, + color: this.options.get('sliceColors')[currentRegion % this.options.get('sliceColors').length], + offset: currentRegion + }; + }, + + changeHighlight: function (highlight) { + var currentRegion = this.currentRegion, + newslice = this.renderSlice(currentRegion, highlight), + shapeid = this.valueShapes[currentRegion]; + delete this.shapes[shapeid]; + this.target.replaceWithShape(shapeid, newslice); + this.valueShapes[currentRegion] = newslice.id; + this.shapes[newslice.id] = currentRegion; + }, + + renderSlice: function (valuenum, highlight) { + var target = this.target, + options = this.options, + radius = this.radius, + borderWidth = options.get('borderWidth'), + offset = options.get('offset'), + circle = 2 * Math.PI, + values = this.values, + total = this.total, + next = offset ? (2*Math.PI)*(offset/360) : 0, + start, end, i, vlen, color; + + vlen = values.length; + for (i = 0; i < vlen; i++) { + start = next; + end = next; + if (total > 0) { // avoid divide by zero + end = next + (circle * (values[i] / total)); + } + if (valuenum === i) { + color = options.get('sliceColors')[i % options.get('sliceColors').length]; + if (highlight) { + color = this.calcHighlightColor(color, options); + } + + return target.drawPieSlice(radius, radius, radius - borderWidth, start, end, undefined, color); + } + next = end; + } + }, + + render: function () { + var target = this.target, + values = this.values, + options = this.options, + radius = this.radius, + borderWidth = options.get('borderWidth'), + shape, i; + + if (!pie._super.render.call(this)) { + return; + } + if (borderWidth) { + target.drawCircle(radius, radius, Math.floor(radius - (borderWidth / 2)), + options.get('borderColor'), undefined, borderWidth).append(); + } + for (i = values.length; i--;) { + if (values[i]) { // don't render zero values + shape = this.renderSlice(i).append(); + this.valueShapes[i] = shape.id; // store just the shapeid + this.shapes[shape.id] = i; + } + } + target.render(); + } + }); + + /** + * Box plots + */ + $.fn.sparkline.box = box = createClass($.fn.sparkline._base, { + type: 'box', + + init: function (el, values, options, width, height) { + box._super.init.call(this, el, values, options, width, height); + this.values = $.map(values, Number); + this.width = options.get('width') === 'auto' ? '4.0em' : width; + this.initTarget(); + if (!this.values.length) { + this.disabled = 1; + } + }, + + /** + * Simulate a single region + */ + getRegion: function () { + return 1; + }, + + getCurrentRegionFields: function () { + var result = [ + { field: 'lq', value: this.quartiles[0] }, + { field: 'med', value: this.quartiles[1] }, + { field: 'uq', value: this.quartiles[2] } + ]; + if (this.loutlier !== undefined) { + result.push({ field: 'lo', value: this.loutlier}); + } + if (this.routlier !== undefined) { + result.push({ field: 'ro', value: this.routlier}); + } + if (this.lwhisker !== undefined) { + result.push({ field: 'lw', value: this.lwhisker}); + } + if (this.rwhisker !== undefined) { + result.push({ field: 'rw', value: this.rwhisker}); + } + return result; + }, + + render: function () { + var target = this.target, + values = this.values, + vlen = values.length, + options = this.options, + canvasWidth = this.canvasWidth, + canvasHeight = this.canvasHeight, + minValue = options.get('chartRangeMin') === undefined ? Math.min.apply(Math, values) : options.get('chartRangeMin'), + maxValue = options.get('chartRangeMax') === undefined ? Math.max.apply(Math, values) : options.get('chartRangeMax'), + canvasLeft = 0, + lwhisker, loutlier, iqr, q1, q2, q3, rwhisker, routlier, i, + size, unitSize; + + if (!box._super.render.call(this)) { + return; + } + + if (options.get('raw')) { + if (options.get('showOutliers') && values.length > 5) { + loutlier = values[0]; + lwhisker = values[1]; + q1 = values[2]; + q2 = values[3]; + q3 = values[4]; + rwhisker = values[5]; + routlier = values[6]; + } else { + lwhisker = values[0]; + q1 = values[1]; + q2 = values[2]; + q3 = values[3]; + rwhisker = values[4]; + } + } else { + values.sort(function (a, b) { return a - b; }); + q1 = quartile(values, 1); + q2 = quartile(values, 2); + q3 = quartile(values, 3); + iqr = q3 - q1; + if (options.get('showOutliers')) { + lwhisker = rwhisker = undefined; + for (i = 0; i < vlen; i++) { + if (lwhisker === undefined && values[i] > q1 - (iqr * options.get('outlierIQR'))) { + lwhisker = values[i]; + } + if (values[i] < q3 + (iqr * options.get('outlierIQR'))) { + rwhisker = values[i]; + } + } + loutlier = values[0]; + routlier = values[vlen - 1]; + } else { + lwhisker = values[0]; + rwhisker = values[vlen - 1]; + } + } + this.quartiles = [q1, q2, q3]; + this.lwhisker = lwhisker; + this.rwhisker = rwhisker; + this.loutlier = loutlier; + this.routlier = routlier; + + unitSize = canvasWidth / (maxValue - minValue + 1); + if (options.get('showOutliers')) { + canvasLeft = Math.ceil(options.get('spotRadius')); + canvasWidth -= 2 * Math.ceil(options.get('spotRadius')); + unitSize = canvasWidth / (maxValue - minValue + 1); + if (loutlier < lwhisker) { + target.drawCircle((loutlier - minValue) * unitSize + canvasLeft, + canvasHeight / 2, + options.get('spotRadius'), + options.get('outlierLineColor'), + options.get('outlierFillColor')).append(); + } + if (routlier > rwhisker) { + target.drawCircle((routlier - minValue) * unitSize + canvasLeft, + canvasHeight / 2, + options.get('spotRadius'), + options.get('outlierLineColor'), + options.get('outlierFillColor')).append(); + } + } + + // box + target.drawRect( + Math.round((q1 - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight * 0.1), + Math.round((q3 - q1) * unitSize), + Math.round(canvasHeight * 0.8), + options.get('boxLineColor'), + options.get('boxFillColor')).append(); + // left whisker + target.drawLine( + Math.round((lwhisker - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight / 2), + Math.round((q1 - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight / 2), + options.get('lineColor')).append(); + target.drawLine( + Math.round((lwhisker - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight / 4), + Math.round((lwhisker - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight - canvasHeight / 4), + options.get('whiskerColor')).append(); + // right whisker + target.drawLine(Math.round((rwhisker - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight / 2), + Math.round((q3 - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight / 2), + options.get('lineColor')).append(); + target.drawLine( + Math.round((rwhisker - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight / 4), + Math.round((rwhisker - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight - canvasHeight / 4), + options.get('whiskerColor')).append(); + // median line + target.drawLine( + Math.round((q2 - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight * 0.1), + Math.round((q2 - minValue) * unitSize + canvasLeft), + Math.round(canvasHeight * 0.9), + options.get('medianColor')).append(); + if (options.get('target')) { + size = Math.ceil(options.get('spotRadius')); + target.drawLine( + Math.round((options.get('target') - minValue) * unitSize + canvasLeft), + Math.round((canvasHeight / 2) - size), + Math.round((options.get('target') - minValue) * unitSize + canvasLeft), + Math.round((canvasHeight / 2) + size), + options.get('targetColor')).append(); + target.drawLine( + Math.round((options.get('target') - minValue) * unitSize + canvasLeft - size), + Math.round(canvasHeight / 2), + Math.round((options.get('target') - minValue) * unitSize + canvasLeft + size), + Math.round(canvasHeight / 2), + options.get('targetColor')).append(); + } + target.render(); + } + }); + + // Setup a very simple "virtual canvas" to make drawing the few shapes we need easier + // This is accessible as $(foo).simpledraw() + + // Detect browser renderer support + (function() { + if (document.namespaces && !document.namespaces.v) { + $.fn.sparkline.hasVML = true; + document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML'); + } else { + $.fn.sparkline.hasVML = false; + } + + var el = document.createElement('canvas'); + $.fn.sparkline.hasCanvas = !!(el.getContext && el.getContext('2d')); + + })() + + VShape = createClass({ + init: function (target, id, type, args) { + this.target = target; + this.id = id; + this.type = type; + this.args = args; + }, + append: function () { + this.target.appendShape(this); + return this; + } + }); + + VCanvas_base = createClass({ + _pxregex: /(\d+)(px)?\s*$/i, + + init: function (width, height, target) { + if (!width) { + return; + } + this.width = width; + this.height = height; + this.target = target; + this.lastShapeId = null; + if (target[0]) { + target = target[0]; + } + $.data(target, '_jqs_vcanvas', this); + }, + + drawLine: function (x1, y1, x2, y2, lineColor, lineWidth) { + return this.drawShape([[x1, y1], [x2, y2]], lineColor, lineWidth); + }, + + drawShape: function (path, lineColor, fillColor, lineWidth) { + return this._genShape('Shape', [path, lineColor, fillColor, lineWidth]); + }, + + drawCircle: function (x, y, radius, lineColor, fillColor, lineWidth) { + return this._genShape('Circle', [x, y, radius, lineColor, fillColor, lineWidth]); + }, + + drawPieSlice: function (x, y, radius, startAngle, endAngle, lineColor, fillColor) { + return this._genShape('PieSlice', [x, y, radius, startAngle, endAngle, lineColor, fillColor]); + }, + + drawRect: function (x, y, width, height, lineColor, fillColor) { + return this._genShape('Rect', [x, y, width, height, lineColor, fillColor]); + }, + + getElement: function () { + return this.canvas; + }, + + /** + * Return the most recently inserted shape id + */ + getLastShapeId: function () { + return this.lastShapeId; + }, + + /** + * Clear and reset the canvas + */ + reset: function () { + alert('reset not implemented'); + }, + + _insert: function (el, target) { + $(target).html(el); + }, + + /** + * Calculate the pixel dimensions of the canvas + */ + _calculatePixelDims: function (width, height, canvas) { + // XXX This should probably be a configurable option + var match; + match = this._pxregex.exec(height); + if (match) { + this.pixelHeight = match[1]; + } else { + this.pixelHeight = $(canvas).height(); + } + match = this._pxregex.exec(width); + if (match) { + this.pixelWidth = match[1]; + } else { + this.pixelWidth = $(canvas).width(); + } + }, + + /** + * Generate a shape object and id for later rendering + */ + _genShape: function (shapetype, shapeargs) { + var id = shapeCount++; + shapeargs.unshift(id); + return new VShape(this, id, shapetype, shapeargs); + }, + + /** + * Add a shape to the end of the render queue + */ + appendShape: function (shape) { + alert('appendShape not implemented'); + }, + + /** + * Replace one shape with another + */ + replaceWithShape: function (shapeid, shape) { + alert('replaceWithShape not implemented'); + }, + + /** + * Insert one shape after another in the render queue + */ + insertAfterShape: function (shapeid, shape) { + alert('insertAfterShape not implemented'); + }, + + /** + * Remove a shape from the queue + */ + removeShapeId: function (shapeid) { + alert('removeShapeId not implemented'); + }, + + /** + * Find a shape at the specified x/y co-ordinates + */ + getShapeAt: function (el, x, y) { + alert('getShapeAt not implemented'); + }, + + /** + * Render all queued shapes onto the canvas + */ + render: function () { + alert('render not implemented'); + } + }); + + VCanvas_canvas = createClass(VCanvas_base, { + init: function (width, height, target, interact) { + VCanvas_canvas._super.init.call(this, width, height, target); + this.canvas = document.createElement('canvas'); + if (target[0]) { + target = target[0]; + } + $.data(target, '_jqs_vcanvas', this); + $(this.canvas).css({ display: 'inline-block', width: width, height: height, verticalAlign: 'top' }); + this._insert(this.canvas, target); + this._calculatePixelDims(width, height, this.canvas); + this.canvas.width = this.pixelWidth; + this.canvas.height = this.pixelHeight; + this.interact = interact; + this.shapes = {}; + this.shapeseq = []; + this.currentTargetShapeId = undefined; + $(this.canvas).css({width: this.pixelWidth, height: this.pixelHeight}); + }, + + _getContext: function (lineColor, fillColor, lineWidth) { + var context = this.canvas.getContext('2d'); + if (lineColor !== undefined) { + context.strokeStyle = lineColor; + } + context.lineWidth = lineWidth === undefined ? 1 : lineWidth; + if (fillColor !== undefined) { + context.fillStyle = fillColor; + } + return context; + }, + + reset: function () { + var context = this._getContext(); + context.clearRect(0, 0, this.pixelWidth, this.pixelHeight); + this.shapes = {}; + this.shapeseq = []; + this.currentTargetShapeId = undefined; + }, + + _drawShape: function (shapeid, path, lineColor, fillColor, lineWidth) { + var context = this._getContext(lineColor, fillColor, lineWidth), + i, plen; + context.beginPath(); + context.moveTo(path[0][0] + 0.5, path[0][1] + 0.5); + for (i = 1, plen = path.length; i < plen; i++) { + context.lineTo(path[i][0] + 0.5, path[i][1] + 0.5); // the 0.5 offset gives us crisp pixel-width lines + } + if (lineColor !== undefined) { + context.stroke(); + } + if (fillColor !== undefined) { + context.fill(); + } + if (this.targetX !== undefined && this.targetY !== undefined && + context.isPointInPath(this.targetX, this.targetY)) { + this.currentTargetShapeId = shapeid; + } + }, + + _drawCircle: function (shapeid, x, y, radius, lineColor, fillColor, lineWidth) { + var context = this._getContext(lineColor, fillColor, lineWidth); + context.beginPath(); + context.arc(x, y, radius, 0, 2 * Math.PI, false); + if (this.targetX !== undefined && this.targetY !== undefined && + context.isPointInPath(this.targetX, this.targetY)) { + this.currentTargetShapeId = shapeid; + } + if (lineColor !== undefined) { + context.stroke(); + } + if (fillColor !== undefined) { + context.fill(); + } + }, + + _drawPieSlice: function (shapeid, x, y, radius, startAngle, endAngle, lineColor, fillColor) { + var context = this._getContext(lineColor, fillColor); + context.beginPath(); + context.moveTo(x, y); + context.arc(x, y, radius, startAngle, endAngle, false); + context.lineTo(x, y); + context.closePath(); + if (lineColor !== undefined) { + context.stroke(); + } + if (fillColor) { + context.fill(); + } + if (this.targetX !== undefined && this.targetY !== undefined && + context.isPointInPath(this.targetX, this.targetY)) { + this.currentTargetShapeId = shapeid; + } + }, + + _drawRect: function (shapeid, x, y, width, height, lineColor, fillColor) { + return this._drawShape(shapeid, [[x, y], [x + width, y], [x + width, y + height], [x, y + height], [x, y]], lineColor, fillColor); + }, + + appendShape: function (shape) { + this.shapes[shape.id] = shape; + this.shapeseq.push(shape.id); + this.lastShapeId = shape.id; + return shape.id; + }, + + replaceWithShape: function (shapeid, shape) { + var shapeseq = this.shapeseq, + i; + this.shapes[shape.id] = shape; + for (i = shapeseq.length; i--;) { + if (shapeseq[i] == shapeid) { + shapeseq[i] = shape.id; + } + } + delete this.shapes[shapeid]; + }, + + replaceWithShapes: function (shapeids, shapes) { + var shapeseq = this.shapeseq, + shapemap = {}, + sid, i, first; + + for (i = shapeids.length; i--;) { + shapemap[shapeids[i]] = true; + } + for (i = shapeseq.length; i--;) { + sid = shapeseq[i]; + if (shapemap[sid]) { + shapeseq.splice(i, 1); + delete this.shapes[sid]; + first = i; + } + } + for (i = shapes.length; i--;) { + shapeseq.splice(first, 0, shapes[i].id); + this.shapes[shapes[i].id] = shapes[i]; + } + + }, + + insertAfterShape: function (shapeid, shape) { + var shapeseq = this.shapeseq, + i; + for (i = shapeseq.length; i--;) { + if (shapeseq[i] === shapeid) { + shapeseq.splice(i + 1, 0, shape.id); + this.shapes[shape.id] = shape; + return; + } + } + }, + + removeShapeId: function (shapeid) { + var shapeseq = this.shapeseq, + i; + for (i = shapeseq.length; i--;) { + if (shapeseq[i] === shapeid) { + shapeseq.splice(i, 1); + break; + } + } + delete this.shapes[shapeid]; + }, + + getShapeAt: function (el, x, y) { + this.targetX = x; + this.targetY = y; + this.render(); + return this.currentTargetShapeId; + }, + + render: function () { + var shapeseq = this.shapeseq, + shapes = this.shapes, + shapeCount = shapeseq.length, + context = this._getContext(), + shapeid, shape, i; + context.clearRect(0, 0, this.pixelWidth, this.pixelHeight); + for (i = 0; i < shapeCount; i++) { + shapeid = shapeseq[i]; + shape = shapes[shapeid]; + this['_draw' + shape.type].apply(this, shape.args); + } + if (!this.interact) { + // not interactive so no need to keep the shapes array + this.shapes = {}; + this.shapeseq = []; + } + } + + }); + + VCanvas_vml = createClass(VCanvas_base, { + init: function (width, height, target) { + var groupel; + VCanvas_vml._super.init.call(this, width, height, target); + if (target[0]) { + target = target[0]; + } + $.data(target, '_jqs_vcanvas', this); + this.canvas = document.createElement('span'); + $(this.canvas).css({ display: 'inline-block', position: 'relative', overflow: 'hidden', width: width, height: height, margin: '0px', padding: '0px', verticalAlign: 'top'}); + this._insert(this.canvas, target); + this._calculatePixelDims(width, height, this.canvas); + this.canvas.width = this.pixelWidth; + this.canvas.height = this.pixelHeight; + groupel = ''; + this.canvas.insertAdjacentHTML('beforeEnd', groupel); + this.group = $(this.canvas).children()[0]; + this.rendered = false; + this.prerender = ''; + }, + + _drawShape: function (shapeid, path, lineColor, fillColor, lineWidth) { + var vpath = [], + initial, stroke, fill, closed, vel, plen, i; + for (i = 0, plen = path.length; i < plen; i++) { + vpath[i] = '' + (path[i][0]) + ',' + (path[i][1]); + } + initial = vpath.splice(0, 1); + lineWidth = lineWidth === undefined ? 1 : lineWidth; + stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="' + lineWidth + 'px" strokeColor="' + lineColor + '" '; + fill = fillColor === undefined ? ' filled="false"' : ' fillColor="' + fillColor + '" filled="true" '; + closed = vpath[0] === vpath[vpath.length - 1] ? 'x ' : ''; + vel = '' + + ' '; + return vel; + }, + + _drawCircle: function (shapeid, x, y, radius, lineColor, fillColor, lineWidth) { + var stroke, fill, vel; + x -= radius; + y -= radius; + stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="' + lineWidth + 'px" strokeColor="' + lineColor + '" '; + fill = fillColor === undefined ? ' filled="false"' : ' fillColor="' + fillColor + '" filled="true" '; + vel = ''; + return vel; + + }, + + _drawPieSlice: function (shapeid, x, y, radius, startAngle, endAngle, lineColor, fillColor) { + var vpath, startx, starty, endx, endy, stroke, fill, vel; + if (startAngle === endAngle) { + return ''; // VML seems to have problem when start angle equals end angle. + } + if ((endAngle - startAngle) === (2 * Math.PI)) { + startAngle = 0.0; // VML seems to have a problem when drawing a full circle that doesn't start 0 + endAngle = (2 * Math.PI); + } + + startx = x + Math.round(Math.cos(startAngle) * radius); + starty = y + Math.round(Math.sin(startAngle) * radius); + endx = x + Math.round(Math.cos(endAngle) * radius); + endy = y + Math.round(Math.sin(endAngle) * radius); + + if (startx === endx && starty === endy) { + if ((endAngle - startAngle) < Math.PI) { + // Prevent very small slices from being mistaken as a whole pie + return ''; + } + // essentially going to be the entire circle, so ignore startAngle + startx = endx = x + radius; + starty = endy = y; + } + + if (startx === endx && starty === endy && (endAngle - startAngle) < Math.PI) { + return ''; + } + + vpath = [x - radius, y - radius, x + radius, y + radius, startx, starty, endx, endy]; + stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1px" strokeColor="' + lineColor + '" '; + fill = fillColor === undefined ? ' filled="false"' : ' fillColor="' + fillColor + '" filled="true" '; + vel = '' + + ' '; + return vel; + }, + + _drawRect: function (shapeid, x, y, width, height, lineColor, fillColor) { + return this._drawShape(shapeid, [[x, y], [x, y + height], [x + width, y + height], [x + width, y], [x, y]], lineColor, fillColor); + }, + + reset: function () { + this.group.innerHTML = ''; + }, + + appendShape: function (shape) { + var vel = this['_draw' + shape.type].apply(this, shape.args); + if (this.rendered) { + this.group.insertAdjacentHTML('beforeEnd', vel); + } else { + this.prerender += vel; + } + this.lastShapeId = shape.id; + return shape.id; + }, + + replaceWithShape: function (shapeid, shape) { + var existing = $('#jqsshape' + shapeid), + vel = this['_draw' + shape.type].apply(this, shape.args); + existing[0].outerHTML = vel; + }, + + replaceWithShapes: function (shapeids, shapes) { + // replace the first shapeid with all the new shapes then toast the remaining old shapes + var existing = $('#jqsshape' + shapeids[0]), + replace = '', + slen = shapes.length, + i; + for (i = 0; i < slen; i++) { + replace += this['_draw' + shapes[i].type].apply(this, shapes[i].args); + } + existing[0].outerHTML = replace; + for (i = 1; i < shapeids.length; i++) { + $('#jqsshape' + shapeids[i]).remove(); + } + }, + + insertAfterShape: function (shapeid, shape) { + var existing = $('#jqsshape' + shapeid), + vel = this['_draw' + shape.type].apply(this, shape.args); + existing[0].insertAdjacentHTML('afterEnd', vel); + }, + + removeShapeId: function (shapeid) { + var existing = $('#jqsshape' + shapeid); + this.group.removeChild(existing[0]); + }, + + getShapeAt: function (el, x, y) { + var shapeid = el.id.substr(8); + return shapeid; + }, + + render: function () { + if (!this.rendered) { + // batch the intial render into a single repaint + this.group.innerHTML = this.prerender; + this.rendered = true; + } + } + }); + +})); diff --git a/addons/crm/static/src/css/crm.css b/addons/crm/static/src/css/crm.css new file mode 100644 index 00000000000..ba4473edc26 --- /dev/null +++ b/addons/crm/static/src/css/crm.css @@ -0,0 +1,64 @@ +.openerp .oe_kanban_view .oe_kanban_crm_salesteams { + width: 345px; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_avatars { + text-align: right; + margin: -5px 0 -10px 0; +} + +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_avatars img { + width: 30px; + height: 30px; + padding-left: 0px; + margin-top: 3px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); + -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); +} + +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list { + position: relative; + margin: 10px; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list div { + width: 160px; + height: 22px; + margin: 0 !important; + position: relative; + display: inline-block; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list a:hover { + text-decoration: underline !important; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list div a:nth-child(2n) { + position: absolute; + left: 90px; + top: 0; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list div:nth-child(2n) a:nth-child(2n) { + left: 110px; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center { + text-align: center; + margin: 3px 0; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center .oe_sum { + margin: 0; + font-size: 40px; +} +.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center .oe_subsum { + font-size: 10px; +} + +.openerp .oe_kanban_view .oe_justgage { + color: black; + display: inline-block; +} + +.openerp .oe_kanban_view .oe_sparkline_bar { + height: 20px; + width: 36px; +} \ No newline at end of file diff --git a/addons/crm/static/src/js/crm_case_section.js b/addons/crm/static/src/js/crm_case_section.js new file mode 100644 index 00000000000..2b4ca741d75 --- /dev/null +++ b/addons/crm/static/src/js/crm_case_section.js @@ -0,0 +1,34 @@ +openerp.crm = function(openerp) { + openerp.web_kanban.KanbanRecord.include({ + on_card_clicked: function() { + if (this.view.dataset.model === 'crm.case.section') { + this.$('.oe_kanban_crm_salesteams_list a').first().click(); + } else { + this._super.apply(this, arguments); + } + }, + }); + + openerp.crm.SparklineBarWidget = openerp.web_kanban.AbstractField.extend({ + className: "oe_sparkline_bar", + start: function() { + var self = this; + var title = this.$node.html(); + setTimeout(function () { + var value = _.pluck(self.field.value, 'value'); + var tooltips = _.pluck(self.field.value, 'tooltip'); + self.$el.sparkline(value, { + type: 'bar', + barWidth: 5, + tooltipFormat: '{{offset:offset}} {{value}}', + tooltipValueLookups: { + 'offset': tooltips + }, + }); + self.$el.tipsy({'delayIn': 0, 'html': true, 'title': function(){return title}, 'gravity': 'n'}); + }, 0); + }, + }); + openerp.web_kanban.fields_registry.add("sparkline_bar", "openerp.crm.SparklineBarWidget"); + +}; diff --git a/addons/crm/test/crm_lead_cancel.yml b/addons/crm/test/crm_lead_cancel.yml index edaf844952a..8749675bf23 100644 --- a/addons/crm/test/crm_lead_cancel.yml +++ b/addons/crm/test/crm_lead_cancel.yml @@ -1,7 +1,9 @@ - - I cancel unqualified lead. + I set a new sale team (with Marketing at parent) and I cancel unqualified lead . - !python {model: crm.lead}: | + section_id = self.pool.get('crm.case.section').create(cr, uid, {'name': "Phone Marketing", 'parent_id': ref("crm.crm_case_section_2")}) + self.write(cr, uid, [ref("crm_case_1")], {'section_id': section_id}) self.case_cancel(cr, uid, [ref("crm_case_1")]) - I check cancelled lead. @@ -42,4 +44,4 @@ I check the lead is correctly escalated to the parent team. - !assert {model: crm.lead, id: crm.crm_case_1, string: Escalate lead to parent team}: - - section_id.name == "Support Department" + - section_id.name == "Marketing" diff --git a/addons/crm/test/crm_lead_message.yml b/addons/crm/test/crm_lead_message.yml index 221a4ab634f..0f7d4655398 100644 --- a/addons/crm/test/crm_lead_message.yml +++ b/addons/crm/test/crm_lead_message.yml @@ -4,8 +4,7 @@ Mail script will fetch his request from mail server. Then I process that mail after read EML file. - !python {model: mail.thread}: | - from openerp import addons - request_file = open(addons.get_module_resource('crm','test', 'customer_request.eml'),'rb') + request_file = open(openerp.modules.module.get_module_resource('crm','test', 'customer_request.eml'),'rb') request_message = request_file.read() self.message_process(cr, uid, 'crm.lead', request_message) - diff --git a/addons/crm/validate_email.py b/addons/crm/validate_email.py new file mode 100644 index 00000000000..38de5743fca --- /dev/null +++ b/addons/crm/validate_email.py @@ -0,0 +1,123 @@ +# RFC 2822 - style email validation for Python +# (c) 2012 Syrus Akbary +# Extended from (c) 2011 Noel Bush +# for support of mx and user check +# This code is made available to you under the GNU LGPL v3. +# +# This module provides a single method, valid_email_address(), +# which returns True or False to indicate whether a given address +# is valid according to the 'addr-spec' part of the specification +# given in RFC 2822. Ideally, we would like to find this +# in some other library, already thoroughly tested and well- +# maintained. The standard Python library email.utils +# contains a parse_addr() function, but it is not sufficient +# to detect many malformed addresses. +# +# This implementation aims to be faithful to the RFC, with the +# exception of a circular definition (see comments below), and +# with the omission of the pattern components marked as "obsolete". + +import re +import smtplib +import socket + +try: + import DNS + ServerError = DNS.ServerError +except: + DNS = None + class ServerError(Exception): pass +# All we are really doing is comparing the input string to one +# gigantic regular expression. But building that regexp, and +# ensuring its correctness, is made much easier by assembling it +# from the "tokens" defined by the RFC. Each of these tokens is +# tested in the accompanying unit test file. +# +# The section of RFC 2822 from which each pattern component is +# derived is given in an accompanying comment. +# +# (To make things simple, every string below is given as 'raw', +# even when it's not strictly necessary. This way we don't forget +# when it is necessary.) +# +WSP = r'[ \t]' # see 2.2.2. Structured Header Field Bodies +CRLF = r'(?:\r\n)' # see 2.2.3. Long Header Fields +NO_WS_CTL = r'\x01-\x08\x0b\x0c\x0f-\x1f\x7f' # see 3.2.1. Primitive Tokens +QUOTED_PAIR = r'(?:\\.)' # see 3.2.2. Quoted characters +FWS = r'(?:(?:' + WSP + r'*' + CRLF + r')?' + \ + WSP + r'+)' # see 3.2.3. Folding white space and comments +CTEXT = r'[' + NO_WS_CTL + \ + r'\x21-\x27\x2a-\x5b\x5d-\x7e]' # see 3.2.3 +CCONTENT = r'(?:' + CTEXT + r'|' + \ + QUOTED_PAIR + r')' # see 3.2.3 (NB: The RFC includes COMMENT here + # as well, but that would be circular.) +COMMENT = r'\((?:' + FWS + r'?' + CCONTENT + \ + r')*' + FWS + r'?\)' # see 3.2.3 +CFWS = r'(?:' + FWS + r'?' + COMMENT + ')*(?:' + \ + FWS + '?' + COMMENT + '|' + FWS + ')' # see 3.2.3 +ATEXT = r'[\w!#$%&\'\*\+\-/=\?\^`\{\|\}~]' # see 3.2.4. Atom +ATOM = CFWS + r'?' + ATEXT + r'+' + CFWS + r'?' # see 3.2.4 +DOT_ATOM_TEXT = ATEXT + r'+(?:\.' + ATEXT + r'+)*' # see 3.2.4 +DOT_ATOM = CFWS + r'?' + DOT_ATOM_TEXT + CFWS + r'?' # see 3.2.4 +QTEXT = r'[' + NO_WS_CTL + \ + r'\x21\x23-\x5b\x5d-\x7e]' # see 3.2.5. Quoted strings +QCONTENT = r'(?:' + QTEXT + r'|' + \ + QUOTED_PAIR + r')' # see 3.2.5 +QUOTED_STRING = CFWS + r'?' + r'"(?:' + FWS + \ + r'?' + QCONTENT + r')*' + FWS + \ + r'?' + r'"' + CFWS + r'?' +LOCAL_PART = r'(?:' + DOT_ATOM + r'|' + \ + QUOTED_STRING + r')' # see 3.4.1. Addr-spec specification +DTEXT = r'[' + NO_WS_CTL + r'\x21-\x5a\x5e-\x7e]' # see 3.4.1 +DCONTENT = r'(?:' + DTEXT + r'|' + \ + QUOTED_PAIR + r')' # see 3.4.1 +DOMAIN_LITERAL = CFWS + r'?' + r'\[' + \ + r'(?:' + FWS + r'?' + DCONTENT + \ + r')*' + FWS + r'?\]' + CFWS + r'?' # see 3.4.1 +DOMAIN = r'(?:' + DOT_ATOM + r'|' + \ + DOMAIN_LITERAL + r')' # see 3.4.1 +ADDR_SPEC = LOCAL_PART + r'@' + DOMAIN # see 3.4.1 + +# A valid address will match exactly the 3.4.1 addr-spec. +VALID_ADDRESS_REGEXP = '^' + ADDR_SPEC + '$' + +def validate_email(email, check_mx=False,verify=False): + + """Indicate whether the given string is a valid email address + according to the 'addr-spec' portion of RFC 2822 (see section + 3.4.1). Parts of the spec that are marked obsolete are *not* + included in this test, and certain arcane constructions that + depend on circular definitions in the spec may not pass, but in + general this should correctly identify any email address likely + to be in use as of 2011.""" + try: + assert re.match(VALID_ADDRESS_REGEXP, email) is not None + check_mx |= verify + if check_mx: + if not DNS: raise Exception('For check the mx records or check if the email exists you must have installed pyDNS python package') + DNS.DiscoverNameServers() + hostname = email[email.find('@')+1:] + mx_hosts = DNS.mxlookup(hostname) + for mx in mx_hosts: + try: + smtp = smtplib.SMTP() + smtp.connect(mx[1]) + if not verify: return True + status, _ = smtp.helo() + if status != 250: continue + smtp.mail('') + status, _ = smtp.rcpt(email) + if status != 250: return False + break + except smtplib.SMTPServerDisconnected: #Server not permits verify user + break + except smtplib.SMTPConnectError: + continue + except (AssertionError, ServerError): + return False + return True + +# import sys + +# sys.modules[__name__],sys.modules['validate_email_module'] = validate_email,sys.modules[__name__] +# from validate_email_module import * diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py index e67b7c0c7be..3c847ade42a 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity.py +++ b/addons/crm/wizard/crm_lead_to_opportunity.py @@ -86,7 +86,7 @@ class crm_lead2opportunity_partner(osv.osv_memory): lead_obj = self.pool.get('crm.lead') for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context): if lead.state in ['done', 'cancel']: - raise osv.except_osv(_("Warning !"), _("Closed/Cancelled leads cannot be converted into opportunities.")) + raise osv.except_osv(_("Warning!"), _("Closed/Cancelled leads cannot be converted into opportunities.")) return False def _convert_opportunity(self, cr, uid, ids, vals, context=None): diff --git a/addons/crm/wizard/crm_lead_to_opportunity_view.xml b/addons/crm/wizard/crm_lead_to_opportunity_view.xml index 00686de1c8e..4093df910d0 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity_view.xml +++ b/addons/crm/wizard/crm_lead_to_opportunity_view.xml @@ -22,7 +22,7 @@ - + @@ -68,13 +68,13 @@ - + - + diff --git a/addons/crm/wizard/crm_merge_opportunities_view.xml b/addons/crm/wizard/crm_merge_opportunities_view.xml index f68abeb8a52..919d83cb9a7 100644 --- a/addons/crm/wizard/crm_merge_opportunities_view.xml +++ b/addons/crm/wizard/crm_merge_opportunities_view.xml @@ -19,7 +19,7 @@ - +
diff --git a/addons/crm/wizard/crm_opportunity_to_phonecall.py b/addons/crm/wizard/crm_opportunity_to_phonecall.py index ee7ed1fc31f..bb1ac2fdce6 100644 --- a/addons/crm/wizard/crm_opportunity_to_phonecall.py +++ b/addons/crm/wizard/crm_opportunity_to_phonecall.py @@ -73,6 +73,5 @@ class crm_opportunity2phonecall(osv.osv_memory): action=data.action, context=context) return {'type': 'ir.actions.act_window_close'} -crm_opportunity2phonecall() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml b/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml index ad369448517..846d71d74da 100644 --- a/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml +++ b/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml @@ -23,7 +23,7 @@ - + diff --git a/addons/crm/wizard/crm_phonecall_to_meeting.py b/addons/crm/wizard/crm_phonecall_to_meeting.py index 4e21e01b834..105ab113a71 100644 --- a/addons/crm/wizard/crm_phonecall_to_meeting.py +++ b/addons/crm/wizard/crm_phonecall_to_meeting.py @@ -59,6 +59,5 @@ class crm_phonecall2meeting(osv.osv_memory): } return res -crm_phonecall2meeting() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/crm_phonecall_to_phonecall.py b/addons/crm/wizard/crm_phonecall_to_phonecall.py index d0bcd12dbb7..7e1da41a29f 100644 --- a/addons/crm/wizard/crm_phonecall_to_phonecall.py +++ b/addons/crm/wizard/crm_phonecall_to_phonecall.py @@ -96,6 +96,5 @@ class crm_phonecall2phonecall(osv.osv_memory): res.update({'partner_id': phonecall.partner_id and phonecall.partner_id.id or False}) return res -crm_phonecall2phonecall() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/crm_phonecall_to_phonecall_view.xml b/addons/crm/wizard/crm_phonecall_to_phonecall_view.xml index e2d25218749..812468b17e6 100644 --- a/addons/crm/wizard/crm_phonecall_to_phonecall_view.xml +++ b/addons/crm/wizard/crm_phonecall_to_phonecall_view.xml @@ -15,7 +15,7 @@ - +
-
-
- - - - diff --git a/addons/crm_claim/test/process/claim.yml b/addons/crm_claim/test/process/claim.yml index bacb073b4b9..a843372956e 100644 --- a/addons/crm_claim/test/process/claim.yml +++ b/addons/crm_claim/test/process/claim.yml @@ -4,8 +4,7 @@ Mail script will be fetched him request from mail server. so I process that mail after read EML file - !python {model: mail.thread}: | - from openerp import addons - request_file = open(addons.get_module_resource('crm_claim','test', 'customer_claim.eml'),'rb') + request_file = open(openerp.modules.module.get_module_resource('crm_claim','test', 'customer_claim.eml'),'rb') request_message = request_file.read() self.message_process(cr, uid, 'crm.claim', request_message) - diff --git a/addons/crm_helpdesk/crm_helpdesk_view.xml b/addons/crm_helpdesk/crm_helpdesk_view.xml index 6c0e3433afe..f97fe654166 100644 --- a/addons/crm_helpdesk/crm_helpdesk_view.xml +++ b/addons/crm_helpdesk/crm_helpdesk_view.xml @@ -48,7 +48,7 @@ - + @@ -115,7 +115,7 @@ - + @@ -151,14 +151,14 @@ - + help="Helpdesk requests that are assigned to me or to one of the sale teams I manage" groups="base.group_multi_salesteams"/> + - + - + diff --git a/addons/crm_helpdesk/i18n/ru.po b/addons/crm_helpdesk/i18n/ru.po index e8eb90af9d7..bb53c03294f 100644 --- a/addons/crm_helpdesk/i18n/ru.po +++ b/addons/crm_helpdesk/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-10-24 05:08+0000\n" +"PO-Revision-Date: 2013-05-30 14:09+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:46+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-05-31 05:38+0000\n" +"X-Generator: Launchpad (build 16660)\n" #. module: crm_helpdesk #: field:crm.helpdesk.report,delay_close:0 @@ -46,7 +46,7 @@ msgstr "Март" #. module: crm_helpdesk #: field:crm.helpdesk,message_unread:0 msgid "Unread Messages" -msgstr "" +msgstr "Непрочитанные" #. module: crm_helpdesk #: field:crm.helpdesk,company_id:0 @@ -63,7 +63,7 @@ msgstr "Адреса наблюдателей" #. module: crm_helpdesk #: view:crm.helpdesk.report:0 msgid "Salesperson" -msgstr "" +msgstr "Продавец" #. module: crm_helpdesk #: selection:crm.helpdesk,priority:0 @@ -106,7 +106,7 @@ msgstr "Отменено" #. module: crm_helpdesk #: help:crm.helpdesk,message_unread:0 msgid "If checked new messages require your attention." -msgstr "" +msgstr "Если отмечено, новые сообщения требуют вашего внимания." #. module: crm_helpdesk #: model:ir.actions.act_window,name:crm_helpdesk.action_report_crm_helpdesk @@ -136,6 +136,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: crm_helpdesk #: view:crm.helpdesk:0 @@ -176,7 +178,7 @@ msgstr "Приоритет" #. module: crm_helpdesk #: field:crm.helpdesk,message_follower_ids:0 msgid "Followers" -msgstr "" +msgstr "Подписчики" #. module: crm_helpdesk #: view:crm.helpdesk:0 @@ -400,7 +402,7 @@ msgstr "В ожидании" #: view:crm.helpdesk.report:0 #: field:crm.helpdesk.report,state:0 msgid "Status" -msgstr "" +msgstr "Статус" #. module: crm_helpdesk #: selection:crm.helpdesk.report,month:0 @@ -454,7 +456,7 @@ msgstr "Планируемая выручка" #. module: crm_helpdesk #: field:crm.helpdesk,message_is_follower:0 msgid "Is a Follower" -msgstr "" +msgstr "Подписан" #. module: crm_helpdesk #: field:crm.helpdesk.report,user_id:0 @@ -501,7 +503,7 @@ msgstr "Январь" #. module: crm_helpdesk #: field:crm.helpdesk,message_summary:0 msgid "Summary" -msgstr "" +msgstr "Итог" #. module: crm_helpdesk #: view:crm.helpdesk:0 @@ -517,7 +519,7 @@ msgstr "Прочее" #. module: crm_helpdesk #: view:crm.helpdesk.report:0 msgid "My Company" -msgstr "" +msgstr "Моя компания" #. module: crm_helpdesk #: view:crm.helpdesk:0 @@ -666,7 +668,7 @@ msgstr "" #. module: crm_helpdesk #: help:crm.helpdesk,message_ids:0 msgid "Messages and communication history" -msgstr "" +msgstr "Сообщения и история общения" #. module: crm_helpdesk #: model:ir.actions.act_window,help:crm_helpdesk.crm_helpdesk_categ_action diff --git a/addons/crm_helpdesk/i18n/zh_CN.po b/addons/crm_helpdesk/i18n/zh_CN.po index 4a80e7f9385..7c8275f606a 100644 --- a/addons/crm_helpdesk/i18n/zh_CN.po +++ b/addons/crm_helpdesk/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: 2012-12-14 13:33+0000\n" -"Last-Translator: 盈通 ccdos \n" +"PO-Revision-Date: 2013-06-07 05:02+0000\n" +"Last-Translator: PeterGao <306739889@qq.com>\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-03-16 05:46+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-06-07 05:48+0000\n" +"X-Generator: Launchpad (build 16667)\n" #. module: crm_helpdesk #: field:crm.helpdesk.report,delay_close:0 @@ -656,6 +656,12 @@ msgid "" " \n" "If the case needs to be reviewed then the status is set to 'Pending'." msgstr "" +"当一个“case(事件)\"被新创建后,这个“case(事件)\"的状态为“草稿”状态。 " +" \n" +"若这个“case(事件)\"正在处理中,这个“case(事件)\"的状态为“开启”状态。\n" +"若这个“case(事件)\"已处理完结,这个“case(事件)\"的状态为“结单”状态。 " +" \n" +"若这个“case(事件)\"需暂停再议,这个“case(事件)\"的状态为“挂起”状态。" #. module: crm_helpdesk #: help:crm.helpdesk,message_ids:0 diff --git a/addons/crm_helpdesk/report/crm_helpdesk_report.py b/addons/crm_helpdesk/report/crm_helpdesk_report.py index 8d535fa07a0..8b54e30ddd3 100644 --- a/addons/crm_helpdesk/report/crm_helpdesk_report.py +++ b/addons/crm_helpdesk/report/crm_helpdesk_report.py @@ -108,6 +108,5 @@ class crm_helpdesk_report(osv.osv): c.categ_id,c.channel_id,c.planned_cost,c.id )""") -crm_helpdesk_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml index 05f502656d2..c1ffc00303d 100644 --- a/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml +++ b/addons/crm_helpdesk/report/crm_helpdesk_report_view.xml @@ -11,7 +11,7 @@ - + @@ -56,12 +56,13 @@ - + - + + @@ -70,7 +71,7 @@ - + diff --git a/addons/crm_helpdesk/test/customer_question.eml b/addons/crm_helpdesk/test/customer_question.eml index 38a4c95fb0c..9bc7c91cb41 100644 --- a/addons/crm_helpdesk/test/customer_question.eml +++ b/addons/crm_helpdesk/test/customer_question.eml @@ -3,7 +3,7 @@ Date: Tue, 25 Oct 2011 13:41:17 +0530 From: Mr. John Right User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110223 Lightning/1.0b2 Thunderbird/3.1.8 MIME-Version: 1.0 -To: info@my.com +To: _helpdesk@my.com Subject: Where is download link of user manual of your product ? Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit diff --git a/addons/crm_helpdesk/test/process/help-desk.yml b/addons/crm_helpdesk/test/process/help-desk.yml index e2be4a64ca3..95536b1c8dd 100644 --- a/addons/crm_helpdesk/test/process/help-desk.yml +++ b/addons/crm_helpdesk/test/process/help-desk.yml @@ -4,8 +4,7 @@ Mail script will be fetched him request from mail server. so I process that mail after read EML file - !python {model: mail.thread}: | - from openerp import addons - request_file = open(addons.get_module_resource('crm_helpdesk','test', 'customer_question.eml'),'rb') + request_file = open(openerp.modules.module.get_module_resource('crm_helpdesk','test', 'customer_question.eml'),'rb') request_message = request_file.read() self.message_process(cr, uid, 'crm.helpdesk', request_message) - diff --git a/addons/crm_partner_assign/i18n/ru.po b/addons/crm_partner_assign/i18n/ru.po index f0a7ff509c9..fa995c8e7a1 100644 --- a/addons/crm_partner_assign/i18n/ru.po +++ b/addons/crm_partner_assign/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: 2011-03-23 13:46+0000\n" +"PO-Revision-Date: 2013-06-06 10:24+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:47+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-06-07 05:48+0000\n" +"X-Generator: Launchpad (build 16667)\n" #. module: crm_partner_assign #: field:crm.lead.report.assign,delay_close:0 @@ -25,7 +25,7 @@ msgstr "Задержка закрытия" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,author_id:0 msgid "Author" -msgstr "" +msgstr "Автор" #. module: crm_partner_assign #: field:crm.lead.report.assign,planned_revenue:0 @@ -38,6 +38,9 @@ msgid "" "Message type: email for email message, notification for system message, " "comment for other messages such as user replies" msgstr "" +"Тип сообщения: эл. почта - для эл. почты, уведомление - для системных " +"сообщений, комментарий - для остальных сообщений таких как сообщения " +"пользователя" #. module: crm_partner_assign #: field:crm.lead.report.assign,nbr:0 @@ -53,7 +56,7 @@ msgstr "Группировать по ..." #. module: crm_partner_assign #: help:crm.lead.forward.to.partner,body:0 msgid "Automatically sanitized HTML contents" -msgstr "" +msgstr "Автоматически обработанное HTML содержимое" #. module: crm_partner_assign #: view:crm.lead:0 @@ -68,7 +71,7 @@ msgstr "Геолоцировать" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,starred:0 msgid "Starred" -msgstr "" +msgstr "Отмеченные" #. module: crm_partner_assign #: view:crm.lead.forward.to.partner:0 @@ -81,6 +84,8 @@ msgid "" "Email address of the sender. This field is set when no matching partner is " "found for incoming emails." msgstr "" +"Адрес эл. почты отправителя. Это поле устанавливается когда партнер не " +"определен для входящих писем." #. module: crm_partner_assign #: view:crm.partner.report.assign:0 @@ -111,7 +116,7 @@ msgstr "Компания" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,notification_ids:0 msgid "Notifications" -msgstr "" +msgstr "Уведомления" #. module: crm_partner_assign #: field:crm.lead.report.assign,date_assign:0 @@ -123,7 +128,7 @@ msgstr "Дата партнера" #: view:crm.partner.report.assign:0 #: view:res.partner:0 msgid "Salesperson" -msgstr "" +msgstr "Продавец" #. module: crm_partner_assign #: selection:crm.lead.report.assign,priority:0 @@ -170,12 +175,12 @@ msgstr "Географическое назначение" #. module: crm_partner_assign #: model:ir.model,name:crm_partner_assign.model_crm_lead_forward_to_partner msgid "Email composition wizard" -msgstr "" +msgstr "Мастер составления эл. почты" #. module: crm_partner_assign #: field:crm.partner.report.assign,turnover:0 msgid "Turnover" -msgstr "" +msgstr "Оборот" #. module: crm_partner_assign #: field:crm.lead.report.assign,date_closed:0 @@ -199,7 +204,7 @@ msgstr "" #. module: crm_partner_assign #: selection:crm.lead.forward.to.partner,type:0 msgid "System notification" -msgstr "" +msgstr "Системное уведомление" #. module: crm_partner_assign #: code:addons/crm_partner_assign/wizard/crm_forward_to_partner.py:74 @@ -271,7 +276,7 @@ msgstr "Тип" #. module: crm_partner_assign #: selection:crm.lead.forward.to.partner,type:0 msgid "Email" -msgstr "" +msgstr "Эл. почта" #. module: crm_partner_assign #: help:crm.lead,partner_assigned_id:0 @@ -286,7 +291,7 @@ msgstr "Низший" #. module: crm_partner_assign #: view:crm.partner.report.assign:0 msgid "Date Invoice" -msgstr "" +msgstr "Дата счета" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,template_id:0 @@ -311,12 +316,12 @@ msgstr "Дата создания" #. module: crm_partner_assign #: model:ir.model,name:crm_partner_assign.model_res_partner_activation msgid "res.partner.activation" -msgstr "" +msgstr "res.partner.activation" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,parent_id:0 msgid "Parent Message" -msgstr "" +msgstr "Родительское сообщение" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,res_id:0 @@ -358,12 +363,12 @@ msgstr "Этап" #: view:crm.lead.report.assign:0 #: field:crm.lead.report.assign,state:0 msgid "Status" -msgstr "" +msgstr "Статус" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,to_read:0 msgid "To read" -msgstr "" +msgstr "Прочитать" #. module: crm_partner_assign #: code:addons/crm_partner_assign/wizard/crm_forward_to_partner.py:74 @@ -418,12 +423,12 @@ msgstr "Количество дней, для закрытия вопроса" #: help:crm.lead.forward.to.partner,notified_partner_ids:0 msgid "" "Partners that have a notification pushing this message in their mailboxes" -msgstr "" +msgstr "Партнеры которые имеют уведомление доставляемое в их почтовые ящики" #. module: crm_partner_assign #: selection:crm.lead.forward.to.partner,type:0 msgid "Comment" -msgstr "" +msgstr "Комментарий" #. module: crm_partner_assign #: field:res.partner,partner_weight:0 @@ -451,7 +456,7 @@ msgstr "Декабрь" #. module: crm_partner_assign #: help:crm.lead.forward.to.partner,vote_user_ids:0 msgid "Users that voted for this message" -msgstr "" +msgstr "Пользователи, которые проголосовали за это сообщение" #. module: crm_partner_assign #: view:crm.lead.report.assign:0 @@ -467,7 +472,7 @@ msgstr "Дата открытия" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,child_ids:0 msgid "Child Messages" -msgstr "" +msgstr "Связанные сообщения" #. module: crm_partner_assign #: field:crm.partner.report.assign,date_review:0 @@ -483,17 +488,17 @@ msgstr "Тема" #. module: crm_partner_assign #: view:crm.lead.forward.to.partner:0 msgid "or" -msgstr "" +msgstr "или" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,body:0 msgid "Contents" -msgstr "" +msgstr "Содержимое" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,vote_user_ids:0 msgid "Votes" -msgstr "" +msgstr "Голоса" #. module: crm_partner_assign #: view:crm.lead.report.assign:0 @@ -504,6 +509,8 @@ msgstr "# Предложений" #: help:crm.lead.forward.to.partner,starred:0 msgid "Current user has a starred notification linked to this message" msgstr "" +"Текущий пользователь имеет отмеченное уведомление, связанное с этим " +"сообщением" #. module: crm_partner_assign #: field:crm.partner.report.assign,date_partnership:0 @@ -561,7 +568,7 @@ msgstr "Август" #. module: crm_partner_assign #: help:crm.lead.forward.to.partner,record_name:0 msgid "Name get of the related document." -msgstr "" +msgstr "Название связанного документа." #. module: crm_partner_assign #: selection:crm.lead.report.assign,priority:0 @@ -663,7 +670,7 @@ msgstr "" #. module: crm_partner_assign #: field:crm.partner.report.assign,period_id:0 msgid "Invoice Period" -msgstr "" +msgstr "Период счета" #. module: crm_partner_assign #: model:ir.model,name:crm_partner_assign.model_res_partner_grade @@ -684,7 +691,7 @@ msgstr "Вложения" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,record_name:0 msgid "Message Record Name" -msgstr "" +msgstr "Название записи сообщения" #. module: crm_partner_assign #: field:res.partner.activation,sequence:0 @@ -699,6 +706,8 @@ msgid "" "Cannot contact geolocation servers. Please make sure that your internet " "connection is up and running (%s)." msgstr "" +"Не удается связаться с сервером геолокации. Пожалуйста, убедитесь, что ваше " +"подключение к интернету работает (%s)." #. module: crm_partner_assign #: selection:crm.lead.report.assign,month:0 @@ -724,7 +733,7 @@ msgstr "Открыто" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,subtype_id:0 msgid "Subtype" -msgstr "" +msgstr "Подтип" #. module: crm_partner_assign #: field:res.partner,date_localization:0 @@ -739,12 +748,12 @@ msgstr "Текущий" #. module: crm_partner_assign #: model:ir.model,name:crm_partner_assign.model_crm_lead msgid "Lead/Opportunity" -msgstr "" +msgstr "Кандидат/Предложение" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,notified_partner_ids:0 msgid "Notified partners" -msgstr "" +msgstr "Уведомленные партнеры" #. module: crm_partner_assign #: view:crm.lead.forward.to.partner:0 @@ -775,7 +784,7 @@ msgstr "Вероятная выручка" #: field:res.partner,activation:0 #: view:res.partner.activation:0 msgid "Activation" -msgstr "" +msgstr "Активация" #. module: crm_partner_assign #: view:crm.lead:0 @@ -792,6 +801,8 @@ msgstr "" #: help:crm.lead.forward.to.partner,to_read:0 msgid "Current user has an unread notification linked to this message" msgstr "" +"Текущий пользователь имеет непрочитанные уведомления, связанные с этим " +"сообщением" #. module: crm_partner_assign #: selection:crm.lead.report.assign,type:0 @@ -860,6 +871,8 @@ msgid "" "Technical field holding the message notifications. Use notified_partner_ids " "to access notified partners." msgstr "" +"Техническое поле, содержащее уведомления. Используйте notified_partner_ids " +"для доступа к оповещаемым партнерам." #. module: crm_partner_assign #: view:crm.partner.report.assign:0 @@ -874,12 +887,12 @@ msgstr "CRM - отчет по кандидатам" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,composition_mode:0 msgid "Composition mode" -msgstr "" +msgstr "Режим составления" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,model:0 msgid "Related Document Model" -msgstr "" +msgstr "Модель связанного документа" #. module: crm_partner_assign #: selection:crm.lead.forward.to.partner,history_mode:0 @@ -892,6 +905,8 @@ msgid "" "Author of the message. If not set, email_from may hold an email address that " "did not match any partner." msgstr "" +"Автор сообщения. Если не установлен, email_from может содержать адрес почты, " +"который не соответствует ни одному партнеру." #. module: crm_partner_assign #: model:ir.model,name:crm_partner_assign.model_crm_partner_report_assign @@ -906,12 +921,12 @@ msgstr "Высокий" #. module: crm_partner_assign #: field:crm.lead.forward.to.partner,partner_ids:0 msgid "Additional contacts" -msgstr "" +msgstr "Дополнительные контакты" #. module: crm_partner_assign #: help:crm.lead.forward.to.partner,parent_id:0 msgid "Initial thread message." -msgstr "" +msgstr "Первое сообщение цепочки." #. module: crm_partner_assign #: field:crm.lead.report.assign,create_date:0 diff --git a/addons/crm_partner_assign/report/crm_lead_report.py b/addons/crm_partner_assign/report/crm_lead_report.py index 2c208131b3a..676a8536b74 100644 --- a/addons/crm_partner_assign/report/crm_lead_report.py +++ b/addons/crm_partner_assign/report/crm_lead_report.py @@ -118,6 +118,5 @@ class crm_lead_report_assign(osv.osv): left join res_partner p on (c.partner_assigned_id=p.id) )""") -crm_lead_report_assign() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm_partner_assign/report/crm_lead_report_view.xml b/addons/crm_partner_assign/report/crm_lead_report_view.xml index ee9266a0235..fbc46302fd7 100644 --- a/addons/crm_partner_assign/report/crm_lead_report_view.xml +++ b/addons/crm_partner_assign/report/crm_lead_report_view.xml @@ -10,7 +10,7 @@ - + @@ -69,7 +69,7 @@ - + diff --git a/addons/crm_partner_assign/report/crm_partner_report.py b/addons/crm_partner_assign/report/crm_partner_report.py index 4611fdd06e4..6f07a8ce03a 100644 --- a/addons/crm_partner_assign/report/crm_partner_report.py +++ b/addons/crm_partner_assign/report/crm_partner_report.py @@ -67,6 +67,5 @@ class crm_partner_report_assign(osv.osv): on (i.partner_id=p.id and i.type in ('out_invoice','out_refund') and i.state in ('open','paid')) )""") -crm_partner_report_assign() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm_partner_assign/report/crm_partner_report_view.xml b/addons/crm_partner_assign/report/crm_partner_report_view.xml index eb2c86874c4..4e7e13afb15 100644 --- a/addons/crm_partner_assign/report/crm_partner_report_view.xml +++ b/addons/crm_partner_assign/report/crm_partner_report_view.xml @@ -8,7 +8,7 @@ crm.partner.report.assign - + @@ -49,7 +49,7 @@ - + diff --git a/addons/crm_partner_assign/res_partner_view.xml b/addons/crm_partner_assign/res_partner_view.xml index 433a290ae81..9e70835a3f1 100644 --- a/addons/crm_partner_assign/res_partner_view.xml +++ b/addons/crm_partner_assign/res_partner_view.xml @@ -140,30 +140,31 @@ + +
+ +
+
+
+
+ + + + +
+
+ +
+
+
+ +
+
+
+
+
+
+ \ No newline at end of file diff --git a/addons/im/watcher.py b/addons/im/watcher.py new file mode 100644 index 00000000000..b8cb74df5ba --- /dev/null +++ b/addons/im/watcher.py @@ -0,0 +1,84 @@ + +import openerp +import openerp.tools.config +import openerp.modules.registry +from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT +import datetime +from openerp.osv import osv, fields +import time +import logging +import json +import select +import gevent +import gevent.event +from openerp.addons.im.im import * + +_logger = logging.getLogger(__name__) + +class ImWatcher(object): + watchers = {} + + @staticmethod + def get_watcher(db_name): + if not ImWatcher.watchers.get(db_name): + ImWatcher(db_name) + return ImWatcher.watchers[db_name] + + def __init__(self, db_name): + self.db_name = db_name + ImWatcher.watchers[db_name] = self + self.waiting = 0 + self.wait_id = 0 + self.users = {} + self.users_watch = {} + gevent.spawn(self.loop) + + def loop(self): + _logger.info("Begin watching on channel im_channel for database " + self.db_name) + stop = False + while not stop: + try: + registry = openerp.modules.registry.RegistryManager.get(self.db_name) + with registry.cursor() as cr: + listen_channel(cr, "im_channel", self.handle_message, self.check_stop) + stop = True + except: + # if something crash, we wait some time then try again + _logger.exception("Exception during watcher activity") + time.sleep(WATCHER_ERROR_DELAY) + _logger.info("End watching on channel im_channel for database " + self.db_name) + del ImWatcher.watchers[self.db_name] + + def handle_message(self, message): + if message["type"] == "message": + for waiter in self.users.get(message["receiver"], {}).values(): + waiter.set() + else: #type status + for waiter in self.users_watch.get(message["user"], {}).values(): + waiter.set() + + def check_stop(self): + return self.waiting == 0 + + def _get_wait_id(self): + self.wait_id += 1 + return self.wait_id + + def stop(self, user_id, watch_users, timeout=None): + wait_id = self._get_wait_id() + event = gevent.event.Event() + self.waiting += 1 + self.users.setdefault(user_id, {})[wait_id] = event + for watch in watch_users: + self.users_watch.setdefault(watch, {})[wait_id] = event + try: + event.wait(timeout) + finally: + for watch in watch_users: + del self.users_watch[watch][wait_id] + if len(self.users_watch[watch]) == 0: + del self.users_watch[watch] + del self.users[user_id][wait_id] + if len(self.users[user_id]) == 0: + del self.users[user_id] + self.waiting -= 1 diff --git a/addons/im_livechat/__init__.py b/addons/im_livechat/__init__.py new file mode 100644 index 00000000000..2825a75179c --- /dev/null +++ b/addons/im_livechat/__init__.py @@ -0,0 +1,2 @@ + +import im_livechat diff --git a/addons/im_livechat/__openerp__.py b/addons/im_livechat/__openerp__.py new file mode 100644 index 00000000000..8b9ea3924d5 --- /dev/null +++ b/addons/im_livechat/__openerp__.py @@ -0,0 +1,29 @@ +{ + 'name' : 'Live Support', + 'version': '1.0', + 'summary': 'Live Chat with Visitors/Customers', + 'category': 'Tools', + 'complexity': 'easy', + 'description': + """ +Live Chat Support +================= + +Allow to drop instant messaging widgets on any web page that will communicate +with the current server and dispatch visitors request amongst several live +chat operators. + + """, + 'data': [ + "security/im_livechat_security.xml", + "security/ir.model.access.csv", + "im_livechat_view.xml", + ], + 'demo': [ + "im_livechat_demo.xml", + ], + 'depends' : ["im", "mail", "portal_anonymous"], + 'installable': True, + 'auto_install': False, + 'application': True, +} diff --git a/addons/im_livechat/im_livechat.py b/addons/im_livechat/im_livechat.py new file mode 100644 index 00000000000..1ffb422fe6a --- /dev/null +++ b/addons/im_livechat/im_livechat.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import openerp +import openerp.addons.im.im as im +import json +import random +import jinja2 +from openerp.osv import osv, fields +from openerp import tools + +env = jinja2.Environment( + loader=jinja2.PackageLoader('openerp.addons.im_livechat', "."), + autoescape=False +) +env.filters["json"] = json.dumps + +class LiveChatController(openerp.addons.web.http.Controller): + _cp_path = '/im_livechat' + + @openerp.addons.web.http.httprequest + def loader(self, req, **kwargs): + p = json.loads(kwargs["p"]) + db = p["db"] + channel = p["channel"] + user_name = p.get("user_name", None) + req.session._db = db + req.session._uid = None + req.session._login = "anonymous" + req.session._password = "anonymous" + info = req.session.model('im_livechat.channel').get_info_for_chat_src(channel) + info["db"] = db + info["channel"] = channel + info["userName"] = user_name + return req.make_response(env.get_template("loader.js").render(info), + headers=[('Content-Type', "text/javascript")]) + + @openerp.addons.web.http.httprequest + def web_page(self, req, **kwargs): + p = json.loads(kwargs["p"]) + db = p["db"] + channel = p["channel"] + req.session._db = db + req.session._uid = None + req.session._login = "anonymous" + req.session._password = "anonymous" + script = req.session.model('im_livechat.channel').read(channel, ["script"])["script"] + info = req.session.model('im_livechat.channel').get_info_for_chat_src(channel) + info["script"] = script + return req.make_response(env.get_template("web_page.html").render(info), + headers=[('Content-Type', "text/html")]) + + @openerp.addons.web.http.jsonrequest + def available(self, req, db, channel): + req.session._db = db + req.session._uid = None + req.session._login = "anonymous" + req.session._password = "anonymous" + return req.session.model('im_livechat.channel').get_available_user(channel) > 0 + +class im_livechat_channel(osv.osv): + _name = 'im_livechat.channel' + + def _get_default_image(self, cr, uid, context=None): + image_path = openerp.modules.get_module_resource('im_livechat', 'static/src/img', 'default.png') + return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64')) + def _get_image(self, cr, uid, ids, name, args, context=None): + result = dict.fromkeys(ids, False) + for obj in self.browse(cr, uid, ids, context=context): + result[obj.id] = tools.image_get_resized_images(obj.image) + return result + def _set_image(self, cr, uid, id, name, value, args, context=None): + return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context) + + + def _are_you_inside(self, cr, uid, ids, name, arg, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + res[record.id] = False + for user in record.user_ids: + if user.id == uid: + res[record.id] = True + break + return res + + def _script(self, cr, uid, ids, name, arg, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + res[record.id] = env.get_template("include.html").render({ + "url": self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url'), + "parameters": {"db":cr.dbname, "channel":record.id}, + }) + return res + + def _web_page(self, cr, uid, ids, name, arg, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + res[record.id] = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + \ + "/im_livechat/web_page?p=" + json.dumps({"db":cr.dbname, "channel":record.id}) + return res + + _columns = { + 'name': fields.char(string="Channel Name", size=200, required=True), + 'user_ids': fields.many2many('res.users', 'im_livechat_channel_im_user', 'channel_id', 'user_id', string="Users"), + 'are_you_inside': fields.function(_are_you_inside, type='boolean', string='Are you inside the matrix?', store=False), + 'script': fields.function(_script, type='text', string='Script', store=False), + 'web_page': fields.function(_web_page, type='url', string='Web Page', store=False, size="200"), + 'button_text': fields.char(string="Text of the Button", size=200), + 'input_placeholder': fields.char(string="Chat Input Placeholder", size=200), + 'default_message': fields.char(string="Welcome Message", size=200, help="This is an automated 'welcome' message that your visitor will see when they initiate a new chat session."), + # image: all image fields are base64 encoded and PIL-supported + 'image': fields.binary("Photo", + help="This field holds the image used as photo for the group, limited to 1024x1024px."), + 'image_medium': fields.function(_get_image, fnct_inv=_set_image, + string="Medium-sized photo", type="binary", multi="_get_image", + store={ + 'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10), + }, + help="Medium-sized photo of the group. It is automatically "\ + "resized as a 128x128px image, with aspect ratio preserved. "\ + "Use this field in form views or some kanban views."), + 'image_small': fields.function(_get_image, fnct_inv=_set_image, + string="Small-sized photo", type="binary", multi="_get_image", + store={ + 'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10), + }, + help="Small-sized photo of the group. It is automatically "\ + "resized as a 64x64px image, with aspect ratio preserved. "\ + "Use this field anywhere a small image is required."), + } + + def _default_user_ids(self, cr, uid, context=None): + return [(6, 0, [uid])] + + _defaults = { + 'button_text': "Have a Question? Chat with us.", + 'input_placeholder': "How may I help you?", + 'default_message': '', + 'user_ids': _default_user_ids, + 'image': _get_default_image, + } + + def get_available_user(self, cr, uid, channel_id, context=None): + channel = self.browse(cr, openerp.SUPERUSER_ID, channel_id, context=context) + users = [] + for user in channel.user_ids: + iuid = self.pool.get("im.user").get_by_user_id(cr, uid, user.id, context=context)["id"] + imuser = self.pool.get("im.user").browse(cr, uid, iuid, context=context) + if imuser.im_status: + users.append(imuser) + if len(users) == 0: + return False + return random.choice(users).id + + def test_channel(self, cr, uid, channel, context=None): + if not channel: + return {} + return { + 'url': self.browse(cr, uid, channel[0], context=context or {}).web_page, + 'type': 'ir.actions.act_url' + } + + def get_info_for_chat_src(self, cr, uid, channel, context=None): + url = self.pool.get('ir.config_parameter').get_param(cr, openerp.SUPERUSER_ID, 'web.base.url') + chan = self.browse(cr, uid, channel, context=context) + return { + "url": url, + 'buttonText': chan.button_text, + 'inputPlaceholder': chan.input_placeholder, + 'defaultMessage': chan.default_message, + "channelName": chan.name, + } + + def join(self, cr, uid, ids, context=None): + self.write(cr, uid, ids, {'user_ids': [(4, uid)]}) + return True + + def quit(self, cr, uid, ids, context=None): + self.write(cr, uid, ids, {'user_ids': [(3, uid)]}) + return True + + +class im_message(osv.osv): + _inherit = 'im.message' + + def _support_member(self, cr, uid, ids, name, arg, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + res[record.id] = False + if record.to_id.user and record.from_id.user: + continue + elif record.to_id.user: + res[record.id] = record.to_id.user.id + elif record.from_id.user: + res[record.id] = record.from_id.user.id + return res + + def _customer(self, cr, uid, ids, name, arg, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + res[record.id] = False + if record.to_id.uuid and record.from_id.uuid: + continue + elif record.to_id.uuid: + res[record.id] = record.to_id.id + elif record.from_id.uuid: + res[record.id] = record.from_id.id + return res + + def _direction(self, cr, uid, ids, name, arg, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + res[record.id] = False + if not not record.to_id.user and not not record.from_id.user: + continue + elif not not record.to_id.user: + res[record.id] = "c2s" + elif not not record.from_id.user: + res[record.id] = "s2c" + return res + + _columns = { + 'support_member_id': fields.function(_support_member, type='many2one', relation='res.users', string='Support Member', store=True, select=True), + 'customer_id': fields.function(_customer, type='many2one', relation='im.user', string='Customer', store=True, select=True), + 'direction': fields.function(_direction, type="selection", selection=[("s2c", "Support Member to Customer"), ("c2s", "Customer to Support Member")], + string='Direction', store=False), + } diff --git a/addons/im_livechat/im_livechat_demo.xml b/addons/im_livechat/im_livechat_demo.xml new file mode 100644 index 00000000000..f199179fb50 --- /dev/null +++ b/addons/im_livechat/im_livechat_demo.xml @@ -0,0 +1,15 @@ + + + + + + YourWebsite.com + Hello, how may I help you? + + + + + + + + diff --git a/addons/im_livechat/im_livechat_view.xml b/addons/im_livechat/im_livechat_view.xml new file mode 100644 index 00000000000..f684fd561fc --- /dev/null +++ b/addons/im_livechat/im_livechat_view.xml @@ -0,0 +1,146 @@ + + + + + + + Live Chat Channels + im_livechat.channel + kanban,form + +

+ Click to define a new live chat channel. +

+ You can create channels for each website on which you want + to integrate the live chat widget, allowing you website + visitors to talk in real time with your operators. +

+ Each channel has it's own URL that you can send by email to + your customers in order to start chatting with you. +

+
+
+ + + + + support_channel.kanban + im_livechat.channel + + + + + + + + +
+ +
+
+

+ +
+ + +
+
+ + + +
+ + + + + support_channel.form + im_livechat.channel + +
+ + +
+
+ + + + + + + + +
+ X +
+ +

+
+
+
+
+
+
+
+ + + + + +
+ +
+ +

+ Copy and paste this code into your website, within the &lt;head&gt; tag: +

+ +

+ or copy this url and send it by email to your customers or suppliers: +

+ +
+ +
+
+
+
+ + + History + im.message + list + ["|", ('to_id.user', '=', None), ('from_id.user', '=', None)] + + + + + im.message.tree + im.message + + + + + + + + + + + + + diff --git a/addons/im_livechat/include.html b/addons/im_livechat/include.html new file mode 100644 index 00000000000..55de6212361 --- /dev/null +++ b/addons/im_livechat/include.html @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/addons/im_livechat/loader.js b/addons/im_livechat/loader.js new file mode 100644 index 00000000000..669591b410f --- /dev/null +++ b/addons/im_livechat/loader.js @@ -0,0 +1,24 @@ + +require.config({ + context: "oelivesupport", + baseUrl: {{url | json}} + "/im_livechat/static/ext/static/js", + shim: { + underscore: { + init: function() { + return _.noConflict(); + }, + }, + "jquery.achtung": { + deps: ['jquery'], + }, + }, +})(["livesupport", "jquery"], function(livesupport, jQuery) { + jQuery.noConflict(); + livesupport.main({{url | json}}, {{db | json}}, "anonymous", "anonymous", {{channel | json}}, { + buttonText: {{buttonText | json}}, + inputPlaceholder: {{inputPlaceholder | json}}, + defaultMessage: {{(defaultMessage or None) | json}}, + auto: window.oe_im_livechat_auto || false, + userName: {{userName | json}} || undefined, + }); +}); diff --git a/addons/im_livechat/security/im_livechat_security.xml b/addons/im_livechat/security/im_livechat_security.xml new file mode 100644 index 00000000000..5ad020a8a78 --- /dev/null +++ b/addons/im_livechat/security/im_livechat_security.xml @@ -0,0 +1,36 @@ + + + + + + Live Support + + + + + User + + The user will be able to join support channels. + + + + Manager + The user will be able to delete support channels. + + + + + + + Live Support Managers can read messages from live support + + + ["|", ('to_id.user', '=', None), ('from_id.user', '=', None)] + + + + + + + + diff --git a/addons/im_livechat/security/ir.model.access.csv b/addons/im_livechat/security/ir.model.access.csv new file mode 100644 index 00000000000..0dcf0bdee6f --- /dev/null +++ b/addons/im_livechat/security/ir.model.access.csv @@ -0,0 +1,8 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_ls_chann1,im_livechat.channel,model_im_livechat_channel,,1,0,0,0 +access_ls_chann2,im_livechat.channel,model_im_livechat_channel,group_im_livechat,1,1,1,0 +access_ls_chann3,im_livechat.channel,model_im_livechat_channel,group_im_livechat_manager,1,1,1,1 +access_ls_message_portal,im_livechat.im.message.portal,im.model_im_message,portal.group_portal,0,0,0,0 +access_im_user_portal,im_livechat.im.user.portal,im.model_im_user,portal.group_portal,1,0,0,0 +access_ls_message,im_livechat.im.message,im.model_im_message,portal.group_anonymous,0,0,0,0 +access_im_user,im_livechat.im.user,im.model_im_user,portal.group_anonymous,1,0,0,0 \ No newline at end of file diff --git a/addons/im_livechat/static/ext/Makefile b/addons/im_livechat/static/ext/Makefile new file mode 100644 index 00000000000..b73ca4f2b89 --- /dev/null +++ b/addons/im_livechat/static/ext/Makefile @@ -0,0 +1,3 @@ + +static/js/livesupport_templates.js: static/js/livesupport_templates.html + python static/js/to_jsonp.py static/js/livesupport_templates.html oe_livesupport_templates_callback > static/js/livesupport_templates.js \ No newline at end of file diff --git a/addons/im_livechat/static/ext/static/audio/Ting.mp3 b/addons/im_livechat/static/ext/static/audio/Ting.mp3 new file mode 100644 index 00000000000..ffbb77144b2 Binary files /dev/null and b/addons/im_livechat/static/ext/static/audio/Ting.mp3 differ diff --git a/addons/im_livechat/static/ext/static/audio/Ting.ogg b/addons/im_livechat/static/ext/static/audio/Ting.ogg new file mode 100644 index 00000000000..74ee13a4e5a Binary files /dev/null and b/addons/im_livechat/static/ext/static/audio/Ting.ogg differ diff --git a/addons/im_livechat/static/ext/static/css/livesupport.css b/addons/im_livechat/static/ext/static/css/livesupport.css new file mode 100644 index 00000000000..bfe26b5e838 --- /dev/null +++ b/addons/im_livechat/static/ext/static/css/livesupport.css @@ -0,0 +1,190 @@ + + + +.openerp_style { /* base style of openerp */ + font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif; + color: #4c4c4c; + font-size: 13px; + background: white; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); +} + +/* button */ + +.oe_chat_button { + position: fixed; + bottom: 0px; + right: 6px; + display: inline-block; + min-width: 100px; + background-color: rgba(60, 60, 60, 0.6); + font-family: 'Lucida Grande', 'Lucida Sans Unicode', Arial, Verdana, sans-serif; + font-size: 14px; + font-weight: bold; + padding: 10px; + color: white; + text-shadow: rgb(59, 76, 88) 1px 1px 0px; + border: 1px solid rgb(80, 80, 80); + border-bottom: 0px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + cursor: pointer; +} + +/* conversations */ + +.oe_im_chatview { + position: fixed; + overflow: hidden; + bottom: 42px; + margin-right: 6px; + background: rgba(60, 60, 60, 0.8); + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + -moz-box-shadow: 0 0 3px rgba(0,0,0,0.3), 0 2px 4px rgba(0,0,0,0.3); + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3); + width: 240px; +} +.oe_im_chatview .oe_im_chatview_disconnected { + display:none; + z-index: 100; + width: 100%; + background: #E8EBEF; + padding: 5px; + font-size: 11px; + color: #999; + line-height: 14px; + height: 28px; + overflow: hidden; +} +.oe_im_chatview.oe_im_chatview_disconnected_status .oe_im_chatview_disconnected { + display: block; +} +.oe_im_chatview .oe_im_chatview_header { + padding: 3px 6px 2px; + background: #DEDEDE; + background: -moz-linear-gradient(#FCFCFC, #DEDEDE); + background: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#DEDEDE)); + -moz-border-radius: 3px 3px 0 0; + -webkit-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; + border-bottom: 1px solid #AEB9BD; + cursor: pointer; +} +.oe_im_chatview .oe_im_chatview_close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; + font-size: 18px; + line-height: 16px; + float: right; + font-weight: bold; + color: black; + text-shadow: 0 1px 0 white; + opacity: 0.2; +} +.oe_im_chatview .oe_im_chatview_content { + overflow: auto; + height: 287px; + width: 240px; +} +.oe_im_chatview.oe_im_chatview_disconnected_status .oe_im_chatview_content { + height: 249px; +} +.oe_im_chatview .oe_im_chatview_footer { + position: relative; + padding: 3px; + border-top: 1px solid #AEB9BD; + background: #DEDEDE; + background: -moz-linear-gradient(#FCFCFC, #DEDEDE); + background: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#DEDEDE)); + -moz-border-radius: 0 0 3px 3px; + -webkit-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; +} +.oe_im_chatview .oe_im_chatview_input { + width: 222px; + font-family: Lato, Helvetica, sans-serif; + font-size: 13px; + color: #333; + padding: 1px 5px; + border: 1px solid #AEB9BD; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + -moz-box-shadow: inset 0 1px 4px rgba(0,0,0,0.2); + -webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.2); + box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.2); +} +.oe_im_chatview .oe_im_chatview_bubble { + background: white; + position: relative; + padding: 3px; + margin: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.oe_im_chatview .oe_im_chatview_clip { + position: relative; + float: left; + width: 26px; + height: 26px; + margin-right: 4px; + -moz-box-shadow: 0 0 2px 1px rgba(0,0,0,0.25); + -webkit-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25); + box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25); +} +.oe_im_chatview .oe_im_chatview_avatar { + float: left; + width: 26px; + height: auto; + clip: rect(0, 26px, 26px, 0); + max-width: 100%; + width: auto 9; + height: auto; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} +.oe_im_chatview .oe_im_chatview_time { + position: absolute; + right: 0px; + top: 0px; + margin: 3px; + text-align: right; + line-height: 13px; + font-size: 11px; + color: #999; + width: 60px; + overflow: hidden; +} +.oe_im_chatview .oe_im_chatview_from { + margin: 0 0 2px 0; + line-height: 14px; + font-weight: bold; + font-size: 12px; + width: 140px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + color: #3A87AD; +} +.oe_im_chatview .oe_im_chatview_bubble_list { +} +.oe_im_chatview .oe_im_chatview_bubble_item { + margin: 0 0 2px 30px; + line-height: 14px; + word-wrap: break-word; +} + +.oe_im_chatview_online { + display: none; + margin-top: -4px; + width: 11px; + height: 11px; +} diff --git a/addons/im_livechat/static/ext/static/img/avatar/avatar.jpeg b/addons/im_livechat/static/ext/static/img/avatar/avatar.jpeg new file mode 100644 index 00000000000..7168794022e Binary files /dev/null and b/addons/im_livechat/static/ext/static/img/avatar/avatar.jpeg differ diff --git a/addons/im_livechat/static/ext/static/img/button-gloss.png b/addons/im_livechat/static/ext/static/img/button-gloss.png new file mode 100755 index 00000000000..6f3957702fe Binary files /dev/null and b/addons/im_livechat/static/ext/static/img/button-gloss.png differ diff --git a/addons/im_livechat/static/ext/static/img/glyphicons-halflings-white.png b/addons/im_livechat/static/ext/static/img/glyphicons-halflings-white.png new file mode 100755 index 00000000000..3bf6484a29d Binary files /dev/null and b/addons/im_livechat/static/ext/static/img/glyphicons-halflings-white.png differ diff --git a/addons/im_livechat/static/ext/static/img/glyphicons-halflings.png b/addons/im_livechat/static/ext/static/img/glyphicons-halflings.png new file mode 100755 index 00000000000..a9969993201 Binary files /dev/null and b/addons/im_livechat/static/ext/static/img/glyphicons-halflings.png differ diff --git a/addons/im_livechat/static/ext/static/img/green.png b/addons/im_livechat/static/ext/static/img/green.png new file mode 100644 index 00000000000..01fb373c251 Binary files /dev/null and b/addons/im_livechat/static/ext/static/img/green.png differ diff --git a/addons/im_livechat/static/ext/static/img/logo.png b/addons/im_livechat/static/ext/static/img/logo.png new file mode 100644 index 00000000000..aca5f4c60d8 Binary files /dev/null and b/addons/im_livechat/static/ext/static/img/logo.png differ diff --git a/addons/im_livechat/static/ext/static/img/wood.png b/addons/im_livechat/static/ext/static/img/wood.png new file mode 100644 index 00000000000..22f2450d3ad Binary files /dev/null and b/addons/im_livechat/static/ext/static/img/wood.png differ diff --git a/addons/im_livechat/static/ext/static/js/jquery.achtung.css b/addons/im_livechat/static/ext/static/js/jquery.achtung.css new file mode 100644 index 00000000000..820ae3e9194 --- /dev/null +++ b/addons/im_livechat/static/ext/static/js/jquery.achtung.css @@ -0,0 +1,306 @@ +/** + * achtung 0.3.0 + * + * Growl-like notifications for jQuery + * + * Copyright (c) 2009 Josh Varner + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Portions of this file are from the jQuery UI CSS framework. + * + * @license http://www.opensource.org/licenses/mit-license.php + * @author Josh Varner + */ + +/* IE 6 doesn't support position: fixed */ +* html #achtung-overlay { + position:absolute; +} + +/* IE6 includes padding in width */ +* html .achtung { + width: 280px; +} + +#achtung-overlay { + overflow: hidden; + position: fixed; + top: 15px; + right: 15px; + width: 280px; + z-index:50; +} + +.achtung { + display:none; + margin-bottom: 8px; + padding: 15px 15px; + background-color: #000; + color: white; + width: 250px; + font-weight: bold; + position:relative; + overflow: hidden; + -moz-box-shadow: #aaa 1px 1px 2px; + -webkit-box-shadow: #aaa 1px 1px 2px; + box-shadow: #aaa 1px 1px 2px; + -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; + /* Note that if using show/hide animations, IE will lose + this setting */ + opacity: .85; + filter:Alpha(Opacity=85); +} + +/** + * This section from jQuery UI CSS framework + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Can (and should) be removed if you are already loading the jQuery UI CSS + * to reduce payload size. + */ +.ui-icon { display: block; overflow: hidden; background-repeat: no-repeat; } +.ui-icon { width: 16px; height: 16px; } +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + +.achtung .achtung-message-icon { + margin-top: 0px; + margin-left: -.5em; + margin-right: .5em; + float: left; + zoom: 1; +} + +.achtung .ui-icon.achtung-close-button { + float: right; + margin-right: -8px; + margin-top: -12px; + cursor: pointer; + color: white; + text-align: right; +} + +.achtung .ui-icon.achtung-close-button:after { + content: "x" +} + +/* Slightly darker for these colors (readability) */ +.achtungSuccess, .achtungFail, .achtungWait { + /* Note that if using show/hide animations, IE will lose + this setting */ + opacity: .93; filter:Alpha(Opacity=93); +} + +.achtungSuccess { + background-color: #4DB559; +} + +.achtungFail { + background-color: #D64450; +} + +.achtungWait { + background-color: #658093; +} + +.achtungSuccess .ui-icon.achtung-close-button, +.achtungFail .ui-icon.achtung-close-button { +} + +.achtungSuccess .ui-icon.achtung-close-button-hover, +.achtungFail .ui-icon.achtung-close-button-hover { +} + +.achtung .wait-icon { +} + +.achtung .achtung-message { + display: inline; +} diff --git a/addons/im_livechat/static/ext/static/js/jquery.achtung.js b/addons/im_livechat/static/ext/static/js/jquery.achtung.js new file mode 100644 index 00000000000..1aa69469c1d --- /dev/null +++ b/addons/im_livechat/static/ext/static/js/jquery.achtung.js @@ -0,0 +1,273 @@ +/** + * achtung 0.3.0 + * + * Growl-like notifications for jQuery + * + * Copyright (c) 2009 Josh Varner + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @license http://www.opensource.org/licenses/mit-license.php + * @author Josh Varner + */ + +/*globals jQuery,clearTimeout,document,navigator,setTimeout +*/ +(function($) { + +/** + * This is based on the jQuery UI $.widget code. I would have just made this + * a $.widget but I didn't want the jQuery UI dependency. + */ +$.fn.achtung = function(options) +{ + var isMethodCall = (typeof options === 'string'), + args = Array.prototype.slice.call(arguments, 0), + name = 'achtung'; + + // handle initialization and non-getter methods + return this.each(function() { + var instance = $.data(this, name); + + // prevent calls to internal methods + if (isMethodCall && options.substring(0, 1) === '_') { + return this; + } + + // constructor + (!instance && !isMethodCall && + $.data(this, name, new $.achtung(this))._init(args)); + + // method call + (instance && isMethodCall && $.isFunction(instance[options]) && + instance[options].apply(instance, args.slice(1))); + }); +}; + +$.achtung = function(element) +{ + var args = Array.prototype.slice.call(arguments, 0), $el; + + if (!element || !element.nodeType) { + $el = $('
'); + return $el.achtung.apply($el, args); + } + + this.$container = $(element); +}; + + +/** + * Static members + **/ +$.extend($.achtung, { + version: '0.3.0', + $overlay: false, + defaults: { + timeout: 10, + disableClose: false, + icon: false, + className: '', + animateClassSwitch: false, + showEffects: {'opacity':'toggle','height':'toggle'}, + hideEffects: {'opacity':'toggle','height':'toggle'}, + showEffectDuration: 500, + hideEffectDuration: 700 + } +}); + +/** + * Non-static members + **/ +$.extend($.achtung.prototype, { + $container: false, + closeTimer: false, + options: {}, + + _init: function(args) + { + var o, self = this; + + args = $.isArray(args) ? args : []; + + + args.unshift($.achtung.defaults); + args.unshift({}); + + o = this.options = $.extend.apply($, args); + + if (!$.achtung.$overlay) { + $.achtung.$overlay = $('
').appendTo(document.body); + } + + if (!o.disableClose) { + $('') + .click(function () { self.close(); }) + .hover(function () { $(this).addClass('achtung-close-button-hover'); }, + function () { $(this).removeClass('achtung-close-button-hover'); }) + .prependTo(this.$container); + } + + this.changeIcon(o.icon, true); + + if (o.message) { + this.$container.append($('' + o.message + '')); + } + + (o.className && this.$container.addClass(o.className)); + (o.css && this.$container.css(o.css)); + + this.$container + .addClass('achtung') + .appendTo($.achtung.$overlay); + + if (o.showEffects) { + this.$container.toggle(); + } else { + this.$container.show(); + } + + if (o.timeout > 0) { + this.timeout(o.timeout); + } + }, + + timeout: function(timeout) + { + var self = this; + + if (this.closeTimer) { + clearTimeout(this.closeTimer); + } + + this.closeTimer = setTimeout(function() { self.close(); }, timeout * 1000); + this.options.timeout = timeout; + }, + + /** + * Change the CSS class associated with this message, using + * a transition if available (not availble in Safari/Webkit). + * If no transition is available, the switch is immediate. + * + * #LATER Check if this has been corrected in Webkit or jQuery UI + * #TODO Make transition time configurable + * @param newClass string Name of new class to associate + */ + changeClass: function(newClass) + { + var self = this; + + if (this.options.className === newClass) { + return; + } + + this.$container.queue(function() { + if (!self.options.animateClassSwitch || + /webkit/.test(navigator.userAgent.toLowerCase()) || + !$.isFunction($.fn.switchClass)) { + self.$container.removeClass(self.options.className); + self.$container.addClass(newClass); + } else { + self.$container.switchClass(self.options.className, newClass, 500); + } + + self.options.className = newClass; + self.$container.dequeue(); + }); + }, + + changeIcon: function(newIcon, force) + { + var self = this; + + if ((force !== true || newIcon === false) && this.options.icon === newIcon) { + return; + } + + if (force || this.options.icon === false) { + this.$container.prepend($('')); + this.options.icon = newIcon; + return; + } else if (newIcon === false) { + this.$container.find('.achtung-message-icon').remove(); + this.options.icon = false; + return; + } + + this.$container.queue(function() { + var $span = $('.achtung-message-icon', self.$container); + + if (!self.options.animateClassSwitch || + /webkit/.test(navigator.userAgent.toLowerCase()) || + !$.isFunction($.fn.switchClass)) { + $span.removeClass(self.options.icon); + $span.addClass(newIcon); + } else { + $span.switchClass(self.options.icon, newIcon, 500); + } + + self.options.icon = newIcon; + self.$container.dequeue(); + }); + }, + + + changeMessage: function(newMessage) + { + this.$container.queue(function() { + $('.achtung-message', $(this)).html(newMessage); + $(this).dequeue(); + }); + }, + + + update: function(options) + { + (options.className && this.changeClass(options.className)); + (options.css && this.$container.css(options.css)); + (typeof(options.icon) !== 'undefined' && this.changeIcon(options.icon)); + (options.message && this.changeMessage(options.message)); + (options.timeout && this.timeout(options.timeout)); + }, + + close: function() + { + var o = this.options, $container = this.$container; + + if (o.hideEffects) { + this.$container.animate(o.hideEffects, o.hideEffectDuration); + } else { + this.$container.hide(); + } + + $container.queue(function() { + $container.removeData('achtung'); + $container.remove(); + + if ($.achtung.$overlay && $.achtung.$overlay.is(':empty')) { + $.achtung.$overlay.remove(); + $.achtung.$overlay = false; + } + + $container.dequeue(); + }); + } +}); + +})(jQuery); \ No newline at end of file diff --git a/addons/im_livechat/static/ext/static/js/jquery.js b/addons/im_livechat/static/ext/static/js/jquery.js new file mode 100644 index 00000000000..ded03845983 --- /dev/null +++ b/addons/im_livechat/static/ext/static/js/jquery.js @@ -0,0 +1,9555 @@ +/*! + * jQuery JavaScript Library v1.9.0 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-1-14 + */ +(function( window, undefined ) { +"use strict"; +var + // A central reference to the root jQuery(document) + rootjQuery, + + // The deferred used on DOM ready + readyList, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + location = window.location, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.9.0", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler and self cleanup method + DOMContentLoaded = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + } else if ( document.readyState === "complete" ) { + // we're here because readyState === "complete" in oldIE + // which is good enough for us to call the dom ready! + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + return jQuery.inArray( fn, list ) > -1; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( list && ( !fired || stack ) ) { + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function() { + + var support, all, a, select, opt, input, fragment, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
a"; + + // Support tests won't run in some limited or non-browser environments + all = div.getElementsByTagName("*"); + a = div.getElementsByTagName("a")[ 0 ]; + if ( !all || !a || !all.length ) { + return {}; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + support = { + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.5/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + checkOn: !!input.value, + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Tests for enctype support on a form (#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode + boxModel: document.compatMode === "CSS1Compat", + + // Will be defined later + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + boxSizingReliable: true, + pixelPosition: false + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
t
"; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + support.boxSizing = ( div.offsetWidth === 4 ); + support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== "undefined" ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + body.style.zoom = 1; + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})(); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt /* For internal use only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data, false ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name, false ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( !name.indexOf( "data-" ) ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + // Try to fetch any internally stored data first + return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + } + + this.each(function() { + jQuery.data( this, key, value ); + }); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + hooks.cur = fn; + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + // Toggle whole class name + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val, + self = jQuery(this); + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + // In IE9+, Flash objects don't have .getAttribute (#12945) + // Support: IE9+ + if ( typeof elem.getAttribute !== "undefined" ) { + ret = elem.getAttribute( name ); + } + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( rboolean.test( name ) ) { + // Set corresponding property to false for boolean attributes + // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8 + if ( !getSetAttribute && ruseDefault.test( name ) ) { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } else { + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + var + // Use .prop to determine if this attribute is understood as boolean + prop = jQuery.prop( elem, name ), + + // Fetch it accordingly + attr = typeof prop === "boolean" && elem.getAttribute( name ), + detail = typeof prop === "boolean" ? + + getSetInput && getSetAttribute ? + attr != null : + // oldIE fabricates an empty string for missing boolean attributes + // and conflates checked/selected into attroperties + ruseDefault.test( name ) ? + elem[ jQuery.camelCase( "default-" + name ) ] : + !!attr : + + // fetch an attribute node for properties not recognized as boolean + elem.getAttributeNode( name ); + + return detail && detail.value !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; + +// fix oldIE value attroperty +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return jQuery.nodeName( elem, "input" ) ? + + // Ignore the value *property* by using defaultValue + elem.defaultValue : + + ret && ret.specified ? ret.value : undefined; + }, + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ? + ret.value : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret == null ? undefined : ret; + } + }); + }); + + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + // Don't attach events to noData or text/comment nodes (but allow plain objects) + elemData = elem.nodeType !== 3 && elem.nodeType !== 8 && jQuery._data( elem ); + + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, + eventPath = [ elem || document ], + type = event.type || event, + namespaces = event.namespace ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + event.isTrigger = true; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, j, ret, matched, handleObj, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + for ( ; cur != this; cur = cur.parentNode || this ) { + + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.disabled !== true || event.type !== "click" ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + } + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== document.activeElement && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === document.activeElement && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === "undefined" ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +(function( window, undefined ) { + +var i, + cachedruns, + Expr, + getText, + isXML, + compile, + hasDuplicate, + outermostContext, + + // Local document vars + setDocument, + document, + docElem, + documentIsXML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + sortOrder, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + support = {}, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Array methods + arr = [], + pop = arr.pop, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rsibling = /[\x20\t\r\n\f]*[+~]/, + + rnative = /\{\s*\[native code\]\s*\}/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g, + funescape = function( _, escaped ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + return high !== high ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Use a stripped-down slice if we can't use a native one +try { + slice.call( docElem.childNodes, 0 )[0].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, + results = []; + for ( ; (elem = this[i]); i++ ) { + results.push( elem ); + } + return results; + }; +} + +/** + * For feature detection + * @param {Function} fn The function to test for native support + */ +function isNative( fn ) { + return rnative.test( fn + "" ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var cache, + keys = []; + + return (cache = function( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + }); +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return fn( div ); + } catch (e) { + return false; + } finally { + // release memory in IE + div = null; + } +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( !documentIsXML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + + // QSA path + if ( support.qsa && !rbuggyQSA.test(selector) ) { + old = true; + nid = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, slice.call( newContext.querySelectorAll( + newSelector + ), 0 ) ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsXML = isXML( doc ); + + // Check if getElementsByTagName("*") returns only elements + support.tagNameNoComments = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if attributes should be retrieved by attribute nodes + support.attributes = assert(function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }); + + // Check if getElementsByClassName can be trusted + support.getByClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length === 2; + }); + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + support.getByName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = doc.getElementsByName && + // buggy browsers will return fewer than the correct 2 + doc.getElementsByName( expando ).length === 2 + + // buggy browsers will return more than the correct 0 + doc.getElementsByName( expando + 0 ).length; + support.getIdNotName = !doc.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }); + + // IE6/7 return modified attributes + Expr.attrHandle = assert(function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }) ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }; + + // ID find and filter + if ( support.getIdNotName ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.tagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Name + Expr.find["NAME"] = support.getByName && function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }; + + // Class + Expr.find["CLASS"] = support.getByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) { + return context.getElementsByClassName( className ); + } + }; + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21), + // no need to also add to buggyMatches since matches checks buggyQSA + // A support test would require too much code (would include document ready) + rbuggyQSA = [ ":focus" ]; + + if ( (support.qsa = isNative(doc.querySelectorAll)) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE8 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = ""; + if ( div.querySelectorAll("[i^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = new RegExp( rbuggyMatches.join("|") ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = isNative(docElem.contains) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + var compare; + + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) { + if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) { + if ( a === doc || contains( preferredDoc, a ) ) { + return -1; + } + if ( b === doc || contains( preferredDoc, b ) ) { + return 1; + } + return 0; + } + return compare & 4 ? -1 : 1; + } + + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return ( ~b.sourceIndex || MAX_NEGATIVE ) - ( contains( preferredDoc, a ) && ~a.sourceIndex || MAX_NEGATIVE ); + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + // Always assume the presence of duplicates if sort doesn't + // pass them to our comparison function (as in Google Chrome). + hasDuplicate = false; + [0, 0].sort( sortOrder ); + support.detectDuplicates = hasDuplicate; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyQSA always contains :focus, so no need for an existence check + if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + var val; + + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + if ( !documentIsXML ) { + name = name.toLowerCase(); + } + if ( (val = Expr.attrHandle[ name ]) ) { + return val( elem ); + } + if ( documentIsXML || support.attributes ) { + return elem.getAttribute( name ); + } + return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ? + name : + val && val.specified ? val.value : null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + i = 1, + j = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +function siblingCheck( a, b ) { + var cur = a && b && a.nextSibling; + + for ( ; cur; cur = cur.nextSibling ) { + if ( cur === b ) { + return -1; + } + } + + return a ? 1 : -1; +} + +// Returns a function to use in pseudos for input types +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +// Returns a function to use in pseudos for buttons +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +// Returns a function to use in pseudos for positionals +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[4] ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + + nodeName = nodeName.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.substr( result.length - check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifider + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsXML ? + elem.getAttribute("xml:lang") || elem.getAttribute("lang") : + elem.lang) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push( { + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && combinator.dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Nested matchers should use non-integer dirruns + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + for ( j = 0; (matcher = elementMatchers[j]); j++ ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + // `i` starts as a string, so matchedCount would equal "00" if there are no elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + for ( j = 0; (matcher = setMatchers[j]); j++ ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && !documentIsXML && + Expr.relative[ tokens[1].type ] ) { + + context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + for ( i = matchExpr["needsContext"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, slice.call( seed, 0 ) ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + documentIsXML, + results, + rsibling.test( selector ) + ); + return results; +} + +// Deprecated +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Easy API for creating new setFilters +function setFilters() {} +Expr.filters = setFilters.prototype = Expr.pseudos; +Expr.setFilters = new setFilters(); + +// Initialize with the default document +setDocument(); + +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + isSimple = /^.[^:#\[\.,]*$/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, ret, self; + + if ( typeof selector !== "string" ) { + self = this; + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < self.length; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + ret = []; + for ( i = 0; i < this.length; i++ ) { + jQuery.find( selector, this[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( jQuery.unique( ret ) ); + ret.selector = ( this.selector ? this.selector + " " : "" ) + selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true) ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + rneedsContext.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + cur = this[i]; + + while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + } + cur = cur.parentNode; + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +jQuery.fn.andSelf = jQuery.fn.addBack; + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( this.length > 1 && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function( value ) { + var isFunc = jQuery.isFunction( value ); + + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( !isFunc && typeof value !== "string" ) { + value = jQuery( value ).not( this ).detach(); + } + + return this.domManip( [ value ], true, function( elem ) { + var next = this.nextSibling, + parent = this.parentNode; + + if ( parent && this.nodeType === 1 || this.nodeType === 11 ) { + + jQuery( this ).remove(); + + if ( next ) { + next.parentNode.insertBefore( elem, next ); + } else { + parent.appendChild( elem ); + } + } + }); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, table ? self.html() : undefined ); + } + self.domManip( args, table, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( + table && jQuery.nodeName( this[i], "table" ) ? + findOrAppend( this[i], "tbody" ) : + this[i], + node, + i + ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery.ajax({ + url: node.src, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +function findOrAppend( elem, tag ) { + return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + var attr = elem.getAttributeNode("type"); + elem.type = ( attr && attr.specified ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, data, e; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== "undefined" ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, srcElements, node, i, clone, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var contains, elem, tag, tmp, wrap, tbody, j, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var data, id, elem, type, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== "undefined" ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + } +}); +var curCSS, getStyles, iframe, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var elem, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + values[ index ] = jQuery._data( elem, "olddisplay" ); + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && elem.style.display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else if ( !values[ index ] && !isHidden( elem ) ) { + jQuery._data( elem, "olddisplay", jQuery.css( elem, "display" ) ); + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + var bool = typeof state === "boolean"; + + return this.each(function() { + if ( bool ? state : isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery(" + + \ No newline at end of file diff --git a/addons/im_livechat/static/src/img/default.png b/addons/im_livechat/static/src/img/default.png new file mode 100644 index 00000000000..07d2503ce4e Binary files /dev/null and b/addons/im_livechat/static/src/img/default.png differ diff --git a/addons/im_livechat/static/src/img/icon.png b/addons/im_livechat/static/src/img/icon.png new file mode 100644 index 00000000000..07d2503ce4e Binary files /dev/null and b/addons/im_livechat/static/src/img/icon.png differ diff --git a/addons/im_livechat/web_page.html b/addons/im_livechat/web_page.html new file mode 100644 index 00000000000..2e1ea609126 --- /dev/null +++ b/addons/im_livechat/web_page.html @@ -0,0 +1,61 @@ + + + + + {{script}} + + + +
+

{{channelName | escape}}

+
Live Chat Powered by OpenERP.
+
+ + diff --git a/addons/l10n_ar/__init__.py b/addons/l10n_ar/__init__.py index 92da5dbf966..25e7e337165 100644 --- a/addons/l10n_ar/__init__.py +++ b/addons/l10n_ar/__init__.py @@ -23,7 +23,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/l10n_at/account_wizard.py b/addons/l10n_at/account_wizard.py index 278837322ac..0aec5392a8a 100644 --- a/addons/l10n_at/account_wizard.py +++ b/addons/l10n_at/account_wizard.py @@ -30,7 +30,6 @@ class AccountWizard_cd(osv.osv_memory): 'code_digits' : 0, } -AccountWizard_cd() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_be/fiscal_templates.xml b/addons/l10n_be/fiscal_templates.xml index 5e26a7e67c1..5cf5a21381b 100644 --- a/addons/l10n_be/fiscal_templates.xml +++ b/addons/l10n_be/fiscal_templates.xml @@ -22,12 +22,6 @@ - - - - - - diff --git a/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py b/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py index d89d427ef6b..0576e1d5f8f 100644 --- a/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py +++ b/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py @@ -84,7 +84,7 @@ class l10n_be_vat_declaration(osv.osv_memory): obj_company = obj_user.browse(cr, uid, uid, context=context).company_id vat_no = obj_company.partner_id.vat if not vat_no: - raise osv.except_osv(_('insufficient data!'), _('No VAT number associated with your company.')) + raise osv.except_osv(_('Insufficient Data!'), _('No VAT number associated with your company.')) vat_no = vat_no.replace(' ','').upper() vat = vat_no[2:] @@ -209,6 +209,5 @@ class l10n_be_vat_declaration(osv.osv_memory): 'target': 'new', } -l10n_be_vat_declaration() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py index 7aa612d95ff..0ffa0c16a24 100644 --- a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py +++ b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py @@ -39,7 +39,6 @@ class vat_listing_clients(osv.osv_memory): 'vat_amount': fields.float('VAT Amount'), } -vat_listing_clients() class partner_vat(osv.osv_memory): """ Vat Listing """ @@ -61,12 +60,12 @@ class partner_vat(osv.osv_memory): company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id period_ids = obj_period.search(cr, uid, [('date_start' ,'>=', date_start), ('date_stop','<=',date_stop), ('company_id','=',company_id)]) if not period_ids: - raise osv.except_osv(_('insufficient data!'), _('No data for the selected year.')) + raise osv.except_osv(_('Insufficient Data!'), _('No data for the selected year.')) partners = [] partner_ids = obj_partner.search(cr, uid, [('vat_subjected', '!=', False), ('vat','ilike','BE%')], context=context) if not partner_ids: - raise osv.except_osv(_('Error'),_('No belgian contact with a VAT number in your database.')) + raise osv.except_osv(_('Error'),_('No belgium contact with a VAT number in your database.')) cr.execute("""SELECT sub1.partner_id, sub1.name, sub1.vat, sub1.turnover, sub2.vat_amount FROM (SELECT l.partner_id, p.name, p.vat, SUM(CASE WHEN c.code ='49' THEN -l.tax_amount ELSE l.tax_amount END) as turnover FROM account_move_line l @@ -91,7 +90,7 @@ class partner_vat(osv.osv_memory): partners.append(id_client) if not partners: - raise osv.except_osv(_('insufficient data!'), _('No data found for the selected year.')) + raise osv.except_osv(_('Insufficient Data!'), _('No data found for the selected year.')) context.update({'partner_ids': partners, 'year': data['year'], 'limit_amount': data['limit_amount']}) model_data_ids = obj_model_data.search(cr, uid, [('model','=','ir.ui.view'), ('name','=','view_vat_listing')]) resource_id = obj_model_data.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id'] @@ -116,7 +115,6 @@ class partner_vat(osv.osv_memory): 'limit_amount': 250, } -partner_vat() class partner_vat_list(osv.osv_memory): """ Partner Vat Listing """ @@ -321,7 +319,6 @@ class partner_vat_list(osv.osv_memory): 'datas': datas, } -partner_vat_list() class partner_vat_listing_print(report_sxw.rml_parse): diff --git a/addons/l10n_be/wizard/l10n_be_vat_intra.py b/addons/l10n_be/wizard/l10n_be_vat_intra.py index ffd42290ed0..a572c3b83b4 100644 --- a/addons/l10n_be/wizard/l10n_be_vat_intra.py +++ b/addons/l10n_be/wizard/l10n_be_vat_intra.py @@ -108,7 +108,7 @@ class partner_vat_intra(osv.osv_memory): # Get Company vat company_vat = data_company.partner_id.vat if not company_vat: - raise osv.except_osv(_('insufficient data!'),_('No VAT number associated with your company.')) + raise osv.except_osv(_('Insufficient Data!'),_('No VAT number associated with your company.')) company_vat = company_vat.replace(' ','').upper() issued_by = company_vat[:2] @@ -120,7 +120,7 @@ class partner_vat_intra(osv.osv_memory): p_id_list = obj_partner.search(cr, uid, [('vat','!=',False)], context=context) if not p_id_list: - raise osv.except_osv(_('Insufficient Data!'),_('No partner has a VAT number asociated with him.')) + raise osv.except_osv(_('Insufficient Data!'),_('No partner has a VAT number associated with him.')) seq_declarantnum = obj_sequence.get(cr, uid, 'declarantnum') dnum = company_vat[2:] + seq_declarantnum[-4:] @@ -282,7 +282,6 @@ class partner_vat_intra(osv.osv_memory): 'datas': datas, } -partner_vat_intra() class vat_intra_print(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): diff --git a/addons/l10n_be_coda/wizard/account_coda_import.py b/addons/l10n_be_coda/wizard/account_coda_import.py index 213040d6204..8aabe601bc8 100644 --- a/addons/l10n_be_coda/wizard/account_coda_import.py +++ b/addons/l10n_be_coda/wizard/account_coda_import.py @@ -128,6 +128,8 @@ class account_coda_import(osv.osv_memory): raise osv.except_osv(_('Error') + ' R1004', _("No matching Bank Account (with Account Journal) found.\n\nPlease set-up a Bank Account with as Account Number '%s' and as Currency '%s' and an Account Journal.") % (statement['acc_number'], statement['currency'])) statement['description'] = rmspaces(line[90:125]) statement['balance_start'] = float(rmspaces(line[43:58])) / 1000 + if line[42] == '1': #1 = Debit, the starting balance is negative + statement['balance_start'] = - statement['balance_start'] statement['balance_start_date'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[58:64]), '%d%m%y')) statement['accountHolder'] = rmspaces(line[64:90]) statement['paperSeqNumber'] = rmspaces(line[2:5]) @@ -389,7 +391,7 @@ class account_coda_import(osv.osv_memory): if statement['coda_note'] != '': self.pool.get('account.bank.statement').write(cr, uid, [statement['id']], {'coda_note': statement['coda_note']}, context=context) model, action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'action_bank_statement_tree') - action = self.pool.get(model).browse(cr, uid, action_id, context=context) + action = self.pool[model].browse(cr, uid, action_id, context=context) return { 'name': action.name, 'view_type': action.view_type, diff --git a/addons/l10n_be_hr_payroll/l10n_be_hr_payroll.py b/addons/l10n_be_hr_payroll/l10n_be_hr_payroll.py index 79909cf79af..e62ea076079 100644 --- a/addons/l10n_be_hr_payroll/l10n_be_hr_payroll.py +++ b/addons/l10n_be_hr_payroll/l10n_be_hr_payroll.py @@ -39,7 +39,6 @@ class hr_contract_be(osv.osv): 'retained_net_amount': fields.float('Net retained ', digits_compute=dp.get_precision('Payroll')), } -hr_contract_be() class hr_employee_be(osv.osv): _inherit = 'hr.employee' @@ -52,6 +51,5 @@ class hr_employee_be(osv.osv): 'disabled_children_number': fields.integer('Number of disabled children'), } -hr_employee_be() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_be_invoice_bba/partner.py b/addons/l10n_be_invoice_bba/partner.py index 9e0eec10713..bf8d5d7a0c3 100644 --- a/addons/l10n_be_invoice_bba/partner.py +++ b/addons/l10n_be_invoice_bba/partner.py @@ -44,9 +44,13 @@ class res_partner(osv.osv): help='Select Algorithm to generate the Structured Communication on Outgoing Invoices.' ), } + def _commercial_fields(self, cr, uid, context=None): + return super(res_partner, self)._commercial_fields(cr, uid, context=context) + \ + ['out_inv_comm_type', 'out_inv_comm_algorithm'] + + _default = { 'out_inv_comm_type': 'none', } -res_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_bo/__init__.py b/addons/l10n_bo/__init__.py index 92da5dbf966..25e7e337165 100644 --- a/addons/l10n_bo/__init__.py +++ b/addons/l10n_bo/__init__.py @@ -23,7 +23,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/l10n_ca/__openerp__.py b/addons/l10n_ca/__openerp__.py index 05279b6ef8e..945327a06bc 100644 --- a/addons/l10n_ca/__openerp__.py +++ b/addons/l10n_ca/__openerp__.py @@ -20,7 +20,7 @@ ############################################################################## { 'name': 'Canada - Accounting', - 'version': '1.0', + 'version': '1.1', 'author': 'Savoir-faire Linux', 'website': 'http://www.savoirfairelinux.com', 'category': 'Localization/Account Charts', @@ -49,7 +49,7 @@ Canadian accounting charts and localizations. 'account_chart_template_fr.xml', 'account_tax_fr.xml', 'fiscal_templates_fr.xml', - 'l10n_ca_wizard.xml', + 'l10n_ca_wizard.xml' ], 'demo': [], 'installable': True, diff --git a/addons/l10n_ca/account_tax_en.xml b/addons/l10n_ca/account_tax_en.xml index 1ff884ac361..afe505f27f5 100644 --- a/addons/l10n_ca/account_tax_en.xml +++ b/addons/l10n_ca/account_tax_en.xml @@ -12,7 +12,6 @@ GSTPST_MB_SALE sale 1 - 1 percent @@ -39,7 +38,7 @@ PST for sales - 7%PSTsale - 0.700000 + 0.070000percent2 @@ -106,7 +105,6 @@ GSTTVQ_SALE sale 1 - 1 percent @@ -152,7 +150,6 @@ GSTPST_SK_SALE sale 1 - 1 percent @@ -281,7 +278,6 @@ GSTPST_MB_PURC purchase 1 - 1 percent @@ -308,7 +304,7 @@ PST for purchases - 7% PST purchase - 0.700000 + 0.070000 percent 2 @@ -375,7 +371,6 @@ GSTTVQ_PURC purchase 1 - 1 percent @@ -421,7 +416,6 @@ GSTPST_SK_PURC purchase 1 - 1 percent diff --git a/addons/l10n_ca/account_tax_fr.xml b/addons/l10n_ca/account_tax_fr.xml index b344feeec83..c34f329be3a 100644 --- a/addons/l10n_ca/account_tax_fr.xml +++ b/addons/l10n_ca/account_tax_fr.xml @@ -12,7 +12,6 @@ TPSTVP_MB_SALE sale 1 - 1 percent @@ -39,7 +38,7 @@ TVP sur les ventes - 7% TVP sale - 0.700000 + 0.070000 percent 2 @@ -106,7 +105,6 @@ TPSTVQ_SALE sale 1 - 1 percent @@ -152,7 +150,6 @@ TPSTVP_SK_SALE sale 1 - 1 percent @@ -281,7 +278,6 @@ TPSTVP_MB_PURC purchase 1 - 1 percent @@ -308,7 +304,7 @@ TVP sur les achats - 7% TVP purchase - 0.700000 + 0.070000 percent 2 @@ -375,7 +371,6 @@ TPSTVQ_PURC purchase 1 - 1 percent @@ -421,7 +416,6 @@ TPSTVP_SK_PURC purchase 1 - 1 percent diff --git a/addons/l10n_ca/fiscal_templates_en.xml b/addons/l10n_ca/fiscal_templates_en.xml index 68e881c3541..a3bab5b89dd 100644 --- a/addons/l10n_ca/fiscal_templates_en.xml +++ b/addons/l10n_ca/fiscal_templates_en.xml @@ -5,17 +5,17 @@ - Provincial Regime + Provincial Regime (PROV) - Harmonized Provinces Regime (12%) + Harmonized Provinces Regime (12%) (BC) - Harmonized Provinces Regime (13%) + Harmonized Provinces Regime (13%) (ON, NB, NL) @@ -25,17 +25,17 @@ - Harmonized Provinces Regime (15%) + Harmonized Provinces Regime (15%) (NS) - Non-Harmonized Provinces Regime + Non-Harmonized Provinces Regime (AB, MB, SK, PE, NT, NU, YT) - International Regime + International Regime (INTL) diff --git a/addons/l10n_ca/fiscal_templates_fr.xml b/addons/l10n_ca/fiscal_templates_fr.xml index 3ba13d6642e..b01ab0985ea 100644 --- a/addons/l10n_ca/fiscal_templates_fr.xml +++ b/addons/l10n_ca/fiscal_templates_fr.xml @@ -5,7 +5,7 @@ - Régime Provincial + Régime Provincial (PROV) @@ -30,12 +30,12 @@ - Régime Provinces Non-Harmonisées + Régime Provinces Non-Harmonisées (AB, MB, SK, PE, NT, NU, YT) - Régime International + Régime International (INTL) diff --git a/addons/l10n_ch/__init__.py b/addons/l10n_ch/__init__.py index f0b006c2b32..12d42707679 100644 --- a/addons/l10n_ch/__init__.py +++ b/addons/l10n_ch/__init__.py @@ -1,8 +1,11 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Author: Nicolas Bessi. Copyright Camptocamp SA -# Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA +# Financial contributors: Hasa SA, Open Net SA, +# Prisme Solutions Informatique SA, Quod SA +# +# Translation contributors: brain-tec AG, Agile Business Group # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/addons/l10n_ch/__openerp__.py b/addons/l10n_ch/__openerp__.py index e068c7365a1..8960224891d 100644 --- a/addons/l10n_ch/__openerp__.py +++ b/addons/l10n_ch/__openerp__.py @@ -1,8 +1,11 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Author: Nicolas Bessi. Copyright Camptocamp SA -# Donors: Hasa SA, Open Net SA and Prisme Solutions Informatique SA +# Financial contributors: Hasa SA, Open Net SA, +# Prisme Solutions Informatique SA, Quod SA +# +# Translation contributors: brain-tec AG, Agile Business Group # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -21,29 +24,29 @@ {'name': 'Switzerland - Accounting', 'description': """ -Swiss localization : -==================== -**Multilang swiss STERCHI account chart and taxes** - **Author:** Camptocamp SA + Swiss localization : + ==================== + **Multilang swiss STERCHI account chart and taxes** + **Author:** Camptocamp SA - **Donors:** Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA + **Financial contributors:** Prisme Solutions Informatique SA, Quod SA - **Translators:** brain-tec AG, Agile Business Group + **Translation contributors:** brain-tec AG, Agile Business Group -**This release will introduce major changes to l10n_ch.** + **This release will introduce major changes to l10n_ch.** -Due to important refactoring needs and the Switzerland adoption of new international payment standard during 2013-2014. We have reorganised the swiss localization addons this way: + Due to important refactoring needs and the Switzerland adoption of new international payment standard during 2013-2014. We have reorganised the swiss localization addons this way: -- **l10n_ch**: Multilang swiss STERCHI account chart and taxes (official addon) -- **l10n_ch_base_bank**: Technical module that introduces a new and simplified version of bank type management -- **l10n_ch_bank**: List of swiss banks -- **l10n_ch_zip**: List of swiss postal zip -- **l10n_ch_dta**: Support of dta payment protocol (will be deprecated end 2014) -- **l10n_ch_payment_slip**: Support of ESR/BVR payment slip report and reconciliation. Report refactored with easy element positioning. -- **l10n_ch_sepa**: Alpha implementation of PostFinance SEPA/PAIN support will be completed during 2013/2014 + - **l10n_ch**: Multilang swiss STERCHI account chart and taxes (official addon) + - **l10n_ch_base_bank**: Technical module that introduces a new and simplified version of bank type management + - **l10n_ch_bank**: List of swiss banks + - **l10n_ch_zip**: List of swiss postal zip + - **l10n_ch_dta**: Support of dta payment protocol (will be deprecated end 2014) + - **l10n_ch_payment_slip**: Support of ESR/BVR payment slip report and reconciliation. Report refactored with easy element positioning. + - **l10n_ch_sepa**: Alpha implementation of PostFinance SEPA/PAIN support will be completed during 2013/2014 -The modules will be soon available on OpenERP swiss localization on launchpad: -https://launchpad.net/openerp-swiss-localization + The modules will be soon available on OpenERP swiss localization on launchpad: + https://launchpad.net/openerp-swiss-localization """, 'version': '7.0', 'author': 'Camptocamp', diff --git a/addons/l10n_ch/account_wizard.py b/addons/l10n_ch/account_wizard.py index e0a9e84b90a..4b985c09b76 100644 --- a/addons/l10n_ch/account_wizard.py +++ b/addons/l10n_ch/account_wizard.py @@ -1,8 +1,11 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # Author: Nicolas Bessi. Copyright Camptocamp SA -# Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA +# Financial contributors: Hasa SA, Open Net SA, +# Prisme Solutions Informatique SA, Quod SA +# +# Translation contributors: brain-tec AG, Agile Business Group # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/addons/l10n_cl/__init__.py b/addons/l10n_cl/__init__.py index 92da5dbf966..25e7e337165 100644 --- a/addons/l10n_cl/__init__.py +++ b/addons/l10n_cl/__init__.py @@ -23,7 +23,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/l10n_cr/l10n_cr_base_data.xml b/addons/l10n_cr/l10n_cr_base_data.xml index 2268ecb37ed..28674185a85 100644 --- a/addons/l10n_cr/l10n_cr_base_data.xml +++ b/addons/l10n_cr/l10n_cr_base_data.xml @@ -1,4 +1,3 @@ - @@ -8,38 +7,38 @@ --> SJ - San José - + San José + A Alajuela - + H Heredia - + C Cartago - + P Puntarenas - + G Guanacaste - + L - Limón - + Limón + @@ -2722,7 +2722,7 @@ view - Amortización acumulada de otras instaciones + Amortización acumulada de otras instalaciones @@ -2730,7 +2730,7 @@ other - Amortización acumulada de otras instaciones + Amortización acumulada de otras instalaciones @@ -4743,7 +4743,7 @@ 460 - + other Anticipos de remuneraciones @@ -4759,7 +4759,7 @@ 465 - + other Remuneraciones pendientes de pago @@ -4775,7 +4775,7 @@ 466 - + other Remuneraciones mediante sistemas de aportación definida pendientes de pago @@ -4805,8 +4805,8 @@ Hacienda Pública, deudora por IVA - - 4700 + + 470000 receivable @@ -4869,6 +4869,14 @@ Hacienda Pública, IVA soportado + + 472000 + + + other + Hacienda Pública. IVA soportado + + 473 @@ -4877,6 +4885,14 @@ Hacienda Pública, retenciones y pagos a cuenta + + 473000 + + + other + Hacienda Pública, retenciones y pagos a cuenta + + 474 @@ -4949,8 +4965,8 @@ Hacienda Pública, acreedora por IVA - - 4750 + + 475000 payable @@ -4965,8 +4981,8 @@ Hacienda Pública, acreedora por retenciones practicadas - - 4751 + + 475100 payable @@ -5029,6 +5045,14 @@ Hacienda Pública, IVA repercutido + + 477000 + + + other + Hacienda Pública. IVA repercutido + + 479 @@ -8722,7 +8746,7 @@ view - Ingresos de créditos a largo plazo + Intereses de deudas @@ -8730,7 +8754,7 @@ view - Ingresos de créditos a largo plazo, empresas del grupo + Intereses de deudas, empresas del grupo @@ -8738,7 +8762,7 @@ other - Ingresos de créditos a largo plazo, empresas del grupo + Intereses de deudas, empresas del grupo @@ -8746,7 +8770,7 @@ view - Ingresos de créditos a largo plazo, empresas asociadas + Intereses de deudas, empresas asociadas @@ -8754,7 +8778,7 @@ other - Ingresos de créditos a largo plazo, empresas asociadas + Intereses de deudas, empresas asociadas @@ -8762,7 +8786,7 @@ view - Ingresos de créditos a largo plazo, otras partes vinculadas + Intereses de deudas, otras partes vinculadas @@ -8770,7 +8794,7 @@ other - Ingresos de créditos a largo plazo, otras partes vinculadas + Intereses de deudas, otras partes vinculadas @@ -8778,7 +8802,7 @@ view - Ingresos de créditos a largo plazo con entidades de crédito + Intereses de deudas con entidades de crédito @@ -8786,7 +8810,7 @@ other - Ingresos de créditos a largo plazo con entidades de crédito + Intereses de deudas con entidades de crédito @@ -8794,7 +8818,7 @@ view - Ingresos de créditos a largo plazo, otras empresas + Intereses de deudas, otras empresas @@ -8802,7 +8826,7 @@ other - Ingresos de créditos a largo plazo, otras empresas + Intereses de deudas, otras empresas diff --git a/addons/l10n_es/account_chart_assoc.xml b/addons/l10n_es/account_chart_assoc.xml new file mode 100644 index 00000000000..670eed53c9b --- /dev/null +++ b/addons/l10n_es/account_chart_assoc.xml @@ -0,0 +1,12426 @@ + + + + + + + + + 0 + + + view + Plan General Contable ASOCIACIONES 2008 + + + + + 1 + + + view + Financiación Básica + + + + 10 + + + view + Capital + + + + + 100 + + + view + Dotación fundacional + + + + 100 + + + other + Dotación fundacional + + + + 101 + + + view + Fondo social + + + + 101 + + + other + Fondo social + + + + 102 + + + view + Capital + + + + 102 + + + other + Capital + + + + 103 + + + view + Fundadores/asociados por desembolsos no exigidos + + + + 1030 + + + view + Fundadores, parte no desembolsada en fundaciones + + + + 1030 + + + other + Fundadores, parte no desembolsada en fundaciones + + + + 1034 + + + view + Asociados, parte no desembolsada en asociaciones + + + + 1034 + + + other + Asociados, parte no desembolsada en asociaciones + + + + 104 + + + view + Fundadores/asociados por aportaciones no dinerarias pendientes + + + + 1040 + + + view + Fundadores, por aportaciones no dinerarias pendientes, en fundaciones + + + + 1040 + + + other + Fundadores, por aportaciones no dinerarias pendientes, en fundaciones + + + + 1044 + + + view + Asociados, por aportaciones no dinerarias pendientes, en asociaciones + + + + 1044 + + + other + Asociados, por aportaciones no dinerarias pendientes, en asociaciones + + + + 108 + + + view + Acciones o participaciones propias en situaciones especiales + + + + 108 + + + other + Acciones o participaciones propias en situaciones especiales + + + + 109 + + + view + Acciones o participaciones propias para reducción de capital + + + + 109 + + + other + Acciones o participaciones propias para reducción de capital + + + + 11 + + + view + Reservas y otros instrumentos de patrimonio + + + + 110 + + + view + Prima de Emisión o asunción + + + + 110 + + + other + Prima de Emisión o asunción + + + + 112 + + + view + Reserva Legal + + + + 112 + + + other + Reserva Legal + + + + 113 + + + view + Reservas voluntarias + + + + 113 + + + other + Reservas voluntarias + + + + 114 + + + view + Reservas especiales + + + + 1140 + + + view + Reservas para acciones o participaciones de la sociedad dominante + + + + 1140 + + + other + Reservas para acciones o participaciones de la sociedad dominante + + + + 1141 + + + view + Reservas estatutarias + + + + 1141 + + + other + Reservas estatutarias + + + + 1142 + + + view + Reserva por capital amortizado + + + + 1142 + + + other + Reserva por capital amortizado + + + + 1144 + + + view + Reservas por acciones propias aceptadas en garantía + + + + 1144 + + + other + Reservas por acciones propias aceptadas en garantía + + + + 118 + + + view + Aportaciones de socios o propietarios + + + + 118 + + + other + Aportaciones de socios o propietarios + + + + 119 + + + view + Diferencias por ajuste del capital a euros + + + + 119 + + + other + Diferencias por ajuste del capital a euros + + + + 12 + + + view + Excedentes pendientes de aplicación + + + + 120 + + + view + Remanente + + + + 120 + + + other + Remanente + + + + 121 + + + view + Excedentes negativos de ejercicios anteriores + + + + 121 + + + other + Excedentes negativos de ejercicios anteriores + + + + 129 + + + view + Excedente del ejercicio + + + + 129 + + + other + Excedente del ejercicio + + + + 13 + + + view + Subvenciones, donaciones y ajustes por cambio de valor + + + + 130 + + + view + Subvenciones oficiales de capital + + + + 1300 + + + view + Subvenciones del Estado + + + + 1300 + + + other + Subvenciones del Estado + + + + 1301 + + + view + Subvenciones de otras Administraciones Públicas + + + + 1301 + + + other + Subvenciones de otras Administraciones Públicas + + + + 131 + + + view + Donaciones y legados de capital + + + + 131 + + + other + Donaciones y legados de capital + + + + 132 + + + view + Otras subvenciones, donaciones y legados + + + + 1320 + + + view + Otras subvenciones + + + + 1320 + + + other + Otras subvenciones + + + + 1321 + + + view + Otras donaciones y legados + + + + 1321 + + + other + Otras donaciones y legados + + + + + 137 + + + view + Ingresos fiscales a distribuir en varios ejercicios + + + + 1370 + + + view + Ingresos fiscales por diferencias permanentes a distribuir en varios ejercicios + + + + 1370 + + + other + Ingresos fiscales por diferencias permanentes a distribuir en varios ejercicios + + + + 1371 + + + view + Ingresos fiscales por deducciones y bonificaciones a distribuir en varios ejercicios + + + + 1371 + + + other + Ingresos fiscales por deducciones y bonificaciones a distribuir en varios ejercicios + + + + 14 + + + view + Provisiones + + + + 141 + + + view + Provisión para impuestos + + + + 141 + + + other + Provisión para impuestos + + + + 142 + + + view + Provisión para otras responsabilidades + + + + 142 + + + other + Provisión para otras responsabilidades + + + + 143 + + + view + Provisión por desmantelamiento, retiro o rehabilitación del inmovilizado + + + + 143 + + + other + Provisión por desmantelamiento, retiro o rehabilitación del inmovilizado + + + + 145 + + + view + Provisión para actuaciones medioambientales + + + + 145 + + + other + Provisión para actuaciones medioambientales + + + + 15 + + + view + Deudas con características especiales + + + + 150 + + + view + Acciones o participaciones consideradas como pasivos financieros + + + + 150 + + + other + Acciones o participaciones consideradas como pasivos financieros + + + + 153 + + + view + Desembolsos no exigidos por acciones o participaciones consideradas como pasivos financieros + + + + 1533 + + + view + Desembolsos no exigidos, empresas del grupo + + + + 1533 + + + other + Desembolsos no exigidos, empresas del grupo + + + + 1534 + + + view + Desembolsos no exigidos, empresas asociadas + + + + 1534 + + + other + Desembolsos no exigidos, empresas asociadas + + + + 1535 + + + view + Desembolsos no exigidos, otras partes vinculadas + + + + 1535 + + + other + Desembolsos no exigidos, otras partes vinculadas + + + + 1536 + + + view + Otros desembolsos no exigidos + + + + 1536 + + + other + Otros desembolsos no exigidos + + + + 154 + + + view + Aportaciones no dinerarias pendientes por acciones o participaciones consideradas como pasivos financieros + + + + 1543 + + + view + Aportaciones no dinerarias pendientes, empresas del grupo + + + + 1543 + + + other + Aportaciones no dinerarias pendientes, empresas del grupo + + + + 1544 + + + view + Aportaciones no dinerarias pendientes, empresas asociadas + + + + 1544 + + + other + Aportaciones no dinerarias pendientes, empresas asociadas + + + + 1545 + + + view + Aportaciones no dinerarias pendientes, otras partes vinculadas + + + + 1545 + + + other + Aportaciones no dinerarias pendientes, otras partes vinculadas + + + + 1546 + + + view + Otras aportaciones no dinerarias pendientes + + + + 1546 + + + other + Otras aportaciones no dinerarias pendientes + + + + 16 + + + view + Deudas con partes vinculadas + + + + 160 + + + view + Deudas con entidades de crédito vinculadas + + + + 1603 + + + view + Deudas con entidades de crédito vinculadas, empresas del grupo + + + + 1603 + + + other + Deudas con entidades de crédito vinculadas, empresas del grupo + + + + 1604 + + + view + Deudas con entidades de crédito vinculadas, empresas asociadas + + + + 1604 + + + other + Deudas con entidades de crédito vinculadas, empresas asociadas + + + + 1605 + + + view + Deudas con otras entidades de crédito vinculadas + + + + 1605 + + + other + Deudas con otras entidades de crédito vinculadas + + + + 161 + + + view + Proveedores de inmovilizado, partes vinculadas + + + + 1613 + + + view + Proveedores de inmovilizado, empresas del grupo + + + + 1613 + + + other + Proveedores de inmovilizado, empresas del grupo + + + + 1614 + + + view + Proveedores de inmovilizado, empresas asociadas + + + + 1614 + + + other + Proveedores de inmovilizado, empresas asociadas + + + + 1615 + + + view + Proveedores de inmovilizado, otras partes vinculadas + + + + 1615 + + + other + Proveedores de inmovilizado, otras partes vinculadas + + + + 162 + + + view + Acreedores por arrendamiento financiero, partes vinculadas + + + + 1623 + + + view + Acreedores por arrendamiento financiero, empresas de grupo + + + + 1623 + + + other + Acreedores por arrendamiento financiero, empresas de grupo + + + + 1624 + + + view + Acreedores por arrendamiento financiero, empresas asociadas + + + + 1624 + + + other + Acreedores por arrendamiento financiero, empresas asociadas + + + + 1625 + + + view + Acreedores por arrendamiento financiero, otras partes vinculadas + + + + 1625 + + + other + Acreedores por arrendamiento financiero, otras partes vinculadas + + + + 163 + + + view + Otras deudas con partes vinculadas + + + + 1633 + + + view + Otras deudas, empresas del grupo + + + + 1633 + + + other + Otras deudas, empresas del grupo + + + + 1634 + + + view + Otras deudas, empresas asociadas + + + + 1634 + + + other + Otras deudas, empresas asociadas + + + + 1635 + + + view + Otras deudas, con otras partes vinculadas + + + + 1635 + + + other + Otras deudas, con otras partes vinculadas + + + + 17 + + + view + Deudas por préstamos recibidos, empréstitos y otros conceptos + + + + 170 + + + view + Deudas con entidades de crédito + + + + 170 + + + other + Deudas con entidades de crédito + + + + 171 + + + view + Deudas + + + + 171 + + + other + Deudas + + + + 172 + + + view + Deudas transformables en subvenciones, donaciones y legados + + + + 172 + + + other + Deudas transformables en subvenciones, donaciones y legados + + + + 173 + + + view + Proveedores de inmovilizado + + + + 173 + + + other + Proveedores de inmovilizado + + + + 174 + + + view + Acreedores por arrendamiento financiero + + + + 174 + + + other + Acreedores por arrendamiento financiero + + + + 175 + + + view + Efectos a pagar + + + + 175 + + + other + Efectos a pagar + + + + 176 + + + view + Pasivos por derivados financieros + + + + 176 + + + other + Pasivos por derivados financieros + + + + 177 + + + view + Obligaciones y bonos + + + + 177 + + + other + Obligaciones y bonos + + + + 179 + + + view + Deudas representadas en otros valores negociables + + + + 179 + + + other + Deudas representadas en otros valores negociables + + + + 18 + + + view + Pasivos por fianzas, garantías y otros conceptos + + + + 180 + + + view + Fianzas recibidas + + + + 180 + + + other + Fianzas recibidas + + + + 181 + + + view + Anticipos recibidos por ventas o prestaciones de servicios + + + + 181 + + + other + Anticipos recibidos por ventas o prestaciones de servicios + + + + 185 + + + view + Depósitos recibidos + + + + 185 + + + other + Depósitos recibidos + + + + 19 + + + view + Situaciones transitorias de financiación + + + + 190 + + + view + Acciones o participaciones emitidas + + + + 190 + + + other + Acciones o participaciones emitidas + + + + 192 + + + view + Suscriptores de acciones + + + + 192 + + + other + Suscriptores de acciones + + + + 194 + + + view + Capital emitido pendiente de inscripción + + + + 194 + + + other + Capital emitido pendiente de inscripción + + + + 195 + + + view + Acciones o participaciones emitidas consideradas como pasivos financieros + + + + 195 + + + other + Acciones o participaciones emitidas consideradas como pasivos financieros + + + + 197 + + + view + Suscriptores de acciones consideradas como pasivos financieros + + + + 197 + + + other + Suscriptores de acciones consideradas como pasivos financieros + + + + 199 + + + view + Acciones o participaciones emitidas consideradas como pasivos financieros pendientes de inscripción + + + + 199 + + + other + Acciones o participaciones emitidas consideradas como pasivos financieros pendientes de inscripción + + + + 2 + + + view + Activo no corriente + + + + 20 + + + view + Inmovilizaciones intangibles + + + + 200 + + + view + Investigación + + + + 200 + + + other + Investigación + + + + 201 + + + view + Desarrollo + + + + 201 + + + other + Desarrollo + + + + 202 + + + view + Concesiones administrativas + + + + 202 + + + other + Concesiones administrativas + + + + 203 + + + view + Propiedad industrial + + + + 203 + + + other + Propiedad industrial + + + + 205 + + + view + Derechos de traspaso + + + + 205 + + + other + Derechos de traspaso + + + + 206 + + + view + Aplicaciones informáticas + + + + 206 + + + other + Aplicaciones informáticas + + + + 207 + + + view + Derechos sobre activos cedidos en uso + + + + 207 + + + other + Derechos sobre activos cedidos en uso + + + + 209 + + + view + Anticipos para inmovilizaciones intangibles + + + + 209 + + + other + Anticipos para inmovilizaciones intangibles + + + + 21 + + + view + Inmovilizaciones materiales + + + + 210 + + + view + Terrenos y bienes naturales + + + + 210 + + + other + Terrenos y bienes naturales + + + + 211 + + + view + Construcciones + + + + 211 + + + other + Construcciones + + + + 212 + + + view + Instalaciones técnicas + + + + 212 + + + other + Instalaciones técnicas + + + + 213 + + + view + Maquinaria + + + + 213 + + + other + Maquinaria + + + + 214 + + + view + Utillaje + + + + 214 + + + other + Utillaje + + + + 215 + + + view + Otras instalaciones + + + + 215 + + + other + Otras instalaciones + + + + 216 + + + view + Mobiliario + + + + 216 + + + other + Mobiliario + + + + 217 + + + view + Equipos para proceso de información + + + + 217 + + + other + Equipos para proceso de información + + + + 218 + + + view + Elementos de transporte + + + + 218 + + + other + Elementos de transporte + + + + 219 + + + view + Otro inmovilizado material + + + + 219 + + + other + Otro inmovilizado material + + + + 22 + + + view + Inversiones inmobiliarias + + + + 220 + + + view + Inversiones en terrenos y bienes naturales + + + + 220 + + + other + Inversiones en terrenos y bienes naturales + + + + 221 + + + view + Inversiones en construcciones + + + + 221 + + + other + Inversiones en construcciones + + + + 23 + + + view + Inmovilizaciones materiales en curso + + + + 230 + + + view + Adaptación de terrenos y bienes naturales + + + + 230 + + + other + Adaptación de terrenos y bienes naturales + + + + 231 + + + view + Construcciones en curso + + + + 231 + + + other + Construcciones en curso + + + + 232 + + + view + Instalaciones técnicas en montaje + + + + 232 + + + other + Instalaciones técnicas en montaje + + + + 233 + + + view + Maquinaria en montaje + + + + 233 + + + other + Maquinaria en montaje + + + + 237 + + + view + Equipos para procesos de información en montaje + + + + 237 + + + other + Equipos para procesos de información en montaje + + + + 239 + + + view + Anticipos para inmovilizaciones materiales + + + + 239 + + + other + Anticipos para inmovilizaciones materiales + + + + 24 + + + view + Bienes del patrimonio histórico + + + + 240 + + + view + Bienes inmuebles + + + + 2400 + + + view + Monumentos + + + + 2400 + + + other + Monumentos + + + + + 2401 + + + view + Jardines históricos + + + + 2401 + + + other + Jardines históricos + + + + + 2402 + + + view + Conjuntos históricos + + + + 2402 + + + other + Conjuntos históricos + + + + + 2403 + + + view + Sitios históricos + + + + 2403 + + + other + Sitios históricos + + + + 2404 + + + view + Zonas arqueológicas + + + + 2404 + + + other + Zonas arqueológicas + + + + 2405 + + + view + Participaciones en otras partes vinculadas + + + + 2405 + + + other + Participaciones en otras partes vinculadas + + + + 241 + + + view + Archivos + + + + 2413 + + + view + Valores representativos de deuda de empresas del grupo + + + + 2413 + + + other + Valores representativos de deuda de empresas del grupo + + + + 2414 + + + view + Valores representativos de deuda de empresas asociadas + + + + 2414 + + + other + Valores representativos de deuda de empresas asociadas + + + + 2415 + + + view + Valores representativos de deuda de otras partes vinculadas + + + + 2415 + + + other + Valores representativos de deuda de otras partes vinculadas + + + + 242 + + + view + Bibliotecas + + + + 2423 + + + view + Créditos a empresas del grupo + + + + 2423 + + + other + Créditos a empresas del grupo + + + + 2424 + + + view + Créditos a empresas asociadas + + + + 2424 + + + other + Créditos a empresas asociadas + + + + 2425 + + + view + Créditos a otras partes vinculadas + + + + 2425 + + + other + Créditos a otras partes vinculadas + + + + + 243 + + + view + Museos + + + + + 243 + + + other + Museos + + + + + 244 + + + view + Bienes muebles + + + + + 244 + + + other + Bienes muebles + + + + + + 249 + + + view + Anticipos sobre bienes del Patrimonio Histórico + + + + + 2490 + + + view + Anticipos sobre bienes inmuebles del Patrimonio Histórico + + + + 2490 + + + other + Anticipos sobre bienes inmuebles del Patrimonio Histórico + + + + + 2491 + + + view + Anticipos sobre archivos del Patrimonio Histórico + + + + 2491 + + + other + Anticipos sobre archivos del Patrimonio Histórico + + + + + 2492 + + + view + Anticipos sobre bibliotecas del Patrimonio Histórico + + + + 2492 + + + other + Anticipos sobre bibliotecas del Patrimonio Histórico + + + + + + 2493 + + + view + Anticipos sobre museos del Patrimonio Histórico + + + + 2493 + + + other + Anticipos sobre museos del Patrimonio Histórico + + + + + 2494 + + + view + Anticipos sobre bienes muebles del Patrimonio Histórico + + + + 2494 + + + other + Anticipos sobre bienes muebles del Patrimonio Histórico + + + + 2495 + + + view + Desembolsos pendientes sobre participaciones en otras partes vinculadas + + + + 2495 + + + other + Desembolsos pendientes sobre participaciones en otras partes vinculadas + + + + 25 + + + view + Otras inversiones financieras + + + + 250 + + + view + Inversiones financieras en instrumentos de patrimonio + + + + 250 + + + other + Inversiones financieras en instrumentos de patrimonio + + + + 251 + + + view + Valores representativos de deuda + + + + 251 + + + other + Valores representativos de deuda + + + + 252 + + + view + Créditos + + + + 252 + + + other + Créditos + + + + 253 + + + view + Créditos por enajenación de inmovilizado + + + + 253 + + + other + Créditos por enajenación de inmovilizado + + + + 254 + + + view + Créditos al personal + + + + 254 + + + other + Créditos al personal + + + + 255 + + + view + Activos por derivados financieros + + + + 255 + + + other + Activos por derivados financieros + + + + 258 + + + view + Imposiciones + + + + 258 + + + other + Imposiciones + + + + 259 + + + view + Desembolsos pendientes sobre participaciones en el patrimonio neto + + + + 259 + + + other + Desembolsos pendientes sobre participaciones en el patrimonio neto + + + + 26 + + + view + Fianzas y depósitos constituidos + + + + 260 + + + view + Fianzas constituidas + + + + 260 + + + other + Fianzas constituidas + + + + 265 + + + view + Depósitos constituidos + + + + 265 + + + other + Depósitos constituidos + + + + 28 + + + view + Amortización acumulada del inmovilizado y otras cuentas correctoras + + + + 280 + + + view + Amortización acumulada del inmovilizado intangible + + + + + 2800 + + + view + Amortización acumulada de investigación + + + + 2800 + + + other + Amortización acumulada de investigación + + + + + + 2801 + + + view + Amortización acumulada de desarrollo + + + + 2801 + + + other + Amortización acumulada de desarrollo + + + + 2802 + + + view + Amortización acumulada de concesiones administrativas + + + + 2802 + + + other + Amortización acumulada de concesiones administrativas + + + + 2803 + + + view + Amortización acumulada de propiedad industrial + + + + 2803 + + + other + Amortización acumulada de propiedad industrial + + + + 2805 + + + view + Amortización acumulada de derechos de traspaso + + + + 2805 + + + other + Amortización acumulada de derechos de traspaso + + + + + 2806 + + + view + Amortización acumulada de aplicaciones informáticas + + + + 2806 + + + other + Amortización acumulada de aplicaciones informáticas + + + + + 2807 + + + view + Amortización acumulada de derechos sobre activos cedidos en uso + + + + 2807 + + + other + Amortización acumulada de derechos sobre activos cedidos en uso + + + + + + + 281 + + + view + Amortización acumulada del inmovilizado material + + + + 2811 + + + view + Amortización acumulada de construcciones + + + + 2811 + + + other + Amortización acumulada de construcciones + + + + 2812 + + + view + Amortización acumulada de instalaciones técnicas + + + + 2812 + + + other + Amortización acumulada de instalaciones técnicas + + + + 2813 + + + view + Amortización acumulada de maquinaria + + + + 2813 + + + other + Amortización acumulada de maquinaria + + + + 2814 + + + view + Amortización acumulada de utillaje + + + + 2814 + + + other + Amortización acumulada de utillaje + + + + 2815 + + + view + Amortización acumulada de otras instaciones + + + + 2815 + + + other + Amortización acumulada de otras instaciones + + + + 2816 + + + view + Amortización acumulada de mobiliario + + + + 2816 + + + other + Amortización acumulada de mobiliario + + + + 2817 + + + view + Amortización acumulada de equipos para proceso de información + + + + 2817 + + + other + Amortización acumulada de equipos para proceso de información + + + + 2818 + + + view + Amortización acumulada de elementos de transporte + + + + 2818 + + + other + Amortización acumulada de elementos de transporte + + + + 2819 + + + view + Amortización acumulada de otro inmovilizado material + + + + 2819 + + + other + Amortización acumulada de otro inmovilizado material + + + + 282 + + + view + Amortización acumulada de las inversiones inmobiliarias + + + + 282 + + + other + Amortización acumulada de las inversiones inmobiliarias + + + + + 283 + + + view + Cesiones de uso sin contraprestación + + + + 2830 + + + view + Cesiones de uso del inmovilizado intangible + + + + 2830 + + + other + Cesiones de uso del inmovilizado intangible + + + + + + 2831 + + + view + Cesiones de uso del inmovilizado material + + + + 2831 + + + other + Cesiones de uso del inmovilizado material + + + + + + 2832 + + + view + Cesiones de uso de las inversiones inmobiliarias + + + + + + 2832 + + + other + Cesiones de uso de las inversiones inmobiliarias + + + + + + 29 + + + view + Deterioro de valor de activos no corrientes + + + + 290 + + + view + Deterioro de valor del inmovilizado intangible + + + + 2900 + + + view + Deterioro del valor de investigación + + + + 2900 + + + other + Deterioro del valor de investigación + + + + 2901 + + + view + Deterioro del valor de desarrollo + + + + 2901 + + + other + Deterioro del valor de desarrollo + + + + 2902 + + + view + Deterioro del valor de concesiones administrativas + + + + 2902 + + + other + Deterioro del valor de concesiones administrativas + + + + 2903 + + + view + Deterioro del valor de propiedad industrial + + + + 2903 + + + other + Deterioro del valor de propiedad industrial + + + + 2905 + + + view + Deterioro del valor de derechos de traspaso + + + + 2905 + + + other + Deterioro del valor de derechos de traspaso + + + + 2906 + + + view + Deterioro del valor de aplicaciones informáticas + + + + 2906 + + + other + Deterioro del valor de aplicaciones informáticas + + + + + 2907 + + + view + Deterioro del valor sobre activos cedidos en uso + + + + 2907 + + + other + Deterioro del valor sobre activos cedidos en uso + + + + + + + + 291 + + + view + Deterioro del valor del inmovilizado material + + + + 2910 + + + view + Deterioro de valor de terrenos y bienes naturales + + + + 2910 + + + other + Deterioro de valor de terrenos y bienes naturales + + + + 2911 + + + view + Deterioro de valor de construcciones + + + + 2911 + + + other + Deterioro de valor de construcciones + + + + 2912 + + + view + Deterioro de valor de instalaciones técnicas + + + + 2912 + + + other + Deterioro de valor de instalaciones técnicas + + + + 2913 + + + view + Deterioro de valor de maquinaria + + + + 2913 + + + other + Deterioro de valor de maquinaria + + + + 2914 + + + view + Deterioro de valor de utillaje + + + + 2914 + + + other + Deterioro de valor de utillaje + + + + 2915 + + + view + Deterioro de valor de otras instaciones + + + + 2915 + + + other + Deterioro de valor de otras instaciones + + + + 2916 + + + view + Deterioro de valor de mobiliario + + + + 2916 + + + other + Deterioro de valor de mobiliario + + + + 2917 + + + view + Deterioro de valor de equipos para proceso de información + + + + 2917 + + + other + Deterioro de valor de equipos para proceso de información + + + + 2918 + + + view + Deterioro de valor de elementos de transporte + + + + 2918 + + + other + Deterioro de valor de elementos de transporte + + + + 2919 + + + view + Deterioro de valor de otro inmovilizado material + + + + 2919 + + + other + Deterioro de valor de otro inmovilizado material + + + + 292 + + + view + Deterioro de valor de las inversiones inmobiliarias + + + + 2920 + + + view + Deterioro de valor de los terrenos y bienes naturales + + + + 2920 + + + other + Deterioro de valor de los terrenos y bienes naturales + + + + 2921 + + + view + Deterioro de valor de construcciones + + + + 2921 + + + other + Deterioro de valor de construcciones + + + + 293 + + + view + Deterioro de valor de participaciones en partes vinculadas + + + + 2933 + + + view + Deterioro de valor de participaciones en empresas del grupo + + + + 2933 + + + other + Deterioro de valor de participaciones en empresas del grupo + + + + 2934 + + + view + Deterioro de valor de participaciones en empresas asociadas + + + + 2934 + + + other + Deterioro de valor de participaciones en empresas asociadas + + + + 2935 + + + view + Deterioro de valor de participaciones a largo plazo en otras partes vinculadas + + + + 2935 + + + other + Deterioro de valor de participaciones a largo plazo en otras partes vinculadas + + + + 294 + + + view + Deterioro de valor de valores representativos de deuda de partes vinculadas + + + + 2943 + + + view + Deterioro de valor de valores representativos de deuda de empresas del grupo + + + + 2943 + + + other + Deterioro de valor de valores representativos de deuda de empresas del grupo + + + + 2944 + + + view + Deterioro de valor de valores representativos de deuda de empresas asociadas + + + + 2944 + + + other + Deterioro de valor de valores representativos de deuda de empresas asociadas + + + + 2945 + + + view + Deterioro de valor de valores representativos de deuda de otras partes vinculadas + + + + 2945 + + + other + Deterioro de valor de valores representativos de deuda de otras partes vinculadas + + + + 295 + + + view + Deterioro de valor de créditos a partes vinculadas + + + + 2953 + + + view + Deterioro de valor de créditos a empresas del grupo + + + + 2953 + + + other + Deterioro de valor de créditos a empresas del grupo + + + + 2954 + + + view + Deterioro de valor de créditos a empresas asociadas + + + + 2954 + + + other + Deterioro de valor de créditos a empresas asociadas + + + + 2955 + + + view + Deterioro de valor de créditos a otras partes vinculadas + + + + 2955 + + + other + Deterioro de valor de créditos a otras partes vinculadas + + + + 296 + + + view + Deterioro de valor de participaciones en el patrimonio neto a largo plazo + + + + 296 + + + other + Deterioro de valor de participaciones en el patrimonio neto a largo plazo + + + + 297 + + + view + Deterioro de valor de valores representativos de deuda + + + + 297 + + + other + Deterioro de valor de valores representativos de deuda + + + + + 298 + + + view + Deterioro de valor de créditos + + + + 298 + + + other + Deterioro de valor de créditos + + + + + 299 + + + view + Deterioro de valor de bienes del Patrimonio Histórico + + + + 299 + + + other + Deterioro de valor de bienes del Patrimonio Histórico + + + + + 2990 + + + view + Deterioro de valor de bienes inmuebles + + + + + 2991 + + + view + Deterioro de valor de archivos + + + + 2991 + + + other + Deterioro de valor de archivos + + + + + + 2992 + + + view + Deterioro de valor de bibliotecas + + + + 2992 + + + other + Deterioro de valor de bibliotecas + + + + + 2993 + + + view + Deterioro de valor de Museos + + + + 2993 + + + other + Deterioro de valor de Museos + + + + + + 2994 + + + view + Deterioro de valor de bienes muebles + + + + 2994 + + + other + Deterioro de valor de bienes muebles + + + + + + 3 + + + view + Existencias + + + + 30 + + + view + Bienes destinados a la actividad + + + + 300 + + + view + Mercaderías A + + + + 300 + + + other + Mercaderías A + + + + 301 + + + view + Mercaderías B + + + + 301 + + + other + Mercaderías B + + + + 31 + + + view + Materias Primas + + + + 310 + + + view + Materias Primas A + + + + 310 + + + other + Materias Primas A + + + + 311 + + + view + Materias Primas B + + + + 311 + + + other + Materias Primas B + + + + 32 + + + view + Otros aprovisionamientos + + + + 320 + + + view + Elementos y conjuntos incorporables + + + + 320 + + + other + Elementos y conjuntos incorporables + + + + 321 + + + view + Combustibles + + + + 321 + + + other + Combustibles + + + + 322 + + + view + Repuestos + + + + 322 + + + other + Repuestos + + + + 325 + + + view + Materiales diversos + + + + 325 + + + other + Materiales diversos + + + + 326 + + + view + Embalajes + + + + 326 + + + other + Embalajes + + + + 327 + + + view + Envases + + + + 327 + + + other + Envases + + + + 328 + + + view + Material de oficina + + + + 328 + + + other + Material de oficina + + + + 33 + + + view + Productos en curso + + + + 330 + + + view + Productos en curso A + + + + 330 + + + other + Productos en curso A + + + + 331 + + + view + Productos en curso B + + + + 331 + + + other + Productos en curso B + + + + 34 + + + view + Productos semiterminados + + + + 340 + + + view + Productos semiterminados A + + + + 340 + + + other + Productos semiterminados A + + + + 341 + + + view + Productos semiterminados B + + + + 341 + + + other + Productos semiterminados B + + + + 35 + + + view + Productos terminados + + + + 350 + + + view + Productos terminados A + + + + 350 + + + other + Productos terminados A + + + + 351 + + + view + Productos terminados B + + + + 351 + + + other + Productos terminados B + + + + 36 + + + view + Subproductos, residuos y materiales recuperados + + + + 360 + + + view + Subproductos A + + + + 360 + + + other + Subproductos A + + + + 361 + + + view + Subproductos B + + + + 361 + + + other + Subproductos B + + + + 365 + + + view + Residuos A + + + + 365 + + + other + Residuos A + + + + 366 + + + view + Residuos B + + + + 366 + + + other + Residuos B + + + + 368 + + + view + Materiales recuperados A + + + + 368 + + + other + Materiales recuperados A + + + + 369 + + + view + Materiales recuperados B + + + + 369 + + + other + Materiales recuperados B + + + + 39 + + + view + Deterioro de valor de las existencias + + + + 390 + + + view + Deterioro de valor de bienes destinados a la actividad + + + + 390 + + + other + Deterioro de valor de bienes destinados a la actividad + + + + 391 + + + view + Deterioro de valor de las materias primas + + + + 391 + + + other + Deterioro de valor de las materias primas + + + + 392 + + + view + Deterioro de valor de otros aprovisionamientos + + + + 392 + + + other + Deterioro de valor de otros aprovisionamientos + + + + 393 + + + view + Deterioro de valor de los productos en curso + + + + 393 + + + other + Deterioro de valor de los productos en curso + + + + 394 + + + view + Deterioro de valor de los productos semiterminados + + + + 394 + + + other + Deterioro de valor de los productos semiterminados + + + + 395 + + + view + Deterioro de valor de los productos terminados + + + + 395 + + + other + Deterioro de valor de los productos terminados + + + + 396 + + + view + Deterioro de valor de los subproductos, residuos y materiales recuperados + + + + 396 + + + other + Deterioro de valor de los subproductos, residuos y materiales recuperados + + + + 4 + + + view + Acreedores y deudores por operaciones de la actividad + + + + 40 + + + view + Proveedores + + + + 400 + + + view + Proveedores + + + + 4000 + + + view + Proveedores (euros) + + + + 4000 + + + payable + Proveedores (euros) + + + + 4004 + + + view + Proveedores (moneda extranjera) + + + + 4004 + + + payable + Proveedores (moneda extranjera) + + + + 4009 + + + view + Proveedores, facturas pendientes de recibir o de formalizar + + + + 4009 + + + payable + Proveedores, facturas pendientes de recibir o de formalizar + + + + 401 + + + view + Proveedores, efectos comerciales a pagar + + + + 401 + + + other + Proveedores, efectos comerciales a pagar + + + + 403 + + + view + Proveedores, empresas del grupo + + + + 4030 + + + view + Proveedores, empresas del grupo (euros) + + + + 4030 + + + payable + Proveedores, empresas del grupo (euros) + + + + 4031 + + + view + Efectos comerciales a pagar, empresas del grupo + + + + 4031 + + + payable + Efectos comerciales a pagar, empresas del grupo + + + + 4034 + + + view + Proveedores, empresas del grupo (moneda extranjera) + + + + 4034 + + + payable + Proveedores, empresas del grupo (moneda extranjera) + + + + 4036 + + + view + Envases y embalajes a devolver a proveedores, empresas del grupo + + + + 4036 + + + payable + Envases y embalajes a devolver a proveedores, empresas del grupo + + + + 4039 + + + view + Proveedores, empresas del grupo, facturas pendientes de recibir o de formalizar + + + + 4039 + + + payable + Proveedores, empresas del grupo, facturas pendientes de recibir o de formalizar + + + + 404 + + + view + Proveedores, empresas asociadas + + + + 404 + + + other + Proveedores, empresas asociadas + + + + 405 + + + view + Proveedores, otras partes vinculadas + + + + 405 + + + other + Proveedores, otras partes vinculadas + + + + 406 + + + view + Envases y embalajes a devolver a proveedores + + + + 406 + + + other + Envases y embalajes a devolver a proveedores + + + + 407 + + + view + Anticipos a proveedores + + + + 407 + + + other + Anticipos a proveedores + + + + 41 + + + view + Benerificiarios y acreedores varios + + + + 410 + + + view + Acreedores por prestaciones de servicios + + + + 4100 + + + view + Acreedores por prestaciones de servicios (euros) + + + + 4100 + + + payable + Acreedores por prestaciones de servicios (euros) + + + + 4104 + + + view + Acreedores por prestaciones de servicios (moneda extranjera) + + + + 4104 + + + payable + Acreedores por prestaciones de servicios (moneda extranjera) + + + + 4109 + + + view + Acreedores por prestaciones de servicios, facturas pendientes de recibir o de formalizar + + + + 4109 + + + payable + Acreedores por prestaciones de servicios, facturas pendientes de recibir o de formalizar + + + + 411 + + + view + Acreedores, efectos comerciales a pagar + + + + 411 + + + other + Acreedores, efectos comerciales a pagar + + + + 412 + + + view + Beneficiarios, acreedores + + + + 412 + + + other + Beneficiarios, acreedores + + + + + + + + + 419 + + + view + Acreedores por operaciones en común + + + + 419 + + + other + Acreedores por operaciones en común + + + + 43 + + + view + Clientes + + + + 430 + + + view + Clientes + + + + 4300 + + + view + Clientes (euros) + + + + 4300 + + + receivable + Clientes (euros) + + + + 4304 + + + view + Clientes (moneda extranjera) + + + + 4304 + + + receivable + Clientes (moneda extranjera) + + + + 4309 + + + view + Clientes, facturas pendientes de recibir o de formalizar + + + + 4309 + + + receivable + Clientes, facturas pendientes de recibir o de formalizar + + + + 431 + + + view + Clientes, efectos comerciales a cobrar + + + + 4310 + + + view + Efectos comerciales en cartera + + + + 4310 + + + receivable + Efectos comerciales en cartera + + + + 4311 + + + view + Efectos comerciales descontados + + + + 4311 + + + receivable + Efectos comerciales descontados + + + + 4312 + + + view + Efectos comerciales en gestión de cobro + + + + 4312 + + + receivable + Efectos comerciales en gestión de cobro + + + + 4315 + + + view + Efectos comerciales impagados + + + + 4315 + + + receivable + Efectos comerciales impagados + + + + 432 + + + view + Clientes, operaciones de factoring + + + + 432 + + + other + Clientes, operaciones de factoring + + + + 433 + + + view + Clientes, empresas del grupo + + + + 4330 + + + view + Clientes empresas del grupo (euros) + + + + 4330 + + + receivable + Clientes empresas del grupo (euros) + + + + 4331 + + + view + Efectos comerciales a cobrar, empresas del grupo + + + + 4331 + + + receivable + Efectos comerciales a cobrar, empresas del grupo + + + + 4332 + + + view + Clientes empresas del grupo, operaciones de factoring + + + + 4332 + + + receivable + Clientes empresas del grupo, operaciones de factoring + + + + 4334 + + + view + Clientes empresas del grupo (moneda extranjera) + + + + 4334 + + + receivable + Clientes empresas del grupo (moneda extranjera) + + + + 4336 + + + view + Clientes empresas del grupo de dudoso cobro + + + + 4336 + + + receivable + Clientes empresas del grupo de dudoso cobro + + + + 4337 + + + view + Envases y embalajes a devolver a clientes, empresas del grupo + + + + 4337 + + + receivable + Envases y embalajes a devolver a clientes, empresas del grupo + + + + 4339 + + + view + Clientes empresas del grupo, facturas pendientes de formalizar + + + + 4339 + + + receivable + Clientes empresas del grupo, facturas pendientes de formalizar + + + + 434 + + + view + Clientes, empresas asociadas + + + + 434 + + + other + Clientes, empresas asociadas + + + + 435 + + + view + Clientes, otras partes vinculadas + + + + 435 + + + other + Clientes, otras partes vinculadas + + + + 436 + + + view + Clientes de dudoso cobro + + + + 436 + + + other + Clientes de dudoso cobro + + + + 437 + + + view + Envases y embalajes a devolver por clientes + + + + 437 + + + other + Envases y embalajes a devolver por clientes + + + + 438 + + + view + Anticipos de clientes + + + + 438 + + + other + Anticipos de clientes + + + + 44 + + + view + Usuarios y deudores varios + + + + 440 + + + view + Deudores + + + + 4400 + + + view + Deudores (euros) + + + + 4400 + + + receivable + Deudores (euros) + + + + 4404 + + + view + Deudores (moneda extranjera) + + + + 4404 + + + receivable + Deudores (moneda extranjera) + + + + 4409 + + + view + Deudores, facturas pendientes de formalizar + + + + 4409 + + + receivable + Deudores, facturas pendientes de formalizar + + + + 441 + + + view + Deudores, efectos comerciales a cobrar + + + + 4410 + + + view + Deudores, efectos comerciales en cartera + + + + 4410 + + + receivable + Deudores, efectos comerciales en cartera + + + + 4411 + + + view + Deudores, efectos comerciales descontados + + + + 4411 + + + receivable + Deudores, efectos comerciales descontados + + + + 4412 + + + view + Deudores, efectos comerciales en gestión de cobro + + + + 4412 + + + receivable + Deudores, efectos comerciales en gestión de cobro + + + + 4415 + + + view + Deudores, efectos comerciales impagados + + + + 4415 + + + receivable + Deudores, efectos comerciales impagados + + + + 446 + + + view + Deudores de dudoso cobro + + + + 446 + + + other + Deudores de dudoso cobro + + + + + 447 + + + view + Usuarios, deudores + + + + 447 + + + other + Usuarios, deudores + + + + 448 + + + view + Patrocinadores, afiliados y otros deudores + + + + 4480 + + + view + Patrocinadores + + + + 4480 + + + other + Patrocinadores + + + + 4482 + + + view + Afiliados + + + + 4482 + + + other + Afiliados + + + + + 4489 + + + view + Otros deudores + + + + 4489 + + + other + Otros deudores + + + + + + 449 + + + view + Deudores por operaciones en común + + + + 449 + + + other + Deudores por operaciones en común + + + + 46 + + + view + Personal + + + + 460 + + + view + Anticipos de remuneraciones + + + + 460 + + + other + Anticipos de remuneraciones + + + + + 464 + + + view + Entregas para gastos a justificar + + + + 464 + + + other + Entregas para gastos a justificar + + + + + + 465 + + + view + Remuneraciones pendientes de pago + + + + 465 + + + other + Remuneraciones pendientes de pago + + + + 47 + + + view + Administraciones públicas + + + + 470 + + + view + Hacienda Pública, deudora por diversos conceptos + + + + 4700 + + + view + Hacienda Pública, deudora por IVA + + + + 4700 + + + receivable + Hacienda Pública, deudora por IVA + + + + 4707 + + + view + Hacienda Pública, deudora por colaboración en la entrega y distribución de subvenciones (art.12 Ley de Subvenciones) + + + + 4707 + + + receivable + Hacienda Pública, deudora por colaboración en la entrega y distribución de subvenciones (art.12 Ley de Subvenciones) + + + + + + 4708 + + + view + Hacienda Pública, deudora por subvenciones concedidas + + + + 4708 + + + receivable + Hacienda Pública, deudora por subvenciones concedidas + + + + 4709 + + + view + Hacienda Pública, deudora por devolución de impuestos + + + + 4709 + + + receivable + Hacienda Pública, deudora por devolución de impuestos + + + + 471 + + + view + Organismos de la Seguridad Social, deudores + + + + 471 + + + other + Organismos de la Seguridad Social, deudores + + + + 472 + + + view + Hacienda Pública, IVA soportado + + + + 472000 + + + other + Hacienda Pública. IVA soportado + + + + 473 + + + view + Hacienda Pública, retenciones y pagos a cuenta + + + + 474 + + + view + Activos por impuesto diferido + + + + 4740 + + + view + Activos por diferencias temporarias deducibles + + + + 4740 + + + other + Activos por diferencias temporarias deducibles + + + + 4742 + + + view + Derechos por deducciones y bonificaciones pendientes de aplicar + + + + 4742 + + + other + Derechos por deducciones y bonificaciones pendientes de aplicar + + + + 4745 + + + view + Crédito por pérdidas a compensar del ejercicio + + + + 4745 + + + other + Crédito por pérdidas a compensar del ejercicio + + + + 475 + + + view + Hacienda Pública, acreedora por conceptos fiscales + + + + 4750 + + + view + Hacienda Pública, acreedora por IVA + + + + 475000 + + + payable + Hacienda Pública, acreedora por IVA + + + + 4751 + + + view + Hacienda Pública, acreedora por retenciones practicadas + + + + 4751 + + + payable + Hacienda Pública, acreedora por retenciones practicadas + + + + 4752 + + + view + Hacienda Pública, acreedora por impuesto sobre sociedades + + + + 4752 + + + payable + Hacienda Pública, acreedora por impuesto sobre sociedades + + + + + 4757 + + + view + Hacienda Pública, acreedora por subvenciones recibidas en concepto de entidad colaboradora (art.12 Ley de Subvenciones) + + + + 4757 + + + payable + Hacienda Pública, acreedora por subvenciones recibidas en concepto de entidad colaboradora (art.12 Ley de Subvencioens) + + + + + 4758 + + + view + Hacienda Pública, acreedora por subvenciones a reintegrar + + + + 4758 + + + payable + Hacienda Pública, acreedora por subvenciones a reintegrar + + + + 476 + + + view + Organismos de la Seguridad Social, acreedores + + + + 476 + + + other + Organismos de la Seguridad Social, acreedores + + + + 477 + + + view + Hacienda Pública, IVA repercutido + + + + 477000 + + + other + Hacienda Pública. IVA repercutido + + + + 479 + + + view + Pasivos por diferencias temporarias imponibles + + + + 479 + + + other + Pasivos por diferencias temporarias imponibles + + + + 48 + + + view + Ajustes por periodificación + + + + 480 + + + view + Gastos anticipados + + + + 480 + + + other + Gastos anticipados + + + + 485 + + + view + Ingresos anticipados + + + + 485 + + + other + Ingresos anticipados + + + + 49 + + + view + Deterioro de valor por operaciones de la actividad y provisiones a corto plazo + + + + 490 + + + view + Deterioro de valor de créditos por operaciones de la actividad + + + + 490 + + + other + Deterioro de valor de créditos por operaciones de la actividad + + + + 493 + + + view + Deterioro de valor de créditos por operaciones comerciales con partes vinculadas + + + + 4933 + + + view + Deterioro de valor de créditos por operaciones comerciales con empresas del grupo + + + + 4933 + + + other + Deterioro de valor de créditos por operaciones comerciales con empresas del grupo + + + + 4934 + + + view + Deterioro de valor de créditos por operaciones comerciales con empresas asociadas + + + + 4934 + + + other + Deterioro de valor de créditos por operaciones comerciales con empresas asociadas + + + + 4935 + + + view + Deterioro de valor de créditos por operaciones comerciales con otras partes vinculadas + + + + 4935 + + + other + Deterioro de valor de créditos por operaciones comerciales con otras partes vinculadas + + + + 499 + + + view + Provisiones por operaciones comerciales + + + + 4994 + + + view + Provisión por contratos onerosos + + + + 4994 + + + other + Provisión por contratos onerosos + + + + 4999 + + + view + Provisión para otras operaciones comerciales + + + + 4999 + + + other + Provisión para otras operaciones comerciales + + + + 5 + + + view + Cuentas financieras + + + + 50 + + + view + Empréstitos, deudas con características especiales y otras emisiones análogas a corto plazo + + + + 500 + + + view + Obligaciones y bonos a corto plazo + + + + 500 + + + other + Obligaciones y bonos a corto plazo + + + + 502 + + + view + Acciones o participaciones a corto plazo consideradas como pasivos financieros + + + + 502 + + + other + Acciones o participaciones a corto plazo consideradas como pasivos financieros + + + + 505 + + + view + Deudas representadas en otros valores negociables a corto plazo + + + + 505 + + + other + Deudas representadas en otros valores negociables a corto plazo + + + + 506 + + + view + Intereses a corto plazo de empréstitos y otras emisiones análogas + + + + 506 + + + other + Intereses a corto plazo de empréstitos y otras emisiones análogas + + + + 507 + + + view + Dividendos de acciones o participaciones consideradas como pasivos financieros + + + + 507 + + + other + Dividendos de acciones o participaciones consideradas como pasivos financieros + + + + 509 + + + view + Valores negociables amortizados + + + + 5090 + + + view + Obligaciones y bonos amortizados + + + + 5090 + + + other + Obligaciones y bonos amortizados + + + + 5095 + + + view + Otros valores negociables amortizados + + + + 5095 + + + other + Otros valores negociables amortizados + + + + 51 + + + view + Deudas a corto plazo con partes vinculadas + + + + 510 + + + view + Deudas a corto plazo con entidades de crédito vinculadas + + + + 5103 + + + view + Deudas a corto plazo con entidades de crédito, empresas del grupo + + + + 5103 + + + other + Deudas a corto plazo con entidades de crédito, empresas del grupo + + + + 5104 + + + view + Deudas a corto plazo con entidades de crédito, empresas asociadas + + + + 5104 + + + other + Deudas a corto plazo con entidades de crédito, empresas asociadas + + + + 5105 + + + view + Deudas a corto plazo con otras entidades de crédito vinculadas + + + + 5105 + + + other + Deudas a corto plazo con otras entidades de crédito vinculadas + + + + 511 + + + view + Proveedores de inmovilizado a corto plazo, partes vinculadas + + + + 5113 + + + view + Proveedores de inmovilizado a corto plazo, empresas del grupo + + + + 5113 + + + other + Proveedores de inmovilizado a corto plazo, empresas del grupo + + + + 5114 + + + view + Proveedores de inmovilizado a corto plazo, empresas asociadas + + + + 5114 + + + other + Proveedores de inmovilizado a corto plazo, empresas asociadas + + + + 5115 + + + view + Proveedores de inmovilizado a corto plazo, otras partes vinculadas + + + + 5115 + + + other + Proveedores de inmovilizado a corto plazo, otras partes vinculadas + + + + 512 + + + view + Acreedores por arrendamiento financiero a corto plazo, partes vinculadas + + + + 5123 + + + view + Acreedores por arrendamiento financiero a corto plazo, empresas del grupo + + + + 5123 + + + other + Acreedores por arrendamiento financiero a corto plazo, empresas del grupo + + + + 5124 + + + view + Acreedores por arrendamiento financiero a corto plazo, empresas asociadas + + + + 5124 + + + other + Acreedores por arrendamiento financiero a corto plazo, empresas asociadas + + + + 5125 + + + view + Acreedores por arrendamiento financiero a corto plazo, otras partes vinculadas + + + + 5125 + + + other + Acreedores por arrendamiento financiero a corto plazo, otras partes vinculadas + + + + 513 + + + view + Otras deudas a corto plazo con partes vinculadas + + + + 5133 + + + view + Otras deudas a corto plazo con empresas del grupo + + + + 5133 + + + other + Otras deudas a corto plazo con empresas del grupo + + + + 5134 + + + view + Otras deudas a corto plazo con empresas asociadas + + + + 5134 + + + other + Otras deudas a corto plazo con empresas asociadas + + + + 5135 + + + view + Otras deudas a corto plazo con otras partes vinculadas + + + + 5135 + + + other + Otras deudas a corto plazo con otras partes vinculadas + + + + 514 + + + view + Intereses a corto plazo de deudas con partes vinculadas + + + + 5143 + + + view + Intereses a corto plazo de deudas con empresas del grupo + + + + 5143 + + + other + Intereses a corto plazo de deudas con empresas del grupo + + + + 5144 + + + view + Intereses a corto plazo de deudas con empresas asociadas + + + + 5144 + + + other + Intereses a corto plazo de deudas con empresas asociadas + + + + 5145 + + + view + Intereses a corto plazo de deudas con otras partes vinculadas + + + + 5145 + + + other + Intereses a corto plazo de deudas con otras partes vinculadas + + + + 52 + + + view + Deudas a corto plazo por préstamos recibidos y otros conceptos + + + + 520 + + + view + Deudas a corto plazo con entidades de crédito + + + + 5200 + + + view + Préstamos a corto plazo de entidades de crédito + + + + 5200 + + + other + Préstamos a corto plazo de entidades de crédito + + + + 5201 + + + view + Deudas a corto plazo por crédito dispuesto + + + + 5201 + + + other + Deudas a corto plazo por crédito dispuesto + + + + 5208 + + + view + Deudas por efectos descontados + + + + 5208 + + + other + Deudas por efectos descontados + + + + 5209 + + + view + Deudas por operaciones de “factoring” + + + + 5209 + + + other + Deudas por operaciones de “factoring” + + + + 521 + + + view + Deudas a corto plazo + + + + 521 + + + other + Deudas a corto plazo + + + + 522 + + + view + Deudas a corto plazo transformables en subvenciones, donaciones y legados + + + + 522 + + + other + Deudas a corto plazo transformables en subvenciones, donaciones y legados + + + + 523 + + + view + Proveedores de inmovilizado a corto plazo + + + + 523 + + + other + Proveedores de inmovilizado a corto plazo + + + + 524 + + + view + Acreedores por arrendamiento financiero a corto plazo + + + + 524 + + + other + Acreedores por arrendamiento financiero a corto plazo + + + + 525 + + + view + Efectos a pagar a corto plazo + + + + 525 + + + other + Efectos a pagar a corto plazo + + + + 526 + + + view + Dividendo activo a pagar + + + + 526 + + + other + Dividendo activo a pagar + + + + 527 + + + view + Intereses a corto plazo de deudas con entidades de crédito + + + + 527 + + + other + Intereses a corto plazo de deudas con entidades de crédito + + + + 528 + + + view + Intereses a corto plazo de deudas + + + + 528 + + + other + Intereses a corto plazo de deudas + + + + 529 + + + view + Provisiones a corto plazo + + + + 5290 + + + view + Provisión a corto plazo por retribuciones al personal + + + + 5290 + + + other + Provisión a corto plazo por retribuciones al personal + + + + 5291 + + + view + Provisión a corto plazo para impuestos + + + + 5291 + + + other + Provisión a corto plazo para impuestos + + + + 5292 + + + view + Provisión a corto plazo para otras responsabilidades + + + + 5292 + + + other + Provisión a corto plazo para otras responsabilidades + + + + 5293 + + + view + Provisión a corto plazo por desmantelamiento, retiro o rehabilitación del inmovilizado + + + + 5293 + + + other + Provisión a corto plazo por desmantelamiento, retiro o rehabilitación del inmovilizado + + + + 5295 + + + view + Provisión a corto plazo para actuaciones medioambientales + + + + 5295 + + + other + Provisión a corto plazo para actuaciones medioambientales + + + + 53 + + + view + Inversiones financieras a corto plazo en partes vinculadas + + + + 530 + + + view + Participaciones a corto plazo en partes vinculadas + + + + 5303 + + + view + Participaciones a corto plazo en empresas del grupo + + + + 5303 + + + other + Participaciones a corto plazo en empresas del grupo + + + + 5304 + + + view + Participaciones a corto plazo en empresas asociadas + + + + 5304 + + + other + Participaciones a corto plazo en empresas asociadas + + + + 5305 + + + view + Participaciones a corto plazo en otras partes vinculadas + + + + 5305 + + + other + Participaciones a corto plazo en otras partes vinculadas + + + + 531 + + + view + Valores representativos de deuda a corto plazo de partes vinculadas + + + + 5313 + + + view + Valores representativos de deuda a corto plazo de empresas del grupo + + + + 5313 + + + other + Valores representativos de deuda a corto plazo de empresas del grupo + + + + 5314 + + + view + Valores representativos de deuda a corto plazo de empresas asociadas + + + + 5314 + + + other + Valores representativos de deuda a corto plazo de empresas asociadas + + + + 5315 + + + view + Valores representativos de deuda a corto plazo de otras partes vinculadas + + + + 5315 + + + other + Valores representativos de deuda a corto plazo de otras partes vinculadas + + + + 532 + + + view + Créditos a corto plazo a partes vinculadas + + + + 5323 + + + view + Créditos a corto plazo a empresas del grupo + + + + 5323 + + + other + Créditos a corto plazo a empresas del grupo + + + + 5324 + + + view + Créditos a corto plazo a empresas asociadas + + + + 5324 + + + other + Créditos a corto plazo a empresas asociadas + + + + 5325 + + + view + Créditos a corto plazo a otras partes vinculadas + + + + 5325 + + + other + Créditos a corto plazo a otras partes vinculadas + + + + 533 + + + view + Intereses a corto plazo de valores representativos de deuda de partes vinculadas + + + + 5333 + + + view + Intereses a corto plazo de valores representativos de deuda de empresas del grupo + + + + 5333 + + + other + Intereses a corto plazo de valores representativos de deuda de empresas del grupo + + + + 5334 + + + view + Intereses a corto plazo de valores representativos de deuda de empresas asociadas + + + + 5334 + + + other + Intereses a corto plazo de valores representativos de deuda de empresas asociadas + + + + 5335 + + + view + Intereses a corto plazo de valores representativos de deuda de otras partes vinculadas + + + + 5335 + + + other + Intereses a corto plazo de valores representativos de deuda de otras partes vinculadas + + + + 534 + + + view + Intereses a corto plazo de créditos a partes vinculadas + + + + 5343 + + + view + Intereses a corto plazo de créditos a empresas del grupo + + + + 5343 + + + other + Intereses a corto plazo de créditos a empresas del grupo + + + + 5344 + + + view + Intereses a corto plazo de créditos a empresas asociadas + + + + 5344 + + + other + Intereses a corto plazo de créditos a empresas asociadas + + + + 5345 + + + view + Intereses a corto plazo de créditos a otras partes vinculadas + + + + 5345 + + + other + Intereses a corto plazo de créditos a otras partes vinculadas + + + + 535 + + + view + Dividendo a cobrar de inversiones financieras en partes vinculadas + + + + 5353 + + + view + Dividendo a cobrar de inversiones financieras en empresas del grupo + + + + 5353 + + + other + Dividendo a cobrar de inversiones financieras en empresas del grupo + + + + 5354 + + + view + Dividendo a cobrar de inversiones financieras en empresas asociadas + + + + 5354 + + + other + Dividendo a cobrar de inversiones financieras en empresas asociadas + + + + 5355 + + + view + Dividendo a cobrar de inversiones financieras en otras partes vinculadas + + + + 5355 + + + other + Dividendo a cobrar de inversiones financieras en otras partes vinculadas + + + + 539 + + + view + Desembolsos pendientes sobre participaciones a corto plazo en partes vinculadas + + + + 5393 + + + view + Desembolsos pendientes sobre participaciones a corto plazo en empresas del grupo + + + + 5393 + + + other + Desembolsos pendientes sobre participaciones a corto plazo en empresas del grupo + + + + 5394 + + + view + Desembolsos pendientes sobre participaciones a corto plazo en empresas asociadas + + + + 5394 + + + other + Desembolsos pendientes sobre participaciones a corto plazo en empresas asociadas + + + + 5395 + + + view + Desembolsos pendientes sobre participaciones a corto plazo en otras partes vinculadas + + + + 5395 + + + other + Desembolsos pendientes sobre participaciones a corto plazo en otras partes vinculadas + + + + 54 + + + view + Otras inversiones financieras a corto plazo + + + + 540 + + + view + Inversiones financieras a corto plazo en instrumentos de patrimonio + + + + 540 + + + other + Inversiones financieras a corto plazo en instrumentos de patrimonio + + + + 541 + + + view + Valores representativos de deuda a corto plazo + + + + 541 + + + other + Valores representativos de deuda a corto plazo + + + + 542 + + + view + Créditos a corto plazo + + + + 542 + + + other + Créditos a corto plazo + + + + 543 + + + view + Créditos a corto plazo por enajenación de inmovilizado + + + + 543 + + + other + Créditos a corto plazo por enajenación de inmovilizado + + + + 544 + + + view + Créditos a corto plazo al personal + + + + 544 + + + other + Créditos a corto plazo al personal + + + + 545 + + + view + Dividendo a cobrar + + + + 545 + + + other + Dividendo a cobrar + + + + 546 + + + view + Intereses a corto plazo de valores representativos de deudas + + + + 546 + + + other + Intereses a corto plazo de valores representativos de deudas + + + + 547 + + + view + Intereses a corto plazo de créditos + + + + 547 + + + other + Intereses a corto plazo de créditos + + + + 548 + + + view + Imposiciones a corto plazo + + + + 548 + + + other + Imposiciones a corto plazo + + + + 549 + + + view + Desembolsos pendientes sobre participaciones en el patrimonio neto a corto plazo + + + + 549 + + + other + Desembolsos pendientes sobre participaciones en el patrimonio neto a corto plazo + + + + 55 + + + view + Otras cuentas no bancarias + + + + 550 + + + view + Titular de la explotación + + + + 550 + + + other + Titular de la explotación + + + + 551 + + + view + Cuenta corriente con patronos y otros + + + + 551 + + + other + Cuenta corriente con patronos y otros + + + + 552 + + + view + Cuenta corriente con otras personas y entidades vinculadas + + + + 5523 + + + view + Cuenta corriente con empresas del grupo + + + + 5523 + + + other + Cuenta corriente con empresas del grupo + + + + 5524 + + + view + Cuenta corriente con empresas asociadas + + + + 5524 + + + other + Cuenta corriente con empresas asociadas + + + + 5525 + + + view + Cuenta corriente con otras partes vinculadas + + + + 5525 + + + other + Cuenta corriente con otras partes vinculadas + + + + 554 + + + view + Cuenta corriente con uniones temporales de empresas y comunidades de bienes + + + + 554 + + + other + Cuenta corriente con uniones temporales de empresas y comunidades de bienes + + + + 555 + + + view + Partidas pendientes de aplicación + + + + 555 + + + other + Partidas pendientes de aplicación + + + + 556 + + + view + Desembolsos exigidos sobre participaciones en el patrimonio neto + + + + 5563 + + + view + Desembolsos exigidos sobre participaciones, empresas del grupo + + + + 5563 + + + other + Desembolsos exigidos sobre participaciones, empresas del grupo + + + + 5564 + + + view + Desembolsos exigidos sobre participaciones, empresas asociadas + + + + 5564 + + + other + Desembolsos exigidos sobre participaciones, empresas asociadas + + + + 5565 + + + view + Desembolsos exigidos sobre participaciones, otras partes vinculadas + + + + 5565 + + + other + Desembolsos exigidos sobre participaciones, otras partes vinculadas + + + + 5566 + + + view + Desembolsos exigidos sobre participaciones de otras empresas + + + + 5566 + + + other + Desembolsos exigidos sobre participaciones de otras empresas + + + + 557 + + + view + Dividendo activo a cuenta + + + + 557 + + + other + Dividendo activo a cuenta + + + + 558 + + + view + Fundadores y asociados por desembolsos exigidos + + + + 5580 + + + view + Socios por desembolsos exigidos sobre acciones o participaciones ordinarias + + + + 5580 + + + other + Socios por desembolsos exigidos sobre acciones o participaciones ordinarias + + + + 5585 + + + view + Socios por desembolsos exigidos sobre acciones o participaciones consideradas como pasivos financieros + + + + 5585 + + + other + Socios por desembolsos exigidos sobre acciones o participaciones consideradas como pasivos financieros + + + + 559 + + + view + Derivados financieros a corto plazo + + + + 5590 + + + view + Activos por derivados financieros a corto plazo + + + + 5590 + + + other + Activos por derivados financieros a corto plazo + + + + 5595 + + + view + Pasivos por derivados financieros a corto plazo + + + + 5595 + + + other + Pasivos por derivados financieros a corto plazo + + + + 56 + + + view + Fianzas y depósitos recibidos y constituidos a corto plazo y ajustes por periodificación + + + + 560 + + + view + Fianzas recibidas a corto plazo + + + + 560 + + + other + Fianzas recibidas a corto plazo + + + + 561 + + + view + Depósitos recibidos a corto plazo + + + + 561 + + + other + Depósitos recibidos a corto plazo + + + + 565 + + + view + Fianzas constituidas a corto plazo + + + + 565 + + + other + Fianzas constituidas a corto plazo + + + + 566 + + + view + Depósitos constituidos a corto plazo + + + + 566 + + + other + Depósitos constituidos a corto plazo + + + + 567 + + + view + Intereses pagados por anticipado + + + + 567 + + + other + Intereses pagados por anticipado + + + + 568 + + + view + Intereses cobrados por anticipado + + + + 568 + + + other + Intereses cobrados por anticipado + + + + 57 + + + view + Tesorería + + + + 570 + + + view + Caja, euros + + + + 570 + + + liquidity + Caja, euros + + + + 571 + + + view + Caja, moneda extranjera + + + + 571 + + + liquidity + Caja, moneda extranjera + + + + 572 + + + view + Bancos e instituciones de crédito c/c vista, euros + + + + 572 + + + liquidity + Bancos e instituciones de crédito c/c vista, euros + + + + 573 + + + view + Bancos e instituciones de crédito c/c vista, moneda extranjera + + + + 573 + + + liquidity + Bancos e instituciones de crédito c/c vista, moneda extranjera + + + + 574 + + + view + Bancos e instituciones de crédito, cuentas de ahorro, euros + + + + 574 + + + liquidity + Bancos e instituciones de crédito, cuentas de ahorro, euros + + + + 575 + + + view + Bancos e instituciones de crédito, cuentas de ahorro, moneda extranjera + + + + 575 + + + liquidity + Bancos e instituciones de crédito, cuentas de ahorro, moneda extranjera + + + + 576 + + + view + Inversiones a corto plazo de gran liquidez + + + + 576 + + + liquidity + Inversiones a corto plazo de gran liquidez + + + + 59 + + + view + Deterioro del valor de inversiones financieras a corto plazo y de activos no corrientes mantenidos para la venta + + + + 593 + + + view + Deterioro de valor de participaciones a corto plazo en partes vinculadas + + + + 5933 + + + view + Deterioro de valor de participaciones a corto plazo en empresas del grupo + + + + 5933 + + + other + Deterioro de valor de participaciones a corto plazo en empresas del grupo + + + + 5934 + + + view + Deterioro de valor de participaciones a corto plazo en empresas asociadas + + + + 5934 + + + other + Deterioro de valor de participaciones a corto plazo en empresas asociadas + + + + 5935 + + + view + Deterioro de valor de participaciones a corto plazo en otras partes vinculadas + + + + 5935 + + + other + Deterioro de valor de participaciones a corto plazo en otras partes vinculadas + + + + 594 + + + view + Deterioro de valor de valores representativos de deuda a corto plazo de partes vinculadas + + + + 5943 + + + view + Deterioro de valor de valores representativos de deuda a corto plazo de empresas del grupo + + + + 5943 + + + other + Deterioro de valor de valores representativos de deuda a corto plazo de empresas del grupo + + + + 5944 + + + view + Deterioro de valor de valores representativos de deuda a corto plazo de empresas asociadas + + + + 5944 + + + other + Deterioro de valor de valores representativos de deuda a corto plazo de empresas asociadas + + + + 5945 + + + view + Deterioro de valor de valores representativos de deuda a corto plazo de otras partes vinculadas + + + + 5945 + + + other + Deterioro de valor de valores representativos de deuda a corto plazo de otras partes vinculadas + + + + 595 + + + view + Deterioro de valor de créditos a corto plazo a partes vinculadas + + + + 5953 + + + view + Deterioro de valor de créditos a corto plazo a empresas del grupo + + + + 5953 + + + other + Deterioro de valor de créditos a corto plazo a empresas del grupo + + + + 5954 + + + view + Deterioro de valor de créditos a corto plazo a empresas asociadas + + + + 5954 + + + other + Deterioro de valor de créditos a corto plazo a empresas asociadas + + + + 5955 + + + view + Deterioro de valor de créditos a corto plazo a otras partes vinculadas + + + + 5955 + + + other + Deterioro de valor de créditos a corto plazo a otras partes vinculadas + + + + 596 + + + view + Deterioro de valor de participaciones a corto plazo + + + + 596 + + + other + Deterioro de valor de participaciones a corto plazo + + + + 597 + + + view + Deterioro de valor de valores representativos de deuda a corto plazo + + + + 597 + + + other + Deterioro de valor de valores representativos de deuda a corto plazo + + + + 598 + + + view + Deterioro de valor de créditos a corto plazo + + + + 598 + + + other + Deterioro de valor de créditos a corto plazo + + + + 6 + + + view + Compras y Gastos + + + + 60 + + + view + Compras + + + + 600 + + + view + Compras de bienes destinados a la actividad + + + + 600 + + + other + Compras de bienes destinados a la actividad + + + + 601 + + + view + Compras de materias primas + + + + 601 + + + other + Compras de materias primas + + + + 602 + + + view + Compras de otros aprovisionamientos + + + + 602 + + + other + Compras de otros aprovisionamientos + + + + 606 + + + view + Descuentos sobre compras por pronto pago + + + + 6060 + + + view + Descuentos sobre compras por pronto pago de bienes destinados a la actividad + + + + 6060 + + + other + Descuentos sobre compras por pronto pago de bienes destinados a la actividad + + + + 6061 + + + view + Descuentos sobre compras por pronto pago de materias primas + + + + 6061 + + + other + Descuentos sobre compras por pronto pago de materias primas + + + + 6062 + + + view + Descuentos sobre compras por pronto pago de otros aprovisionamientos + + + + 6062 + + + other + Descuentos sobre compras por pronto pago de otros aprovisionamientos + + + + 607 + + + view + Trabajos realizados por otras empresas + + + + 607 + + + other + Trabajos realizados por otras empresas + + + + 608 + + + view + Devoluciones de compras y operaciones similares + + + + 6080 + + + view + Devoluciones de compras de bienes destinados a la actividad + + + + 6080 + + + other + Devoluciones de compras de bienes destinados a la actividad + + + + 6081 + + + view + Devoluciones de compras de materias primas + + + + 6081 + + + other + Devoluciones de compras de materias primas + + + + 6082 + + + view + Devoluciones de compras de otros aprovisionamientos + + + + 6082 + + + other + Devoluciones de compras de otros aprovisionamientos + + + + 609 + + + view + “Rappels” por compras + + + + 6090 + + + view + "Rappels" por compras de bienes destinados a la actividad + + + + 6090 + + + other + "Rappels" por compras de bienes destinados a la actividad + + + + 6091 + + + view + "Rappels" por compras de materias primas + + + + 6091 + + + other + "Rappels" por compras de materias primas + + + + 6092 + + + view + "Rappels" por compras de otros aprovisionamientos + + + + 6092 + + + other + "Rappels" por compras de otros aprovisionamientos + + + + 61 + + + view + Variación de existencias + + + + 610 + + + view + Variación de existencias de bienes destinados a la actividad + + + + 610 + + + other + Variación de existencias de mercaderías + + + + 611 + + + view + Variación de existencias de materias primas + + + + 611 + + + other + Variación de existencias de materias primas + + + + 612 + + + view + Variación de existencias de otros aprovisionamientos + + + + 612 + + + other + Variación de existencias de otros aprovisionamientos + + + + 62 + + + view + Servicios Exteriores + + + + 620 + + + view + Gastos en investigación y desarrollo del ejercicio + + + + 620 + + + other + Gastos en investigación y desarrollo del ejercicio + + + + 621 + + + view + Arrendamientos y cánones + + + + 621 + + + other + Arrendamientos y cánones + + + + 622 + + + view + Reparaciones y conservación + + + + 622 + + + other + Reparaciones y conservación + + + + 623 + + + view + Servicios de profesionales independientes + + + + 623 + + + other + Servicios de profesionales independientes + + + + 624 + + + view + Transportes + + + + 624 + + + other + Transportes + + + + 625 + + + view + Primas de seguros + + + + 625 + + + other + Primas de seguros + + + + 626 + + + view + Servicios bancarios y similares + + + + 626 + + + other + Servicios bancarios y similares + + + + 627 + + + view + Publicidad, propaganda y relaciones públicas + + + + 627 + + + other + Publicidad, propaganda y relaciones públicas + + + + 628 + + + view + Suministros + + + + 628 + + + other + Suministros + + + + 629 + + + view + Otros servicios + + + + 629 + + + other + Otros servicios + + + + 63 + + + view + Tributos + + + + 630 + + + view + Impuesto sobre beneficios + + + + 6300 + + + view + Impuesto corriente + + + + 6300 + + + other + Impuesto corriente + + + + 6301 + + + view + Impuesto diferido + + + + 6301 + + + other + Impuesto diferido + + + + 631 + + + view + Otros tributos + + + + 631 + + + other + Otros tributos + + + + 633 + + + view + Ajustes negativos en la imposición sobre beneficios + + + + 633 + + + other + Ajustes negativos en la imposición sobre beneficios + + + + 634 + + + view + Ajustes negativos en la imposición indirecta + + + + 6341 + + + view + Ajustes negativos en IVA de activo corriente + + + + 6341 + + + other + Ajustes negativos en IVA de activo corriente + + + + 6342 + + + view + Ajustes negativos en IVA de inversiones + + + + 6342 + + + other + Ajustes negativos en IVA de inversiones + + + + 636 + + + view + Devolución de impuestos + + + + 636 + + + other + Devolución de impuestos + + + + 638 + + + view + Ajustes positivos en la imposición sobre beneficios + + + + 638 + + + other + Ajustes positivos en la imposición sobre beneficios + + + + 639 + + + view + Ajustes positivos en la imposición indirecta + + + + 6391 + + + view + Ajustes positivos en IVA de activo corriente + + + + 6391 + + + other + Ajustes positivos en IVA de activo corriente + + + + 6392 + + + view + Ajustes positivos en IVA de inversiones + + + + 6392 + + + other + Ajustes positivos en IVA de inversiones + + + + 64 + + + view + Gastos de personal + + + + 640 + + + view + Sueldos y salarios + + + + 640 + + + other + Sueldos y salarios + + + + 641 + + + view + Indemnizaciones + + + + 641 + + + other + Indemnizaciones + + + + 642 + + + view + Seguridad Social a cargo de la empresa + + + + 642 + + + other + Seguridad Social a cargo de la empresa + + + + 649 + + + view + Otros gastos sociales + + + + 649 + + + other + Otros gastos sociales + + + + 65 + + + view + Ayudas monetarias de la entidad y otros gastos de gestión + + + + 650 + + + view + Ayudas monetarias + + + + + 6501 + + + view + Ayudas monetarias individuales + + + + 6501 + + + other + Ayudas monetarias individuales + + + + + 6502 + + + view + Ayudas monetarias a entidades + + + + 6502 + + + other + Ayudas monetarias a entidades + + + + + 6503 + + + view + Ayudas monetarias realizadas a través de otras entidades o centros + + + + 6503 + + + other + Ayudas monetarias realizadas a través de otras entidades o centros + + + + + 6504 + + + view + Ayudas monetarias de cooperación internacional + + + + 6504 + + + other + Ayudas monetarias de cooperación internacional + + + + + + + + 651 + + + view + Ayudas no monetarias + + + + 6510 + + + view + Beneficio transferido (gestor) + + + + 6510 + + + other + Beneficio transferido (gestor) + + + + 6511 + + + view + Ayudas no monetarias individuales + + + + 6511 + + + other + Ayudas no monetarias individuales + + + + 6512 + + + view + Ayudas no monetarias a entidades + + + + 6512 + + + other + Ayudas no monetarias a entidades + + + + + 6513 + + + view + Ayudas no monetarias realizadas a través de otras entidades o centros + + + + 6513 + + + other + Ayudas no monetarias realizadas a través de otras entidades o centros + + + + + 6514 + + + view + Ayudas no monetarias de cooperación internacional + + + + 6514 + + + other + Ayudas no monetarias de cooperación internacional + + + + + 653 + + + view + Compensación de gastos por prestaciones de colaboración + + + + 653 + + + other + Compensación de gastos por prestaciones de colaboración + + + + + 654 + + + view + Reembolsos de gastos al órgano de gobierno + + + + 654 + + + other + Reembolsos de gastos al órgano de gobierno + + + + + 655 + + + view + Pérdidas de créditos derivados de la actividad incobrables + + + + 655 + + + other + Pérdidas de créditos derivados de la actividad incobrables + + + + + + 656 + + + view + Resultados de operaciones en común + + + + 6560 + + + view + Beneficio transferido (gestor) + + + + 6560 + + + other + Beneficio transferido (gestor) + + + + + 6561 + + + view + Pérdida soportada (partícipe o asociado no gestor) + + + + 6561 + + + other + Pérdida soportada(partícipe o asociado no gestor) + + + + + 658 + + + view + Reintegro de subvenciones, donaciones y legados recibidos, afectados a la actividad propia de la entidad + + + + 658 + + + other + Reintegro de subvenciones, donaciones y legados recibidos, afectos a la actividad propia de la entidad + + + + + + 659 + + + view + Otras pérdidas en gestión corriente + + + + 659 + + + other + Otras pérdidas en gestión corriente + + + + 66 + + + view + Gastos financieros + + + + 660 + + + view + Gastos financieros por actualización de provisiones + + + + 660 + + + other + Gastos financieros por actualización de provisiones + + + + 661 + + + view + Intereses de obligaciones y bonos + + + + 6610 + + + view + Intereses de obligaciones y bonos, empresas del grupo + + + + 6610 + + + other + Intereses de obligaciones y bonos, empresas del grupo + + + + 6611 + + + view + Intereses de obligaciones y bonos, empresas asociadas + + + + 6611 + + + other + Intereses de obligaciones y bonos, empresas asociadas + + + + 6612 + + + view + Intereses de obligaciones y bonos, otras partes vinculadas + + + + 6612 + + + other + Intereses de obligaciones y bonos, otras partes vinculadas + + + + 6613 + + + view + Intereses de obligaciones y bonos, otras empresas + + + + 6613 + + + other + Intereses de obligaciones y bonos, otras empresas + + + + 6615 + + + view + Intereses de obligaciones y bonos a corto plazo, empresas del grupo + + + + 6615 + + + other + Intereses de obligaciones y bonos a corto plazo, empresas del grupo + + + + 6616 + + + view + Intereses de obligaciones y bonos a corto plazo, empresas asociadas + + + + 6616 + + + other + Intereses de obligaciones y bonos a corto plazo, empresas asociadas + + + + 6617 + + + view + Intereses de obligaciones y bonos a corto plazo, otras partes vinculadas + + + + 6617 + + + other + Intereses de obligaciones y bonos a corto plazo, otras partes vinculadas + + + + 6618 + + + view + Intereses de obligaciones y bonos a corto plazo, otras empresas + + + + 6618 + + + other + Intereses de obligaciones y bonos a corto plazo, otras empresas + + + + 662 + + + view + Ingresos de créditos a largo plazo + + + + 6620 + + + view + Ingresos de créditos a largo plazo, empresas del grupo + + + + 6620 + + + other + Ingresos de créditos a largo plazo, empresas del grupo + + + + 6621 + + + view + Ingresos de créditos a largo plazo, empresas asociadas + + + + 6621 + + + other + Ingresos de créditos a largo plazo, empresas asociadas + + + + 6622 + + + view + Ingresos de créditos a largo plazo, otras partes vinculadas + + + + 6622 + + + other + Ingresos de créditos a largo plazo, otras partes vinculadas + + + + 6623 + + + view + Ingresos de créditos a largo plazo con entidades de crédito + + + + 6623 + + + other + Ingresos de créditos a largo plazo con entidades de crédito + + + + 6624 + + + view + Ingresos de créditos a largo plazo, otras empresas + + + + 6624 + + + other + Ingresos de créditos a largo plazo, otras empresas + + + + 663 + + + view + Pérdidas por valoración de activos y pasivos financieros por su valor razonable + + + + 663 + + + other + Pérdidas por valoración de activos y pasivos financieros por su valor razonable + + + + 664 + + + view + Dividendos de acciones o participaciones consideradas como pasivos financieros + + + + 6640 + + + view + Dividendos de pasivos, empresas del grupo + + + + 6640 + + + other + Dividendos de pasivos, empresas del grupo + + + + 6641 + + + view + Dividendos de pasivos, empresas asociadas + + + + 6641 + + + other + Dividendos de pasivos, empresas asociadas + + + + 6642 + + + view + Dividendos de pasivos, otras partes vinculadas + + + + 6642 + + + other + Dividendos de pasivos, otras partes vinculadas + + + + 6643 + + + view + Dividendos de pasivos, otras empresas + + + + 6643 + + + other + Dividendos de pasivos, otras empresas + + + + 665 + + + view + Intereses por descuento de efectos y operaciones de “factoring” + + + + 6650 + + + view + Intereses por descuento de efectos en entidades de crédito del grupo + + + + 6650 + + + other + Intereses por descuento de efectos en entidades de crédito del grupo + + + + 6651 + + + view + Intereses por descuento de efectos en entidades de crédito asociadas + + + + 6651 + + + other + Intereses por descuento de efectos en entidades de crédito asociadas + + + + 6652 + + + view + Intereses por descuento de efectos en entidades de crédito vinculadas + + + + 6652 + + + other + Intereses por descuento de efectos en entidades de crédito vinculadas + + + + 6653 + + + view + Intereses por descuento de efectos en otras entidades de crédito + + + + 6653 + + + other + Intereses por descuento de efectos en otras entidades de crédito + + + + 6654 + + + view + Intereses por operaciones de "factoring" con entidades de crédito del grupo + + + + 6654 + + + other + Intereses por operaciones de "factoring" con entidades de crédito del grupo + + + + 6655 + + + view + Intereses por operaciones de "factoring" con entidades de crédito asociadas + + + + 6655 + + + other + Intereses por operaciones de "factoring" con entidades de crédito asociadas + + + + 6656 + + + view + Intereses por operaciones de "factoring" con entidades de crédito vinculadas + + + + 6656 + + + other + Intereses por operaciones de "factoring" con entidades de crédito vinculadas + + + + 6657 + + + view + Intereses por operaciones de "factoring" con otras entidades de crédito + + + + 6657 + + + other + Intereses por operaciones de "factoring" con otras entidades de crédito + + + + 666 + + + view + Pérdidas en participaciones y valores representativos de deuda + + + + 6660 + + + view + Pérdidas en valores representativos de deuda, empresas del grupo + + + + 6660 + + + other + Pérdidas en valores representativos de deuda, empresas del grupo + + + + 6661 + + + view + Pérdidas en valores representativos de deuda, empresas asociadas + + + + 6661 + + + other + Pérdidas en valores representativos de deuda, empresas asociadas + + + + 6662 + + + view + Pérdidas en valores representativos de deuda, otras partes vinculadas + + + + 6662 + + + other + Pérdidas en valores representativos de deuda, otras partes vinculadas + + + + 6663 + + + view + Pérdidas en valores representativos de deuda, otras empresas + + + + 6663 + + + other + Pérdidas en valores representativos de deuda, otras empresas + + + + 6665 + + + view + Pérdidas en valores representativos de deuda a corto plazo, empresas del grupo + + + + 6665 + + + other + Pérdidas en valores representativos de deuda a corto plazo, empresas del grupo + + + + 6666 + + + view + Pérdidas en valores representativos de deuda a corto plazo, empresas asociadas + + + + 6666 + + + other + Pérdidas en valores representativos de deuda a corto plazo, empresas asociadas + + + + 6667 + + + view + Pérdidas en valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 6667 + + + other + Pérdidas en valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 6668 + + + view + Pérdidas en valores representativos de deuda a corto plazo, otras empresas + + + + 6668 + + + other + Pérdidas en valores representativos de deuda a corto plazo, otras empresas + + + + 667 + + + view + Pérdidas de créditos no comerciales + + + + 6670 + + + view + Pérdidas de créditos, empresas del grupo + + + + 6670 + + + other + Pérdidas de créditos, empresas del grupo + + + + 6671 + + + view + Pérdidas de créditos, empresas asociadas + + + + 6671 + + + other + Pérdidas de créditos, empresas asociadas + + + + 6672 + + + view + Pérdidas de créditos, otras partes vinculadas + + + + 6672 + + + other + Pérdidas de créditos, otras partes vinculadas + + + + 6673 + + + view + Pérdidas de créditos, otras empresas + + + + 6673 + + + other + Pérdidas de créditos, otras empresas + + + + 6675 + + + view + Pérdidas de créditos a corto plazo, empresas del grupo + + + + 6675 + + + other + Pérdidas de créditos a corto plazo, empresas del grupo + + + + 6676 + + + view + Pérdidas de créditos a corto plazo, empresas asociadas + + + + 6676 + + + other + Pérdidas de créditos a corto plazo, empresas asociadas + + + + 6677 + + + view + Pérdidas de créditos a corto plazo, otras partes vinculadas + + + + 6677 + + + other + Pérdidas de créditos a corto plazo, otras partes vinculadas + + + + 6678 + + + view + Pérdidas de créditos a corto plazo, otras empresas + + + + 6678 + + + other + Pérdidas de créditos a corto plazo, otras empresas + + + + 668 + + + view + Diferencias negativas de cambio + + + + 668 + + + other + Diferencias negativas de cambio + + + + 669 + + + view + Otros gastos financieros + + + + 669 + + + other + Otros gastos financieros + + + + 67 + + + view + Pérdidas procedentes de activos no corrientes y gastos excepcionales + + + + 670 + + + view + Pérdidas procedentes del inmovilizado intangible + + + + 670 + + + other + Pérdidas procedentes del inmovilizado intangible + + + + 671 + + + view + Pérdidas procedentes del inmovilizado material y bienes del Patrimonio Histórico + + + + 671 + + + other + Pérdidas procedentes del inmovilizado material y bienes del Patrimonio Histórico + + + + 672 + + + view + Pérdidas procedentes de las inversiones inmobiliarias + + + + 672 + + + other + Pérdidas procedentes de las inversiones inmobiliarias + + + + 673 + + + view + Pérdidas procedentes de participaciones en partes vinculadas + + + + 6733 + + + view + Pérdidas procedentes de participaciones en, empresas del grupo + + + + 6733 + + + other + Pérdidas procedentes de participaciones en, empresas del grupo + + + + 6734 + + + view + Pérdidas procedentes de participaciones, empresas asociadas + + + + 6734 + + + other + Pérdidas procedentes de participaciones, empresas asociadas + + + + 6735 + + + view + Pérdidas procedentes de participaciones, otras partes vinculadas + + + + 6735 + + + other + Pérdidas procedentes de participaciones, otras partes vinculadas + + + + 675 + + + view + Pérdidas por operaciones con obligaciones propias + + + + 675 + + + other + Pérdidas por operaciones con obligaciones propias + + + + 678 + + + view + Gastos excepcionales + + + + 678 + + + other + Gastos excepcionales + + + + 68 + + + view + Dotaciones para amortizaciones + + + + 680 + + + view + Amortización del inmovilizado intangible + + + + 680 + + + other + Amortización del inmovilizado intangible + + + + 681 + + + view + Amortización del inmovilizado material + + + + 681 + + + other + Amortización del inmovilizado material + + + + 682 + + + view + Amortización de las inversiones inmobiliarias + + + + 682 + + + other + Amortización de las inversiones inmobiliarias + + + + 69 + + + view + Pérdidas por deterioro y otras dotaciones + + + + 690 + + + view + Pérdidas por deterioro del inmovilizado intangible + + + + 690 + + + other + Pérdidas por deterioro del inmovilizado intangible + + + + 691 + + + view + Pérdidas por deterioro del inmovilizado material y bienes del Patrimonio Histórico + + + + 691 + + + other + Pérdidas por deterioro del inmovilizado material y bienes del Patrimonio Histórico + + + + + 6910 + + + view + Pérdidas por deterioro del inmovilizado material + + + + + 6911 + + + view + Pérdidas por deterioro de bienes del Patrimonio Histórico + + + + 6911 + + + other + Pérdidas por deterioro bienes del Patrimonio Histórico + + + + + + + 692 + + + view + Pérdidas por deterioro de las inversiones inmobiliarias + + + + 692 + + + other + Pérdidas por deterioro de las inversiones inmobiliarias + + + + 693 + + + view + Pérdidas por deterioro de existencias + + + + 6930 + + + view + Pérdidas por deterioro de productos terminados y en curso de fabricación + + + + 6930 + + + other + Pérdidas por deterioro de productos terminados y en curso de fabricación + + + + 6931 + + + view + Pérdidas por deterioro de mercaderías + + + + 6931 + + + other + Pérdidas por deterioro de mercaderías + + + + 6932 + + + view + Pérdidas por deterioro de materias primas + + + + 6932 + + + other + Pérdidas por deterioro de materias primas + + + + 6933 + + + view + Pérdidas por deterioro de otros aprovisionamientos + + + + 6933 + + + other + Pérdidas por deterioro de otros aprovisionamientos + + + + 694 + + + view + Pérdidas por deterioro de créditos por operaciones de la actividad + + + + 694 + + + other + Pérdidas por deterioro de créditos por operaciones de la actividad + + + + 695 + + + view + Dotación a la provisión por operaciones comerciales + + + + 6954 + + + view + Dotación a la provisión por contratos onerosos + + + + 6954 + + + other + Dotación a la provisión por contratos onerosos + + + + 6959 + + + view + Dotación a la provisión para otras operaciones comerciales + + + + 6959 + + + other + Dotación a la provisión para otras operaciones comerciales + + + + 696 + + + view + Pérdidas por deterioro de participaciones y valores representativos de deuda + + + + 6960 + + + view + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, empresas del grupo + + + + 6960 + + + other + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, empresas del grupo + + + + 6961 + + + view + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, empresas asociadas + + + + 6961 + + + other + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, empresas asociadas + + + + 6962 + + + view + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, otras partes vinculadas + + + + 6962 + + + other + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, otras partes vinculadas + + + + 6963 + + + view + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, otras empresas + + + + 6963 + + + other + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto, otras empresas + + + + 6965 + + + view + Pérdidas por deterioro en valores representativos de deuda, empresas del grupo + + + + 6965 + + + other + Pérdidas por deterioro en valores representativos de deuda, empresas del grupo + + + + 6966 + + + view + Pérdidas por deterioro en valores representativos de deuda, empresas asociadas + + + + 6966 + + + other + Pérdidas por deterioro en valores representativos de deuda, empresas asociadas + + + + 6967 + + + view + Pérdidas por deterioro en valores representativos de deuda, otras partes vinculadas + + + + 6967 + + + other + Pérdidas por deterioro en valores representativos de deuda, otras partes vinculadas + + + + 6968 + + + view + Pérdidas por deterioro en valores representativos de deuda, otras empresas + + + + 6968 + + + other + Pérdidas por deterioro en valores representativos de deuda, otras empresas + + + + 697 + + + view + Pérdidas por deterioro de créditos + + + + 6970 + + + view + Pérdidas por deterioro de créditos, empresas del grupo + + + + 6970 + + + other + Pérdidas por deterioro de créditos, empresas del grupo + + + + 6971 + + + view + Pérdidas por deterioro de créditos, empresas asociadas + + + + 6971 + + + other + Pérdidas por deterioro de créditos, empresas asociadas + + + + 6972 + + + view + Pérdidas por deterioro de créditos, otras partes vinculadas + + + + 6972 + + + other + Pérdidas por deterioro de créditos, otras partes vinculadas + + + + 6973 + + + view + Pérdidas por deterioro de créditos, otras empresas + + + + 6973 + + + other + Pérdidas por deterioro de créditos, otras empresas + + + + 698 + + + view + Pérdidas por deterioro de participaciones y valores representativos de deuda a corto plazo + + + + 6980 + + + view + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas del grupo + + + + 6980 + + + other + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas del grupo + + + + 6981 + + + view + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas asociadas + + + + 6981 + + + other + Pérdidas por deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas asociadas + + + + 6985 + + + view + Pérdidas por deterioro en valores representativos de deuda a corto plazo, empresas del grupo + + + + 6985 + + + other + Pérdidas por deterioro en valores representativos de deuda a corto plazo, empresas del grupo + + + + 6986 + + + view + Pérdidas por deterioro en valores representativos de deuda a corto plazo, empresas asociadas + + + + 6986 + + + other + Pérdidas por deterioro en valores representativos de deuda a corto plazo, empresas asociadas + + + + 6987 + + + view + Pérdidas por deterioro en valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 6987 + + + other + Pérdidas por deterioro en valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 6988 + + + view + Pérdidas por deterioro en valores representativos de deuda a corto plazo, otras empresas + + + + 6988 + + + other + Pérdidas por deterioro en valores representativos de deuda a corto plazo, otras empresas + + + + 699 + + + view + Pérdidas por deterioro de créditos a corto plazo + + + + 6990 + + + view + Pérdidas por deterioro de créditos a corto plazo, empresas del grupo + + + + 6990 + + + other + Pérdidas por deterioro de créditos a corto plazo, empresas del grupo + + + + 6991 + + + view + Pérdidas por deterioro de créditos a corto plazo, empresas asociadas + + + + 6991 + + + other + Pérdidas por deterioro de créditos a corto plazo, empresas asociadas + + + + 6992 + + + view + Pérdidas por deterioro de créditos a corto plazo, otras partes vinculadas + + + + 6992 + + + other + Pérdidas por deterioro de créditos a corto plazo, otras partes vinculadas + + + + 6993 + + + view + Pérdidas por deterioro de créditos a corto plazo, otras empresas + + + + 6993 + + + other + Pérdidas por deterioro de créditos a corto plazo, otras empresas + + + + 7 + + + view + Ventas e ingresos + + + + 70 + + + view + Ventas de mercaderías, de producción propia, de servicios, etc. + + + + 700 + + + view + Ventas de mercaderías + + + + 7000 + + + view + Ventas de mercaderías en España + + + + 7000 + + + other + Ventas de mercaderías en España + + + + 7001 + + + view + Ventas de mercaderías Intracomunitarias + + + + 7001 + + + other + Ventas de mercaderías Intracomunitarias + + + + 7002 + + + view + Ventas de mercaderías Exportación + + + + 7002 + + + other + Ventas de mercaderías Exportación + + + + 701 + + + view + Ventas de productos terminados + + + + 7010 + + + view + Ventas de productos terminados en España + + + + 7010 + + + other + Ventas de productos terminados en España + + + + 7011 + + + view + Ventas de productos terminados Intracomunitarias + + + + 7011 + + + other + Ventas de productos terminados Intracomunitarias + + + + 7012 + + + view + Ventas de productos terminados Exportación + + + + 7012 + + + other + Ventas de productos terminados Exportación + + + + 702 + + + view + Ventas de productos semiterminados + + + + 7020 + + + view + Ventas de productos semiterminados en España + + + + 7020 + + + other + Ventas de productos semiterminados en España + + + + 7021 + + + view + Ventas de productos semiterminados Intracomunitarias + + + + 7021 + + + other + Ventas de productos semiterminados Intracomunitarias + + + + 7022 + + + view + Ventas de productos semiterminados Exportación + + + + 7022 + + + other + Ventas de productos semiterminados Exportación + + + + 703 + + + view + Ventas de subproductos y residuos + + + + 7030 + + + view + Ventas de subproductos y residuos en España + + + + 7030 + + + other + Ventas de subproductos y residuos en España + + + + 7031 + + + view + Ventas de subproductos y residuos Intracomunitarias + + + + 7031 + + + other + Ventas de subproductos y residuos Intracomunitarias + + + + 7032 + + + view + Ventas de subproductos y residuos Exportación + + + + 7032 + + + other + Ventas de subproductos y residuos Exportación + + + + 704 + + + view + Ventas de envases y embalajes + + + + 7040 + + + view + Ventas de envases y embalajes en España + + + + 7040 + + + other + Ventas de envases y embalajes en España + + + + 7041 + + + view + Ventas de envases y embalajes Intracomunitarias + + + + 7041 + + + other + Ventas de envases y embalajes Intracomunitarias + + + + 7042 + + + view + Ventas de envases y embalajes Exportación + + + + 7042 + + + other + Ventas de envases y embalajes Exportación + + + + 705 + + + view + Prestaciones de servicios + + + + 7050 + + + view + Prestaciones de servicios en España + + + + 7050 + + + other + Prestaciones de servicios en España + + + + 7051 + + + view + Prestaciones de servicios Intracomunitarias + + + + 7051 + + + other + Prestaciones de servicios Intracomunitarias + + + + 7052 + + + view + Prestaciones de servicios fuera de la UE + + + + 7052 + + + other + Prestaciones de servicios fuera de la UE + + + + 706 + + + view + Descuentos sobre ventas por pronto pago + + + + 7060 + + + view + Descuentos sobre ventas por pronto pago de mercaderías + + + + 7060 + + + other + Descuentos sobre ventas por pronto pago de mercaderías + + + + 7061 + + + view + Descuentos sobre ventas por pronto pago de productos terminados + + + + 7061 + + + other + Descuentos sobre ventas por pronto pago de productos terminados + + + + 7062 + + + view + Descuentos sobre ventas por pronto pago de productos semiterminados + + + + 7062 + + + other + Descuentos sobre ventas por pronto pago de productos semiterminados + + + + 7063 + + + view + Descuentos sobre ventas por pronto pago de subproductos y residuos + + + + 7063 + + + other + Descuentos sobre ventas por pronto pago de subproductos y residuos + + + + 708 + + + view + Devoluciones de ventas y operaciones similares + + + + 7080 + + + view + Devoluciones de ventas de mercaderías + + + + 7080 + + + other + Devoluciones de ventas de mercaderías + + + + 7081 + + + view + Devoluciones de ventas de productos terminados + + + + 7081 + + + other + Devoluciones de ventas de productos terminados + + + + 7082 + + + view + Devoluciones de ventas de productos semiterminados + + + + 7082 + + + other + Devoluciones de ventas de productos semiterminados + + + + 7083 + + + view + Devoluciones de ventas de subproductos y residuos + + + + 7083 + + + other + Devoluciones de ventas de subproductos y residuos + + + + 7084 + + + view + Devoluciones de ventas de envases y embalajes + + + + 7084 + + + other + Devoluciones de ventas de envases y embalajes + + + + 709 + + + view + "Rappels" sobre ventas + + + + 7090 + + + view + "Rappels" sobre ventas de mercaderías + + + + 7090 + + + other + "Rappels" sobre ventas de mercaderías + + + + 7091 + + + view + "Rappels" sobre ventas de productos terminados + + + + 7091 + + + other + "Rappels" sobre ventas de productos terminados + + + + 7092 + + + view + "Rappels" sobre ventas de productos semiterminados + + + + 7092 + + + other + "Rappels" sobre ventas de productos semiterminados + + + + 7093 + + + view + "Rappels" sobre ventas de subproductos y residuos + + + + 7093 + + + other + "Rappels" sobre ventas de subproductos y residuos + + + + 7094 + + + view + "Rappels" sobre ventas de envases y embalajes + + + + 7094 + + + other + "Rappels" sobre ventas de envases y embalajes + + + + 71 + + + view + Variación de existencias + + + + 710 + + + view + Variación de existencias de productos en curso + + + + 710 + + + other + Variación de existencias de productos en curso + + + + 711 + + + view + Variación de existencias de productos semiterminados + + + + 711 + + + other + Variación de existencias de productos semiterminados + + + + 712 + + + view + Variación de existencias de productos terminados + + + + 712 + + + other + Variación de existencias de productos terminados + + + + 713 + + + view + Variación de existencias de subproductos, residuos y materiales recuperados + + + + 713 + + + other + Variación de existencias de subproductos, residuos y materiales recuperados + + + + 72 + + + view + Ingresos propios de la entidad + + + + 720 + + + view + Cuotas de asociados y afiliados + + + + 720 + + + other + Cuotas de asociados y afiliados + + + + + 721 + + + view + Cuotas de usuarios + + + + 721 + + + other + Cuotas de usuarios + + + + + 722 + + + view + Promociones de captación de recursos + + + + 722 + + + other + Promociones de captación de recursos + + + + + 723 + + + view + Ingresos de patrocinadores y colaboraciones + + + + 7230 + + + view + Patrocinio + + + + 7230 + + + other + Patrocinio + + + + + 7231 + + + view + Patrocinio publicitario + + + + 7231 + + + other + Patrocinio publicitario + + + + + + 7233 + + + view + Colaboraciones empresariales + + + + 7233 + + + other + Colaboraciones empresariales + + + + + + + 728 + + + view + Ingresos por reintegro de ayudas y asignaciones + + + + 728 + + + other + Ingresos por reintegro de ayudas y asignaciones + + + + + + + 73 + + + view + Trabajos realizados para la empresa + + + + 730 + + + view + Trabajos realizados para el inmovilizado intangible + + + + 730 + + + other + Trabajos realizados para el inmovilizado intangible + + + + 731 + + + view + Trabajos realizados para el inmovilizado material + + + + 731 + + + other + Trabajos realizados para el inmovilizado material + + + + 732 + + + view + Trabajos realizados en inversiones inmobiliarias + + + + 732 + + + other + Trabajos realizados en inversiones inmobiliarias + + + + 733 + + + view + Trabajos realizados para el inmovilizado material en curso + + + + 733 + + + other + Trabajos realizados para el inmovilizado material en curso + + + + 74 + + + view + Subvenciones, donaciones y legados + + + + 740 + + + view + Subvenciones, donaciones y legados a la explotación + + + + 740 + + + other + Subvenciones, donaciones y legados a la explotación + + + + 746 + + + view + Subvenciones, donaciones y legados de capital transferidos al resultado del ejercicio + + + + 746 + + + other + Subvenciones, donaciones y legados de capital transferidos al resultado del ejercicio + + + + 747 + + + view + Otras subvenciones, donaciones y legados transferidos al resultado del ejercicio + + + + 747 + + + other + Otras subvenciones, donaciones y legados transferidos al resultado del ejercicio + + + + 75 + + + view + Otros ingresos de gestión + + + + 751 + + + view + Resultados de operaciones en común + + + + 7510 + + + view + Pérdida transferido (gestor) + + + + 7510 + + + other + Pérdida transferido (gestor) + + + + 7511 + + + view + Beneficio atribuido (partícipe o asociado no gestor) + + + + 7511 + + + other + Beneficio atribuido (partícipe o asociado no gestor) + + + + 752 + + + view + Ingresos por arrendamientos + + + + 752 + + + other + Ingresos por arrendamientos + + + + 753 + + + view + Ingresos de propiedad industrial cedida en explotación + + + + 753 + + + other + Ingresos de propiedad industrial cedida en explotación + + + + 754 + + + view + Ingresos por comisiones + + + + 754 + + + other + Ingresos por comisiones + + + + 755 + + + view + Ingresos por servicios al personal + + + + 755 + + + other + Ingresos por servicios al personal + + + + 759 + + + view + Ingresos por servicios diversos + + + + 759 + + + other + Ingresos por servicios diversos + + + + 76 + + + view + Ingresos financieros + + + + 760 + + + view + Ingresos de participaciones en instrumentos de patrimonio + + + + 7600 + + + view + Ingresos de participaciones en instrumentos de patrimonio, empresas del grupo + + + + 7600 + + + other + Ingresos de participaciones en instrumentos de patrimonio, empresas del grupo + + + + 7601 + + + view + Ingresos de participaciones en instrumentos de patrimonio, empresas asociadas + + + + 7601 + + + other + Ingresos de participaciones en instrumentos de patrimonio, empresas asociadas + + + + 7602 + + + view + Ingresos de participaciones en instrumentos de patrimonio, otras partes vinculadas + + + + 7602 + + + other + Ingresos de participaciones en instrumentos de patrimonio, otras partes vinculadas + + + + 7603 + + + view + Ingresos de participaciones en instrumentos de patrimonio, otras empresas + + + + 7603 + + + other + Ingresos de participaciones en instrumentos de patrimonio, otras empresas + + + + 761 + + + view + Ingresos de valores representativos de deuda + + + + 7610 + + + view + Ingresos de valores representativos de deuda, empresas del grupo + + + + 7610 + + + other + Ingresos de valores representativos de deuda, empresas del grupo + + + + 7611 + + + view + Ingresos de valores representativos de deuda, empresas asociadas + + + + 7611 + + + other + Ingresos de valores representativos de deuda, empresas asociadas + + + + 7612 + + + view + Ingresos de valores representativos de deuda, otras partes vinculadas + + + + 7612 + + + other + Ingresos de valores representativos de deuda, otras partes vinculadas + + + + 7613 + + + view + Ingresos de valores representativos de deuda, otras empresas + + + + 7613 + + + other + Ingresos de valores representativos de deuda, otras empresas + + + + 762 + + + view + Ingresos de créditos + + + + 7620 + + + view + Ingresos de créditos a largo plazo + + + + 76200 + + + view + Ingresos de créditos a largo plazo, empresas del grupo + + + + 76200 + + + other + Ingresos de créditos a largo plazo, empresas del grupo + + + + 76201 + + + view + Ingresos de créditos a largo plazo, empresas asociadas + + + + 76201 + + + other + Ingresos de créditos a largo plazo, empresas asociadas + + + + 76202 + + + view + Ingresos de créditos a largo plazo, otras partes vinculadas + + + + 76202 + + + other + Ingresos de créditos a largo plazo, otras partes vinculadas + + + + 76203 + + + view + Ingresos de créditos a largo plazo, otras empresas + + + + 76203 + + + other + Ingresos de créditos a largo plazo, otras empresas + + + + 7621 + + + view + Ingresos de créditos a corto plazo + + + + 76210 + + + view + Ingresos de créditos a corto plazo, empresas del grupo + + + + 76210 + + + other + Ingresos de créditos a corto plazo, empresas del grupo + + + + 76211 + + + view + Ingresos de créditos a corto plazo, empresas asociadas + + + + 76211 + + + other + Ingresos de créditos a corto plazo, empresas asociadas + + + + 76212 + + + view + Ingresos de créditos a corto plazo, otras partes vinculadas + + + + 76212 + + + other + Ingresos de créditos a corto plazo, otras partes vinculadas + + + + 76213 + + + view + Ingresos de créditos a corto plazo, otras empresas + + + + 76213 + + + other + Ingresos de créditos a corto plazo, otras empresas + + + + 763 + + + view + Beneficios por valoración de activos y pasivos financieros por su valor razonable + + + + 763 + + + other + Beneficios por valoración de activos y pasivos financieros por su valor razonable + + + + 766 + + + view + Beneficios en participaciones y valores representativos de deuda + + + + 7660 + + + view + Beneficios en valores representativos de deuda a largo plazo, empresas del grupo + + + + 7660 + + + other + Beneficios en valores representativos de deuda a largo plazo, empresas del grupo + + + + 7661 + + + view + Beneficios en valores representativos de deuda a largo plazo, empresas asociadas + + + + 7661 + + + other + Beneficios en valores representativos de deuda a largo plazo, empresas asociadas + + + + 7662 + + + view + Beneficios en valores representativos de deuda a largo plazo, otras partes vinculadas + + + + 7662 + + + other + Beneficios en valores representativos de deuda a largo plazo, otras partes vinculadas + + + + 7663 + + + view + Beneficios en valores representativos de deuda a largo plazo, otras empresas + + + + 7663 + + + other + Beneficios en valores representativos de deuda a largo plazo, otras empresas + + + + 7665 + + + view + Beneficios en valores representativos de deuda a corto plazo, empresas del grupo + + + + 7665 + + + other + Beneficios en valores representativos de deuda a corto plazo, empresas del grupo + + + + 7666 + + + view + Beneficios en valores representativos de deuda a corto plazo, empresas asociadas + + + + 7666 + + + other + Beneficios en valores representativos de deuda a corto plazo, empresas asociadas + + + + 7667 + + + view + Beneficios en valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 7667 + + + other + Beneficios en valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 7668 + + + view + Beneficios en valores representativos de deuda a corto plazo, otras empresas + + + + 7668 + + + other + Beneficios en valores representativos de deuda a corto plazo, otras empresas + + + + 768 + + + view + Diferencias positivas de cambio + + + + 768 + + + other + Diferencias positivas de cambio + + + + 769 + + + view + Otros ingresos financieros + + + + 769 + + + other + Otros ingresos financieros + + + + 77 + + + view + Beneficios procedentes de activos no corrientes e ingresos excepcionales + + + + 770 + + + view + Beneficios procedentes del inmovilizado intangible + + + + 770 + + + other + Beneficios procedentes del inmovilizado intangible + + + + 771 + + + view + Beneficios procedentes del inmovilizado material + + + + 771 + + + other + Beneficios procedentes del inmovilizado material + + + + 772 + + + view + Beneficios procedentes de las inversiones inmobiliarias + + + + 772 + + + other + Beneficios procedentes de las inversiones inmobiliarias + + + + 773 + + + view + Beneficios procedentes de participaciones a largo plazo en partes vinculadas + + + + 7733 + + + view + Beneficios procedentes de participaciones a largo plazo en, empresas del grupo + + + + 7733 + + + other + Beneficios procedentes de participaciones a largo plazo en, empresas del grupo + + + + 7734 + + + view + Beneficios procedentes de participaciones a largo plazo, empresas asociadas + + + + 7734 + + + other + Beneficios procedentes de participaciones a largo plazo, empresas asociadas + + + + 7735 + + + view + Beneficios procedentes de participaciones a largo plazo, otras partes vinculadas + + + + 7735 + + + other + Beneficios procedentes de participaciones a largo plazo, otras partes vinculadas + + + + 775 + + + view + Beneficos por operaciones con obligaciones propias + + + + 775 + + + other + Beneficos por operaciones con obligaciones propias + + + + 778 + + + view + Ingresos excepcionales + + + + 778 + + + other + Ingresos excepcionales + + + + 79 + + + view + Excesos y aplicaciones de provisiones y de pérdidas por deterioro + + + + 790 + + + view + Reversión del deterioro del inmovilizado intangible + + + + 790 + + + other + Reversión del deterioro del inmovilizado intangible + + + + 791 + + + view + Reversión del deterioro del inmovilizado material y de bienes del Patrimonio Histórico + + + + 791 + + + other + Reversión del deterioro del inmovilizado material y de bienes del Patrimonio Histórico + + + + 792 + + + view + Reversión del deterioro de las inversiones inmobiliarias + + + + 792 + + + other + Reversión del deterioro de las inversiones inmobiliarias + + + + 793 + + + view + Reversión del deterioro de existencias + + + + 7930 + + + view + Reversión del deterioro de productos terminados y en curso de fabricación + + + + 7930 + + + other + Reversión del deterioro de productos terminados y en curso de fabricación + + + + 7931 + + + view + Reversión del deterioro de mercaderías + + + + 7931 + + + other + Reversión del deterioro de mercaderías + + + + 7932 + + + view + Reversión del deterioro de materias primas + + + + 7932 + + + other + Reversión del deterioro de materias primas + + + + 7933 + + + view + Reversión del deterioro de otros aprovisionamientos + + + + 7933 + + + other + Reversión del deterioro de otros aprovisionamientos + + + + 794 + + + view + Reversión del deterioro de créditos por operaciones de la actividad + + + + 794 + + + other + Reversión del deterioro de créditos por operaciones de la actividad + + + + 795 + + + view + Exceso de provisiones + + + + 7951 + + + view + Exceso de provisión para impuestos + + + + 7951 + + + other + Exceso de provisión para impuestos + + + + 7952 + + + view + Exceso de provisión para otras responsabilidades + + + + 7952 + + + other + Exceso de provisión para otras responsabilidades + + + + 7954 + + + view + Exceso de provisión por operaciones comerciales + + + + 79544 + + + view + Exceso de provisión por contratos onerosos + + + + 79544 + + + other + Exceso de provisión por contratos onerosos + + + + 79549 + + + view + Exceso de provisión para otras operaciones comerciales + + + + 79549 + + + other + Exceso de provisión para otras operaciones comerciales + + + + 7955 + + + view + Exceso de provisión para actuaciones medioambientales + + + + 7955 + + + other + Exceso de provisión para actuaciones medioambientales + + + + 796 + + + view + Reversión del deterioro de participaciones y valores representativos de deuda a largo plazo + + + + 7960 + + + view + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, empresas del grupo + + + + 7960 + + + other + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, empresas del grupo + + + + 7961 + + + view + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, empresas asociadas + + + + 7961 + + + other + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, empresas asociadas + + + + 7962 + + + view + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, otras partes vinculadas + + + + 7962 + + + other + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, otras partes vinculadas + + + + 7963 + + + view + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, otras empresas + + + + 7963 + + + other + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a largo plazo, otras empresas + + + + 7965 + + + view + Reversión del deterioro de valores representativos de deuda a largo plazo, empresas del grupo + + + + 7965 + + + other + Reversión del deterioro de valores representativos de deuda a largo plazo, empresas del grupo + + + + 7966 + + + view + Reversión del deterioro de valores representativos de deuda a largo plazo, empresas asociadas + + + + 7966 + + + other + Reversión del deterioro de valores representativos de deuda a largo plazo, empresas asociadas + + + + 7967 + + + view + Reversión del deterioro de valores representativos de deuda a largo plazo, otras partes vinculadas + + + + 7967 + + + other + Reversión del deterioro de valores representativos de deuda a largo plazo, otras partes vinculadas + + + + 7968 + + + view + Reversión del deterioro de valores representativos de deuda a largo plazo, otras empresas + + + + 7968 + + + other + Reversión del deterioro de valores representativos de deuda a largo plazo, otras empresas + + + + 797 + + + view + Reversión del deterioro de créditos a largo plazo + + + + 7970 + + + view + Reversión del deterioro de créditos a largo plazo, empresas del grupo + + + + 7970 + + + other + Reversión del deterioro de créditos a largo plazo, empresas del grupo + + + + 7971 + + + view + Reversión del deterioro de créditos a largo plazo, empresas asociadas + + + + 7971 + + + other + Reversión del deterioro de créditos a largo plazo, empresas asociadas + + + + 7972 + + + view + Reversión del deterioro de créditos a largo plazo, otras partes vinculadas + + + + 7972 + + + other + Reversión del deterioro de créditos a largo plazo, otras partes vinculadas + + + + 7973 + + + view + Reversión del deterioro de créditos a largo plazo, otras empresas + + + + 7973 + + + other + Reversión del deterioro de créditos a largo plazo, otras empresas + + + + 798 + + + view + Reversión del deterioro de participaciones y valores representativos de deuda a corto plazo + + + + 7980 + + + view + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas del grupo + + + + 7980 + + + other + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas del grupo + + + + 7981 + + + view + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas asociadas + + + + 7981 + + + other + Reversión del deterioro de participaciones en instrumentos de patrimonio neto a corto plazo, empresas asociadas + + + + 7985 + + + view + Reversión del deterioro de valores representativos de deuda a corto plazo, empresas del grupo + + + + 7985 + + + other + Reversión del deterioro de valores representativos de deuda a corto plazo, empresas del grupo + + + + 7986 + + + view + Reversión del deterioro de valores representativos de deuda a corto plazo, empresas asociadas + + + + 7986 + + + other + Reversión del deterioro de valores representativos de deuda a corto plazo, empresas asociadas + + + + 7987 + + + view + Reversión del deterioro de valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 7987 + + + other + Reversión del deterioro de valores representativos de deuda a corto plazo, otras partes vinculadas + + + + 7988 + + + view + Reversión del deterioro de valores representativos de deuda a corto plazo, otras empresas + + + + 7988 + + + other + Reversión del deterioro de valores representativos de deuda a corto plazo, otras empresas + + + + 799 + + + view + Reversión del deterioro de créditos a corto plazo + + + + 7990 + + + view + Reversión del deterioro de créditos a corto plazo, empresas del grupo + + + + 7990 + + + other + Reversión del deterioro de créditos a corto plazo, empresas del grupo + + + + 7991 + + + view + Reversión del deterioro de créditos a corto plazo, empresas asociadas + + + + 7991 + + + other + Reversión del deterioro de créditos a corto plazo, empresas asociadas + + + + 7992 + + + view + Reversión del deterioro de créditos a corto plazo, otras partes vinculadas + + + + 7992 + + + other + Reversión del deterioro de créditos a corto plazo, otras partes vinculadas + + + + 7993 + + + view + Reversión del deterioro de créditos a corto plazo, otras empresas + + + + 7993 + + + other + Reversión del deterioro de créditos a corto plazo, otras empresas + + + + + + + Plantilla Plan de Impuestos ASSOC + + + + + + Plantilla PGCE Asociaciones 2008 + + + + + + + + + + + diff --git a/addons/l10n_es/account_chart_pymes.xml b/addons/l10n_es/account_chart_pymes.xml index ed2e4f18e7c..223d80e3193 100644 --- a/addons/l10n_es/account_chart_pymes.xml +++ b/addons/l10n_es/account_chart_pymes.xml @@ -1,6 +1,6 @@ - + + Jordi Esteve (Zikzakmedia) - jesteve@zikzakmedia.com 2010-02-18 + + Añadido mapeo de cuentas del regimen de equivalencia para compras : + Ignacio Ibeas (Acysos) - ignacio@acysos.com 2011-02-22 --> + + - Régimen Nacional @@ -32,6 +36,16 @@ + + Retención IRPF 21% + + + + + Retención IRPF 20% + + + Retención IRPF 19% @@ -47,6 +61,11 @@ + + Retención IRPF 9% + + + Retención IRPF 7% @@ -68,6 +87,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -78,7 +145,7 @@ - + @@ -90,35 +157,15 @@ - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - + + @@ -138,6 +185,12 @@ + + + + + + @@ -148,29 +201,24 @@ + + + + + - + - - + + - + + - - - - - - - - - - - - - + + @@ -178,30 +226,71 @@ + + + - + + - - + + - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -215,27 +304,87 @@ - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -260,42 +409,188 @@ - + - - + + - + - - - - - - - - + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -372,7 +667,310 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -386,18 +984,6 @@ - - - - - - - - - - - - @@ -410,6 +996,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -434,6 +1044,18 @@ + + + + + + + + + + + + @@ -446,18 +1068,6 @@ - - - - - - - - - - - - @@ -470,6 +1080,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -495,6 +1129,18 @@ + + + + + + + + + + + + @@ -508,6 +1154,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -520,18 +1190,6 @@ - - - - - - - - - - - - @@ -556,6 +1214,18 @@ + + + + + + + + + + + + @@ -568,6 +1238,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -580,18 +1274,6 @@ - - - - - - - - - - - - @@ -616,7 +1298,19 @@ - + + + + + + + + + + + + + @@ -630,18 +1324,6 @@ - - - - - - - - - - - - @@ -654,6 +1336,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -678,6 +1384,18 @@ + + + + + + + + + + + + @@ -690,18 +1408,6 @@ - - - - - - - - - - - - @@ -714,6 +1420,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -738,7 +1468,142 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -752,18 +1617,6 @@ - - - - - - - - - - - - @@ -776,6 +1629,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -800,6 +1677,18 @@ + + + + + + + + + + + + @@ -812,6 +1701,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -824,18 +1737,6 @@ - - - - - - - - - - - - @@ -862,6 +1763,18 @@ + + + + + + + + + + + + @@ -874,18 +1787,6 @@ - - - - - - - - - - - - @@ -898,6 +1799,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -922,6 +1847,18 @@ + + + + + + + + + + + + @@ -934,18 +1871,6 @@ - - - - - - - - - - - - @@ -958,6 +1883,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -984,6 +1933,19 @@ + + + + + + + + + + + + + @@ -996,18 +1958,6 @@ - - - - - - - - - - - - @@ -1020,6 +1970,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1044,6 +2018,18 @@ + + + + + + + + + + + + @@ -1056,18 +2042,6 @@ - - - - - - - - - - - - @@ -1080,6 +2054,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1104,5 +2102,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/l10n_es/fiscal_templates_assoc.xml b/addons/l10n_es/fiscal_templates_assoc.xml new file mode 100644 index 00000000000..42c7ab464ee --- /dev/null +++ b/addons/l10n_es/fiscal_templates_assoc.xml @@ -0,0 +1,2047 @@ + + + + + + + + Régimen Nacional + + + + + Recargo de Equivalencia + + + + + Régimen Extracomunitario + + + + + Régimen Intracomunitario + + + + + Retención IRPF 21% + + + + + Retención IRPF 20% + + + + + Retención IRPF 19% + + + + + Retención IRPF 18% + + + + + Retención IRPF 15% + + + + + Retención IRPF 9% + + + + + Retención IRPF 7% + + + + + Retención IRPF 2% + + + + + Retención IRPF 1% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/l10n_es/fiscal_templates_pymes.xml b/addons/l10n_es/fiscal_templates_pymes.xml index 05871fad842..2e84e63bc34 100644 --- a/addons/l10n_es/fiscal_templates_pymes.xml +++ b/addons/l10n_es/fiscal_templates_pymes.xml @@ -1,10 +1,10 @@ - + + Añadidas posiciones fiscales Retención de IRPF 19%, 2% : + Jordi Esteve (Zikzakmedia) - jesteve@zikzakmedia.com 2010-02-18 + + Añadido mapeo de cuentas del regimen de equivalencia para compras y ventas separados: + Ignacio Ibeas (Acysos) - ignacio@acysos.com 2011-05-06 --> + + - Régimen Nacional @@ -59,6 +63,16 @@ + + Retención IRPF 21% + + + + + Retención IRPF 20% + + + Retención IRPF 19% @@ -74,6 +88,11 @@ + + Retención IRPF 9% + + + Retención IRPF 7% @@ -94,26 +113,16 @@ + + + + + - + - - - - - - - - - - - - - - - - - + + @@ -121,30 +130,69 @@ + + + - + + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -164,6 +212,12 @@ + + + + + + @@ -175,8 +229,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -198,35 +306,15 @@ - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - + + @@ -246,6 +334,12 @@ + + + + + + @@ -257,30 +351,24 @@ + + + + + + - + - - + + - + - - - - - - - - - - - - - - + + @@ -294,7 +382,7 @@ - + @@ -307,16 +395,220 @@ - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -395,9 +687,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -410,18 +1005,6 @@ - - - - - - - - - - - - @@ -434,6 +1017,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -458,6 +1065,18 @@ + + + + + + + + + + + + @@ -470,6 +1089,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -482,18 +1125,6 @@ - - - - - - - - - - - - @@ -520,6 +1151,18 @@ + + + + + + + + + + + + @@ -532,18 +1175,6 @@ - - - - - - - - - - - - @@ -556,6 +1187,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -580,6 +1235,18 @@ + + + + + + + + + + + + @@ -592,18 +1259,6 @@ - - - - - - - - - - - - @@ -616,6 +1271,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -642,6 +1321,18 @@ + + + + + + + + + + + + @@ -654,18 +1345,6 @@ - - - - - - - - - - - - @@ -678,6 +1357,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -702,6 +1405,18 @@ + + + + + + + + + + + + @@ -714,18 +1429,6 @@ - - - - - - - - - - - - @@ -738,6 +1441,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -762,8 +1489,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -776,18 +1637,6 @@ - - - - - - - - - - - - @@ -800,6 +1649,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -824,6 +1697,18 @@ + + + + + + + + + + + + @@ -836,6 +1721,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -848,17 +1757,6 @@ - - - - - - - - - - - @@ -886,6 +1784,18 @@ + + + + + + + + + + + + @@ -898,18 +1808,6 @@ - - - - - - - - - - - - @@ -922,6 +1820,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -946,6 +1868,18 @@ + + + + + + + + + + + + @@ -958,18 +1892,6 @@ - - - - - - - - - - - - @@ -982,6 +1904,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1008,6 +1954,18 @@ + + + + + + + + + + + + @@ -1020,18 +1978,6 @@ - - - - - - - - - - - - @@ -1044,6 +1990,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1068,6 +2038,18 @@ + + + + + + + + + + + + @@ -1080,6 +2062,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1092,18 +2098,6 @@ - - - - - - - - - - - - @@ -1128,5 +2122,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/l10n_es/taxes_data.xml b/addons/l10n_es/taxes_data.xml index 41b52ee077d..586358ffc70 100644 --- a/addons/l10n_es/taxes_data.xml +++ b/addons/l10n_es/taxes_data.xml @@ -1,25 +1,37 @@ - - - + + - + + Ignacio Ibeas (Acysos) - ignacio@acysos.com (2011-02-22) + Modificado type_tax_use de los recargos de equivalencia a "all" + + Jordi Esteve (Zikzakmedia) - jesteve@zikzakmedia.com (2011-08-29) + Cambiado Recargos de equivalencia de "all" a "venta" (ya existen los de compra). Ahora quedan definidos de la misma forma que en taxes_data_pymes.xml + + Pedro M. Baeza (Serv. Tecnol. Avanzados) - pedro.baeza@serviciosbaeza.com (2013-01-29) + Limpieza de subcuentas de impuestos y corrección de inversión de sujeto pasivo + + --> + + - - + + - + @@ -28,46 +40,102 @@ 1.0 - - - + + + + Base adquisiciones exentas + + -- + 1.0 + + + + Base ventas exentas + -- + + 1.0 + + + + + + IVA Soportado exento (operaciones corrientes) + + percent + + + + + + + purchase + + + + + + IVA Exento + + percent + + + + + + + sale + + - + Régimen general IVA Devengado. Base Imponible 4% [01] 1.0 - + Régimen general IVA Devengado. Base Imponible 7% [04] 1.0 - + Régimen general IVA Devengado. Base Imponible 8% [04] 1.0 - + + + Régimen general IVA Devengado. Base Imponible 10% + [04] + + 1.0 + + Régimen general IVA Devengado. Base Imponible 16% [07] 1.0 - + Régimen general IVA Devengado. Base Imponible 18% [07] 1.0 - + + Régimen general IVA Devengado. Base Imponible 21% + [07] + + 1.0 + + - + Recargo Equivalencia Base Imponible 0.5% [10] 1.0 - + Recargo Equivalencia Base Imponible 1% [13] 1.0 - + + + Recargo Equivalencia Base Imponible 1.4% + [13] + + 1.0 + + Recargo Equivalencia Base Imponible 4% [16] 1.0 - - + + + Recargo Equivalencia Base Imponible 5.2% + [16] + + 1.0 + + - + Adquisiciones intracomunitarias. Base Imponible [19] 1.0 - + - - + + - - + + IVA Cuota total devengada [21] 1.0 - + Régimen general IVA Devengado. Cuota 4% [03] 1.0 - + Régimen general IVA Devengado. Cuota 7% [06] 1.0 - + Régimen general IVA Devengado. Cuota 8% [06] 1.0 - + + + Régimen general IVA Devengado. Cuota 10% + [06] + + 1.0 + + Régimen general IVA Devengado. Cuota 16% [09] @@ -155,7 +243,14 @@ 1.0 - + + + Régimen general IVA Devengado. Cuota 21% + [09] + + 1.0 + + - + Recargo Equivalencia. Cuota 0.5% [12] 1.0 - + Recargo Equivalencia. Cuota 1% [15] 1.0 - + + + Recargo Equivalencia. Cuota 1.4% + [15] + + 1.0 + + Recargo Equivalencia. Cuota 4% [18] 1.0 - - + + + Recargo Equivalencia. Cuota 5.2% + [18] + + 1.0 + + + - + Adquisiciones intracomunitarias. Cuota [20] 1.0 - - - - - + + + + + - - + + @@ -212,7 +321,7 @@ 1.0 - + Base operaciones interiores corrientes @@ -220,19 +329,12 @@ 1.0 - - Base operaciones interiores corrientes (16%) + + Base operaciones interiores corrientes (4%) -- 1.0 - - Base operaciones interiores corrientes (18%) - -- - - 1.0 - - Base operaciones interiores corrientes (7%) -- @@ -245,13 +347,30 @@ 1.0 - - Base operaciones interiores corrientes (4%) + + Base operaciones interiores corrientes (10%) + -- + + 1.0 + + + Base operaciones interiores corrientes (16%) + -- + + 1.0 + + + Base operaciones interiores corrientes (18%) + -- + + 1.0 + + + Base operaciones interiores corrientes (21%) -- 1.0 - Base operaciones interiores bienes inversión @@ -259,19 +378,12 @@ 1.0 - - Base operaciones interiores bienes inversión (16%) + + Base operaciones interiores bienes inversión (4%) -- 1.0 - - Base operaciones interiores bienes inversión (18%) - -- - - 1.0 - - Base operaciones interiores bienes inversión (7%) -- @@ -284,14 +396,31 @@ 1.0 - - Base operaciones interiores bienes inversión (4%) + + Base operaciones interiores bienes inversión (10%) -- 1.0 - - + + Base operaciones interiores bienes inversión (16%) + -- + + 1.0 + + + Base operaciones interiores bienes inversión (18%) + -- + + 1.0 + + + Base operaciones interiores bienes inversión (21%) + -- + + 1.0 + + Base importaciones bienes corrientes @@ -299,6 +428,30 @@ 1.0 + + Base importaciones bienes corrientes (4%) + -- + + 1.0 + + + Base importaciones bienes corrientes (7%) + -- + + 1.0 + + + Base importaciones bienes corrientes (8%) + -- + + 1.0 + + + Base importaciones bienes corrientes (10%) + -- + + 1.0 + Base importaciones bienes corrientes (16%) -- @@ -311,26 +464,13 @@ 1.0 - - - Base importaciones bienes corrientes (7%) + + Base importaciones bienes corrientes (21%) -- 1.0 - - Base importaciones bienes corrientes (8%) - -- - - 1.0 - - - Base importaciones bienes corrientes (4%) - -- - - 1.0 - - + Base importaciones bienes inversión @@ -338,19 +478,12 @@ 1.0 - - Base importaciones bienes inversión (16%) + + Base importaciones bienes inversión (4%) -- 1.0 - - Base importaciones bienes inversión (18%) - -- - - 1.0 - - Base importaciones bienes inversión (7%) -- @@ -363,13 +496,31 @@ 1.0 - - Base importaciones bienes inversión (4%) + + Base importaciones bienes inversión (10%) -- 1.0 - + + Base importaciones bienes inversión (16%) + -- + + 1.0 + + + Base importaciones bienes inversión (18%) + -- + + 1.0 + + + Base importaciones bienes inversión (21%) + -- + + 1.0 + + Base adquisiciones intracomunitarias bienes corrientes @@ -377,6 +528,30 @@ 1.0 + + Base adquisiciones intracomunitarias bienes corrientes (4%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (7%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (8%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (10%) + -- + + 1.0 + Base adquisiciones intracomunitarias bienes corrientes (16%) -- @@ -389,26 +564,13 @@ 1.0 - - - Base adquisiciones intracomunitarias bienes corrientes (7%) + + Base adquisiciones intracomunitarias bienes corrientes (21%) -- 1.0 - - Base adquisiciones intracomunitarias bienes corrientes (8%) - -- - - 1.0 - - - Base adquisiciones intracomunitarias bienes corrientes (4%) - -- - - 1.0 - - + Base adquisiciones intracomunitarias bienes inversión @@ -416,19 +578,12 @@ 1.0 - - Base adquisiciones intracomunitarias bienes inversión (16%) + + Base adquisiciones intracomunitarias bienes inversión (4%) -- 1.0 - - Base adquisiciones intracomunitarias bienes inversión (18%) - -- - - 1.0 - - Base adquisiciones intracomunitarias bienes inversión (7%) -- @@ -441,18 +596,71 @@ 1.0 - - Base adquisiciones intracomunitarias bienes inversión (4%) + + Base adquisiciones intracomunitarias bienes inversión (10%) -- 1.0 - - - + + Base adquisiciones intracomunitarias bienes inversión (16%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (18%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (21%) + -- + + 1.0 + + + + + Recargo Equivalencia Ded. Base Imponible 0.5% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 1% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 1.4% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 4% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 5.2% + -- + + 1.0 + + + - + IVA deducible (Cuota)- Total a deducir [Mod.303] [37] @@ -467,19 +675,12 @@ 1.0 - - Cuotas soportadas operaciones interiores corrientes (16%) + + Cuotas soportadas operaciones interiores corrientes (4%) -- 1.0 - - Cuotas soportadas operaciones interiores corrientes (18%) - -- - - 1.0 - - Cuotas soportadas operaciones interiores corrientes (7%) -- @@ -492,13 +693,31 @@ 1.0 - - Cuotas soportadas operaciones interiores corrientes (4%) + + Cuotas soportadas operaciones interiores corrientes (10%) -- 1.0 - + + Cuotas soportadas operaciones interiores corrientes (16%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (18%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (21%) + -- + + 1.0 + + Cuotas soportadas operaciones interiores bienes inversión @@ -506,19 +725,12 @@ 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (16%) + + Cuotas soportadas operaciones interiores bienes inversión (4%) -- 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (18%) - -- - - 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (7%) -- @@ -531,13 +743,31 @@ 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (4%) + + Cuotas soportadas operaciones interiores bienes inversión (10%) -- 1.0 - + + Cuotas soportadas operaciones interiores bienes inversión (16%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (18%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (21%) + -- + + 1.0 + + Cuotas devengadas importaciones bienes corrientes @@ -545,19 +775,12 @@ 1.0 - - Cuotas devengadas importaciones bienes corrientes (16%) + + Cuotas devengadas importaciones bienes corrientes (4%) -- 1.0 - - Cuotas devengadas importaciones bienes corrientes (18%) - -- - - 1.0 - - Cuotas devengadas importaciones bienes corrientes (7%) -- @@ -570,13 +793,31 @@ 1.0 - - Cuotas devengadas importaciones bienes corrientes (4%) + + Cuotas devengadas importaciones bienes corrientes (10%) -- 1.0 - + + Cuotas devengadas importaciones bienes corrientes (16%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (18%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (21%) + -- + + 1.0 + + Cuotas devengadas importaciones bienes inversión @@ -584,19 +825,12 @@ 1.0 - - Cuotas devengadas importaciones bienes inversión (16%) + + Cuotas devengadas importaciones bienes inversión (4%) -- 1.0 - - Cuotas devengadas importaciones bienes inversión (18%) - -- - - 1.0 - - Cuotas devengadas importaciones bienes inversión (7%) -- @@ -609,13 +843,30 @@ 1.0 - - Cuotas devengadas importaciones bienes inversión (4%) + + Cuotas devengadas importaciones bienes inversión (10%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (16%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (18%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (21%) -- 1.0 - En adquisiciones intracomunitarias bienes corrientes @@ -623,6 +874,30 @@ 1.0 + + En adquisiciones intracomunitarias bienes corrientes (4%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (7%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (8%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (10%) + -- + + 1.0 + En adquisiciones intracomunitarias bienes corrientes (16%) -- @@ -635,26 +910,12 @@ 1.0 - - - En adquisiciones intracomunitarias bienes corrientes (7%) + + En adquisiciones intracomunitarias bienes corrientes (21%) -- 1.0 - - En adquisiciones intracomunitarias bienes corrientes (8%) - -- - - 1.0 - - - En adquisiciones intracomunitarias bienes corrientes (4%) - -- - - 1.0 - - En adquisiciones intracomunitarias bienes inversión @@ -662,19 +923,12 @@ 1.0 - - En adquisiciones intracomunitarias bienes inversión (16%) + + En adquisiciones intracomunitarias bienes inversión (4%) -- 1.0 - - En adquisiciones intracomunitarias bienes inversión (18%) - -- - - 1.0 - - En adquisiciones intracomunitarias bienes inversión (7%) -- @@ -687,8 +941,26 @@ 1.0 - - En adquisiciones intracomunitarias bienes inversión (4%) + + En adquisiciones intracomunitarias bienes inversión (10%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (16%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (18%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (21%) -- 1.0 @@ -716,110 +988,42 @@ 1.0 - - - - - - 472004 - - - other - Hacienda Pública. IVA soportado 4% - - - - - 472007 - - - other - Hacienda Pública. IVA soportado 7% - - - - - 472008 - - - other - Hacienda Pública. IVA soportado 8% - - - - - 472016 - - - other - Hacienda Pública. IVA soportado 16% - - - - - 472018 - - - other - Hacienda Pública. IVA soportado 18% - - - - - 477004 - - - other - Hacienda Pública. IVA repercutido 4% - - - - - 477007 - - - other - Hacienda Pública. IVA repercutido 7% - - - - - 477008 - - - other - Hacienda Pública. IVA repercutido 8% - - - - - 477016 - - - other - Hacienda Pública. IVA repercutido 16% - + + + Recargo Equivalencia Ded. Cuota 0.5% + [12] + + 1.0 - - 477018 - - - other - Hacienda Pública. IVA repercutido 18% - + + Recargo Equivalencia Ded. Cuota 1% + [15] + + 1.0 - - - 475001 - - - payable - Hacienda acreedora IVA - + + + Recargo Equivalencia Ded. Cuota 1.4% + [15] + + 1.0 - - + + + Recargo Equivalencia Ded. Cuota 4% + [18] + + 1.0 + + + + Recargo Equivalencia Ded. Cuota 5.2% + [18] + + 1.0 + + @@ -831,8 +1035,8 @@ 4% IVA Soportado (operaciones corrientes) percent - - + + @@ -843,14 +1047,14 @@ purchase - + 4% IVA Soportado (bienes de inversión) percent - - + + @@ -861,14 +1065,14 @@ purchase - + 7% IVA Soportado (operaciones corrientes) percent - - + + @@ -879,14 +1083,14 @@ purchase - + 7% IVA Soportado (bienes de inversión) percent - - + + @@ -897,14 +1101,14 @@ purchase - + 8% IVA Soportado (operaciones corrientes) percent - - + + @@ -915,14 +1119,14 @@ purchase - + 8% IVA Soportado (bienes de inversión) percent - - + + @@ -933,14 +1137,50 @@ purchase - + + + + 10% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 10% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + 16% IVA Soportado (operaciones corrientes) percent - - + + @@ -951,14 +1191,14 @@ purchase - + 16% IVA Soportado (bienes de inversión) percent - - + + @@ -969,14 +1209,14 @@ purchase - + 18% IVA Soportado (operaciones corrientes) percent - - + + @@ -986,15 +1226,16 @@ purchase + - + 18% IVA Soportado (bienes de inversión) percent - - + + @@ -1005,7 +1246,44 @@ purchase - + + + + 21% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + + 21% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + @@ -1036,15 +1314,15 @@ purchase - + IVA 4% Importaciones bienes corrientes IVA 4% Importaciones bienes corrientes percent - - + + @@ -1061,8 +1339,8 @@ IVA 4% Importaciones bienes de inversión percent - - + + @@ -1073,15 +1351,15 @@ purchase - + IVA 7% Importaciones bienes corrientes IVA 7% Importaciones bienes corrientes percent - - + + @@ -1098,8 +1376,8 @@ IVA 7% Importaciones bienes de inversión percent - - + + @@ -1110,15 +1388,15 @@ purchase - + IVA 8% Importaciones bienes corrientes IVA 8% Importaciones bienes corrientes percent - - + + @@ -1135,8 +1413,8 @@ IVA 8% Importaciones bienes de inversión percent - - + + @@ -1147,15 +1425,53 @@ purchase - + + + + IVA 10% Importaciones bienes corrientes + IVA 10% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 10% Importaciones bienes de inversión + IVA 10% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + IVA 16% Importaciones bienes corrientes IVA 16% Importaciones bienes corrientes percent - - + + @@ -1172,8 +1488,8 @@ IVA 16% Importaciones bienes de inversión percent - - + + @@ -1184,15 +1500,15 @@ purchase - + IVA 18% Importaciones bienes corrientes IVA 18% Importaciones bienes corrientes percent - - + + @@ -1209,8 +1525,8 @@ IVA 18% Importaciones bienes de inversión percent - - + + @@ -1221,7 +1537,44 @@ purchase - + + + + IVA 21% Importaciones bienes corrientes + IVA 21% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 21% Importaciones bienes de inversión + IVA 21% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + @@ -1269,16 +1622,16 @@ percent - - + + - + - + purchase @@ -1287,8 +1640,8 @@ percent - - + + @@ -1299,7 +1652,7 @@ purchase - + IVA 18% Inversión del sujeto pasivo @@ -1333,16 +1686,16 @@ percent - - + + - + - + purchase @@ -1351,8 +1704,8 @@ percent - - + + @@ -1363,16 +1716,81 @@ purchase - - + + + + + IVA 21% Inversión del sujeto pasivo + IVA 21% Inversión del sujeto pasivo + + percent + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (1) + + + percent + + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (2) + + + percent + + + + + + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (3) + + + percent + + + + + + + + + + + purchase + + + IVA 4% percent - - + + @@ -1383,14 +1801,14 @@ sale - + IVA 7% percent - - + + @@ -1401,14 +1819,14 @@ sale - + IVA 8% percent - - + + @@ -1419,14 +1837,32 @@ sale - + + + + IVA 10% + + percent + + + + + + + + + + + sale + + IVA 16% percent - - + + @@ -1437,14 +1873,14 @@ sale - + IVA 18% percent - - + + @@ -1454,17 +1890,37 @@ sale + - - + + + + IVA 21% + + percent + + + + + + + + + + + sale + + + + - 0.50% Recargo Equivalencia + 0.50% Recargo Equivalencia Ventas percent - - + + @@ -1475,14 +1931,14 @@ sale - + - 1% Recargo Equivalencia + 1% Recargo Equivalencia Ventas percent - - + + @@ -1493,14 +1949,32 @@ sale - + + + + 1.4% Recargo Equivalencia Ventas + + percent + + + + + + + + + + + sale + + - 4% Recargo Equivalencia + 4% Recargo Equivalencia Ventas percent - - + + @@ -1511,10 +1985,118 @@ sale - - + + + + 5.2% Recargo Equivalencia Ventas + + percent + + + + + + + + + + + sale + + + + + 0.50% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 1% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 1.4% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 4% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 5.2% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + - + @@ -1528,366 +2110,11 @@ sale - - + + - - - IVA 16% Intracomunitario. Bienes corrientes - IVA 16% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 16% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 16% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - - purchase - - - - - IVA 18% Intracomunitario. Bienes corrientes - IVA 18% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 18% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 18% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - - purchase - - - - - - IVA 16% Intracomunitario. Bienes de inversión - IVA 16% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 16% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 16% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - - - - IVA 18% Intracomunitario. Bienes de inversión - IVA 18% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 18% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 18% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes corrientes - IVA 7% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 7% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes de inversión - IVA 7% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 7% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes corrientes - IVA 8% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 8% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes de inversión - IVA 8% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 8% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - - - + IVA 4% Intracomunitario. Bienes corrientes IVA 4% Intracomunitario. Bienes corrientes @@ -1902,8 +2129,8 @@ IVA 4% Intracomunitario. Bienes corrientes (1) percent - - + + @@ -1918,8 +2145,8 @@ IVA 4% Intracomunitario. Bienes corrientes (2) percent - - + + @@ -1945,8 +2172,8 @@ IVA 4% Intracomunitario. Bienes de inversión (1) percent - - + + @@ -1961,8 +2188,8 @@ IVA 4% Intracomunitario. Bienes de inversión (2) percent - - + + @@ -1972,7 +2199,538 @@ purchase - + + + + IVA 7% Intracomunitario. Bienes corrientes + IVA 7% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 7% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes de inversión + IVA 7% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 7% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes + IVA 8% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión + IVA 8% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes + IVA 10% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión + IVA 10% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes + IVA 16% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión + IVA 16% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes + IVA 18% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + + + IVA 18% Intracomunitario. Bienes de inversión + IVA 18% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 18% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes + IVA 21% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión + IVA 21% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + - + - + IRPF Retenciones practicadas Base Imponible @@ -1990,56 +2748,70 @@ 1.0 - + IRPF Retenciones practicadas Base Imponible 1% B.IRPF1 1.0 - + IRPF Retenciones practicadas Base Imponible 2% B.IRPF2 1.0 - + IRPF Retenciones practicadas Base Imponible 7% B.IRPF7 1.0 - + + + IRPF Retenciones practicadas Base Imponible 9% + B.IRPF9 + + 1.0 + + IRPF Retenciones practicadas Base Imponible 15% B.IRPF15 1.0 - + IRPF Retenciones practicadas Base Imponible 18% B.IRPF18 1.0 - + IRPF Retenciones practicadas Base Imponible 19% B.IRPF19 1.0 - + + + IRPF Retenciones practicadas Base Imponible 20% + B.IRPF20 + + 1.0 + + IRPF Retenciones practicadas Base Imponible 21% B.IRPF21 1.0 - + IRPF Retenciones practicadas Total Cuota @@ -2047,128 +2819,78 @@ 1.0 - + IRPF Retenciones practicadas Cuota 1% IRPF1 1.0 - + IRPF Retenciones practicadas Cuota 2% IRPF2 1.0 - + IRPF Retenciones practicadas Cuota 7% IRPF7 1.0 - + + + IRPF Retenciones practicadas Cuota 9% + IRPF9 + + 1.0 + + IRPF Retenciones practicadas Cuota 15% IRPF15 1.0 - + IRPF Retenciones practicadas Cuota 18% IRPF18 1.0 - + IRPF Retenciones practicadas Cuota 19% IRPF19 1.0 - + + + IRPF Retenciones practicadas Cuota 20% + IRPF20 + + 1.0 + + IRPF Retenciones practicadas Cuota 21% IRPF21 1.0 - - - - 475101 - - - other - Hacienda Pública. Retenciones empresarios módulos 1% - - - - - 475102 - - - other - Hacienda Pública. Retenciones act. agrícolas, ganaderas, forestales 2% - - - - - 475107 - - - other - Hacienda Pública. Retenciones act. profesionales 7% - - - - - 475115 - - - other - Hacienda Pública. Retenciones act. profesionales 15% - - - - - 475118 - - - other - Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 18% - - - - - 475119 - - - other - Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 19% - - - - - 475121 - - - other - Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 21% - - - + Retenciones IRPF 1% percent - - + + @@ -2179,14 +2901,14 @@ purchase - + Retenciones IRPF 2% percent - - + + @@ -2197,14 +2919,14 @@ purchase - + Retenciones IRPF 7% percent - - + + @@ -2215,14 +2937,32 @@ purchase - + + + + Retenciones IRPF 9% + + percent + + + + + + + + + + + purchase + + Retenciones IRPF 15% percent - - + + @@ -2233,14 +2973,14 @@ purchase - + Retenciones IRPF 18% percent - - + + @@ -2251,14 +2991,14 @@ purchase - + Retenciones IRPF 19% percent - - + + @@ -2269,14 +3009,32 @@ purchase - + + + + Retenciones IRPF 20% + + percent + + + + + + + + + + + purchase + + Retenciones IRPF 21% percent - - + + @@ -2287,9 +3045,9 @@ purchase - + - + IRPF Retenciones a cuenta Base Imponible @@ -2297,56 +3055,70 @@ 1.0 - + IRPF Retenciones a cuenta Base Imponible 1% B.IRPF1 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 2% B.IRPF2 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 7% B.IRPF7 AC 1.0 - + + + IRPF Retenciones a cuenta Base Imponible 9% + B.IRPF9 AC + + 1.0 + + IRPF Retenciones a cuenta Base Imponible 15% B.IRPF15 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 18% B.IRPF18 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 19% B.IRPF19 AC 1.0 - + + + IRPF Retenciones a cuenta Base Imponible 20% + B.IRPF20 AC + + 1.0 + + IRPF Retenciones a cuenta Base Imponible 21% B.IRPF21 AC 1.0 - + IRPF Retenciones a cuenta Total Cuota @@ -2354,128 +3126,78 @@ 1.0 - + IRPF Retenciones a cuenta Cuota 1% IRPF1 AC 1.0 - + IRPF Retenciones a cuenta Cuota 2% IRPF2 AC 1.0 - + IRPF Retenciones a cuenta Cuota 7% IRPF7 AC 1.0 - + + + IRPF Retenciones a cuenta Cuota 9% + IRPF9 AC + + 1.0 + + IRPF Retenciones a cuenta Cuota 15% IRPF15 AC 1.0 - + IRPF Retenciones a cuenta Cuota 18% IRPF18 AC 1.0 - + IRPF Retenciones a cuenta Cuota 19% IRPF19 AC 1.0 - + + + IRPF Retenciones a cuenta Cuota 20% + IRPF20 AC + + 1.0 + + IRPF Retenciones a cuenta Cuota 21% IRPF21 AC 1.0 - - - - 473001 - - - other - Hacienda Pública. Retenciones a cuenta empresarios módulos 1% - - - - - 473002 - - - other - Hacienda Pública. Retenciones a cuenta act. agrícolas, ganaderas, forestales 2% - - - - 473007 - - - other - Hacienda Pública. Retenciones a cuenta act. profesionales 7% - - - - - 473015 - - - other - Hacienda Pública. Retenciones a cuenta act. profesionales 15% - - - - - 473018 - - - other - Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 18% - - - - - 473019 - - - other - Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 19% - - - - - 473021 - - - other - Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 21% - - - Retenciones a cuenta IRPF 1% percent - - + + @@ -2486,14 +3208,14 @@ sale - + Retenciones a cuenta IRPF 2% percent - - + + @@ -2504,14 +3226,14 @@ sale - + Retenciones a cuenta IRPF 7% percent - - + + @@ -2522,14 +3244,32 @@ sale - + + + + Retenciones a cuenta IRPF 9% + + percent + + + + + + + + + + + sale + + Retenciones a cuenta IRPF 15% percent - - + + @@ -2540,14 +3280,14 @@ sale - + Retenciones a cuenta IRPF 18% percent - - + + @@ -2558,14 +3298,14 @@ sale - + Retenciones a cuenta IRPF 19% percent - - + + @@ -2576,14 +3316,32 @@ sale - + + + + Retenciones a cuenta IRPF 20% + + percent + + + + + + + + + + + sale + + Retenciones a cuenta IRPF 21% percent - - + + diff --git a/addons/l10n_es/taxes_data_assoc.xml b/addons/l10n_es/taxes_data_assoc.xml new file mode 100644 index 00000000000..e2ebb47fb59 --- /dev/null +++ b/addons/l10n_es/taxes_data_assoc.xml @@ -0,0 +1,3540 @@ + + + + + + + + + + + + + + + + + + + + IVA Devengado Base Imponible + -- + 1.0 + + + + + + Base adquisiciones exentas + + + -- + 1.0 + + + + Base ventas exentas + -- + + + 1.0 + + + + + + IVA Soportado exento (operaciones corrientes) + + percent + + + + + + + purchase + + + + + + IVA Exento + + percent + + + + + + + sale + + + + + + + + Régimen general IVA Devengado. Base Imponible 4% + [01] + + 1.0 + + + + Régimen general IVA Devengado. Base Imponible 7% + [04] + + 1.0 + + + Régimen general IVA Devengado. Base Imponible 8% + [04] + + 1.0 + + + + Régimen general IVA Devengado. Base Imponible 10% + [04] + + 1.0 + + + + Régimen general IVA Devengado. Base Imponible 16% + [07] + + 1.0 + + + Régimen general IVA Devengado. Base Imponible 18% + [07] + + 1.0 + + + + Régimen general IVA Devengado. Base Imponible 21% + [07] + + 1.0 + + + + + + + Recargo Equivalencia Base Imponible 0.5% + [10] + + 1.0 + + + + Recargo Equivalencia Base Imponible 1% + [13] + + 1.0 + + + + Recargo Equivalencia Base Imponible 1.4% + [13] + + 1.0 + + + + Recargo Equivalencia Base Imponible 4% + [16] + + 1.0 + + + + Recargo Equivalencia Base Imponible 5.2% + [16] + + 1.0 + + + + + + + Adquisiciones intracomunitarias. Base Imponible + [19] + + 1.0 + + + + + + + + + + + IVA Cuota total devengada + [21] + 1.0 + + + + + Régimen general IVA Devengado. Cuota 4% + [03] + + 1.0 + + + + Régimen general IVA Devengado. Cuota 7% + [06] + + 1.0 + + + + Régimen general IVA Devengado. Cuota 8% + [06] + + 1.0 + + + + Régimen general IVA Devengado. Cuota 10% + [06] + + 1.0 + + + + Régimen general IVA Devengado. Cuota 16% + [09] + + 1.0 + + + + Régimen general IVA Devengado. Cuota 18% + [09] + + 1.0 + + + + Régimen general IVA Devengado. Cuota 21% + [09] + + 1.0 + + + + + + + Recargo Equivalencia. Cuota 0.5% + [12] + + 1.0 + + + + Recargo Equivalencia. Cuota 1% + [15] + + 1.0 + + + + Recargo Equivalencia. Cuota 1.4% + [15] + + 1.0 + + + + Recargo Equivalencia. Cuota 4% + [18] + + 1.0 + + + + Recargo Equivalencia. Cuota 5.2% + [18] + + 1.0 + + + + + + + Adquisiciones intracomunitarias. Cuota + [20] + + 1.0 + + + + + + + + + + + + + + + IVA Deducible Base Imponible + -- + 1.0 + + + + + + Base operaciones interiores corrientes + [22] + + 1.0 + + + Base operaciones interiores corrientes (16%) + -- + + 1.0 + + + Base operaciones interiores corrientes (18%) + -- + + 1.0 + + + + Base operaciones interiores corrientes (7%) + -- + + 1.0 + + + Base operaciones interiores corrientes (8%) + -- + + 1.0 + + + Base operaciones interiores corrientes (4%) + -- + + 1.0 + + + + Base operaciones interiores corrientes (10%) + -- + + 1.0 + + + + Base operaciones interiores corrientes (21%) + -- + + 1.0 + + + + + Base operaciones interiores bienes inversión + [24] + + 1.0 + + + Base operaciones interiores bienes inversión (16%) + -- + + 1.0 + + + + Base operaciones interiores bienes inversión (18%) + -- + + 1.0 + + + + Base operaciones interiores bienes inversión (7%) + -- + + 1.0 + + + + Base operaciones interiores bienes inversión (8%) + -- + + 1.0 + + + + Base operaciones interiores bienes inversión (4%) + -- + + 1.0 + + + + Base operaciones interiores bienes inversión (10%) + -- + + 1.0 + + + + Base operaciones interiores bienes inversión (21%) + -- + + 1.0 + + + + + + Base importaciones bienes corrientes + [26] + + 1.0 + + + Base importaciones bienes corrientes (16%) + -- + + 1.0 + + + Base importaciones bienes corrientes (18%) + -- + + 1.0 + + + + Base importaciones bienes corrientes (7%) + -- + + 1.0 + + + Base importaciones bienes corrientes (8%) + -- + + 1.0 + + + Base importaciones bienes corrientes (4%) + -- + + 1.0 + + + + Base importaciones bienes corrientes (10%) + -- + + 1.0 + + + Base importaciones bienes corrientes (21%) + -- + + 1.0 + + + + + Base importaciones bienes inversión + [28] + + 1.0 + + + Base importaciones bienes inversión (16%) + -- + + 1.0 + + + Base importaciones bienes inversión (18%) + -- + + 1.0 + + + + Base importaciones bienes inversión (7%) + -- + + 1.0 + + + Base importaciones bienes inversión (8%) + -- + + 1.0 + + + Base importaciones bienes inversión (4%) + -- + + 1.0 + + + Base importaciones bienes inversión (10%) + -- + + 1.0 + + + Base importaciones bienes inversión (21%) + -- + + 1.0 + + + + + Base adquisiciones intracomunitarias bienes corrientes + [30] + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (16%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (18%) + -- + + 1.0 + + + + Base adquisiciones intracomunitarias bienes corrientes (7%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (8%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (4%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (10%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (21%) + -- + + 1.0 + + + + + Base adquisiciones intracomunitarias bienes inversión + [32] + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (16%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (18%) + -- + + 1.0 + + + + Base adquisiciones intracomunitarias bienes inversión (7%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (8%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (4%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (10%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (21%) + -- + + 1.0 + + + + + Recargo Equivalencia Ded. Base Imponible 0.5% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 1% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 1.4% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 4% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 5.2% + -- + + 1.0 + + + + + + + + IVA deducible (Cuota)- Total a deducir [Mod.303] + [37] + + 1.0 + + + + + Cuotas soportadas operaciones interiores corrientes + [23] + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (16%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (18%) + -- + + 1.0 + + + + Cuotas soportadas operaciones interiores corrientes (7%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (8%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (10%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (4%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (21%) + -- + + 1.0 + + + + + Cuotas soportadas operaciones interiores bienes inversión + [25] + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (16%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (18%) + -- + + 1.0 + + + + Cuotas soportadas operaciones interiores bienes inversión (7%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (8%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (4%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (10%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (21%) + -- + + 1.0 + + + + + Cuotas devengadas importaciones bienes corrientes + [27] + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (16%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (18%) + -- + + 1.0 + + + + Cuotas devengadas importaciones bienes corrientes (7%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (8%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (4%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (10%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (21%) + -- + + 1.0 + + + + + Cuotas devengadas importaciones bienes inversión + [29] + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (16%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (18%) + -- + + 1.0 + + + + Cuotas devengadas importaciones bienes inversión (7%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (8%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (4%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (10%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (21%) + -- + + 1.0 + + + + En adquisiciones intracomunitarias bienes corrientes + [31] + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (16%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (18%) + -- + + 1.0 + + + + En adquisiciones intracomunitarias bienes corrientes (7%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (8%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (4%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (10%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (21%) + -- + + 1.0 + + + + En adquisiciones intracomunitarias bienes inversión + [33] + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (16%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (18%) + -- + + 1.0 + + + + En adquisiciones intracomunitarias bienes inversión (7%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (8%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (4%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (10%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (21%) + -- + + 1.0 + + + + + Entregas Intracomunitarias + [42] + + 1.0 + + + + Exportaciones y operaciones asimiladas + [43] + + 1.0 + + + + Inversión del sujeto pasivo + [44] + + 1.0 + + + + + Recargo Equivalencia Ded. Cuota 0.5% + [12] + + 1.0 + + + + Recargo Equivalencia Ded. Cuota 1% + [15] + + 1.0 + + + + Recargo Equivalencia Ded. Cuota 1.4% + [15] + + 1.0 + + + + Recargo Equivalencia Ded. Cuota 4% + [18] + + 1.0 + + + + Recargo Equivalencia Ded. Cuota 5.2% + [18] + + 1.0 + + + + + + + + + + + 4% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 4% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + + + + 7% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 7% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + + + + 8% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 8% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + + + + 10% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 10% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + + + + 16% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 16% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + + + + 18% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 18% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + + + + 21% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + + 21% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + + + + + + IVA 0% Importaciones bienes corrientes + IVA 0% Importaciones bienes corrientes + + percent + + + + + + + purchase + + + + IVA 0% Importaciones bienes de inversión + IVA 0% Importaciones bienes de inversión + + percent + + + + + + + purchase + + + + + IVA 4% Importaciones bienes corrientes + IVA 4% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 4% Importaciones bienes de inversión + IVA 4% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + + + IVA 7% Importaciones bienes corrientes + IVA 7% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 7% Importaciones bienes de inversión + IVA 7% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + + + IVA 8% Importaciones bienes corrientes + IVA 8% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 8% Importaciones bienes de inversión + IVA 8% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + + + IVA 10% Importaciones bienes corrientes + IVA 10% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 10% Importaciones bienes de inversión + IVA 10% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + + + IVA 16% Importaciones bienes corrientes + IVA 16% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 16% Importaciones bienes de inversión + IVA 16% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + + + IVA 18% Importaciones bienes corrientes + IVA 18% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 18% Importaciones bienes de inversión + IVA 18% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + + + IVA 21% Importaciones bienes corrientes + IVA 21% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 21% Importaciones bienes de inversión + IVA 21% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + + + + + + IVA 0% Exportaciones + IVA 0% Exportaciones + + percent + + + + sale + + + + + + IVA 16% Inversión del sujeto pasivo + IVA 16% Inversión del sujeto pasivo + + percent + + + + + + purchase + + + + IVA 16% Inversión del sujeto pasivo (1) + + + percent + + + + + + + purchase + + + + IVA 16% Inversión del sujeto pasivo (2) + + + percent + + + + + + + + + + + purchase + + + + IVA 16% Inversión del sujeto pasivo (3) + + + percent + + + + + + + + + + + purchase + + + + + IVA 18% Inversión del sujeto pasivo + IVA 18% Inversión del sujeto pasivo + + percent + + + + + + purchase + + + + IVA 18% Inversión del sujeto pasivo (1) + + + percent + + + + + + + purchase + + + + IVA 18% Inversión del sujeto pasivo (2) + + + percent + + + + + + + + + + + purchase + + + + IVA 18% Inversión del sujeto pasivo (3) + + + percent + + + + + + + + + + + purchase + + + + + IVA 21% Inversión del sujeto pasivo + IVA 21% Inversión del sujeto pasivo + + percent + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (1) + + + percent + + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (2) + + + percent + + + + + + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (3) + + + percent + + + + + + + + + + + purchase + + + + + + IVA 4% + + percent + + + + + + + + + + + sale + + + + + IVA 7% + + percent + + + + + + + + + + + sale + + + + + IVA 8% + + percent + + + + + + + + + + + sale + + + + + IVA 10% + + percent + + + + + + + + + + + sale + + + + + IVA 16% + + percent + + + + + + + + + + + sale + + + + + IVA 18% + + percent + + + + + + + + + + + sale + + + + + IVA 21% + + percent + + + + + + + + + + + sale + + + + + + + + 0.50% Recargo Equivalencia + + percent + + + + + + + + + + + sale + + + + + 1% Recargo Equivalencia + + percent + + + + + + + + + + + sale + + + + + 1.4% Recargo Equivalencia + + percent + + + + + + + + + + + sale + + + + + 4% Recargo Equivalencia + + percent + + + + + + + + + + + sale + + + + + 5.2% Recargo Equivalencia + + percent + + + + + + + + + + + sale + + + + + 0.50% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 1% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 1.4% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 4% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 5.2% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + + + + + IVA 0% Intracomunitario + IVA 0% Intracomunitario 0 + + percent + + + + + sale + + + + + + + IVA 16% Intracomunitario. Bienes corrientes + IVA 16% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes + IVA 18% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + + + IVA 16% Intracomunitario. Bienes de inversión + IVA 16% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes de inversión + IVA 18% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 18% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes corrientes + IVA 7% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 7% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes de inversión + IVA 7% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 7% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes + IVA 8% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión + IVA 8% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 4% Intracomunitario. Bienes corrientes + IVA 4% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 4% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 4% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 4% Intracomunitario. Bienes de inversión + IVA 4% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 4% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 4% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes + IVA 10% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión + IVA 10% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes + IVA 21% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión + IVA 21% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + + + + + + IRPF Retenciones practicadas Base Imponible + B.IRPF + 1.0 + + + + + IRPF Retenciones practicadas Base Imponible 1% + B.IRPF1 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 2% + B.IRPF2 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 7% + B.IRPF7 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 9% + B.IRPF9 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 15% + B.IRPF15 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 18% + B.IRPF18 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 19% + B.IRPF19 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 20% + B.IRPF20 + + 1.0 + + + + IRPF Retenciones practicadas Base Imponible 21% + B.IRPF21 + + 1.0 + + + + + IRPF Retenciones practicadas Total Cuota + IRPF + + 1.0 + + + + IRPF Retenciones practicadas Cuota 1% + IRPF1 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 2% + IRPF2 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 7% + IRPF7 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 9% + IRPF9 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 15% + IRPF15 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 18% + IRPF18 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 19% + IRPF19 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 20% + IRPF20 + + 1.0 + + + + IRPF Retenciones practicadas Cuota 21% + IRPF21 + + 1.0 + + + + + 475101 + + + other + Hacienda Pública. Retenciones empresarios módulos 1% + + + + + 475102 + + + other + Hacienda Pública. Retenciones act. agrícolas, ganaderas, forestales 2% + + + + + 475107 + + + other + Hacienda Pública. Retenciones act. profesionales 7% + + + + + 475109 + + + other + Hacienda Pública. Retenciones act. profesionales 9% + + + + + 475115 + + + other + Hacienda Pública. Retenciones act. profesionales 15% + + + + + 475118 + + + other + Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 18% + + + + + 475119 + + + other + Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 19% + + + + + 475120 + + + other + Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 20% + + + + + 475121 + + + other + Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 21% + + + + + + + Retenciones IRPF 1% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 2% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 7% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 9% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 15% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 18% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 19% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 20% + + percent + + + + + + + + + + + purchase + + + + + Retenciones IRPF 21% + + percent + + + + + + + + + + + purchase + + + + + + + IRPF Retenciones a cuenta Base Imponible + B.IRPF AC + 1.0 + + + + + IRPF Retenciones a cuenta Base Imponible 1% + B.IRPF1 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 2% + B.IRPF2 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 7% + B.IRPF7 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 9% + B.IRPF9 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 15% + B.IRPF15 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 18% + B.IRPF18 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 19% + B.IRPF19 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 20% + B.IRPF20 AC + + 1.0 + + + + IRPF Retenciones a cuenta Base Imponible 21% + B.IRPF21 AC + + 1.0 + + + + + IRPF Retenciones a cuenta Total Cuota + IRPF AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 1% + IRPF1 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 2% + IRPF2 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 7% + IRPF7 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 9% + IRPF9 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 15% + IRPF15 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 18% + IRPF18 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 19% + IRPF19 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 20% + IRPF20 AC + + 1.0 + + + + IRPF Retenciones a cuenta Cuota 21% + IRPF21 AC + + 1.0 + + + + + 473001 + + + other + Hacienda Pública. Retenciones a cuenta empresarios módulos 1% + + + + + 473002 + + + other + Hacienda Pública. Retenciones a cuenta act. agrícolas, ganaderas, forestales 2% + + + + + 473007 + + + other + Hacienda Pública. Retenciones a cuenta act. profesionales 7% + + + + + 473009 + + + other + Hacienda Pública. Retenciones a cuenta act. profesionales 9% + + + + + 473015 + + + other + Hacienda Pública. Retenciones a cuenta act. profesionales 15% + + + + + 473018 + + + other + Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 18% + + + + + 473019 + + + other + Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 19% + + + + + 473020 + + + other + Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 20% + + + + + 473021 + + + other + Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 21% + + + + + + + Retenciones a cuenta IRPF 1% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 2% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 7% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 9% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 15% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 18% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 19% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 20% + + percent + + + + + + + + + + + sale + + + + + Retenciones a cuenta IRPF 21% + + percent + + + + + + + + + + + sale + + + diff --git a/addons/l10n_es/taxes_data_pymes.xml b/addons/l10n_es/taxes_data_pymes.xml index 7467dbb9596..f48d46d951a 100644 --- a/addons/l10n_es/taxes_data_pymes.xml +++ b/addons/l10n_es/taxes_data_pymes.xml @@ -1,9 +1,10 @@ - + - + + - - - + Ignacio Ibeas (Acysos) - ignacio@acysos.com (2011-05-06) + Añadido Recargos de equivalencia para venta y compra + + Pedro M. Baeza (Serv. Tecnol. Avanzados) - pedro.baeza@serviciosbaeza.com (2013-01-30) + Limpieza de subcuentas de impuestos y corrección de inversión de sujeto pasivo + + --> + + - - + + - + @@ -48,44 +54,103 @@ 1.0 - - - + + + + Base adquisiciones exentas + + -- + 1.0 + + + + Base ventas exentas + -- + + 1.0 + + + + + + IVA Soportado exento (operaciones corrientes) + + percent + + + + + + + purchase + + + + + + IVA Exento + + percent + + + + + + + sale + + - + Régimen general IVA Devengado. Base Imponible 4% [01] 1.0 - + Régimen general IVA Devengado. Base Imponible 7% [04] 1.0 + Régimen general IVA Devengado. Base Imponible 8% [04] 1.0 - + + + Régimen general IVA Devengado. Base Imponible 10% + [04] + + 1.0 + + Régimen general IVA Devengado. Base Imponible 16% [07] 1.0 + Régimen general IVA Devengado. Base Imponible 18% [07] 1.0 - + + + Régimen general IVA Devengado. Base Imponible 21% + [07] + + 1.0 + + - + Recargo Equivalencia Base Imponible 0.5% [10] 1.0 - + Recargo Equivalencia Base Imponible 1% [13] 1.0 - + + + Recargo Equivalencia Base Imponible 1.4% + [13] + + 1.0 + + Recargo Equivalencia Base Imponible 4% [16] 1.0 - - + + + Recargo Equivalencia Base Imponible 5.2% + [16] + + 1.0 + + - + Adquisiciones intracomunitarias. Base Imponible [19] 1.0 - + - - + + - - + + IVA Cuota total devengada [21] 1.0 - + Régimen general IVA Devengado. Cuota 4% [03] 1.0 - + Régimen general IVA Devengado. Cuota 7% [06] 1.0 - + Régimen general IVA Devengado. Cuota 8% [06] 1.0 - + + + Régimen general IVA Devengado. Cuota 10% + [06] + + 1.0 + + Régimen general IVA Devengado. Cuota 16% [09] @@ -173,7 +258,14 @@ 1.0 - + + + Régimen general IVA Devengado. Cuota 21% + [09] + + 1.0 + + - + Recargo Equivalencia. Cuota 0.5% [12] 1.0 - + Recargo Equivalencia. Cuota 1% [15] 1.0 - + + + Recargo Equivalencia. Cuota 1.4% + [15] + + 1.0 + + Recargo Equivalencia. Cuota 4% [18] 1.0 - - + + + Recargo Equivalencia. Cuota 5.2% + [18] + + 1.0 + + + - + Adquisiciones intracomunitarias. Cuota [20] 1.0 - - - - - + + + + + - - + + @@ -230,7 +336,7 @@ 1.0 - + Base operaciones interiores corrientes @@ -238,19 +344,12 @@ 1.0 - - Base operaciones interiores corrientes (16%) + + Base operaciones interiores corrientes (4%) -- 1.0 - - Base operaciones interiores corrientes (18%) - -- - - 1.0 - - Base operaciones interiores corrientes (7%) -- @@ -263,13 +362,31 @@ 1.0 - - Base operaciones interiores corrientes (4%) + + Base operaciones interiores corrientes (10%) -- 1.0 - + + Base operaciones interiores corrientes (16%) + -- + + 1.0 + + + Base operaciones interiores corrientes (18%) + -- + + 1.0 + + + Base operaciones interiores corrientes (21%) + -- + + 1.0 + + Base operaciones interiores bienes inversión @@ -277,48 +394,79 @@ 1.0 - - Base operaciones interiores bienes inversión (16%) - -- - - 1.0 - - - - Base operaciones interiores bienes inversión (18%) - -- - - 1.0 - - - - Base operaciones interiores bienes inversión (7%) - -- - - 1.0 - - - - Base operaciones interiores bienes inversión (8%) - -- - - 1.0 - - Base operaciones interiores bienes inversión (4%) -- 1.0 - - + + Base operaciones interiores bienes inversión (7%) + -- + + 1.0 + + + Base operaciones interiores bienes inversión (8%) + -- + + 1.0 + + + Base operaciones interiores bienes inversión (10%) + -- + + 1.0 + + + Base operaciones interiores bienes inversión (16%) + -- + + 1.0 + + + Base operaciones interiores bienes inversión (18%) + -- + + 1.0 + + + Base operaciones interiores bienes inversión (21%) + -- + + 1.0 + + Base importaciones bienes corrientes [26] 1.0 + + + Base importaciones bienes corrientes (4%) + -- + + 1.0 + + + Base importaciones bienes corrientes (7%) + -- + + 1.0 + + + Base importaciones bienes corrientes (8%) + -- + + 1.0 + + + Base importaciones bienes corrientes (10%) + -- + + 1.0 Base importaciones bienes corrientes (16%) @@ -332,26 +480,13 @@ 1.0 - - - Base importaciones bienes corrientes (7%) + + Base importaciones bienes corrientes (21%) -- 1.0 - - Base importaciones bienes corrientes (8%) - -- - - 1.0 - - - Base importaciones bienes corrientes (4%) - -- - - 1.0 - - + Base importaciones bienes inversión @@ -359,19 +494,12 @@ 1.0 - - Base importaciones bienes inversión (16%) + + Base importaciones bienes inversión (4%) -- 1.0 - - Base importaciones bienes inversión (18%) - -- - - 1.0 - - Base importaciones bienes inversión (7%) -- @@ -384,13 +512,30 @@ 1.0 - - Base importaciones bienes inversión (4%) + + Base importaciones bienes inversión (10%) + -- + + 1.0 + + + Base importaciones bienes inversión (16%) + -- + + 1.0 + + + Base importaciones bienes inversión (18%) + -- + + 1.0 + + + Base importaciones bienes inversión (21%) -- 1.0 - Base adquisiciones intracomunitarias bienes corrientes @@ -398,19 +543,12 @@ 1.0 - - Base adquisiciones intracomunitarias bienes corrientes (16%) + + Base adquisiciones intracomunitarias bienes corrientes (4%) -- 1.0 - - Base adquisiciones intracomunitarias bienes corrientes (18%) - -- - - 1.0 - - Base adquisiciones intracomunitarias bienes corrientes (7%) -- @@ -423,13 +561,30 @@ 1.0 - - Base adquisiciones intracomunitarias bienes corrientes (4%) + + Base adquisiciones intracomunitarias bienes corrientes (10%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (16%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (18%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes corrientes (21%) -- 1.0 - Base adquisiciones intracomunitarias bienes inversión @@ -437,6 +592,30 @@ 1.0 + + Base adquisiciones intracomunitarias bienes inversión (4%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (7%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (8%) + -- + + 1.0 + + + Base adquisiciones intracomunitarias bienes inversión (10%) + -- + + 1.0 + Base adquisiciones intracomunitarias bienes inversión (16%) -- @@ -449,31 +628,53 @@ 1.0 - - - Base adquisiciones intracomunitarias bienes inversión (7%) - -- - - 1.0 - - - Base adquisiciones intracomunitarias bienes inversión (8%) - -- - - 1.0 - - - Base adquisiciones intracomunitarias bienes inversión (4%) + + Base adquisiciones intracomunitarias bienes inversión (21%) -- 1.0 - - + + + Recargo Equivalencia Ded. Base Imponible 0.5% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 1% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 1.4% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 4% + -- + + 1.0 + + + + Recargo Equivalencia Ded. Base Imponible 5.2% + -- + + 1.0 + + + - + IVA deducible (Cuota)- Total a deducir [Mod.303] [37] @@ -488,19 +689,12 @@ 1.0 - - Cuotas soportadas operaciones interiores corrientes (16%) + + Cuotas soportadas operaciones interiores corrientes (4%) -- 1.0 - - Cuotas soportadas operaciones interiores corrientes (18%) - -- - - 1.0 - - Cuotas soportadas operaciones interiores corrientes (7%) -- @@ -513,13 +707,30 @@ 1.0 - - Cuotas soportadas operaciones interiores corrientes (4%) + + Cuotas soportadas operaciones interiores corrientes (10%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (16%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (18%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores corrientes (21%) -- 1.0 - Cuotas soportadas operaciones interiores bienes inversión @@ -527,19 +738,12 @@ 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (16%) + + Cuotas soportadas operaciones interiores bienes inversión (4%) -- 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (18%) - -- - - 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (7%) -- @@ -552,13 +756,30 @@ 1.0 - - Cuotas soportadas operaciones interiores bienes inversión (4%) + + Cuotas soportadas operaciones interiores bienes inversión (10%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (16%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (18%) + -- + + 1.0 + + + Cuotas soportadas operaciones interiores bienes inversión (21%) -- 1.0 - Cuotas devengadas importaciones bienes corrientes @@ -566,19 +787,12 @@ 1.0 - - Cuotas devengadas importaciones bienes corrientes (16%) + + Cuotas devengadas importaciones bienes corrientes (4%) -- 1.0 - - Cuotas devengadas importaciones bienes corrientes (18%) - -- - - 1.0 - - Cuotas devengadas importaciones bienes corrientes (7%) -- @@ -591,13 +805,30 @@ 1.0 - - Cuotas devengadas importaciones bienes corrientes (4%) + + Cuotas devengadas importaciones bienes corrientes (10%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (16%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (18%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes corrientes (21%) -- 1.0 - Cuotas devengadas importaciones bienes inversión @@ -605,19 +836,12 @@ 1.0 - - Cuotas devengadas importaciones bienes inversión (16%) + + Cuotas devengadas importaciones bienes inversión (4%) -- 1.0 - - Cuotas devengadas importaciones bienes inversión (18%) - -- - - 1.0 - - Cuotas devengadas importaciones bienes inversión (7%) -- @@ -630,13 +854,30 @@ 1.0 - - Cuotas devengadas importaciones bienes inversión (4%) + + Cuotas devengadas importaciones bienes inversión (10%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (16%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (18%) + -- + + 1.0 + + + Cuotas devengadas importaciones bienes inversión (21%) -- 1.0 - En adquisiciones intracomunitarias bienes corrientes @@ -644,19 +885,12 @@ 1.0 - - En adquisiciones intracomunitarias bienes corrientes (16%) + + En adquisiciones intracomunitarias bienes corrientes (4%) -- 1.0 - - En adquisiciones intracomunitarias bienes corrientes (18%) - -- - - 1.0 - - En adquisiciones intracomunitarias bienes corrientes (7%) -- @@ -669,13 +903,30 @@ 1.0 - - En adquisiciones intracomunitarias bienes corrientes (4%) + + En adquisiciones intracomunitarias bienes corrientes (10%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (16%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (18%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes corrientes (21%) -- 1.0 - En adquisiciones intracomunitarias bienes inversión @@ -683,19 +934,12 @@ 1.0 - - En adquisiciones intracomunitarias bienes inversión (16%) + + En adquisiciones intracomunitarias bienes inversión (4%) -- 1.0 - - En adquisiciones intracomunitarias bienes inversión (18%) - -- - - 1.0 - - En adquisiciones intracomunitarias bienes inversión (7%) -- @@ -708,13 +952,30 @@ 1.0 - - En adquisiciones intracomunitarias bienes inversión (4%) + + En adquisiciones intracomunitarias bienes inversión (10%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (16%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (18%) + -- + + 1.0 + + + En adquisiciones intracomunitarias bienes inversión (21%) -- 1.0 - Entregas Intracomunitarias @@ -737,109 +998,42 @@ 1.0 - - - + + + Recargo Equivalencia Ded. Cuota 0.5% + [12] + + 1.0 + - - 472004 - - - other - Hacienda Pública. IVA soportado 4% - + + Recargo Equivalencia Ded. Cuota 1% + [15] + + 1.0 - - - 472007 - - - other - Hacienda Pública. IVA soportado 7% - + + + Recargo Equivalencia Ded. Cuota 1.4% + [15] + + 1.0 - - - 472008 - - - other - Hacienda Pública. IVA soportado 8% - + + + Recargo Equivalencia Ded. Cuota 4% + [18] + + 1.0 - - - 472016 - - - other - Hacienda Pública. IVA soportado 16% - + + + Recargo Equivalencia Ded. Cuota 5.2% + [18] + + 1.0 - - - 472018 - - - other - Hacienda Pública. IVA soportado 18% - - - - - 477004 - - - other - Hacienda Pública. IVA repercutido 4% - - - - - 477007 - - - other - Hacienda Pública. IVA repercutido 7% - - - - 477008 - - - other - Hacienda Pública. IVA repercutido 8% - - - - - 477016 - - - other - Hacienda Pública. IVA repercutido 16% - - - - - 477018 - - - other - Hacienda Pública. IVA repercutido 18% - - - - - 475001 - - - payable - Hacienda acreedora IVA - - - - + @@ -851,8 +1045,8 @@ 4% IVA Soportado (operaciones corrientes) percent - - + + @@ -863,14 +1057,14 @@ purchase - + 4% IVA Soportado (bienes de inversión) percent - - + + @@ -881,14 +1075,14 @@ purchase - + 7% IVA Soportado (operaciones corrientes) percent - - + + @@ -899,14 +1093,14 @@ purchase - + 7% IVA Soportado (bienes de inversión) percent - - + + @@ -917,14 +1111,14 @@ purchase - + 8% IVA Soportado (operaciones corrientes) percent - - + + @@ -935,14 +1129,14 @@ purchase - + 8% IVA Soportado (bienes de inversión) percent - - + + @@ -953,14 +1147,50 @@ purchase - + + + + 10% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + 10% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + 16% IVA Soportado (operaciones corrientes) percent - - + + @@ -971,14 +1201,14 @@ purchase - + 16% IVA Soportado (bienes de inversión) percent - - + + @@ -989,14 +1219,14 @@ purchase - + 18% IVA Soportado (operaciones corrientes) percent - - + + @@ -1006,15 +1236,16 @@ purchase + - + 18% IVA Soportado (bienes de inversión) percent - - + + @@ -1025,7 +1256,44 @@ purchase - + + + + 21% IVA Soportado (operaciones corrientes) + + percent + + + + + + + + + + + purchase + + + + + + 21% IVA Soportado (bienes de inversión) + + percent + + + + + + + + + + + purchase + + @@ -1056,15 +1324,15 @@ purchase - + IVA 4% Importaciones bienes corrientes IVA 4% Importaciones bienes corrientes percent - - + + @@ -1081,8 +1349,8 @@ IVA 4% Importaciones bienes de inversión percent - - + + @@ -1093,15 +1361,15 @@ purchase - + IVA 7% Importaciones bienes corrientes IVA 7% Importaciones bienes corrientes percent - - + + @@ -1118,8 +1386,8 @@ IVA 7% Importaciones bienes de inversión percent - - + + @@ -1130,15 +1398,15 @@ purchase - + IVA 8% Importaciones bienes corrientes IVA 8% Importaciones bienes corrientes percent - - + + @@ -1155,8 +1423,8 @@ IVA 8% Importaciones bienes de inversión percent - - + + @@ -1167,15 +1435,52 @@ purchase - + + + + IVA 10% Importaciones bienes corrientes + IVA 10% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 10% Importaciones bienes de inversión + IVA 10% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + + IVA 16% Importaciones bienes corrientes IVA 16% Importaciones bienes corrientes percent - - + + @@ -1192,8 +1497,8 @@ IVA 16% Importaciones bienes de inversión percent - - + + @@ -1204,15 +1509,15 @@ purchase - + IVA 18% Importaciones bienes corrientes IVA 18% Importaciones bienes corrientes percent - - + + @@ -1229,8 +1534,8 @@ IVA 18% Importaciones bienes de inversión percent - - + + @@ -1241,7 +1546,42 @@ purchase - + + + IVA 21% Importaciones bienes corrientes + IVA 21% Importaciones bienes corrientes + + percent + + + + + + + + + + + purchase + + + + IVA 21% Importaciones bienes de inversión + IVA 21% Importaciones bienes de inversión + + percent + + + + + + + + + + + purchase + @@ -1255,7 +1595,7 @@ sale - + @@ -1290,16 +1630,16 @@ percent - - + + - + - + purchase @@ -1308,8 +1648,8 @@ percent - - + + @@ -1320,7 +1660,7 @@ purchase - + IVA 18% Inversión del sujeto pasivo @@ -1354,16 +1694,16 @@ percent - - + + - + - + purchase @@ -1372,8 +1712,8 @@ percent - - + + @@ -1384,15 +1724,79 @@ purchase - + + + IVA 21% Inversión del sujeto pasivo + IVA 21% Inversión del sujeto pasivo + + percent + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (1) + + + percent + + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (2) + + + percent + + + + + + + + + + + purchase + + + + IVA 21% Inversión del sujeto pasivo (3) + + + percent + + + + + + + + + + + purchase + + + IVA 4% percent - - + + @@ -1403,14 +1807,14 @@ sale - + IVA 7% percent - - + + @@ -1421,14 +1825,14 @@ sale - + IVA 8% percent - - + + @@ -1439,14 +1843,32 @@ sale - + + + + IVA 10% + + percent + + + + + + + + + + + sale + + IVA 16% percent - - + + @@ -1457,14 +1879,14 @@ sale - + IVA 18% percent - - + + @@ -1474,17 +1896,36 @@ sale + - - + + + + IVA 21% + + percent + + + + + + + + + + + sale + + + - 0.50% Recargo Equivalencia + 0.50% Recargo Equivalencia Ventas percent - - + + @@ -1495,14 +1936,14 @@ sale - + - 1% Recargo Equivalencia + 1% Recargo Equivalencia Ventas percent - - + + @@ -1513,14 +1954,32 @@ sale - + + + + 1.4% Recargo Equivalencia Ventas + + percent + + + + + + + + + + + sale + + - 4% Recargo Equivalencia + 4% Recargo Equivalencia Ventas percent - - + + @@ -1531,10 +1990,117 @@ sale - - + + + + 5.2% Recargo Equivalencia Ventas + + percent + + + + + + + + + + + sale + + + + 0.50% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 1% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 1.4% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 4% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + + + 5.2% Recargo Equivalencia Compras + + percent + + + + + + + + + + + purchase + + + - + @@ -1548,365 +2114,9 @@ sale - - + + - - - IVA 16% Intracomunitario. Bienes corrientes - IVA 16% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 16% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 16% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - - purchase - - - - - IVA 18% Intracomunitario. Bienes corrientes - IVA 18% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 18% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 18% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - - purchase - - - - - - - IVA 16% Intracomunitario. Bienes de inversión - IVA 16% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 16% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 16% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - - - - - IVA 18% Intracomunitario. Bienes de inversión - IVA 18% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 18% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 18% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes corrientes - IVA 7% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 7% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes de inversión - IVA 7% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 7% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 7% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes corrientes - IVA 8% Intracomunitario. Bienes corrientes - - percent - - purchase - - - - - IVA 8% Intracomunitario. Bienes corrientes (1) - - percent - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes corrientes (2) - - percent - - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes de inversión - IVA 8% Intracomunitario. Bienes de inversión - - percent - - purchase - - - - - IVA 8% Intracomunitario. Bienes de inversión (1) - - percent - - - - - - - - - purchase - - - - - IVA 8% Intracomunitario. Bienes de inversión (2) - - percent - - - - - - - - - - purchase - @@ -1923,8 +2133,8 @@ IVA 4% Intracomunitario. Bienes corrientes (1) percent - - + + @@ -1939,8 +2149,8 @@ IVA 4% Intracomunitario. Bienes corrientes (2) percent - - + + @@ -1966,8 +2176,8 @@ IVA 4% Intracomunitario. Bienes de inversión (1) percent - - + + @@ -1982,8 +2192,8 @@ IVA 4% Intracomunitario. Bienes de inversión (2) percent - - + + @@ -1993,7 +2203,539 @@ purchase - + + + IVA 7% Intracomunitario. Bienes corrientes + IVA 7% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 7% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 7% Intracomunitario. Bienes de inversión + IVA 7% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + + IVA 7% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + + IVA 7% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes + IVA 8% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión + IVA 8% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 8% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes + IVA 10% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión + IVA 10% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 10% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes + IVA 16% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión + IVA 16% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 16% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes + IVA 18% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + + + IVA 18% Intracomunitario. Bienes de inversión + IVA 18% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 18% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 18% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + + + + + IVA 21% Intracomunitario. Bienes corrientes + IVA 21% Intracomunitario. Bienes corrientes + + percent + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes (1) + + percent + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes corrientes (2) + + percent + + + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión + IVA 21% Intracomunitario. Bienes de inversión + + percent + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión (1) + + percent + + + + + + + + + purchase + + + + + IVA 21% Intracomunitario. Bienes de inversión (2) + + percent + + + + + + + + + + purchase + + - + - + IRPF Retenciones practicadas Base Imponible @@ -2011,56 +2753,70 @@ 1.0 - + IRPF Retenciones practicadas Base Imponible 1% B.IRPF1 1.0 - + IRPF Retenciones practicadas Base Imponible 2% B.IRPF2 1.0 - + IRPF Retenciones practicadas Base Imponible 7% B.IRPF7 1.0 - + + + IRPF Retenciones practicadas Base Imponible 9% + B.IRPF9 + + 1.0 + + IRPF Retenciones practicadas Base Imponible 15% B.IRPF15 1.0 - + IRPF Retenciones practicadas Base Imponible 18% B.IRPF18 1.0 - + IRPF Retenciones practicadas Base Imponible 19% B.IRPF19 1.0 - + + + IRPF Retenciones practicadas Base Imponible 20% + B.IRPF20 + + 1.0 + + IRPF Retenciones practicadas Base Imponible 21% B.IRPF21 1.0 - + IRPF Retenciones practicadas Total Cuota @@ -2068,56 +2824,70 @@ 1.0 - + IRPF Retenciones practicadas Cuota 1% IRPF1 1.0 - + IRPF Retenciones practicadas Cuota 2% IRPF2 1.0 - + IRPF Retenciones practicadas Cuota 7% IRPF7 1.0 - + + + IRPF Retenciones practicadas Cuota 9% + IRPF9 + + 1.0 + + IRPF Retenciones practicadas Cuota 15% IRPF15 1.0 - + IRPF Retenciones practicadas Cuota 18% IRPF18 1.0 - + IRPF Retenciones practicadas Cuota 19% IRPF19 1.0 - + + + IRPF Retenciones practicadas Cuota 20% + IRPF20 + + 1.0 + + IRPF Retenciones practicadas Cuota 21% IRPF21 1.0 - + 475101 @@ -2127,7 +2897,7 @@ Hacienda Pública. Retenciones empresarios módulos 1% - + 475102 @@ -2136,7 +2906,7 @@ Hacienda Pública. Retenciones act. agrícolas, ganaderas, forestales 2% - + 475107 @@ -2145,7 +2915,16 @@ Hacienda Pública. Retenciones act. profesionales 7% - + + + 475109 + + + other + Hacienda Pública. Retenciones act. profesionales 9% + + + 475115 @@ -2154,7 +2933,7 @@ Hacienda Pública. Retenciones act. profesionales 15% - + 475118 @@ -2163,7 +2942,7 @@ Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 18% - + 475119 @@ -2172,7 +2951,16 @@ Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 19% - + + + 475120 + + + other + Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 20% + + + 475121 @@ -2181,7 +2969,7 @@ Hacienda Pública. Retenciones arrendamientos, cap. mobiliario 21% - + @@ -2200,7 +2988,7 @@ purchase - + Retenciones IRPF 2% @@ -2218,7 +3006,7 @@ purchase - + Retenciones IRPF 7% @@ -2236,7 +3024,25 @@ purchase - + + + + Retenciones IRPF 9% + + percent + + + + + + + + + + + purchase + + Retenciones IRPF 15% @@ -2254,7 +3060,7 @@ purchase - + Retenciones IRPF 18% @@ -2272,7 +3078,7 @@ purchase - + Retenciones IRPF 19% @@ -2291,6 +3097,24 @@ purchase + + + Retenciones IRPF 20% + + percent + + + + + + + + + + + purchase + + Retenciones IRPF 21% @@ -2308,9 +3132,9 @@ purchase - + - + IRPF Retenciones a cuenta Base Imponible @@ -2318,56 +3142,70 @@ 1.0 - + IRPF Retenciones a cuenta Base Imponible 1% B.IRPF1 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 2% B.IRPF2 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 7% B.IRPF7 AC 1.0 - + + + IRPF Retenciones a cuenta Base Imponible 9% + B.IRPF9 AC + + 1.0 + + IRPF Retenciones a cuenta Base Imponible 15% B.IRPF15 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 18% B.IRPF18 AC 1.0 - + IRPF Retenciones a cuenta Base Imponible 19% B.IRPF19 AC 1.0 - + + + IRPF Retenciones a cuenta Base Imponible 20% + B.IRPF20 AC + + 1.0 + + IRPF Retenciones a cuenta Base Imponible 21% B.IRPF21 AC 1.0 - + IRPF Retenciones a cuenta Total Cuota @@ -2375,56 +3213,70 @@ 1.0 - + IRPF Retenciones a cuenta Cuota 1% IRPF1 AC 1.0 - + IRPF Retenciones a cuenta Cuota 2% IRPF2 AC 1.0 - + IRPF Retenciones a cuenta Cuota 7% IRPF7 AC 1.0 - + + + IRPF Retenciones a cuenta Cuota 9% + IRPF9 AC + + 1.0 + + IRPF Retenciones a cuenta Cuota 15% IRPF15 AC 1.0 - + IRPF Retenciones a cuenta Cuota 18% IRPF18 AC 1.0 - + IRPF Retenciones a cuenta Cuota 19% IRPF19 AC 1.0 - + + + IRPF Retenciones a cuenta Cuota 20% + IRPF20 AC + + 1.0 + + IRPF Retenciones a cuenta Cuota 21% IRPF21 AC 1.0 - + 473001 @@ -2434,7 +3286,7 @@ Hacienda Pública. Retenciones a cuenta empresarios módulos 1% - + 473002 @@ -2443,7 +3295,7 @@ Hacienda Pública. Retenciones a cuenta act. agrícolas, ganaderas, forestales 2% - + 473007 @@ -2452,7 +3304,16 @@ Hacienda Pública. Retenciones a cuenta act. profesionales 7% - + + + 473009 + + + other + Hacienda Pública. Retenciones a cuenta act. profesionales 9% + + + 473015 @@ -2461,7 +3322,7 @@ Hacienda Pública. Retenciones a cuenta act. profesionales 15% - + 473018 @@ -2470,7 +3331,7 @@ Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 18% - + 473019 @@ -2479,7 +3340,16 @@ Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 19% - + + + 473020 + + + other + Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 20% + + + 473021 @@ -2488,7 +3358,7 @@ Hacienda Pública. Retenciones a cuenta arrendamientos, cap. mobiliario 21% - + @@ -2507,7 +3377,7 @@ sale - + Retenciones a cuenta IRPF 2% @@ -2525,7 +3395,7 @@ sale - + Retenciones a cuenta IRPF 7% @@ -2543,7 +3413,25 @@ sale - + + + + Retenciones a cuenta IRPF 9% + + percent + + + + + + + + + + + sale + + Retenciones a cuenta IRPF 15% @@ -2561,7 +3449,7 @@ sale - + Retenciones a cuenta IRPF 18% @@ -2579,7 +3467,7 @@ sale - + Retenciones a cuenta IRPF 19% @@ -2597,7 +3485,25 @@ sale - + + + + Retenciones a cuenta IRPF 20% + + percent + + + + + + + + + + + sale + + Retenciones a cuenta IRPF 21% diff --git a/addons/l10n_fr/__init__.py b/addons/l10n_fr/__init__.py index 8d5728e334e..592068eedda 100644 --- a/addons/l10n_fr/__init__.py +++ b/addons/l10n_fr/__init__.py @@ -22,7 +22,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/l10n_fr/__openerp__.py b/addons/l10n_fr/__openerp__.py index e1d4b9ac334..9a563eeb197 100644 --- a/addons/l10n_fr/__openerp__.py +++ b/addons/l10n_fr/__openerp__.py @@ -22,7 +22,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/l10n_fr/l10n_fr.py b/addons/l10n_fr/l10n_fr.py index c995b44a614..676121b4292 100644 --- a/addons/l10n_fr/l10n_fr.py +++ b/addons/l10n_fr/l10n_fr.py @@ -33,7 +33,6 @@ class l10n_fr_report(osv.osv): ('code_uniq', 'unique (code)','The code report must be unique !') ] -l10n_fr_report() class l10n_fr_line(osv.osv): _name = 'l10n.fr.line' @@ -48,7 +47,6 @@ class l10n_fr_line(osv.osv): ('code_uniq', 'unique (code)', 'The variable name must be unique !') ] -l10n_fr_line() class res_company(osv.osv): _inherit = 'res.company' @@ -58,6 +56,5 @@ class res_company(osv.osv): 'ape': fields.char('APE', size=64), } -res_company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_fr/l10n_fr_view.xml b/addons/l10n_fr/l10n_fr_view.xml old mode 100755 new mode 100644 diff --git a/addons/l10n_fr/report/__init__.py b/addons/l10n_fr/report/__init__.py index 9907a2f5765..c73179a9023 100644 --- a/addons/l10n_fr/report/__init__.py +++ b/addons/l10n_fr/report/__init__.py @@ -22,7 +22,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/l10n_fr/report/base_report.py b/addons/l10n_fr/report/base_report.py index 39a18bc7ca4..bc2cd308bf8 100644 --- a/addons/l10n_fr/report/base_report.py +++ b/addons/l10n_fr/report/base_report.py @@ -22,7 +22,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/l10n_fr/report/bilan_report.py b/addons/l10n_fr/report/bilan_report.py index a7947434da0..2ffbd24cc4f 100644 --- a/addons/l10n_fr/report/bilan_report.py +++ b/addons/l10n_fr/report/bilan_report.py @@ -22,7 +22,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/l10n_fr/report/compute_resultant_report.py b/addons/l10n_fr/report/compute_resultant_report.py index 9a1809fd7cc..5eb62d7e82d 100644 --- a/addons/l10n_fr/report/compute_resultant_report.py +++ b/addons/l10n_fr/report/compute_resultant_report.py @@ -22,7 +22,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/l10n_fr/wizard/__init__.py b/addons/l10n_fr/wizard/__init__.py index 6e29471a975..1bbaf351ea4 100644 --- a/addons/l10n_fr/wizard/__init__.py +++ b/addons/l10n_fr/wizard/__init__.py @@ -22,7 +22,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/l10n_fr/wizard/fr_report_bilan.py b/addons/l10n_fr/wizard/fr_report_bilan.py index 90e97389eed..e7ae542fa3f 100644 --- a/addons/l10n_fr/wizard/fr_report_bilan.py +++ b/addons/l10n_fr/wizard/fr_report_bilan.py @@ -22,7 +22,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 # ############################################################################## @@ -52,6 +52,5 @@ class account_bilan_report(osv.osv_memory): data['form']['fiscalyear_id'] = self.browse(cr, uid, ids)[0].fiscalyear_id.id return {'type': 'ir.actions.report.xml', 'report_name': 'l10n.fr.bilan', 'datas': data} -account_bilan_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_fr/wizard/fr_report_compute_resultant.py b/addons/l10n_fr/wizard/fr_report_compute_resultant.py index eff52189bc9..c83f7494d4a 100644 --- a/addons/l10n_fr/wizard/fr_report_compute_resultant.py +++ b/addons/l10n_fr/wizard/fr_report_compute_resultant.py @@ -22,7 +22,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 # ############################################################################## @@ -52,6 +52,5 @@ class account_cdr_report(osv.osv_memory): data['form']['fiscalyear_id'] = self.browse(cr, uid, ids)[0].fiscalyear_id.id return { 'type': 'ir.actions.report.xml', 'report_name': 'l10n.fr.compute_resultant', 'datas': data} -account_cdr_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_fr_hr_payroll/__init__.py b/addons/l10n_fr_hr_payroll/__init__.py old mode 100755 new mode 100644 diff --git a/addons/l10n_fr_hr_payroll/__openerp__.py b/addons/l10n_fr_hr_payroll/__openerp__.py old mode 100755 new mode 100644 diff --git a/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll.py b/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll.py index 0519fd86a47..ec17792dacd 100644 --- a/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll.py +++ b/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll.py @@ -34,7 +34,6 @@ class res_company(osv.osv): 'conv_coll': fields.char('Convention collective', size=64), } -res_company() class hr_contract(osv.osv): _inherit = 'hr.contract' @@ -44,7 +43,6 @@ class hr_contract(osv.osv): 'niveau': fields.char('Niveau', size=64), 'coef': fields.char('Coefficient', size=64), } -hr_contract() class hr_payslip(osv.osv): _inherit = 'hr.payslip' @@ -52,6 +50,5 @@ class hr_payslip(osv.osv): _columns = { 'payment_mode': fields.char('Mode de paiement', size=64), } -hr_payslip() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll_data.xml b/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll_data.xml old mode 100755 new mode 100644 diff --git a/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll_view.xml b/addons/l10n_fr_hr_payroll/l10n_fr_hr_payroll_view.xml old mode 100755 new mode 100644 diff --git a/addons/l10n_fr_hr_payroll/report/__init__.py b/addons/l10n_fr_hr_payroll/report/__init__.py index 40d2ccc3c05..d6c9481579e 100644 --- a/addons/l10n_fr_hr_payroll/report/__init__.py +++ b/addons/l10n_fr_hr_payroll/report/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python #-*- coding:utf-8 -*- ############################################################################## diff --git a/addons/l10n_fr_rib/bank.py b/addons/l10n_fr_rib/bank.py index 26e10053141..1f5264ef5ac 100644 --- a/addons/l10n_fr_rib/bank.py +++ b/addons/l10n_fr_rib/bank.py @@ -80,7 +80,6 @@ class res_partner_bank(osv.osv): _constraints = [(_check_key, 'The RIB and/or IBAN is not valid', ['rib_acc_number', 'bank_code', 'office', 'key'])] -res_partner_bank() class res_bank(osv.osv): """Add the bank code to make it easier to enter RIB data""" @@ -102,6 +101,5 @@ class res_bank(osv.osv): _columns = { 'rib_code': fields.char('RIB Bank Code', size=64), } -res_bank() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_hr/l10n_hr_chart_template.xml b/addons/l10n_hr/l10n_hr_chart_template.xml old mode 100755 new mode 100644 diff --git a/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py b/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py index 6a7638d919a..fc715ece5b8 100644 --- a/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py +++ b/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py @@ -48,7 +48,6 @@ class hr_contract(osv.osv): 'supplementary_allowance': fields.float('Supplementary Allowance', digits_compute=dp.get_precision('Payroll')), } -hr_contract() class payroll_advice(osv.osv): ''' @@ -104,7 +103,7 @@ class payroll_advice(osv.osv): slip_ids = payslip_pool.search(cr, uid, [('date_from', '<=', advice.date), ('date_to', '>=', advice.date), ('state', '=', 'done')], context=context) for slip in payslip_pool.browse(cr, uid, slip_ids, context=context): if not slip.employee_id.bank_account_id and not slip.employee_id.bank_account_id.acc_number: - raise osv.except_osv(_('Error !'), _('Please define bank account for the %s employee') % (slip.employee_id.name)) + raise osv.except_osv(_('Error!'), _('Please define bank account for the %s employee') % (slip.employee_id.name)) line_ids = payslip_line_pool.search(cr, uid, [ ('slip_id', '=', slip.id), ('code', '=', 'NET')], context=context) if line_ids: line = payslip_line_pool.browse(cr, uid, line_ids, context=context)[0] @@ -130,7 +129,7 @@ class payroll_advice(osv.osv): seq_obj = self.pool.get('ir.sequence') for advice in self.browse(cr, uid, ids, context=context): if not advice.line_ids: - raise osv.except_osv(_('Error !'), _('You can not confirm Payment advice without advice lines.')) + raise osv.except_osv(_('Error!'), _('You can not confirm Payment advice without advice lines.')) advice_date = datetime.strptime(advice.date, DATETIME_FORMAT) advice_year = advice_date.strftime('%m') + '-' + advice_date.strftime('%Y') number = seq_obj.get(cr, uid, 'payment.advice') @@ -157,7 +156,6 @@ class payroll_advice(osv.osv): return { 'value':res } -payroll_advice() class hr_payslip_run(osv.osv): @@ -185,7 +183,7 @@ class hr_payslip_run(osv.osv): users = self.pool.get('res.users').browse(cr, uid, [uid], context=context) for run in self.browse(cr, uid, ids, context=context): if run.available_advice: - raise osv.except_osv(_('Error !'), _("Payment advice already exists for %s, 'Set to Draft' to create a new advice.") %(run.name)) + raise osv.except_osv(_('Error!'), _("Payment advice already exists for %s, 'Set to Draft' to create a new advice.") %(run.name)) advice_data = { 'batch_id': run.id, 'company_id': users[0].company_id.id, @@ -203,7 +201,7 @@ class hr_payslip_run(osv.osv): for slip in payslip_pool.browse(cr, uid, slip_ids, context=context): if not slip.employee_id.bank_account_id or not slip.employee_id.bank_account_id.acc_number: - raise osv.except_osv(_('Error !'), _('Please define bank account for the %s employee') % (slip.employee_id.name)) + raise osv.except_osv(_('Error!'), _('Please define bank account for the %s employee') % (slip.employee_id.name)) line_ids = payslip_line_pool.search(cr, uid, [('slip_id', '=', slip.id), ('code', '=', 'NET')], context=context) if line_ids: line = payslip_line_pool.browse(cr, uid, line_ids, context=context)[0] @@ -216,7 +214,6 @@ class hr_payslip_run(osv.osv): advice_line_pool.create(cr, uid, advice_line, context=context) return self.write(cr, uid, ids, {'available_advice' : True}) -hr_payslip_run() class payroll_advice_line(osv.osv): ''' @@ -247,7 +244,6 @@ class payroll_advice_line(osv.osv): 'debit_credit': 'C', } -payroll_advice_line() class hr_payslip(osv.osv): ''' @@ -265,7 +261,6 @@ class hr_payslip(osv.osv): default.update({'advice_id' : False}) return super(hr_payslip, self).copy(cr, uid, id, default, context=context) -hr_payslip() class res_company(osv.osv): @@ -277,6 +272,5 @@ class res_company(osv.osv): 'dearness_allowance': True, } -res_company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_in_hr_payroll/report/__init__.py b/addons/l10n_in_hr_payroll/report/__init__.py index 8a20170c384..e76f45b69c0 100644 --- a/addons/l10n_in_hr_payroll/report/__init__.py +++ b/addons/l10n_in_hr_payroll/report/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python #-*- coding:utf-8 -*- ############################################################################## diff --git a/addons/l10n_in_hr_payroll/report/payment_advice_report.py b/addons/l10n_in_hr_payroll/report/payment_advice_report.py index 59456b13b55..32c589d2a90 100644 --- a/addons/l10n_in_hr_payroll/report/payment_advice_report.py +++ b/addons/l10n_in_hr_payroll/report/payment_advice_report.py @@ -82,6 +82,5 @@ class payment_advice_report(osv.osv): l.employee_id,l.advice_id,l.bysal,l.ifsc_code, l.name ) """) -payment_advice_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_in_hr_payroll/report/payslip_report.py b/addons/l10n_in_hr_payroll/report/payslip_report.py index b44f123547b..2e1a543a80a 100644 --- a/addons/l10n_in_hr_payroll/report/payslip_report.py +++ b/addons/l10n_in_hr_payroll/report/payslip_report.py @@ -83,6 +83,5 @@ class payslip_report(osv.osv): l.employee_id,p.struct_id,l.category_id ) """) -payslip_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_in_hr_payroll/wizard/hr_salary_employee_bymonth.py b/addons/l10n_in_hr_payroll/wizard/hr_salary_employee_bymonth.py index 62d332ea5b8..93594e1dff8 100644 --- a/addons/l10n_in_hr_payroll/wizard/hr_salary_employee_bymonth.py +++ b/addons/l10n_in_hr_payroll/wizard/hr_salary_employee_bymonth.py @@ -66,6 +66,5 @@ class hr_salary_employee_bymonth(osv.osv_memory): 'datas': datas, } -hr_salary_employee_bymonth() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/l10n_in_hr_payroll/wizard/hr_yearly_salary_detail.py b/addons/l10n_in_hr_payroll/wizard/hr_yearly_salary_detail.py index ed2a02e8d42..de3680f2dd3 100644 --- a/addons/l10n_in_hr_payroll/wizard/hr_yearly_salary_detail.py +++ b/addons/l10n_in_hr_payroll/wizard/hr_yearly_salary_detail.py @@ -61,6 +61,5 @@ class yearly_salary_detail(osv.osv_memory): 'datas': datas, } -yearly_salary_detail() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_it/__openerp__.py b/addons/l10n_it/__openerp__.py index 00ba19e9c42..686fb5ff0d4 100644 --- a/addons/l10n_it/__openerp__.py +++ b/addons/l10n_it/__openerp__.py @@ -29,7 +29,7 @@ { 'name': 'Italy - Accounting', - 'version': '0.1', + 'version': '0.2', 'depends': ['base_vat','account_chart','base_iban'], 'author': 'OpenERP Italian Community', 'description': """ diff --git a/addons/l10n_it/data/account.tax.code.template.csv b/addons/l10n_it/data/account.tax.code.template.csv index d6d6667f43b..e5435945556 100644 --- a/addons/l10n_it/data/account.tax.code.template.csv +++ b/addons/l10n_it/data/account.tax.code.template.csv @@ -1,28 +1,37 @@ code,id,name,parent_id:id ,vat_code_chart_root,Tassazione, IVC,template_ivacode_pagata,IVA a credito,vat_code_chart_root -IVC0,template_ivacode_pagata_0,Esente IVA (credito),template_ivacode_pagata +IVCN,template_ivacode_pagata_ind,IVA a credito indetraibile,vat_code_chart_root +IVC0,template_ivacode_pagata_0,Fuori Campo IVA (credito),template_ivacode_pagata IVCI,template_impcode_pagata,IVA a credito (imponibile),vat_code_chart_root -IVC0I,template_impcode_pagata_0,Esente IVA a credito (imponibile),template_impcode_pagata +IVC0I,template_impcode_pagata_0,Fuori Campo IVA (credito) (imponibile),template_impcode_pagata +IVCart15,template_ivacode_pagata_art15,Escluso Art.15 (credito),template_ivacode_pagata +IVCart15I,template_impcode_pagata_art15,Escluso Art.15. (credito) (imponibile),template_impcode_pagata IVC10,template_ivacode_pagata_10,IVA a credito 10%,template_ivacode_pagata IVC10I,template_impcode_pagata_10,IVA a credito 10% (imponibile),template_impcode_pagata -IVC10ind,template_ivacode_pagata_10ind,IVA a credito 10% indetraibile,template_ivacode_pagata +IVC10ind,template_ivacode_pagata_10ind,IVA a credito 10% indetraibile,template_ivacode_pagata_ind IVC10Iind,template_impcode_pagata_10ind,IVA a credito 10% indetraibile (imponibile),template_impcode_pagata -IVC20ind,template_ivacode_pagata_20ind,IVA a credito 20% indetraibile,template_ivacode_pagata +IVC20ind,template_ivacode_pagata_20ind,IVA a credito 20% indetraibile,template_ivacode_pagata_ind IVC20Iind,template_impcode_pagata_20ind,IVA a credito 20% indetraibile (imponibile),template_impcode_pagata -IVC4ind,template_ivacode_pagata_4ind,IVA a credito 4% indetraibile,template_ivacode_pagata +IVC4ind,template_ivacode_pagata_4ind,IVA a credito 4% indetraibile,template_ivacode_pagata_ind IVC4Iind,template_impcode_pagata_4ind,IVA a credito 4% indetraibile (imponibile),template_impcode_pagata IVC20det10,template_ivacode_pagata_20det10,IVA a credito 20% detraibile 10%,template_ivacode_pagata +IVC20Ndet10,template_ivacode_pagata_20det10ind,IVA a credito 20% detraibile 10% (indetraibile),template_ivacode_pagata_ind IVC20Idet10,template_impcode_pagata_20det10,IVA a credito 20% detraibile 10% (imponibile),template_impcode_pagata IVC20det15,template_ivacode_pagata_20det15,IVA a credito 20% detraibile 15%,template_ivacode_pagata +IVC20Ndet15,template_ivacode_pagata_20det15ind,IVA a credito 20% detraibile 15% (indetraibile),template_ivacode_pagata_ind IVC20Idet15,template_impcode_pagata_20det15,IVA a credito 20% detraibile 15% (imponibile),template_impcode_pagata IVC20det40,template_ivacode_pagata_20det40,IVA a credito 20% detraibile 40%,template_ivacode_pagata +IVC20Ndet40,template_ivacode_pagata_20det40ind,IVA a credito 20% detraibile 40% (indetraibile),template_ivacode_pagata_ind IVC20Idet40,template_impcode_pagata_20det40,IVA a credito 20% detraibile 40% (imponibile),template_impcode_pagata IVC20det50,template_ivacode_pagata_20det50,IVA a credito 20% detraibile 50%,template_ivacode_pagata +IVC20Ndet50,template_ivacode_pagata_20det50ind,IVA a credito 20% detraibile 50% (indetraibile),template_ivacode_pagata_ind IVC20Idet50,template_impcode_pagata_20det50,IVA a credito 20% detraibile 50% (imponibile),template_impcode_pagata IVC10det50,template_ivacode_pagata_10det50,IVA a credito 10% detraibile 50%,template_ivacode_pagata +IVC10Ndet50,template_ivacode_pagata_10det50ind,IVA a credito 10% detraibile 50% (indetraibile),template_ivacode_pagata_ind IVC10Idet50,template_impcode_pagata_10det50,IVA a credito 10% detraibile 50% (imponibile),template_impcode_pagata IVC4det50,template_ivacode_pagata_4det50,IVA a credito 4% detraibile 50%,template_ivacode_pagata +IVC4Ndet50,template_ivacode_pagata_4det50ind,IVA a credito 4% detraibile 50% (indetraibile),template_ivacode_pagata_ind IVC4Idet50,template_impcode_pagata_4det50,IVA a credito 4% detraibile 50% (imponibile),template_impcode_pagata IVC20,template_ivacode_pagata_20,IVA a credito 20%,template_ivacode_pagata IVC20I,template_impcode_pagata_20,IVA a credito 20% (imponibile),template_impcode_pagata @@ -35,9 +44,11 @@ IVC12I,template_impcode_pagata_12,IVA a credito 12% (imponibile),template_impco IVC2,template_ivacode_pagata_2,IVA a credito 2%,template_ivacode_pagata IVC2I,template_impcode_pagata_2,IVA a credito 2% (imponibile),template_impcode_pagata IVD,template_ivacode_riscossa,IVA a debito,vat_code_chart_root -IVD0,template_ivacode_riscossa_0,Esente IVA (debito),template_ivacode_riscossa +IVD0,template_ivacode_riscossa_0,Fuori Campo IVA (debito),template_ivacode_riscossa IVDI,template_impcode_riscossa,IVA a debito (imponibile),vat_code_chart_root -IVD0I,template_impcode_riscossa_0,Esente IVA a debito (imponibile),template_impcode_riscossa +IVD0I,template_impcode_riscossa_0,Fuori Campo IVA (debito) (imponibile),template_impcode_riscossa +IVDart15,template_ivacode_riscossa_art15,Escluso Art.15 (debito),template_ivacode_riscossa +IVDart15I,template_impcode_riscossa_art15,Escluso Art.15 (debito) (imponibile),template_impcode_riscossa IVD10,template_ivacode_riscossa_10,IVA a debito 10%,template_ivacode_riscossa IVD10I,template_impcode_riscossa_10,IVA a debito 10% (imponibile),template_impcode_riscossa IVD20,template_ivacode_riscossa_20,IVA a debito 20%,template_ivacode_riscossa @@ -50,13 +61,17 @@ IVD12,template_ivacode_riscossa_12,IVA a debito 12%,template_ivacode_riscossa IVD12I,template_impcode_riscossa_12,IVA a debito 12% (imponibile),template_impcode_riscossa IVD2,template_ivacode_riscossa_2,IVA a debito 2%,template_ivacode_riscossa IVD2I,template_impcode_riscossa_2,IVA a debito 2% (imponibile),template_impcode_riscossa -IVC21ind,template_ivacode_pagata_21ind,IVA a credito 21% indetraibile,template_ivacode_pagata +IVC21ind,template_ivacode_pagata_21ind,IVA a credito 21% indetraibile,template_ivacode_pagata_ind IVC21Iind,template_impcode_pagata_21ind,IVA a credito 21% indetraibile (imponibile),template_impcode_pagata IVC21det10,template_ivacode_pagata_21det10,IVA a credito 21% detraibile 10%,template_ivacode_pagata +IVC21Ndet10,template_ivacode_pagata_21det10ind,IVA a credito 21% detraibile 10% (indetraibile),template_ivacode_pagata_ind IVC21Idet10,template_impcode_pagata_21det10,IVA a credito 21% detraibile 10% (imponibile),template_impcode_pagata IVC21det15,template_ivacode_pagata_21det15,IVA a credito 21% detraibile 15%,template_ivacode_pagata +IVC21Ndet15,template_ivacode_pagata_21det15ind,IVA a credito 21% detraibile 15% (indetraibile),template_ivacode_pagata_ind IVC21Idet15,template_impcode_pagata_21det15,IVA a credito 21% detraibile 15% (imponibile),template_impcode_pagata IVC21det40,template_ivacode_pagata_21det40,IVA a credito 21% detraibile 40%,template_ivacode_pagata +IVC21Ndet40,template_ivacode_pagata_21det40ind,IVA a credito 21% detraibile 40% (indetraibile),template_ivacode_pagata_ind IVC21Idet40,template_impcode_pagata_21det40,IVA a credito 21% detraibile 40% (imponibile),template_impcode_pagata IVC21det50,template_ivacode_pagata_21det50,IVA a credito 21% detraibile 50%,template_ivacode_pagata +IVC21Ndet50,template_ivacode_pagata_21det50ind,IVA a credito 21% detraibile 50% (indetraibile),template_ivacode_pagata_ind IVC21Idet50,template_impcode_pagata_21det50,IVA a credito 21% detraibile 50% (imponibile),template_impcode_pagata diff --git a/addons/l10n_it/data/account.tax.template.csv b/addons/l10n_it/data/account.tax.template.csv index e003afd1a23..5654b32e5e9 100644 --- a/addons/l10n_it/data/account.tax.template.csv +++ b/addons/l10n_it/data/account.tax.template.csv @@ -1,71 +1,66 @@ id,description,chart_template_id:id,name,sequence,amount,parent_id:id,child_depend,type,account_collected_id:id,account_paid_id:id,type_tax_use,base_code_id:id,tax_code_id:id,ref_base_code_id:id,ref_tax_code_id:id,ref_base_sign,ref_tax_sign,price_include,base_sign,tax_sign -21a,21a,l10n_it_chart_template_generic,Iva al 21% (debito),,0.21,,False,percent,2601,2601,sale,template_impcode_riscossa_21,template_ivacode_riscossa_21,template_impcode_riscossa_21,template_ivacode_riscossa_21,-1,-1,False,, -21b,21b,l10n_it_chart_template_generic,Iva al 21% (credito),,0.21,,False,percent,1601,1601,purchase,template_impcode_pagata_21,template_ivacode_pagata_21,template_impcode_pagata_21,template_ivacode_pagata_21,,,False,-1,-1 -20a,20a,l10n_it_chart_template_generic,Iva al 20% (debito),,0.2,,False,percent,2601,2601,sale,template_impcode_riscossa_20,template_ivacode_riscossa_20,template_impcode_riscossa_20,template_ivacode_riscossa_20,-1,-1,False,, -20b,20b,l10n_it_chart_template_generic,Iva al 20% (credito),,0.2,,False,percent,1601,1601,purchase,template_impcode_pagata_20,template_ivacode_pagata_20,template_impcode_pagata_20,template_ivacode_pagata_20,,,False,-1,-1 -10a,10a,l10n_it_chart_template_generic,Iva al 10% (debito),,0.1,,False,percent,2601,2601,sale,template_impcode_riscossa_10,template_ivacode_riscossa_10,template_impcode_riscossa_10,template_ivacode_riscossa_10,-1,-1,False,, -10b,10b,l10n_it_chart_template_generic,Iva al 10% (credito),,0.1,,False,percent,1601,1601,purchase,template_impcode_pagata_10,template_ivacode_pagata_10,template_impcode_pagata_10,template_ivacode_pagata_10,,,False,-1,-1 -10AO,10AO,l10n_it_chart_template_generic,Iva al 10% indetraibile,,0.1,,True,percent,,,purchase,template_impcode_pagata_10ind,,template_impcode_pagata_10ind,,,,False,-1,-1 -10AOa,10AOa,l10n_it_chart_template_generic,Iva al 10% indetraibile (D),2,0,10AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_10ind,,template_ivacode_pagata_10ind,,,False,, -10AOb,10AOb,l10n_it_chart_template_generic,Iva al 10% indetraibile (I),1,1,10AO,False,percent,,,purchase,,,,,,,False,, -12a,12a,l10n_it_chart_template_generic,Iva 12% (debito),,0.12,,False,percent,2601,2601,sale,template_impcode_riscossa_12,template_ivacode_riscossa_12,template_impcode_riscossa_12,template_ivacode_riscossa_12,-1,-1,False,, -12b,12b,l10n_it_chart_template_generic,Iva 12% (credito),,0.12,,False,percent,1601,1601,purchase,template_impcode_pagata_12,template_ivacode_pagata_12,template_impcode_pagata_12,template_ivacode_pagata_12,,,False,-1,-1 -2010,2010,l10n_it_chart_template_generic,Iva al 20% detraibile 10%,,0.2,,True,percent,,,purchase,template_impcode_pagata_20det10,,template_impcode_pagata_20det10,,,,False,-1,-1 -2010a,2010a,l10n_it_chart_template_generic,Iva al 20% detraibile 10% (D),2,0,2010,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det10,,template_ivacode_pagata_20det10,,,False,, -2010b,2010b,l10n_it_chart_template_generic,Iva al 20% detraibile 10% (I),1,0.9,2010,False,percent,,,purchase,,,,,,,False,, -2015,2015,l10n_it_chart_template_generic,Iva al 20% detraibile 15%,,0.2,,True,percent,,,purchase,template_impcode_pagata_20det15,,template_impcode_pagata_20det15,,,,False,-1,-1 -2015a,2015a,l10n_it_chart_template_generic,Iva al 20% detraibile 15% (D),2,0,2015,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det15,,template_ivacode_pagata_20det15,,,False,, -2015b,2015b,l10n_it_chart_template_generic,Iva al 20% detraibile 15% (I),1,0.85,2015,False,percent,,,purchase,,,,,,,False,, -2040,2040,l10n_it_chart_template_generic,Iva al 20% detraibile 40%,,0.2,,True,percent,,,purchase,template_impcode_pagata_20det40,,template_impcode_pagata_20det40,,,,False,-1,-1 -2040a,2040a,l10n_it_chart_template_generic,Iva al 20% detraibile 40% (D),2,0,2040,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det40,,template_ivacode_pagata_20det40,,,False,, -2040b,2040b,l10n_it_chart_template_generic,Iva al 20% detraibile 40% (I),1,0.6,2040,False,percent,,,purchase,,,,,,,False,, -20AO,20AO,l10n_it_chart_template_generic,Iva al 20% indetraibile,,0.2,,True,percent,,,purchase,template_impcode_pagata_20ind,,template_impcode_pagata_20ind,,,,False,-1,-1 -20AOa,20AOa,l10n_it_chart_template_generic,Iva al 20% indetraibile (D),2,0,20AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_20ind,,template_ivacode_pagata_20ind,,,False,, -20AOb,20AOb,l10n_it_chart_template_generic,Iva al 20% indetraibile (I),1,1,20AO,False,percent,,,purchase,,,,,,,False,, -20I5,20I5,l10n_it_chart_template_generic,IVA al 20% detraibile al 50%,,0.2,,True,percent,,,purchase,template_impcode_pagata_20det50,,template_impcode_pagata_20det50,,,,False,-1,-1 -20I5b,20I5b,l10n_it_chart_template_generic,IVA al 20% detraibile al 50% (I),1,0.5,20I5,False,percent,,,purchase,,,,,,,False,, -20I5a,20I5a,l10n_it_chart_template_generic,IVA al 20% detraibile al 50% (D),2,0,20I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det50,,template_ivacode_pagata_20det50,,,False,, -22a,22a,l10n_it_chart_template_generic,Iva 2% (debito),,0.02,,False,percent,2601,2601,sale,template_impcode_riscossa_2,template_ivacode_riscossa_2,template_impcode_riscossa_2,template_ivacode_riscossa_2,-1,-1,False,, -22b,22b,l10n_it_chart_template_generic,Iva 2% (credito),,0.02,,False,percent,1601,1601,purchase,template_impcode_pagata_2,template_ivacode_pagata_2,template_impcode_pagata_2,template_ivacode_pagata_2,,,False,-1,-1 -4a,4a,l10n_it_chart_template_generic,Iva 4% (debito),,0.04,,False,percent,2601,2601,sale,template_impcode_riscossa_4,template_ivacode_riscossa_4,template_impcode_riscossa_4,template_ivacode_riscossa_4,-1,-1,False,, -4b,4b,l10n_it_chart_template_generic,Iva 4% (credito),,0.04,,False,percent,1601,1601,purchase,template_impcode_pagata_4,template_ivacode_pagata_4,template_impcode_pagata_4,template_ivacode_pagata_4,,,False,-1,-1 -4AO,4AO,l10n_it_chart_template_generic,Iva al 4% indetraibile,,0.04,,True,percent,,,purchase,template_impcode_pagata_4ind,,template_impcode_pagata_4ind,,,,False,-1,-1 -4AOa,4AOa,l10n_it_chart_template_generic,Iva al 4% indetraibile (D),2,0,4AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_4ind,,template_ivacode_pagata_4ind,,,False,, -4AOb,4AOb,l10n_it_chart_template_generic,Iva al 4% indetraibile (I),1,1,4AO,False,percent,,,purchase,,,,,,,False,, -10I5,10I5,l10n_it_chart_template_generic,IVA al 10% detraibile al 50%,,0.1,,True,percent,,,purchase,template_impcode_pagata_10det50,,template_impcode_pagata_10det50,,,,False,-1,-1 -10I5a,10I5a,l10n_it_chart_template_generic,IVA al 10% detraibile al 50% (D),2,0,10I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_10det50,,template_ivacode_pagata_10det50,,,False,, -10I5b,10I5b,l10n_it_chart_template_generic,IVA al 10% detraibile al 50% (I),1,0.5,10I5,False,percent,,,purchase,,,,,,,False,, -4I5,4I5,l10n_it_chart_template_generic,IVA al 4% detraibile al 50%,,0.04,,True,percent,,,purchase,template_impcode_pagata_4det50,,template_impcode_pagata_4det50,,,,False,-1,-1 -4I5a,4I5a,l10n_it_chart_template_generic,IVA al 4% detraibile al 50% (D),2,0,4I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_4det50,,template_ivacode_pagata_4det50,,,False,, -4I5b,4I5b,l10n_it_chart_template_generic,IVA al 4% detraibile al 50% (I),1,0.5,4I5,False,percent,,,purchase,,,,,,,False,, -00a,00a,l10n_it_chart_template_generic,Esente IVA (debito),,0,,False,percent,2601,2601,sale,template_impcode_riscossa_0,template_ivacode_riscossa_0,template_impcode_riscossa_0,template_ivacode_riscossa_0,-1,-1,False,, -00b,00b,l10n_it_chart_template_generic,Esente IVA (credito),,0,,False,percent,1601,1601,purchase,template_impcode_pagata_0,template_ivacode_pagata_0,template_impcode_pagata_0,template_ivacode_pagata_0,,,False,-1,-1 -21a INC,21a INC,l10n_it_chart_template_generic,Iva al 21% (debito) INC,,0.21,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_21,l10n_it.template_ivacode_riscossa_21,l10n_it.template_impcode_riscossa_21,l10n_it.template_ivacode_riscossa_21,-1,-1,True,, -21b INC,21b INC,l10n_it_chart_template_generic,Iva al 21% (credito) INC,,0.21,,False,percent,1601,1601,purchase,template_impcode_pagata_21,template_ivacode_pagata_21,template_impcode_pagata_21,template_ivacode_pagata_21,,,True,-1,-1 -20a INC,20a INC,l10n_it_chart_template_generic,Iva al 20% (debito) INC,,0.2,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_20,l10n_it.template_ivacode_riscossa_20,l10n_it.template_impcode_riscossa_20,l10n_it.template_ivacode_riscossa_20,-1,-1,True,, -20b INC,20b INC,l10n_it_chart_template_generic,Iva al 20% (credito) INC,,0.2,,False,percent,1601,1601,purchase,template_impcode_pagata_20,template_ivacode_pagata_20,template_impcode_pagata_20,template_ivacode_pagata_20,,,True,-1,-1 -10a INC,10a INC,l10n_it_chart_template_generic,Iva al 10% (debito) INC,,0.1,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_10,l10n_it.template_ivacode_riscossa_10,l10n_it.template_impcode_riscossa_10,l10n_it.template_ivacode_riscossa_10,-1,-1,True,, -10b INC,10b INC,l10n_it_chart_template_generic,Iva al 10% (credito) INC,,0.1,,False,percent,1601,1601,purchase,template_impcode_pagata_10,template_ivacode_pagata_10,template_impcode_pagata_10,template_ivacode_pagata_10,,,True,-1,-1 -12a INC,12a INC,l10n_it_chart_template_generic,Iva 12% (debito) INC,,0.12,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_12,l10n_it.template_ivacode_riscossa_12,l10n_it.template_impcode_riscossa_12,l10n_it.template_ivacode_riscossa_12,-1,-1,True,, -12b INC,12b INC,l10n_it_chart_template_generic,Iva 12% (credito) INC,,0.12,,False,percent,1601,1601,purchase,template_impcode_pagata_12,template_ivacode_pagata_12,template_impcode_pagata_12,template_ivacode_pagata_12,,,True,-1,-1 -22a INC,22a INC,l10n_it_chart_template_generic,Iva 2% (debito) INC,,0.02,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_2,l10n_it.template_ivacode_riscossa_2,l10n_it.template_impcode_riscossa_2,l10n_it.template_ivacode_riscossa_2,-1,-1,True,, -22b INC,22b INC,l10n_it_chart_template_generic,Iva 2% (credito) INC,,0.02,,False,percent,1601,1601,purchase,template_impcode_pagata_2,template_ivacode_pagata_2,template_impcode_pagata_2,template_ivacode_pagata_2,,,True,-1,-1 -4a INC,4a INC,l10n_it_chart_template_generic,Iva 4% (debito) INC,,0.04,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_4,l10n_it.template_ivacode_riscossa_4,l10n_it.template_impcode_riscossa_4,l10n_it.template_ivacode_riscossa_4,-1,-1,True,, -4b INC,4b INC,l10n_it_chart_template_generic,Iva 4% (credito) INC,,0.04,,False,percent,1601,1601,purchase,template_impcode_pagata_4,template_ivacode_pagata_4,template_impcode_pagata_4,template_ivacode_pagata_4,,,True,-1,-1 -00a INC,00a INC,l10n_it_chart_template_generic,Esente IVA (debito) INC,,0,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_0,l10n_it.template_ivacode_riscossa_0,l10n_it.template_impcode_riscossa_0,l10n_it.template_ivacode_riscossa_0,-1,-1,True,, -2110,2110,l10n_it_chart_template_generic,Iva al 21% detraibile 10%,,0.21,,True,percent,,,purchase,template_impcode_pagata_21det10,,template_impcode_pagata_21det10,,,,False,-1,-1 -2110a,2110a,l10n_it_chart_template_generic,Iva al 21% detraibile 10% (D),2,0,2110,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det10,,template_ivacode_pagata_21det10,,,False,, -2110b,2110b,l10n_it_chart_template_generic,Iva al 21% detraibile 10% (I),1,0.9,2110,False,percent,,,purchase,,,,,,,False,, -2115,2115,l10n_it_chart_template_generic,Iva al 21% detraibile 15%,,0.21,,True,percent,,,purchase,template_impcode_pagata_21det15,,template_impcode_pagata_21det15,,,,False,-1,-1 -2115a,2115a,l10n_it_chart_template_generic,Iva al 21% detraibile 15% (D),2,0,2115,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det15,,template_ivacode_pagata_21det15,,,False,, -2115b,2115b,l10n_it_chart_template_generic,Iva al 21% detraibile 15% (I),1,0.85,2115,False,percent,,,purchase,,,,,,,False,, -2140,2140,l10n_it_chart_template_generic,Iva al 21% detraibile 40%,,0.21,,True,percent,,,purchase,template_impcode_pagata_21det40,,template_impcode_pagata_21det40,,,,False,-1,-1 -2140a,2140a,l10n_it_chart_template_generic,Iva al 21% detraibile 40% (D),2,0,2140,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det40,,template_ivacode_pagata_21det40,,,False,, -2140b,2140b,l10n_it_chart_template_generic,Iva al 21% detraibile 40% (I),1,0.6,2140,False,percent,,,purchase,,,,,,,False,, -21AO,21AO,l10n_it_chart_template_generic,Iva al 21% indetraibile,,0.21,,True,percent,,,purchase,template_impcode_pagata_21ind,,template_impcode_pagata_21ind,,,,False,-1,-1 -21AOa,21AOa,l10n_it_chart_template_generic,Iva al 21% indetraibile (D),2,0,21AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_21ind,,template_ivacode_pagata_21ind,,,False,, -21AOb,21AOb,l10n_it_chart_template_generic,Iva al 21% indetraibile (I),1,1,21AO,False,percent,,,purchase,,,,,,,False,, -21I5,21I5,l10n_it_chart_template_generic,IVA al 21% detraibile al 50%,,0.21,,True,percent,,,purchase,template_impcode_pagata_21det50,,template_impcode_pagata_21det50,,,,False,-1,-1 -21I5b,21I5b,l10n_it_chart_template_generic,IVA al 21% detraibile al 50% (I),1,0.5,21I5,False,percent,,,purchase,,,,,,,False,, -21I5a,21I5a,l10n_it_chart_template_generic,IVA al 21% detraibile al 50% (D),2,0,21I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det50,,template_ivacode_pagata_21det50,,,False,, - +21v,21v,l10n_it_chart_template_generic,Iva al 21% (debito),1,0.21,,False,percent,2601,2601,sale,template_impcode_riscossa_21,template_ivacode_riscossa_21,template_impcode_riscossa_21,template_ivacode_riscossa_21,-1,-1,False,1,1 +21a,21a,l10n_it_chart_template_generic,Iva al 21% (credito),2,0.21,,False,percent,1601,1601,purchase,template_impcode_pagata_21,template_ivacode_pagata_21,template_impcode_pagata_21,template_ivacode_pagata_21,1,1,False,-1,-1 +20v,20v,l10n_it_chart_template_generic,Iva al 20% (debito),3,0.2,,False,percent,2601,2601,sale,template_impcode_riscossa_20,template_ivacode_riscossa_20,template_impcode_riscossa_20,template_ivacode_riscossa_20,-1,-1,False,1,1 +20a,20a,l10n_it_chart_template_generic,Iva al 20% (credito),4,0.2,,False,percent,1601,1601,purchase,template_impcode_pagata_20,template_ivacode_pagata_20,template_impcode_pagata_20,template_ivacode_pagata_20,1,1,False,-1,-1 +10v,10v,l10n_it_chart_template_generic,Iva al 10% (debito),5,0.1,,False,percent,2601,2601,sale,template_impcode_riscossa_10,template_ivacode_riscossa_10,template_impcode_riscossa_10,template_ivacode_riscossa_10,-1,-1,False,1,1 +10a,10a,l10n_it_chart_template_generic,Iva al 10% (credito),6,0.1,,False,percent,1601,1601,purchase,template_impcode_pagata_10,template_ivacode_pagata_10,template_impcode_pagata_10,template_ivacode_pagata_10,1,1,False,-1,-1 +10AO,10AO,l10n_it_chart_template_generic,Iva al 10% indetraibile,7,0.1,,True,percent,,,purchase,template_impcode_pagata_10ind,,template_impcode_pagata_10ind,,1,1,False,-1,-1 +10AOb,10AOb,l10n_it_chart_template_generic,Iva al 10% indetraibile (D),200,0,10AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_10,,template_ivacode_pagata_10,1,1,False,-1,-1 +10AOa,10AOa,l10n_it_chart_template_generic,Iva al 10% indetraibile (I),100,1,10AO,False,percent,,,purchase,,template_ivacode_pagata_10ind,,template_ivacode_pagata_10ind,1,1,False,-1,-1 +12v,12v,l10n_it_chart_template_generic,Iva 12% (debito),8,0.12,,False,percent,2601,2601,sale,template_impcode_riscossa_12,template_ivacode_riscossa_12,template_impcode_riscossa_12,template_ivacode_riscossa_12,-1,-1,False,1,1 +12a,12a,l10n_it_chart_template_generic,Iva 12% (credito),9,0.12,,False,percent,1601,1601,purchase,template_impcode_pagata_12,template_ivacode_pagata_12,template_impcode_pagata_12,template_ivacode_pagata_12,1,1,False,-1,-1 +2010,2010,l10n_it_chart_template_generic,Iva al 20% detraibile 10%,10,0.2,,True,percent,,,purchase,template_impcode_pagata_20det10,,template_impcode_pagata_20det10,,1,1,False,-1,-1 +2010b,2010b,l10n_it_chart_template_generic,Iva al 20% detraibile 10% (D),200,0,2010,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det10,,template_ivacode_pagata_20det10,1,1,False,-1,-1 +2010a,2010a,l10n_it_chart_template_generic,Iva al 20% detraibile 10% (I),100,0.9,2010,False,percent,,,purchase,,template_ivacode_pagata_20det10ind,,template_ivacode_pagata_20det10ind,1,1,False,-1,-1 +2015,2015,l10n_it_chart_template_generic,Iva al 20% detraibile 15%,11,0.2,,True,percent,,,purchase,template_impcode_pagata_20det15,,template_impcode_pagata_20det15,,1,1,False,-1,-1 +2015b,2015b,l10n_it_chart_template_generic,Iva al 20% detraibile 15% (D),200,0,2015,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det15,,template_ivacode_pagata_20det15,1,1,False,-1,-1 +2015a,2015a,l10n_it_chart_template_generic,Iva al 20% detraibile 15% (I),100,0.85,2015,False,percent,,,purchase,,template_ivacode_pagata_20det15ind,,template_ivacode_pagata_20det15ind,1,1,False,-1,-1 +2040,2040,l10n_it_chart_template_generic,Iva al 20% detraibile 40%,12,0.2,,True,percent,,,purchase,template_impcode_pagata_20det40,,template_impcode_pagata_20det40,,1,1,False,-1,-1 +2040b,2040b,l10n_it_chart_template_generic,Iva al 20% detraibile 40% (D),200,0,2040,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det40,,template_ivacode_pagata_20det40,1,1,False,-1,-1 +2040a,2040a,l10n_it_chart_template_generic,Iva al 20% detraibile 40% (I),100,0.6,2040,False,percent,,,purchase,,template_ivacode_pagata_20det40ind,,template_ivacode_pagata_20det40ind,1,1,False,-1,-1 +20AO,20AO,l10n_it_chart_template_generic,Iva al 20% indetraibile,13,0.2,,True,percent,,,purchase,template_impcode_pagata_20ind,,template_impcode_pagata_20ind,,1,1,False,-1,-1 +20AOb,20AOb,l10n_it_chart_template_generic,Iva al 20% indetraibile (D),200,0,20AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_20ind,,template_ivacode_pagata_20ind,1,1,False,-1,-1 +20AOa,20AOa,l10n_it_chart_template_generic,Iva al 20% indetraibile (I),100,1,20AO,False,percent,,,purchase,,template_ivacode_pagata_20ind,,template_ivacode_pagata_20ind,1,1,False,-1,-1 +20I5,20I5,l10n_it_chart_template_generic,IVA al 20% detraibile al 50%,14,0.2,,True,percent,,,purchase,template_impcode_pagata_20det50,,template_impcode_pagata_20det50,,1,1,False,-1,-1 +20I5b,20I5b,l10n_it_chart_template_generic,IVA al 20% detraibile al 50% (D),200,0,20I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_20det50,,template_ivacode_pagata_20det50,1,1,False,-1,-1 +20I5a,20I5a,l10n_it_chart_template_generic,IVA al 20% detraibile al 50% (I),100,0.5,20I5,False,percent,,,purchase,,template_ivacode_pagata_20det50ind,,template_ivacode_pagata_20det50ind,1,1,False,-1,-1 +22v,22v,l10n_it_chart_template_generic,Iva 2% (debito),15,0.02,,False,percent,2601,2601,sale,template_impcode_riscossa_2,template_ivacode_riscossa_2,template_impcode_riscossa_2,template_ivacode_riscossa_2,-1,-1,False,1,1 +22a,22a,l10n_it_chart_template_generic,Iva 2% (credito),16,0.02,,False,percent,1601,1601,purchase,template_impcode_pagata_2,template_ivacode_pagata_2,template_impcode_pagata_2,template_ivacode_pagata_2,1,1,False,-1,-1 +4v,4v,l10n_it_chart_template_generic,Iva 4% (debito),17,0.04,,False,percent,2601,2601,sale,template_impcode_riscossa_4,template_ivacode_riscossa_4,template_impcode_riscossa_4,template_ivacode_riscossa_4,-1,-1,False,1,1 +4a,4a,l10n_it_chart_template_generic,Iva 4% (credito),18,0.04,,False,percent,1601,1601,purchase,template_impcode_pagata_4,template_ivacode_pagata_4,template_impcode_pagata_4,template_ivacode_pagata_4,1,1,False,-1,-1 +4AO,4AO,l10n_it_chart_template_generic,Iva al 4% indetraibile,19,0.04,,True,percent,,,purchase,template_impcode_pagata_4ind,,template_impcode_pagata_4ind,,1,1,False,-1,-1 +4AOb,4AOb,l10n_it_chart_template_generic,Iva al 4% indetraibile (D),200,0,4AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_4ind,,template_ivacode_pagata_4ind,1,1,False,-1,-1 +4AOa,4AOa,l10n_it_chart_template_generic,Iva al 4% indetraibile (I),100,1,4AO,False,percent,,,purchase,,template_ivacode_pagata_4ind,,template_ivacode_pagata_4ind,1,1,False,-1,-1 +10I5,10I5,l10n_it_chart_template_generic,IVA al 10% detraibile al 50%,20,0.1,,True,percent,,,purchase,template_impcode_pagata_10det50,,template_impcode_pagata_10det50,,1,1,False,-1,-1 +10I5b,10I5b,l10n_it_chart_template_generic,IVA al 10% detraibile al 50% (D),200,0,10I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_10det50,,template_ivacode_pagata_10det50,1,1,False,-1,-1 +10I5a,10I5a,l10n_it_chart_template_generic,IVA al 10% detraibile al 50% (I),100,0.5,10I5,False,percent,,,purchase,,template_ivacode_pagata_10det50ind,,template_ivacode_pagata_10det50ind,1,1,False,-1,-1 +4I5,4I5,l10n_it_chart_template_generic,IVA al 4% detraibile al 50%,21,0.04,,True,percent,,,purchase,template_impcode_pagata_4det50,,template_impcode_pagata_4det50,,1,1,False,-1,-1 +4I5b,4I5b,l10n_it_chart_template_generic,IVA al 4% detraibile al 50% (D),200,0,4I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_4det50,,template_ivacode_pagata_4det50,1,1,False,-1,-1 +4I5a,4I5a,l10n_it_chart_template_generic,IVA al 4% detraibile al 50% (I),100,0.5,4I5,False,percent,,,purchase,,template_ivacode_pagata_4det50ind,,template_ivacode_pagata_4det50ind,1,1,False,-1,-1 +00v,00v,l10n_it_chart_template_generic,Fuori Campo IVA (debito),22,0,,False,percent,2601,2601,sale,template_impcode_riscossa_0,template_ivacode_riscossa_0,template_impcode_riscossa_0,template_ivacode_riscossa_0,-1,-1,False,1,1 +00a,00a,l10n_it_chart_template_generic,Fuori Campo IVA (credito),23,0,,False,percent,1601,1601,purchase,template_impcode_pagata_0,template_ivacode_pagata_0,template_impcode_pagata_0,template_ivacode_pagata_0,1,1,False,-1,-1 +00art15v,00art15v,l10n_it_chart_template_generic,Imponibile Escluso Art.15 (debito),22,0,,False,percent,2601,2601,sale,template_impcode_riscossa_art15,template_ivacode_riscossa_art15,template_impcode_riscossa_art15,template_ivacode_riscossa_art15,-1,-1,False,1,1 +00art15a,00art15a,l10n_it_chart_template_generic,Imponibile Escluso Art.15 (credito),23,0,,False,percent,1601,1601,purchase,template_impcode_pagata_art15,template_ivacode_pagata_art15,template_impcode_pagata_art15,template_ivacode_pagata_art15,1,1,False,-1,-1 +21v INC,21v INC,l10n_it_chart_template_generic,Iva al 21% (debito) INC,24,0.21,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_21,l10n_it.template_ivacode_riscossa_21,l10n_it.template_impcode_riscossa_21,l10n_it.template_ivacode_riscossa_21,-1,-1,True,1,1 +20v INC,20v INC,l10n_it_chart_template_generic,Iva al 20% (debito) INC,25,0.2,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_20,l10n_it.template_ivacode_riscossa_20,l10n_it.template_impcode_riscossa_20,l10n_it.template_ivacode_riscossa_20,-1,-1,True,1,1 +10v INC,10v INC,l10n_it_chart_template_generic,Iva al 10% (debito) INC,26,0.1,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_10,l10n_it.template_ivacode_riscossa_10,l10n_it.template_impcode_riscossa_10,l10n_it.template_ivacode_riscossa_10,-1,-1,True,1,1 +12v INC,12v INC,l10n_it_chart_template_generic,Iva 12% (debito) INC,27,0.12,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_12,l10n_it.template_ivacode_riscossa_12,l10n_it.template_impcode_riscossa_12,l10n_it.template_ivacode_riscossa_12,-1,-1,True,1,1 +22v INC,22v INC,l10n_it_chart_template_generic,Iva 2% (debito) INC,28,0.02,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_2,l10n_it.template_ivacode_riscossa_2,l10n_it.template_impcode_riscossa_2,l10n_it.template_ivacode_riscossa_2,-1,-1,True,1,1 +4v INC,4v INC,l10n_it_chart_template_generic,Iva 4% (debito) INC,29,0.04,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_4,l10n_it.template_ivacode_riscossa_4,l10n_it.template_impcode_riscossa_4,l10n_it.template_ivacode_riscossa_4,-1,-1,True,1,1 +00v INC,00v INC,l10n_it_chart_template_generic,Fuori Campo IVA (debito) INC,30,0,,False,percent,l10n_it.2601,l10n_it.2601,sale,l10n_it.template_impcode_riscossa_0,l10n_it.template_ivacode_riscossa_0,l10n_it.template_impcode_riscossa_0,l10n_it.template_ivacode_riscossa_0,-1,-1,True,1,1 +2110,2110,l10n_it_chart_template_generic,Iva al 21% detraibile 10%,31,0.21,,True,percent,,,purchase,template_impcode_pagata_21det10,,template_impcode_pagata_21det10,,1,1,False,-1,-1 +2110b,2110b,l10n_it_chart_template_generic,Iva al 21% detraibile 10% (D),200,0,2110,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det10,,template_ivacode_pagata_21det10,1,1,False,-1,-1 +2110a,2110a,l10n_it_chart_template_generic,Iva al 21% detraibile 10% (I),100,0.9,2110,False,percent,,,purchase,,template_ivacode_pagata_21det10ind,,template_ivacode_pagata_21det10ind,1,1,False,-1,-1 +2115,2115,l10n_it_chart_template_generic,Iva al 21% detraibile 15%,32,0.21,,True,percent,,,purchase,template_impcode_pagata_21det15,,template_impcode_pagata_21det15,,1,1,False,-1,-1 +2115b,2115b,l10n_it_chart_template_generic,Iva al 21% detraibile 15% (D),200,0,2115,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det15,,template_ivacode_pagata_21det15,1,1,False,-1,-1 +2115a,2115a,l10n_it_chart_template_generic,Iva al 21% detraibile 15% (I),100,0.85,2115,False,percent,,,purchase,,template_ivacode_pagata_21det15ind,,template_ivacode_pagata_21det15ind,1,1,False,-1,-1 +2140,2140,l10n_it_chart_template_generic,Iva al 21% detraibile 40%,33,0.21,,True,percent,,,purchase,template_impcode_pagata_21det40,,template_impcode_pagata_21det40,,1,1,False,-1,-1 +2140b,2140b,l10n_it_chart_template_generic,Iva al 21% detraibile 40% (D),200,0,2140,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det40,,template_ivacode_pagata_21det40,1,1,False,-1,-1 +2140a,2140a,l10n_it_chart_template_generic,Iva al 21% detraibile 40% (I),100,0.6,2140,False,percent,,,purchase,,template_ivacode_pagata_21det40ind,,template_ivacode_pagata_21det40ind,1,1,False,-1,-1 +21AO,21AO,l10n_it_chart_template_generic,Iva al 21% indetraibile,34,0.21,,True,percent,,,purchase,template_impcode_pagata_21ind,,template_impcode_pagata_21ind,,1,1,False,-1,-1 +21AOb,21AOb,l10n_it_chart_template_generic,Iva al 21% indetraibile (D),200,0,21AO,False,balance,1601,1601,purchase,,template_ivacode_pagata_21ind,,template_ivacode_pagata_21ind,1,1,False,-1,-1 +21AOa,21AOa,l10n_it_chart_template_generic,Iva al 21% indetraibile (I),100,1,21AO,False,percent,,,purchase,,template_ivacode_pagata_21ind,,template_ivacode_pagata_21ind,1,1,False,-1,-1 +21I5,21I5,l10n_it_chart_template_generic,IVA al 21% detraibile al 50%,35,0.21,,True,percent,,,purchase,template_impcode_pagata_21det50,,template_impcode_pagata_21det50,,1,1,False,-1,-1 +21I5b,21I5b,l10n_it_chart_template_generic,IVA al 21% detraibile al 50% (D),200,0,21I5,False,balance,1601,1601,purchase,,template_ivacode_pagata_21det50,,template_ivacode_pagata_21det50,1,1,False,-1,-1 +21I5a,21I5a,l10n_it_chart_template_generic,IVA al 21% detraibile al 50% (I),100,0.5,21I5,False,percent,,,purchase,,template_ivacode_pagata_21det50ind,,template_ivacode_pagata_21det50ind,1,1,False,-1,-1 diff --git a/addons/l10n_lu/account_financial_report.xml b/addons/l10n_lu/account_financial_report.xml index b39b0ceb15f..62a7a8c8d7e 100644 --- a/addons/l10n_lu/account_financial_report.xml +++ b/addons/l10n_lu/account_financial_report.xml @@ -84,7 +84,7 @@ - 2. Concessions, brevets, licences, marques, ainsi que droits et valeurs similaires s’ils ont été + 2. Concessions, brevets, licences, marques, ainsi que droits et valeurs similaires s’ils ont été 115 detail_flat @@ -256,7 +256,7 @@ - I. Stocks + I. Stocks 153 detail_flat @@ -292,7 +292,7 @@ - 4. Acomptes versés + 4. Acomptes versés 161 no_detail @@ -301,7 +301,7 @@ - II. Créances + II. Créances 163 detail_flat @@ -364,7 +364,7 @@ - 3. Créances sur des entreprises avec lesquelles la société a un + 3. Créances sur des entreprises avec lesquelles la société a un lien de participation 177 detail_flat @@ -436,7 +436,7 @@ - 2. Actions propres ou parts propres + 2. Actions propres ou parts propres 193 no_detail @@ -445,7 +445,7 @@ - 3. Autres valeurs mobilières + 3. Autres valeurs mobilières 195 no_detail @@ -963,7 +963,7 @@ - CHARGES + A. CHARGES 641 detail_flat @@ -972,7 +972,7 @@ - 1. Consommation de marchandises et de matières premières et consommables + 1. Consommation de marchandises et de matières premières et consommables 601 no_detail @@ -1044,7 +1044,7 @@ - a) sur frais d'établissement et sur immobilisations corporelles + a) sur frais d'établissement et sur immobilisations corporelles et incorporelles 617 no_detail @@ -1071,7 +1071,7 @@ - 6. Corrections de valeur sur immobilisations financières et aj + 6. Corrections de valeur sur immobilisations financières et ajustement de juste valeur sur immobilisations financières 623 no_detail @@ -1080,7 +1080,7 @@ - 7. Corrections de valeur et ajustement de juste valeur sur élém + 7. Corrections de valeur et ajustement de juste valeur sur éléments financiers de l'actif circulant. Moins-values de cessions des valeurs mobilières 625 no_detail @@ -1143,7 +1143,7 @@ - PRODUITS + B. PRODUITS 737 detail_flat @@ -1161,7 +1161,7 @@ - 2. Variation des stocks de produits finis, et de produits et de commandes en cours + 2. Variation des stocks de produits finis, et de produits et de commandes en cours 703 no_detail @@ -1188,7 +1188,7 @@ - a) sur frais d'établissement et sur immobilisations corporelles + a) sur frais d'établissement et sur immobilisations corporelles et incorporelles 709 no_detail diff --git a/addons/l10n_lu/wizard/print_vat.py b/addons/l10n_lu/wizard/print_vat.py index abd5c7ce298..04d4fe9a3b7 100644 --- a/addons/l10n_lu/wizard/print_vat.py +++ b/addons/l10n_lu/wizard/print_vat.py @@ -9,10 +9,10 @@ from __future__ import with_statement import openerp from openerp.osv import fields, osv from openerp import tools +from openerp.modules.module import get_module_resource from openerp.tools.translate import _ from openerp.report.render import render from openerp.report.interface import report_int -from openerp import addons import tempfile import os @@ -53,7 +53,7 @@ class report_custom(report_int): try: tmp_file = tempfile.mkstemp(".pdf")[1] try: - tools.pdf_utils.fill_pdf(addons.get_module_resource('l10n_lu','wizard', '2008_DECL_F_M10.pdf'), tmp_file, result) + tools.pdf_utils.fill_pdf(get_module_resource('l10n_lu','wizard', '2008_DECL_F_M10.pdf'), tmp_file, result) with open(tmp_file, "r") as ofile: self.obj = external_pdf(ofile.read()) finally: @@ -64,7 +64,7 @@ class report_custom(report_int): self.obj.render() return (self.obj.pdf, 'pdf') except Exception: - raise osv.except_osv(_('pdf not created !'), _('Please check if package pdftk is installed!')) + raise osv.except_osv(_('PDF Not Created!'), _('Please check if package pdftk is installed!')) report_custom('report.l10n_lu.tax.report.print') @@ -92,6 +92,5 @@ class vat_declaration_report(osv.osv_memory): data['form']['period_id'] = self.browse(cr, uid, ids)[0].period_id.id return { 'type': 'ir.actions.report.xml', 'report_name': 'l10n_lu.tax.report.print', 'datas': data} -vat_declaration_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_ma/l10n_ma.py b/addons/l10n_ma/l10n_ma.py index 6321516cf0f..a2a28a21f82 100644 --- a/addons/l10n_ma/l10n_ma.py +++ b/addons/l10n_ma/l10n_ma.py @@ -33,7 +33,6 @@ class l10n_ma_report(osv.osv): _sql_constraints = [ ('code_uniq', 'unique (code)','The code report must be unique !') ] -l10n_ma_report() class l10n_ma_line(osv.osv): _name = 'l10n.ma.line' @@ -47,6 +46,5 @@ class l10n_ma_line(osv.osv): _sql_constraints = [ ('code_uniq', 'unique (code)', 'The variable name must be unique !') ] -l10n_ma_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_multilang/account.py b/addons/l10n_multilang/account.py index 4cb0e28b672..55770c5ec14 100644 --- a/addons/l10n_multilang/account.py +++ b/addons/l10n_multilang/account.py @@ -31,21 +31,18 @@ class account_account_template(osv.osv): _columns = { 'name': fields.char('Name', size=128, required=True, select=True, translate=True), } -account_account_template() class account_account(osv.osv): _inherit = 'account.account' _columns = { 'name': fields.char('Name', size=128, required=True, select=True, translate=True), } -account_account() class account_tax(osv.osv): _inherit = 'account.tax' _columns = { 'name': fields.char('Tax Name', size=128, required=True, select=True, translate=True), } -account_tax() class account_tax_template(osv.osv): @@ -53,7 +50,6 @@ class account_tax_template(osv.osv): _columns = { 'name': fields.char('Tax Name', size=128, required=True, select=True, translate=True), } -account_tax_template() class account_tax_code_template(osv.osv): @@ -61,7 +57,6 @@ class account_tax_code_template(osv.osv): _columns = { 'name': fields.char('Tax Case Name', size=64, required=True, translate=True), } -account_tax_code_template() class account_chart_template(osv.osv): @@ -71,7 +66,6 @@ class account_chart_template(osv.osv): 'spoken_languages': fields.char('Spoken Languages', size=64, help="State here the languages for which the translations of templates could be loaded at the time of installation of this localization module and copied in the final object when generating them from templates. You must provide the language codes separated by ';'"), } _order = 'name' -account_chart_template() class account_fiscal_position(osv.osv): @@ -79,7 +73,6 @@ class account_fiscal_position(osv.osv): _columns = { 'name': fields.char('Fiscal Position', size=64, required=True, translate=True), } -account_fiscal_position() class account_fiscal_position_template(osv.osv): @@ -87,7 +80,6 @@ class account_fiscal_position_template(osv.osv): _columns = { 'name': fields.char('Fiscal Position Template', size=64, required=True, translate=True), } -account_fiscal_position_template() class account_journal(osv.osv): @@ -95,7 +87,6 @@ class account_journal(osv.osv): _columns = { 'name': fields.char('Journal Name', size=64, required=True, translate=True), } -account_journal() class account_analytic_account(osv.osv): @@ -103,7 +94,6 @@ class account_analytic_account(osv.osv): _columns = { 'name': fields.char('Account Name', size=128, required=True, translate=True), } -account_analytic_account() class account_analytic_journal(osv.osv): @@ -111,4 +101,3 @@ class account_analytic_journal(osv.osv): _columns = { 'name': fields.char('Journal Name', size=64, required=True, translate=True), } -account_analytic_journal() diff --git a/addons/l10n_multilang/l10n_multilang.py b/addons/l10n_multilang/l10n_multilang.py index 9596b292ff3..b7564a9960a 100644 --- a/addons/l10n_multilang/l10n_multilang.py +++ b/addons/l10n_multilang/l10n_multilang.py @@ -78,7 +78,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): else: #replace the value in the destination object only if it's the user lang if context.get('lang') == lang: - self.pool.get(out_obj._name).write(cr, uid, out_ids[j], {in_field: value[in_id]}) + self.pool[out_obj._name].write(cr, uid, out_ids[j], {in_field: value[in_id]}) else: _logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name)) return True @@ -150,6 +150,5 @@ class wizard_multi_charts_accounts(osv.osv_memory): out_ids = obj_fiscal_position.search(cr, uid, [('company_id', '=', company_id)], order='id') return self.process_translations(cr, uid, langs, obj_fiscal_position_template, field, in_ids, obj_fiscal_position, out_ids, force_write=False, context=context) -wizard_multi_charts_accounts() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_nl/__init__.py b/addons/l10n_nl/__init__.py index 57a3bb10df3..ee9f0292f12 100644 --- a/addons/l10n_nl/__init__.py +++ b/addons/l10n_nl/__init__.py @@ -22,7 +22,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/l10n_nl/__openerp__.py b/addons/l10n_nl/__openerp__.py index 5e811511c01..aec85016ea5 100644 --- a/addons/l10n_nl/__openerp__.py +++ b/addons/l10n_nl/__openerp__.py @@ -22,7 +22,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/l10n_nl/account_chart_netherlands.xml b/addons/l10n_nl/account_chart_netherlands.xml index 516c88bdcf9..c7eefb42cde 100644 --- a/addons/l10n_nl/account_chart_netherlands.xml +++ b/addons/l10n_nl/account_chart_netherlands.xml @@ -3940,7 +3940,7 @@ 2a - Leveringen/diensten waarbij de heffing van omzetbelasting naar u is verlegd (BTW) + Heffing van omzetbelasting is naar u verlegd (BTW) @@ -4052,7 +4052,7 @@ 2a - Leveringen/diensten waarbij de heffing van omzetbelasting naar u is verlegd (omzet) + Heffing van omzetbelasting is naar u verlegd (omzet) @@ -4260,7 +4260,7 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge - purchase + sale 15 @@ -4279,9 +4279,9 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge - 99 + 98 - BTW af te dragen verlegd (inkopen1) + BTW te vorderen verlegd (inkopen1) percent @@ -4304,54 +4304,8 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge + - - purchase - - - 15 - - BTW te vorderen verlegd (inkopen) - 21% BTW verlegd - - percent - - - - - - - purchase - - - - 99 - - BTW te vorderen verlegd (inkopen1) - - percent - - - - - - - - purchase - - - 99 - - BTW te vorderen verlegd (inkopen2) - - percent - - - - - - - purchase @@ -4402,6 +4356,7 @@ TODO rubriek 1c en 1d moeten nog, zijn variabel, dus BTW percentage moet door ge + 20 Inkopen import binnen EU hoog 21% BTW import binnen EU diff --git a/addons/l10n_nl/account_fiscal_position_tax_template.xml b/addons/l10n_nl/account_fiscal_position_tax_template.xml index 622ffafa67c..9fe9a3df786 100644 --- a/addons/l10n_nl/account_fiscal_position_tax_template.xml +++ b/addons/l10n_nl/account_fiscal_position_tax_template.xml @@ -90,6 +90,13 @@ + + + + + + + diff --git a/addons/l10n_nl/account_fiscal_position_template.xml b/addons/l10n_nl/account_fiscal_position_template.xml index fe658c6d4b7..1c69f2d1198 100644 --- a/addons/l10n_nl/account_fiscal_position_template.xml +++ b/addons/l10n_nl/account_fiscal_position_template.xml @@ -7,6 +7,10 @@ Binnenland + + BTW verlegd + + EU landen diff --git a/addons/l10n_pa/__init__.py b/addons/l10n_pa/__init__.py index 92da5dbf966..25e7e337165 100644 --- a/addons/l10n_pa/__init__.py +++ b/addons/l10n_pa/__init__.py @@ -23,7 +23,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/l10n_pe/__init__.py b/addons/l10n_pe/__init__.py index 92da5dbf966..25e7e337165 100644 --- a/addons/l10n_pe/__init__.py +++ b/addons/l10n_pe/__init__.py @@ -23,7 +23,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/l10n_ro/partner_view.xml b/addons/l10n_ro/partner_view.xml index c03d5c9a1a6..102ba3d92f0 100644 --- a/addons/l10n_ro/partner_view.xml +++ b/addons/l10n_ro/partner_view.xml @@ -7,7 +7,6 @@ res.partner - diff --git a/addons/l10n_ro/res_partner.py b/addons/l10n_ro/res_partner.py old mode 100755 new mode 100644 index 1cfe7390a77..79933dc468e --- a/addons/l10n_ro/res_partner.py +++ b/addons/l10n_ro/res_partner.py @@ -1,4 +1,3 @@ - # -*- encoding: utf-8 -*- ############################################################################## # @@ -28,10 +27,32 @@ class res_partner(osv.osv): _columns = { 'nrc' : fields.char('NRC', size=16, help='Registration number at the Registry of Commerce'), } + + # The SQL constraints are no-ops but present only to display the right error message to the + # user when the partial unique indexes defined below raise errors/ + # The real constraints need to be implemented with PARTIAL UNIQUE INDEXES (see auto_init), + # due to the way accounting data is delegated by contacts to their companies in OpenERP 7.0. _sql_constraints = [ - ('vat_uniq', 'unique (vat)', 'The vat of the partner must be unique !'), - ('nrc_uniq', 'unique (nrc)', 'The code of the partner must be unique !') + ('vat_uniq', 'unique (id)', 'The vat of the partner must be unique !'), + ('nrc_uniq', 'unique (id)', 'The code of the partner must be unique !') ] -res_partner() + + def _auto_init(self, cr, context=None): + result = super(res_partner, self)._auto_init(cr, context=context) + # Real implementation of the vat/nrc constraints: only "commercial entities" need to have + # unique numbers, and the condition for being a commercial entity is "is_company or parent_id IS NULL". + # Contacts inside a company automatically have a copy of the company's commercial fields + # (see _commercial_fields()), so they are automatically consistent. + cr.execute(""" + DROP INDEX IF EXISTS res_partner_vat_uniq_for_companies; + DROP INDEX IF EXISTS res_partner_nrc_uniq_for_companies; + CREATE UNIQUE INDEX res_partner_vat_uniq_for_companies ON res_partner (vat) WHERE is_company OR parent_id IS NULL; + CREATE UNIQUE INDEX res_partner_nrc_uniq_for_companies ON res_partner (nrc) WHERE is_company OR parent_id IS NULL; + """) + return result + + def _commercial_fields(self, cr, uid, context=None): + return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['nrc'] + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_vn/__init__.py b/addons/l10n_vn/__init__.py new file mode 100644 index 00000000000..4b18956216e --- /dev/null +++ b/addons/l10n_vn/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module is Copyright (c) 2009-2013 General Solutions (http://gscom.vn) All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_vn/__openerp__.py b/addons/l10n_vn/__openerp__.py new file mode 100644 index 00000000000..19b81654523 --- /dev/null +++ b/addons/l10n_vn/__openerp__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module is Copyright (c) 2009-2013 General Solutions (http://gscom.vn) All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + "name" : "Vietnam Chart of Accounts", + "version" : "1.0", + "author" : "General Solutions", + 'website': 'http://gscom.vn', + "category" : "Localization/Account Charts", + "description": """ +This is the module to manage the accounting chart for Vietnam in OpenERP. +======================================================================== + +This module applies to companies based in Vietnamese Accounting Standard (VAS). + +**Credits:** General Solutions. +""", + "depends" : ["account","base_vat","base_iban"], + "data" : ["account_tax_code.xml","account_chart.xml","account_tax.xml","l10n_vn_wizard.xml"], + "demo" : [], + 'auto_install': False, + "installable": True, +} + diff --git a/addons/l10n_vn/account_chart.xml b/addons/l10n_vn/account_chart.xml new file mode 100755 index 00000000000..c7d3f6a9ee3 --- /dev/null +++ b/addons/l10n_vn/account_chart.xml @@ -0,0 +1,2022 @@ + + + + + + + + 1. TÀI SẢN NGẮN HẠN + current_asset + balance + asset + + + + 1. TÀI SẢN NGẮN HẠN - REC + current_asset + unreconciled + asset + + + + 2. TÀI SẢN DÀI HẠN + long_term_asset + balance + asset + + + + 3. NỢ PHẢI TRẢ + liability + unreconciled + liability + + + + 4. VỐN CHỦ SỞ HỮU + equity + balance + asset + + + + 5. DOANH THU + income + none + income + + + + 6. CHI PHÍ SẢN XUẤT, KINH DOANH + expense + none + expense + + + + 7. THU NHẬP KHÁC + other_income + none + income + + + + 8. CHI PHÍ KHÁC + other_expense + none + expense + + + + 9. XÁC ĐỊNH KẾT QUẢ KINH DOANH + evaluation + none + + + + X. TÀI KHOẢN NGOÀI BẢNG + other + none + + + + CHỈ XEM + view + none + + + + + + + + 0 + Hệ thống tài khoản kế toán Việt Nam + view + + + + + + 1 + TÀI SẢN NGẮN HẠN + view + + + + + + 111 + + view + + + Tiền mặt + + + 1111 + + liquidity + + + Tiền Việt Nam + + + 1112 + + other + + + Ngoại tệ + + + 1113 + + other + + + Vàng bạc, kim khí quý, đá quý + + + + 112 + + view + + + Tiền gửi ngân hàng + + + 1121 + + liquidity + + + Tiền Việt Nam + + + 1122 + + other + + + Ngoại tệ + + + 1123 + + other + + + Vàng bạc, kim khí quý, đá quý + + + + 113 + + view + + + Tiền đang chuyển + + + 1131 + + other + + + Tiền Việt Nam + + + 1132 + + other + + + Ngoại tệ + + + + 121 + + view + + + Đầu tư tài chính ngắn hạn + + + 1211 + + other + + + Cổ phiếu + + + 1212 + + other + + + Trái phiếu, Tín phiếu, Kỳ phiếu + + + + 128 + + view + + + Đầu tư ngắn hạn khác + + + 1281 + + other + + + Tiền gửi có kỳ hạn + + + 1282 + + other + + + Đầu tư ngắn hạn khác + + + + 129 + + other + + + Dự phòng giảm giá đầu tư ngắn hạn + + + + 131 + + receivable + + + Phải thu của khách hàng + + + + 133 + + view + + + Thuế GTGT được khấu trừ + + + 1331 + + other + + + Thuế GTGT được khấu trừ của hàng hóa, dịch vụ + + + + 1332 + + other + + + Thuế GTGT được khấu trừ của TSCĐ + + + + 136 + + view + + + Phải thu nội bộ + + + 1361 + + other + + + Vốn kinh doanh ở đơn vị trực thuộc + + + 1368 + + other + + + Phải thu nội bộ khác + + + + 138 + + view + + + Phải thu khác + + + 1381 + + other + + + Tài sản thiếu chờ xử lý + + + 1385 + + other + + + Phải thu về cổ phần hóa + + + 1388 + + other + + + Phải thu khác + + + + 139 + + other + + + Dự phòng phải thu khó đòi + + + + 141 + + other + + + Tạm ứng + + + + 142 + + other + + + Chi phí trả trước ngắn hạn + + + + 144 + + other + + + Cầm cố, ký cược, ký quỹ ngắn hạn + + + + 151 + + other + + + Hàng hóa mua đang đi trên đường + + + + 152 + + other + + + Nguyên liệu, vật liệu + + + + 153 + + other + + + Công cụ, dụng cụ + + + + 154 + + other + + + Chi phí sản xuất kinh doanh dở dang + + + + 155 + + other + + + Thành phẩm + + + + 156 + + view + + + Hàng hóa + + + 1561 + + other + + + Giá mua hàng hóa + + + 1562 + + other + + + Chi phí thu mua hàng hóa + + + 1567 + + other + + + Hàng hóa bất động sản + + + + 157 + + other + + + Hàng gửi đi bán + + + + 158 + + other + + + Hàng hóa kho bảo thuế + + + + 159 + + other + + + Dự phòng giảm giá hàng tồn kho + + + + 161 + + view + + + Chi sự nghiệp + + + 1611 + + other + + + Chi sự nghiệp năm trước + + + 1612 + + other + + + Chi sự nghiệp năm nay + + + + + 2 + TÀI SẢN DÀI HẠN + view + + + + + + 211 + + view + + + Tài sản cố định hữu hình + + + 2111 + + other + + + Nhà cửa, vật kiến trúc + + + 2112 + + other + + + Máy móc, thiết bị + + + 2113 + + other + + + Phương tiện vận tải truyền dẫn + + + 2114 + + other + + + Thiết bị, dụng cụ quản lý + + + 2115 + + other + + + Cây lâu năm, súc vật làm việc và cho sản phẩm + + + + 2118 + + other + + + Tài sản cố định khác + + + + 212 + + other + + + Tài sản cố định thuê tài chính + + + + 213 + + view + + + Tài sản cố định vô hình + + + 2131 + + other + + + Quyền sử dụng đất + + + 2132 + + other + + + Quyền phát hành + + + 2133 + + other + + + Bản quyền, bằng sáng chế + + + 2134 + + other + + + Nhãn hiệu hàng hóa + + + 2135 + + other + + + Phần mềm máy tính + + + 2136 + + other + + + Giấy phép và giấy phép nhượng quyền + + + 2138 + + other + + + Tài sản cố định vô hình khác + + + + 214 + + view + + + Hao mòn TSCĐ + + + 2141 + + other + + + Hao mòn TSCĐ cố định hữu hình + + + 2142 + + other + + + Hao mòn TSCĐ thuê tài chính + + + 2143 + + other + + + Hao mòn TSCĐ vô hình + + + 2147 + + other + + + Hao mòn bất động sản đầu tư + + + + 217 + + other + + + Bất động sản đầu tư + + + + 221 + + other + + + Đầu tư vào công ty con + + + + 222 + + other + + + Vốn góp liên doanh + + + + 223 + + other + + + Đầu tư vào công ty liên kết + + + + 228 + + view + + + Đầu tư dài hạn khác + + + 2281 + + other + + + Cổ phiếu + + + 2282 + + other + + + Trái phiếu + + + 2288 + + other + + + Đầu tư dài hạn khác + + + + 229 + + other + + + Dự phòng giảm giá đầu tư dài hạn + + + + 241 + + view + + + Xây dựng cơ bản dở dang + + + 2411 + + other + + + Mua sắm TSCĐ + + + 2412 + + other + + + Xây dựng cơ bản + + + 2413 + + other + + + Sửa chữa lớn TSCĐ + + + + 242 + + other + + + Chi phí trả trước dài hạn + + + + 243 + + other + + + Tài sản thuế thu nhập hoãn lại + + + + 244 + + other + + + Ký quỹ, ký cược dài hạn + + + + + 3 + NỢ PHẢI TRẢ + view + + + + + + 311 + + other + + + Vay ngắn hạn + + + + 315 + + other + + + Nợ dài hạn đến hạn trả + + + + 331 + + payable + + + Phải trả người bán + + + + 333 + + view + + + Thuế và các khoản phải nộp Nhà nước + + + 3331 + + view + + + Thuế GTGT phải nộp + + + 33311 + + other + + + Thuế GTGT đầu ra + + + 33312 + + other + + + Thuế GTGT hàng nhập khẩu + + + 3332 + + other + + + Thuế tiêu thụ đặc biệt + + + 3333 + + other + + + Thuế xuất, nhập khẩu + + + 3334 + + other + + + Thuế thu nhập doanh nghiệp + + + 3335 + + other + + + Thuế thu nhập cá nhân + + + 3336 + + other + + + Thuế tài nguyên + + + 3337 + + other + + + Thuế nhà đất, tiền thuê đất + + + 3338 + + other + + + Các loại thuế khác + + + 3339 + + other + + + Phí, lệ phí và các khoản phải nộp khác + + + + 334 + + view + + + Phải trả người lao động + + + 3341 + + other + + + Phải trả công nhân viên + + + 3342 + + other + + + Phải trả người lao động khác + + + + 335 + + other + + + Chi phí phải trả + + + + 336 + + other + + + Phải trả nội bộ + + + + 337 + + other + + + Thanh toán theo tiến độ kế hoạch hợp đồng xây dựng + + + + + 338 + + view + + + Phải trả, phải nộp khác + + + 3381 + + other + + + Tài sản thừa chờ giải quyết + + + 3382 + + other + + + Kinh phí công đoàn + + + 3383 + + other + + + Bảo hiểm xã hội + + + 3384 + + other + + + Bảo hiểm y tế + + + 3385 + + other + + + Phải trả về cổ phần hóa + + + 3386 + + other + + + Nhận ký quỹ, ký cược ngắn hạn + + + 3387 + + other + + + Doanh thu chưa thực hiện + + + 3388 + + other + + + Phải trả, phải nộp khác + + + + 341 + + other + + + Vay dài hạn + + + + 342 + + other + + + Nợ dài hạn + + + + 343 + + view + + + Trái phiếu phát hành + + + 3431 + + other + + + Mệnh giá trái phiếu + + + 3432 + + other + + + Chiết khấu trái phiếu + + + 3434 + + other + + + Phụ trội trái phiếu + + + + 344 + + other + + + Nhận ký quỹ, ký cược dài hạn + + + + 347 + + other + + + Thuế thu nhập hoãn lại phải trả + + + + 351 + + other + + + Quỹ dự phòng trợ cấp mất việc làm + + + + 352 + + other + + + Dự phòng phải trả + + + + + 4 + VỐN CHỦ SỞ HỮU + view + + + + + + 411 + + view + + + Nguồn vốn kinh doanh + + + 4111 + + other + + + Vốn đầu tư chủ sỡ hữu + + + 4112 + + other + + + Thặng dư vốn cổ phần + + + 4118 + + other + + + Vốn khác + + + + 412 + + other + + + Chênh lệch đánh giá lại tài sản + + + + 413 + + view + + + Chênh lệnh tỉ giá hối đoái + + + 4131 + + other + + + Chênh lệnh tỉ giá hối đoái đánh giá lại cuối năm + tài chính + + + 4132 + + other + + + Chênh lệnh tỉ giá hối đoái trong giai đoạn đầu tư + XDCB + + + + 414 + + other + + + Quỹ đầu tư phát triển + + + + 415 + + other + + + Quỹ dự phòng tài chính + + + + 418 + + other + + + Các quỹ khác thuộc vốn chủ sở hữu + + + + 419 + + other + + + Cổ phiếu quỹ + + + + 421 + + view + + + Lợi nhuận chưa phân phối + + + 4211 + + other + + + Lợi nhuận chưa phân phối năm trước + + + 4212 + + other + + + Lợi nhuận chưa phân phối năm nay + + + + 431 + + view + + + Quỹ khen thưởng phúc lợi + + + 4311 + + other + + + Quỹ khen thưởng + + + 4312 + + other + + + Quỹ phúc lợi + + + 4313 + + other + + + Quỹ phúc lợi đã hình thành TSCĐ + + + + 441 + + other + + + Ngồn vố đầu tư xây dựng cơ bản + + + + 461 + + view + + + Nguồn kinh phí sự nghiệp + + + 4611 + + other + + + Nguồn kinh phí sự nghiệp năm trước + + + 4612 + + other + + + Nguồn kinh phí sự nghiệp năm nay + + + + 466 + + other + + + Nguồn kinh phí đã hình thành TSCĐ + + + + + 5 + DOANH THU + view + + + + + + 511 + + view + + + Doanh thu bán hàng và cung cấp dịch vụ + + + 5111 + + other + + + Doanh thu bán hàng hóa + + + 5112 + + other + + + Doanh thu bán các thành phẩm + + + 5113 + + other + + + Doanh thu cung cấp dịch vụ + + + 5114 + + other + + + Doanh thu trợ cấp, trợ giá + + + 5117 + + other + + + Doanh thu kinh doanh bất động sản đầu tư + + + + 512 + + view + + + Doanh thu bán hàng nội bộ + + + 5121 + + other + + + Doanh thu bán hàng hóa + + + 5122 + + other + + + Doanh thu bán các thành phẩm + + + 5123 + + other + + + Doanh thu cung cấp dịch vụ + + + + 515 + + other + + + Doanh thu hoạt động tài chính khác + + + + 521 + + other + + + Chiết khấu thương mại + + + + 531 + + other + + + Hàng bán bị trả lại + + + + 532 + + other + + + Giảm giá hàng bán + + + + + 6 + CHI PHÍ SẢN XUẤT, KINH DOANH + view + + + + + + 611 + + view + + + Mua hàng + + + 6111 + + other + + + Mua nguyên liệu, vật liệu + + + 6112 + + other + + + Mua hàng hóa + + + + 621 + + other + + + Chi phí nguyên liệu, vật liệu trực tiếp + + + + 622 + + other + + + Chi phí nhân công trực tiếp + + + + 623 + + view + + + Chi phí sử dụng máy thi công + + + 6231 + + other + + + Chi phí nhân công + + + 6232 + + other + + + Chi phí vật liệu + + + 6233 + + other + + + Chi phí dụng cụ sản xuất + + + 6234 + + other + + + Chi phí khấu hao máy thi công + + + 6237 + + other + + + Chi phí dịch vụ mua ngoài + + + 6238 + + other + + + Chi phí bằng tiền khác + + + + 627 + + view + + + Chi phí sản xuất chung + + + 6271 + + other + + + Chi phí nhân viên phân xưởng + + + 6272 + + other + + + Chi phí vật liệu + + + 6273 + + other + + + Chi phí dụng cụ sản xuất + + + 6274 + + other + + + Chi phí khấu hao TSCĐ + + + 6277 + + other + + + Chi phí dịch vụ mua ngoài + + + 6278 + + other + + + Chi phí bằng tiền khác + + + + 631 + + other + + + Giá thành sản xuất + + + + 632 + + other + + + Giá vốn hàng bán + + + + 635 + + other + + + Chi phí tài chính + + + + 641 + + view + + + Chi phí bán hàng + + + 6411 + + other + + + Chi phí nhân viên + + + 6412 + + other + + + Chi phí vật liệu, bao bì + + + 6413 + + other + + + Chi phí dụng cụ, đồ dùng + + + 6414 + + other + + + Chi phí khấu hao TSCĐ + + + 6415 + + other + + + Chi phí bảo hành + + + 6417 + + other + + + Chi phí dịch vụ mua ngoài + + + 6418 + + other + + + Chi phí bằng tiền khác + + + + 642 + + view + + + Chi phí quản lý doanh nghiệp + + + 6421 + + other + + + Chi phí nhân viên quản lý + + + 6422 + + other + + + Chi phí vật liệu quản lý + + + 6423 + + other + + + Chi phí đồ dùng văn phòng + + + 6424 + + other + + + Chi phí khấu hao tài sản cố định + + + 6425 + + other + + + Thuế, phí và lệ phí + + + 6426 + + other + + + Chi phí dự phòng + + + 6427 + + other + + + Chi phí dịch vụ mua ngoài + + + 6428 + + other + + + Chi phí bằng tiền khác + + + + + 7 + THU NHẬP KHÁC + view + + + + + + 711 + + other + + + Thu nhập khác + + + + + 8 + CHI PHÍ KHÁC + view + + + + + + 811 + + other + + + Chi phí khác + + + + 821 + + view + + + Chi phí thuế thu nhập doanh nghiệp + + + 8211 + + other + + + Chi phí thuế TNDN hiện hành + + + 8212 + + other + + + Chi phí thuế TNDN hoãn lại + + + + + 9 + XÁC ĐỊNH KẾT QUẢ KINH DOANH + view + + + + + + 911 + + other + + + Xác định kết quả kinh doanh + + + + + X10 + TÀI KHOẢN NGOÀI BẢNG + view + + + + + + 001 + + other + + + Tài sản thuê ngoài + + + + 002 + + other + + + Vật tư, hàng hóa nhận giữ hộ, nhận gia công + + + + 003 + + other + + + Hàng hóa nhận bán hộ, nhận ký gửi, ký cược + + + + 004 + + other + + + Nợ khó đòi đã xử lý + + + + 007 + + other + + + Ngoại tệ các loại + + + + 008 + + other + + + Dự toán chi sự nghiệp, dự án + + + + OBA + + other + + + Opening Balance Account + + + + + VN - Chart of Accounts + 0 + + + + + + + + + + + + diff --git a/addons/l10n_vn/account_tax.xml b/addons/l10n_vn/account_tax.xml new file mode 100755 index 00000000000..85f068023c2 --- /dev/null +++ b/addons/l10n_vn/account_tax.xml @@ -0,0 +1,90 @@ + + + + + + + + + + Thuế GTGT được khấu trừ 10% + + percent + + + purchase + + + + + + + + Thuế GTGT được khấu trừ 5% + + percent + + + purchase + + + + + + + + Thuế GTGT được khấu trừ 0% + + percent + + + purchase + + + + + + + + + + Thuế GTGT phải nộp 10% + + percent + + + sale + + + + + + + + Thuế GTGT phải nộp 5% + + percent + + + sale + + + + + + + + Thuế GTGT phải nộp 0% + + percent + + + sale + + + + + + + + diff --git a/addons/l10n_vn/account_tax_code.xml b/addons/l10n_vn/account_tax_code.xml new file mode 100755 index 00000000000..4f3aee1bfc6 --- /dev/null +++ b/addons/l10n_vn/account_tax_code.xml @@ -0,0 +1,122 @@ + + + + + + + + Tờ khai thuế GTGT + MAIN + + + + HHDV mua vào + + IN + + + + HHDV bán ra + + OUT + + + + + Giá trị HHDV mua vào + + IN_BASE + + + + Giá trị HHDV mua vào chịu thuế 0% + + IN_BASE_00 + + + + Giá trị HHDV mua vào chịu thuế 5% + + IN_BASE_05 + + + + Giá trị HHDV mua vào chịu thuế 10% + + IN_BASE_10 + + + + Giá trị HHDV bán ra + + OUT_BASE + + + + Giá trị HHDV bán ra chịu thuế 0% + + OUT_BASE_00 + + + + Giá trị HHDV bán ra chịu thuế 5% + + OUT_BASE_05 + + + + Giá trị HHDV bán ra chịu thuế 10% + + OUT_BASE_10 + + + + + Thuế GTGT HHDV mua vào + + IN_BALANCE + + + + Thuế GTGT HHDV mua vào chịu thuế 0% + + IN_BALANCE_00 + + + + Thuế GTGT HHDV mua vào chịu thuế 5% + + IN_BALANCE_05 + + + + Thuế GTGT HHDV mua vào chịu thuế 10% + + IN_BALANCE_10 + + + + Thuế GTGT HHDV bán ra + + OUT_BALANCE + + + + Thuế GTGT HHDV bán ra chịu thuế 0% + + OUT_BALANCE_00 + + + + Thuế GTGT HHDV bán ra chịu thuế 5% + + OUT_BALANCE_05 + + + + Thuế GTGT HHDV bán ra chịu thuế 10% + + OUT_BALANCE_10 + + + diff --git a/addons/l10n_vn/l10n_vn_wizard.xml b/addons/l10n_vn/l10n_vn_wizard.xml new file mode 100755 index 00000000000..368a3cbd8b3 --- /dev/null +++ b/addons/l10n_vn/l10n_vn_wizard.xml @@ -0,0 +1,10 @@ + + + + + + open + + + + \ No newline at end of file diff --git a/addons/l10n_vn/static/src/img/icon.png b/addons/l10n_vn/static/src/img/icon.png new file mode 100755 index 00000000000..241a2d3fa74 Binary files /dev/null and b/addons/l10n_vn/static/src/img/icon.png differ diff --git a/addons/lunch/i18n/ko.po b/addons/lunch/i18n/ko.po new file mode 100644 index 00000000000..e76966ad73b --- /dev/null +++ b/addons/lunch/i18n/ko.po @@ -0,0 +1,896 @@ +# 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-05-11 19:34+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-05-12 05:28+0000\n" +"X-Generator: Launchpad (build 16598)\n" + +#. module: lunch +#: field:lunch.product,category_id:0 +#: field:lunch.product.category,name:0 +msgid "Category" +msgstr "범주" + +#. module: lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_order_by_supplier_form +msgid "Today's Orders by Supplier" +msgstr "" + +#. module: lunch +#: view:lunch.order:0 +msgid "My Orders" +msgstr "" + +#. module: lunch +#: selection:lunch.order,state:0 +msgid "Partially Confirmed" +msgstr "" + +#. module: lunch +#: view:lunch.cashmove:0 +#: view:lunch.order.line:0 +msgid "Group By..." +msgstr "" + +#. module: lunch +#: field:lunch.alert,sunday:0 +msgid "Sunday" +msgstr "" + +#. module: lunch +#: field:lunch.order.line,supplier:0 +#: field:lunch.product,supplier:0 +msgid "Supplier" +msgstr "공급업체" + +#. module: lunch +#: view:lunch.order.line:0 +msgid "Today" +msgstr "오늘" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "March" +msgstr "3월" + +#. module: lunch +#: view:lunch.cashmove:0 +msgid "By Employee" +msgstr "직원에 의해" + +#. module: lunch +#: field:lunch.alert,friday:0 +msgid "Friday" +msgstr "" + +#. module: lunch +#: view:lunch.validation:0 +msgid "validate order lines" +msgstr "" + +#. module: lunch +#: view:lunch.order.line:0 +msgid "Order lines Tree" +msgstr "" + +#. module: lunch +#: field:lunch.alert,specific_day:0 +#: field:report.lunch.order.line,day:0 +msgid "Day" +msgstr "" + +#. module: lunch +#: view:lunch.order.line:0 +#: selection:lunch.order.line,state:0 +msgid "Received" +msgstr "받음" + +#. module: lunch +#: view:lunch.order.line:0 +msgid "By Supplier" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_order_tree +msgid "" +"

\n" +" Click to create a lunch order. \n" +"

\n" +"

\n" +" A lunch order is defined by its user, date and order lines.\n" +" Each order line corresponds to a product, an additional note " +"and a price.\n" +" Before selecting your order lines, don't forget to read the " +"warnings displayed in the reddish area.\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: view:lunch.order.line:0 +msgid "Not Received" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_order_by_supplier_form +#: model:ir.ui.menu,name:lunch.menu_lunch_control_suppliers +msgid "Orders by Supplier" +msgstr "" + +#. module: lunch +#: view:lunch.validation:0 +msgid "Receive Meals" +msgstr "" + +#. module: lunch +#: view:lunch.cashmove:0 +msgid "cashmove form" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_cashmove_form +msgid "" +"

\n" +" Here you can see your cash moves.
A cash moves can be " +"either an expense or a payment.\n" +" An expense is automatically created when an order is " +"received while a payment is a reimbursement to the company encoded by the " +"manager.\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: field:lunch.cashmove,amount:0 +msgid "Amount" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_products +#: model:ir.ui.menu,name:lunch.menu_lunch_products +#: field:lunch.order,order_line_ids:0 +msgid "Products" +msgstr "상품" + +#. module: lunch +#: view:lunch.order.line:0 +msgid "By Date" +msgstr "" + +#. module: lunch +#: selection:lunch.order,state:0 +#: view:lunch.order.line:0 +#: selection:lunch.order.line,state:0 +msgid "Cancelled" +msgstr "" + +#. module: lunch +#: view:lunch.cashmove:0 +msgid "lunch employee payment" +msgstr "" + +#. module: lunch +#: view:lunch.alert:0 +msgid "alert tree" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_report_lunch_order_line +msgid "Lunch Orders Statistics" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_alert +msgid "Lunch Alert" +msgstr "" + +#. module: lunch +#: code:addons/lunch/lunch.py:183 +#, python-format +msgid "Select a product and put your order comments on the note." +msgstr "" + +#. module: lunch +#: selection:lunch.alert,alter_type:0 +msgid "Every Week" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_cashmove +msgid "Register Cash Moves" +msgstr "" + +#. module: lunch +#: selection:lunch.order,state:0 +msgid "Confirmed" +msgstr "" + +#. module: lunch +#: view:lunch.order:0 +msgid "lunch orders" +msgstr "" + +#. module: lunch +#: view:lunch.order.line:0 +msgid "Confirm" +msgstr "확정" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_cashmove_form +msgid "Your Account" +msgstr "" + +#. module: lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_cashmove_form +msgid "Your Lunch Account" +msgstr "점심 계정" + +#. module: lunch +#: field:lunch.alert,active_from:0 +msgid "Between" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_order_order +msgid "Wizard to order a meal" +msgstr "" + +#. module: lunch +#: selection:lunch.order,state:0 +#: selection:lunch.order.line,state:0 +msgid "New" +msgstr "" + +#. module: lunch +#: code:addons/lunch/lunch.py:180 +#, python-format +msgid "This is the first time you order a meal" +msgstr "이것은 첫번쨰 고기 주문입니다." + +#. module: lunch +#: field:report.lunch.order.line,price_total:0 +msgid "Total Price" +msgstr "총액" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_validation +msgid "lunch validation for order" +msgstr "" + +#. module: lunch +#: report:lunch.order.line:0 +msgid "Name/Date" +msgstr "이름/날짜" + +#. module: lunch +#: report:lunch.order.line:0 +msgid "Total :" +msgstr "합계 :" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "July" +msgstr "" + +#. module: lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_config +msgid "Configuration" +msgstr "" + +#. module: lunch +#: field:lunch.order,state:0 +#: field:lunch.order.line,state:0 +msgid "Status" +msgstr "상태" + +#. module: lunch +#: view:lunch.order.order:0 +msgid "" +"Order a meal doesn't mean that we have to pay it.\n" +" A meal should be paid when it is received." +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_control_accounts +#: model:ir.ui.menu,name:lunch.menu_lunch_control_accounts +msgid "Control Accounts" +msgstr "" + +#. module: lunch +#: selection:lunch.alert,alter_type:0 +msgid "Every Day" +msgstr "매일" + +#. module: lunch +#: field:lunch.order.line,cashmove:0 +msgid "Cash Move" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.order_order_lines +msgid "Order meals" +msgstr "육류 주문" + +#. module: lunch +#: view:lunch.alert:0 +msgid "Schedule Hour" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "September" +msgstr "9월" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_control_suppliers +msgid "" +"

\n" +" Here you can see every orders grouped by suppliers and by " +"date.\n" +"

\n" +"

\n" +" - Click on the to announce " +"that the order is ordered
\n" +" - Click on the to announce that " +"the order is received
\n" +" - Click on the red X to announce " +"that the order isn't available\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: field:lunch.alert,tuesday:0 +msgid "Tuesday" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_order_tree +msgid "Your Orders" +msgstr "" + +#. module: lunch +#: field:report.lunch.order.line,month:0 +msgid "Month" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_products +msgid "" +"

\n" +" Click to create a product for lunch. \n" +"

\n" +"

\n" +" A product is defined by its name, category, price and " +"supplier.\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: view:lunch.alert:0 +#: field:lunch.alert,message:0 +msgid "Message" +msgstr "" + +#. module: lunch +#: view:lunch.order.order:0 +msgid "Order Meals" +msgstr "" + +#. module: lunch +#: view:lunch.cancel:0 +#: view:lunch.order.order:0 +#: view:lunch.validation:0 +msgid "or" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_product_categories +msgid "" +"

\n" +" Click to create a lunch category. \n" +"

\n" +"

\n" +" Here you can find every lunch categories for products.\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: view:lunch.order.order:0 +msgid "Order meal" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_product_categories +#: model:ir.ui.menu,name:lunch.menu_lunch_product_categories +msgid "Product Categories" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_control_suppliers +msgid "Control Suppliers" +msgstr "" + +#. module: lunch +#: view:lunch.alert:0 +msgid "Schedule Date" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_alert +#: model:ir.ui.menu,name:lunch.menu_lunch_alert +#: field:lunch.order,alerts:0 +msgid "Alerts" +msgstr "" + +#. module: lunch +#: field:lunch.order.line,note:0 +#: field:report.lunch.order.line,note:0 +msgid "Note" +msgstr "" + +#. module: lunch +#: code:addons/lunch/lunch.py:250 +#, python-format +msgid "Add" +msgstr "" + +#. module: lunch +#: view:lunch.product:0 +#: view:lunch.product.category:0 +msgid "Products Form" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.cancel_order_lines +msgid "Cancel meals" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_cashmove +#: view:lunch.cashmove:0 +msgid "lunch cashmove" +msgstr "" + +#. module: lunch +#: view:lunch.cancel:0 +msgid "Are you sure you want to cancel these meals?" +msgstr "" + +#. module: lunch +#: view:lunch.cashmove:0 +msgid "My Account" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "August" +msgstr "" + +#. module: lunch +#: field:lunch.alert,monday:0 +msgid "Monday" +msgstr "" + +#. module: lunch +#: field:lunch.order.line,name:0 +msgid "unknown" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.validate_order_lines +msgid "Receive meals" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "June" +msgstr "" + +#. module: lunch +#: field:lunch.cashmove,user_id:0 +#: field:lunch.order,user_id:0 +#: field:report.lunch.order.line,user_id:0 +msgid "User Name" +msgstr "" + +#. module: lunch +#: model:ir.module.category,name:lunch.module_lunch_category +#: model:ir.ui.menu,name:lunch.menu_lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_title +msgid "Lunch" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_order_line +msgid "lunch order line" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_product +msgid "lunch product" +msgstr "" + +#. module: lunch +#: field:lunch.order.line,user_id:0 +#: model:res.groups,name:lunch.group_lunch_user +msgid "User" +msgstr "" + +#. module: lunch +#: field:lunch.cashmove,date:0 +#: field:lunch.order,date:0 +#: field:lunch.order.line,date:0 +msgid "Date" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "November" +msgstr "" + +#. module: lunch +#: view:lunch.order:0 +msgid "Orders Tree" +msgstr "" + +#. module: lunch +#: view:lunch.order:0 +msgid "Orders Form" +msgstr "" + +#. module: lunch +#: view:lunch.alert:0 +#: view:lunch.order.line:0 +msgid "Search" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "October" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_order_by_supplier_form +msgid "" +"

\n" +" Here you can see today's orders grouped by suppliers.\n" +"

\n" +"

\n" +" - Click on the to announce " +"that the order is ordered
\n" +" - Click on the to announce that " +"the order is received
\n" +" - Click on the to announce that " +"the order isn't available\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "January" +msgstr "" + +#. module: lunch +#: selection:lunch.alert,alter_type:0 +msgid "Specific Day" +msgstr "" + +#. module: lunch +#: field:lunch.alert,wednesday:0 +msgid "Wednesday" +msgstr "" + +#. module: lunch +#: view:lunch.product.category:0 +msgid "Product Category: " +msgstr "" + +#. module: lunch +#: field:lunch.alert,active_to:0 +msgid "And" +msgstr "" + +#. module: lunch +#: selection:lunch.order.line,state:0 +msgid "Ordered" +msgstr "" + +#. module: lunch +#: field:report.lunch.order.line,date:0 +msgid "Date Order" +msgstr "" + +#. module: lunch +#: view:lunch.cancel:0 +msgid "Cancel Orders" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_alert +msgid "" +"

\n" +" Click to create a lunch alert. \n" +"

\n" +"

\n" +" Alerts are used to warn employee from possible issues " +"concerning the lunch orders.\n" +" To create a lunch alert you have to define its recurrency, " +"the time interval during which the alert should be executed and the message " +"to display.\n" +"

\n" +"

\n" +" Example:
\n" +" - Recurency: Everyday
\n" +" - Time interval: from 00h00 am to 11h59 pm
\n" +" - Message: \"You must order before 10h30 am\"\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: view:lunch.cancel:0 +msgid "A cancelled meal should not be paid by employees." +msgstr "" + +#. module: lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_cash +msgid "Administrate Cash Moves" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_cancel +msgid "cancel lunch order" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "December" +msgstr "" + +#. module: lunch +#: view:lunch.cancel:0 +#: view:lunch.order.line:0 +#: view:lunch.order.order:0 +#: view:lunch.validation:0 +msgid "Cancel" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_cashmove +msgid "" +"

\n" +" Click to create a payment. \n" +"

\n" +"

\n" +" Here you can see the employees' payment. A payment is a cash " +"move from the employee to the company.\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: code:addons/lunch/lunch.py:186 +#, python-format +msgid "Your favorite meals will be created based on your last orders." +msgstr "" + +#. module: lunch +#: model:ir.module.category,description:lunch.module_lunch_category +msgid "" +"Helps you handle your lunch needs, if you are a manager you will be able to " +"create new products, cashmoves and to confirm or cancel orders." +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,help:lunch.action_lunch_control_accounts +msgid "" +"

\n" +" Click to create a new payment. \n" +"

\n" +"

\n" +" A cashmove can either be an expense or a payment.
\n" +" An expense is automatically created at the order " +"receipt.
\n" +" A payment represents the employee reimbursement to the " +"company.\n" +"

\n" +" " +msgstr "" + +#. module: lunch +#: field:lunch.alert,alter_type:0 +msgid "Recurrency" +msgstr "" + +#. module: lunch +#: code:addons/lunch/lunch.py:189 +#, python-format +msgid "Don't forget the alerts displayed in the reddish area" +msgstr "" + +#. module: lunch +#: field:lunch.alert,thursday:0 +msgid "Thursday" +msgstr "" + +#. module: lunch +#: report:lunch.order.line:0 +msgid "Unit Price" +msgstr "" + +#. module: lunch +#: field:lunch.order.line,product_id:0 +#: field:lunch.product,name:0 +msgid "Product" +msgstr "" + +#. module: lunch +#: field:lunch.cashmove,description:0 +#: report:lunch.order.line:0 +#: field:lunch.product,description:0 +msgid "Description" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "May" +msgstr "" + +#. module: lunch +#: field:lunch.order.line,price:0 +#: field:lunch.product,price:0 +msgid "Price" +msgstr "" + +#. module: lunch +#: field:lunch.cashmove,state:0 +msgid "Is an order or a Payment" +msgstr "" + +#. module: lunch +#: model:ir.actions.act_window,name:lunch.action_lunch_order_form +#: model:ir.ui.menu,name:lunch.menu_lunch_order_form +msgid "New Order" +msgstr "" + +#. module: lunch +#: view:lunch.cashmove:0 +msgid "cashmove tree" +msgstr "" + +#. module: lunch +#: view:lunch.cancel:0 +msgid "Cancel a meal means that we didn't receive it from the supplier." +msgstr "" + +#. module: lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_cashmove +msgid "Employee Payments" +msgstr "" + +#. module: lunch +#: view:lunch.cashmove:0 +#: selection:lunch.cashmove,state:0 +msgid "Payment" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "February" +msgstr "" + +#. module: lunch +#: field:report.lunch.order.line,year:0 +msgid "Year" +msgstr "" + +#. module: lunch +#: view:lunch.order:0 +msgid "List" +msgstr "" + +#. module: lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_admin +msgid "Administrate Orders" +msgstr "" + +#. module: lunch +#: selection:report.lunch.order.line,month:0 +msgid "April" +msgstr "" + +#. module: lunch +#: view:lunch.order:0 +msgid "Select your order" +msgstr "" + +#. module: lunch +#: field:lunch.cashmove,order_id:0 +#: selection:lunch.cashmove,state:0 +#: report:lunch.order.line:0 +#: view:lunch.order.line:0 +#: field:lunch.order.line,order_id:0 +msgid "Order" +msgstr "" + +#. module: lunch +#: model:ir.actions.report.xml,name:lunch.report_lunch_order +#: model:ir.model,name:lunch.model_lunch_order +#: report:lunch.order.line:0 +msgid "Lunch Order" +msgstr "" + +#. module: lunch +#: view:lunch.order.order:0 +msgid "Are you sure you want to order these meals?" +msgstr "" + +#. module: lunch +#: view:lunch.cancel:0 +msgid "cancel order lines" +msgstr "" + +#. module: lunch +#: model:ir.model,name:lunch.model_lunch_product_category +msgid "lunch product category" +msgstr "" + +#. module: lunch +#: field:lunch.alert,saturday:0 +msgid "Saturday" +msgstr "" + +#. module: lunch +#: model:res.groups,name:lunch.group_lunch_manager +msgid "Manager" +msgstr "" + +#. module: lunch +#: view:lunch.validation:0 +msgid "Did your received these meals?" +msgstr "" + +#. module: lunch +#: view:lunch.validation:0 +msgid "Once a meal is received a new cash move is created for the employee." +msgstr "" + +#. module: lunch +#: view:lunch.product:0 +msgid "Products Tree" +msgstr "" + +#. module: lunch +#: view:lunch.cashmove:0 +#: view:lunch.order:0 +#: field:lunch.order,total:0 +#: view:lunch.order.line:0 +msgid "Total" +msgstr "" + +#. module: lunch +#: model:ir.ui.menu,name:lunch.menu_lunch_order_tree +msgid "Previous Orders" +msgstr "" diff --git a/addons/lunch/report/report_lunch_order.py b/addons/lunch/report/report_lunch_order.py index 3a439a4a4dd..13c885e7896 100644 --- a/addons/lunch/report/report_lunch_order.py +++ b/addons/lunch/report/report_lunch_order.py @@ -60,6 +60,5 @@ class report_lunch_order(osv.osv): lo.date,lo.user_id,lo.note ) """) -report_lunch_order() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml index 3f517ee7858..4e935e4aa88 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -27,6 +27,25 @@ 1000
+ + Garbage Collect Mail Attachments + + + 1 + weeks + -1 + + mail.thread + _garbage_collect_attachments + () + + + + + mail.catchall.alias + catchall + + Discussions diff --git a/addons/mail/html/index.html b/addons/mail/html/index.html new file mode 100644 index 00000000000..b564cf3ab1e --- /dev/null +++ b/addons/mail/html/index.html @@ -0,0 +1,178 @@ +
+
+
+

Enterprise Social Network

+

A private social network for your company

+
+
+
+ + + + +
+
+
+

+Connect with experts, follow what interests you, share documents and promote +best practices. Get work done with effective collaboration across departments, +geographies, documents and business applications. All of this while decreasing +email overload. + +

+ +
+
+
+ +
+
+

Connect with experts

+

Get the right information, when you need it

+
+

+Next time you have a question for the marketing, sales, R&D or any other +department, don't send an email blast-post the question to OpenERP and get +answers from the right persons. +

+
+
+
+ +
+
+
+
+ +
+
+

Follow what interests you

+

Make the information flow across your company

+
+
+ +
+
+
+

+Want to get informed about new product features, hot deals, bottlenecks in projects or any other event? Just follow what interests you to get the information you need what you need; no more, no less. +

+
+
+
+ + +
+
+

Get Things Done

+

Your inbox is a todo list

+
+

+You can process (not only read) the inbox and easily mark messages for future actions. Start feeling the pleasure of having an empty inbox every day; no more overload of information. +

+
+
+
+ +
+
+
+
+ +
+
+

Promote best practices

+

Discussion groups at your fingertips

+
+
+ +
+
+
+

+Cut back on meetings and email chains by working together in groups of interests. Create a group to let people share files, discuss ideas, and vote to promote best practices. +

+
+
+
+ +
+
+

Improve Access to Information and Expertise

+

Easily find the information you need

+
+

+Break down information silos. Search across your existing systems to find the answers and expertise you need to complete projects quickly. +

+
+
+
+ +
+
+
+
+ +
+
+

Collaborate securely

+
+
+ +
+
+
+

+Set the right security policy; public, private or on invitation only -- according to the information sensitivity. +

+
+
+
+ + +
+
+

A Twitter-like Network For Your Company

+
+

+Make every employee feel more connected and engaged with twitter-like features +for your own company. Follow people, share best practices, 'like' top ideas, etc. +

+
+
+
+ +
+
+
+
+ + +
+
+
+

Trusted by millions worldwide

+
+
+
+ + Emails make me waste my time. But I need them. Reading my inbox + is the most unproductive task I do on a daily basis. I have to + spend one or two full hours a day to process my emails. All the + junk flows in the same inbox; spams, information that doesn't + matter, quoted answers of quoted answers, etc. At the end of + the hour, only 10 emails actually requested an answer from me. + Since I use OpenERP, I can do the same job in only 10 minutes! + + + +
Luc de Keyser
+
+
+
+
+
+
+
diff --git a/addons/mail/html/mail_illustration.png b/addons/mail/html/mail_illustration.png new file mode 100644 index 00000000000..4fff4837faa Binary files /dev/null and b/addons/mail/html/mail_illustration.png differ diff --git a/addons/mail/html/mail_sc_00.png b/addons/mail/html/mail_sc_00.png new file mode 100644 index 00000000000..3011ef129b5 Binary files /dev/null and b/addons/mail/html/mail_sc_00.png differ diff --git a/addons/mail/html/mail_sc_01.png b/addons/mail/html/mail_sc_01.png new file mode 100644 index 00000000000..1b1099f6536 Binary files /dev/null and b/addons/mail/html/mail_sc_01.png differ diff --git a/addons/mail/html/mail_sc_02.png b/addons/mail/html/mail_sc_02.png new file mode 100644 index 00000000000..4e59c9d1e0f Binary files /dev/null and b/addons/mail/html/mail_sc_02.png differ diff --git a/addons/mail/html/mail_sc_03.png b/addons/mail/html/mail_sc_03.png new file mode 100644 index 00000000000..dbb14b4da36 Binary files /dev/null and b/addons/mail/html/mail_sc_03.png differ diff --git a/addons/mail/html/mail_sc_04.png b/addons/mail/html/mail_sc_04.png new file mode 100644 index 00000000000..b8f47ba2935 Binary files /dev/null and b/addons/mail/html/mail_sc_04.png differ diff --git a/addons/mail/html/mail_sc_05.png b/addons/mail/html/mail_sc_05.png new file mode 100644 index 00000000000..251b4ebc676 Binary files /dev/null and b/addons/mail/html/mail_sc_05.png differ diff --git a/addons/mail/html/mail_sc_06.png b/addons/mail/html/mail_sc_06.png new file mode 100644 index 00000000000..251b4ebc676 Binary files /dev/null and b/addons/mail/html/mail_sc_06.png differ diff --git a/addons/mail/html/mail_sc_07.png b/addons/mail/html/mail_sc_07.png new file mode 100644 index 00000000000..9a33332817e Binary files /dev/null and b/addons/mail/html/mail_sc_07.png differ diff --git a/addons/mail/html/photo.png b/addons/mail/html/photo.png new file mode 100644 index 00000000000..e605e5c6f8e Binary files /dev/null and b/addons/mail/html/photo.png differ diff --git a/addons/mail/i18n/ko.po b/addons/mail/i18n/ko.po new file mode 100644 index 00000000000..6315792f4fc --- /dev/null +++ b/addons/mail/i18n/ko.po @@ -0,0 +1,1687 @@ +# 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:04+0000\n" +"PO-Revision-Date: 2013-05-12 07:37+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-05-13 05:17+0000\n" +"X-Generator: Launchpad (build 16614)\n" + +#. module: mail +#: view:mail.followers:0 +msgid "Followers Form" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_publisher_warranty_contract +msgid "publisher_warranty.contract" +msgstr "" + +#. module: mail +#: field:mail.compose.message,author_id:0 +#: field:mail.message,author_id:0 +msgid "Author" +msgstr "작성자" + +#. module: mail +#: view:mail.mail:0 +msgid "Message Details" +msgstr "" + +#. module: mail +#: help:mail.mail,email_to:0 +msgid "Message recipients" +msgstr "" + +#. module: mail +#: help:mail.message.subtype,default:0 +msgid "Activated by default when subscribing." +msgstr "" + +#. module: mail +#: view:mail.message:0 +msgid "Comments" +msgstr "" + +#. module: mail +#: view:mail.alias:0 +#: view:mail.mail:0 +msgid "Group By..." +msgstr "" + +#. module: mail +#: help:mail.compose.message,body:0 +#: help:mail.message,body:0 +msgid "Automatically sanitized HTML contents" +msgstr "" + +#. module: mail +#: help:mail.alias,alias_name:0 +msgid "" +"The name of the email alias, e.g. 'jobs' if you want to catch emails for " +"" +msgstr "" + +#. module: mail +#: model:ir.actions.act_window,name:mail.action_email_compose_message_wizard +#: view:mail.compose.message:0 +msgid "Compose Email" +msgstr "메일 작성" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:132 +#, python-format +msgid "Add them into recipients and followers" +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "Group Name" +msgstr "그룹명" + +#. module: mail +#: selection:mail.group,public:0 +msgid "Public" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Body" +msgstr "본문" + +#. module: mail +#: view:mail.message:0 +msgid "Show messages to read" +msgstr "" + +#. module: mail +#: help:mail.compose.message,email_from:0 +#: help:mail.message,email_from:0 +msgid "" +"Email address of the sender. This field is set when no matching partner is " +"found for incoming emails." +msgstr "보내는 사람의 이메일 주소. 이 필드는 수신 메일에서 일치하는 파트너를 찾을 수 없을 때 설정됩니다." + +#. module: mail +#: model:ir.model,name:mail.model_mail_compose_message +msgid "Email composition wizard" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:23 +#, python-format +msgid "Add others" +msgstr "" + +#. module: mail +#: field:mail.message.subtype,parent_id:0 +msgid "Parent" +msgstr "" + +#. module: mail +#: field:mail.group,message_unread:0 +#: field:mail.thread,message_unread:0 +#: field:res.partner,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:296 +#, python-format +msgid "show" +msgstr "" + +#. module: mail +#: help:mail.group,group_ids:0 +msgid "" +"Members of those groups will automatically added as followers. Note that " +"they will be able to manage their subscription manually if necessary." +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/js/mail.js:1019 +#, python-format +msgid "Do you really want to delete this message?" +msgstr "" + +#. module: mail +#: view:mail.message:0 +#: field:mail.notification,read:0 +msgid "Read" +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "Search Groups" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/js/mail_followers.js:159 +#, python-format +msgid "followers" +msgstr "" + +#. module: mail +#: code:addons/mail/mail_message.py:726 +#, python-format +msgid "Access Denied" +msgstr "" + +#. module: mail +#: help:mail.group,image_medium:0 +msgid "" +"Medium-sized photo of the group. It is automatically resized as a 128x128px " +"image, with aspect ratio preserved. Use this field in form views or some " +"kanban views." +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:212 +#, python-format +msgid "Uploading error" +msgstr "" + +#. module: mail +#: model:mail.group,name:mail.group_support +msgid "Support" +msgstr "" + +#. module: mail +#: code:addons/mail/mail_message.py:727 +#, python-format +msgid "" +"The requested operation cannot be completed due to security restrictions. " +"Please contact your system administrator.\n" +"\n" +"(Document type: %s, Operation: %s)" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +#: selection:mail.mail,state:0 +msgid "Received" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Thread" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:29 +#, python-format +msgid "Open the full mail composer" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:29 +#, python-format +msgid "ò" +msgstr "" + +#. module: mail +#: field:base.config.settings,alias_domain:0 +msgid "Alias Domain" +msgstr "" + +#. module: mail +#: field:mail.group,group_ids:0 +msgid "Auto Subscription" +msgstr "" + +#. module: mail +#: field:mail.mail,references:0 +msgid "References" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:206 +#, python-format +msgid "No messages." +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_group +msgid "Discussion group" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:98 +#: code:addons/mail/static/src/xml/mail.xml:110 +#, python-format +msgid "uploading" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:52 +#, python-format +msgid "more." +msgstr "" + +#. module: mail +#: help:mail.compose.message,type:0 +#: help:mail.message,type:0 +msgid "" +"Message type: email for email message, notification for system message, " +"comment for other messages such as user replies" +msgstr "" + +#. module: mail +#: help:mail.message.subtype,relation_field:0 +msgid "" +"Field used to link the related model to the subtype model when using " +"automatic subscription on a related document. The field is used to compute " +"getattr(related_document.relation_field)." +msgstr "" + +#. module: mail +#: selection:mail.mail,state:0 +msgid "Cancelled" +msgstr "" + +#. module: mail +#: field:mail.mail,reply_to:0 +msgid "Reply-To" +msgstr "" + +#. module: mail +#: code:addons/mail/wizard/invite.py:37 +#, python-format +msgid "
You have been invited to follow %s.
" +msgstr "" + +#. module: mail +#: help:mail.group,message_unread:0 +#: help:mail.thread,message_unread:0 +#: help:res.partner,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: mail +#: field:mail.group,image_medium:0 +msgid "Medium-sized photo" +msgstr "" + +#. module: mail +#: model:ir.actions.client,name:mail.action_mail_to_me_feeds +#: model:ir.ui.menu,name:mail.mail_tomefeeds +msgid "To: me" +msgstr "" + +#. module: mail +#: field:mail.message.subtype,name:0 +msgid "Message Type" +msgstr "" + +#. module: mail +#: field:mail.mail,auto_delete:0 +msgid "Auto Delete" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:12 +#: view:mail.group:0 +#, python-format +msgid "Unfollow" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:295 +#, python-format +msgid "show one more message" +msgstr "" + +#. module: mail +#: code:addons/mail/mail_mail.py:74 +#: code:addons/mail/res_users.py:69 +#, python-format +msgid "Invalid Action!" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:25 +#, python-format +msgid "User img" +msgstr "" + +#. module: mail +#: model:ir.actions.act_window,name:mail.action_view_mail_mail +#: model:ir.ui.menu,name:mail.menu_mail_mail +#: view:mail.mail:0 +#: view:mail.message:0 +msgid "Emails" +msgstr "" + +#. module: mail +#: field:mail.followers,partner_id:0 +msgid "Related Partner" +msgstr "" + +#. module: mail +#: help:mail.group,message_summary:0 +#: help:mail.thread,message_summary:0 +#: help:res.partner,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: mail +#: help:mail.alias,alias_model_id:0 +msgid "" +"The model (OpenERP Document Kind) to which this alias corresponds. Any " +"incoming email that does not reply to an existing record will cause the " +"creation of a new record of this model (e.g. a Project Task)" +msgstr "" + +#. module: mail +#: field:mail.message.subtype,relation_field:0 +msgid "Relation field" +msgstr "" + +#. module: mail +#: selection:mail.compose.message,type:0 +#: selection:mail.message,type:0 +msgid "System notification" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_res_partner +#: view:mail.mail:0 +msgid "Partner" +msgstr "" + +#. module: mail +#: model:ir.ui.menu,name:mail.mail_my_stuff +msgid "Organizer" +msgstr "" + +#. module: mail +#: field:mail.compose.message,subject:0 +#: field:mail.message,subject:0 +msgid "Subject" +msgstr "" + +#. module: mail +#: field:mail.wizard.invite,partner_ids:0 +msgid "Partners" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Retry" +msgstr "" + +#. module: mail +#: field:mail.compose.message,email_from:0 +#: field:mail.mail,email_from:0 +#: field:mail.message,email_from:0 +msgid "From" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +#: view:mail.message.subtype:0 +msgid "Email message" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_base_config_settings +msgid "base.config.settings" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:36 +#: view:mail.compose.message:0 +#, python-format +msgid "Send" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/js/mail_followers.js:155 +#, python-format +msgid "No followers" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Failed" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:22 +#: model:ir.actions.act_window,name:mail.action_view_followers +#: model:ir.ui.menu,name:mail.menu_email_followers +#: view:mail.followers:0 +#: field:mail.group,message_follower_ids:0 +#: field:mail.thread,message_follower_ids:0 +#: field:res.partner,message_follower_ids:0 +#, python-format +msgid "Followers" +msgstr "" + +#. module: mail +#: model:ir.actions.client,name:mail.action_mail_archives_feeds +#: model:ir.ui.menu,name:mail.mail_archivesfeeds +msgid "Archives" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:97 +#: code:addons/mail/static/src/xml/mail.xml:109 +#, python-format +msgid "Delete this attachment" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:245 +#: view:mail.mail:0 +#, python-format +msgid "Reply" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/js/mail_followers.js:157 +#, python-format +msgid "One follower" +msgstr "" + +#. module: mail +#: field:mail.compose.message,type:0 +#: field:mail.message,type:0 +msgid "Type" +msgstr "" + +#. module: mail +#: selection:mail.compose.message,type:0 +#: view:mail.mail:0 +#: selection:mail.message,type:0 +msgid "Email" +msgstr "" + +#. module: mail +#: field:ir.ui.menu,mail_group_id:0 +msgid "Mail Group" +msgstr "" + +#. module: mail +#: selection:res.partner,notification_email_send:0 +msgid "Comments and Emails" +msgstr "" + +#. module: mail +#: field:mail.alias,alias_defaults:0 +msgid "Default Values" +msgstr "" + +#. module: mail +#: code:addons/mail/res_users.py:89 +#, python-format +msgid "%s has joined the %s network." +msgstr "" + +#. module: mail +#: help:mail.group,image_small:0 +msgid "" +"Small-sized photo of the group. It is automatically resized as a 64x64px " +"image, with aspect ratio preserved. Use this field anywhere a small image is " +"required." +msgstr "" + +#. module: mail +#: view:mail.compose.message:0 +#: field:mail.message,partner_ids:0 +msgid "Recipients" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:142 +#, python-format +msgid "<<<" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:43 +#, python-format +msgid "Write to the followers of this document..." +msgstr "" + +#. module: mail +#: field:mail.group,group_public_id:0 +msgid "Authorized Group" +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "Join Group" +msgstr "" + +#. module: mail +#: help:mail.mail,email_from:0 +msgid "Message sender, taken from user preferences." +msgstr "" + +#. module: mail +#: code:addons/mail/wizard/invite.py:40 +#, python-format +msgid "
You have been invited to follow a new document.
" +msgstr "" + +#. module: mail +#: field:mail.compose.message,parent_id:0 +#: field:mail.message,parent_id:0 +msgid "Parent Message" +msgstr "" + +#. module: mail +#: field:mail.compose.message,res_id:0 +#: field:mail.followers,res_id:0 +#: field:mail.message,res_id:0 +#: field:mail.wizard.invite,res_id:0 +msgid "Related Document ID" +msgstr "" + +#. module: mail +#: model:ir.actions.client,help:mail.action_mail_to_me_feeds +msgid "" +"

\n" +" No private message.\n" +"

\n" +" This list contains messages sent to you.\n" +"

\n" +" " +msgstr "" + +#. module: mail +#: model:mail.group,name:mail.group_rd +msgid "R&D" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:61 +#, python-format +msgid "/web/binary/upload_attachment" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_thread +msgid "Email Thread" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Advanced" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:244 +#, python-format +msgid "Move to Inbox" +msgstr "" + +#. module: mail +#: code:addons/mail/wizard/mail_compose_message.py:165 +#, python-format +msgid "Re:" +msgstr "" + +#. module: mail +#: field:mail.compose.message,to_read:0 +#: field:mail.message,to_read:0 +msgid "To read" +msgstr "" + +#. module: mail +#: code:addons/mail/res_users.py:69 +#, python-format +msgid "" +"You may not create a user. To create new users, you should use the " +"\"Settings > Users\" menu." +msgstr "" + +#. module: mail +#: help:mail.followers,res_model:0 +#: help:mail.wizard.invite,res_model:0 +msgid "Model of the followed resource" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:320 +#, python-format +msgid "like" +msgstr "" + +#. module: mail +#: view:mail.compose.message:0 +#: view:mail.wizard.invite:0 +msgid "Cancel" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:47 +#, python-format +msgid "Share with my followers..." +msgstr "" + +#. module: mail +#: field:mail.notification,partner_id:0 +msgid "Contact" +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "" +"Only the invited followers can read the\n" +" discussions on this group." +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_ir_ui_menu +msgid "ir.ui.menu" +msgstr "" + +#. module: mail +#: view:mail.message:0 +msgid "Has attachments" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "on" +msgstr "" + +#. module: mail +#: code:addons/mail/mail_message.py:915 +#, python-format +msgid "" +"The following partners chosen as recipients for the email have no email " +"address linked :" +msgstr "" + +#. module: mail +#: help:mail.alias,alias_defaults:0 +msgid "" +"A Python dictionary that will be evaluated to provide default values when " +"creating new records for this alias." +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_message_subtype +msgid "Message subtypes" +msgstr "" + +#. module: mail +#: help:mail.compose.message,notified_partner_ids:0 +#: help:mail.message,notified_partner_ids:0 +msgid "" +"Partners that have a notification pushing this message in their mailboxes" +msgstr "" + +#. module: mail +#: selection:mail.compose.message,type:0 +#: view:mail.mail:0 +#: selection:mail.message,type:0 +msgid "Comment" +msgstr "" + +#. module: mail +#: model:ir.actions.client,help:mail.action_mail_inbox_feeds +msgid "" +"

\n" +" Good Job! Your inbox is empty.\n" +"

\n" +" Your inbox contains private messages or emails sent to " +"you\n" +" as well as information related to documents or people " +"you\n" +" follow.\n" +"

\n" +" " +msgstr "" + +#. module: mail +#: field:mail.mail,notification:0 +msgid "Is Notification" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:188 +#, python-format +msgid "Compose a new message" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Send Now" +msgstr "" + +#. module: mail +#: code:addons/mail/mail_mail.py:74 +#, python-format +msgid "" +"Unable to send email, please configure the sender's email address or alias." +msgstr "" + +#. module: mail +#: help:res.users,alias_id:0 +msgid "" +"Email address internally associated with this user. Incoming emails will " +"appear in the user's notifications." +msgstr "" + +#. module: mail +#: field:mail.group,image:0 +msgid "Photo" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:56 +#: code:addons/mail/static/src/xml/mail.xml:191 +#: view:mail.compose.message:0 +#: view:mail.wizard.invite:0 +#, python-format +msgid "or" +msgstr "" + +#. module: mail +#: help:mail.compose.message,vote_user_ids:0 +#: help:mail.message,vote_user_ids:0 +msgid "Users that voted for this message" +msgstr "" + +#. module: mail +#: help:mail.group,alias_id:0 +msgid "" +"The email address associated with this group. New emails received will " +"automatically create new topics." +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Month" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Email Search" +msgstr "" + +#. module: mail +#: field:mail.compose.message,child_ids:0 +#: field:mail.message,child_ids:0 +msgid "Child Messages" +msgstr "" + +#. module: mail +#: field:mail.alias,alias_user_id:0 +msgid "Owner" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_res_users +msgid "Users" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_message +#: field:mail.mail,mail_message_id:0 +#: view:mail.message:0 +#: field:mail.notification,message_id:0 +#: field:mail.wizard.invite,message:0 +msgid "Message" +msgstr "" + +#. module: mail +#: help:mail.followers,res_id:0 +#: help:mail.wizard.invite,res_id:0 +msgid "Id of the followed resource" +msgstr "" + +#. module: mail +#: field:mail.compose.message,body:0 +#: field:mail.message,body:0 +msgid "Contents" +msgstr "" + +#. module: mail +#: model:ir.actions.act_window,name:mail.action_view_mail_alias +#: model:ir.ui.menu,name:mail.mail_alias_menu +msgid "Aliases" +msgstr "" + +#. module: mail +#: help:mail.message.subtype,description:0 +msgid "" +"Description that will be added in the message posted for this subtype. If " +"void, the name will be added instead." +msgstr "" + +#. module: mail +#: field:mail.compose.message,vote_user_ids:0 +#: field:mail.message,vote_user_ids:0 +msgid "Votes" +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "Group" +msgstr "" + +#. module: mail +#: help:mail.compose.message,starred:0 +#: help:mail.message,starred:0 +msgid "Current user has a starred notification linked to this message" +msgstr "" + +#. module: mail +#: field:mail.group,public:0 +msgid "Privacy" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Notification" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/js/mail.js:650 +#, python-format +msgid "Please complete partner's informations" +msgstr "" + +#. module: mail +#: view:mail.wizard.invite:0 +msgid "Add Followers" +msgstr "" + +#. module: mail +#: view:mail.compose.message:0 +msgid "Followers of selected items and" +msgstr "" + +#. module: mail +#: field:mail.alias,alias_force_thread_id:0 +msgid "Record Thread ID" +msgstr "" + +#. module: mail +#: model:ir.ui.menu,name:mail.mail_group_root +msgid "My Groups" +msgstr "" + +#. module: mail +#: model:ir.actions.client,help:mail.action_mail_archives_feeds +msgid "" +"

\n" +" No message found and no message sent yet.\n" +"

\n" +" Click on the top-right icon to compose a message. This\n" +" message will be sent by email if it's an internal " +"contact.\n" +"

\n" +" " +msgstr "" + +#. module: mail +#: view:mail.mail:0 +#: field:mail.mail,state:0 +msgid "Status" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +#: selection:mail.mail,state:0 +msgid "Outgoing" +msgstr "" + +#. module: mail +#: selection:res.partner,notification_email_send:0 +msgid "All feeds" +msgstr "" + +#. module: mail +#: help:mail.compose.message,record_name:0 +#: help:mail.message,record_name:0 +msgid "Name get of the related document." +msgstr "" + +#. module: mail +#: model:ir.actions.act_window,name:mail.action_view_notifications +#: model:ir.model,name:mail.model_mail_notification +#: model:ir.ui.menu,name:mail.menu_email_notifications +#: field:mail.compose.message,notification_ids:0 +#: view:mail.message:0 +#: field:mail.message,notification_ids:0 +#: view:mail.notification:0 +msgid "Notifications" +msgstr "" + +#. module: mail +#: view:mail.alias:0 +msgid "Search Alias" +msgstr "" + +#. module: mail +#: help:mail.alias,alias_force_thread_id:0 +msgid "" +"Optional ID of a thread (record) to which all incoming messages will be " +"attached, even if they did not reply to it. If set, this will disable the " +"creation of new records completely." +msgstr "" + +#. module: mail +#: help:mail.message.subtype,name:0 +msgid "" +"Message subtype gives a more precise type on the message, especially for " +"system notifications. For example, it can be a notification related to a new " +"record (New), or to a stage change in a process (Stage change). Message " +"subtypes allow to precisely tune the notifications the user want to receive " +"on its wall." +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "by" +msgstr "" + +#. module: mail +#: model:mail.group,name:mail.group_best_sales_practices +msgid "Best Sales Practices" +msgstr "" + +#. module: mail +#: selection:mail.group,public:0 +msgid "Selected Group Only" +msgstr "" + +#. module: mail +#: field:mail.group,message_is_follower:0 +#: field:mail.thread,message_is_follower:0 +#: field:res.partner,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: mail +#: view:mail.alias:0 +#: view:mail.mail:0 +msgid "User" +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "Groups" +msgstr "" + +#. module: mail +#: view:mail.message:0 +msgid "Messages Search" +msgstr "" + +#. module: mail +#: field:mail.compose.message,date:0 +#: field:mail.message,date:0 +msgid "Date" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:34 +#, python-format +msgid "Post" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Extended Filters..." +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:122 +#, python-format +msgid "To:" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:193 +#, python-format +msgid "Write to my followers" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_res_groups +msgid "Access Groups" +msgstr "" + +#. module: mail +#: field:mail.message.subtype,default:0 +msgid "Default" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:294 +#, python-format +msgid "show more message" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:246 +#, python-format +msgid "Mark as Todo" +msgstr "" + +#. module: mail +#: help:mail.message.subtype,parent_id:0 +msgid "Parent subtype, used for automatic subscription." +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_wizard_invite +msgid "Invite wizard" +msgstr "" + +#. module: mail +#: field:mail.group,message_summary:0 +#: field:mail.thread,message_summary:0 +#: field:res.partner,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: mail +#: help:mail.message.subtype,res_model:0 +msgid "" +"Model the subtype applies to. If False, this subtype applies to all models." +msgstr "" + +#. module: mail +#: field:mail.compose.message,subtype_id:0 +#: field:mail.followers,subtype_ids:0 +#: field:mail.message,subtype_id:0 +#: view:mail.message.subtype:0 +msgid "Subtype" +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "Group Form" +msgstr "" + +#. module: mail +#: field:mail.compose.message,starred:0 +#: field:mail.message,starred:0 +#: field:mail.notification,starred:0 +msgid "Starred" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:296 +#, python-format +msgid "more messages" +msgstr "" + +#. module: mail +#: code:addons/mail/update.py:93 +#, python-format +msgid "Error" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:13 +#, python-format +msgid "Following" +msgstr "" + +#. module: mail +#: sql_constraint:mail.alias:0 +msgid "" +"Unfortunately this email alias is already used, please choose a unique one" +msgstr "" + +#. module: mail +#: help:mail.alias,alias_user_id:0 +msgid "" +"The owner of records created upon receiving emails on this alias. If this " +"field is not set the system will attempt to find the right owner based on " +"the sender (From) address, or will use the Administrator account if no " +"system user is found for that address." +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:52 +#, python-format +msgid "And" +msgstr "" + +#. module: mail +#: field:mail.compose.message,message_id:0 +#: field:mail.message,message_id:0 +msgid "Message-Id" +msgstr "" + +#. module: mail +#: help:mail.group,image:0 +msgid "" +"This field holds the image used as photo for the group, limited to " +"1024x1024px." +msgstr "" + +#. module: mail +#: field:mail.compose.message,attachment_ids:0 +#: view:mail.mail:0 +#: field:mail.message,attachment_ids:0 +msgid "Attachments" +msgstr "" + +#. module: mail +#: field:mail.compose.message,record_name:0 +#: field:mail.message,record_name:0 +msgid "Message Record Name" +msgstr "" + +#. module: mail +#: field:mail.mail,email_cc:0 +msgid "Cc" +msgstr "" + +#. module: mail +#: help:mail.notification,starred:0 +msgid "Starred message that goes into the todo mailbox" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:125 +#: view:mail.compose.message:0 +#, python-format +msgid "Followers of" +msgstr "" + +#. module: mail +#: help:mail.mail,auto_delete:0 +msgid "Permanently delete this email after sending it, to save space" +msgstr "" + +#. module: mail +#: model:ir.actions.client,name:mail.action_mail_group_feeds +msgid "Discussion Group" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:242 +#, python-format +msgid "Done" +msgstr "" + +#. module: mail +#: model:mail.message.subtype,name:mail.mt_comment +msgid "Discussions" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:11 +#, python-format +msgid "Follow" +msgstr "" + +#. module: mail +#: field:mail.group,name:0 +msgid "Name" +msgstr "" + +#. module: mail +#: model:mail.group,name:mail.group_all_employees +msgid "Whole Company" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:131 +#: code:addons/mail/static/src/xml/mail.xml:278 +#: view:mail.compose.message:0 +#, python-format +msgid "and" +msgstr "" + +#. module: mail +#: help:mail.mail,body_html:0 +msgid "Rich-text/HTML message" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +msgid "Creation Month" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:306 +#, python-format +msgid "Compose new Message" +msgstr "" + +#. module: mail +#: field:mail.group,menu_id:0 +msgid "Related Menu" +msgstr "" + +#. module: mail +#: view:mail.message:0 +msgid "Content" +msgstr "" + +#. module: mail +#: field:mail.mail,email_to:0 +msgid "To" +msgstr "" + +#. module: mail +#: field:mail.compose.message,notified_partner_ids:0 +#: field:mail.message,notified_partner_ids:0 +msgid "Notified partners" +msgstr "" + +#. module: mail +#: help:mail.group,public:0 +msgid "" +"This group is visible by non members. Invisible groups can add " +"members through the invite button." +msgstr "" + +#. module: mail +#: model:mail.group,name:mail.group_board +msgid "Board meetings" +msgstr "" + +#. module: mail +#: constraint:mail.alias:0 +msgid "" +"Invalid expression, it must be a literal python dictionary definition e.g. " +"\"{'field': 'value'}\"" +msgstr "" + +#. module: mail +#: field:mail.alias,alias_model_id:0 +msgid "Aliased Model" +msgstr "" + +#. module: mail +#: help:mail.compose.message,message_id:0 +#: help:mail.message,message_id:0 +msgid "Message unique identifier" +msgstr "" + +#. module: mail +#: field:mail.group,description:0 +#: field:mail.message.subtype,description:0 +msgid "Description" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_followers +msgid "Document Followers" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail_followers.xml:35 +#, python-format +msgid "Remove this follower" +msgstr "" + +#. module: mail +#: selection:res.partner,notification_email_send:0 +msgid "Never" +msgstr "" + +#. module: mail +#: field:mail.mail,mail_server_id:0 +msgid "Outgoing mail server" +msgstr "" + +#. module: mail +#: code:addons/mail/mail_message.py:919 +#, python-format +msgid "Partners email addresses not found" +msgstr "" + +#. module: mail +#: view:mail.mail:0 +#: selection:mail.mail,state:0 +msgid "Sent" +msgstr "" + +#. module: mail +#: field:mail.mail,body_html:0 +msgid "Rich-text Contents" +msgstr "" + +#. module: mail +#: help:mail.compose.message,to_read:0 +#: help:mail.message,to_read:0 +msgid "Current user has an unread notification linked to this message" +msgstr "" + +#. module: mail +#: help:res.partner,notification_email_send:0 +msgid "" +"Choose in which case you want to receive an email when you receive new feeds." +msgstr "" + +#. module: mail +#: model:ir.actions.act_window,name:mail.action_view_groups +#: model:ir.ui.menu,name:mail.mail_allgroups +msgid "Join a group" +msgstr "" + +#. module: mail +#: model:ir.actions.client,help:mail.action_mail_group_feeds +msgid "" +"

\n" +" No message in this group.\n" +"

\n" +" " +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:213 +#, python-format +msgid "Please, wait while the file is uploading." +msgstr "" + +#. module: mail +#: view:mail.group:0 +msgid "" +"This group is visible by everyone,\n" +" including your customers if you " +"installed\n" +" the portal module." +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:243 +#, python-format +msgid "Set back to Todo" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:128 +#, python-format +msgid "this document" +msgstr "" + +#. module: mail +#: field:mail.compose.message,filter_id:0 +msgid "Filters" +msgstr "" + +#. module: mail +#: field:res.partner,notification_email_send:0 +msgid "Receive Feeds by Email" +msgstr "" + +#. module: mail +#: help:base.config.settings,alias_domain:0 +msgid "" +"If you have setup a catch-all email domain redirected to the OpenERP server, " +"enter the domain name here." +msgstr "" + +#. module: mail +#: model:ir.actions.act_window,name:mail.action_view_mail_message +#: model:ir.ui.menu,name:mail.menu_mail_message +#: field:mail.group,message_ids:0 +#: view:mail.message:0 +#: field:mail.thread,message_ids:0 +#: field:res.partner,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:141 +#, python-format +msgid "others..." +msgstr "" + +#. module: mail +#: model:ir.actions.client,name:mail.action_mail_star_feeds +#: model:ir.ui.menu,name:mail.mail_starfeeds +msgid "To-do" +msgstr "" + +#. module: mail +#: view:mail.alias:0 +#: field:mail.alias,alias_name:0 +#: field:mail.group,alias_id:0 +#: field:res.users,alias_id:0 +msgid "Alias" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_mail +msgid "Outgoing Mails" +msgstr "" + +#. module: mail +#: help:mail.compose.message,notification_ids:0 +#: help:mail.message,notification_ids:0 +msgid "" +"Technical field holding the message notifications. Use notified_partner_ids " +"to access notified partners." +msgstr "" + +#. module: mail +#: model:ir.ui.menu,name:mail.mail_feeds +#: model:ir.ui.menu,name:mail.mail_feeds_main +msgid "Messaging" +msgstr "" + +#. module: mail +#: view:mail.alias:0 +#: field:mail.message.subtype,res_model:0 +msgid "Model" +msgstr "" + +#. module: mail +#: view:mail.message:0 +msgid "Unread" +msgstr "읽지 않음" + +#. module: mail +#: help:mail.followers,subtype_ids:0 +msgid "" +"Message subtypes followed, meaning subtypes that will be pushed onto the " +"user's Wall." +msgstr "" + +#. module: mail +#: help:mail.group,message_ids:0 +#: help:mail.thread,message_ids:0 +#: help:res.partner,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: mail +#: help:mail.mail,references:0 +msgid "Message references, such as identifiers of previous messages" +msgstr "" + +#. module: mail +#: field:mail.compose.message,composition_mode:0 +msgid "Composition mode" +msgstr "" + +#. module: mail +#: field:mail.compose.message,model:0 +#: field:mail.followers,res_model:0 +#: field:mail.message,model:0 +#: field:mail.wizard.invite,res_model:0 +msgid "Related Document Model" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:321 +#, python-format +msgid "unlike" +msgstr "" + +#. module: mail +#: help:mail.compose.message,author_id:0 +#: help:mail.message,author_id:0 +msgid "" +"Author of the message. If not set, email_from may hold an email address that " +"did not match any partner." +msgstr "" + +#. module: mail +#: help:mail.mail,email_cc:0 +msgid "Carbon copy message recipients" +msgstr "" + +#. module: mail +#: field:mail.alias,alias_domain:0 +msgid "Alias domain" +msgstr "" + +#. module: mail +#: code:addons/mail/update.py:93 +#, python-format +msgid "Error during communication with the publisher warranty server." +msgstr "" + +#. module: mail +#: selection:mail.group,public:0 +msgid "Private" +msgstr "" + +#. module: mail +#: model:ir.actions.client,help:mail.action_mail_star_feeds +msgid "" +"

\n" +" No todo.\n" +"

\n" +" When you process messages in your inbox, you can mark " +"some\n" +" as todo. From this menu, you can process all your " +"todo.\n" +"

\n" +" " +msgstr "" + +#. module: mail +#: selection:mail.mail,state:0 +msgid "Delivery Failed" +msgstr "" + +#. module: mail +#: field:mail.compose.message,partner_ids:0 +msgid "Additional contacts" +msgstr "" + +#. module: mail +#: help:mail.compose.message,parent_id:0 +#: help:mail.message,parent_id:0 +msgid "Initial thread message." +msgstr "" + +#. module: mail +#: model:mail.group,name:mail.group_hr_policies +msgid "HR Policies" +msgstr "" + +#. module: mail +#: selection:res.partner,notification_email_send:0 +msgid "Emails only" +msgstr "" + +#. module: mail +#: model:ir.actions.client,name:mail.action_mail_inbox_feeds +#: model:ir.ui.menu,name:mail.mail_inboxfeeds +msgid "Inbox" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/xml/mail.xml:58 +#, python-format +msgid "File" +msgstr "" + +#. module: mail +#. openerp-web +#: code:addons/mail/static/src/js/many2many_tags_email.js:63 +#, python-format +msgid "Please complete partner's informations and Email" +msgstr "" + +#. module: mail +#: model:ir.actions.act_window,name:mail.action_view_message_subtype +#: model:ir.ui.menu,name:mail.menu_message_subtype +msgid "Subtypes" +msgstr "" + +#. module: mail +#: model:ir.model,name:mail.model_mail_alias +msgid "Email Aliases" +msgstr "" + +#. module: mail +#: field:mail.group,image_small:0 +msgid "Small-sized photo" +msgstr "" + +#. module: mail +#: help:mail.mail,reply_to:0 +msgid "Preferred response address for the message" +msgstr "" diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index d5e3b675b56..870695e074e 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -117,8 +117,13 @@ class mail_alias(osv.Model): mail catchall domain from config. e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com` """ - return [(record['id'], "%s@%s" % (record['alias_name'], record['alias_domain'])) - for record in self.read(cr, uid, ids, ['alias_name', 'alias_domain'], context=context)] + res = [] + for record in self.browse(cr, uid, ids, context=context): + if record.alias_name and record.alias_domain: + res.append((record['id'], "%s@%s" % (record.alias_name, record.alias_domain))) + else: + res.append((record['id'], False)) + return res def _find_unique(self, cr, uid, name, context=None): """Find a unique alias name similar to ``name``. If ``name`` is @@ -134,7 +139,7 @@ class mail_alias(osv.Model): return new_name def migrate_to_alias(self, cr, child_model_name, child_table_name, child_model_auto_init_fct, - alias_id_column, alias_key, alias_prefix = '', alias_force_key = '', alias_defaults = {}, context=None): + alias_id_column, alias_key, alias_prefix='', alias_force_key='', alias_defaults={}, context=None): """ Installation hook to create aliases for all users and avoid constraint errors. :param child_model_name: model name of the child class (i.e. res.users) @@ -149,25 +154,27 @@ class mail_alias(osv.Model): :param alias_defaults: dict, keys = mail.alias columns, values = child model column name used for default values (i.e. {'job_id': 'id'}) """ + if context is None: + context = {} - # disable the unique alias_id not null constraint, to avoid spurious warning during + # disable the unique alias_id not null constraint, to avoid spurious warning during # super.auto_init. We'll reinstall it afterwards. alias_id_column.required = False # call _auto_init - child_model_auto_init_fct(cr, context=context) + res = child_model_auto_init_fct(cr, context=context) registry = RegistryManager.get(cr.dbname) mail_alias = registry.get('mail.alias') - child_class_model = registry.get(child_model_name) - no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test':False}) + child_class_model = registry[child_model_name] + no_alias_ids = child_class_model.search(cr, SUPERUSER_ID, [('alias_id', '=', False)], context={'active_test': False}) # Use read() not browse(), to avoid prefetching uninitialized inherited fields for obj_data in child_class_model.read(cr, SUPERUSER_ID, no_alias_ids, [alias_key]): - alias_vals = {'alias_name': '%s%s' % (alias_prefix, obj_data[alias_key]) } + alias_vals = {'alias_name': '%s%s' % (alias_prefix, obj_data[alias_key])} if alias_force_key: alias_vals['alias_force_thread_id'] = obj_data[alias_force_key] - alias_vals['alias_defaults'] = dict( (k, obj_data[v]) for k, v in alias_defaults.iteritems()) - alias_id = mail_alias.create_unique_alias(cr, SUPERUSER_ID, alias_vals, model_name=child_model_name) + alias_vals['alias_defaults'] = dict((k, obj_data[v]) for k, v in alias_defaults.iteritems()) + alias_id = mail_alias.create_unique_alias(cr, SUPERUSER_ID, alias_vals, model_name=context.get('alias_model_name', child_model_name)) child_class_model.write(cr, SUPERUSER_ID, obj_data['id'], {'alias_id': alias_id}) _logger.info('Mail alias created for %s %s (uid %s)', child_model_name, obj_data[alias_key], obj_data['id']) @@ -183,6 +190,8 @@ class mail_alias(osv.Model): # set back the unique alias_id constraint alias_id_column.required = True + return res + def create_unique_alias(self, cr, uid, vals, model_name=None, context=None): """Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index 450b81dabbf..98e88b664e6 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -90,7 +90,7 @@ class mail_notification(osv.Model): continue partner = notification.partner_id # If partners_to_notify specified: restrict to them - if partners_to_notify and partner.id not in partners_to_notify: + if partners_to_notify is not None and partner.id not in partners_to_notify: continue # Do not send to partners without email address defined if not partner.email: @@ -118,8 +118,8 @@ class mail_notification(osv.Model): Administrator

- Send by Your Company using OpenERP. OR - Send by Administrator using OpenERP. + Sent by Your Company using OpenERP. OR + Sent by Administrator using OpenERP.
""" footer = "" @@ -135,14 +135,17 @@ class mail_notification(osv.Model): footer = tools.append_content_to_html(footer, signature, plaintext=False, container_tag='p') # add company signature - if user.company_id: - company = user.company_id.website and "%s" % (user.company_id.website, user.company_id.name) or user.company_id.name + if user.company_id.website: + website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ + else user.company_id.website + company = "%s" % (website_url, user.company_id.name) else: - company = user.name - signature_company = _('Send by %(company)s using %(openerp)s.') % { + company = user.company_id.name + sent_by = _('Sent by %(company)s using %(openerp)s.') + signature_company = '%s' % (sent_by % { 'company': company, 'openerp': "OpenERP" - } + }) footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 5ccee40d5c7..04212b2f58a 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -29,6 +29,7 @@ +
@@ -42,6 +43,9 @@

+
+ %% +
@@ -68,39 +72,43 @@
- +

-
- -
+
- - - - - - - -
- This group is visible by everyone, - including your customers if you installed - the portal module. -
-
- Only the invited followers can read the - discussions on this group. -
-
+ + + + + + +
+ This group is visible by everyone, + including your customers if you installed + the portal module. +
+
+ Only the invited followers can read the + discussions on this group. +
diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index ab2b6f3e922..bd2b9c3f18a 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -27,8 +27,8 @@ from urlparse import urljoin from openerp import tools from openerp import SUPERUSER_ID +from openerp.addons.base.ir.ir_mail_server import MailDeliveryException from openerp.osv import fields, osv -from openerp.osv.orm import except_orm from openerp.tools.translate import _ _logger = logging.getLogger(__name__) @@ -60,9 +60,6 @@ class mail_mail(osv.Model): 'recipient_ids': fields.many2many('res.partner', string='To (Partners)'), 'email_cc': fields.char('Cc', help='Carbon copy message recipients'), 'body_html': fields.text('Rich-text Contents', help="Rich-text/HTML message"), - # If not set in create values, auto-detected based on create values (res_id, model, email_from) - 'reply_to': fields.char('Reply-To', - help='Preferred response address for the message'), # Auto-detected based on create() - if 'mail_message_id' was passed then this mail is a notification # and during unlink() we will not cascade delete the parent and its attachments 'notification': fields.boolean('Is Notification', @@ -93,32 +90,42 @@ class mail_mail(osv.Model): """ Return a specific reply_to: alias of the document through message_get_reply_to or take the email_from """ + # if value specified: directly return it if values.get('reply_to'): return values.get('reply_to') - email_reply_to = False - # model, res_id: comes from values OR related message - model = values.get('model') - res_id = values.get('res_id') - if values.get('mail_message_id') and (not model or not res_id): + mailgateway = True # tells whether the answer will go through the mailgateway, leading to the formatting of reply_to + ir_config_parameter = self.pool.get("ir.config_parameter") + catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context) + + # model, res_id, email_from, reply_to: comes from values OR related message + message = None + if values.get('mail_message_id'): message = self.pool.get('mail.message').browse(cr, uid, values.get('mail_message_id'), context=context) - if not model: - model = message.model - if not res_id: - res_id = message.res_id + model = values.get('model', message and message.model or False) + res_id = values.get('res_id', message and message.res_id or False) + email_from = values.get('email_from', message and message.email_from or False) + email_reply_to = message and message.reply_to or False # if model and res_id: try to use ``message_get_reply_to`` that returns the document alias - if model and res_id and hasattr(self.pool.get(model), 'message_get_reply_to'): - email_reply_to = self.pool.get(model).message_get_reply_to(cr, uid, [res_id], context=context)[0] + if not email_reply_to and model and res_id and hasattr(self.pool[model], 'message_get_reply_to'): + email_reply_to = self.pool[model].message_get_reply_to(cr, uid, [res_id], context=context)[0] + # no alias reply_to -> catchall alias + if not email_reply_to: + catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context) + if catchall_domain and catchall_alias: + email_reply_to = '%s@%s' % (catchall_alias, catchall_domain) # no alias reply_to -> reply_to will be the email_from, only the email part - if not email_reply_to and values.get('email_from'): - emails = tools.email_split(values.get('email_from')) + if not email_reply_to and email_from: + emails = tools.email_split(email_from) if emails: email_reply_to = emails[0] + if emails[0].split('@')[1] != catchall_domain: + mailgateway = False # format 'Document name ' - if email_reply_to and model and res_id: - document_name = self.pool.get(model).name_get(cr, SUPERUSER_ID, [res_id], context=context)[0] + if email_reply_to and model and res_id and mailgateway: + document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0] if document_name: # sanitize document name sanitized_doc_name = re.sub(r'[^\w+.]+', '-', document_name[1]) @@ -195,6 +202,36 @@ class mail_mail(osv.Model): self.unlink(cr, SUPERUSER_ID, [mail.id], context=context) return True + #------------------------------------------------------ + # mail_mail formatting, tools and send mechanism + #------------------------------------------------------ + + # TODO in 8.0(+): maybe factorize this to enable in modules link generation + # independently of mail_mail model + # TODO in 8.0(+): factorize doc name sanitized and 'Followers of ...' formatting + # because it begins to appear everywhere + + def _get_partner_access_link(self, cr, uid, mail, partner=None, context=None): + """ Generate URLs for links in mails: + - partner is an user and has read access to the document: direct link to document with model, res_id + """ + if partner and partner.user_ids: + base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + # the parameters to encode for the query and fragment part of url + query = {'db': cr.dbname} + fragment = { + 'login': partner.user_ids[0].login, + 'action': 'mail.action_mail_redirect', + } + if mail.notification: + fragment.update({ + 'message_id': mail.mail_message_id.id, + }) + url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment))) + return _("""Access your messages and documents in OpenERP""") % url + else: + return None + def send_get_mail_subject(self, cr, uid, mail, force=False, partner=None, context=None): """ If subject is void and record_name defined: ' posted on ' @@ -202,36 +239,12 @@ class mail_mail(osv.Model): :param browse_record mail: mail.mail browse_record :param browse_record partner: specific recipient partner """ - if force or (not mail.subject and mail.model and mail.res_id): + if (force or not mail.subject) and mail.record_name: return 'Re: %s' % (mail.record_name) + elif (force or not mail.subject) and mail.parent_id and mail.parent_id.subject: + return 'Re: %s' % (mail.parent_id.subject) return mail.subject - def send_get_mail_body_footer(self, cr, uid, mail, partner=None, context=None): - """ Return a specific footer for the ir_email body. The main purpose of this method - is to be inherited by Portal, to add modify the link for signing in, in - each notification email a partner receives. - """ - body_footer = "" - # partner is a user, link to a related document (incentive to install portal) - if partner and partner.user_ids and mail.model and mail.res_id \ - and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False): - related_user = partner.user_ids[0] - try: - self.pool.get(mail.model).check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context) - base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') - # the parameters to encode for the query and fragment part of url - query = {'db': cr.dbname} - fragment = { - 'login': related_user.login, - 'model': mail.model, - 'id': mail.res_id, - } - url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment))) - body_footer = _("""Access this document directly in OpenERP""") % url - except except_orm, e: - pass - return body_footer - def send_get_mail_body(self, cr, uid, mail, partner=None, context=None): """ Return a specific ir_email body. The main purpose of this method is to be inherited to add custom content depending on some module. @@ -241,9 +254,10 @@ class mail_mail(osv.Model): """ body = mail.body_html - # add footer - body_footer = self.send_get_mail_body_footer(cr, uid, mail, partner=partner, context=context) - body = tools.append_content_to_html(body, body_footer, plaintext=False, container_tag='div') + # generate footer + link = self._get_partner_access_link(cr, uid, mail, partner, context=context) + if link: + body = tools.append_content_to_html(body, link, plaintext=False, container_tag='div') return body def send_get_email_dict(self, cr, uid, mail, partner=None, context=None): @@ -276,7 +290,7 @@ class mail_mail(osv.Model): 'email_to': email_to, } - def send(self, cr, uid, ids, auto_commit=False, context=None): + def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None): """ Sends the selected emails immediately, ignoring their current state (mails that have already been sent should not be passed unless they should actually be re-sent). @@ -287,6 +301,8 @@ class mail_mail(osv.Model): :param bool auto_commit: whether to force a commit of the mail status after sending each mail (meant only for scheduler processing); should never be True during normal transactions (default: False) + :param bool raise_exception: whether to raise an exception if the + email sending process has failed :return: True """ ir_mail_server = self.pool.get('ir.mail_server') @@ -332,9 +348,16 @@ class mail_mail(osv.Model): # see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1 if mail_sent: self._postprocess_sent_message(cr, uid, mail, context=context) - except Exception: + except Exception as e: _logger.exception('failed sending mail.mail %s', mail.id) mail.write({'state': 'exception'}) + if raise_exception: + if isinstance(e, AssertionError): + # get the args of the original error, wrap into a value and throw a MailDeliveryException + # that is an except_orm, with name and value as arguments + value = '. '.join(e.args) + raise MailDeliveryException(_("Mail Delivery Failed"), value) + raise if auto_commit == True: cr.commit() diff --git a/addons/mail/mail_mail_view.xml b/addons/mail/mail_mail_view.xml index 1ff9a2a292e..7384cc24a75 100644 --- a/addons/mail/mail_mail_view.xml +++ b/addons/mail/mail_mail_view.xml @@ -6,6 +6,11 @@ mail.mail +
+
@@ -196,20 +177,20 @@ - Production Order N° : [[ o.name ]] + Production Order N° : [[ o.name ]] @@ -232,16 +213,16 @@ @@ -266,26 +247,26 @@ - Work Orders [[ o.workcenter_lines ==[] and removeParentNode('para')]] + Work Orders [[ o.workcenter_lines ==[] and removeParentNode('para')]] @@ -317,28 +298,28 @@ - Bill Of Material + Bill Of Material
- Products to Consume [[ o.move_lines ==[] and removeParentNode('section')]] + Products to Consume [[ o.move_lines ==[] and removeParentNode('section')]]
[[ repeatIn(o.move_lines,'line') ]] @@ -363,7 +344,7 @@ - Consumed Products [[ o.move_lines2 ==[] and removeParentNode('section')]] + Consumed Products [[ o.move_lines2 ==[] and removeParentNode('section')]]
[[ repeatIn(o.move_lines2,'line2') ]] diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py index 2feffee94a1..0ebc7bd199d 100644 --- a/addons/mrp/stock.py +++ b/addons/mrp/stock.py @@ -145,7 +145,6 @@ class StockMove(osv.osv): res.append(new_move) return res -StockMove() class StockPicking(osv.osv): @@ -162,7 +161,6 @@ class StockPicking(osv.osv): todo.extend(move_obj._action_explode(cr, uid, move)) return list(set(todo)) -StockPicking() class split_in_production_lot(osv.osv_memory): @@ -179,6 +177,5 @@ class split_in_production_lot(osv.osv_memory): production_obj.write(cr, uid, production_ids, {'move_lines': [(4, m) for m in new_moves]}) return new_moves -split_in_production_lot() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py index 74309b50825..41b6022a178 100644 --- a/addons/mrp/wizard/change_production_qty.py +++ b/addons/mrp/wizard/change_production_qty.py @@ -101,6 +101,5 @@ class change_production_qty(osv.osv_memory): self._update_product_to_produce(cr, uid, prod, wiz_qty.product_qty, context=context) return {} -change_production_qty() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/wizard/mrp_price.py b/addons/mrp/wizard/mrp_price.py index 08506ccf0e2..70b4482b019 100644 --- a/addons/mrp/wizard/mrp_price.py +++ b/addons/mrp/wizard/mrp_price.py @@ -52,6 +52,5 @@ class mrp_price(osv.osv_memory): 'datas' : datas, } -mrp_price() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/wizard/mrp_product_produce.py b/addons/mrp/wizard/mrp_product_produce.py index 3a3c5961d1e..0851657587c 100644 --- a/addons/mrp/wizard/mrp_product_produce.py +++ b/addons/mrp/wizard/mrp_product_produce.py @@ -67,6 +67,5 @@ class mrp_product_produce(osv.osv_memory): data.product_qty, data.mode, context=context) return {} -mrp_product_produce() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/wizard/mrp_workcenter_load.py b/addons/mrp/wizard/mrp_workcenter_load.py index 265c6ddcea0..79905673a6b 100644 --- a/addons/mrp/wizard/mrp_workcenter_load.py +++ b/addons/mrp/wizard/mrp_workcenter_load.py @@ -51,6 +51,5 @@ class mrp_workcenter_load(osv.osv_memory): 'datas' : datas, } -mrp_workcenter_load() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp_byproduct/mrp_byproduct.py b/addons/mrp_byproduct/mrp_byproduct.py index 22bbface59d..2425c2d8fea 100644 --- a/addons/mrp_byproduct/mrp_byproduct.py +++ b/addons/mrp_byproduct/mrp_byproduct.py @@ -64,7 +64,6 @@ class mrp_subproduct(osv.osv): res['value'].update({'product_uom': product.uom_id.id}) return res -mrp_subproduct() class mrp_bom(osv.osv): _name = 'mrp.bom' @@ -75,7 +74,6 @@ class mrp_bom(osv.osv): 'sub_products':fields.one2many('mrp.subproduct', 'bom_id', 'Byproducts'), } -mrp_bom() class mrp_production(osv.osv): _description = 'Production' @@ -143,7 +141,6 @@ class mrp_production(osv.osv): return subproduct_factor return super(mrp_production, self)._get_subproduct_factor(cr, uid, production_id, move_id, context=context) -mrp_production() class change_production_qty(osv.osv_memory): _inherit = 'change.production.qty' diff --git a/addons/mrp_operations/mrp_operations.py b/addons/mrp_operations/mrp_operations.py index c069def7554..87861ba8fc6 100644 --- a/addons/mrp_operations/mrp_operations.py +++ b/addons/mrp_operations/mrp_operations.py @@ -46,7 +46,6 @@ class stock_move(osv.osv): }) return super(stock_move, self).copy(cr, uid, id, default, context) -stock_move() class mrp_production_workcenter_line(osv.osv): @@ -129,7 +128,7 @@ class mrp_production_workcenter_line(osv.osv): elif prod_obj.state =='in_production': return else: - raise osv.except_osv(_('Error!'),_('Manufacturing order cannot start in state "%s"!') % (prod_obj.state,)) + raise osv.except_osv(_('Error!'),_('Manufacturing order cannot be started in state "%s"!') % (prod_obj.state,)) else: oper_ids = self.search(cr,uid,[('production_id','=',prod_obj.id)]) obj = self.browse(cr,uid,oper_ids) @@ -371,7 +370,6 @@ class mrp_production(osv.osv): self._compute_planned_workcenter(cr, uid, ids, context=context) return result -mrp_production() class mrp_operations_operation_code(osv.osv): _name="mrp_operations.operation.code" @@ -380,7 +378,6 @@ class mrp_operations_operation_code(osv.osv): 'code': fields.char('Code', size=16, required=True), 'start_stop': fields.selection([('start','Start'),('pause','Pause'),('resume','Resume'),('cancel','Cancelled'),('done','Done')], 'Status', required=True), } -mrp_operations_operation_code() class mrp_operations_operation(osv.osv): _name="mrp_operations.operation" @@ -446,7 +443,7 @@ class mrp_operations_operation(osv.osv): if not oper_objs: if code.start_stop!='start': - raise osv.except_osv(_('Sorry!'),_('Operation is not started yet !')) + raise osv.except_osv(_('Sorry!'),_('Operation is not started yet!')) return False else: for oper in oper_objs: @@ -560,6 +557,5 @@ class mrp_operations_operation(osv.osv): 'date_start': lambda *a:datetime.now().strftime('%Y-%m-%d %H:%M:%S') } -mrp_operations_operation() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp_operations/process/mrp_operation_process.xml b/addons/mrp_operations/process/mrp_operation_process.xml index 452434bbe92..d448b6a299a 100644 --- a/addons/mrp_operations/process/mrp_operation_process.xml +++ b/addons/mrp_operations/process/mrp_operation_process.xml @@ -75,32 +75,32 @@ - - + + - - + + - - + + - - + + diff --git a/addons/mrp_operations/report/mrp_workorder_analysis.py b/addons/mrp_operations/report/mrp_workorder_analysis.py index 73982b09f8b..f91961ad74c 100644 --- a/addons/mrp_operations/report/mrp_workorder_analysis.py +++ b/addons/mrp_operations/report/mrp_workorder_analysis.py @@ -71,6 +71,5 @@ class mrp_workorder(osv.osv): w.costs_hour, mp.product_id, mp.name, wl.state, wl.date_planned, wl.production_id, wl.workcenter_id )""") -mrp_workorder() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py index 6c3f0ce21e1..f7b082db74b 100644 --- a/addons/mrp_repair/mrp_repair.py +++ b/addons/mrp_repair/mrp_repair.py @@ -365,7 +365,7 @@ class mrp_repair(osv.osv): if repair.state in ('draft','cancel') or repair.invoice_id: continue if not (repair.partner_id.id and repair.partner_invoice_id.id): - raise osv.except_osv(_('No partner !'),_('You have to select a Partner Invoice Address in the repair form !')) + raise osv.except_osv(_('No partner!'),_('You have to select a Partner Invoice Address in the repair form!')) comment = repair.quotation_notes if (repair.invoice_method != 'none'): if group and repair.partner_invoice_id.id in invoices_group: @@ -582,7 +582,7 @@ class ProductChangeMixin(object): result['product_uom'] = product_obj.uom_id and product_obj.uom_id.id or False if not pricelist: warning = { - 'title':'No Pricelist !', + 'title':'No Pricelist!', 'message': 'You have to select a pricelist in the Repair form !\n' 'Please set one before choosing a product.' @@ -699,7 +699,6 @@ class mrp_repair_line(osv.osv, ProductChangeMixin): 'location_dest_id': scrap_location_ids and scrap_location_ids[0] or False, }} -mrp_repair_line() class mrp_repair_fee(osv.osv, ProductChangeMixin): _name = 'mrp.repair.fee' @@ -741,5 +740,4 @@ class mrp_repair_fee(osv.osv, ProductChangeMixin): 'to_invoice': lambda *a: True, } -mrp_repair_fee() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp_repair/mrp_repair_view.xml b/addons/mrp_repair/mrp_repair_view.xml index d35a9ebcf1d..a4526b5b581 100644 --- a/addons/mrp_repair/mrp_repair_view.xml +++ b/addons/mrp_repair/mrp_repair_view.xml @@ -210,7 +210,7 @@ - + diff --git a/addons/mrp_repair/security/mrp_repair_security.xml b/addons/mrp_repair/security/mrp_repair_security.xml index 0b34310fc4e..e94b675b57f 100644 --- a/addons/mrp_repair/security/mrp_repair_security.xml +++ b/addons/mrp_repair/security/mrp_repair_security.xml @@ -11,4 +11,4 @@ - \ No newline at end of file + diff --git a/addons/mrp_repair/wizard/cancel_repair.py b/addons/mrp_repair/wizard/cancel_repair.py index 12b85efd202..4c60f6c3251 100644 --- a/addons/mrp_repair/wizard/cancel_repair.py +++ b/addons/mrp_repair/wizard/cancel_repair.py @@ -81,7 +81,6 @@ class repair_cancel(osv.osv_memory): """ return res -repair_cancel() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp_repair/wizard/make_invoice.py b/addons/mrp_repair/wizard/make_invoice.py index 9442746d68e..f9c84cb7bdb 100644 --- a/addons/mrp_repair/wizard/make_invoice.py +++ b/addons/mrp_repair/wizard/make_invoice.py @@ -68,7 +68,6 @@ class make_invoice(osv.osv_memory): 'type': 'ir.actions.act_window' } -make_invoice() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/multi_company/i18n/ru.po b/addons/multi_company/i18n/ru.po index 3dea680c371..e1665d9c838 100644 --- a/addons/multi_company/i18n/ru.po +++ b/addons/multi_company/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-08-17 11:09+0000\n" +"PO-Revision-Date: 2013-06-06 10:25+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:36+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-06-07 05:48+0000\n" +"X-Generator: Launchpad (build 16667)\n" #. module: multi_company #: model:ir.ui.menu,name:multi_company.menu_custom_multicompany @@ -45,6 +45,16 @@ msgid "" "Thank you in advance for your cooperation.\n" "Best Regards," msgstr "" +"Уважаемые господа,\n" +"\n" +"Наши записи зафиксировали что некоторые платежи остаются неоплаченными. " +"Пожалуйста ознакомьтесь с подробностями ниже.\n" +"Если сумма уже была оплачена, пожалуйста проигнорируйте это оповещение. В " +"ином случае, пожалуйста перечислите нам всю сумму отображенную ниже.\n" +"Если у вас есть какие-либо замечания, пожалуйста свяжитесь с нами.\n" +"\n" +"Заранее благодарим за сотрудничество.\n" +"С наилучшими пожеланиями," #. module: multi_company #: view:multi_company.default:0 diff --git a/addons/multi_company/multi_company_demo.xml b/addons/multi_company/multi_company_demo.xml index 088aa35e915..c772a8fd67d 100644 --- a/addons/multi_company/multi_company_demo.xml +++ b/addons/multi_company/multi_company_demo.xml @@ -192,8 +192,8 @@ SAJ-OpenERP IN sale - - + + @@ -204,8 +204,8 @@ SCNJ-OpenERP IN sale_refund - - + + @@ -216,8 +216,8 @@ EXJ-OpenERP IN purchase - - + + @@ -228,8 +228,8 @@ ECNJ-OpenERP IN purchase_refund - - + + @@ -240,8 +240,8 @@ BNK-OpenERP IN bank - - + + @@ -252,8 +252,8 @@ CHK-OpenERP IN bank - - + + @@ -264,8 +264,8 @@ CSH-OpenERP IN cash - - + + @@ -277,8 +277,8 @@ SAJ-OpenERP US sale - - + + @@ -289,8 +289,8 @@ SCNJ-OpenERP US sale_refund - - + + @@ -301,8 +301,8 @@ EXJ-OpenERP US purchase - - + + @@ -313,8 +313,8 @@ ECNJ-OpenERP US purchase_refund - - + + @@ -325,8 +325,8 @@ BNK-OpenERP US bank - - + + @@ -337,8 +337,8 @@ CHK-OpenERP US bank - - + + @@ -349,8 +349,8 @@ CSH-OpenERP US cash - - + + @@ -363,8 +363,8 @@ SAJ-OpenERP BE sale - - + + @@ -375,8 +375,8 @@ SCNJ-OpenERP BE sale_refund - - + + @@ -387,8 +387,8 @@ EXJ-OpenERP BE purchase - - + + @@ -399,8 +399,8 @@ ECNJ-OpenERP BE purchase_refund - - + + @@ -411,8 +411,8 @@ BNK-OpenERP BE bank - - + + @@ -423,8 +423,8 @@ CHK-OpenERP BE bank - - + + @@ -435,8 +435,8 @@ CSH-OpenERP BE cash - - + + diff --git a/addons/note/html/index.html b/addons/note/html/index.html new file mode 100644 index 00000000000..7ef37c646e9 --- /dev/null +++ b/addons/note/html/index.html @@ -0,0 +1,116 @@ +
+
+

Notes

+

Getting Things Done with Notes

+
+
+ + + + +
+
+
+

+Organize yourself with efficient todo lists and notes. From personnal tasks to collaborative meeting minutes, increase your user's productivity by giving them the tools to prioritize their work, share their ideas and collaborate on documents. +

+ +
+
+
+ +
+
+
+

Personal to-do lists that works

+

+Quickly create to-dos, organize horizontally for the mid-term (today, this week, this month, ...), prioritize vertically for the short term and group by assigning colors. The kanban approach allows a simple visual organization of your to-dos. +

+
+
+ +
+
+

Beat Work Overload

+

+ Feel how good it is to rely on a structured way to organize your work instead of keeping everything in memory. Use notes to Get Things Done. +

+
+
+

Prioritize Efficiently

+

+ Most people are lost in the flow of urgent daily tasks and have difficulties to work on important, long-term tasks. Notes gives you a simple way to allocate time very day to do important, but less urgent tasks. +

+
+
+

Find Motivation to Close Tasks

+

+ People used to work on tasks they like and not on important tasks. Start feeling good by checking tasks as done. +

+
+
+
+
+
+

Adapts to Your Creative Process

+

Customize to your own workflow

+

+Everyone has their own way to organize activities. OpenERP Notes' smart kanban approach allows every user to customize their own steps to process it's to-dos and notes. +

+ + +
+

A Creative Person

+

+A creative person will organize notes based on idea's maturity level: Draft Ideas Mature Ideas Specified To Do

+
+
+

A Frequent Traveler

+

+ An employee travelling a lot can organize their tasks based on the context to perform the task: U.S. Office | London's Office | To Review during Flights | At Home +

+
+
+

A Manager

+

+ A manager will organize their high number of tasks based on prioritizations: Todo Today | This Week | This Month | Later +

+ +
+
+ +
+
+

Personnal Notes

+

Notes are private but can be shared

+
+
+ +
+
+
+

+Write down your ideas in pads, keep your notes at your finger tips, attach related documents and use tags and colors to organize the information. Once your ideas are mature, you can share them to others users, start discussing it and collaborate by improving the specification in the pad. +

+
+
+
+ +
+
+

Collaborative Meeting Minutes

+

Real-time sharing and edition of notes

+
+

+The real time collaborative writings on notes makes it the perfect tool to collaborate on meeting minutes. Attendees will be able to contribute to the minutes, attach important documents or discuss on the related thread. +

+
+
+ +
+
+
+
+
diff --git a/addons/note/html/notes_illu_01.png b/addons/note/html/notes_illu_01.png new file mode 100644 index 00000000000..a7d4197561d Binary files /dev/null and b/addons/note/html/notes_illu_01.png differ diff --git a/addons/note/html/notes_sc_00.png b/addons/note/html/notes_sc_00.png new file mode 100644 index 00000000000..7bb4f95a640 Binary files /dev/null and b/addons/note/html/notes_sc_00.png differ diff --git a/addons/note/html/notes_sc_01.png b/addons/note/html/notes_sc_01.png new file mode 100644 index 00000000000..ce9367abf9b Binary files /dev/null and b/addons/note/html/notes_sc_01.png differ diff --git a/addons/note/html/notes_sc_02.png b/addons/note/html/notes_sc_02.png new file mode 100644 index 00000000000..e47889b33fc Binary files /dev/null and b/addons/note/html/notes_sc_02.png differ diff --git a/addons/note/html/notes_sc_03.png b/addons/note/html/notes_sc_03.png new file mode 100644 index 00000000000..6d59d7e5df8 Binary files /dev/null and b/addons/note/html/notes_sc_03.png differ diff --git a/addons/note/i18n/lt.po b/addons/note/i18n/lt.po new file mode 100644 index 00000000000..3e030054520 --- /dev/null +++ b/addons/note/i18n/lt.po @@ -0,0 +1,284 @@ +# 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:04+0000\n" +"PO-Revision-Date: 2013-04-29 15:23+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: note +#: field:note.note,memo:0 +msgid "Note Content" +msgstr "" + +#. module: note +#: view:note.stage:0 +msgid "Stages of Notes" +msgstr "" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_04 +#: model:note.stage,name:note.note_stage_02 +msgid "This Week" +msgstr "" + +#. module: note +#: model:ir.model,name:note.model_base_config_settings +msgid "base.config.settings" +msgstr "" + +#. module: note +#: model:ir.model,name:note.model_note_tag +msgid "Note Tag" +msgstr "" + +#. module: note +#: model:res.groups,name:note.group_note_fancy +msgid "Notes / Fancy mode" +msgstr "" + +#. module: note +#: model:ir.model,name:note.model_note_note +#: view:note.note:0 +msgid "Note" +msgstr "" + +#. module: note +#: view:note.note:0 +msgid "Group By..." +msgstr "" + +#. module: note +#: field:note.note,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: note +#: model:ir.actions.act_window,help:note.action_note_note +msgid "" +"

\n" +" Click to add a personal note.\n" +"

\n" +" Use notes to organize personal tasks or notes. All\n" +" notes are private; no one else will be able to see them. " +"However\n" +" you can share some notes with other people by inviting " +"followers\n" +" on the note. (Useful for meeting minutes, especially if\n" +" you activate the pad feature for collaborative writings).\n" +"

\n" +" You can customize how you process your notes/tasks by adding,\n" +" removing or modifying columns.\n" +"

\n" +" " +msgstr "" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_01 +#: model:note.stage,name:note.note_stage_01 +msgid "Today" +msgstr "" + +#. module: note +#: model:ir.model,name:note.model_res_users +msgid "Users" +msgstr "" + +#. module: note +#: view:note.note:0 +msgid "í" +msgstr "" + +#. module: note +#: view:note.stage:0 +msgid "Stage of Notes" +msgstr "" + +#. module: note +#: field:note.note,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: note +#: field:note.note,current_partner_id:0 +msgid "unknown" +msgstr "" + +#. module: note +#: view:note.note:0 +msgid "By sticky note Category" +msgstr "" + +#. module: note +#: help:note.note,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: note +#: field:note.stage,name:0 +msgid "Stage Name" +msgstr "" + +#. module: note +#: field:note.note,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_02 +msgid "Tomorrow" +msgstr "" + +#. module: note +#: view:note.note:0 +#: field:note.note,open:0 +msgid "Active" +msgstr "" + +#. module: note +#: help:note.stage,user_id:0 +msgid "Owner of the note stage." +msgstr "" + +#. module: note +#: model:ir.ui.menu,name:note.menu_notes_stage +msgid "Categories" +msgstr "" + +#. module: note +#: view:note.note:0 +#: field:note.note,stage_id:0 +msgid "Stage" +msgstr "" + +#. module: note +#: field:note.tag,name:0 +msgid "Tag Name" +msgstr "" + +#. module: note +#: field:note.note,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: note +#: view:base.config.settings:0 +#: model:ir.actions.act_window,name:note.action_note_note +#: model:ir.ui.menu,name:note.menu_note_notes +#: view:note.note:0 +#: model:note.stage,name:note.note_stage_04 +msgid "Notes" +msgstr "" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_03 +#: model:note.stage,name:note.note_stage_03 +msgid "Later" +msgstr "" + +#. module: note +#: model:ir.model,name:note.model_note_stage +msgid "Note Stage" +msgstr "" + +#. module: note +#: field:note.note,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: note +#: field:note.note,stage_ids:0 +msgid "Stages of Users" +msgstr "" + +#. module: note +#: field:note.note,name:0 +msgid "Note Summary" +msgstr "" + +#. module: note +#: model:ir.actions.act_window,name:note.action_note_stage +#: view:note.note:0 +msgid "Stages" +msgstr "" + +#. module: note +#: help:note.note,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: note +#: view:note.note:0 +msgid "Delete" +msgstr "" + +#. module: note +#: field:note.note,color:0 +msgid "Color Index" +msgstr "" + +#. module: note +#: field:note.note,sequence:0 +#: field:note.stage,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: note +#: view:note.note:0 +#: field:note.note,tag_ids:0 +msgid "Tags" +msgstr "" + +#. module: note +#: view:note.note:0 +msgid "Archive" +msgstr "" + +#. module: note +#: field:base.config.settings,module_note_pad:0 +msgid "Use collaborative pads (etherpad)" +msgstr "" + +#. module: note +#: help:note.note,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: note +#: field:base.config.settings,group_note_fancy:0 +msgid "Use fancy layouts for notes" +msgstr "" + +#. module: note +#: field:note.note,current_partner_id:0 +#: field:note.stage,user_id:0 +msgid "Owner" +msgstr "" + +#. module: note +#: help:note.stage,sequence:0 +msgid "Used to order the note stages" +msgstr "" + +#. module: note +#: field:note.note,date_done:0 +msgid "Date done" +msgstr "" + +#. module: note +#: field:note.stage,fold:0 +msgid "Folded by Default" +msgstr "" diff --git a/addons/note/i18n/ru.po b/addons/note/i18n/ru.po new file mode 100644 index 00000000000..ef2cd6be0c1 --- /dev/null +++ b/addons/note/i18n/ru.po @@ -0,0 +1,286 @@ +# 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:04+0000\n" +"PO-Revision-Date: 2013-06-06 10:35+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-06-07 05:48+0000\n" +"X-Generator: Launchpad (build 16667)\n" + +#. module: note +#: field:note.note,memo:0 +msgid "Note Content" +msgstr "Содержание заметки" + +#. module: note +#: view:note.stage:0 +msgid "Stages of Notes" +msgstr "Этапы заметок" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_04 +#: model:note.stage,name:note.note_stage_02 +msgid "This Week" +msgstr "Эта неделя" + +#. module: note +#: model:ir.model,name:note.model_base_config_settings +msgid "base.config.settings" +msgstr "base.config.settings" + +#. module: note +#: model:ir.model,name:note.model_note_tag +msgid "Note Tag" +msgstr "Тег заметки" + +#. module: note +#: model:res.groups,name:note.group_note_fancy +msgid "Notes / Fancy mode" +msgstr "" + +#. module: note +#: model:ir.model,name:note.model_note_note +#: view:note.note:0 +msgid "Note" +msgstr "Заметка" + +#. module: note +#: view:note.note:0 +msgid "Group By..." +msgstr "Группировать по ..." + +#. module: note +#: field:note.note,message_follower_ids:0 +msgid "Followers" +msgstr "Подписчики" + +#. module: note +#: model:ir.actions.act_window,help:note.action_note_note +msgid "" +"

\n" +" Click to add a personal note.\n" +"

\n" +" Use notes to organize personal tasks or notes. All\n" +" notes are private; no one else will be able to see them. " +"However\n" +" you can share some notes with other people by inviting " +"followers\n" +" on the note. (Useful for meeting minutes, especially if\n" +" you activate the pad feature for collaborative writings).\n" +"

\n" +" You can customize how you process your notes/tasks by adding,\n" +" removing or modifying columns.\n" +"

\n" +" " +msgstr "" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_01 +#: model:note.stage,name:note.note_stage_01 +msgid "Today" +msgstr "Сегодня" + +#. module: note +#: model:ir.model,name:note.model_res_users +msgid "Users" +msgstr "Пользователи" + +#. module: note +#: view:note.note:0 +msgid "í" +msgstr "" + +#. module: note +#: view:note.stage:0 +msgid "Stage of Notes" +msgstr "Этап заметок" + +#. module: note +#: field:note.note,message_unread:0 +msgid "Unread Messages" +msgstr "Непрочитанные" + +#. module: note +#: field:note.note,current_partner_id:0 +msgid "unknown" +msgstr "неизвестно" + +#. module: note +#: view:note.note:0 +msgid "By sticky note Category" +msgstr "" + +#. module: note +#: help:note.note,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "Если отмечено, новые сообщения требуют вашего внимания." + +#. module: note +#: field:note.stage,name:0 +msgid "Stage Name" +msgstr "Название этапа" + +#. module: note +#: field:note.note,message_is_follower:0 +msgid "Is a Follower" +msgstr "Подписан" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_02 +msgid "Tomorrow" +msgstr "Завтра" + +#. module: note +#: view:note.note:0 +#: field:note.note,open:0 +msgid "Active" +msgstr "Активно" + +#. module: note +#: help:note.stage,user_id:0 +msgid "Owner of the note stage." +msgstr "Владелец этапа заметки" + +#. module: note +#: model:ir.ui.menu,name:note.menu_notes_stage +msgid "Categories" +msgstr "Категории" + +#. module: note +#: view:note.note:0 +#: field:note.note,stage_id:0 +msgid "Stage" +msgstr "Этап" + +#. module: note +#: field:note.tag,name:0 +msgid "Tag Name" +msgstr "Название тега" + +#. module: note +#: field:note.note,message_ids:0 +msgid "Messages" +msgstr "Сообщения" + +#. module: note +#: view:base.config.settings:0 +#: model:ir.actions.act_window,name:note.action_note_note +#: model:ir.ui.menu,name:note.menu_note_notes +#: view:note.note:0 +#: model:note.stage,name:note.note_stage_04 +msgid "Notes" +msgstr "Заметки" + +#. module: note +#: model:note.stage,name:note.demo_note_stage_03 +#: model:note.stage,name:note.note_stage_03 +msgid "Later" +msgstr "Позже" + +#. module: note +#: model:ir.model,name:note.model_note_stage +msgid "Note Stage" +msgstr "Этап заметки" + +#. module: note +#: field:note.note,message_summary:0 +msgid "Summary" +msgstr "Итог" + +#. module: note +#: field:note.note,stage_ids:0 +msgid "Stages of Users" +msgstr "Этапы пользователей" + +#. module: note +#: field:note.note,name:0 +msgid "Note Summary" +msgstr "Заметка - кратко" + +#. module: note +#: model:ir.actions.act_window,name:note.action_note_stage +#: view:note.note:0 +msgid "Stages" +msgstr "Этапы" + +#. module: note +#: help:note.note,message_ids:0 +msgid "Messages and communication history" +msgstr "Сообщения и история общения" + +#. module: note +#: view:note.note:0 +msgid "Delete" +msgstr "Удалить" + +#. module: note +#: field:note.note,color:0 +msgid "Color Index" +msgstr "Цветовая палитра" + +#. module: note +#: field:note.note,sequence:0 +#: field:note.stage,sequence:0 +msgid "Sequence" +msgstr "Нумерация" + +#. module: note +#: view:note.note:0 +#: field:note.note,tag_ids:0 +msgid "Tags" +msgstr "Теги" + +#. module: note +#: view:note.note:0 +msgid "Archive" +msgstr "Архив" + +#. module: note +#: field:base.config.settings,module_note_pad:0 +msgid "Use collaborative pads (etherpad)" +msgstr "Используйте совместный планшет (etherpad)" + +#. module: note +#: help:note.note,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 "" +"Содержит сводку по Чаттеру (количество сообщений,...). Эта сводка в формате " +"html для возможности использования в канбан виде" + +#. module: note +#: field:base.config.settings,group_note_fancy:0 +msgid "Use fancy layouts for notes" +msgstr "" + +#. module: note +#: field:note.note,current_partner_id:0 +#: field:note.stage,user_id:0 +msgid "Owner" +msgstr "Владелец" + +#. module: note +#: help:note.stage,sequence:0 +msgid "Used to order the note stages" +msgstr "Используется для сортировки этапов заметок" + +#. module: note +#: field:note.note,date_done:0 +msgid "Date done" +msgstr "Дата выполнения" + +#. module: note +#: field:note.stage,fold:0 +msgid "Folded by Default" +msgstr "Свернуто по умолчанию" diff --git a/addons/note/note.py b/addons/note/note.py index 2d95b15107a..eb9a6397d18 100644 --- a/addons/note/note.py +++ b/addons/note/note.py @@ -141,12 +141,19 @@ class note_note(osv.osv): #note without user's stage nb_notes_ws = self.search(cr,uid, domain+[('stage_ids', 'not in', current_stage_ids)], context=context, count=True) if nb_notes_ws: - result += [{ #notes for unknown stage and if stage_ids is not empty - '__context': {'group_by': groupby[1:]}, - '__domain': domain + [('stage_ids', 'not in', current_stage_ids)], - 'stage_id': (0, 'Unknown'), - 'stage_id_count':nb_notes_ws - }] + # add note to the first column if it's the first stage + dom_not_in = ('stage_ids', 'not in', current_stage_ids) + if result and result[0]['stage_id'][0] == current_stage_ids[0]: + dom_in = result[0]['__domain'].pop() + result[0]['__domain'] = domain + ['|', dom_in, dom_not_in] + else: + # add the first stage column + result = [{ + '__context': {'group_by': groupby[1:]}, + '__domain': domain + [dom_not_in], + 'stage_id': (current_stage_ids[0], stage_name[current_stage_ids[0]]), + 'stage_id_count':nb_notes_ws + }] + result else: # if stage_ids is empty @@ -156,7 +163,7 @@ class note_note(osv.osv): result = [{ #notes for unknown stage '__context': {'group_by': groupby[1:]}, '__domain': domain, - 'stage_id': (0, 'Unknown'), + 'stage_id': False, 'stage_id_count':nb_notes_ws }] else: @@ -187,9 +194,12 @@ class res_users(osv.Model): model_id = data_obj.get_object_reference(cr, uid, 'base', 'group_user') #Employee Group group_id = model_id and model_id[1] or False if group_id in [x.id for x in user.groups_id]: - for note_xml_id in ['note_stage_01','note_stage_02','note_stage_03','note_stage_04']: - data_id = data_obj._get_id(cr, uid, 'note', note_xml_id) + for note_xml_id in ['note_stage_00','note_stage_01','note_stage_02','note_stage_03','note_stage_04']: + try: + data_id = data_obj._get_id(cr, uid, 'note', note_xml_id) + except ValueError: + continue stage_id = data_obj.browse(cr, uid, data_id, context=context).res_id note_obj.copy(cr, uid, stage_id, default = { 'user_id': user_id}, context=context) - return user_id \ No newline at end of file + return user_id diff --git a/addons/note/note_data.xml b/addons/note/note_data.xml index 592292788b3..376b8e9053f 100644 --- a/addons/note/note_data.xml +++ b/addons/note/note_data.xml @@ -2,6 +2,12 @@ + + New + + + + Today 1 diff --git a/addons/note/note_view.xml b/addons/note/note_view.xml index 49a154d10cc..f3b9e4669c7 100644 --- a/addons/note/note_view.xml +++ b/addons/note/note_view.xml @@ -175,7 +175,7 @@ form kanban,tree,form - {'search_default_open_true':True} + {}

Click to add a personal note. @@ -193,7 +193,7 @@ - + diff --git a/addons/note/security/ir.rule.xml b/addons/note/security/ir.rule.xml index b0c79561355..2c6e9f3bc7f 100644 --- a/addons/note/security/ir.rule.xml +++ b/addons/note/security/ir.rule.xml @@ -3,7 +3,7 @@ Only followers can access a sticky notes - + [('message_follower_ids','=',user.partner_id.id)] @@ -14,7 +14,7 @@ Each user have his stage name - + ['|',('user_id','=',False),('user_id','=',user.id)] diff --git a/addons/note_pad/i18n/lt.po b/addons/note_pad/i18n/lt.po new file mode 100644 index 00000000000..3c814e3f7eb --- /dev/null +++ b/addons/note_pad/i18n/lt.po @@ -0,0 +1,28 @@ +# 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-24 18:32+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-25 05:20+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: note_pad +#: model:ir.model,name:note_pad.model_note_note +msgid "Note" +msgstr "Užrašinė" + +#. module: note_pad +#: field:note.note,note_pad_url:0 +msgid "Pad Url" +msgstr "Nuorodą į užrašinę" diff --git a/addons/pad/pad.py b/addons/pad/pad.py index 90f5354054c..4cd9e91b76e 100644 --- a/addons/pad/pad.py +++ b/addons/pad/pad.py @@ -42,7 +42,7 @@ class pad_common(osv.osv_memory): myPad.createPad(path) #get attr on the field model - model = self.pool.get(context["model"]) + model = self.pool[context["model"]] field = model._all_columns[context['field_name']] real_field = field.column.pad_content_field diff --git a/addons/pad/py_etherpad/__init__.py b/addons/pad/py_etherpad/__init__.py index 6af310b48aa..0db607fe16f 100644 --- a/addons/pad/py_etherpad/__init__.py +++ b/addons/pad/py_etherpad/__init__.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """Module to talk to EtherpadLite API.""" import json diff --git a/addons/pad/static/src/css/etherpad.css b/addons/pad/static/src/css/etherpad.css index ad47be32b02..a0002ebe97c 100644 --- a/addons/pad/static/src/css/etherpad.css +++ b/addons/pad/static/src/css/etherpad.css @@ -43,7 +43,7 @@ z-index: 1000; } -.oe_pad.oe_configured .oe_pad_content.oe_editing{ +.oe_pad .oe_pad_content.oe_editing{ border: solid 1px #c4c4c4; height:500px; -webkit-box-shadow: 0 5px 10px rgba(0,0,0,0.1); @@ -53,7 +53,7 @@ box-shadow: 0 5px 10px rgba(0,0,0,0.1); } -.oe_pad.oe_configured.oe_pad_fullscreen .oe_pad_content { +.oe_pad.oe_pad_fullscreen .oe_pad_content { height: 100%; border: none; -webkit-box-shadow: none; @@ -63,7 +63,7 @@ box-shadow: none; } -.oe_pad.oe_unconfigured > p { +.oe_pad .oe_unconfigured { text-align: center; opacity: 0.75; } diff --git a/addons/pad/static/src/js/pad.js b/addons/pad/static/src/js/pad.js index b96047340ad..ba5ee3a3037 100644 --- a/addons/pad/static/src/js/pad.js +++ b/addons/pad/static/src/js/pad.js @@ -1,67 +1,64 @@ openerp.pad = function(instance) { - instance.web.form.FieldPad = instance.web.form.AbstractField.extend({ + instance.web.form.FieldPad = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeWidgetMixin, { template: 'FieldPad', - configured: false, content: "", - start: function() { - this._super(); - var self = this; - this.on('change:effective_readonly',this,function(){ - self.renderElement(); + init: function() { + this._super.apply(this, arguments); + this.set("configured", true); + this.on("change:configured", this, this.switch_configured); + }, + initialize_content: function() { + var self = this; + this.switch_configured(); + this.$('.oe_pad_switch').click(function() { + self.$el.toggleClass('oe_pad_fullscreen'); }); + this.render_value(); + }, + switch_configured: function() { + this.$(".oe_unconfigured").toggle(! this.get("configured")); + this.$(".oe_configured").toggle(this.get("configured")); }, render_value: function() { - var self = this; - var _super = _.bind(this._super, this); - if (this.get("value") === false || this.get("value") === "") { - self.view.dataset.call('pad_generate_url',{context:{ + var self = this; + if (this.get("configured") && ! this.get("value")) { + self.view.dataset.call('pad_generate_url', { + context: { model: self.view.model, field_name: self.name, object_id: self.view.datarecord.id - }}).done(function(data) { - if(data&&data.url){ - self.set({value: data.url}); - _super(data.url); - self.renderElement(); + }, + }).done(function(data) { + if (! data.url) { + self.set("configured", false); + } else { + self.set("value", data.url); } }); - } else { - self.renderElement(); } - this._dirty_flag = true; - }, - renderElement: function(){ - var self = this; + this.$('.oe_pad_content').html(""); var value = this.get('value'); if (this.pad_loading_request) { this.pad_loading_request.abort(); } - if(!_.str.startsWith(value,'http')){ - this.configured = false; - this.content = ""; - }else{ - this.configured = true; - if(!this.get('effective_readonly')){ - this.content = ''; - }else{ + if (_.str.startsWith(value, 'http')) { + if (! this.get('effective_readonly')) { + var content = ''; + this.$('.oe_pad_content').html(content); + this._dirty_flag = true; + } else { this.content = '

... Loading pad ...
'; - this.pad_loading_request = $.get(value+'/export/html') - .done(function(data){ + this.pad_loading_request = $.get(value + '/export/html').done(function(data) { groups = /\<\s*body\s*\>(.*?)\<\s*\/body\s*\>/.exec(data); data = (groups || []).length >= 2 ? groups[1] : ''; self.$('.oe_pad_content').html('
'); self.$('.oe_pad_readonly').html(data); - }).error(function(){ + }).fail(function() { self.$('.oe_pad_content').text('Unable to load pad'); }); } } - this._super(); - this.$('.oe_pad_content').html(this.content); - this.$('.oe_pad_switch').click(function(){ - self.$el.toggleClass('oe_pad_fullscreen'); - }); }, }); diff --git a/addons/pad/static/src/xml/pad.xml b/addons/pad/static/src/xml/pad.xml index bd3e296f9b3..f915e867b35 100644 --- a/addons/pad/static/src/xml/pad.xml +++ b/addons/pad/static/src/xml/pad.xml @@ -5,32 +5,25 @@ - -
-

- You must configure the etherpad through the menu Settings > Companies > Companies, in the configuration tab of your company. -

-
-
- - +
+

+ You must configure the etherpad through the menu Settings > Companies > Companies, in the configuration tab of your company. +

-
-
-
+
+ +
+ &Ntilde; +
+
+
+
+
+ + - -
-
- &Ntilde; -
-
-
-
-
-
diff --git a/addons/pad_project/i18n/lt.po b/addons/pad_project/i18n/lt.po new file mode 100644 index 00000000000..2f7340a36e2 --- /dev/null +++ b/addons/pad_project/i18n/lt.po @@ -0,0 +1,39 @@ +# 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-24 18:35+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-25 05:20+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: pad_project +#: constraint:project.task:0 +msgid "Error ! Task end-date must be greater then task start-date" +msgstr "" +"Klaida! Užduotės pabaigos data negali būti ankstesnė nei pradžios data" + +#. module: pad_project +#: field:project.task,description_pad:0 +msgid "Description PAD" +msgstr "" + +#. module: pad_project +#: model:ir.model,name:pad_project.model_project_task +msgid "Task" +msgstr "Užduotis" + +#. module: pad_project +#: constraint:project.task:0 +msgid "Error ! You cannot create recursive tasks." +msgstr "Klaida! Negalima sukurti rekursinių užduočių." diff --git a/addons/plugin/i18n/lt.po b/addons/plugin/i18n/lt.po new file mode 100644 index 00000000000..dc120cadcf2 --- /dev/null +++ b/addons/plugin/i18n/lt.po @@ -0,0 +1,23 @@ +# 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-24 18:14+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-25 05:20+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: plugin +#: model:ir.model,name:plugin.model_plugin_handler +msgid "plugin.handler" +msgstr "plugin.handler" diff --git a/addons/plugin/plugin_handler.py b/addons/plugin/plugin_handler.py index f13fc255a6d..fc6c874fab5 100644 --- a/addons/plugin/plugin_handler.py +++ b/addons/plugin/plugin_handler.py @@ -58,7 +58,7 @@ class plugin_handler(osv.osv_memory): res_id = msg.res_id model = msg.model url = self._make_url(cr, uid, res_id, model) - name = self.pool.get(model).name_get(cr, uid, [res_id])[0][1] + name = self.pool[model].name_get(cr, uid, [res_id])[0][1] return (model, res_id, url, name) def document_type(self, cr, uid, context=None): @@ -82,7 +82,7 @@ class plugin_handler(osv.osv_memory): @return : the result of name_search a list of tuple [(id, 'name')] """ - return self.pool.get(model).name_search(cr, uid, name) + return self.pool[model].name_search(cr, uid, name) def push_message(self, cr, uid, model, email, res_id=0): """ @@ -92,7 +92,7 @@ class plugin_handler(osv.osv_memory): @return Dictionary which contain model , url and resource id. """ mail_message = self.pool.get('mail.message') - model_obj = self.pool.get(model) + model_obj = self.pool[model] msg = self.pool.get('mail.thread').message_parse(cr, uid, email) message_id = msg.get('message-id') mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)]) @@ -110,7 +110,7 @@ class plugin_handler(osv.osv_memory): model_obj.message_post(cr, uid, [res_id], body=msg.get('body'), subject=msg.get('subject'), - type='email', + type='comment' if model == 'res.partner' else 'email', parent_id=msg.get('parent_id'), attachments=msg.get('attachments')) notify = _("Mail successfully pushed") diff --git a/addons/plugin_thunderbird/static/thunderbird_plugin/install.sh b/addons/plugin_thunderbird/static/thunderbird_plugin/install.sh index e1103b30acf..5ca7a5a934a 100755 --- a/addons/plugin_thunderbird/static/thunderbird_plugin/install.sh +++ b/addons/plugin_thunderbird/static/thunderbird_plugin/install.sh @@ -1,3 +1,4 @@ +#!/bin/sh make clean make cp ../openerp_plugin.xpi /home/openerp/ diff --git a/addons/point_of_sale/account_bank_statement.py b/addons/point_of_sale/account_bank_statement.py index 31415bb847c..9275b975d46 100644 --- a/addons/point_of_sale/account_bank_statement.py +++ b/addons/point_of_sale/account_bank_statement.py @@ -34,7 +34,6 @@ class account_journal(osv.osv): 'self_checkout_payment_method' : False, } -account_journal() class account_cash_statement(osv.osv): _inherit = 'account.bank.statement' @@ -42,6 +41,5 @@ class account_cash_statement(osv.osv): 'pos_session_id' : fields.many2one('pos.session'), } -account_cash_statement() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/html/index.html b/addons/point_of_sale/html/index.html new file mode 100644 index 00000000000..130806ddb11 --- /dev/null +++ b/addons/point_of_sale/html/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/html/pos_checkout.jpg b/addons/point_of_sale/html/pos_checkout.jpg new file mode 100644 index 00000000000..d87e5b8499d Binary files /dev/null and b/addons/point_of_sale/html/pos_checkout.jpg differ diff --git a/addons/point_of_sale/html/pos_customer_form.png b/addons/point_of_sale/html/pos_customer_form.png new file mode 100644 index 00000000000..4e89d43c4c3 Binary files /dev/null and b/addons/point_of_sale/html/pos_customer_form.png differ diff --git a/addons/point_of_sale/html/pos_customers.png b/addons/point_of_sale/html/pos_customers.png new file mode 100644 index 00000000000..6448074c3d9 Binary files /dev/null and b/addons/point_of_sale/html/pos_customers.png differ diff --git a/addons/point_of_sale/html/pos_devices.png b/addons/point_of_sale/html/pos_devices.png new file mode 100644 index 00000000000..a021a87bfac Binary files /dev/null and b/addons/point_of_sale/html/pos_devices.png differ diff --git a/addons/point_of_sale/html/pos_invoice.png b/addons/point_of_sale/html/pos_invoice.png new file mode 100644 index 00000000000..aae4f6d38a5 Binary files /dev/null and b/addons/point_of_sale/html/pos_invoice.png differ diff --git a/addons/point_of_sale/html/pos_offline.png b/addons/point_of_sale/html/pos_offline.png new file mode 100644 index 00000000000..764cda88e87 Binary files /dev/null and b/addons/point_of_sale/html/pos_offline.png differ diff --git a/addons/point_of_sale/html/pos_product_form.png b/addons/point_of_sale/html/pos_product_form.png new file mode 100644 index 00000000000..a25c85b6496 Binary files /dev/null and b/addons/point_of_sale/html/pos_product_form.png differ diff --git a/addons/point_of_sale/html/pos_products.png b/addons/point_of_sale/html/pos_products.png new file mode 100644 index 00000000000..cbfd054d72e Binary files /dev/null and b/addons/point_of_sale/html/pos_products.png differ diff --git a/addons/point_of_sale/html/pos_sc_01.jpg b/addons/point_of_sale/html/pos_sc_01.jpg new file mode 100644 index 00000000000..8fc97e00672 Binary files /dev/null and b/addons/point_of_sale/html/pos_sc_01.jpg differ diff --git a/addons/point_of_sale/html/pos_sc_02.jpg b/addons/point_of_sale/html/pos_sc_02.jpg new file mode 100644 index 00000000000..d26e0504933 Binary files /dev/null and b/addons/point_of_sale/html/pos_sc_02.jpg differ diff --git a/addons/point_of_sale/html/pos_sc_03.jpg b/addons/point_of_sale/html/pos_sc_03.jpg new file mode 100644 index 00000000000..8eb7e312791 Binary files /dev/null and b/addons/point_of_sale/html/pos_sc_03.jpg differ diff --git a/addons/point_of_sale/html/pos_ui_01.png b/addons/point_of_sale/html/pos_ui_01.png new file mode 100644 index 00000000000..1725f91d6f2 Binary files /dev/null and b/addons/point_of_sale/html/pos_ui_01.png differ diff --git a/addons/point_of_sale/html/pos_ui_02.png b/addons/point_of_sale/html/pos_ui_02.png new file mode 100644 index 00000000000..aa0eb51c0f1 Binary files /dev/null and b/addons/point_of_sale/html/pos_ui_02.png differ diff --git a/addons/point_of_sale/html/pos_ui_03.png b/addons/point_of_sale/html/pos_ui_03.png new file mode 100644 index 00000000000..f25f2a49c00 Binary files /dev/null and b/addons/point_of_sale/html/pos_ui_03.png differ diff --git a/addons/point_of_sale/i18n/pt_BR.po b/addons/point_of_sale/i18n/pt_BR.po index eac24526afc..4d4efabdec3 100644 --- a/addons/point_of_sale/i18n/pt_BR.po +++ b/addons/point_of_sale/i18n/pt_BR.po @@ -7,19 +7,19 @@ 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-10-17 00:01+0000\n" -"Last-Translator: Syllas F. de O. Neto \n" +"PO-Revision-Date: 2013-04-18 18:07+0000\n" +"Last-Translator: Thiago Tognoli \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:07+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-19 05:24+0000\n" +"X-Generator: Launchpad (build 16567)\n" #. module: point_of_sale #: field:report.transaction.pos,product_nb:0 msgid "Product Nb." -msgstr "Produto No." +msgstr "Núm. Produto" #. module: point_of_sale #: model:ir.actions.act_window,name:point_of_sale.action_trans_pos_tree_today @@ -286,7 +286,7 @@ msgstr "Desconto (%)" #: report:pos.details:0 #: report:pos.details_summary:0 msgid "Total discount" -msgstr "Total de Desconto" +msgstr "Desconto total" #. module: point_of_sale #. openerp-web @@ -354,6 +354,9 @@ 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 "" +"Marque esta opção se este ponto de venda deve ser aberto por padrão em modo " +"de auto atendimento. Se não marcada, o OpenERP irá usar o modo normal por " +"padrão." #. module: point_of_sale #: model:ir.actions.report.xml,name:point_of_sale.pos_sales_user @@ -444,7 +447,7 @@ msgstr "Você precisa associar um Ponto de Vendas a sua sessão." #. module: point_of_sale #: view:pos.order.line:0 msgid "Total qty" -msgstr "Total de Qtd" +msgstr "Qtd Total" #. module: point_of_sale #: model:product.template,name:point_of_sale.fanta_orange_33cl_product_template @@ -460,6 +463,10 @@ msgid "" "close this session, you can update the 'Closing Cash Control' to avoid any " "difference." msgstr "" +"Por favor, defina suas contas de lucros e perdas no seu método de pagamento " +"'%s'. Isso permitirá o OpenERP colocar a diferença de %.2f em seu saldo " +"final. Para fechar a sessão, você pode atualizar o 'Fechando Controle de " +"Caixa'para evitar qualquer diferença." #. module: point_of_sale #: code:addons/point_of_sale/point_of_sale.py:315 @@ -777,7 +784,7 @@ msgstr "Imprimir Relatório" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_bolognese_product_template msgid "Dr. Oetker Ristorante Bolognese" -msgstr "" +msgstr "Dr. Oetker Ristorante Bolognese" #. module: point_of_sale #: model:pos.category,name:point_of_sale.pizza @@ -787,7 +794,7 @@ msgstr "Pizza" #. module: point_of_sale #: view:pos.session:0 msgid "= Theoretical Balance" -msgstr "" +msgstr "= Balanço Teórico" #. module: point_of_sale #: code:addons/point_of_sale/wizard/pos_return.py:85 @@ -974,7 +981,7 @@ msgstr "Lista de Caixas Registradoras" #. module: point_of_sale #: model:product.template,name:point_of_sale.maes_50cl_product_template msgid "Maes 50cl" -msgstr "" +msgstr "Maes 50cl" #. module: point_of_sale #: view:report.pos.order:0 @@ -1030,7 +1037,7 @@ msgstr "Spa Reine 33cl" #. module: point_of_sale #: model:ir.model,name:point_of_sale.model_pos_discount msgid "Add a Global Discount" -msgstr "Adicionar Desconto Global" +msgstr "Adicionar um Desconto Global" #. module: point_of_sale #: view:pos.config:0 @@ -1040,7 +1047,7 @@ msgstr "Diários" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_prosciutto_product_template msgid "Dr. Oetker Ristorante Prosciutto" -msgstr "" +msgstr "Dr. Oetker Ristorante Prosciutto" #. module: point_of_sale #: model:product.template,name:point_of_sale.lays_light_paprika_170g_product_template @@ -1126,7 +1133,7 @@ msgstr "Re-impressão" #. module: point_of_sale #: model:product.template,name:point_of_sale.chimay_bleu_75cl_product_template msgid "Chimay Bleu 75cl" -msgstr "" +msgstr "Chimay Bleu 75cl" #. module: point_of_sale #: report:pos.payment.report.user:0 @@ -1156,7 +1163,7 @@ msgstr "No. de Linhas" #: code:addons/point_of_sale/static/src/xml/pos.xml:89 #, python-format msgid "Disc" -msgstr "Disco" +msgstr "Desc." #. module: point_of_sale #: view:pos.order:0 @@ -1166,7 +1173,7 @@ msgstr "(atualizar)" #. module: point_of_sale #: model:product.template,name:point_of_sale.ijsboerke_vanille_2,5l_product_template msgid "IJsboerke Vanilla 2.5L" -msgstr "" +msgstr "IJsboerke Vanilla 2.5L" #. module: point_of_sale #: model:ir.actions.act_window,name:point_of_sale.action_report_pos_details @@ -1177,7 +1184,7 @@ msgstr "Detalhes da Venda" #. module: point_of_sale #: model:product.template,name:point_of_sale.evian_2l_product_template msgid "2L Evian" -msgstr "" +msgstr "2L Evian" #. module: point_of_sale #: code:addons/point_of_sale/point_of_sale.py:373 @@ -1185,7 +1192,7 @@ msgstr "" #: code:addons/point_of_sale/wizard/pos_session_opening.py:34 #, python-format msgid "Start Point Of Sale" -msgstr "" +msgstr "Iniciar Ponto de Venda" #. module: point_of_sale #: model:pos.category,name:point_of_sale.pils @@ -1195,7 +1202,7 @@ msgstr "" #. module: point_of_sale #: help:pos.session,cash_register_balance_end_real:0 msgid "Computed using the cash control lines" -msgstr "" +msgstr "Calculado usando as linhas de controle de caixa" #. module: point_of_sale #: report:all.closed.cashbox.of.the.day:0 @@ -1217,7 +1224,7 @@ 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 "" +msgstr "IJsboerke 2.5L White Lady" #. module: point_of_sale #: field:pos.order,lines:0 @@ -1239,7 +1246,7 @@ msgstr "" #: code:addons/point_of_sale/static/src/xml/pos.xml:485 #, python-format msgid "Read Weighting Scale" -msgstr "" +msgstr "Lendo a Balança" #. module: point_of_sale #. openerp-web @@ -1302,7 +1309,7 @@ msgstr "Marcar como Obsoleto" #. module: point_of_sale #: model:product.template,name:point_of_sale.limon_product_template msgid "Stringers" -msgstr "" +msgstr "Limões" #. module: point_of_sale #: field:pos.order,pricelist_id:0 @@ -1369,19 +1376,19 @@ msgstr "Stella Artois 33cl" #. module: point_of_sale #: model:product.template,name:point_of_sale.lays_naturel_300g_product_template msgid "Lays Natural XXL 300g" -msgstr "" +msgstr "Lays Natural XXL 300g" #. module: point_of_sale #. openerp-web #: code:addons/point_of_sale/static/src/xml/pos.xml:479 #, python-format msgid "Scan Item Unrecognized" -msgstr "" +msgstr "item Escaneado não Reconhecido" #. module: point_of_sale #: report:all.closed.cashbox.of.the.day:0 msgid "Today's Closed Cashbox" -msgstr "Fechamento de Caixa do dia" +msgstr "Fechamento de Caixa do Dia" #. module: point_of_sale #: code:addons/point_of_sale/point_of_sale.py:897 @@ -1397,7 +1404,7 @@ msgstr "Fatura Provisória" #. module: point_of_sale #: model:product.template,name:point_of_sale.lays_paprika_oven_150g_product_template msgid "Oven Baked Lays Paprika 150g" -msgstr "" +msgstr "Oven Baked Lays Paprika 150g" #. module: point_of_sale #: report:pos.invoice:0 @@ -1449,7 +1456,7 @@ msgstr "Coca-Cola Light 2L" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_funghi_product_template msgid "Dr. Oetker Ristorante Funghi" -msgstr "" +msgstr "Dr. Oetker Ristorante Funghi" #. module: point_of_sale #: model:ir.actions.act_window,name:point_of_sale.pos_category_action @@ -1477,7 +1484,7 @@ msgstr "Ean Inválido" #. module: point_of_sale #: model:product.template,name:point_of_sale.lindemans_kriek_37,5cl_product_template msgid "Lindemans Kriek 37.5cl" -msgstr "" +msgstr "Lindemans Kriek 37.5cl" #. module: point_of_sale #: view:pos.config:0 @@ -1494,7 +1501,7 @@ msgstr "Coca-Cola Zero 33cl" #: code:addons/point_of_sale/static/src/xml/pos.xml:405 #, python-format msgid "ä" -msgstr "" +msgstr "ä" #. module: point_of_sale #: report:pos.invoice:0 @@ -1523,7 +1530,7 @@ msgstr "Desconhecido" #. module: point_of_sale #: field:product.product,income_pdt:0 msgid "Point of Sale Cash In" -msgstr "" +msgstr "Colocar dinheiro no Ponto de Venda" #. module: point_of_sale #. openerp-web @@ -1608,7 +1615,7 @@ msgstr "" #. module: point_of_sale #: model:product.template,name:point_of_sale.boon_framboise_37,5cl_product_template msgid "Boon Framboise 37.5cl" -msgstr "" +msgstr "Boon Framboise 37.5cl" #. module: point_of_sale #: model:ir.model,name:point_of_sale.model_pos_config @@ -1627,7 +1634,7 @@ msgstr "" #. module: point_of_sale #: field:product.product,expense_pdt:0 msgid "Point of Sale Cash Out" -msgstr "" +msgstr "Sacar do Ponto de Venda" #. module: point_of_sale #: selection:report.pos.order,month:0 @@ -1639,7 +1646,7 @@ msgstr "Novembro" #: code:addons/point_of_sale/static/src/xml/pos.xml:267 #, python-format msgid "Please scan an item or your member card" -msgstr "" +msgstr "Por favor escaneie um item ou seu cartão de associado" #. module: point_of_sale #: model:product.template,name:point_of_sale.poivron_verts_product_template @@ -1649,7 +1656,7 @@ msgstr "Pimentões Verdes" #. module: point_of_sale #: model:product.template,name:point_of_sale.timmermans_faro_37,5cl_product_template msgid "Timmermans Faro 37.5cl" -msgstr "" +msgstr "Timmermans Faro 37.5cl" #. module: point_of_sale #: code:addons/point_of_sale/point_of_sale.py:410 @@ -1662,7 +1669,7 @@ msgstr "" #. module: point_of_sale #: view:pos.session:0 msgid "Validate Closing & Post Entries" -msgstr "" +msgstr "Validar Encerramento e Lançar Entradas" #. module: point_of_sale #: field:report.transaction.pos,no_trans:0 @@ -1705,7 +1712,7 @@ msgstr "Cancelar" #: code:addons/point_of_sale/static/src/xml/pos.xml:296 #, python-format msgid "Please put your product on the scale" -msgstr "" +msgstr "Por favor, coloque seu produto na balança" #. module: point_of_sale #: model:ir.actions.report.xml,name:point_of_sale.pos_details_summary @@ -1715,12 +1722,12 @@ msgstr "Vendas(Resumo)" #. module: point_of_sale #: model:product.template,name:point_of_sale.nectarine_product_template msgid "Peach" -msgstr "" +msgstr "Pêssego" #. module: point_of_sale #: model:product.template,name:point_of_sale.timmermans_kriek_37,5cl_product_template msgid "Timmermans Kriek 37.5cl" -msgstr "" +msgstr "Timmermans Kriek 37.5cl" #. module: point_of_sale #: field:pos.config,sequence_id:0 @@ -1753,7 +1760,7 @@ msgstr "fechar" #. module: point_of_sale #: model:ir.actions.report.xml,name:point_of_sale.report_user_label msgid "User Labels" -msgstr "" +msgstr "Etiquetas do Usuário" #. module: point_of_sale #: model:ir.model,name:point_of_sale.model_pos_order_line @@ -1897,6 +1904,9 @@ msgid "" "complete\n" " your purchase" msgstr "" +"Por favor, insira seu cartão no leitor e aguarde as instruções para " +"completar\n" +" sua compra" #. module: point_of_sale #: help:product.product,income_pdt:0 @@ -1935,6 +1945,8 @@ msgid "" "Unable to open the session. You have to assign a sale journal to your point " "of sale." msgstr "" +"Não é possível abrir a sessão. Você tem que atribuir um diário de venda para " +"o seu ponto de venda." #. module: point_of_sale #: view:report.pos.order:0 @@ -1988,7 +2000,7 @@ msgstr "Estabelecimento:" #. module: point_of_sale #: field:account.journal,self_checkout_payment_method:0 msgid "Self Checkout Payment Method" -msgstr "" +msgstr "Forma de Pagamento do Auto Atendimento" #. module: point_of_sale #: view:pos.order:0 @@ -2124,7 +2136,7 @@ msgstr "Produtos" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_4formaggi_product_template msgid "Dr. Oetker Ristorante Quattro Formaggi" -msgstr "" +msgstr "Dr. Oetker Ristorante Quattro Formaggi" #. module: point_of_sale #: model:product.template,name:point_of_sale.croky_naturel_45g_product_template @@ -2654,7 +2666,7 @@ msgstr "Fatura" #: code:addons/point_of_sale/static/src/xml/pos.xml:701 #, python-format msgid "shift" -msgstr "" +msgstr "shift" #. module: point_of_sale #: model:product.template,name:point_of_sale.rochefort_8_33cl_product_template @@ -2786,7 +2798,7 @@ msgstr "Produto" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_pollo_product_template msgid "Dr. Oetker Ristorante Pollo" -msgstr "" +msgstr "Dr. Oetker Ristorante Pollo" #. module: point_of_sale #: constraint:pos.session:0 @@ -2836,7 +2848,7 @@ msgstr "" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_margherita_product_template msgid "Dr. Oetker La Margherita" -msgstr "" +msgstr "Dr. Oetker La Margherita" #. module: point_of_sale #: view:pos.order:0 @@ -2936,7 +2948,7 @@ msgstr "Gerente" #. module: point_of_sale #: model:product.template,name:point_of_sale.lays_poivre_sel_oven_150g_product_template msgid "Lays Salt and Pepper Oven Baked 150g" -msgstr "" +msgstr "Lays Salt and Pepper Oven Baked 150g" #. module: point_of_sale #: field:pos.details,date_start:0 @@ -2993,7 +3005,7 @@ msgstr "Procurar Pedido de Venda" #. module: point_of_sale #: field:pos.config,iface_self_checkout:0 msgid "Self Checkout Mode" -msgstr "" +msgstr "Modo de Auto Atendimento" #. module: point_of_sale #: field:account.journal,journal_user:0 @@ -3027,7 +3039,7 @@ msgstr "Relatório de Pagamento" #. module: point_of_sale #: model:product.template,name:point_of_sale.fanta_orange_25cl_product_template msgid "Fanta Orange 25cl" -msgstr "" +msgstr "Fanta Laranja 25cl" #. module: point_of_sale #: view:pos.confirm:0 @@ -3063,7 +3075,7 @@ msgstr "Motivo" #. module: point_of_sale #: model:product.template,name:point_of_sale.orangina_33cl_product_template msgid "Orangina 33cl" -msgstr "" +msgstr "Orangina 33cl" #. module: point_of_sale #: view:pos.config:0 @@ -3073,7 +3085,7 @@ msgstr "Definir como Inativo" #. module: point_of_sale #: model:product.template,name:point_of_sale.chimay_bleu_33cl_product_template msgid "Chimay Bleu 33cl" -msgstr "" +msgstr "Chimay Bleu 33cl" #. module: point_of_sale #: model:ir.actions.act_window,name:point_of_sale.action_account_journal_form @@ -3089,7 +3101,7 @@ msgstr "Fritas" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_spinaci_product_template msgid "Dr. Oetker Ristorante Spinaci" -msgstr "" +msgstr "Dr. Oetker Ristorante Spinaci" #. module: point_of_sale #. openerp-web @@ -3121,7 +3133,7 @@ msgstr "Colocar dinheiro em" #. module: point_of_sale #: model:product.template,name:point_of_sale.fanta_zero_orange_1,5l_product_template msgid "Fanta Orange Zero 1.5L" -msgstr "" +msgstr "Fanta Laranja Zero 1.5L" #. module: point_of_sale #: model:product.template,name:point_of_sale.boni_orange_product_template @@ -3234,7 +3246,7 @@ msgstr "Relatório do PDV" #. module: point_of_sale #: model:product.template,name:point_of_sale.chaudfontaine_1,5l_product_template msgid "Chaudfontaine 1.5l" -msgstr "" +msgstr "Chaudfontaine 1.5l" #. module: point_of_sale #: code:addons/point_of_sale/point_of_sale.py:1069 @@ -3304,7 +3316,7 @@ msgstr "Coca-Cola Zero 50cl" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_tonno_product_template msgid "Dr. Oetker Ristorante Tonno" -msgstr "" +msgstr "Dr. Oetker Ristorante Tonno" #. module: point_of_sale #: report:pos.invoice:0 @@ -3346,7 +3358,7 @@ msgstr "cash.box.out" #. module: point_of_sale #: model:product.template,name:point_of_sale.fanta_zero_orange_33cl_product_template msgid "Fanta Zero Orange 33cl" -msgstr "" +msgstr "Fanta Laranja Zero 33cl" #. module: point_of_sale #: help:product.product,available_in_pos:0 @@ -3361,7 +3373,7 @@ msgstr "Dia da data do pedido" #. module: point_of_sale #: model:product.template,name:point_of_sale.maes_33cl_product_template msgid "Maes 33cl" -msgstr "" +msgstr "Maes 33cl" #. module: point_of_sale #. openerp-web @@ -3378,7 +3390,7 @@ msgstr "Configuração" #. module: point_of_sale #: model:product.template,name:point_of_sale.orval_33cl_product_template msgid "Orval 33cl" -msgstr "" +msgstr "Orval 33cl" #. module: point_of_sale #. openerp-web @@ -3411,7 +3423,7 @@ msgstr "Frutas Frescas" #. module: point_of_sale #: model:product.template,name:point_of_sale.lindemans_pecheresse_37,,5cl_product_template msgid "Lindemans sinful 37.5cl" -msgstr "" +msgstr "Lindemans sinful 37.5cl" #. module: point_of_sale #: model:ir.actions.act_window,name:point_of_sale.action_pos_invoice @@ -3431,7 +3443,7 @@ msgstr "Imagem" #. module: point_of_sale #: model:product.template,name:point_of_sale.spa_gazeuse_1,5l_product_template msgid "Spa Barisart 1.5l" -msgstr "" +msgstr "Spa Barisart 1.5l" #. module: point_of_sale #: code:addons/point_of_sale/point_of_sale.py:789 @@ -3443,7 +3455,7 @@ msgstr "Retornar Produtos" #. module: point_of_sale #: model:product.template,name:point_of_sale.jupiler_33cl_product_template msgid "Jupiler 33cl" -msgstr "" +msgstr "Jupiler 33cl" #. module: point_of_sale #. openerp-web @@ -3551,7 +3563,7 @@ msgstr "Balança Eletrônica" #. module: point_of_sale #: model:product.template,name:point_of_sale.spa_gazeuse_50cl_product_template msgid "Spa Barisart 50cl" -msgstr "" +msgstr "Spa Barisart 50cl" #. module: point_of_sale #: field:res.users,pos_config:0 @@ -3595,7 +3607,7 @@ msgstr "Pago" #: code:addons/point_of_sale/static/src/xml/pos.xml:464 #, python-format msgid "3.141Kg Oranges" -msgstr "" +msgstr "3.141Kg de Laranjas" #. module: point_of_sale #: report:pos.invoice:0 @@ -3611,7 +3623,7 @@ msgstr "Por favor informe um parceiro para a venda" #. module: point_of_sale #: model:pos.category,name:point_of_sale.fruity_beers msgid "Fruity Beers" -msgstr "" +msgstr "Cerveja de Frutas" #. module: point_of_sale #: view:pos.session:0 @@ -3623,7 +3635,7 @@ msgstr "" #: code:addons/point_of_sale/static/src/xml/pos.xml:463 #, python-format msgid "Soda 33cl" -msgstr "" +msgstr "Soda 33cl" #. module: point_of_sale #: help:pos.session,cash_register_balance_start:0 @@ -3644,7 +3656,7 @@ msgstr "Vendas do Usuário" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_hawaii_product_template msgid "Dr. Oetker Ristorante Hawaii" -msgstr "" +msgstr "Dr. Oetker Ristorante Hawaii" #. module: point_of_sale #. openerp-web @@ -3678,12 +3690,12 @@ msgstr "" #. module: point_of_sale #: model:product.template,name:point_of_sale.chaudfontaine_petillante_33cl_product_template msgid "Chaudfontaine Petillante 33cl" -msgstr "" +msgstr "Chaudfontaine Petillante 33cl" #. module: point_of_sale #: model:product.template,name:point_of_sale.pepsi_max_2l_product_template msgid "Pepsi Max 2L" -msgstr "" +msgstr "Pepsi Max 2L" #. module: point_of_sale #: field:pos.session,details_ids:0 @@ -3693,17 +3705,17 @@ msgstr "Controle de Caixa" #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_vegetale_product_template msgid "Dr. Oetker Ristorante Vegetable" -msgstr "" +msgstr "Dr. Oetker Ristorante Vegetable" #. module: point_of_sale #: model:pos.category,name:point_of_sale.soda msgid "Soda" -msgstr "" +msgstr "Soda" #. module: point_of_sale #: model:product.template,name:point_of_sale.lays_paprika_300g_product_template msgid "Lays Paprika XXL 300g" -msgstr "" +msgstr "Lays Paprika XXL 300g" #. module: point_of_sale #: report:pos.invoice:0 @@ -3715,7 +3727,7 @@ msgstr "Reembolso" #: code:addons/point_of_sale/static/src/xml/pos.xml:417 #, python-format msgid "Your shopping cart is empty" -msgstr "" +msgstr "Seu Carrinho de Compras está vazio" #. module: point_of_sale #: code:addons/point_of_sale/report/pos_invoice.py:46 @@ -3726,7 +3738,7 @@ msgstr "Por favor crie uma fatura para esta venda." #. module: point_of_sale #: model:product.template,name:point_of_sale.oetker_mozzarella_product_template msgid "Dr. Oetker Ristorante Mozzarella" -msgstr "" +msgstr "Dr. Oetker Ristorante Mozzarella" #. module: point_of_sale #: report:pos.details:0 @@ -3737,7 +3749,7 @@ msgstr "Desc(%)" #. module: point_of_sale #: view:pos.session.opening:0 msgid "The session" -msgstr "" +msgstr "A sessão" #. module: point_of_sale #: view:pos.order:0 @@ -3762,7 +3774,7 @@ msgstr "Ordem de Linhas" #. module: point_of_sale #: view:pos.session.opening:0 msgid "PoS Session Opening" -msgstr "" +msgstr "Abrindo Sessão do PDV" #. module: point_of_sale #: field:pos.order.line,price_subtotal:0 @@ -3780,7 +3792,7 @@ msgstr "excluir" #. module: point_of_sale #: model:product.template,name:point_of_sale.spa_50cl_product_template msgid "Spa Reine 50cl" -msgstr "" +msgstr "Spa Reine 50cl" #. module: point_of_sale #: model:product.template,name:point_of_sale.chicon_flandria_extra_product_template @@ -3791,22 +3803,22 @@ msgstr "" #: model:product.template,name:point_of_sale.lays_light_naturel_170g_product_template #: model:product.template,name:point_of_sale.lays_naturel_170g_product_template msgid "Lays Natural Light 170g" -msgstr "" +msgstr "Lays Natural Light 170g" #. module: point_of_sale #: model:product.template,name:point_of_sale.leffe_blonde_33cl_product_template msgid "Leffe Blonde 33cl" -msgstr "" +msgstr "Leffe Blonde 33cl" #. module: point_of_sale #: model:ir.actions.act_window,name:point_of_sale.action_report_pos_payment msgid "Pyament Report" -msgstr "" +msgstr "Relatório de Pagamento" #. module: point_of_sale #: field:report.transaction.pos,jl_id:0 msgid "Cash Journals" -msgstr "" +msgstr "Diários de Dinheiro" #. module: point_of_sale #: view:pos.session:0 @@ -3816,12 +3828,12 @@ msgstr "Sessão:" #. module: point_of_sale #: field:pos.config,iface_print_via_proxy:0 msgid "Print via Proxy" -msgstr "" +msgstr "Imprimir via Proxy" #. module: point_of_sale #: report:pos.sales.user.today:0 msgid "Today's Sales By User" -msgstr "" +msgstr "Vendas de hoje por Usuário" #. module: point_of_sale #: report:pos.invoice:0 @@ -3858,7 +3870,7 @@ msgstr "Anotações Internas" #. module: point_of_sale #: model:product.template,name:point_of_sale.ijsboerke_chocolat_2,5l_product_template msgid "IJsboerke Chocolat 2.5L" -msgstr "" +msgstr "IJsboerke Chocolat 2.5L" #. module: point_of_sale #: help:pos.category,image_small:0 @@ -3871,7 +3883,7 @@ msgstr "" #. module: point_of_sale #: field:pos.session.opening,pos_state:0 msgid "Session Status" -msgstr "" +msgstr "Status da Sessão" #. module: point_of_sale #: field:pos.order,picking_id:0 @@ -3915,7 +3927,7 @@ msgstr "Editar" #. module: point_of_sale #: view:pos.session.opening:0 msgid "Click to continue the session." -msgstr "" +msgstr "Clique para continuar a sessão." #. module: point_of_sale #: view:pos.config:0 @@ -3930,7 +3942,7 @@ msgstr "" #. module: point_of_sale #: view:pos.session.opening:0 msgid "Start Selling" -msgstr "" +msgstr "Começar a Vender" #. module: point_of_sale #: selection:report.pos.order,month:0 @@ -3963,7 +3975,7 @@ msgstr "" #. module: point_of_sale #: model:product.template,name:point_of_sale.leffe_9_33cl_product_template msgid "Leffe Brune \"9\" 33cl" -msgstr "" +msgstr "Leffe Brune \"9\" 33cl" #. module: point_of_sale #: help:account.journal,journal_user:0 @@ -4011,7 +4023,7 @@ msgstr "" #: code:addons/point_of_sale/static/src/xml/pos.xml:351 #, python-format msgid "Sorry, we could not create a session for this user." -msgstr "" +msgstr "Desculpe, não podemos criar uma sessão para esse usuário." #. module: point_of_sale #: code:addons/point_of_sale/point_of_sale.py:98 @@ -4019,7 +4031,7 @@ msgstr "" #: selection:pos.session.opening,pos_state:0 #, python-format msgid "Opening Control" -msgstr "" +msgstr "Abrindo Controle" #. module: point_of_sale #: view:report.pos.order:0 diff --git a/addons/point_of_sale/i18n/zh_CN.po b/addons/point_of_sale/i18n/zh_CN.po index e4d914ae56e..23dc97f2376 100644 --- a/addons/point_of_sale/i18n/zh_CN.po +++ b/addons/point_of_sale/i18n/zh_CN.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:04+0000\n" -"PO-Revision-Date: 2012-05-10 18:26+0000\n" -"Last-Translator: 开阖软件 Jeff Wang \n" +"PO-Revision-Date: 2013-04-24 06:41+0000\n" +"Last-Translator: viney \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:07+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-25 05:20+0000\n" +"X-Generator: Launchpad (build 16580)\n" #. module: point_of_sale #: field:report.transaction.pos,product_nb:0 @@ -67,7 +67,7 @@ msgstr "" #. module: point_of_sale #: model:pos.category,name:point_of_sale.plain_water msgid "Plain Water" -msgstr "白开水" +msgstr "纯净水" #. module: point_of_sale #: model:product.template,name:point_of_sale.poire_conference_product_template @@ -2269,7 +2269,7 @@ msgstr "7月" #: model:ir.ui.menu,name:point_of_sale.menu_pos_config_pos #: view:pos.session:0 msgid "Point of Sales" -msgstr "" +msgstr "零售" #. module: point_of_sale #: report:pos.details:0 @@ -2303,7 +2303,7 @@ msgstr "打印数" #. module: point_of_sale #: model:ir.model,name:point_of_sale.model_pos_make_payment msgid "Point of Sale Payment" -msgstr "POS付款" +msgstr "付款" #. module: point_of_sale #: model:product.template,name:point_of_sale.coca_light_50cl_product_template @@ -2407,7 +2407,7 @@ msgstr "" #. module: point_of_sale #: model:ir.model,name:point_of_sale.model_pos_receipt msgid "Point of sale receipt" -msgstr "POS收银条" +msgstr "收银条" #. module: point_of_sale #: model:ir.actions.act_window,name:point_of_sale.action_report_sales_by_margin_pos_today diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 7e8487b2b2b..089c577e940 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -50,7 +50,7 @@ class pos_config(osv.osv): required=True, help="An internal identification of the point of sale"), 'journal_ids' : fields.many2many('account.journal', 'pos_config_journal_rel', 'pos_config_id', 'journal_id', 'Available Payment Methods', - domain="[('journal_user', '=', True )]",), + domain="[('journal_user', '=', True ), ('type', 'in', ['bank', 'cash'])]",), 'shop_id' : fields.many2one('sale.shop', 'Shop', required=True), 'journal_id' : fields.many2one('account.journal', 'Sale Journal', @@ -407,7 +407,10 @@ class pos_session(osv.osv): # The pos manager can close statements with maximums. if not self.pool.get('ir.model.access').check_groups(cr, uid, "point_of_sale.group_pos_manager"): raise osv.except_osv( _('Error!'), - _("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.") % (st.difference, st.journal_id.amount_authorized_diff)) + _("Your ending balance is too different from the theoretical cash closing (%.2f), the maximum allowed is: %.2f. You can contact your manager to force it.") % (st.difference, st.journal_id.amount_authorized_diff)) + if (st.journal_id.type not in ['bank', 'cash']): + raise osv.except_osv(_('Error!'), + _("The type of the journal for your payment method should be bank or cash ")) if st.difference and st.journal_id.cash_control == True: if st.difference > 0.0: name= _('Point of Sale Profit') @@ -428,7 +431,6 @@ class pos_session(osv.osv): if st.journal_id.type == 'bank': st.write({'balance_end_real' : st.balance_end}) - getattr(st, 'button_confirm_%s' % st.journal_id.type)(context=context) self._confirm_orders(cr, uid, ids, context=context) self.write(cr, uid, ids, {'state' : 'closed'}, context=context) @@ -522,10 +524,28 @@ class pos_order(osv.osv): self.signal_paid(cr, uid, [order_id]) return order_ids + def write(self, cr, uid, ids, vals, context=None): + res = super(pos_order, self).write(cr, uid, ids, vals, context=context) + #If you change the partner of the PoS order, change also the partner of the associated bank statement lines + partner_obj = self.pool.get('res.partner') + bsl_obj = self.pool.get("account.bank.statement.line") + if 'partner_id' in vals: + for posorder in self.browse(cr, uid, ids, context=context): + if posorder.invoice_id: + raise osv.except_osv( _('Error!'), _("You cannot change the partner of a POS order for which an invoice has already been issued.")) + if vals['partner_id']: + p_id = partner_obj.browse(cr, uid, vals['partner_id'], context=context) + part_id = partner_obj._find_accounting_partner(p_id).id + else: + part_id = False + bsl_ids = [x.id for x in posorder.statement_ids] + bsl_obj.write(cr, uid, bsl_ids, {'partner_id': part_id}, context=context) + return res + def unlink(self, cr, uid, ids, context=None): for rec in self.browse(cr, uid, ids, context=context): if rec.state not in ('draft','cancel'): - raise osv.except_osv(_('Unable to Delete !'), _('In order to delete a sale, it must be new or cancelled.')) + raise osv.except_osv(_('Unable to Delete!'), _('In order to delete a sale, it must be new or cancelled.')) return super(pos_order, self).unlink(cr, uid, ids, context=context) def onchange_partner_id(self, cr, uid, ids, part=False, context=None): @@ -886,6 +906,7 @@ class pos_order(osv.osv): account_tax_obj = self.pool.get('account.tax') user_proxy = self.pool.get('res.users') property_obj = self.pool.get('ir.property') + cur_obj = self.pool.get('res.currency') period = account_period_obj.find(cr, uid, context=context)[0] @@ -948,9 +969,9 @@ class pos_order(osv.osv): }) if data_type == 'product': - key = ('product', values['product_id'],) + key = ('product', values['partner_id'], values['product_id']) elif data_type == 'tax': - key = ('tax', values['tax_code_id'],) + key = ('tax', values['partner_id'], values['tax_code_id'],) elif data_type == 'counter_part': key = ('counter_part', values['partner_id'], values['account_id']) else: @@ -981,17 +1002,19 @@ class pos_order(osv.osv): #TOFIX: a deep refactoring of this method (and class!) is needed in order to get rid of this stupid hack assert order.lines, _('The POS order must have lines when calling this method') # Create an move for each order line + + cur = order.pricelist_id.currency_id for line in order.lines: tax_amount = 0 taxes = [t for t in line.product_id.taxes_id] computed_taxes = account_tax_obj.compute_all(cr, uid, taxes, line.price_unit * (100.0-line.discount) / 100.0, line.qty)['taxes'] for tax in computed_taxes: - tax_amount += round(tax['amount'], 2) + tax_amount += cur_obj.round(cr, uid, cur, tax['amount']) group_key = (tax['tax_code_id'], tax['base_code_id'], tax['account_collected_id'], tax['id']) group_tax.setdefault(group_key, 0) - group_tax[group_key] += round(tax['amount'], 2) + group_tax[group_key] += cur_obj.round(cr, uid, cur, tax['amount']) amount = line.price_subtotal @@ -1026,7 +1049,7 @@ class pos_order(osv.osv): 'debit': ((amount<0) and -amount) or 0.0, 'tax_code_id': tax_code_id, 'tax_amount': tax_amount, - 'partner_id': order.partner_id and order.partner_id.id or False + 'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False }) # For each remaining tax with a code, whe create a move line @@ -1044,6 +1067,7 @@ class pos_order(osv.osv): 'debit': 0.0, 'tax_code_id': tax_code_id, 'tax_amount': tax_amount, + 'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False }) # Create a move for each tax group @@ -1060,6 +1084,7 @@ class pos_order(osv.osv): 'debit': ((tax_amount<0) and -tax_amount) or 0.0, 'tax_code_id': key[tax_code_pos], 'tax_amount': tax_amount, + 'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False }) # counterpart @@ -1068,14 +1093,17 @@ class pos_order(osv.osv): 'account_id': order_account, 'credit': ((order.amount_total < 0) and -order.amount_total) or 0.0, 'debit': ((order.amount_total > 0) and order.amount_total) or 0.0, - 'partner_id': order.partner_id and order.partner_id.id or False + 'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False }) order.write({'state':'done', 'account_move': move_id}) + all_lines = [] for group_key, group_data in grouped_data.iteritems(): for value in group_data: - account_move_line_obj.create(cr, uid, value, context=context) + all_lines.append((0, 0, value),) + if move_id: #In case no order was changed + self.pool.get("account.move").write(cr, uid, [move_id], {'line_id':all_lines}, context=context) return True @@ -1103,7 +1131,6 @@ class account_bank_statement(osv.osv): _defaults = { 'user_id': lambda self,cr,uid,c={}: uid } -account_bank_statement() class account_bank_statement_line(osv.osv): _inherit = 'account.bank.statement.line' @@ -1111,7 +1138,6 @@ class account_bank_statement_line(osv.osv): 'pos_statement_id': fields.many2one('pos.order', ondelete='cascade'), } -account_bank_statement_line() class pos_order_line(osv.osv): _name = "pos.order.line" @@ -1137,7 +1163,7 @@ class pos_order_line(osv.osv): if not product_id: return {} if not pricelist: - raise osv.except_osv(_('No Pricelist !'), + raise osv.except_osv(_('No Pricelist!'), _('You have to select a pricelist in the sale form !\n' \ 'Please set one before choosing a product.')) @@ -1279,7 +1305,7 @@ class ean_wizard(osv.osv_memory): ean13 = openerp.addons.product.product.sanitize_ean13(r.ean13_pattern) m = context.get('active_model') m_id = context.get('active_id') - self.pool.get(m).write(cr,uid,[m_id],{'ean13':ean13}) + self.pool[m].write(cr,uid,[m_id],{'ean13':ean13}) return { 'type' : 'ir.actions.act_window_close' } class product_product(osv.osv): diff --git a/addons/point_of_sale/point_of_sale_demo.xml b/addons/point_of_sale/point_of_sale_demo.xml index 011c6d81bfc..1c61218a4cb 100644 --- a/addons/point_of_sale/point_of_sale_demo.xml +++ b/addons/point_of_sale/point_of_sale_demo.xml @@ -430,6 +430,7 @@ True 1.49 Coca-Cola Regular 1L + 5449000054227 /9j/4AAQSkZJRgABAAEBLAEsAAD/2wCEAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9PjsBCwoKDg0OHBYWHCgoKCgoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O//AABEIAGQAIgMBEQACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APZqYHHfEPXNS0W3sjp0zRGUvvKqD0246g+tc+InKNrHqZVhaVdy5+ljlPCfjPxBf65aW1xevLFJOqOCi8gn6cVnGrPnSPRxuW4elRlJLWx65XWfNENusizXJcMFaUFMngjYo4+Y8ZB7L34/iKW7NKjTjG3b9X5L9fXopqozMPX9Kt9YvtPtp9+AZHbbj7oA9fcrUyipbmtGvOldxdjPPhPS9G1PT7q2EiKbkK3Ixkqdp4H97ApKnFO9jWpja1SNpSOsqzlCgAoArwx77mS6JyGUJH7KOSfxP8hSAW9thd2rRZ2tkMjf3WByp/AgUASROZIwxG1v4l9D3FAD6YHLeN/FqeHFsLSMj7VqMxRSULhEAyzFQRnqB17+1IaKUnjCyaBmHiSOHaMk+SqY/wC+gaGmBHY+NLCWUr/wlUE5AztAjb/0FaSuN2J7PxvAfFNnpj3Kzw3yskcyxFMSDkAknnIyBxT2EdnTEeQ/EzzW8eRSNG7Rw6avl4GQCXbd+PSlzJM1jRqShzJNo4TVZlawmRchihzuBH86pmRz+hXH2bUN57rjHryKSA7RLl7i805rdJfNivoJI2CHghx/TNKTRpCnOeyufQtMzPMvH8ck3jWyjQqubQl2Y4CqNxJPsAP0rlrrmkkfSZI4xw1RvuvvOQ1jRb2S58mGzmmQkKD5RBZiM4xzyKy5ZR0R69OthpQvNxKFt4fZIvtV1ss4wCy7kyzD1A9O2TjJ49cP3t2yFKgp8sIJv5HQabZJb+INMiNys7M+4IsZXCkcE5789O1OEUpIxxc+fC1Go2S8/P8AI9rrtPjThvFMFtc+Kmha4SC+axQ2pkfarne+VyQQD909OcVhUScj2MvlOFHmSvHm1t6b/mcnfalqOk2k8F9ptxb3e3y0meMMm3LHgjA6uemRwOOKxcnFao9inh6NealCacd7Xs+nr28iD/hINMnu/Mj0ySaNGjWNTCPljHDLwTzjAB7jPAycnPG+wLA1oxs5pb9evQ07RpNV8R6fcxyQxrEwHkyTqZXy3zPtHT6HFVH3pI5sRy0MJOLTd+ttF2V2epW/2jz7rzs+X5o8jgfc2Lnp/tbuvP4YrojzXd++n3L9bnztTk5Ycu9tfW7/AEtt+Z458X9Xaw8ZRwTQxvFLYIUZs5U73yQR9KmpT5zuy7M3hNLO1+hx8fim5ih2pqF1GmMbUnOPyBrH2NRdT2f7Wy+erhr5pFV9eS4bDzyyn/bJP86n2M2aRznBw2/I2YPFLat4u0JIIFidbi3t9qvnOJBzxxznpWypu6b6Hj1MypqjOnFN8zbu/P7z6Lrc8c8S/aBtNuoaLegf6yKWIn/dKkf+hGkB5ZkGIY9KBobH1pgdJ8NLM6h8SdJTGRHMZT7bFLD9QKQj6epgeQftAzxCy0W3JBmMkrj2UBQf1I/KkB44n+pH0oGgi5NAHafBiWKL4jQLKQGkglVM/wB7Gf5A0CPo6mB4P8ab42/jy286FZol09Aqt2y75IpDOEuZ7CaycwwBJCOMKP6UwKWnNCs5NwhdMdMZ7ikgOi8J3UMnjrQ/sNsIdt/EC4PJBYAj8iaGB9PUxHkXx50Ca4srDXYI2cWxaCcgZ2q3Kk+2cj8RSYHj39najb6d/aD2c62bSeWJmjIRm54DdCeDQncbTTG2lle6iJhY2k0/kx+ZL5SFiq5AycdByKLgdr8H9BuNS8ZwXJhb7PYjzpHK8A4+UZ9SSD9AaSdxuLW59F1RIjKrqVdQykYIIyDQBR1nRNP13SJdL1C3EtrKACg4xjkEEdCKTApeGPBuieEYpk0i2MZuGBkd3LscdBk9vb3oSA2Y4YoQwijSPcdzbVAyfU0wH0AA/9k= @@ -716,6 +717,7 @@ True 0.44 + 5449000111715 Chaudfontaine 50cl /9j/4AAQSkZJRgABAAEBLAEsAAD/2wCEAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9PjsBCwoKDg0OHBYWHCgoKCgoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O//AABEIAGQAJAMBEQACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APZqYHnfj34gaj4a1xdPtYU8vyVkLkckkn1+ld2EwsKsbswq1XF2Oa/4XBqwmUxwqVHVWAwf6/rXQ8DTSIVeVz2KxuGurC3uGXa0sSuR6EjNeVJWbR0rYnpDCgDjvFfhCw8Qaul1PJIJEiEeF6dSR05712Yau6cLW6nLXg5S0ZjS/DLS127pJl7jk5/Umt/rjfQy9jJPc9Ht0WK3jjQ5VVAB9gK8x7neh9AEVxN5SD1PApxVxN2M6Kzja5EsjMxJyd2TWzm7GSpJu5NfWkE6qehHGRkVMJtDnTUh1o/kAQlmYE8Fj0pT11Kh7uheFZllG/fFzChHBBOffitILRkyeqEQ9xxTAVizD5jxRawEEj7GTC7jvUYzzyadrkt2NWsTQp34O6I4yMkGrh1JkInTjiqBDj065pAQMf38YC/xin0F1NIVkWUdVuBbQxOy5UyYJ/u8HmtKUeZsipLlRQj1WFpBGJV3HoCwAP0zWrpSS2M1VVy5HOZc8AAdwwNQ1YtSuRifddQBFMgdyCw6LgHn9KbjowUtUaorA0KGsqr2O1hkFhWtF+8Z1fhOM8Q38+lWEUtoUWR5QnIz8pB/wr08LSjVk1LscdRuK0LHhi9uzqd7b3dzHMsUalWRcA5J/wAKjFwhyRcVbU0otxk02dJFJvvIdvIyc4PHSuGStFnRF3ZrVgaFLVl3WWP9qtKPxGdX4Th/Elk11p8fzJEsEnms7HBAAPAHfqK9TCVFGb63VjkqQukL4fkeTxDqIJP3IhyMdvTJ/nRiElRh8xxbdRnWWg/02PA9ea86psdNPc2KwNSrqS7rNuM4NXS+Iip8JwvimSKKxhMi7gJRhcZ5wSMj0yK9XBpuTt2OOrbQk8NKy+JNRXbjbHFngZ6Z55NTiv4EPVl0v4jOsgx9uiA9D0rz5fCzoW5qViaFe9lSKEbj944qoK7Jk0jkvFGmTahZW4trbzylwruowCVwc9cZ/OvQwdZU5O7toc1aDklZdSPwxp99aahfXN5bvH5qxhS5zkgHOOTxVYurCUIqL2uFGMlJto6W3KLex5IBOQAK4ZX5WbppM1KxNDP1faYUDlQuTkscCtKZnUa6meiyKoUF9o7A5qxaj2LqNyll/wA+9AbDLfbFfRscb5HHfJNNq8WSnaR0Fc5uVdRhaa3wq7sHp61dN2ZM1dGBftLDAipByuemRg4rqppNnJVbtYjmYyuskI81VOMEkD8hjNacqWj0MeZ3utTWsIJXlVzEyqDksx61y1Gl1Oyld62NesDcOtAAQD1FAAFA6AUBYKACgAD/2Q== @@ -830,6 +832,7 @@ True 0.77 + 5410228142027 Jupiler 33cl /9j/4AAQSkZJRgABAAEBLAEsAAD/2wCEAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9PjsBCwoKDg0OHBYWHCgoKCgoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O//AABEIAGQAPQMBEQACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APZqYGdqet2+myJE6tJK4yFXgAepNACJqrPD5reTEvbc+aVwKU2vyR7mDx7FOCxUj+dMC3Z61bzxF5LuFAOu4hcfnQBZmv444fNSSKVc4+Vuv40gH2l7Hdq20FXX7yt1FMCduq/X+hrCs7Tp6/a/9tf9df1TXUWtxHlnjvxjFDrotYbWG6jiUBw5Iyc+oNc1XEckrI9vA5OsRS5pNrsT6ZrM2q2izw6LdqgGP9HuQR+RIq41m1sYYjK1Slb2i+af/BM+58UwaTcukkWqW7scssipyfzxSdeK3TFDJ681eLi/n/wCH/hOLa/22wtbmY9gIkGfxzmhYiL2uOWT14q7cV/XoQax4pvbWJ3fT3O8/wDLWXp+A/xode3QKWVqb1kbPwv8YG/1G6sL3y0lmw0RGecdsk06VXm3IxuCVGKcT05vvJ9f6GprtKdP/F/7bLz/AM/TqvPWzKmsySQ6PdyRNtdYjg1tLYuik6kU+58838N4buSW5Us7sSWHIry5KV9T7yg6fIlE9M8JXsen+H4kKHcFy2EJH5gV2UmlE+fzCnKdZtHCeM9QF/rDPECwAxjpzWNWze56GB56VKzgzM0afyNRjlcbcHpmpgkpbmuIc50n7up0Wul9TtnjghZnK/KAh6/lW7SaPLp88HrZfMx9K8O+ILO4g1EW0losci/vJPl6kDp170owknew8RiqDg4tpu3Q+homZoYWJySASfXitat+aFv5v/bX56/j3t1Xz3cr60M6Ld/9cjWstmXQ/iR9TxS6P71vrXDI+upbGTqSkBJF4PQkVnJaHXRe6MwmoNGy3owDa7YqwyDcICD3+YVrRXvo4ce2qEj2Hw8Uj8L6YzFUBtYuTxztFejT+Beh8ljP48/8T/Mi190bTmQMCyzRbh6fOKU/hIpb/I7WH/UQf7o/lWVX46f+L/21+f8An6dVK6kGsDOkXQ/6ZGtpbF0vjXqeXaZ4f1K71CC7TTftNoJfnDFQrKDg9T9a5I05N3sfQVcZShTceazsdhqWhaBoqTakdKNwXQQpaxoH3seyqe5/kK6lSgnseJLHYiUbOTOZ8PQ21zo+owaX4PvLO8jjkMU2pxKMyH7qhm5wM+nQeppRpQjsgqY7EVLc02YGl/D3xDY6nZzSwR+XDKjM3nKTgEZNYRoz57nq1cwoPDezTbdkburo1z8MrAQW0106Jb/u4SQxKldwyBkdDz2rpirRR4uIkp1pNbNsWHUtW1Pw9LcarZRWZNxH5KRybyU3DknJ759OlKfwip7v0PUIR+4i/wB0fyqZptxt3/R+a/X06qSDVf8AkFXX/XI/yq5bFU/jXqeY6tPdJHYQQ3j2sCWrSyuHKqo8x8scdew9+BXM1JtJHuUp0qcJzmk9f0RVXSfEGsWC3OnWV89rIuY557tAz88OEJ4/M8d619k0tGcX1+M5WcUtdLLb17nHajNr2l3T292buKVeShmYE/nXLKLT1bR7sainDmjTjJeVv1sbPgDWLyfxbaRS3VwyP5iPHJITg7CeQT64rSkpRqJNnBjJUK+EnKEbNNdLNanRatb3E3w/ms4LaW4KX8kbwxEgui3DZGe3A611vY+e6lLw1Hcx+D5Eu3jEsd1FGIo5Ffy1XbgEgnBPJx71MvhNIbv0PYoT+4i91H8qUpNOPm/0ZJDqn/ILuf8Ark38qp7Dh8SPJ/EsTXel2VvE+17tUtwScLxLITk+nCn8Kzprr5HbjJWjy/3r/gjF/wCElN5pVroOq2Yc2JKQXK3PkFAOMHPB6Y5x0FanCVNZ8aXceiadp+o6ba3v+jbkmuA/nINzAHII4KhSCRzU1KfMjpweKeHldX+T/wCAxvw/lF740tLhE27mAK5zjbERn8cGs7WlFHWqiqUa89rtafM3NY0qLUXurlrPUrsxySukMEmyJs3Eg5O089z7YrZnlFvQ7c23hSbdY21mjXiYjgm80nkZ3NuPze3H0qJfCaQ+J+h69EMwxc9FB/SpnTcpRd9nf8GvluRfcS72/ZJdy7l2HK+taivY8f8AEjJNbQadE2xlvrhY+efu/uxn/eJH41nT6rzO3Gp+4+8UcncPZalCj30/2K8OS8phJSYdmOOQ3XoMHj3NaI4zIuYF1rWb+5UMIHaTyAeMsQxjTH0XAHtincVjp/hParFqF5qk3ENjAzsfQ4I/kT+VRb3jojLloyXdr/M63V4vtPw8s4xazXLS+TI0UOdzksGb6ZyeardGEo8smjI0611Kz0+7VtOj0/TmuIylv5xkkWT5Ov1HPOOtRPYunu/Q9oh/1Ef+6P5VZmNu/wDj0lz/AHDQB5JNHZ3Pis219lYnaZRMT/qpXOFb8MD8zWF46q+7PWUKzcJqN1GK+fcxNa0ud/EHkajClvDZKwIUZLrlm4Hc/Mfr+NNztp1M44duXtOW8fLr8vzMfyZ7283xwt9onYBIkB+QfwoBWdWbbsj08twsKdN1Zqzf4I7O/wDJ8MaTa6CRG2papKkt+V7LkcH3OMe/zHvW6fKknueNVjGtVnOCtFFzUvL/AOEBsvOe8SPyoQfsY/eNwOBVR+FHPW/iS9WZ+nW32XwpdqlhcWSNfRskdy2ZCMKMngdSD2qanwhT3foewwf6iP8A3R/KrM2Nuji0lPohoA8W17jVrv8A67P/AOhGuGp8TPrcD/Bj6I1LTV9L1uyjsPEJaOWJdsN8n3gPRvX/AD9auMozVpfec1bD1cPJzo6p7x/yIZfEPh7w0jjw7aSXt8wx9ruV+VPp0P5AfWrUqdPY55Ucbi/j91djlbFp9R8R29xeytLLNcKXYnk81EZ80zorYRUsO0tEdwNF1XVf7Nt4dWudP08aZE2Lfgu/RhnIxwR611Q+Feh4GI0qy9WR3nhyPw/bTrbSTSQTmAs0r7maQO2SfwIqanwipbv0PUrf/j2i/wBwfyqzNjpE3xsp/iGKAPHfEqyWus3aXNu2Gkcpu9CSQQT1riqpqTPp8DaVGPK+xjEQvKRuKR46kZNZna3NR7spSQQszE3IHJH3fyoKdSaXwk2kRxrq1kwlDN56ZXB45q6fxI5cbKToyTX9XPXNGH/Eh0//AK9Y/wD0EV2w+FHzGJ/jT/xP8yvr1jcajZx2tsm+Rpk/AZ5NE1dEUmk36HXRp5capnO0AZpkjqAKt/p1tqEJjuIY5R6SKGFJpMuFSUHeLaOUvvAmkuWJtJ4Ae9vJkfrmsnRh2O2nmuIj1T9TDn+H+kBj/p92nsyg/wBKn2MfM6Fndb+VDLXwZpFldxXC3t5K8ThgoQDJH4U404p31M6+bVasHFxSudbYwXn2WG1tLORYoY1jWS5O3gDAPv8AhWqemh5s5OcnJ9Wb9naC1j+Zt8h+82MfkPSqJLFABQAUAFAAQD1GaACgAoAKACgA/9k= diff --git a/addons/point_of_sale/report/pos_order_report.py b/addons/point_of_sale/report/pos_order_report.py index 62250f11e17..f4df5f0f5f6 100644 --- a/addons/point_of_sale/report/pos_order_report.py +++ b/addons/point_of_sale/report/pos_order_report.py @@ -84,6 +84,5 @@ class pos_order_report(osv.osv): having sum(l.qty * u.factor) != 0)""") -pos_order_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/report/pos_report.py b/addons/point_of_sale/report/pos_report.py index 0179c7bcf45..96b056fb0fc 100644 --- a/addons/point_of_sale/report/pos_report.py +++ b/addons/point_of_sale/report/pos_report.py @@ -74,7 +74,6 @@ class report_transaction_pos(osv.osv): """) #to_char(date_trunc('day',absl.create_date),'YYYY-MM-DD') #to_char(date_trunc('day',absl.create_date),'YYYY-MM-DD')::text as date_create, -report_transaction_pos() class report_sales_by_user_pos(osv.osv): _name = "report.sales.by.user.pos" @@ -107,7 +106,6 @@ class report_sales_by_user_pos(osv.osv): ) """) -report_sales_by_user_pos() class report_sales_by_user_pos_month(osv.osv): _name = "report.sales.by.user.pos.month" @@ -140,7 +138,6 @@ class report_sales_by_user_pos_month(osv.osv): ) """) -report_sales_by_user_pos_month() class report_sales_by_margin_pos(osv.osv): _name = "report.sales.by.margin.pos" @@ -187,7 +184,6 @@ class report_sales_by_margin_pos(osv.osv): ) """) -report_sales_by_margin_pos() class report_sales_by_margin_pos_month(osv.osv): _name = "report.sales.by.margin.pos.month" @@ -233,6 +229,5 @@ class report_sales_by_margin_pos_month(osv.osv): ) """) -report_sales_by_margin_pos_month() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: 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/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/js/db.js b/addons/point_of_sale/static/src/js/db.js index a79b111b5c5..e47ce66f648 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; } } }, diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 660434ba53e..13003bcf19f 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1,24 +1,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sale var QWeb = instance.web.qweb; - // rounds a value with a fixed number of decimals. - // round(3.141492,2) -> 3.14 - function round(value,decimals){ - var mult = Math.pow(10,decimals || 0); - return Math.round(value*mult)/mult; - } - window.round = round; - - // rounds a value with decimal form precision - // round(3.141592,0.025) ->3.125 - function round_pr(value,precision){ - if(!precision || precision < 0){ - throw new Error('round_pr(): needs a precision greater than zero, got '+precision+' instead'); - } - return Math.round(value / precision) * precision; - } - window.round_pr = round_pr; - + var round_di = instance.web.round_decimals; + var round_pr = instance.web.round_precision // The PosModel contains the Point Of Sale's representation of the backend. // Since the PoS must work in standalone ( Without connection to the server ) @@ -339,7 +323,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')}); }, }); @@ -391,7 +375,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal var quant = Math.max(parseFloat(quantity) || 0, 0); var unit = this.get_unit(); if(unit){ - this.quantity = Math.max(unit.rounding, Math.round(quant / unit.rounding) * unit.rounding); + this.quantity = Math.max(unit.rounding, round_pr(quant, unit.rounding)); this.quantityStr = this.quantity.toFixed(Math.max(0,Math.ceil(Math.log(1.0 / unit.rounding) / Math.log(10)))); }else{ this.quantity = quant; @@ -484,7 +468,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal }, // changes the base price of the product for this orderline set_unit_price: function(price){ - this.price = round(parseFloat(price) || 0, 2); + this.price = round_di(parseFloat(price) || 0, 2); this.trigger('change'); }, get_unit_price: function(){ diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index eca4a3c5915..0bd399428ed 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -983,7 +983,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); + this.pos_widget.action_bar.set_button_disabled('validation', 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..a533f0a8ee6 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -319,6 +319,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 +336,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 +507,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(){ diff --git a/addons/point_of_sale/wizard/pos_box.py b/addons/point_of_sale/wizard/pos_box.py index 776d962a3a8..e1fa90844d7 100644 --- a/addons/point_of_sale/wizard/pos_box.py +++ b/addons/point_of_sale/wizard/pos_box.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python from openerp.osv import osv, fields from openerp.tools.translate import _ @@ -16,7 +15,7 @@ class PosBox(CashBox): active_ids = context.get('active_ids', []) or [] if active_model == 'pos.session': - records = self.pool.get(active_model).browse(cr, uid, active_ids, context=context) + records = self.pool[active_model].browse(cr, uid, active_ids, context=context) bank_statements = [record.cash_register_id for record in records if record.cash_register_id] if not bank_statements: @@ -41,7 +40,7 @@ class PosBoxIn(PosBox): active_ids = context.get('active_ids', []) or [] if active_model == 'pos.session': - session = self.pool.get(active_model).browse(cr, uid, active_ids, context=context)[0] + session = self.pool[active_model].browse(cr, uid, active_ids, context=context)[0] values['ref'] = session.name return values @@ -57,7 +56,7 @@ class PosBoxOut(PosBox): active_ids = context.get('active_ids', []) or [] if active_model == 'pos.session': - session = self.pool.get(active_model).browse(cr, uid, active_ids, context=context)[0] + session = self.pool[active_model].browse(cr, uid, active_ids, context=context)[0] values['ref'] = session.name return values diff --git a/addons/point_of_sale/wizard/pos_box_entries.py b/addons/point_of_sale/wizard/pos_box_entries.py index ff6af8e1f62..8ca4f01b006 100644 --- a/addons/point_of_sale/wizard/pos_box_entries.py +++ b/addons/point_of_sale/wizard/pos_box_entries.py @@ -141,7 +141,6 @@ class pos_box_entries(osv.osv_memory): bank_statement.create(cr, uid, vals, context=context) return {} -pos_box_entries() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_box_out.py b/addons/point_of_sale/wizard/pos_box_out.py index 6b0b9ee4755..51c3993183b 100644 --- a/addons/point_of_sale/wizard/pos_box_out.py +++ b/addons/point_of_sale/wizard/pos_box_out.py @@ -100,7 +100,6 @@ class pos_box_out(osv.osv_memory): statement_line_obj.create(cr, uid, vals, context=context) return {} -pos_box_out() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_confirm.py b/addons/point_of_sale/wizard/pos_confirm.py index f37bdd9f8b8..6a031f54f61 100644 --- a/addons/point_of_sale/wizard/pos_confirm.py +++ b/addons/point_of_sale/wizard/pos_confirm.py @@ -48,7 +48,6 @@ class pos_confirm(osv.osv_memory): data_lines += [x.id for x in move.line_id if x.account_id.id == invoice.account_id.id] self.pool.get('account.move.line').reconcile(cr, uid, data_lines, context=context) return {} -pos_confirm() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_details.py b/addons/point_of_sale/wizard/pos_details.py index 3f06dc57a46..bfd6e7c4ca7 100644 --- a/addons/point_of_sale/wizard/pos_details.py +++ b/addons/point_of_sale/wizard/pos_details.py @@ -60,7 +60,6 @@ class pos_details(osv.osv_memory): 'datas': datas, } -pos_details() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_discount.py b/addons/point_of_sale/wizard/pos_discount.py index d2703b21ad7..d60b2766644 100644 --- a/addons/point_of_sale/wizard/pos_discount.py +++ b/addons/point_of_sale/wizard/pos_discount.py @@ -68,6 +68,5 @@ class pos_discount(osv.osv_memory): order_line_ref.write(cr, uid, [x.id for x in order.lines], {'discount':this.discount}, context=context) return {} -pos_discount() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_open_statement.py b/addons/point_of_sale/wizard/pos_open_statement.py index 750a5519865..30e407d2ad0 100644 --- a/addons/point_of_sale/wizard/pos_open_statement.py +++ b/addons/point_of_sale/wizard/pos_open_statement.py @@ -46,7 +46,7 @@ class pos_open_statement(osv.osv_memory): st_ids = [] j_ids = journal_obj.search(cr, uid, [('journal_user','=',1)], context=context) if not j_ids: - raise osv.except_osv(_('No Cash Register Defined !'), _('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".')) + raise osv.except_osv(_('No Cash Register Defined!'), _('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".')) for journal in journal_obj.browse(cr, uid, j_ids, context=context): ids = statement_obj.search(cr, uid, [('state', '!=', 'confirm'), ('user_id', '=', uid), ('journal_id', '=', journal.id)], context=context) @@ -86,6 +86,5 @@ class pos_open_statement(osv.osv_memory): 'search_view_id': search_id, } -pos_open_statement() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_payment.py b/addons/point_of_sale/wizard/pos_payment.py index 47814761b20..02223153290 100644 --- a/addons/point_of_sale/wizard/pos_payment.py +++ b/addons/point_of_sale/wizard/pos_payment.py @@ -128,7 +128,6 @@ class pos_make_payment(osv.osv_memory): 'amount': _default_amount, } -pos_make_payment() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_payment.xml b/addons/point_of_sale/wizard/pos_payment.xml index 3b1cde3e488..2e828521757 100644 --- a/addons/point_of_sale/wizard/pos_payment.xml +++ b/addons/point_of_sale/wizard/pos_payment.xml @@ -15,7 +15,7 @@
diff --git a/addons/point_of_sale/wizard/pos_payment_report.py b/addons/point_of_sale/wizard/pos_payment_report.py index b28af5a3fff..a591fd4ce5f 100644 --- a/addons/point_of_sale/wizard/pos_payment_report.py +++ b/addons/point_of_sale/wizard/pos_payment_report.py @@ -43,7 +43,6 @@ class pos_payment_report(osv.osv_memory): 'datas': datas, } -pos_payment_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_payment_report_user.py b/addons/point_of_sale/wizard/pos_payment_report_user.py index 06e224f39bc..37a62783ed2 100644 --- a/addons/point_of_sale/wizard/pos_payment_report_user.py +++ b/addons/point_of_sale/wizard/pos_payment_report_user.py @@ -49,7 +49,6 @@ class pos_payment_report_user(osv.osv_memory): 'user_id': fields.many2many('res.users', 'res_user_sale', 'user_id', 'sale_id', 'Salesperson') } -pos_payment_report_user() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_receipt.py b/addons/point_of_sale/wizard/pos_receipt.py index 2a62b74bb30..3e6714f3ac7 100644 --- a/addons/point_of_sale/wizard/pos_receipt.py +++ b/addons/point_of_sale/wizard/pos_receipt.py @@ -55,6 +55,5 @@ class pos_receipt(osv.osv_memory): 'datas': datas, } -pos_receipt() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_return.py b/addons/point_of_sale/wizard/pos_return.py index b4e0e7b2041..f0624948ed5 100644 --- a/addons/point_of_sale/wizard/pos_return.py +++ b/addons/point_of_sale/wizard/pos_return.py @@ -171,7 +171,6 @@ class pos_return(osv.osv_memory): } return act -pos_return() class add_product(osv.osv_memory): _inherit = 'pos.add.product' @@ -321,5 +320,4 @@ class add_product(osv.osv_memory): } return True -add_product() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_sales_user.py b/addons/point_of_sale/wizard/pos_sales_user.py index f2f56d6e35c..e8ece7a7953 100644 --- a/addons/point_of_sale/wizard/pos_sales_user.py +++ b/addons/point_of_sale/wizard/pos_sales_user.py @@ -55,7 +55,6 @@ class pos_sale_user(osv.osv_memory): 'datas': datas, } -pos_sale_user() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_sales_user_current_user.py b/addons/point_of_sale/wizard/pos_sales_user_current_user.py index d3da6a9ad42..d6178ff6a50 100644 --- a/addons/point_of_sale/wizard/pos_sales_user_current_user.py +++ b/addons/point_of_sale/wizard/pos_sales_user_current_user.py @@ -53,7 +53,6 @@ class pos_sales_user_today_current_user(osv.osv_memory): 'datas': datas, } -pos_sales_user_today_current_user() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_sales_user_today.py b/addons/point_of_sale/wizard/pos_sales_user_today.py index dfc40c863b0..65e4182daed 100644 --- a/addons/point_of_sale/wizard/pos_sales_user_today.py +++ b/addons/point_of_sale/wizard/pos_sales_user_today.py @@ -52,7 +52,6 @@ class pos_sales_user_today(osv.osv_memory): 'datas': datas, } -pos_sales_user_today() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/wizard/pos_session_opening.py b/addons/point_of_sale/wizard/pos_session_opening.py index e0135de0cdb..39e7c564831 100644 --- a/addons/point_of_sale/wizard/pos_session_opening.py +++ b/addons/point_of_sale/wizard/pos_session_opening.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python from openerp.osv import osv, fields from openerp.tools.translate import _ @@ -115,4 +114,3 @@ class pos_session_opening(osv.osv_memory): 'pos_config_id' : result, 'show_config' : show_config, } -pos_session_opening() diff --git a/addons/portal/__init__.py b/addons/portal/__init__.py index 0045a557a49..1f60accc83d 100644 --- a/addons/portal/__init__.py +++ b/addons/portal/__init__.py @@ -20,7 +20,9 @@ ############################################################################## import portal +import mail_thread import mail_mail +import mail_message import wizard import acquirer diff --git a/addons/portal/i18n/ko.po b/addons/portal/i18n/ko.po new file mode 100644 index 00000000000..b1d03cc0e7e --- /dev/null +++ b/addons/portal/i18n/ko.po @@ -0,0 +1,497 @@ +# 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-05-14 01:12+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-05-15 05:15+0000\n" +"X-Generator: Launchpad (build 16617)\n" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "Mako" +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/share_wizard.py:50 +#, python-format +msgid "Please select at least one user to share with" +msgstr "" + +#. module: portal +#: view:portal.wizard:0 +msgid "" +"Select which contacts should belong to the portal in the list below.\n" +" The email address of each selected contact must be " +"valid and unique.\n" +" If necessary, you can fix any contact's email " +"address directly in the list." +msgstr "" + +#. module: portal +#: model:mail.group,name:portal.company_jobs +msgid "Company Jobs" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "amount: the total amount to pay, as a float" +msgstr "" + +#. module: portal +#: view:portal.wizard.user:0 +msgid "Contacts" +msgstr "연락처" + +#. module: portal +#: view:share.wizard:0 +#: field:share.wizard,group_ids:0 +msgid "Existing groups" +msgstr "기존 그룹" + +#. module: portal +#: view:res.groups:0 +msgid "Portal Groups" +msgstr "포털 그룹" + +#. module: portal +#: field:portal.wizard,welcome_message:0 +msgid "Invitation Message" +msgstr "초대 메시지" + +#. module: portal +#: view:res.groups:0 +msgid "Non-Portal Groups" +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/share_wizard.py:54 +#, python-format +msgid "Please select at least one group to share with" +msgstr "" + +#. module: portal +#: view:share.wizard:0 +msgid "Details" +msgstr "" + +#. module: portal +#: model:ir.ui.menu,name:portal.portal_orders +msgid "Quotations and Sales Orders" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "reference: the reference number of the document to pay" +msgstr "" + +#. module: portal +#: help:portal.payment.acquirer,visible:0 +msgid "" +"Make this payment acquirer available in portal forms (Customer invoices, " +"etc.)" +msgstr "" + +#. module: portal +#: model:ir.model,name:portal.model_share_wizard +msgid "Share Wizard" +msgstr "" + +#. module: portal +#: field:portal.wizard.user,email:0 +msgid "Email" +msgstr "" + +#. module: portal +#: model:ir.actions.client,help:portal.action_news +msgid "" +"

\n" +" Youd don't have unread company's news.\n" +"

\n" +" " +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/portal_wizard.py:194 +#, python-format +msgid "" +"You must have an email address in your User Preferences to send emails." +msgstr "" + +#. module: portal +#: model:ir.actions.client,name:portal.action_jobs +#: model:ir.ui.menu,name:portal.portal_jobs +msgid "Jobs" +msgstr "" + +#. module: portal +#: field:portal.wizard,user_ids:0 +msgid "Users" +msgstr "" + +#. module: portal +#: code:addons/portal/acquirer.py:82 +#, python-format +msgid "Pay safely online" +msgstr "" + +#. module: portal +#: code:addons/portal/acquirer.py:77 +#, python-format +msgid "No online payment acquirers configured" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "" +"kind: the kind of document on which the payment form is rendered (translated " +"to user language, e.g. \"Invoice\")" +msgstr "" + +#. module: portal +#: help:portal.wizard,portal_id:0 +msgid "The portal that users can be added in or removed from." +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/share_wizard.py:38 +#, python-format +msgid "Users you already shared with" +msgstr "" + +#. module: portal +#: model:ir.actions.client,help:portal.action_jobs +msgid "" +"

\n" +" Youd don't have unread job offers.\n" +"

\n" +" " +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "" +", so it may use Mako expressions.\n" +" The Mako evaluation context provides:" +msgstr "" + +#. module: portal +#: model:ir.ui.menu,name:portal.portal_menu +#: field:portal.wizard,portal_id:0 +#: field:res.groups,is_portal:0 +#: model:res.groups,name:portal.group_portal +msgid "Portal" +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/portal_wizard.py:34 +#, python-format +msgid "Your OpenERP account at %(company)s" +msgstr "" + +#. module: portal +#: model:res.groups,name:portal.group_anonymous +msgid "Anonymous" +msgstr "" + +#. module: portal +#: field:portal.wizard.user,in_portal:0 +msgid "In Portal" +msgstr "" + +#. module: portal +#: model:ir.actions.client,name:portal.action_news +#: model:ir.ui.menu,name:portal.portal_company_news +msgid "News" +msgstr "" + +#. module: portal +#: model:ir.ui.menu,name:portal.portal_after_sales +msgid "After Sale Services" +msgstr "" + +#. module: portal +#: model:res.groups,comment:portal.group_portal +msgid "" +"Portal members have specific access rights (such as record rules and " +"restricted menus).\n" +" They usually do not belong to the usual OpenERP groups." +msgstr "" + +#. module: portal +#: model:ir.actions.act_window,name:portal.action_acquirer_list +#: view:portal.payment.acquirer:0 +msgid "Payment Acquirers" +msgstr "" + +#. module: portal +#: model:ir.ui.menu,name:portal.portal_projects +msgid "Projects" +msgstr "" + +#. module: portal +#: model:ir.actions.client,name:portal.action_mail_inbox_feeds_portal +#: model:ir.ui.menu,name:portal.portal_inbox +msgid "Inbox" +msgstr "" + +#. module: portal +#: view:share.wizard:0 +#: field:share.wizard,user_ids:0 +msgid "Existing users" +msgstr "" + +#. module: portal +#: field:portal.wizard.user,wizard_id:0 +msgid "Wizard" +msgstr "" + +#. module: portal +#: field:portal.payment.acquirer,name:0 +msgid "Name" +msgstr "" + +#. module: portal +#: model:ir.model,name:portal.model_res_groups +msgid "Access Groups" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "uid: the current user id" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "" +"quote(): a method to quote special string character to make them suitable " +"for inclusion in a URL" +msgstr "" + +#. module: portal +#: help:res.groups,is_portal:0 +msgid "If checked, this group is usable as a portal." +msgstr "" + +#. module: portal +#: field:portal.payment.acquirer,form_template:0 +msgid "Payment form template (HTML)" +msgstr "" + +#. module: portal +#: field:portal.wizard.user,partner_id:0 +msgid "Contact" +msgstr "" + +#. module: portal +#: model:ir.model,name:portal.model_mail_mail +msgid "Outgoing Mails" +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/portal_wizard.py:193 +#, python-format +msgid "Email required" +msgstr "" + +#. module: portal +#: model:ir.ui.menu,name:portal.portal_messages +msgid "Messaging" +msgstr "" + +#. module: portal +#: model:res.groups,comment:portal.group_anonymous +msgid "" +"Anonymous users have specific access rights (such as record rules and " +"restricted menus).\n" +" They usually do not belong to the usual OpenERP groups." +msgstr "" + +#. module: portal +#: model:ir.model,name:portal.model_portal_payment_acquirer +msgid "Online Payment Acquirer" +msgstr "" + +#. module: portal +#: model:mail.group,name:portal.company_news_feed +msgid "Company News" +msgstr "" + +#. module: portal +#: code:addons/portal/acquirer.py:76 +#, python-format +msgid "" +"You can finish the configuration in the Bank&Cash settings" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "cr: the current database cursor" +msgstr "" + +#. module: portal +#: model:ir.actions.client,help:portal.action_mail_inbox_feeds_portal +msgid "" +"

\n" +" Good Job! Your inbox is empty.\n" +"

\n" +" Your inbox contains private messages or emails sent to " +"you\n" +" as well as information related to documents or people " +"you\n" +" follow.\n" +"

\n" +" " +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "" +"object: the document on which the payment form is rendered (usually an " +"invoice or sales order record)" +msgstr "" + +#. module: portal +#: help:portal.wizard,welcome_message:0 +msgid "This text is included in the email sent to new users of the portal." +msgstr "" + +#. module: portal +#: model:ir.ui.menu,name:portal.portal_company +msgid "About Us" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "" +"currency: the currency record in which the document is issued (e.g. " +"currency.name could be EUR)" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "Payment Acquirer" +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/portal_wizard.py:35 +#, python-format +msgid "" +"Dear %(name)s,\n" +"\n" +"You have been given access to %(portal)s.\n" +"\n" +"Your login account data is:\n" +"Database: %(db)s\n" +"Username: %(login)s\n" +"\n" +"In order to complete the signin process, click on the following url:\n" +"%(url)s\n" +"\n" +"%(welcome_message)s\n" +"\n" +"--\n" +"OpenERP - Open Source Business Applications\n" +"http://www.openerp.com\n" +msgstr "" + +#. module: portal +#: view:portal.wizard:0 +msgid "or" +msgstr "" + +#. module: portal +#: model:portal.payment.acquirer,form_template:portal.paypal_acquirer +msgid "" +"\n" +"% if object.company_id.paypal_account:\n" +"
\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"\n" +"% endif\n" +" " +msgstr "" + +#. module: portal +#: model:ir.model,name:portal.model_portal_wizard_user +msgid "Portal User Config" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "" +"If the template renders to an empty result in a certain context it will be " +"ignored, as if it was inactive." +msgstr "" + +#. module: portal +#: field:portal.payment.acquirer,visible:0 +msgid "Visible" +msgstr "" + +#. module: portal +#: code:addons/portal/wizard/share_wizard.py:39 +#, python-format +msgid "Existing Groups (e.g Portal Groups)" +msgstr "" + +#. module: portal +#: view:portal.wizard:0 +msgid "Cancel" +msgstr "" + +#. module: portal +#: view:portal.wizard:0 +msgid "Apply" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "ctx: the current context dictionary" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "" +"This is an HTML form template to submit a payment through this acquirer.\n" +" The template will be rendered with" +msgstr "" + +#. module: portal +#: code:addons/portal/mail_mail.py:42 +#, python-format +msgid "" +"Access your personal documents through our Customer Portal" +msgstr "" + +#. module: portal +#: view:portal.payment.acquirer:0 +msgid "Form Template" +msgstr "" + +#. module: portal +#: model:ir.actions.act_window,name:portal.partner_wizard_action +#: model:ir.model,name:portal.model_portal_wizard +#: view:portal.wizard:0 +msgid "Portal Access Management" +msgstr "" diff --git a/addons/portal/mail_mail.py b/addons/portal/mail_mail.py index 3810ddd2540..e412732fdc9 100644 --- a/addons/portal/mail_mail.py +++ b/addons/portal/mail_mail.py @@ -21,7 +21,6 @@ from openerp import SUPERUSER_ID from openerp.osv import osv -from openerp.osv.orm import except_orm from openerp.tools.translate import _ @@ -29,27 +28,19 @@ class mail_mail(osv.Model): """ Update of mail_mail class, to add the signin URL to notifications. """ _inherit = 'mail.mail' - def send_get_mail_body_footer(self, cr, uid, mail, partner=None, context=None): - """ add a signin link inside the body of a mail.mail - :param mail: mail.mail browse_record - :param partner: browse_record of the specific recipient partner - :return: the resulting body_html + def _get_partner_access_link(self, cr, uid, mail, partner=None, context=None): + """ Generate URLs for links in mails: + - partner is not an user: signup_url + - partner is an user: fallback on classic URL """ + if context is None: + context = {} partner_obj = self.pool.get('res.partner') - if partner: - contex_signup = dict(context or {}, signup_valid=True) - partner = partner_obj.browse(cr, SUPERUSER_ID, partner.id, context=contex_signup) - body_footer = _("""Access your messages and documents through our Customer Portal""") % partner.signup_url - # partner is an user: add a link to the document if read access - if partner.user_ids and mail.model and mail.res_id \ - and self.check_access_rights(cr, partner.user_ids[0].id, 'read', raise_exception=False): - related_user = partner.user_ids[0] - try: - self.pool.get(mail.model).check_access_rule(cr, related_user.id, [mail.res_id], 'read', context=context) - url = partner_obj._get_signup_url_for_action(cr, related_user.id, [partner.id], action='', res_id=mail.res_id, model=mail.model, context=context)[partner.id] - text = _("""Access this document directly in OpenERP""") % url - except except_orm, e: - pass - return body_footer + if partner and not partner.user_ids: + contex_signup = dict(context, signup_valid=True) + signup_url = partner_obj._get_signup_url_for_action(cr, SUPERUSER_ID, [partner.id], + action='login', model=mail.model, res_id=mail.res_id, + context=contex_signup)[partner.id] + return _("""Access your messages and documents through our Customer Portal""") % signup_url else: - return super(mail_mail, self).send_get_mail_body_footer(cr, uid, mail, partner=partner, context=context) + return super(mail_mail, self)._get_partner_access_link(cr, uid, mail, partner=partner, context=context) diff --git a/addons/portal/mail_message.py b/addons/portal/mail_message.py new file mode 100644 index 00000000000..d6a38f27378 --- /dev/null +++ b/addons/portal/mail_message.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2011 OpenERP S.A (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import osv, orm +from openerp.tools.translate import _ + + +class mail_message(osv.Model): + """ Update of mail_message class, to restrict mail access. """ + _inherit = 'mail.message' + + def _search(self, cr, uid, args, offset=0, limit=None, order=None, + context=None, count=False, access_rights_uid=None): + """ Override that adds specific access rights of mail.message, to remove + all internal notes if uid is a non-employee + """ + group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id + group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1] + if group_user_id not in [group.id for group in group_ids]: + args = ['&', '|', ('type', '!=', 'comment'), ('subtype_id', '!=', False)] + list(args) + + return super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order, + context=context, count=False, access_rights_uid=access_rights_uid) + + def check_access_rule(self, cr, uid, ids, operation, context=None): + """ Add Access rules of mail.message for non-employee user: + - read: + - raise if the type is comment and subtype NULL (internal note) + """ + group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id + group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1] + if group_user_id not in [group.id for group in group_ids]: + cr.execute('SELECT DISTINCT id FROM "%s" WHERE type = %%s AND subtype_id IS NULL AND id = ANY (%%s)' % (self._table), ('comment', ids,)) + if cr.fetchall(): + raise orm.except_orm(_('Access Denied'), + _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % \ + (self._description, operation)) + + return super(mail_message, self).check_access_rule(cr, uid, ids=ids, operation=operation, context=context) diff --git a/addons/portal/mail_thread.py b/addons/portal/mail_thread.py new file mode 100644 index 00000000000..44bc4d0bde8 --- /dev/null +++ b/addons/portal/mail_thread.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-TODAY OpenERP S.A (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import SUPERUSER_ID +from openerp.osv import osv + + +class mail_thread(osv.AbstractModel): + """ Update of mail_mail class, to add the signin URL to notifications. """ + _inherit = 'mail.thread' + + def _get_inbox_action_xml_id(self, cr, uid, context=None): + """ For a given message, return an action that either + - opens the form view of the related document if model, res_id, and + read access to the document + - opens the Inbox with a default search on the conversation if model, + res_id + - opens the Inbox with context propagated + """ + cur_user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context) + # if uid is a portal user -> action is different + if any(group.is_portal for group in cur_user.groups_id): + return ('portal', 'action_mail_inbox_feeds_portal') + else: + return super(mail_thread, self)._get_inbox_action_xml_id(cr, uid, context=context) diff --git a/addons/portal/portal_demo.xml b/addons/portal/portal_demo.xml index c05189fd2ab..3660754b4ad 100644 --- a/addons/portal/portal_demo.xml +++ b/addons/portal/portal_demo.xml @@ -40,7 +40,7 @@ Mr Demo Portal
mail.group - As your first portal member, I am very pleased to be able to be able to communicate directly with you. Be sure I'll read all news carefully!

]]>
+ As your first portal member, I am very pleased to be able to communicate directly with you. Be sure I'll read all news carefully!

]]>
comment diff --git a/addons/portal/security/ir.model.access.csv b/addons/portal/security/ir.model.access.csv index 31bd7332c2f..26b0b4895e8 100644 --- a/addons/portal/security/ir.model.access.csv +++ b/addons/portal/security/ir.model.access.csv @@ -3,7 +3,7 @@ access_mail_message_portal,mail.message.portal,mail.model_mail_message,group_por access_mail_mail_portal,mail.mail.portal,mail.model_mail_mail,group_portal,1,1,1,0 access_mail_notification_portal,mail.notification.portal,mail.model_mail_notification,group_portal,1,1,1,0 access_mail_followers_portal,mail.followers.portal,mail.model_mail_followers,group_portal,1,1,0,0 -access_res_partner,res.partner,base.model_res_partner,portal.group_portal,1,0,0,0 +access_res_partner_portal,res.partner.portal,base.model_res_partner,portal.group_portal,1,0,0,0 access_acquirer,portal.payment.acquirer,portal.model_portal_payment_acquirer,,1,0,0,0 access_acquirer_all,portal.payment.acquirer,portal.model_portal_payment_acquirer,base.group_system,1,1,1,1 access_ir_attachment_group_portal,ir.attachment group_portal,base.model_ir_attachment,portal.group_portal,1,0,1,0 \ No newline at end of file diff --git a/addons/portal/security/portal_security.xml b/addons/portal/security/portal_security.xml index b2a76800023..02080bdc0ab 100644 --- a/addons/portal/security/portal_security.xml +++ b/addons/portal/security/portal_security.xml @@ -5,7 +5,7 @@ res_partner: read access on my partner - [('user_ids', 'in', user.id)] + [('id', 'child_of', user.commercial_partner_id.id)] diff --git a/addons/portal/tests/test_portal.py b/addons/portal/tests/test_portal.py index 07becf5cdd9..e2b66e65af6 100644 --- a/addons/portal/tests/test_portal.py +++ b/addons/portal/tests/test_portal.py @@ -40,7 +40,9 @@ class test_portal(TestMailBase): self.partner_chell_id = self.user_chell.partner_id.id # Create a PigsPortal group - self.group_port_id = self.mail_group.create(cr, uid, {'name': 'PigsPortal', 'public': 'groups', 'group_public_id': self.group_portal_id}) + self.group_port_id = self.mail_group.create(cr, uid, + {'name': 'PigsPortal', 'public': 'groups', 'group_public_id': self.group_portal_id}, + {'mail_create_nolog': True}) # Set an email address for the user running the tests, used as Sender for outgoing mails self.res_users.write(cr, uid, uid, {'email': 'test@localhost'}) @@ -130,3 +132,94 @@ class test_portal(TestMailBase): 'invite: body of invitation email is incorrect') self.assertTrue(partner_carine.signup_url in sent_email.get('body'), 'invite: body of invitation email does not contain signup url') + + def test_20_notification_url(self): + """ Tests designed to test the URL added in notification emails. """ + cr, uid, group_pigs = self.cr, self.uid, self.group_pigs + + # Partner data + partner_raoul = self.res_partner.browse(cr, uid, self.partner_raoul_id) + partner_bert_id = self.res_partner.create(cr, uid, {'name': 'bert'}) + partner_bert = self.res_partner.browse(cr, uid, partner_bert_id) + # Mail data + mail_mail_id = self.mail_mail.create(cr, uid, {'state': 'exception'}) + mail = self.mail_mail.browse(cr, uid, mail_mail_id) + + # Test: link for nobody -> None + url = self.mail_mail._get_partner_access_link(cr, uid, mail) + self.assertEqual(url, None, + 'notification email: mails not send to a specific partner should not have any URL') + + # Test: link for partner -> signup URL + url = self.mail_mail._get_partner_access_link(cr, uid, mail, partner=partner_bert) + self.assertIn(partner_bert.signup_url, url, + 'notification email: mails send to a not-user partner should contain the signup URL') + + # Test: link for user -> signin + url = self.mail_mail._get_partner_access_link(cr, uid, mail, partner=partner_raoul) + self.assertIn('action=mail.action_mail_redirect', url, + 'notification email: link should contain the redirect action') + self.assertIn('login=%s' % partner_raoul.user_ids[0].login, url, + 'notification email: link should contain the user login') + + @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm') + def test_21_inbox_redirection(self): + """ Tests designed to test the inbox redirection of emails notification URLs. """ + cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs + model, act_id = self.ir_model_data.get_object_reference(cr, uid, 'mail', 'action_mail_inbox_feeds') + model, port_act_id = self.ir_model_data.get_object_reference(cr, uid, 'portal', 'action_mail_inbox_feeds_portal') + # Data: post a message on pigs + msg_id = self.group_pigs.message_post(body='My body', partner_ids=[self.partner_bert_id, self.partner_chell_id], type='comment', subtype='mail.mt_comment') + + # No specific parameters -> should redirect to Inbox + action = self.mail_thread.message_redirect_action(cr, self.user_raoul_id, {'params': {}}) + self.assertEqual(action.get('type'), 'ir.actions.client', + 'URL redirection: action without parameters should redirect to client action Inbox') + self.assertEqual(action.get('id'), act_id, + 'URL redirection: action without parameters should redirect to client action Inbox') + + # Bert has read access to Pigs -> should redirect to form view of Pigs + action = self.mail_thread.message_redirect_action(cr, self.user_raoul_id, {'params': {'message_id': msg_id}}) + self.assertEqual(action.get('type'), 'ir.actions.act_window', + 'URL redirection: action with message_id for read-accredited user should redirect to Pigs') + self.assertEqual(action.get('res_id'), group_pigs.id, + 'URL redirection: action with message_id for read-accredited user should redirect to Pigs') + + # Bert has no read access to Pigs -> should redirect to Inbox + action = self.mail_thread.message_redirect_action(cr, self.user_bert_id, {'params': {'message_id': msg_id}}) + self.assertEqual(action.get('type'), 'ir.actions.client', + 'URL redirection: action without parameters should redirect to client action Inbox') + self.assertEqual(action.get('id'), act_id, + 'URL redirection: action without parameters should redirect to client action Inbox') + + # Chell has no read access to pigs -> should redirect to Portal Inbox + action = self.mail_thread.message_redirect_action(cr, self.user_chell_id, {'params': {'message_id': msg_id}}) + self.assertEqual(action.get('type'), 'ir.actions.client', + 'URL redirection: action without parameters should redirect to client action Inbox') + self.assertEqual(action.get('id'), port_act_id, + 'URL redirection: action without parameters should redirect to client action Inbox') + + def test_30_message_read(self): + cr, uid, group_port_id = self.cr, self.uid, self.group_port_id + + # Data: custom subtypes + mt_group_public_id = self.mail_message_subtype.create(cr, uid, {'name': 'group_public', 'description': 'Group changed'}) + self.ir_model_data.create(cr, uid, {'name': 'mt_group_public', 'model': 'mail.message.subtype', 'module': 'mail', 'res_id': mt_group_public_id}) + # Data: post messages with various subtypes + msg1_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body1', type='comment', subtype='mail.mt_comment') + msg2_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body2', type='comment', subtype='mail.mt_group_public') + msg3_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body3', type='comment', subtype='mail.mt_comment') + msg4_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body4', type='comment') + msg5_id = self.mail_group.message_post(cr, uid, group_port_id, body='Body5', type='notification') + + # Do: Chell search messages: should not see internal notes (comment without subtype) + msg_ids = self.mail_message.search(cr, self.user_chell_id, [('model', '=', 'mail.group'), ('res_id', '=', group_port_id)]) + self.assertEqual(set(msg_ids), set([msg1_id, msg2_id, msg3_id, msg5_id]), + 'mail_message: portal user has access to messages he should not read') + + # Do: Chell read messages she can read + self.mail_message.read(cr, self.user_chell_id, msg_ids, ['body', 'type', 'subtype_id']) + + # Do: Chell read a message she should not be able to read + with self.assertRaises(except_orm): + self.mail_message.read(cr, self.user_chell_id, [msg4_id], ['body', 'type', 'subtype_id']) diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py index e3047cd5edb..3ec2850b4aa 100644 --- a/addons/portal/wizard/portal_wizard.py +++ b/addons/portal/wizard/portal_wizard.py @@ -20,7 +20,6 @@ ############################################################################## import logging -import random from openerp.osv import fields, osv from openerp.tools.translate import _ @@ -34,14 +33,15 @@ _logger = logging.getLogger(__name__) WELCOME_EMAIL_SUBJECT = _("Your OpenERP account at %(company)s") WELCOME_EMAIL_BODY = _("""Dear %(name)s, -You have been given access to %(portal)s. +You have been given access to %(company)s's %(portal)s. Your login account data is: -Database: %(db)s -Username: %(login)s + Username: %(login)s + Portal: %(portal_url)s + Database: %(db)s -In order to complete the signin process, click on the following url: -%(url)s +You can set or change your password via the following url: + %(signup_url)s %(welcome_message)s @@ -116,24 +116,57 @@ class wizard_user(osv.osv_memory): _description = 'Portal User Config' _columns = { - 'wizard_id': fields.many2one('portal.wizard', string='Wizard', required=True), + 'wizard_id': fields.many2one('portal.wizard', string='Wizard', required=True, ondelete='cascade'), 'partner_id': fields.many2one('res.partner', string='Contact', required=True, readonly=True), 'email': fields.char(size=240, string='Email'), 'in_portal': fields.boolean('In Portal'), } - def create(self, cr, uid, values, context=None): - """ overridden to update the partner's email (if necessary) """ - id = super(wizard_user, self).create(cr, uid, values, context) - wuser = self.browse(cr, uid, id, context) - if wuser.partner_id.email != wuser.email: - wuser.partner_id.write({'email': wuser.email}) - return id + def get_error_messages(self, cr, uid, ids, context=None): + res_users = self.pool.get('res.users') + emails = [] + error_empty = [] + error_emails = [] + error_user = [] + ctx = dict(context or {}, active_test=False) + for wizard_user in self.browse(cr, SUPERUSER_ID, ids, context): + if wizard_user.in_portal and not self._retrieve_user(cr, SUPERUSER_ID, wizard_user, context): + email = extract_email(wizard_user.email) + if not email: + error_empty.append(wizard_user.partner_id) + elif email in emails and email not in error_emails: + error_emails.append(wizard_user.partner_id) + user = res_users.search(cr, SUPERUSER_ID, [('login', '=', email)], context=ctx) + if user: + error_user.append(wizard_user.partner_id) + emails.append(email) + + error_msg = [] + if error_empty: + error_msg.append("%s\n- %s" % (_("Some contacts don't have a valid email: "), + '\n- '.join(['%s' % (p.display_name,) for p in error_empty]))) + if error_emails: + error_msg.append("%s\n- %s" % (_("Several contacts have the same email: "), + '\n- '.join([p.email for p in error_emails]))) + if error_user: + error_msg.append("%s\n- %s" % (_("Some contacts have the same email as an existing portal user:"), + '\n- '.join(['%s <%s>' % (p.display_name, p.email) for p in error_user]))) + if error_msg: + error_msg.append(_("To resolve this error, you can: \n" + "- Correct the emails of the relevant contacts\n" + "- Grant access only to contacts with unique emails")) + return error_msg def action_apply(self, cr, uid, ids, context=None): + error_msg = self.get_error_messages(cr, uid, ids, context=context) + if error_msg: + raise osv.except_osv(_('Contacts Error'), "\n\n".join(error_msg)) + for wizard_user in self.browse(cr, SUPERUSER_ID, ids, context): portal = wizard_user.wizard_id.portal_id user = self._retrieve_user(cr, SUPERUSER_ID, wizard_user, context) + if wizard_user.partner_id.email != wizard_user.email: + wizard_user.partner_id.write({'email': wizard_user.email}) if wizard_user.in_portal: # create a user if necessary, and make sure it is in the portal group if not user: @@ -142,8 +175,8 @@ class wizard_user(osv.osv_memory): user.write({'active': True, 'groups_id': [(4, portal.id)]}) # prepare for the signup process user.partner_id.signup_prepare() - wizard_user = self.browse(cr, SUPERUSER_ID, wizard_user.id, context) - self._send_email(cr, uid, wizard_user, context) + wizard_user.refresh() + self._send_email(cr, uid, wizard_user, context) else: # remove the user (if it exists) from the portal group if user and (portal in user.groups_id): @@ -158,13 +191,11 @@ class wizard_user(osv.osv_memory): @param wizard_user: browse record of model portal.wizard.user @return: browse record of model res.users """ - if wizard_user.partner_id.user_ids: - return wizard_user.partner_id.user_ids[0] - # the user may be inactive, search for it + context = dict(context or {}, active_test=False) res_users = self.pool.get('res.users') - domain = [('partner_id', '=', wizard_user.partner_id.id), ('active', '=', False)] - user_ids = res_users.search(cr, uid, domain) - return user_ids and res_users.browse(cr, uid, user_ids[0], context) or False + domain = [('partner_id', '=', wizard_user.partner_id.id)] + user_ids = res_users.search(cr, uid, domain, context=context) + return user_ids and res_users.browse(cr, uid, user_ids[0], context=context) or False def _create_user(self, cr, uid, wizard_user, context=None): """ create a new user for wizard_user.partner_id @@ -172,8 +203,9 @@ class wizard_user(osv.osv_memory): @return: browse record of model res.users """ res_users = self.pool.get('res.users') - create_context = dict(context or {}, noshortcut=True) # to prevent shortcut creation + create_context = dict(context or {}, noshortcut=True, no_reset_password=True) # to prevent shortcut creation values = { + 'email': extract_email(wizard_user.email), 'login': extract_email(wizard_user.email), 'partner_id': wizard_user.partner_id.id, 'groups_id': [(6, 0, [])], @@ -187,15 +219,22 @@ class wizard_user(osv.osv_memory): @param wizard_user: browse record of model portal.wizard.user @return: the id of the created mail.mail record """ + res_partner = self.pool['res.partner'] this_context = context this_user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context) if not this_user.email: - raise osv.except_osv(_('Email required'), + raise osv.except_osv(_('Email Required'), _('You must have an email address in your User Preferences to send emails.')) # determine subject and body in the portal user's language user = self._retrieve_user(cr, SUPERUSER_ID, wizard_user, context) context = dict(this_context or {}, lang=user.lang) + ctx_portal_url = dict(context, signup_force_type_in_url='') + portal_url = res_partner._get_signup_url_for_action(cr, uid, + [user.partner_id.id], + context=ctx_portal_url)[user.partner_id.id] + res_partner.signup_prepare(cr, uid, [user.partner_id.id], context=context) + data = { 'company': this_user.company_id.name, 'portal': wizard_user.wizard_id.portal_id.name, @@ -203,7 +242,8 @@ class wizard_user(osv.osv_memory): 'db': cr.dbname, 'name': user.name, 'login': user.login, - 'url': user.signup_url, + 'signup_url': user.signup_url, + 'portal_url': portal_url, } mail_mail = self.pool.get('mail.mail') mail_values = { diff --git a/addons/portal/wizard/share_wizard.py b/addons/portal/wizard/share_wizard.py index d983bf11ee1..0ffae804f07 100644 --- a/addons/portal/wizard/share_wizard.py +++ b/addons/portal/wizard/share_wizard.py @@ -179,7 +179,6 @@ class share_wizard_portal(osv.TransientModel): super(share_wizard_portal,self)._finish_result_lines(cr, uid, wizard_data, share_group_id, context=context) self.copy_share_group_access_and_delete(cr, wizard_data, share_group_id, context=context) -share_wizard_portal() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/portal_anonymous/i18n/lt.po b/addons/portal_anonymous/i18n/lt.po new file mode 100644 index 00000000000..60643c7f356 --- /dev/null +++ b/addons/portal_anonymous/i18n/lt.po @@ -0,0 +1,25 @@ +# 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-24 18:34+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-25 05:20+0000\n" +"X-Generator: Launchpad (build 16580)\n" + +#. module: portal_anonymous +#. openerp-web +#: code:addons/portal_anonymous/static/src/xml/portal_anonymous.xml:8 +#, python-format +msgid "Login" +msgstr "Prisijungti" diff --git a/addons/portal_anonymous/i18n/ru.po b/addons/portal_anonymous/i18n/ru.po new file mode 100644 index 00000000000..5ae80dfe490 --- /dev/null +++ b/addons/portal_anonymous/i18n/ru.po @@ -0,0 +1,25 @@ +# 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-04-09 13:04+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-04-10 05:21+0000\n" +"X-Generator: Launchpad (build 16550)\n" + +#. module: portal_anonymous +#. openerp-web +#: code:addons/portal_anonymous/static/src/xml/portal_anonymous.xml:8 +#, python-format +msgid "Login" +msgstr "Вход" diff --git a/addons/portal_crm/i18n/fr.po b/addons/portal_crm/i18n/fr.po new file mode 100644 index 00000000000..a0633c60306 --- /dev/null +++ b/addons/portal_crm/i18n/fr.po @@ -0,0 +1,546 @@ +# French 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-22 16:34+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: French \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-23 05:19+0000\n" +"X-Generator: Launchpad (build 16640)\n" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,type:0 +msgid "Lead" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,title:0 +msgid "Title" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,probability:0 +msgid "Success Rate (%)" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Contact us" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_action:0 +msgid "Next Action Date" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,fax:0 +msgid "Fax" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,zip:0 +msgid "Zip" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,company_id:0 +msgid "Company" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,day_open:0 +msgid "Days to Open" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Thank you for your interest, we'll respond to your request shortly." +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Highest" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,mobile:0 +msgid "Mobile" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,description:0 +msgid "Notes" +msgstr "Notes" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,color:0 +msgid "Color Index" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_latitude:0 +msgid "Geo Latitude" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_name:0 +msgid "Customer Name" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "Cancelled" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,channel_id:0 +msgid "Communication channel (mail, direct, phone, ...)" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,type_id:0 +msgid "Campaign" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,ref:0 +msgid "Reference" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_action_next:0 +#: field:portal_crm.crm_contact_us,title_action:0 +msgid "Next Action" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,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: portal_crm +#: field:portal_crm.crm_contact_us,partner_id:0 +msgid "Partner" +msgstr "" + +#. module: portal_crm +#: model:ir.actions.act_window,name:portal_crm.action_contact_us +msgid "Contact Us" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,name:0 +msgid "Subject" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,opt_out:0 +msgid "Opt-Out" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,priority:0 +msgid "Priority" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,state_id:0 +msgid "State" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,partner_id:0 +msgid "Linked partner (optional). Usually created when converting the lead." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,payment_mode:0 +msgid "Payment Mode" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "New" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,type:0 +msgid "Type" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,email_from:0 +msgid "Email" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,channel_id:0 +msgid "Channel" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Name" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Lowest" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,create_date:0 +msgid "Creation Date" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Close" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "Pending" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,type:0 +msgid "Type is used to separate Leads and Opportunities" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,categ_ids:0 +msgid "Categories" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,stage_id:0 +msgid "Stage" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,user_login:0 +msgid "User Login" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,opt_out:0 +msgid "" +"If opt-out is checked, this contact has refused to receive emails or " +"unsubscribed to a campaign." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,contact_name:0 +msgid "Contact Name" +msgstr "" + +#. module: portal_crm +#: model:ir.ui.menu,name:portal_crm.portal_company_contact +msgid "Contact" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_address_email:0 +msgid "Partner Contact Email" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,planned_revenue:0 +msgid "Expected Revenue" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,task_ids:0 +msgid "Tasks" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Contact form" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,company_currency:0 +msgid "Currency" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,write_date:0 +msgid "Update Date" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_deadline:0 +msgid "Expected Closing" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,ref2:0 +msgid "Reference 2" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,user_email:0 +msgid "User Email" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_open:0 +msgid "Opened" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "In Progress" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,partner_name:0 +msgid "" +"The name of the future partner company that will be created while converting " +"the lead into opportunity" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,planned_cost:0 +msgid "Planned Costs" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,date_deadline:0 +msgid "Estimate of the date on which the opportunity will be won." +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,email_cc:0 +msgid "" +"These email addresses will be added to the CC field of all inbound and " +"outbound emails for this record before being sent. Separate multiple email " +"addresses with a comma" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Low" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_closed:0 +#: selection:portal_crm.crm_contact_us,state:0 +msgid "Closed" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_assign:0 +msgid "Assignation Date" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,state:0 +msgid "Status" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Normal" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,email_cc:0 +msgid "Global CC" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,street2:0 +msgid "Street2" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,id:0 +msgid "ID" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,phone:0 +msgid "Phone" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,active:0 +msgid "Active" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,user_id:0 +msgid "Salesperson" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,day_close:0 +msgid "Days to Close" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,company_ids:0 +msgid "Companies" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,section_id:0 +msgid "" +"When sending mails, the default email address is taken from the sales team." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_address_name:0 +msgid "Partner Contact Name" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_longitude:0 +msgid "Geo Longitude" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,date_assign:0 +msgid "Last date this case was forwarded/assigned to a partner" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,email_from:0 +msgid "Email address of the contact" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,city:0 +msgid "City" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Submit" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,function:0 +msgid "Function" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,referred:0 +msgid "Referred By" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_assigned_id:0 +msgid "Assigned Partner" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,type:0 +msgid "Opportunity" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,partner_assigned_id:0 +msgid "Partner this case has been forwarded/assigned to." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,country_id:0 +msgid "Country" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Thank you" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,state:0 +msgid "" +"The Status is set to 'Draft', when a case is created. If the case is in " +"progress the Status is set to 'Open'. When the case is over, the Status is " +"set to 'Done'. If the case needs to be reviewed then the Status is set to " +"'Pending'." +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,type_id:0 +msgid "" +"From which campaign (seminar, marketing campaign, mass mailing, ...) did " +"this contact come from?" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "High" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,section_id:0 +msgid "Sales Team" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,street:0 +msgid "Street" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_action_last:0 +msgid "Last Action" +msgstr "" + +#. module: portal_crm +#: model:ir.model,name:portal_crm.model_portal_crm_crm_contact_us +msgid "Contact form for the portal" +msgstr "" diff --git a/addons/portal_crm/i18n/lt.po b/addons/portal_crm/i18n/lt.po new file mode 100644 index 00000000000..b2b223c6124 --- /dev/null +++ b/addons/portal_crm/i18n/lt.po @@ -0,0 +1,546 @@ +# 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:24+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: portal_crm +#: selection:portal_crm.crm_contact_us,type:0 +msgid "Lead" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,title:0 +msgid "Title" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,probability:0 +msgid "Success Rate (%)" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Contact us" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_action:0 +msgid "Next Action Date" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,fax:0 +msgid "Fax" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,zip:0 +msgid "Zip" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,company_id:0 +msgid "Company" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,day_open:0 +msgid "Days to Open" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Thank you for your interest, we'll respond to your request shortly." +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Highest" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,mobile:0 +msgid "Mobile" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,description:0 +msgid "Notes" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,color:0 +msgid "Color Index" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_latitude:0 +msgid "Geo Latitude" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_name:0 +msgid "Customer Name" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "Cancelled" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,channel_id:0 +msgid "Communication channel (mail, direct, phone, ...)" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,type_id:0 +msgid "Campaign" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,ref:0 +msgid "Reference" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_action_next:0 +#: field:portal_crm.crm_contact_us,title_action:0 +msgid "Next Action" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,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: portal_crm +#: field:portal_crm.crm_contact_us,partner_id:0 +msgid "Partner" +msgstr "" + +#. module: portal_crm +#: model:ir.actions.act_window,name:portal_crm.action_contact_us +msgid "Contact Us" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,name:0 +msgid "Subject" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,opt_out:0 +msgid "Opt-Out" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,priority:0 +msgid "Priority" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,state_id:0 +msgid "State" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,partner_id:0 +msgid "Linked partner (optional). Usually created when converting the lead." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,payment_mode:0 +msgid "Payment Mode" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "New" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,type:0 +msgid "Type" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,email_from:0 +msgid "Email" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,channel_id:0 +msgid "Channel" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Name" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Lowest" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,create_date:0 +msgid "Creation Date" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Close" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "Pending" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,type:0 +msgid "Type is used to separate Leads and Opportunities" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,categ_ids:0 +msgid "Categories" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,stage_id:0 +msgid "Stage" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,user_login:0 +msgid "User Login" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,opt_out:0 +msgid "" +"If opt-out is checked, this contact has refused to receive emails or " +"unsubscribed to a campaign." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,contact_name:0 +msgid "Contact Name" +msgstr "" + +#. module: portal_crm +#: model:ir.ui.menu,name:portal_crm.portal_company_contact +msgid "Contact" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_address_email:0 +msgid "Partner Contact Email" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,planned_revenue:0 +msgid "Expected Revenue" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,task_ids:0 +msgid "Tasks" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Contact form" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,company_currency:0 +msgid "Currency" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,write_date:0 +msgid "Update Date" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_deadline:0 +msgid "Expected Closing" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,ref2:0 +msgid "Reference 2" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,user_email:0 +msgid "User Email" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_open:0 +msgid "Opened" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,state:0 +msgid "In Progress" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,partner_name:0 +msgid "" +"The name of the future partner company that will be created while converting " +"the lead into opportunity" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,planned_cost:0 +msgid "Planned Costs" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,date_deadline:0 +msgid "Estimate of the date on which the opportunity will be won." +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,email_cc:0 +msgid "" +"These email addresses will be added to the CC field of all inbound and " +"outbound emails for this record before being sent. Separate multiple email " +"addresses with a comma" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Low" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_closed:0 +#: selection:portal_crm.crm_contact_us,state:0 +msgid "Closed" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_assign:0 +msgid "Assignation Date" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,state:0 +msgid "Status" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "Normal" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,email_cc:0 +msgid "Global CC" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,street2:0 +msgid "Street2" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,id:0 +msgid "ID" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,phone:0 +msgid "Phone" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,active:0 +msgid "Active" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,user_id:0 +msgid "Salesperson" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,day_close:0 +msgid "Days to Close" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,company_ids:0 +msgid "Companies" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,section_id:0 +msgid "" +"When sending mails, the default email address is taken from the sales team." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_address_name:0 +msgid "Partner Contact Name" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_longitude:0 +msgid "Geo Longitude" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,date_assign:0 +msgid "Last date this case was forwarded/assigned to a partner" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,email_from:0 +msgid "Email address of the contact" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,city:0 +msgid "City" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Submit" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,function:0 +msgid "Function" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,referred:0 +msgid "Referred By" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,partner_assigned_id:0 +msgid "Assigned Partner" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,type:0 +msgid "Opportunity" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,partner_assigned_id:0 +msgid "Partner this case has been forwarded/assigned to." +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,country_id:0 +msgid "Country" +msgstr "" + +#. module: portal_crm +#: view:portal_crm.crm_contact_us:0 +msgid "Thank you" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,state:0 +msgid "" +"The Status is set to 'Draft', when a case is created. If the case is in " +"progress the Status is set to 'Open'. When the case is over, the Status is " +"set to 'Done'. If the case needs to be reviewed then the Status is set to " +"'Pending'." +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: portal_crm +#: help:portal_crm.crm_contact_us,type_id:0 +msgid "" +"From which campaign (seminar, marketing campaign, mass mailing, ...) did " +"this contact come from?" +msgstr "" + +#. module: portal_crm +#: selection:portal_crm.crm_contact_us,priority:0 +msgid "High" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,section_id:0 +msgid "Sales Team" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,street:0 +msgid "Street" +msgstr "" + +#. module: portal_crm +#: field:portal_crm.crm_contact_us,date_action_last:0 +msgid "Last Action" +msgstr "" + +#. module: portal_crm +#: model:ir.model,name:portal_crm.model_portal_crm_crm_contact_us +msgid "Contact form for the portal" +msgstr "" diff --git a/addons/portal_event/i18n/fr.po b/addons/portal_event/i18n/fr.po new file mode 100644 index 00000000000..81c0a603fc6 --- /dev/null +++ b/addons/portal_event/i18n/fr.po @@ -0,0 +1,59 @@ +# French 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-22 16:32+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: French \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-23 05:19+0000\n" +"X-Generator: Launchpad (build 16640)\n" + +#. module: portal_event +#: view:event.event:0 +msgid "Portal Settings" +msgstr "" + +#. module: portal_event +#: model:ir.actions.act_window,help:portal_event.action_event_view +msgid "There are no public events." +msgstr "" + +#. module: portal_event +#: selection:event.event,visibility:0 +msgid "Private" +msgstr "" + +#. module: portal_event +#: model:ir.model,name:portal_event.model_event_event +msgid "Event" +msgstr "" + +#. module: portal_event +#: model:ir.actions.act_window,name:portal_event.action_event_view +#: model:ir.ui.menu,name:portal_event.portal_company_events +msgid "Events" +msgstr "" + +#. module: portal_event +#: field:event.event,visibility:0 +msgid "Visibility" +msgstr "" + +#. module: portal_event +#: help:event.event,visibility:0 +msgid "Event's visibility in the portal's contact page" +msgstr "" + +#. module: portal_event +#: selection:event.event,visibility:0 +msgid "Public" +msgstr "" diff --git a/addons/portal_event/portal_event_view.xml b/addons/portal_event/portal_event_view.xml old mode 100755 new mode 100644 diff --git a/addons/portal_hr_employees/hr_employee_view.xml b/addons/portal_hr_employees/hr_employee_view.xml index a3182cd5b1c..eca13258ff9 100644 --- a/addons/portal_hr_employees/hr_employee_view.xml +++ b/addons/portal_hr_employees/hr_employee_view.xml @@ -33,13 +33,38 @@ - HR - Employess Kanban + HR - Employees Kanban hr.employee - + - - - + + + + +
+
+ +
+
+

+ +

+
    +
  • +
  • +
  • Tel:
  • +
  • Mobile:
  • +
  • +
  • +
+
+
+ +
+
+
diff --git a/addons/portal_hr_employees/i18n/fr.po b/addons/portal_hr_employees/i18n/fr.po new file mode 100644 index 00000000000..3fdc48a35de --- /dev/null +++ b/addons/portal_hr_employees/i18n/fr.po @@ -0,0 +1,95 @@ +# French 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-22 16:29+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: French \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-23 05:19+0000\n" +"X-Generator: Launchpad (build 16640)\n" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Coach" +msgstr "" + +#. module: portal_hr_employees +#: model:ir.actions.act_window,name:portal_hr_employees.action_team +#: view:portal_crm.crm_contact_us:0 +msgid "Our Team" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Group By..." +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Company" +msgstr "" + +#. module: portal_hr_employees +#: selection:hr.employee,visibility:0 +msgid "Public" +msgstr "" + +#. module: portal_hr_employees +#: help:hr.employee,visibility:0 +msgid "Employee's visibility in the portal's contact page" +msgstr "" + +#. module: portal_hr_employees +#: selection:hr.employee,visibility:0 +msgid "Private" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Manager" +msgstr "" + +#. module: portal_hr_employees +#: model:ir.model,name:portal_hr_employees.model_hr_employee +msgid "Employee" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Job" +msgstr "" + +#. module: portal_hr_employees +#: field:hr.employee,visibility:0 +msgid "Visibility" +msgstr "" + +#. module: portal_hr_employees +#: field:hr.employee,public_info:0 +msgid "Public Info" +msgstr "" + +#. module: portal_hr_employees +#: model:ir.model,name:portal_hr_employees.model_portal_crm_crm_contact_us +msgid "Contact form for the portal" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Department" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +#: field:portal_crm.crm_contact_us,employee_ids:0 +msgid "Employees" +msgstr "" diff --git a/addons/portal_hr_employees/i18n/lt.po b/addons/portal_hr_employees/i18n/lt.po new file mode 100644 index 00000000000..50a5a872eac --- /dev/null +++ b/addons/portal_hr_employees/i18n/lt.po @@ -0,0 +1,95 @@ +# 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:24+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: portal_hr_employees +#: view:hr.employee:0 +msgid "Coach" +msgstr "" + +#. module: portal_hr_employees +#: model:ir.actions.act_window,name:portal_hr_employees.action_team +#: view:portal_crm.crm_contact_us:0 +msgid "Our Team" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Group By..." +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Company" +msgstr "" + +#. module: portal_hr_employees +#: selection:hr.employee,visibility:0 +msgid "Public" +msgstr "" + +#. module: portal_hr_employees +#: help:hr.employee,visibility:0 +msgid "Employee's visibility in the portal's contact page" +msgstr "" + +#. module: portal_hr_employees +#: selection:hr.employee,visibility:0 +msgid "Private" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Manager" +msgstr "" + +#. module: portal_hr_employees +#: model:ir.model,name:portal_hr_employees.model_hr_employee +msgid "Employee" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Job" +msgstr "" + +#. module: portal_hr_employees +#: field:hr.employee,visibility:0 +msgid "Visibility" +msgstr "" + +#. module: portal_hr_employees +#: field:hr.employee,public_info:0 +msgid "Public Info" +msgstr "" + +#. module: portal_hr_employees +#: model:ir.model,name:portal_hr_employees.model_portal_crm_crm_contact_us +msgid "Contact form for the portal" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +msgid "Department" +msgstr "" + +#. module: portal_hr_employees +#: view:hr.employee:0 +#: field:portal_crm.crm_contact_us,employee_ids:0 +msgid "Employees" +msgstr "" diff --git a/addons/portal_project/__init__.py b/addons/portal_project/__init__.py index 26c654db9dd..164c7826e47 100644 --- a/addons/portal_project/__init__.py +++ b/addons/portal_project/__init__.py @@ -19,3 +19,4 @@ # ############################################################################## +import project diff --git a/addons/portal_project/project.py b/addons/portal_project/project.py new file mode 100644 index 00000000000..fb783c8a531 --- /dev/null +++ b/addons/portal_project/project.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-TODAY OpenERP S.A (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import osv + + +class portal_project(osv.Model): + """ Update of mail_mail class, to add the signin URL to notifications. """ + _inherit = 'project.project' + + def _get_visibility_selection(self, cr, uid, context=None): + """ Override to add portal option. """ + selection = super(portal_project, self)._get_visibility_selection(cr, uid, context=context) + idx = [item[0] for item in selection].index('public') + selection.insert((idx + 1), ('portal', 'Portal Users and Employees')) + return selection + # return [('public', 'All Users'), + # ('portal', 'Portal Users and Employees'), + # ('employees', 'Employees Only'), + # ('followers', 'Followers Only')] diff --git a/addons/portal_project/security/ir.model.access.csv b/addons/portal_project/security/ir.model.access.csv index 0e743050568..a999f5555d9 100644 --- a/addons/portal_project/security/ir.model.access.csv +++ b/addons/portal_project/security/ir.model.access.csv @@ -5,3 +5,9 @@ access_task_type,task_type,project.model_project_task_type,portal.group_portal,1 access_task_work,task_work,project.model_project_task_work,portal.group_portal,1,0,0,0 access_project_category,project_category,project.model_project_category,portal.group_portal,1,0,0,0 access_account_analytic_account,account_analytic_account,analytic.model_account_analytic_account,portal.group_portal,1,0,0,0 +access_project_anonymous,project,project.model_project_project,portal.group_anonymous,1,0,0,0 +access_task_anonymous,task,project.model_project_task,portal.group_anonymous,1,0,0,0 +access_task_type_anonymous,task_type,project.model_project_task_type,portal.group_anonymous,1,0,0,0 +access_task_work_anonymous,task_work,project.model_project_task_work,portal.group_anonymous,1,0,0,0 +access_project_category_anonymous,project_category,project.model_project_category,portal.group_anonymous,1,0,0,0 +access_account_analytic_account_anonymous,account_analytic_account,analytic.model_account_analytic_account,portal.group_anonymous,1,0,0,0 \ No newline at end of file diff --git a/addons/portal_project/security/portal_security.xml b/addons/portal_project/security/portal_security.xml index 0d995cfd70b..67e57766ebd 100644 --- a/addons/portal_project/security/portal_security.xml +++ b/addons/portal_project/security/portal_security.xml @@ -2,19 +2,67 @@ + + Project: employees: public, portal, employees or following + ['|', + ('privacy_visibility', 'in', ['public', 'portal', 'employees']), + '&', + ('privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), + ] + + + - Portal Projects - - ['|', ('privacy_visibility', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id])] + Project: portal users: public, portal or following + + ['|', + ('privacy_visibility', 'in', ['public', 'portal']), + '&', + ('privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), + ] + + Project: anonymous users: public only + + [('privacy_visibility', '=', 'public')] + + + + + Project/Task: employees: public, portal, employee or (followers and following) + ['|', + ('project_id.privacy_visibility', 'in', ['public', 'portal', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), + ] + + - Portal Tasks - - [('message_follower_ids','in', [user.partner_id.id])] + Project/Task: portal users: public or (portal and colleagues following) or (followers and following) + + ['|', '|', + ('project_id.privacy_visibility', 'in', ['public']), + '&', + ('project_id.privacy_visibility', '=', 'portal'), + ('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), + ] + + Project/Task: anonymous users: public only + + [('project_id.privacy_visibility', '=', 'public')] + + + diff --git a/addons/crm_claim/res_config.py b/addons/portal_project/tests/__init__.py similarity index 63% rename from addons/crm_claim/res_config.py rename to addons/portal_project/tests/__init__.py index aa0cb7ffa20..c79181f7710 100644 --- a/addons/crm_claim/res_config.py +++ b/addons/portal_project/tests/__init__.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Business Applications -# Copyright (C) 2004-2012 OpenERP S.A. (). +# Copyright (c) 2012-TODAY OpenERP S.A. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -19,14 +19,10 @@ # ############################################################################## -from openerp.osv import fields, osv +from . import test_access_rights -class crm_claim_settings(osv.osv_memory): - _name = 'sale.config.settings' - _inherit = ['sale.config.settings', 'fetchmail.config.settings'] +checks = [ + test_access_rights, +] - _columns = { - 'fetchmail_claim': fields.boolean("Create claims from incoming mails", - fetchmail_model='crm.claim', fetchmail_name='Incoming Claims', - help="""Allows you to configure your incoming mail server, and create claims from incoming emails."""), - } +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/portal_project/tests/test_access_rights.py b/addons/portal_project/tests/test_access_rights.py new file mode 100644 index 00000000000..a7d56cb3895 --- /dev/null +++ b/addons/portal_project/tests/test_access_rights.py @@ -0,0 +1,300 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2013-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv.orm import except_orm +from openerp.tests import common +from openerp.tools import mute_logger + + +class TestPortalProject(common.TransactionCase): + + def setUp(self): + super(TestPortalProject, self).setUp() + cr, uid = self.cr, self.uid + + # Useful models + self.project_project = self.registry('project.project') + self.project_task = self.registry('project.task') + self.res_users = self.registry('res.users') + self.res_partner = self.registry('res.partner') + + # Find Employee group + group_employee_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'base', 'group_user') + self.group_employee_id = group_employee_ref and group_employee_ref[1] or False + + # Find Project User group + group_project_user_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'project', 'group_project_user') + self.group_project_user_id = group_project_user_ref and group_project_user_ref[1] or False + + # Find Project Manager group + group_project_manager_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'project', 'group_project_manager') + self.group_project_manager_id = group_project_manager_ref and group_project_manager_ref[1] or False + + # Find Portal group + group_portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal') + self.group_portal_id = group_portal_ref and group_portal_ref[1] or False + + # Find Anonymous group + group_anonymous_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_anonymous') + self.group_anonymous_id = group_anonymous_ref and group_anonymous_ref[1] or False + + # Test users to use through the various tests + self.user_alfred_id = self.res_users.create(cr, uid, { + 'name': 'Alfred EmployeeUser', + 'login': 'alfred', + 'alias_name': 'alfred', + 'groups_id': [(6, 0, [self.group_employee_id, self.group_project_user_id])] + }) + self.user_bert_id = self.res_users.create(cr, uid, { + 'name': 'Bert Nobody', + 'login': 'bert', + 'alias_name': 'bert', + 'groups_id': [(6, 0, [])] + }) + self.user_chell_id = self.res_users.create(cr, uid, { + 'name': 'Chell Portal', + 'login': 'chell', + 'alias_name': 'chell', + 'groups_id': [(6, 0, [self.group_portal_id])] + }) + self.user_donovan_id = self.res_users.create(cr, uid, { + 'name': 'Donovan Anonymous', + 'login': 'donovan', + 'alias_name': 'donovan', + 'groups_id': [(6, 0, [self.group_anonymous_id])] + }) + self.user_ernest_id = self.res_users.create(cr, uid, { + 'name': 'Ernest Manager', + 'login': 'ernest', + 'alias_name': 'ernest', + 'groups_id': [(6, 0, [self.group_project_manager_id])] + }) + + # Test 'Pigs' project + self.project_pigs_id = self.project_project.create(cr, uid, + {'name': 'Pigs', 'privacy_visibility': 'public'}, + {'mail_create_nolog': True}) + # Various test tasks + self.task_1_id = self.project_task.create(cr, uid, + {'name': 'Test1', 'user_id': False, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.task_2_id = self.project_task.create(cr, uid, + {'name': 'Test2', 'user_id': False, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.task_3_id = self.project_task.create(cr, uid, + {'name': 'Test3', 'user_id': False, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.task_4_id = self.project_task.create(cr, uid, + {'name': 'Test4', 'user_id': self.user_alfred_id, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.task_5_id = self.project_task.create(cr, uid, + {'name': 'Test5', 'user_id': self.user_chell_id, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.task_6_id = self.project_task.create(cr, uid, + {'name': 'Test6', 'user_id': self.user_donovan_id, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + + @mute_logger('openerp.addons.base.ir.ir_model', 'openerp.osv.orm') + def test_00_project_access_rights(self): + """ Test basic project access rights, for project and portal_project """ + cr, uid, pigs_id = self.cr, self.uid, self.project_pigs_id + + # ---------------------------------------- + # CASE1: public project + # ---------------------------------------- + + # Do: Alfred reads project -> ok (employee ok public) + self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + # Test: all project tasks visible + task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_task_ids = set([self.task_1_id, self.task_2_id, self.task_3_id, self.task_4_id, self.task_5_id, self.task_6_id]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: project user cannot see all tasks of a public project') + # Test: all project tasks readable + self.project_task.read(cr, self.user_alfred_id, task_ids, ['name']) + # Test: all project tasks writable + self.project_task.write(cr, self.user_alfred_id, task_ids, {'description': 'TestDescription'}) + + # Do: Bert reads project -> crash, no group + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_bert_id, pigs_id, ['name']) + # Test: no project task visible + self.assertRaises(except_orm, self.project_task.search, + cr, self.user_bert_id, [('project_id', '=', pigs_id)]) + # Test: no project task readable + self.assertRaises(except_orm, self.project_task.read, + cr, self.user_bert_id, task_ids, ['name']) + # Test: no project task writable + self.assertRaises(except_orm, self.project_task.write, + cr, self.user_bert_id, task_ids, {'description': 'TestDescription'}) + + # Do: Chell reads project -> ok (portal ok public) + self.project_project.read(cr, self.user_chell_id, pigs_id, ['name']) + # Test: all project tasks visible + task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: project user cannot see all tasks of a public project') + # Test: all project tasks readable + self.project_task.read(cr, self.user_chell_id, task_ids, ['name']) + # Test: no project task writable + self.assertRaises(except_orm, self.project_task.write, + cr, self.user_chell_id, task_ids, {'description': 'TestDescription'}) + + # Do: Donovan reads project -> ok (anonymous ok public) + self.project_project.read(cr, self.user_donovan_id, pigs_id, ['name']) + # Test: all project tasks visible + task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: anonymous user cannot see all tasks of a public project') + # Test: all project tasks readable + self.project_task.read(cr, self.user_donovan_id, task_ids, ['name']) + # Test: no project task writable + self.assertRaises(except_orm, self.project_task.write, + cr, self.user_donovan_id, task_ids, {'description': 'TestDescription'}) + + # ---------------------------------------- + # CASE2: portal project + # ---------------------------------------- + self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'portal'}) + + # Do: Alfred reads project -> ok (employee ok public) + self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + # Test: all project tasks visible + task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: project user cannot see all tasks of a portal project') + + # Do: Bert reads project -> crash, no group + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_bert_id, pigs_id, ['name']) + # Test: no project task searchable + self.assertRaises(except_orm, self.project_task.search, + cr, self.user_bert_id, [('project_id', '=', pigs_id)]) + + # Data: task follower + self.project_task.message_subscribe_users(cr, self.user_alfred_id, [self.task_1_id, self.task_3_id], [self.user_chell_id]) + + # Do: Chell reads project -> ok (portal ok public) + self.project_project.read(cr, self.user_chell_id, pigs_id, ['name']) + # Test: only followed project tasks visible + assigned + task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + test_task_ids = set([self.task_1_id, self.task_3_id, self.task_5_id]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: portal user should see the followed tasks of a portal project') + + # Do: Donovan reads project -> ko (anonymous ko portal) + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_donovan_id, pigs_id, ['name']) + # Test: no project task visible + task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + self.assertFalse(task_ids, 'access rights: anonymous user should not see tasks of a portal project') + + # Data: task follower cleaning + self.project_task.message_unsubscribe_users(cr, self.user_alfred_id, [self.task_1_id, self.task_3_id], [self.user_chell_id]) + + # ---------------------------------------- + # CASE3: employee project + # ---------------------------------------- + self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'employees'}) + + # Do: Alfred reads project -> ok (employee ok employee) + self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + # Test: all project tasks visible + task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_task_ids = set([self.task_1_id, self.task_2_id, self.task_3_id, self.task_4_id, self.task_5_id, self.task_6_id]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: project user cannot see all tasks of an employees project') + + # Do: Bert reads project -> crash, no group + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_bert_id, pigs_id, ['name']) + + # Do: Chell reads project -> ko (portal ko employee) + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_chell_id, pigs_id, ['name']) + # Test: no project task visible + assigned + task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + self.assertFalse(task_ids, 'access rights: portal user should not see tasks of an employees project, even if assigned') + + # Do: Donovan reads project -> ko (anonymous ko employee) + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_donovan_id, pigs_id, ['name']) + # Test: no project task visible + task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + self.assertFalse(task_ids, 'access rights: anonymous user should not see tasks of an employees project') + + # ---------------------------------------- + # CASE4: followers project + # ---------------------------------------- + self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'followers'}) + + # Do: Alfred reads project -> ko (employee ko followers) + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_alfred_id, pigs_id, ['name']) + # Test: no project task visible + task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_task_ids = set([self.task_4_id]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: employee user should not see tasks of a not-followed followers project, only assigned') + + # Do: Bert reads project -> crash, no group + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_bert_id, pigs_id, ['name']) + + # Do: Chell reads project -> ko (portal ko employee) + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_chell_id, pigs_id, ['name']) + # Test: no project task visible + task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + test_task_ids = set([self.task_5_id]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: portal user should not see tasks of a not-followed followers project, only assigned') + + # Do: Donovan reads project -> ko (anonymous ko employee) + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_donovan_id, pigs_id, ['name']) + # Test: no project task visible + task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + self.assertFalse(task_ids, 'access rights: anonymous user should not see tasks of a followers project') + + # Data: subscribe Alfred, Chell and Donovan as follower + self.project_project.message_subscribe_users(cr, uid, [pigs_id], [self.user_alfred_id, self.user_chell_id, self.user_donovan_id]) + self.project_task.message_subscribe_users(cr, self.user_alfred_id, [self.task_1_id, self.task_3_id], [self.user_chell_id, self.user_alfred_id]) + + # Do: Alfred reads project -> ok (follower ok followers) + self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + # Test: followed + assigned tasks visible + task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_task_ids = set([self.task_1_id, self.task_3_id, self.task_4_id]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: employee user should not see followed + assigned tasks of a follower project') + + # Do: Chell reads project -> ok (follower ok follower) + self.project_project.read(cr, self.user_chell_id, pigs_id, ['name']) + # Test: followed + assigned tasks visible + task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + test_task_ids = set([self.task_1_id, self.task_3_id, self.task_5_id]) + self.assertEqual(set(task_ids), test_task_ids, + 'access rights: employee user should not see followed + assigned tasks of a follower project') + + # Do: Donovan reads project -> ko (anonymous ko follower even if follower) + self.assertRaises(except_orm, self.project_project.read, + cr, self.user_donovan_id, pigs_id, ['name']) diff --git a/addons/portal_project_issue/i18n/fr.po b/addons/portal_project_issue/i18n/fr.po new file mode 100644 index 00000000000..48fc9e2ea59 --- /dev/null +++ b/addons/portal_project_issue/i18n/fr.po @@ -0,0 +1,40 @@ +# French 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:06+0000\n" +"PO-Revision-Date: 2013-05-22 08:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: French \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-23 05:19+0000\n" +"X-Generator: Launchpad (build 16640)\n" + +#. module: portal_project_issue +#: view:project.issue:0 +msgid "Creation:" +msgstr "" + +#. module: portal_project_issue +#: model:ir.actions.act_window,help:portal_project_issue.project_issue_categ_act0 +msgid "" +"

\n" +" Click to create an issue.\n" +"

\n" +" You can track your issues from this menu and the action we\n" +" will take.\n" +"

\n" +" " +msgstr "" + +#. module: portal_project_issue +#: model:ir.actions.act_window,name:portal_project_issue.project_issue_categ_act0 +msgid "Issues" +msgstr "" diff --git a/addons/portal_project_issue/security/ir.model.access.csv b/addons/portal_project_issue/security/ir.model.access.csv index 80a38366b51..7355f7a9b1d 100644 --- a/addons/portal_project_issue/security/ir.model.access.csv +++ b/addons/portal_project_issue/security/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_issues,project_issue,project_issue.model_project_issue,portal.group_portal,1,0,0,0 access_case_section,crm_case_section,crm.model_crm_case_section,portal.group_portal,1,0,0,0 +access_issues_anonymous,project_issue,project_issue.model_project_issue,portal.group_anonymous,1,0,0,0 \ No newline at end of file diff --git a/addons/portal_project_issue/security/portal_security.xml b/addons/portal_project_issue/security/portal_security.xml index a121eeb593e..598c1620a82 100644 --- a/addons/portal_project_issue/security/portal_security.xml +++ b/addons/portal_project_issue/security/portal_security.xml @@ -3,14 +3,35 @@ - Portal Personal Issues - - [('message_follower_ids','in', [user.partner_id.id])] + Project/Issue: portal users: public or (portal and colleagues following) or (followers and following) + + ['|', '|', + ('project_id.privacy_visibility', 'in', ['public']), + '&', + ('project_id.privacy_visibility', '=', 'portal'), + ('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), + ] - - - - + + + + Project/Issue: employees: public, portal, employee or (followers and following) + ['|', + ('project_id.privacy_visibility', 'in', ['public', 'portal', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), + ] + + + + Project/Issue: anonymous users: public only + + [('project_id.privacy_visibility', '=', 'public')] + diff --git a/addons/portal_project_issue/tests/__init__.py b/addons/portal_project_issue/tests/__init__.py new file mode 100644 index 00000000000..fa5b47ac535 --- /dev/null +++ b/addons/portal_project_issue/tests/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2013-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import test_access_rights + +checks = [ + test_access_rights, +] + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/portal_project_issue/tests/test_access_rights.py b/addons/portal_project_issue/tests/test_access_rights.py new file mode 100644 index 00000000000..28d337a4965 --- /dev/null +++ b/addons/portal_project_issue/tests/test_access_rights.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2013-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.addons.portal_project.tests.test_access_rights import TestPortalProject +from openerp.osv.orm import except_orm +from openerp.tools import mute_logger + + +class TestPortalIssueProject(TestPortalProject): + + def setUp(self): + super(TestPortalIssueProject, self).setUp() + cr, uid = self.cr, self.uid + + # Useful models + self.project_issue = self.registry('project.issue') + + # Various test issues + self.issue_1_id = self.project_issue.create(cr, uid, + {'name': 'Test1', 'user_id': False, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.issue_2_id = self.project_issue.create(cr, uid, + {'name': 'Test2', 'user_id': False, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.issue_3_id = self.project_issue.create(cr, uid, + {'name': 'Test3', 'user_id': False, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.issue_4_id = self.project_issue.create(cr, uid, + {'name': 'Test4', 'user_id': self.user_alfred_id, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.issue_5_id = self.project_issue.create(cr, uid, + {'name': 'Test5', 'user_id': self.user_chell_id, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + self.issue_6_id = self.project_issue.create(cr, uid, + {'name': 'Test6', 'user_id': self.user_donovan_id, 'project_id': self.project_pigs_id}, + {'mail_create_nolog': True}) + + @mute_logger('openerp.addons.base.ir.ir_model', 'openerp.osv.orm') + def test_00_project_access_rights(self): + """ Test basic project access rights, for project and portal_project """ + cr, uid, pigs_id = self.cr, self.uid, self.project_pigs_id + + # ---------------------------------------- + # CASE1: public project + # ---------------------------------------- + + # Do: Alfred reads project -> ok (employee ok public) + # Test: all project issues visible + issue_ids = self.project_issue.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_issue_ids = set([self.issue_1_id, self.issue_2_id, self.issue_3_id, self.issue_4_id, self.issue_5_id, self.issue_6_id]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: project user cannot see all issues of a public project') + # Test: all project issues readable + self.project_issue.read(cr, self.user_alfred_id, issue_ids, ['name']) + # Test: all project issues writable + self.project_issue.write(cr, self.user_alfred_id, issue_ids, {'description': 'TestDescription'}) + + # Do: Bert reads project -> crash, no group + # Test: no project issue visible + self.assertRaises(except_orm, self.project_issue.search, + cr, self.user_bert_id, [('project_id', '=', pigs_id)]) + # Test: no project issue readable + self.assertRaises(except_orm, self.project_issue.read, + cr, self.user_bert_id, issue_ids, ['name']) + # Test: no project issue writable + self.assertRaises(except_orm, self.project_issue.write, + cr, self.user_bert_id, issue_ids, {'description': 'TestDescription'}) + + # Do: Chell reads project -> ok (portal ok public) + # Test: all project issues visible + issue_ids = self.project_issue.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: project user cannot see all issues of a public project') + # Test: all project issues readable + self.project_issue.read(cr, self.user_chell_id, issue_ids, ['name']) + # Test: no project issue writable + self.assertRaises(except_orm, self.project_issue.write, + cr, self.user_chell_id, issue_ids, {'description': 'TestDescription'}) + + # Do: Donovan reads project -> ok (anonymous ok public) + # Test: all project issues visible + issue_ids = self.project_issue.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: project user cannot see all issues of a public project') + + # ---------------------------------------- + # CASE2: portal project + # ---------------------------------------- + self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'portal'}) + + # Do: Alfred reads project -> ok (employee ok public) + # Test: all project issues visible + issue_ids = self.project_issue.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: project user cannot see all issues of a portal project') + + # Do: Bert reads project -> crash, no group + # Test: no project issue searchable + self.assertRaises(except_orm, self.project_issue.search, + cr, self.user_bert_id, [('project_id', '=', pigs_id)]) + + # Data: issue follower + self.project_issue.message_subscribe_users(cr, self.user_alfred_id, [self.issue_1_id, self.issue_3_id], [self.user_chell_id]) + + # Do: Chell reads project -> ok (portal ok public) + # Test: only followed project issues visible + assigned + issue_ids = self.project_issue.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + test_issue_ids = set([self.issue_1_id, self.issue_3_id, self.issue_5_id]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: portal user should see the followed issues of a portal project') + + # Data: issue follower cleaning + self.project_issue.message_unsubscribe_users(cr, self.user_alfred_id, [self.issue_1_id, self.issue_3_id], [self.user_chell_id]) + + # ---------------------------------------- + # CASE3: employee project + # ---------------------------------------- + self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'employees'}) + + # Do: Alfred reads project -> ok (employee ok employee) + # Test: all project issues visible + issue_ids = self.project_issue.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_issue_ids = set([self.issue_1_id, self.issue_2_id, self.issue_3_id, self.issue_4_id, self.issue_5_id, self.issue_6_id]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: project user cannot see all issues of an employees project') + + # Do: Chell reads project -> ko (portal ko employee) + # Test: no project issue visible + assigned + issue_ids = self.project_issue.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + self.assertFalse(issue_ids, 'access rights: portal user should not see issues of an employees project, even if assigned') + + # ---------------------------------------- + # CASE4: followers project + # ---------------------------------------- + self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'followers'}) + + # Do: Alfred reads project -> ko (employee ko followers) + # Test: no project issue visible + issue_ids = self.project_issue.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_issue_ids = set([self.issue_4_id]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: employee user should not see issues of a not-followed followers project, only assigned') + + # Do: Chell reads project -> ko (portal ko employee) + # Test: no project issue visible + issue_ids = self.project_issue.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + test_issue_ids = set([self.issue_5_id]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: portal user should not see issues of a not-followed followers project, only assigned') + + # Data: subscribe Alfred, Chell and Donovan as follower + self.project_project.message_subscribe_users(cr, uid, [pigs_id], [self.user_alfred_id, self.user_chell_id, self.user_donovan_id]) + self.project_issue.message_subscribe_users(cr, self.user_alfred_id, [self.issue_1_id, self.issue_3_id], [self.user_chell_id, self.user_alfred_id]) + + # Do: Alfred reads project -> ok (follower ok followers) + # Test: followed + assigned issues visible + issue_ids = self.project_issue.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + test_issue_ids = set([self.issue_1_id, self.issue_3_id, self.issue_4_id]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: employee user should not see followed + assigned issues of a follower project') + + # Do: Chell reads project -> ok (follower ok follower) + # Test: followed + assigned issues visible + issue_ids = self.project_issue.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + test_issue_ids = set([self.issue_1_id, self.issue_3_id, self.issue_5_id]) + self.assertEqual(set(issue_ids), test_issue_ids, + 'access rights: employee user should not see followed + assigned issues of a follower project') diff --git a/addons/portal_project_long_term/security/ir.model.access.csv b/addons/portal_project_long_term/security/ir.model.access.csv index 738c264a71c..efbc4fc2418 100644 --- a/addons/portal_project_long_term/security/ir.model.access.csv +++ b/addons/portal_project_long_term/security/ir.model.access.csv @@ -1,2 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_issues,project_phase,project_long_term.model_project_phase,portal.group_portal,1,0,0,0 +access_issues_anonymous,project_phase_anonymous,project_long_term.model_project_phase,portal.group_anonymous,1,0,0,0 diff --git a/addons/portal_project_long_term/security/portal_security.xml b/addons/portal_project_long_term/security/portal_security.xml index b46d277e4ee..d8aec542847 100644 --- a/addons/portal_project_long_term/security/portal_security.xml +++ b/addons/portal_project_long_term/security/portal_security.xml @@ -3,14 +3,17 @@ - Portal Personal Long term project - - ['|',('project_id.message_follower_ids','in', [user.partner_id.id]),('task_ids.message_follower_ids','in', [user.partner_id.id])] + Project/Phase: portal users: public or (portal and colleagues following) or (followers and following) + + [('project_id.privacy_visibility', 'in', ['public', 'portal'])] - - - - + + + + Project/Phase: anonymous users: public only + + [('project_id.privacy_visibility', '=', 'public')] + diff --git a/addons/portal_sale/i18n/lt.po b/addons/portal_sale/i18n/lt.po new file mode 100644 index 00000000000..92db39babce --- /dev/null +++ b/addons/portal_sale/i18n/lt.po @@ -0,0 +1,344 @@ +# 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:06+0000\n" +"PO-Revision-Date: 2013-04-29 15:25+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: portal_sale +#: model:ir.model,name:portal_sale.model_account_config_settings +msgid "account.config.settings" +msgstr "" + +#. module: portal_sale +#: model:ir.actions.act_window,help:portal_sale.portal_action_invoices +msgid "We haven't sent you any invoice." +msgstr "" + +#. module: portal_sale +#: model:email.template,report_name:portal_sale.email_template_edi_sale +msgid "" +"${(object.name or '').replace('/','_')}_${object.state == 'draft' and " +"'draft' or ''}" +msgstr "" + +#. module: portal_sale +#: model:res.groups,name:portal_sale.group_payment_options +msgid "View Online Payment Options" +msgstr "" + +#. module: portal_sale +#: field:account.config.settings,group_payment_options:0 +msgid "Show payment buttons to employees too" +msgstr "" + +#. module: portal_sale +#: model:email.template,subject:portal_sale.email_template_edi_sale +msgid "" +"${object.company_id.name} ${object.state in ('draft', 'sent') and " +"'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })" +msgstr "" + +#. module: portal_sale +#: model:ir.actions.act_window,help:portal_sale.action_quotations_portal +msgid "We haven't sent you any quotation." +msgstr "" + +#. module: portal_sale +#: model:ir.ui.menu,name:portal_sale.portal_sales_orders +msgid "Sales Orders" +msgstr "" + +#. module: portal_sale +#: model:res.groups,comment:portal_sale.group_payment_options +msgid "" +"Members of this group see the online payment options\n" +"on Sale Orders and Customer Invoices. These options are meant for customers " +"who are accessing\n" +"their documents through the portal." +msgstr "" + +#. module: portal_sale +#: model:email.template,body_html:portal_sale.email_template_edi_sale +msgid "" +"\n" +"
\n" +"\n" +"

Hello ${object.partner_id.name},

\n" +" \n" +"

Here is your ${object.state in ('draft', 'sent') and 'quotation' or " +"'order confirmation'} from ${object.company_id.name}:

\n" +"\n" +"

\n" +"   REFERENCES
\n" +"   Order number: ${object.name}
\n" +"   Order total: ${object.amount_total} " +"${object.pricelist_id.currency_id.name}
\n" +"   Order date: ${object.date_order}
\n" +" % if object.origin:\n" +"   Order reference: ${object.origin}
\n" +" % endif\n" +" % if object.client_order_ref:\n" +"   Your reference: ${object.client_order_ref}
\n" +" % endif\n" +" % if object.user_id:\n" +"   Your contact: ${object.user_id.name}\n" +" % endif\n" +"

\n" +"\n" +" <% set signup_url = object.get_signup_url() %>\n" +" % if signup_url:\n" +"

\n" +" You can access this document and pay online via our Customer Portal:\n" +"

\n" +" View ${object.state in ('draft', 'sent') " +"and 'Quotation' or 'Order'}\n" +" % endif\n" +"\n" +" % if object.paypal_url:\n" +"
\n" +"

It is also possible to directly pay with Paypal:

\n" +" \n" +" \n" +" \n" +" % endif\n" +"\n" +"
\n" +"

If you have any question, do not hesitate to contact us.

\n" +"

Thank you for choosing ${object.company_id.name or 'us'}!

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

\n" +" ${object.company_id.name}

\n" +"
\n" +"
\n" +" \n" +" % if object.company_id.street:\n" +" ${object.company_id.street}
\n" +" % endif\n" +" % if object.company_id.street2:\n" +" ${object.company_id.street2}
\n" +" % endif\n" +" % if object.company_id.city or object.company_id.zip:\n" +" ${object.company_id.zip} ${object.company_id.city}
\n" +" % endif\n" +" % if object.company_id.country_id:\n" +" ${object.company_id.state_id and ('%s, ' % " +"object.company_id.state_id.name) or ''} ${object.company_id.country_id.name " +"or ''}
\n" +" % endif\n" +"
\n" +" % if object.company_id.phone:\n" +"
\n" +" Phone:  ${object.company_id.phone}\n" +"
\n" +" % endif\n" +" % if object.company_id.website:\n" +"
\n" +" Web : ${object.company_id.website}\n" +"
\n" +" % endif\n" +"

\n" +"
\n" +"
\n" +" " +msgstr "" + +#. module: portal_sale +#: model:email.template,report_name:portal_sale.email_template_edi_invoice +msgid "" +"Invoice_${(object.number or '').replace('/','_')}_${object.state == 'draft' " +"and 'draft' or ''}" +msgstr "" + +#. module: portal_sale +#: model:email.template,subject:portal_sale.email_template_edi_invoice +msgid "${object.company_id.name} Invoice (Ref ${object.number or 'n/a' })" +msgstr "" + +#. module: portal_sale +#: model:ir.model,name:portal_sale.model_mail_mail +msgid "Outgoing Mails" +msgstr "" + +#. module: portal_sale +#: model:ir.actions.act_window,name:portal_sale.action_quotations_portal +#: model:ir.ui.menu,name:portal_sale.portal_quotations +msgid "Quotations" +msgstr "" + +#. module: portal_sale +#: model:ir.model,name:portal_sale.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: portal_sale +#: field:account.invoice,portal_payment_options:0 +#: field:sale.order,portal_payment_options:0 +msgid "Portal Payment Options" +msgstr "" + +#. module: portal_sale +#: help:account.config.settings,group_payment_options:0 +msgid "" +"Show online payment options on Sale Orders and Customer Invoices to " +"employees. If not checked, these options are only visible to portal users." +msgstr "" + +#. module: portal_sale +#: model:ir.actions.act_window,name:portal_sale.portal_action_invoices +#: model:ir.ui.menu,name:portal_sale.portal_invoices +msgid "Invoices" +msgstr "" + +#. module: portal_sale +#: view:account.config.settings:0 +msgid "Configure payment acquiring methods" +msgstr "" + +#. module: portal_sale +#: model:email.template,body_html:portal_sale.email_template_edi_invoice +msgid "" +"\n" +"
\n" +"\n" +"

Hello ${object.partner_id.name},

\n" +"\n" +"

A new invoice is available for you:

\n" +" \n" +"

\n" +"   REFERENCES
\n" +"   Invoice number: ${object.number}
\n" +"   Invoice total: ${object.amount_total} " +"${object.currency_id.name}
\n" +"   Invoice date: ${object.date_invoice}
\n" +" % if object.origin:\n" +"   Order reference: ${object.origin}
\n" +" % endif\n" +" % if object.user_id:\n" +"   Your contact: ${object.user_id.name}\n" +" % endif\n" +"

\n" +"\n" +" <% set signup_url = object.get_signup_url() %>\n" +" % if signup_url:\n" +"

\n" +" You can access the invoice document and pay online via our Customer " +"Portal:\n" +"

\n" +" View Invoice\n" +" % endif\n" +" \n" +" % if object.paypal_url:\n" +"
\n" +"

It is also possible to directly pay with Paypal:

\n" +" \n" +" \n" +" \n" +" % endif\n" +" \n" +"
\n" +"

If you have any question, do not hesitate to contact us.

\n" +"

Thank you for choosing ${object.company_id.name or 'us'}!

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

\n" +" ${object.company_id.name}

\n" +"
\n" +"
\n" +" \n" +" % if object.company_id.street:\n" +" ${object.company_id.street}
\n" +" % endif\n" +" % if object.company_id.street2:\n" +" ${object.company_id.street2}
\n" +" % endif\n" +" % if object.company_id.city or object.company_id.zip:\n" +" ${object.company_id.zip} ${object.company_id.city}
\n" +" % endif\n" +" % if object.company_id.country_id:\n" +" ${object.company_id.state_id and ('%s, ' % " +"object.company_id.state_id.name) or ''} ${object.company_id.country_id.name " +"or ''}
\n" +" % endif\n" +"
\n" +" % if object.company_id.phone:\n" +"
\n" +" Phone:  ${object.company_id.phone}\n" +"
\n" +" % endif\n" +" % if object.company_id.website:\n" +"
\n" +" Web : ${object.company_id.website}\n" +"
\n" +" % endif\n" +"

\n" +"
\n" +"
\n" +" " +msgstr "" + +#. module: portal_sale +#: model:ir.actions.act_window,help:portal_sale.action_orders_portal +msgid "We haven't sent you any sales order." +msgstr "" + +#. module: portal_sale +#: model:ir.model,name:portal_sale.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: portal_sale +#: model:ir.actions.act_window,name:portal_sale.action_orders_portal +msgid "Sale Orders" +msgstr "" diff --git a/addons/portal_sale/portal_sale.py b/addons/portal_sale/portal_sale.py index cd3b702d3c5..07300c5d463 100644 --- a/addons/portal_sale/portal_sale.py +++ b/addons/portal_sale/portal_sale.py @@ -104,25 +104,6 @@ class account_invoice(osv.Model): pass return action_dict - def invoice_validate(self, cr, uid, ids, context=None): - # fetch the partner's id and subscribe the partner to the invoice - document = self.browse(cr, uid, ids[0], context=context) - partner = document.partner_id - # TDE note: this code should be improved: used a real invite wizard instead of an ugly email - if partner.id not in document.message_follower_ids: - self.message_subscribe(cr, uid, ids, [partner.id], context=context) - mail_values = { - 'recipient_ids': [(4, partner.id)], - 'subject': 'Invitation to follow %s' % document.name_get()[0][1], - 'body_html': 'You have been invited to follow %s' % document.name_get()[0][1], - 'auto_delete': True, - 'type': 'email', - } - mail_obj = self.pool.get('mail.mail') - mail_id = mail_obj.create(cr, uid, mail_values, context=context) - mail_obj.send(cr, uid, [mail_id], context=context) - return super(account_invoice, self).invoice_validate(cr, uid, ids, context=context) - def get_signup_url(self, cr, uid, ids, context=None): assert len(ids) == 1 document = self.browse(cr, uid, ids[0], context=context) diff --git a/addons/portal_stock/security/portal_security.xml b/addons/portal_stock/security/portal_security.xml index 154a7fc9ddd..c5587453e40 100644 --- a/addons/portal_stock/security/portal_security.xml +++ b/addons/portal_stock/security/portal_security.xml @@ -17,19 +17,5 @@
- - Portal Personal Stock Moves - - [('message_follower_ids','in',[user.partner_id.id])] - - - - - Portal Personal Stock Warehouse Orderpoints - - [('message_follower_ids','in',[user.partner_id.id])] - - - diff --git a/addons/process/process.py b/addons/process/process.py index 30a1865af4b..d6a72148fa6 100644 --- a/addons/process/process.py +++ b/addons/process/process.py @@ -288,7 +288,6 @@ class process_process(osv.osv): }) return super(process_process, self).copy(cr, uid, id, default, context) -process_process() class process_node(osv.osv): _name = 'process.node' @@ -323,7 +322,6 @@ class process_node(osv.osv): }) return super(process_node, self).copy_data(cr, uid, id, default, context=context) -process_node() class process_node_condition(osv.osv): _name = 'process.condition' @@ -334,7 +332,6 @@ class process_node_condition(osv.osv): 'model_id': fields.many2one('ir.model', 'Object', ondelete='set null'), 'model_states': fields.char('Expression', required=True, size=128) } -process_node_condition() class process_transition(osv.osv): _name = 'process.transition' @@ -348,7 +345,6 @@ class process_transition(osv.osv): 'group_ids': fields.many2many('res.groups', 'process_transition_group_rel', 'tid', 'rid', string='Required Groups'), 'note': fields.text('Description', translate=True), } -process_transition() class process_transition_action(osv.osv): _name = 'process.transition.action' @@ -381,6 +377,5 @@ class process_transition_action(osv.osv): return super(process_transition_action, self).copy_data(cr, uid, id, default, context) -process_transition_action() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/procurement/company.py b/addons/procurement/company.py index 60e2db873e2..1fd08d967f1 100644 --- a/addons/procurement/company.py +++ b/addons/procurement/company.py @@ -33,6 +33,5 @@ class company(osv.osv): 'schedule_range': 730.0, } -company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/procurement/i18n/lt.po b/addons/procurement/i18n/lt.po new file mode 100644 index 00000000000..6b2ac1a24be --- /dev/null +++ b/addons/procurement/i18n/lt.po @@ -0,0 +1,1005 @@ +# 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:06+0000\n" +"PO-Revision-Date: 2013-04-29 15:26+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: procurement +#: model:ir.ui.menu,name:procurement.menu_stock_sched +msgid "Schedulers" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_make_procurement +msgid "Make Procurements" +msgstr "" + +#. module: procurement +#: help:procurement.order.compute.all,automatic:0 +msgid "" +"Triggers an automatic procurement for all products that have a virtual stock " +"under 0. You should probably not use this option, we suggest using a MTO " +"configuration on products." +msgstr "" + +#. module: procurement +#: view:stock.warehouse.orderpoint:0 +msgid "Group By..." +msgstr "" + +#. module: procurement +#: help:stock.warehouse.orderpoint,procurement_draft_ids:0 +msgid "Draft procurement of the product and location of that orderpoint" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "" +"required quantities are always\n" +" available" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "" +"If there are not enough quantities available, the delivery order\n" +" will wait for new products. To fulfill the " +"inventory, you should\n" +" create others rules like orderpoints." +msgstr "" + +#. module: procurement +#: field:procurement.order,procure_method:0 +#: field:product.template,procure_method:0 +msgid "Procurement Method" +msgstr "" + +#. module: procurement +#: selection:product.template,supply_method:0 +msgid "Manufacture" +msgstr "" + +#. module: procurement +#: model:process.process,name:procurement.process_process_serviceproductprocess0 +msgid "Service" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,name:procurement.action_procurement_compute +msgid "Compute Stock Minimum Rules Only" +msgstr "" + +#. module: procurement +#: view:stock.warehouse.orderpoint:0 +msgid "Rules" +msgstr "" + +#. module: procurement +#: field:procurement.order,company_id:0 +#: field:stock.warehouse.orderpoint,company_id:0 +msgid "Company" +msgstr "" + +#. module: procurement +#: field:procurement.order,product_uos_qty:0 +msgid "UoS Quantity" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Reason" +msgstr "" + +#. module: procurement +#: view:procurement.order.compute:0 +msgid "Compute Procurements" +msgstr "" + +#. module: procurement +#: field:procurement.order,message:0 +msgid "Latest error" +msgstr "" + +#. module: procurement +#: field:stock.warehouse.orderpoint,product_min_qty:0 +msgid "Minimum Quantity" +msgstr "" + +#. module: procurement +#: help:mrp.property,composition:0 +msgid "Not used in computations, for information purpose only." +msgstr "" + +#. module: procurement +#: field:stock.warehouse.orderpoint,procurement_id:0 +msgid "Latest procurement" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,help:procurement.action_orderpoint_form +msgid "" +"You can define your minimum stock rules, so that OpenERP will automatically " +"create draft manufacturing orders or purchase quotations according to the " +"stock level. Once the virtual stock of a product (= stock on hand minus all " +"confirmed orders and reservations) is below the minimum quantity, OpenERP " +"will generate a procurement request to increase the stock up to the maximum " +"quantity." +msgstr "" + +#. module: procurement +#: field:procurement.order,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: procurement +#: help:procurement.order,message:0 +msgid "Exception occurred while computing procurement orders." +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "Products" +msgstr "" + +#. module: procurement +#: selection:procurement.order,state:0 +msgid "Cancelled" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Permanent Procurement Exceptions" +msgstr "" + +#. module: procurement +#: help:procurement.order,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: procurement +#: view:procurement.order.compute.all:0 +msgid "Scheduler Parameters" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_stock_move +msgid "Stock Move" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "Stockable products" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:138 +#, python-format +msgid "Invalid Action!" +msgstr "" + +#. module: procurement +#: help:procurement.order,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: procurement +#: selection:procurement.order,state:0 +msgid "Ready" +msgstr "" + +#. module: procurement +#: field:procurement.order.compute.all,automatic:0 +msgid "Automatic orderpoint" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,help:procurement.procurement_exceptions +msgid "" +"

\n" +" Procurement Orders represent the need for a certain quantity " +"of products, at a given time, in a given location. Sales Orders are one " +"typical source of Procurement Orders (but these are distinct documents). " +"Depending on the procurement parameters and the product configuration, the " +"procurement engine will attempt to satisfy the need by reserving products " +"from stock, ordering products from a supplier, or passing a manufacturing " +"order, etc. A Procurement Exception occurs when the system cannot find a way " +"to fulfill a procurement. Some exceptions will resolve themselves " +"automatically, but others require manual intervention (those are identified " +"by a specific error message).\n" +"

\n" +" " +msgstr "" + +#. module: procurement +#: selection:procurement.order,state:0 +msgid "Confirmed" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Retry" +msgstr "" + +#. module: procurement +#: view:procurement.order.compute:0 +#: view:procurement.orderpoint.compute:0 +msgid "Parameters" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Confirm" +msgstr "" + +#. module: procurement +#: view:stock.warehouse.orderpoint:0 +msgid "Quantity Multiple" +msgstr "" + +#. module: procurement +#: help:procurement.order,origin:0 +msgid "" +"Reference of the document that created this Procurement.\n" +"This is automatically completed by OpenERP." +msgstr "" + +#. module: procurement +#: view:stock.warehouse.orderpoint:0 +msgid "Procurement Orders to Process" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_stock_warehouse_orderpoint +msgid "Minimum Inventory Rule" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:370 +#, python-format +msgid "Procurement '%s' is in exception: " +msgstr "" + +#. module: procurement +#: field:procurement.order,priority:0 +msgid "Priority" +msgstr "" + +#. module: procurement +#: view:stock.warehouse.orderpoint:0 +msgid "Reordering Rules Search" +msgstr "" + +#. module: procurement +#: selection:procurement.order,state:0 +msgid "Waiting" +msgstr "" + +#. module: procurement +#: field:procurement.order,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: procurement +#: field:procurement.order,location_id:0 +#: view:stock.warehouse.orderpoint:0 +#: field:stock.warehouse.orderpoint,location_id:0 +msgid "Location" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_stock_picking +msgid "Picking List" +msgstr "" + +#. module: procurement +#: field:make.procurement,warehouse_id:0 +#: view:stock.warehouse.orderpoint:0 +#: field:stock.warehouse.orderpoint,warehouse_id:0 +msgid "Warehouse" +msgstr "" + +#. module: procurement +#: selection:stock.warehouse.orderpoint,logic:0 +msgid "Best price (not yet active!)" +msgstr "" + +#. module: procurement +#: code:addons/procurement/schedulers.py:110 +#, python-format +msgid "PROC %d: from stock - %3.2f %-5s - %s" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_procurement_order_compute +msgid "Compute Procurement" +msgstr "" + +#. module: procurement +#: field:res.company,schedule_range:0 +msgid "Scheduler Range Days" +msgstr "" + +#. module: procurement +#: view:make.procurement:0 +msgid "Ask New Products" +msgstr "" + +#. module: procurement +#: field:make.procurement,date_planned:0 +msgid "Planned Date" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Group By" +msgstr "" + +#. module: procurement +#: field:make.procurement,qty:0 +#: field:procurement.order,product_qty:0 +msgid "Quantity" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:365 +#, python-format +msgid "Not enough stock and no minimum orderpoint rule defined." +msgstr "" + +#. module: procurement +#: field:make.procurement,uom_id:0 +#: view:procurement.order:0 +msgid "Unit of Measure" +msgstr "" + +#. module: procurement +#: selection:procurement.order,procure_method:0 +#: selection:product.template,procure_method:0 +msgid "Make to Stock" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,help:procurement.procurement_action +msgid "" +"

\n" +" Click to create a procurement order. \n" +"

\n" +" A procurement order is used to record a need for a specific\n" +" product at a specific location. Procurement orders are " +"usually\n" +" created automatically from sales orders, pull logistic rules " +"or\n" +" minimum stock rules.\n" +"

\n" +" When the procurement order is confirmed, it automatically\n" +" creates the necessary operations to fullfil the need: " +"purchase\n" +" order proposition, manufacturing order, etc.\n" +"

\n" +" " +msgstr "" + +#. module: procurement +#: help:procurement.order,procure_method:0 +msgid "" +"If you encode manually a Procurement, you probably want to use a make to " +"order method." +msgstr "" + +#. module: procurement +#: model:ir.ui.menu,name:procurement.menu_stock_procurement +msgid "Automatic Procurements" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "" +"use the available\n" +" inventory" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_procurement_order +#: model:process.process,name:procurement.process_process_procurementprocess0 +#: view:procurement.order:0 +msgid "Procurement" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,name:procurement.procurement_action +msgid "Procurement Orders" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "To Fix" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Exceptions" +msgstr "" + +#. module: procurement +#: model:process.node,note:procurement.process_node_serviceonorder0 +msgid "Assignment from Production or Purchase Order." +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_mrp_property +msgid "Property" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,name:procurement.act_make_procurement +#: view:make.procurement:0 +msgid "Procurement Request" +msgstr "" + +#. module: procurement +#: view:procurement.orderpoint.compute:0 +msgid "Compute Stock" +msgstr "" + +#. module: procurement +#: field:stock.warehouse.orderpoint,procurement_draft_ids:0 +msgid "Related Procurement Orders" +msgstr "" + +#. module: procurement +#: field:procurement.order,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: procurement +#: selection:mrp.property,composition:0 +msgid "plus" +msgstr "" + +#. module: procurement +#: help:procurement.order,state:0 +msgid "" +"When a procurement is created the status is set to 'Draft'.\n" +" If the procurement is confirmed, the status is set to 'Confirmed'. " +" \n" +"After confirming the status is set to 'Running'.\n" +" If any exception arises in the order then the status is set to " +"'Exception'.\n" +" Once the exception is removed the status becomes 'Ready'.\n" +" It is in 'Waiting'. status when the procurement is waiting for another one " +"to finish." +msgstr "" + +#. module: procurement +#: help:stock.warehouse.orderpoint,active:0 +msgid "" +"If the active field is set to False, it will allow you to hide the " +"orderpoint without removing it." +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "" +"When you sell this service, nothing special will be triggered\n" +" to deliver the customer, as you set the " +"procurement method as\n" +" 'Make to Stock'." +msgstr "" + +#. module: procurement +#: help:procurement.orderpoint.compute,automatic:0 +msgid "If the stock of a product is under 0, it will act like an orderpoint" +msgstr "" + +#. module: procurement +#: field:procurement.order,product_uom:0 +#: field:stock.warehouse.orderpoint,product_uom:0 +msgid "Product Unit of Measure" +msgstr "" + +#. module: procurement +#: constraint:stock.warehouse.orderpoint:0 +msgid "" +"You have to select a product unit of measure in the same category than the " +"default unit of measure of the product" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Procurement Lines" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "" +"as it's a consumable (as a result of this, the quantity\n" +" on hand may become negative)." +msgstr "" + +#. module: procurement +#: field:procurement.order,note:0 +msgid "Note" +msgstr "" + +#. module: procurement +#: help:stock.warehouse.orderpoint,product_min_qty:0 +msgid "" +"When the virtual stock goes below the Min Quantity specified for this field, " +"OpenERP generates a procurement to bring the forecasted quantity to the Max " +"Quantity." +msgstr "" + +#. module: procurement +#: selection:procurement.order,state:0 +msgid "Draft" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,name:procurement.action_compute_schedulers +#: model:ir.ui.menu,name:procurement.menu_stock_proc_schedulers +#: view:procurement.order.compute.all:0 +msgid "Run Schedulers" +msgstr "" + +#. module: procurement +#: view:procurement.order.compute:0 +msgid "This wizard will schedule procurements." +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +#: field:procurement.order,state:0 +msgid "Status" +msgstr "" + +#. module: procurement +#: selection:product.template,supply_method:0 +msgid "Buy" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "for the delivery order." +msgstr "" + +#. module: procurement +#: selection:procurement.order,priority:0 +msgid "Normal" +msgstr "" + +#. module: procurement +#: help:product.template,supply_method:0 +msgid "" +"Manufacture: When procuring the product, a manufacturing order or a task " +"will be generated, depending on the product type. \n" +"Buy: When procuring the product, a purchase order will be generated." +msgstr "" + +#. module: procurement +#: field:stock.warehouse.orderpoint,product_max_qty:0 +msgid "Maximum Quantity" +msgstr "" + +#. module: procurement +#: field:procurement.order,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:367 +#, python-format +msgid "Not enough stock." +msgstr "" + +#. module: procurement +#: field:stock.warehouse.orderpoint,active:0 +msgid "Active" +msgstr "" + +#. module: procurement +#: model:process.node,name:procurement.process_node_procureproducts0 +msgid "Procure Products" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:312 +#, python-format +msgid "" +"Please check the quantity in procurement order(s) for the product \"%s\", it " +"should not be 0 or less!" +msgstr "" + +#. module: procurement +#: field:procurement.order,date_planned:0 +msgid "Scheduled date" +msgstr "" + +#. module: procurement +#: selection:procurement.order,state:0 +msgid "Exception" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "" +"When you sell this product, a delivery order will be created.\n" +" OpenERP will consider that the" +msgstr "" + +#. module: procurement +#: code:addons/procurement/schedulers.py:133 +#, python-format +msgid "Automatic OP: %s" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_procurement_orderpoint_compute +msgid "Automatic Order Point" +msgstr "" + +#. module: procurement +#: field:stock.warehouse.orderpoint,qty_multiple:0 +msgid "Qty Multiple" +msgstr "" + +#. module: procurement +#: help:stock.warehouse.orderpoint,qty_multiple:0 +msgid "The procurement quantity will be rounded up to this multiple." +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_res_company +msgid "Companies" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Extra Information" +msgstr "" + +#. module: procurement +#: field:procurement.order,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: procurement +#: sql_constraint:stock.warehouse.orderpoint:0 +msgid "Qty Multiple must be greater than zero." +msgstr "" + +#. module: procurement +#: selection:stock.warehouse.orderpoint,logic:0 +msgid "Order to Max" +msgstr "" + +#. module: procurement +#: field:procurement.order,date_close:0 +msgid "Date Closed" +msgstr "" + +#. module: procurement +#: view:res.company:0 +msgid "Logistics" +msgstr "" + +#. module: procurement +#: help:product.template,procure_method:0 +msgid "" +"Make to Stock: When needed, the product is taken from the stock or we wait " +"for replenishment. \n" +"Make to Order: When needed, the product is purchased or produced." +msgstr "" + +#. module: procurement +#: field:mrp.property,composition:0 +msgid "Properties composition" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:311 +#, python-format +msgid "Data Insufficient !" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_mrp_property_group +#: field:mrp.property,group_id:0 +#: field:mrp.property.group,name:0 +msgid "Property Group" +msgstr "" + +#. module: procurement +#: view:stock.warehouse.orderpoint:0 +msgid "Misc" +msgstr "" + +#. module: procurement +#: field:stock.move,procurements:0 +msgid "Procurements" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Run Procurement" +msgstr "" + +#. module: procurement +#: selection:procurement.order,state:0 +msgid "Done" +msgstr "" + +#. module: procurement +#: view:make.procurement:0 +#: view:procurement.order.compute:0 +#: view:procurement.order.compute.all:0 +#: view:procurement.orderpoint.compute:0 +msgid "Cancel" +msgstr "" + +#. module: procurement +#: field:stock.warehouse.orderpoint,logic:0 +msgid "Reordering Mode" +msgstr "" + +#. module: procurement +#: field:procurement.order,origin:0 +msgid "Source Document" +msgstr "" + +#. module: procurement +#: selection:procurement.order,priority:0 +msgid "Not urgent" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,name:procurement.product_open_orderpoint +#: view:product.product:0 +msgid "Orderpoints" +msgstr "" + +#. module: procurement +#: help:stock.warehouse.orderpoint,product_max_qty:0 +msgid "" +"When the virtual stock goes below the Min Quantity, OpenERP generates a " +"procurement to bring the forecasted quantity to the Quantity specified as " +"Max Quantity." +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_procurement_order_compute_all +msgid "Compute all schedulers" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Late" +msgstr "" + +#. module: procurement +#: view:board.board:0 +msgid "Procurements in Exception" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,name:procurement.procurement_action5 +#: model:ir.actions.act_window,name:procurement.procurement_action_board +#: model:ir.actions.act_window,name:procurement.procurement_exceptions +#: model:ir.ui.menu,name:procurement.menu_stock_procurement_action +#: view:procurement.order:0 +msgid "Procurement Exceptions" +msgstr "" + +#. module: procurement +#: field:product.product,orderpoint_ids:0 +msgid "Minimum Stock Rules" +msgstr "" + +#. module: procurement +#: view:make.procurement:0 +msgid "" +"Fill is this for to launch a procurement request for this\n" +" product. According to the product configuration, " +"this may\n" +" trigger a draft purchase order, a manufacturing " +"order or\n" +" a new task." +msgstr "" + +#. module: procurement +#: field:procurement.order,close_move:0 +msgid "Close Move at end" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Scheduled Date" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_product_product +#: field:make.procurement,product_id:0 +#: view:procurement.order:0 +#: field:procurement.order,product_id:0 +#: field:stock.warehouse.orderpoint,product_id:0 +msgid "Product" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Temporary" +msgstr "" + +#. module: procurement +#: field:mrp.property,description:0 +#: field:mrp.property.group,description:0 +#: field:procurement.order,name:0 +msgid "Description" +msgstr "" + +#. module: procurement +#: selection:procurement.order,priority:0 +msgid "Urgent" +msgstr "" + +#. module: procurement +#: selection:procurement.order,state:0 +msgid "Running" +msgstr "" + +#. module: procurement +#: model:process.node,name:procurement.process_node_serviceonorder0 +#: selection:procurement.order,procure_method:0 +#: selection:product.template,procure_method:0 +msgid "Make to Order" +msgstr "" + +#. module: procurement +#: field:product.template,supply_method:0 +msgid "Supply Method" +msgstr "" + +#. module: procurement +#: field:procurement.order,move_id:0 +msgid "Reservation" +msgstr "" + +#. module: procurement +#: model:process.node,note:procurement.process_node_procureproducts0 +msgid "The way to procurement depends on the product type." +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "When you sell this product, OpenERP will" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Temporary Procurement Exceptions" +msgstr "" + +#. module: procurement +#: field:mrp.property,name:0 +#: field:stock.warehouse.orderpoint,name:0 +msgid "Name" +msgstr "" + +#. module: procurement +#: selection:mrp.property,composition:0 +msgid "max" +msgstr "" + +#. module: procurement +#: model:ir.actions.act_window,name:procurement.act_procurement_2_stock_warehouse_orderpoint +#: model:ir.actions.act_window,name:procurement.act_stock_warehouse_2_stock_warehouse_orderpoint +#: model:ir.actions.act_window,name:procurement.action_orderpoint_form +#: model:ir.ui.menu,name:procurement.menu_stock_order_points +#: view:stock.warehouse.orderpoint:0 +msgid "Reordering Rules" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:139 +#, python-format +msgid "Cannot delete Procurement Order(s) which are in %s state." +msgstr "" + +#. module: procurement +#: field:procurement.order,product_uos:0 +msgid "Product UoS" +msgstr "" + +#. module: procurement +#: model:ir.model,name:procurement.model_product_template +msgid "Product Template" +msgstr "" + +#. module: procurement +#: view:procurement.orderpoint.compute:0 +msgid "" +"Wizard checks all the stock minimum rules and generate procurement order." +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Search Procurement" +msgstr "" + +#. module: procurement +#: help:res.company,schedule_range:0 +msgid "" +"This is the time frame analysed by the scheduler when computing " +"procurements. All procurements that are not between today and today+range " +"are skipped for future computation." +msgstr "" + +#. module: procurement +#: selection:procurement.order,priority:0 +msgid "Very Urgent" +msgstr "" + +#. module: procurement +#: field:procurement.orderpoint.compute,automatic:0 +msgid "Automatic Orderpoint" +msgstr "" + +#. module: procurement +#: help:procurement.order,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: procurement +#: view:procurement.order:0 +msgid "Procurement started late" +msgstr "" + +#. module: procurement +#: selection:mrp.property,composition:0 +msgid "min" +msgstr "" + +#. module: procurement +#: view:make.procurement:0 +#: view:procurement.order.compute:0 +#: view:procurement.order.compute.all:0 +#: view:procurement.orderpoint.compute:0 +msgid "or" +msgstr "" + +#. module: procurement +#: code:addons/procurement/schedulers.py:134 +#, python-format +msgid "SCHEDULER" +msgstr "" + +#. module: procurement +#: view:product.product:0 +msgid "Request Procurement" +msgstr "" + +#. module: procurement +#: code:addons/procurement/schedulers.py:87 +#, python-format +msgid "PROC %d: on order - %3.2f %-5s - %s" +msgstr "" + +#. module: procurement +#: code:addons/procurement/procurement.py:339 +#, python-format +msgid "Products reserved from stock." +msgstr "" diff --git a/addons/procurement/i18n/pt_BR.po b/addons/procurement/i18n/pt_BR.po index 626e66dc827..9e425149ee3 100644 --- a/addons/procurement/i18n/pt_BR.po +++ b/addons/procurement/i18n/pt_BR.po @@ -8,15 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:06+0000\n" -"PO-Revision-Date: 2012-12-21 00:27+0000\n" -"Last-Translator: Fábio Martinelli - http://zupy.com.br " -"\n" +"PO-Revision-Date: 2013-04-18 17:42+0000\n" +"Last-Translator: Thiago Tognoli \n" "Language-Team: Brazilian Portuguese \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:43+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-19 05:24+0000\n" +"X-Generator: Launchpad (build 16567)\n" #. module: procurement #: model:ir.ui.menu,name:procurement.menu_stock_sched @@ -57,7 +56,7 @@ msgid "" " available" msgstr "" "quantidades necessárias estão sempre\n" -"                            disponíveis" +" disponíveis" #. module: procurement #: view:product.product:0 @@ -68,9 +67,9 @@ msgid "" " create others rules like orderpoints." msgstr "" "Se não houver quantidade suficiente disponível, a ordem de entrega\n" -"                            vai esperar por novos produtos. Para cumprir o " +" vai esperar por novos produtos. Para cumprir o " "inventário, você deve\n" -"                            criar outras regras como ponto de compra." +" criar outras regras como ponto de compra." #. module: procurement #: field:procurement.order,procure_method:0 @@ -632,7 +631,7 @@ msgstr "Provisório" #: model:ir.ui.menu,name:procurement.menu_stock_proc_schedulers #: view:procurement.order.compute.all:0 msgid "Run Schedulers" -msgstr "executar Agendadores" +msgstr "Executar Agendadores" #. module: procurement #: view:procurement.order.compute:0 diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 672859db909..93b9417bded 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -307,7 +307,7 @@ class procurement_order(osv.osv): move_obj = self.pool.get('stock.move') for procurement in self.browse(cr, uid, ids, context=context): if procurement.product_qty <= 0.00: - raise osv.except_osv(_('Data Insufficient !'), + raise osv.except_osv(_('Data Insufficient!'), _('Please check the quantity in procurement order(s) for the product "%s", it should not be 0 or less!' % procurement.product_id.name)) if procurement.product_id.type in ('product', 'consu'): if not procurement.move_id: diff --git a/addons/procurement/procurement_view.xml b/addons/procurement/procurement_view.xml index 7f0a28d94dc..76432157555 100644 --- a/addons/procurement/procurement_view.xml +++ b/addons/procurement/procurement_view.xml @@ -18,6 +18,7 @@ + diff --git a/addons/procurement/schedulers.py b/addons/procurement/schedulers.py index 1009873beb2..7c9d5ec3290 100644 --- a/addons/procurement/schedulers.py +++ b/addons/procurement/schedulers.py @@ -155,7 +155,7 @@ class procurement_order(osv.osv): warehouse_obj = self.pool.get('stock.warehouse') warehouse_ids = warehouse_obj.search(cr, uid, [], context=context) - products_ids = product_obj.search(cr, uid, [('purchase_ok', '=', True)], order='id', context=context) + products_ids = product_obj.search(cr, uid, [], order='id', context=context) for warehouse in warehouse_obj.browse(cr, uid, warehouse_ids, context=context): context['warehouse'] = warehouse diff --git a/addons/procurement/stock_orderpoint.xml b/addons/procurement/stock_orderpoint.xml index 31c48046d64..67d610c65c9 100644 --- a/addons/procurement/stock_orderpoint.xml +++ b/addons/procurement/stock_orderpoint.xml @@ -1,4 +1,3 @@ - @@ -7,50 +6,50 @@ 25.0 5.0 - + - + 10.0 5.0 - + - + 12.0 5.0 - + - + 50.0 10.0 - + - + 15.0 5.0 - + - + 5.0 3.0 - + - + - + \ No newline at end of file diff --git a/addons/procurement/wizard/make_procurement_product.py b/addons/procurement/wizard/make_procurement_product.py index aab49bf8e80..bf83bc73f1a 100644 --- a/addons/procurement/wizard/make_procurement_product.py +++ b/addons/procurement/wizard/make_procurement_product.py @@ -126,6 +126,5 @@ class make_procurement(osv.osv_memory): return res -make_procurement() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/procurement/wizard/mrp_procurement.py b/addons/procurement/wizard/mrp_procurement.py index 56386bf234e..fd5a9b530b6 100644 --- a/addons/procurement/wizard/mrp_procurement.py +++ b/addons/procurement/wizard/mrp_procurement.py @@ -46,7 +46,6 @@ class procurement_compute(osv.osv_memory): threaded_calculation.start() return {} -procurement_compute() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/procurement/wizard/orderpoint_procurement.py b/addons/procurement/wizard/orderpoint_procurement.py index 2d5b91d4c81..afc8e2a721f 100644 --- a/addons/procurement/wizard/orderpoint_procurement.py +++ b/addons/procurement/wizard/orderpoint_procurement.py @@ -68,6 +68,5 @@ class procurement_compute(osv.osv_memory): threaded_calculation.start() return {'type': 'ir.actions.act_window_close'} -procurement_compute() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/procurement/wizard/schedulers_all.py b/addons/procurement/wizard/schedulers_all.py index c60ac989274..aab9657ae5d 100644 --- a/addons/procurement/wizard/schedulers_all.py +++ b/addons/procurement/wizard/schedulers_all.py @@ -65,6 +65,5 @@ class procurement_compute_all(osv.osv_memory): threaded_calculation.start() return {'type': 'ir.actions.act_window_close'} -procurement_compute_all() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product/partner.py b/addons/product/partner.py index 1d11e909346..fbfee76d0b2 100644 --- a/addons/product/partner.py +++ b/addons/product/partner.py @@ -36,7 +36,9 @@ class res_partner(osv.osv): help="This pricelist will be used, instead of the default one, for sales to the current partner"), } -res_partner() + def _commercial_fields(self, cr, uid, context=None): + return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['property_product_pricelist'] + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product/partner_view.xml b/addons/product/partner_view.xml index acb087533ac..5117da6044e 100644 --- a/addons/product/partner_view.xml +++ b/addons/product/partner_view.xml @@ -8,9 +8,12 @@ - + +
+

Pricelists are managed on

diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py index 757cce2ae95..6fc926980dd 100644 --- a/addons/product/pricelist.py +++ b/addons/product/pricelist.py @@ -64,7 +64,6 @@ class price_type(osv.osv): "currency_id": _get_currency } -price_type() #---------------------------------------------------------- # Price lists @@ -77,7 +76,6 @@ class product_pricelist_type(osv.osv): 'name': fields.char('Name',size=64, required=True, translate=True), 'key': fields.char('Key', size=64, required=True, help="Used in the code to select specific prices based on the context. Keep unchanged."), } -product_pricelist_type() class product_pricelist(osv.osv): @@ -236,7 +234,10 @@ class product_pricelist(osv.osv): qty, context=context)[res['base_pricelist_id']] ptype_src = self.browse(cr, uid, res['base_pricelist_id']).currency_id.id uom_price_already_computed = True - price = currency_obj.compute(cr, uid, ptype_src, res['currency_id'], price_tmp, round=False) + price = currency_obj.compute(cr, uid, + ptype_src, res['currency_id'], + price_tmp, round=False, + context=context) elif res['base'] == -2: # this section could be improved by moving the queries outside the loop: where = [] @@ -305,7 +306,6 @@ class product_pricelist(osv.osv): res.update({'item_id': {ids[-1]: res_multi.get('item_id', ids[-1])}}) return res -product_pricelist() class product_pricelist_version(osv.osv): @@ -363,7 +363,6 @@ class product_pricelist_version(osv.osv): ['date_start', 'date_end']) ] -product_pricelist_version() class product_pricelist_item(osv.osv): def _price_field_get(self, cr, uid, context=None): @@ -443,7 +442,6 @@ class product_pricelist_item(osv.osv): if prod[0]['code']: return {'value': {'name': prod[0]['code']}} return {} -product_pricelist_item() diff --git a/addons/product/process/product_process.xml b/addons/product/process/product_process.xml index 03ce904abad..652710fac94 100644 --- a/addons/product/process/product_process.xml +++ b/addons/product/process/product_process.xml @@ -43,8 +43,8 @@ - - + +
diff --git a/addons/product/product.py b/addons/product/product.py index 82b37f7b9e8..656812bebbb 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -84,7 +84,6 @@ class product_uom_categ(osv.osv): _columns = { 'name': fields.char('Name', size=64, required=True, translate=True), } -product_uom_categ() class product_uom(osv.osv): _name = 'product.uom' @@ -208,7 +207,6 @@ class product_uom(osv.osv): raise osv.except_osv(_('Warning!'),_("Cannot change the category of existing Unit of Measure '%s'.") % (uom.name,)) return super(product_uom, self).write(cr, uid, ids, vals, context=context) -product_uom() class product_ul(osv.osv): @@ -218,7 +216,6 @@ class product_ul(osv.osv): 'name' : fields.char('Name', size=64,select=True, required=True, translate=True), 'type' : fields.selection([('unit','Unit'),('pack','Pack'),('box', 'Box'), ('pallet', 'Pallet')], 'Type', required=True), } -product_ul() #---------------------------------------------------------- @@ -283,7 +280,6 @@ class product_category(osv.osv): def child_get(self, cr, uid, ids): return [ids] -product_category() #---------------------------------------------------------- @@ -296,9 +292,14 @@ class product_template(osv.osv): _columns = { 'name': fields.char('Name', size=128, required=True, translate=True, select=True), 'product_manager': fields.many2one('res.users','Product Manager'), - 'description': fields.text('Description',translate=True), - 'description_purchase': fields.text('Purchase Description',translate=True), - 'description_sale': fields.text('Sale Description',translate=True), + 'description': fields.text('Description',translate=True, + help="A precise description of the Product, used only for internal information purposes."), + 'description_purchase': fields.text('Purchase Description',translate=True, + help="A description of the Product that you want to communicate to your suppliers. " + "This description will be copied to every Purchase Order, Reception and Supplier Invoice/Refund."), + 'description_sale': fields.text('Sale Description',translate=True, + help="A description of the Product that you want to communicate to your customers. " + "This description will be copied to every Sale Order, Delivery Order and Customer Invoice/Refund"), 'type': fields.selection([('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Consumable are product where you don't manage stock, a service is a non-material product provided by a company or an individual."), 'produce_delay': fields.float('Manufacturing Lead Time', help="Average delay in days to produce this product. In the case of multi-level BOM, the manufacturing lead times of the components will be added."), 'rental': fields.boolean('Can be Rent'), @@ -401,7 +402,6 @@ class product_template(osv.osv): pass return super(product_template, self).name_get(cr, user, ids, context) -product_template() class product_product(osv.osv): def view_header_get(self, cr, uid, view_id, view_type, context=None): @@ -523,6 +523,13 @@ class product_product(osv.osv): def _set_image(self, cr, uid, id, name, value, args, context=None): return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context) + def _get_name_template_ids(self, cr, uid, ids, context=None): + result = set() + template_ids = self.pool.get('product.product').search(cr, uid, [('product_tmpl_id', 'in', ids)]) + for el in template_ids: + result.add(el) + return list(result) + _defaults = { 'active': lambda *a: 1, 'price_extra': lambda *a: 0.0, @@ -554,7 +561,11 @@ class product_product(osv.osv): 'price_extra': fields.float('Variant Price Extra', digits_compute=dp.get_precision('Product Price')), 'price_margin': fields.float('Variant Price Margin', digits_compute=dp.get_precision('Product Price')), 'pricelist_id': fields.dummy(string='Pricelist', relation='product.pricelist', type='many2one'), - 'name_template': fields.related('product_tmpl_id', 'name', string="Template Name", type='char', size=128, store=True, select=True), + 'name_template': fields.related('product_tmpl_id', 'name', string="Template Name", type='char', size=128, store={ + 'product.template': (_get_name_template_ids, ['name'], 10), + 'product.product': (lambda self, cr, uid, ids, c=None: ids, [], 10), + + }, select=True), 'color': fields.integer('Color Index'), # image: all image fields are base64 encoded and PIL-supported 'image': fields.binary("Image", @@ -753,7 +764,6 @@ class product_product(osv.osv): args.append((('categ_id', 'child_of', context['search_default_categ_id']))) return super(product_product, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=False) -product_product() class product_packaging(osv.osv): _name = "product.packaging" @@ -819,7 +829,6 @@ class product_packaging(osv.osv): return (10 - (sum % 10)) % 10 checksum = staticmethod(checksum) -product_packaging() class product_supplierinfo(osv.osv): @@ -893,7 +902,6 @@ class product_supplierinfo(osv.osv): res[supplier.id] = price return res _order = 'sequence' -product_supplierinfo() class pricelist_partnerinfo(osv.osv): @@ -905,7 +913,6 @@ class pricelist_partnerinfo(osv.osv): 'price': fields.float('Unit Price', required=True, digits_compute=dp.get_precision('Product Price'), help="This price will be considered as a price for the supplier Unit of Measure if any or the default Unit of Measure of the product otherwise"), } _order = 'min_quantity asc' -pricelist_partnerinfo() class res_currency(osv.osv): _inherit = 'res.currency' diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml index 00e925fd6a0..bcc0ae838ae 100644 --- a/addons/product/product_view.xml +++ b/addons/product/product_view.xml @@ -88,6 +88,7 @@
+ diff --git a/addons/product/report/product_label.xsl b/addons/product/report/product_label.xsl index 641db73ea7d..5dbb2d64a28 100644 --- a/addons/product/report/product_label.xsl +++ b/addons/product/report/product_label.xsl @@ -67,7 +67,7 @@
diff --git a/addons/product/wizard/product_price.py b/addons/product/wizard/product_price.py index 8989e97d656..5b5c4ccd834 100644 --- a/addons/product/wizard/product_price.py +++ b/addons/product/wizard/product_price.py @@ -60,6 +60,5 @@ class product_price_list(osv.osv_memory): 'report_name': 'product.pricelist', 'datas': datas, } -product_price_list() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product_expiry/product_expiry.py b/addons/product_expiry/product_expiry.py index 457b4428522..4d8fd49ec4f 100644 --- a/addons/product_expiry/product_expiry.py +++ b/addons/product_expiry/product_expiry.py @@ -74,7 +74,6 @@ class stock_production_lot(osv.osv): 'removal_date': _get_date('removal_time'), 'alert_date': _get_date('alert_time'), } -stock_production_lot() class product_product(osv.osv): _inherit = 'product.product' @@ -88,5 +87,4 @@ class product_product(osv.osv): 'alert_time': fields.integer('Product Alert Time', help='When a new a Serial Number is issued, this is the number of days before an alert should be notified.'), } -product_product() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product_manufacturer/product_manufacturer.py b/addons/product_manufacturer/product_manufacturer.py index fdd25133433..ea7acf66670 100644 --- a/addons/product_manufacturer/product_manufacturer.py +++ b/addons/product_manufacturer/product_manufacturer.py @@ -28,7 +28,6 @@ class product_product(osv.osv): 'manufacturer_pref' : fields.char('Manufacturer Product Code', size=64), 'attribute_ids': fields.one2many('product.manufacturer.attribute', 'product_id', 'Attributes'), } -product_product() class product_attribute(osv.osv): _name = "product.manufacturer.attribute" @@ -38,6 +37,5 @@ class product_attribute(osv.osv): 'value' : fields.char('Value', size=64), 'product_id': fields.many2one('product.product', 'Product', ondelete='cascade'), } -product_attribute() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product_margin/product_margin.py b/addons/product_margin/product_margin.py index f9187647f35..1bbfe8c285b 100644 --- a/addons/product_margin/product_margin.py +++ b/addons/product_margin/product_margin.py @@ -128,6 +128,5 @@ class product_product(osv.osv): help="Expected margin * 100 / Expected Sale"), } -product_product() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product_margin/wizard/product_margin.py b/addons/product_margin/wizard/product_margin.py index 6c54bd72be3..7a56ed2e13d 100644 --- a/addons/product_margin/wizard/product_margin.py +++ b/addons/product_margin/wizard/product_margin.py @@ -81,6 +81,5 @@ class product_margin(osv.osv_memory): 'search_view_id': id['res_id'] } -product_margin() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product_visible_discount/product_visible_discount.py b/addons/product_visible_discount/product_visible_discount.py index 3928c2e4676..4f8a7b0b9cc 100644 --- a/addons/product_visible_discount/product_visible_discount.py +++ b/addons/product_visible_discount/product_visible_discount.py @@ -33,7 +33,6 @@ class product_pricelist(osv.osv): 'visible_discount': True, } -product_pricelist() class sale_order_line(osv.osv): _inherit = "sale.order.line" @@ -95,7 +94,6 @@ class sale_order_line(osv.osv): result['discount'] = 0.0 return res -sale_order_line() class account_invoice_line(osv.osv): _inherit = "account.invoice.line" @@ -161,6 +159,5 @@ class account_invoice_line(osv.osv): result['discount']=0.0 return res -account_invoice_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/company.py b/addons/project/company.py index 459c24e7b8a..19f40436070 100644 --- a/addons/project/company.py +++ b/addons/project/company.py @@ -31,7 +31,6 @@ class res_company(osv.osv): "forget to setup the right unit of measure in your employees.", ), } -res_company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/html/Mario-Riva.png b/addons/project/html/Mario-Riva.png new file mode 100644 index 00000000000..35b030a4265 Binary files /dev/null and b/addons/project/html/Mario-Riva.png differ diff --git a/addons/project/html/Yoshi-Tashiro.png b/addons/project/html/Yoshi-Tashiro.png new file mode 100644 index 00000000000..f3457a9088e Binary files /dev/null and b/addons/project/html/Yoshi-Tashiro.png differ diff --git a/addons/project/html/index.html b/addons/project/html/index.html new file mode 100644 index 00000000000..93f1be8a41d --- /dev/null +++ b/addons/project/html/index.html @@ -0,0 +1,197 @@ +
+
+

Project Management

+

Infinitely flexible. Incredibly easy to use.

+
+
+ + + + +
+
+
+

+OpenERP's collaborative and realtime project management helps your team get +work done. Keep track of everything, from the big picture to the minute +details, from the customer contract to the billing. +

+ +
+
+
+ +
+
+

Designed to fit your own process

+
+

+Organize projects around your own processes. Work on tasks and issues using the kanban view, schedule tasks using the gantt chart +and control deadlines in the calendar view. Every project may have it's own stages +allowing teams to optimize their job. +

+
+
+

Kanban

+
+ +
+
+
+

Gantt Charts

+ +

+
+
+

Calendar

+ +
+
+
+ +
+
+

Easy to use

+
+ +
+
+

+Get organized as fast as you can think. The easy-to-use interface takes no time +to learn, and every action is instantaneous, so there’s nothing standing +between you and your sweet productive flow. +

+
+
+
+ +
+

Work Together

+

Real time chats, document sharing, email integration

+
+
+

+Use open chatter to communicate with your team or customers and share comments +and documents on tasks and issues. Integrate discussion fast with the email +integration. +

+Talk to others users or customers with the live chat feature. +

+
+
+ +
+
+
+ +
+
+

Collaborative Writing

+

The power of etherpad, inside your tasks

+
+ +
+
+

+Collaboratively edit the same specifications or meeting minutes right inside the +application. The incorporated etherpad feature allows several people to work +on the same tasks, at the same time. +

+

+This is very efficient for scrum meetings, meeting minutes or complex +specifications. Every user has their own color and you can replay the whole +creation of the content. +

+
+
+
+ +
+
+

Get Work Done

+
+

+Get alerts on followed events to stay up to date with what interests you. Use +instant green/red visual indicators to scan through what has been done and what +requires your attention. +

+
+
+ +
+
+
+ +
+
+

Timesheets, Contracts & Invoicing

+
+ +
+
+

+Projects are automatically integrated with customer contracts allowing you to +invoice based on time & materials and record timesheets easily. +

+
+
+
+ + +
+
+

Track Issues

+

Support services, helpdesk, bug tracker, etc.

+
+

+Single out the issues that arise in a project in order to have a better focus +on resolving them. Integrate customer interaction on every issue and get +accurate reports on your team's performance. +

+
+
+
+ +
+
+
+
+ +
+
+
+

Many companies already enjoy it

+

Hear what they have to say !

+
+
+
+ + OpenERP provides essential platform for our project management. + Things are better organized and much more visible with it. + + + +
Yoshi Tashiro
+
Managing Director, RoomsFor (Hong Kong)
+
+
+
+
+
+ + The possibility to link the Project Management to Sales and Manufacturing widely + extends the range of possible applications beyond the needs of service companies. + + + +
Mario Riva
+ +
+
+
+
+
+
+
diff --git a/addons/project/html/project_01.png b/addons/project/html/project_01.png new file mode 100644 index 00000000000..0c86a2965d5 Binary files /dev/null and b/addons/project/html/project_01.png differ diff --git a/addons/project/html/project_calendar.png b/addons/project/html/project_calendar.png new file mode 100644 index 00000000000..f8c8fca7662 Binary files /dev/null and b/addons/project/html/project_calendar.png differ diff --git a/addons/project/html/project_chat.png b/addons/project/html/project_chat.png new file mode 100644 index 00000000000..8cb771e876f Binary files /dev/null and b/addons/project/html/project_chat.png differ diff --git a/addons/project/html/project_easy.png b/addons/project/html/project_easy.png new file mode 100644 index 00000000000..4ffde14b42b Binary files /dev/null and b/addons/project/html/project_easy.png differ diff --git a/addons/project/html/project_etherpad.png b/addons/project/html/project_etherpad.png new file mode 100644 index 00000000000..038b210ee18 Binary files /dev/null and b/addons/project/html/project_etherpad.png differ diff --git a/addons/project/html/project_gantt.png b/addons/project/html/project_gantt.png new file mode 100644 index 00000000000..34486b98558 Binary files /dev/null and b/addons/project/html/project_gantt.png differ diff --git a/addons/project/html/project_illu_01.png b/addons/project/html/project_illu_01.png new file mode 100644 index 00000000000..4fff4837faa Binary files /dev/null and b/addons/project/html/project_illu_01.png differ diff --git a/addons/project/html/project_kanban.png b/addons/project/html/project_kanban.png new file mode 100644 index 00000000000..c541d3b5d08 Binary files /dev/null and b/addons/project/html/project_kanban.png differ diff --git a/addons/project/html/project_kpi.png b/addons/project/html/project_kpi.png new file mode 100644 index 00000000000..c58f8176098 Binary files /dev/null and b/addons/project/html/project_kpi.png differ diff --git a/addons/project/html/project_timesheet.png b/addons/project/html/project_timesheet.png new file mode 100644 index 00000000000..d06c3a924ec Binary files /dev/null and b/addons/project/html/project_timesheet.png differ diff --git a/addons/project/i18n/ru.po b/addons/project/i18n/ru.po index 1743d66e55d..b64662f916b 100644 --- a/addons/project/i18n/ru.po +++ b/addons/project/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:04+0000\n" -"PO-Revision-Date: 2013-03-14 06:44+0000\n" +"PO-Revision-Date: 2013-05-28 06:22+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 04:56+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-05-29 05:37+0000\n" +"X-Generator: Launchpad (build 16640)\n" #. module: project #: view:project.project:0 @@ -27,6 +27,8 @@ msgid "" "If checked, this contract will be available in the project menu and you will " "be able to manage tasks or track issues" msgstr "" +"Если выбрано, этот контракт станет активным в меню проекта, и вы сможете " +"редактировать задачи или отслеживать проблемы" #. module: project #: field:project.project,progress_rate:0 @@ -217,7 +219,7 @@ msgstr "Предложение контакта" #. module: project #: help:project.config.settings,group_time_work_estimation_tasks:0 msgid "Allows you to compute Time Estimation on tasks." -msgstr "" +msgstr "Позволяет вычислить расход времени на задачи." #. module: project #: field:report.project.task.user,user_id:0 @@ -913,6 +915,8 @@ msgid "" "Provides management of issues/bugs in projects.\n" " This installs the module project_issue." msgstr "" +"Обеспечивает управление проблем / ошибок в проектах.\n" +" Устанавливает модуль project_issue." #. module: project #: help:project.task,kanban_state:0 @@ -927,7 +931,7 @@ msgstr "" #. module: project #: view:project.task:0 msgid "10" -msgstr "" +msgstr "10" #. module: project #: help:project.project,analytic_account_id:0 @@ -953,7 +957,7 @@ msgstr "Отменить" #. module: project #: view:project.project:0 msgid "Other Info" -msgstr "" +msgstr "Прочая информация" #. module: project #: view:project.task.delegate:0 @@ -981,6 +985,8 @@ msgid "" "Follow this project to automatically track the events associated to tasks " "and issues of this project." msgstr "" +"Позволяет проекту автоматически отслеживать события, связанные с задачами и " +"проблемами этого проекта." #. module: project #: view:project.task:0 @@ -990,7 +996,7 @@ msgstr "Исполнитель" #. module: project #: model:mail.message.subtype,name:project.mt_task_stage msgid "Stage Changed" -msgstr "" +msgstr "Стадия изменена" #. module: project #: view:project.project:0 @@ -1006,7 +1012,7 @@ msgstr "Важное" #. module: project #: field:project.category,name:0 msgid "Name" -msgstr "" +msgstr "Название" #. module: project #: selection:report.project.task.user,month:0 @@ -1033,7 +1039,7 @@ msgstr "Общие" #: help:project.project,message_ids:0 #: help:project.task,message_ids:0 msgid "Messages and communication history" -msgstr "" +msgstr "Сообщения и история общения" #. module: project #: view:project.project:0 @@ -1041,6 +1047,8 @@ msgid "" "To invoice or setup invoicing and renewal options, go to the related " "contract:" msgstr "" +"Для выставления счета или изменения счета и обновления вариантов, перейти к " +"соответствующему контракту:" #. module: project #: field:project.task.delegate,state:0 @@ -1097,7 +1105,7 @@ msgstr "Порученные задания" #: view:project.task:0 #: field:project.task,message_unread:0 msgid "Unread Messages" -msgstr "" +msgstr "Непрочитанные" #. module: project #: view:project.task:0 @@ -1139,7 +1147,7 @@ msgstr "Показывать только срочные задания" #. module: project #: model:project.category,name:project.project_category_04 msgid "Usability" -msgstr "" +msgstr "Удобство использования" #. module: project #: view:report.project.task.user:0 @@ -1156,7 +1164,7 @@ msgstr "Выполнил(а)" #: code:addons/project/project.py:181 #, python-format msgid "Invalid Action!" -msgstr "" +msgstr "Неверное действие!" #. module: project #: help:project.task.type,state:0 @@ -1165,6 +1173,9 @@ msgid "" "stage. For example, if a stage is related to the status 'Close', when your " "document reaches this stage, it is automatically closed." msgstr "" +"Статус документа автоматически изменяется по выбранному этапу. Например, " +"если стадия связана со статусом «Закрыть» , когда ваш документ достигает " +"этой стадии, оно автоматически закрывается." #. module: project #: view:project.task:0 @@ -1174,7 +1185,7 @@ msgstr "Доп. информация" #. module: project #: view:project.task:0 msgid "Edit..." -msgstr "" +msgstr "Изменить..." #. module: project #: view:report.project.task.user:0 @@ -1185,7 +1196,7 @@ msgstr "№ задачи" #. module: project #: field:project.project,doc_count:0 msgid "Number of documents attached" -msgstr "" +msgstr "Количество прикрепленных документов" #. module: project #: field:project.task,priority:0 @@ -1205,6 +1216,9 @@ msgid "" "automatically synchronizedwith Tasks (or optionally Issues if the Issue " "Tracker module is installed)." msgstr "" +"Внутренние e-mail, связанный с этим проектом. Входящие письма автоматически " +"синхронизируются с заданиями (или проблемами, если модуль Issue Tracker " +"установлен)." #. module: project #: model:ir.actions.act_window,help:project.open_task_type_form @@ -1237,7 +1251,7 @@ msgstr "%s (копия)" #. module: project #: model:mail.message.subtype,name:project.mt_project_task_stage msgid "Task Stage Changed" -msgstr "" +msgstr "Этап задачи изменен" #. module: project #: view:project.task:0 @@ -1269,12 +1283,12 @@ msgstr "Время отсрочки" #. module: project #: view:project.project:0 msgid "Team" -msgstr "" +msgstr "Группа" #. module: project #: help:project.config.settings,time_unit:0 msgid "This will set the unit of measure used in projects and tasks." -msgstr "" +msgstr "Установить единицу измерения, используемую в проектах и задачах." #. module: project #: selection:project.task,priority:0 @@ -1328,7 +1342,7 @@ msgstr "Заголовок вашего проверочного задания" #. module: project #: field:project.config.settings,time_unit:0 msgid "Working time unit" -msgstr "" +msgstr "Единица рабочего времени" #. module: project #: view:project.project:0 @@ -1344,7 +1358,7 @@ msgstr "Низкий" #. module: project #: selection:project.project,state:0 msgid "Closed" -msgstr "" +msgstr "Закрыто" #. module: project #: view:project.project:0 @@ -1366,7 +1380,7 @@ msgstr "В ожидании" #: view:project.category:0 #: field:project.task,categ_ids:0 msgid "Tags" -msgstr "" +msgstr "Теги" #. module: project #: model:ir.model,name:project.model_project_task_history @@ -1386,7 +1400,7 @@ msgstr "" #. module: project #: help:project.config.settings,group_manage_delegation_task:0 msgid "Allows you to delegate tasks to other users." -msgstr "" +msgstr "Позволяет делегировать задачи другим пользователям." #. module: project #: field:project.project,active:0 @@ -1415,7 +1429,7 @@ msgstr "" #. module: project #: view:project.config.settings:0 msgid "Helpdesk & Support" -msgstr "" +msgstr "Поддержка" #. module: project #: help:report.project.task.user,opening_days:0 @@ -1441,7 +1455,7 @@ msgstr "" #: code:addons/project/project.py:220 #, python-format msgid "Attachments" -msgstr "" +msgstr "Вложения" #. module: project #: view:project.task:0 @@ -1464,6 +1478,8 @@ msgid "" "You cannot delete a project containing tasks. You can either delete all the " "project's tasks and then delete the project or simply deactivate the project." msgstr "" +"Вы не можете удалить проект, содержащий задачи. Вы можете либо удалить все " +"задачи проекта, а затем удалить проект или просто сделать проект неактивным." #. module: project #: model:process.transition.action,name:project.process_transition_action_draftopentask0 @@ -1474,7 +1490,7 @@ msgstr "Открытые" #. module: project #: field:project.project,privacy_visibility:0 msgid "Privacy / Visibility" -msgstr "" +msgstr "Безопасность/Видимость" #. module: project #: view:project.task:0 @@ -1488,7 +1504,7 @@ msgstr "Оставшееся время" #. module: project #: model:mail.message.subtype,description:project.mt_task_stage msgid "Stage changed" -msgstr "" +msgstr "Этап изменен" #. module: project #: constraint:project.task:0 @@ -1521,7 +1537,7 @@ msgstr "Общее время" #. module: project #: model:ir.model,name:project.model_project_config_settings msgid "project.config.settings" -msgstr "" +msgstr "project.config.settings" #. module: project #: model:project.task.type,name:project.project_tt_development @@ -1586,12 +1602,12 @@ msgstr "Назначить на" #. module: project #: model:res.groups,name:project.group_time_work_estimation_tasks msgid "Time Estimation on Tasks" -msgstr "" +msgstr "Оценка времени на задачи" #. module: project #: field:project.task,total_hours:0 msgid "Total" -msgstr "" +msgstr "Всего" #. module: project #: model:process.node,note:project.process_node_taskbydelegate0 @@ -1601,7 +1617,7 @@ msgstr "Поручить ваше задание другому пользова #. module: project #: model:mail.message.subtype,description:project.mt_task_started msgid "Task started" -msgstr "" +msgstr "Задание начато" #. module: project #: help:project.task.reevaluate,remaining_hours:0 @@ -1614,6 +1630,8 @@ msgid "" "This stage is not visible, for example in status bar or kanban view, when " "there are no records in that stage to display." msgstr "" +"Эта стадия не видима, например в статус-баре или виде канбан, когда нет " +"записей на этой стадии для отображения." #. module: project #: view:project.task:0 @@ -1643,7 +1661,7 @@ msgstr "Проекты в ожидании" #. module: project #: view:project.task:0 msgid "Remaining" -msgstr "" +msgstr "Осталось" #. module: project #: field:project.task,progress:0 @@ -1672,17 +1690,17 @@ msgstr "" #. module: project #: field:project.config.settings,module_project_issue:0 msgid "Track issues and bugs" -msgstr "" +msgstr "Отслеживание проблем и ошибок" #. module: project #: field:project.config.settings,module_project_mrp:0 msgid "Generate tasks from sale orders" -msgstr "" +msgstr "Создание задач из заказов" #. module: project #: model:ir.ui.menu,name:project.menu_task_types_view msgid "Task Stages" -msgstr "" +msgstr "Этапы задач" #. module: project #: model:process.node,note:project.process_node_drafttask0 @@ -1693,7 +1711,7 @@ msgstr "Определить требования и установить зап #: field:project.project,message_ids:0 #: field:project.task,message_ids:0 msgid "Messages" -msgstr "" +msgstr "Сообщения" #. module: project #: field:project.project,color:0 @@ -1752,17 +1770,17 @@ msgstr "Дата окончания" #. module: project #: field:project.task.type,state:0 msgid "Related Status" -msgstr "" +msgstr "Связанный статус" #. module: project #: view:project.project:0 msgid "Documents" -msgstr "" +msgstr "Документы" #. module: project #: model:mail.message.subtype,description:project.mt_task_new msgid "Task created" -msgstr "" +msgstr "Задача создана" #. module: project #: view:report.project.task.user:0 @@ -1774,7 +1792,7 @@ msgstr "# дней" #: field:project.project,message_follower_ids:0 #: field:project.task,message_follower_ids:0 msgid "Followers" -msgstr "" +msgstr "Подписчики" #. module: project #: selection:project.project,state:0 @@ -1812,7 +1830,7 @@ msgstr "Проверка задания" #. module: project #: field:project.config.settings,module_project_long_term:0 msgid "Manage resources planning on gantt view" -msgstr "" +msgstr "Управление планированием ресурсов на диаграмме Ганта" #. module: project #: view:project.task:0 @@ -1871,7 +1889,7 @@ msgstr "Проекты" #. module: project #: model:res.groups,name:project.group_tasks_work_on_tasks msgid "Task's Work on Tasks" -msgstr "" +msgstr "Задачи, работающие на задачи" #. module: project #: help:project.task.delegate,name:0 @@ -1914,7 +1932,7 @@ msgstr "Декабрь" #: view:project.task.delegate:0 #: view:project.task.reevaluate:0 msgid "or" -msgstr "" +msgstr "или" #. module: project #: help:project.config.settings,module_project_mrp:0 @@ -1938,7 +1956,7 @@ msgstr "" #. module: project #: model:project.category,name:project.project_category_03 msgid "Experiment" -msgstr "" +msgstr "Эксперимент" #. module: project #: model:process.transition.action,name:project.process_transition_action_opendrafttask0 @@ -1998,7 +2016,7 @@ msgstr "" #: model:ir.actions.act_window,name:project.action_config_settings #: view:project.config.settings:0 msgid "Configure Project" -msgstr "" +msgstr "Настроить проект" #. module: project #: view:project.task.history.cumulative:0 @@ -2030,7 +2048,7 @@ msgstr "Пожалуйста, сначала удалите проект, ссы #: model:mail.message.subtype,name:project.mt_project_task_new #: model:mail.message.subtype,name:project.mt_task_new msgid "Task Created" -msgstr "" +msgstr "Задание создано" #. module: project #: view:report.project.task.user:0 @@ -2048,12 +2066,12 @@ msgstr "Проекты, в которых я менеджер" #: selection:project.task.history,kanban_state:0 #: selection:project.task.history.cumulative,kanban_state:0 msgid "Ready for next stage" -msgstr "" +msgstr "Готово к следующей стадии" #. module: project #: field:project.task.type,case_default:0 msgid "Default for New Projects" -msgstr "" +msgstr "По умолчанию для нового проекта" #. module: project #: view:project.task:0 @@ -2098,7 +2116,7 @@ msgstr "" #. module: project #: model:mail.message.subtype,description:project.mt_task_closed msgid "Task closed" -msgstr "" +msgstr "Задание закрыто" #. module: project #: selection:report.project.task.user,month:0 @@ -2130,13 +2148,13 @@ msgstr "" #. module: project #: selection:project.project,privacy_visibility:0 msgid "Followers Only" -msgstr "" +msgstr "Только для подписчиков" #. module: project #: view:board.board:0 #: field:project.project,task_count:0 msgid "Open Tasks" -msgstr "" +msgstr "Открытые задачи" #. module: project #: field:project.project,priority:0 diff --git a/addons/project/i18n/th.po b/addons/project/i18n/th.po new file mode 100644 index 00000000000..7dfd58eee63 --- /dev/null +++ b/addons/project/i18n/th.po @@ -0,0 +1,2109 @@ +# 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:04+0000\n" +"PO-Revision-Date: 2013-05-15 07:02+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: project +#: view:project.project:0 +msgid "Email Interface" +msgstr "" + +#. module: project +#: help:account.analytic.account,use_tasks:0 +msgid "" +"If checked, this contract will be available in the project menu and you will " +"be able to manage tasks or track issues" +msgstr "" + +#. module: project +#: field:project.project,progress_rate:0 +#: view:report.project.task.user:0 +#: field:report.project.task.user,progress:0 +msgid "Progress" +msgstr "" + +#. module: project +#: model:process.node,name:project.process_node_taskbydelegate0 +msgid "Task by delegate" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Parent" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.dblc_proj +msgid "Project's tasks" +msgstr "" + +#. module: project +#: field:project.task.type,name:0 +msgid "Stage Name" +msgstr "" + +#. module: project +#: model:process.transition.action,name:project.process_transition_action_openpendingtask0 +msgid "Set pending" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "New Project Based on Template" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,day:0 +msgid "Day" +msgstr "" + +#. module: project +#: model:project.task.type,name:project.project_tt_merge +msgid "Merge" +msgstr "" + +#. module: project +#: view:res.partner:0 +msgid "Start Task" +msgstr "" + +#. module: project +#: code:addons/project/project.py:932 +#, python-format +msgid "Warning !" +msgstr "" + +#. module: project +#: help:project.project,message_unread:0 +#: help:project.task,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: project +#: model:process.node,name:project.process_node_donetask0 +msgid "Done task" +msgstr "" + +#. module: project +#: model:process.node,note:project.process_node_donetask0 +msgid "Task is Completed" +msgstr "" + +#. module: project +#: view:res.partner:0 +msgid "False" +msgstr "" + +#. module: project +#: model:project.task.type,name:project.project_tt_testing +msgid "Testing" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_account_analytic_account +msgid "Analytic Account" +msgstr "" + +#. module: project +#: field:project.config.settings,group_time_work_estimation_tasks:0 +msgid "Manage time estimation on tasks" +msgstr "" + +#. module: project +#: help:project.project,message_summary:0 +#: help:project.task,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: project +#: code:addons/project/project.py:432 +#: code:addons/project/project.py:1318 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_res_partner +msgid "Partner" +msgstr "" + +#. module: project +#: field:project.config.settings,group_manage_delegation_task:0 +msgid "Allow task delegation" +msgstr "" + +#. module: project +#: field:project.task.delegate,planned_hours:0 +#: view:report.project.task.user:0 +#: field:report.project.task.user,hours_planned:0 +msgid "Planned Hours" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Reset as Project" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "In progress tasks" +msgstr "" + +#. module: project +#: help:project.project,progress_rate:0 +msgid "Percent of tasks closed according to the total of tasks todo." +msgstr "" + +#. module: project +#: model:ir.actions.client,name:project.action_client_project_menu +msgid "Open Project Menu" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,help:project.action_project_task_user_tree +msgid "" +"This report allows you to analyse the performance of your projects and " +"users. You can analyse the quantities of tasks, the hours spent compared to " +"the planned hours, the average number of days to open or close a task, etc." +msgstr "" + +#. module: project +#: view:project.task.delegate:0 +msgid "Validation Task Title" +msgstr "" + +#. module: project +#: model:res.groups,name:project.group_delegate_task +msgid "Task Delegation" +msgstr "" + +#. module: project +#: field:project.project,planned_hours:0 +#: field:project.task.history,planned_hours:0 +#: field:project.task.history.cumulative,planned_hours:0 +msgid "Planned Time" +msgstr "" + +#. module: project +#: selection:project.project,privacy_visibility:0 +msgid "Public" +msgstr "" + +#. module: project +#: model:project.category,name:project.project_category_01 +msgid "Contact's suggestion" +msgstr "" + +#. module: project +#: help:project.config.settings,group_time_work_estimation_tasks:0 +msgid "Allows you to compute Time Estimation on tasks." +msgstr "" + +#. module: project +#: field:report.project.task.user,user_id:0 +msgid "Assigned To" +msgstr "" + +#. module: project +#: model:mail.message.subtype,name:project.mt_project_task_closed +#: model:mail.message.subtype,name:project.mt_task_closed +msgid "Task Done" +msgstr "" + +#. module: project +#: view:project.project:0 +#: view:report.project.task.user:0 +#: field:report.project.task.user,partner_id:0 +msgid "Contact" +msgstr "" + +#. module: project +#: model:process.transition,name:project.process_transition_delegate0 +#: view:project.task:0 +msgid "Delegate" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.open_view_template_project +#: view:project.project:0 +msgid "Templates of Projects" +msgstr "" + +#. module: project +#: field:project.project,analytic_account_id:0 +msgid "Contract/Analytic" +msgstr "" + +#. module: project +#: view:project.config.settings:0 +msgid "Project Management" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.action_project_task_delegate +#: view:project.task.delegate:0 +msgid "Project Task Delegate" +msgstr "" + +#. module: project +#: model:mail.message.subtype,name:project.mt_project_task_started +#: model:mail.message.subtype,name:project.mt_task_started +msgid "Task Started" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Very Important" +msgstr "" + +#. module: project +#: view:project.config.settings:0 +msgid "Support" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Member" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Cancel Task" +msgstr "" + +#. module: project +#: help:project.project,members:0 +msgid "" +"Project's members are users who can have an access to the tasks related to " +"this project." +msgstr "" + +#. module: project +#: view:project.project:0 +#: field:project.task,manager_id:0 +msgid "Project Manager" +msgstr "" + +#. module: project +#: field:project.project,state:0 +#: field:project.task,state:0 +#: field:project.task.history,state:0 +#: field:project.task.history.cumulative,state:0 +#: field:report.project.task.user,state:0 +msgid "Status" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "August" +msgstr "" + +#. module: project +#: view:project.project:0 +#: field:project.project,complete_name:0 +msgid "Project Name" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "June" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "October" +msgstr "" + +#. module: project +#: help:project.project,total_hours:0 +msgid "" +"Sum of total hours of all tasks related to this project and its child " +"projects." +msgstr "" + +#. module: project +#: help:project.project,active:0 +msgid "" +"If the active field is set to False, it will allow you to hide the project " +"without removing it." +msgstr "" + +#. module: project +#: model:process.transition,note:project.process_transition_opendonetask0 +msgid "When task is completed, it will come into the done state." +msgstr "" + +#. module: project +#: field:project.project,message_summary:0 +#: field:project.task,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Append this project to another one using analytic accounts hierarchy" +msgstr "" + +#. module: project +#: view:project.task:0 +#: view:project.task.history.cumulative:0 +msgid "In Progress Tasks" +msgstr "" + +#. module: project +#: help:res.company,project_time_mode_id:0 +msgid "" +"This will set the unit of measure used in projects and tasks.\n" +"If you use the timesheet linked to projects (project_timesheet module), " +"don't forget to setup the right unit of measure in your employees." +msgstr "" + +#. module: project +#: field:project.task,user_id:0 +#: view:report.project.task.user:0 +msgid "Assigned to" +msgstr "" + +#. module: project +#: code:addons/project/project.py:1021 +#, python-format +msgid "Delegated User should be specified" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Project(s) Manager" +msgstr "" + +#. module: project +#: selection:project.project,state:0 +#: view:project.task:0 +#: selection:project.task,state:0 +#: selection:project.task.history,state:0 +#: selection:project.task.history.cumulative,state:0 +#: selection:project.task.type,state:0 +#: selection:report.project.task.user,state:0 +msgid "In Progress" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Reactivate" +msgstr "" + +#. module: project +#: field:project.project,resource_calendar_id:0 +msgid "Working Time" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.action_project_task_reevaluate +msgid "Re-evaluate Task" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Validate planned time" +msgstr "" + +#. module: project +#: field:project.config.settings,module_pad:0 +msgid "Use integrated collaborative note pads on task" +msgstr "" + +#. module: project +#: model:mail.message.subtype,name:project.mt_project_task_blocked +#: model:mail.message.subtype,name:project.mt_task_blocked +msgid "Task Blocked" +msgstr "" + +#. module: project +#: model:process.node,note:project.process_node_opentask0 +msgid "Encode your working hours." +msgstr "" + +#. module: project +#: field:project.project,alias_id:0 +msgid "Alias" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "oe_kanban_text_red" +msgstr "" + +#. module: project +#: model:mail.message.subtype,description:project.mt_task_blocked +msgid "Task blocked" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Delegation" +msgstr "" + +#. module: project +#: field:project.task,create_date:0 +msgid "Create Date" +msgstr "" + +#. module: project +#: view:res.partner:0 +msgid "For changing to open state" +msgstr "" + +#. module: project +#: view:project.config.settings:0 +msgid "Apply" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_task_delegate +msgid "Task Delegate" +msgstr "" + +#. module: project +#: help:project.task.delegate,new_task_description:0 +msgid "Reinclude the description of the task in the task of the user" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Project Settings" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "My tasks" +msgstr "" + +#. module: project +#: model:process.transition,name:project.process_transition_opendonetask0 +msgid "Open Done Task" +msgstr "" + +#. module: project +#: field:project.task.delegate,planned_hours_me:0 +msgid "Hours to Validate" +msgstr "" + +#. module: project +#: help:project.task,remaining_hours:0 +msgid "" +"Total remaining time, can be re-estimated periodically by the assignee of " +"the task." +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "March" +msgstr "" + +#. module: project +#: view:board.board:0 +#: model:ir.actions.act_window,name:project.my_open_tasks_action +#: view:project.task:0 +#: view:project.task.history.cumulative:0 +msgid "My Tasks" +msgstr "" + +#. module: project +#: constraint:project.task:0 +msgid "Error ! You cannot create recursive tasks." +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "Pending tasks" +msgstr "" + +#. module: project +#: view:project.task.reevaluate:0 +msgid "_Evaluate" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,opening_days:0 +msgid "Days to Open" +msgstr "" + +#. module: project +#: selection:report.project.task.user,priority:0 +msgid "Very urgent" +msgstr "" + +#. module: project +#: help:project.task.delegate,project_id:0 +#: help:project.task.delegate,user_id:0 +msgid "User you want to delegate this task to" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Set as Template" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_task +#: view:project.config.settings:0 +#: view:project.project:0 +#: view:project.task:0 +#: field:project.task.history,task_id:0 +#: field:project.task.history.cumulative,task_id:0 +#: field:project.task.work,task_id:0 +#: view:report.project.task.user:0 +msgid "Task" +msgstr "" + +#. module: project +#: help:project.config.settings,group_tasks_work_on_tasks:0 +msgid "Allows you to compute work on tasks." +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Administration" +msgstr "" + +#. module: project +#: field:project.config.settings,group_tasks_work_on_tasks:0 +msgid "Log work activities on tasks" +msgstr "" + +#. module: project +#: model:project.task.type,name:project.project_tt_analysis +msgid "Analysis" +msgstr "" + +#. module: project +#: field:project.task,name:0 +#: field:report.project.task.user,name:0 +msgid "Task Summary" +msgstr "" + +#. module: project +#: field:project.task,active:0 +msgid "Not a Template Task" +msgstr "" + +#. module: project +#: field:project.task,planned_hours:0 +msgid "Initially Planned Hours" +msgstr "" + +#. module: project +#: model:process.transition,note:project.process_transition_delegate0 +msgid "Delegates tasks to the other user" +msgstr "" + +#. module: project +#: help:project.task,effective_hours:0 +msgid "Computed using the sum of the task work done." +msgstr "" + +#. module: project +#: model:ir.actions.act_window,help:project.open_view_project_all +msgid "" +"

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

\n" +" Projects are used to organize your activities; plan\n" +" tasks, track issues, invoice timesheets. You can define\n" +" internal projects (R&D, Improve Sales Process),\n" +" private projects (My Todos) or customer ones.\n" +"

\n" +" You will be able collaborate with internal users on\n" +" projects or invite customers to share your activities.\n" +"

\n" +" " +msgstr "" + +#. module: project +#: view:project.config.settings:0 +msgid "Planning" +msgstr "" + +#. module: project +#: view:project.task:0 +#: field:project.task,date_deadline:0 +#: field:report.project.task.user,date_deadline:0 +msgid "Deadline" +msgstr "" + +#. module: project +#: view:project.task.history.cumulative:0 +msgid "Ready" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "New Tasks" +msgstr "" + +#. module: project +#: field:project.config.settings,module_project_issue_sheet:0 +msgid "Invoice working time on issues" +msgstr "" + +#. module: project +#: view:project.project:0 +#: view:project.task:0 +#: field:project.task.history,end_date:0 +#: field:project.task.history.cumulative,end_date:0 +msgid "End Date" +msgstr "" + +#. module: project +#: model:project.task.type,name:project.project_tt_specification +msgid "Specification" +msgstr "" + +#. module: project +#: model:process.transition,note:project.process_transition_draftopentask0 +msgid "From draft state, it will come into the open state." +msgstr "" + +#. module: project +#: view:project.task.history.cumulative:0 +msgid "Task's Analysis" +msgstr "" + +#. module: project +#: view:project.task.delegate:0 +#: field:project.task.delegate,new_task_description:0 +msgid "New Task Description" +msgstr "" + +#. module: project +#: field:report.project.task.user,delay_endings_days:0 +msgid "Overpassed Deadline" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "New tasks" +msgstr "" + +#. module: project +#: selection:project.task,priority:0 +#: selection:report.project.task.user,priority:0 +msgid "Medium" +msgstr "" + +#. module: project +#: field:project.project,total_hours:0 +msgid "Total Time" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "Creation Date" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Miscellaneous" +msgstr "" + +#. module: project +#: view:project.task:0 +#: field:project.task,stage_id:0 +#: field:project.task.history,type_id:0 +#: field:project.task.history.cumulative,type_id:0 +msgid "Stage" +msgstr "" + +#. module: project +#: model:process.transition,name:project.process_transition_draftopentask0 +msgid "Draft Open task" +msgstr "" + +#. module: project +#: field:project.project,alias_model:0 +msgid "Alias Model" +msgstr "" + +#. module: project +#: help:report.project.task.user,closing_days:0 +msgid "Number of Days to close the task" +msgstr "" + +#. module: project +#: view:board.board:0 +msgid "My Board" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.open_task_type_form +msgid "Stages" +msgstr "" + +#. module: project +#: view:project.project:0 +#: view:project.task:0 +msgid "Delete" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "In progress" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "September" +msgstr "" + +#. module: project +#: selection:report.project.task.user,priority:0 +msgid "Urgent" +msgstr "" + +#. module: project +#: model:project.category,name:project.project_category_02 +msgid "Feature request" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Delegated tasks" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_task_work +msgid "Project Task Work" +msgstr "" + +#. module: project +#: code:addons/project/wizard/project_task_delegate.py:81 +#, python-format +msgid "CHECK: %s" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Close Project" +msgstr "" + +#. module: project +#: field:project.project,tasks:0 +msgid "Task Activities" +msgstr "" + +#. module: project +#: field:project.project,effective_hours:0 +#: field:project.task.work,hours:0 +msgid "Time Spent" +msgstr "" + +#. module: project +#: view:project.project:0 +#: view:project.task:0 +msgid "í" +msgstr "" + +#. module: project +#: field:account.analytic.account,company_uom_id:0 +msgid "unknown" +msgstr "" + +#. module: project +#: field:project.project,message_is_follower:0 +#: field:project.task,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: project +#: field:project.task,work_ids:0 +msgid "Work done" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "Extended Filters..." +msgstr "" + +#. module: project +#: model:ir.ui.menu,name:project.menu_tasks_config +msgid "GTD" +msgstr "" + +#. module: project +#: help:project.task,state:0 +msgid "" +"The status is set to 'Draft', when a case is created. " +"If the case is in progress the status is set to 'Open'. " +"When the case is over, the status is set to 'Done'. If " +"the case needs to be reviewed then the status is set " +"to 'Pending'." +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_res_company +msgid "Companies" +msgstr "" + +#. module: project +#: field:project.task.type,fold:0 +msgid "Folded by Default" +msgstr "" + +#. module: project +#: field:project.task.history,date:0 +#: field:project.task.history.cumulative,date:0 +#: field:project.task.work,date:0 +msgid "Date" +msgstr "" + +#. module: project +#: help:project.config.settings,module_project_issue:0 +msgid "" +"Provides management of issues/bugs in projects.\n" +" This installs the module project_issue." +msgstr "" + +#. module: project +#: help:project.task,kanban_state:0 +msgid "" +"A task's kanban state indicates special situations affecting it:\n" +" * Normal is the default situation\n" +" * Blocked indicates something is preventing the progress of this task\n" +" * Ready for next stage indicates the task is ready to be pulled to the next " +"stage" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "10" +msgstr "" + +#. module: project +#: help:project.project,analytic_account_id:0 +msgid "" +"Link this project to an analytic account if you need financial management on " +"projects. It enables you to connect projects with budgets, planning, cost " +"and revenue analysis, timesheets on projects, etc." +msgstr "" + +#. module: project +#: model:process.transition.action,name:project.process_transition_action_draftcanceltask0 +#: model:process.transition.action,name:project.process_transition_action_opencanceltask0 +#: view:project.config.settings:0 +#: view:project.task.delegate:0 +#: view:project.task.reevaluate:0 +msgid "Cancel" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Other Info" +msgstr "" + +#. module: project +#: view:project.task.delegate:0 +msgid "_Delegate" +msgstr "" + +#. module: project +#: selection:project.task,priority:0 +#: selection:report.project.task.user,priority:0 +msgid "Very Low" +msgstr "" + +#. module: project +#: help:project.project,effective_hours:0 +msgid "" +"Sum of spent hours of all tasks related to this project and its child " +"projects." +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "" +"Follow this project to automatically track the events associated to tasks " +"and issues of this project." +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Users" +msgstr "" + +#. module: project +#: model:mail.message.subtype,name:project.mt_task_stage +msgid "Stage Changed" +msgstr "" + +#. module: project +#: view:project.project:0 +#: model:res.groups,name:project.group_project_manager +msgid "Manager" +msgstr "" + +#. module: project +#: selection:project.task,priority:0 +msgid "Important" +msgstr "" + +#. module: project +#: field:project.category,name:0 +msgid "Name" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "November" +msgstr "" + +#. module: project +#: view:project.task.reevaluate:0 +msgid "Reevaluate Task" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_task_type +#: view:project.task.type:0 +msgid "Task Stage" +msgstr "" + +#. module: project +#: view:project.task.type:0 +msgid "Common" +msgstr "" + +#. module: project +#: help:project.project,message_ids:0 +#: help:project.task,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "" +"To invoice or setup invoicing and renewal options, go to the related " +"contract:" +msgstr "" + +#. module: project +#: field:project.task.delegate,state:0 +msgid "Validation State" +msgstr "" + +#. module: project +#: field:project.task.work,name:0 +msgid "Work summary" +msgstr "" + +#. module: project +#: view:project.project:0 +#: view:project.task:0 +#: view:report.project.task.user:0 +msgid "Group By..." +msgstr "" + +#. module: project +#: view:project.project:0 +#: selection:project.project,state:0 +msgid "Template" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Re-open project" +msgstr "" + +#. module: project +#: help:project.project,priority:0 +msgid "Gives the sequence order when displaying the list of projects" +msgstr "" + +#. module: project +#: constraint:project.project:0 +msgid "Error! project start-date must be lower then project end-date." +msgstr "" + +#. module: project +#: field:project.project,members:0 +msgid "Project Members" +msgstr "" + +#. module: project +#: field:project.task,child_ids:0 +msgid "Delegated Tasks" +msgstr "" + +#. module: project +#: view:project.project:0 +#: field:project.project,message_unread:0 +#: view:project.task:0 +#: field:project.task,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: project +#: view:project.task:0 +#: field:project.task,parent_ids:0 +msgid "Parent Tasks" +msgstr "" + +#. module: project +#: model:process.node,name:project.process_node_opentask0 +msgid "Open task" +msgstr "" + +#. module: project +#: view:project.task.type:0 +msgid "Stages common to all projects" +msgstr "" + +#. module: project +#: model:process.node,name:project.process_node_drafttask0 +msgid "Draft task" +msgstr "" + +#. module: project +#: field:project.task,notes:0 +msgid "Notes" +msgstr "" + +#. module: project +#: view:project.task:0 +#: view:project.task.history.cumulative:0 +msgid "Pending Tasks" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Show only tasks having a deadline" +msgstr "" + +#. module: project +#: model:project.category,name:project.project_category_04 +msgid "Usability" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,hours_delay:0 +msgid "Avg. Plan.-Eff." +msgstr "" + +#. module: project +#: field:project.task.work,user_id:0 +msgid "Done by" +msgstr "" + +#. module: project +#: code:addons/project/project.py:181 +#, python-format +msgid "Invalid Action!" +msgstr "" + +#. module: project +#: help:project.task.type,state:0 +msgid "" +"The status of your document is automatically changed regarding the selected " +"stage. For example, if a stage is related to the status 'Close', when your " +"document reaches this stage, it is automatically closed." +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Extra Info" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Edit..." +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,nbr:0 +msgid "# of tasks" +msgstr "" + +#. module: project +#: field:project.project,doc_count:0 +msgid "Number of documents attached" +msgstr "" + +#. module: project +#: field:project.task,priority:0 +#: field:report.project.task.user,priority:0 +msgid "Priority" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Open Projects" +msgstr "" + +#. module: project +#: help:project.project,alias_id:0 +msgid "" +"Internal email associated with this project. Incoming emails are " +"automatically synchronizedwith Tasks (or optionally Issues if the Issue " +"Tracker module is installed)." +msgstr "" + +#. module: project +#: model:ir.actions.act_window,help:project.open_task_type_form +msgid "" +"

\n" +" Click to add a stage in the task pipeline.\n" +"

\n" +" Define the steps that will be used in the project from the\n" +" creation of the task, up to the closing of the task or " +"issue.\n" +" You will use these stages in order to track the progress in\n" +" solving a task or an issue.\n" +"

\n" +" " +msgstr "" + +#. module: project +#: help:project.task,total_hours:0 +msgid "Computed as: Time Spent + Remaining Time." +msgstr "" + +#. module: project +#: code:addons/project/project.py:356 +#: code:addons/project/project.py:377 +#: code:addons/project/project.py:709 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: project +#: model:mail.message.subtype,name:project.mt_project_task_stage +msgid "Task Stage Changed" +msgstr "" + +#. module: project +#: view:project.task:0 +#: field:project.task.history,remaining_hours:0 +#: field:project.task.history.cumulative,remaining_hours:0 +msgid "Remaining Time" +msgstr "" + +#. module: project +#: field:project.task.delegate,name:0 +msgid "Delegated Title" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "July" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_task_reevaluate +msgid "project.task.reevaluate" +msgstr "" + +#. module: project +#: field:project.task,delay_hours:0 +msgid "Delay Hours" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Team" +msgstr "" + +#. module: project +#: help:project.config.settings,time_unit:0 +msgid "This will set the unit of measure used in projects and tasks." +msgstr "" + +#. module: project +#: selection:project.task,priority:0 +msgid "Very important" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,month:0 +msgid "Month" +msgstr "" + +#. module: project +#: model:project.task.type,name:project.project_tt_design +msgid "Design" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Start Date" +msgstr "" + +#. module: project +#: view:project.task:0 +#: selection:project.task,kanban_state:0 +#: selection:project.task.history,kanban_state:0 +#: view:project.task.history.cumulative:0 +#: selection:project.task.history.cumulative,kanban_state:0 +msgid "Blocked" +msgstr "" + +#. module: project +#: help:project.task,progress:0 +msgid "" +"If the task has a progress of 99.99% you should close the task if it's " +"finished or reevaluate the time" +msgstr "" + +#. module: project +#: field:project.task,user_email:0 +msgid "User Email" +msgstr "" + +#. module: project +#: help:project.task.delegate,prefix:0 +msgid "Title for your validation task" +msgstr "" + +#. module: project +#: field:project.config.settings,time_unit:0 +msgid "Working time unit" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Projects in which I am a member." +msgstr "" + +#. module: project +#: selection:project.task,priority:0 +#: selection:report.project.task.user,priority:0 +msgid "Low" +msgstr "" + +#. module: project +#: selection:project.project,state:0 +msgid "Closed" +msgstr "" + +#. module: project +#: view:project.project:0 +#: selection:project.project,state:0 +#: view:project.task:0 +#: selection:project.task,state:0 +#: selection:project.task.delegate,state:0 +#: selection:project.task.history,state:0 +#: selection:project.task.history.cumulative,state:0 +#: selection:project.task.type,state:0 +#: view:report.project.task.user:0 +#: selection:report.project.task.user,state:0 +msgid "Pending" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.project_category_action +#: model:ir.ui.menu,name:project.menu_project_category_act +#: view:project.category:0 +#: field:project.task,categ_ids:0 +msgid "Tags" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_task_history +#: model:ir.model,name:project.model_project_task_history_cumulative +msgid "History of Tasks" +msgstr "" + +#. module: project +#: help:project.task.delegate,state:0 +msgid "" +"New state of your own task. Pending will be reopened automatically when the " +"delegated task is closed" +msgstr "" + +#. module: project +#: help:project.config.settings,group_manage_delegation_task:0 +msgid "Allows you to delegate tasks to other users." +msgstr "" + +#. module: project +#: field:project.project,active:0 +msgid "Active" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_category +msgid "Category of project's task, issue, ..." +msgstr "" + +#. module: project +#: help:project.project,resource_calendar_id:0 +msgid "Timetable working hours to adjust the gantt diagram report" +msgstr "" + +#. module: project +#: help:project.task,delay_hours:0 +msgid "" +"Computed as difference between planned hours by the project manager and the " +"total hours of the task." +msgstr "" + +#. module: project +#: view:project.config.settings:0 +msgid "Helpdesk & Support" +msgstr "" + +#. module: project +#: help:report.project.task.user,opening_days:0 +msgid "Number of Days to Open the task" +msgstr "" + +#. module: project +#: field:project.task,delegated_user_id:0 +msgid "Delegated To" +msgstr "" + +#. module: project +#: help:project.task,planned_hours:0 +msgid "" +"Estimated time to do the task, usually set by the project manager when the " +"task is in draft state." +msgstr "" + +#. module: project +#: code:addons/project/project.py:220 +#, python-format +msgid "Attachments" +msgstr "" + +#. module: project +#: view:project.task:0 +#: selection:project.task,state:0 +#: selection:project.task.delegate,state:0 +#: selection:project.task.history,state:0 +#: selection:project.task.history.cumulative,state:0 +#: model:project.task.type,name:project.project_tt_deployment +#: selection:project.task.type,state:0 +#: view:report.project.task.user:0 +#: selection:report.project.task.user,state:0 +#: view:res.partner:0 +msgid "Done" +msgstr "" + +#. module: project +#: code:addons/project/project.py:182 +#, python-format +msgid "" +"You cannot delete a project containing tasks. You can either delete all the " +"project's tasks and then delete the project or simply deactivate the project." +msgstr "" + +#. module: project +#: model:process.transition.action,name:project.process_transition_action_draftopentask0 +#: view:project.project:0 +msgid "Open" +msgstr "" + +#. module: project +#: field:project.project,privacy_visibility:0 +msgid "Privacy / Visibility" +msgstr "" + +#. module: project +#: view:project.task:0 +#: field:project.task,remaining_hours:0 +#: field:project.task.reevaluate,remaining_hours:0 +#: view:report.project.task.user:0 +#: field:report.project.task.user,remaining_hours:0 +msgid "Remaining Hours" +msgstr "" + +#. module: project +#: model:mail.message.subtype,description:project.mt_task_stage +msgid "Stage changed" +msgstr "" + +#. module: project +#: constraint:project.task:0 +msgid "Error ! Task end-date must be greater then task start-date" +msgstr "" + +#. module: project +#: field:project.task.history,user_id:0 +#: field:project.task.history.cumulative,user_id:0 +msgid "Responsible" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Search Project" +msgstr "" + +#. module: project +#: view:project.task.delegate:0 +msgid "Delegated Task" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,total_hours:0 +msgid "Total Hours" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_project_config_settings +msgid "project.config.settings" +msgstr "" + +#. module: project +#: model:project.task.type,name:project.project_tt_development +msgid "Development" +msgstr "" + +#. module: project +#: help:project.task,active:0 +msgid "" +"This field is computed automatically and have the same behavior than the " +"boolean 'active' field: if the task is linked to a template or unactivated " +"project, it will be hidden unless specifically asked." +msgstr "" + +#. module: project +#: model:res.request.link,name:project.req_link_task +msgid "Project task" +msgstr "" + +#. module: project +#: field:project.task,effective_hours:0 +msgid "Hours Spent" +msgstr "" + +#. module: project +#: help:project.config.settings,module_pad:0 +msgid "" +"Lets the company customize which Pad installation should be used to link to " +"new pads\n" +" (by default, http://ietherpad.com/).\n" +" This installs the module pad." +msgstr "" + +#. module: project +#: field:project.task,id:0 +msgid "ID" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.action_view_task_overpassed_draft +msgid "Overpassed Tasks" +msgstr "" + +#. module: project +#: code:addons/project/project.py:932 +#, python-format +msgid "" +"Child task still open.\n" +"Please cancel or complete child task first." +msgstr "" + +#. module: project +#: field:project.task.delegate,user_id:0 +msgid "Assign To" +msgstr "" + +#. module: project +#: model:res.groups,name:project.group_time_work_estimation_tasks +msgid "Time Estimation on Tasks" +msgstr "" + +#. module: project +#: field:project.task,total_hours:0 +msgid "Total" +msgstr "" + +#. module: project +#: model:process.node,note:project.process_node_taskbydelegate0 +msgid "Delegate your task to the other user" +msgstr "" + +#. module: project +#: model:mail.message.subtype,description:project.mt_task_started +msgid "Task started" +msgstr "" + +#. module: project +#: help:project.task.reevaluate,remaining_hours:0 +msgid "Put here the remaining hours required to close the task." +msgstr "" + +#. module: project +#: help:project.task.type,fold:0 +msgid "" +"This stage is not visible, for example in status bar or kanban view, when " +"there are no records in that stage to display." +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Deadlines" +msgstr "" + +#. module: project +#: code:addons/project/wizard/project_task_delegate.py:69 +#: code:addons/project/wizard/project_task_delegate.py:70 +#: code:addons/project/wizard/project_task_delegate.py:77 +#: code:addons/project/wizard/project_task_delegate.py:78 +#, python-format +msgid "CHECK: " +msgstr "" + +#. module: project +#: code:addons/project/project.py:432 +#, python-format +msgid "You must assign members on the project '%s' !" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Pending Projects" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Remaining" +msgstr "" + +#. module: project +#: field:project.task,progress:0 +msgid "Progress (%)" +msgstr "" + +#. module: project +#: field:project.task,company_id:0 +#: field:project.task.work,company_id:0 +#: view:report.project.task.user:0 +#: field:report.project.task.user,company_id:0 +msgid "Company" +msgstr "" + +#. module: project +#: help:project.config.settings,module_project_timesheet:0 +msgid "" +"This allows you to transfer the entries under tasks defined for Project " +"Management to\n" +" the timesheet line entries for particular date and user, " +"with the effect of creating,\n" +" editing and deleting either ways.\n" +" This installs the module project_timesheet." +msgstr "" + +#. module: project +#: field:project.config.settings,module_project_issue:0 +msgid "Track issues and bugs" +msgstr "" + +#. module: project +#: field:project.config.settings,module_project_mrp:0 +msgid "Generate tasks from sale orders" +msgstr "" + +#. module: project +#: model:ir.ui.menu,name:project.menu_task_types_view +msgid "Task Stages" +msgstr "" + +#. module: project +#: model:process.node,note:project.process_node_drafttask0 +msgid "Define the Requirements and Set Planned Hours." +msgstr "" + +#. module: project +#: field:project.project,message_ids:0 +#: field:project.task,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: project +#: field:project.project,color:0 +#: field:project.task,color:0 +msgid "Color Index" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.open_board_project +#: model:ir.model,name:project.model_project_project +#: model:ir.ui.menu,name:project.menu_project_dashboard +#: model:ir.ui.menu,name:project.menu_project_management +#: view:project.project:0 +#: view:project.task:0 +#: field:project.task,project_id:0 +#: field:project.task.delegate,project_id:0 +#: field:project.task.history.cumulative,project_id:0 +#: view:report.project.task.user:0 +#: field:report.project.task.user,project_id:0 +#: model:res.request.link,name:project.req_link_project +msgid "Project" +msgstr "" + +#. module: project +#: selection:project.project,state:0 +#: selection:project.task,state:0 +#: selection:project.task.history,state:0 +#: selection:project.task.history.cumulative,state:0 +#: model:project.task.type,name:project.project_tt_cancel +#: selection:project.task.type,state:0 +#: selection:report.project.task.user,state:0 +msgid "Cancelled" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,help:project.act_project_project_2_project_task_all +#: model:ir.actions.act_window,help:project.action_view_task +msgid "" +"

\n" +" Click to create a new task.\n" +"

\n" +" OpenERP's project management allows you to manage the " +"pipeline\n" +" of tasks in order to get things done efficiently. You can\n" +" track progress, discuss on tasks, attach documents, etc.\n" +"

\n" +" " +msgstr "" + +#. module: project +#: field:project.task,date_end:0 +#: field:report.project.task.user,date_end:0 +msgid "Ending Date" +msgstr "" + +#. module: project +#: field:project.task.type,state:0 +msgid "Related Status" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Documents" +msgstr "" + +#. module: project +#: model:mail.message.subtype,description:project.mt_task_new +msgid "Task created" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,no_of_days:0 +msgid "# of Days" +msgstr "" + +#. module: project +#: field:project.project,message_follower_ids:0 +#: field:project.task,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: project +#: selection:project.project,state:0 +#: view:project.task:0 +#: selection:project.task,state:0 +#: selection:project.task.history,state:0 +#: selection:project.task.history.cumulative,state:0 +#: selection:project.task.type,state:0 +#: view:report.project.task.user:0 +msgid "New" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.action_view_task_history_cumulative +#: model:ir.ui.menu,name:project.menu_action_view_task_history_cumulative +msgid "Cumulative Flow" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,hours_effective:0 +msgid "Effective Hours" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "OverPass delay" +msgstr "" + +#. module: project +#: view:project.task.delegate:0 +msgid "Validation Task" +msgstr "" + +#. module: project +#: field:project.config.settings,module_project_long_term:0 +msgid "Manage resources planning on gantt view" +msgstr "" + +#. module: project +#: view:project.task:0 +#: view:project.task.history.cumulative:0 +msgid "Unassigned Tasks" +msgstr "" + +#. module: project +#: help:project.project,planned_hours:0 +msgid "" +"Sum of planned hours of all tasks related to this project and its child " +"projects." +msgstr "" + +#. module: project +#: view:res.partner:0 +msgid "For changing to done state" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "My Task" +msgstr "" + +#. module: project +#: view:project.task:0 +#: view:project.task.history.cumulative:0 +#: view:report.project.task.user:0 +msgid "My Projects" +msgstr "" + +#. module: project +#: help:project.task,sequence:0 +msgid "Gives the sequence order when displaying a list of tasks." +msgstr "" + +#. module: project +#: field:project.task,date_start:0 +#: field:report.project.task.user,date_start:0 +msgid "Starting Date" +msgstr "" + +#. module: project +#: code:addons/project/project.py:398 +#: model:ir.actions.act_window,name:project.open_view_project_all +#: model:ir.ui.menu,name:project.menu_projects +#: view:project.project:0 +#: field:project.task.type,project_ids:0 +#: view:res.company:0 +#, python-format +msgid "Projects" +msgstr "" + +#. module: project +#: model:res.groups,name:project.group_tasks_work_on_tasks +msgid "Task's Work on Tasks" +msgstr "" + +#. module: project +#: help:project.task.delegate,name:0 +msgid "New title of the task delegated to the user" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.action_project_task_user_tree +#: model:ir.ui.menu,name:project.menu_project_task_user_tree +#: view:report.project.task.user:0 +msgid "Tasks Analysis" +msgstr "" + +#. module: project +#: view:project.task:0 +#: view:project.task.history.cumulative:0 +msgid "Project Tasks" +msgstr "" + +#. module: project +#: field:account.analytic.account,use_tasks:0 +#: model:ir.actions.act_window,name:project.act_project_project_2_project_task_all +#: model:ir.actions.act_window,name:project.action_view_task +#: model:ir.ui.menu,name:project.menu_action_view_task +#: model:process.process,name:project.process_process_tasksprocess0 +#: view:project.project:0 +#: view:project.task:0 +#: view:res.partner:0 +#: field:res.partner,task_ids:0 +msgid "Tasks" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "December" +msgstr "" + +#. module: project +#: view:project.config.settings:0 +#: view:project.task.delegate:0 +#: view:project.task.reevaluate:0 +msgid "or" +msgstr "" + +#. module: project +#: help:project.config.settings,module_project_mrp:0 +msgid "" +"This feature automatically creates project tasks from service products in " +"sale orders.\n" +" More precisely, tasks are created for procurement lines with " +"product of type 'Service',\n" +" procurement method 'Make to Order', and supply method " +"'Manufacture'.\n" +" This installs the module project_mrp." +msgstr "" + +#. module: project +#: help:project.task.delegate,planned_hours:0 +msgid "Estimated time to close this task by the delegated user" +msgstr "" + +#. module: project +#: model:project.category,name:project.project_category_03 +msgid "Experiment" +msgstr "" + +#. module: project +#: model:process.transition.action,name:project.process_transition_action_opendrafttask0 +#: selection:report.project.task.user,state:0 +msgid "Draft" +msgstr "" + +#. module: project +#: field:project.task,kanban_state:0 +#: field:project.task.history,kanban_state:0 +#: field:project.task.history.cumulative,kanban_state:0 +msgid "Kanban State" +msgstr "" + +#. module: project +#: field:project.config.settings,module_project_timesheet:0 +msgid "Record timesheet lines per tasks" +msgstr "" + +#. module: project +#: model:ir.model,name:project.model_report_project_task_user +msgid "Tasks by user and project" +msgstr "" + +#. module: project +#: field:res.company,project_time_mode_id:0 +msgid "Project Time Unit" +msgstr "" + +#. module: project +#: view:project.task:0 +#: selection:project.task,kanban_state:0 +#: selection:project.task.history,kanban_state:0 +#: selection:project.task.history.cumulative,kanban_state:0 +msgid "Normal" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,closing_days:0 +msgid "Days to Close" +msgstr "" + +#. module: project +#: model:res.groups,name:project.group_project_user +msgid "User" +msgstr "" + +#. module: project +#: help:project.project,alias_model:0 +msgid "" +"The kind of document created when an email is received on this project's " +"email alias" +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.action_config_settings +#: view:project.config.settings:0 +msgid "Configure Project" +msgstr "" + +#. module: project +#: view:project.task.history.cumulative:0 +msgid "Tasks's Cumulative Flow" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "January" +msgstr "" + +#. module: project +#: field:project.task.delegate,prefix:0 +msgid "Your Task Title" +msgstr "" + +#. module: project +#: view:project.task.reevaluate:0 +msgid "Reevaluation Task" +msgstr "" + +#. module: project +#: code:addons/project/project.py:1318 +#, python-format +msgid "Please delete the project linked with this account first." +msgstr "" + +#. module: project +#: model:mail.message.subtype,name:project.mt_project_task_new +#: model:mail.message.subtype,name:project.mt_task_new +msgid "Task Created" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +msgid "Non Assigned Tasks to users" +msgstr "" + +#. module: project +#: view:project.project:0 +msgid "Projects in which I am a manager" +msgstr "" + +#. module: project +#: view:project.task:0 +#: selection:project.task,kanban_state:0 +#: selection:project.task.history,kanban_state:0 +#: selection:project.task.history.cumulative,kanban_state:0 +msgid "Ready for next stage" +msgstr "" + +#. module: project +#: field:project.task.type,case_default:0 +msgid "Default for New Projects" +msgstr "" + +#. module: project +#: view:project.task:0 +#: field:project.task,description:0 +#: field:project.task.type,description:0 +msgid "Description" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "May" +msgstr "" + +#. module: project +#: help:project.task.type,case_default:0 +msgid "" +"If you check this field, this stage will be proposed by default on each new " +"project. It will not assign this stage to existing projects." +msgstr "" + +#. module: project +#: field:project.task,partner_id:0 +msgid "Customer" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "February" +msgstr "" + +#. module: project +#: help:project.config.settings,module_project_long_term:0 +msgid "" +"A long term project management module that tracks planning, scheduling, and " +"resource allocation.\n" +" This installs the module project_long_term." +msgstr "" + +#. module: project +#: model:mail.message.subtype,description:project.mt_task_closed +msgid "Task closed" +msgstr "" + +#. module: project +#: selection:report.project.task.user,month:0 +msgid "April" +msgstr "" + +#. module: project +#: view:project.task:0 +msgid "Spent Hours" +msgstr "" + +#. module: project +#: help:project.project,sequence:0 +msgid "Gives the sequence order when displaying a list of Projects." +msgstr "" + +#. module: project +#: model:ir.actions.act_window,name:project.act_res_users_2_project_task_opened +msgid "Assigned Tasks" +msgstr "" + +#. module: project +#: help:project.config.settings,module_project_issue_sheet:0 +msgid "" +"Provides timesheet support for the issues/bugs management in project.\n" +" This installs the module project_issue_sheet." +msgstr "" + +#. module: project +#: selection:project.project,privacy_visibility:0 +msgid "Followers Only" +msgstr "" + +#. module: project +#: view:board.board:0 +#: field:project.project,task_count:0 +msgid "Open Tasks" +msgstr "" + +#. module: project +#: field:project.project,priority:0 +#: field:project.project,sequence:0 +#: field:project.task,sequence:0 +#: field:project.task.type,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: project +#: view:project.task:0 +#: view:project.task.work:0 +msgid "Task Work" +msgstr "" + +#. module: project +#: help:project.task.delegate,planned_hours_me:0 +msgid "" +"Estimated time for you to validate the work done by the user to whom you " +"delegate this task" +msgstr "" + +#. module: project +#: view:report.project.task.user:0 +#: field:report.project.task.user,year:0 +msgid "Year" +msgstr "" + +#. module: project +#: field:project.project,type_ids:0 +#: view:project.task.type:0 +msgid "Tasks Stages" +msgstr "" diff --git a/addons/project/process/task_process.xml b/addons/project/process/task_process.xml index 4a73bfd00d1..9955fe1ffe1 100644 --- a/addons/project/process/task_process.xml +++ b/addons/project/process/task_process.xml @@ -68,24 +68,24 @@ - - + + - - + + - - + + diff --git a/addons/project/project.py b/addons/project/project.py index 0751865d9c4..28e4bd6e5d2 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -85,7 +85,7 @@ class project(osv.osv): if context and context.get('user_preference'): cr.execute("""SELECT project.id FROM project_project project LEFT JOIN account_analytic_account account ON account.id = project.analytic_account_id - LEFT JOIN project_user_rel rel ON rel.project_id = project.analytic_account_id + LEFT JOIN project_user_rel rel ON rel.project_id = project.id WHERE (account.user_id = %s or rel.uid = %s)"""%(user, user)) return [(r[0]) for r in cr.fetchall()] return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, @@ -198,8 +198,12 @@ class project(osv.osv): return res def _task_count(self, cr, uid, ids, field_name, arg, context=None): + if context is None: + context = {} res = dict.fromkeys(ids, 0) - task_ids = self.pool.get('project.task').search(cr, uid, [('project_id', 'in', ids)]) + ctx = context.copy() + ctx['active_test'] = False + task_ids = self.pool.get('project.task').search(cr, uid, [('project_id', 'in', ids)], context=ctx) for task in self.pool.get('project.task').browse(cr, uid, task_ids, context): res[task.project_id.id] += 1 return res @@ -208,6 +212,12 @@ class project(osv.osv): """Overriden in project_issue to offer more options""" return [('project.task', "Tasks")] + def _get_visibility_selection(self, cr, uid, context=None): + """ Overriden in portal_project to offer more options """ + return [('public', 'Public'), + ('employees', 'Employees Only'), + ('followers', 'Followers Only')] + def attachment_tree_view(self, cr, uid, ids, context): task_ids = self.pool.get('project.task').search(cr, uid, [('project_id', 'in', ids)]) domain = [ @@ -229,6 +239,8 @@ class project(osv.osv): } # Lambda indirection method to avoid passing a copy of the overridable method when declaring the field _alias_models = lambda self, *args, **kwargs: self._get_alias_models(*args, **kwargs) + _visibility_selection = lambda self, *args, **kwargs: self._get_visibility_selection(*args, **kwargs) + _columns = { 'complete_name': fields.function(_complete_name, string="Project Name", type='char', size=250), 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the project without removing it."), @@ -267,7 +279,17 @@ class project(osv.osv): "with Tasks (or optionally Issues if the Issue Tracker module is installed)."), 'alias_model': fields.selection(_alias_models, "Alias Model", select=True, required=True, help="The kind of document created when an email is received on this project's email alias"), - 'privacy_visibility': fields.selection([('public','All Users'), ('followers','Followers Only')], 'Privacy / Visibility', required=True), + 'privacy_visibility': fields.selection(_visibility_selection, 'Privacy / Visibility', required=True, + help="Holds visibility of the tasks or issues that belong to the current project:\n" + "- Public: everybody sees everything; if portal is activated, portal users\n" + " see all tasks or issues; if anonymous portal is activated, visitors\n" + " see all tasks or issues\n" + "- Portal (only available if Portal is installed): employees see everything;\n" + " if portal is activated, portal users see the tasks or issues followed by\n" + " them or by someone of their company\n" + "- Employees Only: employees see all tasks or issues\n" + "- Followers Only: employees see only the followed tasks or issues; if portal\n" + " is activated, portal users see the followed tasks or issues."), 'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','Pending'),('close','Closed')], 'Status', required=True,), 'doc_count':fields.function(_get_attached_docs, string="Number of documents attached", type='int') } @@ -285,8 +307,7 @@ class project(osv.osv): 'sequence': 10, 'type_ids': _get_type_common, 'alias_model': 'project.task', - 'privacy_visibility': 'public', - 'alias_domain': False, # always hide alias during creation + 'privacy_visibility': 'employees', } # TODO: Why not using a SQL contraints ? @@ -429,7 +450,7 @@ class project(osv.osv): for project in projects: if (not project.members) and force_members: - raise osv.except_osv(_('Warning!'),_("You must assign members on the project '%s' !") % (project.name,)) + raise osv.except_osv(_('Warning!'),_("You must assign members on the project '%s'!") % (project.name,)) resource_pool = self.pool.get('resource.resource') @@ -531,11 +552,11 @@ def Project(): context = dict(context, project_creation_in_progress=True) mail_alias = self.pool.get('mail.alias') if not vals.get('alias_id') and vals.get('name', False): - vals.pop('alias_name', None) # prevent errors during copy() + alias_name = vals.pop('alias_name', None) # prevent errors during copy() alias_id = mail_alias.create_unique_alias(cr, uid, # Using '+' allows using subaddressing for those who don't # have a catchall domain setup. - {'alias_name': "project+"+short_name(vals['name'])}, + {'alias_name': alias_name or "project+"+short_name(vals['name'])}, model_name=vals.get('alias_model', 'project.task'), context=context) vals['alias_id'] = alias_id @@ -560,12 +581,12 @@ class task(base_stage, osv.osv): _track = { 'state': { - 'project.mt_task_new': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'new', + 'project.mt_task_new': lambda self, cr, uid, obj, ctx=None: obj['state'] in ['new', 'draft'], 'project.mt_task_started': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'open', 'project.mt_task_closed': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done', }, 'stage_id': { - 'project.mt_task_stage': lambda self, cr, uid, obj, ctx=None: obj['state'] not in ['new', 'done', 'open'], + 'project.mt_task_stage': lambda self, cr, uid, obj, ctx=None: obj['state'] not in ['new', 'draft', 'done', 'open'], }, 'kanban_state': { # kanban state: tracked, but only block subtype 'project.mt_task_blocked': lambda self, cr, uid, obj, ctx=None: obj['kanban_state'] == 'blocked', @@ -732,7 +753,7 @@ class task(base_stage, osv.osv): 'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True), 'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."), 'stage_id': fields.many2one('project.task.type', 'Stage', track_visibility='onchange', - domain="['&', ('fold', '=', False), ('project_ids', '=', project_id)]"), + domain="[('project_ids', '=', project_id)]"), 'state': fields.related('stage_id', 'state', type="selection", store=True, selection=_TASK_STATE, string="Status", readonly=True, help='The status is set to \'Draft\', when a case is created.\ @@ -889,6 +910,12 @@ class task(base_stage, osv.osv): res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm) return res + def get_empty_list_help(self, cr, uid, help, context=None): + context['empty_list_help_id'] = context.get('default_project_id') + context['empty_list_help_model'] = 'project.project' + context['empty_list_help_document_name'] = _("tasks") + return super(task, self).get_empty_list_help(cr, uid, help, context=context) + # ---------------------------------------- # Case management # ---------------------------------------- @@ -929,7 +956,7 @@ class task(base_stage, osv.osv): if task.child_ids: for child in task.child_ids: if child.state in ['draft', 'open', 'pending']: - raise osv.except_osv(_("Warning !"), _("Child task still open.\nPlease cancel or complete child task first.")) + raise osv.except_osv(_("Warning!"), _("Child task still open.\nPlease cancel or complete child task first.")) return True def action_close(self, cr, uid, ids, context=None): @@ -1093,10 +1120,12 @@ class task(base_stage, osv.osv): context = {} if not vals.get('stage_id'): ctx = context.copy() - if vals.get('project_id'): + if vals.get('project_id'): ctx['default_project_id'] = vals['project_id'] vals['stage_id'] = self._get_default_stage_id(cr, uid, context=ctx) - task_id = super(task, self).create(cr, uid, vals, context=context) + # context: no_log, because subtype already handle this + create_context = dict(context, mail_create_nolog=True) + task_id = super(task, self).create(cr, uid, vals, context=create_context) self._store_history(cr, uid, [task_id], context=context) return task_id @@ -1170,6 +1199,17 @@ class task(base_stage, osv.osv): return [task.project_id.message_get_reply_to()[0] if task.project_id else False for task in self.browse(cr, uid, ids, context=context)] + def check_mail_message_access(self, cr, uid, mids, operation, model_obj=None, context=None): + """ mail.message document permission rule: can post a new message if can read + because of portal document. """ + if not model_obj: + model_obj = self + if operation == 'create': + model_obj.check_access_rights(cr, uid, 'read') + model_obj.check_access_rule(cr, uid, mids, 'read', context=context) + else: + return super(task, self).check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context) + def message_new(self, cr, uid, msg, custom_values=None, context=None): """ Override to updates the document according to the email. """ if custom_values is None: custom_values = {} @@ -1178,7 +1218,7 @@ class task(base_stage, osv.osv): 'planned_hours': 0.0, } defaults.update(custom_values) - return super(task,self).message_new(cr, uid, msg, custom_values=defaults, context=context) + return super(task, self).message_new(cr, uid, msg, custom_values=defaults, context=context) def message_update(self, cr, uid, ids, msg, update_vals=None, context=None): """ Override to update the task according to the email. """ diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index f5fbf878fd0..b7dcc2bdb83 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -62,7 +62,7 @@ E-Learning Integration project.task - public + employees @@ -76,6 +76,7 @@ Website Design Templates project.task + employees @@ -89,6 +90,7 @@ Data Import/Export Plugin project.task + followers diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 16dbe44ccc1..eb042e5f0c7 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -50,16 +50,18 @@ Tasks project.task kanban,tree,form,calendar,gantt,graph - {'search_default_project_id': [active_id], 'default_project_id': active_id} + { + 'search_default_project_id': [active_id], + 'default_project_id': active_id, + 'active_test': False, + } -

- Click to create a new task. -

- OpenERP's project management allows you to manage the pipeline - of tasks in order to get things done efficiently. You can - track progress, discuss on tasks, attach documents, etc. -

+

+ OpenERP's project management allows you to manage the pipeline + of tasks in order to get things done efficiently. You can + track progress, discuss on tasks, attach documents, etc. +

@@ -87,6 +89,17 @@

+
+
-

+
+ %% +
@@ -622,13 +630,11 @@ kanban,tree,form,calendar,gantt,graph -

- Click to create a new task. -

- OpenERP's project management allows you to manage the pipeline - of tasks in order to get things done efficiently. You can - track progress, discuss on tasks, attach documents, etc. -

+

+ OpenERP's project management allows you to manage the pipeline + of tasks in order to get things done efficiently. You can + track progress, discuss on tasks, attach documents, etc. +

diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml index c30c91fe6c0..17e059c8de7 100644 --- a/addons/project/report/project_cumulative.xml +++ b/addons/project/report/project_cumulative.xml @@ -6,7 +6,7 @@ project.task.history.cumulative.tree project.task.history.cumulative - + diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py index 8e7dca059f9..006aae1085c 100644 --- a/addons/project/report/project_report.py +++ b/addons/project/report/project_report.py @@ -117,5 +117,4 @@ class report_project_task_user(osv.osv): """) -report_project_task_user() diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml index 10f3f4a8c7c..d9650e165ce 100644 --- a/addons/project/report/project_report_view.xml +++ b/addons/project/report/project_report_view.xml @@ -69,7 +69,7 @@ - + diff --git a/addons/project/res_partner.py b/addons/project/res_partner.py index 97fca8c459f..e4ca63d79d8 100644 --- a/addons/project/res_partner.py +++ b/addons/project/res_partner.py @@ -29,7 +29,6 @@ class res_partner(osv.osv): 'task_ids': fields.one2many('project.task', 'partner_id', 'Tasks'), } -res_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml index f1d8c7e760f..e674019443b 100644 --- a/addons/project/security/project_security.xml +++ b/addons/project/security/project_security.xml @@ -38,39 +38,60 @@ - Project multi-company + Project: multi-company - ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + ['|', + ('company_id', '=', False), + ('company_id', 'child_of', [user.company_id.id]), + ] + + + + Project: project manager: see all + + [(1, '=', 1)] + - Public Members + Project: employees: public, employees or followers - - ['|',('privacy_visibility','in',[False,'public']),('message_follower_ids','in',[user.partner_id.id])] + ['|', + ('privacy_visibility', 'in', ['public', 'employees']), + ('message_follower_ids', 'in', [user.partner_id.id]) + ] + - Task multi-company + Project/Task: multi-company - ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + ['|', + ('company_id', '=', False), + ('company_id', 'child_of', [user.company_id.id]), + ] - Tasks According to User and Project + Project/Task: employees: public or employee or (followers and following) - - ['|','|','|',('user_id','=',False),('user_id','=',user.id),('project_id.members','in', [user.id]),('project_id.user_id','=',user.id)] - + ['|', + ('project_id.privacy_visibility', 'in', ['public', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.partner_id.id]), + ] + - Project Managers: all tasks from all projects + Project/Task: project manager: see all - [(1,'=',1)] + [(1, '=', 1)] + diff --git a/addons/project/wizard/project_task_delegate.py b/addons/project/wizard/project_task_delegate.py index bb15c62db1f..6a26868557e 100644 --- a/addons/project/wizard/project_task_delegate.py +++ b/addons/project/wizard/project_task_delegate.py @@ -125,13 +125,12 @@ class project_task_delegate(osv.osv_memory): action_model, action_id = models_data.get_object_reference(cr, uid, 'project', 'action_view_task') view_model, task_view_form_id = models_data.get_object_reference(cr, uid, 'project', 'view_task_form2') view_model, task_view_tree_id = models_data.get_object_reference(cr, uid, 'project', 'view_task_tree2') - action = self.pool.get(action_model).read(cr, uid, action_id, context=context) + action = self.pool[action_model].read(cr, uid, action_id, context=context) action['res_id'] = delegated_tasks[task_id] action['view_id'] = False action['views'] = [(task_view_form_id, 'form'), (task_view_tree_id, 'tree')] action['help'] = False return action -project_task_delegate() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/wizard/project_task_reevaluate.py b/addons/project/wizard/project_task_reevaluate.py index 1cbea397d5e..eeb8cccc5d2 100644 --- a/addons/project/wizard/project_task_reevaluate.py +++ b/addons/project/wizard/project_task_reevaluate.py @@ -80,6 +80,5 @@ class project_task_reevaluate(osv.osv_memory): if context.get('button_reactivate'): task_pool.do_reopen(cr, uid, [task_id], context=context) return {'type': 'ir.actions.act_window_close'} -project_task_reevaluate() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_gtd/project_gtd.py b/addons/project_gtd/project_gtd.py index 715544cf4fc..47569e863aa 100644 --- a/addons/project_gtd/project_gtd.py +++ b/addons/project_gtd/project_gtd.py @@ -37,7 +37,6 @@ class project_gtd_context(osv.osv): } _order = "sequence, name" -project_gtd_context() class project_gtd_timebox(osv.osv): @@ -49,7 +48,6 @@ class project_gtd_timebox(osv.osv): 'icon': fields.selection(tools.icons, 'Icon', size=64), } -project_gtd_timebox() class project_task(osv.osv): _inherit = "project.task" @@ -120,6 +118,5 @@ class project_task(osv.osv): return res -project_task() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_gtd/project_gtd_view.xml b/addons/project_gtd/project_gtd_view.xml index 1467ce55fab..4bfd5b783c7 100644 --- a/addons/project_gtd/project_gtd_view.xml +++ b/addons/project_gtd/project_gtd_view.xml @@ -106,6 +106,8 @@ + + diff --git a/addons/project_gtd/wizard/project_gtd_empty.py b/addons/project_gtd/wizard/project_gtd_empty.py index 26e438b789e..3233e2534af 100644 --- a/addons/project_gtd/wizard/project_gtd_empty.py +++ b/addons/project_gtd/wizard/project_gtd_empty.py @@ -49,7 +49,7 @@ class project_timebox_empty(osv.osv_memory): ids = obj_tb.search(cr, uid, [], context=context) if not len(ids): - raise osv.except_osv(_('Error!'), _('No timebox child of this one !')) + raise osv.except_osv(_('Error!'), _('No timebox child of this one!')) tids = obj_task.search(cr, uid, [('timebox_id', '=', context['active_id'])]) for task in obj_task.browse(cr, uid, tids, context): if (task.state in ('cancel','done')) or (task.user_id.id <> uid): @@ -62,6 +62,5 @@ class project_timebox_empty(osv.osv_memory): obj_task.write(cr, uid, close, {'timebox_id':False}) return {} -project_timebox_empty() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_gtd/wizard/project_gtd_fill.py b/addons/project_gtd/wizard/project_gtd_fill.py index ae8fea61e1c..121bd7efdac 100644 --- a/addons/project_gtd/wizard/project_gtd_fill.py +++ b/addons/project_gtd/wizard/project_gtd_fill.py @@ -56,6 +56,5 @@ class project_timebox_fill(osv.osv_memory): self.pool.get('project.task').write(cr, uid, data[0]['task_ids'], {'timebox_id':data[0]['timebox_to_id'][0]}) return {'type': 'ir.actions.act_window_close'} -project_timebox_fill() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index f8f6510cd49..8bcac4581c3 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -19,11 +19,12 @@ # ############################################################################## +from openerp import SUPERUSER_ID from openerp.addons.base_status.base_stage import base_stage from openerp.addons.project.project import _TASK_STATE from openerp.addons.crm import crm from datetime import datetime -from openerp.osv import fields,osv +from openerp.osv import fields, osv, orm from openerp.tools.translate import _ import binascii import time @@ -40,7 +41,6 @@ class project_issue_version(osv.osv): _defaults = { 'active': 1, } -project_issue_version() class project_issue(base_stage, osv.osv): _name = "project.issue" @@ -50,12 +50,12 @@ class project_issue(base_stage, osv.osv): _track = { 'state': { - 'project_issue.mt_issue_new': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'new', + 'project_issue.mt_issue_new': lambda self, cr, uid, obj, ctx=None: obj['state'] in ['new', 'draft'], 'project_issue.mt_issue_closed': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done', 'project_issue.mt_issue_started': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'open', }, 'stage_id': { - 'project_issue.mt_issue_stage': lambda self, cr, uid, obj, ctx=None: obj['state'] not in ['new', 'done', 'open'], + 'project_issue.mt_issue_stage': lambda self, cr, uid, obj, ctx=None: obj['state'] not in ['new', 'draft', 'done', 'open'], }, 'kanban_state': { 'project_issue.mt_issue_blocked': lambda self, cr, uid, obj, ctx=None: obj['kanban_state'] == 'blocked', @@ -70,7 +70,9 @@ class project_issue(base_stage, osv.osv): if vals.get('project_id'): ctx['default_project_id'] = vals['project_id'] vals['stage_id'] = self._get_default_stage_id(cr, uid, context=ctx) - return super(project_issue, self).create(cr, uid, vals, context=context) + # context: no_log, because subtype already handle this + create_context = dict(context, mail_create_nolog=True) + return super(project_issue, self).create(cr, uid, vals, context=create_context) def _get_default_project_id(self, cr, uid, context=None): """ Gives default project by checking if present in the context """ @@ -271,7 +273,7 @@ class project_issue(base_stage, osv.osv): 'version_id': fields.many2one('project.issue.version', 'Version'), 'stage_id': fields.many2one ('project.task.type', 'Stage', track_visibility='onchange', - domain="['&', ('fold', '=', False), ('project_ids', '=', project_id)]"), + domain="[('project_ids', '=', project_id)]"), 'project_id':fields.many2one('project.project', 'Project', track_visibility='onchange'), 'duration': fields.float('Duration'), 'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]"), @@ -416,6 +418,12 @@ class project_issue(base_stage, osv.osv): self.write(cr, uid, ids, {'date_open': False, 'date_closed': False}) return res + def get_empty_list_help(self, cr, uid, help, context=None): + context['empty_list_help_model'] = 'project.project' + context['empty_list_help_id'] = context.get('default_project_id') + context['empty_list_help_document_name'] = _("issues") + return super(project_issue, self).get_empty_list_help(cr, uid, help, context=context) + # ------------------------------------------------------- # Stage management # ------------------------------------------------------- @@ -487,13 +495,27 @@ class project_issue(base_stage, osv.osv): return [issue.project_id.message_get_reply_to()[0] if issue.project_id else False for issue in self.browse(cr, uid, ids, context=context)] + def check_mail_message_access(self, cr, uid, mids, operation, model_obj=None, context=None): + """ mail.message document permission rule: can post a new message if can read + because of portal document. """ + if not model_obj: + model_obj = self + if operation == 'create': + model_obj.check_access_rights(cr, uid, 'read') + model_obj.check_access_rule(cr, uid, mids, 'read', context=context) + else: + return super(project_issue, self).check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context) + def message_get_suggested_recipients(self, cr, uid, ids, context=None): recipients = super(project_issue, self).message_get_suggested_recipients(cr, uid, ids, context=context) - for issue in self.browse(cr, uid, ids, context=context): - if issue.partner_id: - self._message_add_suggested_recipient(cr, uid, recipients, issue, partner=issue.partner_id, reason=_('Customer')) - elif issue.email_from: - self._message_add_suggested_recipient(cr, uid, recipients, issue, email=issue.email_from, reason=_('Customer Email')) + try: + for issue in self.browse(cr, uid, ids, context=context): + if issue.partner_id: + self._message_add_suggested_recipient(cr, uid, recipients, issue, partner=issue.partner_id, reason=_('Customer')) + elif issue.email_from: + self._message_add_suggested_recipient(cr, uid, recipients, issue, email=issue.email_from, reason=_('Customer Email')) + except (osv.except_osv, orm.except_orm): # no read access rights -> just ignore suggested recipients because this imply modifying followers + pass return recipients def message_new(self, cr, uid, msg, custom_values=None, context=None): @@ -555,15 +577,13 @@ class project_issue(base_stage, osv.osv): """ if context is None: context = {} - res = super(project_issue, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs) - if thread_id: - self.write(cr, uid, thread_id, {'date_action_last': time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) - - return res + self.write(cr, SUPERUSER_ID, thread_id, {'date_action_last': time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) + return res -class project(osv.osv): + +class project(osv.Model): _inherit = "project.project" def _get_alias_models(self, cr, uid, context=None): @@ -578,7 +598,9 @@ class project(osv.osv): return res _columns = { - 'project_escalation_id' : fields.many2one('project.project','Project Escalation', help='If any issue is escalated from the current Project, it will be listed under the project selected here.', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}), + 'project_escalation_id': fields.many2one('project.project', 'Project Escalation', + help='If any issue is escalated from the current Project, it will be listed under the project selected here.', + states={'close': [('readonly', True)], 'cancelled': [('readonly', True)]}), 'issue_count': fields.function(_issue_count, type='integer', string="Unclosed Issues"), } @@ -593,14 +615,13 @@ class project(osv.osv): (_check_escalation, 'Error! You cannot assign escalation to the same project!', ['project_escalation_id']) ] -project() -class account_analytic_account(osv.osv): +class account_analytic_account(osv.Model): _inherit = 'account.analytic.account' _description = 'Analytic Account' _columns = { - 'use_issues' : fields.boolean('Issues', help="Check this field if this project manages issues"), + 'use_issues': fields.boolean('Issues', help="Check this field if this project manages issues"), } def on_change_template(self, cr, uid, ids, template_id, context=None): @@ -611,16 +632,34 @@ class account_analytic_account(osv.osv): return res def _trigger_project_creation(self, cr, uid, vals, context=None): - if context is None: context = {} + if context is None: + context = {} res = super(account_analytic_account, self)._trigger_project_creation(cr, uid, vals, context=context) return res or (vals.get('use_issues') and not 'project_creation_in_progress' in context) -account_analytic_account() -class project_project(osv.osv): +class project_project(osv.Model): _inherit = 'project.project' + _defaults = { 'use_issues': True } + def _check_create_write_values(self, cr, uid, vals, context=None): + """ Perform some check on values given to create or write. """ + # Handle use_tasks / use_issues: if only one is checked, alias should take the same model + if vals.get('use_tasks') and not vals.get('use_issues'): + vals['alias_model'] = 'project.task' + elif vals.get('use_issues') and not vals.get('use_tasks'): + vals['alias_model'] = 'project.issue' + + def create(self, cr, uid, vals, context=None): + self._check_create_write_values(cr, uid, vals, context=context) + return super(project_project, self).create(cr, uid, vals, context=context) + + def write(self, cr, uid, ids, vals, context=None): + self._check_create_write_values(cr, uid, vals, context=context) + return super(project_project, self).write(cr, uid, ids, vals, context=context) + + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_issue/project_issue_menu.xml b/addons/project_issue/project_issue_menu.xml index 78841f56156..308b4884844 100644 --- a/addons/project_issue/project_issue_menu.xml +++ b/addons/project_issue/project_issue_menu.xml @@ -14,13 +14,11 @@ -

- Click to report a new issue. -

- The OpenERP issues tacker allows you to efficiantly manage things - like internal requests, software development bugs, customer - complaints, project troubles, material breakdowns, etc. -

+

+ The OpenERP issues tacker allows you to efficiantly manage things + like internal requests, software development bugs, customer + complaints, project troubles, material breakdowns, etc. +

diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 500a1376422..46caba0021e 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -68,15 +68,16 @@
- Product + Product - Quantity + Quantity - Source Location + Source Location - Destination Location + Destination Location
- Source Document + Source Document - Product + Product - Quantity + Quantity
- Scheduled Date + Scheduled Date - Printing date + Printing date - Partner Ref + Partner Ref - SO Number + SO Number
- Sequence + Sequence - Name [[ o.workcenter_lines ==[] and removeParentNode('blockTable')]] + Name [[ o.workcenter_lines ==[] and removeParentNode('blockTable')]] - WorkCenter + WorkCenter - No. Of Cycles + No. Of Cycles - No. Of Hours + No. Of Hours
- Product + Product - Quantity + Quantity - Source Location + Source Location - Destination Location + Destination Location
- +