diff --git a/addons/account/account.py b/addons/account/account.py index 8c7f058acc6..3959799f1bb 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -25,8 +25,9 @@ from dateutil.relativedelta import relativedelta from operator import itemgetter import time +import openerp from openerp import SUPERUSER_ID -from openerp import pooler, tools +from openerp import tools from openerp.osv import fields, osv from openerp.tools.translate import _ from openerp.tools.float_utils import float_round @@ -131,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" @@ -197,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') @@ -211,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" @@ -696,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" @@ -848,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" @@ -944,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" @@ -1006,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'])) @@ -1015,7 +1009,7 @@ 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: @@ -1026,6 +1020,9 @@ class account_period(osv.osv): 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')) 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 @@ -1067,7 +1064,6 @@ class account_period(osv.osv): 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)]) -account_period() class account_journal_period(osv.osv): _name = "account.journal.period" @@ -1124,7 +1120,6 @@ class account_journal_period(osv.osv): } _order = "period_id" -account_journal_period() class account_fiscalyear(osv.osv): _inherit = "account.fiscalyear" @@ -1141,7 +1136,6 @@ class account_fiscalyear(osv.osv): }) return super(account_fiscalyear, self).copy(cr, uid, id, default=default, context=context) -account_fiscalyear() #---------------------------------------------------------- # Entries #---------------------------------------------------------- @@ -1219,7 +1213,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] @@ -1380,6 +1374,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): @@ -1416,6 +1411,7 @@ class account_move(osv.osv): context = {} if context is None else context.copy() default.update({ 'state':'draft', + 'ref': False, 'name':'/', }) context.update({ @@ -1637,7 +1633,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" @@ -1711,7 +1706,6 @@ class account_move_reconcile(osv.osv): result.append((r.id,r.name)) return result -account_move_reconcile() #---------------------------------------------------------- # Tax @@ -1791,7 +1785,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] @@ -1859,7 +1853,6 @@ class account_tax_code(osv.osv): ] _order = 'code' -account_tax_code() class account_tax(osv.osv): """ @@ -1883,7 +1876,7 @@ class account_tax(osv.osv): def get_precision_tax(): def change_digit_tax(cr): - res = pooler.get_pool(cr.dbname).get('decimal.precision').precision_get(cr, SUPERUSER_ID, 'Account') + res = openerp.registry(cr.dbname)['decimal.precision'].precision_get(cr, SUPERUSER_ID, 'Account') return (16, res+2) return change_digit_tax @@ -2267,7 +2260,6 @@ class account_tax(osv.osv): total += r['amount'] return res -account_tax() # --------------------------------------------------------- # Account Entries Models @@ -2379,7 +2371,6 @@ class account_model(osv.osv): return {'value': {'company_id': company_id}} -account_model() class account_model_line(osv.osv): _name = "account.model.line" @@ -2403,7 +2394,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 @@ -2477,7 +2467,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" @@ -2506,7 +2495,6 @@ class account_subscription_line(osv.osv): _rec_name = 'date' -account_subscription_line() # --------------------------------------------------------------- # Account Templates: Account, Tax, Tax Code and chart. + Wizard @@ -2514,7 +2502,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" @@ -2642,7 +2629,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. @@ -2696,7 +2682,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): @@ -2768,7 +2753,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): @@ -2801,7 +2785,6 @@ class account_chart_template(osv.osv): 'complete_tax_set': True, } -account_chart_template() class account_tax_template(osv.osv): @@ -2931,7 +2914,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 @@ -2979,7 +2961,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' @@ -2992,7 +2973,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' @@ -3004,7 +2984,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 @@ -3397,7 +3376,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: @@ -3544,7 +3523,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' @@ -3556,6 +3534,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..023765d73f0 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 @@ -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..40f0ca80738 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): @@ -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 1d9a4a794eb..0c2e5845b89 100644 --- a/addons/account/account_financial_report.py +++ b/addons/account/account_financial_report.py @@ -24,8 +24,6 @@ from datetime import datetime from dateutil.relativedelta import relativedelta from operator import itemgetter -from openerp import netsvc -from openerp import pooler from openerp.osv import fields, osv import openerp.addons.decimal_precision as dp from openerp.tools.translate import _ @@ -140,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_invoice.py b/addons/account/account_invoice.py index d771bc59506..c47cf70b673 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -24,7 +24,6 @@ from lxml import etree import openerp.addons.decimal_precision as dp import openerp.exceptions -from openerp import pooler from openerp.osv import fields, osv, orm from openerp.tools.translate import _ @@ -97,6 +96,8 @@ class account_invoice(osv.osv): for m in invoice.move_id.line_id: if m.account_id.type in ('receivable','payable'): result[invoice.id] += m.amount_residual_currency + #prevent the residual amount on the invoice to be less than 0 + result[invoice.id] = max(result[invoice.id], 0.0) return result # Give Journal Items related to the payment reconciled to this invoice @@ -285,7 +286,10 @@ class account_invoice(osv.osv): 'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'), 'move_name': fields.char('Journal Entry', size=64, readonly=True, states={'draft':[('readonly',False)]}), 'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, track_visibility='onchange', states={'draft':[('readonly',False)]}), - 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]}) + 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]}), + 'commercial_partner_id': fields.related('partner_id', 'commercial_partner_id', string='Commercial Entity', type='many2one', + relation='res.partner', store=True, readonly=True, + help="The commercial entity that will be used on Journal Entries for this invoice") } _defaults = { 'type': _get_type, @@ -312,7 +316,7 @@ class account_invoice(osv.osv): context = {} if context.get('active_model', '') in ['res.partner'] and context.get('active_ids', False) and context['active_ids']: - partner = self.pool.get(context['active_model']).read(cr, uid, context['active_ids'], ['supplier','customer'])[0] + partner = self.pool[context['active_model']].read(cr, uid, context['active_ids'], ['supplier','customer'])[0] if not view_type: view_id = self.pool.get('ir.ui.view').search(cr, uid, [('name', '=', 'account.invoice.tree')]) view_type = 'tree' @@ -366,18 +370,6 @@ class account_invoice(osv.osv): context['view_id'] = view_id return context - def create(self, cr, uid, vals, context=None): - if context is None: - context = {} - try: - return super(account_invoice, self).create(cr, uid, vals, context) - except Exception, e: - if '"journal_id" viol' in e.args[0]: - raise orm.except_orm(_('Configuration Error!'), - _('There is no Sale/Purchase Journal(s) defined.')) - else: - raise orm.except_orm(_('Unknown Error!'), str(e)) - def invoice_print(self, cr, uid, ids, context=None): ''' This function prints the invoice and mark it as sent, so that we can see more easily the next step of the workflow @@ -420,6 +412,7 @@ class account_invoice(osv.osv): 'mark_invoice_as_sent': True, }) return { + 'name': _('Compose Email'), 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', @@ -995,8 +988,7 @@ class account_invoice(osv.osv): 'narration':inv.comment } period_id = inv.period_id and inv.period_id.id or False - ctx.update(company_id=inv.company_id.id, - account_period_prefer_normal=True) + ctx.update(company_id=inv.company_id.id) if not period_id: period_ids = period_obj.find(cr, uid, inv.date_invoice, context=ctx) period_id = period_ids and period_ids[0] or False @@ -1272,9 +1264,7 @@ class account_invoice(osv.osv): ref = invoice.reference else: ref = self._convert_ref(cr, uid, invoice.number) - partner = invoice.partner_id - if partner.parent_id and not partner.is_company: - partner = partner.parent_id + partner = self.pool['res.partner']._find_accounting_partner(invoice.partner_id) # Pay attention to the sign for both debit/credit AND amount_currency l1 = { 'debit': direction * pay_amount>0 and direction * pay_amount, @@ -1594,7 +1584,6 @@ class account_invoice_line(osv.osv): unique_tax_ids = product_change_result['value']['invoice_line_tax_id'] return {'value':{'invoice_line_tax_id': unique_tax_ids}} -account_invoice_line() class account_invoice_tax(osv.osv): _name = "account.invoice.tax" @@ -1745,15 +1734,11 @@ class res_partner(osv.osv): 'invoice_ids': fields.one2many('account.invoice.line', 'partner_id', 'Invoices', readonly=True), } - def _find_accounting_partner(self, part): + def _find_accounting_partner(self, partner): ''' Find the partner for which the accounting entries will be created ''' - #if the chosen partner is not a company and has a parent company, use the parent for the journal entries - #because you want to invoice 'Agrolait, accounting department' but the journal items are for 'Agrolait' - if part.parent_id and not part.is_company: - part = part.parent_id - return part + return partner.commercial_partner_id def copy(self, cr, uid, id, default=None, context=None): default = default or {} diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 8c0854bd6c6..7469c38decb 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -117,6 +117,7 @@ + @@ -320,7 +321,8 @@ + options='{"always_reload": True}' + domain="[('customer', '=', True)]"/> @@ -447,18 +449,20 @@ account.invoice - + - - + + + - + + @@ -621,8 +625,6 @@ - - p.last_reconciliation_date) AND l.state <> 'draft' GROUP BY l.partner_id, p.last_reconciliation_date ) AS s - WHERE debit > 0 AND credit > 0 + WHERE debit > 0 AND credit > 0 AND (last_reconciliation_date IS NULL OR max_date > last_reconciliation_date) ORDER BY last_reconciliation_date""") - ids = cr.fetchall() - ids = len(ids) and [x[0] for x in ids] or [] - return self.pool.get('res.partner').name_get(cr, uid, ids, context=context) + ids = [x[0] for x in cr.fetchall()] + if not ids: + return [] + + # To apply the ir_rules + partner_obj = self.pool.get('res.partner') + ids = partner_obj.search(cr, uid, [('id', 'in', ids)], context=context) + return partner_obj.name_get(cr, uid, ids, context=context) def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False): move_rec_obj = self.pool.get('account.move.reconcile') @@ -983,8 +980,7 @@ class account_move_line(osv.osv): if context is None: context = {} period_pool = self.pool.get('account.period') - ctx = dict(context, account_period_prefer_normal=True) - pids = period_pool.find(cr, user, date, context=ctx) + pids = period_pool.find(cr, user, date, context=context) if pids: res.update({ 'period_id':pids[0] @@ -1306,6 +1302,5 @@ class account_move_line(osv.osv): bool(journal.currency),bool(journal.analytic_journal_id))) return result -account_move_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account_report.xml b/addons/account/account_report.xml index 0017409f416..6e121c9f5a5 100644 --- a/addons/account/account_report.xml +++ b/addons/account/account_report.xml @@ -11,7 +11,7 @@ - + - + @@ -1194,7 +1194,12 @@ sequence="1" groups="group_account_user" /> - + + Journal Items + account.move.line + {'search_default_partner_id': [active_id], 'default_partner_id': active_id} + + account.move.line @@ -1288,7 +1293,7 @@ - + @@ -1352,7 +1357,7 @@ - + @@ -1771,23 +1776,6 @@ - - - - - , 2012. +# Els Van Vossel , 2012, 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:04+0000\n" -"PO-Revision-Date: 2012-12-19 18:03+0000\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:20+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 @@ -258,7 +258,7 @@ msgstr "Belgische rapporten" #. module: account #: model:mail.message.subtype,name:account.mt_invoice_validated msgid "Validated" -msgstr "" +msgstr "Goedgekeurd" #. module: account #: model:account.account.type,name:account.account_type_income_view1 @@ -473,14 +473,14 @@ msgstr "" #. module: account #: help:account.bank.statement.line,name:0 msgid "Originator to Beneficiary Information" -msgstr "" +msgstr "Informatie Afzender naar Begunstigde" #. module: account #. openerp-web #: code:addons/account/static/src/xml/account_move_line_quickadd.xml:8 #, python-format msgid "Period :" -msgstr "" +msgstr "Periode:" #. module: account #: field:account.account.template,chart_template_id:0 @@ -494,6 +494,7 @@ msgstr "Boekhoudplansjabloon" #: selection:account.invoice.refund,filter_refund:0 msgid "Modify: create refund, reconcile and create a new draft invoice" msgstr "" +"Wijzigen: factuur crediteren, afpunten en een nieuwe conceptfactuur maken" #. module: account #: help:account.config.settings,tax_calculation_rounding_method:0 @@ -803,7 +804,7 @@ msgstr "Stel de bankrekeningen van uw bedrijf in" #. module: account #: view:account.invoice.refund:0 msgid "Create Refund" -msgstr "" +msgstr "Creditnota maken" #. module: account #: constraint:account.move.line:0 @@ -833,7 +834,7 @@ msgstr "Bent u zeker dat u de boeking wilt uitvoeren?" #: code:addons/account/account_invoice.py:1330 #, python-format msgid "Invoice partially paid: %s%s of %s%s (%s%s remaining)." -msgstr "" +msgstr "Factuur is gedeeltelijk betaald: %s%s of %s%s (%s%s blijft open)" #. module: account #: view:account.invoice:0 @@ -1010,6 +1011,8 @@ msgid "" " opening/closing fiscal " "year process." msgstr "" +"U kunt geen afpunting ongedaan maken als deze afpunting voortkomt uit een " +"heropening." #. module: account #: model:ir.actions.act_window,name:account.action_subscription_form_new @@ -1052,7 +1055,7 @@ msgstr "Aankoopjournaal" #. module: account #: model:mail.message.subtype,description:account.mt_invoice_paid msgid "Invoice paid" -msgstr "" +msgstr "Factuur betaald" #. module: account #: view:validate.account.move:0 @@ -1375,6 +1378,8 @@ msgid "" "The amount expressed in the secondary currency must be positif when journal " "item are debit and negatif when journal item are credit." msgstr "" +"Het bedrag in secundaire munt moet positief zijn als de boekingslijn debet " +"is en negatief bij een creditbedrag." #. module: account #: view:account.invoice.cancel:0 @@ -1940,7 +1945,7 @@ msgstr "Verkopen per rekeningtype" #: model:account.payment.term,name:account.account_payment_term_15days #: model:account.payment.term,note:account.account_payment_term_15days msgid "15 Days" -msgstr "" +msgstr "15 dagen" #. module: account #: model:ir.ui.menu,name:account.periodical_processing_invoicing @@ -2084,7 +2089,7 @@ msgstr "Voorlopig rekeninguittreksel" #. module: account #: model:mail.message.subtype,description:account.mt_invoice_validated msgid "Invoice validated" -msgstr "" +msgstr "Factuur goedgekeurd" #. module: account #: field:account.config.settings,module_account_check_writing:0 @@ -2342,6 +2347,7 @@ msgid "" "You cannot change the type of account to '%s' type as it contains journal " "items!" msgstr "" +"U kunt het rekeningtype niet wijzigen in '%s' omdat er al boekingen zijn." #. module: account #: model:ir.model,name:account.model_account_aged_trial_balance @@ -2358,7 +2364,7 @@ msgstr "Boekjaar afsluiten" #: code:addons/account/static/src/xml/account_move_line_quickadd.xml:14 #, python-format msgid "Journal :" -msgstr "" +msgstr "Journaal:" #. module: account #: sql_constraint:account.fiscal.position.tax:0 @@ -2718,6 +2724,8 @@ msgid "" "You cannot change the type of account from 'Closed' to any other type as it " "contains journal items!" msgstr "" +"U kunt het rekeningtype niet wijzigen van 'Afgesloten' in een ander type als " +"er boekingen zijn." #. module: account #: field:account.invoice.report,account_line_id:0 @@ -2811,7 +2819,7 @@ msgstr "Rekeningeigenschappen" #. module: account #: selection:account.invoice.refund,filter_refund:0 msgid "Create a draft refund" -msgstr "" +msgstr "Maak een voorlopige creditnota" #. module: account #: view:account.partner.reconcile.process:0 @@ -3360,7 +3368,7 @@ msgstr "" #: view:account.unreconcile:0 #: view:account.unreconcile.reconcile:0 msgid "Unreconcile Transactions" -msgstr "" +msgstr "Afpuntingen ongedaan maken" #. module: account #: field:wizard.multi.charts.accounts,only_one_chart_template:0 @@ -3558,7 +3566,7 @@ msgstr "Aantal cijfers voor de rekeningcode" #. module: account #: field:res.partner,property_supplier_payment_term:0 msgid "Supplier Payment Term" -msgstr "" +msgstr "Betaaltermijn leverancier" #. module: account #: view:account.fiscalyear:0 @@ -3633,7 +3641,7 @@ msgstr "Elektronisch bestand" #. module: account #: field:account.move.line,reconcile:0 msgid "Reconcile Ref" -msgstr "" +msgstr "Afpuntingsreferentie" #. module: account #: field:account.config.settings,has_chart_of_accounts:0 @@ -3734,6 +3742,88 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +"\n" +"

Hallo ${object.partner_id.name},

\n" +"\n" +"

Er is een nieuwe factuur voor u:

\n" +" \n" +"

\n" +"   REFERENTIE
\n" +"   Factuurnummer: ${object.number}
\n" +"   Totaal: ${object.amount_total} " +"${object.currency_id.name}
\n" +"   Datum: ${object.date_invoice}
\n" +" % if object.origin:\n" +"   Referentie: ${object.origin}
\n" +" % endif\n" +" % if object.user_id:\n" +"   Uw contactpersoon: ${object.user_id.name}\n" +" % endif\n" +"

\n" +" \n" +" % if object.paypal_url:\n" +"
\n" +"

U kunt ook onmiddellijk betalen via Paypal:

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

Neem gerust contact met ons op als u vragen heeft.

\n" +"

Bedankt dat u hebt gekozen voor ${object.company_id.name or " +"'ons'}!

\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" +" Tel.:  ${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" +" " #. module: account #: view:account.period:0 @@ -3922,6 +4012,8 @@ msgid "" "You cannot create journal items with a secondary currency without recording " "both 'currency' and 'amount currency' field." msgstr "" +"U kunt geen boekingslijnen in een secundaire munt maken zonder beide velden " +"'valuta' en 'bedrag valuta' in te vullen." #. module: account #: field:account.financial.report,display_detail:0 @@ -4224,7 +4316,7 @@ msgstr "" #. module: account #: model:ir.model,name:account.model_account_journal_cashbox_line msgid "account.journal.cashbox.line" -msgstr "" +msgstr "account.journal.cashbox.line" #. module: account #: model:ir.model,name:account.model_account_partner_reconcile_process @@ -4498,7 +4590,7 @@ msgstr "Uw bankrekeningen instellen" #. module: account #: xsl:account.transfer:0 msgid "Partner ID" -msgstr "" +msgstr "Relatie-ID" #. module: account #: help:account.bank.statement,message_ids:0 @@ -4704,6 +4796,8 @@ msgid "" "This payment term will be used instead of the default one for sale orders " "and customer invoices" msgstr "" +"Deze betalingsvoorwaarde vervangt de standaardvoorwaarde van de huidige " +"relatie." #. module: account #: view:account.config.settings:0 @@ -4731,7 +4825,7 @@ msgstr "Geboekte lijnen" #. module: account #: field:account.move.line,blocked:0 msgid "No Follow-up" -msgstr "" +msgstr "Geen aanmaning" #. module: account #: view:account.tax.template:0 @@ -4858,6 +4952,7 @@ msgstr "Maand" #, python-format msgid "You cannot change the code of account which contains journal items!" msgstr "" +"U kunt de code van een rekening niet wijzigen als er al boekingen zijn." #. module: account #: field:account.config.settings,purchase_sequence_prefix:0 @@ -4895,7 +4990,7 @@ msgstr "Rek.type" #. module: account #: selection:account.journal,type:0 msgid "Bank and Checks" -msgstr "" +msgstr "Bank en cheques" #. module: account #: field:account.account.template,note:0 @@ -4977,7 +5072,7 @@ msgstr "Schakel dit in als u ook rekeningen met een nulsaldo wilt weergeven." #. module: account #: field:account.move.reconcile,opening_reconciliation:0 msgid "Opening Entries Reconciliation" -msgstr "" +msgstr "Afpunting openingsboekingen" #. module: account #. openerp-web @@ -5018,7 +5113,7 @@ msgstr "Boekhoudplan" #. module: account #: field:account.invoice,reference_type:0 msgid "Payment Reference" -msgstr "" +msgstr "Betaalreferentie" #. module: account #: selection:account.financial.report,style_overwrite:0 @@ -5092,7 +5187,7 @@ msgstr "Af te punten boekingen" #. module: account #: model:ir.model,name:account.model_account_tax_template msgid "Templates for Taxes" -msgstr "" +msgstr "Btw-sjablonen" #. module: account #: sql_constraint:account.period:0 @@ -5667,6 +5762,8 @@ msgstr "Doelbewegingen" msgid "" "Move cannot be deleted if linked to an invoice. (Invoice: %s - Move ID:%s)" msgstr "" +"Boeking kan niet worden verwijderd als deze is gekoppeld aan een factuur " +"(Factuur: %s - boeking: %s)" #. module: account #: view:account.bank.statement:0 @@ -6225,6 +6322,8 @@ msgid "" "This payment term will be used instead of the default one for purchase " "orders and supplier invoices" msgstr "" +"Deze betalingsvoorwaarde vervangt de standaardvoorwaarde van de huidige " +"relatie voor aankooporders en aankoopfacturen." #. module: account #: help:account.automatic.reconcile,power:0 @@ -6734,7 +6833,7 @@ msgstr "Analytische lijn" #. module: account #: model:ir.ui.menu,name:account.menu_action_model_form msgid "Models" -msgstr "" +msgstr "Modellen" #. module: account #: code:addons/account/account_invoice.py:1091 @@ -7055,6 +7154,12 @@ msgid "" "due date, make sure that the payment term is not set on the invoice. If you " "keep the payment term and the due date empty, it means direct payment." msgstr "" +"Als u betalingstermijnen gebruikt, wordt de vervaldatum automatisch berekend " +"bij het maken van de boekingen. De betalingsvoorwaarde kan verschillende " +"vervaldatums berekenen, vb. 50% nu en 50% binnen een maand. Als u een " +"specifieke vervaldatum wilt instellen, gebruikt u beter geen " +"betalingstermijn. Als u zowel betalingstermijn als vervaldatum leeglaat, " +"gaat het om een contante betaling." #. module: account #: code:addons/account/account.py:414 @@ -7296,6 +7401,8 @@ msgid "" "If you unreconcile transactions, you must also verify all the actions that " "are linked to those transactions because they will not be disabled" msgstr "" +"Als u afgepunte transacties ongedaan maakt, moet u alle gekoppelde acties " +"nakijken, want deze worden niet ongedaan gemaakt." #. module: account #: view:account.account.template:0 @@ -7330,6 +7437,7 @@ msgid "" "You cannot provide a secondary currency if it is the same than the company " "one." msgstr "" +"U kunt geen secundaire munt ingeven die identiek is aan de firmamunt." #. module: account #: selection:account.tax.template,applicable_type:0 @@ -7467,7 +7575,7 @@ msgstr "Manueel" #. module: account #: selection:account.invoice.refund,filter_refund:0 msgid "Cancel: create refund and reconcile" -msgstr "" +msgstr "Annuleren: maak een creditnota en punt af" #. module: account #: code:addons/account/wizard/account_report_aged_partner_balance.py:58 @@ -7564,7 +7672,7 @@ msgstr "Alle boekingen" #. module: account #: constraint:account.move.reconcile:0 msgid "You can only reconcile journal items with the same partner." -msgstr "" +msgstr "U kunt enkel boekingen met dezelfde relatie afpunten." #. module: account #: view:account.journal.select:0 @@ -7682,7 +7790,7 @@ msgstr "" #. module: account #: field:account.invoice,paypal_url:0 msgid "Paypal Url" -msgstr "" +msgstr "Paypal-url" #. module: account #: field:account.config.settings,module_account_voucher:0 @@ -8390,7 +8498,7 @@ msgstr "" #. module: account #: field:account.move.line,amount_residual_currency:0 msgid "Residual Amount in Currency" -msgstr "" +msgstr "Restbedrag in valuta" #. module: account #: field:account.config.settings,sale_refund_sequence_prefix:0 @@ -8444,6 +8552,8 @@ msgid "" "Refund base on this type. You can not Modify and Cancel if the invoice is " "already reconciled" msgstr "" +"Creditnota voor dit type. U kunt niet wijzigen of annuleren als de factuur " +"al is afgepunt." #. module: account #: field:account.bank.statement.line,sequence:0 @@ -8461,7 +8571,7 @@ msgstr "Volgorde" #. module: account #: field:account.config.settings,paypal_account:0 msgid "Paypal account" -msgstr "" +msgstr "Paypal-rekening" #. module: account #: selection:account.print.journal,sort_selection:0 @@ -8730,7 +8840,7 @@ msgstr "Omgekeerde analytische balans -" #: help:account.move.reconcile,opening_reconciliation:0 msgid "" "Is this reconciliation produced by the opening of a new fiscal year ?." -msgstr "" +msgstr "Komt deze afpunting van een openingsboeking?" #. module: account #: view:account.analytic.line:0 @@ -9011,7 +9121,7 @@ msgstr "Eindbalans" #. module: account #: field:account.journal,centralisation:0 msgid "Centralized Counterpart" -msgstr "" +msgstr "Gecentraliseerde tegenboeking" #. module: account #: help:account.move.line,blocked:0 @@ -9047,6 +9157,12 @@ msgid "" "invoice will be created \n" " so that you can edit it." msgstr "" +"Gebruik deze optie als u een factuur wilt annuleren en een nieuwe maken.\n" +" De creditnota wordt gemaakt, goedgekeurd " +"en afgepunt\n" +" met de huidige factuur. Een nieuwe, " +"voorlopige factuur wordt gemaakt\n" +" die u kunt bewerken." #. module: account #: model:process.transition,name:account.process_transition_filestatement0 @@ -9079,7 +9195,7 @@ msgstr "Rekeningtypen" #. module: account #: model:email.template,subject:account.email_template_edi_invoice msgid "${object.company_id.name} Invoice (Ref ${object.number or 'n/a'})" -msgstr "" +msgstr "${object.company_id.name} Factuur (Ref. ${object.number or 'nvt' })" #. module: account #: code:addons/account/account_move_line.py:1213 @@ -9149,6 +9265,19 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Klik om een journaal toe te voegen.\n" +"

\n" +" Een journaal groepeert boekingen in functie\n" +" van de dagelijkse bezigheden.\n" +"

\n" +" Een firma geruikt doorgaans een journaal per betaalmethode " +"(kas,\n" +" bankrekeningen, cheques), een aankoopdagboek, een " +"verkoopdagboek\n" +" en een diversendagboek.\n" +"

\n" +" " #. module: account #: model:ir.model,name:account.model_account_fiscalyear_close_state @@ -9276,6 +9405,9 @@ msgid "" "computed. Because it is space consuming, we do not allow to use it while " "doing a comparison." msgstr "" +"Met deze optie krijgt u meer details over de manier waarop de saldi worden " +"berekend. Omdat dit ruimte inneemt, is deze optie niet mogelijk bij " +"vergelijkingen." #. module: account #: model:ir.model,name:account.model_account_fiscalyear_close @@ -9292,6 +9424,8 @@ msgstr "De code van de rekening moet uniek zijn per firma." #: help:product.template,property_account_expense:0 msgid "This account will be used to value outgoing stock using cost price." msgstr "" +"Deze rekening dient voor de voorraadwaardering van de uitgaande voorraad op " +"basis van de kostprijs." #. module: account #: view:account.invoice:0 @@ -9354,6 +9488,17 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Klik als u een nieuwe recurrente boeking wilt maken.\n" +"

\n" +" Een terugkerende boeking wordt regelmatig op een bepaald " +"tijdstip herhaald,\n" +" vb. bij vervallen van een contract of overeenkomst met een\n" +" klant of een leverancier. U kunt dergelijke boekingen " +"voorbereiden\n" +" zodat deze automatisch worden geboekt.\n" +"

\n" +" " #. module: account #: view:account.journal:0 @@ -9396,6 +9541,8 @@ msgid "" "This allows you to check writing and printing.\n" " This installs the module account_check_writing." msgstr "" +"Hiermee kunt u cheques schrijven en afdrukken.\n" +" Hiermee wordt de module account_check_writing geïnstalleerd." #. module: account #: model:res.groups,name:account.group_account_invoice @@ -9681,6 +9828,9 @@ msgid "" "chart\n" " of accounts." msgstr "" +"Bevestigde facturen kunnen niet meer\n" +" worden gewijzigd. Facturen krijgen een uniek nummer\n" +" en de boekingen worden gemaakt." #. module: account #: model:process.node,note:account.process_node_bankstatement0 @@ -9906,11 +10056,15 @@ msgid "" "payments.\n" " This installs the module account_payment." msgstr "" +"Hiermee kunt u betaalopdrachten maken\n" +" * die als basis dienen voor verdere automatisering,\n" +" * om efficiënter betalingen te kunnen uitvoeren.\n" +" Hiermee wordt de module account_payment geïnstalleerd." #. module: account #: xsl:account.transfer:0 msgid "Document" -msgstr "" +msgstr "Document" #. module: account #: view:account.chart.template:0 @@ -10132,7 +10286,7 @@ msgstr "Kan geen boekingen maken tussen verschillende firma's." #. module: account #: model:ir.ui.menu,name:account.menu_finance_periodical_processing msgid "Periodic Processing" -msgstr "" +msgstr "Periodieke verwerking" #. module: account #: view:account.invoice.report:0 @@ -10212,7 +10366,7 @@ msgstr "Vervaldatum" #: model:account.payment.term,name:account.account_payment_term_immediate #: model:account.payment.term,note:account.account_payment_term_immediate msgid "Immediate Payment" -msgstr "" +msgstr "Contante betaling" #. module: account #: code:addons/account/account.py:1464 @@ -10424,11 +10578,16 @@ msgid "" "analytic account.\n" " This installs the module account_budget." msgstr "" +"Hiermee kunnen accountants budgetten beheren.\n" +" Als de hoofdbudgetten zijn ingesteld, kunnen de " +"projectleiders\n" +" het geplande bedrag instellen per analytische rekening.\n" +" Hiermee wordt de module account_budget geïnstalleerd." #. module: account #: field:account.bank.statement.line,name:0 msgid "OBI" -msgstr "" +msgstr "Omschrijving" #. module: account #: help:res.partner,property_account_payable:0 @@ -10915,6 +11074,8 @@ msgid "" "If you unreconcile transactions, you must also verify all the actions that " "are linked to those transactions because they will not be disable" msgstr "" +"Als u afgepunte transacties ongedaan maakt, moet u alle gekoppelde acties " +"nakijken, want deze worden niet ongedaan gemaakt." #. module: account #: code:addons/account/account_move_line.py:1059 @@ -10949,6 +11110,9 @@ msgid "" "customer. The tool search can also be used to personalise your Invoices " "reports and so, match this analysis to your needs." msgstr "" +"Dit rapport biedt een overzicht van het bedrag gefactureerd aan uw klant. De " +"zoekfunctie kan worden aangepast om het overzicht van uw facturen te " +"personaliseren, zodat u de gewenste analyse krijgt." #. module: account #: view:account.partner.reconcile.process:0 @@ -11207,6 +11371,16 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Klik als u een nieuw btw-vak wilt toevoegen.\n" +"

\n" +" Afhankelijk van uw land, dient een btw-vak om uw btw-" +"aangifte in te vullen.\n" +" In OpenERP kunt u een btw-structuur instellen en elke btw-" +"berekening\n" +" kan in een of meer btw-vakken worden opgenomen.\n" +"

\n" +" " #. module: account #: selection:account.entries.report,month:0 @@ -11233,6 +11407,18 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Selecteer de periode en het journaal.\n" +"

\n" +" Hiermee kan de boekhouder in een sneltempo boekingen " +"invoeren in\n" +" OpenERP. Als u een aankoopfactuur wilt inboeken,\n" +" begint u met de kostenrekening. OpenERP stelt automatisch\n" +" de betrokken btw voor die is gekoppeld aan deze rekening, " +"net\n" +" als de centralisatierekening.\n" +"

\n" +" " #. module: account #: help:account.invoice.line,account_id:0 @@ -11403,7 +11589,7 @@ msgstr "Rekeningmodel" #: code:addons/account/account_cash_statement.py:292 #, python-format msgid "Loss" -msgstr "" +msgstr "Verlies" #. module: account #: selection:account.entries.report,month:0 @@ -11475,7 +11661,7 @@ msgstr "Kostenrekening van productsjabloon" #. module: account #: field:res.partner,property_payment_term:0 msgid "Customer Payment Term" -msgstr "" +msgstr "Betaaltermijn klant" #. module: account #: help:accounting.report,label_filter:0 diff --git a/addons/account/i18n/pt_BR.po b/addons/account/i18n/pt_BR.po index ba985c5e0a8..d1816589139 100644 --- a/addons/account/i18n/pt_BR.po +++ b/addons/account/i18n/pt_BR.po @@ -7,15 +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-12-22 23:17+0000\n" -"Last-Translator: Fábio Martinelli - http://zupy.com.br " -"\n" +"PO-Revision-Date: 2013-04-18 17:44+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:19+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: account #: model:process.transition,name:account.process_transition_supplierreconcilepaid0 @@ -431,7 +430,7 @@ msgstr "Data de criação" #. module: account #: selection:account.journal,type:0 msgid "Purchase Refund" -msgstr "Devolução da Venda" +msgstr "Devolução de Compra" #. module: account #: selection:account.journal,type:0 @@ -12678,13 +12677,6 @@ msgstr "" #~ msgid "This period is already closed !" #~ msgstr "Este período já está fechado" -#, python-format -#~ msgid "" -#~ "Selected Move lines does not have any account move enties in draft state" -#~ msgstr "" -#~ "As linhas do movimento selecionado nao tem nenhuma conta a ser movida para o " -#~ "estado de esboço" - #~ msgid "Unpaid Customer Refunds" #~ msgstr "Reembolsos a clientes não pagos" @@ -13232,6 +13224,13 @@ msgstr "" #~ msgid "Can not %s draft/proforma/cancel invoice." #~ msgstr "Não pode %s provisório/proforma/cancelar fatura." +#, python-format +#~ msgid "" +#~ "Selected Move lines does not have any account move enties in draft state" +#~ msgstr "" +#~ "As linhas de movimento selecionadas não tem nenhum movimento nesta conta no " +#~ "modo provisório" + #, python-format #~ msgid "Can not pay draft/proforma/cancel invoice." #~ msgstr "Não se pode pagar uma fatura provisória/proforma/cancelada" diff --git a/addons/account/installer.py b/addons/account/installer.py index d02e7196d4d..537371d0f64 100644 --- a/addons/account/installer.py +++ b/addons/account/installer.py @@ -23,10 +23,16 @@ import datetime from dateutil.relativedelta import relativedelta import logging from operator import itemgetter -from os.path import join as opj import time +import urllib2 +import urlparse -from openerp import netsvc, tools +try: + import simplejson as json +except ImportError: + import json # noqa + +from openerp.release import serie from openerp.tools.translate import _ from openerp.osv import fields, osv @@ -38,13 +44,28 @@ class account_installer(osv.osv_memory): def _get_charts(self, cr, uid, context=None): modules = self.pool.get('ir.module.module') + + # try get the list on apps server + try: + apps_server = self.pool.get('ir.config_parameter').get_param(cr, uid, 'apps.server', 'https://apps.openerp.com') + + up = urlparse.urlparse(apps_server) + url = '{0.scheme}://{0.netloc}/apps/charts?serie={1}'.format(up, serie) + + j = urllib2.urlopen(url, timeout=3).read() + apps_charts = json.loads(j) + + charts = dict(apps_charts) + except Exception: + charts = dict() + # Looking for the module with the 'Account Charts' category category_name, category_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'module_category_localization_account_charts') ids = modules.search(cr, uid, [('category_id', '=', category_id)], context=context) - charts = list( - sorted(((m.name, m.shortdesc) - for m in modules.browse(cr, uid, ids, context=context)), - key=itemgetter(1))) + if ids: + charts.update((m.name, m.shortdesc) for m in modules.browse(cr, uid, ids, context=context)) + + charts = sorted(charts.items(), key=itemgetter(1)) charts.insert(0, ('configurable', _('Custom'))) return charts @@ -57,9 +78,9 @@ class account_installer(osv.osv_memory): "country."), 'date_start': fields.date('Start Date', required=True), 'date_stop': fields.date('End Date', required=True), - 'period': fields.selection([('month', 'Monthly'), ('3months','3 Monthly')], 'Periods', required=True), + 'period': fields.selection([('month', 'Monthly'), ('3months', '3 Monthly')], 'Periods', required=True), 'company_id': fields.many2one('res.company', 'Company', required=True), - 'has_default_company' : fields.boolean('Has Default Company', readonly=True), + 'has_default_company': fields.boolean('Has Default Company', readonly=True), } def _default_company(self, cr, uid, context=None): @@ -78,30 +99,29 @@ class account_installer(osv.osv_memory): 'has_default_company': _default_has_default_company, 'charts': 'configurable' } - + def get_unconfigured_cmp(self, cr, uid, context=None): """ get the list of companies that have not been configured yet but don't care about the demo chart of accounts """ - cmp_select = [] company_ids = self.pool.get('res.company').search(cr, uid, [], context=context) cr.execute("SELECT company_id FROM account_account WHERE active = 't' AND account_account.parent_id IS NULL AND name != %s", ("Chart For Automated Tests",)) configured_cmp = [r[0] for r in cr.fetchall()] return list(set(company_ids)-set(configured_cmp)) - + def check_unconfigured_cmp(self, cr, uid, context=None): """ check if there are still unconfigured companies """ if not self.get_unconfigured_cmp(cr, uid, context=context): raise osv.except_osv(_('No unconfigured company !'), _("There is currently no company without chart of account. The wizard will therefore not be executed.")) - + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): - if context is None:context = {} - res = super(account_installer, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False) + if context is None: context = {} + res = super(account_installer, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=False) cmp_select = [] # display in the widget selection only the companies that haven't been configured yet unconfigured_cmp = self.get_unconfigured_cmp(cr, uid, context=context) for field in res['fields']: if field == 'company_id': - res['fields'][field]['domain'] = [('id','in',unconfigured_cmp)] + res['fields'][field]['domain'] = [('id', 'in', unconfigured_cmp)] res['fields'][field]['selection'] = [('', '')] if unconfigured_cmp: cmp_select = [(line.id, line.name) for line in self.pool.get('res.company').browse(cr, uid, unconfigured_cmp)] @@ -117,7 +137,7 @@ class account_installer(osv.osv_memory): def execute(self, cr, uid, ids, context=None): self.execute_simple(cr, uid, ids, context) - super(account_installer, self).execute(cr, uid, ids, context=context) + return super(account_installer, self).execute(cr, uid, ids, context=context) def execute_simple(self, cr, uid, ids, context=None): if context is None: @@ -129,8 +149,8 @@ class account_installer(osv.osv_memory): if not f_ids: name = code = res['date_start'][:4] if int(name) != int(res['date_stop'][:4]): - name = res['date_start'][:4] +'-'+ res['date_stop'][:4] - code = res['date_start'][2:4] +'-'+ res['date_stop'][2:4] + name = res['date_start'][:4] + '-' + res['date_stop'][:4] + code = res['date_start'][2:4] + '-' + res['date_stop'][2:4] vals = { 'name': name, 'code': code, @@ -150,8 +170,7 @@ class account_installer(osv.osv_memory): chart = self.read(cr, uid, ids, ['charts'], context=context)[0]['charts'] _logger.debug('Installing chart of accounts %s', chart) - return modules | set([chart]) + return (modules | set([chart])) - set(['has_default_company', 'configurable']) -account_installer() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/ir_sequence.py b/addons/account/ir_sequence.py index 56e1a4d0367..d3615a847b7 100644 --- a/addons/account/ir_sequence.py +++ b/addons/account/ir_sequence.py @@ -38,7 +38,6 @@ class ir_sequence_fiscalyear(osv.osv): 'Main Sequence must be different from current !'), ] -ir_sequence_fiscalyear() class ir_sequence(osv.osv): _inherit = 'ir.sequence' @@ -56,6 +55,5 @@ class ir_sequence(osv.osv): return super(ir_sequence, self)._next(cr, uid, [line.sequence_id.id], context) return super(ir_sequence, self)._next(cr, uid, seq_ids, context) -ir_sequence() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/partner.py b/addons/account/partner.py index 346cc38f5df..f582da6b765 100644 --- a/addons/account/partner.py +++ b/addons/account/partner.py @@ -66,7 +66,6 @@ class account_fiscal_position(osv.osv): break return account_id -account_fiscal_position() class account_fiscal_position_tax(osv.osv): _name = 'account.fiscal.position.tax' @@ -84,7 +83,6 @@ class account_fiscal_position_tax(osv.osv): 'A tax fiscal position could be defined only once time on same taxes.') ] -account_fiscal_position_tax() class account_fiscal_position_account(osv.osv): _name = 'account.fiscal.position.account' @@ -102,7 +100,6 @@ class account_fiscal_position_account(osv.osv): 'An account fiscal position could be defined only once time on same accounts.') ] -account_fiscal_position_account() class res_partner(osv.osv): _name = 'res.partner' @@ -233,9 +230,13 @@ class res_partner(osv.osv): help="This payment term will be used instead of the default one for purchase orders and supplier invoices"), 'ref_companies': fields.one2many('res.company', 'partner_id', 'Companies that refers to partner'), - 'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the date of the last reconciliation made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 ways: either the last debit/credit entry was reconciled, either the user pressed the button "Fully Reconciled" in the manual reconciliation process') + 'last_reconciliation_date': fields.datetime('Latest Full Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the last date where a reconciliation has been made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 different ways: either the last unreconciled debit/credit entry of this partner was reconciled, either the user pressed the button "Nothing more to reconcile" during the manual reconciliation process.') } -res_partner() + def _commercial_fields(self, cr, uid, context=None): + return super(res_partner, self)._commercial_fields(cr, uid, context=context) + \ + ['debit_limit', 'property_account_payable', 'property_account_receivable', 'property_account_position', + 'property_payment_term', 'property_supplier_payment_term', 'last_reconciliation_date'] + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml index 1267e20165b..b6fae3140b5 100644 --- a/addons/account/partner_view.xml +++ b/addons/account/partner_view.xml @@ -50,6 +50,29 @@
+ + {'search_default_partner_id': [active_id], 'default_partner_id': active_id} + Contracts/Analytic Accounts + account.analytic.account + tree,form + + + partner.view.buttons + res.partner + + + + +
- Last Reconciliation: + Latest Manual Reconciliation Processed:
- +
diff --git a/addons/account/test/account_bank_statement.yml b/addons/account/test/account_bank_statement.yml index cbd35be438a..3711cff4d56 100644 --- a/addons/account/test/account_bank_statement.yml +++ b/addons/account/test/account_bank_statement.yml @@ -7,7 +7,7 @@ import time journal = self._default_journal_id(cr, uid, {'lang': u'en_US', 'tz': False, 'active_model': 'ir.ui.menu', 'journal_type': 'bank', 'period_id': time.strftime('%m'), 'active_ids': [ref('menu_bank_statement_tree')], 'active_id': ref('menu_bank_statement_tree')}) - assert journal, _('Journal has not been selected') + assert journal, 'Journal has not been selected' - I create a bank statement with Opening and Closing balance 0. - diff --git a/addons/account/test/account_report.yml b/addons/account/test/account_report.yml index 0064a1d2556..7a2d09486e4 100644 --- a/addons/account/test/account_report.yml +++ b/addons/account/test/account_report.yml @@ -14,8 +14,9 @@ - !python {model: account.invoice}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.account.invoice').create(cr, uid, [ref('account.account_invoice_customer0')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('account.account_invoice_customer0')], 'account.invoice', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account-invoice.'+format), 'wb+').write(data) @@ -24,8 +25,9 @@ - !python {model: res.partner}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.account.overdue').create(cr, uid, [ref('base.res_partner_1'),ref('base.res_partner_2'),ref('base.res_partner_12')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('base.res_partner_1'),ref('base.res_partner_2'),ref('base.res_partner_12')], 'account.overdue', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account-report_overdue.'+format), 'wb+').write(data) - diff --git a/addons/account/test/account_use_model.yml b/addons/account/test/account_use_model.yml index ab69b251919..16153cd6f8c 100644 --- a/addons/account/test/account_use_model.yml +++ b/addons/account/test/account_use_model.yml @@ -41,7 +41,7 @@ ids = self.search(cr, uid, [('ref', '=', 'My Test Model')]) self.button_validate(cr, uid, ids, {}) moves = self.browse(cr, uid, ids)[0] - assert(moves.state == 'posted'), _('Journal Entries are not in posted state') + assert(moves.state == 'posted'), 'Journal Entries are not in posted state' - Then I create Recurring Lines - @@ -57,7 +57,7 @@ self.compute(cr, uid, [ref('test_recurring_lines')], {'lang': u'en_US', 'active_model': 'ir.ui.menu', 'active_ids': [ref('menu_action_subscription_form')], 'tz': False, 'active_id': ref('menu_action_subscription_form')}) subscription_lines = subscription_line_obj.search(cr, uid, [('subscription_id', '=', ref('test_recurring_lines'))]) - assert subscription_lines, _('Subscription lines has not been created') + assert subscription_lines, 'Subscription lines has not been created' - I provide date in 'Generate Entries' wizard - @@ -69,5 +69,5 @@ !python {model: account.subscription.generate}: | res = self.action_generate(cr, uid, [ref('account_subscription_generate')], {'lang': u'en_US', 'active_model': 'ir.ui.menu', 'active_ids': [ref('menu_generate_subscription')], 'tz': False, 'active_id': ref('menu_generate_subscription')}) - assert res, _('Move for subscription lines has not been created') + assert res, 'Move for subscription lines has not been created' diff --git a/addons/account/wizard/account_automatic_reconcile.py b/addons/account/wizard/account_automatic_reconcile.py index 88d31b5b6c5..f6f0c90b1e2 100644 --- a/addons/account/wizard/account_automatic_reconcile.py +++ b/addons/account/wizard/account_automatic_reconcile.py @@ -246,6 +246,5 @@ class account_automatic_reconcile(osv.osv_memory): 'context': context, } -account_automatic_reconcile() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_change_currency.py b/addons/account/wizard/account_change_currency.py index 73fd52b3fcb..c3726ece676 100644 --- a/addons/account/wizard/account_change_currency.py +++ b/addons/account/wizard/account_change_currency.py @@ -73,6 +73,5 @@ class account_change_currency(osv.osv_memory): obj_inv.write(cr, uid, [invoice.id], {'currency_id': new_currency}, context=context) return {'type': 'ir.actions.act_window_close'} -account_change_currency() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_chart.py b/addons/account/wizard/account_chart.py index 32b83a0a670..38df2f7484d 100644 --- a/addons/account/wizard/account_chart.py +++ b/addons/account/wizard/account_chart.py @@ -105,6 +105,5 @@ class account_chart(osv.osv_memory): 'fiscalyear': _get_fiscalyear, } -account_chart() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_financial_report.py b/addons/account/wizard/account_financial_report.py index dde07eb7034..2ce7118335a 100644 --- a/addons/account/wizard/account_financial_report.py +++ b/addons/account/wizard/account_financial_report.py @@ -93,6 +93,5 @@ class accounting_report(osv.osv_memory): 'datas': data, } -accounting_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_fiscalyear_close.py b/addons/account/wizard/account_fiscalyear_close.py index d4f7b3e6654..6ceb833816b 100644 --- a/addons/account/wizard/account_fiscalyear_close.py +++ b/addons/account/wizard/account_fiscalyear_close.py @@ -278,6 +278,5 @@ class account_fiscalyear_close(osv.osv_memory): return {'type': 'ir.actions.act_window_close'} -account_fiscalyear_close() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_fiscalyear_close_state.py b/addons/account/wizard/account_fiscalyear_close_state.py index 746f1c47976..ed84ab65184 100644 --- a/addons/account/wizard/account_fiscalyear_close_state.py +++ b/addons/account/wizard/account_fiscalyear_close_state.py @@ -56,6 +56,5 @@ class account_fiscalyear_close_state(osv.osv_memory): return {'type': 'ir.actions.act_window_close'} -account_fiscalyear_close_state() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_invoice_refund.py b/addons/account/wizard/account_invoice_refund.py index df4ad3494d2..5be9ebc5c80 100644 --- a/addons/account/wizard/account_invoice_refund.py +++ b/addons/account/wizard/account_invoice_refund.py @@ -181,9 +181,9 @@ class account_invoice_refund(osv.osv_memory): invoice = invoice[0] del invoice['id'] invoice_lines = inv_line_obj.browse(cr, uid, invoice['invoice_line'], context=context) - invoice_lines = inv_obj._refund_cleanup_lines(cr, uid, invoice_lines) + invoice_lines = inv_obj._refund_cleanup_lines(cr, uid, invoice_lines, context=context) tax_lines = inv_tax_obj.browse(cr, uid, invoice['tax_line'], context=context) - tax_lines = inv_obj._refund_cleanup_lines(cr, uid, tax_lines) + tax_lines = inv_obj._refund_cleanup_lines(cr, uid, tax_lines, context=context) invoice.update({ 'type': inv.type, 'date_invoice': date, @@ -220,6 +220,5 @@ class account_invoice_refund(osv.osv_memory): return self.compute_refund(cr, uid, ids, data_refund, context=context) -account_invoice_refund() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_invoice_state.py b/addons/account/wizard/account_invoice_state.py index 9fab19ff42c..1aed2c6c477 100644 --- a/addons/account/wizard/account_invoice_state.py +++ b/addons/account/wizard/account_invoice_state.py @@ -21,7 +21,6 @@ from openerp.osv import osv from openerp.tools.translate import _ -from openerp import pooler class account_invoice_confirm(osv.osv_memory): """ @@ -34,8 +33,7 @@ class account_invoice_confirm(osv.osv_memory): def invoice_confirm(self, cr, uid, ids, context=None): if context is None: context = {} - pool_obj = pooler.get_pool(cr.dbname) - account_invoice_obj = pool_obj.get('account.invoice') + account_invoice_obj = self.pool['account.invoice'] data_inv = account_invoice_obj.read(cr, uid, context['active_ids'], ['state'], context=context) for record in data_inv: if record['state'] not in ('draft','proforma','proforma2'): @@ -44,7 +42,6 @@ class account_invoice_confirm(osv.osv_memory): return {'type': 'ir.actions.act_window_close'} -account_invoice_confirm() class account_invoice_cancel(osv.osv_memory): """ @@ -58,8 +55,7 @@ class account_invoice_cancel(osv.osv_memory): def invoice_cancel(self, cr, uid, ids, context=None): if context is None: context = {} - pool_obj = pooler.get_pool(cr.dbname) - account_invoice_obj = pool_obj.get('account.invoice') + account_invoice_obj = self.pool['account.invoice'] data_inv = account_invoice_obj.read(cr, uid, context['active_ids'], ['state'], context=context) for record in data_inv: if record['state'] in ('cancel','paid'): @@ -67,6 +63,5 @@ class account_invoice_cancel(osv.osv_memory): account_invoice_obj.signal_invoice_cancel(cr , uid, [record['id']]) return {'type': 'ir.actions.act_window_close'} -account_invoice_cancel() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_journal_select.py b/addons/account/wizard/account_journal_select.py index 7edd7923f4c..a4a1d4a6a9f 100644 --- a/addons/account/wizard/account_journal_select.py +++ b/addons/account/wizard/account_journal_select.py @@ -45,6 +45,5 @@ class account_journal_select(osv.osv_memory): result['context'] = str({'journal_id': journal_id, 'period_id': period_id}) return result -account_journal_select() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_move_bank_reconcile.py b/addons/account/wizard/account_move_bank_reconcile.py index 283068ae693..0fb4633163b 100644 --- a/addons/account/wizard/account_move_bank_reconcile.py +++ b/addons/account/wizard/account_move_bank_reconcile.py @@ -59,6 +59,5 @@ the bank account\nin the journal definition for reconciliation.')) 'type': 'ir.actions.act_window' } -account_move_bank_reconcile() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_move_line_reconcile_select.py b/addons/account/wizard/account_move_line_reconcile_select.py index 76af8538e05..658a6c5d503 100644 --- a/addons/account/wizard/account_move_line_reconcile_select.py +++ b/addons/account/wizard/account_move_line_reconcile_select.py @@ -50,6 +50,5 @@ class account_move_line_reconcile_select(osv.osv_memory): 'type': 'ir.actions.act_window' } -account_move_line_reconcile_select() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_move_line_select.py b/addons/account/wizard/account_move_line_select.py index b56621f2114..630db9fd1d6 100644 --- a/addons/account/wizard/account_move_line_select.py +++ b/addons/account/wizard/account_move_line_select.py @@ -67,6 +67,5 @@ class account_move_line_select(osv.osv_memory): result['domain']=result['domain'][0:-1]+','+domain+result['domain'][-1] return result -account_move_line_select() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_move_line_unreconcile_select.py b/addons/account/wizard/account_move_line_unreconcile_select.py index f9009fc8199..31fbeddeea8 100644 --- a/addons/account/wizard/account_move_line_unreconcile_select.py +++ b/addons/account/wizard/account_move_line_unreconcile_select.py @@ -39,6 +39,5 @@ class account_move_line_unreconcile_select(osv.osv_memory): 'type': 'ir.actions.act_window' } -account_move_line_unreconcile_select() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_open_closed_fiscalyear.py b/addons/account/wizard/account_open_closed_fiscalyear.py index 3b5d956d381..f4e90ae9f2f 100644 --- a/addons/account/wizard/account_open_closed_fiscalyear.py +++ b/addons/account/wizard/account_open_closed_fiscalyear.py @@ -43,6 +43,5 @@ class account_open_closed_fiscalyear(osv.osv_memory): cr.execute('delete from account_move where id IN %s', (tuple(ids_move),)) return {'type': 'ir.actions.act_window_close'} -account_open_closed_fiscalyear() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_period_close.py b/addons/account/wizard/account_period_close.py index fad757c0ff9..a50861c65ef 100644 --- a/addons/account/wizard/account_period_close.py +++ b/addons/account/wizard/account_period_close.py @@ -55,6 +55,5 @@ class account_period_close(osv.osv_memory): return {'type': 'ir.actions.act_window_close'} -account_period_close() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_reconcile.py b/addons/account/wizard/account_reconcile.py index 81609249fd7..0d5a3525af4 100644 --- a/addons/account/wizard/account_reconcile.py +++ b/addons/account/wizard/account_reconcile.py @@ -91,7 +91,6 @@ class account_move_line_reconcile(osv.osv_memory): period_id, journal_id, context=context) return {'type': 'ir.actions.act_window_close'} -account_move_line_reconcile() class account_move_line_reconcile_writeoff(osv.osv_memory): """ @@ -149,7 +148,6 @@ class account_move_line_reconcile_writeoff(osv.osv_memory): context['analytic_id'] = data['analytic_id'][0] if context['date_p']: date = context['date_p'] - ids = period_obj.find(cr, uid, dt=date, context=context) if ids: period_id = ids[0] @@ -158,6 +156,5 @@ class account_move_line_reconcile_writeoff(osv.osv_memory): period_id, journal_id, context=context) return {'type': 'ir.actions.act_window_close'} -account_move_line_reconcile_writeoff() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_reconcile_partner_process.py b/addons/account/wizard/account_reconcile_partner_process.py index 1c317111888..bcbdb3fb5db 100644 --- a/addons/account/wizard/account_reconcile_partner_process.py +++ b/addons/account/wizard/account_reconcile_partner_process.py @@ -98,6 +98,5 @@ class account_partner_reconcile_process(osv.osv_memory): 'next_partner_id': _get_partner, } -account_partner_reconcile_process() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_account_balance.py b/addons/account/wizard/account_report_account_balance.py index e883a59c102..fd3c966e306 100644 --- a/addons/account/wizard/account_report_account_balance.py +++ b/addons/account/wizard/account_report_account_balance.py @@ -38,6 +38,5 @@ class account_balance_report(osv.osv_memory): data = self.pre_print_report(cr, uid, ids, data, context=context) return {'type': 'ir.actions.report.xml', 'report_name': 'account.account.balance', 'datas': data} -account_balance_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_aged_partner_balance.py b/addons/account/wizard/account_report_aged_partner_balance.py index 1054e7fa285..c483487b78f 100644 --- a/addons/account/wizard/account_report_aged_partner_balance.py +++ b/addons/account/wizard/account_report_aged_partner_balance.py @@ -86,6 +86,5 @@ class account_aged_trial_balance(osv.osv_memory): 'datas': data } -account_aged_trial_balance() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_central_journal.py b/addons/account/wizard/account_report_central_journal.py index da8be6d4735..a6bc111fa35 100644 --- a/addons/account/wizard/account_report_central_journal.py +++ b/addons/account/wizard/account_report_central_journal.py @@ -38,7 +38,6 @@ class account_central_journal(osv.osv_memory): 'datas': data, } -account_central_journal() #vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_common.py b/addons/account/wizard/account_report_common.py index 52a35327845..c457140684a 100644 --- a/addons/account/wizard/account_report_common.py +++ b/addons/account/wizard/account_report_common.py @@ -178,6 +178,5 @@ class account_common_report(osv.osv_memory): data['form']['used_context'] = used_context return self._print_report(cr, uid, ids, data, context=context) -account_common_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_common_account.py b/addons/account/wizard/account_report_common_account.py index 7cedf427386..13b83c32958 100644 --- a/addons/account/wizard/account_report_common_account.py +++ b/addons/account/wizard/account_report_common_account.py @@ -41,7 +41,6 @@ class account_common_account_report(osv.osv_memory): data['form'].update(self.read(cr, uid, ids, ['display_account'], context=context)[0]) return data -account_common_account_report() #vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_common_journal.py b/addons/account/wizard/account_report_common_journal.py index 609c2840ca6..a03315ecf7c 100644 --- a/addons/account/wizard/account_report_common_journal.py +++ b/addons/account/wizard/account_report_common_journal.py @@ -50,6 +50,5 @@ class account_common_journal_report(osv.osv_memory): data['form']['active_ids'] = self.pool.get('account.journal.period').search(cr, uid, [('journal_id', 'in', data['form']['journal_ids']), ('period_id', 'in', period_list)], context=context) return data -account_common_journal_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_common_partner.py b/addons/account/wizard/account_report_common_partner.py index 9779005b0de..d50a54ef32c 100644 --- a/addons/account/wizard/account_report_common_partner.py +++ b/addons/account/wizard/account_report_common_partner.py @@ -42,7 +42,6 @@ class account_common_partner_report(osv.osv_memory): data['form'].update(self.read(cr, uid, ids, ['result_selection'], context=context)[0]) return data -account_common_partner_report() #vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_general_journal.py b/addons/account/wizard/account_report_general_journal.py index 4a170a84db1..e5e516b1f38 100644 --- a/addons/account/wizard/account_report_general_journal.py +++ b/addons/account/wizard/account_report_general_journal.py @@ -34,7 +34,6 @@ class account_general_journal(osv.osv_memory): data = self.pre_print_report(cr, uid, ids, data, context=context) return {'type': 'ir.actions.report.xml', 'report_name': 'account.general.journal', 'datas': data} -account_general_journal() #vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_general_ledger.py b/addons/account/wizard/account_report_general_ledger.py index a10ff624fee..fae60df63fb 100644 --- a/addons/account/wizard/account_report_general_ledger.py +++ b/addons/account/wizard/account_report_general_ledger.py @@ -58,6 +58,5 @@ class account_report_general_ledger(osv.osv_memory): return { 'type': 'ir.actions.report.xml', 'report_name': 'account.general.ledger_landscape', 'datas': data} return { 'type': 'ir.actions.report.xml', 'report_name': 'account.general.ledger', 'datas': data} -account_report_general_ledger() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_partner_balance.py b/addons/account/wizard/account_report_partner_balance.py index 33a7a42072c..fbe18f27d69 100644 --- a/addons/account/wizard/account_report_partner_balance.py +++ b/addons/account/wizard/account_report_partner_balance.py @@ -50,6 +50,5 @@ class account_partner_balance(osv.osv_memory): 'datas': data, } -account_partner_balance() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_partner_ledger.py b/addons/account/wizard/account_report_partner_ledger.py index d1e6dd9809e..fdabe49ff17 100644 --- a/addons/account/wizard/account_report_partner_ledger.py +++ b/addons/account/wizard/account_report_partner_ledger.py @@ -67,6 +67,5 @@ class account_partner_ledger(osv.osv_memory): 'datas': data, } -account_partner_ledger() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_print_journal.py b/addons/account/wizard/account_report_print_journal.py index b91fe04660a..3ad45268248 100644 --- a/addons/account/wizard/account_report_print_journal.py +++ b/addons/account/wizard/account_report_print_journal.py @@ -72,7 +72,6 @@ class account_print_journal(osv.osv_memory): report_name = 'account.journal.period.print' return {'type': 'ir.actions.report.xml', 'report_name': report_name, 'datas': data} -account_print_journal() #vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_state_open.py b/addons/account/wizard/account_state_open.py index 5d0ae6b66bd..1950a139983 100644 --- a/addons/account/wizard/account_state_open.py +++ b/addons/account/wizard/account_state_open.py @@ -20,7 +20,6 @@ ############################################################################## from openerp.osv import osv -from openerp import netsvc from openerp.tools.translate import _ class account_state_open(osv.osv_memory): @@ -38,6 +37,5 @@ class account_state_open(osv.osv_memory): obj_invoice.signal_open_test(cr, uid, context['active_ids'][0]) return {'type': 'ir.actions.act_window_close'} -account_state_open() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_subscription_generate.py b/addons/account/wizard/account_subscription_generate.py index f5babc4fd87..a61f3eee252 100644 --- a/addons/account/wizard/account_subscription_generate.py +++ b/addons/account/wizard/account_subscription_generate.py @@ -48,6 +48,5 @@ class account_subscription_generate(osv.osv_memory): result['domain'] = str([('id','in',moves_created)]) return result -account_subscription_generate() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_tax_chart.py b/addons/account/wizard/account_tax_chart.py index 84859e2077c..3283d2ba6d1 100644 --- a/addons/account/wizard/account_tax_chart.py +++ b/addons/account/wizard/account_tax_chart.py @@ -38,7 +38,7 @@ class account_tax_chart(osv.osv_memory): def _get_period(self, cr, uid, context=None): """Return default period value""" - period_ids = self.pool.get('account.period').find(cr, uid) + period_ids = self.pool.get('account.period').find(cr, uid, context=context) return period_ids and period_ids[0] or False def account_tax_chart_open_window(self, cr, uid, ids, context=None): @@ -73,6 +73,5 @@ class account_tax_chart(osv.osv_memory): 'target_move': 'posted' } -account_tax_chart() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_unreconcile.py b/addons/account/wizard/account_unreconcile.py index ff592a329c7..425e549fec2 100644 --- a/addons/account/wizard/account_unreconcile.py +++ b/addons/account/wizard/account_unreconcile.py @@ -33,7 +33,6 @@ class account_unreconcile(osv.osv_memory): obj_move_line._remove_move_reconcile(cr, uid, context['active_ids'], context=context) return {'type': 'ir.actions.act_window_close'} -account_unreconcile() class account_unreconcile_reconcile(osv.osv_memory): _name = "account.unreconcile.reconcile" @@ -48,6 +47,5 @@ class account_unreconcile_reconcile(osv.osv_memory): obj_move_reconcile.unlink(cr, uid, rec_ids, context=context) return {'type': 'ir.actions.act_window_close'} -account_unreconcile_reconcile() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_use_model.py b/addons/account/wizard/account_use_model.py index 795284c8fef..06f02719065 100644 --- a/addons/account/wizard/account_use_model.py +++ b/addons/account/wizard/account_use_model.py @@ -71,6 +71,5 @@ class account_use_model(osv.osv_memory): 'type': 'ir.actions.act_window', } -account_use_model() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_validate_account_move.py b/addons/account/wizard/account_validate_account_move.py index faf7f8e2ccd..324248284f1 100644 --- a/addons/account/wizard/account_validate_account_move.py +++ b/addons/account/wizard/account_validate_account_move.py @@ -40,7 +40,6 @@ class validate_account_move(osv.osv_memory): obj_move.button_validate(cr, uid, ids_move, context=context) return {'type': 'ir.actions.act_window_close'} -validate_account_move() class validate_account_move_lines(osv.osv_memory): _name = "validate.account.move.lines" @@ -61,7 +60,6 @@ class validate_account_move_lines(osv.osv_memory): raise osv.except_osv(_('Warning!'), _('Selected Entry Lines does not have any account move enties in draft state.')) obj_move.button_validate(cr, uid, move_ids, context) return {'type': 'ir.actions.act_window_close'} -validate_account_move_lines() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_vat.py b/addons/account/wizard/account_vat.py index a60a7906e28..37bf4b029a6 100644 --- a/addons/account/wizard/account_vat.py +++ b/addons/account/wizard/account_vat.py @@ -59,6 +59,5 @@ class account_vat_declaration(osv.osv_memory): 'datas': datas, } -account_vat_declaration() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/pos_box.py b/addons/account/wizard/pos_box.py index 49178dfd3ea..874a8e3b7c9 100644 --- a/addons/account/wizard/pos_box.py +++ b/addons/account/wizard/pos_box.py @@ -21,7 +21,7 @@ class CashBox(osv.osv_memory): active_model = context.get('active_model', False) or False active_ids = context.get('active_ids', []) or [] - 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) return self._run(cr, uid, ids, records, context=None) @@ -63,11 +63,12 @@ class CashBoxIn(CashBox): 'name' : box.name, } -CashBoxIn() class CashBoxOut(CashBox): _name = 'cash.box.out' + _columns = CashBox._columns.copy() + def _compute_values_for_statement_line(self, cr, uid, box, record, context=None): amount = box.amount or 0.0 return { @@ -78,4 +79,3 @@ class CashBoxOut(CashBox): 'name' : box.name, } -CashBoxOut() diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 0a56c80766b..33ab3be209c 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -352,11 +352,10 @@ class account_analytic_account(osv.osv): res[account.id] = 0.0 sale_ids = sale_obj.search(cr, uid, [('project_id','=', account.id), ('state', '=', 'manual')], context=context) for sale in sale_obj.browse(cr, uid, sale_ids, context=context): - if not sale.invoiced: - res[account.id] += sale.amount_untaxed - for invoice in sale.invoice_ids: - if invoice.state not in ('draft', 'cancel'): - res[account.id] -= invoice.amount_untaxed + res[account.id] += sale.amount_untaxed + for invoice in sale.invoice_ids: + if invoice.state != 'cancel': + res[account.id] -= invoice.amount_untaxed return res def _timesheet_ca_invoiced_calc(self, cr, uid, ids, name, arg, context=None): diff --git a/addons/account_analytic_analysis/account_analytic_analysis_view.xml b/addons/account_analytic_analysis/account_analytic_analysis_view.xml index 6f670b2c6b9..d31746e7e70 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis_view.xml +++ b/addons/account_analytic_analysis/account_analytic_analysis_view.xml @@ -213,7 +213,7 @@ - + @@ -267,7 +267,7 @@
- + diff --git a/addons/account_analytic_default/account_analytic_default.py b/addons/account_analytic_default/account_analytic_default.py index 9d7df0aa010..1696874f0f5 100644 --- a/addons/account_analytic_default/account_analytic_default.py +++ b/addons/account_analytic_default/account_analytic_default.py @@ -67,7 +67,6 @@ class account_analytic_default(osv.osv): best_index = index return res -account_analytic_default() class account_invoice_line(osv.osv): _inherit = "account.invoice.line" @@ -82,7 +81,6 @@ class account_invoice_line(osv.osv): res_prod['value'].update({'account_analytic_id': False}) return res_prod -account_invoice_line() class stock_picking(osv.osv): @@ -97,7 +95,6 @@ class stock_picking(osv.osv): return super(stock_picking, self)._get_account_analytic_invoice(cursor, user, picking, move_line) -stock_picking() class sale_order_line(osv.osv): _inherit = "sale.order.line" @@ -118,6 +115,5 @@ class sale_order_line(osv.osv): inv_line_obj.write(cr, uid, [line.id], {'account_analytic_id': rec.analytic_id.id}, context=context) return create_ids -sale_order_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_default/i18n/nl_BE.po b/addons/account_analytic_default/i18n/nl_BE.po index 4d7b5295f16..86fed1b535a 100644 --- a/addons/account_analytic_default/i18n/nl_BE.po +++ b/addons/account_analytic_default/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:05+0000\n" -"PO-Revision-Date: 2012-11-27 13:19+0000\n" +"PO-Revision-Date: 2013-04-15 15:56+0000\n" "Last-Translator: Els Van Vossel (Agaplan) \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:28+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n" +"X-Generator: Launchpad (build 16564)\n" #. module: account_analytic_default #: model:ir.actions.act_window,name:account_analytic_default.analytic_rule_action_partner @@ -40,6 +40,9 @@ msgid "" "default (e.g. create new customer invoice or Sales order if we select this " "product, it will automatically take this as an analytic account)" msgstr "" +"Kies een product voor de analytische rekening in analytische " +"standaardrekening (vb. maak een nieuwe verkoopfactuur of verkooporder: als " +"we dit product kiezen, wordt de analytische rekening voorgesteld)." #. module: account_analytic_default #: model:ir.model,name:account_analytic_default.model_stock_picking @@ -64,6 +67,9 @@ msgid "" "default (e.g. create new customer invoice or Sales order if we select this " "partner, it will automatically take this as an analytic account)" msgstr "" +"Kies een relatie voor de analytische rekening in analytische " +"standaardrekening (vb. maak een nieuwe verkoopfactuur of verkooporder: als " +"we deze relatie kiezen, wordt de analytische rekening voorgesteld)." #. module: account_analytic_default #: view:account.analytic.default:0 @@ -118,6 +124,9 @@ msgid "" "default (e.g. create new customer invoice or Sales order if we select this " "company, it will automatically take this as an analytic account)" msgstr "" +"Kies een firma voor de analytische rekening in analytische standaardrekening " +"(vb. maak een nieuwe verkoopfactuur of verkooporder: als we deze firma " +"kiezen, wordt de analytische rekening voorgesteld)." #. module: account_analytic_default #: view:account.analytic.default:0 diff --git a/addons/account_analytic_plans/account_analytic_plans.py b/addons/account_analytic_plans/account_analytic_plans.py index 5834db99cd3..54b15ad565b 100644 --- a/addons/account_analytic_plans/account_analytic_plans.py +++ b/addons/account_analytic_plans/account_analytic_plans.py @@ -40,10 +40,10 @@ class one2many_mod2(fields.one2many): plan = journal.plan_id if plan and len(plan.plan_ids) > pnum: acc_id = plan.plan_ids[pnum].root_analytic_id.id - ids2 = obj.pool.get(self._obj).search(cr, user, [(self._fields_id,'in',ids),('analytic_account_id','child_of',[acc_id])], limit=self._limit) + ids2 = obj.pool[self._obj].search(cr, user, [(self._fields_id,'in',ids),('analytic_account_id','child_of',[acc_id])], limit=self._limit) if ids2 is None: - ids2 = obj.pool.get(self._obj).search(cr, user, [(self._fields_id,'in',ids)], limit=self._limit) - for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'): + ids2 = obj.pool[self._obj].search(cr, user, [(self._fields_id,'in',ids)], limit=self._limit) + for r in obj.pool[self._obj]._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'): res[r[self._fields_id]].append( r['id'] ) return res @@ -65,7 +65,6 @@ class account_analytic_line(osv.osv): 'percentage': fields.float('Percentage') } -account_analytic_line() class account_analytic_plan(osv.osv): _name = "account.analytic.plan" @@ -75,7 +74,6 @@ class account_analytic_plan(osv.osv): 'plan_ids': fields.one2many('account.analytic.plan.line', 'plan_id', 'Analytic Plans'), } -account_analytic_plan() class account_analytic_plan_line(osv.osv): _name = "account.analytic.plan.line" @@ -94,7 +92,6 @@ class account_analytic_plan_line(osv.osv): 'max_required': 100.0, } -account_analytic_plan_line() class account_analytic_plan_instance(osv.osv): _name = "account.analytic.plan.instance" @@ -257,7 +254,6 @@ class account_analytic_plan_instance(osv.osv): vals['code'] = this.code and (str(this.code)+'*') or "*" return super(account_analytic_plan_instance, self).write(cr, uid, ids, vals, context=context) -account_analytic_plan_instance() class account_analytic_plan_instance_line(osv.osv): _name = "account.analytic.plan.instance.line" @@ -280,7 +276,6 @@ class account_analytic_plan_instance_line(osv.osv): res.append((record['id'], record['analytic_account_id'])) return res -account_analytic_plan_instance_line() class account_journal(osv.osv): _inherit = "account.journal" @@ -289,7 +284,6 @@ class account_journal(osv.osv): 'plan_id': fields.many2one('account.analytic.plan', 'Analytic Plans'), } -account_journal() class account_invoice_line(osv.osv): _inherit = "account.invoice.line" @@ -315,7 +309,6 @@ class account_invoice_line(osv.osv): res_prod['value'].update({'analytics_id': rec.analytics_id.id}) return res_prod -account_invoice_line() class account_move_line(osv.osv): @@ -370,7 +363,6 @@ class account_move_line(osv.osv): result = super(account_move_line, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu) return result -account_move_line() class account_invoice(osv.osv): _name = "account.invoice" @@ -425,14 +417,12 @@ class account_invoice(osv.osv): il['analytic_lines'].append((0, 0, al_vals)) return iml -account_invoice() class account_analytic_plan(osv.osv): _inherit = "account.analytic.plan" _columns = { 'default_instance_id': fields.many2one('account.analytic.plan.instance', 'Default Entries'), } -account_analytic_plan() class analytic_default(osv.osv): _inherit = "account.analytic.default" @@ -440,7 +430,6 @@ class analytic_default(osv.osv): 'analytics_id': fields.many2one('account.analytic.plan.instance', 'Analytic Distribution'), } -analytic_default() class sale_order_line(osv.osv): _inherit = "sale.order.line" @@ -459,7 +448,6 @@ class sale_order_line(osv.osv): inv_line_obj.write(cr, uid, [line.id], {'analytics_id': rec.analytics_id.id}, context=context) return create_ids -sale_order_line() class account_bank_statement(osv.osv): @@ -488,7 +476,6 @@ class account_bank_statement(osv.osv): continue return True -account_bank_statement() class account_bank_statement_line(osv.osv): @@ -497,6 +484,5 @@ class account_bank_statement_line(osv.osv): _columns = { 'analytics_id': fields.many2one('account.analytic.plan.instance', 'Analytic Distribution'), } -account_bank_statement_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_plans/account_analytic_plans_view.xml b/addons/account_analytic_plans/account_analytic_plans_view.xml index 3dcbcda6952..be46b9a6923 100644 --- a/addons/account_analytic_plans/account_analytic_plans_view.xml +++ b/addons/account_analytic_plans/account_analytic_plans_view.xml @@ -64,30 +64,6 @@
- - - - account.invoice.line.form.inherit - account.invoice.line - - - - - - - - - - account.invoice.supplier.form.inherit - account.invoice - - 2 - - - - - - diff --git a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml index 7f891332aeb..6aa67a3052a 100644 --- a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml +++ b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml @@ -3,8 +3,9 @@ - !python {model: account.analytic.account}: | import os, time - from openerp import netsvc, tools + import openerp.report + from openerp import tools data_dict = {'model': 'account.analytic.account', 'form': {'date1':time.strftime("%Y-01-01"),'date2':time.strftime('%Y-%m-%d'),'journal_ids':[6,0,(ref('account.cose_journal_sale'))],'ref':ref('account.analytic_root'),'empty_line':True,'id':ref('account.analytic_root'),'context':{}}} - (data, format) = netsvc.LocalService('report.account.analytic.account.crossovered.analytic').create(cr, uid, [ref('account.analytic_root')], data_dict, {}) + data, format = openerp.report.render_report(cr, uid, [ref('account.analytic_root')], 'account.analytic.account.crossovered.analytic', data_dict, {}) if tools.config['test_report_directory']: - file(os.path.join(tools.config['test_report_directory'], 'account_analytic_plans-crossovered_analyitic.'+format), 'wb+').write(data) \ No newline at end of file + file(os.path.join(tools.config['test_report_directory'], 'account_analytic_plans-crossovered_analyitic.'+format), 'wb+').write(data) diff --git a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py index 640443c8a0b..d3581d6c457 100644 --- a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py +++ b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py @@ -71,6 +71,5 @@ class account_crossovered_analytic(osv.osv_memory): 'datas': datas, } -account_crossovered_analytic() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_plans/wizard/analytic_plan_create_model.py b/addons/account_analytic_plans/wizard/analytic_plan_create_model.py index 7038a6f1025..3a206aa227e 100644 --- a/addons/account_analytic_plans/wizard/analytic_plan_create_model.py +++ b/addons/account_analytic_plans/wizard/analytic_plan_create_model.py @@ -55,6 +55,5 @@ class analytic_plan_create_model(osv.osv_memory): else: return {'type': 'ir.actions.act_window_close'} -analytic_plan_create_model() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_anglo_saxon/product.py b/addons/account_anglo_saxon/product.py index 443642d048b..b52d9ed3bbd 100644 --- a/addons/account_anglo_saxon/product.py +++ b/addons/account_anglo_saxon/product.py @@ -48,7 +48,6 @@ class product_category(osv.osv): help="This account will be used to value outgoing stock using cost price."), } -product_category() class product_template(osv.osv): _inherit = "product.template" @@ -78,7 +77,6 @@ class product_template(osv.osv): help="This account will be used to value outgoing stock using cost price."), } -product_template() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_anglo_saxon/purchase.py b/addons/account_anglo_saxon/purchase.py index 959f8b7eb49..c10a2a97d80 100644 --- a/addons/account_anglo_saxon/purchase.py +++ b/addons/account_anglo_saxon/purchase.py @@ -37,6 +37,5 @@ class purchase_order(osv.osv): new_account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, acc_id) line.update({'account_id': new_account_id}) return line -purchase_order() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_anglo_saxon/stock.py b/addons/account_anglo_saxon/stock.py index 191249a6640..1cf3ecf21ef 100644 --- a/addons/account_anglo_saxon/stock.py +++ b/addons/account_anglo_saxon/stock.py @@ -57,7 +57,6 @@ class stock_picking(osv.osv): self.pool.get('account.invoice.line').write(cr, uid, [ol.id], {'account_id': a}) return res -stock_picking() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py index 5a22a888772..5c019155fdc 100644 --- a/addons/account_asset/account_asset.py +++ b/addons/account_asset/account_asset.py @@ -70,7 +70,6 @@ class account_asset_category(osv.osv): res['value'] = {'account_depreciation_id': account_asset_id} return res -account_asset_category() class account_asset_asset(osv.osv): _name = 'account.asset.asset' @@ -80,10 +79,10 @@ class account_asset_asset(osv.osv): for asset in self.browse(cr, uid, ids, context=context): if asset.account_move_line_ids: raise osv.except_osv(_('Error!'), _('You cannot delete an asset that contains posted depreciation lines.')) - return super(account_account, self).unlink(cr, uid, ids, context=context) + return super(account_asset_asset, self).unlink(cr, uid, ids, context=context) def _get_period(self, cr, uid, context=None): - periods = self.pool.get('account.period').find(cr, uid) + periods = self.pool.get('account.period').find(cr, uid, context=context) if periods: return periods[0] else: @@ -361,7 +360,6 @@ class account_asset_asset(osv.osv): 'context': context, } -account_asset_asset() class account_asset_depreciation_line(osv.osv): _name = 'account.asset.depreciation.line' @@ -456,7 +454,6 @@ class account_asset_depreciation_line(osv.osv): asset.write({'state': 'close'}) return created_move_ids -account_asset_depreciation_line() class account_move_line(osv.osv): _inherit = 'account.move.line' @@ -465,7 +462,6 @@ class account_move_line(osv.osv): 'entry_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}), } -account_move_line() class account_asset_history(osv.osv): _name = 'account.asset.history' @@ -490,6 +486,5 @@ class account_asset_history(osv.osv): 'user_id': lambda self, cr, uid, ctx: uid } -account_asset_history() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_asset/account_asset_invoice.py b/addons/account_asset/account_asset_invoice.py index 7e2f24f0d0a..d5b1c298c0b 100644 --- a/addons/account_asset/account_asset_invoice.py +++ b/addons/account_asset/account_asset_invoice.py @@ -35,7 +35,6 @@ class account_invoice(osv.osv): res['asset_id'] = x.get('asset_id', False) return res -account_invoice() class account_invoice_line(osv.osv): @@ -66,6 +65,5 @@ class account_invoice_line(osv.osv): asset_obj.validate(cr, uid, [asset_id], context=context) return True -account_invoice_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_asset/account_asset_view.xml b/addons/account_asset/account_asset_view.xml index c4cb17bded3..fe1fcf473ba 100644 --- a/addons/account_asset/account_asset_view.xml +++ b/addons/account_asset/account_asset_view.xml @@ -223,7 +223,7 @@ - +
diff --git a/addons/account_asset/i18n/nl_BE.po b/addons/account_asset/i18n/nl_BE.po index 5bee5f9bfd9..3413cf38ac8 100644 --- a/addons/account_asset/i18n/nl_BE.po +++ b/addons/account_asset/i18n/nl_BE.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:04+0000\n" -"PO-Revision-Date: 2012-11-27 13:35+0000\n" +"PO-Revision-Date: 2013-04-15 15:59+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-03-16 05:50+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n" +"X-Generator: Launchpad (build 16564)\n" #. module: account_asset #: view:account.asset.asset:0 @@ -148,7 +148,7 @@ msgstr "Dit is het bedrag dat u niet kunt afschrijven." #. module: account_asset #: help:account.asset.asset,method_period:0 msgid "The amount of time between two depreciations, in months" -msgstr "" +msgstr "De tijd tussen twee afschrijvingen, in maanden" #. module: account_asset #: field:account.asset.depreciation.line,depreciation_date:0 @@ -265,7 +265,7 @@ msgstr "Duur wijzigen" #: help:account.asset.category,method_number:0 #: help:account.asset.history,method_number:0 msgid "The number of depreciations needed to depreciate your asset" -msgstr "" +msgstr "Het aantal keer dat er moet worden afgeschreven." #. module: account_asset #: view:account.asset.category:0 @@ -295,7 +295,7 @@ msgstr "" #. module: account_asset #: field:account.asset.depreciation.line,remaining_value:0 msgid "Next Period Depreciation" -msgstr "" +msgstr "Volgende afschrijvingsperiode" #. module: account_asset #: help:account.asset.history,method_period:0 @@ -346,7 +346,7 @@ msgstr "Investeringscategorie zoeken" #. module: account_asset #: view:asset.modify:0 msgid "months" -msgstr "" +msgstr "maanden" #. module: account_asset #: model:ir.model,name:account_asset.model_account_invoice_line @@ -608,7 +608,7 @@ msgstr "Afschrijvingsmethode" #. module: account_asset #: field:account.asset.depreciation.line,amount:0 msgid "Current Depreciation" -msgstr "" +msgstr "Huidige afschrijving" #. module: account_asset #: field:account.asset.asset,name:0 @@ -653,6 +653,9 @@ msgid "" " * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n" " * Degressive: Calculated on basis of: Residual Value * Degressive Factor" msgstr "" +"Kies de methode om het aantal afschrijvingsregels te berekenen.\n" +" * Lineair: op basis van: brutowaarde / aantal afschrijvingen\n" +" * Degressief: op basis van: restwaarde * degressieve factor" #. module: account_asset #: field:account.asset.depreciation.line,move_check:0 diff --git a/addons/account_asset/report/account_asset_report.py b/addons/account_asset/report/account_asset_report.py index 1554880ac38..40ab1c778f0 100644 --- a/addons/account_asset/report/account_asset_report.py +++ b/addons/account_asset/report/account_asset_report.py @@ -82,6 +82,5 @@ class asset_asset_report(osv.osv): a.purchase_value, a.id, a.salvage_value )""") -asset_asset_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_asset/report/account_asset_report_view.xml b/addons/account_asset/report/account_asset_report_view.xml index 4865196c4a8..c772c6e4103 100644 --- a/addons/account_asset/report/account_asset_report_view.xml +++ b/addons/account_asset/report/account_asset_report_view.xml @@ -49,7 +49,7 @@ - + diff --git a/addons/account_asset/wizard/account_asset_change_duration.py b/addons/account_asset/wizard/account_asset_change_duration.py index 19782c76367..f27507ac2b3 100755 --- a/addons/account_asset/wizard/account_asset_change_duration.py +++ b/addons/account_asset/wizard/account_asset_change_duration.py @@ -127,6 +127,5 @@ class asset_modify(osv.osv_memory): asset_obj.compute_depreciation_board(cr, uid, [asset_id], context=context) return {'type': 'ir.actions.act_window_close'} -asset_modify() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_asset/wizard/wizard_asset_compute.py b/addons/account_asset/wizard/wizard_asset_compute.py index cc870329840..f7cc6cf89c0 100755 --- a/addons/account_asset/wizard/wizard_asset_compute.py +++ b/addons/account_asset/wizard/wizard_asset_compute.py @@ -30,7 +30,7 @@ class asset_depreciation_confirmation_wizard(osv.osv_memory): } def _get_period(self, cr, uid, context=None): - periods = self.pool.get('account.period').find(cr, uid) + periods = self.pool.get('account.period').find(cr, uid, context=context) if periods: return periods[0] return False @@ -55,6 +55,5 @@ class asset_depreciation_confirmation_wizard(osv.osv_memory): 'type': 'ir.actions.act_window', } -asset_depreciation_confirmation_wizard() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_bank_statement_extensions/account_bank_statement.py b/addons/account_bank_statement_extensions/account_bank_statement.py index 60dcc6dfa25..b9e44ee8f9c 100644 --- a/addons/account_bank_statement_extensions/account_bank_statement.py +++ b/addons/account_bank_statement_extensions/account_bank_statement.py @@ -56,7 +56,6 @@ class account_bank_statement(osv.osv): (tuple([x.id for x in st.line_ids]),)) return True -account_bank_statement() class account_bank_statement_line_global(osv.osv): _name = 'account.bank.statement.line.global' @@ -100,7 +99,6 @@ class account_bank_statement_line_global(osv.osv): ids = self.search(cr, user, args, context=context, limit=limit) return self.name_get(cr, user, ids, context=context) -account_bank_statement_line_global() class account_bank_statement_line(osv.osv): _inherit = 'account.bank.statement.line' @@ -130,6 +128,5 @@ class account_bank_statement_line(osv.osv): Please go to the associated bank statement in order to delete and/or modify bank statement line.')) return super(account_bank_statement_line, self).unlink(cr, uid, ids, context=context) -account_bank_statement_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_bank_statement_extensions/i18n/cs.po b/addons/account_bank_statement_extensions/i18n/cs.po new file mode 100644 index 00000000000..4eef2acf03b --- /dev/null +++ b/addons/account_bank_statement_extensions/i18n/cs.po @@ -0,0 +1,357 @@ +# Czech 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-03-31 16:42+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: account_bank_statement_extensions +#: help:account.bank.statement.line.global,name:0 +msgid "Originator to Beneficiary Information" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +#: selection:account.bank.statement.line,state:0 +msgid "Confirmed" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement:0 +#: view:account.bank.statement.line:0 +msgid "Glob. Id" +msgstr "" + +#. module: account_bank_statement_extensions +#: selection:account.bank.statement.line.global,type:0 +msgid "CODA" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line.global,parent_id:0 +msgid "Parent Code" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Debit" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:cancel.statement.line:0 +#: model:ir.actions.act_window,name:account_bank_statement_extensions.action_cancel_statement_line +#: model:ir.model,name:account_bank_statement_extensions.model_cancel_statement_line +msgid "Cancel selected statement lines" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line,val_date:0 +msgid "Value Date" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Group By..." +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +#: selection:account.bank.statement.line,state:0 +msgid "Draft" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Statement" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:confirm.statement.line:0 +#: model:ir.actions.act_window,name:account_bank_statement_extensions.action_confirm_statement_line +#: model:ir.model,name:account_bank_statement_extensions.model_confirm_statement_line +msgid "Confirm selected statement lines" +msgstr "" + +#. module: account_bank_statement_extensions +#: report:bank.statement.balance.report:0 +#: model:ir.actions.report.xml,name:account_bank_statement_extensions.bank_statement_balance_report +msgid "Bank Statement Balances Report" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:cancel.statement.line:0 +msgid "Cancel Lines" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line.global:0 +#: model:ir.model,name:account_bank_statement_extensions.model_account_bank_statement_line_global +msgid "Batch Payment Info" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line,state:0 +msgid "Status" +msgstr "" + +#. module: account_bank_statement_extensions +#: code:addons/account_bank_statement_extensions/account_bank_statement.py:129 +#, python-format +msgid "" +"Delete operation not allowed. Please go to the associated bank " +"statement in order to delete and/or modify bank statement line." +msgstr "" + +#. module: account_bank_statement_extensions +#: view:confirm.statement.line:0 +msgid "or" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:confirm.statement.line:0 +msgid "Confirm Lines" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line.global:0 +msgid "Transactions" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line.global,type:0 +msgid "Type" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +#: report:bank.statement.balance.report:0 +msgid "Journal" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Confirmed Statement Lines." +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Credit Transactions." +msgstr "" + +#. module: account_bank_statement_extensions +#: model:ir.actions.act_window,help:account_bank_statement_extensions.action_cancel_statement_line +msgid "cancel selected statement lines." +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line,counterparty_number:0 +msgid "Counterparty Number" +msgstr "" + +#. module: account_bank_statement_extensions +#: report:bank.statement.balance.report:0 +msgid "Closing Balance" +msgstr "" + +#. module: account_bank_statement_extensions +#: report:bank.statement.balance.report:0 +msgid "Date" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +#: field:account.bank.statement.line,globalisation_amount:0 +msgid "Glob. Amount" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Debit Transactions." +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Extended Filters..." +msgstr "" + +#. module: account_bank_statement_extensions +#: view:confirm.statement.line:0 +msgid "Confirmed lines cannot be changed anymore." +msgstr "" + +#. module: account_bank_statement_extensions +#: view:cancel.statement.line:0 +msgid "Are you sure you want to cancel the selected Bank Statement lines ?" +msgstr "" + +#. module: account_bank_statement_extensions +#: report:bank.statement.balance.report:0 +msgid "Name" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line.global,name:0 +msgid "OBI" +msgstr "" + +#. module: account_bank_statement_extensions +#: selection:account.bank.statement.line.global,type:0 +msgid "ISO 20022" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Notes" +msgstr "" + +#. module: account_bank_statement_extensions +#: selection:account.bank.statement.line.global,type:0 +msgid "Manual" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Bank Transaction" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Credit" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line.global,amount:0 +msgid "Amount" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Fin.Account" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line,counterparty_currency:0 +msgid "Counterparty Currency" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line,counterparty_bic:0 +msgid "Counterparty BIC" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line.global,child_ids:0 +msgid "Child Codes" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Search Bank Transactions" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:confirm.statement.line:0 +msgid "Are you sure you want to confirm the selected Bank Statement lines ?" +msgstr "" + +#. module: account_bank_statement_extensions +#: help:account.bank.statement.line,globalisation_id:0 +msgid "" +"Code to identify transactions belonging to the same globalisation level " +"within a batch payment" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Draft Statement Lines." +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Glob. Am." +msgstr "" + +#. module: account_bank_statement_extensions +#: model:ir.model,name:account_bank_statement_extensions.model_account_bank_statement_line +msgid "Bank Statement Line" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line.global,code:0 +msgid "Code" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line,counterparty_name:0 +msgid "Counterparty Name" +msgstr "" + +#. module: account_bank_statement_extensions +#: model:ir.model,name:account_bank_statement_extensions.model_res_partner_bank +msgid "Bank Accounts" +msgstr "" + +#. module: account_bank_statement_extensions +#: model:ir.model,name:account_bank_statement_extensions.model_account_bank_statement +msgid "Bank Statement" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Statement Line" +msgstr "" + +#. module: account_bank_statement_extensions +#: sql_constraint:account.bank.statement.line.global:0 +msgid "The code must be unique !" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line.global,bank_statement_line_ids:0 +#: model:ir.actions.act_window,name:account_bank_statement_extensions.action_bank_statement_line +#: model:ir.ui.menu,name:account_bank_statement_extensions.bank_statement_line +msgid "Bank Statement Lines" +msgstr "" + +#. module: account_bank_statement_extensions +#: code:addons/account_bank_statement_extensions/account_bank_statement.py:129 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line.global:0 +msgid "Child Batch Payments" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:confirm.statement.line:0 +msgid "Cancel" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Statement Lines" +msgstr "" + +#. module: account_bank_statement_extensions +#: view:account.bank.statement.line:0 +msgid "Total Amount" +msgstr "" + +#. module: account_bank_statement_extensions +#: field:account.bank.statement.line,globalisation_id:0 +msgid "Globalisation ID" +msgstr "" diff --git a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py index 9f28b083603..59b8efb23e1 100644 --- a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py +++ b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py @@ -21,15 +21,12 @@ ############################################################################## import time + from openerp.report import report_sxw -from openerp import pooler -import logging -_logger = logging.getLogger(__name__) class bank_statement_balance_report(report_sxw.rml_parse): def set_context(self, objects, data, ids, report_type=None): - #_logger.warning('addons.'+__name__, 'set_context, objects = %s, data = %s, ids = %s' % (objects, data, ids)) cr = self.cr uid = self.uid context = self.context diff --git a/addons/account_bank_statement_extensions/res_partner_bank.py b/addons/account_bank_statement_extensions/res_partner_bank.py index f866634a08c..22baa78d39f 100644 --- a/addons/account_bank_statement_extensions/res_partner_bank.py +++ b/addons/account_bank_statement_extensions/res_partner_bank.py @@ -35,5 +35,4 @@ class res_partner_bank(osv.osv): ids = self.search(cr, user, args, context=context, limit=limit) return self.name_get(cr, user, ids, context=context) -res_partner_bank() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_bank_statement_extensions/wizard/cancel_statement_line.py b/addons/account_bank_statement_extensions/wizard/cancel_statement_line.py index 46d71354d4b..15c242e9c33 100644 --- a/addons/account_bank_statement_extensions/wizard/cancel_statement_line.py +++ b/addons/account_bank_statement_extensions/wizard/cancel_statement_line.py @@ -32,6 +32,5 @@ class cancel_statement_line(osv.osv_memory): line_obj.write(cr, uid, line_ids, {'state': 'draft'}, context=context) return {} -cancel_statement_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_bank_statement_extensions/wizard/confirm_statement_line.py b/addons/account_bank_statement_extensions/wizard/confirm_statement_line.py index 3a887a52441..c330a2cc359 100644 --- a/addons/account_bank_statement_extensions/wizard/confirm_statement_line.py +++ b/addons/account_bank_statement_extensions/wizard/confirm_statement_line.py @@ -32,6 +32,5 @@ class confirm_statement_line(osv.osv_memory): line_obj.write(cr, uid, line_ids, {'state': 'confirm'}, context=context) return {} -confirm_statement_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/account_budget.py b/addons/account_budget/account_budget.py index a88c468fff1..e6fc3a29668 100644 --- a/addons/account_budget/account_budget.py +++ b/addons/account_budget/account_budget.py @@ -48,7 +48,6 @@ class account_budget_post(osv.osv): } _order = "name" -account_budget_post() class crossovered_budget(osv.osv): @@ -104,7 +103,6 @@ class crossovered_budget(osv.osv): }) return True -crossovered_budget() class crossovered_budget_lines(osv.osv): @@ -202,7 +200,6 @@ class crossovered_budget_lines(osv.osv): 'company_id': fields.related('crossovered_budget_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True) } -crossovered_budget_lines() class account_analytic_account(osv.osv): _inherit = "account.analytic.account" @@ -211,6 +208,5 @@ class account_analytic_account(osv.osv): 'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'analytic_account_id', 'Budget Lines'), } -account_analytic_account() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/report/analytic_account_budget_report.py b/addons/account_budget/report/analytic_account_budget_report.py index eed8ded213f..6701fc06a2b 100644 --- a/addons/account_budget/report/analytic_account_budget_report.py +++ b/addons/account_budget/report/analytic_account_budget_report.py @@ -22,7 +22,6 @@ import time import datetime -from openerp import pooler from openerp.report import report_sxw class analytic_account_budget_report(report_sxw.rml_parse): diff --git a/addons/account_budget/report/crossovered_budget_report.py b/addons/account_budget/report/crossovered_budget_report.py index 4a3b632a8de..70cbdecb713 100644 --- a/addons/account_budget/report/crossovered_budget_report.py +++ b/addons/account_budget/report/crossovered_budget_report.py @@ -22,7 +22,6 @@ import time import datetime -from openerp import pooler from openerp.report import report_sxw import operator from openerp import osv diff --git a/addons/account_budget/wizard/account_budget_analytic.py b/addons/account_budget/wizard/account_budget_analytic.py index 0cdb7504f75..90285b90d1e 100644 --- a/addons/account_budget/wizard/account_budget_analytic.py +++ b/addons/account_budget/wizard/account_budget_analytic.py @@ -50,6 +50,5 @@ class account_budget_analytic(osv.osv_memory): 'datas': datas, } -account_budget_analytic() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/wizard/account_budget_crossovered_report.py b/addons/account_budget/wizard/account_budget_crossovered_report.py index 97fc43c8e9d..6f89a3cd95c 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_report.py @@ -51,6 +51,5 @@ class account_budget_crossvered_report(osv.osv_memory): 'datas': datas, } -account_budget_crossvered_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py index f42c39ec6ac..6e3131b584c 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py @@ -53,7 +53,6 @@ class account_budget_crossvered_summary_report(osv.osv_memory): 'datas': datas, } -account_budget_crossvered_summary_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/wizard/account_budget_report.py b/addons/account_budget/wizard/account_budget_report.py index 5db6c68d508..54c3180ee0d 100644 --- a/addons/account_budget/wizard/account_budget_report.py +++ b/addons/account_budget/wizard/account_budget_report.py @@ -52,6 +52,5 @@ class account_budget_report(osv.osv_memory): 'datas': datas, } -account_budget_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_cancel/i18n/hu.po b/addons/account_cancel/i18n/hu.po index 6b63bb37bb2..bab8304030f 100644 --- a/addons/account_cancel/i18n/hu.po +++ b/addons/account_cancel/i18n/hu.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:05+0000\n" -"PO-Revision-Date: 2011-01-30 16:46+0000\n" -"Last-Translator: Krisztian Eyssen \n" +"PO-Revision-Date: 2013-04-04 13:17+0000\n" +"Last-Translator: krnkris \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:42+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-05 05:37+0000\n" +"X-Generator: Launchpad (build 16550)\n" #. module: account_cancel #: view:account.invoice:0 msgid "Cancel" -msgstr "" +msgstr "Sztornó" #~ msgid "Account Cancel" #~ msgstr "Érvénytelenítés" diff --git a/addons/account_check_writing/account.py b/addons/account_check_writing/account.py index 62b7336dc5f..035e3a710b0 100644 --- a/addons/account_check_writing/account.py +++ b/addons/account_check_writing/account.py @@ -29,7 +29,6 @@ class account_journal(osv.osv): 'use_preprint_check': fields.boolean('Use Preprinted Check'), } -account_journal() class res_company(osv.osv): _inherit = "res.company" @@ -46,5 +45,4 @@ class res_company(osv.osv): 'check_layout' : lambda *a: 'top', } -res_company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_check_writing/account_voucher.py b/addons/account_check_writing/account_voucher.py index 7a5d12f5cff..8e1ad2e1fbf 100644 --- a/addons/account_check_writing/account_voucher.py +++ b/addons/account_check_writing/account_voucher.py @@ -97,4 +97,3 @@ class account_voucher(osv.osv): res['arch'] = etree.tostring(doc) return res -account_voucher() diff --git a/addons/account_check_writing/i18n/hu.po b/addons/account_check_writing/i18n/hu.po new file mode 100644 index 00000000000..528cb4fed60 --- /dev/null +++ b/addons/account_check_writing/i18n/hu.po @@ -0,0 +1,247 @@ +# Hungarian 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-11 22:57+0000\n" +"Last-Translator: krnkris \n" +"Language-Team: Hungarian \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-12 05:21+0000\n" +"X-Generator: Launchpad (build 16564)\n" + +#. module: account_check_writing +#: selection:res.company,check_layout:0 +msgid "Check on Top" +msgstr "Fennt lévő csekk" + +#. module: account_check_writing +#: report:account.print.check.top:0 +msgid "Open Balance" +msgstr "Nyitó egyenleg" + +#. module: account_check_writing +#: view:account.check.write:0 +#: view:account.voucher:0 +msgid "Print Check" +msgstr "Csekk nyomtatása" + +#. module: account_check_writing +#: selection:res.company,check_layout:0 +msgid "Check in middle" +msgstr "Középen lévő csekk" + +#. module: account_check_writing +#: help:res.company,check_layout:0 +msgid "" +"Check on top is compatible with Quicken, QuickBooks and Microsoft Money. " +"Check in middle is compatible with Peachtree, ACCPAC and DacEasy. Check on " +"bottom is compatible with Peachtree, ACCPAC and DacEasy only" +msgstr "" +"Fennt lévő csekk kompatibilis a Quicken, QuickBooks és Microsoft Money " +"csekkekekl. A középen lévő csekkek kompatibilisek a Peachtree, ACCPAC és " +"DacEasy csekkekel. Az alul lévő csekkek kompatibilisek a Peachtree, ACCPAC " +"és DacEasy only csekkekel." + +#. module: account_check_writing +#: selection:res.company,check_layout:0 +msgid "Check on bottom" +msgstr "Alul lévő csekkek" + +#. module: account_check_writing +#: model:ir.actions.act_window,name:account_check_writing.action_account_check_write +msgid "Print Check in Batch" +msgstr "Csekkek kötegelt nyomtatása" + +#. module: account_check_writing +#: code:addons/account_check_writing/wizard/account_check_batch_printing.py:59 +#, python-format +msgid "One of the printed check already got a number." +msgstr "Egyik, már kinyomtatott csekk már el van látva számmal." + +#. module: account_check_writing +#: help:account.journal,allow_check_writing:0 +msgid "Check this if the journal is to be used for writing checks." +msgstr "Jelölje be ezt, ha naplót csekkírásra használja." + +#. module: account_check_writing +#: field:account.journal,allow_check_writing:0 +msgid "Allow Check writing" +msgstr "Csekk írás engedélyezése." + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Description" +msgstr "Leírás" + +#. module: account_check_writing +#: model:ir.model,name:account_check_writing.model_account_journal +msgid "Journal" +msgstr "Napló" + +#. module: account_check_writing +#: model:ir.actions.act_window,name:account_check_writing.action_write_check +#: model:ir.ui.menu,name:account_check_writing.menu_action_write_check +msgid "Write Checks" +msgstr "Csekkek írása" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Discount" +msgstr "Kedvezmény" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Original Amount" +msgstr "Eredeti összeg" + +#. module: account_check_writing +#: field:res.company,check_layout:0 +msgid "Check Layout" +msgstr "Csekk elrendezése" + +#. module: account_check_writing +#: field:account.voucher,allow_check:0 +msgid "Allow Check Writing" +msgstr "Csekk írás engedélyezése" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Payment" +msgstr "Kifizetés" + +#. module: account_check_writing +#: field:account.journal,use_preprint_check:0 +msgid "Use Preprinted Check" +msgstr "Előre nyomtatott csekk használata" + +#. module: account_check_writing +#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_bottom +msgid "Print Check (Bottom)" +msgstr "Csekk nyomtatás (Alsó)" + +#. module: account_check_writing +#: model:ir.actions.act_window,help:account_check_writing.action_write_check +msgid "" +"

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

\n" +" The check payment form allows you to track the payment you " +"do\n" +" to your suppliers using checks. When you select a supplier, " +"the\n" +" payment method and an amount for the payment, OpenERP will\n" +" propose to reconcile your payment with the open supplier\n" +" invoices or bills.\n" +"

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

\n" +" Kattintson új csekk létrehozásához. \n" +"

\n" +" A csekk kifizetési lap lehetővé teszi a beszállítókhoz " +"történt \n" +" csekken történt kifizetések nyomon követését. Ha kiválaszt " +"egy beszállítót,\n" +" a fizetési módot és az összeget, OpenERP javasolni fogja \n" +" a fizetés összeegyeztetését a még nyitott beszállítói " +"számlákkal és\n" +" fizetésekkel.\n" +"

\n" +" " + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Due Date" +msgstr "Fizetési határidő" + +#. module: account_check_writing +#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_middle +msgid "Print Check (Middle)" +msgstr "Csekk nyomtatás (Középső)" + +#. module: account_check_writing +#: model:ir.model,name:account_check_writing.model_res_company +msgid "Companies" +msgstr "Vállalatok" + +#. module: account_check_writing +#: code:addons/account_check_writing/wizard/account_check_batch_printing.py:59 +#, python-format +msgid "Error!" +msgstr "Hiba!" + +#. module: account_check_writing +#: help:account.check.write,check_number:0 +msgid "The number of the next check number to be printed." +msgstr "A következő csekkszám nyomtatása" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +msgid "Balance Due" +msgstr "Esedékes egyenleg" + +#. module: account_check_writing +#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_top +msgid "Print Check (Top)" +msgstr "Csekk nyomtatás (Felső)" + +#. module: account_check_writing +#: report:account.print.check.bottom:0 +#: report:account.print.check.middle:0 +#: report:account.print.check.top:0 +msgid "Check Amount" +msgstr "Csekk végösszege" + +#. module: account_check_writing +#: model:ir.model,name:account_check_writing.model_account_voucher +msgid "Accounting Voucher" +msgstr "Könyvelési bizonylat" + +#. module: account_check_writing +#: view:account.check.write:0 +msgid "or" +msgstr "vagy" + +#. module: account_check_writing +#: field:account.voucher,amount_in_word:0 +msgid "Amount in Word" +msgstr "Összeg szavakkal" + +#. module: account_check_writing +#: model:ir.model,name:account_check_writing.model_account_check_write +msgid "Prin Check in Batch" +msgstr "Csekk kötegelt nyomtatása" + +#. module: account_check_writing +#: view:account.check.write:0 +msgid "Cancel" +msgstr "Mégse" + +#. module: account_check_writing +#: field:account.check.write,check_number:0 +msgid "Next Check Number" +msgstr "Következő csekk száma" + +#. module: account_check_writing +#: view:account.check.write:0 +msgid "Check" +msgstr "Csekk" diff --git a/addons/account_check_writing/wizard/account_check_batch_printing.py b/addons/account_check_writing/wizard/account_check_batch_printing.py index afeb5de6445..c3a13e2c687 100644 --- a/addons/account_check_writing/wizard/account_check_batch_printing.py +++ b/addons/account_check_writing/wizard/account_check_batch_printing.py @@ -83,5 +83,4 @@ class account_check_write(osv.osv_memory): 'nodestroy': True } -account_check_write() diff --git a/addons/account_followup/account_followup_customers.xml b/addons/account_followup/account_followup_customers.xml index 6be11399b68..6893abe012e 100644 --- a/addons/account_followup/account_followup_customers.xml +++ b/addons/account_followup/account_followup_customers.xml @@ -10,7 +10,7 @@ - + @@ -29,7 +29,7 @@ res.partner - + diff --git a/addons/account_followup/i18n/hu.po b/addons/account_followup/i18n/hu.po index a8fc4f8963c..e69bb7b38c0 100644 --- a/addons/account_followup/i18n/hu.po +++ b/addons/account_followup/i18n/hu.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: Krisztian Eyssen \n" +"PO-Revision-Date: 2013-04-04 13:15+0000\n" +"Last-Translator: krnkris \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-04-05 05:37+0000\n" +"X-Generator: Launchpad (build 16550)\n" #. module: account_followup #: model:email.template,subject:account_followup.email_template_account_followup_default @@ -22,12 +22,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} Fizetési felszólítás" #. module: account_followup #: help:res.partner,latest_followup_level_id:0 msgid "The maximum follow-up level" -msgstr "" +msgstr "Fizetési-emlékeztető szint maximuma" #. module: account_followup #: view:account_followup.stat:0 @@ -43,33 +43,33 @@ msgstr "Fizetési emlékeztető" #. 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 "Következő művelet időpontja" #. module: account_followup #: view:account_followup.followup.line:0 #: field:account_followup.followup.line,manual_action:0 msgid "Manual Action" -msgstr "" +msgstr "Kézi művelet" #. module: account_followup #: field:account_followup.sending.results,needprinting:0 msgid "Needs Printing" -msgstr "" +msgstr "Nyomtatás szükséges" #. module: account_followup #: view:res.partner:0 msgid "⇾ Mark as Done" -msgstr "" +msgstr "⇾ Jelölje elvégzettnek" #. module: account_followup #: field:account_followup.followup.line,manual_action_note:0 msgid "Action To Do" -msgstr "" +msgstr "Elvégzendő művelet" #. module: account_followup #: field:account_followup.followup,company_id:0 @@ -94,34 +94,34 @@ msgstr "E-mail tárgya" #. 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 "a határidő napján, a következő műveleteket hajtsa végre:" #. module: account_followup #: view:account_followup.followup.line:0 msgid "Follow-up Steps" -msgstr "" +msgstr "Fizetési-emlékezetető lépései" #. module: account_followup #: field:account_followup.print,email_body:0 msgid "Email Body" -msgstr "" +msgstr "E-mail szövege" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_account_followup_print msgid "Send Follow-Ups" -msgstr "" +msgstr "Fizetési-emlékezető küldése" #. module: account_followup #: report:account_followup.followup.print:0 #: code:addons/account_followup/account_followup.py:263 #, python-format msgid "Amount" -msgstr "" +msgstr "Összeg" #. module: account_followup #: help:res.partner,payment_next_action:0 @@ -129,11 +129,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 "" +"Ez a következő elvégezni kívánt művelet. Ez automatikusan beállított amint " +"a partner elér egy olyan fizetési-emlékeztető szintet, ami kézi beavatkozást " +"igényel. " #. module: account_followup #: view:res.partner:0 msgid "No Responsible" -msgstr "" +msgstr "Nincs felelős" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line2 @@ -158,6 +161,24 @@ msgid "" "\n" "Best Regards,\n" msgstr "" +"\n" +"Tisztelt %(partner_name)s,\n" +"\n" +"Csalódottan vettük tudomásul, és ezért fizetési-emlékeztetőt vagyunk " +"kénytelenek küldeni, mivel a számlája már régebben esedékessé vált.\n" +"\n" +"Fontos, hogy azonnal fizessenek, egyéb esetben kénytelenek vagyunk elbírálni " +"a számlájuk lezárását, ami azzal jár, hogy nem leszünk képesek időben " +"szállítani az Önök vállalakozásának (termékeket/szolgáltatásokat).\n" +"Kérjük Önöket a fizetés 8 napon belüli pontos teljesítésére.\n" +"\n" +"Ha a fizetéssel kapcsolatban probléma merült fel, amit mi nem vettünk " +"figyelembe, akkor kérjük vegyék fel a könyvelési csoportunkkal a " +"kapcsolatot, hogy elháríthassuk azt amilyen gyorsan csak lehet.\n" +"\n" +"A lejárt számlák részleteit lentebb találják.\n" +"\n" +"Üdvözlettel,\n" #. module: account_followup #: model:email.template,body_html:account_followup.email_template_account_followup_level0 @@ -195,6 +216,39 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +"\n" +"

Tisztelt ${object.name},

\n" +"

\n" +" Ha időközben kiegyenlítésre került, vagy a mi hibánkból adódóan téves, " +"akkor tárgytalan, \n" +"de adataink szerint a következő tétel kifizetés nélkül maradt. \n" +"Kérjük Önöket a fizetés 8 napon belüli pontos teljesítésére.\n" +"\n" +"Ha a levél elküldése előtt a fizetés már megtörtént akkor kérjük tekintsék " +"ezt tárgytalannak. Kérjük vegyék fel a kapcsolatot könyvelési " +"csoportunkkal. \n" +"\n" +"

\n" +"
\n" +"Üdvözlettel,\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 "Tartozik összesen" #. module: account_followup #: field:res.partner,payment_next_action:0 msgid "Next Action" -msgstr "" +msgstr "Következő művelet" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": Partner Name" -msgstr "" +msgstr ": Partner neve" #. module: account_followup #: field:account_followup.followup.line,manual_action_responsible_id:0 msgid "Assign a Responsible" -msgstr "" +msgstr "Jelöljön ki egy felelőst" #. module: account_followup #: view:account_followup.followup:0 @@ -255,6 +309,16 @@ msgid "" " same customer, the actions of the most \n" " overdue invoice will be executed." msgstr "" +"Egy vevő kifizetetlen számlájának emlékeztetésére,\n" +" meghatározhat különböző műveleteket a vevő késedel-\n" +" métől függően. Ezek a műveletek fizetési-emlékeztető " +"szintekbe\n" +" csoportosítottak, melyek a számla fizetési határidő " +"dátumától\n" +" számított bizonyos napokon lesznek kapcsolva.\n" +" Ha több lejárt számlája is van ugyanannak a \n" +" vevőnek, akkor a leghosszabb nappal lejárt művelet \n" +" lesz elvégezve." #. module: account_followup #: report:account_followup.followup.print:0 @@ -269,7 +333,7 @@ msgstr "Partnerek" #. module: account_followup #: sql_constraint:account_followup.followup:0 msgid "Only one follow-up per company is allowed" -msgstr "" +msgstr "Vállalatonként csak egy fizetési-emlékeztető engedélyezett" #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:254 @@ -280,12 +344,12 @@ msgstr "Fizetési emlékeztető" #. module: account_followup #: help:account_followup.followup.line,send_letter:0 msgid "When processing, it will print a letter" -msgstr "" +msgstr "Ha el lesz végeve, akkor levelet fog nyomtatni" #. module: account_followup #: field:res.partner,payment_earliest_due_date:0 msgid "Worst Due Date" -msgstr "" +msgstr "Legroszabb leghoszabb lejárati idő" #. module: account_followup #: view:account_followup.stat:0 @@ -295,17 +359,17 @@ msgstr "Nem peresített" #. module: account_followup #: view:account_followup.print:0 msgid "Send emails and generate letters" -msgstr "" +msgstr "Küldjön e-mail-t és hozzon létre levelet" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_customer_followup msgid "Manual Follow-Ups" -msgstr "" +msgstr "Kézi fizetési-emlékeztető" #. 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 +411,40 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +" \n" +"

Dear ${object.name},

\n" +"

\n" +" Csalódottan vettük tudomásul, és ezért fizetési-emlékeztetőt vagyunk " +"kénytelenek küldeni, mivel a számlája már régebben esedékessé vált.Fontos, " +"hogy azonnal fizessenek, egyéb esetben kénytelenek vagyunk elbírálni a " +"számlájuk lezárását, ami azzal jár, hogy nem leszünk képesek időben " +"szállítani az Önök vállalakozásának (termékeket/szolgáltatásokat).\n" +"Kérjük Önöket a fizetés 8 napon belüli pontos teljesítésére.\n" +"Ha a fizetéssel kapcsolatban probléma merült fel, amit mi nem vettünk " +"figyelembe, akkor kérjük vegyék fel a könyvelési csoportunkkal a " +"kapcsolatot, hogy elháríthassuk azt amilyen gyorsan csak lehet.\n" +"A lejárt számlák részleteit lentebb találják.\n" +"

\n" +"
\n" +"Üdvözlettel,\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 +454,49 @@ msgstr "Tartozik" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_stat msgid "Follow-up Statistics" -msgstr "" +msgstr "Fizetési-emlékeztető statisztikák" #. module: account_followup #: view:res.partner:0 msgid "Send Overdue Email" -msgstr "" +msgstr "Lejárt dátumú fizetésről e-mail emlékeztető küldése" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_followup_line msgid "Follow-up Criteria" -msgstr "" +msgstr "Fizetési-emlékeztető kritériom" #. module: account_followup #: help:account_followup.followup.line,sequence:0 msgid "Gives the sequence order when displaying a list of follow-up lines." -msgstr "Megadja a fizetési emlékeztető sorok listázási sorrendjét." +msgstr "Megadja a fizetési-emlékeztető sorok listázási sorrendjét." #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:166 #, python-format msgid " will be sent" -msgstr "" +msgstr " el lesz küldve" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": User's Company Name" -msgstr "" +msgstr ": Felhasználó vállalata neve" #. module: account_followup #: view:account_followup.followup.line:0 #: field:account_followup.followup.line,send_letter:0 msgid "Send a Letter" -msgstr "" +msgstr "Levél küldése" #. module: account_followup #: model:ir.actions.act_window,name:account_followup.action_account_followup_definition_form msgid "Payment Follow-ups" -msgstr "" +msgstr "fizetési-emlékeztetők kifizetése" #. module: account_followup #: field:account_followup.followup.line,delay:0 msgid "Due Days" -msgstr "" +msgstr "Határidő túllépése napokban" #. module: account_followup #: field:account.move.line,followup_line_id:0 @@ -414,12 +512,12 @@ msgstr "Legutolsó fizetési emlékeztető" #. module: account_followup #: model:ir.ui.menu,name:account_followup.menu_manual_reconcile_followup msgid "Reconcile Invoices & Payments" -msgstr "" +msgstr "Számlák & Fizetések párosítása" #. module: account_followup #: model:ir.ui.menu,name:account_followup.account_followup_s msgid "Do Manual Follow-Ups" -msgstr "" +msgstr "Kézi fizetési-emlékeztető elvégzése" #. module: account_followup #: report:account_followup.followup.print:0 @@ -429,17 +527,17 @@ msgstr "P." #. module: account_followup #: field:account_followup.print,email_conf:0 msgid "Send Email Confirmation" -msgstr "" +msgstr "E-mail megerősítés küldése" #. module: account_followup #: view:account_followup.stat:0 msgid "Follow-up Entries with period in current year" -msgstr "" +msgstr "Fizetési-emlékeztető bejegyzések a tárgyi évben" #. module: account_followup #: field:account_followup.stat.by.partner,date_followup:0 msgid "Latest follow-up" -msgstr "" +msgstr "Legutóbbi fizetési-emlékeztető" #. module: account_followup #: field:account_followup.print,partner_lang:0 @@ -450,12 +548,12 @@ msgstr "E-mail küldése a partner nyelvén" #: code:addons/account_followup/wizard/account_followup_print.py:169 #, python-format msgid " email(s) sent" -msgstr "" +msgstr " e-mail(ek) elküldve" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_print msgid "Print Follow-up & Send Mail to Customers" -msgstr "" +msgstr "Fizetési-emlékeztető nyomtatása & E-mail küldése a vevők részére" #. module: account_followup #: field:account_followup.followup.line,description:0 @@ -466,12 +564,12 @@ msgstr "Kinyomtatott üzenet" #: code:addons/account_followup/wizard/account_followup_print.py:155 #, python-format msgid "Anybody" -msgstr "" +msgstr "Bárki" #. module: account_followup #: help:account_followup.followup.line,send_email:0 msgid "When processing, it will send an email" -msgstr "" +msgstr "végrehajtáskor egy e-mailt fog küldeni" #. module: account_followup #: view:account_followup.stat.by.partner:0 @@ -481,7 +579,7 @@ msgstr "Emlékeztetendő partner" #. module: account_followup #: view:res.partner:0 msgid "Print Overdue Payments" -msgstr "" +msgstr "Határidőn túli fizetések nyomtatása" #. module: account_followup #: field:account_followup.followup.line,followup_id:0 @@ -494,11 +592,12 @@ msgstr "Fizetési emlékeztetők" #, python-format msgid "Email not sent because of email address of partner not filled in" msgstr "" +"E-mail nem lett elküldve, mert a partner e-mail címe nem lett kitöltve" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_followup msgid "Account Follow-up" -msgstr "" +msgstr "Fizetési-emlékeztető könyvelés" #. module: account_followup #: help:res.partner,payment_responsible_id:0 @@ -506,11 +605,13 @@ msgid "" "Optionally you can assign a user to this field, which will make him " "responsible for the action." msgstr "" +"Választhat felhasználót is erre a mezőre, ami felelőssé teszi erre a " +"műveletre." #. 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 "A különböző levelek és e-mailek küldéséből származó eredmény" #. module: account_followup #: constraint:account_followup.followup.line:0 @@ -518,27 +619,29 @@ msgid "" "Your description is invalid, use the right legend or %% if you want to use " "the percent character." msgstr "" +"A leírása érvénytelen, használja a jobb oldali feliratot vagy %% ha akarja a " +"százalék karaktert használja." #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:172 #, python-format msgid " manual action(s) assigned:" -msgstr "" +msgstr " kézi művelet(ek) hozzárendelve:" #. module: account_followup #: view:res.partner:0 msgid "Search Partner" -msgstr "" +msgstr "Partner keresés" #. module: account_followup #: model:ir.ui.menu,name:account_followup.account_followup_print_menu msgid "Send Letters and Emails" -msgstr "" +msgstr "Levelek és E-mailek küldése" #. module: account_followup #: view:account_followup.followup:0 msgid "Search Follow-up" -msgstr "" +msgstr "Fizetési-emlékeztető keresése" #. module: account_followup #: view:res.partner:0 @@ -549,12 +652,12 @@ msgstr "" #: code:addons/account_followup/wizard/account_followup_print.py:237 #, python-format msgid "Send Letters and Emails: Actions Summary" -msgstr "" +msgstr "Levelek és E-mailek küldése: Műveletek összegzése" #. module: account_followup #: view:account_followup.print:0 msgid "or" -msgstr "" +msgstr "vagy" #. module: account_followup #: view:res.partner:0 @@ -562,21 +665,23 @@ msgid "" "If not specified by the latest follow-up level, it will send from the " "default email template" msgstr "" +"Ha nincs meghatározva a legutóbbi fizetési-emlékeztető szinttel, akkor az " +"alapértelmezett e-mail sablonnal lesz elküldve" #. module: account_followup #: sql_constraint:account_followup.followup.line:0 msgid "Days of the follow-up levels must be different" -msgstr "" +msgstr "A fizetési-emlékeztető szintek napjainak különbözőeknek kell lenniük" #. module: account_followup #: view:res.partner:0 msgid "Click to mark the action as done." -msgstr "" +msgstr "Kattintson a művelet elvégzésének jelülésére." #. module: account_followup #: model:ir.ui.menu,name:account_followup.menu_action_followup_stat_follow msgid "Follow-Ups Analysis" -msgstr "" +msgstr "Fizetési-emlékeztető elemzések" #. module: account_followup #: help:res.partner,payment_next_action_date:0 @@ -586,11 +691,16 @@ msgid "" "action. Can be practical to set manually e.g. to see if he keeps his " "promises." msgstr "" +"Ez az amikor kézi fizetési-emlékeztető szükséges. A mai nap lesz beállítva, " +"ha a partner egy olyan fizetési-emlékeztető szintet kap ami kézi " +"beavatkozást igényel. Praktikus lehet kézire állítani pl. megfigyelni, hogy " +"betartja-e a szavát." #. module: account_followup #: view:res.partner:0 msgid "Print overdue payments report independent of follow-up line" msgstr "" +"fizetési-emlékeztető soroktól független lejárt fizetési tételek nyomtatása" #. module: account_followup #: help:account_followup.print,date:0 @@ -609,7 +719,7 @@ msgstr "Fizetési emlékeztető küldés időpontja" #: view:res.partner:0 #: field:res.partner,payment_responsible_id:0 msgid "Follow-up Responsible" -msgstr "" +msgstr "Fizetési-emlékeztető felelőse" #. module: account_followup #: model:email.template,body_html:account_followup.email_template_account_followup_level2 @@ -646,6 +756,37 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +" \n" +"

Dear ${object.name},

\n" +"

\n" +" A többszörös fizetési-emlékeztető ellenére, még mindig nem történt meg a " +"számla kiegyenlítése.\n" +"Ha nem történik meg a kiegyenlítés 8 napon belül, törvényes úton vagyunk " +"kénytelenek az adósságot behajtani, minden további felszólítás nélkül.\n" +"Úgy gondoljuk, hogy ez nem lesz szükséges lépés a lenti részletekkel " +"kapcsolatban.\n" +"Az üggyel kapcsolatban felmerült kérdésekben, kérjük vegyék fel a " +"kapcsolatot a könyvelési csoportunkkal.\n" +"

\n" +"
\n" +"Tisztelttel,\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 @@ -655,7 +796,7 @@ msgstr "Bizonylat: vevő folyószámla kivonat" #. module: account_followup #: model:ir.ui.menu,name:account_followup.account_followup_menu msgid "Follow-up Levels" -msgstr "" +msgstr "Fizetési-emlékeztető szintek" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line4 @@ -678,40 +819,54 @@ msgid "" "Best Regards,\n" " " msgstr "" +"\n" +"Tisztelt %(partner_name)s,\n" +"\n" +"A többszörös fizetési-emlékeztető ellenére, még mindig nem történt meg a " +"számla kiegyenlítése.\n" +"Ha nem történik meg a kiegyenlítés 8 napon belül, törvényes úton vagyunk " +"kénytelenek az adósságot behajtani, minden további felszólítás nélkül.\n" +"Úgy gondoljuk, hogy ez nem lesz szükséges lépés a lenti részletekkel " +"kapcsolatban.\n" +"Az üggyel kapcsolatban felmerült kérdésekben, kérjük vegyék fel a " +"kapcsolatot a könyvelési csoportunkkal.\n" +"\n" +"Üdvözlettel,\n" +" " #. module: account_followup #: field:res.partner,payment_amount_due:0 msgid "Amount Due" -msgstr "" +msgstr "Esedékes összeg" #. module: account_followup #: field:account.move.line,followup_date:0 msgid "Latest Follow-up" -msgstr "Legutolsó fizetési emlékeztető" +msgstr "Legutobbi fizetési emlékeztető" #. module: account_followup #: view:account_followup.sending.results:0 msgid "Download Letters" -msgstr "" +msgstr "Levelek letöltése" #. module: account_followup #: field:account_followup.print,company_id:0 #: field:res.partner,unreconciled_aml_ids:0 msgid "unknown" -msgstr "" +msgstr "ismeretlen" #. module: account_followup #: code:addons/account_followup/account_followup.py:314 #, python-format msgid "Printed overdue payments report" -msgstr "" +msgstr "Lejárt fizetési tételek jelentésének nyomtatása" #. module: account_followup #: help:account_followup.followup.line,manual_action:0 msgid "" "When processing, it will set the manual action to be taken for that " "customer. " -msgstr "" +msgstr "Végrehajtáskor, a vevőhöz a kézi műveletet fogja beállítani. " #. module: account_followup #: view:res.partner:0 @@ -721,18 +876,25 @@ msgid "" " order to exclude it from the next follow-up " "actions." msgstr "" +"Alább a vevő ügyleteinek története.\n" +" Ellenőrizheti a \"Nincs fizetési-emlékeztető\" " +"soron\n" +" a következő fizetési-emlékeztető műveletekből " +"való kizárását." #. 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 " ki kellett volna küldeni az e-mail(ek)t, de " #. 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 "" +"Ellenőrizze, hogy a fizetési-emlékeztető szintek változtatása nélkül " +"szeretné a fizetési-emlékeztetők nyomtatást." #. module: account_followup #: model:ir.model,name:account_followup.model_account_move_line @@ -742,12 +904,12 @@ msgstr "Könyvelési tételsorok" #. module: account_followup #: report:account_followup.followup.print:0 msgid "Total:" -msgstr "" +msgstr "Összesen:" #. module: account_followup #: field:account_followup.followup.line,email_template_id:0 msgid "Email Template" -msgstr "" +msgstr "E-mail sablon" #. module: account_followup #: field:account_followup.print,summary:0 @@ -758,7 +920,7 @@ msgstr "Összegzés" #: view:account_followup.followup.line:0 #: field:account_followup.followup.line,send_email:0 msgid "Send an Email" -msgstr "" +msgstr "Egy E-amil küldése" #. module: account_followup #: field:account_followup.stat,credit:0 @@ -768,7 +930,7 @@ msgstr "Követel" #. module: account_followup #: field:res.partner,payment_amount_overdue:0 msgid "Amount Overdue" -msgstr "" +msgstr "Lejárt összeg" #. module: account_followup #: help:res.partner,latest_followup_level_id_without_lit:0 @@ -776,12 +938,14 @@ msgid "" "The maximum follow-up level without taking into account the account move " "lines with litigation" msgstr "" +"A maximum fizetési-emlékeztető szint ami megtehető anélkül, hogy az ne " +"kerüljön peres eléjárásra" #. module: account_followup #: view:account_followup.stat:0 #: field:res.partner,latest_followup_date:0 msgid "Latest Follow-up Date" -msgstr "" +msgstr "Legutóbbi fizetési-emlékeztető dátuma." #. module: account_followup #: model:email.template,body_html:account_followup.email_template_account_followup_default @@ -814,6 +978,34 @@ msgid "" "\n" " " msgstr "" +"\n" +"
\n" +" \n" +"

Tisztelt ${object.name},

\n" +"

\n" +" Ha időközben kiegyenlítésre került, vagy a mi hibánkból adódóan téves, " +"akkor tárgytalan, \n" +"de adataink szerint a következő tétel kifizetés nélkül maradt. \n" +"Kérjük Önöket a fizetés 8 napon belüli pontos teljesítésére.\n" +"Ha a levél elküldése előtt a fizetés már megtörtént akkor kérjük tekintsék " +"ezt tárgytalannak. Kérjük vegyék fel a kapcsolatot könyvelési " +"csoportunkkal. \n" +"

\n" +"
\n" +"Üdvözlettel,\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 +1018,17 @@ msgstr "Egyenleg" #. module: account_followup #: help:res.partner,payment_note:0 msgid "Payment Note" -msgstr "" +msgstr "Megjegyzés a fizetéshez" #. module: account_followup #: view:res.partner:0 msgid "My Follow-ups" -msgstr "" +msgstr "Fizetési-emlékeztetőim" #. 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,6 +1046,18 @@ msgid "" "\n" "Best Regards,\n" msgstr "" +"\n" +"Dear %(partner_name)s,\n" +"\n" +" Ha időközben kiegyenlítésre került, vagy a mi hibánkból adódóan téves, " +"akkor tárgytalan, de adataink szerint a következő tétel kifizetés nélkül " +"maradt. Kérjük Önöket a fizetés 8 napon belüli pontos teljesítésére.\n" +"\n" +"Ha a levél elküldése előtt a fizetés már megtörtént akkor kérjük tekintsék " +"ezt tárgytalannak. Kérjük vegyék fel a kapcsolatot könyvelési " +"csoportunkkal. \n" +"\n" +"Üdvözlettel,\n" #. module: account_followup #: field:account_followup.stat,date_move_last:0 @@ -870,12 +1074,12 @@ msgstr "Időszak" #: 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 a partnernek nincs hitele azért a művelet törölve lett" #. module: account_followup #: model:ir.actions.report.xml,name:account_followup.account_followup_followup_report msgid "Follow-up Report" -msgstr "" +msgstr "Fizetési-emlékeztető jelentés" #. module: account_followup #: view:res.partner:0 @@ -883,6 +1087,8 @@ msgid "" ", the latest payment follow-up\n" " was:" msgstr "" +", a legutóbbi fizetési-emlékeztető kifizetés\n" +" ez volt:" #. module: account_followup #: view:account_followup.print:0 @@ -892,7 +1098,7 @@ msgstr "Mégse" #. module: account_followup #: view:account_followup.sending.results:0 msgid "Close" -msgstr "" +msgstr "Lezár" #. module: account_followup #: view:account_followup.stat:0 @@ -908,23 +1114,23 @@ msgstr "Maximális fizetési emlékeztető szint" #: code:addons/account_followup/wizard/account_followup_print.py:171 #, python-format msgid " had unknown email address(es)" -msgstr "" +msgstr " ismeretlen e-mail címe(i) van(nak)" #. module: account_followup #: view:res.partner:0 msgid "Responsible" -msgstr "" +msgstr "Felelős" #. module: account_followup #: model:ir.ui.menu,name:account_followup.menu_finance_followup #: view:res.partner:0 msgid "Payment Follow-up" -msgstr "" +msgstr "Fizetési-emlékeztető kifizetés" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": Current Date" -msgstr "" +msgstr ": Jelenlegi dátum" #. module: account_followup #: view:account_followup.print:0 @@ -933,16 +1139,20 @@ msgid "" " set the manual actions per customer, according to " "the follow-up levels defined." msgstr "" +"Ez a művelet fizetési-emlékeztető e-mail küldéseket indít, levelet nyomtat " +"és\n" +" beállítja a vevőnkénti kézi műveletet, a fizetési-" +"emlékeztető szintek beállításának megfelelően." #. module: account_followup #: field:account_followup.followup.line,name:0 msgid "Follow-Up Action" -msgstr "" +msgstr "Fizetési-emlékeztető művelet" #. module: account_followup #: view:account_followup.stat:0 msgid "Including journal entries marked as a litigation" -msgstr "" +msgstr "Beleértve a peres megjelölésű jelentés bejegyzéseket" #. module: account_followup #: report:account_followup.followup.print:0 @@ -955,7 +1165,7 @@ msgstr "Megjegyzés" #. module: account_followup #: view:account_followup.sending.results:0 msgid "Summary of actions" -msgstr "" +msgstr "Műveletek összegzése" #. module: account_followup #: report:account_followup.followup.print:0 @@ -965,7 +1175,7 @@ msgstr "Hiv." #. module: account_followup #: view:account_followup.followup.line:0 msgid "After" -msgstr "" +msgstr "Utána" #. module: account_followup #: view:account_followup.stat:0 @@ -975,7 +1185,7 @@ msgstr "Tárgyév" #. module: account_followup #: field:res.partner,latest_followup_level_id_without_lit:0 msgid "Latest Follow-up Level without litigation" -msgstr "" +msgstr "Legitóbbi per nélküli fizetési-emlékeztetőt szint" #. module: account_followup #: model:ir.actions.act_window,help:account_followup.action_account_manual_reconcile_receivable @@ -985,6 +1195,10 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Nem talált jelentés tartalmat.\n" +"

\n" +" " #. module: account_followup #: view:account.move.line:0 @@ -994,7 +1208,7 @@ msgstr "Partner tételek" #. module: account_followup #: view:account_followup.stat:0 msgid "Follow-up lines" -msgstr "" +msgstr "Fizetési emlékeztető sorok" #. module: account_followup #: model:account_followup.followup.line,description:account_followup.demo_followup_line3 @@ -1015,6 +1229,21 @@ msgid "" "\n" "Best Regards,\n" msgstr "" +"\n" +"Tisztelt %(partner_name)s,\n" +"\n" +" A többszörös fizetési-emlékeztető ellenére, még mindig nem történt meg a " +"számla kiegyenlítése.\n" +"Ha nem történik meg a kiegyenlítés 8 napon belül, törvényes úton vagyunk " +"kénytelenek az adósságot behajtani, minden további felszólítás nélkül.\n" +"\n" +"Úgy gondoljuk, hogy ez nem lesz szükséges lépés a lenti részletekkel " +"kapcsolatban.\n" +"\n" +"Az üggyel kapcsolatban felmerült kérdésekben, kérjük vegyék fel a " +"kapcsolatot a könyvelési csoportunkkal.\n" +"\n" +"Üdvözlettel,\n" #. module: account_followup #: help:account_followup.print,partner_lang:0 @@ -1036,6 +1265,13 @@ msgid "" "installed\n" " using to top right icon." msgstr "" +"Írja ide ennek a levélnek a levél bemutatását,\n" +" a fizetési-emlékeztető szint szerint. " +"Használhatóak a\n" +" következő kulcsszavak a szövegben. Meg kell " +"lennie\n" +" az összes jobb felső ikon szerinti nyelv " +"fordításban is!" #. module: account_followup #: view:account_followup.stat:0 @@ -1051,7 +1287,7 @@ msgstr "Név" #. module: account_followup #: field:res.partner,latest_followup_level_id:0 msgid "Latest Follow-up Level" -msgstr "" +msgstr "Legitóbbi fizetési-emlékeztető szint" #. module: account_followup #: field:account_followup.stat,date_move:0 @@ -1062,23 +1298,23 @@ msgstr "Első tétel" #. module: account_followup #: model:ir.model,name:account_followup.model_account_followup_stat_by_partner msgid "Follow-up Statistics by Partner" -msgstr "" +msgstr "Fizetési-emlékeztető partnerenkénti statisztika" #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:172 #, python-format msgid " letter(s) in report" -msgstr "" +msgstr " level(ek) a jelentésben" #. module: account_followup #: view:res.partner:0 msgid "Partners with Overdue Credits" -msgstr "" +msgstr "Lejárt fizetési hitelekkel rendelkező partnerek" #. module: account_followup #: view:res.partner:0 msgid "Customer Followup" -msgstr "" +msgstr "Vevői fizetési-emlékeztető" #. module: account_followup #: model:ir.actions.act_window,help:account_followup.action_account_followup_definition_form @@ -1094,22 +1330,33 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Kattintson a fizetési-emlékeztető szint és műveletének " +"létrehozásához.\n" +"

\n" +" Minden lépéshez, határozza meg a műveletet amit a lejárat " +"után annyi nappal el fog végezni.\n" +" Lehetséges nyomtatás és e-mail sablon használatával egy " +"üzenet eljuttatása a vevő\n" +" részére.\n" +"

\n" +" " #. module: account_followup #: code:addons/account_followup/wizard/account_followup_print.py:166 #, python-format msgid "Follow-up letter of " -msgstr "" +msgstr "Fizetési-emlékeztető levél ide " #. module: account_followup #: view:res.partner:0 msgid "The" -msgstr "" +msgstr "A" #. module: account_followup #: view:account_followup.print:0 msgid "Send follow-ups" -msgstr "" +msgstr "Fizetési-emlékeztető küldése" #. module: account_followup #: view:account.move.line:0 @@ -1124,7 +1371,7 @@ msgstr "Sorszám" #. module: account_followup #: view:res.partner:0 msgid "Follow-ups To Do" -msgstr "" +msgstr "Még végrehejtandó fizetési-emlékeztető" #. module: account_followup #: report:account_followup.followup.print:0 @@ -1143,26 +1390,30 @@ msgid "" "the reminder. Could be negative if you want to send a polite alert " "beforehand." msgstr "" +"A számla lejárati dátuma utáni napok száma, amíg várakozik a felszólítás " +"küldése előtt. Negatív is lehet, ha egy udvarias levelet szeretne küldeni a " +"lejárati dátumra vonatkozólag." #. module: account_followup #: help:res.partner,latest_followup_date:0 msgid "Latest date that the follow-up level of the partner was changed" msgstr "" +"Legutóbbi dátum amikor a vevőnek a fizetési-emlékeztető szintje változott" #. module: account_followup #: field:account_followup.print,test_print:0 msgid "Test Print" -msgstr "" +msgstr "Nyomtatás teszt" #. module: account_followup #: view:account_followup.followup.line:0 msgid ": User Name" -msgstr "" +msgstr ": Felhasználó neve" #. module: account_followup #: view:res.partner:0 msgid "Accounting" -msgstr "" +msgstr "Könyvelés" #. module: account_followup #: field:account_followup.stat,blocked:0 @@ -1172,7 +1423,7 @@ msgstr "Zárolt" #. module: account_followup #: field:res.partner,payment_note:0 msgid "Customer Payment Promise" -msgstr "" +msgstr "Vevő fizetésre vonatkozó igérete" #, python-format #~ msgid "Follwoup Summary" 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/report/account_followup_print.py b/addons/account_followup/report/account_followup_print.py index 16d88d69572..eecba81acb9 100644 --- a/addons/account_followup/report/account_followup_print.py +++ b/addons/account_followup/report/account_followup_print.py @@ -22,7 +22,6 @@ import time from collections import defaultdict -from openerp import pooler from openerp.report import report_sxw class report_rappel(report_sxw.rml_parse): @@ -38,9 +37,8 @@ class report_rappel(report_sxw.rml_parse): }) def _ids_to_objects(self, ids): - pool = pooler.get_pool(self.cr.dbname) all_lines = [] - for line in pool.get('account_followup.stat.by.partner').browse(self.cr, self.uid, ids): + for line in self.pool['account_followup.stat.by.partner'].browse(self.cr, self.uid, ids): if line not in all_lines: all_lines.append(line) return all_lines @@ -49,8 +47,7 @@ class report_rappel(report_sxw.rml_parse): return self._lines_get_with_partner(stat_by_partner_line.partner_id, stat_by_partner_line.company_id.id) def _lines_get_with_partner(self, partner, company_id): - pool = pooler.get_pool(self.cr.dbname) - moveline_obj = pool.get('account.move.line') + moveline_obj = self.pool['account.move.line'] moveline_ids = moveline_obj.search(self.cr, self.uid, [ ('partner_id', '=', partner.id), ('account_id.type', '=', 'receivable'), @@ -80,7 +77,7 @@ class report_rappel(report_sxw.rml_parse): if context is None: context = {} context.update({'lang': stat_line.partner_id.lang}) - fp_obj = pooler.get_pool(self.cr.dbname).get('account_followup.followup') + fp_obj = self.pool['account_followup.followup'] fp_line = fp_obj.browse(self.cr, self.uid, followup_id, context=context).followup_line if not fp_line: raise osv.except_osv(_('Error!'),_("The followup plan defined for the current company does not have any followup action.")) @@ -94,10 +91,10 @@ class report_rappel(report_sxw.rml_parse): li_delay.sort(reverse=True) a = {} #look into the lines of the partner that already have a followup level, and take the description of the higher level for which it is available - partner_line_ids = pooler.get_pool(self.cr.dbname).get('account.move.line').search(self.cr, self.uid, [('partner_id','=',stat_line.partner_id.id),('reconcile_id','=',False),('company_id','=',stat_line.company_id.id),('blocked','=',False),('state','!=','draft'),('debit','!=',False),('account_id.type','=','receivable'),('followup_line_id','!=',False)]) + partner_line_ids = self.pool['account.move.line'].search(self.cr, self.uid, [('partner_id','=',stat_line.partner_id.id),('reconcile_id','=',False),('company_id','=',stat_line.company_id.id),('blocked','=',False),('state','!=','draft'),('debit','!=',False),('account_id.type','=','receivable'),('followup_line_id','!=',False)]) partner_max_delay = 0 partner_max_text = '' - for i in pooler.get_pool(self.cr.dbname).get('account.move.line').browse(self.cr, self.uid, partner_line_ids, context=context): + for i in self.pool['account.move.line'].browse(self.cr, self.uid, partner_line_ids, context=context): if i.followup_line_id.delay > partner_max_delay and i.followup_line_id.description: partner_max_delay = i.followup_line_id.delay partner_max_text = i.followup_line_id.description @@ -107,7 +104,7 @@ class report_rappel(report_sxw.rml_parse): 'partner_name': stat_line.partner_id.name, 'date': time.strftime('%Y-%m-%d'), 'company_name': stat_line.company_id.name, - 'user_signature': pooler.get_pool(self.cr.dbname).get('res.users').browse(self.cr, self.uid, self.uid, context).signature or '', + 'user_signature': self.pool['res.users'].browse(self.cr, self.uid, self.uid, context).signature or '', } return text 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/tests/test_account_followup.py b/addons/account_followup/tests/test_account_followup.py index a421931665a..9e70430c518 100644 --- a/addons/account_followup/tests/test_account_followup.py +++ b/addons/account_followup/tests/test_account_followup.py @@ -5,8 +5,6 @@ import datetime from openerp import tools from openerp.tests.common import TransactionCase -from openerp import netsvc - class TestAccountFollowup(TransactionCase): def setUp(self): """ setUp ***""" 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/i18n/hu.po b/addons/account_payment/i18n/hu.po index d45c8e42485..9bfe4215880 100644 --- a/addons/account_payment/i18n/hu.po +++ b/addons/account_payment/i18n/hu.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-01-30 18:36+0000\n" -"Last-Translator: Krisztian Eyssen \n" +"PO-Revision-Date: 2013-03-26 14:28+0000\n" +"Last-Translator: krnkris \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:26+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-03-27 04:36+0000\n" +"X-Generator: Launchpad (build 16540)\n" #. module: account_payment #: model:ir.actions.act_window,help:account_payment.action_payment_order_tree @@ -28,6 +28,14 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Kattintson átutalási megbízás létrehozásához.\n" +"

\n" +" Az átutalási, fizetési megbízás egy fizetési igény " +"kiegyenlítése a beszállító felé vagy \n" +" egy vevő jóváíró számlájához a vállalkozásánál.\n" +"

\n" +" " #. module: account_payment #: field:payment.line,currency:0 @@ -81,7 +89,7 @@ msgstr "Vállalat" #. module: account_payment #: model:res.groups,name:account_payment.group_account_payment msgid "Accounting / Payments" -msgstr "" +msgstr "Könyvelés / Átutalások, fizetések" #. module: account_payment #: selection:payment.line,state:0 @@ -123,13 +131,15 @@ msgid "" "You cannot cancel an invoice which has already been imported in a payment " "order. Remove it from the following payment order : %s." msgstr "" +"Nem tud visszavonni olyan számlát ami már be lett töltve, importálva az " +"utalásba. Vegye le a következő utalási megbízásból : %s." #. module: account_payment #: code:addons/account_payment/account_invoice.py:43 #: code:addons/account_payment/account_move_line.py:110 #, python-format msgid "Error!" -msgstr "" +msgstr "Hiba!" #. module: account_payment #: report:payment.order:0 @@ -194,6 +204,10 @@ msgid "" " Once the bank is confirmed the status is set to 'Confirmed'.\n" " Then the order is paid the status is 'Done'." msgstr "" +"Ha az utalás, megbízás be lett rögzítve akkor annak állapota 'Tervezet'.\n" +" Ha a bank jóváhagyta annak rögzítési állapotát akkor az állapota " +"'Jóváhagyott'.\n" +" Ha az utalás, fizetés végrehajtva akkor annak az állapota 'Elvégezve'." #. module: account_payment #: view:payment.order:0 @@ -219,7 +233,7 @@ msgstr "Struktúrált" #. module: account_payment #: view:account.bank.statement:0 msgid "Import Payment Lines" -msgstr "" +msgstr "Utalási sorok betöltése, importálása" #. module: account_payment #: view:payment.line:0 @@ -261,7 +275,7 @@ msgstr "" #. module: account_payment #: field:payment.order,date_created:0 msgid "Creation Date" -msgstr "" +msgstr "Létrehozás dátuma" #. module: account_payment #: help:payment.mode,journal:0 @@ -271,7 +285,7 @@ msgstr "A fizetési mód bank- vagy pénztárnaplója" #. module: account_payment #: selection:payment.order,date_prefered:0 msgid "Fixed date" -msgstr "Rögzített" +msgstr "Rögzített dátum" #. module: account_payment #: field:payment.line,info_partner:0 @@ -369,7 +383,7 @@ msgstr "Átutalás hozzáadása a kivonathoz" #: code:addons/account_payment/account_move_line.py:110 #, python-format msgid "There is no partner defined on the entry line." -msgstr "" +msgstr "A beviteli soron nem lett partner meghatározva" #. module: account_payment #: help:payment.mode,name:0 @@ -401,7 +415,7 @@ msgstr "Tervezet" #: view:payment.order:0 #: field:payment.order,state:0 msgid "Status" -msgstr "" +msgstr "Állapot" #. module: account_payment #: help:payment.line,communication2:0 @@ -432,7 +446,7 @@ msgstr "Átutalás sorok" #. module: account_payment #: model:ir.model,name:account_payment.model_account_move_line msgid "Journal Items" -msgstr "Könyvelési tételsorok" +msgstr "Könyvelési napló tételsorok" #. module: account_payment #: help:payment.line,move_line_id:0 @@ -449,7 +463,7 @@ msgstr "Keresés" #. module: account_payment #: field:payment.order,user_id:0 msgid "Responsible" -msgstr "" +msgstr "Felelős" #. module: account_payment #: field:payment.line,date:0 @@ -464,7 +478,7 @@ msgstr "Összesen:" #. module: account_payment #: field:payment.order,date_done:0 msgid "Execution Date" -msgstr "" +msgstr "Kivitelezés dátuma" #. module: account_payment #: view:account.payment.populate.statement:0 @@ -538,12 +552,12 @@ msgstr "Közlemény" #: view:account.payment.populate.statement:0 #: view:payment.order.create:0 msgid "Cancel" -msgstr "Mégse" +msgstr "Visszavonás" #. module: account_payment #: field:payment.line,bank_id:0 msgid "Destination Bank Account" -msgstr "" +msgstr "Jogosult bankszámla száma" #. module: account_payment #: view:payment.line:0 @@ -581,7 +595,7 @@ msgstr "Közlemény folytatása" #. module: account_payment #: field:payment.order,date_scheduled:0 msgid "Scheduled Date" -msgstr "" +msgstr "Tervezett dátum" #. module: account_payment #: view:account.payment.make.payment:0 @@ -676,14 +690,14 @@ msgstr "Átutalás végrehajtása" #. module: account_payment #: field:payment.order,date_prefered:0 msgid "Preferred Date" -msgstr "" +msgstr "Előnyben részesített dátum" #. module: account_payment #: view:account.payment.make.payment:0 #: view:account.payment.populate.statement:0 #: view:payment.order.create:0 msgid "or" -msgstr "" +msgstr "vagy" #. module: account_payment #: help:payment.mode,bank_id:0 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/report/payment_order.py b/addons/account_payment/report/payment_order.py index 112476dd080..a851a54ecbb 100644 --- a/addons/account_payment/report/payment_order.py +++ b/addons/account_payment/report/payment_order.py @@ -21,7 +21,6 @@ import time -from openerp import pooler from openerp.report import report_sxw class payment_order(report_sxw.rml_parse): @@ -38,8 +37,7 @@ class payment_order(report_sxw.rml_parse): def _get_invoice_name(self, invoice_id): if invoice_id: - pool = pooler.get_pool(self.cr.dbname) - value_name = pool.get('account.invoice').name_get(self.cr, self.uid, [invoice_id]) + value_name = self.pool['account.invoice'].name_get(self.cr, self.uid, [invoice_id]) if value_name: return value_name[0][1] return False @@ -67,8 +65,7 @@ class payment_order(report_sxw.rml_parse): def _get_account_name(self,bank_id): if bank_id: - pool = pooler.get_pool(self.cr.dbname) - value_name = pool.get('res.partner.bank').name_get(self.cr, self.uid, [bank_id]) + value_name = self.pool['res.partner.bank'].name_get(self.cr, self.uid, [bank_id]) if value_name: return value_name[0][1] return False diff --git a/addons/account_payment/test/account_payment_report.yml b/addons/account_payment/test/account_payment_report.yml index 055e2804ee3..3def62de429 100644 --- a/addons/account_payment/test/account_payment_report.yml +++ b/addons/account_payment/test/account_payment_report.yml @@ -3,7 +3,8 @@ - !python {model: payment.order}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.payment.order').create(cr, uid, [ref('payment_order_1')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('payment_order_1')], 'payment.order', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account_payment-payment_order_report.'+format), 'wb+').write(data) diff --git a/addons/account_payment/wizard/account_payment_order.py b/addons/account_payment/wizard/account_payment_order.py index 4bd969726fe..08d36c45eff 100644 --- a/addons/account_payment/wizard/account_payment_order.py +++ b/addons/account_payment/wizard/account_payment_order.py @@ -118,6 +118,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_sequence/i18n/cs.po b/addons/account_sequence/i18n/cs.po new file mode 100644 index 00000000000..480e6f5ff6b --- /dev/null +++ b/addons/account_sequence/i18n/cs.po @@ -0,0 +1,150 @@ +# Czech 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-03-31 16:43+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: account_sequence +#: view:account.sequence.installer:0 +#: model:ir.actions.act_window,name:account_sequence.action_account_seq_installer +msgid "Account Sequence Application Configuration" +msgstr "" + +#. module: account_sequence +#: help:account.move,internal_sequence_number:0 +#: help:account.move.line,internal_sequence_number:0 +msgid "Internal Sequence Number" +msgstr "" + +#. module: account_sequence +#: help:account.sequence.installer,number_next:0 +msgid "Next number of this sequence" +msgstr "" + +#. module: account_sequence +#: field:account.sequence.installer,number_next:0 +msgid "Next Number" +msgstr "" + +#. module: account_sequence +#: field:account.sequence.installer,number_increment:0 +msgid "Increment Number" +msgstr "" + +#. module: account_sequence +#: help:account.sequence.installer,number_increment:0 +msgid "The next number of the sequence will be incremented by this number" +msgstr "" + +#. module: account_sequence +#: view:account.sequence.installer:0 +msgid "Configure Your Account Sequence Application" +msgstr "" + +#. module: account_sequence +#: view:account.sequence.installer:0 +msgid "Configure" +msgstr "" + +#. module: account_sequence +#: help:account.sequence.installer,suffix:0 +msgid "Suffix value of the record for the sequence" +msgstr "" + +#. module: account_sequence +#: field:account.sequence.installer,company_id:0 +msgid "Company" +msgstr "" + +#. module: account_sequence +#: field:account.sequence.installer,padding:0 +msgid "Number padding" +msgstr "" + +#. module: account_sequence +#: model:ir.model,name:account_sequence.model_account_move_line +msgid "Journal Items" +msgstr "" + +#. module: account_sequence +#: field:account.move,internal_sequence_number:0 +#: field:account.move.line,internal_sequence_number:0 +msgid "Internal Number" +msgstr "" + +#. module: account_sequence +#: help:account.sequence.installer,padding:0 +msgid "" +"OpenERP will automatically adds some '0' on the left of the 'Next Number' to " +"get the required padding size." +msgstr "" + +#. module: account_sequence +#: field:account.sequence.installer,name:0 +msgid "Name" +msgstr "" + +#. module: account_sequence +#: field:account.journal,internal_sequence_id:0 +msgid "Internal Sequence" +msgstr "" + +#. module: account_sequence +#: help:account.sequence.installer,prefix:0 +msgid "Prefix value of the record for the sequence" +msgstr "" + +#. module: account_sequence +#: model:ir.model,name:account_sequence.model_account_move +msgid "Account Entry" +msgstr "" + +#. module: account_sequence +#: field:account.sequence.installer,suffix:0 +msgid "Suffix" +msgstr "" + +#. module: account_sequence +#: view:account.sequence.installer:0 +msgid "title" +msgstr "" + +#. module: account_sequence +#: field:account.sequence.installer,prefix:0 +msgid "Prefix" +msgstr "" + +#. module: account_sequence +#: help:account.journal,internal_sequence_id:0 +msgid "" +"This sequence will be used to maintain the internal number for the journal " +"entries related to this journal." +msgstr "" + +#. module: account_sequence +#: model:ir.model,name:account_sequence.model_account_sequence_installer +msgid "account.sequence.installer" +msgstr "" + +#. module: account_sequence +#: model:ir.model,name:account_sequence.model_account_journal +msgid "Journal" +msgstr "" + +#. module: account_sequence +#: view:account.sequence.installer:0 +msgid "You can enhance the Account Sequence Application by installing ." +msgstr "" diff --git a/addons/account_test/account_test.py b/addons/account_test/account_test.py index da7bb8e308d..98e27380837 100644 --- a/addons/account_test/account_test.py +++ b/addons/account_test/account_test.py @@ -56,5 +56,4 @@ class accounting_assert_test(osv.osv): 'sequence': 10, } -accounting_assert_test() diff --git a/addons/account_test/i18n/cs.po b/addons/account_test/i18n/cs.po new file mode 100644 index 00000000000..82c85a734dd --- /dev/null +++ b/addons/account_test/i18n/cs.po @@ -0,0 +1,241 @@ +# Czech 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-03-31 16:43+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\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 "" + +#. 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 "" + +#. 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 "" + +#. 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 "" + +#. 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 "" + +#. 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_test/i18n/hu.po b/addons/account_test/i18n/hu.po new file mode 100644 index 00000000000..b2d8eb81feb --- /dev/null +++ b/addons/account_test/i18n/hu.po @@ -0,0 +1,241 @@ +# Hungarian 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-02 12:44+0000\n" +"Last-Translator: krnkris \n" +"Language-Team: Hungarian \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-03 05:26+0000\n" +"X-Generator: Launchpad (build 16546)\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 "" + +#. 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 "Teszt név" + +#. 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 "" + +#. 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 "Tesztek" + +#. 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 "" + +#. 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 "" + +#. 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 "" + +#. 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_test/i18n/zh_CN.po b/addons/account_test/i18n/zh_CN.po new file mode 100644 index 00000000000..081320aa24a --- /dev/null +++ b/addons/account_test/i18n/zh_CN.po @@ -0,0 +1,241 @@ +# Chinese (Simplified) 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-03-21 19:22+0000\n" +"Last-Translator: Liuming \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-22 04:57+0000\n" +"X-Generator: Launchpad (build 16532)\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 "" + +#. 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 "" + +#. 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 "" + +#. 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 "" + +#. 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/account_voucher.py b/addons/account_voucher/account_voucher.py index c6f754ed18f..b176c3b8fd9 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -40,7 +40,6 @@ class res_company(osv.osv): domain="[('type', '=', 'other')]",), } -res_company() class account_config_settings(osv.osv_memory): _inherit = 'account.config.settings' @@ -85,7 +84,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): @@ -1488,7 +1487,6 @@ class account_voucher_line(osv.osv): 'type':ttype }) return values -account_voucher_line() class account_bank_statement(osv.osv): _inherit = 'account.bank.statement' @@ -1540,7 +1538,6 @@ class account_bank_statement(osv.osv): 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 +1591,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/i18n/hu.po b/addons/account_voucher/i18n/hu.po index 12f12ce6eb9..1a50a813042 100644 --- a/addons/account_voucher/i18n/hu.po +++ b/addons/account_voucher/i18n/hu.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-12-27 22:53+0000\n" -"Last-Translator: Balint (eSolve) \n" +"PO-Revision-Date: 2013-04-04 11:34+0000\n" +"Last-Translator: krnkris \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-04-05 05:37+0000\n" +"X-Generator: Launchpad (build 16550)\n" #. module: account_voucher #: field:account.bank.statement.line,voucher_id:0 msgid "Reconciliation" -msgstr "" +msgstr "Párosítás" #. 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 @@ -51,7 +51,7 @@ msgstr "Nyitott vevő tételek" #: view:account.voucher:0 #: view:sale.receipt.report:0 msgid "Group By..." -msgstr "Csoportosítás" +msgstr "Csoportosítás ezzel..." #. module: account_voucher #: help:account.voucher,writeoff_amount:0 @@ -59,11 +59,13 @@ msgid "" "Computed as the difference between the amount stated in the voucher and the " "sum of allocation on the voucher lines." msgstr "" +"Különbség ami a nyugtán lévő végösszeg és a nyugta soraiban lévő rész " +"összegek különbsége." #. module: account_voucher #: view:account.voucher:0 msgid "(Update)" -msgstr "" +msgstr "(Frissítés)" #. module: account_voucher #: view:account.voucher:0 @@ -90,7 +92,7 @@ msgstr "Március" #. module: account_voucher #: field:account.voucher,message_unread:0 msgid "Unread Messages" -msgstr "" +msgstr "Olvasatlan üzenetek" #. module: account_voucher #: view:account.voucher:0 @@ -100,7 +102,7 @@ msgstr "Számla kifizetése" #. module: account_voucher #: view:account.voucher:0 msgid "Are you sure you want to cancel this receipt?" -msgstr "" +msgstr "Biztos, hogy vissza akarja vonni ezt a bevételi bizonylatot?" #. module: account_voucher #: view:account.voucher:0 @@ -115,13 +117,13 @@ msgstr "Tranzakció hivatkozási száma" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Group by year of Invoice Date" -msgstr "" +msgstr "Számla kibocsátási éve szerinti csoportosítás" #. module: account_voucher #: view:sale.receipt.report:0 #: field:sale.receipt.report,user_id:0 msgid "Salesperson" -msgstr "" +msgstr "Értékesítő" #. module: account_voucher #: view:account.voucher:0 @@ -135,6 +137,8 @@ msgid "" "You can not change the journal as you already reconciled some statement " "lines!" msgstr "" +"Nem tudja a naplót megváltoztatni mivel a kivonatok egyes sorait már " +"párosította!" #. module: account_voucher #: view:account.voucher:0 @@ -145,7 +149,7 @@ msgstr "Jóváhagyás" #: 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 "Beszállítói átutalások, fizetések" #. module: account_voucher #: model:ir.actions.act_window,help:account_voucher.action_purchase_receipt @@ -158,6 +162,15 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Kattintson vásárlási bevételi bizonylat rögzítéséhez. \n" +"

\n" +" Ha a vásárlási bevételi bizonylat igazolva lett, rögzítheti " +"a \n" +" vásárlási bevételi bizonylathoz kapcsolódó beszállítói " +"kifizetést.\n" +"

\n" +" " #. module: account_voucher #: view:account.voucher:0 @@ -167,7 +180,7 @@ msgstr "Nyugták keresése" #. module: account_voucher #: field:account.voucher,writeoff_acc_id:0 msgid "Counterpart Account" -msgstr "" +msgstr "Ellenszámla" #. module: account_voucher #: field:account.voucher,account_id:0 @@ -179,7 +192,7 @@ msgstr "Főkönyvi számla" #. module: account_voucher #: field:account.voucher,line_dr_ids:0 msgid "Debits" -msgstr "Tartozik" +msgstr "Tartozások" #. module: account_voucher #: view:account.statement.from.invoice.lines:0 @@ -189,7 +202,7 @@ msgstr "Rendben" #. module: account_voucher #: field:account.voucher.line,reconcile:0 msgid "Full Reconcile" -msgstr "" +msgstr "Teljes párosítás" #. module: account_voucher #: field:account.voucher,date_due:0 @@ -207,13 +220,13 @@ msgstr "Megjegyzések" #. module: account_voucher #: field:account.voucher,message_ids:0 msgid "Messages" -msgstr "" +msgstr "Üzenetek" #. module: account_voucher #: 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 "Vásárlások bevételi bizonylatai" #. module: account_voucher #: field:account.voucher.line,move_line_id:0 @@ -225,7 +238,7 @@ msgstr "Könyvelési tételsor" #: code:addons/account_voucher/account_voucher.py:981 #, python-format msgid "Error!" -msgstr "" +msgstr "Hiba!" #. module: account_voucher #: field:account.voucher.line,amount:0 @@ -269,11 +282,18 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Kattintson értékesítési bevételi bizonylat létrehozásához.\n" +"

\n" +" Ha az értékesítési bizonylat igazolva lett, rögzítheti az \n" +" értékesítéshez tartozó vevői befizetést.\n" +"

\n" +" " #. module: account_voucher #: help:account.voucher,message_unread:0 msgid "If checked new messages require your attention." -msgstr "" +msgstr "Ha be van jelölve, akkor figyelje az új üzeneteket." #. module: account_voucher #: model:ir.model,name:account_voucher.model_account_bank_statement_line @@ -296,17 +316,17 @@ msgstr "ÁFA" #: code:addons/account_voucher/account_voucher.py:879 #, python-format msgid "Invalid Action!" -msgstr "" +msgstr "Érvénytelen lépés!" #. module: account_voucher #: field:account.voucher,comment:0 msgid "Counterpart Comment" -msgstr "" +msgstr "Ellenoldali meglyegyzés" #. module: account_voucher #: field:account.voucher.line,account_analytic_id:0 msgid "Analytic Account" -msgstr "Gyűjtőkód" +msgstr "Gyűjtő/elemző könyvelés" #. module: account_voucher #: help:account.voucher,message_summary:0 @@ -314,11 +334,13 @@ msgid "" "Holds the Chatter summary (number of messages, ...). This summary is " "directly in html format in order to be inserted in kanban views." msgstr "" +"A chettelés összegzést megállítja (üzenetek száma,...). Ez az összegzés " +"direkt HTML formátumú ahhoz hogy beilleszthető legyen a kanban nézetekbe." #. module: account_voucher #: view:account.voucher:0 msgid "Total Allocation" -msgstr "" +msgstr "Összes kiosztás" #. module: account_voucher #: view:account.voucher:0 @@ -328,7 +350,7 @@ msgstr "Fizetési információ" #. module: account_voucher #: view:account.voucher:0 msgid "(update)" -msgstr "" +msgstr "(frissítés)" #. module: account_voucher #: view:account.voucher:0 @@ -347,20 +369,20 @@ msgstr "Számlák importálása" #: code:addons/account_voucher/account_voucher.py:1112 #, python-format msgid "Wrong voucher line" -msgstr "" +msgstr "Nem megfelelő nyugta sor" #. module: account_voucher #: selection:account.voucher,pay_now:0 #: selection:sale.receipt.report,pay_now:0 msgid "Pay Later or Group Funds" -msgstr "Későbbi fizetés" +msgstr "Fizessen később vagy csoportosítsa a pénzeket" #. module: account_voucher #: view:account.voucher:0 #: selection:account.voucher,type:0 #: selection:sale.receipt.report,type:0 msgid "Receipt" -msgstr "Befizetés" +msgstr "Bevételi bizonylat" #. module: account_voucher #: code:addons/account_voucher/account_voucher.py:1018 @@ -370,6 +392,9 @@ msgid "" "settings, to manage automatically the booking of accounting entries related " "to differences between exchange rates." msgstr "" +"Be kell állítani a 'Átváltási arány nyereség számlája' a könyvelés " +"beállításainál, ahhoz, hogy kezelni tudja az automatikus könyvelését azoknak " +"a számla tételeknek, melyek az átváltási arányok különbségéből adódhatnak." #. module: account_voucher #: view:account.voucher:0 @@ -397,7 +422,7 @@ msgstr "Szállítói nyugta" #. module: account_voucher #: field:account.voucher,message_follower_ids:0 msgid "Followers" -msgstr "" +msgstr "Követők" #. module: account_voucher #: selection:account.voucher.line,type:0 @@ -408,13 +433,13 @@ msgstr "Tartozik" #: code:addons/account_voucher/account_voucher.py:1547 #, python-format msgid "Unable to change journal !" -msgstr "" +msgstr "Naplót nem lehet megváltoztatni !" #. module: account_voucher #: view:sale.receipt.report:0 #: field:sale.receipt.report,nbr:0 msgid "# of Voucher Lines" -msgstr "Nyugtasorok száma" +msgstr "# nyugta sor száma" #. module: account_voucher #: view:sale.receipt.report:0 @@ -425,7 +450,7 @@ msgstr "Típus" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Pro-forma Vouchers" -msgstr "" +msgstr "Pro-forma nyugták" #. module: account_voucher #: view:account.voucher:0 @@ -444,6 +469,13 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Kattintson új beszállítói fizetés létrehozásához.\n" +"

\n" +" OpenERP segít a kifizetéseinek, valamint a beszállítók " +"részére még fizetendő mérleg könnyű nyomon követéséhez.\n" +"

\n" +" " #. module: account_voucher #: view:account.voucher:0 @@ -458,17 +490,17 @@ msgstr "Nyugta tételek" #. module: account_voucher #: field:account.voucher,name:0 msgid "Memo" -msgstr "Megnevezés" +msgstr "Emlékeztető" #. module: account_voucher #: view:account.voucher:0 msgid "Are you sure to unreconcile and cancel this record ?" -msgstr "" +msgstr "Biztosan visszavonja a bejegyzés párosítását?" #. module: account_voucher #: field:account.voucher,is_multi_currency:0 msgid "Multi Currency Voucher" -msgstr "" +msgstr "Több pénznemű nyugták" #. module: account_voucher #: view:account.voucher:0 @@ -492,17 +524,25 @@ msgid "" "\n" "* The 'Cancelled' status is used when user cancel voucher." msgstr "" +" * A 'Tervezet' állapotot használja amint egy felhasználó létrehoz egy új és " +"még le nem igazolt nyugtát. \n" +"* 'Pro-forma' lesz, ha a nyugta Pro-forma állapotú, a nyugtának még nincs " +"nyugta száma. \n" +"* 'Elküldött' állapotú, ha egy felhasználó létrehozta a nyugtát, egy nyugta " +"számot generált hozzá, és a könyvelésben egy nyugta bevitel létre lett hozva " +" \n" +"* A 'Visszavonva' állapot lesz, ha egy felhasználó visszavonta a nyugtát." #. module: account_voucher #: field:account.voucher,writeoff_amount:0 msgid "Difference Amount" -msgstr "" +msgstr "Különbség számla" #. module: account_voucher #: view:sale.receipt.report:0 #: field:sale.receipt.report,due_delay:0 msgid "Avg. Due Delay" -msgstr "Álagos fizetési határidő" +msgstr "Álagos fizetési késedelem" #. module: account_voucher #: code:addons/account_voucher/invoice.py:34 @@ -524,7 +564,7 @@ msgstr "ÁFA összege" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Validated Vouchers" -msgstr "" +msgstr "Jóváhagyott nyugták" #. module: account_voucher #: model:ir.actions.act_window,help:account_voucher.action_vendor_receipt @@ -541,12 +581,24 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Kattintson új kifizetés rögzítéséhez. \n" +"

\n" +" Vigye be a vásárlót és a fizetési módot és utána, vagy " +"hozzon\n" +" létre kézzel egy fizetési rekordot, vagy az OpenERP fel fog " +"ajánlani\n" +" automatikusan a fizetéshez tartozó összeegyeztetést a\n" +" nyitott számlákkal vagy értékesítési bevételi " +"bizonylatokkal.\n" +"

\n" +" " #. module: account_voucher #: field:account.config.settings,expense_currency_exchange_account_id:0 #: field:res.company,expense_currency_exchange_account_id:0 msgid "Loss Exchange Rate Account" -msgstr "" +msgstr "Árfolyamveszteség számla" #. module: account_voucher #: view:account.voucher:0 @@ -570,7 +622,7 @@ msgstr "Ellenőrizendő" #: code:addons/account_voucher/account_voucher.py:1194 #, python-format msgid "change" -msgstr "" +msgstr "módosítás" #. module: account_voucher #: code:addons/account_voucher/account_voucher.py:1014 @@ -580,6 +632,9 @@ msgid "" "settings, to manage automatically the booking of accounting entries related " "to differences between exchange rates." msgstr "" +"Be kell állítani a 'Árfolyamveszteség számla' a könyvelés beállításoknál, " +"ahhoz, hogy kezelni tudja automatikusan a könyvelési tételek rögzítését, " +"melyek az átváltási árfolyam különbségekkel összefüggenek." #. module: account_voucher #: view:account.voucher:0 @@ -589,7 +644,7 @@ msgstr "Költség sorok" #. module: account_voucher #: view:account.voucher:0 msgid "Sale voucher" -msgstr "" +msgstr "Értékesítési nyugta" #. module: account_voucher #: help:account.voucher,is_multi_currency:0 @@ -597,11 +652,13 @@ msgid "" "Fields with internal purpose only that depicts if the voucher is a multi " "currency one or not" msgstr "" +"Belső használatú mezők, melyek azt ábrázolják, hogy a nyugták több " +"pénzneműek vagy nem" #. module: account_voucher #: view:account.invoice:0 msgid "Register Payment" -msgstr "Kifizetés" +msgstr "Kifizetés rögzítés" #. module: account_voucher #: field:account.statement.from.invoice.lines,line_ids:0 @@ -616,7 +673,7 @@ msgstr "December" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Group by month of Invoice Date" -msgstr "" +msgstr "Csoportosítás számla dátuma alapján" #. module: account_voucher #: view:sale.receipt.report:0 @@ -634,22 +691,22 @@ msgstr "Pénznem" #. module: account_voucher #: view:account.statement.from.invoice.lines:0 msgid "Payable and Receivables" -msgstr "Vevők és szállítók" +msgstr "Fizetendők & Bevételek" #. module: account_voucher #: view:account.voucher:0 msgid "Voucher Payment" -msgstr "" +msgstr "Nyugta kiegyenlítés" #. module: account_voucher #: field:sale.receipt.report,state:0 msgid "Voucher Status" -msgstr "" +msgstr "Nyugta állapota" #. module: account_voucher #: view:account.voucher:0 msgid "Are you sure to unreconcile this record?" -msgstr "" +msgstr "Biztosan törölni szeretné ennek a rekordnak a párosítását?" #. module: account_voucher #: field:account.voucher,company_id:0 @@ -662,53 +719,53 @@ msgstr "Vállalat" #. module: account_voucher #: help:account.voucher,paid:0 msgid "The Voucher has been totally paid." -msgstr "" +msgstr "A nyugta teljesen ki lett egyenlítve" #. module: account_voucher #: selection:account.voucher,payment_option:0 msgid "Reconcile Payment Balance" -msgstr "" +msgstr "Fizetési egyenleg párosítás" #. module: account_voucher #: code:addons/account_voucher/account_voucher.py:975 #, python-format msgid "Configuration Error !" -msgstr "" +msgstr "Beállítási hiba!" #. module: account_voucher #: view:account.voucher:0 #: view:sale.receipt.report:0 msgid "Draft Vouchers" -msgstr "" +msgstr "Nyugta tervezetek" #. module: account_voucher #: view:sale.receipt.report:0 #: field:sale.receipt.report,price_total_tax:0 msgid "Total With Tax" -msgstr "Bruttó érték" +msgstr "Bruttó érték adóval" #. module: account_voucher #: view:account.voucher:0 msgid "Purchase Voucher" -msgstr "" +msgstr "Beszerzési nyugta" #. module: account_voucher #: view:account.voucher:0 #: field:account.voucher,state:0 #: view:sale.receipt.report:0 msgid "Status" -msgstr "" +msgstr "Állapot" #. module: account_voucher #: view:account.voucher:0 msgid "Allocation" -msgstr "" +msgstr "Kiosztás" #. module: account_voucher #: view:account.statement.from.invoice.lines:0 #: view:account.voucher:0 msgid "or" -msgstr "" +msgstr "vagy" #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -718,7 +775,7 @@ msgstr "Augusztus" #. module: account_voucher #: view:account.voucher:0 msgid "Validate Payment" -msgstr "" +msgstr "Fizetés jóváhagyása" #. module: account_voucher #: help:account.voucher,audit:0 @@ -726,6 +783,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 "" +"Jelölje be, ha bizonytalan a napló tétel kontírozásában. Ennek hatására " +"könyvelő szekértő által 'ellenőrizendő'-ként jelölődik meg." #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -736,7 +795,7 @@ msgstr "Október" #: code:addons/account_voucher/account_voucher.py:976 #, python-format msgid "Please activate the sequence of selected journal !" -msgstr "" +msgstr "Kérem a sorozat aktiválását a kiválasztott naplóra !" #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -746,23 +805,23 @@ msgstr "Június" #. module: account_voucher #: field:account.voucher,payment_rate_currency_id:0 msgid "Payment Rate Currency" -msgstr "" +msgstr "Fizetési pénznem aránya" #. module: account_voucher #: field:account.voucher,paid:0 msgid "Paid" -msgstr "" +msgstr "Rendezett" #. module: account_voucher #: 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 "Értékesítési bevételi bizonylatok" #. module: account_voucher #: field:account.voucher,message_is_follower:0 msgid "Is a Follower" -msgstr "" +msgstr "Ez egy követő" #. module: account_voucher #: field:account.voucher,analytic_id:0 @@ -789,7 +848,7 @@ msgstr "Kiterjesztett szűrők" #. module: account_voucher #: field:account.voucher,paid_amount_in_company_currency:0 msgid "Paid Amount in Company Currency" -msgstr "" +msgstr "Kifizetett összeg a vállalat pénznemében" #. module: account_voucher #: field:account.bank.statement.line,amount_reconciled:0 @@ -805,7 +864,7 @@ msgstr "Azonnali kifizetés" #. module: account_voucher #: field:account.voucher.line,type:0 msgid "Dr/Cr" -msgstr "" +msgstr "T/K" #. module: account_voucher #: field:account.voucher,pre_line:0 @@ -816,7 +875,7 @@ msgstr "Előző kifizetések ?" #: code:addons/account_voucher/account_voucher.py:1112 #, python-format msgid "The invoice you are willing to pay is not valid anymore." -msgstr "" +msgstr "A kifizetni kívánt számla már nem érvényes." #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -827,52 +886,52 @@ msgstr "Január" #: model:ir.actions.act_window,name:account_voucher.action_voucher_list #: model:ir.ui.menu,name:account_voucher.menu_encode_entries_by_voucher msgid "Journal Vouchers" -msgstr "Nyugták" +msgstr "Nyugták naplói" #. module: account_voucher #: model:ir.model,name:account_voucher.model_res_company msgid "Companies" -msgstr "" +msgstr "Vállalatok" #. module: account_voucher #: field:account.voucher,message_summary:0 msgid "Summary" -msgstr "" +msgstr "Összegzés" #. module: account_voucher #: field:account.voucher,active:0 msgid "Active" -msgstr "" +msgstr "Aktív" #. module: account_voucher #: code:addons/account_voucher/account_voucher.py:982 #, python-format msgid "Please define a sequence on the journal." -msgstr "" +msgstr "Kérem egy sorozat meghatározását a naplón." #. 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 "Vevői befizetések" #. module: account_voucher #: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all #: model:ir.ui.menu,name:account_voucher.menu_action_sale_receipt_report_all #: view:sale.receipt.report:0 msgid "Sales Receipts Analysis" -msgstr "" +msgstr "Értékesítési bevételi bizonylatok elemzései" #. module: account_voucher #: view:sale.receipt.report:0 msgid "Group by Invoice Date" -msgstr "" +msgstr "Számla dátuma szerinti csoportosítása" #. module: account_voucher #: view:account.voucher:0 msgid "Post" -msgstr "Könyvelés" +msgstr "Elküld" #. module: account_voucher #: view:account.voucher:0 @@ -883,7 +942,7 @@ msgstr "Számlák és kifizetetlen tételek" #: view:sale.receipt.report:0 #: field:sale.receipt.report,price_total:0 msgid "Total Without Tax" -msgstr "Nettó érték" +msgstr "Nettó, adó nélküli érték" #. module: account_voucher #: view:account.voucher:0 @@ -919,7 +978,7 @@ msgstr "Bankkivonat" #. module: account_voucher #: view:account.bank.statement:0 msgid "onchange_amount(amount)" -msgstr "" +msgstr "onchange_amount(amount)" #. module: account_voucher #: selection:sale.receipt.report,month:0 @@ -952,19 +1011,19 @@ msgstr "Nyugta tételsorok" #: view:account.statement.from.invoice.lines:0 #: view:account.voucher:0 msgid "Cancel" -msgstr "Mégsem" +msgstr "Visszavonás" #. module: account_voucher #: model:ir.actions.client,name:account_voucher.action_client_invoice_menu msgid "Open Invoicing Menu" -msgstr "" +msgstr "Számlázási menü megnyitása" #. module: account_voucher #: selection:account.voucher,state:0 #: view:sale.receipt.report:0 #: selection:sale.receipt.report,state:0 msgid "Pro-forma" -msgstr "Pro forma" +msgstr "Pro-forma" #. module: account_voucher #: view:account.voucher:0 @@ -977,6 +1036,8 @@ msgstr "Könyvelési tételsorok" #, python-format msgid "Please define default credit/debit accounts on the journal \"%s\"." msgstr "" +"Kérem meghatározni az alapértelmezett követelés/tartozás könyvelést a naplón " +"\"%s\"." #. module: account_voucher #: selection:account.voucher,type:0 @@ -993,7 +1054,7 @@ msgstr "Fizetés" #. module: account_voucher #: view:account.voucher:0 msgid "Currency Options" -msgstr "" +msgstr "Pénznem lehetőségek" #. module: account_voucher #: help:account.voucher,payment_option:0 @@ -1003,6 +1064,10 @@ msgid "" "either choose to keep open this difference on the partner's account, or " "reconcile it with the payment(s)" msgstr "" +"Ez a mező megkönnyíti a választást ahhoz, hogy mit szeretne tenni a " +"kifizetett összeg és a kiosztott összeg közti különbségekkel. Hagyhatja " +"nyitottan ezt a különbséget a partner számláján, vagy párosíthatja a " +"fizetés(ek)el." #. module: account_voucher #: model:ir.actions.act_window,help:account_voucher.action_sale_receipt_report_all @@ -1016,16 +1081,24 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Erről a jelentésről, a vevőnek elküldött számlákról és fizetési\n" +" határidőkről és késve fizetésről áttekintést kaphat. A \n" +" keresési eszköz használható a számla beszámolók személyre\n" +" szabásához és így, az elemzést az igényének megfelelően " +"alakíthatja.\n" +"

\n" +" " #. module: account_voucher #: view:account.voucher:0 msgid "Posted Vouchers" -msgstr "" +msgstr "Elküldött nyugták" #. module: account_voucher #: field:account.voucher,payment_rate:0 msgid "Exchange Rate" -msgstr "" +msgstr "Árfolyam arány" #. module: account_voucher #: view:account.voucher:0 @@ -1045,7 +1118,7 @@ msgstr "Május" #. module: account_voucher #: view:account.voucher:0 msgid "Sale Receipt" -msgstr "" +msgstr "Értékesítési bevételi bizonylat" #. module: account_voucher #: view:account.voucher:0 @@ -1064,7 +1137,7 @@ msgstr "Belső megjegyzések" #: view:account.voucher:0 #: field:account.voucher,line_cr_ids:0 msgid "Credits" -msgstr "Követel" +msgstr "Követelések" #. module: account_voucher #: field:account.voucher.line,amount_original:0 @@ -1074,7 +1147,7 @@ msgstr "Eredeti összeg" #. module: account_voucher #: view:account.voucher:0 msgid "Purchase Receipt" -msgstr "" +msgstr "Vásárlási bevételi bizonylatok" #. module: account_voucher #: help:account.voucher,payment_rate:0 @@ -1082,6 +1155,8 @@ msgid "" "The specific rate that will be used, in this voucher, between the selected " "currency (in 'Payment Rate Currency' field) and the voucher currency." msgstr "" +"Az arány, mely ezen nyugtán lesz használva, a kiválasztott pénznem (a " +"'Fizetési pénznem aránya' mezőben) és a nyugta pénzneme közt." #. module: account_voucher #: view:account.voucher:0 @@ -1113,12 +1188,12 @@ msgstr "Február" #. module: account_voucher #: view:account.voucher:0 msgid "Supplier Invoices and Outstanding transactions" -msgstr "Bejövő számlák és kifizetetlen tételek" +msgstr "Beszállítók bejövő számlái és kifizetetlen tételek" #. module: account_voucher #: field:account.voucher,reference:0 msgid "Ref #" -msgstr "Hiv. szám" +msgstr "Hiv. szám #" #. module: account_voucher #: view:sale.receipt.report:0 @@ -1130,7 +1205,7 @@ msgstr "Év" #: field:account.config.settings,income_currency_exchange_account_id:0 #: field:res.company,income_currency_exchange_account_id:0 msgid "Gain Exchange Rate Account" -msgstr "" +msgstr "Árfolyamnyereség számla" #. module: account_voucher #: selection:account.voucher,type:0 @@ -1146,7 +1221,7 @@ msgstr "Április" #. module: account_voucher #: help:account.voucher,tax_id:0 msgid "Only for tax excluded from price" -msgstr "" +msgstr "Csak az árakból kihagyott adók" #. module: account_voucher #: field:account.voucher,type:0 @@ -1156,7 +1231,7 @@ msgstr "Alapértelmezett típus" #. module: account_voucher #: help:account.voucher,message_ids:0 msgid "Messages and communication history" -msgstr "" +msgstr "Üzenetek és kommunikációs történet" #. module: account_voucher #: model:ir.model,name:account_voucher.model_account_statement_from_invoice_lines @@ -1180,12 +1255,16 @@ msgid "" "The amount of the voucher must be the same amount as the one on the " "statement line." msgstr "" +"A nyugtán lévő összegnek ugyanannak kell lennie mint ami a kivonat sorában " +"szerepel." #. module: account_voucher #: code:addons/account_voucher/account_voucher.py:879 #, python-format msgid "Cannot delete voucher(s) which are already opened or paid." msgstr "" +"Nem lehet olyan nyugtá(ka)t törölni, melyek meg lettek nyitva vagy ki lettek " +"fozetve." #. module: account_voucher #: help:account.voucher,date:0 @@ -1195,7 +1274,7 @@ msgstr "Könyvelési tételek teljesítési dátuma" #. module: account_voucher #: model:mail.message.subtype,name:account_voucher.mt_voucher_state_change msgid "Status Change" -msgstr "" +msgstr "Állapotváltozás" #. module: account_voucher #: selection:account.voucher,payment_option:0 @@ -1223,7 +1302,7 @@ msgstr "Nettó érték" #. module: account_voucher #: model:ir.model,name:account_voucher.model_sale_receipt_report msgid "Sales Receipt Statistics" -msgstr "Értékesítési nyugta statisztika" +msgstr "Értékesítési bevételi bizonylatok statisztikái" #. module: account_voucher #: view:account.voucher:0 @@ -1242,14 +1321,14 @@ msgstr "Nyitott egyenleg" #. module: account_voucher #: model:mail.message.subtype,description:account_voucher.mt_voucher_state_change msgid "Status changed" -msgstr "" +msgstr "Állapot megváltozott" #. module: account_voucher #: code:addons/account_voucher/account_voucher.py:1014 #: code:addons/account_voucher/account_voucher.py:1018 #, python-format msgid "Insufficient Configuration!" -msgstr "" +msgstr "Nem megfelelő beállítás!" #. module: account_voucher #: help:account.voucher,active:0 @@ -1258,6 +1337,9 @@ msgid "" "inactive, which allow to hide the customer/supplier payment while the bank " "statement isn't confirmed." msgstr "" +"Alapértelmezetten, a tervezet bank kivonathoz párosított nyugták nem lesznek " +"aktívak, így el lehet tüntetni a vevő/beszállító fizetéseket amíg a banki " +"kivonatok nem kerülnek jóváhagyásra." #~ msgid "Particulars" #~ msgstr "Adatok" @@ -1308,9 +1390,6 @@ msgstr "" #~ msgid "Want to remove accounting entries too ?" #~ msgstr "A könyvelési tételeket is törölni szeretné?" -#~ msgid "Sales Receipt" -#~ msgstr "Nyugta" - #~ msgid "Unreconciliation" #~ msgstr "Párosítás visszavonása" @@ -1483,3 +1562,6 @@ msgstr "" #~ msgid "Canceled" #~ msgstr "Érvénytelenített" + +#~ msgid "Sales Receipt" +#~ msgstr "Értékesítési bevételi bizonylat" diff --git a/addons/account_voucher/invoice.py b/addons/account_voucher/invoice.py index c0584ddbd52..03a3e5fab67 100644 --- a/addons/account_voucher/invoice.py +++ b/addons/account_voucher/invoice.py @@ -52,6 +52,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/test/account_voucher_report.yml b/addons/account_voucher/test/account_voucher_report.yml index e8dbde413f2..96e96e4bdfd 100644 --- a/addons/account_voucher/test/account_voucher_report.yml +++ b/addons/account_voucher/test/account_voucher_report.yml @@ -20,7 +20,8 @@ - !python {model: account.voucher}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.voucher.cash_receipt.drcr').create(cr, uid, [ref("account_voucher_voucheraxelor0again")], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref("account_voucher_voucheraxelor0again")], 'voucher.cash_receipt.drcr', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account_voucher-report.'+format), 'wb+').write(data) diff --git a/addons/account_voucher/test/case5_suppl_usd_usd.yml b/addons/account_voucher/test/case5_suppl_usd_usd.yml index ace88e0bd4d..917e2366f56 100644 --- a/addons/account_voucher/test/case5_suppl_usd_usd.yml +++ b/addons/account_voucher/test/case5_suppl_usd_usd.yml @@ -125,7 +125,6 @@ - !python {model: account.voucher}: | import time - from openerp import netsvc vals = {} voucher_id = self.browse(cr, uid, ref('account_voucher_case_5_supplier_flow')) for item in voucher_id.line_dr_ids: diff --git a/addons/account_voucher/test/sales_payment.yml b/addons/account_voucher/test/sales_payment.yml index 37264de114a..71e605d5651 100644 --- a/addons/account_voucher/test/sales_payment.yml +++ b/addons/account_voucher/test/sales_payment.yml @@ -37,7 +37,6 @@ I will create and post an account voucher of amount 450.0 for the partner Seagate. - !python {model: account.voucher}: | - from openerp import netsvc vals = {} journal_id = self.default_get(cr, uid, ['journal_id']).get('journal_id',None) res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_19"), journal_id, 0.0, 1, ttype='receipt', date=False) diff --git a/addons/account_voucher/test/sales_receipt.yml b/addons/account_voucher/test/sales_receipt.yml index dc5602753fd..d27083b4513 100644 --- a/addons/account_voucher/test/sales_receipt.yml +++ b/addons/account_voucher/test/sales_receipt.yml @@ -45,7 +45,6 @@ I create and post a voucher payment of amount 30000.0 for the partner Seagate - !python {model: account.voucher}: | - from openerp import netsvc vals = {} journal_id = self.default_get(cr, uid, ['journal_id']).get('journal_id',None) res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_19"), journal_id, 0.0, 1, ttype='receipt', date=False) diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index de873c9195c..109c2f9aec9 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 @@ - + diff --git a/addons/account_voucher/voucher_sales_purchase_view.xml b/addons/account_voucher/voucher_sales_purchase_view.xml index 05b783dd339..6a84a09d5e6 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 @@ - + 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..ac298713b04 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -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/hu.po b/addons/analytic/i18n/hu.po index bf379e9f17c..4c6b076773d 100644 --- a/addons/analytic/i18n/hu.po +++ b/addons/analytic/i18n/hu.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-01-30 18:54+0000\n" -"Last-Translator: Krisztian Eyssen \n" +"PO-Revision-Date: 2013-03-25 13:25+0000\n" +"Last-Translator: krnkris \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:41+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-03-26 04:44+0000\n" +"X-Generator: Launchpad (build 16540)\n" #. module: analytic #: field:account.analytic.account,child_ids:0 @@ -24,13 +24,13 @@ msgstr "Alárendelt gyűjtőkódok" #. module: analytic #: selection:account.analytic.account,state:0 msgid "In Progress" -msgstr "" +msgstr "Folyamatban" #. module: analytic #: code:addons/analytic/analytic.py:229 #, python-format msgid "Contract: " -msgstr "" +msgstr "Szerződés: " #. module: analytic #: selection:account.analytic.account,state:0 @@ -40,7 +40,7 @@ msgstr "Sablon" #. module: analytic #: view:account.analytic.account:0 msgid "End Date" -msgstr "" +msgstr "Befejezés dátuma" #. module: analytic #: help:account.analytic.line,unit_amount:0 @@ -64,6 +64,14 @@ msgid "" "The special type 'Template of Contract' allows you to define a template with " "default data that you can reuse easily." msgstr "" +"A nézet típus kiválasztásával, megtiltja ezzel a fiókkal a napló bejegyzés " +"készítését.\n" +"Az 'Elemző/gyüjtő számla' típust olyan fiókokhoz használja, melyeket csak " +"könyveléshez használ.\n" +"Ha Szerződést vagy Projektet választ, lehetősége lesz kezelni a fiók " +"érvényesítés és számlázási lehetőségeit.\n" +"A speciális 'Szerződési sablon' típus lehetővé teszi alapértékekkel " +"kitöltött sablon létrehozását, melyet könnyen ismét felhasználhat." #. module: analytic #: view:account.analytic.account:0 @@ -82,12 +90,12 @@ msgstr "" #. module: analytic #: selection:account.analytic.account,type:0 msgid "Contract or Project" -msgstr "" +msgstr "Projekt szerződése" #. module: analytic #: field:account.analytic.account,name:0 msgid "Account/Contract Name" -msgstr "" +msgstr "Fiók/Szerződés neve" #. module: analytic #: field:account.analytic.account,manager_id:0 @@ -97,7 +105,7 @@ msgstr "Felelős" #. module: analytic #: field:account.analytic.account,message_follower_ids:0 msgid "Followers" -msgstr "" +msgstr "Követők" #. module: analytic #: selection:account.analytic.account,state:0 @@ -107,28 +115,28 @@ msgstr "Lezárt" #. module: analytic #: model:mail.message.subtype,name:analytic.mt_account_pending msgid "Contract to Renew" -msgstr "" +msgstr "Megújítandó szerződés" #. module: analytic #: selection:account.analytic.account,state:0 msgid "New" -msgstr "" +msgstr "Új" #. module: analytic #: field:account.analytic.account,user_id:0 msgid "Project Manager" -msgstr "" +msgstr "Projektmenedzser" #. module: analytic #: field:account.analytic.account,state:0 msgid "Status" -msgstr "" +msgstr "Állapot" #. module: analytic #: code:addons/analytic/analytic.py:271 #, python-format msgid "%s (copy)" -msgstr "" +msgstr "%s (másolat)" #. module: analytic #: model:ir.model,name:analytic.model_account_analytic_line @@ -144,12 +152,12 @@ msgstr "Leírás" #. module: analytic #: field:account.analytic.account,message_unread:0 msgid "Unread Messages" -msgstr "" +msgstr "Olvasatlan üzenetek" #. module: analytic #: constraint:account.analytic.account:0 msgid "Error! You cannot create recursive analytic accounts." -msgstr "" +msgstr "Hiba! Nem tud visszatérő Elemző/Gyűjtő számlákat létrehozni." #. module: analytic #: field:account.analytic.account,company_id:0 @@ -160,12 +168,12 @@ msgstr "Vállalat" #. module: analytic #: view:account.analytic.account:0 msgid "Renewal" -msgstr "" +msgstr "Megújítás" #. module: analytic #: help:account.analytic.account,message_ids:0 msgid "Messages and communication history" -msgstr "" +msgstr "Üzenetek és kommunikációs történet" #. module: analytic #: model:mail.message.subtype,description:analytic.mt_account_opened @@ -194,7 +202,7 @@ msgstr "" #. module: analytic #: field:account.analytic.account,message_is_follower:0 msgid "Is a Follower" -msgstr "" +msgstr "Ez egy követő" #. module: analytic #: field:account.analytic.line,user_id:0 @@ -204,7 +212,7 @@ msgstr "Felhasználó" #. module: analytic #: model:mail.message.subtype,description:analytic.mt_account_pending msgid "Contract pending" -msgstr "" +msgstr "Szerződés függőben" #. module: analytic #: field:account.analytic.line,date:0 @@ -214,12 +222,12 @@ msgstr "Dátum" #. module: analytic #: model:mail.message.subtype,name:analytic.mt_account_closed msgid "Contract Finished" -msgstr "" +msgstr "Szerződés végrehejtva" #. module: analytic #: view:account.analytic.account:0 msgid "Terms and Conditions" -msgstr "" +msgstr "Kikötések és feltételek" #. module: analytic #: help:account.analytic.line,amount:0 @@ -233,17 +241,17 @@ msgstr "" #. module: analytic #: field:account.analytic.account,partner_id:0 msgid "Customer" -msgstr "" +msgstr "Vevő" #. module: analytic #: field:account.analytic.account,child_complete_ids:0 msgid "Account Hierarchy" -msgstr "" +msgstr "Számla fiók hierarchia, rangsor" #. module: analytic #: field:account.analytic.account,message_ids:0 msgid "Messages" -msgstr "" +msgstr "Üzenetek" #. module: analytic #: field:account.analytic.account,parent_id:0 @@ -253,23 +261,23 @@ msgstr "Fölérendelt gyűjtőkód" #. module: analytic #: view:account.analytic.account:0 msgid "Contract Information" -msgstr "" +msgstr "Szerződé információja" #. module: analytic #: field:account.analytic.account,template_id:0 #: selection:account.analytic.account,type:0 msgid "Template of Contract" -msgstr "" +msgstr "Szerződés sablonja" #. module: analytic #: field:account.analytic.account,message_summary:0 msgid "Summary" -msgstr "" +msgstr "Összegzés" #. module: analytic #: field:account.analytic.account,quantity_max:0 msgid "Prepaid Service Units" -msgstr "" +msgstr "Előre fizetett szolgáltatási egység" #. module: analytic #: field:account.analytic.account,credit:0 @@ -279,12 +287,12 @@ msgstr "Követel" #. module: analytic #: model:mail.message.subtype,name:analytic.mt_account_opened msgid "Contract Opened" -msgstr "" +msgstr "Szerződés megnyitva, elindítva" #. module: analytic #: model:mail.message.subtype,description:analytic.mt_account_closed msgid "Contract closed" -msgstr "" +msgstr "Szerződés lezárva" #. module: analytic #: selection:account.analytic.account,state:0 @@ -294,7 +302,7 @@ msgstr "Érvénytelenített" #. module: analytic #: selection:account.analytic.account,type:0 msgid "Analytic View" -msgstr "" +msgstr "Elemző nézet" #. module: analytic #: field:account.analytic.account,balance:0 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 254dad95c7d..a1bf43714ce 100644 --- a/addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py +++ b/addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py @@ -76,11 +76,11 @@ class account_analytic_account(osv.osv): GROUP BY product_id, user_id, to_invoice, product_uom_id, line.name""", (account.id,)) res[account.id] = 0.0 - for product_id, price, user_id, factor_id, qty, uom, line_name in cr.fetchall(): + for product_id, total_amount, user_id, factor_id, qty, uom, line_name in cr.fetchall(): #the amount to reinvoice is the real cost. We don't use the pricelist - price = -price + total_amount = -total_amount factor = self.pool.get('hr_timesheet_invoice.factor').browse(cr, uid, factor_id, context=context) - res[account.id] += price * qty * (100 - factor.factor or 0.0) / 100.0 + res[account.id] += total_amount * (100 - factor.factor or 0.0) / 100.0 return res def _expense_invoiced_calc(self, cr, uid, ids, name, arg, context=None): @@ -89,8 +89,13 @@ class account_analytic_account(osv.osv): for account in self.browse(cr, uid, ids, context=context): res[account.id] = 0.0 line_ids = lines_obj.search(cr, uid, [('account_id','=', account.id), ('invoice_id','!=',False), ('to_invoice','!=', False), ('journal_id.type', '=', 'purchase')], context=context) + #Put invoices in separate array in order not to calculate them double + invoices = [] for line in lines_obj.browse(cr, uid, line_ids, context=context): - res[account.id] += line.invoice_id.amount_untaxed + if line.invoice_id not in invoices: + invoices.append(line.invoice_id) + for invoice in invoices: + res[account.id] += invoice.amount_untaxed return res def _ca_invoiced_calc(self, cr, uid, ids, name, arg, context=None): @@ -147,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/cs.po b/addons/analytic_contract_hr_expense/i18n/cs.po new file mode 100644 index 00000000000..b57756bce0b --- /dev/null +++ b/addons/analytic_contract_hr_expense/i18n/cs.po @@ -0,0 +1,72 @@ +# Czech 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-03-31 16:44+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "or view" +msgstr "" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "Nothing to invoice, create" +msgstr "" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "expenses" +msgstr "" + +#. module: analytic_contract_hr_expense +#: model:ir.model,name:analytic_contract_hr_expense.model_account_analytic_account +msgid "Analytic Account" +msgstr "" + +#. 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 "" + +#. module: analytic_contract_hr_expense +#: code:addons/analytic_contract_hr_expense/analytic_contract_hr_expense.py:121 +#, python-format +msgid "Expenses of %s" +msgstr "" + +#. 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 "" + +#. module: analytic_contract_hr_expense +#: field:account.analytic.account,est_expenses:0 +msgid "Estimation of Expenses to Invoice" +msgstr "" + +#. module: analytic_contract_hr_expense +#: field:account.analytic.account,charge_expenses:0 +msgid "Charge Expenses" +msgstr "" + +#. module: analytic_contract_hr_expense +#: view:account.analytic.account:0 +msgid "⇒ Invoice" +msgstr "" 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/anonymization/anonymization.py b/addons/anonymization/anonymization.py index de46e2e8d03..025f1f79f70 100644 --- a/addons/anonymization/anonymization.py +++ b/addons/anonymization/anonymization.py @@ -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) @@ -543,7 +543,7 @@ 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 + 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/anonymization/i18n/cs.po b/addons/anonymization/i18n/cs.po new file mode 100644 index 00000000000..aa320cbba21 --- /dev/null +++ b/addons/anonymization/i18n/cs.po @@ -0,0 +1,331 @@ +# Czech 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-03-31 16:44+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: anonymization +#: model:ir.model,name:anonymization.model_ir_model_fields_anonymize_wizard +msgid "ir.model.fields.anonymize.wizard" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,model_id:0 +msgid "Object" +msgstr "" + +#. module: anonymization +#: model:ir.model,name:anonymization.model_ir_model_fields_anonymization_migration_fix +msgid "ir.model.fields.anonymization.migration.fix" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.migration.fix,target_version:0 +msgid "Target Version" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.migration.fix,query_type:0 +msgid "sql" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:91 +#, python-format +msgid "" +"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." +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,field_name:0 +msgid "Field Name" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,field_id:0 +#: field:ir.model.fields.anonymization.migration.fix,field_name:0 +msgid "Field" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization,state:0 +msgid "New" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymize.wizard,file_import:0 +msgid "Import" +msgstr "" + +#. module: anonymization +#: model:ir.model,name:anonymization.model_ir_model_fields_anonymization +msgid "ir.model.fields.anonymization" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:300 +#, python-format +msgid "" +"Before executing the anonymization process, you should make a backup of your " +"database." +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,state:0 +#: field:ir.model.fields.anonymize.wizard,state:0 +msgid "Status" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,direction:0 +msgid "Direction" +msgstr "" + +#. module: anonymization +#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymization_tree +#: view:ir.model.fields.anonymization:0 +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_fields +msgid "Anonymized Fields" +msgstr "" + +#. module: anonymization +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization +msgid "Database anonymization" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,direction:0 +msgid "clear -> anonymized" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization,state:0 +#: selection:ir.model.fields.anonymize.wizard,state:0 +msgid "Anonymized" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,state:0 +msgid "unknown" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:448 +#, python-format +msgid "Anonymized value is None. This cannot happens." +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,filepath:0 +msgid "File path" +msgstr "" + +#. module: anonymization +#: help:ir.model.fields.anonymize.wizard,file_import:0 +msgid "" +"This is the file created by the anonymization process. It should have the " +"'.pickle' extention." +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.history,date:0 +msgid "Date" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymize.wizard,file_export:0 +msgid "Export" +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymize.wizard:0 +msgid "Reverse the Database Anonymization" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:444 +#, python-format +msgid "" +"Cannot anonymize fields of these types: binary, many2many, many2one, " +"one2many, reference." +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymize.wizard:0 +msgid "Database Anonymization" +msgstr "" + +#. module: anonymization +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_wizard +msgid "Anonymize database" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.migration.fix,query_type:0 +msgid "python" +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymization.history:0 +#: field:ir.model.fields.anonymization.history,field_ids:0 +msgid "Fields" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization,state:0 +#: selection:ir.model.fields.anonymize.wizard,state:0 +msgid "Clear" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:533 +#, python-format +msgid "" +"It is not possible to reverse the anonymization process without supplying " +"the anonymization export file." +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymize.wizard,summary:0 +msgid "Summary" +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymization:0 +msgid "Anonymized Field" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:391 +#: code:addons/anonymization/anonymization.py:526 +#, python-format +msgid "" +"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." +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymize.wizard,state:0 +msgid "Unstable" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,state:0 +msgid "Exception occured" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization,state:0 +msgid "Not Existing" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization,model_name:0 +msgid "Object Name" +msgstr "" + +#. module: anonymization +#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymization_history_tree +#: view:ir.model.fields.anonymization.history:0 +#: model:ir.ui.menu,name:anonymization.menu_administration_anonymization_history +msgid "Anonymization History" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.migration.fix,model_name:0 +msgid "Model" +msgstr "" + +#. module: anonymization +#: model:ir.model,name:anonymization.model_ir_model_fields_anonymization_history +msgid "ir.model.fields.anonymization.history" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:358 +#, python-format +msgid "" +"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." +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:389 +#: code:addons/anonymization/anonymization.py:448 +#, python-format +msgid "Error !" +msgstr "" + +#. module: anonymization +#: model:ir.actions.act_window,name:anonymization.action_ir_model_fields_anonymize_wizard +#: view:ir.model.fields.anonymize.wizard:0 +msgid "Anonymize Database" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymize.wizard,name:0 +msgid "File Name" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.migration.fix,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,direction:0 +msgid "anonymized -> clear" +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,state:0 +msgid "Started" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:389 +#, python-format +msgid "The database is currently anonymized, you cannot anonymize it again." +msgstr "" + +#. module: anonymization +#: selection:ir.model.fields.anonymization.history,state:0 +msgid "Done" +msgstr "" + +#. module: anonymization +#: field:ir.model.fields.anonymization.migration.fix,query:0 +#: field:ir.model.fields.anonymization.migration.fix,query_type:0 +msgid "Query" +msgstr "" + +#. module: anonymization +#: view:ir.model.fields.anonymization.history:0 +#: field:ir.model.fields.anonymization.history,msg:0 +#: field:ir.model.fields.anonymize.wizard,msg:0 +msgid "Message" +msgstr "" + +#. module: anonymization +#: code:addons/anonymization/anonymization.py:65 +#: sql_constraint:ir.model.fields.anonymization:0 +#, python-format +msgid "You cannot have two fields with the same name on the same object!" +msgstr "" diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 0debdf11492..159baf3a9e7 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -19,10 +19,10 @@ # ############################################################################## +import openerp from openerp.osv import fields, osv import openerp.service.model from openerp.tools.translate import _ -from openerp import pooler import time from openerp import tools from openerp import SUPERUSER_ID @@ -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')) @@ -113,7 +112,6 @@ class audittrail_rule(osv.osv): value = "ir.actions.act_window" + ',' + str(w_id[0]) val_id = ir_values_obj.search(cr, uid, [('model', '=', thisrule.object_id.model), ('value', '=', value)]) if val_id: - ir_values_obj = pooler.get_pool(cr.dbname).get('ir.values') res = ir_values_obj.unlink(cr, uid, [val_id[0]]) self.write(cr, uid, [thisrule.id], {"state": "draft"}) #End Loop @@ -132,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: @@ -191,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,8 +210,8 @@ def create_log_line(cr, uid, log_id, model, lines=None): """ if lines is None: lines = [] - pool = pooler.get_pool(cr.dbname) - obj_pool = pool.get(model.model) + pool = openerp.registry(cr.dbname) + 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,8 +249,8 @@ def log_fct(cr, uid_orig, model, method, fct_src, *args, **kw): @return: Returns result as per method of Object proxy """ - pool = pooler.get_pool(cr.dbname) - resource_pool = pool.get(model) + pool = openerp.registry(cr.dbname) + 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 @@ -322,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 = {} @@ -391,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 @@ -458,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, @@ -492,7 +490,7 @@ def check_rules(cr, uid, model, method): @param method: method to log: create, read, unlink,write,actions,workflow actions @return: True or False """ - pool = pooler.get_pool(cr.dbname) + pool = openerp.registry(cr.dbname) if 'audittrail.rule' in pool.models: model_ids = pool.get('ir.model').search(cr, SUPERUSER_ID, [('model', '=', model)]) model_id = model_ids and model_ids[0] or False 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/cs.po b/addons/auth_crypt/i18n/cs.po index b97e90df13b..0ae0746fbdb 100644 --- a/addons/auth_crypt/i18n/cs.po +++ b/addons/auth_crypt/i18n/cs.po @@ -1,41 +1,28 @@ # Czech 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-04-06 05:20+0000\n" -"Last-Translator: Jiří Hajda \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2013-03-31 16:44+0000\n" +"Last-Translator: FULL NAME \n" "Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" -#. module: base_crypt -#: model:ir.model,name:base_crypt.model_res_users -msgid "Users" +#. module: auth_crypt +#: field:res.users,password_crypt:0 +msgid "Encrypted Password" msgstr "" -#~ msgid "You can not have two users with the same login !" -#~ msgstr "Nemůžete mít dva uživatele se stejným přihlašovacím jménem !" - -#, python-format -#~ msgid "Error" -#~ msgstr "Chyba" - -#, python-format -#~ msgid "Please specify the password !" -#~ msgstr "Prosíme zadejte heslo!" - -#~ msgid "The chosen company is not in the allowed companies for this user" -#~ msgstr "" -#~ "Vybraná společnost není v povolených společnostech pro tohoto uživatele" - -#~ msgid "res.users" -#~ msgstr "res.users" +#. module: auth_crypt +#: model:ir.model,name:auth_crypt.model_res_users +msgid "Users" +msgstr "" 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/i18n/cs.po b/addons/auth_ldap/i18n/cs.po new file mode 100644 index 00000000000..539c923450d --- /dev/null +++ b/addons/auth_ldap/i18n/cs.po @@ -0,0 +1,159 @@ +# Czech 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-03-31 16:44+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: auth_ldap +#: field:res.company.ldap,user:0 +msgid "Template User" +msgstr "" + +#. module: auth_ldap +#: help:res.company.ldap,ldap_tls:0 +msgid "" +"Request secure TLS/SSL encryption when connecting to the LDAP server. This " +"option requires a server with STARTTLS enabled, otherwise all authentication " +"attempts will fail." +msgstr "" + +#. module: auth_ldap +#: view:res.company:0 +#: view:res.company.ldap:0 +msgid "LDAP Configuration" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,ldap_binddn:0 +msgid "LDAP binddn" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,company:0 +msgid "Company" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,ldap_server:0 +msgid "LDAP Server address" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,ldap_server_port:0 +msgid "LDAP Server port" +msgstr "" + +#. module: auth_ldap +#: help:res.company.ldap,create_user:0 +msgid "" +"Automatically create local user accounts for new users authenticating via " +"LDAP" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,ldap_base:0 +msgid "LDAP base" +msgstr "" + +#. module: auth_ldap +#: view:res.company.ldap:0 +msgid "User Information" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,ldap_password:0 +msgid "LDAP password" +msgstr "" + +#. module: auth_ldap +#: model:ir.model,name:auth_ldap.model_res_company +msgid "Companies" +msgstr "" + +#. module: auth_ldap +#: view:res.company.ldap:0 +msgid "Process Parameter" +msgstr "" + +#. module: auth_ldap +#: model:ir.model,name:auth_ldap.model_res_company_ldap +msgid "res.company.ldap" +msgstr "" + +#. module: auth_ldap +#: help:res.company.ldap,user:0 +msgid "User to copy when creating new users" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,ldap_tls:0 +msgid "Use TLS" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: auth_ldap +#: view:res.company.ldap:0 +msgid "Login Information" +msgstr "" + +#. module: auth_ldap +#: view:res.company.ldap:0 +msgid "Server Information" +msgstr "" + +#. module: auth_ldap +#: model:ir.actions.act_window,name:auth_ldap.action_ldap_installer +msgid "Setup your LDAP Server" +msgstr "" + +#. module: auth_ldap +#: view:res.company:0 +#: field:res.company,ldaps:0 +msgid "LDAP Parameters" +msgstr "" + +#. module: auth_ldap +#: help:res.company.ldap,ldap_password:0 +msgid "" +"The password of the user account on the LDAP server that is used to query " +"the directory." +msgstr "" + +#. module: auth_ldap +#: help:res.company.ldap,ldap_binddn:0 +msgid "" +"The user account on the LDAP server that is used to query the directory. " +"Leave empty to connect anonymously." +msgstr "" + +#. module: auth_ldap +#: model:ir.model,name:auth_ldap.model_res_users +msgid "Users" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,ldap_filter:0 +msgid "LDAP filter" +msgstr "" + +#. module: auth_ldap +#: field:res.company.ldap,create_user:0 +msgid "Create user" +msgstr "" diff --git a/addons/auth_ldap/users_ldap.py b/addons/auth_ldap/users_ldap.py index a63d52209ba..8e7128ca91e 100644 --- a/addons/auth_ldap/users_ldap.py +++ b/addons/auth_ldap/users_ldap.py @@ -23,7 +23,6 @@ import logging from ldap.filter import filter_format import openerp.exceptions -from openerp import pooler from openerp import tools from openerp.osv import fields, osv from openerp import SUPERUSER_ID @@ -188,7 +187,7 @@ class CompanyLDAP(osv.osv): user_id = res[0] elif conf['create_user']: _logger.debug("Creating new OpenERP user \"%s\" from LDAP" % login) - user_obj = self.pool.get('res.users') + user_obj = self.pool['res.users'] values = self.map_ldap_attributes(cr, uid, conf, login, ldap_entry) if conf['user']: user_id = user_obj.copy(cr, SUPERUSER_ID, conf['user'], @@ -228,7 +227,6 @@ class CompanyLDAP(osv.osv): 'create_user': True, } -CompanyLDAP() class res_company(osv.osv): @@ -237,7 +235,6 @@ class res_company(osv.osv): 'ldaps': fields.one2many( 'res.company.ldap', 'company', 'LDAP Parameters'), } -res_company() class users(osv.osv): @@ -246,8 +243,8 @@ class users(osv.osv): user_id = super(users, self).login(db, login, password) if user_id: return user_id - cr = pooler.get_db(db).cursor() - ldap_obj = pooler.get_pool(db).get('res.company.ldap') + cr = self.pool.db.cursor() + ldap_obj = self.pool['res.company.ldap'] for conf in ldap_obj.get_ldap_dicts(cr): entry = ldap_obj.authenticate(conf, login, password) if entry: @@ -269,12 +266,12 @@ class users(osv.osv): except openerp.exceptions.AccessDenied: pass - cr = pooler.get_db(db).cursor() + cr = self.pool.db.cursor() cr.execute('SELECT login FROM res_users WHERE id=%s AND active=TRUE', (int(uid),)) res = cr.fetchone() if res: - ldap_obj = pooler.get_pool(db).get('res.company.ldap') + ldap_obj = self.pool['res.company.ldap'] for conf in ldap_obj.get_ldap_dicts(cr): if ldap_obj.authenticate(conf, res[0], passwd): self._uid_cache.setdefault(db, {})[uid] = passwd @@ -283,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/controllers/main.py b/addons/auth_oauth/controllers/main.py index 1c38f7f4eae..3f7ef2f3f0c 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -64,8 +64,13 @@ class OAuthController(oeweb.Controller): u = registry.get('res.users') credentials = u.auth_oauth(cr, SUPERUSER_ID, provider, kw, context=context) cr.commit() - action = state.get('a', None) - url = '/#action=' + action if action else '/' + action = state.get('a') + menu = state.get('m') + url = '/' + if action: + url = '/#action=%s' % action + elif menu: + url = '/#menu_id=%s' % menu return login_and_redirect(req, *credentials, redirect_url=url) except AttributeError: # auth_signup is not installed diff --git a/addons/auth_oauth/i18n/cs.po b/addons/auth_oauth/i18n/cs.po new file mode 100644 index 00000000000..e607a08a7bd --- /dev/null +++ b/addons/auth_oauth/i18n/cs.po @@ -0,0 +1,135 @@ +# Czech 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-03-31 16:45+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: auth_oauth +#: field:auth.oauth.provider,validation_endpoint:0 +msgid "Validation URL" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,auth_endpoint:0 +msgid "Authentication URL" +msgstr "" + +#. module: auth_oauth +#: model:ir.model,name:auth_oauth.model_base_config_settings +msgid "base.config.settings" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,name:0 +msgid "Provider name" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,scope:0 +msgid "Scope" +msgstr "" + +#. module: auth_oauth +#: field:res.users,oauth_provider_id:0 +msgid "OAuth Provider" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,css_class:0 +msgid "CSS class" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,body:0 +msgid "Body" +msgstr "" + +#. module: auth_oauth +#: model:ir.model,name:auth_oauth.model_res_users +msgid "Users" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,sequence:0 +msgid "unknown" +msgstr "" + +#. module: auth_oauth +#: field:res.users,oauth_access_token:0 +msgid "OAuth Access Token" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,client_id:0 +#: field:base.config.settings,auth_oauth_facebook_client_id:0 +#: field:base.config.settings,auth_oauth_google_client_id:0 +msgid "Client ID" +msgstr "" + +#. module: auth_oauth +#: model:ir.ui.menu,name:auth_oauth.menu_oauth_providers +msgid "OAuth Providers" +msgstr "" + +#. module: auth_oauth +#: model:ir.model,name:auth_oauth.model_auth_oauth_provider +msgid "OAuth2 provider" +msgstr "" + +#. module: auth_oauth +#: field:res.users,oauth_uid:0 +msgid "OAuth User ID" +msgstr "" + +#. module: auth_oauth +#: field:base.config.settings,auth_oauth_facebook_enabled:0 +msgid "Allow users to sign in with Facebook" +msgstr "" + +#. module: auth_oauth +#: sql_constraint:res.users:0 +msgid "OAuth UID must be unique per provider" +msgstr "" + +#. module: auth_oauth +#: help:res.users,oauth_uid:0 +msgid "Oauth Provider user_id" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,data_endpoint:0 +msgid "Data URL" +msgstr "" + +#. module: auth_oauth +#: view:auth.oauth.provider:0 +msgid "arch" +msgstr "" + +#. module: auth_oauth +#: model:ir.actions.act_window,name:auth_oauth.action_oauth_provider +msgid "Providers" +msgstr "" + +#. module: auth_oauth +#: field:base.config.settings,auth_oauth_google_enabled:0 +msgid "Allow users to sign in with Google" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,enabled:0 +msgid "Allowed" +msgstr "" diff --git a/addons/auth_oauth/i18n/tr.po b/addons/auth_oauth/i18n/tr.po new file mode 100644 index 00000000000..7faa18ccebf --- /dev/null +++ b/addons/auth_oauth/i18n/tr.po @@ -0,0 +1,135 @@ +# Turkish 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-03-21 19:39+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Turkish \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-22 04:57+0000\n" +"X-Generator: Launchpad (build 16532)\n" + +#. module: auth_oauth +#: field:auth.oauth.provider,validation_endpoint:0 +msgid "Validation URL" +msgstr "Onaylama URL" + +#. module: auth_oauth +#: field:auth.oauth.provider,auth_endpoint:0 +msgid "Authentication URL" +msgstr "Kimlik Doğrulama URL" + +#. module: auth_oauth +#: model:ir.model,name:auth_oauth.model_base_config_settings +msgid "base.config.settings" +msgstr "base.config.settings" + +#. module: auth_oauth +#: field:auth.oauth.provider,name:0 +msgid "Provider name" +msgstr "Sağlayıcı adı" + +#. module: auth_oauth +#: field:auth.oauth.provider,scope:0 +msgid "Scope" +msgstr "Kapsam" + +#. module: auth_oauth +#: field:res.users,oauth_provider_id:0 +msgid "OAuth Provider" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,css_class:0 +msgid "CSS class" +msgstr "CSS class" + +#. module: auth_oauth +#: field:auth.oauth.provider,body:0 +msgid "Body" +msgstr "" + +#. module: auth_oauth +#: model:ir.model,name:auth_oauth.model_res_users +msgid "Users" +msgstr "Kullanıcılar" + +#. module: auth_oauth +#: field:auth.oauth.provider,sequence:0 +msgid "unknown" +msgstr "bilinmeyen" + +#. module: auth_oauth +#: field:res.users,oauth_access_token:0 +msgid "OAuth Access Token" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,client_id:0 +#: field:base.config.settings,auth_oauth_facebook_client_id:0 +#: field:base.config.settings,auth_oauth_google_client_id:0 +msgid "Client ID" +msgstr "" + +#. module: auth_oauth +#: model:ir.ui.menu,name:auth_oauth.menu_oauth_providers +msgid "OAuth Providers" +msgstr "" + +#. module: auth_oauth +#: model:ir.model,name:auth_oauth.model_auth_oauth_provider +msgid "OAuth2 provider" +msgstr "" + +#. module: auth_oauth +#: field:res.users,oauth_uid:0 +msgid "OAuth User ID" +msgstr "" + +#. module: auth_oauth +#: field:base.config.settings,auth_oauth_facebook_enabled:0 +msgid "Allow users to sign in with Facebook" +msgstr "Kullanıcılara Facebook ile oturum için izin ver" + +#. module: auth_oauth +#: sql_constraint:res.users:0 +msgid "OAuth UID must be unique per provider" +msgstr "" + +#. module: auth_oauth +#: help:res.users,oauth_uid:0 +msgid "Oauth Provider user_id" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,data_endpoint:0 +msgid "Data URL" +msgstr "Data URL" + +#. module: auth_oauth +#: view:auth.oauth.provider:0 +msgid "arch" +msgstr "" + +#. module: auth_oauth +#: model:ir.actions.act_window,name:auth_oauth.action_oauth_provider +msgid "Providers" +msgstr "Sağlayıcılar" + +#. module: auth_oauth +#: field:base.config.settings,auth_oauth_google_enabled:0 +msgid "Allow users to sign in with Google" +msgstr "" + +#. module: auth_oauth +#: field:auth.oauth.provider,enabled:0 +msgid "Allowed" +msgstr "İzinVerildi" diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index 7ee83bd99e9..131ae5c1c42 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -5,6 +5,7 @@ openerp.auth_oauth = function(instance) { start: function(parent, params) { var self = this; var d = this._super.apply(this, arguments); + this.$el.hide(); this.$el.on('click', 'a.zocial', this.on_oauth_sign_in); this.oauth_providers = []; if(this.params.oauth_error === 1) { @@ -24,6 +25,8 @@ openerp.auth_oauth = function(instance) { var db = this.$("form [name=db]").val(); if (db) { this.rpc("/auth_oauth/list_providers", { dbname: db }).done(this.on_oauth_loaded); + } else { + this.$el.show(); } }, on_oauth_loaded: function(result) { @@ -32,6 +35,7 @@ openerp.auth_oauth = function(instance) { if (this.oauth_providers.length === 1 && params.type === 'signup') { this.do_oauth_sign_in(this.oauth_providers[0]); } else { + this.$el.show(); this.$('.oe_oauth_provider_login_button').remove(); var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this}); this.$(".oe_login_pane form ul").after(buttons); @@ -57,7 +61,7 @@ openerp.auth_oauth = function(instance) { state: JSON.stringify(state), }; var url = provider.auth_endpoint + '?' + $.param(params); - window.location = url; + instance.web.redirect(url); }, _oauth_state: function(provider) { // return the state object sent back with the redirected uri diff --git a/addons/auth_oauth_signup/i18n/cs.po b/addons/auth_oauth_signup/i18n/cs.po new file mode 100644 index 00000000000..6351d6c056c --- /dev/null +++ b/addons/auth_oauth_signup/i18n/cs.po @@ -0,0 +1,23 @@ +# Czech 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-03-31 16:45+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: auth_oauth_signup +#: model:ir.model,name:auth_oauth_signup.model_res_users +msgid "Users" +msgstr "" 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/cs.po b/addons/auth_openid/i18n/cs.po new file mode 100644 index 00000000000..071ee7ea210 --- /dev/null +++ b/addons/auth_openid/i18n/cs.po @@ -0,0 +1,97 @@ +# Czech 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-03-31 16:45+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:24 +#, python-format +msgid "Username" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:12 +#: view:res.users:0 +#, python-format +msgid "OpenID" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:30 +#: field:res.users,openid_url:0 +#, python-format +msgid "OpenID URL" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:9 +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:10 +#, python-format +msgid "Google" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:11 +#, python-format +msgid "Launchpad" +msgstr "" + +#. module: auth_openid +#: help:res.users,openid_email:0 +msgid "Used for disambiguation in case of a shared OpenID URL" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:18 +#, python-format +msgid "Google Apps Domain" +msgstr "" + +#. module: auth_openid +#: field:res.users,openid_email:0 +msgid "OpenID Email" +msgstr "" + +#. module: auth_openid +#: field:res.users,openid_key:0 +msgid "OpenID Key" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:8 +#, python-format +msgid "Password" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:10 +#, python-format +msgid "Google Apps" +msgstr "" + +#. module: auth_openid +#: model:ir.model,name:auth_openid.model_res_users +msgid "Users" +msgstr "" diff --git a/addons/auth_openid/i18n/ru.po b/addons/auth_openid/i18n/ru.po new file mode 100644 index 00000000000..6041300fe60 --- /dev/null +++ b/addons/auth_openid/i18n/ru.po @@ -0,0 +1,97 @@ +# 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-03-23 11:37+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-03-24 04:45+0000\n" +"X-Generator: Launchpad (build 16540)\n" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:24 +#, python-format +msgid "Username" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:12 +#: view:res.users:0 +#, python-format +msgid "OpenID" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:30 +#: field:res.users,openid_url:0 +#, python-format +msgid "OpenID URL" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:9 +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:10 +#, python-format +msgid "Google" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:11 +#, python-format +msgid "Launchpad" +msgstr "" + +#. module: auth_openid +#: help:res.users,openid_email:0 +msgid "Used for disambiguation in case of a shared OpenID URL" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:18 +#, python-format +msgid "Google Apps Domain" +msgstr "" + +#. module: auth_openid +#: field:res.users,openid_email:0 +msgid "OpenID Email" +msgstr "" + +#. module: auth_openid +#: field:res.users,openid_key:0 +msgid "OpenID Key" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:8 +#, python-format +msgid "Password" +msgstr "" + +#. module: auth_openid +#. openerp-web +#: code:addons/auth_openid/static/src/xml/auth_openid.xml:10 +#, python-format +msgid "Google Apps" +msgstr "" + +#. module: auth_openid +#: model:ir.model,name:auth_openid.model_res_users +msgid "Users" +msgstr "" diff --git a/addons/auth_openid/res_users.py b/addons/auth_openid/res_users.py index feea2d8d396..47e119f2a1e 100644 --- a/addons/auth_openid/res_users.py +++ b/addons/auth_openid/res_users.py @@ -91,7 +91,6 @@ class res_users(osv.osv): raise self._uid_cache.setdefault(db, {})[uid] = passwd -res_users() diff --git a/addons/auth_signup/i18n/cs.po b/addons/auth_signup/i18n/cs.po new file mode 100644 index 00000000000..ee9cf157cdd --- /dev/null +++ b/addons/auth_signup/i18n/cs.po @@ -0,0 +1,279 @@ +# Czech 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-03-31 16:45+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\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/es_CO.po b/addons/auth_signup/i18n/es_CO.po new file mode 100644 index 00000000000..eb590e320ac --- /dev/null +++ b/addons/auth_signup/i18n/es_CO.po @@ -0,0 +1,298 @@ +# Spanish (Colombia) 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-03-21 21:49+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Colombia) \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-22 04:57+0000\n" +"X-Generator: Launchpad (build 16532)\n" + +#. module: auth_signup +#: field:res.partner,signup_type:0 +msgid "Signup Token Type" +msgstr "Tipo de palabra de ingreso" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_uninvited:0 +msgid "Allow external users to sign up" +msgstr "Permitir ingreso a usuarios externos" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:16 +#, python-format +msgid "Confirm Password" +msgstr "Confirmar Contraseña" + +#. module: auth_signup +#: help:base.config.settings,auth_signup_uninvited:0 +msgid "If unchecked, only invited users may sign up." +msgstr "Si no está marcado, sólo los usuarios invitados pueden ingresar." + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_base_config_settings +msgid "base.config.settings" +msgstr "base.config.settings" + +#. module: auth_signup +#: code:addons/auth_signup/res_users.py:265 +#, python-format +msgid "Cannot send email: user has no email address." +msgstr "" +"No se pudo enviar el correo eléctronico: el usuario no tiene dirección de " +"correo." + +#. 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 "Restablecer contraseña" + +#. module: auth_signup +#: field:base.config.settings,auth_signup_template_user_id:0 +msgid "Template user for new users created through signup" +msgstr "" +"Plantilla de usuario para los nuevos usuarios creados a través del ingreso" + +#. module: auth_signup +#: model:email.template,subject:auth_signup.reset_password_email +msgid "Password reset" +msgstr "Restablecer contraseña" + +#. 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 "Por favor introduzca una contraseña y confírmela." + +#. 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 "Registro" + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "New" +msgstr "Nuevo(a)" + +#. 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 "Estado" + +#. module: auth_signup +#: model:email.template,body_html:auth_signup.reset_password_email +msgid "" +"\n" +"

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

\n" +"\n" +"

You may change your password by following this link.

\n" +"\n" +"

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

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

Se ha solicitado un cambio de contraseña dedse la cuenta de OpenERP " +"asociada con este correo eléctronico.

\n" +"\n" +"

Debería cambiar su contraseña siguiendo este enlace.

\n" +"\n" +"

Nota: Si no espera estanotificación, puede ignorarla de forma segura.

" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:111 +#, python-format +msgid "Please enter a name." +msgstr "Por favor, introduzca un nombre." + +#. module: auth_signup +#: model:ir.model,name:auth_signup.model_res_users +msgid "Users" +msgstr "Usuarios" + +#. module: auth_signup +#: field:res.partner,signup_url:0 +msgid "Signup URL" +msgstr "URL de Ingreso" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:114 +#, python-format +msgid "Please enter a username." +msgstr "Por favor, introduzca un nombre de usuario." + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "Active" +msgstr "Activo(a)" + +#. 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 "" +"No se puede enviar el correo electrónico: no se ha configurado un servidor " +"de correo saliente.\n" +"Puede configurarlo en Configuración / Configuraciones Generales." + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:12 +#, python-format +msgid "Username" +msgstr "Nombre de Usuario" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:8 +#, python-format +msgid "Name" +msgstr "Nombre" + +#. 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 "" +"Por favor ingresea un Nombre de Usuario o dirección de correo electrónico." + +#. module: auth_signup +#: selection:res.users,state:0 +msgid "Resetting Password" +msgstr "Restableciendo la Contraseña" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:13 +#, python-format +msgid "Username (Email)" +msgstr "Nombre de Usuario (Dirección de correo electrónico)" + +#. module: auth_signup +#: field:res.partner,signup_expiration:0 +msgid "Signup Expiration" +msgstr "Vencimiento del Ingreso" + +#. 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 "" +"Esto permite a los usuarios lanzar un restablecimiento de la contraseña " +"desde la página de Inicio de Sesión." + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:22 +#, python-format +msgid "Log in" +msgstr "Iniciar Sesión" + +#. module: auth_signup +#: field:res.partner,signup_valid:0 +msgid "Signup Token is Valid" +msgstr "La Palabra de Ingreso es Válida" + +#. 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 "Inicio de Sesión" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/js/auth_signup.js:94 +#, python-format +msgid "Invalid signup token" +msgstr "Palabra de ingreso no válida" + +#. 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 "Las contraseñas no coinciden. Por favor vuelva a escribirlas." + +#. 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 "No se ha seleccionado ninguna base de datos!" + +#. 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 "" +"Habilitar restablecimiento de la contraseña desde la página de Inicio de " +"Sesión" + +#. module: auth_signup +#. openerp-web +#: code:addons/auth_signup/static/src/xml/auth_signup.xml:27 +#, python-format +msgid "Back to Login" +msgstr "Volver al Inicio de Sesión" + +#. 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 "Empresa/Cliente" + +#. module: auth_signup +#: field:res.partner,signup_token:0 +msgid "Signup Token" +msgstr "Palabra de Ingreso" 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..f4a985280ac 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -200,6 +200,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 diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 62c808ed556..9d7d4d34ac4 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -96,7 +96,7 @@ class base_action_rule(osv.osv): """ filter the list record_ids that satisfy the action filter """ if record_ids and action_filter: assert action.model == action_filter.model_id, "Filter model different from action rule model" - model = self.pool.get(action_filter.model_id) + model = self.pool[action_filter.model_id] domain = [('id', 'in', record_ids)] + eval(action_filter.domain) ctx = dict(context or {}) ctx.update(eval(action_filter.context)) @@ -106,7 +106,7 @@ class base_action_rule(osv.osv): def _process(self, cr, uid, action, record_ids, context=None): """ process the given action on the records """ # execute server actions - model = self.pool.get(action.model_id.model) + model = self.pool[action.model_id.model] if action.server_action_ids: server_action_ids = map(int, action.server_action_ids) for record in model.browse(cr, uid, record_ids, context): @@ -195,7 +195,7 @@ class base_action_rule(osv.osv): ids = self.search(cr, SUPERUSER_ID, []) for action_rule in self.browse(cr, SUPERUSER_ID, ids): model = action_rule.model_id.model - model_obj = self.pool.get(model) + model_obj = self.pool[model] if not hasattr(model_obj, 'base_action_ruled'): model_obj.create = self._wrap_create(model_obj.create, model) model_obj.write = self._wrap_write(model_obj.write, model) @@ -232,7 +232,7 @@ class base_action_rule(osv.osv): last_run = get_datetime(action.last_run) if action.last_run else False # retrieve all the records that satisfy the action's condition - model = self.pool.get(action.model_id.model) + model = self.pool[action.model_id.model] domain = [] ctx = dict(context) if action.filter_id: diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml index 4e551fa21c5..5eaaf08dad4 100644 --- a/addons/base_action_rule/base_action_rule_view.xml +++ b/addons/base_action_rule/base_action_rule_view.xml @@ -27,8 +27,8 @@ - - + + diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index ca75c9e20fc..896349ec5e6 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -591,7 +591,7 @@ property or property parameter."), for vals in self.browse(cr, uid, ids, context=context): if vals.ref and vals.ref.user_id: - mod_obj = self.pool.get(vals.ref._name) + mod_obj = self.pool[vals.ref._name] res=mod_obj.read(cr,uid,[vals.ref.id],['duration','class'],context) defaults = {'user_id': vals.user_id.id, 'organizer_id': vals.ref.user_id.id,'duration':res[0]['duration'],'class':res[0]['class']} mod_obj.copy(cr, uid, vals.ref.id, default=defaults, context=context) @@ -632,7 +632,6 @@ property or property parameter."), res = super(calendar_attendee, self).create(cr, uid, vals, context=context) return res -calendar_attendee() class res_alarm(osv.osv): """Resource Alarm """ @@ -684,7 +683,7 @@ true, it will allow you to hide the event alarm information without removing it. ir_obj = self.pool.get('ir.model') model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0] - model_obj = self.pool.get(model) + model_obj = self.pool[model] for data in model_obj.browse(cr, uid, ids, context=context): basic_alarm = data.alarm_id @@ -754,7 +753,7 @@ true, it will allow you to hide the event alarm information without removing it. alarm_obj = self.pool.get('calendar.alarm') ir_obj = self.pool.get('ir.model') model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0] - model_obj = self.pool.get(model) + model_obj = self.pool[model] for data in model_obj.browse(cr, uid, ids, context=context): alarm_ids = alarm_obj.search(cr, uid, [('model_id', '=', model_id), ('res_id', '=', data.id)]) if alarm_ids: @@ -763,7 +762,6 @@ true, it will allow you to hide the event alarm information without removing it. where id=%%s' % model_obj._table,(data.id,)) return True -res_alarm() class calendar_alarm(osv.osv): _name = 'calendar.alarm' @@ -853,13 +851,15 @@ class calendar_alarm(osv.osv): for alarm in self.browse(cr, uid, alarm_ids, context=context): next_trigger_date = None update_vals = {} - model_obj = self.pool.get(alarm.model_id.model) + model_obj = self.pool[alarm.model_id.model] res_obj = model_obj.browse(cr, uid, alarm.res_id, context=context) re_dates = [] if hasattr(res_obj, 'rrule') and res_obj.rrule: event_date = datetime.strptime(res_obj.date, '%Y-%m-%d %H:%M:%S') - recurrent_dates = get_recurrent_dates(res_obj.rrule, res_obj.exdate, event_date, res_obj.exrule) + #exdate is a string and we need a list + exdate = res_obj.exdate and res_obj.exdate.split(',') or [] + recurrent_dates = get_recurrent_dates(res_obj.rrule, exdate, event_date, res_obj.exrule) trigger_interval = alarm.trigger_interval if trigger_interval == 'days': @@ -916,7 +916,6 @@ From: self.write(cr, uid, [alarm.id], update_vals) return True -calendar_alarm() class calendar_event(osv.osv): @@ -1608,7 +1607,6 @@ rule or repeating pattern of time to exclude from the recurring rule."), """ return self.write(cr, uid, ids, {'state': 'confirmed'}, context) -calendar_event() class calendar_todo(osv.osv): """ Calendar Task """ @@ -1657,7 +1655,6 @@ class calendar_todo(osv.osv): __attribute__ = {} -calendar_todo() class ir_values(osv.osv): @@ -1702,7 +1699,6 @@ class ir_values(osv.osv): return super(ir_values, self).get(cr, uid, key, key2, new_model, \ meta, context, res_id_req, without_user, key2_req) -ir_values() class ir_model(osv.osv): @@ -1728,7 +1724,6 @@ class ir_model(osv.osv): val['id'] = base_calendar_id2real_id(val['id']) return isinstance(ids, (str, int, long)) and data[0] or data -ir_model() original_exp_report = openerp.service.report.exp_report diff --git a/addons/base_calendar/base_calendar_data.xml b/addons/base_calendar/base_calendar_data.xml index 727a0703db2..64aa7ba59b6 100644 --- a/addons/base_calendar/base_calendar_data.xml +++ b/addons/base_calendar/base_calendar_data.xml @@ -126,7 +126,7 @@ Run Event Reminder - 1 + 5 minutes -1 diff --git a/addons/base_calendar/crm_meeting.py b/addons/base_calendar/crm_meeting.py index 6010f5ccfca..aa476002abc 100644 --- a/addons/base_calendar/crm_meeting.py +++ b/addons/base_calendar/crm_meeting.py @@ -135,7 +135,7 @@ class mail_message(osv.osv): def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None): if doc_model == 'crm.meeting': - for virtual_id in self.pool.get(doc_model).get_recurrent_ids(cr, uid, doc_dict.keys(), [], context=context): + for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], context=context): doc_dict.setdefault(virtual_id, doc_dict[get_real_ids(virtual_id)]) return super(mail_message, self)._find_allowed_model_wise(cr, uid, doc_model, doc_dict, context=context) diff --git a/addons/base_crypt/i18n/nl_BE.po b/addons/base_crypt/i18n/nl_BE.po index 7ad3faa1ef5..d77a3f14b47 100644 --- a/addons/base_crypt/i18n/nl_BE.po +++ b/addons/base_crypt/i18n/nl_BE.po @@ -8,19 +8,19 @@ 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" +"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: 2013-03-16 05:49+0000\n" -"X-Generator: Launchpad (build 16532)\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 msgid "Users" -msgstr "" +msgstr "Gebruikers" #~ msgid "You can not have two users with the same login !" #~ msgstr "U kunt geen twee gebruikers met dezelfde login maken." diff --git a/addons/base_gengo/i18n/cs.po b/addons/base_gengo/i18n/cs.po new file mode 100644 index 00000000000..91dc5ea941d --- /dev/null +++ b/addons/base_gengo/i18n/cs.po @@ -0,0 +1,249 @@ +# Czech 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-03-31 16:46+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: base_gengo +#: view:res.company:0 +msgid "Comments for Translator" +msgstr "" + +#. module: base_gengo +#: field:ir.translation,job_id:0 +msgid "Gengo Job ID" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/wizard/base_gengo_translations.py:114 +#, python-format +msgid "This language is not supported by the Gengo translation services." +msgstr "" + +#. module: base_gengo +#: field:res.company,gengo_comment:0 +msgid "Comments" +msgstr "" + +#. module: base_gengo +#: field:res.company,gengo_private_key:0 +msgid "Gengo Private Key" +msgstr "" + +#. module: base_gengo +#: model:ir.model,name:base_gengo.model_base_gengo_translations +msgid "base.gengo.translations" +msgstr "" + +#. module: base_gengo +#: help:res.company,gengo_auto_approve:0 +msgid "Jobs are Automatically Approved by Gengo." +msgstr "" + +#. module: base_gengo +#: field:base.gengo.translations,lang_id:0 +msgid "Language" +msgstr "" + +#. module: base_gengo +#: field:ir.translation,gengo_comment:0 +msgid "Comments & Activity Linked to Gengo" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/wizard/base_gengo_translations.py:124 +#, python-format +msgid "Gengo Sync Translation (Response)" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/wizard/base_gengo_translations.py:72 +#, python-format +msgid "" +"Gengo `Public Key` or `Private Key` are missing. Enter your Gengo " +"authentication parameters under `Settings > Companies > Gengo Parameters`." +msgstr "" + +#. module: base_gengo +#: selection:ir.translation,gengo_translation:0 +msgid "Translation By Machine" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/wizard/base_gengo_translations.py:155 +#, python-format +msgid "" +"%s\n" +"\n" +"--\n" +" Commented on %s by %s." +msgstr "" + +#. module: base_gengo +#: field:ir.translation,gengo_translation:0 +msgid "Gengo Translation Service Level" +msgstr "" + +#. module: base_gengo +#: constraint:ir.translation:0 +msgid "" +"The Gengo translation service selected is not supported for this language." +msgstr "" + +#. module: base_gengo +#: selection:ir.translation,gengo_translation:0 +msgid "Standard" +msgstr "" + +#. module: base_gengo +#: help:ir.translation,gengo_translation:0 +msgid "" +"You can select here the service level you want for an automatic translation " +"using Gengo." +msgstr "" + +#. module: base_gengo +#: field:base.gengo.translations,restart_send_job:0 +msgid "Restart Sending Job" +msgstr "" + +#. module: base_gengo +#: view:ir.translation:0 +msgid "To Approve In Gengo" +msgstr "" + +#. module: base_gengo +#: view:res.company:0 +msgid "Private Key" +msgstr "" + +#. module: base_gengo +#: view:res.company:0 +msgid "Public Key" +msgstr "" + +#. module: base_gengo +#: field:res.company,gengo_public_key:0 +msgid "Gengo Public Key" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/wizard/base_gengo_translations.py:123 +#, python-format +msgid "Gengo Sync Translation (Request)" +msgstr "" + +#. module: base_gengo +#: view:ir.translation:0 +msgid "Translations" +msgstr "" + +#. module: base_gengo +#: field:res.company,gengo_auto_approve:0 +msgid "Auto Approve Translation ?" +msgstr "" + +#. module: base_gengo +#: model:ir.actions.act_window,name:base_gengo.action_wizard_base_gengo_translations +#: model:ir.ui.menu,name:base_gengo.menu_action_wizard_base_gengo_translations +msgid "Gengo: Manual Request of Translation" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/ir_translation.py:62 +#: code:addons/base_gengo/wizard/base_gengo_translations.py:109 +#, python-format +msgid "Gengo Authentication Error" +msgstr "" + +#. module: base_gengo +#: model:ir.model,name:base_gengo.model_res_company +msgid "Companies" +msgstr "" + +#. module: base_gengo +#: view:ir.translation:0 +msgid "" +"Note: If the translation state is 'In Progress', it means that the " +"translation has to be approved to be uploaded in this system. You are " +"supposed to do that directly by using your Gengo Account" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/wizard/base_gengo_translations.py:82 +#, python-format +msgid "" +"Gengo connection failed with this message:\n" +"``%s``" +msgstr "" + +#. module: base_gengo +#: view:res.company:0 +msgid "Gengo Parameters" +msgstr "" + +#. module: base_gengo +#: view:base.gengo.translations:0 +msgid "Send" +msgstr "" + +#. module: base_gengo +#: selection:ir.translation,gengo_translation:0 +msgid "Ultra" +msgstr "" + +#. module: base_gengo +#: model:ir.model,name:base_gengo.model_ir_translation +msgid "ir.translation" +msgstr "" + +#. module: base_gengo +#: view:ir.translation:0 +msgid "Gengo Translation Service" +msgstr "" + +#. module: base_gengo +#: selection:ir.translation,gengo_translation:0 +msgid "Pro" +msgstr "" + +#. module: base_gengo +#: view:base.gengo.translations:0 +msgid "Gengo Request Form" +msgstr "" + +#. module: base_gengo +#: code:addons/base_gengo/wizard/base_gengo_translations.py:114 +#, python-format +msgid "Warning" +msgstr "" + +#. module: base_gengo +#: help:res.company,gengo_comment:0 +msgid "" +"This comment will be automatically be enclosed in each an every request sent " +"to Gengo" +msgstr "" + +#. module: base_gengo +#: view:base.gengo.translations:0 +msgid "Cancel" +msgstr "" + +#. module: base_gengo +#: view:base.gengo.translations:0 +msgid "or" +msgstr "" diff --git a/addons/base_iban/base_iban.py b/addons/base_iban/base_iban.py index 0872af2d0f3..d50ca33ff15 100644 --- a/addons/base_iban/base_iban.py +++ b/addons/base_iban/base_iban.py @@ -181,6 +181,5 @@ class res_partner_bank(osv.osv): (_check_bank, '\nPlease define BIC/Swift code on bank for bank type IBAN Account to make valid payments', ['bic']) ] -res_partner_bank() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_import/i18n/cs.po b/addons/base_import/i18n/cs.po new file mode 100644 index 00000000000..e49e2198de7 --- /dev/null +++ b/addons/base_import/i18n/cs.po @@ -0,0 +1,1164 @@ +# Czech 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-03-31 16:46+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:451 +#, python-format +msgid "Get all possible values" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:71 +#, python-format +msgid "Need to import data from an other application?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:163 +#, python-format +msgid "" +"When you use External IDs, you can import CSV files \n" +" with the \"External ID\" column to define the " +"External \n" +" ID of each record you import. Then, you will be able " +"\n" +" to make a reference to that record with columns like " +"\n" +" \"Field/External ID\". The following two CSV files " +"give \n" +" you an example for Products and their Categories." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:271 +#, python-format +msgid "" +"How to export/import different tables from an SQL \n" +" application to OpenERP?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:331 +#, python-format +msgid "Relation Fields" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:142 +#, python-format +msgid "" +"Country/Database ID: the unique OpenERP ID for a \n" +" record, defined by the ID postgresql column" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:155 +#, python-format +msgid "" +"Use \n" +" Country/Database ID: You should rarely use this \n" +" notation. It's mostly used by developers as it's " +"main \n" +" advantage is to never have conflicts (you may have \n" +" several records with the same name, but they always " +"\n" +" have a unique Database ID)" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:146 +#, python-format +msgid "" +"For the country \n" +" Belgium, you can use one of these 3 ways to import:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:303 +#, python-format +msgid "company_1,Bigees,True" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_m2o +msgid "base_import.tests.models.m2o" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:297 +#, python-format +msgid "" +"copy \n" +" (select 'company_'||id as \"External " +"ID\",company_name \n" +" as \"Name\",'True' as \"Is a Company\" from " +"companies) TO \n" +" '/tmp/company.csv' with CSV HEADER;" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:206 +#, python-format +msgid "CSV file for Manufacturer, Retailer" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:160 +#, python-format +msgid "" +"Use \n" +" Country/External ID: Use External ID when you import " +"\n" +" data from a third party application." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:316 +#, python-format +msgid "person_1,Fabien,False,company_1" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:80 +#, python-format +msgid "XXX/External ID" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:351 +#, python-format +msgid "Don't Import" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:24 +#, python-format +msgid "Select the" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:100 +#, python-format +msgid "" +"Note that if your CSV file \n" +" has a tabulation as separator, OpenERP will not \n" +" detect the separations. You will need to change the " +"\n" +" file format options in your spreadsheet application. " +"\n" +" See the following question." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:141 +#, python-format +msgid "Country: the name or code of the country" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_o2m_child +msgid "base_import.tests.models.o2m.child" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:239 +#, python-format +msgid "Can I import several times the same record?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:15 +#, python-format +msgid "Validate" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:55 +#, python-format +msgid "Map your data to OpenERP" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:153 +#, python-format +msgid "" +"Use Country: This is \n" +" the easiest way when your data come from CSV files \n" +" that have been created manually." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:127 +#, python-format +msgid "" +"What's the difference between Database ID and \n" +" External ID?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:138 +#, python-format +msgid "" +"For example, to \n" +" reference the country of a contact, OpenERP proposes " +"\n" +" you 3 different fields to import:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:175 +#, python-format +msgid "What can I do if I have multiple matches for a field?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:302 +#, python-format +msgid "External ID,Name,Is a Company" +msgstr "" + +#. module: base_import +#: field:base_import.tests.models.preview,somevalue:0 +msgid "Some Value" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:231 +#, python-format +msgid "" +"The following CSV file shows how to import \n" +" suppliers and their respective contacts" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:109 +#, python-format +msgid "" +"How can I change the CSV file format options when \n" +" saving in my spreadsheet application?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:320 +#, python-format +msgid "" +"As you can see in this file, Fabien and Laurence \n" +" are working for the Bigees company (company_1) and \n" +" Eric is working for the Organi company. The relation " +"\n" +" between persons and companies is done using the \n" +" External ID of the companies. We had to prefix the \n" +" \"External ID\" by the name of the table to avoid a " +"\n" +" conflict of ID between persons and companies " +"(person_1 \n" +" and company_1 who shared the same ID 1 in the " +"orignial \n" +" database)." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:308 +#, python-format +msgid "" +"copy (select \n" +" 'person_'||id as \"External ID\",person_name as \n" +" \"Name\",'False' as \"Is a " +"Company\",'company_'||company_id\n" +" as \"Related Company/External ID\" from persons) TO " +"\n" +" '/tmp/person.csv' with CSV" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:148 +#, python-format +msgid "Country: Belgium" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_char_stillreadonly +msgid "base_import.tests.models.char.stillreadonly" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:314 +#, python-format +msgid "" +"External ID,Name,Is a \n" +" Company,Related Company/External ID" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:233 +#, python-format +msgid "Suppliers and their respective contacts" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:179 +#, python-format +msgid "" +"If for example you have two product categories \n" +" with the child name \"Sellable\" (ie. \"Misc. \n" +" Products/Sellable\" & \"Other Products/Sellable\"),\n" +" your validation is halted but you may still import \n" +" your data. However, we recommend you do not import " +"the \n" +" data because they will all be linked to the first \n" +" 'Sellable' category found in the Product Category " +"list \n" +" (\"Misc. Products/Sellable\"). We recommend you " +"modify \n" +" one of the duplicates' values or your product " +"category \n" +" hierarchy." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:306 +#, python-format +msgid "" +"To create the CSV file for persons, linked to \n" +" companies, we will use the following SQL command in " +"\n" +" PSQL:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:119 +#, python-format +msgid "" +"Microsoft Excel will allow \n" +" you to modify only the encoding when saving \n" +" (in 'Save As' dialog box > click 'Tools' dropdown \n" +" list > Encoding tab)." +msgstr "" + +#. module: base_import +#: field:base_import.tests.models.preview,othervalue:0 +msgid "Other Variable" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:82 +#, python-format +msgid "" +"will also be used to update the original\n" +" import if you need to re-import modified data\n" +" later, it's thus good practice to specify it\n" +" whenever possible" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:26 +#, python-format +msgid "" +"file to import. If you need a sample importable file, you\n" +" can use the export tool to generate one." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:148 +#, python-format +msgid "" +"Country/Database \n" +" ID: 21" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_char +msgid "base_import.tests.models.char" +msgstr "" + +#. module: base_import +#: help:base_import.import,file:0 +msgid "File to check and/or import, raw binary (not base64)" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:230 +#, python-format +msgid "Purchase orders with their respective purchase order lines" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:60 +#, python-format +msgid "" +"If the file contains\n" +" the column names, OpenERP can try auto-detecting the\n" +" field corresponding to the column. This makes imports\n" +" simpler especially when the file has many columns." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:26 +#, python-format +msgid ".CSV" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:360 +#, python-format +msgid "" +". The issue is\n" +" usually an incorrect file encoding." +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_m2o_required +msgid "base_import.tests.models.m2o.required" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_char_noreadonly +msgid "base_import.tests.models.char.noreadonly" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:113 +#, python-format +msgid "" +"If you edit and save CSV files in speadsheet \n" +" applications, your computer's regional settings will " +"\n" +" be applied for the separator and delimiter. \n" +" We suggest you use OpenOffice or LibreOffice Calc \n" +" as they will allow you to modify all three options \n" +" (in 'Save As' dialog box > Check the box 'Edit " +"filter \n" +" settings' > Save)." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:30 +#, python-format +msgid "CSV File:" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_preview +msgid "base_import.tests.models.preview" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_char_required +msgid "base_import.tests.models.char.required" +msgstr "" + +#. module: base_import +#: code:addons/base_import/models.py:112 +#, python-format +msgid "Database ID" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:313 +#, python-format +msgid "It will produce the following CSV file:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:362 +#, python-format +msgid "Here is the start of the file we could not import:" +msgstr "" + +#. module: base_import +#: field:base_import.import,file_type:0 +msgid "File Type" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_import +msgid "base_import.import" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_o2m +msgid "base_import.tests.models.o2m" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:360 +#, python-format +msgid "Import preview failed due to:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:144 +#, python-format +msgid "" +"Country/External ID: the ID of this record \n" +" referenced in another application (or the .XML file " +"\n" +" that imported it)" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:35 +#, python-format +msgid "Reload data to check changes." +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_char_readonly +msgid "base_import.tests.models.char.readonly" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:131 +#, python-format +msgid "" +"Some fields define a relationship with another \n" +" object. For example, the country of a contact is a \n" +" link to a record of the 'Country' object. When you \n" +" want to import such fields, OpenERP will have to \n" +" recreate links between the different records. \n" +" To help you import such fields, OpenERP provides 3 \n" +" mechanisms. You must use one and only one mechanism " +"\n" +" per field you want to import." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:201 +#, python-format +msgid "" +"The tags should be separated by a comma without any \n" +" spacing. For example, if you want you customer to be " +"\n" +" lined to both tags 'Manufacturer' and 'Retailer' \n" +" then you will encode it as follow \"Manufacturer,\n" +" Retailer\" in the same column of your CSV file." +msgstr "" + +#. module: base_import +#: code:addons/base_import/models.py:264 +#, python-format +msgid "You must configure at least one field to import" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:304 +#, python-format +msgid "company_2,Organi,True" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:58 +#, python-format +msgid "" +"The first row of the\n" +" file contains the label of the column" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_char_states +msgid "base_import.tests.models.char.states" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:7 +#, python-format +msgid "Import a CSV File" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:74 +#, python-format +msgid "Quoting:" +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_m2o_required_related +msgid "base_import.tests.models.m2o.required.related" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:293 +#, python-format +msgid ")." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:18 +#: code:addons/base_import/static/src/xml/import.xml:396 +#, python-format +msgid "Import" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:438 +#, python-format +msgid "Here are the possible values:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:82 +#, python-format +msgid "The" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:248 +#, python-format +msgid "" +"A single column was found in the file, this often means the file separator " +"is incorrect" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:293 +#, python-format +msgid "dump of such a PostgreSQL database" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:301 +#, python-format +msgid "This SQL command will create the following CSV file:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:228 +#, python-format +msgid "" +"The following CSV file shows how to import purchase \n" +" orders with their respective purchase order lines:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:91 +#, python-format +msgid "" +"What can I do when the Import preview table isn't \n" +" displayed correctly?" +msgstr "" + +#. module: base_import +#: field:base_import.tests.models.char,value:0 +#: field:base_import.tests.models.char.noreadonly,value:0 +#: field:base_import.tests.models.char.readonly,value:0 +#: field:base_import.tests.models.char.required,value:0 +#: field:base_import.tests.models.char.states,value:0 +#: field:base_import.tests.models.char.stillreadonly,value:0 +#: field:base_import.tests.models.m2o,value:0 +#: field:base_import.tests.models.m2o.related,value:0 +#: field:base_import.tests.models.m2o.required,value:0 +#: field:base_import.tests.models.m2o.required.related,value:0 +#: field:base_import.tests.models.o2m,value:0 +#: field:base_import.tests.models.o2m.child,parent_id:0 +#: field:base_import.tests.models.o2m.child,value:0 +msgid "unknown" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:317 +#, python-format +msgid "person_2,Laurence,False,company_1" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:149 +#, python-format +msgid "Country/External ID: base.be" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:288 +#, python-format +msgid "" +"As an example, suppose you have a SQL database \n" +" with two tables you want to import: companies and \n" +" persons. Each person belong to one company, so you \n" +" will have to recreate the link between a person and " +"\n" +" the company he work for. (If you want to test this \n" +" example, here is a" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:427 +#, python-format +msgid "(%d more)" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:227 +#, python-format +msgid "File for some Quotations" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:72 +#, python-format +msgid "Encoding:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:280 +#, python-format +msgid "" +"To manage relations between tables, \n" +" you can use the \"External ID\" facilities of " +"OpenERP. \n" +" The \"External ID\" of a record is the unique " +"identifier \n" +" of this record in another application. This " +"\"External \n" +" ID\" must be unique accoss all the records of all \n" +" objects, so it's a good practice to prefix this \n" +" \"External ID\" with the name of the application or " +"\n" +" table. (like 'company_1', 'person_1' instead of '1')" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:295 +#, python-format +msgid "" +"We will first export all companies and their \n" +" \"External ID\". In PSQL, write the following " +"command:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:212 +#, python-format +msgid "" +"How can I import a one2many relationship (e.g. several \n" +" Order Lines of a Sales Order)?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:404 +#, python-format +msgid "Everything seems valid." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:188 +#, python-format +msgid "" +"However if you do not wish to change your \n" +" configuration of product categories, we recommend " +"you \n" +" use make use of the external ID for this field \n" +" 'Category'." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:421 +#, python-format +msgid "at row %d" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:197 +#, python-format +msgid "" +"How can I import a many2many relationship field \n" +" (e.g. a customer that has multiple tags)?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:80 +#, python-format +msgid "XXX/ID" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:275 +#, python-format +msgid "" +"If you need to import data from different tables, \n" +" you will have to recreate relations between records " +"\n" +" belonging to different tables. (e.g. if you import \n" +" companies and persons, you will have to recreate the " +"\n" +" link between each person and the company they work \n" +" for)." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:150 +#, python-format +msgid "" +"According to your need, you should use \n" +" one of these 3 ways to reference records in " +"relations. \n" +" Here is when you should use one or the other, \n" +" according to your need:" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:319 +#, python-format +msgid "person_4,Ramsy,False,company_3" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:261 +#, python-format +msgid "" +"If you do not set all fields in your CSV file, \n" +" OpenERP will assign the default value for every non " +"\n" +" defined fields. But if you\n" +" set fields with empty values in your CSV file, " +"OpenERP \n" +" will set the EMPTY value in the field, instead of \n" +" assigning the default value." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:20 +#, python-format +msgid "Cancel" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:257 +#, python-format +msgid "" +"What happens if I do not provide a value for a \n" +" specific field?" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:68 +#, python-format +msgid "Frequently Asked Questions" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:305 +#, python-format +msgid "company_3,Boum,True" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:249 +#, python-format +msgid "" +"This feature \n" +" allows you to use the Import/Export tool of OpenERP " +"to \n" +" modify a batch of records in your favorite " +"spreadsheet \n" +" application." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:77 +#, python-format +msgid "" +"column in OpenERP. When you\n" +" import an other record that links to the first\n" +" one, use" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:242 +#, python-format +msgid "" +"If you import a file that contains one of the \n" +" column \"External ID\" or \"Database ID\", records " +"that \n" +" have already been imported will be modified instead " +"of \n" +" being created. This is very usefull as it allows you " +"\n" +" to import several times the same CSV file while " +"having \n" +" made some changes in between two imports. OpenERP " +"will \n" +" take care of creating or modifying each record \n" +" depending if it's new or not." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:169 +#, python-format +msgid "CSV file for categories" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:330 +#, python-format +msgid "Normal Fields" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:74 +#, python-format +msgid "" +"In order to re-create relationships between\n" +" different records, you should use the unique\n" +" identifier from the original application and\n" +" map it to the" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:170 +#, python-format +msgid "CSV file for Products" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:216 +#, python-format +msgid "" +"If you want to import sales order having several \n" +" order lines; for each order line, you need to " +"reserve \n" +" a specific row in the CSV file. The first order line " +"\n" +" will be imported on the same row as the information " +"\n" +" relative to order. Any additional lines will need an " +"\n" +" addtional row that does not have any information in " +"\n" +" the fields relative to the order." +msgstr "" + +#. module: base_import +#: model:ir.model,name:base_import.model_base_import_tests_models_m2o_related +msgid "base_import.tests.models.m2o.related" +msgstr "" + +#. module: base_import +#: field:base_import.tests.models.preview,name:0 +msgid "Name" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:80 +#, python-format +msgid "to the original unique identifier." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:318 +#, python-format +msgid "person_3,Eric,False,company_2" +msgstr "" + +#. module: base_import +#: field:base_import.import,res_model:0 +msgid "Model" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:77 +#: code:addons/base_import/static/src/xml/import.xml:82 +#, python-format +msgid "ID" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:329 +#, python-format +msgid "" +"The two files produced are ready to be imported in \n" +" OpenERP without any modifications. After having \n" +" imported these two CSV files, you will have 4 " +"contacts \n" +" and 3 companies. (the firsts two contacts are linked " +"\n" +" to the first company). You must first import the \n" +" companies and then the persons." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:95 +#, python-format +msgid "" +"By default the Import preview is set on commas as \n" +" field separators and quotation marks as text \n" +" delimiters. If your csv file does not have these \n" +" settings, you can modify the File Format Options \n" +" (displayed under the Browse CSV file bar after you \n" +" select your file)." +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:73 +#, python-format +msgid "Separator:" +msgstr "" + +#. module: base_import +#: field:base_import.import,file_name:0 +msgid "File Name" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/models.py:80 +#: code:addons/base_import/models.py:111 +#: code:addons/base_import/static/src/xml/import.xml:77 +#: code:addons/base_import/static/src/xml/import.xml:82 +#, python-format +msgid "External ID" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:39 +#, python-format +msgid "File Format Options…" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/js/import.js:423 +#, python-format +msgid "between rows %d and %d" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:19 +#, python-format +msgid "or" +msgstr "" + +#. module: base_import +#. openerp-web +#: code:addons/base_import/static/src/xml/import.xml:223 +#, python-format +msgid "" +"As an example, here is \n" +" purchase.order_functional_error_line_cant_adpat.CSV " +"\n" +" file of some quotations you can import, based on " +"demo \n" +" data." +msgstr "" + +#. module: base_import +#: field:base_import.import,file:0 +msgid "File" +msgstr "" diff --git a/addons/base_import/i18n/hu.po b/addons/base_import/i18n/hu.po index 2c3c4e60ab2..db143a0f032 100644 --- a/addons/base_import/i18n/hu.po +++ b/addons/base_import/i18n/hu.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2013-03-17 23:49+0000\n" +"PO-Revision-Date: 2013-03-27 22:52+0000\n" "Last-Translator: krnkris \n" "Language-Team: Hungarian \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-19 05:33+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-03-29 04:36+0000\n" +"X-Generator: Launchpad (build 16546)\n" #. module: base_import #. openerp-web @@ -441,6 +441,20 @@ msgid "" "category \n" " hierarchy." msgstr "" +"Például, ha két termék kategóriával rendelkezik \n" +" ezzel az al-névvel \"Értékesíthető\" (pl. \"Egyéb \n" +" Termékek/Értékesíthetők\" & \"Más " +"Termékek/Értékesíthetők\"),\n" +" akkor a jóváhagyás meg lesz állítva, de az adatait " +"még tudja \n" +" importálni. Azonban, nem ajánlott az adat betöltése " +"\n" +" mivel az összes adat az első találhat " +"'Értékesíthető' kategóriához \n" +" lesz hozzárendelve a Termék kategória listában \n" +" (\"Egyéb Termékeke/Értékesíthető\"). Ajánljuk, hogy " +"módosítsa \n" +" a termék kategória rangsor egyik ismétlődő értékét ." #. module: base_import #. openerp-web @@ -452,6 +466,9 @@ msgid "" "\n" " PSQL:" msgstr "" +"Személyekhez CVS fájl létrehozása, vállalatokhoz\n" +" kapcsolva, a következő SQL parancsot használva a \n" +" PSQL-ben:" #. module: base_import #. openerp-web @@ -463,11 +480,16 @@ msgid "" " (in 'Save As' dialog box > click 'Tools' dropdown \n" " list > Encoding tab)." msgstr "" +"Microsoft Excel lehetővé teszi\n" +" csak a kódolás módosítását az elmentés alatt \n" +" (a 'Mentés másként' párbeszéd ablakban > kattints a " +"'Kellékek' legördülő \n" +" listán > a Kódolás fülre)." #. module: base_import #: field:base_import.tests.models.preview,othervalue:0 msgid "Other Variable" -msgstr "" +msgstr "Másik változó" #. module: base_import #. openerp-web @@ -479,6 +501,11 @@ msgid "" " later, it's thus good practice to specify it\n" " whenever possible" msgstr "" +"az eredeti importálás frissítéséhez is \n" +" használja, ha később is fel akarja használni az újra-" +"importált módosított\n" +" adatot, amikor csak lehet ez egy jó gyakorlás a \n" +" meghatározáshoz" #. module: base_import #. openerp-web @@ -488,6 +515,9 @@ msgid "" "file to import. If you need a sample importable file, you\n" " can use the export tool to generate one." msgstr "" +"fájl importáláshoz, betöltéshez. Ha szüksége van egy importálható példa " +"fájlra, akkor\n" +" használhatja az export eszközt egy új generálásához." #. module: base_import #. openerp-web @@ -497,16 +527,19 @@ msgid "" "Country/Database \n" " ID: 21" msgstr "" +"Ország/Adatbázis \n" +" ID: 21" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_char msgid "base_import.tests.models.char" -msgstr "" +msgstr "base_import.tests.models.char" #. module: base_import #: help:base_import.import,file:0 msgid "File to check and/or import, raw binary (not base64)" msgstr "" +"Az importálandó és/vagy ellenőrizni kívánt fájl, nyers bináris (nem base64)" #. module: base_import #. openerp-web @@ -514,6 +547,7 @@ msgstr "" #, python-format msgid "Purchase orders with their respective purchase order lines" msgstr "" +"Beszerzési megrendelések a hozzájuk tartozó beszerzési megrendelés sorokkal" #. module: base_import #. openerp-web @@ -525,13 +559,18 @@ msgid "" " field corresponding to the column. This makes imports\n" " simpler especially when the file has many columns." msgstr "" +"Ha a fájl tartalmazza\n" +" az oszlop neveket, OpenERP megpróbálhatja automatikusan " +"észlelni\n" +" oszlophoz tartozó mezőt. Ez az importálásokat egyszerűbbé\n" +" teszi, főként, ha a fájl tele van oszlopokkal." #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:26 #, python-format msgid ".CSV" -msgstr "" +msgstr ".CSV" #. module: base_import #. openerp-web @@ -541,16 +580,18 @@ msgid "" ". The issue is\n" " usually an incorrect file encoding." msgstr "" +". A probléma\n" +" általában a téves fájl kódolás." #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_m2o_required msgid "base_import.tests.models.m2o.required" -msgstr "" +msgstr "base_import.tests.models.m2o.required" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_char_noreadonly msgid "base_import.tests.models.char.noreadonly" -msgstr "" +msgstr "base_import.tests.models.char.noreadonly" #. module: base_import #. openerp-web @@ -567,65 +608,75 @@ msgid "" "filter \n" " settings' > Save)." msgstr "" +"Ha szerkeszti és menti a CSV fájlt a táblázat kezelő \n" +" alkalmazásokban, a számítógépének területi " +"beállítása lesz \n" +" az elválasztáshoz és a határolójelekhez használva. \n" +" Ajánljuk az OpenOffice vagy LibreOffice Calc \n" +" használatát, mivel ezek lehetővé teszik mindhárom " +"lehetőség\n" +" módosítását (a 'Mentés másként' beszédpanelen > a\n" +" 'Szerkesztési szűrő beállítás' négyzetnek\n" +" a bejelölésével > Mentés)." #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:30 #, python-format msgid "CSV File:" -msgstr "" +msgstr "CSV Fájl:" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_preview msgid "base_import.tests.models.preview" -msgstr "" +msgstr "base_import.tests.models.preview" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_char_required msgid "base_import.tests.models.char.required" -msgstr "" +msgstr "base_import.tests.models.char.required" #. module: base_import #: code:addons/base_import/models.py:112 #, python-format msgid "Database ID" -msgstr "" +msgstr "Adatbázis ID azonosító" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:313 #, python-format msgid "It will produce the following CSV file:" -msgstr "" +msgstr "Ez a következő CSV fájlt fogja létrehozni:" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:362 #, python-format msgid "Here is the start of the file we could not import:" -msgstr "" +msgstr "Itt van a fájlnak az eleje, melyiket nem tudtuk importálni:" #. module: base_import #: field:base_import.import,file_type:0 msgid "File Type" -msgstr "" +msgstr "Fájl típus" #. module: base_import #: model:ir.model,name:base_import.model_base_import_import msgid "base_import.import" -msgstr "" +msgstr "base_import.import" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_o2m msgid "base_import.tests.models.o2m" -msgstr "" +msgstr "base_import.tests.models.o2m" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:360 #, python-format msgid "Import preview failed due to:" -msgstr "" +msgstr "Import előnézet ezért nem sikerült:" #. module: base_import #. openerp-web @@ -637,18 +688,22 @@ msgid "" "\n" " that imported it)" msgstr "" +"Ország/Külső ID azonosító: ennek a rekordnak az ID azonosítója\n" +" másik alkalmazásban egy hivatkozás (vagy az .XML " +"fájl \n" +" ami importálta azt)" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:35 #, python-format msgid "Reload data to check changes." -msgstr "" +msgstr "Adatok újratöltése a változások ellenőrzéséhez." #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_char_readonly msgid "base_import.tests.models.char.readonly" -msgstr "" +msgstr "base_import.tests.models.char.readonly" #. module: base_import #. openerp-web @@ -665,6 +720,18 @@ msgid "" "\n" " per field you want to import." msgstr "" +"Egyes mezők hivatkozásokat határoznak meg más \n" +" objektummal. Például, egy kapcsolat országa \n" +" csatolva van egy 'Ország' tárgyú rekorddal. Ha ilyen " +"\n" +" mezőket szeretne importálni, OpenERP újra létre " +"kell\n" +" hozza a kapcsolatokat a különböző rekordokhoz. \n" +" Ilyen mezők importálásának segítésére, OpenERP három " +"\n" +" módot biztosít. Kizárólag egy módszert használhat az " +"\n" +" importálni kívánt mezőnként." #. module: base_import #. openerp-web @@ -678,19 +745,26 @@ msgid "" " then you will encode it as follow \"Manufacturer,\n" " Retailer\" in the same column of your CSV file." msgstr "" +"A címkéket vesszővel kell elválasztani egyéb szóköz használata \n" +" nélkül. Például, ha a vevőjét két címkéhez szeretné " +"\n" +" társítani, mint 'Gyártó' és 'Kiskereskedő' \n" +" akkor azt a következő képpen kell bevinnie " +"\"Gyártó,\n" +" Kiskereskedő\" a CVS fájl ugyanazon oszlopába." #. module: base_import #: code:addons/base_import/models.py:264 #, python-format msgid "You must configure at least one field to import" -msgstr "" +msgstr "Legalább egy mezőt be kell állítania az importáláshoz" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:304 #, python-format msgid "company_2,Organi,True" -msgstr "" +msgstr "vállalat_2,Organi,Igaz" #. module: base_import #. openerp-web @@ -700,37 +774,39 @@ msgid "" "The first row of the\n" " file contains the label of the column" msgstr "" +"A fájl első oszlopa\n" +" tartalmazza az oszlop elnevezését" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_char_states msgid "base_import.tests.models.char.states" -msgstr "" +msgstr "base_import.tests.models.char.states" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:7 #, python-format msgid "Import a CSV File" -msgstr "" +msgstr "Egy CVS fájl importálása" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:74 #, python-format msgid "Quoting:" -msgstr "" +msgstr "Hivatkozni:" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_m2o_required_related msgid "base_import.tests.models.m2o.required.related" -msgstr "" +msgstr "base_import.tests.models.m2o.required.related" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:293 #, python-format msgid ")." -msgstr "" +msgstr "nkat)." #. module: base_import #. openerp-web @@ -738,21 +814,21 @@ msgstr "" #: code:addons/base_import/static/src/xml/import.xml:396 #, python-format msgid "Import" -msgstr "" +msgstr "Importálás" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:438 #, python-format msgid "Here are the possible values:" -msgstr "" +msgstr "Ezek a lehetséges értékek:" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:82 #, python-format msgid "The" -msgstr "" +msgstr "A" #. module: base_import #. openerp-web @@ -762,20 +838,22 @@ msgid "" "A single column was found in the file, this often means the file separator " "is incorrect" msgstr "" +"Egy oszlop található a fájlban, Ez sokszor azt jelenti, hogy a fájl " +"elválasztó hibás" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:293 #, python-format msgid "dump of such a PostgreSQL database" -msgstr "" +msgstr "ilyen jellegű PostgreSQL adatbázis eldobása" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:301 #, python-format msgid "This SQL command will create the following CSV file:" -msgstr "" +msgstr "Ez az SQL parancs ezt a CSV fájlt fogja létre hozni:" #. module: base_import #. openerp-web @@ -785,6 +863,9 @@ msgid "" "The following CSV file shows how to import purchase \n" " orders with their respective purchase order lines:" msgstr "" +"A következő CSV fájl megmutatja hogyan importálja a beszerzési \n" +" megrendeléseket a hozzá tartozó beszerzési " +"megrendelés sorokkal:" #. module: base_import #. openerp-web @@ -794,6 +875,8 @@ msgid "" "What can I do when the Import preview table isn't \n" " displayed correctly?" msgstr "" +"Mit tehetek, ha a kijelzőn lévő import tábla\n" +" előnézete hibás?" #. module: base_import #: field:base_import.tests.models.char,value:0 @@ -810,21 +893,21 @@ msgstr "" #: field:base_import.tests.models.o2m.child,parent_id:0 #: field:base_import.tests.models.o2m.child,value:0 msgid "unknown" -msgstr "" +msgstr "ismeretlen" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:317 #, python-format msgid "person_2,Laurence,False,company_1" -msgstr "" +msgstr "személy_2,Laurence,Hamis,vállalat_1" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:149 #, python-format msgid "Country/External ID: base.be" -msgstr "" +msgstr "Ország/Külső ID azonosító: base.be" #. module: base_import #. openerp-web @@ -839,27 +922,35 @@ msgid "" " the company he work for. (If you want to test this \n" " example, here is a" msgstr "" +"Példának, feltételezzük, hogy van egy SQL adatbázis \n" +" két importálandó táblázattal: vállalatok és \n" +" személyek. Mindegyik személy egy vállalathoz " +"tartozik, így \n" +" létre kell hozni a kapcsolatot a személyek és a " +"munkahelyi \n" +" vállalatuk közt. (Ha tesztelni szeretné \n" +" ezt a példát, itt van a" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:427 #, python-format msgid "(%d more)" -msgstr "" +msgstr "(%d több)" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:227 #, python-format msgid "File for some Quotations" -msgstr "" +msgstr "Fájl egy pár kérdésnek" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:72 #, python-format msgid "Encoding:" -msgstr "" +msgstr "Kódolás:" #. module: base_import #. openerp-web @@ -879,6 +970,20 @@ msgid "" "\n" " table. (like 'company_1', 'person_1' instead of '1')" msgstr "" +"Táblák közti relációk összefésülésének kezelése, \n" +" használhatja a \"Külső ID azonosító\" OpenERP " +"lehetőséget. \n" +" A rekordhoz tartozó \"Külső ID azonosító\" a rekord " +"egy másik \n" +" alkalmazáson belüli egyedi azonosítója. Ez a \"Külső " +"ID\n" +" azonosító\" egyedi kell legyen minden rekordban és " +"az összes \n" +" objektumon, ezért jó gyakorlat ennek a \"Külső ID " +"azonosítónak\"\n" +" az alkalmazás vagy tábla előtaggal való " +"kiegészítése. \n" +" (mint 'vállalat_1', 'személy_1' az '1' helyett)" #. module: base_import #. openerp-web @@ -889,6 +994,9 @@ msgid "" " \"External ID\". In PSQL, write the following " "command:" msgstr "" +"Először az összes vállalatot és a hozzá tartozó \"Külső ID azonosító\" lesz " +"\n" +" exportálva. A PSQL-ben, írja a következő parancsot:" #. module: base_import #. openerp-web @@ -898,13 +1006,15 @@ msgid "" "How can I import a one2many relationship (e.g. several \n" " Order Lines of a Sales Order)?" msgstr "" +"Hogyan tudom importálni a one2many kapcsolatot (pl. egyes \n" +" megrendelés sorokat egy megrendelésből)?" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:404 #, python-format msgid "Everything seems valid." -msgstr "" +msgstr "Úgy néz ki mindegyik érvényes." #. module: base_import #. openerp-web @@ -917,13 +1027,18 @@ msgid "" " use make use of the external ID for this field \n" " 'Category'." msgstr "" +"Azonban, ha nem szeretné a termék kategóriákat\n" +" beállításait megváltoztatni, azt ajánljuk, hogy " +"használja \n" +" a külső ID azonosító használatát erre a 'Kategória'\n" +" mezőre." #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:421 #, python-format msgid "at row %d" -msgstr "" +msgstr "Ebben a sorban %d" #. module: base_import #. openerp-web @@ -933,13 +1048,15 @@ msgid "" "How can I import a many2many relationship field \n" " (e.g. a customer that has multiple tags)?" msgstr "" +"Hogyan tudom importálni egy many2many kapcsolati mezőt \n" +" (pl. egy vevő akinek több címkéje van)?" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:80 #, python-format msgid "XXX/ID" -msgstr "" +msgstr "XXX/ID" #. module: base_import #. openerp-web @@ -955,6 +1072,14 @@ msgid "" " link between each person and the company they work \n" " for)." msgstr "" +"Ha különböző táblázatokból kell adatot importálni, \n" +" akkor a különböző táblázatok közötti rekordok " +"kapcsolatait\n" +" újra létre kell hozni. (pl. ha vállalatokat és " +"személyeket \n" +" importál, akkor létre kell hoznia a kapcsolatot \n" +" minden személy és a vállalata közt, ahol " +"alakalmazott)." #. module: base_import #. openerp-web @@ -967,13 +1092,19 @@ msgid "" " Here is when you should use one or the other, \n" " according to your need:" msgstr "" +"Az igénye szerint, használni kell \n" +" egyet a lehetésges 3 közül a a rekordokra " +"hivatkozáshoz a kapcsolatokban. \n" +" It van, ha egyiket a másik helyett kelle használni, " +"\n" +" az igénye szerint:" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:319 #, python-format msgid "person_4,Ramsy,False,company_3" -msgstr "" +msgstr "személy_4,Ramsy,Hamis,vállalat_3" #. module: base_import #. openerp-web @@ -989,13 +1120,20 @@ msgid "" " will set the EMPTY value in the field, instead of \n" " assigning the default value." msgstr "" +"Ha nem állítja be az összes mezőt a CSV fájlban, \n" +" OpenERP az alapértelmezett értéket fogja adni minden " +"olyan mezőnak ami \n" +" nincs meghatározva. Ha a mezőnek\n" +" üres értéket ad a CSV fájlban, OpenERP \n" +" az ÜRES értéket fogja beállítani a mezőre, az \n" +" alapértelmezett érték hozzáadása helyett." #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:20 #, python-format msgid "Cancel" -msgstr "" +msgstr "Megszakítás" #. module: base_import #. openerp-web @@ -1005,20 +1143,22 @@ msgid "" "What happens if I do not provide a value for a \n" " specific field?" msgstr "" +"Mi történik, ha nem adok meg értéket egy \n" +" bizonyos mezőhöz?" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:68 #, python-format msgid "Frequently Asked Questions" -msgstr "" +msgstr "Leggyakoribb kérdések" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:305 #, python-format msgid "company_3,Boum,True" -msgstr "" +msgstr "vállalat_3,Boum,Igaz" #. module: base_import #. openerp-web @@ -1032,6 +1172,12 @@ msgid "" "spreadsheet \n" " application." msgstr "" +"Ez a tulajdonság \n" +" lehetővé teszi az OpenERP Import/Export eszköz " +"használatát \n" +" a rekord kötegek módosítására a kedvenc táblázat " +"kezelőjénak \n" +" alkalmazásával." #. module: base_import #. openerp-web @@ -1042,6 +1188,9 @@ msgid "" " import an other record that links to the first\n" " one, use" msgstr "" +"oszlop az OpenERP-ben. Ha\n" +" másik rekordot importál amelyik az elsőre\n" +" hivatkozik, hasznája" #. module: base_import #. openerp-web @@ -1068,14 +1217,14 @@ msgstr "" #: code:addons/base_import/static/src/xml/import.xml:169 #, python-format msgid "CSV file for categories" -msgstr "" +msgstr "CSV fájl kategóriákhoz" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:330 #, python-format msgid "Normal Fields" -msgstr "" +msgstr "Normál mezők" #. module: base_import #. openerp-web @@ -1087,13 +1236,18 @@ msgid "" " identifier from the original application and\n" " map it to the" msgstr "" +"A különböző rekordok közötti kapcsolat újboli\n" +" létrehozásához, az eredeti alkalmazás \n" +" egyedi azonosítójának használata\n" +" szükséges amit\n" +" irányítson ehhez" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:170 #, python-format msgid "CSV file for Products" -msgstr "" +msgstr "CSV fájl a termékekhez" #. module: base_import #. openerp-web @@ -1117,31 +1271,31 @@ msgstr "" #. module: base_import #: model:ir.model,name:base_import.model_base_import_tests_models_m2o_related msgid "base_import.tests.models.m2o.related" -msgstr "" +msgstr "base_import.tests.models.m2o.related" #. module: base_import #: field:base_import.tests.models.preview,name:0 msgid "Name" -msgstr "" +msgstr "Név" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:80 #, python-format msgid "to the original unique identifier." -msgstr "" +msgstr "az eredeti egyedi ID azonosítóhoz." #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:318 #, python-format msgid "person_3,Eric,False,company_2" -msgstr "" +msgstr "személy_3,Eric,Hamis,vállalt_2" #. module: base_import #: field:base_import.import,res_model:0 msgid "Model" -msgstr "" +msgstr "Modell" #. module: base_import #. openerp-web @@ -1149,7 +1303,7 @@ msgstr "" #: code:addons/base_import/static/src/xml/import.xml:82 #, python-format msgid "ID" -msgstr "" +msgstr "Azonosító ID" #. module: base_import #. openerp-web @@ -1184,12 +1338,12 @@ msgstr "" #: code:addons/base_import/static/src/js/import.js:73 #, python-format msgid "Separator:" -msgstr "" +msgstr "Elválasztó:" #. module: base_import #: field:base_import.import,file_name:0 msgid "File Name" -msgstr "" +msgstr "Fájl neve" #. module: base_import #. openerp-web @@ -1199,28 +1353,28 @@ msgstr "" #: code:addons/base_import/static/src/xml/import.xml:82 #, python-format msgid "External ID" -msgstr "" +msgstr "Külső ID azonosító" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:39 #, python-format msgid "File Format Options…" -msgstr "" +msgstr "Fájl formátum lehetőségek…" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/js/import.js:423 #, python-format msgid "between rows %d and %d" -msgstr "" +msgstr "oszlopok közt %d és %d" #. module: base_import #. openerp-web #: code:addons/base_import/static/src/xml/import.xml:19 #, python-format msgid "or" -msgstr "" +msgstr "vagy" #. module: base_import #. openerp-web diff --git a/addons/base_report_designer/base_report_designer.py b/addons/base_report_designer/base_report_designer.py index 180a534b07f..bc7959a17df 100644 --- a/addons/base_report_designer/base_report_designer.py +++ b/addons/base_report_designer/base_report_designer.py @@ -20,13 +20,13 @@ ############################################################################## import base64 +from StringIO import StringIO + +from openerp.modules.module import get_module_resource import openerp.modules.registry from openerp.osv import osv from openerp_sxw2rml import sxw2rml -from StringIO import StringIO -from openerp import pooler -from openerp import addons - + class report_xml(osv.osv): _inherit = 'ir.actions.report.xml' @@ -37,31 +37,25 @@ class report_xml(osv.osv): ''' sxwval = StringIO(base64.decodestring(file_sxw)) if file_type=='sxw': - fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb') + fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb') if file_type=='odt': - fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb') + fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb') return {'report_rml_content': str(sxw2rml(sxwval, xsl=fp.read()))} def upload_report(self, cr, uid, report_id, file_sxw, file_type, context=None): ''' Untested function ''' - pool = pooler.get_pool(cr.dbname) sxwval = StringIO(base64.decodestring(file_sxw)) if file_type=='sxw': - fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb') + fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb') if file_type=='odt': - fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb') - report = pool.get('ir.actions.report.xml').write(cr, uid, [report_id], { + fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb') + report = self.pool['ir.actions.report.xml'].write(cr, uid, [report_id], { 'report_sxw_content': base64.decodestring(file_sxw), 'report_rml_content': str(sxw2rml(sxwval, xsl=fp.read())), }) - # FIXME: this should be moved to an override of the ir.actions.report_xml.create() method - cr.commit() - pool.get('ir.actions.report.xml').register_all(cr) - openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname) - return True def report_get(self, cr, uid, report_id, context=None): @@ -82,7 +76,6 @@ class report_xml(osv.osv): 'report_rml_content': rml_data and base64.encodestring(rml_data) or False } -report_xml() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_report_designer/base_report_designer_installer.xml b/addons/base_report_designer/base_report_designer_installer.xml index 657eae8fd63..99898f5a703 100644 --- a/addons/base_report_designer/base_report_designer_installer.xml +++ b/addons/base_report_designer/base_report_designer_installer.xml @@ -20,7 +20,7 @@ - + diff --git a/addons/base_report_designer/installer.py b/addons/base_report_designer/installer.py index bfda6e7a30f..7fddc27f037 100644 --- a/addons/base_report_designer/installer.py +++ b/addons/base_report_designer/installer.py @@ -23,7 +23,6 @@ from openerp.osv import fields from openerp.osv import osv import base64 from openerp.tools.translate import _ -from openerp import addons class base_report_designer_installer(osv.osv_memory): _name = 'base_report_designer.installer' @@ -31,13 +30,13 @@ class base_report_designer_installer(osv.osv_memory): def default_get(self, cr, uid, fields, context=None): data = super(base_report_designer_installer, self).default_get(cr, uid, fields, context=context) - plugin_file = open(addons.get_module_resource('base_report_designer','plugin', 'openerp_report_designer.zip'),'rb') - data['plugin_file'] = base64.encodestring(plugin_file.read()) + base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + data['plugin_file'] = base_url + '/base_report_designer/static/base-report-designer-plugin/openerp_report_designer.zip' return data _columns = { 'name':fields.char('File name', size=34), - 'plugin_file':fields.binary('OpenObject Report Designer Plug-in', readonly=True, help="OpenObject Report Designer plug-in file. Save as this file and install this plug-in in OpenOffice."), + 'plugin_file':fields.char('OpenObject Report Designer Plug-in', size=256, readonly=True, help="OpenObject Report Designer plug-in file. Save as this file and install this plug-in in OpenOffice."), 'description':fields.text('Description', readonly=True) } @@ -58,6 +57,5 @@ class base_report_designer_installer(osv.osv_memory): 4. if your connection success, A message appears like 'You can start creating your report in current document.'. """ } -base_report_designer_installer() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_report_designer/openerp_sxw2rml/normalized_odt2rml.xsl b/addons/base_report_designer/openerp_sxw2rml/normalized_odt2rml.xsl index 50ffb3d81be..9f9e5050d69 100644 --- a/addons/base_report_designer/openerp_sxw2rml/normalized_odt2rml.xsl +++ b/addons/base_report_designer/openerp_sxw2rml/normalized_odt2rml.xsl @@ -414,7 +414,7 @@ - . + diff --git a/addons/base_report_designer/openerp_sxw2rml/normalized_oo2rml.xsl b/addons/base_report_designer/openerp_sxw2rml/normalized_oo2rml.xsl index 66ef0b5b53c..ae68ae1ed1b 100644 --- a/addons/base_report_designer/openerp_sxw2rml/normalized_oo2rml.xsl +++ b/addons/base_report_designer/openerp_sxw2rml/normalized_oo2rml.xsl @@ -414,7 +414,7 @@ - . + diff --git a/addons/base_report_designer/plugin/openerp_report_designer.zip b/addons/base_report_designer/static/base-report-designer-plugin/openerp_report_designer.zip similarity index 100% rename from addons/base_report_designer/plugin/openerp_report_designer.zip rename to addons/base_report_designer/static/base-report-designer-plugin/openerp_report_designer.zip diff --git a/addons/base_report_designer/wizard/base_report_designer_modify.py b/addons/base_report_designer/wizard/base_report_designer_modify.py index abef384cd91..e8ed45e7ce1 100644 --- a/addons/base_report_designer/wizard/base_report_designer_modify.py +++ b/addons/base_report_designer/wizard/base_report_designer_modify.py @@ -24,7 +24,7 @@ import base64 import time import urllib -from openerp import osv, pooler, tools +from openerp import osv, tools from openerp.osv import fields, osv from openerp.tools.translate import _ @@ -39,9 +39,9 @@ class base_report_sxw(osv.osv_memory): def get_report(self, cr, uid, ids, context=None): data = self.read(cr, uid, ids, context=context)[0] - data_obj = self.pool.get('ir.model.data') + data_obj = self.pool['ir.model.data'] id2 = data_obj._get_id(cr, uid, 'base_report_designer', 'view_base_report_file_sxw') - report = self.pool.get('ir.actions.report.xml').browse(cr, uid, data['report_id'], context=context) + report = self.pool['ir.actions.report.xml'].browse(cr, uid, data['report_id'], context=context) if id2: id2 = data_obj.browse(cr, uid, id2, context=context).res_id return { @@ -54,7 +54,6 @@ class base_report_sxw(osv.osv_memory): 'target': 'new', } -base_report_sxw() class base_report_file_sxw(osv.osv_memory): """Base Report File sxw """ @@ -74,9 +73,9 @@ class base_report_file_sxw(osv.osv_memory): """ res = super(base_report_file_sxw, self).default_get(cr, uid, fields, context=context) - report_id1 = self.pool.get('base.report.sxw').search(cr,uid,[]) - data = self.pool.get('base.report.sxw').read(cr, uid, report_id1, context=context)[0] - report = self.pool.get('ir.actions.report.xml').browse(cr, uid, data['report_id'], context=context) + report_id1 = self.pool['base.report.sxw'].search(cr,uid,[]) + data = self.pool['base.report.sxw'].read(cr, uid, report_id1, context=context)[0] + report = self.pool['ir.actions.report.xml'].browse(cr, uid, data['report_id'], context=context) if context is None: context={} if 'report_id' in fields: @@ -97,14 +96,14 @@ class base_report_file_sxw(osv.osv_memory): sxwval = StringIO.StringIO(base64.decodestring(data['file_sxw_upload'])) fp = tools.file_open('normalized_oo2rml.xsl',subdir='addons/base_report_designer/openerp_sxw2rml') newrmlcontent = str(openerp_sxw2rml.sxw2rml(sxwval, xsl=fp.read())) - report = self.pool.get('ir.actions.report.xml').write(cr, uid, [data['report_id']], { + report = self.pool['ir.actions.report.xml'].write(cr, uid, [data['report_id']], { 'report_sxw_content': base64.decodestring(data['file_sxw_upload']), 'report_rml_content': newrmlcontent }) cr.commit() - data_obj = self.pool.get('ir.model.data') + data_obj = self.pool['ir.model.data'] id2 = data_obj._get_id(cr, uid, 'base_report_designer', 'view_base_report_file_rml') - report = self.pool.get('ir.actions.report.xml').browse(cr, uid, data['report_id'], context=context) + report = self.pool['ir.actions.report.xml'].browse(cr, uid, data['report_id'], context=context) if id2: id2 = data_obj.browse(cr, uid, id2, context=context).res_id return { @@ -116,7 +115,6 @@ class base_report_file_sxw(osv.osv_memory): 'type': 'ir.actions.act_window', 'target': 'new', } -base_report_file_sxw() class base_report_rml_save(osv.osv_memory): """Base Report file Save""" @@ -135,9 +133,9 @@ class base_report_rml_save(osv.osv_memory): """ res = super(base_report_rml_save, self).default_get(cr, uid, fields, context=context) - report_id = self.pool.get('base.report.sxw').search(cr,uid,[]) - data = self.pool.get('base.report.file.sxw').read(cr, uid, report_id, context=context)[0] - report = self.pool.get('ir.actions.report.xml').browse(cr, uid, data['report_id'], context=context) + report_id = self.pool['base.report.sxw'].search(cr,uid,[]) + data = self.pool['base.report.file.sxw'].read(cr, uid, report_id, context=context)[0] + report = self.pool['ir.actions.report.xml'].browse(cr, uid, data['report_id'], context=context) if 'file_rml' in fields: res['file_rml'] = base64.encodestring(report.report_rml_content) @@ -146,6 +144,5 @@ class base_report_rml_save(osv.osv_memory): 'file_rml':fields.binary('Save As'), } -base_report_rml_save() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_setup/base_setup.py b/addons/base_setup/base_setup.py index 3e7c1d1f846..ac4ce5b55b6 100644 --- a/addons/base_setup/base_setup.py +++ b/addons/base_setup/base_setup.py @@ -21,7 +21,6 @@ import simplejson import cgi -from openerp import pooler from openerp import tools from openerp.osv import fields, osv from openerp.tools.translate import _ diff --git a/addons/base_status/i18n/cs.po b/addons/base_status/i18n/cs.po new file mode 100644 index 00000000000..3fdb5247e7f --- /dev/null +++ b/addons/base_status/i18n/cs.po @@ -0,0 +1,76 @@ +# Czech 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-03-30 12:43+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-31 05:28+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "Error !" +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:166 +#, python-format +msgid "%s has been opened." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:199 +#, python-format +msgid "%s has been renewed." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "Error!" +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "" +"You can not escalate, you are already at the top level regarding your sales-" +"team category." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:193 +#, python-format +msgid "%s is now pending." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:187 +#, python-format +msgid "%s has been canceled." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "" +"You are already at the top level of your sales-team category.\n" +"Therefore you cannot escalate furthermore." +msgstr "" + +#. module: base_status +#: code:addons/base_status/base_state.py:181 +#, python-format +msgid "%s has been closed." +msgstr "" diff --git a/addons/base_status/i18n/nl_BE.po b/addons/base_status/i18n/nl_BE.po new file mode 100644 index 00000000000..6a3c2d83fc7 --- /dev/null +++ b/addons/base_status/i18n/nl_BE.po @@ -0,0 +1,80 @@ +# 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:40+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: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "Error !" +msgstr "Fout" + +#. module: base_status +#: code:addons/base_status/base_state.py:166 +#, python-format +msgid "%s has been opened." +msgstr "%s is geopend." + +#. module: base_status +#: code:addons/base_status/base_state.py:199 +#, python-format +msgid "%s has been renewed." +msgstr "%s is vernieuwd." + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "Error!" +msgstr "Fout" + +#. module: base_status +#: code:addons/base_status/base_state.py:107 +#, python-format +msgid "" +"You can not escalate, you are already at the top level regarding your sales-" +"team category." +msgstr "" +"U kunt niet escaleren; u heeft het hoogste niveau in de verkoopteams al " +"bereikt." + +#. module: base_status +#: code:addons/base_status/base_state.py:193 +#, python-format +msgid "%s is now pending." +msgstr "%s is wachtend." + +#. module: base_status +#: code:addons/base_status/base_state.py:187 +#, python-format +msgid "%s has been canceled." +msgstr "%s is geannuleerd." + +#. module: base_status +#: code:addons/base_status/base_stage.py:210 +#, python-format +msgid "" +"You are already at the top level of your sales-team category.\n" +"Therefore you cannot escalate furthermore." +msgstr "" +"U bent al op het hoogste niveau van uw verkoopteam.\n" +"U kunt dus niet verder escaleren." + +#. module: base_status +#: code:addons/base_status/base_state.py:181 +#, python-format +msgid "%s has been closed." +msgstr "%s is gesloten." diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py index 616333e3b47..e7501334997 100644 --- a/addons/base_vat/base_vat.py +++ b/addons/base_vat/base_vat.py @@ -134,6 +134,9 @@ class res_partner(osv.osv): 'vat_subjected': fields.boolean('VAT Legal Statement', help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement.") } + def _commercial_fields(self, cr, uid, context=None): + return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['vat_subjected'] + def _construct_constraint_msg(self, cr, uid, ids, context=None): def default_vat_check(cn, vn): # by default, a VAT number is valid if: @@ -243,6 +246,5 @@ class res_partner(osv.osv): return False return check == int(vat[8]) -res_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_vat/i18n/nl_BE.po b/addons/base_vat/i18n/nl_BE.po index 39966dc58ef..a2fe05c5705 100644 --- a/addons/base_vat/i18n/nl_BE.po +++ b/addons/base_vat/i18n/nl_BE.po @@ -7,19 +7,19 @@ 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: 2012-10-01 11:23+0000\n" +"PO-Revision-Date: 2013-04-15 16:03+0000\n" "Last-Translator: Els Van Vossel (Agaplan) \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:10+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n" +"X-Generator: Launchpad (build 16564)\n" #. module: base_vat #: view:res.partner:0 msgid "Check Validity" -msgstr "" +msgstr "Geldigheid controleren" #. module: base_vat #: code:addons/base_vat/base_vat.py:147 @@ -45,7 +45,7 @@ msgstr "Bedrijven" #: code:addons/base_vat/base_vat.py:111 #, python-format msgid "Error!" -msgstr "" +msgstr "Fout" #. module: base_vat #: help:res.partner,vat_subjected:0 diff --git a/addons/board/static/src/js/dashboard.js b/addons/board/static/src/js/dashboard.js index bd9625a4fa8..3489b686e1b 100644 --- a/addons/board/static/src/js/dashboard.js +++ b/addons/board/static/src/js/dashboard.js @@ -419,8 +419,10 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({ instance.web.SearchView.include({ add_common_inputs: function() { this._super(); - (new instance.board.AddToDashboard(this)); - + var vm = this.getParent().getParent(); + if (vm.inner_action && vm.inner_action.views) { + (new instance.board.AddToDashboard(this)); + } } }); diff --git a/addons/claim_from_delivery/i18n/nl_BE.po b/addons/claim_from_delivery/i18n/nl_BE.po index a8793109b5f..38aab39e523 100644 --- a/addons/claim_from_delivery/i18n/nl_BE.po +++ b/addons/claim_from_delivery/i18n/nl_BE.po @@ -8,29 +8,29 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-12-21 17:05+0000\n" -"PO-Revision-Date: 2012-10-01 11:24+0000\n" +"PO-Revision-Date: 2013-04-15 16:38+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-03-16 05:41+0000\n" -"X-Generator: Launchpad (build 16532)\n" +"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n" +"X-Generator: Launchpad (build 16564)\n" #. module: claim_from_delivery #: view:stock.picking.out:0 msgid "Claims" -msgstr "" +msgstr "Klachten" #. module: claim_from_delivery #: model:res.request.link,name:claim_from_delivery.request_link_claim_from_delivery msgid "Delivery Order" -msgstr "" +msgstr "Leveringsorder" #. module: claim_from_delivery #: model:ir.actions.act_window,name:claim_from_delivery.action_claim_from_delivery msgid "Claim From Delivery" -msgstr "" +msgstr "Klachten van levering" #~ msgid "Claim" #~ msgstr "Klacht" diff --git a/addons/contacts/i18n/es_CO.po b/addons/contacts/i18n/es_CO.po new file mode 100644 index 00000000000..d4b8e87b899 --- /dev/null +++ b/addons/contacts/i18n/es_CO.po @@ -0,0 +1,46 @@ +# Spanish (Colombia) 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-03-21 21:43+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Colombia) \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-22 04:57+0000\n" +"X-Generator: Launchpad (build 16532)\n" + +#. module: contacts +#: model:ir.actions.act_window,help:contacts.action_contacts +msgid "" +"

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

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

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

\n" +" Pulse para añadir un contacto a su libreta de direcciones.\n" +"

\n" +" OpenERP le ayuda a seguir el rastro a todas las actividades " +"relativas a\n" +" un cliente: discusiones, histórico de oportunidades de negocio,\n" +" documentos, etc.\n" +"

\n" +" " + +#. module: contacts +#: model:ir.actions.act_window,name:contacts.action_contacts +#: model:ir.ui.menu,name:contacts.menu_contacts +msgid "Contacts" +msgstr "Contactos" diff --git a/addons/contacts/i18n/nl_BE.po b/addons/contacts/i18n/nl_BE.po new file mode 100644 index 00000000000..78fdb540ad6 --- /dev/null +++ b/addons/contacts/i18n/nl_BE.po @@ -0,0 +1,46 @@ +# 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: contacts +#: model:ir.actions.act_window,help:contacts.action_contacts +msgid "" +"

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

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

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

\n" +" Klik hier om een contactpersoon toe te voegen aan het " +"adresboek.\n" +"

\n" +" Met OpenERP kunt u eenvoudig alle activiteiten registreren met " +"betrekking tot \n" +" een klant, discussies, opportuniteiten, documenten, enz. \n" +"

\n" +" " + +#. module: contacts +#: model:ir.actions.act_window,name:contacts.action_contacts +#: model:ir.ui.menu,name:contacts.menu_contacts +msgid "Contacts" +msgstr "Contactpersonen" diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 0dd075d48e6..072624a7d98 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -81,6 +81,8 @@ Dashboard for CRM will include: 'crm_lead_view.xml', 'crm_lead_menu.xml', + 'crm_case_section_view.xml', + 'crm_meeting_menu.xml', 'crm_phonecall_view.xml', @@ -103,20 +105,37 @@ Dashboard for CRM will include: 'crm_action_rule_demo.xml', ], 'test': [ - 'test/process/communication_with_customer.yml', - 'test/process/lead2opportunity2win.yml', - 'test/process/lead2opportunity_assign_salesmen.yml', - 'test/process/merge_opportunity.yml', - 'test/process/cancel_lead.yml', - 'test/process/segmentation.yml', - 'test/process/phonecalls.yml', - 'test/ui/crm_demo.yml', - 'test/ui/duplicate_lead.yml', - 'test/ui/delete_lead.yml', + 'test/crm_lead_message.yml', + 'test/lead2opportunity2win.yml', + 'test/lead2opportunity_assign_salesmen.yml', + 'test/crm_lead_merge.yml', + 'test/crm_lead_cancel.yml', + 'test/segmentation.yml', + 'test/phonecalls.yml', + 'test/crm_lead_onchange.yml', + 'test/crm_lead_copy.yml', + 'test/crm_lead_unlink.yml', + ], + 'css': [ + 'static/src/css/crm.css' + ], + 'js': [ + 'static/src/js/crm.js' ], 'installable': True, 'application': True, 'auto_install': False, - 'images': ['images/crm_dashboard.png', 'images/customers.png','images/leads.png','images/opportunities_kanban.png','images/opportunities_form.png','images/opportunities_calendar.png','images/opportunities_graph.png','images/logged_calls.png','images/scheduled_calls.png','images/stages.png'], + 'images': [ + 'images/crm_dashboard.png', + 'images/customers.png', + 'images/leads.png', + 'images/opportunities_kanban.png', + 'images/opportunities_form.png', + 'images/opportunities_calendar.png', + 'images/opportunities_graph.png', + 'images/logged_calls.png', + 'images/scheduled_calls.png', + 'images/stages.png', + ], } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/crm.py b/addons/crm/crm.py index df6d5e12b66..7b6fe02afa8 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -98,6 +98,7 @@ class crm_case_stage(osv.osv): 'case_default': True, } + class crm_case_section(osv.osv): """ Model for sales teams. """ _name = "crm.case.section" @@ -107,7 +108,7 @@ class crm_case_section(osv.osv): _order = "complete_name" def get_full_name(self, cr, uid, ids, field_name, arg, context=None): - return dict(self.name_get(cr, uid, ids, context=context)) + return dict(self.name_get(cr, uid, ids, context=context)) _columns = { 'name': fields.char('Sales Team', size=64, required=True, translate=True), @@ -117,27 +118,36 @@ class crm_case_section(osv.osv): "true, it will allow you to hide the sales team without removing it."), 'change_responsible': fields.boolean('Reassign Escalated', help="When escalating to this team override the salesman with the team leader."), 'user_id': fields.many2one('res.users', 'Team Leader'), - 'member_ids':fields.many2many('res.users', 'sale_member_rel', 'section_id', 'member_id', 'Team Members'), + 'member_ids': fields.many2many('res.users', 'sale_member_rel', 'section_id', 'member_id', 'Team Members'), 'reply_to': fields.char('Reply-To', size=64, help="The email address put in the 'Reply-To' of all emails sent by OpenERP about cases in this sales team"), 'parent_id': fields.many2one('crm.case.section', 'Parent Team'), 'child_ids': fields.one2many('crm.case.section', 'parent_id', 'Child Teams'), 'resource_calendar_id': fields.many2one('resource.calendar', "Working Time", help="Used to compute open days"), 'note': fields.text('Description'), - 'working_hours': fields.float('Working Hours', digits=(16,2 )), + 'working_hours': fields.float('Working Hours', digits=(16, 2)), 'stage_ids': fields.many2many('crm.case.stage', 'section_stage_rel', 'section_id', 'stage_id', 'Stages'), 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True, help="The email address associated with this team. New emails received will automatically " "create new leads assigned to the team."), + 'open_lead_ids': fields.one2many('crm.lead', 'section_id', + string='Open Leads', readonly=True, + domain=['&', ('type', '!=', 'opportunity'), ('state', 'not in', ['done', 'cancel'])]), + 'open_opportunity_ids': fields.one2many('crm.lead', 'section_id', + string='Open Opportunities', readonly=True, + domain=['&', '|', ('type', '=', 'opportunity'), ('type', '=', 'both'), ('state', 'not in', ['done', 'cancel'])]), + 'color': fields.integer('Color Index'), + 'use_leads': fields.boolean('Leads', + help="This enables the management of leads in the sales team. Otherwise the sales team manages only opportunities."), } def _get_stage_common(self, cr, uid, context): - ids = self.pool.get('crm.case.stage').search(cr, uid, [('case_default','=',1)], context=context) + ids = self.pool.get('crm.case.stage').search(cr, uid, [('case_default', '=', 1)], context=context) return ids _defaults = { 'active': 1, 'stage_ids': _get_stage_common, - 'alias_domain': False, # always hide alias during creation + 'use_leads': True, } _sql_constraints = [ @@ -150,7 +160,7 @@ class crm_case_section(osv.osv): def name_get(self, cr, uid, ids, context=None): """Overrides orm name_get method""" - if not isinstance(ids, list) : + if not isinstance(ids, list): ids = [ids] res = [] if not ids: @@ -167,20 +177,20 @@ class crm_case_section(osv.osv): def create(self, cr, uid, vals, context=None): mail_alias = self.pool.get('mail.alias') if not vals.get('alias_id'): - vals.pop('alias_name', None) # prevent errors during copy() + alias_name = vals.pop('alias_name', None) or vals.get('name') # prevent errors during copy() alias_id = mail_alias.create_unique_alias(cr, uid, - {'alias_name': vals['name']}, + {'alias_name': alias_name}, model_name="crm.lead", context=context) vals['alias_id'] = alias_id res = super(crm_case_section, self).create(cr, uid, vals, context) - mail_alias.write(cr, uid, [vals['alias_id']], {'alias_defaults': {'section_id': res, 'type':'lead'}}, context) + mail_alias.write(cr, uid, [vals['alias_id']], {'alias_defaults': {'section_id': res, 'type': 'lead'}}, context) return res def unlink(self, cr, uid, ids, context=None): # Cascade-delete mail aliases as well, as they should not exist without the sales team. mail_alias = self.pool.get('mail.alias') - alias_ids = [team.alias_id.id for team in self.browse(cr, uid, ids, context=context) if team.alias_id ] + alias_ids = [team.alias_id.id for team in self.browse(cr, uid, ids, context=context) if team.alias_id] res = super(crm_case_section, self).unlink(cr, uid, ids, context=context) mail_alias.unlink(cr, uid, alias_ids, context=context) return res @@ -230,4 +240,5 @@ class crm_payment_mode(osv.osv): 'section_id': fields.many2one('crm.case.section', 'Sales Team'), } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/crm_case_section_view.xml b/addons/crm/crm_case_section_view.xml new file mode 100644 index 00000000000..c788872b47e --- /dev/null +++ b/addons/crm/crm_case_section_view.xml @@ -0,0 +1,294 @@ + + + + + + + + Leads + crm.lead + tree,form + ['|', ('type','=','lead'), ('type','=',False)] + + + { + 'search_default_section_id': [active_id], + 'search_default_open': 1, + 'default_section_id': active_id, + 'default_type': 'lead', + 'stage_type': 'lead', + } + + +

+ Use leads if you need a qualification step before creating an + opportunity or a customer. It can be a business card you received, + a contact form filled in your website, or a file of unqualified + prospects you import, etc. +

+ Once qualified, the lead can be converted into a business + opportunity and/or a new customer in your address book. +

+
+
+ + + + + Opportunities + crm.lead + kanban,tree,graph,form,calendar + [('type','=','opportunity')] + + + { + 'search_default_section_id': [active_id], + 'search_default_new': 1, + 'search_default_open': 1, + 'default_section_id': active_id, + 'stage_type': 'opportunity', + 'default_type': 'opportunity', + 'default_user_id': uid, + } + + +

+ Click to create a new opportunity. +

+ OpenERP helps you keep track of your sales pipeline to follow + up potential sales and better forecast your future revenues. +

+ You will be able to plan meetings and phone calls from + opportunities, convert them into quotations, attach related + documents, track all discussions, and much more. +

+
+
+ + + + + crm.case.section.kanban + crm.case.section + + + + + + + + + + + + + +
+
+ í +
+
+

+
+ %% +
+ +
+ + + + +
+
+
+
+
+
+
+
+ + + + + Sales Teams + crm.case.section + form + kanban,tree,form + + +

+ Click here to define a new sales team. +

+ Use sales team to organize your different salespersons or + departments into separate teams. Each team will work in + its own list of opportunities. +

+
+
+ + + + + crm.case.section.form + crm.case.section + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ X +
+
+ +
+
+
+
+
+
+
+
+ + + + + + + +
+
+
+ + +
+
+
+
+ + + + + crm.case.section.tree + crm.case.section + child_ids + + + + + + + + + + + + + + kanban + + + + + + + tree + + + + + + + form + + + + + + Cases by Sales Team + crm.case.section + [('parent_id','=',False)] + tree + + + + + Sales Teams + crm.case.section + form + + +

+ Click here to define a new sales team. +

+ Use sales team to organize your different salespersons or + departments into separate teams. Each team will work in + its own list of opportunities. +

+
+
+ + +
+
\ No newline at end of file diff --git a/addons/crm/crm_data.xml b/addons/crm/crm_data.xml index 3db7a457dfd..f24aee13c1d 100644 --- a/addons/crm/crm_data.xml +++ b/addons/crm/crm_data.xml @@ -27,8 +27,10 @@ - Sales Department + Sales Sales + True + @@ -64,12 +66,6 @@

To manage quotations and sale orders, install the "Sales Management" application.

]]>
- - sales - - - {'type':'lead'} - diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 53fd7179c25..4e5dee5ae34 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -22,6 +22,7 @@ from openerp.addons.base_status.base_stage import base_stage import crm from datetime import datetime +from operator import itemgetter from openerp.osv import fields, osv import time from openerp import tools @@ -84,6 +85,13 @@ class crm_lead(base_stage, format_address, osv.osv): }, } + def get_empty_list_help(self, cr, uid, help, context=None): + if context.get('default_type') == 'lead': + context['empty_list_help_model'] = 'crm.case.section' + context['empty_list_help_id'] = context.get('default_section_id') + context['empty_list_help_document_name'] = _("leads") + return super(crm_lead, self).get_empty_list_help(cr, uid, help, context=context) + def create(self, cr, uid, vals, context=None): if context is None: context = {} @@ -355,6 +363,16 @@ class crm_lead(base_stage, format_address, osv.osv): } return {'value' : values} + def on_change_user(self, cr, uid, ids, user_id, context=None): + """ When changing the user, also set a section_id or restrict section id + to the ones user_id is member of. """ + section_id = False + if user_id: + section_ids = self.pool.get('crm.case.section').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context) + if section_ids: + section_id = section_ids[0] + return {'value': {'section_id': section_id}} + def _check(self, cr, uid, ids=False, context=None): """ Override of the base.stage method. Function called by the scheduler to process cases for date actions @@ -628,12 +646,13 @@ class crm_lead(base_stage, format_address, osv.osv): opportunities = self.browse(cr, uid, ids, context=context) sequenced_opps = [] for opportunity in opportunities: + sequence = -1 if opportunity.stage_id and opportunity.stage_id.state != 'cancel': - sequenced_opps.append((opportunity.stage_id.sequence, opportunity)) - else: - sequenced_opps.append((-1, opportunity)) - sequenced_opps.sort(key=lambda tup: tup[0], reverse=True) - opportunities = [opportunity for sequence, opportunity in sequenced_opps] + sequence = opportunity.stage_id.sequence + sequenced_opps.append(((int(sequence != -1 and opportunity.type == 'opportunity'), sequence, -opportunity.id), opportunity)) + + sequenced_opps.sort(reverse=True) + opportunities = map(itemgetter(1), sequenced_opps) ids = [opportunity.id for opportunity in opportunities] highest = opportunities[0] opportunities_rest = opportunities[1:] @@ -652,11 +671,10 @@ class crm_lead(base_stage, format_address, osv.osv): opportunities.extend(opportunities_rest) self._merge_notify(cr, uid, highest, opportunities, context=context) # Check if the stage is in the stages of the sales team. If not, assign the stage with the lowest sequence - if merged_data.get('type') == 'opportunity' and merged_data.get('section_id'): - section_stages = self.pool.get('crm.case.section').read(cr, uid, merged_data['section_id'], ['stage_ids'], context=context) - if merged_data.get('stage_id') not in section_stages['stage_ids']: - stages_sequences = self.pool.get('crm.case.stage').search(cr, uid, [('id','in',section_stages['stage_ids'])], order='sequence', limit=1, context=context) - merged_data['stage_id'] = stages_sequences and stages_sequences[0] or False + if merged_data.get('section_id'): + section_stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('section_ids', 'in', merged_data['section_id']), ('type', '=', merged_data.get('type'))], order='sequence', context=context) + if merged_data.get('stage_id') not in section_stage_ids: + merged_data['stage_id'] = section_stage_ids and section_stage_ids[0] or False # Write merged data into first opportunity self.write(cr, uid, [highest.id], merged_data, context=context) # Delete tail opportunities @@ -944,6 +962,7 @@ class crm_lead(base_stage, format_address, osv.osv): 'default_composition_mode': 'comment', }) return { + 'name': _('Compose Email'), 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', @@ -1034,6 +1053,14 @@ class crm_lead(base_stage, format_address, osv.osv): message = _("%s a call for %s.%s") % (prefix, phonecall.date, suffix) return self.message_post(cr, uid, ids, body=message, context=context) + def log_meeting(self, cr, uid, ids, meeting_subject, meeting_date, duration, context=None): + if not duration: + duration = _('unknown') + else: + duration = str(duration) + message = _("Meeting scheduled at '%s'
Subject: %s
Duration: %s hour(s)") % (meeting_date, meeting_subject, duration) + return self.message_post(cr, uid, ids, body=message, context=context) + def onchange_state(self, cr, uid, ids, state_id, context=None): if state_id: country_id=self.pool.get('res.country.state').browse(cr, uid, state_id, context).country_id.id diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index e335bd1b2ff..0979a94eb3f 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -7,68 +7,69 @@ New draft - - + + both Opportunity open - - + + lead - - Qualification - - open - - - opportunity - - - Proposition - - open - - - opportunity - - - Negotiation - - open - - - opportunity - - - Won - - done - - - - opportunity - Dead cancel - - + + lead + + Qualification + + open + + + opportunity + + + Proposition + + open + + + opportunity + + + Negotiation + + open + + + opportunity + + + Won + + + done + + + + opportunity + Lost cancel - - + + opportunity @@ -228,7 +229,7 @@ Lead/Opportunity Mass Mail - ${object.partner_id and object.partner_id.id} + ${object.partner_id != False and object.partner_id.id} ${not object.partner_id and object.email_from} diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml index 8c38ed41a1c..2226b4ac895 100644 --- a/addons/crm/crm_lead_menu.xml +++ b/addons/crm/crm_lead_menu.xml @@ -9,34 +9,23 @@ ['|', ('type','=','lead'), ('type','=',False)] - {'default_type':'lead', 'stage_type':'lead'} - -

- Click to create an unqualified lead. -

- Use leads if you need a qualification step before creating an - opportunity or a customer. It can be a business card you received, - a contact form filled in your website, or a file of unqualified - prospects you import, etc. -

- Once qualified, the lead can be converted into a business - opportunity and/or a new customer in your address book. -

+ { + 'default_type':'lead', + 'stage_type':'lead', + 'search_default_unassigned':1, + } + + +

+ Use leads if you need a qualification step before creating an + opportunity or a customer. It can be a business card you received, + a contact form filled in your website, or a file of unqualified + prospects you import, etc. +

+ Once qualified, the lead can be converted into a business + opportunity and/or a new customer in your address book. +

- - - - - tree - - - - - - - form - - @@ -44,20 +33,25 @@ crm.lead kanban,tree,graph,form,calendar [('type','=','opportunity')] - {'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid} + { + 'stage_type': 'opportunity', + 'default_type': 'opportunity', + 'default_user_id': uid + } + -

- Click to create a new opportunity. -

- OpenERP helps you keep track of your sales pipeline to follow - up potential sales and better forecast your future revenues. -

- You will be able to plan meetings and phone calls from - opportunities, convert them into quotations, attach related - documents, track all discussions, and much more. -

+

+ Click to create a new opportunity. +

+ OpenERP helps you keep track of your sales pipeline to follow + up potential sales and better forecast your future revenues. +

+ You will be able to plan meetings and phone calls from + opportunities, convert them into quotations, attach related + documents, track all discussions, and much more. +

@@ -82,9 +76,13 @@ - - - + + + diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index df28d240a0c..8c22a0a2e1c 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -100,6 +100,7 @@ + +
+ +
+
+
+
+ + + + +
+
+ +
+
+
+ +
+
+
+
+
+
+ \ No newline at end of file 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..6e17c1a127f --- /dev/null +++ b/addons/im_livechat/security/ir.model.access.csv @@ -0,0 +1,6 @@ +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,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..6fd090a89ce 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..8d17ea85bd3 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_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..b74cfa21b8a 100644 --- a/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py +++ b/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py @@ -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..29a1a1508a4 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 """ @@ -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..703ab9db59b 100644 --- a/addons/l10n_be/wizard/l10n_be_vat_intra.py +++ b/addons/l10n_be/wizard/l10n_be_vat_intra.py @@ -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/l10n_be_coda_view.xml b/addons/l10n_be_coda/l10n_be_coda_view.xml index 2464e5e9082..8c11913b14d 100644 --- a/addons/l10n_be_coda/l10n_be_coda_view.xml +++ b/addons/l10n_be_coda/l10n_be_coda_view.xml @@ -41,6 +41,7 @@ 10 + 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_br/account.py b/addons/l10n_br/account.py index 05ad589ab82..1adb6d92baa 100644 --- a/addons/l10n_br/account.py +++ b/addons/l10n_br/account.py @@ -17,7 +17,7 @@ #along with this program. If not, see . # ################################################################################# -from openerp import pooler +import openerp from openerp.osv import fields, osv TAX_CODE_COLUMNS = { @@ -92,7 +92,8 @@ class account_tax_code(osv.osv): def get_precision_tax(): def change_digit_tax(cr): - res = pooler.get_pool(cr.dbname).get('decimal.precision').precision_get(cr, 1, 'Account') + decimal_precision = openerp.registry(cr.dbname)['decimal.precision'] + res = decimal_precision.precision_get(cr, 1, 'Account') return (16, res+2) return change_digit_tax 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/test/l10n_fr_report.yml b/addons/l10n_fr/test/l10n_fr_report.yml index 44db53d0a77..25de74dd313 100644 --- a/addons/l10n_fr/test/l10n_fr_report.yml +++ b/addons/l10n_fr/test/l10n_fr_report.yml @@ -3,8 +3,9 @@ - !python {model: account.move.line}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.l10n.fr.bilan').create(cr, uid, [], {'model':'account.move.line', 'form':{'fiscalyear_id': ref('account.data_fiscalyear')}}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [], 'l10n.fr.bilan', {'model':'account.move.line', 'form':{'fiscalyear_id': ref('account.data_fiscalyear')}}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'l10n_fr-bilan_report.'+format), 'wb+').write(data) @@ -13,7 +14,8 @@ - !python {model: account.move.line}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.l10n.fr.compute_resultant').create(cr, uid, [], {'model':'account.move.line', 'form':{'fiscalyear_id': ref('account.data_fiscalyear')}}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [], 'l10n.fr.compute_resultant', {'model':'account.move.line', 'form':{'fiscalyear_id': ref('account.data_fiscalyear')}}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'l10n_fr-compute_resultant_report.'+format), 'wb+').write(data) diff --git a/addons/l10n_fr/wizard/fr_report_bilan.py b/addons/l10n_fr/wizard/fr_report_bilan.py index 90e97389eed..291557f8fba 100644 --- a/addons/l10n_fr/wizard/fr_report_bilan.py +++ b/addons/l10n_fr/wizard/fr_report_bilan.py @@ -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..8d8aed8baff 100644 --- a/addons/l10n_fr/wizard/fr_report_compute_resultant.py +++ b/addons/l10n_fr/wizard/fr_report_compute_resultant.py @@ -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/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_rib/bank.py b/addons/l10n_fr_rib/bank.py index 8ad86932a34..1f5264ef5ac 100644 --- a/addons/l10n_fr_rib/bank.py +++ b/addons/l10n_fr_rib/bank.py @@ -19,7 +19,6 @@ # ############################################################################## -from openerp import netsvc from openerp.osv import fields, osv from openerp.tools.translate import _ @@ -81,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""" @@ -103,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_in_hr_payroll/l10n_in_hr_payroll.py b/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py index 6a7638d919a..348bb71c95e 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): ''' @@ -157,7 +156,6 @@ class payroll_advice(osv.osv): return { 'value':res } -payroll_advice() class hr_payslip_run(osv.osv): @@ -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/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/test/payment_advice.yml b/addons/l10n_in_hr_payroll/test/payment_advice.yml index ff391dd5363..0b4b16a629c 100644 --- a/addons/l10n_in_hr_payroll/test/payment_advice.yml +++ b/addons/l10n_in_hr_payroll/test/payment_advice.yml @@ -36,7 +36,8 @@ - !python {model: hr.payroll.advice}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.payroll.advice').create(cr, uid, [ref('l10n_in_hr_payroll.payment_advice_1')], {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('l10n_in_hr_payroll.payment_advice_1')], 'payroll.advice', {}, {}) if tools.config['test_report_directory']: - file(os.path.join(tools.config['test_report_directory'], 'l10n_in_hr_payroll_summary report'+format), 'wb+').write(data) \ No newline at end of file + file(os.path.join(tools.config['test_report_directory'], 'l10n_in_hr_payroll_summary report'+format), 'wb+').write(data) 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_lu/test/l10n_lu_report.yml b/addons/l10n_lu/test/l10n_lu_report.yml index cacb3015ab2..0ee032d581c 100644 --- a/addons/l10n_lu/test/l10n_lu_report.yml +++ b/addons/l10n_lu/test/l10n_lu_report.yml @@ -9,8 +9,9 @@ - !python {model: res.partner}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.l10n_lu.tax.report.print').create(cr, uid, [], {'model':'ir.ui.menu', 'form':{'tax_code_id': ref('account_tax_code_id_r1'), 'period_id': ref('account.period_1')}}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [], 'l10n_lu.tax.report.print', {'model':'ir.ui.menu', 'form':{'tax_code_id': ref('account_tax_code_id_r1'), 'period_id': ref('account.period_1')}}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'l10n_lu-vat_report.'+format), 'wb+').write(data) diff --git a/addons/l10n_lu/wizard/print_vat.py b/addons/l10n_lu/wizard/print_vat.py index 9e1190cfae5..bfa058720d3 100644 --- a/addons/l10n_lu/wizard/print_vat.py +++ b/addons/l10n_lu/wizard/print_vat.py @@ -5,13 +5,14 @@ #Tranquil IT Systems from __future__ import with_statement + +import openerp from openerp.osv import fields, osv -from openerp import pooler 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 @@ -30,8 +31,8 @@ class report_custom(report_int): def create(self, cr, uid, ids, datas, context=None): - pool = pooler.get_pool(cr.dbname) - taxobj = pool.get('account.tax.code') + registry = openerp.registry(cr.dbname) + taxobj = registry['account.tax.code'] if context is None: context = {} @@ -40,7 +41,7 @@ class report_custom(report_int): for t in taxobj.browse(cr, uid, code_ids, {'period_id': datas['form']['period_id']}): if str(t.code): result['case_'+str(t.code)] = '%.2f' % (t.sum_period or 0.0, ) - user = pool.get('res.users').browse(cr, uid, uid, context) + user = registry['res.users'].browse(cr, uid, uid, context) # Not Clean, to be changed partner = user.company_id.partner_id @@ -52,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: @@ -91,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_ro/res_partner.py b/addons/l10n_ro/res_partner.py index 1cfe7390a77..96de4b4e86a 100755 --- a/addons/l10n_ro/res_partner.py +++ b/addons/l10n_ro/res_partner.py @@ -28,10 +28,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/lunch/lunch.py b/addons/lunch/lunch.py index 9f18c391eec..efad6fd6944 100644 --- a/addons/lunch/lunch.py +++ b/addons/lunch/lunch.py @@ -169,7 +169,7 @@ class lunch_order(osv.Model): line_ref = self.pool.get("lunch.order.line") if view_type == 'form': doc = etree.XML(res['arch']) - pref_ids = line_ref.search(cr, uid, [('user_id', '=', uid)], order='create_date desc', context=context) + pref_ids = line_ref.search(cr, uid, [('user_id', '=', uid)], order='id desc', context=context) xml_start = etree.Element("div") #If there are no preference (it's the first time for the user) if len(pref_ids)==0: @@ -215,63 +215,70 @@ class lunch_order(osv.Model): currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id #For each preferences that we get, we will create the XML structure - for key,value in categories.items(): + for key, value in categories.items(): xml_pref_1 = etree.Element("div") - xml_pref_1.set('class','oe_lunch_30pc') + xml_pref_1.set('class', 'oe_lunch_30pc') xml_pref_2 = etree.Element("h2") xml_pref_2.text = key xml_pref_1.append(xml_pref_2) i = 0 value = value.values() + #TODO: sorted_values is used for a quick and dirty hack in order to display the 5 last orders of each categories. + #It would be better to fetch only the 5 items to display instead of fetching everything then sorting them in order to keep only the 5 last. + #NB: The note could also be ignored + we could fetch the preferences on the most ordered products instead of the last ones... + sorted_values = {} for val in value: - for pref in val.values(): - #We only show 5 preferences per category (or it will be too long) - if i==5: break - i+=1 - xml_pref_3 = etree.Element("div") - xml_pref_3.set('class','oe_lunch_vignette') - xml_pref_1.append(xml_pref_3) + for elmt in val.values(): + sorted_values[elmt.id] = elmt + for key, pref in sorted(sorted_values.iteritems(), key=lambda (k, v): (k, v), reverse=True): + #We only show 5 preferences per category (or it will be too long) + if i == 5: + break + i += 1 + xml_pref_3 = etree.Element("div") + xml_pref_3.set('class','oe_lunch_vignette') + xml_pref_1.append(xml_pref_3) - xml_pref_4 = etree.Element("span") - xml_pref_4.set('class','oe_lunch_button') - xml_pref_3.append(xml_pref_4) + xml_pref_4 = etree.Element("span") + xml_pref_4.set('class','oe_lunch_button') + xml_pref_3.append(xml_pref_4) - xml_pref_5 = etree.Element("button") - xml_pref_5.set('name',"add_preference_"+str(pref.id)) - xml_pref_5.set('class','oe_link oe_i oe_button_plus') - xml_pref_5.set('type','object') - xml_pref_5.set('string','+') - xml_pref_4.append(xml_pref_5) + xml_pref_5 = etree.Element("button") + xml_pref_5.set('name',"add_preference_"+str(pref.id)) + xml_pref_5.set('class','oe_link oe_i oe_button_plus') + xml_pref_5.set('type','object') + xml_pref_5.set('string','+') + xml_pref_4.append(xml_pref_5) - xml_pref_6 = etree.Element("button") - xml_pref_6.set('name',"add_preference_"+str(pref.id)) - xml_pref_6.set('class','oe_link oe_button_add') - xml_pref_6.set('type','object') - xml_pref_6.set('string',_("Add")) - xml_pref_4.append(xml_pref_6) + xml_pref_6 = etree.Element("button") + xml_pref_6.set('name',"add_preference_"+str(pref.id)) + xml_pref_6.set('class','oe_link oe_button_add') + xml_pref_6.set('type','object') + xml_pref_6.set('string',_("Add")) + xml_pref_4.append(xml_pref_6) - xml_pref_7 = etree.Element("div") - xml_pref_7.set('class','oe_group_text_button') - xml_pref_3.append(xml_pref_7) + xml_pref_7 = etree.Element("div") + xml_pref_7.set('class','oe_group_text_button') + xml_pref_3.append(xml_pref_7) - xml_pref_8 = etree.Element("div") - xml_pref_8.set('class','oe_lunch_text') - xml_pref_8.text = escape(pref.product_id.name)+str(" ") - xml_pref_7.append(xml_pref_8) + xml_pref_8 = etree.Element("div") + xml_pref_8.set('class','oe_lunch_text') + xml_pref_8.text = escape(pref.product_id.name)+str(" ") + xml_pref_7.append(xml_pref_8) - price = pref.product_id.price or 0.0 - cur = currency.name or '' - xml_pref_9 = etree.Element("span") - xml_pref_9.set('class','oe_tag') - xml_pref_9.text = str(price)+str(" ")+cur - xml_pref_8.append(xml_pref_9) + price = pref.product_id.price or 0.0 + cur = currency.name or '' + xml_pref_9 = etree.Element("span") + xml_pref_9.set('class','oe_tag') + xml_pref_9.text = str(price)+str(" ")+cur + xml_pref_8.append(xml_pref_9) - xml_pref_10 = etree.Element("div") - xml_pref_10.set('class','oe_grey') - xml_pref_10.text = escape(pref.note or '') - xml_pref_3.append(xml_pref_10) + xml_pref_10 = etree.Element("div") + xml_pref_10.set('class','oe_grey') + xml_pref_10.text = escape(pref.note or '') + xml_pref_3.append(xml_pref_10) - xml_start.append(xml_pref_1) + xml_start.append(xml_pref_1) first_node = doc.xpath("//div[@name='preferences']") if first_node and len(first_node)>0: 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..02cfd626768 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -27,6 +27,19 @@ 1000 + + Garbage Collect Mail Attachments + + + 1 + weeks + -1 + + mail.thread + _garbage_collect_attachments + () + + Discussions diff --git a/addons/mail/i18n/cs.po b/addons/mail/i18n/cs.po new file mode 100644 index 00000000000..e12668ab3ee --- /dev/null +++ b/addons/mail/i18n/cs.po @@ -0,0 +1,1687 @@ +# Czech 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-03-25 07:50+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-26 04:44+0000\n" +"X-Generator: Launchpad (build 16540)\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 d9c49d833ab..8730599ad72 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 @@ -155,11 +160,11 @@ class mail_alias(osv.Model): 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) + 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]): @@ -183,13 +188,18 @@ 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 - make it unique, and the ``alias_model_id`` value will set to the - model ID of the ``model_name`` value, if provided, + make it unique (and certain unsafe characters replaced), and + he ``alias_model_id`` value will set to the model ID of the ``model_name`` + value, if provided, """ - alias_name = re.sub(r'[^\w+]', '-', remove_accents(vals['alias_name'])).lower() + # when an alias name appears to already be an email, we keep the local part only + alias_name = remove_accents(vals['alias_name']).lower().split('@')[0] + alias_name = re.sub(r'[^\w+.]+', '-', alias_name) alias_name = self._find_unique(cr, uid, alias_name, context=context) vals['alias_name'] = alias_name if model_name: diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index aa23e418d35..450b81dabbf 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -95,6 +95,9 @@ class mail_notification(osv.Model): # Do not send to partners without email address defined if not partner.email: continue + # Do not send to partners having same email address than the author (can cause loops or bounce effect due to messy database) + if message.author_id and message.author_id.email == partner.email: + continue # Partner does not want to receive any emails or is opt-out if partner.notification_email_send == 'none': continue @@ -136,10 +139,10 @@ class mail_notification(osv.Model): company = user.company_id.website and "%s" % (user.company_id.website, user.company_id.name) or user.company_id.name else: company = user.name - signature_company = _('Send by %(company)s using %(openerp)s.' % { + signature_company = _('Send by %(company)s using %(openerp)s.') % { 'company': company, 'openerp': "OpenERP" - }) + } footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') return footer @@ -186,11 +189,16 @@ class mail_notification(osv.Model): signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context) body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div') + references = False + if msg.parent_id: + references = msg.parent_id.message_id + mail_values = { 'mail_message_id': msg.id, 'auto_delete': True, 'body_html': body_html, - 'recipient_ids': [(4, id) for id in notify_partner_ids] + 'recipient_ids': [(4, id) for id in notify_partner_ids], + 'references': references, } if msg.email_from: mail_values['email_from'] = msg.email_from diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index 24aed942b1b..977608f487e 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -144,11 +144,19 @@ class mail_group(osv.Model): search_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'view_message_search') params = { 'search_view_id': search_ref and search_ref[1] or False, - 'domain': [('model', '=', 'mail.group'), ('res_id', '=', mail_group_id)], - 'context': {'default_model': 'mail.group', 'default_res_id': mail_group_id, 'search_default_message_unread': True}, + 'domain': [ + ('model', '=', 'mail.group'), + ('res_id', '=', mail_group_id), + ], + 'context': { + 'default_model': 'mail.group', + 'default_res_id': mail_group_id, + }, 'res_model': 'mail.message', 'thread_level': 1, - 'header_description': self._generate_header_description(cr, uid, group, context=context) + 'header_description': self._generate_header_description(cr, uid, group, context=context), + 'view_mailbox': True, + 'compose_placeholder': 'Send a message to the group', } cobj = self.pool.get('ir.actions.client') newref = cobj.copy(cr, SUPERUSER_ID, ref[1], default={'params': str(params), 'name': vals['name']}, context=context) diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 77c0b8f6c86..04212b2f58a 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -7,7 +7,6 @@ mail.wall mail.message { - 'search_default_message_unread': True } { 'read_action': 'read' @@ -30,6 +29,7 @@ +
@@ -43,6 +43,9 @@

+
+ %% +
@@ -69,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 43d0d707699..3c30a950230 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -21,6 +21,7 @@ import base64 import logging +import re from urllib import urlencode from urlparse import urljoin @@ -96,9 +97,19 @@ class mail_mail(osv.Model): 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): + 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 + # if model and res_id: try to use ``message_get_reply_to`` that returns the document alias - if values.get('model') and values.get('res_id') and hasattr(self.pool.get(values.get('model')), 'message_get_reply_to'): - email_reply_to = self.pool.get(values.get('model')).message_get_reply_to(cr, uid, [values.get('res_id')], context=context)[0] + if 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 -> 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')) @@ -106,10 +117,13 @@ class mail_mail(osv.Model): email_reply_to = emails[0] # format 'Document name ' - if email_reply_to and values.get('model') and values.get('res_id'): - document_name = self.pool.get(values.get('model')).name_get(cr, SUPERUSER_ID, [values.get('res_id')], context=context)[0] + if email_reply_to and model and res_id: + document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0] if document_name: - email_reply_to = _('Followers of %s <%s>') % (document_name[1], email_reply_to) + # sanitize document name + sanitized_doc_name = re.sub(r'[^\w+.]+', '-', document_name[1]) + # generate reply to + email_reply_to = _('"Followers of %s" <%s>') % (sanitized_doc_name, email_reply_to) return email_reply_to @@ -203,7 +217,7 @@ class mail_mail(osv.Model): 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) + self.pool[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} @@ -242,7 +256,19 @@ class mail_mail(osv.Model): body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) subject = self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context) body_alternative = tools.html2plaintext(body) - email_to = [partner.email] if partner else tools.email_split(mail.email_to) + + # generate email_to, heuristic: + # 1. if 'partner' is specified and there is a related document: Followers of 'Doc' + # 2. if 'partner' is specified, but no related document: Partner Name + # 3; fallback on mail.email_to that we split to have an email addresses list + if partner and mail.record_name: + sanitized_record_name = re.sub(r'[^\w+.]+', '-', mail.record_name) + email_to = [_('"Followers of %s" <%s>') % (sanitized_record_name, partner.email)] + elif partner: + email_to = ['%s <%s>' % (partner.name, partner.email)] + else: + email_to = tools.email_split(mail.email_to) + return { 'body': body, 'body_alternative': body_alternative, diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 8442891f3f9..defc12a2f73 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -76,9 +76,9 @@ class mail_message(osv.Model): # TDE note: regroup by model/ids, to have less queries to perform result = dict.fromkeys(ids, False) for message in self.read(cr, uid, ids, ['model', 'res_id'], context=context): - if not message.get('model') or not message.get('res_id') or not self.pool.get(message['model']): + if not message.get('model') or not message.get('res_id') or message['model'] not in self.pool: continue - result[message['id']] = self.pool.get(message['model']).name_get(cr, SUPERUSER_ID, [message['res_id']], context=context)[0][1] + result[message['id']] = self.pool[message['model']].name_get(cr, SUPERUSER_ID, [message['res_id']], context=context)[0][1] return result def _get_to_read(self, cr, uid, ids, name, arg, context=None): @@ -268,19 +268,25 @@ class mail_message(osv.Model): domain = [('partner_id', '=', user_pid), ('message_id', 'in', msg_ids)] if not create_missing: domain += [('starred', '=', not starred)] + values = { + 'starred': starred + } + if starred: + values['read'] = False + notif_ids = notification_obj.search(cr, uid, domain, context=context) # all message have notifications: already set them as (un)starred if len(notif_ids) == len(msg_ids) or not create_missing: - notification_obj.write(cr, uid, notif_ids, {'starred': starred}, context=context) + notification_obj.write(cr, uid, notif_ids, values, context=context) return starred # some messages do not have notifications: find which one, create notification, update starred status notified_msg_ids = [notification.message_id.id for notification in notification_obj.browse(cr, uid, notif_ids, context=context)] to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids)) for msg_id in to_create_msg_ids: - notification_obj.create(cr, uid, {'partner_id': user_pid, 'starred': starred, 'message_id': msg_id}, context=context) - notification_obj.write(cr, uid, notif_ids, {'starred': starred}, context=context) + notification_obj.create(cr, uid, dict(values, partner_id=user_pid, message_id=msg_id), context=context) + notification_obj.write(cr, uid, notif_ids, values, context=context) return starred #------------------------------------------------------ @@ -363,6 +369,7 @@ class mail_message(osv.Model): return {'id': message.id, 'type': message.type, + 'subtype': message.subtype_id.name if message.subtype_id else False, 'body': body_html, 'model': message.model, 'res_id': message.res_id, @@ -563,7 +570,7 @@ class mail_message(osv.Model): def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None): doc_ids = doc_dict.keys() - allowed_doc_ids = self.pool.get(doc_model).search(cr, uid, [('id', 'in', doc_ids)], context=context) + allowed_doc_ids = self.pool[doc_model].search(cr, uid, [('id', 'in', doc_ids)], context=context) return set([message_id for allowed_doc_id in allowed_doc_ids for message_id in doc_dict[allowed_doc_id]]) def _find_allowed_doc_ids(self, cr, uid, model_ids, context=None): @@ -711,7 +718,7 @@ class mail_message(osv.Model): model_record_ids = _generate_model_record_ids(message_values, other_ids) document_related_ids = [] for model, doc_dict in model_record_ids.items(): - model_obj = self.pool.get(model) + model_obj = self.pool[model] mids = model_obj.exists(cr, uid, doc_dict.keys()) if operation in ['create', 'write', 'unlink']: model_obj.check_access_rights(cr, uid, 'write') @@ -767,7 +774,7 @@ class mail_message(osv.Model): attachments_to_delete = [] for message in self.browse(cr, uid, ids, context=context): for attach in message.attachment_ids: - if attach.res_model == self._name and attach.res_id == message.id: + if attach.res_model == self._name and (attach.res_id == message.id or attach.res_id == 0): attachments_to_delete.append(attach.id) if attachments_to_delete: self.pool.get('ir.attachment').unlink(cr, uid, attachments_to_delete, context=context) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index b8bd028289f..5ddf412e66b 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -89,6 +89,46 @@ class mail_thread(osv.AbstractModel): # :param function lambda: returns whether the tracking should record using this subtype _track = {} + def get_empty_list_help(self, cr, uid, help, context=None): + """ Override of BaseModel.get_empty_list_help() to generate an help message + that adds alias information. """ + model = context.get('empty_list_help_model') + res_id = context.get('empty_list_help_id') + ir_config_parameter = self.pool.get("ir.config_parameter") + catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context) + document_name = context.get('empty_list_help_document_name', _('document')) + alias = None + + if catchall_domain and model and res_id: # specific res_id -> find its alias (i.e. section_id specified) + object_id = self.pool.get(model).browse(cr, uid, res_id, context=context) + alias = object_id.alias_id + elif catchall_domain and model: # no specific res_id given -> generic help message, take an example alias (i.e. alias of some section_id) + model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] + alias_obj = self.pool.get('mail.alias') + alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=1, order='id ASC') + if alias_ids: + alias = alias_obj.browse(cr, uid, alias_ids[0], context=context) + + if alias: + alias_email = alias.name_get()[0][1] + return _("""

+ Click here to add a new %(document)s or send an email to: %(email)s +

+ %(static_help)s""" + ) % { + 'document': document_name, + 'email': alias_email, + 'static_help': help or '' + } + + if document_name != 'document' and help and help.find("oe_view_nocontent_create") == -1: + return _("

Click here to add a new %(document)s

%(static_help)s") % { + 'document': document_name, + 'static_help': help or '', + } + + return help + def _get_message_data(self, cr, uid, ids, name, args, context=None): """ Computes: - message_unread: has uid unread message for the document @@ -368,7 +408,7 @@ class mail_thread(osv.AbstractModel): posted = False for subtype in subtypes: try: - subtype_rec = self.pool.get('ir.model.data').get_object(cr, uid, subtype.split('.')[0], subtype.split('.')[1]) + subtype_rec = self.pool.get('ir.model.data').get_object(cr, uid, subtype.split('.')[0], subtype.split('.')[1], context=context) except ValueError, e: _logger.debug('subtype %s not found, giving error "%s"' % (subtype, e)) continue @@ -389,6 +429,26 @@ class mail_thread(osv.AbstractModel): return [('message_unread', '=', True)] return [] + def _garbage_collect_attachments(self, cr, uid, context=None): + """ Garbage collect lost mail attachments. Those are attachments + - linked to res_model 'mail.compose.message', the composer wizard + - with res_id 0, because they were created outside of an existing + wizard (typically user input through Chatter or reports + created on-the-fly by the templates) + - unused since at least one day (create_date and write_date) + """ + limit_date = datetime.datetime.utcnow() - datetime.timedelta(days=1) + limit_date_str = datetime.datetime.strftime(limit_date, tools.DEFAULT_SERVER_DATETIME_FORMAT) + ir_attachment_obj = self.pool.get('ir.attachment') + attach_ids = ir_attachment_obj.search(cr, uid, [ + ('res_model', '=', 'mail.compose.message'), + ('res_id', '=', 0), + ('create_date', '<', limit_date_str), + ('write_date', '<', limit_date_str), + ], context=context) + ir_attachment_obj.unlink(cr, uid, attach_ids, context=context) + return True + #------------------------------------------------------ # Email specific #------------------------------------------------------ @@ -409,18 +469,27 @@ class mail_thread(osv.AbstractModel): """ Used by the plugin addon, based for plugin_outlook and others. """ ret_dict = {} for model_name in self.pool.obj_list(): - model = self.pool.get(model_name) + model = self.pool[model_name] if 'mail.thread' in getattr(model, '_inherit', []): ret_dict[model_name] = model._description return ret_dict def _message_find_partners(self, cr, uid, message, header_fields=['From'], context=None): - """ Find partners related to some header fields of the message. """ + """ Find partners related to some header fields of the message. + + TDE TODO: merge me with other partner finding methods in 8.0 """ + partner_obj = self.pool.get('res.partner') + partner_ids = [] s = ', '.join([decode(message.get(h)) for h in header_fields if message.get(h)]) - return [partner_id for email in tools.email_split(s) - for partner_id in self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], limit=1, context=context)] + for email_address in tools.email_split(s): + related_partners = partner_obj.search(cr, uid, [('email', 'ilike', email_address), ('user_ids', '!=', False)], limit=1, context=context) + if not related_partners: + related_partners = partner_obj.search(cr, uid, [('email', 'ilike', email_address)], limit=1, context=context) + partner_ids += related_partners + return partner_ids def _message_find_user_id(self, cr, uid, message, context=None): + """ TDE TODO: check and maybe merge me with other user finding methods in 8.0 """ from_local_part = tools.email_split(decode(message.get('From')))[0] # FP Note: canonification required, the minimu: .lower() user_ids = self.pool.get('res.users').search(cr, uid, ['|', @@ -462,6 +531,8 @@ class mail_thread(osv.AbstractModel): """ assert isinstance(message, Message), 'message must be an email.message.Message at this point' message_id = message.get('Message-Id') + email_from = decode_header(message, 'From') + email_to = decode_header(message, 'To') references = decode_header(message, 'References') in_reply_to = decode_header(message, 'In-Reply-To') @@ -472,12 +543,12 @@ class mail_thread(osv.AbstractModel): if ref_match: thread_id = int(ref_match.group(1)) model = ref_match.group(2) or model - model_pool = self.pool.get(model) - if thread_id and model and model_pool and model_pool.exists(cr, uid, thread_id) \ - and hasattr(model_pool, 'message_update'): - _logger.debug('Routing mail with Message-Id %s: direct reply to model: %s, thread_id: %s, custom_values: %s, uid: %s', - message_id, model, thread_id, custom_values, uid) - return [(model, thread_id, custom_values, uid)] + if thread_id and model in self.pool: + model_obj = self.pool[model] + if model_obj.exists(cr, uid, thread_id) and hasattr(model_obj, 'message_update'): + _logger.info('Routing mail from %s to %s with Message-Id %s: direct reply to model: %s, thread_id: %s, custom_values: %s, uid: %s', + email_from, email_to, message_id, model, thread_id, custom_values, uid) + return [(model, thread_id, custom_values, uid)] # Verify whether this is a reply to a private message if in_reply_to: @@ -487,8 +558,8 @@ class mail_thread(osv.AbstractModel): ], limit=1, context=context) if message_ids: message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context) - _logger.debug('Routing mail with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s', - message_id, message.id, custom_values, uid) + _logger.info('Routing mail from %s to %s with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s', + email_from, email_to, message_id, message.id, custom_values, uid) return [(message.model, message.res_id, custom_values, uid)] # 2. Look for a matching mail.alias entry @@ -515,10 +586,11 @@ class mail_thread(osv.AbstractModel): # Note: recognized partners will be added as followers anyway # user_id = self._message_find_user_id(cr, uid, message, context=context) user_id = uid - _logger.debug('No matching user_id for the alias %s', alias.alias_name) + _logger.info('No matching user_id for the alias %s', alias.alias_name) routes.append((alias.alias_model_id.model, alias.alias_force_thread_id, \ eval(alias.alias_defaults), user_id)) - _logger.debug('Routing mail with Message-Id %s: direct alias match: %r', message_id, routes) + _logger.info('Routing mail from %s to %s with Message-Id %s: direct alias match: %r', + email_from, email_to, message_id, routes) return routes # 3. Fallback to the provided parameters, if they work @@ -527,15 +599,20 @@ class mail_thread(osv.AbstractModel): # Legacy: fallback to matching [ID] in the Subject match = tools.res_re.search(decode_header(message, 'Subject')) thread_id = match and match.group(1) + # Convert into int (bug spotted in 7.0 because of str) + try: + thread_id = int(thread_id) + except: + thread_id = False assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ - "No possible route found for incoming message with Message-Id %s. " \ - "Create an appropriate mail.alias or force the destination model." % message_id + "No possible route found for incoming message from %s to %s (Message-Id %s:)." \ + "Create an appropriate mail.alias or force the destination model." % (email_from, email_to, message_id) if thread_id and not model_pool.exists(cr, uid, thread_id): _logger.warning('Received mail reply to missing document %s! Ignoring and creating new document instead for Message-Id %s', - thread_id, message_id) + thread_id, message_id) thread_id = None - _logger.debug('Routing mail with Message-Id %s: fallback to model:%s, thread_id:%s, custom_values:%s, uid:%s', - message_id, model, thread_id, custom_values, uid) + _logger.info('Routing mail from %s to %s with Message-Id %s: fallback to model:%s, thread_id:%s, custom_values:%s, uid:%s', + email_from, email_to, message_id, model, thread_id, custom_values, uid) return [(model, thread_id, custom_values, uid)] def message_process(self, cr, uid, model, message, custom_values=None, @@ -585,12 +662,24 @@ class mail_thread(osv.AbstractModel): if isinstance(message, unicode): message = message.encode('utf-8') msg_txt = email.message_from_string(message) - routes = self.message_route(cr, uid, msg_txt, model, - thread_id, custom_values, - context=context) + + # parse the message, verify we are not in a loop by checking message_id is not duplicated msg = self.message_parse(cr, uid, msg_txt, save_original=save_original, context=context) if strip_attachments: msg.pop('attachments', None) + if msg.get('message_id'): # should always be True as message_parse generate one if missing + existing_msg_ids = self.pool.get('mail.message').search(cr, SUPERUSER_ID, [ + ('message_id', '=', msg.get('message_id')), + ], context=context) + if existing_msg_ids: + _logger.info('Ignored mail from %s to %s with Message-Id %s:: found duplicated Message-Id during processing', + msg.get('from'), msg.get('to'), msg.get('message_id')) + return False + + # find possible routes for the message + routes = self.message_route(cr, uid, msg_txt, model, + thread_id, custom_values, + context=context) # postpone setting msg.partner_ids after message_post, to avoid double notifications partner_ids = msg.pop('partner_ids', []) @@ -600,7 +689,7 @@ class mail_thread(osv.AbstractModel): if self._name == 'mail.thread': context.update({'thread_model': model}) if model: - model_pool = self.pool.get(model) + model_pool = self.pool[model] assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" % \ (msg['message_id'], model) @@ -654,7 +743,7 @@ class mail_thread(osv.AbstractModel): if isinstance(custom_values, dict): data = custom_values.copy() model = context.get('thread_model') or self._name - model_pool = self.pool.get(model) + model_pool = self.pool[model] fields = model_pool.fields_get(cr, uid, context=context) if 'name' in fields and not data.get('name'): data['name'] = msg_dict.get('subject', '') @@ -787,7 +876,7 @@ class mail_thread(osv.AbstractModel): # as RFC2822 requires timezone offset in Date headers. stored_date = parsed_date.replace(tzinfo=pytz.utc) else: - stored_date = parsed_date.astimezone(pytz.utc) + stored_date = parsed_date.astimezone(tz=pytz.utc) except Exception: _logger.warning('Failed to parse Date header %r in incoming mail ' 'with message-id %r, assuming current date/time.', @@ -806,7 +895,7 @@ class mail_thread(osv.AbstractModel): if parent_ids: msg_dict['parent_id'] = parent_ids[0] - msg_dict['body'], msg_dict['attachments'] = self._message_extract_payload(message) + msg_dict['body'], msg_dict['attachments'] = self._message_extract_payload(message, save_original=save_original) return msg_dict #------------------------------------------------------ @@ -826,7 +915,8 @@ class mail_thread(osv.AbstractModel): recipient in the result dictionary. The form is : partner_id, partner_name or partner_name, reason """ if email and not partner: - partner_info = self.message_get_partner_info_from_emails(cr, uid, [email], context=context)[0] + # get partner info from email + partner_info = self.message_get_partner_info_from_emails(cr, uid, [email], context=context, res_id=obj.id)[0] if partner_info.get('partner_id'): partner = self.pool.get('res.partner').browse(cr, SUPERUSER_ID, [partner_info.get('partner_id')], context=context)[0] if email and email in [val[1] for val in result[obj.id]]: # already existing email -> skip @@ -854,29 +944,49 @@ class mail_thread(osv.AbstractModel): self._message_add_suggested_recipient(cr, uid, result, obj, partner=obj.user_id.partner_id, reason=self._all_columns['user_id'].column.string, context=context) return result - def message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None): + def message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None, res_id=None): + """ Wrapper with weird order parameter because of 7.0 fix. + + TDE TODO: remove me in 8.0 """ + return self.message_find_partner_from_emails(cr, uid, res_id, emails, link_mail=link_mail, context=context) + + def message_find_partner_from_emails(self, cr, uid, id, emails, link_mail=False, context=None): """ Convert a list of emails into a list partner_ids and a list new_partner_ids. The return value is non conventional because it is meant to be used by the mail widget. :return dict: partner_ids and new_partner_ids - """ + + TDE TODO: merge me with other partner finding methods in 8.0 """ mail_message_obj = self.pool.get('mail.message') partner_obj = self.pool.get('res.partner') result = list() + if id and self._name != 'mail.thread': + obj = self.browse(cr, SUPERUSER_ID, id, context=context) + else: + obj = None for email in emails: partner_info = {'full_name': email, 'partner_id': False} m = re.search(r"((.+?)\s*<)?([^<>]+@[^<>]+)>?", email, re.IGNORECASE | re.DOTALL) if not m: continue email_address = m.group(3) - ids = partner_obj.search(cr, SUPERUSER_ID, [('email', '=', email_address)], context=context) - if ids: - partner_info['partner_id'] = ids[0] + # first try: check in document's followers + if obj: + for follower in obj.message_follower_ids: + if follower.email == email_address: + partner_info['partner_id'] = follower.id + # second try: check in partners + if not partner_info.get('partner_id'): + ids = partner_obj.search(cr, SUPERUSER_ID, [('email', 'ilike', email_address), ('user_ids', '!=', False)], limit=1, context=context) + if not ids: + ids = partner_obj.search(cr, SUPERUSER_ID, [('email', 'ilike', email_address)], limit=1, context=context) + if ids: + partner_info['partner_id'] = ids[0] result.append(partner_info) # link mail with this from mail to the new partner id - if link_mail and ids: + if link_mail and partner_info['partner_id']: message_ids = mail_message_obj.search(cr, SUPERUSER_ID, [ '|', ('email_from', '=', email), @@ -884,7 +994,7 @@ class mail_thread(osv.AbstractModel): ('author_id', '=', False) ], context=context) if message_ids: - mail_message_obj.write(cr, SUPERUSER_ID, message_ids, {'author_id': ids[0]}, context=context) + mail_message_obj.write(cr, SUPERUSER_ID, message_ids, {'author_id': partner_info['partner_id']}, context=context) return result def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', @@ -929,12 +1039,31 @@ class mail_thread(osv.AbstractModel): model = False if thread_id: model = context.get('thread_model', self._name) if self._name == 'mail.thread' else self._name + if model != self._name: + del context['thread_model'] + return self.pool[model].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) + + # 0: Parse email-from, try to find a better author_id based on document's followers for incoming emails + email_from = kwargs.get('email_from') + if email_from and thread_id and type == 'email' and kwargs.get('author_id'): + email_list = tools.email_split(email_from) + doc = self.browse(cr, uid, thread_id, context=context) + if email_list and doc: + author_ids = self.pool.get('res.partner').search(cr, uid, [ + ('email', 'ilike', email_list[0]), + ('id', 'in', [f.id for f in doc.message_follower_ids]) + ], limit=1, context=context) + if author_ids: + kwargs['author_id'] = author_ids[0] + author_id = kwargs.get('author_id') + if author_id is None: # keep False values + author_id = self.pool.get('mail.message')._get_default_author(cr, uid, context=context) # 1: Handle content subtype: if plaintext, converto into HTML if content_subtype == 'plaintext': body = tools.plaintext2html(body) - # 2: Private message: add recipients (recipients and author of parent message) + # 2: Private message: add recipients (recipients and author of parent message) - current author # + legacy-code management (! we manage only 4 and 6 commands) partner_ids = set() kwargs_partner_ids = kwargs.pop('partner_ids', []) @@ -947,11 +1076,13 @@ class mail_thread(osv.AbstractModel): partner_ids.add(partner_id) else: pass # we do not manage anything else - if parent_id and model == 'mail.thread': + if parent_id and not model: parent_message = mail_message.browse(cr, uid, parent_id, context=context) - partner_ids |= set([partner.id for partner in parent_message.partner_ids]) + private_followers = set([partner.id for partner in parent_message.partner_ids]) if parent_message.author_id: - partner_ids.add(parent_message.author_id.id) + private_followers.add(parent_message.author_id.id) + private_followers -= set([author_id]) + partner_ids |= private_followers # 3. Attachments # - HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message @@ -959,7 +1090,6 @@ class mail_thread(osv.AbstractModel): if attachment_ids: filtered_attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [ ('res_model', '=', 'mail.compose.message'), - ('res_id', '=', 0), ('create_uid', '=', uid), ('id', 'in', attachment_ids)], context=context) if filtered_attachment_ids: @@ -1012,6 +1142,7 @@ class mail_thread(osv.AbstractModel): values = kwargs values.update({ + 'author_id': author_id, 'model': model, 'res_id': thread_id or False, 'body': body, diff --git a/addons/mail/res_users.py b/addons/mail/res_users.py index f7c91939b98..5545745b235 100644 --- a/addons/mail/res_users.py +++ b/addons/mail/res_users.py @@ -60,8 +60,9 @@ class res_users(osv.Model): def _auto_init(self, cr, context=None): """ Installation hook: aliases, partner following themselves """ # create aliases for all users and avoid constraint errors - self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(res_users, self)._auto_init, + res = self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(res_users, self)._auto_init, self._columns['alias_id'], 'login', alias_force_key='id', context=context) + return res def create(self, cr, uid, data, context=None): # create default alias same as the login diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 51306727a09..6bc086a5b58 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -57,6 +57,9 @@ .openerp .oe_mail .oe_msg.oe_msg_nobody{ background: #F8F8F8; } +.openerp .oe_mail .oe_msg.oe_msg_notification{ + background: #F8F8F8; +} .openerp .oe_mail .oe_msg .oe_msg_left{ position: absolute; left:0; top: 0; bottom: 0; width: 40px; @@ -568,7 +571,6 @@ text-shadow: none; width: 100%; } -.openerp .oe_followers button.oe_invite, .openerp .oe_followers button.oe_follower.oe_following{ color: white; background-color: #3465A4; @@ -626,6 +628,8 @@ height: 32px; overflow: hidden; white-space: nowrap; + text-overflow: ellipsis; + margin-right: 10px; } .openerp .oe_followers .oe_partner img{ width: 32px; diff --git a/addons/mail/static/src/css/mail_group.css b/addons/mail/static/src/css/mail_group.css index c1cefee9070..4f2b8a16dd0 100644 --- a/addons/mail/static/src/css/mail_group.css +++ b/addons/mail/static/src/css/mail_group.css @@ -14,6 +14,10 @@ padding: 0px 18px; } +.openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_avatar { + padding-top: 3px; +} + /* Resize footer width */ .openerp .oe_form div.oe_mail_group_footer { max-width: 80%; @@ -21,7 +25,7 @@ /* Resize group description */ .openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_text > textarea { - height: 40px; + height: 60px; } /* ------------------------------ */ diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index f6e098b466d..b1a579ba057 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -217,6 +217,7 @@ openerp.mail = function (session) { this.res_id = datasets.res_id || this.context.default_res_id || false, this.parent_id = datasets.parent_id || false, this.type = datasets.type || false, + this.subtype = datasets.subtype || false, this.is_author = datasets.is_author || false, this.is_private = datasets.is_private || false, this.subject = datasets.subject || false, @@ -619,7 +620,10 @@ openerp.mail = function (session) { // have unknown names -> call message_get_partner_info_from_emails to try to find partner_id var find_done = $.Deferred(); if (names_to_find.length > 0) { - find_done = self.parent_thread.ds_thread._model.call('message_get_partner_info_from_emails', [names_to_find]); + var values = { + 'res_id': this.context.default_res_id, + } + find_done = self.parent_thread.ds_thread._model.call('message_get_partner_info_from_emails', [names_to_find], values); } else { find_done.resolve([]); @@ -665,7 +669,11 @@ openerp.mail = function (session) { var new_names_to_find = _.difference(names_to_find, names_to_remove); find_done = $.Deferred(); if (new_names_to_find.length > 0) { - find_done = self.parent_thread.ds_thread._model.call('message_get_partner_info_from_emails', [new_names_to_find, true]); + var values = { + 'link_mail': true, + 'res_id': self.context.default_res_id, + } + find_done = self.parent_thread.ds_thread._model.call('message_get_partner_info_from_emails', [new_names_to_find], values); } else { find_done.resolve([]); @@ -688,6 +696,10 @@ openerp.mail = function (session) { on_message_post: function (event) { var self = this; + if (self.flag_post) { + return; + } + self.flag_post = true; if (this.do_check_attachment_upload() && (this.attachment_ids.length || this.$('textarea').val().match(/\S+/))) { if (this.is_log) { this.do_send_message_post([], this.is_log); @@ -735,6 +747,7 @@ openerp.mail = function (session) { thread.insert_message( message, root ? undefined : self.$el, root ); }); self.on_cancel(); + self.flag_post = false; }); }, @@ -910,9 +923,6 @@ openerp.mail = function (session) { // read messages self.parent_thread.message_fetch(this.domain, this.context, false, function (arg, data) { - if (self.options.root_thread == self.parent_thread) { - data.reverse(); - } self.id = false; // insert the message on dom after this message self.parent_thread.switch_new_message( data, self.$el ); @@ -1206,13 +1216,13 @@ openerp.mail = function (session) { this.author_id = datasets.author_id || false; this.thread_level = (datasets.thread_level+1) || 0; datasets.partner_ids = datasets.partner_ids || []; - if (datasets.author_id && ! _.contains(datasets.partner_ids, datasets.author_id) && datasets.author_id[0]) { + if (datasets.author_id && !_.contains(_.flatten(datasets.partner_ids),datasets.author_id[0]) && datasets.author_id[0]) { datasets.partner_ids.push(datasets.author_id); } this.partner_ids = datasets.partner_ids; this.messages = []; - this.options.flat_mode = !!(this.options.display_indented_thread > this.thread_level ? this.options.display_indented_thread - this.thread_level : 0); + this.options.flat_mode = (this.options.display_indented_thread - this.thread_level > 0); // object compose message this.compose_message = false; @@ -1387,7 +1397,10 @@ openerp.mail = function (session) { if (this.options.help) { no_message.html(this.options.help); } - no_message.appendTo(this.$el); + if (!this.$el.find(".oe_view_nocontent").length) + { + no_message.appendTo(this.$el); + } }, /** @@ -1434,8 +1447,8 @@ openerp.mail = function (session) { create_message_object: function (data) { var self = this; - var data = _.extend(data, {'thread_level': data.thread_level ? data.thread_level : self.thread_level}); - data.options = _.extend(self.options, data.options); + data.thread_level = self.thread_level || 0; + data.options = _.extend(data.options || {}, self.options); if (data.type=='expandable') { var message = new mail.ThreadExpandable(self, data, {'context':{ @@ -1480,8 +1493,7 @@ openerp.mail = function (session) { } this.$('.oe_view_nocontent').remove(); - - if (dom_insert_after) { + if (dom_insert_after && dom_insert_after.parent()[0] == self.$el[0]) { message.insertAfter(dom_insert_after); } else if (prepend) { message.prependTo(self.$el); @@ -1500,6 +1512,7 @@ openerp.mail = function (session) { */ switch_new_message: function (records, dom_insert_after) { var self=this; + var dom_insert_after = typeof dom_insert_after == 'object' ? dom_insert_after : false; _(records).each(function (record) { var thread = self.browse_thread({ 'id': record.parent_id, @@ -1508,7 +1521,7 @@ openerp.mail = function (session) { // create object and attach to the thread object var message = thread.create_message_object( record ); // insert the message on dom - thread.insert_message( message, typeof dom_insert_after == 'object' ? dom_insert_after : false); + thread.insert_message( message, dom_insert_after); }); if (!records.length && this.options.root_thread == this) { this.no_message(); @@ -1932,6 +1945,7 @@ openerp.mail = function (session) { this.$(".oe_write_full").click(function (event) { event.stopPropagation(); var action = { + name: _t('Compose Email'), type: 'ir.actions.act_window', res_model: 'mail.compose.message', view_mode: 'form', diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 6fc2f0fdfcd..f812844194b 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -148,8 +148,6 @@ openerp_mail_followers = function(session, mail) { }).then(self.proxy('display_generic')); }, _format_followers: function(count){ - // TDE note: why redefining _t ? - function _t(str) { return str; } var str = ''; if(count <= 0){ str = _t('No followers'); diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index b26ef06f5e4..7e7d772397a 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -226,7 +226,7 @@ -
+
@@ -246,7 +246,11 @@

- : + + + + + :

@@ -259,13 +263,23 @@ - + + updated document + + • + + + logged a note - + to + + nobody + - + @@ -275,6 +289,9 @@ and more + + notified + • • diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index 16bef174470..f3317223f1d 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -30,7 +30,7 @@ -->
- + X
diff --git a/addons/mail/tests/__init__.py b/addons/mail/tests/__init__.py index b945da54655..ff1080b0580 100644 --- a/addons/mail/tests/__init__.py +++ b/addons/mail/tests/__init__.py @@ -19,11 +19,12 @@ # ############################################################################## -from . import test_mail_message, test_mail_features, test_message_read, test_invite +from . import test_mail_message, test_mail_features, test_mail_gateway, test_message_read, test_invite checks = [ test_mail_message, test_mail_features, + test_mail_gateway, test_message_read, test_invite, ] diff --git a/addons/mail/tests/test_mail_base.py b/addons/mail/tests/test_mail_base.py index fb53220ef1f..a3b90288f0b 100644 --- a/addons/mail/tests/test_mail_base.py +++ b/addons/mail/tests/test_mail_base.py @@ -70,9 +70,9 @@ class TestMailBase(common.TransactionCase): # Test users to use through the various tests self.user_raoul_id = self.res_users.create(cr, uid, - {'name': 'Raoul Grosbedon', 'signature': 'Raoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]}) + {'name': 'Raoul Grosbedon', 'signature': 'SignRaoul', 'email': 'raoul@raoul.fr', 'login': 'raoul', 'groups_id': [(6, 0, [self.group_employee_id])]}) self.user_bert_id = self.res_users.create(cr, uid, - {'name': 'Bert Tartignole', 'signature': 'Bert', 'email': 'bert@bert.fr', 'login': 'bert', 'groups_id': [(6, 0, [])]}) + {'name': 'Bert Tartignole', 'signature': 'SignBert', 'email': 'bert@bert.fr', 'login': 'bert', 'groups_id': [(6, 0, [])]}) self.user_raoul = self.res_users.browse(cr, uid, self.user_raoul_id) self.user_bert = self.res_users.browse(cr, uid, self.user_bert_id) self.user_admin = self.res_users.browse(cr, uid, uid) diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py index da7f2ae351c..7eea66b3b90 100644 --- a/addons/mail/tests/test_mail_features.py +++ b/addons/mail/tests/test_mail_features.py @@ -22,164 +22,29 @@ from openerp.addons.mail.tests.test_mail_base import TestMailBase from openerp.tools.mail import html_sanitize -MAIL_TEMPLATE = """Return-Path: -To: {to} -Received: by mail1.openerp.com (Postfix, from userid 10002) - id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST) -From: Sylvie Lelitre -Subject: {subject} -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_Part_4200734_24778174.1344608186754" -Date: Fri, 10 Aug 2012 14:16:26 +0000 -Message-ID: <1198923581.41972151344608186760.JavaMail@agrolait.com> -{extra} -------=_Part_4200734_24778174.1344608186754 -Content-Type: text/plain; charset=utf-8 -Content-Transfer-Encoding: quoted-printable - -Please call me as soon as possible this afternoon! - --- -Sylvie -------=_Part_4200734_24778174.1344608186754 -Content-Type: text/html; charset=utf-8 -Content-Transfer-Encoding: quoted-printable - - - - =20 - - =20 - =20 - -

Please call me as soon as possible this afternoon!

- -

--
- Sylvie -

- - -------=_Part_4200734_24778174.1344608186754-- -""" - -MAIL_TEMPLATE_PLAINTEXT = """Return-Path: -To: {to} -Received: by mail1.openerp.com (Postfix, from userid 10002) - id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST) -From: Sylvie Lelitre -Subject: {subject} -MIME-Version: 1.0 -Content-Type: text/plain -Date: Fri, 10 Aug 2012 14:16:26 +0000 -Message-ID: {msg_id} -{extra} - -Please call me as soon as possible this afternoon! - --- -Sylvie -""" - class test_mail(TestMailBase): - - def test_00_message_process(self): - """ Testing incoming emails processing. """ - cr, uid, user_raoul = self.cr, self.uid, self.user_raoul - - # groups@.. will cause the creation of new mail groups - self.mail_group_model_id = self.ir_model.search(cr, uid, [('model', '=', 'mail.group')])[0] - self.mail_alias.create(cr, uid, {'alias_name': 'groups', 'alias_model_id': self.mail_group_model_id}) - - # Incoming mail creates a new mail_group "frogs" - self.assertEqual(self.mail_group.search(cr, uid, [('name', '=', 'frogs')]), []) - mail_frogs = MAIL_TEMPLATE.format(to='groups@example.com, other@gmail.com', subject='frogs', extra='') - self.mail_thread.message_process(cr, uid, None, mail_frogs) - frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'frogs')]) - self.assertTrue(len(frog_groups) == 1) - - # Previously-created group can be emailed now - it should have an implicit alias group+frogs@... - frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) - group_messages = frog_group.message_ids - self.assertTrue(len(group_messages) == 1, 'New group should only have the original message') - mail_frog_news = MAIL_TEMPLATE.format(to='Friendly Frogs ', subject='news', extra='') - self.mail_thread.message_process(cr, uid, None, mail_frog_news) - frog_group.refresh() - self.assertTrue(len(frog_group.message_ids) == 2, 'Group should contain 2 messages now') - - # Even with a wrong destination, a reply should end up in the correct thread - mail_reply = MAIL_TEMPLATE.format(to='erroneous@example.com>', subject='Re: news', - extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) - self.mail_thread.message_process(cr, uid, None, mail_reply) - frog_group.refresh() - self.assertTrue(len(frog_group.message_ids) == 3, 'Group should contain 3 messages now') - - # No model passed and no matching alias must raise - mail_spam = MAIL_TEMPLATE.format(to='noone@example.com', subject='spam', extra='') - self.assertRaises(Exception, - self.mail_thread.message_process, - cr, uid, None, mail_spam) - - # plain text content should be wrapped and stored as html - test_msg_id = '' - mail_text = MAIL_TEMPLATE_PLAINTEXT.format(to='groups@example.com', subject='frogs', extra='', msg_id=test_msg_id) - self.mail_thread.message_process(cr, uid, None, mail_text) - new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id', '=', test_msg_id)])[0]) - self.assertEqual(new_mail.body, '

\nPlease call me as soon as possible this afternoon!\n\n--\nSylvie\n
', - 'plaintext mail incorrectly parsed') - - # Do: post a new message, with a known partner - test_msg_id = '' - TEMPLATE_MOD = MAIL_TEMPLATE_PLAINTEXT.replace('Sylvie Lelitre ', user_raoul.email) - mail_new = TEMPLATE_MOD.format(to='Friendly Frogs ', subject='extra news', extra='', msg_id=test_msg_id) - self.mail_thread.message_process(cr, uid, None, mail_new) - new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id', '=', test_msg_id)])[0]) - # Test: author_id set, not email_from - self.assertEqual(new_mail.author_id, user_raoul.partner_id, 'message process wrong author found') - self.assertEqual(new_mail.email_from, user_raoul.email, 'message process wrong email_from') - - # Do: post a new message, with a unknown partner - test_msg_id = '' - TEMPLATE_MOD = MAIL_TEMPLATE_PLAINTEXT.replace('Sylvie Lelitre ', '_abcd_') - mail_new = TEMPLATE_MOD.format(to='Friendly Frogs ', subject='super news', extra='', msg_id=test_msg_id) - self.mail_thread.message_process(cr, uid, None, mail_new) - new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id', '=', test_msg_id)])[0]) - # Test: author_id set, not email_from - self.assertFalse(new_mail.author_id, 'message process shnould not have found a partner for _abcd_ email address') - self.assertIn('_abcd_', new_mail.email_from, 'message process should set en email_from when not finding a partner_id') - - def test_05_thread_parent_resolution(self): - """Verify parent/child relationships are correctly established when processing incoming mails""" + + def test_000_alias_setup(self): + """ Test basic mail.alias setup works, before trying to use them for routing """ cr, uid = self.cr, self.uid - group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) - msg1 = group_pigs.message_post(body='My Body', subject='1') - msg2 = group_pigs.message_post(body='My Body', subject='2') - msg1, msg2 = self.mail_message.browse(cr, uid, [msg1, msg2]) - self.assertTrue(msg1.message_id, "New message should have a proper message_id") + self.user_valentin_id = self.res_users.create(cr, uid, + {'name': 'Valentin Cognito', 'email': 'valentin.cognito@gmail.com', 'login': 'valentin.cognito'}) + self.user_valentin = self.res_users.browse(cr, uid, self.user_valentin_id) + self.assertEquals(self.user_valentin.alias_name, self.user_valentin.login, "Login should be used as alias") - # Reply to msg1, make sure the reply is properly attached using the various reply identification mechanisms - # 1. In-Reply-To header - reply_msg = MAIL_TEMPLATE.format(to='Pretty Pigs , other@gmail.com', subject='Re: 1', - extra='In-Reply-To: %s' % msg1.message_id) - self.mail_group.message_process(cr, uid, None, reply_msg) + self.user_pagan_id = self.res_users.create(cr, uid, + {'name': 'Pagan Le Marchant', 'email': 'plmarchant@gmail.com', 'login': 'plmarchant@gmail.com'}) + self.user_pagan = self.res_users.browse(cr, uid, self.user_pagan_id) + self.assertEquals(self.user_pagan.alias_name, 'plmarchant', "If login is an email, the alias should keep only the local part") - # 2. References header - reply_msg2 = MAIL_TEMPLATE.format(to='Pretty Pigs , other@gmail.com', subject='Re: Re: 1', - extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % msg1.message_id) - self.mail_group.message_process(cr, uid, None, reply_msg2) + self.user_barty_id = self.res_users.create(cr, uid, + {'name': 'Bartholomew Ironside', 'email': 'barty@gmail.com', 'login': 'b4r+_#_R3wl$$'}) + self.user_barty = self.res_users.browse(cr, uid, self.user_barty_id) + self.assertEquals(self.user_barty.alias_name, 'b4r+_-_r3wl-', 'Disallowed chars should be replaced by hyphens') - # 3. Subject contains [] + model passed to message+process -> only attached to group, not to mail - reply_msg3 = MAIL_TEMPLATE.format(to='Pretty Pigs , other@gmail.com', - extra='', subject='Re: [%s] 1' % self.group_pigs_id) - self.mail_group.message_process(cr, uid, 'mail.group', reply_msg3) - group_pigs.refresh() - msg1.refresh() - self.assertEqual(5, len(group_pigs.message_ids), 'group should contain 5 messages') - self.assertEqual(2, len(msg1.child_ids), 'msg1 should have 2 children now') - - def test_10_followers_function_field(self): + def test_00_followers_function_field(self): """ Tests designed for the many2many function field 'follower_ids'. We will test to perform writes using the many2many commands 0, 3, 4, 5 and 6. """ @@ -236,7 +101,7 @@ class test_mail(TestMailBase): follower_ids = set([follower.partner_id.id for follower in self.mail_followers.browse(cr, uid, fol_obj_ids)]) self.assertEqual(follower_ids, set([partner_bert_id, user_admin.partner_id.id]), 'Bert and Admin should be the followers of dummy mail.group data') - def test_11_message_followers_and_subtypes(self): + def test_05_message_followers_and_subtypes(self): """ Tests designed for the subscriber API as well as message subtypes """ cr, uid, user_admin, user_raoul, group_pigs = self.cr, self.uid, self.user_admin, self.user_raoul, self.group_pigs # Data: message subtypes @@ -288,7 +153,7 @@ class test_mail(TestMailBase): self.assertTrue(subtype_data['mt_mg_nodef']['followed'], 'Admin should follow mt_mg_nodef in pigs') self.assertTrue(subtype_data['mt_all_nodef']['followed'], 'Admin should follow mt_all_nodef in pigs') - def test_20_message_quote_context(self): + def test_10_message_quote_context(self): """ Tests designed for message_post. """ cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs @@ -306,239 +171,398 @@ class test_mail(TestMailBase): self.assertNotIn('First answer, should not be displayed', result, 'Old answer should not be in quote.') self.assertNotIn('My answer I am propagating', result, 'Thread header content should be in quote.') - def test_21_message_post(self): + def test_20_message_post(self): """ Tests designed for message_post. """ cr, uid, user_raoul, group_pigs = self.cr, self.uid, self.user_raoul, self.group_pigs - self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a'}) + + # -------------------------------------------------- + # Data creation + # -------------------------------------------------- + # 0 - Update existing users-partners + self.res_users.write(cr, uid, [uid], {'email': 'a@a'}) + self.res_users.write(cr, uid, [self.user_raoul_id], {'email': 'r@r'}) # 1 - Bert Tartopoils, with email, should receive emails for comments and emails p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'}) # 2 - Carine Poilvache, with email, should receive emails for emails p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notification_email_send': 'email'}) # 3 - Dédé Grosbedon, without email, to test email verification; should receive emails for every message - p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'notification_email_send': 'all'}) - - # Subscribe Raoul, #1, #2 - group_pigs.message_subscribe([self.partner_raoul_id, p_b_id, p_c_id]) - - # Mail data + p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'email': 'd@d', 'notification_email_send': 'all'}) + # 4 - Attachments + attach1_id = self.ir_attachment.create(cr, user_raoul.id, { + 'name': 'Attach1', 'datas_fname': 'Attach1', + 'datas': 'bWlncmF0aW9uIHRlc3Q=', + 'res_model': 'mail.compose.message', 'res_id': 0}) + attach2_id = self.ir_attachment.create(cr, user_raoul.id, { + 'name': 'Attach2', 'datas_fname': 'Attach2', + 'datas': 'bWlncmF0aW9uIHRlc3Q=', + 'res_model': 'mail.compose.message', 'res_id': 0}) + attach3_id = self.ir_attachment.create(cr, user_raoul.id, { + 'name': 'Attach3', 'datas_fname': 'Attach3', + 'datas': 'bWlncmF0aW9uIHRlc3Q=', + 'res_model': 'mail.compose.message', 'res_id': 0}) + # 5 - Mail data _subject = 'Pigs' _mail_subject = 'Re: %s' % (group_pigs.name) _body1 = '

Pigs rules

' - _mail_body1 = '

Pigs rules

' - _mail_signature1 = '

Raoul

' - _mail_bodyalt1 = 'Pigs rules\n' - _mail_signaturealt1 = '\nRaoul\n' - _body2 = 'Pigs rules' - _mail_body2 = '

Pigs rules

' - _mail_signature2 = '

Raoul

' - _mail_bodyalt2 = 'Pigs rules\n' - _mail_signaturealt2 = '\nRaoul\n' - _attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')] + _body2 = 'Pigs rocks' + _attachments = [ + ('List1', 'My first attachment'), + ('List2', 'My second attachment') + ] - # ---------------------------------------- - # CASE1: post comment, body and subject specified - # ---------------------------------------- + # -------------------------------------------------- + # CASE1: post comment + partners + attachments + # -------------------------------------------------- - # 1. Post a new comment on Pigs + # Data: set alias_domain to see emails with alias + self.registry('ir.config_parameter').set_param(self.cr, self.uid, 'mail.catchall.domain', 'schlouby.fr') + # Data: change Pigs name to test reply_to + self.mail_group.write(cr, uid, [self.group_pigs_id], {'name': '"Pigs" !ù $%-'}) + + # Do: subscribe Raoul + new_follower_ids = [self.partner_raoul_id] + group_pigs.message_subscribe(new_follower_ids) + # Test: group followers = Raoul + uid + group_fids = [follower.id for follower in group_pigs.message_follower_ids] + test_fids = new_follower_ids + [self.partner_admin_id] + self.assertEqual(set(test_fids), set(group_fids), + 'message_subscribe: incorrect followers after subscribe') + + # Do: Raoul message_post on Pigs self._init_mock_build_email() - msg1_id = self.mail_group.message_post(cr, user_raoul.id, self.group_pigs_id, body=_body1, subject=_subject, type='comment', subtype='mt_comment') - message1 = self.mail_message.browse(cr, uid, msg1_id) + msg1_id = self.mail_group.message_post(cr, user_raoul.id, self.group_pigs_id, + body=_body1, subject=_subject, partner_ids=[p_b_id, p_c_id], + attachment_ids=[attach1_id, attach2_id], attachments=_attachments, + type='comment', subtype='mt_comment') + msg = self.mail_message.browse(cr, uid, msg1_id) + msg_message_id = msg.message_id + msg_pids = [partner.id for partner in msg.notified_partner_ids] + msg_aids = [attach.id for attach in msg.attachment_ids] sent_emails = self._build_email_kwargs_list - # Test: mail.mail notifications have been deleted - self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg1_id)]), 'mail.mail notifications should have been auto-deleted!') - # Test: mail_message: subject is _subject, body is _body1 (no formatting done) - self.assertEqual(message1.subject, _subject, 'mail.message subject incorrect') - self.assertEqual(message1.body, _body1, 'mail.message body incorrect') - # Test: sent_email: email send by server: correct subject, body, body_alternative - self.assertEqual(len(sent_emails), 2, 'sent_email number of sent emails incorrect') - for sent_email in sent_emails: - self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect') - self.assertIn(_mail_body1, sent_email['body'], 'sent_email body incorrect') - self.assertIn(_mail_signature1, sent_email['body'], 'sent_email body incorrect (no signature)') - self.assertIn("OpenERP", sent_email['body'], 'sent_email body incorrect (no OpenERP company)') - # the html2plaintext uses etree or beautiful soup, so the result may be slighly different - # depending if you have installed beautiful soup. - self.assertIn(_mail_bodyalt1, sent_email['body_alternative'], 'sent_email body_alternative is incorrect') - self.assertIn(_mail_signaturealt1, sent_email['body_alternative'], 'sent_email body_alternative is incorrect (no signature)') - self.assertIn("OpenERP", sent_email['body_alternative'], 'sent_email body incorrect (no OpenERP company)') - # Test: mail_message: notified_partner_ids = group followers - message_pids = set([partner.id for partner in message1.notified_partner_ids]) + + # Test: mail_message: subject and body not modified + self.assertEqual(_subject, msg.subject, 'message_post: mail.message subject incorrect') + self.assertEqual(_body1, msg.body, 'message_post: mail.message body incorrect') + # Test: mail_message: notified_partner_ids = group followers + partner_ids - author test_pids = set([self.partner_admin_id, p_b_id, p_c_id]) - self.assertEqual(test_pids, message_pids, 'mail.message notified partners incorrect') + self.assertEqual(test_pids, set(msg_pids), 'message_post: mail.message notified partners incorrect') + # Test: mail_message: attachments (4, attachment_ids + attachments) + test_aids = set([attach1_id, attach2_id]) + msg_attach_names = set([attach.name for attach in msg.attachment_ids]) + test_attach_names = set(['Attach1', 'Attach2', 'List1', 'List2']) + self.assertEqual(len(msg_aids), 4, + 'message_post: mail.message wrong number of attachments') + self.assertEqual(msg_attach_names, test_attach_names, + 'message_post: mail.message attachments incorrectly added') + self.assertTrue(test_aids.issubset(set(msg_aids)), + 'message_post: mail.message attachments duplicated') + for attach in msg.attachment_ids: + self.assertEqual(attach.res_model, 'mail.group', + 'message_post: mail.message attachments were not linked to the document') + self.assertEqual(attach.res_id, group_pigs.id, + 'message_post: mail.message attachments were not linked to the document') + if 'List' in attach.name: + self.assertIn((attach.name, attach.datas.decode('base64')), _attachments, + 'message_post: mail.message attachment name / data incorrect') + dl_attach = self.mail_message.download_attachment(cr, user_raoul.id, id_message=msg.id, attachment_id=attach.id) + self.assertIn((dl_attach['filename'], dl_attach['base64'].decode('base64')), _attachments, + 'message_post: mail.message download_attachment is incorrect') + + # Test: followers: same as before (author was already subscribed) + group_pigs.refresh() + group_fids = [follower.id for follower in group_pigs.message_follower_ids] + test_fids = new_follower_ids + [self.partner_admin_id] + self.assertEqual(set(test_fids), set(group_fids), + 'message_post: wrong followers after posting') + + # Test: mail_mail: notifications have been deleted + self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg1_id)]), + 'message_post: mail.mail notifications should have been auto-deleted!') + + # Test: notifications emails: to a and b, c is email only, r is author + # test_emailto = ['Administrator ', 'Bert Tartopoils '] + test_emailto = ['"Followers of -Pigs-" ', '"Followers of -Pigs-" '] + self.assertEqual(len(sent_emails), 2, + 'message_post: notification emails wrong number of send emails') + self.assertEqual(set([m['email_to'][0] for m in sent_emails]), set(test_emailto), + 'message_post: notification emails wrong recipients (email_to)') + for sent_email in sent_emails: + self.assertEqual(sent_email['email_from'], 'Raoul Grosbedon ', + 'message_post: notification email wrong email_from: should use alias of sender') + self.assertEqual(len(sent_email['email_to']), 1, + 'message_post: notification email sent to more than one email address instead of a precise partner') + self.assertIn(sent_email['email_to'][0], test_emailto, + 'message_post: notification email email_to incorrect') + self.assertEqual(sent_email['reply_to'], '"Followers of -Pigs-" ', + 'message_post: notification email reply_to incorrect') + self.assertEqual(_subject, sent_email['subject'], + 'message_post: notification email subject incorrect') + self.assertIn(_body1, sent_email['body'], + 'message_post: notification email body incorrect') + self.assertIn(user_raoul.signature, sent_email['body'], + 'message_post: notification email body should contain the sender signature') + self.assertIn('Pigs rules', sent_email['body_alternative'], + 'message_post: notification email body alternative should contain the body') + self.assertNotIn('

', sent_email['body_alternative'], + 'message_post: notification email body alternative still contains html') + self.assertIn(user_raoul.signature, sent_email['body_alternative'], + 'message_post: notification email body alternative should contain the sender signature') + self.assertFalse(sent_email['references'], + 'message_post: references should be False when sending a message that is not a reply') + # Test: notification linked to this message = group followers = notified_partner_ids notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', msg1_id)]) notif_pids = set([notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)]) - self.assertEqual(notif_pids, test_pids, 'mail.message notification partners incorrect') - # Test: sent_email: email_to should contain b@b, not c@c (pref email), not a@a (writer) - for sent_email in sent_emails: - self.assertTrue(set(sent_email['email_to']).issubset(set(['a@a', 'b@b'])), 'sent_email email_to is incorrect') + self.assertEqual(notif_pids, test_pids, + 'message_post: mail.message created mail.notification incorrect') - # ---------------------------------------- - # CASE2: post an email with attachments, parent_id, partner_ids, parent notification - # ---------------------------------------- + # Data: Pigs name back to normal + self.mail_group.write(cr, uid, [self.group_pigs_id], {'name': 'Pigs'}) - # 1. Post a new email comment on Pigs + # -------------------------------------------------- + # CASE2: reply + parent_id + parent notification + # -------------------------------------------------- + + # Data: remove alias_domain to see emails with alias + param_ids = self.registry('ir.config_parameter').search(cr, uid, [('key', '=', 'mail.catchall.domain')]) + self.registry('ir.config_parameter').unlink(cr, uid, param_ids) + + # Do: Raoul message_post on Pigs self._init_mock_build_email() - msg2_id = self.mail_group.message_post(cr, user_raoul.id, self.group_pigs_id, body=_body2, type='email', subtype='mt_comment', - partner_ids=[p_d_id], parent_id=msg1_id, attachments=_attachments, - context={'mail_post_autofollow': True}) - message2 = self.mail_message.browse(cr, uid, msg2_id) + msg2_id = self.mail_group.message_post(cr, user_raoul.id, self.group_pigs_id, + body=_body2, type='email', subtype='mt_comment', + partner_ids=[p_d_id], parent_id=msg1_id, attachment_ids=[attach3_id], + context={'mail_post_autofollow': True}) + msg = self.mail_message.browse(cr, uid, msg2_id) + msg_pids = [partner.id for partner in msg.notified_partner_ids] + msg_aids = [attach.id for attach in msg.attachment_ids] sent_emails = self._build_email_kwargs_list - self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg2_id)]), 'mail.mail notifications should have been auto-deleted!') - # Test: mail_message: subject is False, body is _body2 (no formatting done), parent_id is msg_id - self.assertEqual(message2.subject, False, 'mail.message subject incorrect') - self.assertEqual(message2.body, html_sanitize(_body2), 'mail.message body incorrect') - self.assertEqual(message2.parent_id.id, msg1_id, 'mail.message parent_id incorrect') - # Test: sent_email: email send by server: correct automatic subject, body, body_alternative - self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect') - for sent_email in sent_emails: - self.assertEqual(sent_email['subject'], _mail_subject, 'sent_email subject incorrect') - self.assertIn(_mail_body2, sent_email['body'], 'sent_email body incorrect') - self.assertIn(_mail_signature2, sent_email['body'], 'sent_email body incorrect (no signature)') - self.assertIn("OpenERP", sent_email['body'], 'sent_email body incorrect (no OpenERP company)') - # body_alternative - self.assertIn(_mail_bodyalt2, sent_email['body_alternative'], 'sent_email body_alternative is incorrect') - self.assertIn(_mail_signaturealt2, sent_email['body_alternative'], 'sent_email body_alternative is incorrect (no signature)') - self.assertIn("OpenERP", sent_email['body'], 'sent_email body incorrect (no OpenERP company)') + + # Test: mail_message: subject is False, body, parent_id is msg_id + self.assertEqual(msg.subject, False, 'message_post: mail.message subject incorrect') + self.assertEqual(msg.body, html_sanitize(_body2), 'message_post: mail.message body incorrect') + self.assertEqual(msg.parent_id.id, msg1_id, 'message_post: mail.message parent_id incorrect') # Test: mail_message: notified_partner_ids = group followers - message_pids = set([partner.id for partner in message2.notified_partner_ids]) - test_pids = set([self.partner_admin_id, p_b_id, p_c_id, p_d_id]) - self.assertEqual(message_pids, test_pids, 'mail.message partners incorrect') - # Test: notifications linked to this message = group followers = notified_partner_ids + test_pids = [self.partner_admin_id, p_d_id] + self.assertEqual(set(test_pids), set(msg_pids), 'message_post: mail.message partners incorrect') + # Test: mail_message: notifications linked to this message = group followers = notified_partner_ids notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', msg2_id)]) - notif_pids = set([notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)]) - self.assertEqual(notif_pids, test_pids, 'mail.message notification partners incorrect') - # Test: sent_email: email_to should contain b@b, c@c, not a@a (writer) + notif_pids = [notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)] + self.assertEqual(set(test_pids), set(notif_pids), 'message_post: mail.message notification partners incorrect') + + # Test: mail_mail: notifications deleted + self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg2_id)]), 'mail.mail notifications should have been auto-deleted!') + + # Test: emails send by server (to a, b, c, d) + # test_emailto = [u'Administrator ', u'Bert Tartopoils ', u'Carine Poilvache ', u'D\xe9d\xe9 Grosbedon '] + test_emailto = [u'"Followers of Pigs" ', u'"Followers of Pigs" ', u'"Followers of Pigs" ', u'"Followers of Pigs" '] + # self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect') for sent_email in sent_emails: - self.assertTrue(set(sent_email['email_to']).issubset(set(['a@a', 'b@b', 'c@c'])), 'sent_email email_to incorrect') - # Test: attachments - for attach in message2.attachment_ids: - self.assertEqual(attach.res_model, 'mail.group', 'mail.message attachment res_model incorrect') - self.assertEqual(attach.res_id, self.group_pigs_id, 'mail.message attachment res_id incorrect') - self.assertIn((attach.name, attach.datas.decode('base64')), _attachments, - 'mail.message attachment name / data incorrect') - # Test: download attachments - for attach in message2.attachment_ids: - dl_attach = self.mail_message.download_attachment(cr, user_raoul.id, id_message=message2.id, attachment_id=attach.id) - self.assertIn((dl_attach['filename'], dl_attach['base64'].decode('base64')), _attachments, 'mail.message download_attachment is incorrect') + self.assertEqual(sent_email['email_from'], 'Raoul Grosbedon ', + 'message_post: notification email wrong email_from: should use email of sender when no alias domain set') + self.assertEqual(len(sent_email['email_to']), 1, + 'message_post: notification email sent to more than one email address instead of a precise partner') + self.assertIn(sent_email['email_to'][0], test_emailto, + 'message_post: notification email email_to incorrect') + self.assertEqual(sent_email['reply_to'], '"Followers of Pigs" ', + 'message_post: notification email reply_to incorrect: should name Followers of Pigs, and have raoul email') + self.assertEqual(_mail_subject, sent_email['subject'], + 'message_post: notification email subject incorrect') + self.assertIn(html_sanitize(_body2), sent_email['body'], + 'message_post: notification email does not contain the body') + self.assertIn(user_raoul.signature, sent_email['body'], + 'message_post: notification email body should contain the sender signature') + self.assertIn('Pigs rocks', sent_email['body_alternative'], + 'message_post: notification email body alternative should contain the body') + self.assertNotIn('

', sent_email['body_alternative'], + 'message_post: notification email body alternative still contains html') + self.assertIn(user_raoul.signature, sent_email['body_alternative'], + 'message_post: notification email body alternative should contain the sender signature') + self.assertIn(msg_message_id, sent_email['references'], + 'message_post: notification email references lacks parent message message_id') + # Test: attachments + download + for attach in msg.attachment_ids: + self.assertEqual(attach.res_model, 'mail.group', + 'message_post: mail.message attachment res_model incorrect') + self.assertEqual(attach.res_id, self.group_pigs_id, + 'message_post: mail.message attachment res_id incorrect') - # 2. Dédé has been notified -> should also have been notified of the parent message - message1.refresh() - message_pids = set([partner.id for partner in message1.notified_partner_ids]) + # Test: Dédé has been notified -> should also have been notified of the parent message + msg = self.mail_message.browse(cr, uid, msg1_id) + msg_pids = set([partner.id for partner in msg.notified_partner_ids]) test_pids = set([self.partner_admin_id, p_b_id, p_c_id, p_d_id]) - self.assertEqual(test_pids, message_pids, 'mail.message parent notification not created') + self.assertEqual(test_pids, msg_pids, 'message_post: mail.message parent notification not created') - # 3. Reply to the last message, check that its parent will be the first message + # Do: reply to last message msg3_id = self.mail_group.message_post(cr, user_raoul.id, self.group_pigs_id, body='Test', parent_id=msg2_id) - message = self.mail_message.browse(cr, uid, msg3_id) - self.assertEqual(message.parent_id.id, msg1_id, 'message_post did not flatten the thread structure') + msg = self.mail_message.browse(cr, uid, msg3_id) + # Test: check that its parent will be the first message + self.assertEqual(msg.parent_id.id, msg1_id, 'message_post did not flatten the thread structure') def test_25_message_compose_wizard(self): """ Tests designed for the mail.compose.message wizard. """ - cr, uid, user_admin, group_pigs = self.cr, self.uid, self.user_admin, self.group_pigs + cr, uid, user_raoul, group_pigs = self.cr, self.uid, self.user_raoul, self.group_pigs mail_compose = self.registry('mail.compose.message') - self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a'}) - group_bird_id = self.mail_group.create(cr, uid, {'name': 'Bird', 'description': 'Bird resistance'}, {'mail_create_nolog': True}) - group_bird = self.mail_group.browse(cr, uid, group_bird_id) - # Mail data + # -------------------------------------------------- + # Data creation + # -------------------------------------------------- + # 0 - Update existing users-partners + self.res_users.write(cr, uid, [uid], {'email': 'a@a'}) + self.res_users.write(cr, uid, [self.user_raoul_id], {'email': 'r@r'}) + # 1 - Bert Tartopoils, with email, should receive emails for comments and emails + p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'}) + # 2 - Carine Poilvache, with email, should receive emails for emails + p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notification_email_send': 'email'}) + # 3 - Dédé Grosbedon, without email, to test email verification; should receive emails for every message + p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'email': 'd@d', 'notification_email_send': 'all'}) + # 4 - Create a Bird mail.group, that will be used to test mass mailing + group_bird_id = self.mail_group.create(cr, uid, + { + 'name': 'Bird', + 'description': 'Bird resistance', + }, context={'mail_create_nolog': True}) + group_bird = self.mail_group.browse(cr, uid, group_bird_id) + # 5 - Mail data _subject = 'Pigs' _body = 'Pigs rule' - _reply_subject = 'Re: Pigs' + _reply_subject = 'Re: %s' % _subject _attachments = [ {'name': 'First', 'datas_fname': 'first.txt', 'datas': 'My first attachment'.encode('base64')}, {'name': 'Second', 'datas_fname': 'second.txt', 'datas': 'My second attachment'.encode('base64')} ] _attachments_test = [('first.txt', 'My first attachment'), ('second.txt', 'My second attachment')] - - # 1 - Bert Tartopoils, with email, should receive emails for comments and emails - p_b_id = self.res_partner.create(cr, uid, {'name': 'Bert Tartopoils', 'email': 'b@b'}) - # 2 - Carine Poilvache, with email, should never receive emails - p_c_id = self.res_partner.create(cr, uid, {'name': 'Carine Poilvache', 'email': 'c@c', 'notification_email_send': 'email'}) - # 3 - Dédé Grosbedon, without email, to test email verification; should receive emails for every message - p_d_id = self.res_partner.create(cr, uid, {'name': 'Dédé Grosbedon', 'email': 'd@d', 'notification_email_send': 'all'}) - - # Subscribe #1 + # 6 - Subscribe Bert to Pigs group_pigs.message_subscribe([p_b_id]) - # ---------------------------------------- - # CASE1: comment on group_pigs - # ---------------------------------------- + # -------------------------------------------------- + # CASE1: wizard + partners + context keys + # -------------------------------------------------- - # 1. Comment group_pigs with body_text and subject - compose_id = mail_compose.create(cr, uid, - {'subject': _subject, 'body': _body, 'partner_ids': [(4, p_c_id), (4, p_d_id)]}, - {'default_composition_mode': 'comment', 'default_model': 'mail.group', 'default_res_id': self.group_pigs_id, - 'default_content_subtype': 'plaintext'}) + # Do: Raoul wizard-composes on Pigs with auto-follow for partners, not for author + compose_id = mail_compose.create(cr, user_raoul.id, + { + 'subject': _subject, + 'body': _body, + 'partner_ids': [(4, p_c_id), (4, p_d_id)], + }, context={ + 'default_composition_mode': 'comment', + 'default_model': 'mail.group', + 'default_res_id': self.group_pigs_id, + }) compose = mail_compose.browse(cr, uid, compose_id) - # Test: mail.compose.message: composition_mode, model, res_id - self.assertEqual(compose.composition_mode, 'comment', 'mail.compose.message incorrect composition_mode') - self.assertEqual(compose.model, 'mail.group', 'mail.compose.message incorrect model') - self.assertEqual(compose.res_id, self.group_pigs_id, 'mail.compose.message incorrect res_id') - # 2. Post the comment, get created message - mail_compose.send_mail(cr, uid, [compose_id], {'mail_post_autofollow': True}) + # Test: mail.compose.message: composition_mode, model, res_id + self.assertEqual(compose.composition_mode, 'comment', 'compose wizard: mail.compose.message incorrect composition_mode') + self.assertEqual(compose.model, 'mail.group', 'compose wizard: mail.compose.message incorrect model') + self.assertEqual(compose.res_id, self.group_pigs_id, 'compose wizard: mail.compose.message incorrect res_id') + + # Do: Post the comment + mail_compose.send_mail(cr, user_raoul.id, [compose_id], {'mail_post_autofollow': True, 'mail_create_nosubscribe': True}) group_pigs.refresh() message = group_pigs.message_ids[0] - # Test: mail.message: subject, body inside pre - self.assertEqual(message.subject, _subject, 'mail.message incorrect subject') - self.assertEqual(message.body, '

%s

' % _body, 'mail.message incorrect body') - # Test: mail.message: notified_partner_ids = entries in mail.notification: group_pigs fans (a, b) + mail.compose.message partner_ids (c, d) + + # Test: mail.group: followers (c and d added by auto follow key; raoul not added by nosubscribe key) + pigs_pids = [p.id for p in group_pigs.message_follower_ids] + test_pids = [self.partner_admin_id, p_b_id, p_c_id, p_d_id] + self.assertEqual(set(pigs_pids), set(test_pids), + 'compose wizard: mail_post_autofollow and mail_create_nosubscribe context keys not correctly taken into account') + + # Test: mail.message: subject, body inside p + self.assertEqual(message.subject, _subject, 'compose wizard: mail.message incorrect subject') + self.assertEqual(message.body, '

%s

' % _body, 'compose wizard: mail.message incorrect body') + # Test: mail.message: notified_partner_ids = admin + bert (followers) + c + d (recipients) msg_pids = [partner.id for partner in message.notified_partner_ids] - test_pids = [p_b_id, p_c_id, p_d_id] - notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', message.id)]) - self.assertEqual(len(notif_ids), 3, 'mail.message: too much notifications created') - self.assertEqual(set(msg_pids), set(test_pids), 'mail.message notified_partner_ids incorrect') + test_pids = [self.partner_admin_id, p_b_id, p_c_id, p_d_id] + self.assertEqual(set(msg_pids), set(test_pids), + 'compose wizard: mail.message notified_partner_ids incorrect') - # ---------------------------------------- - # CASE2: reply to last comment with attachments - # ---------------------------------------- + # -------------------------------------------------- + # CASE2: reply + attachments + # -------------------------------------------------- - # 1. Update last comment subject, reply with attachments - message.write({'subject': _subject}) - compose_id = mail_compose.create(cr, uid, - {'attachment_ids': [(0, 0, _attachments[0]), (0, 0, _attachments[1])]}, - {'default_composition_mode': 'reply', 'default_model': 'mail.thread', 'default_res_id': self.group_pigs_id, 'default_parent_id': message.id}) + # Do: Reply with attachments + compose_id = mail_compose.create(cr, user_raoul.id, + { + 'attachment_ids': [(0, 0, _attachments[0]), (0, 0, _attachments[1])] + }, context={ + 'default_composition_mode': 'reply', + 'default_model': 'mail.thread', + 'default_res_id': self.group_pigs_id, + 'default_parent_id': message.id + }) compose = mail_compose.browse(cr, uid, compose_id) - # Test: model, res_id, parent_id - self.assertEqual(compose.model, 'mail.group', 'mail.compose.message incorrect model') - self.assertEqual(compose.res_id, self.group_pigs_id, 'mail.compose.message incorrect res_id') - self.assertEqual(compose.parent_id.id, message.id, 'mail.compose.message incorrect parent_id') - # Test: mail.message: subject as Re:.., body in html, parent_id - self.assertEqual(compose.subject, _reply_subject, 'mail.message incorrect subject') - # self.assertIn('Administrator wrote:
Pigs rules
', compose.body, 'mail.message body is incorrect') - self.assertEqual(compose.parent_id and compose.parent_id.id, message.id, 'mail.message parent_id incorrect') - # Test: mail.message: attachments + + # Test: mail.compose.message: model, res_id, parent_id + self.assertEqual(compose.model, 'mail.group', 'compose wizard: mail.compose.message incorrect model') + self.assertEqual(compose.res_id, self.group_pigs_id, 'compose wizard: mail.compose.message incorrect res_id') + self.assertEqual(compose.parent_id.id, message.id, 'compose wizard: mail.compose.message incorrect parent_id') + + # Test: mail.compose.message: subject as Re:.., body, parent_id + self.assertEqual(compose.subject, _reply_subject, 'compose wizard: mail.compose.message incorrect subject') + self.assertFalse(compose.body, 'compose wizard: mail.compose.message body should not contain parent message body') + self.assertEqual(compose.parent_id and compose.parent_id.id, message.id, 'compose wizard: mail.compose.message parent_id incorrect') + # Test: mail.compose.message: attachments for attach in compose.attachment_ids: - self.assertIn((attach.datas_fname, attach.datas.decode('base64')), _attachments_test, 'mail.message attachment name / data incorrect') + self.assertIn((attach.datas_fname, attach.datas.decode('base64')), _attachments_test, + 'compose wizard: mail.message attachment name / data incorrect') - # ---------------------------------------- + # -------------------------------------------------- # CASE3: mass_mail on Pigs and Bird - # ---------------------------------------- + # -------------------------------------------------- - # 1. mass_mail on pigs and bird - compose_id = mail_compose.create(cr, uid, - {'subject': _subject, 'body': '${object.description}'}, - {'default_composition_mode': 'mass_mail', 'default_model': 'mail.group', 'default_res_id': False, 'default_notify': True, - 'active_ids': [self.group_pigs_id, group_bird_id]}) + # Do: Compose in mass_mail_mode on pigs and bird + compose_id = mail_compose.create(cr, user_raoul.id, + { + 'subject': _subject, + 'body': '${object.description}', + 'partner_ids': [(4, p_c_id), (4, p_d_id)], + }, context={ + 'default_composition_mode': 'mass_mail', + 'default_model': 'mail.group', + 'default_res_id': False, + 'active_ids': [self.group_pigs_id, group_bird_id], + }) compose = mail_compose.browse(cr, uid, compose_id) - # 2. Post the comment, get created message for each group - mail_compose.send_mail(cr, uid, [compose_id], - context={'default_res_id': -1, 'active_ids': [self.group_pigs_id, group_bird_id]}) + # D: Post the comment, get created message for each group + mail_compose.send_mail(cr, user_raoul.id, [compose_id], context={ + 'default_res_id': -1, + 'active_ids': [self.group_pigs_id, group_bird_id] + }) group_pigs.refresh() group_bird.refresh() message1 = group_pigs.message_ids[0] message2 = group_bird.message_ids[0] + # Test: Pigs and Bird did receive their message test_msg_ids = self.mail_message.search(cr, uid, [], limit=2) - self.assertIn(message1.id, test_msg_ids, 'Pigs did not receive its mass mailing message') - self.assertIn(message2.id, test_msg_ids, 'Bird did not receive its mass mailing message') - # Test: mail.message: subject, body - self.assertEqual(message1.subject, _subject, 'mail.message subject incorrect') - self.assertEqual(message1.body, '

%s

' % group_pigs.description, 'mail.message body incorrect') - self.assertEqual(message2.subject, _subject, 'mail.message subject incorrect') - self.assertEqual(message2.body, '

%s

' % group_bird.description, 'mail.message body incorrect') + self.assertIn(message1.id, test_msg_ids, 'compose wizard: Pigs did not receive its mass mailing message') + self.assertIn(message2.id, test_msg_ids, 'compose wizard: Bird did not receive its mass mailing message') + + # Test: mail.message: subject, body, subtype, notified partners (nobody + specific recipients) + self.assertEqual(message1.subject, _subject, + 'compose wizard: message_post: mail.message in mass mail subject incorrect') + self.assertEqual(message1.body, '

%s

' % group_pigs.description, + 'compose wizard: message_post: mail.message in mass mail body incorrect') + self.assertEqual(set([p.id for p in message1.notified_partner_ids]), set([p_c_id, p_d_id]), + 'compose wizard: message_post: mail.message in mass mail incorrect notified partners') + self.assertEqual(message2.subject, _subject, + 'compose wizard: message_post: mail.message in mass mail subject incorrect') + self.assertEqual(message2.body, '

%s

' % group_bird.description, + 'compose wizard: message_post: mail.message in mass mail body incorrect') + self.assertEqual(set([p.id for p in message2.notified_partner_ids]), set([p_c_id, p_d_id]), + 'compose wizard: message_post: mail.message in mass mail incorrect notified partners') + + # Test: mail.group followers: author not added as follower in mass mail mode + pigs_pids = [p.id for p in group_pigs.message_follower_ids] + test_pids = [self.partner_admin_id, p_b_id, p_c_id, p_d_id] + self.assertEqual(set(pigs_pids), set(test_pids), + 'compose wizard: mail_post_autofollow and mail_create_nosubscribe context keys not correctly taken into account') + bird_pids = [p.id for p in group_bird.message_follower_ids] + test_pids = [self.partner_admin_id] + self.assertEqual(set(bird_pids), set(test_pids), + 'compose wizard: mail_post_autofollow and mail_create_nosubscribe context keys not correctly taken into account') def test_30_needaction(self): """ Tests for mail.message needaction. """ diff --git a/addons/mail/tests/test_mail_gateway.py b/addons/mail/tests/test_mail_gateway.py new file mode 100644 index 00000000000..e4269d59d8b --- /dev/null +++ b/addons/mail/tests/test_mail_gateway.py @@ -0,0 +1,466 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# 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 +# 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.mail.tests.test_mail_base import TestMailBase + +MAIL_TEMPLATE = """Return-Path: +To: {to} +Received: by mail1.openerp.com (Postfix, from userid 10002) + id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST) +From: {email_from} +Subject: {subject} +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="----=_Part_4200734_24778174.1344608186754" +Date: Fri, 10 Aug 2012 14:16:26 +0000 +Message-ID: {msg_id} +{extra} +------=_Part_4200734_24778174.1344608186754 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +Please call me as soon as possible this afternoon! + +-- +Sylvie +------=_Part_4200734_24778174.1344608186754 +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + + + + =20 + + =20 + =20 + +

Please call me as soon as possible this afternoon!

+ +

--
+ Sylvie +

+ + +------=_Part_4200734_24778174.1344608186754-- +""" + +MAIL_TEMPLATE_PLAINTEXT = """Return-Path: +To: {to} +Received: by mail1.openerp.com (Postfix, from userid 10002) + id 5DF9ABFB2A; Fri, 10 Aug 2012 16:16:39 +0200 (CEST) +From: Sylvie Lelitre +Subject: {subject} +MIME-Version: 1.0 +Content-Type: text/plain +Date: Fri, 10 Aug 2012 14:16:26 +0000 +Message-ID: {msg_id} +{extra} + +Please call me as soon as possible this afternoon! + +-- +Sylvie +""" + + +class TestMailgateway(TestMailBase): + + def test_00_partner_find_from_email(self): + """ Tests designed for partner fetch based on emails. """ + cr, uid, user_raoul, group_pigs = self.cr, self.uid, self.user_raoul, self.group_pigs + + # -------------------------------------------------- + # Data creation + # -------------------------------------------------- + # 1 - Partner ARaoul + p_a_id = self.res_partner.create(cr, uid, {'name': 'ARaoul', 'email': 'test@test.fr'}) + + # -------------------------------------------------- + # CASE1: without object + # -------------------------------------------------- + + # Do: find partner with email -> first partner should be found + partner_info = self.mail_thread.message_find_partner_from_emails(cr, uid, None, ['Maybe Raoul '], link_mail=False)[0] + self.assertEqual(partner_info['full_name'], 'Maybe Raoul ', + 'mail_thread: message_find_partner_from_emails did not handle email') + self.assertEqual(partner_info['partner_id'], p_a_id, + 'mail_thread: message_find_partner_from_emails wrong partner found') + + # Data: add some data about partners + # 2 - User BRaoul + p_b_id = self.res_partner.create(cr, uid, {'name': 'BRaoul', 'email': 'test@test.fr', 'user_ids': [(4, user_raoul.id)]}) + + # Do: find partner with email -> first user should be found + partner_info = self.mail_thread.message_find_partner_from_emails(cr, uid, None, ['Maybe Raoul '], link_mail=False)[0] + self.assertEqual(partner_info['partner_id'], p_b_id, + 'mail_thread: message_find_partner_from_emails wrong partner found') + + # -------------------------------------------------- + # CASE1: with object + # -------------------------------------------------- + + # Do: find partner in group where there is a follower with the email -> should be taken + self.mail_group.message_subscribe(cr, uid, [group_pigs.id], [p_b_id]) + partner_info = self.mail_group.message_find_partner_from_emails(cr, uid, group_pigs.id, ['Maybe Raoul '], link_mail=False)[0] + self.assertEqual(partner_info['partner_id'], p_b_id, + 'mail_thread: message_find_partner_from_emails wrong partner found') + + def test_10_message_process(self): + """ Testing incoming emails processing. """ + cr, uid, user_raoul = self.cr, self.uid, self.user_raoul + + def format_and_process(template, to='groups@example.com, other@gmail.com', subject='Frogs', + extra='', email_from='Sylvie Lelitre ', + msg_id='<1198923581.41972151344608186760.JavaMail@agrolait.com>', + model=None): + self.assertEqual(self.mail_group.search(cr, uid, [('name', '=', subject)]), []) + mail = template.format(to=to, subject=subject, extra=extra, email_from=email_from, msg_id=msg_id) + self.mail_thread.message_process(cr, uid, model, mail) + return self.mail_group.search(cr, uid, [('name', '=', subject)]) + + # -------------------------------------------------- + # Data creation + # -------------------------------------------------- + + # groups@.. will cause the creation of new mail groups + self.mail_group_model_id = self.ir_model.search(cr, uid, [('model', '=', 'mail.group')])[0] + alias_id = self.mail_alias.create(cr, uid, { + 'alias_name': 'groups', + 'alias_user_id': False, + 'alias_model_id': self.mail_group_model_id}) + + # -------------------------------------------------- + # Test1: new record creation + # -------------------------------------------------- + + # Do: incoming mail from an unknown partner on an alias creates a new mail_group "frogs" + self._init_mock_build_email() + frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com') + sent_emails = self._build_email_kwargs_list + # Test: one group created by mailgateway administrator + self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created') + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + res = self.mail_group.perm_read(cr, uid, [frog_group.id], details=False) + self.assertEqual(res[0].get('create_uid'), uid, + 'message_process: group should have been created by uid as alias_user__id is False on the alias') + # Test: one message that is the incoming email + self.assertEqual(len(frog_group.message_ids), 1, + 'message_process: newly created group should have the incoming email in message_ids') + msg = frog_group.message_ids[0] + self.assertEqual('Frogs', msg.subject, + 'message_process: newly created group should have the incoming email as first message') + self.assertIn('Please call me as soon as possible this afternoon!', msg.body, + 'message_process: newly created group should have the incoming email as first message') + self.assertEqual('email', msg.type, + 'message_process: newly created group should have an email as first message') + self.assertEqual('Discussions', msg.subtype_id.name, + 'message_process: newly created group should not have a log first message but an email') + # Test: message: unknown email address -> message has email_from, not author_id + self.assertFalse(msg.author_id, + 'message_process: message on created group should not have an author_id') + self.assertIn('test.sylvie.lelitre@agrolait.com', msg.email_from, + 'message_process: message on created group should have an email_from') + # Test: followers: nobody + self.assertEqual(len(frog_group.message_follower_ids), 0, 'message_process: newly create group should not have any follower') + # Test: sent emails: no-one + self.assertEqual(len(sent_emails), 0, + 'message_process: should create emails without any follower added') + # Data: unlink group + frog_group.unlink() + + # Do: incoming email from a known partner on an alias with known recipients, alias is owned by user that can create a group + self.mail_alias.write(cr, uid, [alias_id], {'alias_user_id': self.user_raoul_id}) + p1id = self.res_partner.create(cr, uid, {'name': 'Sylvie Lelitre', 'email': 'test.sylvie.lelitre@agrolait.com'}) + p2id = self.res_partner.create(cr, uid, {'name': 'Other Poilvache', 'email': 'other@gmail.com'}) + self._init_mock_build_email() + frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com') + sent_emails = self._build_email_kwargs_list + # Test: one group created by Raoul + self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created') + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + res = self.mail_group.perm_read(cr, uid, [frog_group.id], details=False) + self.assertEqual(res[0].get('create_uid'), self.user_raoul_id, + 'message_process: group should have been created by alias_user_id') + # Test: one message that is the incoming email + self.assertEqual(len(frog_group.message_ids), 1, + 'message_process: newly created group should have the incoming email in message_ids') + msg = frog_group.message_ids[0] + # Test: message: unknown email address -> message has email_from, not author_id + self.assertEqual(p1id, msg.author_id.id, + 'message_process: message on created group should have Sylvie as author_id') + self.assertIn('Sylvie Lelitre ', msg.email_from, + 'message_process: message on created group should have have an email_from') + # Test: author (not recipient and not raoul (as alias owner)) added as follower + frog_follower_ids = set([p.id for p in frog_group.message_follower_ids]) + self.assertEqual(frog_follower_ids, set([p1id]), + 'message_process: newly created group should have 1 follower (author, not creator, not recipients)') + # Test: sent emails: no-one, no bounce effet + self.assertEqual(len(sent_emails), 0, + 'message_process: should not bounce incoming emails') + # Data: unlink group + frog_group.unlink() + + # Do: incoming email from a known partner that is also an user that can create a mail.group + self.res_users.create(cr, uid, {'partner_id': p1id, 'login': 'sylvie', 'groups_id': [(6, 0, [self.group_employee_id])]}) + frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com') + # Test: one group created by Raoul (or Sylvie maybe, if we implement it) + self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created') + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + # Test: one message that is the incoming email + self.assertEqual(len(frog_group.message_ids), 1, + 'message_process: newly created group should have the incoming email in message_ids') + # Test: author (and not recipient) added as follower + frog_follower_ids = set([p.id for p in frog_group.message_follower_ids]) + self.assertEqual(frog_follower_ids, set([p1id]), + 'message_process: newly created group should have 1 follower (author, not creator, not recipients)') + # Test: sent emails: no-one, no bounce effet + self.assertEqual(len(sent_emails), 0, + 'message_process: should not bounce incoming emails') + + # -------------------------------------------------- + # Test2: discussion update + # -------------------------------------------------- + + # Do: even with a wrong destination, a reply should end up in the correct thread + frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other@gmail.com', + msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>', + to='erroneous@example.com>', subject='Re: news', + extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) + # Test: no group 'Re: news' created, still only 1 Frogs group + self.assertEqual(len(frog_groups), 0, + 'message_process: reply on Frogs should not have created a new group with new subject') + frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) + self.assertEqual(len(frog_groups), 1, + 'message_process: reply on Frogs should not have created a duplicate group with old subject') + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + # Test: one new message + self.assertEqual(len(frog_group.message_ids), 2, 'message_process: group should contain 2 messages after reply') + # Test: author (and not recipient) added as follower + frog_follower_ids = set([p.id for p in frog_group.message_follower_ids]) + self.assertEqual(frog_follower_ids, set([p1id, p2id]), + 'message_process: after reply, group should have 2 followers') + + # Do: due to some issue, same email goes back into the mailgateway + frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other@gmail.com', + msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>', + subject='Re: news', extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) + # Test: no group 'Re: news' created, still only 1 Frogs group + self.assertEqual(len(frog_groups), 0, + 'message_process: reply on Frogs should not have created a new group with new subject') + frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) + self.assertEqual(len(frog_groups), 1, + 'message_process: reply on Frogs should not have created a duplicate group with old subject') + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + # Test: no new message + self.assertEqual(len(frog_group.message_ids), 2, 'message_process: message with already existing message_id should not have been duplicated') + # Test: message_id is still unique + msg_ids = self.mail_message.search(cr, uid, [('message_id', 'ilike', '<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>')]) + self.assertEqual(len(msg_ids), 1, + 'message_process: message with already existing message_id should not have been duplicated') + + # -------------------------------------------------- + # Test3: email_from and partner finding + # -------------------------------------------------- + + # Data: extra partner with Raoul's email -> test the 'better author finding' + extra_partner_id = self.res_partner.create(cr, uid, {'name': 'A-Raoul', 'email': 'test_raoul@email.com'}) + # extra_user_id = self.res_users.create(cr, uid, {'name': 'B-Raoul', 'email': self.user_raoul.email}) + # extra_user_pid = self.res_users.browse(cr, uid, extra_user_id).partner_id.id + + # Do: post a new message, with a known partner -> duplicate emails -> partner + format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik ', + to='erroneous@example.com>', subject='Re: news (2)', + msg_id='<1198923581.41972151344608186760.JavaMail.new1@agrolait.com>', + extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) + frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + # Test: author is A-Raoul (only existing) + self.assertEqual(frog_group.message_ids[0].author_id.id, extra_partner_id, + 'message_process: email_from -> author_id wrong') + + # Do: post a new message, with a known partner -> duplicate emails -> user + frog_group.message_unsubscribe([extra_partner_id]) + raoul_email = self.user_raoul.email + self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'}) + format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik ', + to='erroneous@example.com>', subject='Re: news (3)', + msg_id='<1198923581.41972151344608186760.JavaMail.new2@agrolait.com>', + extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) + frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + # Test: author is Raoul (user), not A-Raoul + self.assertEqual(frog_group.message_ids[0].author_id.id, self.partner_raoul_id, + 'message_process: email_from -> author_id wrong') + + # Do: post a new message, with a known partner -> duplicate emails -> partner because is follower + frog_group.message_unsubscribe([self.partner_raoul_id]) + frog_group.message_subscribe([extra_partner_id]) + raoul_email = self.user_raoul.email + self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'}) + format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik ', + to='erroneous@example.com>', subject='Re: news (3)', + msg_id='<1198923581.41972151344608186760.JavaMail.new3@agrolait.com>', + extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) + frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + # Test: author is Raoul (user), not A-Raoul + self.assertEqual(frog_group.message_ids[0].author_id.id, extra_partner_id, + 'message_process: email_from -> author_id wrong') + + self.res_users.write(cr, uid, self.user_raoul_id, {'email': raoul_email}) + + # -------------------------------------------------- + # Test4: misc gateway features + # -------------------------------------------------- + + # Do: incoming email with model that does not accepts incoming emails must raise + self.assertRaises(AssertionError, + format_and_process, + MAIL_TEMPLATE, + to='noone@example.com', subject='spam', extra='', model='res.country', + msg_id='<1198923581.41972151344608186760.JavaMail.new4@agrolait.com>') + + # Do: incoming email without model and without alias must raise + self.assertRaises(AssertionError, + format_and_process, + MAIL_TEMPLATE, + to='noone@example.com', subject='spam', extra='', + msg_id='<1198923581.41972151344608186760.JavaMail.new5@agrolait.com>') + + # Do: incoming email with model that accepting incoming emails as fallback + frog_groups = format_and_process(MAIL_TEMPLATE, + to='noone@example.com', + subject='Spammy', extra='', model='mail.group', + msg_id='<1198923581.41972151344608186760.JavaMail.new6@agrolait.com>') + self.assertEqual(len(frog_groups), 1, + 'message_process: erroneous email but with a fallback model should have created a new mail.group') + + # Do: incoming email in plaintext should be stored as html + frog_groups = format_and_process(MAIL_TEMPLATE_PLAINTEXT, + to='groups@example.com', subject='Frogs Return', extra='', + msg_id='') + # Test: one group created with one message + self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created') + frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) + msg = frog_group.message_ids[0] + # Test: plain text content should be wrapped and stored as html + self.assertEqual(msg.body, '

\nPlease call me as soon as possible this afternoon!\n\n--\nSylvie\n
', + 'message_process: plaintext incoming email incorrectly parsed') + + def test_20_thread_parent_resolution(self): + """ Testing parent/child relationships are correctly established when processing incoming mails """ + cr, uid = self.cr, self.uid + + def format(template, to='Pretty Pigs , other@gmail.com', subject='Re: 1', + extra='', email_from='Sylvie Lelitre ', + msg_id='<1198923581.41972151344608186760.JavaMail@agrolait.com>'): + return template.format(to=to, subject=subject, extra=extra, email_from=email_from, msg_id=msg_id) + + group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) + msg1 = group_pigs.message_post(body='My Body', subject='1') + msg2 = group_pigs.message_post(body='My Body', subject='2') + msg1, msg2 = self.mail_message.browse(cr, uid, [msg1, msg2]) + self.assertTrue(msg1.message_id, "message_process: new message should have a proper message_id") + + # Reply to msg1, make sure the reply is properly attached using the various reply identification mechanisms + # 0. Direct alias match + reply_msg1 = format(MAIL_TEMPLATE, to='Pretty Pigs ', + extra='In-Reply-To: %s' % msg1.message_id, + msg_id='<1198923581.41972151344608186760.JavaMail.2@agrolait.com>') + self.mail_group.message_process(cr, uid, None, reply_msg1) + + # 1. In-Reply-To header + reply_msg2 = format(MAIL_TEMPLATE, to='erroneous@example.com', + extra='In-Reply-To: %s' % msg1.message_id, + msg_id='<1198923581.41972151344608186760.JavaMail.3@agrolait.com>') + self.mail_group.message_process(cr, uid, None, reply_msg2) + + # 2. References header + reply_msg3 = format(MAIL_TEMPLATE, to='erroneous@example.com', + extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % msg1.message_id, + msg_id='<1198923581.41972151344608186760.JavaMail.4@agrolait.com>') + self.mail_group.message_process(cr, uid, None, reply_msg3) + + # 3. Subject contains [] + model passed to message+process -> only attached to group, but not to mail (not in msg1.child_ids) + reply_msg4 = format(MAIL_TEMPLATE, to='erroneous@example.com', + extra='', subject='Re: [%s] 1' % self.group_pigs_id, + msg_id='<1198923581.41972151344608186760.JavaMail.5@agrolait.com>') + self.mail_group.message_process(cr, uid, 'mail.group', reply_msg4) + + group_pigs.refresh() + msg1.refresh() + self.assertEqual(6, len(group_pigs.message_ids), 'message_process: group should contain 6 messages') + self.assertEqual(3, len(msg1.child_ids), 'message_process: msg1 should have 3 children now') + + def test_30_private_discussion(self): + """ Testing private discussion between partners. """ + cr, uid = self.cr, self.uid + + # Do: Raoul writes to Bert and Administrator, with a thread_model in context that should not be taken into account + msg1_pids = [self.partner_admin_id, self.partner_bert_id] + msg1_id = self.mail_thread.message_post(cr, self.user_raoul_id, False, + partner_ids=msg1_pids, + subtype='mail.mt_comment', + context={'thread_model': 'mail.group'}) + + # Test: message recipients + msg = self.mail_message.browse(cr, uid, msg1_id) + msg_pids = [p.id for p in msg.partner_ids] + msg_nids = [p.id for p in msg.notified_partner_ids] + test_pids = msg1_pids + test_nids = msg1_pids + self.assertEqual(set(msg_pids), set(test_pids), + 'message_post: private discussion: incorrect recipients') + self.assertEqual(set(msg_nids), set(test_nids), + 'message_post: private discussion: incorrect notified recipients') + self.assertEqual(msg.model, False, + 'message_post: private discussion: context key "thread_model" not correctly ignored when having no res_id') + + # Do: Bert replies through mailgateway (is a customer) + msg2_id = self.mail_thread.message_post(cr, uid, False, + author_id=self.partner_bert_id, + parent_id=msg1_id, subtype='mail.mt_comment') + + # Test: message recipients + msg = self.mail_message.browse(cr, uid, msg2_id) + msg_pids = [p.id for p in msg.partner_ids] + msg_nids = [p.id for p in msg.notified_partner_ids] + test_pids = [self.partner_admin_id, self.partner_raoul_id] + test_nids = test_pids + self.assertEqual(set(msg_pids), set(test_pids), + 'message_post: private discussion: incorrect recipients when replying') + self.assertEqual(set(msg_nids), set(test_nids), + 'message_post: private discussion: incorrect notified recipients when replying') + + # Do: Administrator replies + msg3_id = self.mail_thread.message_post(cr, uid, False, + parent_id=msg2_id, subtype='mail.mt_comment') + + # Test: message recipients + msg = self.mail_message.browse(cr, uid, msg3_id) + msg_pids = [p.id for p in msg.partner_ids] + msg_nids = [p.id for p in msg.notified_partner_ids] + test_pids = [self.partner_bert_id, self.partner_raoul_id] + test_nids = test_pids + self.assertEqual(set(msg_pids), set(test_pids), + 'message_post: private discussion: incorrect recipients when replying') + self.assertEqual(set(msg_nids), set(test_nids), + 'message_post: private discussion: incorrect notified recipients when replying') diff --git a/addons/mail/update.py b/addons/mail/update.py index bcec6f5f8b6..94416aeb356 100644 --- a/addons/mail/update.py +++ b/addons/mail/update.py @@ -5,7 +5,7 @@ import sys import urllib import urllib2 -from openerp import pooler +import openerp from openerp import release from openerp.osv import fields, osv from openerp.tools.translate import _ @@ -26,7 +26,7 @@ def get_sys_logs(self, cr, uid): """ Utility method to send a publisher warranty get logs messages. """ - pool = pooler.get_pool(cr.dbname) + pool = openerp.registry(cr.dbname) dbuuid = pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') db_create_date = pool.get('ir.config_parameter').get_param(cr, uid, 'database.create_date') diff --git a/addons/mail/wizard/invite.py b/addons/mail/wizard/invite.py index 2eb48f3d998..4ff6584d789 100644 --- a/addons/mail/wizard/invite.py +++ b/addons/mail/wizard/invite.py @@ -37,10 +37,10 @@ class invite_wizard(osv.osv_memory): res_id = result.get('res_id') if 'message' in fields and model and res_id: ir_model = self.pool.get('ir.model') - model_ids = ir_model.search(cr, uid, [('model', '=', self.pool.get(model)._name)], context=context) + model_ids = ir_model.search(cr, uid, [('model', '=', self.pool[model]._name)], context=context) model_name = ir_model.name_get(cr, uid, model_ids, context=context)[0][1] - document_name = self.pool.get(model).name_get(cr, uid, [res_id], context=context)[0][1] + document_name = self.pool[model].name_get(cr, uid, [res_id], context=context)[0][1] message = _('

Hello,

%s invited you to follow %s document: %s.

') % (user_name, model_name, document_name) result['message'] = message elif 'message' in fields: @@ -63,7 +63,7 @@ class invite_wizard(osv.osv_memory): def add_followers(self, cr, uid, ids, context=None): for wizard in self.browse(cr, uid, ids, context=context): - model_obj = self.pool.get(wizard.res_model) + model_obj = self.pool[wizard.res_model] document = model_obj.browse(cr, uid, wizard.res_id, context=context) # filter partner_ids to get the new followers, to avoid sending email to already following partners diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 5622d723eb9..dfda3038de8 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -19,10 +19,9 @@ # ############################################################################## -import base64 import re from openerp import tools - +from openerp import SUPERUSER_ID from openerp.osv import osv from openerp.osv import fields from openerp.tools.safe_eval import safe_eval as eval @@ -136,6 +135,29 @@ class mail_compose_message(osv.TransientModel): 'same_thread': lambda self, cr, uid, ctx={}: True, } + def check_access_rule(self, cr, uid, ids, operation, context=None): + """ Access rules of mail.compose.message: + - create: if + - model, no res_id, I create a message in mass mail mode + - then: fall back on mail.message acces rules + """ + if isinstance(ids, (int, long)): + ids = [ids] + + # Author condition (CREATE (mass_mail)) + if operation == 'create' and uid != SUPERUSER_ID: + # read mail_compose_message.ids to have their values + message_values = {} + cr.execute('SELECT DISTINCT id, model, res_id FROM "%s" WHERE id = ANY (%%s) AND res_id = 0' % self._table, (ids,)) + for id, rmod, rid in cr.fetchall(): + message_values[id] = {'model': rmod, 'res_id': rid} + # remove from the set to check the ids that mail_compose_message accepts + author_ids = [mid for mid, message in message_values.iteritems() + if message.get('model') and not message.get('res_id')] + ids = list(set(ids) - set(author_ids)) + + return super(mail_compose_message, self).check_access_rule(cr, uid, ids, operation, context=context) + def _notify(self, cr, uid, newid, context=None): """ Override specific notify method of mail.message, because we do not want that feature in the wizard. """ @@ -150,12 +172,18 @@ class mail_compose_message(osv.TransientModel): related to. :param int res_id: id of the document record this mail is related to """ - doc_name_get = self.pool.get(model).name_get(cr, uid, [res_id], context=context) + doc_name_get = self.pool[model].name_get(cr, uid, [res_id], context=context) + record_name = False if doc_name_get: record_name = doc_name_get[0][1] - else: - record_name = False - return {'model': model, 'res_id': res_id, 'record_name': record_name} + values = { + 'model': model, + 'res_id': res_id, + 'record_name': record_name, + } + if record_name: + values['subject'] = 'Re: %s' % record_name + return values def get_message_data(self, cr, uid, message_id, context=None): """ Returns a defaults-like dict with initial values for the composition @@ -173,7 +201,7 @@ class mail_compose_message(osv.TransientModel): # create subject re_prefix = _('Re:') - reply_subject = tools.ustr(message_data.subject or '') + reply_subject = tools.ustr(message_data.subject or message_data.record_name or '') if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)) and message_data.subject: reply_subject = "%s %s" % (re_prefix, reply_subject) # get partner_ids from original message @@ -200,33 +228,35 @@ class mail_compose_message(osv.TransientModel): email(s), rendering any template patterns on the fly if needed. """ if context is None: context = {} + ir_attachment_obj = self.pool.get('ir.attachment') active_ids = context.get('active_ids') is_log = context.get('mail_compose_log', False) for wizard in self.browse(cr, uid, ids, context=context): mass_mail_mode = wizard.composition_mode == 'mass_mail' - if mass_mail_mode: # mass mail: avoid any auto subscription because this could lead to people being follower of plenty of documents - context['mail_create_nosubscribe'] = True - active_model_pool = self.pool.get(wizard.model if wizard.model else 'mail.thread') + active_model_pool = self.pool[wizard.model if wizard.model else 'mail.thread'] # wizard works in batch mode: [res_id] or active_ids res_ids = active_ids if mass_mail_mode and wizard.model and active_ids else [wizard.res_id] for res_id in res_ids: - # default values, according to the wizard options + # mail.message values, according to the wizard options post_values = { 'subject': wizard.subject, 'body': wizard.body, 'parent_id': wizard.parent_id and wizard.parent_id.id, 'partner_ids': [partner.id for partner in wizard.partner_ids], - 'attachments': [(attach.datas_fname or attach.name, base64.b64decode(attach.datas)) for attach in wizard.attachment_ids], + 'attachment_ids': [attach.id for attach in wizard.attachment_ids], } # mass mailing: render and override default values if mass_mail_mode and wizard.model: email_dict = self.render_message(cr, uid, wizard, res_id, context=context) - new_partner_ids = email_dict.pop('partner_ids', []) - post_values['partner_ids'] += new_partner_ids - new_attachments = email_dict.pop('attachments', []) - post_values['attachments'] += new_attachments + post_values['partner_ids'] += email_dict.pop('partner_ids', []) + post_values['attachments'] = email_dict.pop('attachments', []) + attachment_ids = [] + for attach_id in post_values.pop('attachment_ids'): + new_attach_id = ir_attachment_obj.copy(cr, uid, attach_id, {'res_model': self._name, 'res_id': wizard.id}, context=context) + attachment_ids.append(new_attach_id) + post_values['attachment_ids'] = attachment_ids post_values.update(email_dict) # email_from: mass mailing only can specify another email_from if email_dict.get('email_from'): @@ -244,8 +274,12 @@ class mail_compose_message(osv.TransientModel): self.pool.get('mail.mail').create(cr, uid, post_values, context=context) else: subtype = 'mail.mt_comment' - if is_log or (mass_mail_mode and not wizard.notify): + if is_log: # log a note: subtype is False subtype = False + elif mass_mail_mode: # mass mail: is a log pushed to recipients unless specified, author not added + if not wizard.notify: + subtype = False + context = dict(context, mail_create_nosubscribe=True) # add context key to avoid subscribing the author msg_id = active_model_pool.message_post(cr, uid, [res_id], type='comment', subtype=subtype, context=context, **post_values) # mass_mailing, post without notify: notify specific partners if mass_mail_mode and not wizard.notify and post_values['partner_ids']: @@ -285,7 +319,7 @@ class mail_compose_message(osv.TransientModel): exp = str(match.group()[2:-1]).strip() result = eval(exp, { 'user': self.pool.get('res.users').browse(cr, uid, uid, context=context), - 'object': self.pool.get(model).browse(cr, uid, res_id, context=context), + 'object': self.pool[model].browse(cr, uid, res_id, context=context), 'context': dict(context), # copy context to prevent side-effects of eval }) return result and tools.ustr(result) or '' diff --git a/addons/marketing_campaign/marketing_campaign.py b/addons/marketing_campaign/marketing_campaign.py index d4b05c50127..fdec2fb39e0 100644 --- a/addons/marketing_campaign/marketing_campaign.py +++ b/addons/marketing_campaign/marketing_campaign.py @@ -32,7 +32,6 @@ import re from openerp.addons.decimal_precision import decimal_precision as dp from openerp.osv import fields, osv -from openerp import netsvc from openerp.tools.translate import _ _intervalTypes = { @@ -166,7 +165,7 @@ Normal - the campaign runs normally and automatically sends all emails and repor # dead code def signal(self, cr, uid, model, res_id, signal, run_existing=True, context=None): - record = self.pool.get(model).browse(cr, uid, res_id, context) + record = self.pool[model].browse(cr, uid, res_id, context) return self._signal(cr, uid, record, signal, run_existing, context) #dead code @@ -229,7 +228,7 @@ Normal - the campaign runs normally and automatically sends all emails and repor if unique_value: if unique_field.ttype == 'many2one': unique_value = unique_value.id - similar_res_ids = self.pool.get(campaign_rec.object_id.model).search(cr, uid, + similar_res_ids = self.pool[campaign_rec.object_id.model].search(cr, uid, [(unique_field.name, '=', unique_value)], context=context) if similar_res_ids: duplicate_workitem_domain = [('res_id','in', similar_res_ids), @@ -237,7 +236,6 @@ Normal - the campaign runs normally and automatically sends all emails and repor return Workitems.search(cr, uid, duplicate_workitem_domain, context=context) -marketing_campaign() class marketing_campaign_segment(osv.osv): _name = "marketing.campaign.segment" @@ -350,7 +348,7 @@ class marketing_campaign_segment(osv.osv): act_ids = self.pool.get('marketing.campaign.activity').search(cr, uid, [('start', '=', True), ('campaign_id', '=', segment.campaign_id.id)], context=context) - model_obj = self.pool.get(segment.object_id.model) + model_obj = self.pool[segment.object_id.model] criteria = [] if segment.sync_last_date and segment.sync_mode != 'all': criteria += [(segment.sync_mode, '>', segment.sync_last_date)] @@ -384,7 +382,6 @@ class marketing_campaign_segment(osv.osv): Workitems.process_all(cr, uid, list(campaigns), context=context) return True -marketing_campaign_segment() class marketing_campaign_activity(osv.osv): _name = "marketing.campaign.activity" @@ -511,7 +508,6 @@ class marketing_campaign_activity(osv.osv): workitem = workitem_obj.browse(cr, uid, wi_id, context=context) return action(cr, uid, activity, workitem, context=context) -marketing_campaign_activity() class marketing_campaign_transition(osv.osv): _name = "marketing.campaign.transition" @@ -583,7 +579,6 @@ class marketing_campaign_transition(osv.osv): ('interval_positive', 'CHECK(interval_nbr >= 0)', 'The interval must be positive or zero') ] -marketing_campaign_transition() class marketing_campaign_workitem(osv.osv): _name = "marketing.campaign.workitem" @@ -595,7 +590,7 @@ class marketing_campaign_workitem(osv.osv): if not wi.res_id: continue - proxy = self.pool.get(wi.object_id.model) + proxy = self.pool[wi.object_id.model] if not proxy.exists(cr, uid, [wi.res_id]): continue ng = proxy.name_get(cr, uid, [wi.res_id], context=context) @@ -629,7 +624,7 @@ class marketing_campaign_workitem(osv.osv): for id, res_id, model in res: workitem_map.setdefault(model,{}).setdefault(res_id,set()).add(id) for model, id_map in workitem_map.iteritems(): - model_pool = self.pool.get(model) + model_pool = self.pool[model] condition_name[0] = model_pool._rec_name condition = [('id', 'in', id_map.keys()), condition_name] for res_id in model_pool.search(cr, uid, condition, context=context): @@ -677,7 +672,7 @@ class marketing_campaign_workitem(osv.osv): return False activity = workitem.activity_id - proxy = self.pool.get(workitem.object_id.model) + proxy = self.pool[workitem.object_id.model] object_id = proxy.browse(cr, uid, workitem.res_id, context=context) eval_context = { @@ -819,7 +814,6 @@ class marketing_campaign_workitem(osv.osv): raise osv.except_osv(_('No preview'),_('The current step for this item has no email or report to preview.')) return res -marketing_campaign_workitem() class email_template(osv.osv): _inherit = "email.template" @@ -829,7 +823,6 @@ class email_template(osv.osv): # TODO: add constraint to prevent disabling / disapproving an email account used in a running campaign -email_template() class report_xml(osv.osv): _inherit = 'ir.actions.report.xml' @@ -842,7 +835,6 @@ class report_xml(osv.osv): args.append(('model', '=', model)) return super(report_xml, self).search(cr, uid, args, offset, limit, order, context, count) -report_xml() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/marketing_campaign/report/campaign_analysis.py b/addons/marketing_campaign/report/campaign_analysis.py index 1fc8a5f1dc7..f09ed966857 100644 --- a/addons/marketing_campaign/report/campaign_analysis.py +++ b/addons/marketing_campaign/report/campaign_analysis.py @@ -98,6 +98,5 @@ class campaign_analysis(osv.osv): wi.date::date ) """) -campaign_analysis() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/marketing_campaign/res_partner.py b/addons/marketing_campaign/res_partner.py index c151c2f4050..b012cbb7181 100644 --- a/addons/marketing_campaign/res_partner.py +++ b/addons/marketing_campaign/res_partner.py @@ -36,7 +36,6 @@ class res_partner(osv.osv): }) return super(res_partner, self).copy(cr, uid, id, default=default, context=context) -res_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/membership/membership.py b/addons/membership/membership.py index ae7f4948d72..b75284637c9 100644 --- a/addons/membership/membership.py +++ b/addons/membership/membership.py @@ -169,7 +169,6 @@ class membership_line(osv.osv): (_check_membership_date, 'Error, this membership product is out of date', []) ] -membership_line() class Partner(osv.osv): @@ -442,7 +441,6 @@ class Partner(osv.osv): self.pool.get('res.partner').write(cr, uid, ids, {}) return invoice_list -Partner() class Product(osv.osv): @@ -476,7 +474,6 @@ class Product(osv.osv): 'membership': False, } -Product() class Invoice(osv.osv): @@ -494,7 +491,6 @@ class Invoice(osv.osv): member_line_obj.write(cr, uid, mlines, {'date_cancel': today}) return super(Invoice, self).action_cancel(cr, uid, ids, context=context) -Invoice() class account_invoice_line(osv.osv): _inherit='account.invoice.line' @@ -561,6 +557,5 @@ class account_invoice_line(osv.osv): }, context=context) return result -account_invoice_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/membership/report/report_membership.py b/addons/membership/report/report_membership.py index f68e52992af..081a2f0d8a5 100644 --- a/addons/membership/report/report_membership.py +++ b/addons/membership/report/report_membership.py @@ -139,6 +139,5 @@ class report_membership(osv.osv): membership_amount )""") -report_membership() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/membership/test/test_membership.yml b/addons/membership/test/test_membership.yml index 40d1785c29a..489b8b06afb 100644 --- a/addons/membership/test/test_membership.yml +++ b/addons/membership/test/test_membership.yml @@ -31,7 +31,6 @@ I'm Opening that Invoice which is created for "Seagate". - !python {model: res.partner}: | - from openerp.tools.translate import _ invoice_pool = self.pool.get('account.invoice') partner_pool = self.pool.get('res.partner') membership_line_pool = self.pool.get('membership.membership_line') @@ -39,7 +38,7 @@ membership_line_ids = membership_line_pool.search(cr, uid, [('membership_id','=',ref('product_product_membershipproduct0')),('partner','=',ref('base.res_partner_19'))]) membership_lines = membership_line_pool.browse(cr, uid, membership_line_ids) - assert membership_lines, _('Membership is not registrated.') + assert membership_lines, 'Membership is not registrated.' membership_line = membership_lines[0] invoice_pool.signal_invoice_open(cr, uid, [membership_line.account_invoice_id.id]) @@ -105,7 +104,6 @@ I'm doing to make credit note of invoice which is paid by "Seagate" to cancel membership. - !python {model: account.invoice}: | - from openerp.tools.translate import _ invoice_pool = self.pool.get('account.invoice') partner_pool = self.pool.get('res.partner') membership_line_pool = self.pool.get('membership.membership_line') @@ -114,7 +112,7 @@ membership_line_ids = membership_line_pool.search(cr, uid, [('membership_id','=',ref('product_product_membershipproduct0')),('partner','=',ref('base.res_partner_19'))]) membership_lines = membership_line_pool.browse(cr, uid, membership_line_ids) - assert membership_lines, _('Membership is not registrated.') + assert membership_lines, 'Membership is not registrated.' membership_line = membership_lines[0] refund_id = invoice_refund_pool.create(cr, uid, {'description': 'Refund of Membership', 'filter_refund': 'refund'}, {'active_id': membership_line.account_invoice_id.id}) invoice_refund_pool.invoice_refund(cr, uid, [refund_id], {'active_id': membership_line.account_invoice_id.id, 'active_ids': [membership_line.account_invoice_id.id]}) diff --git a/addons/membership/wizard/membership_invoice.py b/addons/membership/wizard/membership_invoice.py index 2425cd648ea..a1e07146da0 100644 --- a/addons/membership/wizard/membership_invoice.py +++ b/addons/membership/wizard/membership_invoice.py @@ -73,6 +73,5 @@ class membership_invoice(osv.osv_memory): 'search_view_id': search_view_id, } -membership_invoice() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/company.py b/addons/mrp/company.py index af8a21f4934..375a318c9d0 100644 --- a/addons/mrp/company.py +++ b/addons/mrp/company.py @@ -30,7 +30,6 @@ class company(osv.osv): _defaults = { 'manufacturing_lead': lambda *a: 1.0, } -company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/i18n/es_MX.po b/addons/mrp/i18n/es_MX.po index 82d584be219..f9fb2d53cb7 100644 --- a/addons/mrp/i18n/es_MX.po +++ b/addons/mrp/i18n/es_MX.po @@ -1,72 +1,61 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * mrp +# Spanish (Mexico) 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: OpenERP Server 6.0dev\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2011-01-11 11:15+0000\n" -"PO-Revision-Date: 2011-03-12 16:35+0000\n" -"Last-Translator: Jordi Esteve (www.zikzakmedia.com) " -"\n" -"Language-Team: \n" +"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-03-23 21:44+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Mexico) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-05 04:59+0000\n" -"X-Generator: Launchpad (build 13830)\n" +"X-Launchpad-Export-Date: 2013-03-24 04:45+0000\n" +"X-Generator: Launchpad (build 16540)\n" #. module: mrp -#: field:mrp.production,move_created_ids:0 -#: field:mrp.production,move_created_ids2:0 -msgid "Moves Created" -msgstr "Movimientos creados" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_production_action +#: help:mrp.config.settings,module_mrp_repair:0 msgid "" -"Manufacturing Orders are usually proposed automatically by OpenERP based on " -"the bill of materials and the procurement rules, but you can also create " -"manufacturing orders manually. OpenERP will handle the consumption of the " -"raw materials (stock decrease) and the production of the finished products " -"(stock increase) when the order is processed." +"Allows to manage all product repairs.\n" +" * Add/remove products in the reparation\n" +" * Impact for stocks\n" +" * Invoicing (products and/or services)\n" +" * Warranty concept\n" +" * Repair quotation report\n" +" * Notes for the technician and for the final customer.\n" +" This installs the module mrp_repair." msgstr "" -"Las órdenes de fabricación suelen ser propuestas automáticamente por OpenERP " -"en base a la lista de materiales y las reglas de abastecimiento, pero " -"también puede crear órdenes de fabricación manualmente. OpenERP controlará " -"el consumo de las materias primas (disminución de stock) y la producción de " -"los productos terminados (aumento de stock) cuando se procese la orden." - -#. module: mrp -#: help:mrp.production,location_src_id:0 -msgid "Location where the system will look for components." -msgstr "Ubicación donde el sistema buscará los componentes." - -#. module: mrp -#: field:mrp.production,workcenter_lines:0 -msgid "Work Centers Utilisation" -msgstr "Utilización del centro de producción" - -#. module: mrp -#: view:mrp.routing.workcenter:0 -msgid "Routing Work Centers" -msgstr "Ruta de centros de producción" - -#. module: mrp -#: model:ir.module.module,shortdesc:mrp.module_meta_information -msgid "Manufacturing Resource Planning" -msgstr "Planificación de recursos de fabricación (MRP)" #. module: mrp #: report:mrp.production.order:0 msgid "No. Of Cycles" -msgstr "Núm. de ciclos" +msgstr "" #. module: mrp +#: help:mrp.production,location_src_id:0 +msgid "Location where the system will look for components." +msgstr "" + +#. module: mrp +#: field:mrp.production,workcenter_lines:0 +msgid "Work Centers Utilisation" +msgstr "" + +#. module: mrp +#: view:mrp.routing.workcenter:0 +msgid "Routing Work Centers" +msgstr "" + +#. module: mrp +#: field:mrp.production.workcenter.line,cycle:0 #: field:mrp.routing.workcenter,cycle_nbr:0 +#: field:report.workcenter.load,cycle:0 msgid "Number of Cycles" -msgstr "Número de ciclos" +msgstr "" #. module: mrp #: model:process.transition,note:mrp.process_transition_minimumstockprocure0 @@ -74,26 +63,12 @@ msgid "" "The 'Minimum stock rule' allows the system to create procurement orders " "automatically as soon as the minimum stock is reached." msgstr "" -"La 'regla de stock mínimo' permite al sistema de crear órdenes de " -"abasteciemiento automáticamente cuando el stock mínimo es alcanzado" - -#. module: mrp -#: field:mrp.production,picking_id:0 -#: field:mrp.production.order,picking_id:0 -msgid "Picking list" -msgstr "Albarán" - -#. module: mrp -#: code:addons/mrp/report/price.py:121 -#, python-format -msgid "Hourly Cost" -msgstr "Coste horario" #. module: mrp #: code:addons/mrp/report/price.py:130 #, python-format -msgid "Cost Price per Uom" -msgstr "Precio de coste pour Udm" +msgid "Hourly Cost" +msgstr "" #. module: mrp #: view:mrp.production:0 @@ -101,36 +76,32 @@ msgid "Scrap Products" msgstr "Productos de desecho" #. module: mrp -#: view:mrp.production.order:0 -#: field:mrp.production.order,day:0 -msgid "Day" -msgstr "Día" +#: view:mrp.workcenter:0 +msgid "Mrp Workcenter" +msgstr "" #. module: mrp #: model:ir.actions.act_window,name:mrp.mrp_routing_action #: model:ir.ui.menu,name:mrp.menu_mrp_routing_action msgid "Routings" -msgstr "Procesos productivos" - -#. module: mrp -#: field:mrp.workcenter,product_id:0 -msgid "Work Center Product" -msgstr "Producto centro de producción" +msgstr "" #. module: mrp #: view:mrp.bom:0 msgid "Search Bill Of Material" -msgstr "Buscar lista de materiales" +msgstr "" #. module: mrp #: model:process.node,note:mrp.process_node_stockproduct1 msgid "For stockable products and consumables" -msgstr "Para productos almacenables y consumibles" +msgstr "" #. module: mrp -#: model:process.transition,name:mrp.process_transition_stockproduction0 -msgid "To Produce" -msgstr "A producir" +#: help:mrp.bom,message_unread:0 +#: help:mrp.production,message_unread:0 +#: help:mrp.production.workcenter.line,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" #. module: mrp #: help:mrp.routing.workcenter,cycle_nbr:0 @@ -138,76 +109,63 @@ msgid "" "Number of iterations this work center has to do in the specified operation " "of the routing." msgstr "" -"Número de iteraciones que debe realizar este centro de producción en la " -"operación indicada de la ruta." + +#. module: mrp +#: view:product.product:0 +msgid "False" +msgstr "" #. module: mrp #: view:mrp.bom:0 #: field:mrp.bom,code:0 -#: view:mrp.production:0 #: field:mrp.production,name:0 msgid "Reference" -msgstr "Referencia" +msgstr "" #. module: mrp #: view:mrp.production:0 msgid "Finished Products" -msgstr "Productos finalizados" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Manufacturing Orders which are currently in production." +msgstr "" + +#. module: mrp +#: help:mrp.bom,message_summary:0 +#: help:mrp.production,message_summary:0 +#: help:mrp.production.workcenter.line,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: mrp #: model:process.transition,name:mrp.process_transition_servicerfq0 #: model:process.transition,name:mrp.process_transition_stockrfq0 msgid "To Buy" -msgstr "A comprar" - -#. module: mrp -#: view:mrp.production.order:0 -msgid "Raw Material Location" -msgstr "Ubicación de materias primas" - -#. module: mrp -#: help:mrp.installer,mrp_operations:0 -msgid "" -"Enhances production orders with readiness states as well as the start date " -"and end date of execution of the order." msgstr "" -"Mejora las órdenes de producción con los estados de preparación, así como la " -"fecha de inicio y final de la ejecución de la orden." #. module: mrp #: model:process.transition,note:mrp.process_transition_purchaseprocure0 msgid "The system launches automatically a RFQ to the preferred supplier." msgstr "" -"El sistema crea automáticamente una petición de presupuesto al proveedor " -"preferido." #. module: mrp #: view:mrp.production:0 msgid "Products to Finish" -msgstr "Productos a terminar" +msgstr "" #. module: mrp #: selection:mrp.bom,method:0 msgid "Set / Pack" -msgstr "Conjunto / Paquete" - -#. module: mrp -#: field:mrp.installer,mrp_subproduct:0 -msgid "MRP Subproducts" -msgstr "Subproductos MRP" - -#. module: mrp -#: view:mrp.production:0 -#: field:mrp.production,state:0 -#: view:mrp.production.order:0 -#: field:mrp.production.order,state:0 -msgid "State" -msgstr "Estado" +msgstr "" #. module: mrp #: field:mrp.workcenter,costs_hour:0 msgid "Cost per hour" -msgstr "Coste por hora" +msgstr "" #. module: mrp #: model:process.transition,note:mrp.process_transition_stockproduction0 @@ -215,188 +173,221 @@ msgid "" "In case the Supply method of the product is Produce, the system creates a " "production order." msgstr "" -"En caso de que el método de suministro del producto es Producir, el sistema " -"crea una orden de producción." - -#. module: mrp -#: view:mrp.production:0 -msgid "UOM" -msgstr "UdM" #. module: mrp #: field:change.production.qty,product_qty:0 -#: field:mrp.bom,product_qty:0 -#: field:mrp.production,product_qty:0 -#: view:mrp.production.order:0 -#: field:mrp.production.order,product_qty:0 -#: field:mrp.production.product.line,product_qty:0 msgid "Product Qty" -msgstr "Ctdad producto" +msgstr "" #. module: mrp -#: help:mrp.workcenter,product_id:0 -msgid "" -"Fill this product to track easily your production costs in the analytic " -"accounting." +#: view:mrp.production:0 +msgid "Unit of Measure" msgstr "" -"Introduzca este producto para realizar fácilmente un seguimiento de sus " -"costes de producción en la contabilidad analítica." #. module: mrp #: model:process.node,note:mrp.process_node_purchaseprocure0 msgid "For purchased material" -msgstr "Para material comprado" +msgstr "" #. module: mrp -#: field:mrp.bom.revision,indice:0 -msgid "Revision" -msgstr "Revisión" +#: model:ir.ui.menu,name:mrp.menu_mrp_production_order_action +msgid "Order Planning" +msgstr "" #. module: mrp -#: model:ir.ui.menu,name:mrp.next_id_77 -msgid "Reporting" -msgstr "Informe" +#: field:mrp.config.settings,module_mrp_operations:0 +msgid "Allow detailed planning of work order" +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:633 +#, python-format +msgid "Cannot cancel manufacturing order!" +msgstr "" #. module: mrp #: field:mrp.workcenter,costs_cycle_account_id:0 msgid "Cycle Account" -msgstr "Cuenta ciclo" +msgstr "" #. module: mrp -#: code:addons/mrp/report/price.py:121 +#: code:addons/mrp/report/price.py:130 #, python-format msgid "Work Cost" -msgstr "Coste del trabajo" - -#. module: mrp -#: report:bom.structure:0 -msgid "[" -msgstr "[" +msgstr "" #. module: mrp #: model:process.transition,name:mrp.process_transition_procureserviceproduct0 msgid "Procurement of services" -msgstr "Abastecimiento de servicios" +msgstr "" #. module: mrp #: view:mrp.workcenter:0 msgid "Capacity Information" -msgstr "Información de capacidad" +msgstr "" + +#. module: mrp +#: field:mrp.routing,workcenter_lines:0 +msgid "Work Centers" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,help:mrp.mrp_routing_action +msgid "" +"

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

\n" +" Routings allow you to create and manage the manufacturing\n" +" operations that should be followed within your work centers " +"in\n" +" order to produce a product. They are attached to bills of\n" +" materials that will define the required raw materials.\n" +"

\n" +" " +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +#: field:mrp.production,move_created_ids2:0 +msgid "Produced Products" +msgstr "" #. module: mrp #: report:mrp.production.order:0 msgid "Destination Location" -msgstr "Ubicación destino" - -#. module: mrp -#: view:mrp.installer:0 -msgid "title" -msgstr "título" - -#. module: mrp -#: model:ir.ui.menu,name:mrp.menu_mrp_bom -msgid "Master Data" -msgstr "Datos principales" - -#. module: mrp -#: model:process.transition,note:mrp.process_transition_stockmts0 -msgid "" -"The system waits for the products to be available in the stock. These " -"products are typically procured manually or through a minimum stock rule." msgstr "" -"El sistema espera a que los productos estén disponibles en el stock. Estos " -"productos suelen ser adquiridos de forma manual o a través de una regla de " -"stock mínimo." + +#. module: mrp +#: view:mrp.config.settings:0 +msgid "Master Data" +msgstr "" + +#. module: mrp +#: field:mrp.config.settings,module_mrp_byproduct:0 +msgid "Produce several products from one manufacturing order" +msgstr "" + +#. module: mrp +#: help:mrp.config.settings,group_mrp_properties:0 +msgid "" +"The selection of the right Bill of Material to use will depend on the " +"properties specified on the sales order and the Bill of Material." +msgstr "" + +#. module: mrp +#: view:mrp.bom:0 +msgid "" +"When processing a sales order for this product, the delivery order\n" +" will contain the raw materials, instead of " +"the finished product." +msgstr "" #. module: mrp #: report:mrp.production.order:0 msgid "Partner Ref" -msgstr "Ref. empresa" +msgstr "" #. module: mrp #: selection:mrp.workcenter.load,measure_unit:0 msgid "Amount in hours" -msgstr "Cantidad en horas" +msgstr "" #. module: mrp #: field:mrp.production,product_lines:0 msgid "Scheduled goods" -msgstr "Bienes planificados" +msgstr "" #. module: mrp #: selection:mrp.bom,type:0 msgid "Sets / Phantom" -msgstr "Conjuntos / Fantasma" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +#: field:mrp.production,state:0 +msgid "Status" +msgstr "" #. module: mrp #: help:mrp.bom,position:0 msgid "Reference to a position in an external plan." -msgstr "Referencia a una ubicación en una plan. externa" +msgstr "" #. module: mrp -#: selection:mrp.production.order,month:0 -msgid "August" -msgstr "Agosto" - -#. module: mrp -#: constraint:stock.move:0 -msgid "You try to assign a lot which is not from the same product" -msgstr "Está intentando asignar un lote que no es del mismo producto" - -#. module: mrp -#: model:ir.model,name:mrp.model_mrp_production_order -msgid "Production Order Report" -msgstr "Informe de órden de producción" - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "June" -msgstr "Junio" +#: model:res.groups,name:mrp.group_mrp_routings +msgid "Manage Routings" +msgstr "" #. module: mrp #: model:ir.model,name:mrp.model_mrp_product_produce msgid "Product Produce" -msgstr "Producir producto" +msgstr "" #. module: mrp -#: selection:mrp.production.order,month:0 -msgid "October" -msgstr "Octubre" +#: constraint:mrp.bom:0 +msgid "Error ! You cannot create recursive BoM." +msgstr "" #. module: mrp -#: code:addons/mrp/report/price.py:177 -#, python-format -msgid "Components Cost of " -msgstr "Coste de los componentes de " +#: model:ir.model,name:mrp.model_mrp_routing_workcenter +msgid "Work Center Usage" +msgstr "" #. module: mrp #: model:process.transition,name:mrp.process_transition_procurestockableproduct0 msgid "Procurement of stockable Product" -msgstr "Abastecimiento de producto almacenable" +msgstr "" #. module: mrp -#: view:mrp.bom:0 -msgid "Default UOM" -msgstr "UdM por defecto" +#: model:ir.actions.act_window,help:mrp.mrp_production_action +msgid "" +"

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

\n" +" A manufacuring order, based on a bill of materials, will\n" +" consume raw materials and produce finished products.\n" +"

\n" +" Manufacturing orders are usually proposed automatically " +"based\n" +" on customer requirements or automated rules like the " +"minimum\n" +" stock rule.\n" +"

\n" +" " +msgstr "" #. module: mrp -#: code:addons/mrp/report/price.py:130 +#: sql_constraint:mrp.production:0 +msgid "Reference must be unique per Company!" +msgstr "" + +#. module: mrp +#: code:addons/mrp/report/price.py:139 #: report:bom.structure:0 +#: view:mrp.bom:0 #: field:mrp.product_price,number:0 +#: view:mrp.production:0 #: report:mrp.production.order:0 #, python-format msgid "Quantity" -msgstr "Cantidad" +msgstr "" #. module: mrp -#: field:mrp.production.workcenter.line,hour:0 -msgid "Nbr of hours" -msgstr "Nº de horas" +#: help:mrp.workcenter,product_id:0 +msgid "" +"Fill this product to easily track your production costs in the analytic " +"accounting." +msgstr "" + +#. module: mrp +#: field:mrp.workcenter,product_id:0 +msgid "Work Center Product" +msgstr "" #. module: mrp #: view:mrp.production:0 msgid "Confirm Production" -msgstr "Confirmar producción" +msgstr "" #. module: mrp #: model:process.transition,note:mrp.process_transition_stockproduct0 @@ -404,8 +395,6 @@ msgid "" "The system creates an order (production or purchased) depending on the sold " "quantity and the products parameters." msgstr "" -"El sistema crea una orden (de producción o de compra) en función de la " -"cantidad vendida y los parámetros de los productos." #. module: mrp #: model:process.transition,note:mrp.process_transition_servicemts0 @@ -413,49 +402,85 @@ msgid "" "This is used in case of a service without any impact in the system, a " "training session for instance." msgstr "" -"Esto se utiliza en caso de un servicio sin ningún tipo de impacto en el " -"sistema, una sesión de formación, por ejemplo." #. module: mrp -#: field:mrp.installer,mrp_repair:0 -msgid "Repairs" -msgstr "Reparaciones" +#: field:mrp.bom,product_qty:0 +#: field:mrp.production,product_qty:0 +#: field:mrp.production.product.line,product_qty:0 +msgid "Product Quantity" +msgstr "" #. module: mrp -#: field:mrp.installer,stock_location:0 -msgid "Advanced Routes" -msgstr "Rutas avanzadas" +#: help:mrp.production,picking_id:0 +msgid "" +"This is the Internal Picking List that brings the finished product to the " +"production plan" +msgstr "" #. module: mrp #: model:ir.ui.menu,name:mrp.menu_view_resource_calendar_search_mrp msgid "Working Time" -msgstr "Horario trabajo" +msgstr "" + +#. module: mrp +#: help:mrp.production,state:0 +msgid "" +"When the production order is created the status is set to 'Draft'.\n" +" If the order is confirmed the status is set to 'Waiting " +"Goods'.\n" +" If any exceptions are there, the status is set to 'Picking " +"Exception'.\n" +" If the stock is available then the status is set to 'Ready " +"to Produce'.\n" +" When the production gets started then the status is set to " +"'In Production'.\n" +" When the production is over, the status is set to 'Done'." +msgstr "" #. module: mrp #: model:ir.actions.act_window,name:mrp.action_report_in_out_picking_tree msgid "Weekly Stock Value Variation" -msgstr "Variación del valor del stock semanal" - -#. module: mrp -#: help:mrp.installer,mrp_repair:0 -msgid "" -"Enables warranty and repair management (and their impact on stocks and " -"invoicing)." msgstr "" -"Activa la garantía y la gestión de reparaciones (y su impacto sobre stocks y " -"facturación)" #. module: mrp -#: field:mrp.production,date_planned_date:0 +#: model:ir.actions.act_window,help:mrp.mrp_property_action +msgid "" +"

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

\n" +" The Properties in OpenERP are used to select the right bill " +"of\n" +" materials for manufacturing a product when you have " +"different\n" +" ways of building the same product. You can assign several\n" +" properties to each bill of materials. When a salesperson\n" +" creates a sales order, they can relate it to several " +"properties\n" +" and OpenERP will automatically select the BoM to use " +"according\n" +" the needs.\n" +"

\n" +" " +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +#: field:mrp.production,date_planned:0 #: report:mrp.production.order:0 -#: field:mrp.production.order,date_planned:0 msgid "Scheduled Date" -msgstr "Fecha programada" +msgstr "" #. module: mrp +#: code:addons/mrp/procurement.py:124 +#, python-format +msgid "Manufacturing Order %s created." +msgstr "" + +#. module: mrp +#: view:mrp.bom:0 #: report:mrp.production.order:0 msgid "Bill Of Material" -msgstr "Lista de Material" +msgstr "" #. module: mrp #: help:mrp.routing,location_id:0 @@ -464,165 +489,140 @@ msgid "" "needed.Set a location if you produce at a fixed location. This can be a " "partner location if you subcontract the manufacturing operations." msgstr "" -"Dejarlo vacío si se produce en el mismo lugar en que los productos acabados " -"son necesarios. Indique una ubicación si se produce en una ubicación fija. " -"Puede ser una ubicación de otra empresa si subcontrata las operaciones de " -"fabricación." #. module: mrp #: view:board.board:0 msgid "Stock Value Variation" -msgstr "Variación del valor de stock" +msgstr "" #. module: mrp #: model:ir.actions.act_window,name:mrp.action2 msgid "Bill of Materials Structure" -msgstr "Estructura lista de materiales" +msgstr "" #. module: mrp #: model:process.node,note:mrp.process_node_serviceproduct0 msgid "Product type is service" -msgstr "Producto de tipo servicio" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_property_group_action -msgid "" -"Define specific property groups that can be assigned to the properties of " -"your bill of materials." msgstr "" -"Definir grupos específicos de propiedad que se pueden asignar a las " -"propiedades de su lista de materiales." - -#. module: mrp -#: model:process.transition,name:mrp.process_transition_bom0 -msgid "Manufacturing decomposition" -msgstr "Descomposición fabricación" - -#. module: mrp -#: model:process.node,note:mrp.process_node_serviceproduct1 -msgid "For Services." -msgstr "Para servicios" - -#. module: mrp -#: field:mrp.bom.revision,date:0 -msgid "Modification Date" -msgstr "Fecha de modificación" - -#. module: mrp -#: help:mrp.workcenter,costs_cycle_account_id:0 -#: help:mrp.workcenter,costs_hour_account_id:0 -msgid "" -"Complete this only if you want automatic analytic accounting entries on " -"production orders." -msgstr "" -"Rellenarlo sólo si desea crear entradas automáticas de contabilidad " -"analítica según órdenes de producción." - -#. module: mrp -#: field:mrp.production.workcenter.line,cycle:0 -msgid "Nbr of cycles" -msgstr "Nº de ciclos" - -#. module: mrp -#: model:process.node,note:mrp.process_node_orderrfq0 -#: model:process.node,note:mrp.process_node_rfq0 -msgid "Request for Quotation." -msgstr "Solicitud de presupuesto." - -#. module: mrp -#: model:process.transition,note:mrp.process_transition_billofmaterialrouting0 -msgid "" -"The Bill of Material is linked to a routing, i.e. the succession of work " -"centers." -msgstr "" -"La lista de materiales está vinculada a una ruta, es decir, la sucesión de " -"centros de producción." - -#. module: mrp -#: constraint:product.product:0 -msgid "Error: Invalid ean code" -msgstr "Error: Código EAN no válido" - -#. module: mrp -#: view:mrp.routing:0 -#: field:mrp.routing,location_id:0 -msgid "Production Location" -msgstr "Ubicación de producción" - -#. module: mrp -#: view:mrp.production:0 -msgid "Change Qty" -msgstr "Cambiar Ctd." - -#. module: mrp -#: view:mrp.production:0 -msgid "Force Reservation" -msgstr "Forzar reservas" - -#. module: mrp -#: field:mrp.bom.revision,author_id:0 -msgid "Author" -msgstr "Autor" - -#. module: mrp -#: field:report.mrp.inout,value:0 -msgid "Stock value" -msgstr "Valor del stock" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.action_product_bom_structure -msgid "Product BoM Structure" -msgstr "Estructura LdM del producto" - -#. module: mrp -#: view:mrp.production:0 -msgid "Search Production" -msgstr "Buscar producción" - -#. module: mrp -#: code:addons/mrp/report/price.py:130 -#, python-format -msgid "Supplier Price per Uom" -msgstr "Precio proveedor por UdM" - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "March" -msgstr "Marzo" - -#. module: mrp -#: field:mrp.bom,child_complete_ids:0 -msgid "BoM Hierarchy" -msgstr "Estructura LdM" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.act_mrp_product_produce -#: view:mrp.product.produce:0 -#: view:mrp.production:0 -msgid "Produce" -msgstr "Producir" #. module: mrp #: help:mrp.workcenter,costs_cycle:0 msgid "Specify Cost of Work Center per cycle." msgstr "" +#. module: mrp +#: model:process.transition,name:mrp.process_transition_bom0 +msgid "Manufacturing decomposition" +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_serviceproduct1 +msgid "For Services." +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_orderrfq0 +#: model:process.node,note:mrp.process_node_rfq0 +msgid "Request for Quotation." +msgstr "" + +#. module: mrp +#: view:change.production.qty:0 +#: view:mrp.config.settings:0 +#: view:mrp.product.produce:0 +#: view:mrp.product_price:0 +#: view:mrp.workcenter.load:0 +msgid "or" +msgstr "" + +#. module: mrp +#: model:process.transition,note:mrp.process_transition_billofmaterialrouting0 +msgid "" +"The Bill of Material is linked to a routing, i.e. the succession of work " +"centers." +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +#: field:mrp.production,move_created_ids:0 +msgid "Products to Produce" +msgstr "" + +#. module: mrp +#: view:mrp.config.settings:0 +msgid "Apply" +msgstr "" + +#. module: mrp +#: view:mrp.routing:0 +#: field:mrp.routing,location_id:0 +msgid "Production Location" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Force Reservation" +msgstr "" + +#. module: mrp +#: field:report.mrp.inout,value:0 +msgid "Stock value" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.action_product_bom_structure +msgid "Product BoM Structure" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Search Production" +msgstr "" + +#. module: mrp +#: help:mrp.routing.workcenter,sequence:0 +msgid "" +"Gives the sequence order when displaying a list of routing Work Centers." +msgstr "" + +#. module: mrp +#: field:mrp.bom,child_complete_ids:0 +msgid "BoM Hierarchy" +msgstr "" + +#. module: mrp +#: model:process.transition,name:mrp.process_transition_stockproduction0 +msgid "To Produce" +msgstr "" + +#. module: mrp +#: help:mrp.config.settings,module_stock_no_autopicking:0 +msgid "" +"This module allows an intermediate picking process to provide raw materials " +"to production orders.\n" +" For example to manage production made by your suppliers (sub-" +"contracting).\n" +" To achieve this, set the assembled product which is sub-" +"contracted to \"No Auto-Picking\"\n" +" and put the location of the supplier in the routing of the " +"assembly operation.\n" +" This installs the module stock_no_autopicking." +msgstr "" + #. module: mrp #: selection:mrp.production,state:0 -#: view:mrp.production.order:0 -#: selection:mrp.production.order,state:0 msgid "Picking Exception" -msgstr "Excepción albarán" +msgstr "" #. module: mrp #: field:mrp.bom,bom_lines:0 msgid "BoM Lines" -msgstr "Líneas de las listas de materiales" +msgstr "" #. module: mrp #: field:mrp.workcenter,time_start:0 msgid "Time before prod." -msgstr "Tiempo antes producción" +msgstr "" #. module: mrp #: help:mrp.routing,active:0 @@ -630,59 +630,53 @@ msgid "" "If the active field is set to False, it will allow you to hide the routing " "without removing it." msgstr "" -"Si el campo activo se desmarca, permite ocultar la ruta sin eliminarla." #. module: mrp #: model:process.transition,name:mrp.process_transition_billofmaterialrouting0 msgid "Material Routing" -msgstr "Ruta del material" +msgstr "" #. module: mrp #: view:mrp.production:0 #: field:mrp.production,move_lines2:0 #: report:mrp.production.order:0 -#: field:mrp.production.order,consumed_products:0 msgid "Consumed Products" -msgstr "Productos consumidos" - -#. module: mrp -#: constraint:mrp.bom:0 -msgid "Error ! You can not create recursive BoM." -msgstr "¡Error! No puede crear Listas de Material recursivas." +msgstr "" #. module: mrp #: model:ir.actions.act_window,name:mrp.action_mrp_workcenter_load_wizard #: model:ir.model,name:mrp.model_mrp_workcenter_load #: model:ir.model,name:mrp.model_report_workcenter_load msgid "Work Center Load" -msgstr "Carga centro de producción" +msgstr "" #. module: mrp -#: code:addons/mrp/procurement.py:45 +#: code:addons/mrp/procurement.py:50 #, python-format msgid "No BoM defined for this product !" -msgstr "¡No se ha definido LdM para este producto!" +msgstr "" #. module: mrp #: model:ir.actions.act_window,name:mrp.mrp_bom_form_action2 #: model:ir.ui.menu,name:mrp.menu_mrp_bom_form_action2 msgid "Bill of Material Components" -msgstr "Componentes de lista de materiales" +msgstr "" #. module: mrp -#: field:mrp.production.order,nbr:0 -msgid "# of Lines" -msgstr "Nº de líneas" +#: model:ir.model,name:mrp.model_stock_move +msgid "Stock Move" +msgstr "" #. module: mrp #: model:ir.ui.menu,name:mrp.menu_mrp_planning +#: view:mrp.config.settings:0 msgid "Planning" -msgstr "Planificación" +msgstr "" #. module: mrp #: view:mrp.production:0 msgid "Ready" -msgstr "Preparado" +msgstr "" #. module: mrp #: help:mrp.production,routing_id:0 @@ -692,142 +686,151 @@ msgid "" "operations and to plan future loads on work centers based on production " "plannification." msgstr "" -"Lista de las operaciones (lista de los centros de trabajo) para producir los " -"productos acabados. La ruta se utiliza principalmente para calcular los " -"costes del centro de trabajo durante las operaciones y planificar la carga " -"en el futuro en los centros de trabajo basada en la planificación de " -"producción." #. module: mrp #: help:mrp.workcenter,time_cycle:0 msgid "Time in hours for doing one cycle." -msgstr "Tiempo en horas para realizar un ciclo." +msgstr "" #. module: mrp -#: report:bom.structure:0 -msgid "BOM Ref" -msgstr "Ref LdM" +#: model:ir.actions.act_window,help:mrp.mrp_bom_form_action2 +msgid "" +"

\n" +" Click to add a component to a bill of material.\n" +"

\n" +" Bills of materials components are components and by-" +"products\n" +" used to create master bills of materials. Use this menu to\n" +" search in which BoM a specific component is used.\n" +"

\n" +" " +msgstr "" + +#. module: mrp +#: constraint:mrp.bom:0 +msgid "BoM line product should not be same as BoM product." +msgstr "" #. module: mrp #: view:mrp.production:0 -#: selection:mrp.production,state:0 -#: view:mrp.production.order:0 -#: selection:mrp.production.order,state:0 msgid "In Production" -msgstr "En producción" +msgstr "" #. module: mrp #: model:ir.ui.menu,name:mrp.menu_mrp_property msgid "Master Bill of Materials" -msgstr "Lista de materiales maestra" +msgstr "" #. module: mrp -#: help:mrp.bom,product_uos:0 +#: help:mrp.config.settings,module_product_manufacturer:0 msgid "" -"Product UOS (Unit of Sale) is the unit of measurement for the invoicing and " -"promotion of stock." +"This allows you to define the following for a product:\n" +" * Manufacturer\n" +" * Manufacturer Product Name\n" +" * Manufacturer Product Code\n" +" * Product Attributes.\n" +" This installs the module product_manufacturer." msgstr "" -"UdV del producto (Unidad de Venta) es la unidad de medida para la " -"facturación y la promoción de existencias." #. module: mrp #: view:mrp.product_price:0 #: view:mrp.workcenter.load:0 msgid "Print" -msgstr "Imprimir" +msgstr "" #. module: mrp #: view:mrp.bom:0 #: view:mrp.workcenter:0 msgid "Type" -msgstr "Tipo" +msgstr "" #. module: mrp -#: code:addons/mrp/report/price.py:150 -#: code:addons/mrp/report/price.py:201 -#, python-format -msgid "Total Cost of " -msgstr "Coste total de " +#: model:ir.actions.act_window,help:mrp.mrp_workcenter_action +msgid "" +"

\n" +" Click to add a work center.\n" +"

\n" +" Work Centers allow you to create and manage manufacturing\n" +" units. They consist of workers and/or machines, which are\n" +" considered as units for task assignation as well as " +"capacity\n" +" and planning forecast.\n" +"

\n" +" " +msgstr "" #. module: mrp #: model:process.node,note:mrp.process_node_minimumstockrule0 msgid "Linked to the 'Minimum stock rule' supplying method." -msgstr "Vinculado al método de abastecimiento 'Regla de stock mínimo'." +msgstr "" #. module: mrp #: selection:mrp.workcenter.load,time_unit:0 msgid "Per month" -msgstr "Por mes" +msgstr "" #. module: mrp -#: code:addons/mrp/mrp.py:595 -#: code:addons/mrp/wizard/change_production_qty.py:77 -#: code:addons/mrp/wizard/change_production_qty.py:82 -#, python-format -msgid "Couldn't find bill of material for product" -msgstr "No se puede encontrar la lista de material para el producto" +#: help:mrp.bom,product_uom:0 +msgid "" +"Unit of Measure (Unit of Measure) is the unit of measurement for the " +"inventory control" +msgstr "" #. module: mrp #: report:bom.structure:0 msgid "Product Name" -msgstr "Nombre producto" - -#. module: mrp -#: code:addons/mrp/mrp.py:495 -#, python-format -msgid "Invalid action !" -msgstr "¡Acción no válida!" +msgstr "" #. module: mrp #: help:mrp.bom,product_efficiency:0 msgid "A factor of 0.9 means a loss of 10% within the production process." msgstr "" -"Un factor de 0.9 indica una pérdida del 10% en el proceso de producción." #. module: mrp -#: view:mrp.installer:0 -msgid "" -"Add more functionalities to the core Manufacturing Application with the " -"following addons." +#: code:addons/mrp/mrp.py:737 +#: code:addons/mrp/mrp.py:765 +#, python-format +msgid "Warning!" msgstr "" -"Añada más funcionalidades en el núcleo de la aplicación de fabricación con " -"los siguientes módulos." #. module: mrp #: report:mrp.production.order:0 msgid "Printing date" -msgstr "Fecha impresión" +msgstr "" #. module: mrp #: model:process.node,name:mrp.process_node_orderrfq0 #: model:process.node,name:mrp.process_node_rfq0 msgid "RFQ" -msgstr "Petición presupuesto" +msgstr "" #. module: mrp #: model:process.transition,name:mrp.process_transition_producttostockrules0 msgid "Procurement rule" -msgstr "Regla de abastecimiento" +msgstr "" #. module: mrp -#: help:mrp.workcenter,costs_hour:0 -msgid "Specify Cost of Work center per hour." -msgstr "Especificar costes del centro de trabajo por hora." +#: help:mrp.workcenter,costs_cycle_account_id:0 +#: help:mrp.workcenter,costs_hour_account_id:0 +msgid "" +"Fill this only if you want automatic analytic accounting entries on " +"production orders." +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Mark as Started" +msgstr "" #. module: mrp #: view:mrp.production:0 msgid "Partial" -msgstr "Parcial" - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "September" -msgstr "Septiembre" +msgstr "" #. module: mrp #: report:mrp.production.order:0 msgid "WorkCenter" -msgstr "Centro de producción" +msgstr "" #. module: mrp #: model:process.transition,note:mrp.process_transition_procureserviceproduct0 @@ -836,188 +839,282 @@ msgid "" "order creates a RFQ for a subcontracting purchase order or waits until the " "service is done (= the delivery of the products)." msgstr "" -"Dependiendo del método elegido para \"suministrar\" del servicio, la orden " -"de abastecimiento crea una solicitud de presupuesto para un pedido de compra " -"(subcontratación) o espera hasta que el servicio se realice (= la entrega de " -"los productos)." #. module: mrp #: selection:mrp.production,priority:0 -#: selection:mrp.production.order,priority:0 msgid "Urgent" -msgstr "Urgente" +msgstr "" #. module: mrp -#: model:ir.model,name:mrp.model_mrp_routing_workcenter -msgid "Work Center Usage" +#: view:mrp.production:0 +msgid "Manufacturing Orders which are waiting for raw materials." +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:285 +#, python-format +msgid "" +"The Product Unit of Measure you chose has a different category than in the " +"product form." msgstr "" #. module: mrp #: model:ir.model,name:mrp.model_mrp_production +#: view:mrp.config.settings:0 +#: view:mrp.production:0 +#: field:mrp.production.workcenter.line,production_id:0 +#: field:procurement.order,production_id:0 msgid "Manufacturing Order" -msgstr "Órden de producción" +msgstr "" #. module: mrp #: model:process.transition,name:mrp.process_transition_productionprocureproducts0 msgid "Procurement of raw material" -msgstr "Abastecimiento de materias primas" +msgstr "" #. module: mrp -#: help:mrp.routing.workcenter,hour_nbr:0 +#: sql_constraint:mrp.bom:0 msgid "" -"Time in hours for this work center to achieve the operation of the specified " -"routing." +"All product quantities must be greater than 0.\n" +"You should install the mrp_byproduct module if you want to manage extra " +"products on BoMs !" msgstr "" -"Tiempo en horas para este centro de producción para realizar la operación de " -"la ruta indicada." #. module: mrp #: view:mrp.production:0 #: field:mrp.production,cycle_total:0 msgid "Total Cycles" -msgstr "Total ciclos" +msgstr "" #. module: mrp #: selection:mrp.production,state:0 -#: view:mrp.production.order:0 -#: selection:mrp.production.order,state:0 msgid "Ready to Produce" -msgstr "Listo para producir" +msgstr "" #. module: mrp -#: field:mrp.bom.revision,name:0 -msgid "Modification name" -msgstr "Nombre de modificación" +#: field:mrp.bom,message_is_follower:0 +#: field:mrp.production,message_is_follower:0 +#: field:mrp.production.workcenter.line,message_is_follower:0 +msgid "Is a Follower" +msgstr "" #. module: mrp #: view:mrp.bom:0 #: view:mrp.production:0 -#: field:mrp.production.order,date:0 msgid "Date" -msgstr "Fecha" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,help:mrp.mrp_production_action_planning +msgid "" +"

\n" +" Click to start a new manufacturing order. \n" +"

\n" +" A manufacuring order, based on a bill of materials, will\n" +" consume raw materials and produce finished products.\n" +"

\n" +" Manufacturing orders are usually proposed automatically " +"based\n" +" on customer requirements or automated rules like the " +"minimum\n" +" stock rule.\n" +"

\n" +" " +msgstr "" #. module: mrp #: field:mrp.bom,type:0 msgid "BoM Type" -msgstr "Tipo de lista de materiales" +msgstr "" #. module: mrp -#: view:mrp.production.order:0 -msgid "Extended Filters..." -msgstr "Filtros extendidos..." - -#. module: mrp -#: code:addons/mrp/procurement.py:47 +#: code:addons/mrp/procurement.py:52 #, python-format msgid "" "Procurement '%s' has an exception: 'No BoM defined for this product !'" msgstr "" -"Abastecimiento '%s' tiene una excepción: 'El producto no tiene LdM definida!'" #. module: mrp -#: view:mrp.production.order:0 #: view:mrp.property:0 msgid "Search" -msgstr "Buscar" +msgstr "" #. module: mrp -#: field:report.workcenter.load,cycle:0 -msgid "Nbr of cycle" -msgstr "Núm. de ciclo" +#: model:process.node,note:mrp.process_node_billofmaterial0 +msgid "Product's structure" +msgstr "" #. module: mrp #: model:ir.model,name:mrp.model_res_company msgid "Companies" -msgstr "Compañías" +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:634 +#, python-format +msgid "" +"You must first cancel related internal picking attached to this " +"manufacturing order." +msgstr "" #. module: mrp #: model:process.node,name:mrp.process_node_minimumstockrule0 #: model:process.node,name:mrp.process_node_productminimumstockrule0 msgid "Minimum Stock" -msgstr "Stock mínimo" +msgstr "" #. module: mrp -#: model:ir.ui.menu,name:mrp.menus_dash_mrp -msgid "Dashboard" -msgstr "Tablero" - -#. module: mrp -#: view:board.board:0 -msgid "Work Center Future Load" -msgstr "Carga futura del centro de producción" +#: code:addons/mrp/report/price.py:160 +#: code:addons/mrp/report/price.py:211 +#, python-format +msgid "Total Cost of %s %s" +msgstr "" #. module: mrp #: model:process.node,name:mrp.process_node_stockproduct0 #: model:process.node,name:mrp.process_node_stockproduct1 #: model:process.process,name:mrp.process_process_stockableproductprocess0 msgid "Stockable Product" -msgstr "Producto almacenable" +msgstr "" #. module: mrp -#: code:addons/mrp/report/price.py:121 +#: code:addons/mrp/report/price.py:130 #, python-format msgid "Work Center name" -msgstr "Nombre del centro de producción" +msgstr "" #. module: mrp #: field:mrp.routing,code:0 msgid "Code" -msgstr "Código" +msgstr "" #. module: mrp #: report:mrp.production.order:0 msgid "No. Of Hours" -msgstr "Núm. de horas" - -#. module: mrp -#: field:mrp.installer,mrp_jit:0 -msgid "Just In Time Scheduling" -msgstr "Planificación 'Just in Time'" +msgstr "" #. module: mrp #: view:mrp.property:0 -#: view:mrp.property.group:0 msgid "Property Group" -msgstr "Grupo de propiedad" +msgstr "" #. module: mrp -#: view:mrp.production:0 -msgid "Qty" -msgstr "Ctd." +#: field:mrp.config.settings,group_mrp_routings:0 +msgid "Manage routings and work orders " +msgstr "" #. module: mrp #: model:process.node,note:mrp.process_node_production0 msgid "Manufacturing Plan." -msgstr "Plan de producción" +msgstr "" #. module: mrp #: view:mrp.routing:0 #: view:mrp.workcenter:0 msgid "Inactive" -msgstr "Inactivo" - -#. module: mrp -#: help:mrp.installer,mrp_subproduct:0 -msgid "" -"Enables multiple product output from a single production order: without " -"this, a production order can have only one output product." msgstr "" -"Habilita la salida de múltiples productos de una sola orden de producción: " -"sin ello, una orden de producción sólo puede tener un producto de salida." #. module: mrp #: view:change.production.qty:0 +#: view:mrp.config.settings:0 #: view:mrp.product.produce:0 #: view:mrp.product_price:0 -#: view:mrp.production:0 #: view:mrp.workcenter.load:0 msgid "Cancel" -msgstr "Cancelar" +msgstr "" + +#. module: mrp +#: model:process.transition,note:mrp.process_transition_servicerfq0 +msgid "" +"If the service has a 'Buy' supply method, this creates a RFQ, a " +"subcontracting demand for instance." +msgstr "" #. module: mrp #: view:mrp.production:0 -msgid "Split in production lots" -msgstr "Dividir en lotes de producción" +msgid "Late" +msgstr "" + +#. module: mrp +#: model:process.node,name:mrp.process_node_servicemts0 +msgid "Make to stock" +msgstr "" + +#. module: mrp +#: report:bom.structure:0 +msgid "BOM Name" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.act_product_manufacturing_open +#: model:ir.actions.act_window,name:mrp.mrp_production_action +#: model:ir.actions.act_window,name:mrp.mrp_production_action_planning +#: model:ir.ui.menu,name:mrp.menu_mrp_production_action +#: view:mrp.production:0 +msgid "Manufacturing Orders" +msgstr "" + +#. module: mrp +#: selection:mrp.production,state:0 +msgid "Awaiting Raw Materials" +msgstr "" + +#. module: mrp +#: field:mrp.bom,position:0 +msgid "Internal Reference" +msgstr "" + +#. module: mrp +#: field:mrp.production,product_uos_qty:0 +msgid "Product UoS Quantity" +msgstr "" + +#. module: mrp +#: field:mrp.bom,name:0 +#: report:mrp.production.order:0 +#: field:mrp.production.product.line,name:0 +#: view:mrp.property:0 +#: field:mrp.routing,name:0 +#: field:mrp.routing.workcenter,name:0 +msgid "Name" +msgstr "" + +#. module: mrp +#: report:mrp.production.order:0 +msgid "Production Order N° :" +msgstr "" + +#. module: mrp +#: field:mrp.product.produce,mode:0 +msgid "Mode" +msgstr "" + +#. module: mrp +#: help:mrp.bom,message_ids:0 +#: help:mrp.production,message_ids:0 +#: help:mrp.production.workcenter.line,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: mrp +#: field:mrp.workcenter.load,measure_unit:0 +msgid "Amount measuring unit" +msgstr "" + +#. module: mrp +#: help:mrp.config.settings,module_mrp_jit:0 +msgid "" +"This allows Just In Time computation of procurement orders.\n" +" All procurement orders will be processed immediately, which " +"could in some\n" +" cases entail a small performance impact.\n" +" This installs the module mrp_jit." +msgstr "" + +#. module: mrp +#: help:mrp.workcenter,costs_hour:0 +msgid "Specify Cost of Work Center per hour." +msgstr "" #. module: mrp #: help:mrp.workcenter,capacity_per_cycle:0 @@ -1026,1257 +1123,140 @@ msgid "" "Center represents a team of 5 workers, the capacity per cycle is 5." msgstr "" -#. module: mrp -#: model:process.transition,note:mrp.process_transition_servicerfq0 -msgid "" -"If the service has a 'Buy' supply method, this creates a RFQ, a " -"subcontracting demand for instance." -msgstr "" -"Si el servicio tiene un método de suministro 'Comprar', se crea una " -"solicitud de presupuesto, por ejemplo, una petición de subcontratación." - -#. module: mrp -#: field:mrp.production,move_prod_id:0 -msgid "Move product" -msgstr "Movimiento producto" - -#. module: mrp -#: view:mrp.production:0 -msgid "Late" -msgstr "Retrasado" - -#. module: mrp -#: model:process.node,name:mrp.process_node_servicemts0 -msgid "Make to stock" -msgstr "Obtener para stock" - -#. module: mrp -#: help:mrp.routing.workcenter,sequence:0 -msgid "" -"Gives the sequence order when displaying a list of routing work centers." -msgstr "" -"Proporciona el orden de secuencias cuando se muestra una lista de " -"enrutamiento de los centros de trabajo." - -#. module: mrp -#: report:bom.structure:0 -msgid "BOM Name" -msgstr "Nombre LdM" - -#. module: mrp -#: view:mrp.production:0 -msgid "Start Production" -msgstr "Empezar producción" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.open_board_manufacturing -#: model:ir.ui.menu,name:mrp.menu_board_manufacturing -msgid "Production Dashboard" -msgstr "Tablero de producción" - -#. module: mrp -#: view:mrp.production:0 -msgid "Source Loc." -msgstr "Ubic. orígen" - -#. module: mrp -#: field:mrp.bom,position:0 -msgid "Internal Reference" -msgstr "Referencia interna" - -#. module: mrp -#: help:mrp.installer,stock_location:0 -msgid "" -"Manages product routes and paths within and between locations (e.g. " -"warehouses)." -msgstr "" -"Gestiona las rutas y caminos de los productos dentro y entre las ubicaciones " -"(por ejemplo, almacenes)." - -#. module: mrp -#: model:process.node,note:mrp.process_node_billofmaterial0 -msgid "Product's structure" -msgstr "Estructura de producto" - -#. module: mrp -#: field:mrp.bom,name:0 -#: report:mrp.production.order:0 -#: field:mrp.production.product.line,name:0 -#: field:mrp.routing,name:0 -#: field:mrp.routing.workcenter,name:0 -msgid "Name" -msgstr "Nombre" - -#. module: mrp -#: view:mrp.installer:0 -msgid "MRP Application Configuration" -msgstr "Configuración aplicación MRP" - -#. module: mrp -#: help:mrp.installer,mrp_jit:0 -msgid "" -"Enables Just In Time computation of procurement orders.\n" -"\n" -"While it's more resource intensive than the default setup, the JIT computer " -"avoids having to wait for the procurement scheduler to run or having to run " -"the procurement scheduler manually." -msgstr "" -"Permite el cálculo de las órdenes de abastecimiento justo a tiempo (Just In " -"Time).\n" -"\n" -"Si bien consume más recursos que la configuración predeterminada, el cálculo " -"JIT evita tener que esperar a que se ejecute el planificador de " -"abastecimientos o tener que ejecutar el planificador de abastecimientos de " -"forma manual." - -#. module: mrp -#: field:mrp.product.produce,mode:0 -msgid "Mode" -msgstr "Modo" - -#. module: mrp -#: report:bom.structure:0 -msgid "]" -msgstr "]" - -#. module: mrp -#: field:mrp.workcenter.load,measure_unit:0 -msgid "Amount measuring unit" -msgstr "Importe unidad de medida" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_production_action_planning -msgid "" -"Manufacturing Orders describe the operations that need to be carried out and " -"the raw materials usage for each production stage. You use specifications " -"(bills of materials or BoM) to work out the raw material requirements and " -"the manufacturing orders needed for the finished products. Once the bills of " -"materials have been defined, OpenERP is capable of automatically deciding on " -"the manufacturing route depending on the needs of the company." -msgstr "" -"Las órdenes de fabricación describen las operaciones que deben ser " -"realizadas y las materias primas necesarias para cada etapa de fabricación. " -"Utilice las especificaciones (listas de materiales o LdM) para obtener las " -"necesidades de materias primas y las órdenes de fabricación necesarias para " -"los productos finales. Una vez las listas de materiales hayan sido " -"definidas, OpenERP es capz de decidir automáticamente al ruta de fabricación " -"en función de las necesidades de la compañía." - -#. module: mrp -#: constraint:mrp.production:0 -msgid "Order quantity cannot be negative or zero !" -msgstr "¡Cantidad ordenada no puede ser negativa o cero!" - #. module: mrp #: model:ir.actions.act_window,name:mrp.mrp_production_action3 msgid "Manufacturing Orders in Progress" -msgstr "Órdenes de producción en progreso" +msgstr "" #. module: mrp -#: model:ir.module.module,description:mrp.module_meta_information -msgid "" -"\n" -" This is the base module to manage the manufacturing process in OpenERP.\n" -"\n" -" Features:\n" -" * Make to Stock / Make to Order (by line)\n" -" * Multi-level BoMs, no limit\n" -" * Multi-level routing, no limit\n" -" * Routing and work center integrated with analytic accounting\n" -" * Scheduler computation periodically / Just In Time module\n" -" * Multi-pos, multi-warehouse\n" -" * Different reordering policies\n" -" * Cost method by product: standard price, average price\n" -" * Easy analysis of troubles or needs\n" -" * Very flexible\n" -" * Allows to browse Bill of Materials in complete structure\n" -" that include child and phantom BoMs\n" -" It supports complete integration and planification of stockable goods,\n" -" consumable of services. Services are completely integrated with the " -"rest\n" -" of the software. For instance, you can set up a sub-contracting service\n" -" in a BoM to automatically purchase on order the assembly of your " -"production.\n" -"\n" -" Reports provided by this module:\n" -" * Bill of Material structure and components\n" -" * Load forecast on Work Centers\n" -" * Print a production order\n" -" * Stock forecasts\n" -" Dashboard provided by this module::\n" -" * List of next production orders\n" -" * List of deliveries (out picking)\n" -" * Graph of work center load\n" -" * List of procurement in exception\n" -" " +#: model:ir.actions.client,name:mrp.action_client_mrp_menu +msgid "Open MRP Menu" msgstr "" #. module: mrp #: model:ir.actions.act_window,name:mrp.mrp_production_action4 msgid "Manufacturing Orders Waiting Products" -msgstr "Órdenes de producción en espera de productos" +msgstr "" #. module: mrp #: view:mrp.bom:0 #: view:mrp.production:0 -#: view:mrp.production.order:0 #: view:mrp.property:0 #: view:mrp.routing:0 #: view:mrp.workcenter:0 msgid "Group By..." -msgstr "Agrupar por..." +msgstr "" #. module: mrp -#: code:addons/mrp/report/price.py:121 +#: code:addons/mrp/report/price.py:130 #, python-format msgid "Cycles Cost" -msgstr "Coste ciclos" +msgstr "" + +#. module: mrp +#: code:addons/mrp/wizard/change_production_qty.py:83 +#: code:addons/mrp/wizard/change_production_qty.py:88 +#, python-format +msgid "Cannot find bill of material for this product." +msgstr "" #. module: mrp #: selection:mrp.workcenter.load,measure_unit:0 msgid "Amount in cycles" -msgstr "Valor en ciclos" +msgstr "" #. module: mrp #: field:mrp.production,location_dest_id:0 -#: view:mrp.production.order:0 -#: field:mrp.production.order,location_dest_id:0 msgid "Finished Products Location" -msgstr "Ubicación productos finalizados" +msgstr "" #. module: mrp #: model:ir.ui.menu,name:mrp.menu_pm_resources_config msgid "Resources" -msgstr "Recursos" +msgstr "" + +#. module: mrp +#: help:mrp.routing.workcenter,hour_nbr:0 +msgid "" +"Time in hours for this Work Center to achieve the operation of the specified " +"routing." +msgstr "" #. module: mrp #: field:mrp.workcenter,costs_journal_id:0 msgid "Analytic Journal" -msgstr "Diario analítico" +msgstr "" #. module: mrp -#: model:ir.actions.act_window,name:mrp.mrp_workcenter_action -#: model:ir.ui.menu,name:mrp.menu_view_resource_search_mrp -#: field:mrp.routing,workcenter_lines:0 -msgid "Work Centers" -msgstr "Centros de producción" +#: code:addons/mrp/report/price.py:139 +#, python-format +msgid "Supplier Price per Unit of Measure" +msgstr "" #. module: mrp #: selection:mrp.workcenter.load,time_unit:0 msgid "Per week" -msgstr "Por semana" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_routing_action -msgid "" -"Routings allow you to create and manage the manufacturing operations that " -"should be followed within your work centers in order to produce a product. " -"They are attached to bills of materials that will define the required raw " -"materials." msgstr "" -"Las rutas le permiten crear y gestionar las operaciones de fabricación a " -"realizar en sus centros de producción para fabricar un producto. Están " -"relacionadas con las listas de materiales que definirán las materias primas " -"necesarias." #. module: mrp -#: field:report.workcenter.load,hour:0 -msgid "Nbr of hour" -msgstr "Núm. de hora" +#: field:mrp.bom,message_unread:0 +#: field:mrp.production,message_unread:0 +#: field:mrp.production.workcenter.line,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: mrp +#: model:process.transition,note:mrp.process_transition_stockmts0 +msgid "" +"The system waits for the products to be available in the stock. These " +"products are typically procured manually or through a minimum stock rule." +msgstr "" #. module: mrp #: view:mrp.routing:0 msgid "Work Center Operations" -msgstr "Operaciones del centro de producción" +msgstr "" #. module: mrp #: view:mrp.routing:0 msgid "Notes" -msgstr "Notas" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Manufacturing Orders which are ready to start production." +msgstr "" #. module: mrp #: model:ir.model,name:mrp.model_mrp_bom #: view:mrp.bom:0 #: field:mrp.production,bom_id:0 -#: field:mrp.production.order,bom_id:0 #: model:process.node,name:mrp.process_node_billofmaterial0 msgid "Bill of Material" -msgstr "Lista de material" +msgstr "" #. module: mrp #: view:mrp.workcenter.load:0 msgid "Select time unit" -msgstr "Seleccionar unidad de tiempo" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.product_supply_method_produce +#: model:ir.ui.menu,name:mrp.menu_mrp_bom +#: model:ir.ui.menu,name:mrp.menu_mrp_product_form +#: view:mrp.config.settings:0 +msgid "Products" +msgstr "" #. module: mrp #: view:report.workcenter.load:0 msgid "Work Center load" -msgstr "Carga centro de producción" +msgstr "" #. module: mrp #: help:mrp.production,location_dest_id:0 msgid "Location where the system will stock the finished products." -msgstr "Ubicación donde el sistema almacenará los productos finalizados." - -#. module: mrp -#: help:mrp.production,picking_id:0 -msgid "" -"This is the Internal Picking List that brings the finished product to the " -"production plan" msgstr "" -"Este es el albarán interno que trae el producto terminado hacia el plan de " -"producción." - -#. module: mrp -#: field:stock.change.standard.price,change_parent_price:0 -msgid "Change Parent Price" -msgstr "Cambiar precio padre" - -#. module: mrp -#: model:ir.model,name:mrp.model_stock_move -msgid "Stock Move" -msgstr "Moviemiento de stock" - -#. module: mrp -#: model:process.transition,note:mrp.process_transition_producttostockrules0 -msgid "" -"The Minimum Stock Rule is an automatic procurement rule based on a mini and " -"maxi quantity. It's available in the Inventory management menu and " -"configured by product." -msgstr "" -"La regla de stock mínimo es una regla de abastecimiento automático basado en " -"una cantidad mínima y máxima. Está disponible en el menú de gestión de " -"inventario y configurable por producto." - -#. module: mrp -#: selection:mrp.workcenter.load,time_unit:0 -msgid "Day by day" -msgstr "Día por día" - -#. module: mrp -#: view:mrp.bom:0 -msgid "Revisions" -msgstr "Revisiones" - -#. module: mrp -#: view:mrp.installer:0 -msgid "Configure Your Manufacturing Resource Planning Application" -msgstr "" -"Configure su aplicación de planificación de recursos de fabricación (MRP)" - -#. module: mrp -#: field:mrp.production,priority:0 -#: field:mrp.production.order,priority:0 -msgid "Priority" -msgstr "Prioridad" - -#. module: mrp -#: model:ir.model,name:mrp.model_stock_picking -msgid "Picking List" -msgstr "Albarán" - -#. module: mrp -#: view:mrp.production.order:0 -msgid "Month -1" -msgstr "Mes -1" - -#. module: mrp -#: code:addons/mrp/mrp.py:924 -#, python-format -msgid "Manufacturing order '%s' is scheduled for the %s." -msgstr "Órden de producción '%s' planificada para el '%s'" - -#. module: mrp -#: report:mrp.production.order:0 -msgid "Production Order N° :" -msgstr "Núm. orden producción :" - -#. module: mrp -#: code:addons/mrp/mrp.py:640 -#, python-format -msgid "Manufacturing order '%s' is ready to produce." -msgstr "Orden fabricación '%s' está preparada para producir." - -#. module: mrp -#: model:ir.model,name:mrp.model_mrp_production_product_line -msgid "Production Scheduled Product" -msgstr "Fabricación planificada producto" - -#. module: mrp -#: help:res.company,manufacturing_lead:0 -msgid "Security days for each manufacturing operation." -msgstr "Días de seguridad para cada operación de fabricación." - -#. module: mrp -#: model:process.node,name:mrp.process_node_mts0 -#: model:process.transition,name:mrp.process_transition_servicemts0 -#: model:process.transition,name:mrp.process_transition_stockmts0 -msgid "Make to Stock" -msgstr "Obtener para stock" - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "July" -msgstr "Julio" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_bom_form_action -msgid "" -"Master Bills of Materials allow you to create and manage the list of " -"necessary raw materials used to make a finished product. OpenERP will use " -"these BoMs to automatically propose manufacturing orders according to " -"product needs. You can either create a bill of materials to define specific " -"production steps or define a single multi-level bill of materials." -msgstr "" -"Las listas de materiales maestras le permiten crear y gestionar la lista de " -"las materias primas necesarias utilizadas para fabricar un producto acabado. " -"OpenERP utilizará estas LdMs para proponer automáticamente órdenes de " -"fabricación en función de las necesidades de producto. Puede crear una lista " -"de materiales para definir los pasos de producción o definir una única lista " -"de materiales multi-nivel." - -#. module: mrp -#: model:process.transition,note:mrp.process_transition_stockrfq0 -msgid "" -"In case the Supply method of the product is Buy, the system creates a " -"purchase order." -msgstr "" -"En caso de que el método de suministro del producto se Compra, el sistema " -"crea un pedido de compra." - -#. module: mrp -#: model:ir.model,name:mrp.model_procurement_order -msgid "Procurement" -msgstr "Abastecimiento" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.action_view_mrp_product_price_wizard -#: view:mrp.product_price:0 -msgid "Product Cost Structure" -msgstr "Estructura de los costes del producto" - -#. module: mrp -#: code:addons/mrp/report/price.py:130 -#, python-format -msgid "Components suppliers" -msgstr "Proveedores de componentes" - -#. module: mrp -#: model:ir.model,name:mrp.model_mrp_installer -msgid "mrp.installer" -msgstr "mrp.instalador" - -#. module: mrp -#: view:mrp.production:0 -msgid "Production Work Centers" -msgstr "Centros de trabajo de producción" - -#. module: mrp -#: view:mrp.production.order:0 -#: field:mrp.production.order,month:0 -msgid "Month" -msgstr "Mes" - -#. module: mrp -#: code:addons/mrp/wizard/change_production_qty.py:62 -#, python-format -msgid "Active Id is not found" -msgstr "ID activo no se encuentra" - -#. module: mrp -#: view:mrp.workcenter:0 -msgid "Search for mrp workcenter" -msgstr "Buscar por centro de producción mrp" - -#. module: mrp -#: view:mrp.bom:0 -msgid "BoM Structure" -msgstr "Despiece de la LdM" - -#. module: mrp -#: field:mrp.production,date_start:0 -#: field:mrp.production.order,date_start:0 -msgid "Start Date" -msgstr "Fecha inicial" - -#. module: mrp -#: field:mrp.workcenter,costs_hour_account_id:0 -msgid "Hour Account" -msgstr "Cuenta horas" - -#. module: mrp -#: view:mrp.production:0 -msgid "Destination Loc." -msgstr "Ubic. destino" - -#. module: mrp -#: field:mrp.production.order,product_id2:0 -msgid "Product Consumed" -msgstr "Producto consumido" - -#. module: mrp -#: view:mrp.production:0 -msgid "Pending" -msgstr "Pendiente" - -#. module: mrp -#: field:mrp.bom,active:0 -#: field:mrp.routing,active:0 -msgid "Active" -msgstr "Activo" - -#. module: mrp -#: model:process.node,name:mrp.process_node_procureproducts0 -msgid "Procure Products" -msgstr "Abastecer productos" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.action_report_workcenter_load_tree -#: view:report.workcenter.load:0 -msgid "Work Center Loads" -msgstr "Cargas centro de producción" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.mrp_property_action -#: model:ir.ui.menu,name:mrp.menu_mrp_property_action -#: view:mrp.bom:0 -#: field:mrp.bom,property_ids:0 -#: view:mrp.property:0 -#: view:procurement.order:0 -#: field:procurement.order,property_ids:0 -msgid "Properties" -msgstr "Propiedades" - -#. module: mrp -#: help:mrp.production,origin:0 -msgid "" -"Reference of the document that generated this production order request." -msgstr "" -"Referencia al documento que generó esta solicitud de orden de producción." - -#. module: mrp -#: sql_constraint:mrp.bom:0 -msgid "" -"All product quantities must be greater than 0.\n" -"You should install the mrp_subproduct module if you want to manage extra " -"products on BoMs !" -msgstr "" -"Todas las cantidades de producto deben de ser superiores a cero.\n" -"¡Debe instalar el módulo mrp_subproduct si quiere gestionar productos extra " -"en las LdM!" - -#. module: mrp -#: view:mrp.production:0 -msgid "Extra Information" -msgstr "Información extra" - -#. module: mrp -#: model:ir.model,name:mrp.model_change_production_qty -msgid "Change Quantity of Products" -msgstr "Cambiar cantidad de productos" - -#. module: mrp -#: model:process.node,note:mrp.process_node_productionorder0 -msgid "Drives the procurement orders for raw material." -msgstr "Guía las órdenes de abastecimiento para materias primas." - -#. module: mrp -#: view:mrp.production.order:0 -msgid "Current" -msgstr "Actual" - -#. module: mrp -#: field:mrp.workcenter,costs_general_account_id:0 -msgid "General Account" -msgstr "Cuenta general" - -#. module: mrp -#: report:mrp.production.order:0 -msgid "SO Number" -msgstr "Número venta" - -#. module: mrp -#: selection:mrp.production,state:0 -#: view:mrp.production.order:0 -#: selection:mrp.production.order,state:0 -msgid "Done" -msgstr "Realizado" - -#. module: mrp -#: model:ir.model,name:mrp.model_stock_change_standard_price -msgid "Change Standard Price" -msgstr "Cambio de precio estándar" - -#. module: mrp -#: field:mrp.production,origin:0 -#: report:mrp.production.order:0 -#: field:mrp.production.order,origin:0 -msgid "Source Document" -msgstr "Documento origen" - -#. module: mrp -#: selection:mrp.production,priority:0 -#: selection:mrp.production.order,priority:0 -msgid "Not urgent" -msgstr "No urgente" - -#. module: mrp -#: help:stock.change.standard.price,change_parent_price:0 -msgid "" -"This will change the price of parent products also according to the BoM " -"structure specified for the product." -msgstr "" -"Esto cambiará el precio de los productos padre de acuerdo a la estructura de " -"la lista de materiales del producto." - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.mrp_production_action2 -msgid "Manufacturing Orders To Start" -msgstr "Órdenes de producción a iniciar" - -#. module: mrp -#: code:addons/mrp/mrp.py:495 -#, python-format -msgid "Cannot delete Production Order(s) which are in %s State!" -msgstr "" -"¡No se puede eliminar orden(es) de producción que están en estado %s!" - -#. module: mrp -#: model:ir.model,name:mrp.model_mrp_workcenter -#: field:mrp.production.workcenter.line,workcenter_id:0 -#: field:mrp.routing.workcenter,workcenter_id:0 -#: view:mrp.workcenter:0 -#: field:report.workcenter.load,workcenter_id:0 -msgid "Work Center" -msgstr "Centro de producción" - -#. module: mrp -#: field:mrp.workcenter,capacity_per_cycle:0 -msgid "Capacity per Cycle" -msgstr "Capacidad por ciclo" - -#. module: mrp -#: model:ir.model,name:mrp.model_product_product -#: view:mrp.bom:0 -#: field:mrp.bom,product_id:0 -#: view:mrp.production:0 -#: field:mrp.production,product_id:0 -#: report:mrp.production.order:0 -#: view:mrp.production.order:0 -#: field:mrp.production.order,product_id:0 -#: field:mrp.production.product.line,product_id:0 -msgid "Product" -msgstr "Producto" - -#. module: mrp -#: view:mrp.production:0 -#: field:mrp.production,hour_total:0 -msgid "Total Hours" -msgstr "Total horas" - -#. module: mrp -#: field:mrp.production,location_src_id:0 -#: field:mrp.production.order,location_src_id:0 -msgid "Raw Materials Location" -msgstr "Ubicación materias primas" - -#. module: mrp -#: view:mrp.product_price:0 -msgid "Print Cost Structure of Product." -msgstr "Imprimir la estructura de costes del producto" - -#. module: mrp -#: field:mrp.bom,product_uos:0 -#: field:mrp.production.product.line,product_uos:0 -msgid "Product UOS" -msgstr "UdV del producto" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_workcenter_action -msgid "" -"Work Centers allow you to create and manage manufacturing units consisting " -"of one or more persons and/or machines that can be considered as a unit for " -"capacity and planning forecasting." -msgstr "" -"Los centros de trabajo le permiten crear y administrar unidades de " -"producción que consisten en una o más personas y / o máquinas que se pueden " -"considerar como una unidad para la capacidad de planificación y previsión." - -#. module: mrp -#: view:mrp.production:0 -msgid "Consume Products" -msgstr "Consumir productos" - -#. module: mrp -#: field:mrp.bom,product_uom:0 -#: field:mrp.production,product_uom:0 -#: field:mrp.production.order,product_uom:0 -#: field:mrp.production.product.line,product_uom:0 -msgid "Product UOM" -msgstr "UdM del producto" - -#. module: mrp -#: model:process.node,name:mrp.process_node_stock0 -#: model:process.transition,name:mrp.process_transition_servicemto0 -#: model:process.transition,name:mrp.process_transition_stockproduct0 -msgid "Make to Order" -msgstr "Obtener bajo pedido" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.action_report_mrp_production_order -#: model:ir.ui.menu,name:mrp.menu_report_mrp_production_orders_tree -msgid "Production Analysis" -msgstr "Análisis de producción" - -#. module: mrp -#: code:addons/mrp/mrp.py:349 -#, python-format -msgid "Copy" -msgstr "Copiar" - -#. module: mrp -#: view:mrp.production.lot.line:0 -msgid "Production Products" -msgstr "Productos producidos" - -#. module: mrp -#: field:mrp.production,date_finished:0 -#: field:mrp.production.order,date_finished:0 -msgid "End Date" -msgstr "Fecha final" - -#. module: mrp -#: field:mrp.workcenter,resource_id:0 -msgid "Resource" -msgstr "Recurso" - -#. module: mrp -#: help:mrp.bom,date_start:0 -#: help:mrp.bom,date_stop:0 -msgid "Validity of this BoM or component. Keep empty if it's always valid." -msgstr "" -"Validez de esta LdM o componente. Dejarlo vacío si siempre es válido." - -#. module: mrp -#: field:mrp.production,product_uos:0 -msgid "Product UoS" -msgstr "UdV del producto" - -#. module: mrp -#: view:mrp.production.order:0 -msgid "#Line Orders" -msgstr "Nº línea órdenes" - -#. module: mrp -#: selection:mrp.production,priority:0 -#: selection:mrp.production.order,priority:0 -msgid "Very Urgent" -msgstr "Muy urgente" - -#. module: mrp -#: help:mrp.bom,routing_id:0 -msgid "" -"The list of operations (list of work centers) to produce the finished " -"product. The routing is mainly used to compute work center costs during " -"operations and to plan future loads on work centers based on production " -"planning." -msgstr "" -"La lista de operaciones (lista de los centros de trabajo) para producir los " -"productos terminados. La ruta se utiliza principalmente para calcular los " -"costes del centro de trabajo durante las operaciones de carga y planificar " -"el futuro en los centros de trabajo basado en la planificación de la " -"producción." - -#. module: mrp -#: view:change.production.qty:0 -msgid "Approve" -msgstr "Aprobar" - -#. module: mrp -#: view:mrp.property.group:0 -msgid "Properties categories" -msgstr "Categorías de propiedades" - -#. module: mrp -#: help:mrp.production.workcenter.line,sequence:0 -msgid "Gives the sequence order when displaying a list of work orders." -msgstr "" -"Indica el orden de secuencia cuando se muestra una lista de órdenes de " -"trabajo." - -#. module: mrp -#: report:mrp.production.order:0 -msgid "Source Location" -msgstr "Ubicación origen" - -#. module: mrp -#: view:mrp.production:0 -#: view:mrp.production.product.line:0 -msgid "Scheduled Products" -msgstr "Productos planificados" - -#. module: mrp -#: view:mrp.production.lot.line:0 -msgid "Production Products Consommation" -msgstr "Consumición de productos producidos" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.mrp_production_action -#: model:ir.actions.act_window,name:mrp.mrp_production_action_planning -#: model:ir.ui.menu,name:mrp.menu_mrp_production_action -#: model:ir.ui.menu,name:mrp.menu_mrp_production_order_action -#: view:mrp.production:0 -msgid "Manufacturing Orders" -msgstr "Órdenes de producción" - -#. module: mrp -#: help:mrp.product.produce,mode:0 -msgid "" -"'Consume only' mode will only consume the products with the quantity " -"selected.\n" -"'Consume & Produce' mode will consume as well as produce the products with " -"the quantity selected and it will finish the production order when total " -"ordered quantities are produced." -msgstr "" -"El modo 'Sólo consumir' sólo se consumen los productos con la cantidad " -"seleccionada.\n" -"El modo 'Consumo y Producción' se consumen y también se producen los " -"productos con la cantidad seleccionada y finalizará la orden de producción " -"cuando el total de las cantidades solicitadas se han producido." - -#. module: mrp -#: view:mrp.production:0 -#: report:mrp.production.order:0 -msgid "Work Orders" -msgstr "Órdenes de trabajo" - -#. module: mrp -#: field:mrp.workcenter,costs_cycle:0 -msgid "Cost per cycle" -msgstr "Coste por ciclo" - -#. module: mrp -#: model:process.node,name:mrp.process_node_serviceproduct0 -#: model:process.node,name:mrp.process_node_serviceproduct1 -msgid "Service" -msgstr "Servicio" - -#. module: mrp -#: selection:mrp.production,state:0 -#: selection:mrp.production.order,state:0 -msgid "Cancelled" -msgstr "Cancelado" - -#. module: mrp -#: view:mrp.production.order:0 -msgid "BOM" -msgstr "LdM" - -#. module: mrp -#: help:mrp.bom,product_uom:0 -msgid "" -"UoM (Unit of Measure) is the unit of measurement for the inventory control" -msgstr "" -"UdM(Unidad de medida) es la unidad de medida para el control de inventario" - -#. module: mrp -#: model:process.transition,note:mrp.process_transition_bom0 -msgid "" -"The Bill of Material is the product's decomposition. The components (that " -"are products themselves) can also have their own Bill of Material (multi-" -"level)." -msgstr "" -"La lista de materiales es la composición del producto. Los componentes (que " -"son también productos) pueden tener sus propias listas de materiales (multi-" -"nivel)." - -#. module: mrp -#: field:mrp.bom,company_id:0 -#: field:mrp.production,company_id:0 -#: view:mrp.production.order:0 -#: field:mrp.production.order,company_id:0 -#: field:mrp.routing,company_id:0 -#: field:mrp.routing.workcenter,company_id:0 -#: view:mrp.workcenter:0 -msgid "Company" -msgstr "Compañía" - -#. module: mrp -#: field:mrp.workcenter,time_cycle:0 -msgid "Time for 1 cycle (hour)" -msgstr "Tiempo para 1 ciclo (horas)" - -#. module: mrp -#: model:ir.actions.report.xml,name:mrp.report_mrp_production_report -#: field:mrp.production.product.line,production_id:0 -#: field:mrp.production.workcenter.line,production_id:0 -#: model:process.node,name:mrp.process_node_production0 -#: model:process.node,name:mrp.process_node_productionorder0 -msgid "Production Order" -msgstr "Orden de producción" - -#. module: mrp -#: model:process.node,note:mrp.process_node_productminimumstockrule0 -msgid "Automatic procurement rule" -msgstr "Regla de abastecimiento automática" - -#. module: mrp -#: view:mrp.production:0 -msgid "Compute Data" -msgstr "Calcular datos" - -#. module: mrp -#: field:mrp.production,product_uos_qty:0 -msgid "Product UoS Qty" -msgstr "Cant. UdV del producto" - -#. module: mrp -#: code:addons/mrp/report/price.py:130 -#: view:mrp.bom:0 -#, python-format -msgid "Components" -msgstr "Componentes" - -#. module: mrp -#: report:bom.structure:0 -#: model:ir.actions.report.xml,name:mrp.report_bom_structure -msgid "BOM Structure" -msgstr "Despiece de la LdM" - -#. module: mrp -#: field:mrp.bom,date_stop:0 -msgid "Valid Until" -msgstr "Válido hasta" - -#. module: mrp -#: field:mrp.bom,date_start:0 -msgid "Valid From" -msgstr "Válido desde" - -#. module: mrp -#: selection:mrp.bom,type:0 -msgid "Normal BoM" -msgstr "LdM normal" - -#. module: mrp -#: field:res.company,manufacturing_lead:0 -msgid "Manufacturing Lead Time" -msgstr "Tiempo entrega de fabricación" - -#. module: mrp -#: field:mrp.bom,product_uos_qty:0 -#: field:mrp.production.product.line,product_uos_qty:0 -msgid "Product UOS Qty" -msgstr "Ctdad UdV producto" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.action_report_in_out_picking_tree -msgid "" -"Weekly Stock Value Variation enables you to track the stock value evolution " -"linked to manufacturing activities, receptions of products and delivery " -"orders." -msgstr "" -"La variación semanal del valor del stock permite realizar un seguimiento de " -"la evolución del valor del stock relativo a las actividades de fabricacion, " -"recepciónd de productos y ordenes de entrega." - -#. module: mrp -#: view:mrp.product.produce:0 -msgid "Confirm" -msgstr "Confirmar" - -#. module: mrp -#: field:mrp.bom,product_efficiency:0 -msgid "Manufacturing Efficiency" -msgstr "Eficiencia de la producción" - -#. module: mrp -#: constraint:res.company:0 -msgid "Error! You can not create recursive companies." -msgstr "¡Error! No puede crear compañías recursivas." - -#. module: mrp -#: help:mrp.bom,active:0 -msgid "" -"If the active field is set to False, it will allow you to hide the bills of " -"material without removing it." -msgstr "" -"Si el campo activo se desmarca, permite ocultar las listas de material sin " -"eliminarlas." - -#. module: mrp -#: field:mrp.bom,product_rounding:0 -msgid "Product Rounding" -msgstr "Redondeo del producto" - -#. module: mrp -#: model:ir.model,name:mrp.model_mrp_production_workcenter_line -#: field:mrp.production.workcenter.line,name:0 -msgid "Work Order" -msgstr "Orden de trabajo" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.action_report_mrp_production_order -msgid "" -"This reporting allows you to analyse your manufacturing activities and " -"performance." -msgstr "" -"Estos informes le permiten analizar sus actividad productiva y su " -"rendimiento." - -#. module: mrp -#: selection:mrp.product.produce,mode:0 -msgid "Consume Only" -msgstr "Consumir únicamente" - -#. module: mrp -#: view:mrp.production:0 -msgid "Recreate Picking" -msgstr "Volver a crear albarán" - -#. module: mrp -#: help:mrp.bom,type:0 -msgid "" -"If a sub-product is used in several products, it can be useful to create its " -"own BoM. Though if you don't want separated production orders for this sub-" -"product, select Set/Phantom as BoM type. If a Phantom BoM is used for a root " -"product, it will be sold and shipped as a set of components, instead of " -"being produced." -msgstr "" -"Si un sub-producto se utiliza en varios productos, puede ser útil crear su " -"propia lista de materiales. Aunque si no quiere órdenes de producción " -"separadas para este sub-producto, seleccione Conjunto/Fantasma como tipo de " -"LdM. Si una LdM fantasma se utiliza para un producto raíz, será vendida y " -"enviada como un conjunto de componentes, en vez de ser producida." - -#. module: mrp -#: field:mrp.bom,method:0 -msgid "Method" -msgstr "Método" - -#. module: mrp -#: help:mrp.production,state:0 -msgid "" -"When the production order is created the state is set to 'Draft'.\n" -" If the order is confirmed the state is set to 'Waiting Goods'.\n" -" If any exceptions are there, the state is set to 'Picking Exception'. " -" \n" -"If the stock is available then the state is set to 'Ready to Produce'.\n" -" When the production gets started then the state is set to 'In Production'.\n" -" When the production is over, the state is set to 'Done'." -msgstr "" -"Cuando se crea la orden de fabricación su estado es fijado a \"Borrador\"\n" -" Si la orden está confirmdada, el estado es fijado a \"Esperando " -"mercancía\"\n" -" Si existe alguna excepción, el estado es fijado a \"Excepcion de " -"abastecimiento\"\n" -"Si el stock está disponible, el estado es fijado a \"Listo para producir\"\n" -" Cuando la fabricación comienza, el estado es fijado a \"En producción\"\n" -" Cuando la fabricación finaliza, el estado es fijado a \"Realizado\"" - -#. module: mrp -#: selection:mrp.bom,method:0 -msgid "On Order" -msgstr "En orden" - -#. module: mrp -#: model:ir.ui.menu,name:mrp.menu_mrp_configuration -#: view:res.company:0 -msgid "Configuration" -msgstr "Configuración" - -#. module: mrp -#: field:mrp.workcenter,time_stop:0 -msgid "Time after prod." -msgstr "Tiempo después producción" - -#. module: mrp -#: field:mrp.workcenter.load,time_unit:0 -msgid "Type of period" -msgstr "Tipo de período" - -#. module: mrp -#: view:mrp.production:0 -msgid "Total Qty" -msgstr "Ctdad total" - -#. module: mrp -#: field:mrp.routing.workcenter,hour_nbr:0 -msgid "Number of Hours" -msgstr "Número de horas" - -#. module: mrp -#: view:mrp.workcenter:0 -msgid "Costing Information" -msgstr "Información de costes" - -#. module: mrp -#: model:process.node,name:mrp.process_node_purchaseprocure0 -msgid "Procurement Orders" -msgstr "Órdenes de abastecimiento" - -#. module: mrp -#: help:mrp.bom,product_rounding:0 -msgid "Rounding applied on the product quantity." -msgstr "Redondeo aplicado sobre la cantidad de producto" - -#. module: mrp -#: model:process.node,note:mrp.process_node_stock0 -msgid "Assignment from Production or Purchase Order." -msgstr "Asignación desde producción o pedido de compra." - -#. module: mrp -#: field:mrp.routing.workcenter,routing_id:0 -msgid "Parent Routing" -msgstr "Proceso productivo padre" - -#. module: mrp -#: view:mrp.installer:0 -msgid "Configure" -msgstr "Configurar" - -#. module: mrp -#: help:mrp.workcenter,time_start:0 -msgid "Time in hours for the setup." -msgstr "Tiempo en horas para la configuración." - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "December" -msgstr "Diciembre" - -#. module: mrp -#: field:mrp.installer,config_logo:0 -msgid "Image" -msgstr "Imagen" - -#. module: mrp -#: field:mrp.bom.revision,bom_id:0 -#: field:procurement.order,bom_id:0 -msgid "BoM" -msgstr "Lista de materiales (LdM)" - -#. module: mrp -#: model:ir.model,name:mrp.model_report_mrp_inout -#: view:report.mrp.inout:0 -msgid "Stock value variation" -msgstr "Variación del valor del stock" - -#. module: mrp -#: model:process.node,note:mrp.process_node_mts0 -#: model:process.node,note:mrp.process_node_servicemts0 -msgid "Assignment from stock." -msgstr "Asignación desde stock." - -#. module: mrp -#: selection:mrp.production,state:0 -#: view:mrp.production.order:0 -#: selection:mrp.production.order,state:0 -msgid "Waiting Goods" -msgstr "Esperando mercancía" - -#. module: mrp -#: field:mrp.bom.revision,last_indice:0 -msgid "last indice" -msgstr "Último índice" - -#. module: mrp -#: field:mrp.bom,revision_ids:0 -#: view:mrp.bom.revision:0 -msgid "BoM Revisions" -msgstr "Revisiones lista de materiales" - -#. module: mrp -#: selection:mrp.production,state:0 -#: selection:mrp.production.order,state:0 -msgid "Draft" -msgstr "Borrador" - -#. module: mrp -#: field:report.mrp.inout,date:0 -#: field:report.workcenter.load,name:0 -msgid "Week" -msgstr "Semana" - -#. module: mrp -#: field:mrp.installer,progress:0 -msgid "Configuration Progress" -msgstr "Progreso de la configuración" - -#. module: mrp -#: selection:mrp.production,priority:0 -#: selection:mrp.production.order,priority:0 -msgid "Normal" -msgstr "Normal" - -#. module: mrp -#: model:process.node,note:mrp.process_node_routing0 -msgid "Manufacturing Steps." -msgstr "Etapas de producción." - -#. module: mrp -#: code:addons/mrp/report/price.py:136 -#: model:ir.actions.report.xml,name:mrp.report_cost_structure -#, python-format -msgid "Cost Structure" -msgstr "Estructura de costes" - -#. module: mrp -#: selection:mrp.product.produce,mode:0 -msgid "Consume & Produce" -msgstr "Consumir y Producir" - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "November" -msgstr "Noviembre" - -#. module: mrp -#: field:mrp.bom,bom_id:0 -msgid "Parent BoM" -msgstr "Lista de materiales (LdM) padre" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_bom_form_action2 -msgid "" -"Bills of materials components are components and sub-products used to create " -"master bills of materials. Use this menu to search in which BoM a specific " -"component is used." -msgstr "" -"Los componente de listas de materiales son componentes y sub-productos " -"utilizados para crear listas de materiales maestras. Utilice este menú para " -"buscar en qué LdM es utilizado un componente específico." - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "January" -msgstr "Enero" - -#. module: mrp -#: model:process.node,note:mrp.process_node_stockproduct0 -msgid "Product type is Stockable or Consumable." -msgstr "Tipo de producto es almacenable o consumible." - -#. module: mrp -#: code:addons/mrp/mrp.py:595 -#: code:addons/mrp/wizard/change_production_qty.py:77 -#: code:addons/mrp/wizard/change_production_qty.py:82 -#, python-format -msgid "Error" -msgstr "Error" - -#. module: mrp -#: field:mrp.product.produce,product_qty:0 -msgid "Select Quantity" -msgstr "Seleccionar cantidad" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.act_product_product_2_mrp_bom -#: model:ir.actions.act_window,name:mrp.mrp_bom_form_action -#: model:ir.ui.menu,name:mrp.menu_mrp_bom_form_action -#: field:product.product,bom_ids:0 -msgid "Bill of Materials" -msgstr "Lista de materiales (LdM)" #. module: mrp #: help:mrp.routing.workcenter,routing_id:0 @@ -2287,26 +1267,359 @@ msgid "" msgstr "" #. module: mrp -#: model:ir.model,name:mrp.model_mrp_bom_revision -msgid "Bill of Material Revision" -msgstr "Revisión de lista de materiales" +#: code:addons/mrp/mrp.py:505 +#, python-format +msgid "Invalid Action!" +msgstr "" #. module: mrp -#: view:mrp.routing.workcenter:0 -#: view:mrp.workcenter:0 -msgid "General Information" -msgstr "Información general" +#: model:process.transition,note:mrp.process_transition_producttostockrules0 +msgid "" +"The Minimum Stock Rule is an automatic procurement rule based on a mini and " +"maxi quantity. It's available in the Inventory management menu and " +"configured by product." +msgstr "" + +#. module: mrp +#: code:addons/mrp/report/price.py:187 +#, python-format +msgid "Components Cost of %s %s" +msgstr "" + +#. module: mrp +#: selection:mrp.workcenter.load,time_unit:0 +msgid "Day by day" +msgstr "" + +#. module: mrp +#: field:mrp.production,priority:0 +msgid "Priority" +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_stock_picking +#: field:mrp.production,picking_id:0 +msgid "Picking List" +msgstr "" + +#. module: mrp +#: help:mrp.production,bom_id:0 +msgid "" +"Bill of Materials allow you to define the list of required raw materials to " +"make a finished product." +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:375 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_mrp_production_product_line +msgid "Production Scheduled Product" +msgstr "" + +#. module: mrp +#: code:addons/mrp/report/price.py:204 +#, python-format +msgid "Work Cost of %s %s" +msgstr "" + +#. module: mrp +#: help:res.company,manufacturing_lead:0 +msgid "Security days for each manufacturing operation." +msgstr "" + +#. module: mrp +#: model:process.node,name:mrp.process_node_mts0 +#: model:process.transition,name:mrp.process_transition_servicemts0 +#: model:process.transition,name:mrp.process_transition_stockmts0 +msgid "Make to Stock" +msgstr "" + +#. module: mrp +#: constraint:mrp.production:0 +msgid "Order quantity cannot be negative or zero!" +msgstr "" + +#. module: mrp +#: model:process.transition,note:mrp.process_transition_stockrfq0 +msgid "" +"In case the Supply method of the product is Buy, the system creates a " +"purchase order." +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_procurement_order +msgid "Procurement" +msgstr "" + +#. module: mrp +#: field:mrp.config.settings,module_product_manufacturer:0 +msgid "Define manufacturers on products " +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.action_view_mrp_product_price_wizard +#: view:mrp.product_price:0 +msgid "Product Cost Structure" +msgstr "" + +#. module: mrp +#: code:addons/mrp/report/price.py:139 +#, python-format +msgid "Components suppliers" +msgstr "" #. module: mrp #: view:mrp.production:0 -msgid "Productions" -msgstr "Producciones" +msgid "Production Work Centers" +msgstr "" #. module: mrp -#: code:addons/mrp/report/price.py:194 +#: view:mrp.workcenter:0 +msgid "Search for mrp workcenter" +msgstr "" + +#. module: mrp +#: view:mrp.bom:0 +msgid "BoM Structure" +msgstr "" + +#. module: mrp +#: field:mrp.production,date_start:0 +msgid "Start Date" +msgstr "" + +#. module: mrp +#: field:mrp.workcenter,costs_hour_account_id:0 +msgid "Hour Account" +msgstr "" + +#. module: mrp +#: field:mrp.bom,product_uom:0 +#: field:mrp.production,product_uom:0 +#: field:mrp.production.product.line,product_uom:0 +msgid "Product Unit of Measure" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Destination Loc." +msgstr "" + +#. module: mrp +#: field:mrp.bom,method:0 +msgid "Method" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Pending" +msgstr "" + +#. module: mrp +#: field:mrp.bom,active:0 +#: field:mrp.routing,active:0 +msgid "Active" +msgstr "" + +#. module: mrp +#: help:mrp.config.settings,group_mrp_routings:0 +msgid "" +"Routings allow you to create and manage the manufacturing operations that " +"should be followed\n" +" within your work centers in order to produce a product. They " +"are attached to bills of materials\n" +" that will define the required raw materials." +msgstr "" + +#. module: mrp +#: view:report.workcenter.load:0 +msgid "Work Center Loads" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.mrp_property_action +#: model:ir.ui.menu,name:mrp.menu_mrp_property_action +#: view:mrp.bom:0 +#: field:mrp.bom,property_ids:0 +#: view:mrp.property:0 +#: field:procurement.order,property_ids:0 +msgid "Properties" +msgstr "" + +#. module: mrp +#: help:mrp.production,origin:0 +msgid "" +"Reference of the document that generated this production order request." +msgstr "" + +#. module: mrp +#: model:process.transition,name:mrp.process_transition_minimumstockprocure0 +msgid "'Minimum stock rule' material" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Extra Information" +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_change_production_qty +msgid "Change Quantity of Products" +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_productionorder0 +msgid "Drives the procurement orders for raw material." +msgstr "" + +#. module: mrp +#: field:mrp.production.product.line,product_uos_qty:0 +msgid "Product UOS Quantity" +msgstr "" + +#. module: mrp +#: field:mrp.workcenter,costs_general_account_id:0 +msgid "General Account" +msgstr "" + +#. module: mrp +#: report:mrp.production.order:0 +msgid "SO Number" +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:505 #, python-format -msgid "Work Cost of " -msgstr "Coste trabajo de " +msgid "Cannot delete a manufacturing order in state '%s'." +msgstr "" + +#. module: mrp +#: selection:mrp.production,state:0 +msgid "Done" +msgstr "" + +#. module: mrp +#: view:product.product:0 +msgid "When you sell this product, OpenERP will trigger" +msgstr "" + +#. module: mrp +#: field:mrp.production,origin:0 +#: report:mrp.production.order:0 +msgid "Source Document" +msgstr "" + +#. module: mrp +#: selection:mrp.production,priority:0 +msgid "Not urgent" +msgstr "" + +#. module: mrp +#: field:mrp.production,user_id:0 +msgid "Responsible" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.mrp_production_action2 +msgid "Manufacturing Orders To Start" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.mrp_workcenter_action +#: model:ir.model,name:mrp.model_mrp_workcenter +#: model:ir.ui.menu,name:mrp.menu_view_resource_search_mrp +#: field:mrp.production.workcenter.line,workcenter_id:0 +#: field:mrp.routing.workcenter,workcenter_id:0 +#: view:mrp.workcenter:0 +#: field:report.workcenter.load,workcenter_id:0 +msgid "Work Center" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,help:mrp.mrp_property_group_action +msgid "" +"

\n" +" Click to create a group of properties.\n" +"

\n" +" Define specific property groups that can be assigned to " +"your\n" +" bill of materials and sales orders. Properties allows " +"OpenERP\n" +" to automatically select the right bill of materials " +"according\n" +" to properties selected in the sales order by salesperson.\n" +"

\n" +" For instance, in the property group \"Warranty\", you an " +"have\n" +" two properties: 1 year warranty, 3 years warranty. " +"Depending\n" +" on the propoerties selected in the sales order, OpenERP " +"will\n" +" schedule a production using the matching bill of materials.\n" +"

\n" +" " +msgstr "" + +#. module: mrp +#: field:mrp.workcenter,capacity_per_cycle:0 +msgid "Capacity per Cycle" +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_product_product +#: view:mrp.bom:0 +#: field:mrp.bom,product_id:0 +#: view:mrp.production:0 +#: field:mrp.production,product_id:0 +#: report:mrp.production.order:0 +#: field:mrp.production.product.line,product_id:0 +msgid "Product" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +#: field:mrp.production,hour_total:0 +msgid "Total Hours" +msgstr "" + +#. module: mrp +#: field:mrp.production,location_src_id:0 +msgid "Raw Materials Location" +msgstr "" + +#. module: mrp +#: view:mrp.product_price:0 +msgid "Print Cost Structure of Product." +msgstr "" + +#. module: mrp +#: field:mrp.bom,product_uos:0 +#: field:mrp.production.product.line,product_uos:0 +msgid "Product UOS" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Consume Products" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.act_mrp_product_produce +#: view:mrp.product.produce:0 +#: view:mrp.production:0 +msgid "Produce" +msgstr "" + +#. module: mrp +#: model:process.node,name:mrp.process_node_stock0 +#: model:process.transition,name:mrp.process_transition_servicemto0 +#: model:process.transition,name:mrp.process_transition_stockproduct0 +msgid "Make to Order" +msgstr "" #. module: mrp #: help:mrp.workcenter,note:0 @@ -2316,160 +1629,656 @@ msgid "" msgstr "" #. module: mrp -#: model:ir.model,name:mrp.model_mrp_routing -#: view:mrp.bom:0 -#: field:mrp.bom,routing_id:0 -#: view:mrp.production:0 -#: field:mrp.production,routing_id:0 -#: field:mrp.production.order,routing_id:0 -#: view:mrp.routing:0 -#: model:process.node,name:mrp.process_node_routing0 -msgid "Routing" -msgstr "Proceso productivo" - -#. module: mrp -#: field:mrp.installer,mrp_operations:0 -msgid "Manufacturing Operations" -msgstr "Operaciones de producción" - -#. module: mrp -#: field:mrp.production,date_planned:0 -msgid "Scheduled date" -msgstr "Fecha planificada" - -#. module: mrp -#: constraint:stock.move:0 -msgid "You must assign a production lot for this product" -msgstr "Debe asignar un lote de producción para este producto" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.mrp_property_action -msgid "" -"The Properties in OpenERP are used to select the right bill of materials for " -"manufacturing a product when you have different ways of building the same " -"product. You can assign several properties to each Bill of Materials. When a " -"sales person creates a sales order, he can relate it to several properties " -"and OpenERP will automatically select the BoM to use according the the needs." +#: field:mrp.production,date_finished:0 +msgid "End Date" msgstr "" -"Las propiedades en OpenERP se utilizan para seleccionar la correcta lista de " -"materiales para la fabricación de uno de los productos cuando se tienen " -"diferentes formas de fabricar el mismo producto. Puede asignar varias " -"propiedades para cada lista de materiales. Cuando un vendedor crea un pedido " -"de cliente, él puede relacionarlo con varias propiedades y OpenERP " -"seleccionará automáticamente la lista de materiales para utilizar según las " -"necesidades." #. module: mrp -#: view:mrp.production.order:0 +#: field:mrp.workcenter,resource_id:0 +msgid "Resource" +msgstr "" + +#. module: mrp +#: help:mrp.bom,date_start:0 +#: help:mrp.bom,date_stop:0 +msgid "Validity of this BoM or component. Keep empty if it's always valid." +msgstr "" + +#. module: mrp +#: field:mrp.production,product_uos:0 +msgid "Product UoS" +msgstr "" + +#. module: mrp +#: selection:mrp.production,priority:0 +msgid "Very Urgent" +msgstr "" + +#. module: mrp +#: help:mrp.bom,routing_id:0 +msgid "" +"The list of operations (list of work centers) to produce the finished " +"product. The routing is mainly used to compute work center costs during " +"operations and to plan future loads on work centers based on production " +"planning." +msgstr "" + +#. module: mrp +#: view:change.production.qty:0 +msgid "Approve" +msgstr "" + +#. module: mrp +#: view:mrp.config.settings:0 +msgid "Order" +msgstr "" + +#. module: mrp +#: view:mrp.property.group:0 +msgid "Properties categories" +msgstr "" + +#. module: mrp +#: help:mrp.production.workcenter.line,sequence:0 +msgid "Gives the sequence order when displaying a list of work orders." +msgstr "" + +#. module: mrp +#: report:mrp.production.order:0 +msgid "Source Location" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +#: view:mrp.production.product.line:0 +msgid "Scheduled Products" +msgstr "" + +#. module: mrp +#: model:res.groups,name:mrp.group_mrp_manager +msgid "Manager" +msgstr "" + +#. module: mrp +#: help:mrp.product.produce,mode:0 +msgid "" +"'Consume only' mode will only consume the products with the quantity " +"selected.\n" +"'Consume & Produce' mode will consume as well as produce the products with " +"the quantity selected and it will finish the production order when total " +"ordered quantities are produced." +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +#: report:mrp.production.order:0 +msgid "Work Orders" +msgstr "" + +#. module: mrp +#: field:mrp.workcenter,costs_cycle:0 +msgid "Cost per cycle" +msgstr "" + +#. module: mrp +#: model:process.node,name:mrp.process_node_serviceproduct0 +#: model:process.node,name:mrp.process_node_serviceproduct1 +msgid "Service" +msgstr "" + +#. module: mrp +#: selection:mrp.production,state:0 +msgid "Cancelled" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "(Update)" +msgstr "" + +#. module: mrp +#: help:mrp.config.settings,module_mrp_operations:0 +msgid "" +"This allows to add state, date_start,date_stop in production order operation " +"lines (in the \"Work Centers\" tab).\n" +" This installs the module mrp_operations." +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:737 +#, python-format +msgid "" +"You are going to consume total %s quantities of \"%s\".\n" +"But you can only consume up to total %s quantities." +msgstr "" + +#. module: mrp +#: model:process.transition,note:mrp.process_transition_bom0 +msgid "" +"The Bill of Material is the product's decomposition. The components (that " +"are products themselves) can also have their own Bill of Material (multi-" +"level)." +msgstr "" + +#. module: mrp +#: field:mrp.bom,company_id:0 +#: field:mrp.production,company_id:0 +#: field:mrp.routing,company_id:0 +#: field:mrp.routing.workcenter,company_id:0 +#: view:mrp.workcenter:0 +msgid "Company" +msgstr "" + +#. module: mrp +#: view:mrp.bom:0 +msgid "Default Unit of Measure" +msgstr "" + +#. module: mrp +#: field:mrp.workcenter,time_cycle:0 +msgid "Time for 1 cycle (hour)" +msgstr "" + +#. module: mrp +#: model:ir.actions.report.xml,name:mrp.report_mrp_production_report +#: field:mrp.production.product.line,production_id:0 +#: model:process.node,name:mrp.process_node_production0 +#: model:process.node,name:mrp.process_node_productionorder0 +msgid "Production Order" +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_productminimumstockrule0 +msgid "Automatic procurement rule" +msgstr "" + +#. module: mrp +#: field:mrp.bom,message_ids:0 +#: field:mrp.production,message_ids:0 +#: field:mrp.production.workcenter.line,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Compute Data" +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:610 +#: code:addons/mrp/wizard/change_production_qty.py:83 +#: code:addons/mrp/wizard/change_production_qty.py:88 +#, python-format +msgid "Error!" +msgstr "" + +#. module: mrp +#: code:addons/mrp/report/price.py:139 +#: view:mrp.bom:0 +#, python-format +msgid "Components" +msgstr "" + +#. module: mrp +#: report:bom.structure:0 +#: model:ir.actions.report.xml,name:mrp.report_bom_structure +msgid "BOM Structure" +msgstr "" + +#. module: mrp +#: field:mrp.config.settings,module_mrp_jit:0 +msgid "Generate procurement in real time" +msgstr "" + +#. module: mrp +#: field:mrp.bom,date_stop:0 +msgid "Valid Until" +msgstr "" + +#. module: mrp +#: field:mrp.bom,date_start:0 +msgid "Valid From" +msgstr "" + +#. module: mrp +#: selection:mrp.bom,type:0 +msgid "Normal BoM" +msgstr "" + +#. module: mrp +#: field:res.company,manufacturing_lead:0 +msgid "Manufacturing Lead Time" +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:285 +#, python-format +msgid "Warning" +msgstr "" + +#. module: mrp +#: field:mrp.bom,product_uos_qty:0 +msgid "Product UOS Qty" +msgstr "" + +#. module: mrp +#: field:mrp.production,move_prod_id:0 +msgid "Product Move" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,help:mrp.action_report_in_out_picking_tree +msgid "" +"Weekly Stock Value Variation enables you to track the stock value evolution " +"linked to manufacturing activities, receptions of products and delivery " +"orders." +msgstr "" + +#. module: mrp +#: view:mrp.product.produce:0 +msgid "Confirm" +msgstr "" + +#. module: mrp +#: field:mrp.bom,product_efficiency:0 +msgid "Manufacturing Efficiency" +msgstr "" + +#. module: mrp +#: field:mrp.bom,message_follower_ids:0 +#: field:mrp.production,message_follower_ids:0 +#: field:mrp.production.workcenter.line,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: mrp +#: help:mrp.bom,active:0 +msgid "" +"If the active field is set to False, it will allow you to hide the bills of " +"material without removing it." +msgstr "" + +#. module: mrp +#: field:mrp.bom,product_rounding:0 +msgid "Product Rounding" +msgstr "" + +#. module: mrp +#: selection:mrp.production,state:0 +msgid "New" +msgstr "" + +#. module: mrp +#: selection:mrp.product.produce,mode:0 +msgid "Consume Only" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Recreate Picking" +msgstr "" + +#. module: mrp +#: selection:mrp.bom,method:0 +msgid "On Order" +msgstr "" + +#. module: mrp +#: model:ir.ui.menu,name:mrp.menu_mrp_configuration +msgid "Configuration" +msgstr "" + +#. module: mrp +#: view:mrp.bom:0 +msgid "Starting Date" +msgstr "" + +#. module: mrp +#: field:mrp.workcenter,time_stop:0 +msgid "Time after prod." +msgstr "" + +#. module: mrp +#: field:mrp.workcenter.load,time_unit:0 +msgid "Type of period" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Total Qty" +msgstr "" + +#. module: mrp +#: field:mrp.production.workcenter.line,hour:0 +#: field:mrp.routing.workcenter,hour_nbr:0 +#: field:report.workcenter.load,hour:0 +msgid "Number of Hours" +msgstr "" + +#. module: mrp +#: view:mrp.workcenter:0 +msgid "Costing Information" +msgstr "" + +#. module: mrp +#: model:process.node,name:mrp.process_node_purchaseprocure0 +msgid "Procurement Orders" +msgstr "" + +#. module: mrp +#: help:mrp.bom,product_rounding:0 +msgid "Rounding applied on the product quantity." +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_stock0 +msgid "Assignment from Production or Purchase Order." +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,help:mrp.mrp_bom_form_action +msgid "" +"

\n" +" Click to create a bill of material. \n" +"

\n" +" Bills of Materials allow you to define the list of required " +"raw\n" +" materials used to make a finished product; through a " +"manufacturing\n" +" order or a pack of products.\n" +"

\n" +" OpenERP uses these BoMs to automatically propose " +"manufacturing\n" +" orders according to procurement needs.\n" +"

\n" +" " +msgstr "" + +#. module: mrp +#: field:mrp.routing.workcenter,routing_id:0 +msgid "Parent Routing" +msgstr "" + +#. module: mrp +#: help:mrp.workcenter,time_start:0 +msgid "Time in hours for the setup." +msgstr "" + +#. module: mrp +#: field:mrp.config.settings,module_mrp_repair:0 +msgid "Manage repairs of products " +msgstr "" + +#. module: mrp +#: help:mrp.config.settings,module_mrp_byproduct:0 +msgid "" +"You can configure by-products in the bill of material.\n" +" Without this module: A + B + C -> D.\n" +" With this module: A + B + C -> D + E.\n" +" This installs the module mrp_byproduct." +msgstr "" + +#. module: mrp +#: field:procurement.order,bom_id:0 +msgid "BoM" +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_report_mrp_inout +#: view:report.mrp.inout:0 +msgid "Stock value variation" +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_mts0 +#: model:process.node,note:mrp.process_node_servicemts0 +msgid "Assignment from stock." +msgstr "" + +#. module: mrp +#: code:addons/mrp/report/price.py:139 +#, python-format +msgid "Cost Price per Unit of Measure" +msgstr "" + +#. module: mrp +#: field:report.mrp.inout,date:0 +#: view:report.workcenter.load:0 +#: field:report.workcenter.load,name:0 +msgid "Week" +msgstr "" + +#. module: mrp +#: selection:mrp.production,priority:0 +msgid "Normal" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Production started late" +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_routing0 +msgid "Manufacturing Steps." +msgstr "" + +#. module: mrp +#: code:addons/mrp/report/price.py:146 +#: model:ir.actions.report.xml,name:mrp.report_cost_structure +#, python-format +msgid "Cost Structure" +msgstr "" + +#. module: mrp +#: model:res.groups,name:mrp.group_mrp_user +msgid "User" +msgstr "" + +#. module: mrp +#: selection:mrp.product.produce,mode:0 +msgid "Consume & Produce" +msgstr "" + +#. module: mrp +#: field:mrp.bom,bom_id:0 +msgid "Parent BoM" +msgstr "" + +#. module: mrp +#: report:bom.structure:0 +msgid "BOM Ref" +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:765 +#, python-format +msgid "" +"You are going to produce total %s quantities of \"%s\".\n" +"But you can only produce up to total %s quantities." +msgstr "" + +#. module: mrp +#: model:process.node,note:mrp.process_node_stockproduct0 +msgid "Product type is Stockable or Consumable." +msgstr "" + +#. module: mrp +#: selection:mrp.production,state:0 +msgid "Production Started" +msgstr "" + +#. module: mrp +#: model:process.node,name:mrp.process_node_procureproducts0 +msgid "Procure Products" +msgstr "" + +#. module: mrp +#: field:mrp.product.produce,product_qty:0 +msgid "Select Quantity" +msgstr "" + +#. module: mrp +#: model:ir.actions.act_window,name:mrp.mrp_bom_form_action +#: model:ir.actions.act_window,name:mrp.product_open_bom +#: model:ir.ui.menu,name:mrp.menu_mrp_bom_form_action +#: view:mrp.bom:0 +#: view:product.product:0 +#: field:product.product,bom_ids:0 +msgid "Bill of Materials" +msgstr "" + +#. module: mrp +#: code:addons/mrp/mrp.py:610 +#, python-format +msgid "Cannot find a bill of material for this product." +msgstr "" + +#. module: mrp +#: view:product.product:0 +msgid "" +"using the bill of materials assigned to this product.\n" +" The delivery order will be ready once the production " +"is done." +msgstr "" + +#. module: mrp +#: field:mrp.config.settings,module_stock_no_autopicking:0 +msgid "Manage manual picking to fulfill manufacturing orders " +msgstr "" + +#. module: mrp +#: view:mrp.routing.workcenter:0 +#: view:mrp.workcenter:0 +msgid "General Information" +msgstr "" + +#. module: mrp +#: view:mrp.production:0 +msgid "Productions" +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_stock_move_split +#: view:mrp.production:0 +msgid "Split in Serial Numbers" +msgstr "" + +#. module: mrp +#: help:mrp.bom,product_uos:0 +msgid "" +"Product UOS (Unit of Sale) is the unit of measurement for the invoicing and " +"promotion of stock." +msgstr "" + +#. module: mrp +#: view:mrp.production:0 #: field:stock.move,production_id:0 msgid "Production" -msgstr "Producción" +msgstr "" + +#. module: mrp +#: model:ir.model,name:mrp.model_mrp_production_workcenter_line +#: field:mrp.production.workcenter.line,name:0 +msgid "Work Order" +msgstr "" #. module: mrp #: view:board.board:0 msgid "Procurements in Exception" -msgstr "Abastecimientos en excepción" - -#. module: mrp -#: model:process.transition,name:mrp.process_transition_minimumstockprocure0 -msgid "'Minimum stock rule' material" -msgstr "material 'regla stock mínimo'" +msgstr "" #. module: mrp #: model:ir.model,name:mrp.model_mrp_product_price msgid "Product Price" -msgstr "Precio del producto" - -#. module: mrp -#: model:ir.actions.act_window,name:mrp.action_mrp_installer -msgid "MRP Applications Configuration" -msgstr "Configuración de las aplicaciónes MRP" - -#. module: mrp -#: model:ir.model,name:mrp.model_stock_move_split -msgid "Split in Production lots" -msgstr "Dividir en lotes de producción" +msgstr "" #. module: mrp #: view:change.production.qty:0 msgid "Change Quantity" -msgstr "Cambiar cantidad" +msgstr "" #. module: mrp #: view:change.production.qty:0 #: model:ir.actions.act_window,name:mrp.action_change_production_qty msgid "Change Product Qty" -msgstr "Cambiar Ctd. producto" +msgstr "" #. module: mrp -#: view:mrp.bom.revision:0 -#: field:mrp.bom.revision,description:0 -#: view:mrp.property:0 -#: view:mrp.property.group:0 #: field:mrp.routing,note:0 -#: view:mrp.routing.workcenter:0 #: field:mrp.routing.workcenter,note:0 -#: view:mrp.workcenter:0 #: field:mrp.workcenter,note:0 msgid "Description" -msgstr "Descripción" - -#. module: mrp -#: selection:mrp.production.order,month:0 -msgid "May" -msgstr "Mayo" +msgstr "" #. module: mrp #: view:board.board:0 msgid "Manufacturing board" -msgstr "Tablero fabricación" - -#. module: mrp -#: field:mrp.production,date_planned_end:0 -msgid "Scheduled End Date" -msgstr "Fecha de fin planificada" - -#. module: mrp -#: model:ir.actions.act_window,help:mrp.action_report_workcenter_load_tree -msgid "" -"Work Center Loads gives you a projection of work center loads over a " -"specified period. It is expressed in number of hours and machine related " -"cycles." msgstr "" -"Las cargas de los centros de producción muestran un pronóstico de la carga " -"de los centros de producción respecto a un periodo determinado. Está " -"expresado en número de horas y ciclos de máquina relacionados." + +#. module: mrp +#: code:addons/mrp/wizard/change_production_qty.py:68 +#, python-format +msgid "Active Id not found" +msgstr "" #. module: mrp #: model:process.node,note:mrp.process_node_procureproducts0 msgid "The way to procurement depends on the product type." -msgstr "La forma de abastecer depende del tipo de producto." +msgstr "" #. module: mrp +#: model:ir.actions.act_window,name:mrp.open_board_manufacturing +#: model:ir.ui.menu,name:mrp.menu_board_manufacturing #: model:ir.ui.menu,name:mrp.menu_mrp_manufacturing +#: model:ir.ui.menu,name:mrp.next_id_77 msgid "Manufacturing" -msgstr "Fabricación" +msgstr "" #. module: mrp -#: view:board.board:0 -msgid "Next Production Orders" -msgstr "Próximas órdenes de producción" +#: help:mrp.bom,type:0 +msgid "" +"If a by-product is used in several products, it can be useful to create its " +"own BoM. Though if you don't want separated production orders for this by-" +"product, select Set/Phantom as BoM type. If a Phantom BoM is used for a root " +"product, it will be sold and shipped as a set of components, instead of " +"being produced." +msgstr "" #. module: mrp -#: selection:mrp.production.order,month:0 -msgid "February" -msgstr "Febrero" +#: model:ir.actions.act_window,name:mrp.action_mrp_configuration +#: view:mrp.config.settings:0 +msgid "Configure Manufacturing" +msgstr "" + +#. module: mrp +#: view:product.product:0 +msgid "" +"a manufacturing\n" +" order" +msgstr "" + +#. module: mrp +#: field:mrp.config.settings,group_mrp_properties:0 +msgid "Allow several bill of materials per products using properties" +msgstr "" #. module: mrp #: model:ir.actions.act_window,name:mrp.mrp_property_group_action #: model:ir.ui.menu,name:mrp.menu_mrp_property_group_action msgid "Property Groups" -msgstr "Grupos de propiedades" +msgstr "" #. module: mrp -#: selection:mrp.production.order,month:0 -msgid "April" -msgstr "Abril" +#: model:ir.model,name:mrp.model_mrp_routing +#: view:mrp.bom:0 +#: field:mrp.bom,routing_id:0 +#: view:mrp.production:0 +#: field:mrp.production,routing_id:0 +#: view:mrp.routing:0 +#: model:process.node,name:mrp.process_node_routing0 +msgid "Routing" +msgstr "" #. module: mrp #: model:process.transition,note:mrp.process_transition_procurestockableproduct0 @@ -2477,19 +2286,23 @@ msgid "" "Depending on the chosen method to supply the stockable products, the " "procurement order creates a RFQ, a production order, ... " msgstr "" -"Dependiendo del método elegido para suministrar los productos almacenables, " -"la orden de abastecimiento crea una petición de presupuesto, una orden de " -"producción, ... " #. module: mrp #: help:mrp.workcenter,time_stop:0 msgid "Time in hours for the cleaning." -msgstr "Tiempo en horas para la limpieza." +msgstr "" + +#. module: mrp +#: field:mrp.bom,message_summary:0 +#: field:mrp.production,message_summary:0 +#: field:mrp.production.workcenter.line,message_summary:0 +msgid "Summary" +msgstr "" #. module: mrp #: model:process.transition,name:mrp.process_transition_purchaseprocure0 msgid "Automatic RFQ" -msgstr "Petición de presupuesto automática" +msgstr "" #. module: mrp #: model:process.transition,note:mrp.process_transition_servicemto0 @@ -2497,8 +2310,6 @@ msgid "" "If the service has a 'Produce' supply method, this creates a task in the " "project management module of OpenERP." msgstr "" -"Si el servicio tiene un método de suministro 'Producir', se crea una tarea " -"en el módulo de gestión de proyectos de OpenERP." #. module: mrp #: model:process.transition,note:mrp.process_transition_productionprocureproducts0 @@ -2507,10 +2318,6 @@ msgid "" "production order creates as much procurement orders as components listed in " "the BOM, through a run of the schedulers (MRP)." msgstr "" -"Para poder suministrar materias primas (que deben ser compradas o " -"producidas), la orden de producción genera tantas órdenes de abastecimiento " -"como componentes figuren en la lista de materiales, a través de una " -"ejecución de las planificaciones (MRP)." #. module: mrp #: help:mrp.product_price,number:0 @@ -2518,13 +2325,11 @@ msgid "" "Specify quantity of products to produce or buy. Report of Cost structure " "will be displayed base on this quantity." msgstr "" -"Indique la cantidad de productos a producir o comprar. El informe de la " -"estructura de costes se muestra basándose en esta cantidad." #. module: mrp #: selection:mrp.bom,method:0 msgid "On Stock" -msgstr "En stock" +msgstr "" #. module: mrp #: field:mrp.bom,sequence:0 @@ -2532,897 +2337,26 @@ msgstr "En stock" #: field:mrp.production.workcenter.line,sequence:0 #: field:mrp.routing.workcenter,sequence:0 msgid "Sequence" -msgstr "Secuencia" +msgstr "" #. module: mrp #: model:ir.ui.menu,name:mrp.menu_view_resource_calendar_leaves_search_mrp msgid "Resource Leaves" -msgstr "Ausencias recursos" +msgstr "" #. module: mrp #: help:mrp.bom,sequence:0 msgid "Gives the sequence order when displaying a list of bills of material." msgstr "" -"Indica el orden de secuencia cuando se muestra una lista de listas de " -"materiales." + +#. module: mrp +#: model:ir.model,name:mrp.model_mrp_config_settings +msgid "mrp.config.settings" +msgstr "" #. module: mrp #: view:mrp.production:0 #: field:mrp.production,move_lines:0 #: report:mrp.production.order:0 -#: field:mrp.production.order,products_to_consume:0 msgid "Products to Consume" -msgstr "Productos a consumir" - -#. module: mrp -#: view:mrp.production.order:0 -#: field:mrp.production.order,year:0 -msgid "Year" -msgstr "Año" - -#~ msgid "-" -#~ msgstr "-" - -#~ 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 "" -#~ "Dispara un abastecimiento automático para todos los productos que tienen un " -#~ "stock virtual menor que 0. Probablemente no debería utilizar esta opción, " -#~ "sugerimos utilizar una configuración de MTO en productos." - -#~ msgid "Compute Stock Minimum Rules Only" -#~ msgstr "Calcular sólo reglas de stock mínimo" - -#~ msgid "Exceptions Procurements" -#~ msgstr "Excepciones de abastecimientos" - -#~ msgid "UoS Quantity" -#~ msgstr "Cantidad UdV" - -#~ msgid "Routing Workcenters" -#~ msgstr "Procesos productivos de los centros de producción" - -#~ msgid "Not used in computations, for information purpose only." -#~ msgstr "No utilizado en cálculos, sólo con la finalidad de informar." - -#~ msgid "Packing list" -#~ msgstr "Albarán" - -#~ msgid "Stockable Stock" -#~ msgstr "Stock productos almacenables" - -#~ msgid "Origin" -#~ msgstr "Origen" - -#~ msgid "Automatic orderpoint" -#~ msgstr "Generación de orden automática" - -#, python-format -#~ msgid "No supplier defined for this product !" -#~ msgstr "¡No se ha definido un proveedor para este producto!" - -#, python-format -#~ msgid "Product name" -#~ msgstr "Nombre producto" - -#~ msgid "Invalid XML for View Architecture!" -#~ msgstr "¡XML inválido para la definición de la vista!" - -#~ msgid "" -#~ "This is the days added to what you promise to customers for security purpose" -#~ msgstr "" -#~ "Éstos son los días añadidos a los que promete a los clientes por razones de " -#~ "seguridad" - -#~ msgid "Best price (not yet active!)" -#~ msgstr "Mejor precio (aún no activo!)" - -#~ msgid "Product & Location" -#~ msgstr "Producto & Ubicación" - -#~ msgid "MRP & Logistic Scheduler" -#~ msgstr "Planificador MRP & Logística" - -#~ msgid "" -#~ "Number of operation this workcenter can do in parallel. If this workcenter " -#~ "represent a team of 5 workers, the capacity per cycle is 5." -#~ msgstr "" -#~ "Número de operaciones que este centro de producción puede realizar en " -#~ "paralelo. Si este centro de producción tuviera un equipo de 5 trabajadores, " -#~ "la capacidad por ciclo sería de 5." - -#~ msgid "Ask New Products" -#~ msgstr "Solicitar nuevos productos" - -#~ msgid "Automatic Procurements" -#~ msgstr "Abastecimientos automáticos" - -#~ msgid "Products Consummed" -#~ msgstr "Productos consumidos" - -#~ msgid "Packing Exception" -#~ msgstr "Excepción de empaquetado" - -#~ msgid "A purchase order is created for a sub-contracting demand." -#~ msgstr "Una orden de compra es creada para sub-contratar la demanda." - -#~ msgid "Analytic Accounting" -#~ msgstr "Contabilidad analítica" - -#~ msgid "Do nothing" -#~ msgstr "No hacer nada" - -#, python-format -#~ msgid "products" -#~ msgstr "productos" - -#~ msgid "If the stock of a product is under 0, it will act like an orderpoint" -#~ msgstr "Si el stock de un producto es menor que 0, actuará como una orden" - -#~ msgid "you can see the minimum stock rules from product" -#~ msgstr "puede ver las reglas de stock mínimo desde producto" - -#~ msgid "This wizard will schedule procurements." -#~ msgstr "Este asistente planificará abastecimientos." - -#~ msgid "Internal Ref." -#~ msgstr "Ref. interna" - -#~ msgid "Status" -#~ msgstr "Estado" - -#~ msgid "Stockable Production Order" -#~ msgstr "Orden producción almacenable" - -#~ msgid "Stockable Request" -#~ msgstr "Solicitud almacenable" - -#, python-format -#~ msgid "Workcenter name" -#~ msgstr "Nombre centro de producción" - -#~ msgid "Service on Order" -#~ msgstr "Servicio sobre orden" - -#~ msgid "" -#~ "When the virtual stock goes belong the Min Quantity, Open ERP generates a " -#~ "procurement to bring the virtual stock to the Max Quantity." -#~ msgstr "" -#~ "Cuando el stock virtual disminuye por debajo de la cantidad mínima, OpenERP " -#~ "genera un abastecimiento para que el stock virtual sea la cantidad máxima." - -#~ msgid "Stockable Make to Stock" -#~ msgstr "Almacenable obtenido para stock" - -#~ msgid "Production Orders" -#~ msgstr "Órdenes de producción" - -#~ msgid "Procure Service Product" -#~ msgstr "Abastecer producto servicio" - -#, python-format -#~ msgid "Product Quantity" -#~ msgstr "Cantidad producto" - -#~ msgid "Procurements" -#~ msgstr "Abastecimientos" - -#~ msgid "Production scheduled products" -#~ msgstr "Producción planificada de productos" - -#~ msgid "Details" -#~ msgstr "Detalles" - -#~ msgid "Procurement Process" -#~ msgstr "Proceso de abastecimiento" - -#, python-format -#~ msgid "Product Standard Price" -#~ msgstr "Precio estándar producto" - -#~ msgid "" -#~ "Rounding applied on the product quantity. For integer only values, put 1.0" -#~ msgstr "" -#~ "Redondeo aplicado a la cantidad de producto. Para valores siempre enteros " -#~ "introduzca 1.0" - -#~ msgid "Reservation" -#~ msgstr "Reserva" - -#~ msgid "product" -#~ msgstr "producto" - -#~ msgid "max" -#~ msgstr "máx" - -#~ msgid "Product to stock rules" -#~ msgstr "Producto a reglas de stock" - -#, python-format -#~ msgid "from stock: products assigned." -#~ msgstr "desde stock: productos asignados." - -#~ msgid "Print product price" -#~ msgstr "Imprimir coste del producto" - -#~ msgid "Make Procurement" -#~ msgstr "Realizar abastecimiento" - -#~ msgid "If Procure method is Make to order and supply method is produce" -#~ msgstr "" -#~ "si método de abastecimiento es obtener bajo pedido y método de suministro es " -#~ "producir" - -#~ msgid "Purchase Lead Time" -#~ msgstr "Plazo de tiempo de compra" - -#~ msgid "Stockable Product Stock" -#~ msgstr "Stock de producto almacenable" - -#~ msgid "Production Procure Products" -#~ msgstr "Productos para abastecer la producción" - -#~ msgid "Service Product Process" -#~ msgstr "Proceso producto de servicios" - -#~ msgid "Procurement convert into the draft purchase order." -#~ msgstr "Abastecimiento se convierte en la orden de compra borrador." - -#~ msgid "Latest error" -#~ msgstr "Último error" - -#, python-format -#~ msgid "from stock and no minimum orderpoint rule defined" -#~ msgstr "desde stock y no se ha definido regla mínima generación orden" - -#~ msgid "Routing workcenter usage" -#~ msgstr "Procesos productivos del centro de producción" - -#~ msgid "If Product type is Stockable and procure method is make to stock" -#~ msgstr "" -#~ "Si el tipo de producto es almacenable y el método de abastecimiento es " -#~ "obtener para stock" - -#~ msgid "Manufacturity Lead Time" -#~ msgstr "Plazo de entrega de fabricación" - -#~ msgid "Exceptions Procurements to Fix" -#~ msgstr "Excepciones de abastecimientos a corregir" - -#~ msgid "Workcenter Operations" -#~ msgstr "Operaciones del centro de producción" - -#~ msgid "Production Orders Planning" -#~ msgstr "Planificación órdenes de producción" - -#~ msgid "Factor that multiplies all times expressed in the workcenter." -#~ msgstr "" -#~ "Factor que multiplica todos los tiempos expresados en el centro de " -#~ "producción." - -#~ msgid "" -#~ "This is the Internal Picking List take bring the raw materials to the " -#~ "production plan." -#~ msgstr "" -#~ "Ésta es la lista de empaquetado interna que lleva las materias primas a la " -#~ "producción planificada." - -#~ msgid "Qty Multiple" -#~ msgstr "Ctdad múltiple" - -#~ msgid "Waiting" -#~ msgstr "En espera" - -#~ msgid "For stockable and consumable" -#~ msgstr "Para almacenables y consumibles" - -#~ msgid "indice type" -#~ msgstr "Tipo de índice" - -#, python-format -#~ msgid "Hours Cost" -#~ msgstr "Coste horas" - -#~ msgid "Production orders are created for the product manufacturing." -#~ msgstr "Se crean órdenes de producción para la fabricación del producto." - -#~ msgid "Min Quantity" -#~ msgstr "Cantidad mín" - -#~ msgid "Production orders" -#~ msgstr "Órdenes de producción" - -#~ msgid "BoM Hyerarchy" -#~ msgstr "Jerarquía LdM" - -#~ msgid "Procurement Lines" -#~ msgstr "Líneas de abastecimiento" - -#~ msgid "If Product type is service and procure method is Make to stock" -#~ msgstr "" -#~ "si el tipo de producto es servicio y el método de abastecimiento es obtener " -#~ "para stock" - -#~ msgid "If Product type is service" -#~ msgstr "Si el tipo de producto es servicio" - -#, python-format -#~ msgid "SUBTOTAL" -#~ msgstr "SUBTOTAL" - -#~ msgid "Security Days" -#~ msgstr "Días de seguridad" - -#~ msgid "Exception" -#~ msgstr "Excepción" - -#~ msgid "" -#~ "This wizard will planify the procurement for this product. This procurement " -#~ "may generate task, production orders or purchase orders." -#~ msgstr "" -#~ "Este asistente planificará el abastecimiento para este producto. El " -#~ "abastecimiento puede generar tareas, órdenes de producción o órdenes de " -#~ "compra." - -#~ msgid "The system waits for requested products in stock." -#~ msgstr "El sistema espera los productos solicitados en stock." - -#~ msgid "Serivce Stockable Order" -#~ msgstr "Orden servicio almacenable" - -#~ msgid "From minimum stock rules, it goes for procure product." -#~ msgstr "Desde reglas de stock mínimo, va a abastecer el producto." - -#~ msgid "Production done" -#~ msgstr "Producción realizada" - -#, python-format -#~ msgid "Unit Product Price" -#~ msgstr "Precio producto unidad" - -#~ msgid "References" -#~ msgstr "Referencias" - -#~ msgid "Machine" -#~ msgstr "Fabricación" - -#~ msgid "Workcenter Name" -#~ msgstr "Nombre centro de producción" - -#~ msgid "min" -#~ msgstr "mín" - -#~ msgid "" -#~ "Description of the workcenter. Explain here what's a cycle according to this " -#~ "workcenter." -#~ msgstr "" -#~ "Descripción del centro de producción. Describa aquí que es un ciclo según " -#~ "este centro de producción." - -#~ msgid "Human Resource" -#~ msgstr "Recurso humano" - -#~ msgid "Workcenters" -#~ msgstr "Centros de producción" - -#~ msgid "on order" -#~ msgstr "bajo pedido" - -#~ msgid "Compute All Schedulers" -#~ msgstr "Calcular todas las planificaciones" - -#~ msgid "Create Procurement" -#~ msgstr "Crear abastecimiento" - -#, python-format -#~ msgid "Product uom" -#~ msgstr "UdM producto" - -#~ msgid "Number of Cycle" -#~ msgstr "Número de ciclos" - -#~ msgid "Run procurement" -#~ msgstr "Ejecutar abastecimiento" - -#~ msgid "" -#~ "This is the time frame analysed by the scheduler when computing " -#~ "procurements. All procurement that are not between today and today+range are " -#~ "skipped for futur computation." -#~ msgstr "" -#~ "Éste es el intervalo temporal analizado por el planificador al calcular " -#~ "abastecimientos. Todos los abastecimientos que no estén entre hoy y " -#~ "hoy+intervalo son omitidos para el cálculos futuros." - -#~ msgid "Time Efficiency" -#~ msgstr "Eficiencia temporal" - -#~ msgid "Scheduler Parameters" -#~ msgstr "Parámetros del planificador" - -#~ msgid "A cycle is defined in the workcenter definition." -#~ msgstr "En la definición de un centro de producción se define un ciclo." - -#~ msgid "Unit of Measure" -#~ msgstr "Unidad de medida" - -#~ msgid "Procurement Method" -#~ msgstr "Método abastecimiento" - -#~ msgid "Compute Procurements" -#~ msgstr "Calcular abastecimientos" - -#~ msgid "Wait for available products for reservation" -#~ msgstr "Esperar productos disponibles para reservarlos" - -#~ msgid "Validate" -#~ msgstr "Validar" - -#~ msgid "Procurement Purchase" -#~ msgstr "Compra de abastecimiento" - -#~ msgid "Number of products to produce" -#~ msgstr "Número de productos a producir" - -#~ msgid "Material routing" -#~ msgstr "Procesos productivos del material" - -#~ msgid "Minimum stock rule" -#~ msgstr "Regla de stock mínimo" - -#~ msgid "Product Efficiency" -#~ msgstr "Eficiencia del producto" - -#~ msgid "Orderpoint minimum rule" -#~ msgstr "Regla mínima generación orden" - -#~ msgid "Service Make to Stock" -#~ msgstr "Servicio obtener para stock" - -#~ msgid "Sale Ref" -#~ msgstr "Ref. venta" - -#~ msgid "Location" -#~ msgstr "Ubicación" - -#~ msgid "New Procurement" -#~ msgstr "Nuevo abastecimiento" - -#~ msgid "Tool" -#~ msgstr "Maquinaria" - -#~ msgid "" -#~ "Location where the system will look for products used in raw materials." -#~ msgstr "" -#~ "Ubicación donde el sistema buscará productos utilizados en las materias " -#~ "primas." - -#~ msgid "Planned Date" -#~ msgstr "Fecha prevista" - -#~ msgid "Procurement orders" -#~ msgstr "Órdenes de abastecimiento" - -#~ msgid "If product type is service and procure method is Make to order" -#~ msgstr "" -#~ "si el tipo de producto es servicio y el método de abastecimiento es obtener " -#~ "bajo pedido" - -#~ msgid "Scheduler Range" -#~ msgstr "Margen planificador" - -#~ msgid "Max Quantity" -#~ msgstr "Cantidad máx" - -#~ msgid "Minimum Stock Procure" -#~ msgstr "Abastecer stock mínimo" - -#~ msgid "This is the leads/security time for each purchase order." -#~ msgstr "Éste es el plazo/seguridad de tiempo para cada orden de compra." - -#~ msgid "alphabetical indices" -#~ msgstr "índices alfabéticos" - -#~ msgid "Procurement for raw materials." -#~ msgstr "Abastecimiento para materia primas." - -#~ msgid "Note" -#~ msgstr "Nota" - -#~ msgid "Procure Stockable Product" -#~ msgstr "Abastecimiento producto almacenable" - -#~ msgid "Paid ?" -#~ msgstr "¿Pagado?" - -#~ msgid "Define a routing to describe the manufacturing steps." -#~ msgstr "" -#~ "Definir un proceso productivo para describir los pasos de fabricación" - -#~ msgid "Define the product structure, with sub-products and/or components." -#~ msgstr "" -#~ "Definir la estructura del producto, con subproductos y/o componentes." - -#~ msgid "" -#~ "Procurement is created if the product quantity is lower than the minimum " -#~ "limit." -#~ msgstr "" -#~ "Se crea el abastecimiento si la cantidad de producto es menor que el límite " -#~ "mínimo." - -#~ msgid "Date Closed" -#~ msgstr "Fecha de cierre" - -#~ msgid "Properties composition" -#~ msgstr "Composición de propiedades" - -#~ msgid "Production Orders Waiting Products" -#~ msgstr "Órdenes de producción esperando productos" - -#~ msgid "Change Product Qty." -#~ msgstr "Cambiar Ctd. producto" - -#~ msgid "The procurement quantity will by rounded up to this multiple." -#~ msgstr "La cantidad abastecida será redondeada hacia arriba a este múltiplo." - -#~ msgid "Reordering Mode" -#~ msgstr "Modo de pedir de nuevo" - -#~ msgid "" -#~ "The Object name must start with x_ and not contain any special character !" -#~ msgstr "" -#~ "¡El nombre del objeto debe empezar con x_ y no contener ningún carácter " -#~ "especial!" - -#~ msgid "Central document to procure products" -#~ msgstr "Documento central para abastecer productos" - -#~ msgid "Production Orders in Progress" -#~ msgstr "Órdenes de producción en proceso" - -#~ msgid "Minimum Stock Rules" -#~ msgstr "Reglas de stock mínimo" - -#~ msgid "" -#~ "Reference of the document that created this procurement.\n" -#~ "This is automatically completed by Open ERP." -#~ msgstr "" -#~ "Referencia del documento que ha creado este abastecimiento.\n" -#~ "Éste es completado automáticamente por OpenERP." - -#~ msgid "Product type is Stockable and procure method is make to stock" -#~ msgstr "" -#~ "Tipo de producto es almacenable y método de abastecimiento es obtener para " -#~ "stock" - -#~ msgid "Product UoM" -#~ msgstr "UdM del producto" - -#~ msgid "Workcenter" -#~ msgstr "Centro de producción" - -#~ msgid "Purchase Order" -#~ msgstr "Orden de compra" - -#~ msgid "" -#~ "If you encode manually a procurement, you probably want to use a make to " -#~ "order method." -#~ msgstr "" -#~ "Si codifica manualmente un abastecimiento, probablemente desea usar un " -#~ "método obtener bajo pedido." - -#~ msgid "Stockable Order Request" -#~ msgstr "Solicitud orden almacenable" - -#~ msgid "numeric indices" -#~ msgstr "índices numéricos" - -#~ msgid "If Procure method is Make to order and supply method is buy" -#~ msgstr "" -#~ "si método de abastecimiento es obtener bajo pedido y método de suministro es " -#~ "comprar" - -#~ msgid "if Product type is Stockable in procurement order" -#~ msgstr "si el tipo de producto es almacenable en orden de abastecimiento" - -#~ msgid "Bill of material revisions" -#~ msgstr "Revisiones lista de material" - -#~ msgid "Planification" -#~ msgstr "Planificación" - -#~ msgid "" -#~ "Use a phantom bill of material in raw materials lines that have to be " -#~ "automatically computed in on eproduction order and not one per level.If you " -#~ "put \"Phantom/Set\" at the root level of a bill of material it is considered " -#~ "as a set or pack: the products are replaced by the components between the " -#~ "sale order to the picking without going through the production order.The " -#~ "normal BoM will generate one production order per BoM level." -#~ msgstr "" -#~ "Utilice una lista de materiales fantasma en líneas de materias primas que se " -#~ "deban calcular automáticamente en una orden de producción y no una por " -#~ "nivel. Si indica \"Fantasma/Conjunto\" en el nivel raíz de una lista de " -#~ "materiales es considerada como un conjunto o paquete: Los productos se " -#~ "reemplazan por los componentes entre el pedido de venta y el empaquetado sin " -#~ "generar la orden de producción. La LdM normal generará una orden de " -#~ "producción por nivel de LdM." - -#, python-format -#~ msgid "No address defined for the supplier" -#~ msgstr "No se ha definido dirección para el proveedor" - -#~ msgid "Your procurement request has been sent !" -#~ msgstr "¡Su petición de abastecimiento ha sido enviada!" - -#~ msgid "Internal Procurement Request" -#~ msgstr "Solicitud de abastecimiento interna" - -#~ msgid "Property Categories" -#~ msgstr "Categorías de propiedades" - -#~ msgid "Compute Procurements Only" -#~ msgstr "Calcular sólo abastecimientos" - -#~ msgid "Temporary Procurement Exceptions" -#~ msgstr "Excepciones de abastecimiento temporales" - -#~ msgid "Confirmed" -#~ msgstr "Confirmada" - -#~ msgid "Parameters" -#~ msgstr "Parámetros" - -#~ msgid "Production workcenters used" -#~ msgstr "Centros de producción utilizados" - -#~ msgid "Workcenters Utilisation" -#~ msgstr "Utilización del centro de producción" - -#~ msgid "" -#~ "Efficiency on the production. A factor of 0.9 means a loss of 10% in the " -#~ "production." -#~ msgstr "" -#~ "Eficiencia en la producción. Un factor de 0.9 significa una pérdida del 10% " -#~ "en la producción." - -#~ msgid "If procurement is make to order" -#~ msgstr "si abastecimiento es obtener bajo pedido" - -#~ msgid "Minimum Stock Rule" -#~ msgstr "Regla de stock mínimo" - -#~ msgid "New Bill of Materials" -#~ msgstr "Nueva lista de materiales" - -#, python-format -#~ msgid "Product quantity" -#~ msgstr "Cantidad producto" - -#~ msgid "Property" -#~ msgstr "Propiedad" - -#~ msgid "Canceled" -#~ msgstr "Cancelado" - -#~ msgid "plus" -#~ msgstr "más" - -#~ msgid "Stockable Product Process" -#~ msgstr "Proceso producto almacenable" - -#~ msgid "New Production Order" -#~ msgstr "Nueva orden de producción" - -#~ msgid "A Request for Quotation is created and sent to the supplier." -#~ msgstr "Una solicitud de presupuesto es creada y enviada al proveedor." - -#~ msgid "Retry" -#~ msgstr "Volver a intentar" - -#~ msgid "When any procuere products, it comes into the prpcurement orders" -#~ msgstr "" -#~ "Cuando alguien abastece productos, se convierte en las órdenes de " -#~ "abastecimiento" - -#~ msgid "Production Orders To Start" -#~ msgstr "Órdenes de producción a iniciar" - -#~ msgid "Procurement Reason" -#~ msgstr "Motivo del abastecimiento" - -#~ msgid "An entry is being made from billing material to routing." -#~ msgstr "Se crea una entrada desde material facturable a proceso productivo." - -#~ msgid "The normal working time of the workcenter." -#~ msgstr "El horario de trabajo normal del centro de producción." - -#~ msgid "Order to Max" -#~ msgstr "Ordenar el máximo" - -#~ msgid "In procurement order, if product type is service" -#~ msgstr "En orden de abastecimiento, si tipo de producto es servicio" - -#~ msgid "from stock" -#~ msgstr "desde stock" - -#~ msgid "Close" -#~ msgstr "Cerrar" - -#, python-format -#~ msgid "TOTAL" -#~ msgstr "TOTAL" - -#~ msgid "Sale Name" -#~ msgstr "Nombre venta" - -#, python-format -#~ msgid "Product supplier" -#~ msgstr "Proveedor producto" - -#~ msgid "Create minimum stock rules" -#~ msgstr "Crear reglas de stock mínimo" - -#~ msgid "Warehouse" -#~ msgstr "Almacén" - -#~ msgid "Service Product" -#~ msgstr "Producto servicio" - -#~ msgid "Close Move at end" -#~ msgstr "Movimiento de cierre al final" - -#~ msgid "Running" -#~ msgstr "En proceso" - -#~ msgid "Unscheduled procurements" -#~ msgstr "Abastecimientos no planificados" - -#~ msgid "Bill of Material Structure" -#~ msgstr "Despiece de la lista de materiales" - -#~ msgid "Workcenter load" -#~ msgstr "Carga del centro de producción" - -#~ msgid "Procurement Details" -#~ msgstr "Detalles de abastecimiento" - -#~ msgid "You can see its bill of material which are used to make product" -#~ msgstr "" -#~ "Puede ver su lista de material que se utiliza para fabricar el producto" - -#~ msgid "Bill of Materials Components" -#~ msgstr "Componentes de la lista de materiales" - -#, python-format -#~ msgid "Warning !" -#~ msgstr "¡Aviso!" - -#, python-format -#~ msgid "" -#~ "The production is in \"%s\" state. You can not change the production " -#~ "quantity anymore" -#~ msgstr "" -#~ "La producción está en estado \"%s\". Ya no puede cambiar la cantidad a " -#~ "producir." - -#~ msgid "Production Workcenters" -#~ msgstr "Centros de producción" - -#~ msgid "Invalid model name in the action definition." -#~ msgstr "Nombre de modelo no válido en la definición de acción." - -#~ msgid "" -#~ "The list of operations (list of workcenters) to produce the finished " -#~ "product. The routing is mainly used to compute workcenter costs during " -#~ "operations and to plan futur loads on workcenters based on production " -#~ "plannification." -#~ msgstr "" -#~ "La lista de operaciones (lista de centros de producción) para producir el " -#~ "producto terminado. La ruta se utiliza principalmente para calcular los " -#~ "costes de los centros de producción durante la fabricación y para prever " -#~ "futuras cargas de los centros de producción a partir de la planificación de " -#~ "la producción." - -#~ msgid "Workcenter Usage" -#~ msgstr "Uso centro de producción" - -#~ msgid "" -#~ "Routing indicates all the workcenters used, for how long and/or cycles.If " -#~ "Routing is indicated then,the third tab of a production order (workcenters) " -#~ "will be automatically pre-completed." -#~ msgstr "" -#~ "La ruta indica todos los centros de producción utilizados, por cuánto tiempo " -#~ "y/o ciclos. Si se indica la ruta, entonces la tercera pestaña de una orden " -#~ "de producción (centros de producción) será automáticamente pre-completada." - -#~ msgid "" -#~ "Number of operations this work center can do in parallel. If this work " -#~ "center represents a team of 5 workers, the capacity per cycle is 5." -#~ msgstr "" -#~ "El número de operaciones de este centro de trabajo se puede hacer en " -#~ "paralelo. Si este centro de trabajo representa un equipo del 5 trabajadores, " -#~ "la capacidad por ciclo es de 5." - -#~ msgid "" -#~ "Description of the work center. Explain here what's a cycle according to " -#~ "this work center." -#~ msgstr "" -#~ "Descripción del centro de trabajo. Explique aquí lo que es un ciclo de " -#~ "acuerdo con este centro de trabajo." - -#~ msgid "Specify Cost of Work center per cycle." -#~ msgstr "Especificar costes del centro de trabajo por ciclo." - -#~ msgid "" -#~ "\n" -#~ " This is the base module to manage the manufacturing process in OpenERP.\n" -#~ "\n" -#~ " Features:\n" -#~ " * Make to Stock / Make to Order (by line)\n" -#~ " * Multi-level BoMs, no limit\n" -#~ " * Multi-level routing, no limit\n" -#~ " * Routing and work center integrated with analytic accounting\n" -#~ " * Scheduler computation periodically / Just In Time module\n" -#~ " * Multi-pos, multi-warehouse\n" -#~ " * Different reordering policies\n" -#~ " * Cost method by product: standard price, average price\n" -#~ " * Easy analysis of troubles or needs\n" -#~ " * Very flexible\n" -#~ " * Allows to browse Bill of Materials in complete structure\n" -#~ " that include child and phantom BoMs\n" -#~ " It supports complete integration and planification of stockable goods,\n" -#~ " consumable of services. Services are completely integrated with the " -#~ "rest\n" -#~ " of the software. For instance, you can set up a sub-contracting service\n" -#~ " in a BoM to automatically purchase on order the assembly of your " -#~ "production.\n" -#~ "\n" -#~ " Reports provided by this module:\n" -#~ " * Bill of Material structure and components\n" -#~ " * Load forecast on workcenters\n" -#~ " * Print a production order\n" -#~ " * Stock forecasts\n" -#~ " Dashboard provided by this module::\n" -#~ " * List of next production orders\n" -#~ " * List of deliveries (out picking)\n" -#~ " * Graph of work center load\n" -#~ " * List of procurement in exception\n" -#~ " " -#~ msgstr "" -#~ "\n" -#~ " Este es el módulo base para gestionar los procesos de fabricación en " -#~ "OpenERP.\n" -#~ "\n" -#~ " Características:\n" -#~ " *Obtener para stock / Obtener bajo pedido (por línea)\n" -#~ " *BoMs multi-niveles, sin límite\n" -#~ " *Ubicaciones multi-nivel, sin límite\n" -#~ " *Ubicaciones y centros de trabajo integrados con la contabilidad " -#~ "analítica\n" -#~ " *Ejecución periódica del cálculo de la planificación / Módulo 'Just In " -#~ "Time'\n" -#~ " *Multi-pv, multi-almacén\n" -#~ " *Diferentes políticas de pedido\n" -#~ " *Método de coste por producto: precio estándar, precio medio\n" -#~ " *Fácil análisis de problemas o necesidades\n" -#~ " *Muy flexible\n" -#~ " *Permite inspeccionar la estructura completa de Facturas de Materiales\n" -#~ " que incluyen BoMs hijas y fantasmas\n" -#~ " Soporta integración y planificación de mercancías almacenables,\n" -#~ " y consumo de servicios. Los servicios se integran completamente con el " -#~ "resto\n" -#~ " de la aplicación. Por ejemplo, se puede establecer una servicio de " -#~ "subcontratación\n" -#~ " en una BoM para encargar automáticamente el montaje de su producción.\n" -#~ "\n" -#~ " Los informes que facilita este módulo:\n" -#~ " *Componentes y estructura de la BoMs\n" -#~ " *Previsión de carga de los centros de trabajo\n" -#~ " *Previsión de almacén\n" -#~ " Tableros proporcionados en este módulo:\n" -#~ " *Lista de órdenes de producción próximas\n" -#~ " *Lista de entregas\n" -#~ " *Gráfico de carga del centro de trabajo\n" -#~ " *Lista de órdenes de fabricación con excepciones\n" -#~ " " +msgstr "" diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 58fcacaa1f5..7fb40ce12af 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -70,7 +70,6 @@ class mrp_workcenter(osv.osv): value = {'costs_hour': cost.standard_price} return {'value': value} -mrp_workcenter() class mrp_routing(osv.osv): @@ -98,7 +97,6 @@ class mrp_routing(osv.osv): 'active': lambda *a: 1, 'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.routing', context=context) } -mrp_routing() class mrp_routing_workcenter(osv.osv): """ @@ -124,7 +122,6 @@ class mrp_routing_workcenter(osv.osv): 'cycle_nbr': lambda *a: 1.0, 'hour_nbr': lambda *a: 0.0, } -mrp_routing_workcenter() class mrp_bom(osv.osv): """ diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index f3da234463c..2af1e876c70 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -701,11 +701,6 @@ -
diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py index 73707e39807..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): @@ -374,7 +373,7 @@ class product_pricelist_item(osv.osv): result.append((line.id, line.name)) result.append((-1, _('Other Pricelist'))) - result.append((-2, _('Partner section of the product form'))) + result.append((-2, _('Supplier Prices on the product form'))) return result _name = "product.pricelist.item" @@ -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/product.py b/addons/product/product.py index 33225c92c6f..518e455ddc1 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() #---------------------------------------------------------- @@ -401,7 +397,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 +518,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 +556,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", @@ -588,10 +594,13 @@ class product_product(osv.osv): # Check if the product is last product of this template other_product_ids = self.search(cr, uid, [('product_tmpl_id', '=', tmpl_id), ('id', '!=', product.id)], context=context) if not other_product_ids: - unlink_product_tmpl_ids.append(tmpl_id) + unlink_product_tmpl_ids.append(tmpl_id) unlink_ids.append(product.id) + res = super(product_product, self).unlink(cr, uid, unlink_ids, context=context) + # delete templates after calling super, as deleting template could lead to deleting + # products due to ondelete='cascade' self.pool.get('product.template').unlink(cr, uid, unlink_product_tmpl_ids, context=context) - return super(product_product, self).unlink(cr, uid, unlink_ids, context=context) + return res def onchange_uom(self, cursor, user, ids, uom_id, uom_po_id): if uom_id and uom_po_id: @@ -750,7 +759,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" @@ -816,7 +824,6 @@ class product_packaging(osv.osv): return (10 - (sum % 10)) % 10 checksum = staticmethod(checksum) -product_packaging() class product_supplierinfo(osv.osv): @@ -890,7 +897,6 @@ class product_supplierinfo(osv.osv): res[supplier.id] = price return res _order = 'sequence' -product_supplierinfo() class pricelist_partnerinfo(osv.osv): @@ -902,7 +908,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_report.xml b/addons/product/product_report.xml index 6135fe64bca..791063696c4 100644 --- a/addons/product/product_report.xml +++ b/addons/product/product_report.xml @@ -9,6 +9,7 @@ name="product.pricelist" rml="product/report/product_pricelist.rml" menu="False" - auto="False"/> + parser="product.report.product_pricelist.product_pricelist" + /> diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml index ddb1ab3809f..00e925fd6a0 100644 --- a/addons/product/product_view.xml +++ b/addons/product/product_view.xml @@ -581,6 +581,7 @@ +

The prices below will only be taken into account when your pricelist is set as based on supplier prices.

diff --git a/addons/product/report/product_pricelist.py b/addons/product/report/product_pricelist.py index 5e9f8cf0a8a..44433f39055 100644 --- a/addons/product/report/product_pricelist.py +++ b/addons/product/report/product_pricelist.py @@ -21,7 +21,6 @@ import time -from openerp import pooler from openerp.osv import osv from openerp.report import report_sxw from openerp.tools.translate import _ @@ -63,20 +62,17 @@ class product_pricelist(report_sxw.rml_parse): return True def _get_pricelist(self, pricelist_id): - pool = pooler.get_pool(self.cr.dbname) - pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['name'], context=self.localcontext)[0] + pricelist = self.pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['name'], context=self.localcontext)[0] return pricelist['name'] def _get_currency(self, pricelist_id): - pool = pooler.get_pool(self.cr.dbname) - pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0] + pricelist = self.pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0] return pricelist['currency_id'][1] # TODO 7.0 - remove this method, its unused def _get_currency_symbol(self, pricelist_id): - pool = pooler.get_pool(self.cr.dbname) - pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0] - symbol = pool.get('res.currency').read(self.cr, self.uid, [pricelist['currency_id'][0]], ['symbol'], context=self.localcontext)[0] + pricelist = self.pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0] + symbol = self.pool.get('res.currency').read(self.cr, self.uid, [pricelist['currency_id'][0]], ['symbol'], context=self.localcontext)[0] return symbol['symbol'] or '' def _get_categories(self, products, form): @@ -84,20 +80,19 @@ class product_pricelist(report_sxw.rml_parse): res=[] self.pricelist = form['price_list'] self._set_quantity(form) - pool = pooler.get_pool(self.cr.dbname) pro_ids=[] for product in products: pro_ids.append(product.id) if product.categ_id.id not in cat_ids: cat_ids.append(product.categ_id.id) - cats = pool.get('product.category').name_get(self.cr, self.uid, cat_ids, context=self.localcontext) + cats = self.pool.get('product.category').name_get(self.cr, self.uid, cat_ids, context=self.localcontext) if not cats: return res for cat in cats: - product_ids=pool.get('product.product').search(self.cr, self.uid, [('id', 'in', pro_ids), ('categ_id', '=', cat[0])], context=self.localcontext) + product_ids=self.pool.get('product.product').search(self.cr, self.uid, [('id', 'in', pro_ids), ('categ_id', '=', cat[0])], context=self.localcontext) products = [] - for product in pool.get('product.product').read(self.cr, self.uid, product_ids, ['name', 'code'], context=self.localcontext): + for product in self.pool.get('product.product').read(self.cr, self.uid, product_ids, ['name', 'code'], context=self.localcontext): val = { 'id':product['id'], 'name':product['name'], @@ -116,16 +111,13 @@ class product_pricelist(report_sxw.rml_parse): def _get_price(self, pricelist_id, product_id, qty): sale_price_digits = self.get_digits(dp='Product Price') - pool = pooler.get_pool(self.cr.dbname) pricelist = self.pool.get('product.pricelist').browse(self.cr, self.uid, [pricelist_id], context=self.localcontext)[0] - price_dict = pool.get('product.pricelist').price_get(self.cr, self.uid, [pricelist_id], product_id, qty, context=self.localcontext) + price_dict = self.pool.get('product.pricelist').price_get(self.cr, self.uid, [pricelist_id], product_id, qty, context=self.localcontext) if price_dict[pricelist_id]: price = self.formatLang(price_dict[pricelist_id], digits=sale_price_digits, currency_obj=pricelist.currency_id) else: - res = pool.get('product.product').read(self.cr, self.uid, [product_id]) + res = self.pool.get('product.product').read(self.cr, self.uid, [product_id]) price = self.formatLang(res[0]['list_price'], digits=sale_price_digits, currency_obj=pricelist.currency_id) return price -report_sxw.report_sxw('report.product.pricelist','product.product','addons/product/report/product_pricelist.rml',parser=product_pricelist) - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: 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 e939e594437..4d8fd49ec4f 100644 --- a/addons/product_expiry/product_expiry.py +++ b/addons/product_expiry/product_expiry.py @@ -19,8 +19,9 @@ ############################################################################## import datetime + +import openerp from openerp.osv import fields, osv -from openerp import pooler class stock_production_lot(osv.osv): _inherit = 'stock.production.lot' @@ -34,7 +35,7 @@ class stock_production_lot(osv.osv): if not context.get('product_id', False): date = False else: - product = pooler.get_pool(cr.dbname).get('product.product').browse( + product = openerp.registry(cr.dbname)['product.product'].browse( cr, uid, context['product_id']) duration = getattr(product, dtype) # set date to False when no expiry time specified on the product @@ -73,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' @@ -87,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/project.py b/addons/project/project.py index 5263fea9166..8d7f09f8c4e 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -208,6 +208,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', 'All Users'), + ('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 +235,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 +275,7 @@ 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), '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') } @@ -286,7 +294,6 @@ class project(osv.osv): 'type_ids': _get_type_common, 'alias_model': 'project.task', 'privacy_visibility': 'public', - 'alias_domain': False, # always hide alias during creation } # TODO: Why not using a SQL contraints ? @@ -531,11 +538,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 @@ -605,8 +612,7 @@ class task(base_stage, osv.osv): search_domain = [] project_id = self._resolve_project_id_from_context(cr, uid, context=context) if project_id: - search_domain += ['|', ('project_ids', '=', project_id)] - search_domain += [('id', 'in', ids)] + search_domain += [('project_ids', '=', project_id)] stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context) result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context) # restore order of the search @@ -889,6 +895,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 # ---------------------------------------- diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml index 025327d70b3..7bf1a623a2c 100644 --- a/addons/project/project_data.xml +++ b/addons/project/project_data.xml @@ -21,6 +21,7 @@ Projects 3 + view diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 16dbe44ccc1..298355d4c82 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -50,16 +50,17 @@ 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, + } -

- 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 +88,17 @@

+
+
-

+
+ %% +
Tasks @@ -622,13 +628,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_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..4bbaa9b788e 100644 --- a/addons/project/security/project_security.xml +++ b/addons/project/security/project_security.xml @@ -38,39 +38,62 @@ - 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 following or assigned - - ['|','|','|',('user_id','=',False),('user_id','=',user.id),('project_id.members','in', [user.id]),('project_id.user_id','=',user.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/wizard/project_gtd_empty.py b/addons/project_gtd/wizard/project_gtd_empty.py index 26e438b789e..36c64cbc224 100644 --- a/addons/project_gtd/wizard/project_gtd_empty.py +++ b/addons/project_gtd/wizard/project_gtd_empty.py @@ -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/i18n/cs.po b/addons/project_issue/i18n/cs.po new file mode 100644 index 00000000000..cab9361dc60 --- /dev/null +++ b/addons/project_issue/i18n/cs.po @@ -0,0 +1,984 @@ +# Czech 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-03-31 16:53+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: project_issue +#: model:project.category,name:project_issue.project_issue_category_03 +msgid "Deadly bug" +msgstr "" + +#. module: project_issue +#: help:project.config.settings,fetchmail_issue:0 +msgid "" +"Allows you to configure your incoming mail server, and create issues from " +"incoming emails." +msgstr "" + +#. module: project_issue +#: field:project.issue.report,delay_open:0 +msgid "Avg. Delay to Open" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: view:project.issue.report:0 +msgid "Group By..." +msgstr "" + +#. module: project_issue +#: field:project.issue,working_hours_open:0 +msgid "Working Hours to Open the Issue" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,description:project_issue.mt_issue_started +msgid "Issue started" +msgstr "" + +#. module: project_issue +#: field:project.issue,date_open:0 +msgid "Opened" +msgstr "" + +#. module: project_issue +#: field:project.issue.report,opening_date:0 +msgid "Date of Opening" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "March" +msgstr "" + +#. module: project_issue +#: field:project.issue,progress:0 +msgid "Progress (%)" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: field:project.issue,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: project_issue +#: field:project.issue,company_id:0 +#: view:project.issue.report:0 +#: field:project.issue.report,company_id:0 +msgid "Company" +msgstr "" + +#. module: project_issue +#: field:project.issue,email_cc:0 +msgid "Watchers Emails" +msgstr "" + +#. module: project_issue +#: help:project.issue,kanban_state:0 +msgid "" +"A Issue's kanban state indicates special situations affecting it:\n" +" * Normal is the default situation\n" +" * Blocked indicates something is preventing the progress of this issue\n" +" * Ready for next stage indicates the issue is ready to be pulled to the " +"next stage" +msgstr "" + +#. module: project_issue +#: help:project.issue,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: project_issue +#: help:account.analytic.account,use_issues:0 +msgid "Check this field if this project manages issues" +msgstr "" + +#. module: project_issue +#: field:project.issue,day_open:0 +msgid "Days to Open" +msgstr "" + +#. module: project_issue +#: code:addons/project_issue/project_issue.py:473 +#, python-format +msgid "" +"You cannot escalate this issue.\n" +"The relevant Project has not configured the Escalation Project!" +msgstr "" + +#. module: project_issue +#: constraint:project.project:0 +msgid "Error! You cannot assign escalation to the same project!" +msgstr "" + +#. module: project_issue +#: selection:project.issue,priority:0 +#: selection:project.issue.report,priority:0 +msgid "Highest" +msgstr "" + +#. module: project_issue +#: help:project.issue,inactivity_days:0 +msgid "Difference in days between last action and current date" +msgstr "" + +#. module: project_issue +#: view:project.issue.report:0 +#: field:project.issue.report,day:0 +msgid "Day" +msgstr "" + +#. module: project_issue +#: field:project.issue,days_since_creation:0 +msgid "Days since creation date" +msgstr "" + +#. module: project_issue +#: field:project.issue,task_id:0 +#: view:project.issue.report:0 +#: field:project.issue.report,task_id:0 +msgid "Task" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,name:project_issue.mt_project_issue_stage +msgid "Issue Stage Changed" +msgstr "" + +#. module: project_issue +#: field:project.issue,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: project_issue +#: field:project.issue,inactivity_days:0 +msgid "Days since last action" +msgstr "" + +#. module: project_issue +#: model:ir.model,name:project_issue.model_project_project +#: view:project.issue:0 +#: field:project.issue,project_id:0 +#: view:project.issue.report:0 +#: field:project.issue.report,project_id:0 +msgid "Project" +msgstr "" + +#. module: project_issue +#: model:ir.actions.act_window,help:project_issue.project_issue_categ_act0 +msgid "" +"

\n" +" Click to report a new issue.\n" +"

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

\n" +" " +msgstr "" + +#. module: project_issue +#: selection:project.issue,state:0 +#: selection:project.issue.report,state:0 +msgid "Cancelled" +msgstr "" + +#. module: project_issue +#: field:project.issue,description:0 +msgid "Private Note" +msgstr "" + +#. module: project_issue +#: field:project.issue.report,date_closed:0 +msgid "Date of Closing" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Issue Tracker Search" +msgstr "" + +#. module: project_issue +#: field:project.issue,color:0 +msgid "Color Index" +msgstr "" + +#. module: project_issue +#: field:project.issue.report,working_hours_open:0 +msgid "Avg. Working Hours to Open" +msgstr "" + +#. module: project_issue +#: model:ir.model,name:project_issue.model_account_analytic_account +msgid "Analytic Account" +msgstr "" + +#. module: project_issue +#: help:project.issue,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_issue +#: help:project.project,project_escalation_id:0 +msgid "" +"If any issue is escalated from the current Project, it will be listed under " +"the project selected here." +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Extra Info" +msgstr "" + +#. module: project_issue +#: model:ir.actions.act_window,help:project_issue.action_project_issue_report +msgid "" +"This report on the project issues allows you to analyse the quality of your " +"support or after-sales services. You can track the issues per age. You can " +"analyse the time required to open or close an issue, the number of email to " +"exchange and the time spent on average by issues." +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Edit..." +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Responsible" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Statistics" +msgstr "" + +#. module: project_issue +#: field:project.issue,kanban_state:0 +msgid "Kanban State" +msgstr "" + +#. module: project_issue +#: code:addons/project_issue/project_issue.py:368 +#, python-format +msgid "Project issue converted to task." +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: field:project.issue,priority:0 +#: view:project.issue.report:0 +#: field:project.issue.report,priority:0 +msgid "Priority" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: field:project.issue,version_id:0 +#: view:project.issue.report:0 +#: field:project.issue.report,version_id:0 +msgid "Version" +msgstr "" + +#. module: project_issue +#: field:project.issue,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: selection:project.issue,state:0 +#: view:project.issue.report:0 +msgid "New" +msgstr "" + +#. module: project_issue +#: model:ir.actions.act_window,name:project_issue.project_issue_categ_action +msgid "Issue Categories" +msgstr "" + +#. module: project_issue +#: field:project.issue,email_from:0 +msgid "Email" +msgstr "" + +#. module: project_issue +#: field:project.issue,channel_id:0 +#: field:project.issue.report,channel_id:0 +msgid "Channel" +msgstr "" + +#. module: project_issue +#: selection:project.issue,priority:0 +#: selection:project.issue.report,priority:0 +msgid "Lowest" +msgstr "" + +#. module: project_issue +#: code:addons/project_issue/project_issue.py:390 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Unassigned Issues" +msgstr "" + +#. module: project_issue +#: field:project.issue,create_date:0 +#: view:project.issue.report:0 +#: field:project.issue.report,creation_date:0 +msgid "Creation Date" +msgstr "" + +#. module: project_issue +#: model:ir.actions.act_window,name:project_issue.project_issue_version_action +#: model:ir.ui.menu,name:project_issue.menu_project_issue_version_act +msgid "Versions" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "To Do Issues" +msgstr "" + +#. module: project_issue +#: model:ir.model,name:project_issue.model_project_issue_version +msgid "project.issue.version" +msgstr "" + +#. module: project_issue +#: field:project.config.settings,fetchmail_issue:0 +msgid "Create issues from an incoming email account " +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: selection:project.issue,state:0 +#: view:project.issue.report:0 +msgid "Done" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "July" +msgstr "" + +#. module: project_issue +#: model:ir.ui.menu,name:project_issue.menu_project_issue_category_act +msgid "Categories" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: field:project.issue,stage_id:0 +#: view:project.issue.report:0 +#: field:project.issue.report,stage_id:0 +msgid "Stage" +msgstr "" + +#. module: project_issue +#: model:ir.actions.act_window,name:project_issue.action_project_issue_report +#: model:ir.ui.menu,name:project_issue.menu_project_issue_report_tree +#: view:project.issue.report:0 +msgid "Issues Analysis" +msgstr "" + +#. module: project_issue +#: code:addons/project_issue/project_issue.py:507 +#, python-format +msgid "No Subject" +msgstr "" + +#. module: project_issue +#: model:ir.actions.act_window,name:project_issue.action_view_my_project_issue_tree +msgid "My Project Issues" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: field:project.issue,partner_id:0 +#: view:project.issue.report:0 +#: field:project.issue.report,partner_id:0 +msgid "Contact" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Delete" +msgstr "" + +#. module: project_issue +#: code:addons/project_issue/project_issue.py:373 +#, python-format +msgid "Tasks" +msgstr "" + +#. module: project_issue +#: field:project.issue.report,nbr:0 +msgid "# of Issues" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "September" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "December" +msgstr "" + +#. module: project_issue +#: field:project.issue,categ_ids:0 +msgid "Tags" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Issue Tracker Tree" +msgstr "" + +#. module: project_issue +#: model:project.category,name:project_issue.project_issue_category_01 +msgid "Little problem" +msgstr "" + +#. module: project_issue +#: view:project.project:0 +msgid "creates" +msgstr "" + +#. module: project_issue +#: model:crm.case.categ,name:project_issue.feature_request_categ +msgid "Feature Requests" +msgstr "" + +#. module: project_issue +#: field:project.issue,write_date:0 +msgid "Update Date" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Project:" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Open Features" +msgstr "" + +#. module: project_issue +#: field:project.issue,date_action_next:0 +msgid "Next Action" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: selection:project.issue,kanban_state:0 +msgid "Blocked" +msgstr "" + +#. module: project_issue +#: field:project.issue,user_email:0 +msgid "User Email" +msgstr "" + +#. module: project_issue +#: view:project.issue.report:0 +msgid "#Number of Project Issues" +msgstr "" + +#. module: project_issue +#: help:project.issue,channel_id:0 +msgid "Communication channel." +msgstr "" + +#. module: project_issue +#: help:project.issue,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: project_issue +#: model:crm.case.categ,name:project_issue.bug_categ +msgid "Maintenance" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,state:0 +msgid "Draft" +msgstr "" + +#. module: project_issue +#: selection:project.issue,priority:0 +#: selection:project.issue.report,priority:0 +msgid "Low" +msgstr "" + +#. module: project_issue +#: field:project.issue,date_closed:0 +#: selection:project.issue.report,state:0 +msgid "Closed" +msgstr "" + +#. module: project_issue +#: field:project.issue.report,delay_close:0 +msgid "Avg. Delay to Close" +msgstr "" + +#. module: project_issue +#: selection:project.issue,state:0 +#: view:project.issue.report:0 +#: selection:project.issue.report,state:0 +msgid "Pending" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: field:project.issue,state:0 +#: field:project.issue.report,state:0 +msgid "Status" +msgstr "" + +#. module: project_issue +#: view:project.issue.report:0 +msgid "#Project Issues" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "August" +msgstr "" + +#. module: project_issue +#: selection:project.issue,kanban_state:0 +#: selection:project.issue,priority:0 +#: selection:project.issue.report,priority:0 +msgid "Normal" +msgstr "" + +#. module: project_issue +#: field:project.project,issue_count:0 +msgid "unknown" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Category:" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "June" +msgstr "" + +#. module: project_issue +#: help:project.issue,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "New Issues" +msgstr "" + +#. module: project_issue +#: field:project.issue,day_close:0 +msgid "Days to Close" +msgstr "" + +#. module: project_issue +#: field:project.issue,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: project_issue +#: help:project.issue,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_issue +#: field:project.issue,active:0 +#: field:project.issue.version,active:0 +msgid "Active" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "November" +msgstr "" + +#. module: project_issue +#: code:addons/project_issue/project_issue.py:473 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: project_issue +#: view:project.issue.report:0 +msgid "Search" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "October" +msgstr "" + +#. module: project_issue +#: help:project.issue,days_since_creation:0 +msgid "Difference in days between creation date and current date" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "January" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Feature Tracker Tree" +msgstr "" + +#. module: project_issue +#: help:project.issue,email_from:0 +msgid "These people will receive email." +msgstr "" + +#. module: project_issue +#: field:project.issue,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: project_issue +#: field:project.issue,date:0 +msgid "Date" +msgstr "" + +#. module: project_issue +#: field:project.issue,user_id:0 +#: view:project.issue.report:0 +#: field:project.issue.report,user_id:0 +msgid "Assigned to" +msgstr "" + +#. module: project_issue +#: view:project.config.settings:0 +msgid "Configure" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,description:project_issue.mt_issue_closed +msgid "Issue closed" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Current Features" +msgstr "" + +#. module: project_issue +#: view:project.issue.version:0 +msgid "Issue Version" +msgstr "" + +#. module: project_issue +#: field:project.issue.version,name:0 +msgid "Version Number" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Cancel" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,state:0 +msgid "Open" +msgstr "" + +#. module: project_issue +#: field:account.analytic.account,use_issues:0 +#: model:ir.actions.act_window,name:project_issue.act_project_project_2_project_issue_all +#: model:ir.actions.act_window,name:project_issue.project_issue_categ_act0 +#: model:ir.ui.menu,name:project_issue.menu_project_confi +#: model:ir.ui.menu,name:project_issue.menu_project_issue_track +#: view:project.issue:0 +#: view:project.project:0 +msgid "Issues" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: selection:project.issue,state:0 +msgid "In Progress" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: view:project.issue.report:0 +msgid "To Do" +msgstr "" + +#. module: project_issue +#: model:ir.model,name:project_issue.model_project_issue +#: view:project.issue.report:0 +msgid "Project Issue" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Creation Month" +msgstr "" + +#. module: project_issue +#: help:project.issue,progress:0 +msgid "Computed as: Time Spent / Total Time." +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: selection:project.issue,kanban_state:0 +msgid "Ready for next stage" +msgstr "" + +#. module: project_issue +#: view:project.issue.report:0 +#: field:project.issue.report,section_id:0 +msgid "Sale Team" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: view:project.issue.report:0 +#: field:project.issue.report,month:0 +msgid "Month" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +#: field:project.issue,name:0 +#: view:project.project:0 +msgid "Issue" +msgstr "" + +#. module: project_issue +#: model:project.category,name:project_issue.project_issue_category_02 +msgid "PBCK" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Feature Tracker Search" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Description" +msgstr "" + +#. module: project_issue +#: field:project.issue,section_id:0 +msgid "Sales Team" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "May" +msgstr "" + +#. module: project_issue +#: model:ir.model,name:project_issue.model_project_config_settings +msgid "project.config.settings" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,name:project_issue.mt_issue_closed +#: model:mail.message.subtype,name:project_issue.mt_project_issue_closed +msgid "Issue Closed" +msgstr "" + +#. module: project_issue +#: view:project.issue.report:0 +#: field:project.issue.report,email:0 +msgid "# Emails" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,name:project_issue.mt_issue_new +#: model:mail.message.subtype,name:project_issue.mt_project_issue_new +msgid "Issue Created" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,name:project_issue.mt_issue_blocked +#: model:mail.message.subtype,name:project_issue.mt_project_issue_blocked +msgid "Issue Blocked" +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "February" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,description:project_issue.mt_issue_stage +#: model:mail.message.subtype,description:project_issue.mt_project_issue_stage +msgid "Stage changed" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "Feature description" +msgstr "" + +#. module: project_issue +#: field:project.project,project_escalation_id:0 +msgid "Project Escalation" +msgstr "" + +#. module: project_issue +#: model:ir.actions.act_window,help:project_issue.project_issue_version_action +msgid "" +"

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

\n" +" Define here the different versions of your products on " +"which\n" +" you can work on issues.\n" +"

\n" +" " +msgstr "" + +#. module: project_issue +#: help:project.issue,section_id:0 +msgid "" +"Sales team to which Case belongs to. Define " +"Responsible user and Email account for mail gateway." +msgstr "" + +#. module: project_issue +#: view:board.board:0 +msgid "My Issues" +msgstr "" + +#. module: project_issue +#: help:project.issue.report,delay_open:0 +msgid "Number of Days to open the project issue." +msgstr "" + +#. module: project_issue +#: selection:project.issue.report,month:0 +msgid "April" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "⇒ Escalate" +msgstr "" + +#. module: project_issue +#: view:project.issue:0 +msgid "References" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,description:project_issue.mt_issue_new +msgid "Issue created" +msgstr "" + +#. module: project_issue +#: field:project.issue,working_hours_close:0 +msgid "Working Hours to Close the Issue" +msgstr "" + +#. module: project_issue +#: field:project.issue,id:0 +msgid "ID" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,description:project_issue.mt_issue_blocked +msgid "Issue blocked" +msgstr "" + +#. module: project_issue +#: model:ir.model,name:project_issue.model_project_issue_report +msgid "project.issue.report" +msgstr "" + +#. module: project_issue +#: help:project.issue.report,delay_close:0 +msgid "Number of Days to close the project issue" +msgstr "" + +#. module: project_issue +#: field:project.issue.report,working_hours_close:0 +msgid "Avg. Working Hours to Close" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,name:project_issue.mt_issue_stage +msgid "Stage Changed" +msgstr "" + +#. module: project_issue +#: selection:project.issue,priority:0 +#: selection:project.issue.report,priority:0 +msgid "High" +msgstr "" + +#. module: project_issue +#: field:project.issue,date_deadline:0 +msgid "Deadline" +msgstr "" + +#. module: project_issue +#: field:project.issue,date_action_last:0 +msgid "Last Action" +msgstr "" + +#. module: project_issue +#: view:project.issue.report:0 +#: field:project.issue.report,name:0 +msgid "Year" +msgstr "" + +#. module: project_issue +#: field:project.issue,duration:0 +msgid "Duration" +msgstr "" + +#. module: project_issue +#: model:mail.message.subtype,name:project_issue.mt_issue_started +#: model:mail.message.subtype,name:project_issue.mt_project_issue_started +msgid "Issue Started" +msgstr "" diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index a8f2ba28553..517d335aa48 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -40,7 +40,6 @@ class project_issue_version(osv.osv): _defaults = { 'active': 1, } -project_issue_version() class project_issue(base_stage, osv.osv): _name = "project.issue" @@ -137,6 +136,13 @@ class project_issue(base_stage, osv.osv): res = {} for issue in self.browse(cr, uid, ids, context=context): + + # if the working hours on the project are not defined, use default ones (8 -> 12 and 13 -> 17 * 5), represented by None + if not issue.project_id or not issue.project_id.resource_calendar_id: + working_hours = None + else: + working_hours = issue.project_id.resource_calendar_id.id + res[issue.id] = {} for field in fields: duration = 0 @@ -150,20 +156,24 @@ class project_issue(base_stage, osv.osv): ans = date_open - date_create date_until = issue.date_open #Calculating no. of working hours to open the issue - if issue.project_id.resource_calendar_id: - hours = cal_obj.interval_hours_get(cr, uid, issue.project_id.resource_calendar_id.id, + hours = cal_obj._interval_hours_get(cr, uid, working_hours, date_create, - date_open) + date_open, + timezone_from_uid=issue.user_id.id or uid, + exclude_leaves=False, + context=context) elif field in ['working_hours_close','day_close']: if issue.date_closed: date_close = datetime.strptime(issue.date_closed, "%Y-%m-%d %H:%M:%S") date_until = issue.date_closed ans = date_close - date_create #Calculating no. of working hours to close the issue - if issue.project_id.resource_calendar_id: - hours = cal_obj.interval_hours_get(cr, uid, issue.project_id.resource_calendar_id.id, - date_create, - date_close) + hours = cal_obj._interval_hours_get(cr, uid, working_hours, + date_create, + date_close, + timezone_from_uid=issue.user_id.id or uid, + exclude_leaves=False, + context=context) elif field in ['days_since_creation']: if issue.create_date: days_since_creation = datetime.today() - datetime.strptime(issue.create_date, "%Y-%m-%d %H:%M:%S") @@ -182,27 +192,12 @@ class project_issue(base_stage, osv.osv): resource_ids = res_obj.search(cr, uid, [('user_id','=',issue.user_id.id)]) if resource_ids and len(resource_ids): resource_id = resource_ids[0] - duration = float(ans.days) - if issue.project_id and issue.project_id.resource_calendar_id: - duration = float(ans.days) * 24 - - new_dates = cal_obj.interval_min_get(cr, uid, - issue.project_id.resource_calendar_id.id, - date_create, - duration, resource=resource_id) - no_days = [] - date_until = datetime.strptime(date_until, '%Y-%m-%d %H:%M:%S') - for in_time, out_time in new_dates: - if in_time.date not in no_days: - no_days.append(in_time.date) - if out_time > date_until: - break - duration = len(no_days) + duration = float(ans.days) + float(ans.seconds)/(24*3600) if field in ['working_hours_open','working_hours_close']: res[issue.id][field] = hours - else: - res[issue.id][field] = abs(float(duration)) + elif field in ['day_open','day_close']: + res[issue.id][field] = duration return res @@ -392,10 +387,18 @@ class project_issue(base_stage, osv.osv): context=context) def write(self, cr, uid, ids, vals, context=None): - #Update last action date every time the user change the stage, the state or send a new email - logged_fields = ['stage_id', 'state', 'message_ids'] - if any([field in vals for field in logged_fields]): - vals['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S') + + #Update last action date every time the user changes the stage + if 'stage_id' in vals: + vals['date_action_last'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + state = self.pool.get('project.task.type').browse(cr, uid, vals['stage_id'], context=context).state + for issue in self.browse(cr, uid, ids, context=context): + # Change from draft to not draft EXCEPT cancelled: The issue has been opened -> set the opening date + if issue.state == 'draft' and state not in ('draft', 'cancelled'): + vals['date_open'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + # Change from not done to done: The issue has been closed -> set the closing date + if issue.state != 'done' and state == 'done': + vals['date_closed'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) return super(project_issue, self).write(cr, uid, ids, vals, context) @@ -412,6 +415,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 # ------------------------------------------------------- @@ -545,8 +554,22 @@ class project_issue(base_stage, osv.osv): return super(project_issue, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context) + def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, content_subtype='html', **kwargs): + """ Overrides mail_thread message_post so that we can set the date of last action field when + a new message is posted on the issue. + """ + 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 -class project(osv.osv): + +class project(osv.Model): _inherit = "project.project" def _get_alias_models(self, cr, uid, context=None): @@ -561,7 +584,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"), } @@ -576,14 +601,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): @@ -594,16 +618,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..f15355e9cc8 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -146,7 +146,7 @@ project.issue - + @@ -154,10 +154,11 @@ - + + @@ -302,7 +303,18 @@ form Issues kanban,tree,form,calendar,graph - {'search_default_project_id': [active_id], 'default_project_id': active_id} + { + 'search_default_project_id': [active_id], + 'default_project_id': active_id, + } + + +

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

+
@@ -324,9 +336,18 @@ - - diff --git a/addons/project_issue/report/project_issue_report.py b/addons/project_issue/report/project_issue_report.py index a5eb903a742..5cca0ff8689 100644 --- a/addons/project_issue/report/project_issue_report.py +++ b/addons/project_issue/report/project_issue_report.py @@ -63,9 +63,9 @@ class project_issue_report(osv.osv): 'project_id':fields.many2one('project.project', 'Project',readonly=True), 'version_id': fields.many2one('project.issue.version', 'Version'), 'user_id' : fields.many2one('res.users', 'Assigned to',readonly=True), - 'partner_id': fields.many2one('res.partner','Contact',domain="[('object_id.model', '=', 'project.issue')]"), + 'partner_id': fields.many2one('res.partner','Contact'), 'channel_id': fields.many2one('crm.case.channel', 'Channel',readonly=True), - 'task_id': fields.many2one('project.task', 'Task',domain="[('object_id.model', '=', 'project.issue')]" ), + 'task_id': fields.many2one('project.task', 'Task'), 'email': fields.integer('# Emails', size=128, readonly=True), } @@ -96,8 +96,8 @@ class project_issue_report(osv.osv): c.channel_id, c.task_id, date_trunc('day',c.create_date) as create_date, - extract('epoch' from (c.date_open-c.create_date))/(3600*24) as delay_open, - extract('epoch' from (c.date_closed-c.date_open))/(3600*24) as delay_close, + c.day_open as delay_open, + c.day_close as delay_close, (SELECT count(id) FROM mail_message WHERE model='project.issue' AND res_id=c.id) AS email FROM @@ -105,6 +105,5 @@ class project_issue_report(osv.osv): WHERE c.active= 'true' )""") -project_issue_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_issue/report/project_issue_report_view.xml b/addons/project_issue/report/project_issue_report_view.xml index 47ea91fad5f..a885dcd8a7f 100644 --- a/addons/project_issue/report/project_issue_report_view.xml +++ b/addons/project_issue/report/project_issue_report_view.xml @@ -14,7 +14,7 @@ - + @@ -55,7 +55,7 @@ - + diff --git a/addons/project_issue/security/project_issue_security.xml b/addons/project_issue/security/project_issue_security.xml index c3119073a75..5215a94a8b7 100644 --- a/addons/project_issue/security/project_issue_security.xml +++ b/addons/project_issue/security/project_issue_security.xml @@ -1,5 +1,27 @@ + + + Project/Issue: project manager: see all + + [(1, '=', 1)] + + + + + Project/Issue: employees: public or employee or following or assigned + + ['|', + '|', + ('project_id.privacy_visibility', 'in', ['public', 'employees']), + '&', + ('project_id.privacy_visibility', '=', 'followers'), + ('message_follower_ids', 'in', [user.id]), + ('user_id', '=', user.id), + ] + + + diff --git a/addons/project_issue/test/subscribe_issue.yml b/addons/project_issue/test/subscribe_issue.yml index 9f16dc80b97..af81ff4d295 100644 --- a/addons/project_issue/test/subscribe_issue.yml +++ b/addons/project_issue/test/subscribe_issue.yml @@ -2,8 +2,7 @@ In Order to test process of Issue in OpenERP, Custmer send the issue by email. - !python {model: mail.thread}: | - from openerp import addons - request_file = open(addons.get_module_resource('project_issue','test', 'issue.eml'),'rb') + request_file = open(openerp.modules.module.get_module_resource('project_issue','test', 'issue.eml'),'rb') request_message = request_file.read() self.message_process(cr, uid, 'project.issue', request_message) - @@ -14,4 +13,4 @@ assert issue_ids and len(issue_ids), "issue is not created after getting request" issue = self.browse(cr, uid, issue_ids[0], context=context) assert not issue.partner_id, "Customer should be a new" - assert issue.name == "Error in the account module", "Subject does not match" \ No newline at end of file + assert issue.name == "Error in the account module", "Subject does not match" diff --git a/addons/project_issue_sheet/i18n/cs.po b/addons/project_issue_sheet/i18n/cs.po new file mode 100644 index 00000000000..606e4246807 --- /dev/null +++ b/addons/project_issue_sheet/i18n/cs.po @@ -0,0 +1,72 @@ +# Czech 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-03-31 16:53+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: project_issue_sheet +#: code:addons/project_issue_sheet/project_issue_sheet.py:57 +#, python-format +msgid "The Analytic Account is pending !" +msgstr "" + +#. module: project_issue_sheet +#: model:ir.model,name:project_issue_sheet.model_account_analytic_line +msgid "Analytic Line" +msgstr "" + +#. module: project_issue_sheet +#: model:ir.model,name:project_issue_sheet.model_project_issue +msgid "Project Issue" +msgstr "" + +#. module: project_issue_sheet +#: model:ir.model,name:project_issue_sheet.model_hr_analytic_timesheet +msgid "Timesheet Line" +msgstr "" + +#. module: project_issue_sheet +#: view:project.issue:0 +msgid "on_change_project(project_id)" +msgstr "" + +#. module: project_issue_sheet +#: code:addons/project_issue_sheet/project_issue_sheet.py:57 +#: field:project.issue,analytic_account_id:0 +#, python-format +msgid "Analytic Account" +msgstr "" + +#. module: project_issue_sheet +#: view:project.issue:0 +msgid "Worklogs" +msgstr "" + +#. module: project_issue_sheet +#: field:account.analytic.line,create_date:0 +msgid "Create Date" +msgstr "" + +#. module: project_issue_sheet +#: view:project.issue:0 +#: field:project.issue,timesheet_ids:0 +msgid "Timesheets" +msgstr "" + +#. module: project_issue_sheet +#: field:hr.analytic.timesheet,issue_id:0 +msgid "Issue" +msgstr "" diff --git a/addons/project_issue_sheet/project_issue_sheet.py b/addons/project_issue_sheet/project_issue_sheet.py index 8fe645e19fe..551ef3c8194 100644 --- a/addons/project_issue_sheet/project_issue_sheet.py +++ b/addons/project_issue_sheet/project_issue_sheet.py @@ -58,7 +58,6 @@ class project_issue(osv.osv): return result -project_issue() class account_analytic_line(osv.osv): _inherit = 'account.analytic.line' @@ -67,7 +66,6 @@ class account_analytic_line(osv.osv): 'create_date' : fields.datetime('Create Date', readonly=True), } -account_analytic_line() class hr_analytic_issue(osv.osv): @@ -77,6 +75,5 @@ class hr_analytic_issue(osv.osv): 'issue_id' : fields.many2one('project.issue', 'Issue'), } -hr_analytic_issue() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_long_term/i18n/cs.po b/addons/project_long_term/i18n/cs.po new file mode 100644 index 00000000000..fb1fb15f3a2 --- /dev/null +++ b/addons/project_long_term/i18n/cs.po @@ -0,0 +1,502 @@ +# Czech 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-03-31 16:54+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: project_long_term +#: help:project.phase,constraint_date_end:0 +msgid "force the phase to finish before this date" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: selection:project.phase,state:0 +msgid "In Progress" +msgstr "" + +#. module: project_long_term +#: field:account.analytic.account,use_phases:0 +#: model:ir.actions.act_window,name:project_long_term.act_project_phases +#: view:project.project:0 +msgid "Phases" +msgstr "" + +#. module: project_long_term +#: model:ir.actions.act_window,name:project_long_term.act_resouce_allocation +#: model:ir.ui.menu,name:project_long_term.menu_resouce_allocation +#: view:project.phase:0 +#: view:project.user.allocation:0 +msgid "Team Planning" +msgstr "" + +#. module: project_long_term +#: field:project.phase,user_ids:0 +msgid "Assigned Users" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: field:project.phase,next_phase_ids:0 +msgid "Next Phases" +msgstr "" + +#. module: project_long_term +#: model:ir.model,name:project_long_term.model_project_user_allocation +msgid "Phase User Allocation" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Project's Tasks" +msgstr "" + +#. module: project_long_term +#: model:ir.actions.act_window,help:project_long_term.action_project_compute_phases +msgid "" +"To schedule phases of all or a specified project. It then open a gantt " +"view.\n" +" " +msgstr "" + +#. module: project_long_term +#: field:project.phase,task_ids:0 +msgid "Project Tasks" +msgstr "" + +#. module: project_long_term +#: model:ir.actions.act_window,name:project_long_term.action_project_compute_phases +#: model:ir.ui.menu,name:project_long_term.menu_compute_phase +#: view:project.compute.phases:0 +msgid "Schedule Phases" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: field:project.phase,state:0 +msgid "Status" +msgstr "" + +#. module: project_long_term +#: field:project.compute.phases,target_project:0 +msgid "Action" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Start Phase" +msgstr "" + +#. module: project_long_term +#: model:ir.model,name:project_long_term.model_project_task +msgid "Task" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Draft" +msgstr "" + +#. module: project_long_term +#: view:project.compute.phases:0 +#: view:project.compute.tasks:0 +msgid "C_ompute" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: selection:project.phase,state:0 +msgid "New" +msgstr "" + +#. module: project_long_term +#: field:project.phase,product_uom:0 +msgid "Duration Unit of Measure" +msgstr "" + +#. module: project_long_term +#: model:ir.ui.menu,name:project_long_term.menu_view_resource_calendar_leaves +msgid "Resource Leaves" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: selection:project.phase,state:0 +msgid "Pending" +msgstr "" + +#. module: project_long_term +#: help:project.phase,progress:0 +msgid "Computed based on related tasks" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "In Progress Phases" +msgstr "" + +#. module: project_long_term +#: code:addons/project_long_term/project_long_term.py:140 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: project_long_term +#: code:addons/project_long_term/wizard/project_compute_phases.py:48 +#, python-format +msgid "Please specify a project to schedule." +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: view:project.user.allocation:0 +msgid "Group By..." +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Remaining Hours" +msgstr "" + +#. module: project_long_term +#: field:project.phase,constraint_date_start:0 +msgid "Minimum Start Date" +msgstr "" + +#. module: project_long_term +#: help:project.phase,product_uom:0 +msgid "" +"Unit of Measure (Unit of Measure) is the unit of measurement for Duration" +msgstr "" + +#. module: project_long_term +#: help:project.phase,user_ids:0 +msgid "" +"The resources on the project can be computed automatically by the scheduler." +msgstr "" + +#. module: project_long_term +#: field:project.phase,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: project_long_term +#: help:account.analytic.account,use_phases:0 +msgid "Check this field if you plan to use phase-based scheduling" +msgstr "" + +#. module: project_long_term +#: help:project.phase,state:0 +msgid "" +"If the phase is created the status 'Draft'.\n" +" If the phase is started, the status becomes 'In Progress'.\n" +" If review is needed the phase is in 'Pending' status. " +" \n" +" If the phase is over, the status is set to 'Done'." +msgstr "" + +#. module: project_long_term +#: field:project.phase,progress:0 +msgid "Progress" +msgstr "" + +#. module: project_long_term +#: model:ir.ui.menu,name:project_long_term.menu_pm_users_project1 +#: model:ir.ui.menu,name:project_long_term.menu_view_resource +msgid "Resources" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "My Projects" +msgstr "" + +#. module: project_long_term +#: view:project.project:0 +#: view:project.user.allocation:0 +msgid "Phase" +msgstr "" + +#. module: project_long_term +#: help:project.phase,duration:0 +msgid "By default in days" +msgstr "" + +#. module: project_long_term +#: model:ir.ui.menu,name:project_long_term.menu_view_resource_calendar +msgid "Working Time" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Pending Phases" +msgstr "" + +#. module: project_long_term +#: help:project.user.allocation,date_start:0 +msgid "Starting Date" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Related Tasks" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Start Month" +msgstr "" + +#. module: project_long_term +#: field:project.phase,date_end:0 +#: field:project.user.allocation,date_end:0 +msgid "End Date" +msgstr "" + +#. module: project_long_term +#: model:ir.model,name:project_long_term.model_project_compute_tasks +msgid "Project Compute Tasks" +msgstr "" + +#. module: project_long_term +#: model:ir.actions.act_window,help:project_long_term.act_project_phase +msgid "" +"A project can be split into the different phases. For each phase, you can " +"define your users allocation, describe different tasks and link your phase " +"to previous and next phases, add date constraints for the automated " +"scheduling. Use the long term planning in order to planify your available " +"users, convert your phases into a series of tasks when you start working on " +"the project." +msgstr "" + +#. module: project_long_term +#: selection:project.compute.phases,target_project:0 +msgid "Compute a Single Project" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: field:project.phase,previous_phase_ids:0 +msgid "Previous Phases" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "New Phases" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Tasks Details" +msgstr "" + +#. module: project_long_term +#: field:project.project,phase_count:0 +msgid "Open Phases" +msgstr "" + +#. module: project_long_term +#: help:project.phase,date_end:0 +msgid "" +" It's computed by the scheduler according to the start date and the duration." +msgstr "" + +#. module: project_long_term +#: constraint:project.phase:0 +msgid "Loops in phases not allowed" +msgstr "" + +#. module: project_long_term +#: view:project.user.allocation:0 +#: field:project.user.allocation,user_id:0 +msgid "User" +msgstr "" + +#. module: project_long_term +#: model:ir.model,name:project_long_term.model_project_project +#: field:project.compute.phases,project_id:0 +#: field:project.compute.tasks,project_id:0 +#: view:project.phase:0 +#: field:project.phase,project_id:0 +#: view:project.task:0 +#: view:project.user.allocation:0 +#: field:project.user.allocation,project_id:0 +msgid "Project" +msgstr "" + +#. module: project_long_term +#: view:project.compute.phases:0 +#: view:project.compute.tasks:0 +msgid "Cancel" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Project Users" +msgstr "" + +#. module: project_long_term +#: model:ir.model,name:project_long_term.model_project_phase +#: view:project.phase:0 +#: view:project.task:0 +#: field:project.task,phase_id:0 +#: field:project.user.allocation,phase_id:0 +msgid "Project Phase" +msgstr "" + +#. module: project_long_term +#: model:ir.ui.menu,name:project_long_term.menu_phase_schedule +msgid "Scheduling" +msgstr "" + +#. module: project_long_term +#: constraint:project.phase:0 +msgid "Phase start-date must be lower than phase end-date." +msgstr "" + +#. module: project_long_term +#: selection:project.phase,state:0 +msgid "Cancelled" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Total Hours" +msgstr "" + +#. module: project_long_term +#: model:ir.model,name:project_long_term.model_project_compute_phases +msgid "Project Compute Phases" +msgstr "" + +#. module: project_long_term +#: field:project.phase,date_start:0 +#: field:project.user.allocation,date_start:0 +msgid "Start Date" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Constraints" +msgstr "" + +#. module: project_long_term +#: help:project.phase,sequence:0 +msgid "Gives the sequence order when displaying a list of phases." +msgstr "" + +#. module: project_long_term +#: model:ir.actions.act_window,name:project_long_term.project_phase_task_list +msgid "Tasks" +msgstr "" + +#. module: project_long_term +#: help:project.user.allocation,date_end:0 +msgid "Ending Date" +msgstr "" + +#. module: project_long_term +#: code:addons/project_long_term/wizard/project_compute_phases.py:48 +#, python-format +msgid "Error!" +msgstr "" + +#. module: project_long_term +#: help:project.phase,date_start:0 +msgid "" +"It's computed by the scheduler according the project date or the end date of " +"the previous phase." +msgstr "" + +#. module: project_long_term +#: model:ir.actions.act_window,name:project_long_term.act_project_phase +#: model:ir.actions.act_window,name:project_long_term.act_project_phase_list +#: model:ir.ui.menu,name:project_long_term.menu_project_phase +#: model:ir.ui.menu,name:project_long_term.menu_project_phase_list +#: view:project.phase:0 +#: field:project.project,phase_ids:0 +msgid "Project Phases" +msgstr "" + +#. module: project_long_term +#: help:project.phase,constraint_date_start:0 +msgid "force the phase to start after this date" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +msgid "Month" +msgstr "" + +#. module: project_long_term +#: model:ir.model,name:project_long_term.model_account_analytic_account +msgid "Analytic Account" +msgstr "" + +#. module: project_long_term +#: field:project.phase,constraint_date_end:0 +msgid "Deadline" +msgstr "" + +#. module: project_long_term +#: view:project.user.allocation:0 +msgid "Project User Allocation" +msgstr "" + +#. module: project_long_term +#: model:ir.actions.act_window,name:project_long_term.action_project_compute_tasks +#: model:ir.ui.menu,name:project_long_term.menu_compute_tasks +#: view:project.compute.tasks:0 +msgid "Schedule Tasks" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: selection:project.phase,state:0 +msgid "Done" +msgstr "" + +#. module: project_long_term +#: selection:project.compute.phases,target_project:0 +msgid "Compute All My Projects" +msgstr "" + +#. module: project_long_term +#: field:project.phase,user_force_ids:0 +msgid "Force Assigned Users" +msgstr "" + +#. module: project_long_term +#: view:project.phase:0 +#: field:project.phase,duration:0 +msgid "Duration" +msgstr "" + +#. module: project_long_term +#: view:project.user.allocation:0 +msgid "Users" +msgstr "" + +#. module: project_long_term +#: field:project.phase,name:0 +msgid "Name" +msgstr "" + +#. module: project_long_term +#: view:project.compute.phases:0 +#: view:project.compute.tasks:0 +msgid "or" +msgstr "" diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py index e53ff9ed253..a950907fb69 100644 --- a/addons/project_long_term/project_long_term.py +++ b/addons/project_long_term/project_long_term.py @@ -198,7 +198,6 @@ class project_phase(osv.osv): result += "\n" return result -project_phase() class project_user_allocation(osv.osv): _name = 'project.user.allocation' @@ -211,7 +210,6 @@ class project_user_allocation(osv.osv): 'date_start': fields.datetime('Start Date', help="Starting Date"), 'date_end': fields.datetime('End Date', help="Ending Date"), } -project_user_allocation() class project(osv.osv): _inherit = "project.project" @@ -267,7 +265,6 @@ class project(osv.osv): 'date_end': p.end.strftime('%Y-%m-%d %H:%M:%S') }, context=context) return True -project() class account_analytic_account(osv.osv): _inherit = 'account.analytic.account' @@ -283,17 +280,17 @@ class account_analytic_account(osv.osv): res['value']['use_phases'] = template.use_phases return res - def _trigger_project_creation(self, cr, uid, vals, context=None): - res= super(account_analytic_account, self)._trigger_project_creation(cr, uid, vals, context=context) - return res or vals.get('use_phases') -account_analytic_account() + def _trigger_project_creation(self, cr, uid, vals, context=None): + 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_phases') and not 'project_creation_in_progress' in context) + class project_task(osv.osv): _inherit = "project.task" _columns = { 'phase_id': fields.many2one('project.phase', 'Project Phase', domain="[('project_id', '=', project_id)]"), } -project_task() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_long_term/wizard/project_compute_phases.py b/addons/project_long_term/wizard/project_compute_phases.py index c9aa7eb3573..5ac89e2def2 100644 --- a/addons/project_long_term/wizard/project_compute_phases.py +++ b/addons/project_long_term/wizard/project_compute_phases.py @@ -71,6 +71,5 @@ class project_compute_phases(osv.osv_memory): result['context'] = {"search_default_project_id":project_id, "default_project_id":project_id, "search_default_current": 1} return result -project_compute_phases() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_long_term/wizard/project_compute_tasks.py b/addons/project_long_term/wizard/project_compute_tasks.py index f21dab8a6d2..d442aee7790 100644 --- a/addons/project_long_term/wizard/project_compute_tasks.py +++ b/addons/project_long_term/wizard/project_compute_tasks.py @@ -59,6 +59,5 @@ class project_compute_tasks(osv.osv_memory): result['target'] = 'current' return result -project_compute_tasks() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_mrp/project_mrp.py b/addons/project_mrp/project_mrp.py index a6f0495a962..bb25b4aae24 100644 --- a/addons/project_mrp/project_mrp.py +++ b/addons/project_mrp/project_mrp.py @@ -45,14 +45,12 @@ class project_task(osv.osv): res = super(project_task, self).do_cancel(cr, uid, ids, *args, **kwargs) self._validate_subflows(cr, uid, ids) return res -project_task() class product_product(osv.osv): _inherit = "product.product" _columns = { 'project_id': fields.many2one('project.project', 'Project', ondelete='set null',) } -product_product() class sale_order(osv.osv): _inherit ='sale.order' @@ -108,5 +106,4 @@ class sale_order(osv.osv): 'picked_rate': fields.function(_picked_rate, method=True, string='Picked', type='float'), } -sale_order() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_mrp/project_procurement.py b/addons/project_mrp/project_procurement.py index 79228fe3285..f4b4a28db46 100644 --- a/addons/project_mrp/project_procurement.py +++ b/addons/project_mrp/project_procurement.py @@ -94,6 +94,5 @@ class procurement_order(osv.osv): if procurement.sale_line_id and procurement.sale_line_id.order_id: procurement.sale_line_id.order_id.message_post(body=body) -procurement_order() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_mrp/test/project_task_procurement.yml b/addons/project_mrp/test/project_task_procurement.yml index 8854ce20c80..967461ca30a 100644 --- a/addons/project_mrp/test/project_task_procurement.yml +++ b/addons/project_mrp/test/project_task_procurement.yml @@ -27,7 +27,7 @@ assert (not project and not account) or project.analytic_account_id == account, "Project does not correspond." planned_hours = self._convert_qty_company_hours(cr, uid, procurement, context=context) assert task.planned_hours == planned_hours, 'Planned Hours do not correspond.' - assert datetime.strptime(task.date_deadline, '%Y-%m-%d') == datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S'), 'Deadline does not correspond.' + assert datetime.strptime(task.date_deadline, '%Y-%m-%d') == datetime.strptime(procurement.date_planned[:10], '%Y-%m-%d'), 'Deadline does not correspond.' if procurement.product_id.product_manager: assert task.user_id.id == procurement.product_id.product_manager.id, 'Allocated Person does not correspond with Service Product Manager.' - diff --git a/addons/project_timesheet/project_timesheet.py b/addons/project_timesheet/project_timesheet.py index c1f8f6409a9..ffee600f5a7 100644 --- a/addons/project_timesheet/project_timesheet.py +++ b/addons/project_timesheet/project_timesheet.py @@ -22,7 +22,6 @@ import time import datetime from openerp.osv import fields, osv -from openerp import pooler from openerp import tools from openerp.tools.translate import _ @@ -70,7 +69,6 @@ class project_project(osv.osv): result['help'] = help return result -project_project() class project_work(osv.osv): _inherit = "project.task.work" @@ -219,7 +217,6 @@ class project_work(osv.osv): 'hr_analytic_timesheet_id':fields.many2one('hr.analytic.timesheet','Related Timeline Id', ondelete='set null'), } -project_work() class task(osv.osv): _inherit = "project.task" @@ -255,7 +252,6 @@ class task(osv.osv): hr_anlytic_timesheet.write(cr, uid, [line_id], vals_line, {}) return super(task,self).write(cr, uid, ids, vals, context) -task() class res_partner(osv.osv): _inherit = 'res.partner' @@ -267,7 +263,6 @@ class res_partner(osv.osv): return super(res_partner,self).unlink(cursor, user, ids, context=context) -res_partner() class account_analytic_line(osv.osv): _inherit = "account.analytic.line" @@ -294,6 +289,5 @@ class account_analytic_line(osv.osv): raise osv.except_osv(_('Invalid Analytic Account !'), _('You cannot select a Analytic Account which is in Close or Cancelled state.')) return res -account_analytic_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_timesheet/report/task_report.py b/addons/project_timesheet/report/task_report.py index c4945e942f6..3411a73a239 100644 --- a/addons/project_timesheet/report/task_report.py +++ b/addons/project_timesheet/report/task_report.py @@ -79,6 +79,5 @@ class report_timesheet_task_user(osv.osv): to_char(to_date(months.name, 'YYYY/MM/DD'),'MM') ) """) -report_timesheet_task_user() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/company.py b/addons/purchase/company.py index 275f5ea200d..cc98c200458 100644 --- a/addons/purchase/company.py +++ b/addons/purchase/company.py @@ -24,13 +24,16 @@ from openerp.osv import osv,fields class company(osv.osv): _inherit = 'res.company' _columns = { - 'po_lead': fields.float('Purchase Lead Time', required=True, - help="This is the leads/security time for each purchase order."), + 'po_lead': fields.float( + 'Purchase Lead Time', required=True, + help="Margin of error for supplier lead times. When the system"\ + "generates Purchase Orders for procuring products,"\ + "they will be scheduled that many days earlier "\ + "to cope with unexpected supplier delays."), } _defaults = { 'po_lead': lambda *a: 1.0, } -company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/partner.py b/addons/purchase/partner.py index 56eaf288fe6..5e5af0815e3 100644 --- a/addons/purchase/partner.py +++ b/addons/purchase/partner.py @@ -43,6 +43,9 @@ class res_partner(osv.osv): super(res_partner, self).copy(cr, uid, id, default=default, context=context) + def _commercial_fields(self, cr, uid, context=None): + return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['property_product_pricelist_purchase'] + _columns = { 'property_product_pricelist_purchase': fields.property( 'product.pricelist', @@ -55,7 +58,6 @@ class res_partner(osv.osv): 'purchase_order_count': fields.function(_purchase_order_count, string='# of Purchase Order', type='integer'), 'purchase_order_ids': fields.one2many('purchase.order','partner_id','Purchase Order') } -res_partner() diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 23f889b136f..26e34048b40 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -20,12 +20,13 @@ ############################################################################## import time +import pytz +from openerp import SUPERUSER_ID from datetime import datetime from dateutil.relativedelta import relativedelta from operator import attrgetter from openerp.osv import fields, osv -from openerp import pooler from openerp.tools.translate import _ import openerp.addons.decimal_precision as dp from openerp.osv.orm import browse_record, browse_null @@ -372,7 +373,7 @@ class purchase_order(osv.osv): pick_ids += [picking.id for picking in po.picking_ids] action_model, action_id = tuple(mod_obj.get_object_reference(cr, uid, 'stock', 'action_picking_tree4')) - 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) ctx = eval(action['context']) ctx.update({ 'search_default_purchase_id': ids[0] @@ -427,6 +428,7 @@ class purchase_order(osv.osv): 'default_composition_mode': 'comment', }) return { + 'name': _('Compose Email'), 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', @@ -592,11 +594,34 @@ class purchase_order(osv.osv): self.signal_purchase_cancel(cr, uid, ids) return True + def date_to_datetime(self, cr, uid, userdate, context=None): + """ Convert date values expressed in user's timezone to + server-side UTC timestamp, assuming a default arbitrary + time of 12:00 AM - because a time is needed. + + :param str userdate: date string in in user time zone + :return: UTC datetime string for server-side use + """ + # TODO: move to fields.datetime in server after 7.0 + user_date = datetime.strptime(userdate, DEFAULT_SERVER_DATE_FORMAT) + if context and context.get('tz'): + tz_name = context['tz'] + else: + tz_name = self.pool.get('res.users').read(cr, SUPERUSER_ID, uid, ['tz'])['tz'] + if tz_name: + utc = pytz.timezone('UTC') + context_tz = pytz.timezone(tz_name) + user_datetime = user_date + relativedelta(hours=12.0) + local_timestamp = context_tz.localize(user_datetime, is_dst=False) + user_datetime = local_timestamp.astimezone(utc) + return user_datetime.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + return user_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + def _prepare_order_picking(self, cr, uid, order, context=None): return { 'name': self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.in'), 'origin': order.name + ((order.origin and (':' + order.origin)) or ''), - 'date': order.date_order, + 'date': self.date_to_datetime(cr, uid, order.date_order, context), 'partner_id': order.dest_address_id.id or order.partner_id.id, 'invoice_state': '2binvoiced' if order.invoice_method == 'picking' else 'none', 'type': 'in', @@ -614,8 +639,8 @@ class purchase_order(osv.osv): 'product_uos_qty': order_line.product_qty, 'product_uom': order_line.product_uom.id, 'product_uos': order_line.product_uom.id, - 'date': order_line.date_planned, - 'date_expected': order_line.date_planned, + 'date': self.date_to_datetime(cr, uid, order.date_order, context), + 'date_expected': self.date_to_datetime(cr, uid, order.date_order, context), 'location_id': order.partner_id.property_stock_supplier.id, 'location_dest_id': order.location_id.id, 'picking_id': picking_id, @@ -990,7 +1015,6 @@ class purchase_order_line(osv.osv): self.write(cr, uid, ids, {'state': 'confirmed'}, context=context) return True -purchase_order_line() class procurement_order(osv.osv): _inherit = 'procurement.order' diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml index 056a06f0750..4432d2b3200 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -270,7 +270,7 @@ - + @@ -297,7 +297,7 @@ - + @@ -335,7 +335,7 @@ ir.actions.act_window purchase.order {} - [('state','in',('draft','sent','cancel'))] + [('state','in',('draft','sent','cancel', 'confirmed'))] tree,form,graph,calendar @@ -481,7 +481,7 @@ - + diff --git a/addons/purchase/report/order.py b/addons/purchase/report/order.py index e415af53434..68d92970aa0 100644 --- a/addons/purchase/report/order.py +++ b/addons/purchase/report/order.py @@ -21,8 +21,6 @@ import time from openerp.report import report_sxw -from openerp.osv import osv -from openerp import pooler class order(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): diff --git a/addons/purchase/report/purchase_report.py b/addons/purchase/report/purchase_report.py index 1855ed173ca..5af74b23495 100644 --- a/addons/purchase/report/purchase_report.py +++ b/addons/purchase/report/purchase_report.py @@ -136,7 +136,6 @@ class purchase_report(osv.osv): u2.factor ) """) -purchase_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/report/request_quotation.py b/addons/purchase/report/request_quotation.py index 1179e704eb0..7be23113584 100644 --- a/addons/purchase/report/request_quotation.py +++ b/addons/purchase/report/request_quotation.py @@ -21,8 +21,6 @@ import time from openerp.report import report_sxw -from openerp.osv import osv -from openerp import pooler class request_quotation(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): diff --git a/addons/purchase/res_config.py b/addons/purchase/res_config.py index 130247037a4..f5f2dfcdda5 100644 --- a/addons/purchase/res_config.py +++ b/addons/purchase/res_config.py @@ -20,7 +20,6 @@ ############################################################################## from openerp.osv import fields, osv -from openerp import pooler from openerp.tools.translate import _ class purchase_config_settings(osv.osv_memory): @@ -66,6 +65,11 @@ Example: Product: this product is deprecated, do not purchase more than 5. 'default_invoice_method': 'manual', } + def onchange_purchase_analytic_plans(self, cr, uid, ids, module_purchase_analytic_plans, context=None): + """ change group_analytic_account_for_purchases following module_purchase_analytic_plans """ + if not module_purchase_analytic_plans: + return {} + return {'value': {'group_analytic_account_for_purchases': module_purchase_analytic_plans}} @@ -82,6 +86,8 @@ class account_config_settings(osv.osv_memory): def onchange_purchase_analytic_plans(self, cr, uid, ids, module_purchase_analytic_plans, context=None): """ change group_analytic_account_for_purchases following module_purchase_analytic_plans """ + if not module_purchase_analytic_plans: + return {} return {'value': {'group_analytic_account_for_purchases': module_purchase_analytic_plans}} # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/res_config_view.xml b/addons/purchase/res_config_view.xml index 7f1cfc64f39..276dc892392 100644 --- a/addons/purchase/res_config_view.xml +++ b/addons/purchase/res_config_view.xml @@ -67,7 +67,7 @@
- +
@@ -109,7 +109,7 @@
- +
diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index 60b439a2097..e64c12a2359 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -29,7 +29,6 @@ class stock_move(osv.osv): readonly=True), } -stock_move() # # Inherit of picking to add the link to the PO diff --git a/addons/purchase/test/ui/print_report.yml b/addons/purchase/test/ui/print_report.yml index c5a9448e497..94cf49655b6 100644 --- a/addons/purchase/test/ui/print_report.yml +++ b/addons/purchase/test/ui/print_report.yml @@ -3,8 +3,9 @@ - !python {model: purchase.order}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.purchase.quotation').create(cr, uid, [ref('purchase.purchase_order_1'),ref('purchase.purchase_order_2')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('purchase.purchase_order_1'), ref('purchase.purchase_order_2')], 'purchase.quotation', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'purchase-request_quotation'+format), 'wb+').write(data) - diff --git a/addons/purchase/wizard/purchase_line_invoice.py b/addons/purchase/wizard/purchase_line_invoice.py index 12dbf4a09f6..f97d82a8456 100644 --- a/addons/purchase/wizard/purchase_line_invoice.py +++ b/addons/purchase/wizard/purchase_line_invoice.py @@ -142,7 +142,6 @@ class purchase_line_invoice(osv.osv_memory): 'context': "{'type':'in_invoice', 'journal_type': 'purchase'}", 'type': 'ir.actions.act_window' } -purchase_line_invoice() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/wizard/purchase_order_group.py b/addons/purchase/wizard/purchase_order_group.py index b47f4e608a8..243f27efea4 100644 --- a/addons/purchase/wizard/purchase_order_group.py +++ b/addons/purchase/wizard/purchase_order_group.py @@ -21,9 +21,6 @@ import time from openerp.osv import fields, osv -from openerp import netsvc -from openerp import pooler -from openerp.osv.orm import browse_record, browse_null from openerp.tools.translate import _ class purchase_order_group(osv.osv_memory): @@ -86,6 +83,5 @@ class purchase_order_group(osv.osv_memory): 'search_view_id': id['res_id'] } -purchase_order_group() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase_analytic_plans/purchase_analytic_plans.py b/addons/purchase_analytic_plans/purchase_analytic_plans.py index c80beddd20f..a654de83253 100644 --- a/addons/purchase_analytic_plans/purchase_analytic_plans.py +++ b/addons/purchase_analytic_plans/purchase_analytic_plans.py @@ -29,7 +29,6 @@ class purchase_order_line(osv.osv): 'analytics_id':fields.many2one('account.analytic.plan.instance','Analytic Distribution'), } -purchase_order_line() class purchase_order(osv.osv): _name='purchase.order' @@ -40,6 +39,5 @@ class purchase_order(osv.osv): res['analytics_id'] = order_line.analytics_id.id return res -purchase_order() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase_analytic_plans/purchase_analytic_plans_view.xml b/addons/purchase_analytic_plans/purchase_analytic_plans_view.xml index bcc67a2a215..d1db411f68c 100644 --- a/addons/purchase_analytic_plans/purchase_analytic_plans_view.xml +++ b/addons/purchase_analytic_plans/purchase_analytic_plans_view.xml @@ -38,5 +38,22 @@ + + + + + + + + account.invoice.supplier.form.inherit + account.invoice + + 2 + + + + + + diff --git a/addons/purchase_double_validation/i18n/cs.po b/addons/purchase_double_validation/i18n/cs.po new file mode 100644 index 00000000000..70256f5adc4 --- /dev/null +++ b/addons/purchase_double_validation/i18n/cs.po @@ -0,0 +1,49 @@ +# Czech 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-03-31 16:54+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: purchase_double_validation +#: model:ir.model,name:purchase_double_validation.model_purchase_config_settings +msgid "purchase.config.settings" +msgstr "" + +#. module: purchase_double_validation +#: view:purchase.order:0 +msgid "Purchase orders which are not approved yet." +msgstr "" + +#. module: purchase_double_validation +#: field:purchase.config.settings,limit_amount:0 +msgid "limit to require a second approval" +msgstr "" + +#. module: purchase_double_validation +#: view:board.board:0 +#: model:ir.actions.act_window,name:purchase_double_validation.purchase_waiting +msgid "Purchase Orders Waiting Approval" +msgstr "" + +#. module: purchase_double_validation +#: view:purchase.order:0 +msgid "To Approve" +msgstr "" + +#. module: purchase_double_validation +#: help:purchase.config.settings,limit_amount:0 +msgid "Amount after which validation of purchase is required." +msgstr "" diff --git a/addons/purchase_requisition/i18n/cs.po b/addons/purchase_requisition/i18n/cs.po new file mode 100644 index 00000000000..ab1ba503fe7 --- /dev/null +++ b/addons/purchase_requisition/i18n/cs.po @@ -0,0 +1,473 @@ +# Czech 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-03-31 16:55+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Request a Quotation" +msgstr "" + +#. module: purchase_requisition +#: selection:purchase.requisition,exclusive:0 +msgid "Multiple Requisitions" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition.line,product_uom_id:0 +msgid "Product Unit of Measure" +msgstr "" + +#. module: purchase_requisition +#: model:ir.actions.act_window,help:purchase_requisition.action_purchase_requisition +msgid "" +"

\n" +" Click to start a new purchase requisition process. \n" +"

\n" +" A purchase requisition is the step before a request for " +"quotation.\n" +" In a purchase requisition (or purchase tender), you can record " +"the\n" +" products you need to buy and trigger the creation of RfQs to\n" +" suppliers. After the negotiation, once you have reviewed all " +"the\n" +" supplier's offers, you can validate some and cancel others.\n" +"

\n" +" " +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +#: field:purchase.requisition,user_id:0 +msgid "Responsible" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +#: field:purchase.requisition,state:0 +msgid "Status" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Send to Suppliers" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Group By..." +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +#: selection:purchase.requisition,state:0 +msgid "Purchase Done" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,message_follower_ids:0 +msgid "Followers" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Purchase Requisition in negociation" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +#: field:purchase.requisition.partner,partner_id:0 +msgid "Supplier" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +#: selection:purchase.requisition,state:0 +msgid "New" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +msgid "Product Detail" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +msgid "Qty" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +msgid "Type" +msgstr "" + +#. module: purchase_requisition +#: model:ir.actions.act_window,name:purchase_requisition.action_purchase_requisition_partner +#: model:ir.actions.report.xml,name:purchase_requisition.report_purchase_requisition +#: model:ir.model,name:purchase_requisition.model_purchase_requisition +#: model:ir.module.category,name:purchase_requisition.module_category_purchase_requisition +#: field:product.product,purchase_requisition:0 +#: field:purchase.order,requisition_id:0 +#: view:purchase.requisition:0 +#: field:purchase.requisition.line,requisition_id:0 +#: view:purchase.requisition.partner:0 +msgid "Purchase Requisition" +msgstr "" + +#. module: purchase_requisition +#: model:ir.model,name:purchase_requisition.model_purchase_requisition_line +msgid "Purchase Requisition Line" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.order:0 +msgid "Purchase Orders with requisition" +msgstr "" + +#. module: purchase_requisition +#: model:ir.model,name:purchase_requisition.model_product_product +#: field:purchase.requisition.line,product_id:0 +msgid "Product" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Quotations" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Terms and Conditions" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +#: field:purchase.requisition,description:0 +msgid "Description" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,message_unread:0 +msgid "Unread Messages" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,company_id:0 +#: field:purchase.requisition.line,company_id:0 +msgid "Company" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition.partner:0 +msgid "Create Quotation" +msgstr "" + +#. module: purchase_requisition +#: help:purchase.requisition,message_ids:0 +msgid "Messages and communication history" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Approved by Supplier" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition.partner:0 +msgid "or" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Reset to Draft" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Current Purchase Requisition" +msgstr "" + +#. module: purchase_requisition +#: model:res.groups,name:purchase_requisition.group_purchase_requisition_user +msgid "User" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +msgid "Order Reference" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,message_is_follower:0 +msgid "Is a Follower" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition.line,product_qty:0 +msgid "Quantity" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Unassigned Requisition" +msgstr "" + +#. module: purchase_requisition +#: model:ir.actions.act_window,name:purchase_requisition.action_purchase_requisition +#: model:ir.ui.menu,name:purchase_requisition.menu_purchase_requisition_pro_mgt +msgid "Purchase Requisitions" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +msgid "Quotation Detail" +msgstr "" + +#. module: purchase_requisition +#: code:addons/purchase_requisition/purchase_requisition.py:134 +#, python-format +msgid "" +"You have already one %s purchase order for this partner, you must cancel " +"this purchase order to create a new quotation." +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "End Date" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +#: field:purchase.requisition,name:0 +msgid "Requisition Reference" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,line_ids:0 +msgid "Products to Purchase" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +#: selection:purchase.requisition,state:0 +msgid "Sent to Suppliers" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Search Purchase Requisition" +msgstr "" + +#. module: purchase_requisition +#: code:addons/purchase_requisition/wizard/purchase_requisition_partner.py:41 +#, python-format +msgid "No Product in Tender." +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +msgid "Date Ordered" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,message_ids:0 +msgid "Messages" +msgstr "" + +#. module: purchase_requisition +#: help:purchase.requisition,exclusive:0 +msgid "" +"Purchase Requisition (exclusive): On the confirmation of a purchase order, " +"it cancels the remaining purchase order.\n" +"Purchase Requisition(Multiple): It allows to have multiple purchase " +"orders.On confirmation of a purchase order it does not cancel the remaining " +"orders" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Cancel Purchase Order" +msgstr "" + +#. module: purchase_requisition +#: model:ir.model,name:purchase_requisition.model_purchase_order +#: view:purchase.requisition:0 +msgid "Purchase Order" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,origin:0 +msgid "Source Document" +msgstr "" + +#. module: purchase_requisition +#: code:addons/purchase_requisition/wizard/purchase_requisition_partner.py:41 +#, python-format +msgid "Error!" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,exclusive:0 +msgid "Requisition Type" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "New Purchase Requisition" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Products" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Order Date" +msgstr "" + +#. module: purchase_requisition +#: selection:purchase.requisition,state:0 +msgid "Cancelled" +msgstr "" + +#. module: purchase_requisition +#: model:ir.model,name:purchase_requisition.model_purchase_requisition_partner +msgid "Purchase Requisition Partner" +msgstr "" + +#. module: purchase_requisition +#: help:purchase.requisition,message_unread:0 +msgid "If checked new messages require your attention." +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +msgid "Purchase for Requisitions" +msgstr "" + +#. module: purchase_requisition +#: model:ir.actions.act_window,name:purchase_requisition.act_res_partner_2_purchase_order +msgid "Purchase orders" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,date_end:0 +msgid "Requisition Deadline" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,message_summary:0 +msgid "Summary" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Reference" +msgstr "" + +#. module: purchase_requisition +#: model:ir.model,name:purchase_requisition.model_procurement_order +msgid "Procurement" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +#: view:purchase.requisition:0 +msgid "Source" +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,warehouse_id:0 +msgid "Warehouse" +msgstr "" + +#. module: purchase_requisition +#: field:procurement.order,requisition_id:0 +msgid "Latest Requisition" +msgstr "" + +#. module: purchase_requisition +#: model:res.groups,name:purchase_requisition.group_purchase_requisition_manager +msgid "Manager" +msgstr "" + +#. module: purchase_requisition +#: selection:purchase.requisition,exclusive:0 +msgid "Purchase Requisition (exclusive)" +msgstr "" + +#. module: purchase_requisition +#: help:purchase.requisition,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: purchase_requisition +#: report:purchase.requisition:0 +msgid "Product UoM" +msgstr "" + +#. module: purchase_requisition +#: code:addons/purchase_requisition/purchase_requisition.py:134 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Confirm Purchase Order" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition.partner:0 +msgid "Cancel" +msgstr "" + +#. module: purchase_requisition +#: report:purchase.requisition:0 +#: field:purchase.requisition,date_start:0 +msgid "Requisition Date" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Start Date" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.requisition:0 +msgid "Unassigned" +msgstr "" + +#. module: purchase_requisition +#: view:purchase.order:0 +msgid "Requisition" +msgstr "" + +#. module: purchase_requisition +#: help:product.product,purchase_requisition:0 +msgid "" +"Check this box to generates purchase requisition instead of generating " +"requests for quotation from procurement." +msgstr "" + +#. module: purchase_requisition +#: field:purchase.requisition,purchase_ids:0 +msgid "Purchase Orders" +msgstr "" diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index b213f958736..c5d32136a7a 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -194,7 +194,6 @@ class purchase_requisition_line(osv.osv): _defaults = { 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'purchase.requisition.line', context=c), } -purchase_requisition_line() class purchase_order(osv.osv): _inherit = "purchase.order" @@ -216,7 +215,6 @@ class purchase_order(osv.osv): po.requisition_id.tender_done(context=context) return res -purchase_order() class product_product(osv.osv): _inherit = 'product.product' @@ -228,7 +226,6 @@ class product_product(osv.osv): 'purchase_requisition': False } -product_product() class procurement_order(osv.osv): @@ -261,6 +258,5 @@ class procurement_order(osv.osv): res = super(procurement_order, self).make_po(cr, uid, ids, context=context) return res -procurement_order() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase_requisition/report/requisition.py b/addons/purchase_requisition/report/requisition.py index 315a34d37e9..d7d38f2114e 100644 --- a/addons/purchase_requisition/report/requisition.py +++ b/addons/purchase_requisition/report/requisition.py @@ -21,8 +21,6 @@ import time from openerp.report import report_sxw -from openerp.osv import osv -from openerp import pooler class requisition(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): diff --git a/addons/purchase_requisition/test/purchase_requisition.yml b/addons/purchase_requisition/test/purchase_requisition.yml index bb6daf9eec1..808b2eb5350 100644 --- a/addons/purchase_requisition/test/purchase_requisition.yml +++ b/addons/purchase_requisition/test/purchase_requisition.yml @@ -84,7 +84,8 @@ - !python {model: purchase.requisition}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.purchase.requisition').create(cr, uid, [ref('purchase_requisition.requisition1')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('purchase_requisition.requisition1')], 'purchase.requisition', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'purchase_requisition-purchase_requisition_report.'+format), 'wb+').write(data) diff --git a/addons/purchase_requisition/wizard/purchase_requisition_partner.py b/addons/purchase_requisition/wizard/purchase_requisition_partner.py index 58a72556b22..0fee8745931 100644 --- a/addons/purchase_requisition/wizard/purchase_requisition_partner.py +++ b/addons/purchase_requisition/wizard/purchase_requisition_partner.py @@ -47,7 +47,6 @@ class purchase_requisition_partner(osv.osv_memory): self.pool.get('purchase.requisition').make_purchase_order(cr, uid, active_ids, data.partner_id.id, context=context) return {'type': 'ir.actions.act_window_close'} -purchase_requisition_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/report/invoice.py b/addons/report_intrastat/report/invoice.py index c1f3823c9d8..c38a62774ac 100644 --- a/addons/report_intrastat/report/invoice.py +++ b/addons/report_intrastat/report/invoice.py @@ -21,7 +21,6 @@ import time from openerp.report import report_sxw -from openerp import pooler class account_invoice_intrastat(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): diff --git a/addons/report_intrastat/report_intrastat.py b/addons/report_intrastat/report_intrastat.py index 2d11151cb5b..003aaec8447 100644 --- a/addons/report_intrastat/report_intrastat.py +++ b/addons/report_intrastat/report_intrastat.py @@ -34,7 +34,6 @@ class res_country(osv.osv): 'intrastat': lambda *a: False, } -res_country() class report_intrastat_code(osv.osv): @@ -45,7 +44,6 @@ class report_intrastat_code(osv.osv): 'description': fields.char('Description', size=64), } -report_intrastat_code() class product_template(osv.osv): @@ -55,7 +53,6 @@ class product_template(osv.osv): 'intrastat_id': fields.many2one('report.intrastat.code', 'Intrastat code'), } -product_template() class report_intrastat(osv.osv): _name = "report.intrastat" @@ -122,6 +119,5 @@ class report_intrastat(osv.osv): group by to_char(inv.create_date, 'YYYY'), to_char(inv.create_date, 'MM'),intrastat.id,inv.type,pt.intrastat_id, inv_country.code,inv.number, inv.currency_id )""") -report_intrastat() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/test/report_intrastat_report.yml b/addons/report_intrastat/test/report_intrastat_report.yml index e51bfbbe748..687f605b901 100644 --- a/addons/report_intrastat/test/report_intrastat_report.yml +++ b/addons/report_intrastat/test/report_intrastat_report.yml @@ -14,7 +14,8 @@ - !python {model: account.invoice}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.account.invoice.intrastat').create(cr, uid, [ref('test_invoice_1')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('test_invoice_1')], 'account.invoice.intrastat', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'report_intrastat-intrastat_report.'+format), 'wb+').write(data) diff --git a/addons/report_webkit/__openerp__.py b/addons/report_webkit/__openerp__.py index d1640ab2f30..b962669eee9 100644 --- a/addons/report_webkit/__openerp__.py +++ b/addons/report_webkit/__openerp__.py @@ -92,6 +92,9 @@ TODO: 'demo': [ "report/webkit_report_demo.xml", ], + 'test': [ + "test/print.yml", + ], 'installable': True, 'auto_install': False, 'images': ['images/companies_webkit.jpeg','images/header_html.jpeg','images/header_img.jpeg'], diff --git a/addons/report_webkit/header.py b/addons/report_webkit/header.py index 71deb57c370..9713efc5382 100644 --- a/addons/report_webkit/header.py +++ b/addons/report_webkit/header.py @@ -87,7 +87,6 @@ class HeaderHTML(osv.osv): help="Select Proper Paper size" ) } -HeaderHTML() class HeaderImage(osv.osv): """Logo allows you to define multiple logo per company""" @@ -98,6 +97,5 @@ class HeaderImage(osv.osv): 'name' : fields.char('Name', size=128, required =True, help="Name of Image"), 'type' : fields.char('Type', size=32, required =True, help="Image type(png,gif,jpeg)") } -HeaderImage() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_webkit/i18n/cs.po b/addons/report_webkit/i18n/cs.po new file mode 100644 index 00000000000..bacda6d4bdf --- /dev/null +++ b/addons/report_webkit/i18n/cs.po @@ -0,0 +1,517 @@ +# Czech 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-03-31 16:55+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-01 05:06+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: report_webkit +#: view:ir.actions.report.xml:0 +msgid "Webkit Template (used if Report File is not found)" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "Tabloid 29 279.4 x 431.8 mm" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "Ledger 28 431.8 x 279.4 mm" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:233 +#, python-format +msgid "No header defined for this Webkit report!" +msgstr "" + +#. module: report_webkit +#: help:ir.header_img,type:0 +msgid "Image type(png,gif,jpeg)" +msgstr "" + +#. module: report_webkit +#: help:ir.actions.report.xml,precise_mode:0 +msgid "" +"This mode allow more precise element " +" position as each object is printed on a separate HTML. " +" but memory and disk " +"usage is wider" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "Executive 4 7.5 x 10 inches, 190.5 x 254 mm" +msgstr "" + +#. module: report_webkit +#: field:ir.header_img,company_id:0 +#: field:ir.header_webkit,company_id:0 +msgid "Company" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:234 +#, python-format +msgid "Please set a header in company settings." +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "DLE 26 110 x 220 mm" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B7 21 88 x 125 mm" +msgstr "" + +#. module: report_webkit +#: view:res.company:0 +msgid "Headers" +msgstr "" + +#. module: report_webkit +#: help:ir.header_img,name:0 +msgid "Name of Image" +msgstr "" + +#. module: report_webkit +#: model:ir.actions.act_window,name:report_webkit.action_header_webkit +#: model:ir.ui.menu,name:report_webkit.menu_header_webkit +msgid "Webkit Headers/Footers" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "Legal 3 8.5 x 14 inches, 215.9 x 355.6 mm" +msgstr "" + +#. module: report_webkit +#: model:ir.model,name:report_webkit.model_ir_header_webkit +msgid "ir.header_webkit" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A4 0 210 x 297 mm, 8.26 x 11.69 inches" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:176 +#, python-format +msgid "Webkit error" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B2 17 500 x 707 mm" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:260 +#: code:addons/report_webkit/webkit_report.py:271 +#: code:addons/report_webkit/webkit_report.py:280 +#: code:addons/report_webkit/webkit_report.py:293 +#: code:addons/report_webkit/webkit_report.py:304 +#, python-format +msgid "Webkit render!" +msgstr "" + +#. module: report_webkit +#: model:ir.model,name:report_webkit.model_ir_header_img +msgid "ir.header_img" +msgstr "" + +#. module: report_webkit +#: field:ir.actions.report.xml,precise_mode:0 +msgid "Precise Mode" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:96 +#, python-format +msgid "" +"Please install executable on your system (sudo apt-get install wkhtmltopdf) " +"or download it from here: " +"http://code.google.com/p/wkhtmltopdf/downloads/list and set the path in the " +"ir.config_parameter with the webkit_path key.Minimal version is 0.9.9" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A0 5 841 x 1189 mm" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "C5E 24 163 x 229 mm" +msgstr "" + +#. module: report_webkit +#: field:ir.header_img,type:0 +msgid "Type" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/wizard/report_webkit_actions.py:133 +#, python-format +msgid "Client Actions Connections" +msgstr "" + +#. module: report_webkit +#: field:res.company,header_image:0 +msgid "Available Images" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,html:0 +msgid "webkit header" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B1 15 707 x 1000 mm" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A1 6 594 x 841 mm" +msgstr "" + +#. module: report_webkit +#: help:ir.actions.report.xml,webkit_header:0 +msgid "The header linked to the report" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:95 +#, python-format +msgid "Wkhtmltopdf library path is not set" +msgstr "" + +#. module: report_webkit +#: view:ir.actions.report.xml:0 +#: view:res.company:0 +msgid "Webkit" +msgstr "" + +#. module: report_webkit +#: help:ir.header_webkit,format:0 +msgid "Select Proper Paper size" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B5 1 176 x 250 mm, 6.93 x 9.84 inches" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A7 11 74 x 105 mm" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A6 10 105 x 148 mm" +msgstr "" + +#. module: report_webkit +#: help:ir.actions.report.xml,report_webkit_data:0 +msgid "This template will be used if the main report file is not found" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "Folio 27 210 x 330 mm" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,margin_top:0 +msgid "Top Margin (mm)" +msgstr "" + +#. module: report_webkit +#: view:report.webkit.actions:0 +msgid "_Ok" +msgstr "" + +#. module: report_webkit +#: help:report.webkit.actions,print_button:0 +msgid "" +"Check this to add a Print action for this Report in the sidebar of the " +"corresponding document types" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B3 18 353 x 500 mm" +msgstr "" + +#. module: report_webkit +#: field:ir.actions.report.xml,webkit_header:0 +msgid "Webkit Header" +msgstr "" + +#. module: report_webkit +#: help:ir.actions.report.xml,webkit_debug:0 +msgid "Enable the webkit engine debugger" +msgstr "" + +#. module: report_webkit +#: field:ir.header_img,img:0 +msgid "Image" +msgstr "" + +#. module: report_webkit +#: view:ir.header_img:0 +msgid "Header Image" +msgstr "" + +#. module: report_webkit +#: field:res.company,header_webkit:0 +msgid "Available html" +msgstr "" + +#. module: report_webkit +#: help:report.webkit.actions,open_action:0 +msgid "" +"Check this to view the newly added internal print action after creating it " +"(technical view) " +msgstr "" + +#. module: report_webkit +#: view:res.company:0 +msgid "Images" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,orientation:0 +msgid "Portrait" +msgstr "" + +#. module: report_webkit +#: view:report.webkit.actions:0 +msgid "or" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,orientation:0 +msgid "Landscape" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B8 22 62 x 88 mm" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:177 +#, python-format +msgid "The command 'wkhtmltopdf' failed with error code = %s. Message: %s" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A2 7 420 x 594 mm" +msgstr "" + +#. module: report_webkit +#: field:report.webkit.actions,print_button:0 +msgid "Add print button" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A9 13 37 x 52 mm" +msgstr "" + +#. module: report_webkit +#: model:ir.model,name:report_webkit.model_res_company +msgid "Companies" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,margin_bottom:0 +msgid "Bottom Margin (mm)" +msgstr "" + +#. module: report_webkit +#: model:ir.model,name:report_webkit.model_report_webkit_actions +msgid "Webkit Actions" +msgstr "" + +#. module: report_webkit +#: field:report.webkit.actions,open_action:0 +msgid "Open added action" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,margin_right:0 +msgid "Right Margin (mm)" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:228 +#, python-format +msgid "Webkit report template not found!" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,orientation:0 +msgid "Orientation" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B6 20 125 x 176 mm" +msgstr "" + +#. module: report_webkit +#: help:ir.header_webkit,html:0 +msgid "Set Webkit Report Header" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,format:0 +msgid "Paper size" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid ":B10 16 31 x 44 mm" +msgstr "" + +#. module: report_webkit +#: view:report.webkit.actions:0 +msgid "Cancel" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,css:0 +msgid "Header CSS" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B4 19 250 x 353 mm" +msgstr "" + +#. module: report_webkit +#: model:ir.actions.act_window,name:report_webkit.action_header_img +#: model:ir.ui.menu,name:report_webkit.menu_header_img +msgid "Webkit Logos" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:172 +#, python-format +msgid "No diagnosis message was provided" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A3 8 297 x 420 mm" +msgstr "" + +#. module: report_webkit +#: field:ir.actions.report.xml,report_webkit_data:0 +msgid "Webkit Template" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,footer_html:0 +msgid "webkit footer" +msgstr "" + +#. module: report_webkit +#: field:ir.actions.report.xml,webkit_debug:0 +msgid "Webkit debug" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "Letter 2 8.5 x 11 inches, 215.9 x 279.4 mm" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B0 14 1000 x 1414 mm" +msgstr "" + +#. module: report_webkit +#: field:ir.header_img,name:0 +#: field:ir.header_webkit,name:0 +msgid "Name" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A5 9 148 x 210 mm" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "A8 12 52 x 74 mm" +msgstr "" + +#. module: report_webkit +#: model:ir.actions.act_window,name:report_webkit.wizard_ofdo_report_actions +#: view:report.webkit.actions:0 +msgid "Add Print Buttons" +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "Comm10E 25 105 x 241 mm, U.S. Common 10 Envelope" +msgstr "" + +#. module: report_webkit +#: field:ir.header_webkit,margin_left:0 +msgid "Left Margin (mm)" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:228 +#, python-format +msgid "Error!" +msgstr "" + +#. module: report_webkit +#: help:ir.header_webkit,footer_html:0 +msgid "Set Webkit Report Footer." +msgstr "" + +#. module: report_webkit +#: selection:ir.header_webkit,format:0 +msgid "B9 23 33 x 62 mm" +msgstr "" + +#. module: report_webkit +#: model:ir.model,name:report_webkit.model_ir_actions_report_xml +msgid "ir.actions.report.xml" +msgstr "" + +#. module: report_webkit +#: code:addons/report_webkit/webkit_report.py:174 +#, python-format +msgid "The following diagnosis message was provided:\n" +msgstr "" + +#. module: report_webkit +#: view:ir.header_webkit:0 +msgid "HTML Header" +msgstr "" diff --git a/addons/report_webkit/ir_report.py b/addons/report_webkit/ir_report.py index 8b8f99b8ebf..4b64a54c420 100644 --- a/addons/report_webkit/ir_report.py +++ b/addons/report_webkit/ir_report.py @@ -29,113 +29,61 @@ # ############################################################################## -from openerp.osv import fields, osv -import openerp.report.interface -from openerp.report.report_sxw import rml_parse +import openerp +from openerp.osv import fields, orm from webkit_report import WebKitParser -def register_report(name, model, tmpl_path, parser=rml_parse): - """Register the report into the services""" - name = 'report.%s' % name - if name in openerp.report.interface.report_int._reports: - service = openerp.report.interface.report_int._reports[name] - if isinstance(service, WebKitParser): - #already instantiated properly, skip it - return - if hasattr(service, 'parser'): - parser = service.parser - del openerp.report.interface.report_int._reports[name] - WebKitParser(name, model, tmpl_path, parser=parser) - - -class ReportXML(osv.osv): - - def __init__(self, pool, cr): - super(ReportXML, self).__init__(pool, cr) - - def register_all(self,cursor): - value = super(ReportXML, self).register_all(cursor) - cursor.execute("SELECT * FROM ir_act_report_xml WHERE report_type = 'webkit'") - records = cursor.dictfetchall() - for record in records: - register_report(record['report_name'], record['model'], record['report_rml']) - return value - - def unlink(self, cursor, user, ids, context=None): - """Delete report and unregister it""" - trans_obj = self.pool.get('ir.translation') - trans_ids = trans_obj.search( - cursor, - user, - [('type', '=', 'report'), ('res_id', 'in', ids)] - ) - trans_obj.unlink(cursor, user, trans_ids) - - # Warning: we cannot unregister the services at the moment - # because they are shared across databases. Calling a deleted - # report will fail so it's ok. - - res = super(ReportXML, self).unlink( - cursor, - user, - ids, - context - ) - return res - - def create(self, cursor, user, vals, context=None): - "Create report and register it" - res = super(ReportXML, self).create(cursor, user, vals, context) - if vals.get('report_type','') == 'webkit': - # I really look forward to virtual functions :S - register_report( - vals['report_name'], - vals['model'], - vals.get('report_rml', False) - ) - return res - - def write(self, cr, uid, ids, vals, context=None): - "Edit report and manage it registration" - if isinstance(ids, (int, long)): - ids = [ids,] - for rep in self.browse(cr, uid, ids, context=context): - if rep.report_type != 'webkit': - continue - if vals.get('report_name', False) and \ - vals['report_name'] != rep.report_name: - report_name = vals['report_name'] - else: - report_name = rep.report_name - - register_report( - report_name, - vals.get('model', rep.model), - vals.get('report_rml', rep.report_rml) - ) - res = super(ReportXML, self).write(cr, uid, ids, vals, context) - return res - - _name = 'ir.actions.report.xml' +class ir_actions_report_xml(orm.Model): _inherit = 'ir.actions.report.xml' _columns = { - 'webkit_header': fields.property( - 'ir.header_webkit', - type='many2one', - relation='ir.header_webkit', - string='Webkit Header', - help="The header linked to the report", - view_load=True, - required=True - ), - 'webkit_debug' : fields.boolean('Webkit debug', help="Enable the webkit engine debugger"), - 'report_webkit_data': fields.text('Webkit Template', help="This template will be used if the main report file is not found"), - 'precise_mode':fields.boolean('Precise Mode', help='This mode allow more precise element \ - position as each object is printed on a separate HTML.\ - but memory and disk usage is wider') + 'webkit_header': fields.property('ir.header_webkit', + type='many2one', relation='ir.header_webkit', + string='Webkit Header', help="The header linked to the report", + view_load=True, required=True), + 'webkit_debug': fields.boolean('Webkit debug', + help="Enable the webkit engine debugger"), + 'report_webkit_data': fields.text('Webkit Template', + help="This template will be used if the main report file is not found"), + 'precise_mode': fields.boolean('Precise Mode', + help="This mode allow more precise element position as each object" + " is printed on a separate HTML but memory and disk usage are wider.") } -ReportXML() + def _lookup_report(self, cr, name): + """ + Look up a report definition. + """ + import operator + import os + opj = os.path.join + + # First lookup in the deprecated place, because if the report definition + # has not been updated, it is more likely the correct definition is there. + # Only reports with custom parser specified in Python are still there. + if 'report.' + name in openerp.report.interface.report_int._reports: + new_report = openerp.report.interface.report_int._reports['report.' + name] + if not isinstance(new_report, WebKitParser): + new_report = None + else: + cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s and report_type=%s", (name, 'webkit')) + r = cr.dictfetchone() + if r: + if r['parser']: + parser = operator.attrgetter(r['parser'])(openerp.addons) + kwargs = { 'parser': parser } + else: + kwargs = {} + + new_report = WebKitParser('report.'+r['report_name'], + r['model'], opj('addons',r['report_rml'] or '/'), + header=r['header'], register=False, **kwargs) + else: + new_report = None + + if new_report: + return new_report + else: + return super(ir_actions_report_xml, self)._lookup_report(cr, name) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_webkit/report_helper.py b/addons/report_webkit/report_helper.py index bc2eb9397ec..af9408b834e 100644 --- a/addons/report_webkit/report_helper.py +++ b/addons/report_webkit/report_helper.py @@ -29,7 +29,7 @@ # ############################################################################## -from openerp import pooler +import openerp class WebKitHelper(object): """Set of usefull report helper""" @@ -37,7 +37,7 @@ class WebKitHelper(object): "constructor" self.cursor = cursor self.uid = uid - self.pool = pooler.get_pool(self.cursor.dbname) + self.pool = openerp.registry(self.cursor.dbname) self.report_id = report_id self.context = context diff --git a/addons/report_webkit/test/print.yml b/addons/report_webkit/test/print.yml new file mode 100644 index 00000000000..b201efa97de --- /dev/null +++ b/addons/report_webkit/test/print.yml @@ -0,0 +1,10 @@ +- + Print the report_webkit demo report. +- + !python {model: ir.actions.report.xml}: | + import os + from openerp import netsvc, tools + ids = self.pool['ir.actions.report.xml'].search(cr, uid, [], {}) + (data, format) = netsvc.LocalService('report.webkit.ir.actions.report.xml').create(cr, uid, ids, {}, {}) + if tools.config['test_report_directory']: + file(os.path.join(tools.config['test_report_directory'], 'report_webkit_demo_report.'+format), 'wb+').write(data) diff --git a/addons/report_webkit/webkit_report.py b/addons/report_webkit/webkit_report.py index f4f65e56596..3d8e41c42ff 100644 --- a/addons/report_webkit/webkit_report.py +++ b/addons/report_webkit/webkit_report.py @@ -38,11 +38,10 @@ import tempfile import time import logging -from openerp import netsvc -from openerp import pooler from report_helper import WebKitHelper +import openerp +from openerp.modules.module import get_module_resource from openerp.report.report_sxw import * -from openerp import addons from openerp import tools from openerp.tools.translate import _ from openerp.osv.osv import except_osv @@ -117,16 +116,16 @@ class WebKitParser(report_sxw): """Custom class that use webkit to render HTML reports Code partially taken from report openoffice. Thanks guys :) """ - def __init__(self, name, table, rml=False, parser=False, - header=True, store=False): + def __init__(self, name, table, rml=False, parser=rml_parse, + header=True, store=False, register=True): self.parser_instance = False self.localcontext = {} report_sxw.__init__(self, name, table, rml, parser, - header, store) + header, store, register=register) def get_lib(self, cursor, uid): """Return the lib wkhtml path""" - proxy = self.pool.get('ir.config_parameter') + proxy = self.pool['ir.config_parameter'] webkit_path = proxy.get_param(cursor, uid, 'webkit_path') if not webkit_path: @@ -242,7 +241,7 @@ class WebKitParser(report_sxw): def translate_call(self, src): """Translate String.""" - ir_translation = self.pool.get('ir.translation') + ir_translation = self.pool['ir.translation'] res = ir_translation._get_source(self.parser_instance.cr, self.parser_instance.uid, None, 'report', self.parser_instance.localcontext.get('lang', 'en_US'), src) if not res : @@ -255,13 +254,12 @@ class WebKitParser(report_sxw): # just try to find an xml id for the report cr = cursor - import openerp.pooler as pooler - pool = pooler.get_pool(cr.dbname) - found_xml_ids = pool.get("ir.model.data").search(cr, uid, [["model", "=", "ir.actions.report.xml"], \ + pool = openerp.registry(cr.dbname) + found_xml_ids = pool["ir.model.data"].search(cr, uid, [["model", "=", "ir.actions.report.xml"], \ ["res_id", "=", report_xml.id]], context=context) xml_id = None if found_xml_ids: - xml_id = pool.get("ir.model.data").read(cr, uid, found_xml_ids[0], ["module", "name"]) + xml_id = pool["ir.model.data"].read(cr, uid, found_xml_ids[0], ["module", "name"]) xml_id = "%s.%s" % (xml_id["module"], xml_id["name"]) if context is None: @@ -275,14 +273,14 @@ class WebKitParser(report_sxw): self.name2, context=context) - self.pool = pooler.get_pool(cursor.dbname) + self.pool = pool objs = self.getObjects(cursor, uid, ids, context) self.parser_instance.set_context(objs, data, ids, report_xml.report_type) template = False if report_xml.report_file : - path = addons.get_module_resource(*report_xml.report_file.split(os.path.sep)) + path = get_module_resource(*report_xml.report_file.split(os.path.sep)) if path and os.path.exists(path) : template = file(path).read() if not template and report_xml.report_webkit_data : @@ -298,7 +296,7 @@ class WebKitParser(report_sxw): ) if not report_xml.header : header = '' - default_head = addons.get_module_resource('report_webkit', 'default_header.html') + default_head = get_module_resource('report_webkit', 'default_header.html') with open(default_head,'r') as f: header = f.read() css = report_xml.webkit_header.css @@ -367,8 +365,8 @@ class WebKitParser(report_sxw): def create(self, cursor, uid, ids, data, context=None): """We override the create function in order to handle generator Code taken from report openoffice. Thanks guys :) """ - pool = pooler.get_pool(cursor.dbname) - ir_obj = pool.get('ir.actions.report.xml') + pool = openerp.registry(cursor.dbname) + ir_obj = pool['ir.actions.report.xml'] report_xml_ids = ir_obj.search(cursor, uid, [('report_name', '=', self.name[7:])], context=context) if report_xml_ids: diff --git a/addons/report_webkit/wizard/report_webkit_actions.py b/addons/report_webkit/wizard/report_webkit_actions.py index b0e761752f6..5f91d05d671 100644 --- a/addons/report_webkit/wizard/report_webkit_actions.py +++ b/addons/report_webkit/wizard/report_webkit_actions.py @@ -31,7 +31,6 @@ from openerp.tools.translate import _ from openerp.osv import fields, osv -from openerp import pooler class report_webkit_actions(osv.osv_memory): _name = "report.webkit.actions" @@ -61,13 +60,13 @@ class report_webkit_actions(osv.osv_memory): if not record_id or (active_model and active_model != 'ir.actions.report.xml'): return res - report = self.pool.get('ir.actions.report.xml').browse( + report = self.pool['ir.actions.report.xml'].browse( cr, uid, context.get('active_id'), context=context ) - ir_values_obj = self.pool.get('ir.values') + ir_values_obj = self.pool['ir.values'] ids = ir_values_obj.search( cr, uid, @@ -93,7 +92,7 @@ class report_webkit_actions(osv.osv_memory): """ if context is None: context = {} - report_obj = self.pool.get('ir.actions.report.xml') + report_obj = self.pool['ir.actions.report.xml'] for current in self.browse(cr, uid, ids, context=context): report = report_obj.browse( cr, @@ -102,7 +101,7 @@ class report_webkit_actions(osv.osv_memory): context=context ) if current.print_button: - ir_values_obj = pooler.get_pool(cr.dbname).get('ir.values') + ir_values_obj = self.pool['ir.values'] res = ir_values_obj.set( cr, uid, @@ -114,7 +113,7 @@ class report_webkit_actions(osv.osv_memory): isobject=True ) else: - ir_values_obj = pooler.get_pool(cr.dbname).get('ir.values') + ir_values_obj = self.pool['ir.values'] res = ir_values_obj.set( cr, uid, @@ -139,6 +138,5 @@ class report_webkit_actions(osv.osv_memory): 'type': 'ir.actions.act_window', } -report_webkit_actions() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/resource/resource.py b/addons/resource/resource.py index 727ca93d7c9..944c90a3749 100644 --- a/addons/resource/resource.py +++ b/addons/resource/resource.py @@ -19,7 +19,9 @@ # ############################################################################## +import pytz from datetime import datetime, timedelta +from dateutil import rrule import math from faces import * from openerp.osv import fields, osv @@ -212,47 +214,109 @@ class resource_calendar(osv.osv): @return : Total number of working hours based dt_from and dt_end and resource if supplied. """ - if not id: - return 0.0 - dt_leave = self._get_leaves(cr, uid, id, resource) - hours = 0.0 + return self._interval_hours_get(cr, uid, id, dt_from, dt_to, resource_id=resource) - current_hour = dt_from.hour + def _interval_hours_get(self, cr, uid, id, dt_from, dt_to, resource_id=False, timezone_from_uid=None, exclude_leaves=True, context=None): + """ Calculates the Total Working hours based on given start_date to + end_date, If resource id is supplied that it will consider the source + leaves also in calculating the hours. - while (dt_from <= dt_to): - cr.execute("select hour_from,hour_to from resource_calendar_attendance where dayofweek='%s' and calendar_id=%s order by hour_from", (dt_from.weekday(),id)) - der = cr.fetchall() - for (hour_from,hour_to) in der: - if hours != 0.0:#For first time of the loop only,hours will be 0 - current_hour = hour_from - leave_flag = False - if (hour_to>=current_hour): - dt_check = dt_from.strftime('%Y-%m-%d') - for leave in dt_leave: - if dt_check == leave: - dt_check = datetime.strptime(dt_check, "%Y-%m-%d") + timedelta(days=1) - leave_flag = True + @param dt_from : date start to calculate hours + @param dt_end : date end to calculate hours + @param resource_id: optional resource id, If given resource leave will be + considered. + @param timezone_from_uid: optional uid, if given we will considerer + working hours in that user timezone + @param exclude_leaves: optionnal, if set to True (default) we will exclude + resource leaves from working hours + @param context: current request context + @return : Total number of working hours based dt_from and dt_end and + resource if supplied. + """ + utc_tz = pytz.timezone('UTC') + local_tz = utc_tz - if leave_flag: - break - else: - d1 = dt_from - d2 = datetime(dt_from.year, dt_from.month, dt_from.day, int(math.floor(hour_to)), int((hour_to%1) * 60)) + if timezone_from_uid: + users_obj = self.pool.get('res.users') + user_timezone = users_obj.browse(cr, uid, timezone_from_uid, context=context).partner_id.tz + if user_timezone: + try: + local_tz = pytz.timezone(user_timezone) + except pytz.UnknownTimeZoneError: + pass # fallback to UTC as local timezone - if hours != 0.0:#For first time of the loop only,hours will be 0 - d1 = datetime(dt_from.year, dt_from.month, dt_from.day, int(math.floor(current_hour)), int((current_hour%1) * 60)) + def utc_to_local_zone(naive_datetime): + utc_dt = utc_tz.localize(naive_datetime, is_dst=False) + return utc_dt.astimezone(local_tz) - if dt_from.day == dt_to.day: - if hour_from <= dt_to.hour <= hour_to: - d2 = dt_to - dt_from = d2 - hours += (d2-d1).seconds - dt_from = datetime(dt_from.year, dt_from.month, dt_from.day, int(math.floor(current_hour)), int((current_hour%1) * 60)) + timedelta(days=1) - current_hour = 0.0 + def float_time_convert(float_val): + factor = float_val < 0 and -1 or 1 + val = abs(float_val) + return (factor * int(math.floor(val)), int(round((val % 1) * 60))) - return (hours/3600) + # Get slots hours per day + # {day_of_week: [(8, 12), (13, 17), ...], ...} + hours_range_per_weekday = {} + if id: + cr.execute("select dayofweek, hour_from,hour_to from resource_calendar_attendance where calendar_id=%s order by hour_from", (id,)) + for weekday, hour_from, hour_to in cr.fetchall(): + weekday = int(weekday) + hours_range_per_weekday.setdefault(weekday, []) + hours_range_per_weekday[weekday].append((hour_from, hour_to)) + else: + # considering default working hours (Monday -> Friday, 8 -> 12, 13 -> 17) + for weekday in range(5): + hours_range_per_weekday[weekday] = [(8, 12), (13, 17)] + + ## Interval between dt_from - dt_to + ## + ## dt_from dt_to + ## =============|==================|============ + ## [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] + ## + ## [ : start of range + ## ] : end of range + ## + ## case 1: range end before interval start (skip) + ## case 2: range overlap interval start (fit start to internal) + ## case 3: range within interval + ## case 4: range overlap interval end (fit end to interval) + ## case 5: range start after interval end (skip) + + interval_start = utc_to_local_zone(dt_from) + interval_end = utc_to_local_zone(dt_to) + hours_timedelta = timedelta() + + # Get leaves for requested resource + dt_leaves = set([]) + if exclude_leaves and id: + dt_leaves = set(self._get_leaves(cr, uid, id, resource=resource_id)) + + for day in rrule.rrule(rrule.DAILY, dtstart=interval_start, + until=interval_end+timedelta(days=1), + byweekday=hours_range_per_weekday.keys()): + if exclude_leaves and day.strftime('%Y-%m-%d') in dt_leaves: + # XXX: futher improve leave management to allow for partial day leave + continue + for (range_from, range_to) in hours_range_per_weekday.get(day.weekday(), []): + range_from_hour, range_from_min = float_time_convert(range_from) + range_to_hour, range_to_min = float_time_convert(range_to) + daytime_start = local_tz.localize(day.replace(hour=range_from_hour, minute=range_from_min, second=0, tzinfo=None)) + daytime_end = local_tz.localize(day.replace(hour=range_to_hour, minute=range_to_min, second=0, tzinfo=None)) + + # case 1 & 5: time range out of interval + if daytime_end < interval_start or daytime_start > interval_end: + continue + # case 2 & 4: adjust start, end to fit within interval + daytime_start = max(daytime_start, interval_start) + daytime_end = min(daytime_end, interval_end) + + # case 2+, 4+, 3 + hours_timedelta += (daytime_end - daytime_start) + + # return timedelta converted to hours + return (hours_timedelta.days * 24.0 + hours_timedelta.seconds / 3600.0) -resource_calendar() class resource_calendar_attendance(osv.osv): _name = "resource.calendar.attendance" @@ -272,7 +336,6 @@ class resource_calendar_attendance(osv.osv): _defaults = { 'dayofweek' : '0' } -resource_calendar_attendance() def hours_time_string(hours): """ convert a number of hours (float) into a string with format '%H:%M' """ @@ -410,7 +473,6 @@ class resource_resource(osv.osv): wktime_cal.append((non_working[:-1], time_range)) return wktime_cal -resource_resource() class resource_calendar_leaves(osv.osv): _name = "resource.calendar.leaves" @@ -443,6 +505,5 @@ class resource_calendar_leaves(osv.osv): return {'value': result} return {'value': {'calendar_id': []}} -resource_calendar_leaves() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/resource/test/resource.yml b/addons/resource/test/resource.yml index 5b7fa108101..28604518b7b 100644 --- a/addons/resource/test/resource.yml +++ b/addons/resource/test/resource.yml @@ -40,12 +40,13 @@ I check Actual working hours on resource 'Developer' from this week - !python {model: resource.calendar}: | - from datetime import datetime, timedelta + from datetime import datetime + from dateutil.relativedelta import relativedelta now = datetime.now() - dt_from = now - timedelta(days=now.weekday()) - dt_to = dt_from+ timedelta(days=6) + dt_from = now - relativedelta(days=now.weekday(), hour=8, minute=30) + dt_to = dt_from + relativedelta(days=6, hour=17) hours = self.interval_hours_get(cr, uid, ref('timesheet_group1'), dt_from, dt_to, resource=ref('resource_developer')) - assert hours > 27 , 'Invalid Total Week working hour calculated' + assert hours > 27 , 'Invalid Total Week working hour calculated, got %r, expected > 27' % hours - Project Analysis work is of 20 hours which will start from Week start so i will calculate working schedule for resource Analyst for the same. - diff --git a/addons/sale/report/sale_order.py b/addons/sale/report/sale_order.py index b4f0b1589aa..134e87a0c2e 100644 --- a/addons/sale/report/sale_order.py +++ b/addons/sale/report/sale_order.py @@ -27,9 +27,18 @@ class order(report_sxw.rml_parse): def __init__(self, cr, uid, name, context=None): super(order, self).__init__(cr, uid, name, context=context) self.localcontext.update({ - 'time': time, + 'time': time, + 'show_discount':self._show_discount, }) + def _show_discount(self, uid, context=None): + cr = self.cr + try: + group_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'group_discount_per_so_line')[1] + except: + return False + return group_id in [x.id for x in self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id] + report_sxw.report_sxw('report.sale.order', 'sale.order', 'addons/sale/report/sale_order.rml', parser=order, header="external") # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/report/sale_order.rml b/addons/sale/report/sale_order.rml index a00d2d4e3ef..130220535f9 100644 --- a/addons/sale/report/sale_order.rml +++ b/addons/sale/report/sale_order.rml @@ -251,7 +251,7 @@ Unit Price
" xml += location_name[0]['name'] + '' - prod_info = pooler.get_pool(cr.dbname).get('stock.location')._product_get(cr, uid, location_id) + prod_info = registry['stock.location']._product_get(cr, uid, location_id) xml += "" for prod_id in prod_info.keys(): if prod_info[prod_id] != 0.0: - prod_name = pooler.get_pool(cr.dbname).get('product.product').read(cr, uid, [prod_id], ['name']) + prod_name = registry['product.product'].read(cr, uid, [prod_id], ['name']) xml += prod_name[0]['name'] + '\n' xml += '' @@ -66,7 +67,7 @@ class report_custom(report_rml): xml += str(prod_info[prod_id]) + '\n' xml += '' - location_child = pooler.get_pool(cr.dbname).get('stock.location').read(cr, uid, [location_id], ['child_ids']) + location_child = registry['stock.location'].read(cr, uid, [location_id], ['child_ids']) for child_id in location_child[0]['child_ids']: xml += process(child_id, level+1) return xml diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 6bf020623f7..764d9de453e 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -19,7 +19,6 @@ # ############################################################################## -from lxml import etree from datetime import datetime from dateutil.relativedelta import relativedelta import time @@ -50,7 +49,6 @@ class stock_incoterms(osv.osv): 'active': True, } -stock_incoterms() class stock_journal(osv.osv): _name = "stock.journal" @@ -63,7 +61,6 @@ class stock_journal(osv.osv): 'user_id': lambda s, c, u, ctx: u } -stock_journal() #---------------------------------------------------------- # Stock Location @@ -473,7 +470,6 @@ class stock_location(osv.osv): continue return False -stock_location() class stock_tracking(osv.osv): @@ -539,7 +535,6 @@ class stock_tracking(osv.osv): """ return self.pool.get('action.traceability').action_traceability(cr,uid,ids,context) -stock_tracking() #---------------------------------------------------------- # Stock Picking @@ -617,7 +612,7 @@ class stock_picking(osv.osv): return res def create(self, cr, user, vals, context=None): - if ('name' not in vals) or (vals.get('name')=='/'): + if ('name' not in vals) or (vals.get('name')=='/') or (vals.get('name') == False): seq_obj_name = self._name vals['name'] = self.pool.get('ir.sequence').get(cr, user, seq_obj_name) new_id = super(stock_picking, self).create(cr, user, vals, context) @@ -704,29 +699,29 @@ class stock_picking(osv.osv): default = {} default = default.copy() picking_obj = self.browse(cr, uid, id, context=context) - move_obj=self.pool.get('stock.move') - if ('name' not in default) or (picking_obj.name=='/'): - seq_obj_name = 'stock.picking.' + picking_obj.type + move_obj = self.pool.get('stock.move') + if ('name' not in default) or (picking_obj.name == '/'): + seq_obj_name = 'stock.picking.' + picking_obj.type default['name'] = self.pool.get('ir.sequence').get(cr, uid, seq_obj_name) default['origin'] = '' default['backorder_id'] = False if 'invoice_state' not in default and picking_obj.invoice_state == 'invoiced': default['invoice_state'] = '2binvoiced' - res=super(stock_picking, self).copy(cr, uid, id, default, context) + res = super(stock_picking, self).copy(cr, uid, id, default, context) if res: picking_obj = self.browse(cr, uid, res, context=context) for move in picking_obj.move_lines: - move_obj.write(cr, uid, [move.id], {'tracking_id': False,'prodlot_id':False, 'move_history_ids2': [(6, 0, [])], 'move_history_ids': [(6, 0, [])]}) + move_obj.write(cr, uid, [move.id], {'tracking_id': False, 'prodlot_id': False, 'move_history_ids2': [(6, 0, [])], 'move_history_ids': [(6, 0, [])]}) return res - + def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False): if view_type == 'form' and not view_id: mod_obj = self.pool.get('ir.model.data') if self._name == "stock.picking.in": - model,view_id = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_in_form') + model, view_id = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_in_form') if self._name == "stock.picking.out": - model,view_id = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_form') - return super(stock_picking,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) + model, view_id = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_form') + return super(stock_picking, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) def onchange_partner_in(self, cr, uid, ids, partner_id=None, context=None): return {} @@ -1492,7 +1487,6 @@ class stock_production_lot(osv.osv): default.update(date=time.strftime('%Y-%m-%d %H:%M:%S'), move_ids=[]) return super(stock_production_lot, self).copy(cr, uid, id, default=default, context=context) -stock_production_lot() class stock_production_lot_revision(osv.osv): _name = 'stock.production.lot.revision' @@ -1513,7 +1507,6 @@ class stock_production_lot_revision(osv.osv): 'date': fields.date.context_today, } -stock_production_lot_revision() # ---------------------------------------------------- # Move @@ -2440,9 +2433,8 @@ class stock_move(osv.osv): context = {} ctx = context.copy() for move in self.browse(cr, uid, ids, context=context): - if move.state != 'draft' and not ctx.get('call_unlink',False): - raise osv.except_osv(_('User Error!'), - _('You can only delete draft moves.')) + if move.state != 'draft' and not ctx.get('call_unlink', False): + raise osv.except_osv(_('User Error!'), _('You can only delete draft moves.')) return super(stock_move, self).unlink( cr, uid, ids, context=ctx) @@ -2470,13 +2462,20 @@ class stock_move(osv.osv): raise osv.except_osv(_('Warning!'), _('Please provide a positive quantity to scrap.')) res = [] for move in self.browse(cr, uid, ids, context=context): + source_location = move.location_id + if move.state == 'done': + source_location = move.location_dest_id + if source_location.usage != 'internal': + #restrict to scrap from a virtual location because it's meaningless and it may introduce errors in stock ('creating' new products from nowhere) + raise osv.except_osv(_('Error!'), _('Forbidden operation: it is not allowed to scrap products from a virtual location.')) move_qty = move.product_qty uos_qty = quantity / move_qty * move.product_uos_qty default_val = { + 'location_id': source_location.id, 'product_qty': quantity, 'product_uos_qty': uos_qty, 'state': move.state, - 'scrapped' : True, + 'scrapped': True, 'location_dest_id': location_id, 'tracking_id': move.tracking_id.id, 'prodlot_id': move.prodlot_id.id, @@ -2732,7 +2731,6 @@ class stock_move(osv.osv): return [move.id for move in complete] -stock_move() class stock_inventory(osv.osv): _name = "stock.inventory" @@ -2855,7 +2853,6 @@ class stock_inventory(osv.osv): self.write(cr, uid, [inv.id], {'state': 'cancel'}, context=context) return True -stock_inventory() class stock_inventory_line(osv.osv): _name = "stock.inventory.line" @@ -2895,7 +2892,6 @@ class stock_inventory_line(osv.osv): result = {'product_qty': amount, 'product_uom': uom, 'prod_lot_id': False} return {'value': result} -stock_inventory_line() #---------------------------------------------------------- # Stock Warehouse @@ -2927,7 +2923,6 @@ class stock_warehouse(osv.osv): 'lot_output_id': _default_lot_output_id, } -stock_warehouse() #---------------------------------------------------------- # "Empty" Classes that are used to vary from the original stock.picking (that are dedicated to the internal pickings) @@ -2939,6 +2934,12 @@ class stock_picking_in(osv.osv): _table = "stock_picking" _description = "Incoming Shipments" + def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False): + return self.pool.get('stock.picking').search(cr, user, args, offset, limit, order, context, count) + + def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): + return self.pool.get('stock.picking').read(cr, uid, ids, fields=fields, context=context, load=load) + def check_access_rights(self, cr, uid, operation, raise_exception=True): #override in order to redirect the check of acces rights on the stock.picking object return self.pool.get('stock.picking').check_access_rights(cr, uid, operation, raise_exception=raise_exception) @@ -2994,6 +2995,12 @@ class stock_picking_out(osv.osv): _table = "stock_picking" _description = "Delivery Orders" + def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False): + return self.pool.get('stock.picking').search(cr, user, args, offset, limit, order, context, count) + + def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): + return self.pool.get('stock.picking').read(cr, uid, ids, fields=fields, context=context, load=load) + def check_access_rights(self, cr, uid, operation, raise_exception=True): #override in order to redirect the check of acces rights on the stock.picking object return self.pool.get('stock.picking').check_access_rights(cr, uid, operation, raise_exception=raise_exception) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index bc47d83dc89..6097885175b 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -817,7 +817,7 @@ - + @@ -944,6 +944,7 @@ + @@ -1069,6 +1070,7 @@ + @@ -1129,7 +1131,7 @@ stock.move - + @@ -1380,7 +1382,7 @@ - + diff --git a/addons/stock/test/stock_report.yml b/addons/stock/test/stock_report.yml index b1590a4d819..2b062742294 100644 --- a/addons/stock/test/stock_report.yml +++ b/addons/stock/test/stock_report.yml @@ -3,8 +3,9 @@ - !python {model: stock.location}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.lot.stock.overview').create(cr, uid, [ref('location_refrigerator')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('location_refrigerator')], 'lot.stock.overview', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-overview'+format), 'wb+').write(data) - @@ -12,8 +13,9 @@ - !python {model: stock.location}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.lot.stock.overview_all').create(cr, uid, [ref('location_refrigerator')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('location_refrigerator')], 'lot.stock.overview_all', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-overviewall'+format), 'wb+').write(data) - @@ -21,8 +23,9 @@ - !python {model: stock.inventory}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.stock.inventory.move').create(cr, uid, [ref('stock_inventory_icecream')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('stock_inventory_icecream')], 'stock.inventory.move', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-stock_inventory_move.'+format), 'wb+').write(data) - @@ -30,8 +33,9 @@ - !python {model: stock.picking}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.stock.picking.list').create(cr, uid, [ref('outgoing_shipment')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('outgoing_shipment')], 'stock.picking.list', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-picking_list'+format), 'wb+').write(data) - @@ -39,8 +43,9 @@ - !python {model: product.product}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.stock.product.history').create(cr, uid, [ref('product_icecream')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('product_icecream')], 'stock.product.history', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-product_stock_report.'+format), 'wb+').write(data) diff --git a/addons/stock/wizard/stock_change_standard_price.py b/addons/stock/wizard/stock_change_standard_price.py index 881b5fd9af7..e6614724454 100644 --- a/addons/stock/wizard/stock_change_standard_price.py +++ b/addons/stock/wizard/stock_change_standard_price.py @@ -116,6 +116,5 @@ class change_standard_price(osv.osv_memory): prod_obj.do_change_standard_price(cr, uid, [rec_id], datas, context) return {'type': 'ir.actions.act_window_close'} -change_standard_price() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/stock_fill_inventory.py b/addons/stock/wizard/stock_fill_inventory.py index 237033bb7b0..e3341bd6a80 100644 --- a/addons/stock/wizard/stock_fill_inventory.py +++ b/addons/stock/wizard/stock_fill_inventory.py @@ -143,6 +143,5 @@ class stock_fill_inventory(osv.osv_memory): return {'type': 'ir.actions.act_window_close'} -stock_fill_inventory() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/stock_inventory_merge.py b/addons/stock/wizard/stock_inventory_merge.py index 171a193e173..e2b5cff513d 100644 --- a/addons/stock/wizard/stock_inventory_merge.py +++ b/addons/stock/wizard/stock_inventory_merge.py @@ -86,7 +86,6 @@ class stock_inventory_merge(osv.osv_memory): return {'type': 'ir.actions.act_window_close'} -stock_inventory_merge() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/stock_invoice_onshipping.py b/addons/stock/wizard/stock_invoice_onshipping.py index 7c960c5e617..c95508cd71b 100644 --- a/addons/stock/wizard/stock_invoice_onshipping.py +++ b/addons/stock/wizard/stock_invoice_onshipping.py @@ -39,7 +39,7 @@ class stock_invoice_onshipping(osv.osv_memory): if not model or 'stock.picking' not in model: return [] - model_pool = self.pool.get(model) + model_pool = self.pool[model] journal_obj = self.pool.get('account.journal') res_ids = context and context.get('active_ids', []) vals = [] @@ -119,7 +119,7 @@ class stock_invoice_onshipping(osv.osv_memory): elif inv_type == "in_refund": action_model,action_id = data_pool.get_object_reference(cr, uid, 'account', "action_invoice_tree4") if action_model: - action_pool = self.pool.get(action_model) + action_pool = self.pool[action_model] action = action_pool.read(cr, uid, action_id, context=context) action['domain'] = "[('id','in', ["+','.join(map(str,invoice_ids))+"])]" return action @@ -146,6 +146,5 @@ class stock_invoice_onshipping(osv.osv_memory): context=context) return res -stock_invoice_onshipping() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/stock_location_product.py b/addons/stock/wizard/stock_location_product.py index 59d99167e6a..ef7c9848160 100644 --- a/addons/stock/wizard/stock_location_product.py +++ b/addons/stock/wizard/stock_location_product.py @@ -57,6 +57,5 @@ class stock_location_product(osv.osv_memory): 'domain': [('type', '<>', 'service')], } -stock_location_product() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/stock_move.py b/addons/stock/wizard/stock_move.py index 09f684aa691..a98d0ebda02 100644 --- a/addons/stock/wizard/stock_move.py +++ b/addons/stock/wizard/stock_move.py @@ -78,7 +78,6 @@ class stock_move_consume(osv.osv_memory): context=context) return {'type': 'ir.actions.act_window_close'} -stock_move_consume() class stock_move_scrap(osv.osv_memory): @@ -139,7 +138,6 @@ class stock_move_scrap(osv.osv_memory): context=context) return {'type': 'ir.actions.act_window_close'} -stock_move_scrap() class split_in_production_lot(osv.osv_memory): @@ -255,7 +253,6 @@ class split_in_production_lot(osv.osv_memory): return new_move -split_in_production_lot() class stock_move_split_lines_exist(osv.osv_memory): _name = "stock.move.split.lines" diff --git a/addons/stock/wizard/stock_return_picking.py b/addons/stock/wizard/stock_return_picking.py index 4eb817e9c71..c51e1415249 100644 --- a/addons/stock/wizard/stock_return_picking.py +++ b/addons/stock/wizard/stock_return_picking.py @@ -19,7 +19,6 @@ # ############################################################################## -from openerp import netsvc import time from openerp.osv import osv,fields @@ -39,7 +38,6 @@ class stock_return_picking_memory(osv.osv_memory): } -stock_return_picking_memory() class stock_return_picking(osv.osv_memory): @@ -226,6 +224,5 @@ class stock_return_picking(osv.osv_memory): 'context':context, } -stock_return_picking() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/stock_splitinto.py b/addons/stock/wizard/stock_splitinto.py index 3485a6e8264..76a80595be6 100644 --- a/addons/stock/wizard/stock_splitinto.py +++ b/addons/stock/wizard/stock_splitinto.py @@ -80,7 +80,6 @@ class stock_split_into(osv.osv_memory): return {'type': 'ir.actions.act_window_close'} -stock_split_into() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/stock_traceability.py b/addons/stock/wizard/stock_traceability.py index 123a76acd43..c13fc1cf7a6 100644 --- a/addons/stock/wizard/stock_traceability.py +++ b/addons/stock/wizard/stock_traceability.py @@ -53,6 +53,7 @@ class action_traceability(osv.osv_memory): 'domain': "[('id','in',["+','.join(map(str, ids))+"])]", 'name': ((type1=='move_history_ids2') and _('Upstream Traceability')) or _('Downstream Traceability'), 'view_mode': 'tree', + 'view_type': 'tree', 'res_model': 'stock.move', 'field_parent': type1, 'view_id': (view_id,'View'), @@ -61,7 +62,6 @@ class action_traceability(osv.osv_memory): } return value -action_traceability() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_invoice_directly/wizard/stock_invoice.py b/addons/stock_invoice_directly/wizard/stock_invoice.py index 5de6490dc0f..ba41de626da 100644 --- a/addons/stock_invoice_directly/wizard/stock_invoice.py +++ b/addons/stock_invoice_directly/wizard/stock_invoice.py @@ -45,6 +45,5 @@ class invoice_directly(osv.osv_memory): } return {'type': 'ir.actions.act_window_close'} -invoice_directly() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_location/procurement_pull.py b/addons/stock_location/procurement_pull.py index 9f5dfb77375..5b030b5befe 100644 --- a/addons/stock_location/procurement_pull.py +++ b/addons/stock_location/procurement_pull.py @@ -19,7 +19,6 @@ ############################################################################## from openerp.osv import osv -from openerp import netsvc from openerp.tools.translate import _ class procurement_order(osv.osv): diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py index 1258ddb529f..e22ccf80f8f 100644 --- a/addons/stock_location/stock_location.py +++ b/addons/stock_location/stock_location.py @@ -54,7 +54,6 @@ class stock_location_path(osv.osv): 'invoice_state': 'none', 'picking_type': 'internal', } -stock_location_path() class product_pulled_flow(osv.osv): _name = 'product.pulled.flow' @@ -85,7 +84,6 @@ class product_pulled_flow(osv.osv): 'invoice_state': 'none', 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'product.pulled.flow', context=c), } -product_pulled_flow() class product_product(osv.osv): _inherit = 'product.product' @@ -96,7 +94,6 @@ class product_product(osv.osv): help="These rules set the right path of the product in the "\ "whole location tree.") } -product_product() class stock_move(osv.osv): _inherit = 'stock.move' @@ -114,7 +111,6 @@ class stock_move(osv.osv): res = super(stock_move, self)._prepare_chained_picking(cr, uid, picking_name, picking, picking_type, moves_todo, context=context) res.update({'invoice_state': moves_todo[0][1][6] or 'none'}) return res -stock_move() class stock_location(osv.osv): _inherit = 'stock.location' @@ -124,5 +120,4 @@ class stock_location(osv.osv): if path.location_from_id.id == location.id: return path.location_dest_id, path.auto, path.delay, path.journal_id and path.journal_id.id or False, path.company_id and path.company_id.id or False, path.picking_type, path.invoice_state return super(stock_location, self).chained_location_get(cr, uid, location, partner, product, context) -stock_location() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_location/test/stock_location_push_flow.yml b/addons/stock_location/test/stock_location_push_flow.yml index 27164848f77..64bd30e0c99 100644 --- a/addons/stock_location/test/stock_location_push_flow.yml +++ b/addons/stock_location/test/stock_location_push_flow.yml @@ -94,12 +94,11 @@ I check the move is in waiting state. - !python {model: stock.picking }: | - from openerp.tools.translate import _ picking_id = self.search(cr, uid, [('origin','=','Pushed Flow Test'),('type','=','out')]) if picking_id: pick=self.browse(cr,uid,picking_id[0]) for move in pick.move_lines: - assert(move.state == 'waiting'), _('Stock is not in waiting state') + assert(move.state == 'waiting'), 'Stock is not in waiting state' - I receive the order of the supplier Micro Link Technologies from the Incoming Shipments menu. - @@ -123,8 +122,7 @@ I check the Outgoing Orders is automatically done. - !python {model: stock.picking }: | - from openerp.tools.translate import _ picking_id = self.search(cr, uid, [('origin','=','Pushed Flow Test'),('type','=','out')]) if picking_id: pick=self.browse(cr,uid,picking_id[0]) - assert(pick.state == 'done'), _('Picking is not in done state') + assert(pick.state == 'done'), 'Picking is not in done state' diff --git a/addons/stock_no_autopicking/stock_no_autopicking.py b/addons/stock_no_autopicking/stock_no_autopicking.py index 904854f3533..dd8fb31f59f 100644 --- a/addons/stock_no_autopicking/stock_no_autopicking.py +++ b/addons/stock_no_autopicking/stock_no_autopicking.py @@ -29,12 +29,10 @@ class product(osv.osv): _defaults = { 'auto_pick': True } -product() class mrp_production(osv.osv): _inherit = "mrp.production" def _get_auto_picking(self, cr, uid, production): return production.product_id.auto_pick -mrp_production() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/subscription/subscription.py b/addons/subscription/subscription.py index d181e97e8f0..b7ae720c187 100644 --- a/addons/subscription/subscription.py +++ b/addons/subscription/subscription.py @@ -38,7 +38,6 @@ class subscription_document(osv.osv): _defaults = { 'active' : lambda *a: True, } -subscription_document() class subscription_document_fields(osv.osv): _name = "subscription.document.fields" @@ -50,7 +49,6 @@ class subscription_document_fields(osv.osv): 'document_id': fields.many2one('subscription.document', 'Subscription Document', ondelete='cascade'), } _defaults = {} -subscription_document_fields() def _get_document_types(self, cr, uid, context=None): cr.execute('select m.model, s.name from subscription_document s, ir_model m WHERE s.model = m.id order by s.name') @@ -85,6 +83,17 @@ class subscription_subscription(osv.osv): 'state': lambda *a: 'draft' } + def _auto_end(self, cr, context=None): + super(subscription_subscription, self)._auto_end(cr, context=context) + # drop the FK from subscription to ir.cron, as it would cause deadlocks + # during cron job execution. When model_copy() tries to write() on the subscription, + # it has to wait for an ExclusiveLock on the cron job record, but the latter + # is locked by the cron system for the duration of the job! + # FIXME: the subscription module should be reviewed to simplify the scheduling process + # and to use a unique cron job for all subscriptions, so that it never needs to + # be updated during its execution. + cr.execute("ALTER TABLE %s DROP CONSTRAINT %s" % (self._table, '%s_cron_id_fkey' % self._table)) + def set_process(self, cr, uid, ids, context=None): for row in self.read(cr, uid, ids, context=context): mapping = {'name':'name','interval_number':'interval_number','interval_type':'interval_type','exec_init':'numbercall','date_init':'nextcall'} @@ -104,7 +113,7 @@ class subscription_subscription(osv.osv): try: (model_name, id) = row['doc_source'].split(',') id = int(id) - model = self.pool.get(model_name) + model = self.pool[model_name] except: raise osv.except_osv(_('Wrong Source Document !'), _('Please provide another source document.\nThis one does not exist !')) @@ -125,7 +134,7 @@ class subscription_subscription(osv.osv): # the subscription is over and we mark it as being done if remaining == 1: state = 'done' - id = self.pool.get(model_name).copy(cr, uid, id, default, context) + id = self.pool[model_name].copy(cr, uid, id, default, context) self.pool.get('subscription.subscription.history').create(cr, uid, {'subscription_id': row['id'], 'date':time.strftime('%Y-%m-%d %H:%M:%S'), 'document_id': model_name+','+str(id)}) self.write(cr, uid, [row['id']], {'state':state}) return True @@ -146,7 +155,6 @@ class subscription_subscription(osv.osv): def set_draft(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state':'draft'}) return True -subscription_subscription() class subscription_subscription_history(osv.osv): _name = "subscription.subscription.history" @@ -157,7 +165,6 @@ class subscription_subscription_history(osv.osv): 'subscription_id': fields.many2one('subscription.subscription', 'Subscription', ondelete='cascade'), 'document_id': fields.reference('Source Document', required=True, selection=_get_document_types, size=128), } -subscription_subscription_history() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/survey/report/survey_analysis_report.py b/addons/survey/report/survey_analysis_report.py index b4e7765346c..581f52d49be 100644 --- a/addons/survey/report/survey_analysis_report.py +++ b/addons/survey/report/survey_analysis_report.py @@ -22,15 +22,17 @@ import time -from openerp import pooler, tools +import openerp +from openerp import tools from openerp.report import report_sxw from openerp.report.interface import report_rml from openerp.tools import to_xml class survey_analysis(report_rml): def create(self, cr, uid, ids, datas, context): - surv_obj = pooler.get_pool(cr.dbname).get('survey') - user_obj = pooler.get_pool(cr.dbname).get('res.users') + registry = openerp.registry(cr.dbname) + surv_obj = registry['survey'] + user_obj = registry['res.users'] rml_obj=report_sxw.rml_parse(cr, uid, surv_obj._name,context) company=user_obj.browse(cr,uid,[uid],context)[0].company_id diff --git a/addons/survey/report/survey_browse_response.py b/addons/survey/report/survey_browse_response.py index f910140727d..4f2dd8544e0 100644 --- a/addons/survey/report/survey_browse_response.py +++ b/addons/survey/report/survey_browse_response.py @@ -22,7 +22,8 @@ import time -from openerp import pooler, tools +import openerp +from openerp import tools from openerp.report import report_sxw from openerp.report.interface import report_rml from openerp.tools import to_xml @@ -33,6 +34,8 @@ class survey_browse_response(report_rml): _display_ans_in_rows = 5 _pageSize = ('29.7cm','21.1cm') + registry = openerp.registry(cr.dbname) + if datas.has_key('form') and datas['form'].get('orientation','') == 'vertical': if datas['form'].get('paper_size','') == 'letter': _pageSize = ('21.6cm','27.9cm') @@ -187,7 +190,7 @@ class survey_browse_response(report_rml): """ - surv_resp_obj = pooler.get_pool(cr.dbname).get('survey.response') + surv_resp_obj = registry['survey.response'] rml_obj=report_sxw.rml_parse(cr, uid, surv_resp_obj._name,context) if datas.has_key('form') and datas['form'].has_key('response_ids'): response_id = datas['form']['response_ids'] @@ -196,8 +199,8 @@ class survey_browse_response(report_rml): else: response_id = surv_resp_obj.search(cr, uid, [('survey_id', 'in', ids)]) - surv_resp_line_obj = pooler.get_pool(cr.dbname).get('survey.response.line') - surv_obj = pooler.get_pool(cr.dbname).get('survey') + surv_resp_line_obj = registry['survey.response.line'] + surv_obj = registry['survey'] for response in surv_resp_obj.browse(cr, uid, response_id): for survey in surv_obj.browse(cr, uid, [response.survey_id.id]): @@ -261,7 +264,7 @@ class survey_browse_response(report_rml): elif que.type in ['table']: if len(answer) and answer[0].state == "done": - col_heading = pooler.get_pool(cr.dbname).get('survey.tbl.column.heading') + col_heading = registry['survey.tbl.column.heading'] cols_widhts = [] tbl_width = float(_tbl_widths.replace('cm', '')) for i in range(0, len(que.column_heading_ids)): diff --git a/addons/survey/report/survey_form.py b/addons/survey/report/survey_form.py index 8375df6acaf..1868faeee03 100644 --- a/addons/survey/report/survey_form.py +++ b/addons/survey/report/survey_form.py @@ -20,7 +20,8 @@ # ############################################################################## -from openerp import pooler, tools +import openerp +from openerp import tools from openerp.report.interface import report_rml from openerp.tools import to_xml @@ -146,7 +147,7 @@ class survey_form(report_rml): """ - surv_obj = pooler.get_pool(cr.dbname).get('survey') + surv_obj = openerp.registry(cr.dbname)['survey'] for survey in surv_obj.browse(cr,uid,ids): rml += """ diff --git a/addons/survey/survey.py b/addons/survey/survey.py index 241b9739016..ad96145741b 100644 --- a/addons/survey/survey.py +++ b/addons/survey/survey.py @@ -25,7 +25,7 @@ from dateutil.relativedelta import relativedelta from time import strftime import os -from openerp import netsvc, tools +from openerp import tools from openerp.osv import fields, osv from openerp.tools.translate import _ @@ -36,7 +36,6 @@ class survey_type(osv.osv): 'name': fields.char("Name", size=128, required=1, translate=True), 'code': fields.char("Code", size=64), } -survey_type() class survey(osv.osv): _name = 'survey' @@ -196,7 +195,6 @@ class survey(osv.osv): 'context': context } -survey() class survey_history(osv.osv): _name = 'survey.history' @@ -210,7 +208,6 @@ class survey_history(osv.osv): _defaults = { 'date': lambda * a: datetime.datetime.now() } -survey_history() class survey_page(osv.osv): _name = 'survey.page' @@ -260,7 +257,6 @@ class survey_page(osv.osv): vals.update({'title':title}) return super(survey_page, self).copy(cr, uid, ids, vals, context=context) -survey_page() class survey_question(osv.osv): _name = 'survey.question' @@ -561,7 +557,6 @@ class survey_question(osv.osv): data['page_id']= context.get('page_id', False) return data -survey_question() class survey_question_column_heading(osv.osv): @@ -594,7 +589,6 @@ class survey_question_column_heading(osv.osv): 'in_visible_rating_weight': _get_in_visible_rating_weight, 'in_visible_menu_choice': _get_in_visible_menu_choice, } -survey_question_column_heading() class survey_answer(osv.osv): _name = 'survey.answer' @@ -651,7 +645,6 @@ class survey_answer(osv.osv): data = super(survey_answer, self).default_get(cr, uid, fields, context) return data -survey_answer() class survey_response(osv.osv): _name = "survey.response" @@ -684,7 +677,6 @@ class survey_response(osv.osv): def copy(self, cr, uid, id, default=None, context=None): raise osv.except_osv(_('Warning!'),_('You cannot duplicate the resource!')) -survey_response() class survey_response_line(osv.osv): _name = 'survey.response.line' @@ -708,7 +700,6 @@ class survey_response_line(osv.osv): 'state' : lambda * a: "draft", } -survey_response_line() class survey_tbl_column_heading(osv.osv): _name = 'survey.tbl.column.heading' @@ -720,7 +711,6 @@ class survey_tbl_column_heading(osv.osv): 'response_table_id': fields.many2one('survey.response.line', 'Answer', ondelete='cascade'), } -survey_tbl_column_heading() class survey_response_answer(osv.osv): _name = 'survey.response.answer' @@ -736,7 +726,6 @@ class survey_response_answer(osv.osv): 'comment_field': fields.char('Comment', size = 255) } -survey_response_answer() class res_users(osv.osv): _inherit = "res.users" @@ -745,7 +734,6 @@ class res_users(osv.osv): 'survey_id': fields.many2many('survey', 'survey_users_rel', 'uid', 'sid', 'Groups'), } -res_users() class survey_request(osv.osv): _name = "survey.request" @@ -786,6 +774,5 @@ class survey_request(osv.osv): return {'value': {'email': user.email}} return {} -survey_request() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/survey/wizard/survey_answer.py b/addons/survey/wizard/survey_answer.py index d935eb92ade..6d473754988 100644 --- a/addons/survey/wizard/survey_answer.py +++ b/addons/survey/wizard/survey_answer.py @@ -25,8 +25,10 @@ from lxml import etree import os from time import strftime -from openerp import addons, netsvc, tools +from openerp import tools +from openerp.modules.module import get_module_resource from openerp.osv import fields, osv +import openerp.report from openerp.tools import to_xml from openerp.tools.translate import _ from openerp.tools.safe_eval import safe_eval @@ -401,16 +403,17 @@ class survey_question_wiz(osv.osv_memory): sur_response_obj.write(cr, uid, [sur_name_read.response], {'state' : 'done'}) # mark the survey request as done; call 'survey_req_done' on its actual model - survey_req_obj = self.pool.get(context.get('active_model')) - if survey_req_obj and hasattr(survey_req_obj, 'survey_req_done'): - survey_req_obj.survey_req_done(cr, uid, context.get('active_ids', []), context=context) + if context.get('active_model') in self.pool: + survey_req_obj = self.pool[context.get('active_model')] + if hasattr(survey_req_obj, 'survey_req_done'): + survey_req_obj.survey_req_done(cr, uid, context.get('active_ids', []), context=context) if sur_rec.send_response: survey_data = survey_obj.browse(cr, uid, survey_id) response_id = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False))['response'] report = self.create_report(cr, uid, [survey_id], 'report.survey.browse.response', survey_data.title,context) attachments = {} - pdf_filename = addons.get_module_resource('survey', 'report') + survey_data.title + ".pdf" + pdf_filename = get_module_resource('survey', 'report') + survey_data.title + ".pdf" if os.path.exists(pdf_filename): file = open(pdf_filename) file_data = "" @@ -422,7 +425,7 @@ class survey_question_wiz(osv.osv_memory): attachments[survey_data.title + ".pdf"] = file_data file.close() - os.remove(addons.get_module_resource('survey', 'report') + survey_data.title + ".pdf") + os.remove(get_module_resource('survey', 'report') + survey_data.title + ".pdf") context.update({'response_id':response_id}) user_email = user_obj.browse(cr, uid, uid, context).email resp_email = survey_data.responsible_id and survey_data.responsible_id.email or False @@ -463,9 +466,8 @@ class survey_question_wiz(osv.osv_memory): return (False, Exception('Report name and Resources ids are required !!!')) try: uid = 1 - service = netsvc.LocalService(report_name); - (result, format) = service.create(cr, uid, res_ids, {}, context) - ret_file_name = addons.get_module_resource('survey', 'report') + file_name + '.pdf' + result, format = openerp.report.render_report(cr, uid, res_ids, report_name[len('report.'):], {}, context) + ret_file_name = get_module_resource('survey', 'report') + file_name + '.pdf' fp = open(ret_file_name, 'wb+'); fp.write(result); fp.close(); @@ -609,10 +611,10 @@ class survey_question_wiz(osv.osv_memory): survey_obj.write(cr, uid, survey_id, {'tot_start_survey' : sur_rec['tot_start_survey'] + 1}) if context.has_key('cur_id'): if context.has_key('request') and context.get('request',False): - self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id}) - self.pool.get(context.get('object',False)).survey_req_done(cr, uid, [int(context.get('cur_id'))], context) + self.pool[context.get('object')].write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id}) + self.pool[context.get('object')].survey_req_done(cr, uid, [int(context.get('cur_id'))], context) else: - self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id}) + self.pool[context.get('object')].write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id}) if sur_name_read['store_ans'] and type(safe_eval(sur_name_read['store_ans'])) == dict: sur_name_read['store_ans'] = safe_eval(sur_name_read['store_ans']) for key,val in sur_name_read['store_ans'].items(): @@ -1252,6 +1254,5 @@ class survey_question_wiz(osv.osv_memory): 'context': context } -survey_question_wiz() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/survey/wizard/survey_browse_answer.py b/addons/survey/wizard/survey_browse_answer.py index a37a4e4f7ca..1b461761bb5 100644 --- a/addons/survey/wizard/survey_browse_answer.py +++ b/addons/survey/wizard/survey_browse_answer.py @@ -55,6 +55,5 @@ class survey_browse_answer(osv.osv_memory): 'context' : context } -survey_browse_answer() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/survey/wizard/survey_print.py b/addons/survey/wizard/survey_print.py index 9f0b21affa6..f0e39f99cb9 100644 --- a/addons/survey/wizard/survey_print.py +++ b/addons/survey/wizard/survey_print.py @@ -63,6 +63,5 @@ class survey_print(osv.osv_memory): 'report_name': 'survey.form', 'datas': datas, } -survey_print() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/survey/wizard/survey_print_answer.py b/addons/survey/wizard/survey_print_answer.py index 0cadd6bf832..417d1bb732f 100644 --- a/addons/survey/wizard/survey_print_answer.py +++ b/addons/survey/wizard/survey_print_answer.py @@ -68,6 +68,5 @@ class survey_print_answer(osv.osv_memory): 'datas': datas, } -survey_print_answer() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/survey/wizard/survey_print_statistics.py b/addons/survey/wizard/survey_print_statistics.py index f2e25eb8d53..d005dbee31a 100644 --- a/addons/survey/wizard/survey_print_statistics.py +++ b/addons/survey/wizard/survey_print_statistics.py @@ -45,6 +45,5 @@ class survey_print_statistics(osv.osv_memory): 'datas': datas, } -survey_print_statistics() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/survey/wizard/survey_send_invitation.py b/addons/survey/wizard/survey_send_invitation.py index 4913ca09eab..ca6a8e4b15d 100644 --- a/addons/survey/wizard/survey_send_invitation.py +++ b/addons/survey/wizard/survey_send_invitation.py @@ -26,8 +26,10 @@ import os import datetime import socket -from openerp import addons, netsvc, tools +from openerp import tools +from openerp.modules.module import get_module_resource from openerp.osv import fields, osv +import openerp.report from openerp.tools.translate import _ @@ -84,9 +86,8 @@ Thanks,''') % (name, self.pool.get('ir.config_parameter').get_param(cr, uid, 'we if not report_name or not res_ids: return (False, Exception('Report name and Resources ids are required !!!')) try: - ret_file_name = addons.get_module_resource('survey', 'report') + file_name + '.pdf' - service = netsvc.LocalService(report_name); - (result, format) = service.create(cr, uid, res_ids, {}, {}) + ret_file_name = get_module_resource('survey', 'report') + file_name + '.pdf' + result, format = openerp.report.render_report(cr, uid, res_ids, report_name[len('report.'):], {}, {}) fp = open(ret_file_name, 'wb+'); fp.write(result); fp.close(); @@ -128,7 +129,7 @@ Thanks,''') % (name, self.pool.get('ir.config_parameter').get_param(cr, uid, 'we new_user.append(use.id) for id in survey_ref.browse(cr, uid, survey_ids): report = self.create_report(cr, uid, [id.id], 'report.survey.form', id.title) - file = open(addons.get_module_resource('survey', 'report') + id.title +".pdf") + file = open(get_module_resource('survey', 'report') + id.title +".pdf") file_data = "" while 1: line = file.readline() @@ -137,7 +138,7 @@ Thanks,''') % (name, self.pool.get('ir.config_parameter').get_param(cr, uid, 'we break file.close() attachments[id.title +".pdf"] = file_data - os.remove(addons.get_module_resource('survey', 'report') + id.title +".pdf") + os.remove(get_module_resource('survey', 'report') + id.title +".pdf") for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids): if not partner.email: @@ -220,7 +221,6 @@ Thanks,''') % (name, self.pool.get('ir.config_parameter').get_param(cr, uid, 'we 'target': 'new', 'context': context } -survey_send_invitation() class survey_send_invitation_log(osv.osv_memory): _name = 'survey.send.invitation.log' @@ -235,6 +235,5 @@ class survey_send_invitation_log(osv.osv_memory): data['note'] = context.get('note', '') return data -survey_send_invitation_log() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/warning/warning.py b/addons/warning/warning.py index 4bdada396bc..e9e9161bacb 100644 --- a/addons/warning/warning.py +++ b/addons/warning/warning.py @@ -50,7 +50,6 @@ class res_partner(osv.osv): 'invoice_warn' : 'no-message', } -res_partner() class sale_order(osv.osv): @@ -79,7 +78,6 @@ class sale_order(osv.osv): warning['message'] = message and message + ' ' + result['warning']['message'] or result['warning']['message'] return {'value': result.get('value',{}), 'warning':warning} -sale_order() class purchase_order(osv.osv): @@ -108,7 +106,6 @@ class purchase_order(osv.osv): return {'value': result.get('value',{}), 'warning':warning} -purchase_order() class account_invoice(osv.osv): @@ -145,7 +142,6 @@ class account_invoice(osv.osv): return {'value': result.get('value',{}), 'warning':warning} -account_invoice() class stock_picking(osv.osv): _inherit = 'stock.picking' @@ -173,7 +169,6 @@ class stock_picking(osv.osv): return {'value': result.get('value',{}), 'warning':warning} -stock_picking() # FIXME:(class stock_picking_in and stock_picking_out) this is a temporary workaround because of a framework bug (ref: lp:996816). # It should be removed as soon as the bug is fixed @@ -243,7 +238,6 @@ class product_product(osv.osv): 'purchase_line_warn' : 'no-message', } -product_product() class sale_order_line(osv.osv): _inherit = 'sale.order.line' @@ -279,7 +273,6 @@ class sale_order_line(osv.osv): return {'value': result.get('value',{}), 'warning':warning} -sale_order_line() class purchase_order_line(osv.osv): _inherit = 'purchase.order.line' @@ -311,7 +304,6 @@ class purchase_order_line(osv.osv): return {'value': result.get('value',{}), 'warning':warning} -purchase_order_line() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/web_linkedin/i18n/cs.po b/addons/web_linkedin/i18n/cs.po new file mode 100644 index 00000000000..6057606cdf4 --- /dev/null +++ b/addons/web_linkedin/i18n/cs.po @@ -0,0 +1,137 @@ +# Czech 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-03-30 21:01+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-31 05:28+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "here:" +msgstr "" + +#. module: web_linkedin +#: field:sale.config.settings,api_key:0 +msgid "API Key" +msgstr "" + +#. module: web_linkedin +#. openerp-web +#: code:addons/web_linkedin/static/src/js/linkedin.js:249 +#, python-format +msgid "No results found" +msgstr "" + +#. module: web_linkedin +#. openerp-web +#: code:addons/web_linkedin/static/src/js/linkedin.js:84 +#, python-format +msgid "Ok" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "Log into LinkedIn." +msgstr "" + +#. module: web_linkedin +#. openerp-web +#: code:addons/web_linkedin/static/src/xml/linkedin.xml:13 +#, python-format +msgid "People" +msgstr "" + +#. module: web_linkedin +#: model:ir.model,name:web_linkedin.model_sale_config_settings +msgid "sale.config.settings" +msgstr "" + +#. module: web_linkedin +#: field:sale.config.settings,server_domain:0 +msgid "unknown" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "https://www.linkedin.com/secure/developer" +msgstr "" + +#. module: web_linkedin +#. openerp-web +#: code:addons/web_linkedin/static/src/xml/linkedin.xml:15 +#, python-format +msgid "Companies" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "API key" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "Copy the" +msgstr "" + +#. module: web_linkedin +#. openerp-web +#: code:addons/web_linkedin/static/src/js/linkedin.js:181 +#, python-format +msgid "LinkedIn search" +msgstr "" + +#. module: web_linkedin +#. openerp-web +#: code:addons/web_linkedin/static/src/xml/linkedin.xml:31 +#, python-format +msgid "" +"LinkedIn access was not enabled on this server.\n" +" Please ask your administrator to configure it in Settings > " +"Configuration > Sales > Social Network Integration." +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "" +"To use the LinkedIn module with this database, an API Key is required. " +"Please follow this procedure:" +msgstr "" + +#. module: web_linkedin +#. openerp-web +#: code:addons/web_linkedin/static/src/js/linkedin.js:82 +#, python-format +msgid "LinkedIn is not enabled" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "Add a new application and fill the form:" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "Go to this URL:" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "The programming tool is Javascript" +msgstr "" + +#. module: web_linkedin +#: view:sale.config.settings:0 +msgid "JavaScript API Domain:" +msgstr ""
- Disc.(%) + [[not show_discount(user.id) and removeParentNode('para') ]]Disc.(%) Price @@ -275,7 +275,7 @@ [[ formatLang(line.price_unit , digits=get_digits(dp='Product Price'))]] - [[ formatLang(line.discount, digits=get_digits(dp='Discount'))]] + [[show_discount(user.id) and formatLang(line.discount, digits=get_digits(dp='Discount')) or '']] [[ formatLang(line.price_subtotal, digits=get_digits(dp='Account'), currency_obj=o.pricelist_id.currency_id) ]] diff --git a/addons/sale/report/sale_report.py b/addons/sale/report/sale_report.py index a20ba01f300..80143379247 100644 --- a/addons/sale/report/sale_report.py +++ b/addons/sale/report/sale_report.py @@ -88,12 +88,11 @@ class sale_report(osv.osv): s.project_id as analytic_account_id from sale_order s - left join sale_order_line l on (s.id=l.order_id) + join sale_order_line l on (s.id=l.order_id) left join product_product p on (l.product_id=p.id) left join product_template t on (p.product_tmpl_id=t.id) left join product_uom u on (u.id=l.product_uom) left join product_uom u2 on (u2.id=t.uom_id) - where l.product_id is not null group by l.product_id, l.product_uom_qty, @@ -111,6 +110,5 @@ class sale_report(osv.osv): s.project_id ) """) -sale_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/res_config.py b/addons/sale/res_config.py index 3fb8e049e8d..ec2307ca983 100644 --- a/addons/sale/res_config.py +++ b/addons/sale/res_config.py @@ -22,7 +22,6 @@ import logging from openerp.osv import fields, osv -from openerp import pooler from openerp.tools.translate import _ _logger = logging.getLogger(__name__) @@ -144,6 +143,8 @@ class account_config_settings(osv.osv_memory): def onchange_sale_analytic_plans(self, cr, uid, ids, module_sale_analytic_plans, context=None): """ change group_analytic_account_for_sales following module_sale_analytic_plans """ + if not module_sale_analytic_plans: + return {} return {'value': {'group_analytic_account_for_sales': module_sale_analytic_plans}} # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/res_partner_view.xml b/addons/sale/res_partner_view.xml index 54a9813eea9..40ac119fdee 100644 --- a/addons/sale/res_partner_view.xml +++ b/addons/sale/res_partner_view.xml @@ -63,14 +63,34 @@ sale.group_delivery_invoice_address - - False False + sale.group_delivery_invoice_address - + + False + sale.group_delivery_invoice_address + + + False + sale.group_delivery_invoice_address + + + False + sale.group_delivery_invoice_address + + + False + sale.group_delivery_invoice_address + + + False + sale.group_delivery_invoice_address + + + False sale.group_delivery_invoice_address diff --git a/addons/sale/sale.py b/addons/sale/sale.py index bf9e9484b9f..210e4dd3be6 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -22,7 +22,6 @@ from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta import time -from openerp import pooler from openerp.osv import fields, osv from openerp.tools.translate import _ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP, float_compare @@ -43,7 +42,6 @@ class sale_shop(osv.osv): 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'sale.shop', context=c), } -sale_shop() class sale_order(osv.osv): _name = "sale.order" @@ -212,8 +210,7 @@ class sale_order(osv.osv): 'order_policy': fields.selection([ ('manual', 'On Demand'), ], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, - help="""This field controls how invoice and delivery operations are synchronized. - - With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""), + help="""This field controls how invoice and delivery operations are synchronized."""), 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."), 'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", string="Currency", readonly=True, required=True), 'project_id': fields.many2one('account.analytic.account', 'Contract / Analytic', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."), @@ -323,10 +320,6 @@ class sale_order(osv.osv): return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False, 'payment_term': False, 'fiscal_position': False}} part = self.pool.get('res.partner').browse(cr, uid, part, context=context) - #if the chosen partner is not a company and has a parent company, use the parent to choose the delivery, the - #invoicing addresses and all the fields related to the partner. - if part.parent_id and not part.is_company: - part = part.parent_id addr = self.pool.get('res.partner').address_get(cr, uid, [part.id], ['delivery', 'invoice', 'contact']) pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False payment_term = part.property_payment_term and part.property_payment_term.id or False @@ -544,6 +537,9 @@ class sale_order(osv.osv): invoice_ref += o.name + '|' self.write(cr, uid, [o.id], {'state': 'progress'}) cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res)) + #remove last '|' in invoice_ref + if len(invoice_ref) >= 1: + invoice_ref = invoice_ref[:-1] invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref}) else: for order, il in val: @@ -1024,4 +1020,16 @@ class account_invoice(osv.Model): sale_order_obj.message_post(cr, uid, so_ids, body=_("Invoice paid"), context=context) return res + def unlink(self, cr, uid, ids, context=None): + """ Overwrite unlink method of account invoice to send a trigger to the sale workflow upon invoice deletion """ + invoice_ids = self.search(cr, uid, [('id', 'in', ids), ('state', 'in', ['draft', 'cancel'])], context=context) + #if we can't cancel all invoices, do nothing + if len(invoice_ids) == len(ids): + #Cancel invoice(s) first before deleting them so that if any sale order is associated with them + #it will trigger the workflow to put the sale order in an 'invoice exception' state + wf_service = netsvc.LocalService("workflow") + for id in ids: + wf_service.trg_validate(uid, 'account.invoice', id, 'invoice_cancel', cr) + return super(account_invoice, self).unlink(cr, uid, ids, context=context) + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index e3a393666b4..e24a6e45fe0 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -156,7 +156,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -328,19 +328,23 @@ form tree,form,calendar,graph - {'show_address': 1} - [('state','not in',('draft','sent','cancel'))] + { + 'search_default_my_sale_orders_filter': 1 + } + + [('state', 'not in', ('draft', 'sent', 'cancel'))] -

- Click to create a quotation that can be converted into a sales - order. -

- OpenERP will help you efficiently handle the complete sales flow: - quotation, sales order, delivery, invoicing and payment. -

+

+ Click to create a quotation that can be converted into a sales + order. +

+ OpenERP will help you efficiently handle the complete sales flow: + quotation, sales order, delivery, invoicing and payment. +

- + + Sales in Exception @@ -371,7 +375,7 @@ form tree,form,calendar,graph - {'show_address': 1} + {'search_default_my_sale_orders_filter': 1} [('state','in',('draft','sent','cancel'))] @@ -390,8 +394,8 @@ + action="action_quotations" parent="base.menu_sales" + sequence="5"/> Old Quotations @@ -472,7 +476,7 @@ - + @@ -498,7 +502,7 @@ - + diff --git a/addons/sale/wizard/sale_line_invoice.py b/addons/sale/wizard/sale_line_invoice.py index bed474728d7..83b953cc4d5 100644 --- a/addons/sale/wizard/sale_line_invoice.py +++ b/addons/sale/wizard/sale_line_invoice.py @@ -21,11 +21,11 @@ from openerp.osv import osv, fields from openerp.tools.translate import _ -from openerp import netsvc class sale_order_line_make_invoice(osv.osv_memory): _name = "sale.order.line.make.invoice" _description = "Sale OrderLine Make_invoice" + def make_invoices(self, cr, uid, ids, context=None): """ To make invoices. @@ -82,34 +82,30 @@ class sale_order_line_make_invoice(osv.osv_memory): sales_order_obj = self.pool.get('sale.order') for line in sales_order_line_obj.browse(cr, uid, context.get('active_ids', []), context=context): if (not line.invoiced) and (line.state not in ('draft', 'cancel')): - if not line.order_id.id in invoices: - invoices[line.order_id.id] = [] - line_id = sales_order_line_obj.invoice_line_create(cr, uid, - [line.id]) + if not line.order_id in invoices: + invoices[line.order_id] = [] + line_id = sales_order_line_obj.invoice_line_create(cr, uid, [line.id]) for lid in line_id: - invoices[line.order_id.id].append((line, lid)) - for result in invoices.values(): - order = result[0][0].order_id - il = map(lambda x: x[1], result) + invoices[line.order_id].append(lid) + for order, il in invoices.items(): res = make_invoice(order, il) cr.execute('INSERT INTO sale_order_invoice_rel \ (order_id,invoice_id) values (%s,%s)', (order.id, res)) - flag = True - data_sale = sales_order_obj.browse(cr, uid, line.order_id.id, context=context) sales_order_obj.message_post(cr, uid, [order.id], body=_("Invoice created"), context=context) + data_sale = sales_order_obj.browse(cr, uid, order.id, context=context) for line in data_sale.order_line: if not line.invoiced: flag = False break if flag: - sales_order_obj.signal_manual_invoice(cr, uid, [line.order_id.id]) - sales_order_obj.write(cr, uid, [line.order_id.id], {'state': 'progress'}) + wf_service.trg_validate(uid, 'sale.order', order.id, 'manual_invoice', cr) + sales_order_obj.write(cr, uid, [order.id], {'state': 'progress'}) if not invoices: raise osv.except_osv(_('Warning!'), _('Invoice cannot be created for this Sales Order Line due to one of the following reasons:\n1.The state of this sales order line is either "draft" or "cancel"!\n2.The Sales Order Line is Invoiced!')) if context.get('open_invoices', False): - return self.open_invoices( cr, uid, ids, res, context=context) + return self.open_invoices(cr, uid, ids, res, context=context) return {'type': 'ir.actions.act_window_close'} def open_invoices(self, cr, uid, ids, invoice_ids, context=None): @@ -119,7 +115,7 @@ class sale_order_line_make_invoice(osv.osv_memory): form_id = form_res and form_res[1] or False tree_res = ir_model_data.get_object_reference(cr, uid, 'account', 'invoice_tree') tree_id = tree_res and tree_res[1] or False - + return { 'name': _('Invoice'), 'view_type': 'form', @@ -132,6 +128,5 @@ class sale_order_line_make_invoice(osv.osv_memory): 'type': 'ir.actions.act_window', } -sale_order_line_make_invoice() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/wizard/sale_make_invoice.py b/addons/sale/wizard/sale_make_invoice.py index 1b885998f83..3712feda20b 100644 --- a/addons/sale/wizard/sale_make_invoice.py +++ b/addons/sale/wizard/sale_make_invoice.py @@ -20,7 +20,6 @@ from openerp.osv import fields, osv from openerp.tools.translate import _ -from openerp import netsvc class sale_make_invoice(osv.osv_memory): _name = "sale.make.invoice" @@ -40,7 +39,7 @@ class sale_make_invoice(osv.osv_memory): record_id = context and context.get('active_id', False) order = self.pool.get('sale.order').browse(cr, uid, record_id, context=context) if order.state == 'draft': - raise osv.except_osv(_('Warning!'),'You cannot create invoice when sales order is not confirmed.') + raise osv.except_osv(_('Warning!'), _('You cannot create invoice when sales order is not confirmed.')) return False def make_invoices(self, cr, uid, ids, context=None): @@ -51,8 +50,11 @@ class sale_make_invoice(osv.osv_memory): if context is None: context = {} data = self.read(cr, uid, ids)[0] - order_obj.action_invoice_create(cr, uid, context.get(('active_ids'), []), data['grouped'], date_invoice = data['invoice_date']) - order_obj.signal_manual_invoice(cr, uid, context.get(('active_ids'), [])) + for sale_order in order_obj.browse(cr, uid, context.get(('active_ids'), []), context=context): + if sale_order.state != 'manual': + raise osv.except_osv(_('Warning!'), _("You shouldn't manually invoice the following sale order %s") % (sale_order.name)) + + order_obj.action_invoice_create(cr, uid, context.get(('active_ids'), []), data['grouped'], date_invoice=data['invoice_date']) for o in order_obj.browse(cr, uid, context.get(('active_ids'), []), context=context): for i in o.invoice_ids: @@ -61,10 +63,9 @@ class sale_make_invoice(osv.osv_memory): result = mod_obj.get_object_reference(cr, uid, 'account', 'action_invoice_tree1') id = result and result[1] or False result = act_obj.read(cr, uid, [id], context=context)[0] - result['domain'] = "[('id','in', ["+','.join(map(str,newinv))+"])]" + result['domain'] = "[('id','in', [" + ','.join(map(str, newinv)) + "])]" return result -sale_make_invoice() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/wizard/sale_make_invoice.xml b/addons/sale/wizard/sale_make_invoice.xml index ced64a0f79d..de680feb049 100644 --- a/addons/sale/wizard/sale_make_invoice.xml +++ b/addons/sale/wizard/sale_make_invoice.xml @@ -6,16 +6,16 @@ sale.make.invoice -
-
+
+
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py index 5d3cc165b46..4cb00245ade 100644 --- a/addons/sale/wizard/sale_make_invoice_advance.py +++ b/addons/sale/wizard/sale_make_invoice_advance.py @@ -210,6 +210,5 @@ class sale_advance_payment_inv(osv.osv_memory): 'type': 'ir.actions.act_window', } -sale_advance_payment_inv() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_analytic_plans/sale_analytic_plans.py b/addons/sale_analytic_plans/sale_analytic_plans.py index 2abbab7ab38..522f6b6f0fb 100644 --- a/addons/sale_analytic_plans/sale_analytic_plans.py +++ b/addons/sale_analytic_plans/sale_analytic_plans.py @@ -37,7 +37,6 @@ class sale_order_line(osv.osv): i = i + 1 return create_ids -sale_order_line() class sale_order(osv.osv): _inherit = "sale.order" diff --git a/addons/sale_analytic_plans/sale_analytic_plans_view.xml b/addons/sale_analytic_plans/sale_analytic_plans_view.xml index 6c788866520..3600d71b7d4 100644 --- a/addons/sale_analytic_plans/sale_analytic_plans_view.xml +++ b/addons/sale_analytic_plans/sale_analytic_plans_view.xml @@ -38,5 +38,19 @@
+ + + + + account.invoice.line.form.inherit + account.invoice.line + + + + + + + + diff --git a/addons/sale_crm/report/sale_crm_account_invoice_report_view.xml b/addons/sale_crm/report/sale_crm_account_invoice_report_view.xml index 41166d56713..983701d9690 100644 --- a/addons/sale_crm/report/sale_crm_account_invoice_report_view.xml +++ b/addons/sale_crm/report/sale_crm_account_invoice_report_view.xml @@ -10,7 +10,7 @@ - + diff --git a/addons/sale_crm/sale_crm.py b/addons/sale_crm/sale_crm.py index 1f3f85d5ed1..d0899729050 100644 --- a/addons/sale_crm/sale_crm.py +++ b/addons/sale_crm/sale_crm.py @@ -19,8 +19,10 @@ # ############################################################################## +from datetime import datetime from openerp.osv import osv, fields + class sale_order(osv.osv): _inherit = 'sale.order' _columns = { @@ -30,19 +32,64 @@ class sale_order(osv.osv): } +class crm_case_section(osv.osv): + _inherit = 'crm.case.section' + + def _get_sum_month_invoice(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) + obj = self.pool.get('account.invoice.report') + when = datetime.today() + for section_id in ids: + invoice_ids = obj.search(cr, uid, [("section_id", "=", section_id), ('state', 'not in', ['draft', 'cancel']), ('year', '=', when.year), ('month', '=', when.month > 9 and when.month or "0%s" % when.month)], context=context) + for invoice in obj.browse(cr, uid, invoice_ids, context=context): + res[section_id] += invoice.price_total + return res + + _columns = { + 'quotation_ids': fields.one2many('sale.order', 'section_id', + string='Quotations', readonly=True, + domain=[('state', 'in', ['draft', 'sent', 'cancel'])]), + 'sale_order_ids': fields.one2many('sale.order', 'section_id', + string='Sale Orders', readonly=True, + domain=[('state', 'not in', ['draft', 'sent', 'cancel'])]), + 'invoice_ids': fields.one2many('account.invoice', 'section_id', + string='Invoices', readonly=True, + domain=[('state', 'not in', ['draft', 'cancel'])]), + 'sum_month_invoice': fields.function(_get_sum_month_invoice, + string='Total invoiced this month', + type='integer', readonly=True), + } + + class res_users(osv.Model): _inherit = 'res.users' _columns = { 'default_section_id': fields.many2one('crm.case.section', 'Default Sales Team'), } + +class sale_crm_lead(osv.Model): + _inherit = 'crm.lead' + + def on_change_user(self, cr, uid, ids, user_id, context=None): + """ Override of on change user_id on lead/opportunity; when having sale + the new logic is : + - use user.default_section_id + - or fallback on previous behavior """ + if user_id: + user = self.pool.get('res.users').browse(cr, uid, user_id, context=context) + if user.default_section_id and user.default_section_id.id: + return {'value': {'section_id': user.default_section_id.id}} + return super(sale_crm_lead, self).on_change_user(cr, uid, ids, user_id, context=context) + + class account_invoice(osv.osv): _inherit = 'account.invoice' _columns = { 'section_id': fields.many2one('crm.case.section', 'Sales Team'), } _defaults = { - 'section_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).default_section_id.id or False, + 'section_id': lambda self, cr, uid, c=None: self.pool.get('res.users').browse(cr, uid, uid, c).default_section_id.id or False, } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml index 0b5fce2f5cd..f8b4228334e 100644 --- a/addons/sale_crm/sale_crm_view.xml +++ b/addons/sale_crm/sale_crm_view.xml @@ -22,7 +22,7 @@ - + @@ -41,7 +41,7 @@ help="My Sales Team(s)"/> - + @@ -53,18 +53,22 @@ - - + + + account.invoice.groupby account.invoice + + + @@ -79,7 +83,7 @@ - + @@ -113,5 +117,132 @@ + + + + Sales Orders + ir.actions.act_window + sale.order + form + tree,form,calendar,graph + + [('state','not in',('draft','sent','cancel'))] + { + 'search_default_section_id': [active_id], + 'default_section_id': active_id, + 'search_default_my_sale_orders_filter': 1, + } + + +

+ Click to create a quotation that can be converted into a sales + order. +

+ OpenERP will help you efficiently handle the complete sales flow: + quotation, sales order, delivery, invoicing and payment. +

+
+
+ + + Quotations + ir.actions.act_window + sale.order + form + + tree,form,calendar,graph + { + 'search_default_section_id': [active_id], + 'default_section_id': active_id, 'show_address': 1, + 'search_default_my_sale_orders_filter': 1 + } + + [('state','in',('draft','sent','cancel'))] + + +

+ Click to create a quotation, the first step of a new sale. +

+ OpenERP will help you handle efficiently the complete sale flow: + from the quotation to the sales order, the + delivery, the invoicing and the payment collection. +

+ The social feature helps you organize discussions on each sales + order, and allow your customers to keep track of the evolution + of the sales order. +

+
+
+ + + Invoices + account.invoice + form + tree,form,calendar,graph + + [ + ('state', 'not in', ['draft', 'cancel']), + ('type', '=', 'out_invoice')] + { + 'search_default_section_id': [active_id], + 'default_section_id': active_id}, + 'default_type':'out_invoice', + 'type':'out_invoice', + 'journal_type': 'sale', + } + + + + + + 1 + tree + + + + + 2 + form + + + + + + crm.case.section.kanban + crm.case.section + + + + + + + + + + + + Quotations + Quotation + + + + Sales Orders + Sales Order + + + + Invoices + Invoice + + + +
+
+
Invoiced this month
+
+
+
+
+
diff --git a/addons/sale_crm/wizard/crm_make_sale.py b/addons/sale_crm/wizard/crm_make_sale.py index a052f47ca1f..6bea6286456 100644 --- a/addons/sale_crm/wizard/crm_make_sale.py +++ b/addons/sale_crm/wizard/crm_make_sale.py @@ -153,6 +153,5 @@ class crm_make_sale(osv.osv_memory): 'partner_id': _selectPartner, } -crm_make_sale() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_journal/sale_journal.py b/addons/sale_journal/sale_journal.py index 8463ab3f3bd..9e10c826898 100644 --- a/addons/sale_journal/sale_journal.py +++ b/addons/sale_journal/sale_journal.py @@ -34,7 +34,6 @@ class sale_journal_invoice_type(osv.osv): 'active': True, 'invoicing_method': 'simple' } -sale_journal_invoice_type() #============================================== # sale journal inherit @@ -52,28 +51,28 @@ class res_partner(osv.osv): group_name = "Accounting Properties", help = "This invoicing type will be used, by default, to invoice 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_invoice_type'] + class picking(osv.osv): _inherit = "stock.picking" _columns = { 'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type', readonly=True) } -picking() class stock_picking_in(osv.osv): _inherit = "stock.picking.in" _columns = { 'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type', readonly=True) } -stock_picking_in() class stock_picking_out(osv.osv): _inherit = "stock.picking.out" _columns = { 'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type', readonly=True) } -stock_picking_out() class sale(osv.osv): @@ -95,6 +94,5 @@ class sale(osv.osv): result['value']['invoice_type_id'] = itype.id return result -sale() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_journal/sale_journal_view.xml b/addons/sale_journal/sale_journal_view.xml index bcd83b5be84..9d41103252e 100644 --- a/addons/sale_journal/sale_journal_view.xml +++ b/addons/sale_journal/sale_journal_view.xml @@ -146,7 +146,7 @@ - + diff --git a/addons/sale_margin/i18n/cs.po b/addons/sale_margin/i18n/cs.po new file mode 100644 index 00000000000..dd01e0973bc --- /dev/null +++ b/addons/sale_margin/i18n/cs.po @@ -0,0 +1,46 @@ +# Czech 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-03-30 12:41+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-31 05:27+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: sale_margin +#: field:sale.order.line,purchase_price:0 +msgid "Cost Price" +msgstr "" + +#. module: sale_margin +#: model:ir.model,name:sale_margin.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: sale_margin +#: field:sale.order,margin:0 +#: field:sale.order.line,margin:0 +msgid "Margin" +msgstr "" + +#. module: sale_margin +#: model:ir.model,name:sale_margin.model_sale_order_line +msgid "Sales Order Line" +msgstr "" + +#. module: sale_margin +#: help:sale.order,margin:0 +msgid "" +"It gives profitability by calculating the difference between the Unit Price " +"and the cost price." +msgstr "" diff --git a/addons/sale_margin/sale_margin.py b/addons/sale_margin/sale_margin.py index dc8c4dfff3c..4c2e9ffc4f4 100644 --- a/addons/sale_margin/sale_margin.py +++ b/addons/sale_margin/sale_margin.py @@ -56,7 +56,6 @@ class sale_order_line(osv.osv): 'purchase_price': fields.float('Cost Price', digits=(16,2)) } -sale_order_line() class sale_order(osv.osv): _inherit = "sale.order" @@ -82,6 +81,5 @@ class sale_order(osv.osv): }), } -sale_order() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/sale_mrp/i18n/cs.po b/addons/sale_mrp/i18n/cs.po new file mode 100644 index 00000000000..78ae9292dbd --- /dev/null +++ b/addons/sale_mrp/i18n/cs.po @@ -0,0 +1,43 @@ +# Czech 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-03-30 12:41+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-31 05:27+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: sale_mrp +#: model:ir.model,name:sale_mrp.model_mrp_production +msgid "Manufacturing Order" +msgstr "" + +#. module: sale_mrp +#: help:mrp.production,sale_name:0 +msgid "Indicate the name of sales order." +msgstr "" + +#. module: sale_mrp +#: help:mrp.production,sale_ref:0 +msgid "Indicate the Customer Reference from sales order." +msgstr "" + +#. module: sale_mrp +#: field:mrp.production,sale_ref:0 +msgid "Sale Reference" +msgstr "" + +#. module: sale_mrp +#: field:mrp.production,sale_name:0 +msgid "Sale Name" +msgstr "" diff --git a/addons/sale_mrp/sale_mrp.py b/addons/sale_mrp/sale_mrp.py index a5043d3b7d5..77a35972638 100644 --- a/addons/sale_mrp/sale_mrp.py +++ b/addons/sale_mrp/sale_mrp.py @@ -74,6 +74,5 @@ class mrp_production(osv.osv): 'sale_ref': fields.function(_ref_calc, multi='sale_name', type='char', string='Sale Reference', help='Indicate the Customer Reference from sales order.'), } -mrp_production() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_mrp/test/sale_mrp.yml b/addons/sale_mrp/test/sale_mrp.yml index 9b70e052854..5be5210b623 100644 --- a/addons/sale_mrp/test/sale_mrp.yml +++ b/addons/sale_mrp/test/sale_mrp.yml @@ -92,11 +92,10 @@ I verify that a procurement has been generated for sale order - !python {model: procurement.order}: | - from openerp.tools.translate import _ sale_order_obj = self.pool.get('sale.order') so = sale_order_obj.browse(cr, uid, ref("sale_order_so0")) proc_ids = self.search(cr, uid, [('origin','=',so.name)]) - assert proc_ids, _('No Procurements!') + assert proc_ids, 'No Procurements!' - Then I click on the "Run Procurement" button - @@ -112,7 +111,7 @@ sale_order_obj = self.pool.get('sale.order') so = sale_order_obj.browse(cr, uid, ref("sale_order_so0")) proc_ids = self.search(cr, uid, [('origin','=',so.name) and ('state','=','running')]) - assert proc_ids, _('Procurement is not in the running state!') + assert proc_ids, 'Procurement is not in the running state!' - I verify that a manufacturing order has been generated, and that its name and reference are correct - @@ -120,7 +119,7 @@ mnf_obj = self.pool.get('mrp.production') so = self.browse(cr, uid, ref("sale_order_so0")) mnf_id = mnf_obj.search(cr, uid, [('origin','=',so.name)]) - assert mnf_id, _('Manufacturing order has not been generated') + assert mnf_id, 'Manufacturing order has not been generated' mo = mnf_obj.browse(cr, uid, mnf_id)[0] assert mo.sale_name == so.name, 'Wrong Name for the Manufacturing Order. Expected %s, Got %s' % (so.name, mo.name) assert mo.sale_ref == so.client_order_ref, 'Wrong Sale Reference for the Manufacturing Order' diff --git a/addons/sale_order_dates/i18n/cs.po b/addons/sale_order_dates/i18n/cs.po new file mode 100644 index 00000000000..a1583d48efe --- /dev/null +++ b/addons/sale_order_dates/i18n/cs.po @@ -0,0 +1,58 @@ +# Czech 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-03-30 12:41+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech \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-31 05:27+0000\n" +"X-Generator: Launchpad (build 16546)\n" + +#. module: sale_order_dates +#: view:sale.order:0 +msgid "Dates" +msgstr "" + +#. module: sale_order_dates +#: field:sale.order,commitment_date:0 +msgid "Commitment Date" +msgstr "" + +#. module: sale_order_dates +#: field:sale.order,effective_date:0 +msgid "Effective Date" +msgstr "" + +#. module: sale_order_dates +#: help:sale.order,effective_date:0 +msgid "Date on which picking is created." +msgstr "" + +#. module: sale_order_dates +#: help:sale.order,requested_date:0 +msgid "Date requested by the customer for the sale." +msgstr "" + +#. module: sale_order_dates +#: field:sale.order,requested_date:0 +msgid "Requested Date" +msgstr "" + +#. module: sale_order_dates +#: model:ir.model,name:sale_order_dates.model_sale_order +msgid "Sales Order" +msgstr "" + +#. module: sale_order_dates +#: help:sale.order,commitment_date:0 +msgid "Committed date for delivery." +msgstr "" diff --git a/addons/sale_order_dates/sale_order_dates.py b/addons/sale_order_dates/sale_order_dates.py index d54eca88ca5..64b939de088 100644 --- a/addons/sale_order_dates/sale_order_dates.py +++ b/addons/sale_order_dates/sale_order_dates.py @@ -59,6 +59,5 @@ class sale_order_dates(osv.osv): 'effective_date': fields.function(_get_effective_date, type='date', store=True, string='Effective Date',help="Date on which picking is created."), } -sale_order_dates() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/company.py b/addons/sale_stock/company.py index 67440ed6c67..5be1dbd524d 100644 --- a/addons/sale_stock/company.py +++ b/addons/sale_stock/company.py @@ -24,13 +24,15 @@ from openerp.osv import fields, osv class company(osv.osv): _inherit = 'res.company' _columns = { - 'security_lead': fields.float('Security Days', required=True, - help="This is the days added to what you promise to customers "\ - "for security purpose"), + 'security_lead': fields.float( + 'Security Days', required=True, + help="Margin of error for dates promised to customers. "\ + "Products will be scheduled for procurement and delivery "\ + "that many days earlier than the actual promised date, to "\ + "cope with unexpected delays in the supply chain."), } _defaults = { 'security_lead': 0.0, } -company() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/process/sale_stock_process.xml b/addons/sale_stock/process/sale_stock_process.xml index 666f6ba6502..c10b34c8866 100644 --- a/addons/sale_stock/process/sale_stock_process.xml +++ b/addons/sale_stock/process/sale_stock_process.xml @@ -64,17 +64,6 @@ - - - - - - - - - @@ -106,7 +95,7 @@ - + diff --git a/addons/sale_stock/report/sale_report.py b/addons/sale_stock/report/sale_report.py index ade84b269e6..63641020d98 100644 --- a/addons/sale_stock/report/sale_report.py +++ b/addons/sale_stock/report/sale_report.py @@ -68,8 +68,8 @@ class sale_report(osv.osv): s.project_id as analytic_account_id from sale_order s - left join sale_order_line l on (s.id=l.order_id) - left join product_product p on (l.product_id=p.id) + join sale_order_line l on (s.id=l.order_id) + left join product_product p on (l.product_id=p.id) left join product_template t on (p.product_tmpl_id=t.id) left join product_uom u on (u.id=l.product_uom) left join product_uom u2 on (u2.id=t.uom_id) @@ -91,6 +91,5 @@ class sale_report(osv.osv): s.project_id ) """) -sale_report() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_stock/res_config.py b/addons/sale_stock/res_config.py index 3a6dcb404dd..d06b6a81b32 100644 --- a/addons/sale_stock/res_config.py +++ b/addons/sale_stock/res_config.py @@ -20,7 +20,6 @@ ############################################################################## from openerp.osv import fields, osv -from openerp import pooler from openerp.tools.translate import _ class sale_configuration(osv.osv_memory): diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index bd4eb2b8256..e71fb92f842 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -24,6 +24,8 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO from dateutil.relativedelta import relativedelta from openerp.osv import fields, osv from openerp.tools.translate import _ +import pytz +from openerp import SUPERUSER_ID class sale_shop(osv.osv): _inherit = "sale.shop" @@ -31,7 +33,6 @@ class sale_shop(osv.osv): 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'), } -sale_shop() class sale_order(osv.osv): _inherit = "sale.order" @@ -229,6 +230,29 @@ class sale_order(osv.osv): res.append(line.procurement_id.id) return res + def date_to_datetime(self, cr, uid, userdate, context=None): + """ Convert date values expressed in user's timezone to + server-side UTC timestamp, assuming a default arbitrary + time of 12:00 AM - because a time is needed. + + :param str userdate: date string in in user time zone + :return: UTC datetime string for server-side use + """ + # TODO: move to fields.datetime in server after 7.0 + user_date = datetime.strptime(userdate, DEFAULT_SERVER_DATE_FORMAT) + if context and context.get('tz'): + tz_name = context['tz'] + else: + tz_name = self.pool.get('res.users').read(cr, SUPERUSER_ID, uid, ['tz'])['tz'] + if tz_name: + utc = pytz.timezone('UTC') + context_tz = pytz.timezone(tz_name) + user_datetime = user_date + relativedelta(hours=12.0) + local_timestamp = context_tz.localize(user_datetime, is_dst=False) + user_datetime = local_timestamp.astimezone(utc) + return user_datetime.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + return user_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + # if mode == 'finished': # returns True if all lines are done, False otherwise # if mode == 'canceled': @@ -311,7 +335,7 @@ class sale_order(osv.osv): return { 'name': pick_name, 'origin': order.name, - 'date': order.date_order, + 'date': self.date_to_datetime(cr, uid, order.date_order, context), 'type': 'out', 'state': 'auto', 'move_type': order.picking_policy, @@ -345,7 +369,8 @@ class sale_order(osv.osv): return True def _get_date_planned(self, cr, uid, order, line, start_date, context=None): - date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=line.delay or 0.0) + start_date = self.date_to_datetime(cr, uid, start_date, context) + date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=line.delay or 0.0) date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) return date_planned @@ -605,11 +630,6 @@ class sale_advance_payment_inv(osv.osv_memory): sale_line_obj = self.pool.get('sale.order.line') wizard = self.browse(cr, uid, [result], context) sale = sale_obj.browse(cr, uid, sale_id, context=context) - if sale.order_policy == 'postpaid': - raise osv.except_osv( - _('Error!'), - _("You cannot make an advance on a sales order \ - that is defined as 'Automatic Invoice after delivery'.")) # If invoice on picking: add the cost on the SO # If not, the advance will be deduced when generating the final invoice diff --git a/addons/sale_stock/stock.py b/addons/sale_stock/stock.py index e1070998ae8..ad19684c4cf 100644 --- a/addons/sale_stock/stock.py +++ b/addons/sale_stock/stock.py @@ -54,7 +54,7 @@ class stock_picking(osv.osv): We select the partner of the sales order as the partner of the customer invoice """ if picking.sale_id: - return picking.sale_id.partner_id + return picking.sale_id.partner_invoice_id return super(stock_picking, self)._get_partner_to_invoice(cr, uid, picking, context=context) def _get_comment_invoice(self, cursor, user, picking): diff --git a/addons/sale_stock/test/picking_order_policy.yml b/addons/sale_stock/test/picking_order_policy.yml index f761dfb65db..afffda1ef21 100644 --- a/addons/sale_stock/test/picking_order_policy.yml +++ b/addons/sale_stock/test/picking_order_policy.yml @@ -5,6 +5,12 @@ - !assert {model: sale.order, id: sale.sale_order_6, string: The amount of the Quotation is not correctly computed}: - sum([l.price_subtotal for l in order_line]) == amount_untaxed +- + I set an explicit invoicing partner that is different from the main SO Customer +- + !python {model: sale.order, id: sale.sale_order_6}: | + order = self.browse(cr, uid, ref("sale.sale_order_6")) + order.write({'partner_invoice_id': ref('base.res_partner_address_29')}) - I confirm the quotation with Invoice based on deliveries policy. - @@ -26,7 +32,8 @@ order = self.browse(cr, uid, ref("sale.sale_order_6")) for order_line in order.order_line: procurement = order_line.procurement_id - date_planned = datetime.strptime(order.date_order, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=order_line.delay or 0.0) + sale_order_date = self.date_to_datetime(cr, uid, order.date_order, context) + date_planned = datetime.strptime(sale_order_date, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=order_line.delay or 0.0) date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) assert procurement.date_planned == date_planned, "Scheduled date is not correspond." assert procurement.product_id.id == order_line.product_id.id, "Product is not correspond." @@ -60,7 +67,8 @@ output_id = sale_order.shop_id.warehouse_id.lot_output_id.id for move in picking.move_lines: order_line = move.sale_line_id - date_planned = datetime.strptime(sale_order.date_order, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=order_line.delay or 0.0) + sale_order_date = self.date_to_datetime(cr, uid, sale_order.date_order, context) + date_planned = datetime.strptime(sale_order_date, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=order_line.delay or 0.0) date_planned = (date_planned - timedelta(days=sale_order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) assert datetime.strptime(move.date_expected, DEFAULT_SERVER_DATETIME_FORMAT) == datetime.strptime(date_planned, DEFAULT_SERVER_DATETIME_FORMAT), "Excepted Date is not correspond with Planned Date." assert move.product_id.id == order_line.product_id.id,"Product is not correspond." @@ -108,13 +116,13 @@ !python {model: sale.order}: | order = self.browse(cr, uid, ref("sale.sale_order_6")) assert order.invoice_ids, "Invoice is not created." - ac = order.partner_id.property_account_receivable.id + ac = order.partner_invoice_id.property_account_receivable.id journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale'), ('company_id', '=', order.company_id.id)]) for invoice in order.invoice_ids: assert invoice.type == 'out_invoice',"Invoice should be Customer Invoice." assert invoice.account_id.id == ac,"Invoice account is not correspond." assert invoice.reference == order.client_order_ref or order.name,"Reference is not correspond." - assert invoice.partner_id.id == order.partner_id.id,"Customer is not correspond." + assert invoice.partner_id.id == order.partner_invoice_id.id,"Customer does not correspond." assert invoice.currency_id.id == order.pricelist_id.currency_id.id, "Currency is not correspond." assert invoice.comment == (order.note or ''),"Note is not correspond." assert invoice.journal_id.id in journal_ids,"Sales Journal is not link on Invoice." @@ -162,8 +170,9 @@ - !python {model: sale.order}: | import os - from openerp import netsvc, tools - (data, format) = netsvc.LocalService('report.sale.order').create(cr, uid, [ref('sale.sale_order_6')], {}, {}) + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('sale.sale_order_6')], 'sale.order', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'sale-sale_order.'+format), 'wb+').write(data) diff --git a/addons/share/res_users.py b/addons/share/res_users.py index 25fd25c234f..30200133f8e 100644 --- a/addons/share/res_users.py +++ b/addons/share/res_users.py @@ -34,7 +34,6 @@ class res_groups(osv.osv): domain.append(('share', '=', False)) return super(res_groups, self).get_application_groups(cr, uid, domain=domain, context=context) -res_groups() class res_users(osv.osv): _name = 'res.users' @@ -43,6 +42,5 @@ class res_users(osv.osv): 'share': fields.boolean('Share User', readonly=True, help="External user with limited access, created only for the purpose of sharing data.") } -res_users() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py index 429a1dc2f08..3a26dcb9e6b 100644 --- a/addons/share/wizard/share_wizard.py +++ b/addons/share/wizard/share_wizard.py @@ -205,7 +205,7 @@ class share_wizard(osv.TransientModel): raise osv.except_osv(_('No email address configured'), _('You must configure your email address in the user preferences before using the Share button.')) model, res_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'share', 'action_share_wizard_step1') - action = self.pool.get(model).read(cr, uid, res_id, context=context) + action = self.pool[model].read(cr, uid, res_id, context=context) action['res_id'] = ids[0] action.pop('context', '') return action @@ -404,7 +404,7 @@ class share_wizard(osv.TransientModel): local_rel_fields = [] models = [x[1].model for x in relation_fields] model_obj = self.pool.get('ir.model') - model_osv = self.pool.get(model.model) + model_osv = self.pool[model.model] for colinfo in model_osv._all_columns.itervalues(): coldef = colinfo.column coltype = coldef._type @@ -412,7 +412,7 @@ class share_wizard(osv.TransientModel): if coltype in ttypes and colinfo.column._obj not in models: relation_model_id = model_obj.search(cr, UID_ROOT, [('model','=',coldef._obj)])[0] relation_model_browse = model_obj.browse(cr, UID_ROOT, relation_model_id, context=context) - relation_osv = self.pool.get(coldef._obj) + relation_osv = self.pool[coldef._obj] if coltype == 'one2many': # don't record reverse path if it's not a real m2o (that happens, but rarely) dest_model_ci = relation_osv._all_columns @@ -422,7 +422,7 @@ class share_wizard(osv.TransientModel): local_rel_fields.append((relation_field, relation_model_browse)) for parent in relation_osv._inherits: if parent not in models: - parent_model = self.pool.get(parent) + parent_model = self.pool[parent] parent_colinfos = parent_model._all_columns parent_model_browse = model_obj.browse(cr, UID_ROOT, model_obj.search(cr, UID_ROOT, [('model','=',parent)]))[0] @@ -458,7 +458,7 @@ class share_wizard(osv.TransientModel): """ # obj0 class and its parents obj0 = [(None, model)] - model_obj = self.pool.get(model.model) + model_obj = self.pool[model.model] ir_model_obj = self.pool.get('ir.model') for parent in model_obj._inherits: parent_model_browse = ir_model_obj.browse(cr, UID_ROOT, @@ -777,7 +777,7 @@ class share_wizard(osv.TransientModel): # Record id not found: issue if res_id <= 0: raise osv.except_osv(_('Record id not found'), _('The share engine has not been able to fetch a record_id for your invitation.')) - self.pool.get(model.model).message_subscribe(cr, uid, [res_id], new_ids + existing_ids, context=context) + self.pool[model.model].message_subscribe(cr, uid, [res_id], new_ids + existing_ids, context=context) # self.send_invite_email(cr, uid, wizard_data, context=context) # self.send_invite_note(cr, uid, model.model, res_id, wizard_data, context=context) @@ -823,7 +823,7 @@ class share_wizard(osv.TransientModel): elif tmp_idx == len(wizard_data.result_line_ids)-2: body += ' and' body += '.' - return self.pool.get(model_name).message_post(cr, uid, [res_id], body=body, context=context) + return self.pool[model_name].message_post(cr, uid, [res_id], body=body, context=context) def send_invite_email(self, cr, uid, wizard_data, context=None): # TDE Note: not updated because will disappear @@ -902,7 +902,6 @@ class share_wizard(osv.TransientModel): options = dict(title=opt_title, search=opt_search) return {'value': {'embed_code': self._generate_embedded_code(wizard, options)}} -share_wizard() class share_result_line(osv.osv_memory): _name = 'share.wizard.result.line' diff --git a/addons/stock/partner.py b/addons/stock/partner.py index f5f02b7cd19..b8bad4faf95 100644 --- a/addons/stock/partner.py +++ b/addons/stock/partner.py @@ -41,6 +41,5 @@ class res_partner(osv.osv): help="This stock location will be used, instead of the default one, as the source location for goods you receive from the current partner"), } -res_partner() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/product.py b/addons/stock/product.py index 1d56ce64988..29445f671ee 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -479,7 +479,6 @@ class product_product(osv.osv): res['fields']['qty_available']['string'] = _('Produced Qty') return res -product_product() class product_template(osv.osv): _name = 'product.template' @@ -528,7 +527,6 @@ class product_template(osv.osv): _defaults = { 'sale_delay': 7, } -product_template() class product_category(osv.osv): @@ -558,6 +556,5 @@ class product_category(osv.osv): help="When real-time inventory valuation is enabled on a product, this account will hold the current value of the products.",), } -product_category() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/report/lot_overview.py b/addons/stock/report/lot_overview.py index 9d6626bbd14..c8e80ac54b9 100644 --- a/addons/stock/report/lot_overview.py +++ b/addons/stock/report/lot_overview.py @@ -18,7 +18,6 @@ # along with this program. If not, see . # ############################################################################## -from openerp import pooler import time from openerp.report import report_sxw @@ -35,7 +34,7 @@ class lot_overview(report_sxw.rml_parse): }) def process(self, location_id): - location_obj = pooler.get_pool(self.cr.dbname).get('stock.location') + location_obj = self.pool['stock.location'] data = location_obj._product_get_report(self.cr,self.uid, [location_id]) data['location_name'] = location_obj.read(self.cr, self.uid, [location_id],['complete_name'])[0]['complete_name'] diff --git a/addons/stock/report/lot_overview_all.py b/addons/stock/report/lot_overview_all.py index ca6611de89b..aba97fa6e1e 100644 --- a/addons/stock/report/lot_overview_all.py +++ b/addons/stock/report/lot_overview_all.py @@ -18,7 +18,6 @@ # along with this program. If not, see . # ############################################################################## -from openerp import pooler import time from openerp.report import report_sxw @@ -35,7 +34,7 @@ class lot_overview_all(report_sxw.rml_parse): }) def process(self, location_id): - location_obj = pooler.get_pool(self.cr.dbname).get('stock.location') + location_obj = self.pool['stock.location'] data = location_obj._product_get_all_report(self.cr,self.uid, [location_id]) data['location_name'] = location_obj.read(self.cr, self.uid, [location_id],['complete_name'])[0]['complete_name'] self.price_total = 0.0 diff --git a/addons/stock/report/picking.py b/addons/stock/report/picking.py index a33ec28cb35..512d124ee0c 100644 --- a/addons/stock/report/picking.py +++ b/addons/stock/report/picking.py @@ -22,7 +22,6 @@ import time from openerp.report import report_sxw from openerp.osv import osv -from openerp import pooler class picking(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): diff --git a/addons/stock/report/product_stock.py b/addons/stock/report/product_stock.py index 9ccda54b693..d213db673dc 100644 --- a/addons/stock/report/product_stock.py +++ b/addons/stock/report/product_stock.py @@ -22,14 +22,15 @@ from datetime import datetime from dateutil.relativedelta import relativedelta +import openerp from openerp import osv import time from openerp.report.interface import report_int from openerp.report.render import render import stock_graph -from openerp import pooler import StringIO +import unicodedata class external_pdf(render): def __init__(self, pdf): @@ -45,24 +46,25 @@ class report_stock(report_int): def create(self, cr, uid, ids, datas, context=None): if context is None: context = {} + registry = openerp.registry(cr.dbname) product_ids = ids if 'location_id' in context: location_id = context['location_id'] else: - warehouse_id = pooler.get_pool(cr.dbname).get('stock.warehouse').search(cr, uid, [])[0] - location_id = pooler.get_pool(cr.dbname).get('stock.warehouse').browse(cr, uid, warehouse_id).lot_stock_id.id + warehouse_id = registry['stock.warehouse'].search(cr, uid, [])[0] + location_id = registry['stock.warehouse'].browse(cr, uid, warehouse_id).lot_stock_id.id - loc_ids = pooler.get_pool(cr.dbname).get('stock.location').search(cr, uid, [('location_id','child_of',[location_id])]) + loc_ids = registry['stock.location'].search(cr, uid, [('location_id','child_of',[location_id])]) now = time.strftime('%Y-%m-%d') dt_from = now dt_to = now - names = dict(pooler.get_pool(cr.dbname).get('product.product').name_get(cr, uid, product_ids)) + names = dict(registry['product.product'].name_get(cr, uid, product_ids)) for name in names: names[name] = names[name].encode('utf8') products = {} - prods = pooler.get_pool(cr.dbname).get('stock.location')._product_all_get(cr, uid, location_id, product_ids) + prods = registry['stock.location']._product_all_get(cr, uid, location_id, product_ids) for p in prods: products[p] = [(now,prods[p])] @@ -106,7 +108,12 @@ class report_stock(report_int): io = StringIO.StringIO() gt = stock_graph.stock_graph(io) for prod_id in products: - gt.add(prod_id, names.get(prod_id, 'Unknown'), products[prod_id]) + prod_name = names.get(prod_id,'Unknown') + if isinstance(prod_name, str): + prod_name = prod_name.decode('utf-8') + prod_name = unicodedata.normalize('NFKD',prod_name) + prod_name = prod_name.encode('ascii','replace') + gt.add(prod_id, prod_name, products[prod_id]) gt.draw() gt.close() self.obj = external_pdf(io.getvalue()) diff --git a/addons/stock/report/report_stock.py b/addons/stock/report/report_stock.py index 0aac0d6599b..d4bbb3ab127 100644 --- a/addons/stock/report/report_stock.py +++ b/addons/stock/report/report_stock.py @@ -77,7 +77,6 @@ class stock_report_prodlots(osv.osv): def unlink(self, cr, uid, ids, context=None): raise osv.except_osv(_('Error!'), _('You cannot delete any record!')) -stock_report_prodlots() class stock_report_tracklots(osv.osv): _name = "stock.report.tracklots" @@ -133,7 +132,6 @@ class stock_report_tracklots(osv.osv): def unlink(self, cr, uid, ids, context=None): raise osv.except_osv(_('Error!'), _('You cannot delete any record!')) -stock_report_tracklots() class report_stock_lines_date(osv.osv): _name = "report.stock.lines.date" @@ -162,6 +160,5 @@ class report_stock_lines_date(osv.osv): group by p.id )""") -report_stock_lines_date() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/report/report_stock_move.py b/addons/stock/report/report_stock_move.py index 39591021735..b8c22062fa5 100644 --- a/addons/stock/report/report_stock_move.py +++ b/addons/stock/report/report_stock_move.py @@ -142,7 +142,6 @@ class report_stock_move(osv.osv): ) """) -report_stock_move() class report_stock_inventory(osv.osv): @@ -193,6 +192,7 @@ CREATE OR REPLACE view report_stock_inventory AS ( LEFT JOIN product_uom pu2 ON (m.product_uom=pu2.id) LEFT JOIN product_uom u ON (m.product_uom=u.id) LEFT JOIN stock_location l ON (m.location_id=l.id) + WHERE m.state != 'cancel' GROUP BY m.id, m.product_id, m.product_uom, pt.categ_id, m.partner_id, m.location_id, m.location_dest_id, m.prodlot_id, m.date, m.state, l.usage, l.scrap_location, m.company_id, pt.uom_id, to_char(m.date, 'YYYY'), to_char(m.date, 'MM') @@ -216,13 +216,13 @@ CREATE OR REPLACE view report_stock_inventory AS ( LEFT JOIN product_uom pu2 ON (m.product_uom=pu2.id) LEFT JOIN product_uom u ON (m.product_uom=u.id) LEFT JOIN stock_location l ON (m.location_dest_id=l.id) + WHERE m.state != 'cancel' GROUP BY m.id, m.product_id, m.product_uom, pt.categ_id, m.partner_id, m.location_id, m.location_dest_id, m.prodlot_id, m.date, m.state, l.usage, l.scrap_location, m.company_id, pt.uom_id, to_char(m.date, 'YYYY'), to_char(m.date, 'MM') ) ); """) -report_stock_inventory() diff --git a/addons/stock/report/report_stock_move_view.xml b/addons/stock/report/report_stock_move_view.xml index 4f3e256389c..fcf99f6e51e 100644 --- a/addons/stock/report/report_stock_move_view.xml +++ b/addons/stock/report/report_stock_move_view.xml @@ -149,7 +149,7 @@ - + diff --git a/addons/stock/report/stock_by_location.py b/addons/stock/report/stock_by_location.py index 7ca209c9ed2..153b92f077c 100644 --- a/addons/stock/report/stock_by_location.py +++ b/addons/stock/report/stock_by_location.py @@ -19,7 +19,7 @@ # ############################################################################## -from openerp import pooler +import openerp from openerp.report.interface import report_rml from openerp.report.interface import toxml @@ -47,16 +47,17 @@ class report_custom(report_rml): """ def process(location_id, level): + registry = openerp.registry(cr.dbname) xml = '' - location_name = pooler.get_pool(cr.dbname).get('stock.location').read(cr, uid, [location_id], ['name']) + location_name = registry['stock.location'].read(cr, uid, [location_id], ['name']) xml += "