[MERGE]with lp:openobject-addons

bzr revid: jam@tinyerp.com-20110630122751-xd4w6p9e0iy1rga6
This commit is contained in:
Jigar Amin 2011-06-30 17:57:51 +05:30
commit 9df301fd1b
133 changed files with 12311 additions and 2902 deletions

View File

@ -1331,6 +1331,7 @@ class account_move(osv.osv):
def _centralise(self, cr, uid, move, mode, context=None):
assert mode in ('debit', 'credit'), 'Invalid Mode' #to prevent sql injection
currency_obj = self.pool.get('res.currency')
if context is None:
context = {}
@ -1381,6 +1382,34 @@ class account_move(osv.osv):
cr.execute('SELECT SUM(%s) FROM account_move_line WHERE move_id=%%s AND id!=%%s' % (mode,), (move.id, line_id2))
result = cr.fetchone()[0] or 0.0
cr.execute('update account_move_line set '+mode2+'=%s where id=%s', (result, line_id))
#adjust also the amount in currency if needed
cr.execute("select currency_id, sum(amount_currency) as amount_currency from account_move_line where move_id = %s and currency_id is not null group by currency_id", (move.id,))
for row in cr.dictfetchall():
currency_id = currency_obj.browse(cr, uid, row['currency_id'], context=context)
if not currency_obj.is_zero(cr, uid, currency_id, row['amount_currency']):
amount_currency = row['amount_currency'] * -1
account_id = amount_currency > 0 and move.journal_id.default_debit_account_id.id or move.journal_id.default_credit_account_id.id
cr.execute('select id from account_move_line where move_id=%s and centralisation=\'currency\' and currency_id = %slimit 1', (move.id, row['currency_id']))
res = cr.fetchone()
if res:
cr.execute('update account_move_line set amount_currency=%s , account_id=%s where id=%s', (amount_currency, account_id, res[0]))
else:
context.update({'journal_id': move.journal_id.id, 'period_id': move.period_id.id})
line_id = self.pool.get('account.move.line').create(cr, uid, {
'name': _('Currency Adjustment'),
'centralisation': 'currency',
'account_id': account_id,
'move_id': move.id,
'journal_id': move.journal_id.id,
'period_id': move.period_id.id,
'date': move.period_id.date_stop,
'debit': 0.0,
'credit': 0.0,
'currency_id': row['currency_id'],
'amount_currency': amount_currency,
}, context)
return True
#

View File

@ -503,7 +503,7 @@ class account_move_line(osv.osv):
}),
'date_created': fields.date('Creation date', select=True),
'analytic_lines': fields.one2many('account.analytic.line', 'move_id', 'Analytic lines'),
'centralisation': fields.selection([('normal','Normal'),('credit','Credit Centralisation'),('debit','Debit Centralisation')], 'Centralisation', size=6),
'centralisation': fields.selection([('normal','Normal'),('credit','Credit Centralisation'),('debit','Debit Centralisation'),('currency','Currency Adjustment')], 'Centralisation', size=8),
'balance': fields.function(_balance, fnct_search=_balance_search, method=True, string='Balance'),
'state': fields.selection([('draft','Unbalanced'), ('valid','Valid')], 'State', readonly=True,
help='When new move line is created the state will be \'Draft\'.\n* When all the payments are done it will be in \'Valid\' state.'),

File diff suppressed because it is too large Load Diff

View File

@ -263,7 +263,7 @@ class account_invoice(osv.osv):
'move_lines':fields.function(_get_lines, method=True, type='many2many', relation='account.move.line', string='Entry Lines'),
'residual': fields.function(_amount_residual, method=True, digits_compute=dp.get_precision('Account'), string='Residual',
store={
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line'], 50),
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line','move_id'], 50),
'account.invoice.tax': (_get_invoice_tax, None, 50),
'account.invoice.line': (_get_invoice_line, ['price_unit','invoice_line_tax_id','quantity','discount','invoice_id'], 50),
'account.move.line': (_get_invoice_from_line, None, 50),

View File

@ -31,12 +31,13 @@ class account_treasury_report(osv.osv):
def _compute_balances(self, cr, uid, ids, field_names, arg=None, context=None,
query='', query_params=()):
all_treasury_lines = self.search(cr, uid, [], context=context)
current_sum = 0
all_companies = self.pool.get('res.company').search(cr, uid, [], context=context)
current_sum = dict((company, 0.0) for company in all_companies)
res = dict((id, dict((fn, 0.0) for fn in field_names)) for id in all_treasury_lines)
for record in self.browse(cr, uid, all_treasury_lines, context=context):
res[record.id]['starting_balance'] = current_sum
current_sum += record.balance
res[record.id]['ending_balance'] = current_sum
res[record.id]['starting_balance'] = current_sum[record.company_id.id]
current_sum[record.company_id.id] += record.balance
res[record.id]['ending_balance'] = current_sum[record.company_id.id]
return res
_columns = {

View File

@ -103,6 +103,14 @@ class account_fiscalyear_close(osv.osv_memory):
if accnt_type_data.close_method=='none' or account.type == 'view':
continue
if accnt_type_data.close_method=='balance':
balance_in_currency = 0.0
if account.currency_id:
cr.execute('SELECT sum(amount_currency) as balance_in_currency FROM account_move_line ' \
'WHERE account_id = %s ' \
'AND ' + query_line + ' ' \
'AND currency_id = %s', (account.id, account.currency_id.id))
balance_in_currency = cr.dictfetchone()['balance_in_currency']
if abs(account.balance)>0.0001:
obj_acc_move_line.create(cr, uid, {
'debit': account.balance>0 and account.balance,
@ -111,7 +119,9 @@ class account_fiscalyear_close(osv.osv_memory):
'date': period.date_start,
'journal_id': new_journal.id,
'period_id': period.id,
'account_id': account.id
'account_id': account.id,
'currency_id': account.currency_id and account.currency_id.id or False,
'amount_currency': balance_in_currency,
}, {'journal_id': new_journal.id, 'period_id':period.id})
if accnt_type_data.close_method == 'unreconciled':
offset = 0

View File

@ -0,0 +1,33 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-22 05:51+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-23 04:56+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: account_accountant
#: model:ir.module.module,description:account_accountant.module_meta_information
msgid ""
"\n"
"This module gives the admin user the access to all the accounting features "
"like the journal\n"
"items and the chart of accounts.\n"
" "
msgstr ""
#. module: account_accountant
#: model:ir.module.module,shortdesc:account_accountant.module_meta_information
msgid "Accountant"
msgstr "Kirjanpitäjä"

View File

@ -0,0 +1,111 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-29 08:04+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-30 04:34+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: account_anglo_saxon
#: view:product.category:0
msgid " Accounting Property"
msgstr " Kirjanpito-ominaisuus"
#. module: account_anglo_saxon
#: sql_constraint:purchase.order:0
msgid "Order Reference must be unique !"
msgstr "Tilauksen viite tulee olla yksilöllinen!"
#. module: account_anglo_saxon
#: constraint:product.category:0
msgid "Error ! You can not create recursive categories."
msgstr "Virhe ! Et voi luoda rekursiivisia luokkia."
#. module: account_anglo_saxon
#: constraint:product.template:0
msgid ""
"Error: The default UOM and the purchase UOM must be in the same category."
msgstr ""
"Virhe: Oletus mittayksikkö ja ostojen mittayksikkö täytyy olla samassa "
"kategoriassa."
#. module: account_anglo_saxon
#: model:ir.model,name:account_anglo_saxon.model_account_invoice_line
msgid "Invoice Line"
msgstr "Laskun rivi"
#. module: account_anglo_saxon
#: model:ir.model,name:account_anglo_saxon.model_purchase_order
msgid "Purchase Order"
msgstr "Ostotilaus"
#. module: account_anglo_saxon
#: model:ir.model,name:account_anglo_saxon.model_product_template
msgid "Product Template"
msgstr "Tuotteen malli"
#. module: account_anglo_saxon
#: model:ir.model,name:account_anglo_saxon.model_product_category
msgid "Product Category"
msgstr "Tuotteen kategoria"
#. module: account_anglo_saxon
#: model:ir.module.module,shortdesc:account_anglo_saxon.module_meta_information
msgid "Stock Accounting for Anglo Saxon countries"
msgstr "Varastokirjanpito anglosaksalaisille maille"
#. module: account_anglo_saxon
#: field:product.category,property_account_creditor_price_difference_categ:0
#: field:product.template,property_account_creditor_price_difference:0
msgid "Price Difference Account"
msgstr "Hintaerotuksen tili"
#. module: account_anglo_saxon
#: model:ir.model,name:account_anglo_saxon.model_account_invoice
msgid "Invoice"
msgstr "Lasku"
#. module: account_anglo_saxon
#: model:ir.model,name:account_anglo_saxon.model_stock_picking
msgid "Picking List"
msgstr "Keräilylista"
#. module: account_anglo_saxon
#: model:ir.module.module,description:account_anglo_saxon.module_meta_information
msgid ""
"This module will support the Anglo-Saxons accounting methodology by\n"
" changing the accounting logic with stock transactions. The difference "
"between the Anglo-Saxon accounting countries\n"
" and the Rhine or also called Continental accounting countries is the "
"moment of taking the Cost of Goods Sold versus Cost of Sales.\n"
" Anglo-Saxons accounting does take the cost when sales invoice is "
"created, Continental accounting will take the cost at the moment the goods "
"are shipped.\n"
" This module will add this functionality by using a interim account, to "
"store the value of shipped goods and will contra book this interim account\n"
" when the invoice is created to transfer this amount to the debtor or "
"creditor account.\n"
" Secondly, price differences between actual purchase price and fixed "
"product standard price are booked on a separate account"
msgstr ""
#. module: account_anglo_saxon
#: help:product.category,property_account_creditor_price_difference_categ:0
#: help:product.template,property_account_creditor_price_difference:0
msgid ""
"This account will be used to value price difference between purchase price "
"and cost price."
msgstr ""
"Tätä tiliä käytetään arvostamaan hintaeroa ostohinnan ja kustannushinnan "
"välillä"

View File

@ -0,0 +1,261 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-28 09:19+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-29 04:43+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: account_coda
#: help:account.coda,journal_id:0
#: field:account.coda.import,journal_id:0
msgid "Bank Journal"
msgstr "Pankkitapahtumat"
#. module: account_coda
#: view:account.coda:0
#: field:account.coda.import,note:0
msgid "Log"
msgstr "Loki"
#. module: account_coda
#: model:ir.model,name:account_coda.model_account_coda_import
msgid "Account Coda Import"
msgstr "Tilien Coda tuonti"
#. module: account_coda
#: field:account.coda,name:0
msgid "Coda file"
msgstr "Coda tiedosto"
#. module: account_coda
#: view:account.coda:0
msgid "Group By..."
msgstr "Ryhmittely.."
#. module: account_coda
#: field:account.coda.import,awaiting_account:0
msgid "Default Account for Unrecognized Movement"
msgstr "Oletustili tuntemattomille siirroille"
#. module: account_coda
#: help:account.coda,date:0
msgid "Import Date"
msgstr "Tuontipäivä"
#. module: account_coda
#: field:account.coda,note:0
msgid "Import log"
msgstr "Tuontiloki"
#. module: account_coda
#: view:account.coda.import:0
msgid "Import"
msgstr "Tuo"
#. module: account_coda
#: view:account.coda:0
msgid "Coda import"
msgstr "Coda tuonti"
#. module: account_coda
#: code:addons/account_coda/account_coda.py:51
#, python-format
msgid "Coda file not found for bank statement !!"
msgstr "Coda tiedostoa ei löytynyt tiliotteelle"
#. module: account_coda
#: help:account.coda.import,awaiting_account:0
msgid ""
"Set here the default account that will be used, if the partner is found but "
"does not have the bank account, or if he is domiciled"
msgstr ""
#. module: account_coda
#: view:account.coda:0
#: field:account.coda,company_id:0
msgid "Company"
msgstr "Yritys"
#. module: account_coda
#: help:account.coda.import,def_payable:0
msgid ""
"Set here the payable account that will be used, by default, if the partner "
"is not found"
msgstr ""
#. module: account_coda
#: view:account.coda:0
msgid "Search Coda"
msgstr "Hae coda"
#. module: account_coda
#: view:account.coda:0
#: field:account.coda,user_id:0
msgid "User"
msgstr "Käyttäjä"
#. module: account_coda
#: view:account.coda:0
#: field:account.coda,date:0
msgid "Date"
msgstr "Päiväys"
#. module: account_coda
#: model:ir.ui.menu,name:account_coda.menu_account_coda_statement
msgid "Coda Import Logs"
msgstr "Coda tuontilokit"
#. module: account_coda
#: model:ir.model,name:account_coda.model_account_coda
msgid "coda for an Account"
msgstr "Coda tilille"
#. module: account_coda
#: field:account.coda.import,def_payable:0
msgid "Default Payable Account"
msgstr "Oletus maksutili"
#. module: account_coda
#: help:account.coda,name:0
msgid "Store the detail of bank statements"
msgstr "Talleta tiliotteiden yksityiskohdat"
#. module: account_coda
#: view:account.coda.import:0
msgid "Cancel"
msgstr "Peruuta"
#. module: account_coda
#: view:account.coda.import:0
msgid "Open Statements"
msgstr "Avaa tiliotteet"
#. module: account_coda
#: code:addons/account_coda/wizard/account_coda_import.py:167
#, python-format
msgid "The bank account %s is not defined for the partner %s.\n"
msgstr ""
#. module: account_coda
#: model:ir.ui.menu,name:account_coda.menu_account_coda_import
msgid "Import Coda Statements"
msgstr "Tuo Coda tiedot"
#. module: account_coda
#: view:account.coda.import:0
#: model:ir.actions.act_window,name:account_coda.action_account_coda_import
msgid "Import Coda Statement"
msgstr "Tuo Coda tiedot"
#. module: account_coda
#: model:ir.module.module,description:account_coda.module_meta_information
msgid ""
"\n"
" Module provides functionality to import\n"
" bank statements from coda files.\n"
" "
msgstr ""
#. module: account_coda
#: view:account.coda:0
msgid "Statements"
msgstr "Tiliotteet"
#. module: account_coda
#: field:account.bank.statement,coda_id:0
msgid "Coda"
msgstr "Coda"
#. module: account_coda
#: view:account.coda.import:0
msgid "Results :"
msgstr "Tulokset :"
#. module: account_coda
#: view:account.coda.import:0
msgid "Result of Imported Coda Statements"
msgstr "Tulos tuoduista Coda tiliotteista"
#. module: account_coda
#: help:account.coda.import,def_receivable:0
msgid ""
"Set here the receivable account that will be used, by default, if the "
"partner is not found"
msgstr ""
"Valitse tähän oletustili jota käytetään jos saapuneen maksun kumppania ei "
"löydetä"
#. module: account_coda
#: field:account.coda.import,coda:0
#: model:ir.actions.act_window,name:account_coda.act_account_payment_account_bank_statement
msgid "Coda File"
msgstr "Coda tiedosto"
#. module: account_coda
#: model:ir.model,name:account_coda.model_account_bank_statement
msgid "Bank Statement"
msgstr "Pankin tiliote"
#. module: account_coda
#: model:ir.actions.act_window,name:account_coda.action_account_coda
msgid "Coda Logs"
msgstr "Coda lokit"
#. module: account_coda
#: code:addons/account_coda/wizard/account_coda_import.py:311
#, python-format
msgid "Result"
msgstr "Tulos"
#. module: account_coda
#: view:account.coda.import:0
msgid "Click on 'New' to select your file :"
msgstr "Valitse 'uusi' valitaksesi tiedostosi :"
#. module: account_coda
#: field:account.coda.import,def_receivable:0
msgid "Default Receivable Account"
msgstr "Oletus saamistili"
#. module: account_coda
#: view:account.coda.import:0
msgid "Close"
msgstr "Sulje"
#. module: account_coda
#: field:account.coda,statement_ids:0
msgid "Generated Bank Statements"
msgstr "Luodut tiliotteet"
#. module: account_coda
#: model:ir.module.module,shortdesc:account_coda.module_meta_information
msgid "Account CODA - import bank statements from coda file"
msgstr ""
#. module: account_coda
#: view:account.coda.import:0
msgid "Configure Your Journal and Account :"
msgstr ""
#. module: account_coda
#: view:account.coda:0
msgid "Coda Import"
msgstr ""
#. module: account_coda
#: view:account.coda:0
#: field:account.coda,journal_id:0
msgid "Journal"
msgstr ""

View File

@ -0,0 +1,221 @@
# Norwegian Bokmal translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-24 11:23+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Norwegian Bokmal <nb@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-25 04:59+0000\n"
"X-Generator: Launchpad (build 13168)\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
#: constraint:account.move:0
msgid ""
"You cannot create entries on different periods/journals in the same move"
msgstr ""
#. module: account_sequence
#: help:account.move,internal_sequence_number:0
#: help:account.move.line,internal_sequence_number:0
msgid "Internal Sequence Number"
msgstr "Internt sekvensnummer"
#. module: account_sequence
#: help:account.sequence.installer,number_next:0
msgid "Next number of this sequence"
msgstr "Neste nummer på denne sekvensen"
#. module: account_sequence
#: field:account.sequence.installer,number_next:0
msgid "Next Number"
msgstr "Neste nummer"
#. module: account_sequence
#: field:account.sequence.installer,number_increment:0
msgid "Increment Number"
msgstr ""
#. module: account_sequence
#: model:ir.module.module,description:account_sequence.module_meta_information
msgid ""
"\n"
" This module maintains internal sequence number for accounting entries.\n"
" "
msgstr ""
#. module: account_sequence
#: model:ir.module.module,shortdesc:account_sequence.module_meta_information
msgid "Entries Sequence Numbering"
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
#: field:account.sequence.installer,progress:0
msgid "Configuration Progress"
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
#: 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
#: 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
#: constraint:account.move.line:0
msgid "Company must be same for its related account and period."
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
#: constraint:account.move.line:0
msgid "You can not create move line on closed account."
msgstr ""
#. module: account_sequence
#: constraint:account.move:0
msgid ""
"You cannot create more than one move per period on centralized journal"
msgstr ""
#. module: account_sequence
#: sql_constraint:account.move.line:0
msgid "Wrong credit or debit value in accounting entry !"
msgstr ""
#. module: account_sequence
#: field:account.journal,internal_sequence_id:0
msgid "Internal Sequence"
msgstr ""
#. module: account_sequence
#: model:ir.model,name:account_sequence.model_account_sequence_installer
msgid "account.sequence.installer"
msgstr ""
#. module: account_sequence
#: view:account.sequence.installer:0
msgid "Configure"
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
#: field:account.sequence.installer,config_logo:0
msgid "Image"
msgstr ""
#. module: account_sequence
#: view:account.sequence.installer:0
msgid "title"
msgstr ""
#. module: account_sequence
#: sql_constraint:account.journal:0
msgid "The name of the journal must be unique per company !"
msgstr ""
#. module: account_sequence
#: field:account.sequence.installer,prefix:0
msgid "Prefix"
msgstr ""
#. module: account_sequence
#: sql_constraint:account.journal:0
msgid "The code of the journal must be unique per company !"
msgstr ""
#. module: account_sequence
#: constraint:account.move.line:0
msgid ""
"You can not create move line on receivable/payable account without partner"
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 ""
#. module: account_sequence
#: constraint:account.move.line:0
msgid "You can not create move line on view account."
msgstr ""

261
addons/analytic/i18n/fi.po Normal file
View File

@ -0,0 +1,261 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-29 06:16+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-30 04:34+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: analytic
#: field:account.analytic.account,child_ids:0
msgid "Child Accounts"
msgstr "Alatason tilit"
#. module: analytic
#: field:account.analytic.account,name:0
msgid "Account Name"
msgstr "Tilin nimi"
#. module: analytic
#: help:account.analytic.line,unit_amount:0
msgid "Specifies the amount of quantity to count."
msgstr "Määrittelee laskettavan määrän"
#. module: analytic
#: model:ir.module.module,description:analytic.module_meta_information
msgid ""
"Module for defining analytic accounting object.\n"
" "
msgstr ""
"Moduuli analyyttisten tilien määrittelyyn.\n"
" "
#. module: analytic
#: field:account.analytic.account,state:0
msgid "State"
msgstr "Tila"
#. module: analytic
#: field:account.analytic.account,user_id:0
msgid "Account Manager"
msgstr "Asiakas päällikkö"
#. module: analytic
#: selection:account.analytic.account,state:0
msgid "Draft"
msgstr "Luonnos"
#. module: analytic
#: selection:account.analytic.account,state:0
msgid "Closed"
msgstr "Suljettu"
#. module: analytic
#: field:account.analytic.account,debit:0
msgid "Debit"
msgstr "Debet"
#. module: analytic
#: help:account.analytic.account,state:0
msgid ""
"* When an account is created its in 'Draft' state. "
" \n"
"* If any associated partner is there, it can be in 'Open' state. "
" \n"
"* If any pending balance is there it can be in 'Pending'. "
" \n"
"* And finally when all the transactions are over, it can be in 'Close' "
"state. \n"
"* The project can be in either if the states 'Template' and 'Running'.\n"
" If it is template then we can make projects based on the template projects. "
"If its in 'Running' state it is a normal project. "
" \n"
" If it is to be reviewed then the state is 'Pending'.\n"
" When the project is completed the state is set to 'Done'."
msgstr ""
#. module: analytic
#: field:account.analytic.account,type:0
msgid "Account Type"
msgstr "Tilityyppi"
#. module: analytic
#: selection:account.analytic.account,state:0
msgid "Template"
msgstr "Mallipohja"
#. module: analytic
#: selection:account.analytic.account,state:0
msgid "Pending"
msgstr "Odottava"
#. module: analytic
#: model:ir.model,name:analytic.model_account_analytic_line
msgid "Analytic Line"
msgstr "Analyyttinen rivi"
#. module: analytic
#: field:account.analytic.account,description:0
#: field:account.analytic.line,name:0
msgid "Description"
msgstr "Kuvaus"
#. module: analytic
#: selection:account.analytic.account,type:0
msgid "Normal"
msgstr "Tavallinen"
#. module: analytic
#: field:account.analytic.account,company_id:0
#: field:account.analytic.line,company_id:0
msgid "Company"
msgstr "Yritys"
#. module: analytic
#: field:account.analytic.account,quantity_max:0
msgid "Maximum Quantity"
msgstr "Maksimimäärä"
#. module: analytic
#: field:account.analytic.line,user_id:0
msgid "User"
msgstr "Käyttäjä"
#. module: analytic
#: field:account.analytic.account,parent_id:0
msgid "Parent Analytic Account"
msgstr "Ylempi analyyttinen tili"
#. module: analytic
#: field:account.analytic.line,date:0
msgid "Date"
msgstr "Päiväys"
#. module: analytic
#: field:account.analytic.account,currency_id:0
msgid "Account currency"
msgstr "Tilin valuutta"
#. module: analytic
#: field:account.analytic.account,quantity:0
#: field:account.analytic.line,unit_amount:0
msgid "Quantity"
msgstr "Määrä"
#. module: analytic
#: help:account.analytic.line,amount:0
msgid ""
"Calculated by multiplying the quantity and the price given in the Product's "
"cost price. Always expressed in the company main currency."
msgstr ""
"Laskettu kertomalla määrä ja tuotteen kustannushinta. Yrityksen "
"päävaluutassa."
#. module: analytic
#: help:account.analytic.account,quantity_max:0
msgid "Sets the higher limit of quantity of hours."
msgstr "Asettaa tuntien määrän ylärajan"
#. module: analytic
#: field:account.analytic.account,credit:0
msgid "Credit"
msgstr "Kredit"
#. module: analytic
#: field:account.analytic.line,amount:0
msgid "Amount"
msgstr "Määrä"
#. module: analytic
#: field:account.analytic.account,contact_id:0
msgid "Contact"
msgstr "Yhteyshenkilö"
#. module: analytic
#: constraint:account.analytic.account:0
msgid ""
"Error! The currency has to be the same as the currency of the selected "
"company"
msgstr "Virhe! Valuutan tulee olla sama kun valitun yrityksen valutta."
#. module: analytic
#: selection:account.analytic.account,state:0
msgid "Cancelled"
msgstr "Peruttu"
#. module: analytic
#: field:account.analytic.account,balance:0
msgid "Balance"
msgstr "Saldo"
#. module: analytic
#: constraint:account.analytic.account:0
msgid "Error! You can not create recursive analytic accounts."
msgstr "Virhe! Et voi luoda sisäkkäisiä analyyttisiä tilejä."
#. module: analytic
#: help:account.analytic.account,type:0
msgid ""
"If you select the View Type, it means you won't allow to create journal "
"entries using that account."
msgstr ""
"Jos valitset näkymätyypin, se tarkoittaa että et voi luoda "
"päiväkirjamerkintöjä käyttäen sitä tiliä."
#. module: analytic
#: field:account.analytic.account,date:0
msgid "Date End"
msgstr "Loppupäiväys"
#. module: analytic
#: field:account.analytic.account,code:0
msgid "Account Code"
msgstr "Tilikoodi"
#. module: analytic
#: field:account.analytic.account,complete_name:0
msgid "Full Account Name"
msgstr "Tilin kokonimi"
#. module: analytic
#: field:account.analytic.line,account_id:0
#: model:ir.model,name:analytic.model_account_analytic_account
#: model:ir.module.module,shortdesc:analytic.module_meta_information
msgid "Analytic Account"
msgstr "Analyyttinen tili"
#. module: analytic
#: selection:account.analytic.account,type:0
msgid "View"
msgstr "Näkymä"
#. module: analytic
#: field:account.analytic.account,partner_id:0
msgid "Partner"
msgstr "Kumppani"
#. module: analytic
#: field:account.analytic.account,date_start:0
msgid "Date Start"
msgstr "Aloituspäivämäärä"
#. module: analytic
#: selection:account.analytic.account,state:0
msgid "Open"
msgstr "Avoin"
#. module: analytic
#: field:account.analytic.account,line_ids:0
msgid "Analytic Entries"
msgstr "Analyyttiset viennit"

View File

@ -0,0 +1,103 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-03 16:56+0000\n"
"PO-Revision-Date: 2011-06-29 05:53+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-30 04:34+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: analytic_user_function
#: field:analytic_user_funct_grid,product_id:0
msgid "Product"
msgstr "Tuote"
#. module: analytic_user_function
#: code:addons/analytic_user_function/analytic_user_function.py:96
#: code:addons/analytic_user_function/analytic_user_function.py:131
#, python-format
msgid "Error !"
msgstr "Virhe !"
#. module: analytic_user_function
#: model:ir.model,name:analytic_user_function.model_hr_analytic_timesheet
msgid "Timesheet Line"
msgstr "Tuntilistan rivi"
#. module: analytic_user_function
#: field:analytic_user_funct_grid,account_id:0
#: model:ir.model,name:analytic_user_function.model_account_analytic_account
msgid "Analytic Account"
msgstr "Analyyttinen tili"
#. module: analytic_user_function
#: view:account.analytic.account:0
#: field:account.analytic.account,user_product_ids:0
msgid "Users/Products Rel."
msgstr "Käyttäjän/Tuotteen suhde"
#. module: analytic_user_function
#: field:analytic_user_funct_grid,user_id:0
msgid "User"
msgstr "Käyttäjä"
#. module: analytic_user_function
#: constraint:account.analytic.account:0
msgid ""
"Error! The currency has to be the same as the currency of the selected "
"company"
msgstr "Virhe! Valuutan tulee olla sama kun valitun yrityksen valutta."
#. module: analytic_user_function
#: code:addons/analytic_user_function/analytic_user_function.py:97
#: code:addons/analytic_user_function/analytic_user_function.py:132
#, python-format
msgid "There is no expense account define for this product: \"%s\" (id:%d)"
msgstr "Tuotteelle ei ole määritelty kulutiliä: \"%s\" (id:%d)"
#. module: analytic_user_function
#: model:ir.model,name:analytic_user_function.model_analytic_user_funct_grid
msgid "Relation table between users and products on a analytic account"
msgstr "Viitetaulu käyttäjien ja tuotteiden välillä analyyttisellä tilillä"
#. module: analytic_user_function
#: model:ir.module.module,description:analytic_user_function.module_meta_information
msgid ""
"\n"
"\n"
" This module allows you to define what is the default function of a "
"specific user on a given account. This is mostly used when a user encodes "
"his timesheet: the values are retrieved and the fields are auto-filled... "
"but the possibility to change these values is still available.\n"
"\n"
" Obviously if no data has been recorded for the current account, the "
"default value is given as usual by the employee data so that this module is "
"perfectly compatible with older configurations.\n"
"\n"
" "
msgstr ""
#. module: analytic_user_function
#: model:ir.module.module,shortdesc:analytic_user_function.module_meta_information
msgid "Analytic User Function"
msgstr "Analyyttinen käyttäjätoiminto"
#. module: analytic_user_function
#: constraint:account.analytic.account:0
msgid "Error! You can not create recursive analytic accounts."
msgstr "Virhe! Et voi luoda sisäkkäisiä analyyttisiä tilejä."
#. module: analytic_user_function
#: view:analytic_user_funct_grid:0
msgid "User's Product for this Analytic Account"
msgstr "Käyttäjän tuote tälle analyyttiselle tilille"

View File

@ -0,0 +1,141 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-27 10:43+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-28 04:40+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: association
#: field:profile.association.config.install_modules_wizard,wiki:0
msgid "Wiki"
msgstr ""
#. module: association
#: view:profile.association.config.install_modules_wizard:0
msgid "Event Management"
msgstr "Tapahtumienhallinta"
#. module: association
#: field:profile.association.config.install_modules_wizard,project_gtd:0
msgid "Getting Things Done"
msgstr "Saada asiat tehtyä"
#. module: association
#: model:ir.module.module,description:association.module_meta_information
msgid "This module is to create Profile for Associates"
msgstr "Tämä moduuli mahdollistaa yhdistysjäsenprofiilien luonnin"
#. module: association
#: field:profile.association.config.install_modules_wizard,progress:0
msgid "Configuration Progress"
msgstr "Konfiguraation eteneminen"
#. module: association
#: view:profile.association.config.install_modules_wizard:0
msgid ""
"Here are specific applications related to the Association Profile you "
"selected."
msgstr ""
"Tässä on määritellyt ohjelmat jotka liittyvät valitsemaasi "
"yhdistysprofiiliin."
#. module: association
#: view:profile.association.config.install_modules_wizard:0
msgid "title"
msgstr "otsikko"
#. module: association
#: help:profile.association.config.install_modules_wizard,event_project:0
msgid "Helps you to manage and organize your events."
msgstr "Auttaa sinua hallitsemaan ja organisoimaan tapahtumia"
#. module: association
#: field:profile.association.config.install_modules_wizard,config_logo:0
msgid "Image"
msgstr "Kuva"
#. module: association
#: help:profile.association.config.install_modules_wizard,hr_expense:0
msgid ""
"Tracks and manages employee expenses, and can automatically re-invoice "
"clients if the expenses are project-related."
msgstr ""
"Seuraa ja hallitsee työntekijäkuluja ja voi automaattisesti laskuttaa "
"asiakasta, jos kulut liittyvät projektiin."
#. module: association
#: help:profile.association.config.install_modules_wizard,project_gtd:0
msgid ""
"GTD is a methodology to efficiently organise yourself and your tasks. This "
"module fully integrates GTD principle with OpenERP's project management."
msgstr ""
#. module: association
#: view:profile.association.config.install_modules_wizard:0
msgid "Resources Management"
msgstr "Resurssienhallinta"
#. module: association
#: model:ir.module.module,shortdesc:association.module_meta_information
msgid "Association profile"
msgstr "Yhdistysprofiili"
#. module: association
#: field:profile.association.config.install_modules_wizard,hr_expense:0
msgid "Expenses Tracking"
msgstr "Kulujenseuranta"
#. module: association
#: model:ir.actions.act_window,name:association.action_config_install_module
#: view:profile.association.config.install_modules_wizard:0
msgid "Association Application Configuration"
msgstr "Jäsenhakemuksen konfiguraatio"
#. module: association
#: help:profile.association.config.install_modules_wizard,wiki:0
msgid ""
"Lets you create wiki pages and page groups in order to keep track of "
"business knowledge and share it with and between your employees."
msgstr ""
#. module: association
#: help:profile.association.config.install_modules_wizard,project:0
msgid ""
"Helps you manage your projects and tasks by tracking them, generating "
"plannings, etc..."
msgstr ""
"Auttaa sinua hallitsemaan projektejasi ja tehtäviäsi seuraamalla niitä, "
"luomalla suunnitelmia yms."
#. module: association
#: model:ir.model,name:association.model_profile_association_config_install_modules_wizard
msgid "profile.association.config.install_modules_wizard"
msgstr ""
#. module: association
#: field:profile.association.config.install_modules_wizard,event_project:0
msgid "Events"
msgstr "Tapahtumat"
#. module: association
#: view:profile.association.config.install_modules_wizard:0
#: field:profile.association.config.install_modules_wizard,project:0
msgid "Project Management"
msgstr "Projektinhallinta"
#. module: association
#: view:profile.association.config.install_modules_wizard:0
msgid "Configure"
msgstr "Konfiguroi"

View File

@ -487,21 +487,24 @@ base_action_rule()
class ir_cron(osv.osv):
_inherit = 'ir.cron'
_inherit = 'ir.cron'
_init_done = False
def _poolJobs(self, db_name, check=False):
try:
db = pooler.get_db(db_name)
except:
return False
cr = db.cursor()
try:
next = datetime.now().strftime('%Y-%m-%d %H:00:00')
# Putting nextcall always less than current time in order to call it every time
cr.execute('UPDATE ir_cron set nextcall = \'%s\' where numbercall<>0 and active and model=\'base.action.rule\' ' % (next))
finally:
cr.commit()
cr.close()
if not self._init_done:
self._init_done = True
try:
db = pooler.get_db(db_name)
except:
return False
cr = db.cursor()
try:
next = datetime.now().strftime('%Y-%m-%d %H:00:00')
# Putting nextcall always less than current time in order to call it every time
cr.execute('UPDATE ir_cron set nextcall = \'%s\' where numbercall<>0 and active and model=\'base.action.rule\' ' % (next))
finally:
cr.commit()
cr.close()
super(ir_cron, self)._poolJobs(db_name, check=check)

View File

@ -1,11 +1,55 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name": "Base calendar",
"version": "2.0",
"depends": ['base'],
"js": [
'static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.js',
'static/src/js/calendar.js'
"name" : "Basic Calendar Functionality",
"version" : "1.0",
"depends" : ["base"],
'description': """
This is a full-featured calendar system.
========================================
It supports:
- Calendar of events
- Alerts (create requests)
- Recurring events
- Invitations to people""",
"author" : "OpenERP SA",
'category': 'Tools',
'website': 'http://www.openerp.com',
"init_xml" : [
'base_calendar_data.xml'
],
"css": ['static/lib/dhtmlxScheduler/codebase/dhtmlxscheduler.css'],
'active': True
"demo_xml" : [],
"update_xml" : [
'security/calendar_security.xml',
'security/ir.model.access.csv',
'wizard/base_calendar_invite_attendee_view.xml',
'base_calendar_view.xml'
],
"test" : ['test/base_calendar_test.yml'],
"installable" : True,
"active" : False,
"certificate" : "00694071962960352821",
'images': ['images/base_calendar1.jpeg','images/base_calendar2.jpeg','images/base_calendar3.jpeg','images/base_calendar4.jpeg',],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -22,6 +22,7 @@
from datetime import datetime, timedelta, date
from dateutil import parser
from dateutil import rrule
from dateutil.relativedelta import relativedelta
from osv import fields, osv
from service import web_services
from tools.translate import _
@ -47,20 +48,22 @@ def get_recurrent_dates(rrulestring, exdate, startdate=None, exrule=None):
def todate(date):
val = parser.parse(''.join((re.compile('\d')).findall(date)))
return val
if not startdate:
startdate = datetime.now()
if not exdate:
exdate = []
rset1 = rrule.rrulestr(str(rrulestring), dtstart=startdate, forceset=True)
for date in exdate:
datetime_obj = todate(date)
rset1._exdate.append(datetime_obj)
if exrule:
rset1.exrule(rrule.rrulestr(str(exrule), dtstart=startdate))
return list(rset1._iter())
return list(rset1)
def base_calendar_id2real_id(base_calendar_id=None, with_date=False):
"""
@ -373,7 +376,8 @@ property or property parameter."),
multi='event_end_date'),
'ref': fields.reference('Event Ref', selection=_links_get, size=128),
'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"),
}
}
_defaults = {
'state': 'needs-action',
'role': 'req-participant',
@ -411,7 +415,7 @@ property or property parameter."),
cal = vobject.iCalendar()
event = cal.add('vevent')
if not event_obj.date_deadline or not event_obj.date:
raise osv.except_osv(_('Warning !'),_("Couldn't Invite because date is not specified!"))
raise osv.except_osv(_('Warning !'),_("Couldn't Invite because date is not specified!"))
event.add('created').value = ics_datetime(time.strftime('%Y-%m-%d %H:%M:%S'))
event.add('dtstart').value = ics_datetime(event_obj.date)
event.add('dtend').value = ics_datetime(event_obj.date_deadline)
@ -456,7 +460,7 @@ property or property parameter."),
trigger.value = delta
# Compute other details
valarm.add('DESCRIPTION').value = alarm_data['name'] or 'OpenERP'
for attendee in event_obj.attendee_ids:
attendee_add = event.add('attendee')
attendee_add.params['CUTYPE'] = [str(attendee.cutype)]
@ -674,7 +678,7 @@ true, it will allow you to hide the event alarm information without removing it.
new_res_alarm = alarm_ids[0]
cr.execute('UPDATE %s ' % model_obj._table + \
' SET base_calendar_alarm_id=%s, alarm_id=%s ' \
' WHERE id=%s',
' WHERE id=%s',
(cal_alarm.id, new_res_alarm, data.id))
self.do_alarm_unlink(cr, uid, [data.id], model)
@ -806,7 +810,6 @@ class calendar_alarm(osv.osv):
@param use_new_cursor: False or the dbname
@param context: A standard dictionary for contextual values
"""
return True # XXX FIXME REMOVE THIS AFTER FIXING get_recurrent_dates!!
if context is None:
context = {}
current_datetime = datetime.now()
@ -914,22 +917,6 @@ class calendar_event(osv.osv):
def _tz_get(self, cr, uid, context=None):
return [(x.lower(), x) for x in pytz.all_timezones]
def onchange_allday(self, cr, uid, ids, allday, context=None):
"""Sets duration as 24 Hours if event is selected for all day
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of calendar events IDs.
@param allday: Value of allday boolean
@param context: A standard dictionary for contextual values
"""
if not allday or not ids:
return {}
value = {
'duration': 24
}
return {'value': value}
def onchange_dates(self, cr, uid, ids, start_date, duration=False, end_date=False, allday=False, context=None):
"""Returns duration and/or end date based on values passed
@param self: The object pointer
@ -952,8 +939,13 @@ class calendar_event(osv.osv):
value['duration'] = duration
if allday: # For all day event
value = {'duration': 24}
value = {'duration': 24.0}
duration = 24.0
if start_date:
start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
start_date = datetime.strftime(datetime(start.year, start.month, start.day, 0,0,0), "%Y-%m-%d %H:%M:%S")
value['date'] = start_date
start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
if end_date and not duration:
@ -966,7 +958,7 @@ class calendar_event(osv.osv):
value['date_deadline'] = end.strftime("%Y-%m-%d %H:%M:%S")
elif end_date and duration and not allday:
# we have both, keep them synchronized:
# set duration based on end_date (arbitrary decision: this avoid
# set duration based on end_date (arbitrary decision: this avoid
# getting dates like 06:31:48 instead of 06:32:00)
end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
diff = end - start
@ -982,88 +974,10 @@ class calendar_event(osv.osv):
"""
if context is None:
context = {}
cr.execute('select id from '+self._table+' where recurrent_uid in %s', (tuple(ids),))
r_ids = map(lambda x: x[0], cr.fetchall())
self.unlink(cr, uid, r_ids, context=context)
return True
def _set_rrulestring(self, cr, uid, id, name, value, arg, context=None):
"""
Sets values of fields that defines event recurrence from the value of rrule string
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param id: List of calendar event's ids.
@param context: A standard dictionary for contextual values
@return: dictionary of rrule value.
"""
if context is None:
context = {}
cr.execute("UPDATE %s set freq='None',interval=0,count=0,end_date=Null,\
mo=False,tu=False,we=False,th=False,fr=False,sa=False,su=False,\
day=0,select1='date',month_list=Null ,byday=Null where id=%%s" % (self._table), (id,))
if not value:
cr.execute("UPDATE %s set rrule_type='none' where id=%%s" % self._table,(id,))
return True
val = {}
for part in value.split(';'):
if part.lower().__contains__('freq') and len(value.split(';')) <=2:
rrule_type = part.lower()[5:]
break
else:
rrule_type = 'custom'
break
ans = value.split(';')
for i in ans:
val[i.split('=')[0].lower()] = i.split('=')[1].lower()
if not val.get('interval'):
rrule_type = 'custom'
elif int(val.get('interval')) > 1: #If interval is other than 1 rule is custom
rrule_type = 'custom'
qry = "UPDATE \"%s\" set rrule_type=%%s " % self._table
qry_args = [ rrule_type, ]
new_val = val.copy()
for k, v in val.items():
if val['freq'] == 'weekly' and val.get('byday'):
for day in val['byday'].split(','):
new_val[day] = True
val.pop('byday')
if val.get('until'):
until = parser.parse(''.join((re.compile('\d')).findall(val.get('until'))))
new_val['end_date'] = until.strftime('%Y-%m-%d')
val.pop('until')
new_val.pop('until')
if val.get('bymonthday'):
new_val['day'] = val.get('bymonthday')
val.pop('bymonthday')
new_val['select1'] = 'date'
new_val.pop('bymonthday')
if val.get('byday'):
d = val.get('byday')
if '-' in d:
new_val['byday'] = d[:2]
new_val['week_list'] = d[2:4].upper()
else:
new_val['byday'] = d[:1]
new_val['week_list'] = d[1:3].upper()
new_val['select1'] = 'day'
if val.get('bymonth'):
new_val['month_list'] = val.get('bymonth')
val.pop('bymonth')
new_val.pop('bymonth')
for k, v in new_val.items():
qry += ", %s=%%s" % k
qry_args.append(v)
qry = qry + " where id=%s"
qry_args.append(id)
cr.execute(qry, qry_args)
for event_id in ids:
cr.execute("select id from %s where recurrent_uid=%%s" % (self._table), (event_id,))
r_ids = map(lambda x: x[0], cr.fetchall())
self.unlink(cr, uid, r_ids, context=context)
return True
def _get_rulestring(self, cr, uid, ids, name, arg, context=None):
@ -1075,28 +989,15 @@ class calendar_event(osv.osv):
@param context: A standard dictionary for contextual values
@return: dictionary of rrule value.
"""
result = {}
for datas in self.read(cr, uid, ids, context=context):
for datas in self.read(cr, uid, ids, ['id','byday','recurrency', 'month_list','end_date', 'rrule_type', 'select1', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'exrule', 'day', 'week_list' ], context=context):
event = datas['id']
if datas.get('rrule_type'):
if datas.get('rrule_type') == 'none':
result[event] = False
cr.execute("UPDATE %s set exrule=Null where id=%%s" % self._table,( event,))
if datas.get('rrule_type') :
if datas.get('interval', 0) < 0:
raise osv.except_osv(_('Warning!'), _('Interval can not be Negative'))
if datas.get('count', 0) < 0:
raise osv.except_osv(_('Warning!'), _('Count can not be Negative'))
rrule_custom = self.compute_rule_string(cr, uid, datas, \
context=context)
result[event] = rrule_custom
else:
result[event] = self.compute_rule_string(cr, uid, {'freq': datas.get('rrule_type').upper(), 'interval': 1}, context=context)
for id, myrule in result.items():
#Remove the events generated from recurrent event
if not myrule:
self.unlink_events(cr, uid, [id], context=context)
if datas.get('interval', 0) < 0:
raise osv.except_osv(_('Warning!'), _('Interval can not be Negative'))
if datas.get('count', 0) < 0:
raise osv.except_osv(_('Warning!'), _('Count can not be Negative'))
result[event] = self.compute_rule_string(datas)
return result
_columns = {
@ -1122,14 +1023,10 @@ defines the list of date/time exceptions for a recurring calendar component."),
'exrule': fields.char('Exception Rule', size=352, help="Defines a \
rule or repeating pattern of time to exclude from the recurring rule."),
'rrule': fields.function(_get_rulestring, type='char', size=124, method=True, \
string='Recurrent Rule', store=True, \
fnct_inv=_set_rrulestring, help='Defines a\
rule or repeating pattern for recurring events\n\
e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=-1SU'),
store=True, string='Recurrent Rule'),
'rrule_type': fields.selection([('none', ''), ('daily', 'Daily'), \
('weekly', 'Weekly'), ('monthly', 'Monthly'), \
('yearly', 'Yearly'),],
('yearly', 'Yearly'),],
'Recurrency', states={'done': [('readonly', True)]},
help="Let the event automatically repeat at that interval"),
'alarm_id': fields.many2one('res.alarm', 'Alarm', states={'done': [('readonly', True)]},
@ -1141,14 +1038,7 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
'organizer': fields.char("Organizer", size=256, states={'done': [('readonly', True)]}), # Map with Organizer Attribure of VEvent.
'organizer_id': fields.many2one('res.users', 'Organizer', states={'done': [('readonly', True)]}),
'freq': fields.selection([('None', 'No Repeat'),
('hourly', 'Hours'),
('daily', 'Days'),
('weekly', 'Weeks'),
('monthly', 'Months'),
('yearly', 'Years'), ], 'Frequency'),
'end_type' : fields.selection([('forever', 'Forever'), ('count', 'Fix amout of times'), ('end_date','End date')], 'Way to end reccurency'),
'end_type' : fields.selection([('count', 'Fix amout of times'), ('end_date','End date')], 'Way to end reccurency'),
'interval': fields.integer('Repeat every', help="Repeat every (Days/Week/Month/Year)"),
'count': fields.integer('Repeat', help="Repeat x times"),
'mo': fields.boolean('Mon'),
@ -1158,7 +1048,7 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'fr': fields.boolean('Fri'),
'sa': fields.boolean('Sat'),
'su': fields.boolean('Sun'),
'select1': fields.selection([('date', 'Date of month'),
'select1': fields.selection([('date', 'Date of month'),
('day', 'Day of month')], 'Option'),
'day': fields.integer('Date of month'),
'week_list': fields.selection([('MO', 'Monday'), ('TU', 'Tuesday'), \
@ -1175,8 +1065,8 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
'active': fields.boolean('Active', help="If the active field is set to \
true, it will allow you to hide the event alarm information without removing it."),
'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
'edit_all': fields.boolean('Edit All', help="Edit all Occurrences of recurrent Meeting."),
'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
'edit_all': fields.boolean('Edit All', help="Edit all Occurrences of recurrent Meeting."),
}
def default_organizer(self, cr, uid, context=None):
user_pool = self.pool.get('res.users')
@ -1187,11 +1077,12 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
return res
_defaults = {
'end_type' : 'forever',
'end_type' : 'count',
'count' : 1,
'rrule_type' : 'none',
'state': 'tentative',
'class': 'public',
'show_as': 'busy',
'freq': 'None',
'select1': 'date',
'interval': 1,
'active': 1,
@ -1200,43 +1091,7 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'edit_all' : False,
}
def onchange_edit_all(self, cr, uid, ids, rrule_type,edit_all, context=None):
if not context:
context = {}
value = {}
if edit_all and rrule_type:
for id in ids:
base_calendar_id2real_id(id)
return value
def modify_all(self, cr, uid, event_ids, defaults, context=None, *args):
"""
Modifies the recurring event
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param event_ids: List of crm meetings IDs.
@param context: A standard dictionary for contextual values
@return: True
"""
for event_id in event_ids:
event_id = base_calendar_id2real_id(event_id)
defaults.pop('id')
defaults.update({'table': self._table})
qry = "UPDATE %(table)s set name = '%(name)s', \
date = '%(date)s', date_deadline = '%(date_deadline)s'"
if defaults.get('alarm_id'):
qry += ", alarm_id = %(alarm_id)s"
if defaults.get('location'):
qry += ", location = '%(location)s'"
qry += "WHERE id = %s" % (event_id)
cr.execute(qry, defaults)
return True
def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100):
def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100, context=None):
"""Gives virtual event ids for recurring events based on value of Recurrence Rule
This method gives ids of dates that comes between start date and end date of calendar views
@param self: The object pointer
@ -1245,46 +1100,32 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
@param base_start_date: Get Start Date
@param base_until_date: Get End Date
@param limit: The Number of Results to Return """
if not context:
context = {}
virtual_id = context and context.get('virtual_id', False) or False
if not limit:
limit = 100
if isinstance(select, (str, int, long)):
ids = [select]
else:
ids = select
result = []
recur_dict = []
if ids and (base_start_date or base_until_date):
cr.execute("select m.id, m.rrule, m.date, m.date_deadline, m.duration, \
m.exdate, m.exrule, m.recurrent_id, m.recurrent_uid from " + self._table + \
" m where m.id = ANY(%s)", (ids,) )
count = 0
for data in cr.dictfetchall():
if ids and virtual_id:
for data in super(calendar_event, self).read(cr, uid, ids, context=context):
start_date = base_start_date and datetime.strptime(base_start_date[:10]+ ' 00:00:00' , "%Y-%m-%d %H:%M:%S") or False
until_date = base_until_date and datetime.strptime(base_until_date[:10]+ ' 23:59:59', "%Y-%m-%d %H:%M:%S") or False
if count > limit:
break
event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")
# To check: If the start date is replace by event date .. the event date will be changed by that of calendar code
start_date = event_date
if not data['rrule']:
if start_date and (event_date < start_date):
continue
if until_date and (event_date > until_date):
continue
idval = real_id2base_calendar_id(data['id'], data['date'])
if not data['recurrent_id']:
result.append(idval)
count += 1
else:
ex_id = real_id2base_calendar_id(data['recurrent_uid'], data['recurrent_id'])
ls = base_calendar_id2real_id(ex_id, with_date=data and data.get('duration', 0) or 0)
if not isinstance(ls, (str, int, long)) and len(ls) >= 2:
if ls[1] == data['recurrent_id']:
result.append(idval)
recur_dict.append(ex_id)
idval = data['id']
result.append(idval)
else:
start_date = event_date
exdate = data['exdate'] and data['exdate'].split(',') or []
rrule_str = data['rrule']
new_rrule_str = []
@ -1300,6 +1141,8 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
until_date = rrule_until_date
if until_date:
value = until_date.strftime("%Y%m%d%H%M%S")
else:
value = value.strftime("%Y%m%d%H%M%S")
new_rule = '%s=%s' % (name, value)
new_rrule_str.append(new_rule)
if not is_until and until_date:
@ -1309,6 +1152,7 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
new_rrule_str.append(new_rule)
new_rrule_str = ';'.join(new_rrule_str)
rdates = get_recurrent_dates(str(new_rrule_str), exdate, start_date, data['exrule'])
for r_date in rdates:
if start_date and r_date < start_date:
continue
@ -1316,77 +1160,75 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
continue
idval = real_id2base_calendar_id(data['id'], r_date.strftime("%Y-%m-%d %H:%M:%S"))
result.append(idval)
count += 1
if result:
ids = list(set(result)-set(recur_dict))
ids = list(set(result))
if isinstance(select, (str, int, long)):
return ids and ids[0] or False
return ids
def compute_rule_string(self, cr, uid, datas, context=None, *args):
def compute_rule_string(self, datas):
"""
Compute rule string according to value type RECUR of iCalendar from the values given.
@param self: the object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param datas: dictionary of freq and interval value.
@param context: A standard dictionary for contextual values
@return: String value of the format RECUR of iCalendar
"""
weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
weekstring = ''
monthstring = ''
yearstring = ''
freq=datas.get('rrule_type')
if freq == 'none':
def get_week_string(freq, datas):
weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
if byday:
return ';BYDAY=' + ','.join(byday)
return ''
def get_month_string(freq, datas):
if freq == 'monthly':
if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
raise osv.except_osv(_('Error!'), ("Please select proper Day of month"))
if datas.get('select1')=='day':
return ';BYDAY=' + datas.get('byday') + datas.get('week_list')
elif datas.get('select1')=='date':
return ';BYMONTHDAY=' + str(datas.get('day'))
return ''
def get_end_date(datas):
if datas.get('end_date'):
datas['end_date_new'] = ''.join((re.compile('\d')).findall(datas.get('end_date'))) + 'T235959Z'
interval_srting = datas.get('interval') and (';INTERVAL=' + str(datas.get('interval'))) or ''
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
if byday:
weekstring = ';BYDAY=' + ','.join(byday)
elif freq == 'monthly':
if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
raise osv.except_osv(_('Error!'), ("Please select proper Day of month"))
if datas.get('select1')=='day':
monthstring = ';BYDAY=' + datas.get('byday') + datas.get('week_list')
elif datas.get('select1')=='date':
monthstring = ';BYMONTHDAY=' + str(datas.get('day'))
return (datas.get('end_type') == 'count' and (';COUNT=' + str(datas.get('count'))) or '') +\
((datas.get('end_date_new') and datas.get('end_type') == 'end_date' and (';UNTIL=' + datas.get('end_date_new'))) or '')
if datas.get('end_date'):
datas['end_date'] = ''.join((re.compile('\d')).findall(datas.get('end_date'))) + 'T235959Z'
enddate = (datas.get('count') and (';COUNT=' + str(datas.get('count'))) or '') +\
((datas.get('end_date') and (';UNTIL=' + datas.get('end_date'))) or '')
freq=datas.get('rrule_type')
if freq == 'none':
return ''
interval_srting = datas.get('interval') and (';INTERVAL=' + str(datas.get('interval'))) or ''
return 'FREQ=' + freq.upper() + get_week_string(freq, datas) + interval_srting + get_end_date(datas) + get_month_string(freq, datas)
rrule_string = 'FREQ=' + freq.upper() + weekstring + interval_srting \
+ enddate + monthstring + yearstring
return rrule_string
def search(self, cr, uid, args, offset=0, limit=100, order=None,
def remove_virtual_id(self, ids):
if isinstance(ids, (str, int)):
return base_calendar_id2real_id(ids)
if isinstance(ids, (list, tuple)):
res = []
for id in ids:
res.append(base_calendar_id2real_id(id))
return res
def search(self, cr, uid, args, offset=0, limit=0, order=None,
context=None, count=False):
"""
Overrides orm search method.
@param cr: the current row, from the database cursor,
@param user: the current users ID for security checks,
@param args: list of tuples of form [(name_of_the_field, operator, value), ...].
@param offset: The Number of Results to Pass
@param limit: The Number of Results to Return
@param context: A standard dictionary for contextual values
@param count: If its True the method returns number of records instead of ids
@return: List of id
"""
args_without_date = []
start_date = False
until_date = False
for arg in args:
if arg[0] not in ('date', unicode('date'), 'date_deadline', unicode('date_deadline')):
if arg[0] == "id":
new_id = self.remove_virtual_id(arg[2])
new_arg = (arg[0], arg[1], new_id)
args_without_date.append(new_arg)
elif arg[0] not in ('date', unicode('date'), 'date_deadline', unicode('date_deadline')):
args_without_date.append(arg)
else:
if arg[1] in ('>', '>='):
@ -1397,12 +1239,17 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
if until_date:
continue
until_date = arg[2]
res = super(calendar_event, self).search(cr, uid, args_without_date, \
offset, limit, order, context, count)
0, 0, order, context, count=False)
res = self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit, context=context)
if count:
return len(res)
elif limit:
return res[offset:offset+limit]
else:
return res
res = self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
return res
def get_edit_all(self, cr, uid, id, vals=None):
"""
@ -1413,22 +1260,25 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
if(vals and 'edit_all' in vals): #we jsut check edit_all
return vals['edit_all']
else: #it's a recurrent event and edit_all is already check
return meeting['recurrency'] and meeting['edit_all']
return meeting['recurrency'] and meeting['edit_all']
def _get_data(self, cr, uid, id, context=None):
res = self.read(cr, uid, [id],['date', 'date_deadline'])
return res[0]
def need_to_update(self, event_id, vals):
split_id = str(event_id).split("-")
if len(split_id) < 2:
return False
else:
date_start = vals.get('date', '')
try:
date_start = datetime.strptime(date_start, '%Y-%m-%d %H:%M:%S').strftime("%Y%m%d%H%M%S")
return date_start == split_id[1]
except Exception:
return True
def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True):
"""
Overrides orm write method.
@param self: the object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of crm meeting's ids
@param vals: Dictionary of field value.
@param context: A standard dictionary for contextual values
@return: True
"""
if context is None:
context = {}
if isinstance(ids, (str, int, long)):
@ -1440,12 +1290,15 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
for event_id in select:
real_event_id = base_calendar_id2real_id(event_id)
if(self.get_edit_all(cr, uid, event_id, vals=vals)):
edit_all = self.get_edit_all(cr, uid, event_id, vals=vals)
if edit_all:
if self.need_to_update(event_id, vals):
res = self._get_data(cr, uid, real_event_id, context=context)
vals.update(res)
event_id = real_event_id
if len(str(event_id).split('-')) > 1:
#if edit one instance of a reccurrent id
if len(str(event_id).split('-')) > 1 and not edit_all:
data = self.read(cr, uid, event_id, ['date', 'date_deadline', \
'rrule', 'duration', 'exdate'])
if data.get('rrule'):
@ -1458,15 +1311,15 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'edit_all': False,
'recurrency' : False,
})
new_id = self.copy(cr, uid, real_event_id, default=data, context=context)
date_new = event_id.split('-')[1]
date_new = time.strftime("%Y%m%dT%H%M%S", \
time.strptime(date_new, "%Y%m%d%H%M%S"))
exdate = (data['exdate'] and (data['exdate'] + ',') or '') + date_new
res = self.write(cr, uid, [real_event_id], {'exdate': exdate})
context.update({'active_id': new_id, 'active_ids': [new_id]})
continue
if not real_event_id in new_ids:
@ -1482,10 +1335,6 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
vals.get('allday', False),
context=context)
vals.update(updated_vals.get('value', {}))
if not 'edit_all' in vals:
vals['edit_all'] = False
if new_ids:
res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
@ -1494,18 +1343,9 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
# change alarm details
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date', context=context)
return res
return res or True and False
def browse(self, cr, uid, ids, context=None, list_class=None, fields_process=None):
"""
Overrides orm browse method.
@param self: the object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of crm meeting's ids
@param context: A standard dictionary for contextual values
@return: the object list.
"""
if isinstance(ids, (str, int, long)):
select = [ids]
else:
@ -1518,19 +1358,29 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
return res
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
if not context:
context = {}
if 'date' in groupby:
raise osv.except_osv(_('Warning !'), _('Group by date not supported, use the calendar view instead'))
virtual_id = context.get('virtual_id', False)
context.update({'virtual_id': False})
res = super(calendar_event, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby)
for re in res:
#remove the count, since the value is not consistent with the result of the search when expand the group
for groupname in groupby:
if re.get(groupname + "_count"):
del re[groupname + "_count"]
re.get('__context').update({'virtual_id' : virtual_id})
return res
def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
"""
Overrides orm Read method.Read List of fields for calendar event.
@param cr: the current row, from the database cursor,
@param user: the current users ID for security checks,
@param ids: List of calendar event's id.
@param fields: List of fields.
@param context: A standard dictionary for contextual values
@return: List of Dictionary of form [{name_of_the_field: value, ...}, ...]
"""
# FIXME This whole id mangling has to go!
if context is None:
context = {}
if isinstance(ids, (str, int, long)):
select = [ids]
@ -1544,9 +1394,10 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
fields.append('duration')
for base_calendar_id, real_id in select:
for base_calendar_id, real_id in select:
#REVET: Revision ID: olt@tinyerp.com-20100924131709-cqsd1ut234ni6txn
res = super(calendar_event, self).read(cr, uid, real_id, fields=fields, context=context, load=load)
if not res :
continue
ls = base_calendar_id2real_id(base_calendar_id, with_date=res and res.get('duration', 0) or 0)
@ -1558,41 +1409,34 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
result.append(res)
if isinstance(ids, (str, int, long)):
return result and result[0] or False
return result
def copy(self, cr, uid, id, default=None, context=None):
"""
Duplicate record on specified id.
@param self: the object pointer.
@param cr: the current row, from the database cursor,
@param id: id of record from which we duplicated.
@param context: A standard dictionary for contextual values
@return: Duplicate record id.
"""
if context is None:
context = {}
res = super(calendar_event, self).copy(cr, uid, base_calendar_id2real_id(id), default, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
return res
def unlink(self, cr, uid, ids, context=None):
"""
Deletes records specified in ids.
@param self: the object pointer.
@param cr: the current row, from the database cursor,
@param id: List of calendar event's id.
@param context: A standard dictionary for contextual values
@return: True
"""
res = False
for event_datas in self.read(cr, uid, ids, ['date', 'rrule', 'exdate'], context=context):
event_id = event_datas['id']
if not isinstance(ids, list):
ids = [ids]
res = False
for id in ids:
data_list = self.read(cr, uid, [id], ['date', 'rrule', 'exdate'], context=context)
if len(data_list) < 1:
continue
event_data = data_list[0]
event_id = event_data['id']
if self.get_edit_all(cr, uid, event_id, vals=None):
event_id = base_calendar_id2real_id(event_id)
if isinstance(event_id, (int, long)):
res = super(calendar_event, self).unlink(cr, uid, event_id, context=context)
self.pool.get('res.alarm').do_alarm_unlink(cr, uid, [event_id], self._name)
@ -1600,11 +1444,11 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
else:
str_event, date_new = event_id.split('-')
event_id = int(str_event)
if event_datas['rrule']:
if event_data['rrule']:
# Remove one of the recurrent event
date_new = time.strftime("%Y%m%dT%H%M%S", \
time.strptime(date_new, "%Y%m%d%H%M%S"))
exdate = (event_datas['exdate'] and (event_datas['exdate'] + ',') or '') + date_new
exdate = (event_data['exdate'] and (event_data['exdate'] + ',') or '') + date_new
res = self.write(cr, uid, [event_id], {'exdate': exdate})
else:
res = super(calendar_event, self).unlink(cr, uid, [event_id], context=context)
@ -1613,15 +1457,6 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
return res
def create(self, cr, uid, vals, context=None):
"""
Create new record.
@param self: the object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param vals: dictionary of every field value.
@param context: A standard dictionary for contextual values
@return: new created record id.
"""
if context is None:
context = {}
@ -1635,11 +1470,13 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
vals.get('allday', False),
context=context)
vals.update(updated_vals.get('value', {}))
res = super(calendar_event, self).create(cr, uid, vals, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
return res
def do_tentative(self, cr, uid, ids, context=None, *args):
""" Makes event invitation as Tentative
@ -1710,7 +1547,7 @@ class calendar_todo(osv.osv):
@param args: list of tuples of form [(name_of_the_field, operator, value), ...].
@param context: A standard dictionary for contextual values
"""
assert name == 'date'
return self.write(cr, uid, id, { 'date_start': value }, context=context)
@ -1742,9 +1579,9 @@ class ir_attachment(osv.osv):
for arg in args:
args1.append(map(lambda x:str(x).split('-')[0], arg))
return super(ir_attachment, self).search_count(cr, user, args1, context)
def create(self, cr, uid, vals, context=None):
if context:
id = context.get('default_res_id', False)

View File

@ -242,8 +242,7 @@
widget="selection" />
<group colspan="2" col="4" attrs="{'readonly': [('state','=','done')]}">
<field name="recurrency"/>
<field name="edit_all" attrs="{'invisible':[('recurrency','=', False)]}"
on_change="onchange_edit_all(rrule_type,edit_all)"/>
<field name="edit_all" attrs="{'invisible':[('recurrency','=', False)]}" />
</group>
</group>
<notebook colspan="4">

View File

@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-20 20:46+0000\n"
"PO-Revision-Date: 2011-06-23 19:26+0000\n"
"Last-Translator: Ayhan KIZILTAN <Unknown>\n"
"Language-Team: Turkish <tr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-21 04:37+0000\n"
"X-Launchpad-Export-Date: 2011-06-24 05:00+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: base_calendar
@ -925,7 +925,7 @@ msgstr "Yinele"
msgid ""
"Reference to the URIthat points to the directory information corresponding "
"to the attendee."
msgstr ""
msgstr "Katılımcıyla ilgili dizin bilgisine yönlendiren URL ile ilişkilidir."
#. module: base_calendar
#: selection:base.calendar.set.exrule,month_list:0
@ -1166,6 +1166,8 @@ msgid ""
"If the active field is set to true, it will allow you to hide the event "
"alarm information without removing it."
msgstr ""
"Etkin alan yanlış olarak ayarlıysa, etkinlik alarmını kaldırmadan "
"gizlemenizi sağlar."
#. module: base_calendar
#: field:calendar.event,recurrent_id:0
@ -1253,6 +1255,8 @@ msgid ""
"calendar component, than that provided by the "
"\"SUMMARY\" property"
msgstr ""
"Takvim bileşeninin tanımını \"ÖZET\" özelliğinden eldeedilenden daha tam "
"olarak belirtir."
#. module: base_calendar
#: view:calendar.event:0
@ -1327,6 +1331,8 @@ msgstr "Muafşyet Kuralı"
msgid ""
"To specify the language for text values in aproperty or property parameter."
msgstr ""
"Bir özellikteki ya da özellik parametresine ait metin değerlerinin dilini "
"belirler."
#. module: base_calendar
#: view:calendar.event:0
@ -1668,6 +1674,12 @@ msgid ""
" * Points to a procedure resource, which is invoked when "
" the alarm is triggered for procedure."
msgstr ""
"* Alarmın ses çalması için tetiklendiği durumuna benzeterek, Bir ses "
"kaynağını işaret eder.\n"
" * Bir epostaya mesal eki olarak gönderilmek istenen "
"dosya,\n"
" * Alarm işlem için tetiklendiğinde işlem kaynağını "
"işaret eder."
#. module: base_calendar
#: selection:base.calendar.set.exrule,byday:0

View File

@ -15,7 +15,8 @@
Now I will set recurrence for this event to occur monday and friday of week
-
!python {model: calendar.event}: |
self.write(cr, uid, [ref("calendar_event_technicalpresentation0")], {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly'})
data = {'fr': 1, 'mo': 1, 'interval': 1, 'rrule_type': 'weekly', 'end_type': 'end_date', 'end_date': '2011-05-31 00:00:00'}
self.write(cr, uid, [ref("calendar_event_technicalpresentation0")], data)
- |
In order to check that recurrent events are views successfully in calendar view,
I will open calendar view of events
@ -27,7 +28,7 @@
I will search for one of the recurrent event and count the number of events
-
!python {model: calendar.event}: |
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')] )
ids = self.search(cr, uid, [('date', '>=', '2011-04-30 16:00:00'), ('date', '<=', '2011-05-31 00:00:00')], context={'virtual_id': True} )
assert len(ids) == 9
- |
Now I will make All day event and test it

View File

@ -19,9 +19,7 @@
#
##############################################################################
import calendar_event_edit_all
import base_calendar_invite_attendee
import base_calendar_set_exrule
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,163 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from base_calendar import base_calendar
from osv import fields, osv
from tools.translate import _
import tools
import re
months = {
1: "January", 2: "February", 3: "March", 4: "April", \
5: "May", 6: "June", 7: "July", 8: "August", 9: "September", \
10: "October", 11: "November", 12: "December"
}
class base_calendar_set_exrule(osv.osv_memory):
"""
Set Exrule.
"""
_name = "base.calendar.set.exrule"
_description = "Set Exrule"
_columns = {
'freq': fields.selection([('None', 'No Repeat'), \
('secondly', 'Secondly'), \
('minutely', 'Minutely'), \
('hourly', 'Hourly'), \
('daily', 'Daily'), \
('weekly', 'Weekly'), \
('monthly', 'Monthly'), \
('yearly', 'Yearly')], 'Frequency',required=True),
'interval': fields.integer('Interval'),
'count': fields.integer('Count'),
'mo': fields.boolean('Mon'),
'tu': fields.boolean('Tue'),
'we': fields.boolean('Wed'),
'th': fields.boolean('Thu'),
'fr': fields.boolean('Fri'),
'sa': fields.boolean('Sat'),
'su': fields.boolean('Sun'),
'select1': fields.selection([('date', 'Date of month'), \
('day', 'Day of month')], 'Option'),
'day': fields.integer('Date of month'),
'week_list': fields.selection([('MO', 'Monday'), ('TU', 'Tuesday'), \
('WE', 'Wednesday'), ('TH', 'Thursday'), \
('FR', 'Friday'), ('SA', 'Saturday'), \
('SU', 'Sunday')], 'Weekday'),
'byday': fields.selection([('1', 'First'), ('2', 'Second'), \
('3', 'Third'), ('4', 'Fourth'), \
('5', 'Fifth'), ('-1', 'Last')], 'By day'),
'month_list': fields.selection(months.items(),'Month'),
'end_date': fields.date('Repeat Until'),
}
def view_init(self, cr, uid, fields, context=None):
"""
This function checks for precondition before wizard executes
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param fields: List of fields for default value
@param context: A standard dictionary for contextual values
"""
if context is None:
context = {}
event_obj = self.pool.get(context.get('active_model'))
for event in event_obj.browse(cr, uid, context.get('active_ids', []), context=context):
if not event.rrule:
raise osv.except_osv(_("Warning !"), _("Please Apply Recurrency before applying Exception Rule."))
return False
def compute_exrule_string(self, cr, uid, ids, context=None):
"""
Compute rule string.
@param self: the object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param datas: dictionary of freq and interval value.
@return: string value which compute FREQILY;INTERVAL
"""
weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
weekstring = ''
monthstring = ''
yearstring = ''
if context is None:
context = {}
ex_id = base_calendar.base_calendar_id2real_id(context.get('active_id', False))
model = context.get('model', False)
model_obj = self.pool.get(model)
for datas in self.read(cr, uid, ids, context=context):
freq = datas.get('freq')
if freq == 'None':
model_obj.write(cr, uid, ex_id,{'exrule': ''})
return{}
interval_srting = datas.get('interval') and (';INTERVAL=' + str(datas.get('interval'))) or ''
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
if byday:
weekstring = ';BYDAY=' + ','.join(byday)
elif freq == 'monthly':
if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
raise osv.except_osv(_('Error!'), ("Please select proper Day of month"))
if datas.get('select1')=='day':
monthstring = ';BYDAY=' + datas.get('byday') + datas.get('week_list')
elif datas.get('select1')=='date':
monthstring = ';BYMONTHDAY=' + str(datas.get('day'))
elif freq == 'yearly':
if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31):
raise osv.except_osv(_('Error!'), ("Please select proper Day of month"))
bymonth = ';BYMONTH=' + str(datas.get('month_list'))
if datas.get('select1')=='day':
bystring = ';BYDAY=' + datas.get('byday') + datas.get('week_list')
elif datas.get('select1')=='date':
bystring = ';BYMONTHDAY=' + str(datas.get('day'))
yearstring = bymonth + bystring
if datas.get('end_date'):
datas['end_date'] = ''.join((re.compile('\d')).findall(datas.get('end_date'))) + '235959Z'
enddate = (datas.get('count') and (';COUNT=' + str(datas.get('count'))) or '') +\
((datas.get('end_date') and (';UNTIL=' + datas.get('end_date'))) or '')
exrule_string = 'FREQ=' + freq.upper() + weekstring + interval_srting \
+ enddate + monthstring + yearstring
model_obj.write(cr, uid, ex_id,{'exrule': exrule_string})
return {'type': 'ir.actions.act_window_close'}
_defaults = {
'freq': lambda *x: 'None',
'select1': lambda *x: 'date',
'interval': lambda *x: 1,
}
base_calendar_set_exrule()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,71 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_base_calendar_set_exrule" model="ir.ui.view">
<field name="name">base.calendar.set.exrule.form</field>
<field name="model">base.calendar.set.exrule</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Set Exrule">
<separator string="Select range to Exclude" colspan="8"/>
<group col="8" colspan="6">
<field name="interval" />
<field name="freq" />
<field name="count" />
<field name="end_date" />
</group>
<group col="8" colspan="8" name="Select weekdays"
attrs="{'invisible' : [('freq','!=','weekly')]}">
<field name="mo" colspan="1" />
<field name="tu" colspan="1" />
<field name="we" colspan="1" />
<field name="th" colspan="1" />
<field name="fr" colspan="1" />
<field name="sa" colspan="1" />
<field name="su" colspan="1" />
<newline />
</group>
<group col="8" colspan="6"
attrs="{'invisible' : [('freq','!=','monthly'), ('freq','!=','yearly')]}">
<group col="2" colspan="1">
<field name="select1" />
</group>
<group col="2" colspan="1"
attrs="{'invisible' : [('select1','=','day')]}">
<field name="day"
attrs="{'required' : [('select1','=','date')]}"/>
</group>
<group col="3" colspan="1"
attrs="{'invisible' : [('select1','=','date')]}">
<field name="byday" string="The"
attrs="{'required' : [('select1','=','day')]}"/>
<field name="week_list" nolabel="1"
attrs="{'required' : [('select1','=','day')]}"/>
</group>
<group col="1" colspan="1"
attrs="{'invisible' : [('freq','!=','yearly')]}">
<field name="month_list" string="of"
colspan="1"
attrs="{'required' : [('freq','=','yearly')]}"/>
</group>
</group>
<group colspan="4" col="6">
<separator string="" colspan="8"/>
<label string="" colspan="2"/>
<button icon="gtk-cancel" special="cancel" string="_Cancel"/>
<button icon="gtk-ok" string="_Ok" name="compute_exrule_string" type="object"/>
</group>
</form>
</field>
</record>
<record id="action_base_calendar_set_exrule" model="ir.actions.act_window">
<field name="name">Set Exclude range</field>
<field name="res_model">base.calendar.set.exrule</field>
<field name="view_type">form</field>
<field name="view_mode">form,tree</field>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@ -1,98 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv
from osv import fields
class calendar_event_edit_all(osv.osv_memory):
def _default_values(self, cr, uid, context=None):
""" Get Default value for Start Date
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
@Return: Get Default value for Start Date
"""
context_id = context and context.get('active_id', False) or False
if context_id:
if context.get('date'):
return context.get('date')
else:
model = context.get('model', False)
model_obj = self.pool.get(model)
event = model_obj.read(cr, uid, context_id, ['name', 'location', 'alarm_id'])
return event['date']
def _default_deadline(self, cr, uid, context=None):
""" Get Default value for End Date
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
@return: Get Default value for End Date
"""
context_id = context and context.get('active_id', False) or False
if context_id:
if context.get('date_deadline'):
return context.get('date_deadline')
else:
model = context.get('model', False)
model_obj = self.pool.get(model)
event = model_obj.read(cr, uid, context_id, ['name', 'location', 'alarm_id'])
return event['date_deadline']
def modify_this(self, cr, uid, ids, context=None):
"""
Modify All event for Crm Meeting.
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of calendar event edit alls IDs
@return: dictionary {}
"""
if context is None:
context = {}
context_id = context and context.get('active_id', False) or False
if context_id:
for datas in self.read(cr, uid, ids):
model = context.get('model', False)
model_obj = self.pool.get(model)
model_obj.modify_all(cr, uid, [context_id], datas, context=context)
return {'type': 'ir.actions.act_window_close'}
_name = "calendar.event.edit.all"
_description = "Calendar Edit all event"
_columns = {
'name': fields.char('Title', size=64, required=True),
'date': fields.datetime('Start Date', required=True),
'date_deadline': fields.datetime('End Date', required=True),
'location': fields.char('Location', size=124),
'alarm_id': fields.many2one('res.alarm', 'Reminder'),
}
_defaults = {
'date': _default_values,
'date_deadline': _default_deadline
}
calendar_event_edit_all()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_calendar_event_edit_all" model="ir.ui.view">
<field name="name">calendar.event.edit.all.form</field>
<field name="model">calendar.event.edit.all</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Edit all Occurrences">
<group colspan="4" >
<separator string="" colspan="4" />
<newline/>
<field name='name' colspan="4" />
<newline />
<field name='location' colspan="4" />
<newline />
<field name='date' />
<field name='date_deadline' />
<newline />
<field name='alarm_id'/>
</group>
<separator string="" colspan="4" />
<group colspan="4" col="6">
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
<button icon="gtk-save" string="_Save" name="modify_this" type="object"/>
</group>
</form>
</field>
</record>
<record id="action_calendar_event_edit_all" model="ir.actions.act_window">
<field name="name">Edit all events</field>
<field name="res_model">calendar.event.edit.all</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_calendar_event_edit_all"/>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,77 @@
# Chinese (Simplified) translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-22 08:19+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-23 04:56+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: base_crypt
#: sql_constraint:res.users:0
msgid "You can not have two users with the same login !"
msgstr "你不能同时登录两个用户!"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "res.users"
msgstr "res.users"
#. module: base_crypt
#: constraint:res.users:0
msgid "The chosen company is not in the allowed companies for this user"
msgstr "用户无权操作所选择公司数据"
#. module: base_crypt
#: code:addons/base_crypt/crypt.py:132
#, python-format
msgid "Please specify the password !"
msgstr "请指定密码!"
#. module: base_crypt
#: model:ir.module.module,shortdesc:base_crypt.module_meta_information
msgid "Base - Password Encryption"
msgstr "Base - Password Encryption"
#. module: base_crypt
#: code:addons/base_crypt/crypt.py:132
#, python-format
msgid "Error"
msgstr "错误"
#. module: base_crypt
#: model:ir.module.module,description:base_crypt.module_meta_information
msgid ""
"This module replaces the cleartext password in the database with a password "
"hash,\n"
"preventing anyone from reading the original password.\n"
"For your existing user base, the removal of the cleartext passwords occurs "
"the first time\n"
"a user logs into the database, after installing base_crypt.\n"
"After installing this module it won't be possible to recover a forgotten "
"password for your\n"
"users, the only solution is for an admin to set a new password.\n"
"\n"
"Note: installing this module does not mean you can ignore basic security "
"measures,\n"
"as the password is still transmitted unencrypted on the network (by the "
"client),\n"
"unless you are using a secure protocol such as XML-RPCS.\n"
" "
msgstr ""
"这个模块在数据库里用密码散列代替原来的明文密码,防止任何人读取到原密码。\n"
"对于已存在在数据当安装了base_crypt后明文密码会在用户第一次登陆数据库的时候清除。\n"
"在安装了这个模块后将不能恢复已遗忘的用户密码,唯一的解决办法是通过管理员输入一个新密码。\n"
"注意:安装这个模块并不意味着你可以忽略基本安全措施,\n"
"除非你用了一个安全协议例如XML-RPCS否则密码在网络仍然以非加密的形式传输通过客户端\n"
" "

View File

@ -0,0 +1,32 @@
# Chinese (Simplified) translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-29 01:21+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-30 04:34+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: base_tools
#: model:ir.module.module,shortdesc:base_tools.module_meta_information
msgid "Common base for tools modules"
msgstr "base_tools"
#. module: base_tools
#: model:ir.module.module,description:base_tools.module_meta_information
msgid ""
"\n"
" "
msgstr ""
"\n"
" "

818
addons/caldav/i18n/fi.po Normal file
View File

@ -0,0 +1,818 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
"PO-Revision-Date: 2011-06-28 09:32+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-29 04:43+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: caldav
#: view:basic.calendar:0
msgid "Value Mapping"
msgstr ""
#. module: caldav
#: help:caldav.browse,url:0
msgid "Url of the caldav server, use for synchronization"
msgstr ""
#. module: caldav
#: field:basic.calendar.alias,name:0
msgid "Filename"
msgstr "Tiedostonnimi"
#. module: caldav
#: model:ir.model,name:caldav.model_calendar_event_export
msgid "Event Export"
msgstr ""
#. module: caldav
#: view:calendar.event.subscribe:0
msgid "Provide path for Remote Calendar"
msgstr ""
#. module: caldav
#: model:ir.actions.act_window,name:caldav.action_calendar_event_import_values
msgid "Import .ics File"
msgstr ""
#. module: caldav
#: view:calendar.event.export:0
msgid "_Close"
msgstr ""
#. module: caldav
#: selection:basic.calendar.attributes,type:0
#: selection:basic.calendar.lines,name:0
msgid "Attendee"
msgstr "Osallistuja"
#. module: caldav
#: sql_constraint:basic.calendar.fields:0
msgid "Can not map a field more than once"
msgstr ""
#. module: caldav
#: code:addons/caldav/calendar.py:787
#: code:addons/caldav/calendar.py:877
#: code:addons/caldav/wizard/calendar_event_import.py:63
#, python-format
msgid "Warning !"
msgstr "Varoitus !"
#. module: caldav
#: field:basic.calendar.lines,object_id:0
msgid "Object"
msgstr "Objekti"
#. module: caldav
#: view:basic.calendar:0
msgid "Todo"
msgstr "Tehtävät"
#. module: caldav
#: model:ir.model,name:caldav.model_user_preference
msgid "User preference Form"
msgstr ""
#. module: caldav
#: field:user.preference,service:0
msgid "Services"
msgstr "Palvelut"
#. module: caldav
#: selection:basic.calendar.fields,fn:0
msgid "Expression as constant"
msgstr ""
#. module: caldav
#: selection:user.preference,device:0
msgid "Evolution"
msgstr "Evoluutio"
#. module: caldav
#: view:calendar.event.import:0
#: view:calendar.event.subscribe:0
msgid "Ok"
msgstr "OK"
#. module: caldav
#: code:addons/caldav/calendar.py:877
#, python-format
msgid "Please provide proper configuration of \"%s\" in Calendar Lines"
msgstr ""
#. module: caldav
#: field:calendar.event.export,name:0
msgid "File name"
msgstr "Tiedostonimi"
#. module: caldav
#: field:caldav.browse,url:0
msgid "Caldav Server"
msgstr "Caldav palvelin"
#. module: caldav
#: code:addons/caldav/wizard/calendar_event_subscribe.py:59
#, python-format
msgid "Error!"
msgstr "Virhe!"
#. module: caldav
#: help:caldav.browse,caldav_doc_file:0
msgid "download full caldav Documentation."
msgstr ""
#. module: caldav
#: selection:user.preference,device:0
msgid "iPhone"
msgstr ""
#. module: caldav
#: code:addons/caldav/wizard/caldav_browse.py:32
#, python-format
msgid ""
"\n"
" * Webdav server that provides remote access to calendar\n"
" * Synchronisation of calendar using WebDAV\n"
" * Customize calendar event and todo attribute with any of OpenERP model\n"
" * Provides iCal Import/Export functionality\n"
"\n"
" To access Calendars using CalDAV clients, point them to:\n"
" "
"http://HOSTNAME:PORT/webdav/DATABASE_NAME/calendars/users/USERNAME/c\n"
"\n"
" To access OpenERP Calendar using WebCal to remote site use the URL "
"like:\n"
" "
"http://HOSTNAME:PORT/webdav/DATABASE_NAME/Calendars/CALENDAR_NAME.ics\n"
"\n"
" Where,\n"
" HOSTNAME: Host on which OpenERP server(With webdav) is running\n"
" PORT : Port on which OpenERP server is running (By Default : 8069)\n"
" DATABASE_NAME: Name of database on which OpenERP Calendar is "
"created\n"
" CALENDAR_NAME: Name of calendar to access\n"
" "
msgstr ""
#. module: caldav
#: code:addons/caldav/wizard/caldav_browse.py:147
#, python-format
msgid ""
"\n"
"Prerequire\n"
"----------\n"
"If you are using thunderbird, first you need to install the lightning "
"module\n"
"http://www.mozilla.org/projects/calendar/lightning/\n"
"\n"
"configuration\n"
"-------------\n"
"\n"
"1. Go to Calendar View\n"
"\n"
"2. File -> New Calendar\n"
"\n"
"3. Chosse \"On the Network\"\n"
"\n"
"4. for format choose CalDav\n"
" and as location the url given above (ie : "
"http://host.com:8069/webdav/db/calendars/users/demo/c/Meetings)\n"
" \n"
"5. Choose a name and a color for the Calendar, and we advice you to uncheck "
"\"alarm\"\n"
"\n"
"6. Then put your openerp login and password (to give the password only check "
"the box \"Use password Manager to remember this password\"\n"
"\n"
"7. Then Finish, your meetings should appear now in your calendar view\n"
msgstr ""
#. module: caldav
#: selection:basic.calendar,type:0
#: selection:basic.calendar.attributes,type:0
#: selection:basic.calendar.lines,name:0
msgid "TODO"
msgstr "Tehtävät"
#. module: caldav
#: view:calendar.event.export:0
msgid "Export ICS"
msgstr ""
#. module: caldav
#: selection:basic.calendar.fields,fn:0
msgid "Use the field"
msgstr "Käytä kenttää"
#. module: caldav
#: code:addons/caldav/calendar.py:787
#, python-format
msgid "Can not create line \"%s\" more than once"
msgstr ""
#. module: caldav
#: view:basic.calendar:0
#: field:basic.calendar,line_ids:0
#: model:ir.model,name:caldav.model_basic_calendar_lines
msgid "Calendar Lines"
msgstr "Kalenteririvit"
#. module: caldav
#: model:ir.model,name:caldav.model_calendar_event_subscribe
msgid "Event subscribe"
msgstr ""
#. module: caldav
#: view:calendar.event.import:0
msgid "Import ICS"
msgstr ""
#. module: caldav
#: view:calendar.event.import:0
#: view:calendar.event.subscribe:0
#: view:user.preference:0
msgid "_Cancel"
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_event
msgid "basic.calendar.event"
msgstr ""
#. module: caldav
#: view:basic.calendar:0
#: selection:basic.calendar,type:0
#: selection:basic.calendar.attributes,type:0
#: selection:basic.calendar.lines,name:0
msgid "Event"
msgstr ""
#. module: caldav
#: field:document.directory,calendar_collection:0
#: field:user.preference,collection:0
msgid "Calendar Collection"
msgstr ""
#. module: caldav
#: constraint:document.directory:0
msgid "Error! You can not create recursive Directories."
msgstr "Virhe! Et voi luoda rekursiivisia kansioita."
#. module: caldav
#: view:user.preference:0
msgid "_Open"
msgstr ""
#. module: caldav
#: field:basic.calendar,type:0
#: field:basic.calendar.attributes,type:0
#: field:basic.calendar.fields,type_id:0
#: field:basic.calendar.lines,name:0
msgid "Type"
msgstr "Tyyppi"
#. module: caldav
#: help:calendar.event.export,name:0
msgid "Save in .ics format"
msgstr ""
#. module: caldav
#: code:addons/caldav/calendar.py:1291
#, python-format
msgid "Error !"
msgstr "Virhe !"
#. module: caldav
#: code:addons/caldav/wizard/caldav_browse.py:128
#, python-format
msgid ""
"\n"
" 1. Go to Calendar View\n"
"\n"
" 2. File -> New -> Calendar\n"
"\n"
" 3. Fill the form \n"
" - type : CalDav\n"
" - name : Whaterver you want (ie : Meeting)\n"
" - url : "
"http://HOST:PORT/webdav/DB_NAME/calendars/users/USER/c/Meetings (ie : "
"http://localhost:8069/webdav/db_1/calendars/users/demo/c/Meetings) the one "
"given on the top of this window\n"
" - uncheck \"User SSL\"\n"
" - Username : Your username (ie : Demo)\n"
" - Refresh : everytime you want that evolution synchronize the data "
"with the server\n"
"\n"
" 4. Click ok and give your openerp password\n"
"\n"
" 5. A new calendar named with the name you gave should appear on the left "
"side. \n"
" "
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_attributes
msgid "Calendar attributes"
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_caldav_browse
msgid "Caldav Browse"
msgstr ""
#. module: caldav
#: model:ir.module.module,description:caldav.module_meta_information
msgid ""
"\n"
" This module Contains basic functionality for caldav system like: \n"
" - Webdav server that provides remote access to calendar\n"
" - Synchronisation of calendar using WebDAV\n"
" - Customize calendar event and todo attribute with any of OpenERP model\n"
" - Provides iCal Import/Export functionality\n"
"\n"
" To access Calendars using CalDAV clients, point them to:\n"
" "
"http://HOSTNAME:PORT/webdav/DATABASE_NAME/calendars/users/USERNAME/c\n"
"\n"
" To access OpenERP Calendar using WebCal to remote site use the URL "
"like:\n"
" "
"http://HOSTNAME:PORT/webdav/DATABASE_NAME/Calendars/CALENDAR_NAME.ics\n"
"\n"
" Where,\n"
" HOSTNAME: Host on which OpenERP server(With webdav) is running\n"
" PORT : Port on which OpenERP server is running (By Default : 8069)\n"
" DATABASE_NAME: Name of database on which OpenERP Calendar is "
"created\n"
" CALENDAR_NAME: Name of calendar to access\n"
msgstr ""
#. module: caldav
#: selection:user.preference,device:0
msgid "Android based device"
msgstr ""
#. module: caldav
#: field:basic.calendar,create_date:0
msgid "Created Date"
msgstr "Luontipäivä"
#. module: caldav
#: view:basic.calendar:0
msgid "Attributes Mapping"
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_document_directory
msgid "Directory"
msgstr "Hakemisto"
#. module: caldav
#: field:calendar.event.subscribe,url_path:0
msgid "Provide path for remote calendar"
msgstr ""
#. module: caldav
#: view:caldav.browse:0
msgid "_Ok"
msgstr ""
#. module: caldav
#: field:basic.calendar.lines,domain:0
msgid "Domain"
msgstr "Toimialue"
#. module: caldav
#: view:calendar.event.subscribe:0
msgid "_Subscribe"
msgstr ""
#. module: caldav
#: field:basic.calendar,user_id:0
msgid "Owner"
msgstr "Omistaja"
#. module: caldav
#: view:basic.calendar:0
#: field:basic.calendar.alias,cal_line_id:0
#: field:basic.calendar.lines,calendar_id:0
#: model:ir.ui.menu,name:caldav.menu_calendar
#: field:user.preference,calendar:0
msgid "Calendar"
msgstr "kalenteri"
#. module: caldav
#: code:addons/caldav/calendar.py:41
#, python-format
msgid ""
"Please install python-vobject from http://vobject.skyhouseconsulting.com/"
msgstr ""
#. module: caldav
#: code:addons/caldav/wizard/calendar_event_import.py:63
#, python-format
msgid "Invalid format of the ics, file can not be imported"
msgstr "Virheellinen ics formaatti, tiedostoa ei voi tuoda"
#. module: caldav
#: selection:user.preference,service:0
msgid "CalDAV"
msgstr ""
#. module: caldav
#: field:basic.calendar.fields,field_id:0
msgid "OpenObject Field"
msgstr ""
#. module: caldav
#: field:basic.calendar.alias,res_id:0
msgid "Res. ID"
msgstr ""
#. module: caldav
#: view:calendar.event.subscribe:0
msgid "Message..."
msgstr "Viesti..."
#. module: caldav
#: selection:user.preference,device:0
msgid "Other"
msgstr "Muu"
#. module: caldav
#: view:basic.calendar:0
#: field:basic.calendar,has_webcal:0
msgid "WebCal"
msgstr ""
#. module: caldav
#: view:document.directory:0
#: model:ir.actions.act_window,name:caldav.action_calendar_collection_form
#: model:ir.ui.menu,name:caldav.menu_calendar_collection
msgid "Calendar Collections"
msgstr ""
#. module: caldav
#: code:addons/caldav/calendar.py:813
#: sql_constraint:basic.calendar.alias:0
#, python-format
msgid "The same filename cannot apply to two records!"
msgstr ""
#. module: caldav
#: sql_constraint:document.directory:0
msgid "Directory cannot be parent of itself!"
msgstr ""
#. module: caldav
#: view:basic.calendar:0
#: field:document.directory,calendar_ids:0
#: model:ir.actions.act_window,name:caldav.action_caldav_form
#: model:ir.ui.menu,name:caldav.menu_caldav_directories
msgid "Calendars"
msgstr "Kalenterit"
#. module: caldav
#: field:basic.calendar,collection_id:0
msgid "Collection"
msgstr "Kokoelma"
#. module: caldav
#: field:basic.calendar,write_date:0
msgid "Write Date"
msgstr ""
#. module: caldav
#: code:addons/caldav/wizard/caldav_browse.py:104
#, python-format
msgid ""
"\n"
"Prerequire\n"
"----------\n"
"There is no buit-in way to synchronize calendar with caldav.\n"
"So you need to install a third part software : Calendar (CalDav) \n"
"for now it's the only one\n"
"\n"
"configuration\n"
"-------------\n"
"\n"
"1. Open Calendar Sync\n"
" I'll get an interface with 2 tabs\n"
" Stay on the first one\n"
" \n"
"2. CaDAV Calendar URL : put the URL given above (ie : "
"http://host.com:8069/webdav/db/calendars/users/demo/c/Meetings)\n"
"\n"
"3. Put your openerp username and password\n"
"\n"
"4. If your server don't use SSL, you'll get a warnign, say \"Yes\"\n"
"\n"
"5. Then you can synchronize manually or custom the settings to synchronize "
"every x minutes.\n"
" \n"
" "
msgstr ""
#. module: caldav
#: code:addons/caldav/wizard/caldav_browse.py:53
#, python-format
msgid ""
"\n"
" For SSL specific configuration see the documentation below\n"
"\n"
"Now, to setup the calendars, you need to:\n"
"\n"
"1. Click on the \"Settings\" and go to the \"Mail, Contacts, Calendars\" "
"page.\n"
"2. Go to \"Add account...\"\n"
"3. Click on \"Other\"\n"
"4. From the \"Calendars\" group, select \"Add CalDAV Account\"\n"
"\n"
"5. Enter the host's name \n"
" (ie : if the url is http://openerp.com:8069/webdav/db_1/calendars/ , "
"openerp.com is the host)\n"
"\n"
"6. Fill Username and password with your openerp login and password\n"
"\n"
"7. As a description, you can either leave the server's name or\n"
" something like \"OpenERP calendars\".\n"
"\n"
"9. If you are not using a SSL server, you'll get an error, do not worry and "
"push \"Continue\"\n"
"\n"
"10. Then click to \"Advanced Settings\" to specify the right\n"
" ports and paths. \n"
" \n"
"11. Specify the port for the OpenERP server: 8071 for SSL, 8069 without.\n"
"\n"
"12. Set the \"Account URL\" to the right path of the OpenERP webdav:\n"
" the url given by the wizard (ie : "
"http://my.server.ip:8069/webdav/dbname/calendars/ )\n"
"\n"
"11. Click on Done. The phone will hopefully connect to the OpenERP server\n"
" and verify it can use the account.\n"
"\n"
"12. Go to the main menu of the iPhone and enter the Calendar application.\n"
" Your OpenERP calendars will be visible inside the selection of the\n"
" \"Calendars\" button.\n"
" Note that when creating a new calendar entry, you will have to specify\n"
" which calendar it should be saved at.\n"
"\n"
"\n"
"\n"
"IF you need SSL (and your certificate is not a verified one, as usual),\n"
"then you first will need to let the iPhone trust that. Follow these\n"
"steps:\n"
"\n"
" s1. Open Safari and enter the https location of the OpenERP server:\n"
" https://my.server.ip:8071/\n"
" (assuming you have the server at \"my.server.ip\" and the HTTPS port\n"
" is the default 8071)\n"
" s2. Safari will try to connect and issue a warning about the "
"certificate\n"
" used. Inspect the certificate and click \"Accept\" so that iPhone\n"
" now trusts it. \n"
" "
msgstr ""
#. module: caldav
#: sql_constraint:document.directory:0
msgid "The directory name must be unique !"
msgstr "Hakemiston nimen tulee olla uniikki !"
#. module: caldav
#: view:user.preference:0
msgid "User Preference"
msgstr ""
#. module: caldav
#: code:addons/caldav/wizard/calendar_event_subscribe.py:59
#, python-format
msgid "Please provide Proper URL !"
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_timezone
msgid "basic.calendar.timezone"
msgstr ""
#. module: caldav
#: field:basic.calendar.fields,expr:0
msgid "Expression"
msgstr "Lauseke"
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_attendee
msgid "basic.calendar.attendee"
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_alias
msgid "basic.calendar.alias"
msgstr ""
#. module: caldav
#: view:calendar.event.import:0
#: field:calendar.event.import,file_path:0
msgid "Select ICS file"
msgstr ""
#. module: caldav
#: field:caldav.browse,caldav_doc_file:0
msgid "Caldav Document"
msgstr ""
#. module: caldav
#: field:basic.calendar.lines,mapping_ids:0
msgid "Fields Mapping"
msgstr "Kenttien kartoitukset"
#. module: caldav
#: view:caldav.browse:0
msgid "Browse caldav"
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar
msgid "basic.calendar"
msgstr ""
#. module: caldav
#: view:basic.calendar:0
msgid "Other Info"
msgstr "Muu tieto"
#. module: caldav
#: field:user.preference,device:0
msgid "Software/Devices"
msgstr "Ohjelmisto/Laitteet"
#. module: caldav
#: help:basic.calendar,has_webcal:0
msgid ""
"Also export a <name>.ics entry next to the calendar folder, with WebCal "
"content."
msgstr ""
#. module: caldav
#: field:basic.calendar.fields,fn:0
msgid "Function"
msgstr "Toiminto"
#. module: caldav
#: view:basic.calendar:0
#: field:basic.calendar,description:0
#: view:caldav.browse:0
#: field:caldav.browse,description:0
msgid "Description"
msgstr "Kuvaus"
#. module: caldav
#: help:basic.calendar.alias,cal_line_id:0
msgid "The calendar/line this mapping applies to"
msgstr ""
#. module: caldav
#: field:basic.calendar.fields,mapping:0
msgid "Mapping"
msgstr "Mäppäys"
#. module: caldav
#: code:addons/caldav/wizard/calendar_event_import.py:86
#, python-format
msgid "Import Sucessful"
msgstr "Tuonti onnistui"
#. module: caldav
#: view:calendar.event.import:0
msgid "_Import"
msgstr "_Tuo"
#. module: caldav
#: model:ir.model,name:caldav.model_calendar_event_import
msgid "Event Import"
msgstr ""
#. module: caldav
#: selection:basic.calendar.fields,fn:0
msgid "Interval in hours"
msgstr "Väli tuntia"
#. module: caldav
#: view:calendar.event.subscribe:0
msgid "Subscribe to Remote Calendar"
msgstr ""
#. module: caldav
#: help:basic.calendar,calendar_color:0
msgid "For supporting clients, the color of the calendar entries"
msgstr ""
#. module: caldav
#: field:basic.calendar,name:0
#: field:basic.calendar.attributes,name:0
#: field:basic.calendar.fields,name:0
msgid "Name"
msgstr "Nimi"
#. module: caldav
#: selection:basic.calendar.attributes,type:0
#: selection:basic.calendar.lines,name:0
msgid "Alarm"
msgstr "Hälytys"
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_alarm
msgid "basic.calendar.alarm"
msgstr ""
#. module: caldav
#: code:addons/caldav/calendar.py:1291
#, python-format
msgid "Attendee must have an Email Id"
msgstr ""
#. module: caldav
#: model:ir.actions.act_window,name:caldav.action_calendar_event_export_values
msgid "Export .ics File"
msgstr ""
#. module: caldav
#: code:addons/caldav/calendar.py:41
#, python-format
msgid "vobject Import Error!"
msgstr ""
#. module: caldav
#: field:calendar.event.export,file_path:0
msgid "Save ICS file"
msgstr ""
#. module: caldav
#: selection:user.preference,device:0
msgid "Sunbird/Thunderbird"
msgstr ""
#. module: caldav
#: field:basic.calendar,calendar_order:0
msgid "Order"
msgstr "Järjestys"
#. module: caldav
#: model:ir.module.module,shortdesc:caldav.module_meta_information
msgid "Share Calendar using CalDAV"
msgstr "Jaa kalenteri käyttäen CalDAV:ia"
#. module: caldav
#: field:basic.calendar,calendar_color:0
msgid "Color"
msgstr "Väri"
#. module: caldav
#: view:basic.calendar:0
msgid "MY"
msgstr ""
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_fields
msgid "Calendar fields"
msgstr "Kalenterikentät"
#. module: caldav
#: view:calendar.event.import:0
msgid "Import Message"
msgstr ""
#. module: caldav
#: model:ir.actions.act_window,name:caldav.action_calendar_event_subscribe
#: model:ir.actions.act_window,name:caldav.action_calendar_event_subscribe_values
msgid "Subscribe"
msgstr "Tilaa"
#. module: caldav
#: sql_constraint:document.directory:0
msgid "Directory must have a parent or a storage"
msgstr "Hakemistolla täytyy olla ylätason hakemisto tai tietovarasto"
#. module: caldav
#: model:ir.model,name:caldav.model_basic_calendar_todo
msgid "basic.calendar.todo"
msgstr ""
#. module: caldav
#: help:basic.calendar,calendar_order:0
msgid "For supporting clients, the order of this folder among the calendars"
msgstr ""

View File

@ -26,9 +26,8 @@ import addons
from tools.translate import _
class caldav_browse(osv.osv_memory):
__doc = {
'other' : _("""
* Webdav server that provides remote access to calendar
* Synchronisation of calendar using WebDAV
@ -45,11 +44,8 @@ class caldav_browse(osv.osv_memory):
HOSTNAME: Host on which OpenERP server(With webdav) is running
PORT : Port on which OpenERP server is running (By Default : 8069)
DATABASE_NAME: Name of database on which OpenERP Calendar is created
CALENDAR_NAME: Name of calendar to access
"""),
'iphone' : _("""
For SSL specific configuration see the documentation below
@ -60,7 +56,7 @@ Now, to setup the calendars, you need to:
3. Click on "Other"
4. From the "Calendars" group, select "Add CalDAV Account"
5. Enter the host's name
5. Enter the host's name
(ie : if the url is http://openerp.com:8069/webdav/db_1/calendars/ , openerp.com is the host)
6. Fill Username and password with your openerp login and password
@ -71,8 +67,8 @@ Now, to setup the calendars, you need to:
9. If you are not using a SSL server, you'll get an error, do not worry and push "Continue"
10. Then click to "Advanced Settings" to specify the right
ports and paths.
ports and paths.
11. Specify the port for the OpenERP server: 8071 for SSL, 8069 without.
12. Set the "Account URL" to the right path of the OpenERP webdav:
@ -87,8 +83,6 @@ Now, to setup the calendars, you need to:
Note that when creating a new calendar entry, you will have to specify
which calendar it should be saved at.
IF you need SSL (and your certificate is not a verified one, as usual),
then you first will need to let the iPhone trust that. Follow these
steps:
@ -99,13 +93,13 @@ steps:
is the default 8071)
s2. Safari will try to connect and issue a warning about the certificate
used. Inspect the certificate and click "Accept" so that iPhone
now trusts it.
now trusts it.
"""),
'android' : _("""
Prerequire
----------
There is no buit-in way to synchronize calendar with caldav.
So you need to install a third part software : Calendar (CalDav)
So you need to install a third part software : Calendar (CalDav)
for now it's the only one
configuration
@ -114,7 +108,7 @@ configuration
1. Open Calendar Sync
I'll get an interface with 2 tabs
Stay on the first one
2. CaDAV Calendar URL : put the URL given above (ie : http://host.com:8069/webdav/db/calendars/users/demo/c/Meetings)
3. Put your openerp username and password
@ -122,7 +116,7 @@ configuration
4. If your server don't use SSL, you'll get a warnign, say "Yes"
5. Then you can synchronize manually or custom the settings to synchronize every x minutes.
"""),
'evolution' : _("""
@ -130,7 +124,7 @@ configuration
2. File -> New -> Calendar
3. Fill the form
3. Fill the form
- type : CalDav
- name : Whaterver you want (ie : Meeting)
- url : http://HOST:PORT/webdav/DB_NAME/calendars/users/USER/c/Meetings (ie : http://localhost:8069/webdav/db_1/calendars/users/demo/c/Meetings) the one given on the top of this window
@ -140,10 +134,9 @@ configuration
4. Click ok and give your openerp password
5. A new calendar named with the name you gave should appear on the left side.
5. A new calendar named with the name you gave should appear on the left side.
"""),
'thunderbird' : _("""
Prerequire
----------
@ -161,7 +154,7 @@ configuration
4. for format choose CalDav
and as location the url given above (ie : http://host.com:8069/webdav/db/calendars/users/demo/c/Meetings)
5. Choose a name and a color for the Calendar, and we advice you to uncheck "alarm"
6. Then put your openerp login and password (to give the password only check the box "Use password Manager to remember this password"
@ -169,8 +162,6 @@ configuration
7. Then Finish, your meetings should appear now in your calendar view
"""),
}
_name = 'caldav.browse'
_description = 'Caldav Browse'
@ -181,55 +172,48 @@ configuration
}
def default_get(self, cr, uid, fields, context=None):
pref_obj = self.pool.get('user.preference')
pref_ids = pref_obj.browse(cr, uid ,context.get('rec_id',False), context=context)
res = {}
host = ''
host = context.get('host')
port = ''
prefix = 'http://'
prefix = 'http://'
if not config.get('xmlrpc'):
if not config.get('netrpc'):
prefix = 'https://'
host = config.get('xmlrpcs_interface', None)
prefix = 'https://'
port = config.get('xmlrpcs_port', 8071)
else:
host = config.get('netrpc_interface', None)
port = config.get('netrpc_port',8070)
else:
host = config.get('xmlrpc_interface', None)
port = config.get('netrpc_port',8070)
else:
port = config.get('xmlrpc_port',8069)
if host == '' or None:
host = 'localhost'
port = 8069
if not config.get_misc('webdav','enable',True):
raise Exception("WebDAV is disabled, cannot continue")
user_pool = self.pool.get('res.users')
current_user = user_pool.browse(cr, uid, uid, context=context)
pref_obj = self.pool.get('user.preference')
pref_ids = pref_obj.browse(cr, uid ,context.get('rec_id',False), context=context)
#TODO write documentation
res['description'] = self.__doc['other']
if pref_ids:
pref_ids = pref_ids[0]
pref_ids = pref_ids[0]
if pref_ids.device == 'iphone':
url = host + ':' + str(port) + '/'+ pref_ids.service + '/' + cr.dbname + '/'+'calendars/'
else :
url = host + ':' + str(port) + '/'+ pref_ids.service + '/' + cr.dbname + '/'+'calendars/'+ 'users/'+ current_user.login + '/'+ pref_ids.collection.name+ '/'+ pref_ids.calendar.name
res['description'] = self.__doc.get(pref_ids.device , self.__doc['other'])
file = open(addons.get_module_resource('caldav','doc', 'caldav_doc.pdf'),'rb')
res['caldav_doc_file'] = base64.encodestring(file.read())
#res['doc_link'] = 'http://doc.openerp.com/'
res['url'] = prefix+url
return res
def browse_caldav(self, cr, uid, ids, context):
return {}
caldav_browse()
class user_preference(osv.osv_memory):
_name = 'user.preference'
_description = 'User preference Form'
@ -238,32 +222,39 @@ class user_preference(osv.osv_memory):
'calendar' :fields.many2one('basic.calendar', 'Calendar', required=True),
'service': fields.selection([('webdav','CalDAV')], "Services"),
'device' : fields.selection([('other', 'Other'), ('iphone', 'iPhone'), ('android', 'Android based device'),('thunderbird', 'Sunbird/Thunderbird'), ('evolution','Evolution')], "Software/Devices"),
'host_name': fields.char('Host Name', size=64, required=True),
}
def _get_default_calendar(self, cr, uid, context):
if context == None:
context = {}
name = context.get('cal_name')
collection_obj = self.pool.get('basic.calendar')
ids = collection_obj.search(cr, uid, [('name', '=', name)])
return ids[0]
def _get_default_collection(self, cr, uid, context):
collection_obj = self.pool.get('document.directory')
ids = collection_obj.search(cr, uid, [('name', '=', 'c')])
return ids[0]
def _get_default_host(self, cr, uid, context):
ids=self.search(cr,uid,[])
host_name = ''
if ids:
ids = len(ids)> 1 and len(ids)-1 or ids[0] # Use len(ids)-1 for taking the value of last id
host_name = self.browse(cr, uid,[ids],context=context)[0].host_name
return host_name
_defaults={
'service': 'webdav',
'collection' : _get_default_collection,
'calendar' : _get_default_calendar,
'device' : 'other',
}
'host_name':_get_default_host
}
def open_window(self, cr, uid, ids, context=None):
obj_model = self.pool.get('ir.model.data')
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','caldav_Browse')])
@ -278,6 +269,22 @@ class user_preference(osv.osv_memory):
'target': 'new',
'context': context,
}
def next_window(self, cr, uid, ids, context=None):
obj_model = self.pool.get('ir.model.data')
host_name = self.browse (cr,uid,ids)[0].host_name
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','user_prefernce_form')])
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])
context.update({'res_id': ids,'host':host_name})
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'user.preference',
'views': [(resource_id,'form')],
'type': 'ir.actions.act_window',
'target': 'new',
'context': context,
}
user_preference()

View File

@ -11,19 +11,39 @@
<group colspan="4" width="700" height="500">
<separator string="Browse caldav" colspan="4"/>
<field name="url" colspan="4" />
<separator string="Description" colspan="4"/>
<field name="description" colspan="4" nolabel="1"/>
<separator colspan="4"/>
<group col="4" colspan="4">
<label string="" colspan="2"/>
<button special="cancel" string="_Close" icon="gtk-close"/>
</group>
<group col="4" colspan="4">
<label string="" colspan="2"/>
<button special="cancel" string="_Close" icon="gtk-close"/>
</group>
</group>
</form>
</field>
</record>
<record id="host_prefernce_form" model="ir.ui.view">
<field name="name">host_preference</field>
<field name="model">user.preference</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Caldav's host name configuration">
<label string="Configure your openerp hostname. For example : " colspan="4"></label>
<newline/>
<label string="database.my.openerp.com or companyserver.com" colspan="4"/>
<newline/>
<separator colspan="4"/>
<field name="host_name" colspan="4" width="250" />
<separator colspan="4"/>
<group col="4" colspan="4">
<button special="cancel" string="_Cancel" icon="gtk-cancel"/>
<button name="next_window" string="Next" type="object" icon="gtk-go-forward"/>
</group>
</form>
</field>
</record>
<record id="user_prefernce_form" model="ir.ui.view">
<field name="name">user_preference</field>
<field name="model">user.preference</field>

View File

@ -129,6 +129,7 @@ Creates a dashboard for CRM that includes:
'test/test_crm_phonecall.yml',
'test/test_crm_recurrent_meeting.yml',
'test/test_crm_stage_changes.yml',
'test/test_crm_recurrent_meeting_case2.yml',
],
'installable': True,
'active': False,

View File

@ -44,8 +44,177 @@ AVAILABLE_PRIORITIES = [
('5', 'Lowest'),
]
class crm_case(object):
"""A simple python class to be used for common functions """
class crm_base(object):
"""
Base classe for crm object,
Object that inherit from this class should have
date_open
date_closed
user_id
partner_id
partner_address_id
as field to be compatible with this class
"""
def _get_default_partner_address(self, cr, uid, context=None):
"""Gives id of default address for current user
:param context: if portal in context is false return false anyway
"""
if context is None:
context = {}
if not context.get('portal'):
return False
return self.pool.get('res.users').browse(cr, uid, uid, context).address_id.id
def _get_default_partner(self, cr, uid, context=None):
"""Gives id of partner for current user
:param context: if portal in context is false return false anyway
"""
if context is None:
context = {}
if not context.get('portal', False):
return False
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
if not user.address_id:
return False
return user.address_id.partner_id.id
def _get_default_email(self, cr, uid, context=None):
"""Gives default email address for current user
:param context: if portal in context is false return false anyway
"""
if not context.get('portal', False):
return False
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
if not user.address_id:
return False
return user.address_id.email
def _get_default_user(self, cr, uid, context=None):
"""Gives current user id
:param context: if portal in context is false return false anyway
"""
if context and context.get('portal', False):
return False
return uid
def _get_section(self, cr, uid, context=None):
"""Gives section id for current User
"""
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
return user.context_section_id.id or False
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
"""This function returns value of partner email based on Partner Address
@param ids: List of case IDs
@param add: Id of Partner's address
@email: Partner's email ID
"""
if not add:
return {'value': {'email_from': False}}
address = self.pool.get('res.partner.address').browse(cr, uid, add)
if address.email:
return {'value': {'email_from': address.email, 'phone': address.phone}}
else:
return {'value': {'phone': address.phone}}
def onchange_partner_id(self, cr, uid, ids, part, email=False):
"""This function returns value of partner address based on partner
@param ids: List of case IDs
@param part: Partner's id
@email: Partner's email ID
"""
data={}
if part:
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
data = {'partner_address_id': addr['contact']}
data.update(self.onchange_partner_address_id(cr, uid, ids, addr['contact'])['value'])
return {'value': data}
def case_open(self, cr, uid, ids, *args):
"""Opens Case
@param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
for case in cases:
data = {'state': 'open', 'active': True}
if not case.user_id:
data['user_id'] = uid
self.write(cr, uid, case.id, data)
self._action(cr, uid, cases, 'open')
return True
def case_close(self, cr, uid, ids, *args):
"""Closes Case
@param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'done',
'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'),
})
#
# We use the cache of cases to keep the old case state
#
self._action(cr, uid, cases, 'done')
return True
def case_cancel(self, cr, uid, ids, *args):
"""Cancels Case
@param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'cancel',
'active': True})
self._action(cr, uid, cases, 'cancel')
for case in cases:
message = _("The case '%s' has been cancelled.") % (case.name,)
self.log(cr, uid, case.id, message)
return True
def case_pending(self, cr, uid, ids, *args):
"""Marks case as pending
@param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'pending', 'active': True})
self._action(cr, uid, cases, 'pending')
return True
def case_reset(self, cr, uid, ids, *args):
"""Resets case as draft
@param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'draft', 'active': True})
self._action(cr, uid, cases, 'draft')
return True
def _action(self, cr, uid, cases, state_to, scrit=None, context=None):
if context is None:
context = {}
context['state_to'] = state_to
rule_obj = self.pool.get('base.action.rule')
model_obj = self.pool.get('ir.model')
model_ids = model_obj.search(cr, uid, [('model','=',self._name)])
rule_ids = rule_obj.search(cr, uid, [('model_id','=',model_ids[0])])
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
class crm_case(crm_base):
"""
A simple python class to be used for common functions
Object that inherit from this class should inherit from mailgate.thread
And need a stage_id field
And object that inherit (orm inheritance) from a class the overwrite copy
"""
def _find_lost_stage(self, cr, uid, type, section_id):
return self._find_percent_stage(cr, uid, 0.0, type, section_id)
@ -105,35 +274,7 @@ class crm_case(object):
return {'value':{}}
return {'value':{'probability': stage.probability}}
def _get_default_partner_address(self, cr, uid, context=None):
"""Gives id of default address for current user
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context is None:
context = {}
if not context.get('portal', False):
return False
return self.pool.get('res.users').browse(cr, uid, uid, context).address_id.id
def _get_default_partner(self, cr, uid, context=None):
"""Gives id of partner for current user
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context is None:
context = {}
if not context.get('portal', False):
return False
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
if not user.address_id:
return False
return user.address_id.partner_id.id
def copy(self, cr, uid, id, default=None, context=None):
"""
@ -145,6 +286,7 @@ class crm_case(object):
@param default: Dictionary of default values for copy.
@param context: A standard dictionary for contextual values
"""
if context is None:
context = {}
if default is None:
@ -164,40 +306,9 @@ class crm_case(object):
})
return super(osv.osv, self).copy(cr, uid, id, default, context=context)
def _get_default_email(self, cr, uid, context=None):
"""Gives default email address for current user
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if not context.get('portal', False):
return False
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
if not user.address_id:
return False
return user.address_id.email
def _get_default_user(self, cr, uid, context=None):
"""Gives current user id
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.get('portal', False):
return False
return uid
def _get_section(self, cr, uid, context=None):
"""Gives section id for current User
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
return user.context_section_id.id or False
def _find_next_stage(self, cr, uid, stage_list, index, current_seq, stage_pool, context=None):
if index + 1 == len(stage_list):
@ -274,38 +385,9 @@ class crm_case(object):
@param context: A standard dictionary for contextual values"""
return self.stage_change(cr, uid, ids, context=context, order='sequence desc')
def onchange_partner_id(self, cr, uid, ids, part, email=False):
"""This function returns value of partner address based on partner
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of case IDs
@param part: Partner's id
@email: Partner's email ID
"""
data={}
if part:
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
data = {'partner_address_id': addr['contact']}
data.update(self.onchange_partner_address_id(cr, uid, ids, addr['contact'])['value'])
return {'value': data}
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
"""This function returns value of partner email based on Partner Address
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of case IDs
@param add: Id of Partner's address
@email: Partner's email ID
"""
if not add:
return {'value': {'email_from': False}}
address = self.pool.get('res.partner.address').browse(cr, uid, add)
if address.email:
return {'value': {'email_from': address.email, 'phone': address.phone}}
else:
return {'value': {'phone': address.phone}}
def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, email_from=False, message_id=False, attach=[], context=None):
mailgate_pool = self.pool.get('mailgate.thread')
@ -522,15 +604,7 @@ class crm_case(object):
cases = self.browse(cr, uid, ids2, context=context)
return self._action(cr, uid, cases, False, context=context)
def _action(self, cr, uid, cases, state_to, scrit=None, context=None):
if context is None:
context = {}
context['state_to'] = state_to
rule_obj = self.pool.get('base.action.rule')
model_obj = self.pool.get('ir.model')
model_ids = model_obj.search(cr, uid, [('model','=',self._name)])
rule_ids = rule_obj.search(cr, uid, [('model_id','=',model_ids[0])])
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
def format_body(self, body):
return self.pool.get('base.action.rule').format_body(body)

View File

@ -37,6 +37,7 @@ class crm_installer(osv.osv_memory):
'thunderbird': fields.boolean('Thunderbird', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
'outlook': fields.boolean('MS-Outlook', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
'wiki_sale_faq': fields.boolean('Sale FAQ', help="Helps you manage wiki pages for Frequently Asked Questions on Sales Application."),
'import_google': fields.boolean('Google Import', help="Imports contacts and events from your google account."),
}
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):

View File

@ -19,7 +19,7 @@
<attribute name="string">Enhance your core CRM Application with additional functionalities.</attribute>
</xpath>
<xpath expr='//separator[@string="vsep"]' position='attributes'>
<attribute name='rowspan'>13</attribute>
<attribute name='rowspan'>8</attribute>
<attribute name='string'></attribute>
</xpath>
<xpath expr="//button[@string='Install Modules']" position="attributes">
@ -37,6 +37,7 @@
<separator string="Synchronization" colspan="4" />
<field name="crm_caldav" />
<field name="fetchmail" />
<field name="import_google"/>
</group>
<group colspan="2" col="2">
<separator string="Plug-In" colspan="4" />

View File

@ -270,7 +270,6 @@ class crm_lead(crm_case, osv.osv):
data_obj = self.pool.get('ir.model.data')
value = {}
view_id = False
for case in self.browse(cr, uid, ids, context=context):
context.update({'active_id': case.id})

View File

@ -20,7 +20,7 @@
##############################################################################
from base_calendar import base_calendar
from crm import crm_case
from crm import crm_base, crm_case
from osv import fields, osv
from tools.translate import _
import logging
@ -36,13 +36,13 @@ class crm_phonecall(crm_case, osv.osv):
crm_phonecall()
class crm_meeting(crm_case, osv.osv):
class crm_meeting(crm_base, osv.osv):
""" CRM Meeting Cases """
_name = 'crm.meeting'
_description = "Meeting"
_order = "id desc"
_inherit = ['mailgate.thread',"calendar.event"]
_inherit = "calendar.event"
_columns = {
# From crm.case
'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),

View File

@ -51,7 +51,7 @@
<field name="res_model">crm.meeting</field>
<field name="view_mode">calendar,tree,form,gantt</field>
<field name="view_id" ref="crm_case_calendar_view_meet"/>
<field name="context">{"search_default_user_id":uid, 'search_default_section_id': section_id}</field>
<field name="context">{"search_default_user_id":uid, 'search_default_section_id': section_id, 'virtual_id' : True}</field>
<field name="search_view_id" ref="view_crm_case_meetings_filter"/>
<field name="help">The meeting calendar is shared between the sales teams and fully integrated with other applications such as the employee holidays or the business opportunities. You can also synchronize meetings with your mobile phone using the caldav interface.
</field>

View File

@ -45,8 +45,7 @@
widget="selection" />
<group colspan="2" col="4" attrs="{'readonly': ['|', ('recurrent_uid','!=',False), ('state','=','done')]}">
<field name="recurrency"/>
<field name="edit_all" attrs="{'invisible':[('recurrency','=', False)]}"
on_change="onchange_edit_all(rrule_type,edit_all)"/>
<field name="edit_all" attrs="{'invisible':[('recurrency','=', False)]}" />
</group>
</group>
<notebook colspan="4">

View File

@ -19,20 +19,19 @@
#
##############################################################################
from crm import crm_case
from crm import crm_base
from osv import fields, osv
from tools.translate import _
import crm
import time
from datetime import datetime
class crm_phonecall(crm_case, osv.osv):
class crm_phonecall(crm_base, osv.osv):
""" Phonecall Cases """
_name = "crm.phonecall"
_description = "Phonecall"
_order = "id desc"
_inherit = ['mailgate.thread']
_columns = {
# From crm.case
'id': fields.integer('ID'),
@ -96,6 +95,8 @@ class crm_phonecall(crm_case, osv.osv):
'active': 1,
}
# From crm.case
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):

View File

@ -57,7 +57,7 @@
!python {model: crm.meeting}: |
import time
from datetime import datetime, date, timedelta
ids = self.search(cr, uid, [('date', '>=', time.strftime('%Y-%m-%d 00:00:00')), ('date', '<=', (datetime.now()+timedelta(31)).strftime('%Y-%m-%d 00:00:00')), ('name', '=', 'Regarding Presentation')] )
ids = self.search(cr, uid, [('date', '>=', time.strftime('%Y-%m-%d 00:00:00')), ('date', '<=', (datetime.now()+timedelta(31)).strftime('%Y-%m-%d 00:00:00')), ('name', '=', 'Regarding Presentation')], context={'virtual_id': True})
assert len(ids) == 10
- |

View File

@ -0,0 +1,98 @@
-
In order to test recurrent meetings in OpenERP, I create meetings with different recurrency using different test cases.
-
I create a recurrent meeting with daily recurrency and fixed amount of time.
-
!record {model: crm.meeting, id: crm_meeting_testmeeting0}:
count: 5
date: '2011-04-13 11:04:00'
date_deadline: '2011-04-13 12:04:00'
day: 0.0
duration: 1.0
name: Test Meeting
recurrency: true
recurrent_uid: 0.0
rrule_type: daily
sequence: 0.0
-
I search for all the recurrent meetings.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_testmeeting0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 5, 'Recurrent daily meetings are not created !'
-
Now I create a weekly meeting till a particular end date.
-
!record {model: crm.meeting, id: crm_meeting_reviewcodewithprogrammer0}:
date: '2011-04-18 11:47:00'
date_deadline: '2011-04-18 12:47:00'
day: 0.0
duration: 1.0
end_date: '2011-04-30'
end_type: end_date
fr: true
mo: true
th: true
tu: true
we: true
name: Review code with programmer
recurrency: true
recurrent_uid: 0.0
rrule_type: weekly
sequence: 0.0
-
I search for all the recurrent weekly meetings.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_reviewcodewithprogrammer0')]),('date','>=','2011-03-13'), ('date_deadline', '<=', '2011-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 10, 'Recurrent weekly meetings are not created !'
-
I want to schedule a meeting every month for Sprint review.
-
!record {model: crm.meeting, id: crm_meeting_sprintreview0}:
count: 12
date: '2011-04-01 12:01:00'
date_deadline: '2011-04-01 13:01:00'
day: 1
duration: 1.0
name: Sprint Review
recurrency: true
recurrent_uid: 0.0
rrule_type: monthly
sequence: 0.0
-
I search for all the recurrent monthly meetings.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
assert len(meeting_ids) == 12, 'Recurrent monthly meetings are not created !'
-
I change name of my monthly Sprint Review meeting.
-
!python {model: crm.meeting}: |
from base_calendar import base_calendar
base_cal_id = base_calendar.real_id2base_calendar_id(ref('crm_meeting_sprintreview0'), '2011-09-01 13:01:00')
self.write(cr, uid, [base_cal_id], {'name': 'Sprint Review for google modules', 'edit_all': True})
-
I check whether all the records are edited or not.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('id', 'in', [ref('crm_meeting_sprintreview0')]),('date','>=','2011-03-01'), ('date_deadline', '<=', '2012-05-13')], context={'virtual_id': True})
meetings = self.browse(cr, uid, meeting_ids, context)
for meeting in meetings:
assert meeting.name == 'Sprint Review for google modules', 'Name not changed for id: %s' %meeting.id
-
I change description of my weekly meeting Review code with programmer.
-
!python {model: crm.meeting}: |
from base_calendar import base_calendar
base_cal_id = base_calendar.real_id2base_calendar_id(ref('crm_meeting_reviewcodewithprogrammer0'), '2011-04-25 12:47:00')
self.write(cr, uid, [base_cal_id], {'description': 'Review code of the module: sync_google_calendar.'})
-
I check whether the record is edited perfectly or not.
-
!python {model: crm.meeting}: |
meeting_ids = self.search(cr, uid, [('recurrent_uid', '=', ref('crm_meeting_reviewcodewithprogrammer0')), ('recurrent_id','=','2011-04-25 12:47:00')], context)
assert meeting_ids, 'Meeting is not edited !'

View File

@ -149,7 +149,6 @@ class crm_lead2partner(osv.osv_memory):
contact_obj = self.pool.get('res.partner.address')
partner_ids = []
partner_id = False
contact_id = False
rec_ids = context and context.get('active_ids', [])
for data in self.browse(cr, uid, ids, context=context):
@ -160,7 +159,7 @@ class crm_lead2partner(osv.osv_memory):
'user_id': lead.user_id.id,
'comment': lead.description,
})
contact_id = contact_obj.create(cr, uid, {
contact_obj.create(cr, uid, {
'partner_id': partner_id,
'name': lead.contact_name,
'phone': lead.phone,
@ -180,7 +179,6 @@ class crm_lead2partner(osv.osv_memory):
else:
if data.partner_id:
partner_id = data.partner_id.id
contact_id = partner_obj.address_get(cr, uid, [partner_id])['default']
self.assign_partner(cr, uid, lead.id, partner_id)
partner_ids.append(partner_id)
return partner_ids

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
@ -141,7 +140,7 @@ class crm_merge_opportunity(osv.osv_memory):
attach_ids = self.get_attachments(cr, uid, opp, context=context)
self.set_attachements_res_id(cr, uid, first_opportunity.id, attach_ids)
for history in opp.message_ids:
new_history = message_obj.write(cr, uid, history.id, {'res_id': first_opportunity.id, 'name' : _("From %s : %s") % (opp.name, history.name) }, context=context)
message_obj.write(cr, uid, history.id, {'res_id': first_opportunity.id, 'name' : _("From %s : %s") % (opp.name, history.name) }, context=context)
#Notification about loss of information
details = []
@ -184,8 +183,6 @@ class crm_merge_opportunity(osv.osv_memory):
# Get Opportunity views
result = models_data._get_id(
cr, uid, 'crm', 'view_crm_case_opportunities_filter')
opportunity_view_form = models_data._get_id(
cr, uid, 'crm', 'crm_case_form_view_oppor')
opportunity_view_tree = models_data._get_id(
@ -229,7 +226,7 @@ class crm_merge_opportunity(osv.osv_memory):
This function gets default values
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param uid: the current users ID for security checks,
@param fields: List of fields for default value
@param context: A standard dictionary for contextual values

View File

@ -21,6 +21,8 @@
from osv import osv, fields
from tools.translate import _
import pprint
pp = pprint.PrettyPrinter(indent=4)
import time
@ -121,23 +123,24 @@ class crm_opportunity2phonecall(osv.osv_memory):
for opp in opp_obj.browse(cr, uid, record_ids, context=context):
vals = {
'name' : opp.name,
'case_id' : opp.id ,
'case_id' : opp.id,
'user_id' : this.user_id and this.user_id.id or False,
'categ_id' : this.categ_id.id,
'description' : opp.description or False,
'date' : this.date,
'section_id' : this.section_id.id or opp.section_id.id or False,
'section_id' : this.section_id.id or False,
'partner_id': opp.partner_id and opp.partner_id.id or False,
'partner_address_id': opp.partner_address_id and opp.partner_address_id.id or False,
'partner_phone' : opp.phone or (opp.partner_address_id and opp.partner_address_id.phone or False),
'partner_mobile' : opp.partner_address_id and opp.partner_address_id.mobile or False,
'priority': opp.priority,
'opportunity_id': opp.id
'opportunity_id': opp.id,
'date_open': time.strftime('%Y-%m-%d %H:%M:%S')
}
new_case = phonecall_obj.create(cr, uid, vals, context=context)
if this.action == 'schedule':
phonecall_obj.case_open(cr, uid, [new_case])
elif this.action == 'log':
if this.action == 'log':
phonecall_obj.case_close(cr, uid, [new_case])
value = {
@ -149,7 +152,7 @@ class crm_opportunity2phonecall(osv.osv_memory):
'res_id' : new_case,
'views': [(id3, 'form'), (id2, 'tree'), (False, 'calendar')],
'type': 'ir.actions.act_window',
'search_view_id': res['res_id']
'search_view_id': res['res_id'],
}
return value

View File

@ -5,7 +5,7 @@
<field name="name">Caldav Browse</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">user.preference</field>
<field name="view_id" ref="caldav.user_prefernce_form"/>
<field name="view_id" ref="caldav.host_prefernce_form"/>
<field name="context">{'cal_name' : 'Meetings'}</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>

View File

@ -180,7 +180,7 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Helpdesk Support Tree"
colors="black:state=='open';blue:state=='pending';gray:state in ('cancel','close')">
colors="black:state=='open';blue:state=='pending';gray:state in ('cancel','done')">
<field name="name" string="Query" />
<field name="partner_id" string="Partner"/>
<field name="date" string="Date"/>

View File

@ -0,0 +1,695 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-06-28 09:47+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-29 04:43+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: crm_helpdesk
#: field:crm.helpdesk.report,delay_close:0
msgid "Delay to Close"
msgstr "Sulkemisen viive"
#. module: crm_helpdesk
#: field:crm.helpdesk.report,nbr:0
msgid "# of Cases"
msgstr "Tapausten määrä"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: view:crm.helpdesk.report:0
msgid "Group By..."
msgstr "Ryhmittely.."
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Today"
msgstr "Tänään"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "March"
msgstr "Maaliskuu"
#. module: crm_helpdesk
#: field:crm.helpdesk,company_id:0
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,company_id:0
msgid "Company"
msgstr "Yritys"
#. module: crm_helpdesk
#: field:crm.helpdesk,email_cc:0
msgid "Watchers Emails"
msgstr "Seuraajien Sähköpostit"
#. module: crm_helpdesk
#: selection:crm.helpdesk,priority:0
#: selection:crm.helpdesk.report,priority:0
msgid "Highest"
msgstr "Korkein"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,day:0
msgid "Day"
msgstr "Päivä"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Add Internal Note"
msgstr "Lisää sisäinen huomautus"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Notes"
msgstr "Huomautukset"
#. module: crm_helpdesk
#: field:crm.helpdesk,message_ids:0
msgid "Messages"
msgstr "Viestit"
#. module: crm_helpdesk
#: selection:crm.helpdesk,state:0
#: selection:crm.helpdesk.report,state:0
msgid "Cancelled"
msgstr "Peruttu"
#. module: crm_helpdesk
#: field:crm.helpdesk,partner_address_id:0
msgid "Partner Contact"
msgstr "Kumppanin Yhteystiedot"
#. module: crm_helpdesk
#: model:ir.actions.act_window,name:crm_helpdesk.action_report_crm_helpdesk
#: model:ir.ui.menu,name:crm_helpdesk.menu_report_crm_helpdesks_tree
msgid "Helpdesk Analysis"
msgstr "Helpdeskin analyysi"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,date_closed:0
msgid "Close Date"
msgstr "Sulkemispäivä"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid " Month "
msgstr " Kuukausi "
#. module: crm_helpdesk
#: field:crm.helpdesk,ref:0
msgid "Reference"
msgstr "Viite"
#. module: crm_helpdesk
#: field:crm.helpdesk,date_action_next:0
msgid "Next Action"
msgstr "Seuraava Toimenpide"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Helpdesk Supports"
msgstr "Helpdesk tukee"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Extra Info"
msgstr "Lisätiedot"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: field:crm.helpdesk,partner_id:0
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,partner_id:0
msgid "Partner"
msgstr "Kumppani"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Estimates"
msgstr "Arviot"
#. module: crm_helpdesk
#: field:crm.helpdesk.report,section_id:0
msgid "Section"
msgstr "Osa"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: field:crm.helpdesk,priority:0
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,priority:0
msgid "Priority"
msgstr "Prioriteetti"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Send New Email"
msgstr "Lähetä uusi sähköposti"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "Won"
msgstr "Voitettu"
#. module: crm_helpdesk
#: field:crm.helpdesk.report,delay_expected:0
msgid "Overpassed Deadline"
msgstr "Ylitetty aikaraja"
#. module: crm_helpdesk
#: model:ir.model,name:crm_helpdesk.model_crm_helpdesk_report
msgid "Helpdesk report after Sales Services"
msgstr "Helpdesk raportti jälkimarkkinointipalveluista"
#. module: crm_helpdesk
#: field:crm.helpdesk,email_from:0
msgid "Email"
msgstr "Sähköposti"
#. module: crm_helpdesk
#: field:crm.helpdesk,canal_id:0
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,canal_id:0
msgid "Channel"
msgstr "Kanava"
#. module: crm_helpdesk
#: selection:crm.helpdesk,priority:0
#: selection:crm.helpdesk.report,priority:0
msgid "Lowest"
msgstr "Alin"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "# Mails"
msgstr "Sähköpostien määrä"
#. module: crm_helpdesk
#: field:crm.helpdesk,create_date:0
#: field:crm.helpdesk.report,create_date:0
msgid "Creation Date"
msgstr "Luontipäivämäärä"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Reset to Draft"
msgstr "Palauta luonnokseksi"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: selection:crm.helpdesk,state:0
#: selection:crm.helpdesk.report,state:0
msgid "Pending"
msgstr "Odottava"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: field:crm.helpdesk,date_deadline:0
#: field:crm.helpdesk.report,date_deadline:0
msgid "Deadline"
msgstr "Määräaika"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "July"
msgstr "Heinäkuu"
#. module: crm_helpdesk
#: model:ir.actions.act_window,name:crm_helpdesk.crm_helpdesk_categ_action
msgid "Helpdesk Categories"
msgstr "Helpdesk kategoriat"
#. module: crm_helpdesk
#: model:ir.ui.menu,name:crm_helpdesk.menu_crm_case_helpdesk-act
msgid "Categories"
msgstr "Kategoriat"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "History Information"
msgstr "Historiatiedot"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Dates"
msgstr "Päivämäärät"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid " Month-1 "
msgstr " Kuukausi-1 "
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "#Helpdesk"
msgstr ""
#. module: crm_helpdesk
#: help:crm.helpdesk,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: crm_helpdesk
#: view:crm.helpdesk:0
msgid "References"
msgstr "Viitteet"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "September"
msgstr "Syyskuu"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Communication"
msgstr "Viestintä"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,month:0
msgid "Month"
msgstr "Kuukausi"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Escalate"
msgstr "Kohota"
#. module: crm_helpdesk
#: field:crm.helpdesk,write_date:0
msgid "Update Date"
msgstr "Päivityksen päiväys"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Query"
msgstr "Kysely"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "Salesman"
msgstr "Myyjä"
#. module: crm_helpdesk
#: field:crm.helpdesk,ref2:0
msgid "Reference 2"
msgstr "Viittaus 2"
#. module: crm_helpdesk
#: field:crm.helpdesk,categ_id:0
#: field:crm.helpdesk.report,categ_id:0
msgid "Category"
msgstr "Kategoria"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid " Year "
msgstr " Vuosi "
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Helpdesk Support"
msgstr "Helpdeskin tuki"
#. module: crm_helpdesk
#: field:crm.helpdesk,planned_cost:0
#: field:crm.helpdesk.report,planned_cost:0
msgid "Planned Costs"
msgstr "Suunnitellut kulut"
#. module: crm_helpdesk
#: model:ir.module.module,description:crm_helpdesk.module_meta_information
msgid "Helpdesk Management"
msgstr "Helpdeskin hallinta"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Search Helpdesk"
msgstr "Hae helpdeskiä"
#. module: crm_helpdesk
#: selection:crm.helpdesk,state:0
#: selection:crm.helpdesk.report,state:0
msgid "Draft"
msgstr "Luonnos"
#. module: crm_helpdesk
#: selection:crm.helpdesk,priority:0
#: selection:crm.helpdesk.report,priority:0
msgid "Low"
msgstr "Matala"
#. module: crm_helpdesk
#: field:crm.helpdesk,date_closed:0
#: selection:crm.helpdesk,state:0
#: selection:crm.helpdesk.report,state:0
msgid "Closed"
msgstr "Suljettu"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "7 Days"
msgstr "7 päivää"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Communication & History"
msgstr "Kommunikaatio ja historia"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "August"
msgstr "Elokuu"
#. module: crm_helpdesk
#: selection:crm.helpdesk,priority:0
#: selection:crm.helpdesk.report,priority:0
msgid "Normal"
msgstr "Tavallinen"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Global CC"
msgstr ""
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "June"
msgstr "Kesäkuu"
#. module: crm_helpdesk
#: field:crm.helpdesk,planned_revenue:0
msgid "Planned Revenue"
msgstr "Suunniteltu liikevaihto"
#. module: crm_helpdesk
#: field:crm.helpdesk.report,user_id:0
msgid "User"
msgstr "Käyttäjä"
#. module: crm_helpdesk
#: field:crm.helpdesk,active:0
msgid "Active"
msgstr "Aktiivinen"
#. module: crm_helpdesk
#: model:ir.module.module,shortdesc:crm_helpdesk.module_meta_information
msgid "CRM Helpdesk"
msgstr ""
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "Extended Filters..."
msgstr "Laajennetut Suotimet..."
#. module: crm_helpdesk
#: model:ir.actions.act_window,name:crm_helpdesk.crm_case_helpdesk_act111
msgid "Helpdesk Requests"
msgstr "Helpdesk pyynnöt"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "Search"
msgstr "Etsi"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "October"
msgstr "Lokakuu"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "January"
msgstr "Tammikuu"
#. module: crm_helpdesk
#: help:crm.helpdesk,email_from:0
msgid "These people will receive email."
msgstr "Nämä henkilöt vastaanottavat sähköpostin."
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: field:crm.helpdesk,date:0
msgid "Date"
msgstr "Päiväys"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "November"
msgstr "Marraskuu"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "History"
msgstr "Historia"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Attachments"
msgstr "Liitteet"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Misc"
msgstr "Sekalaiset"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: field:crm.helpdesk,state:0
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,state:0
msgid "State"
msgstr "Tila"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "General"
msgstr "Yleinen"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Send Reminder"
msgstr "Lähetä muistutus"
#. module: crm_helpdesk
#: help:crm.helpdesk,section_id:0
msgid ""
"Sales team to which Case belongs to. Define "
"Responsible user and Email account for mail gateway."
msgstr ""
"Myyntitiili mille tapaus kuuluu. Määrittele vastuuhenkilö ja "
"sähköpostiosoite sähköpostin välityspalvelimelle"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Done"
msgstr "Valmis"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "December"
msgstr "Joulukuu"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Cancel"
msgstr "Peruuta"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Close"
msgstr "Sulje"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: selection:crm.helpdesk,state:0
#: selection:crm.helpdesk.report,state:0
msgid "Open"
msgstr "Avaa"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Helpdesk Support Tree"
msgstr "Helpdeskin tukipuu"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Categorization"
msgstr "Kategorisointi"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
#: model:ir.model,name:crm_helpdesk.model_crm_helpdesk
#: model:ir.ui.menu,name:crm_helpdesk.menu_config_helpdesk
msgid "Helpdesk"
msgstr "Helpdesk"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: field:crm.helpdesk,user_id:0
msgid "Responsible"
msgstr "Vastuuhenkilö"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "Current"
msgstr "Nykyinen"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Details"
msgstr "Yksityiskohdat"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
msgid "Reply"
msgstr "Vastaa"
#. module: crm_helpdesk
#: field:crm.helpdesk,description:0
msgid "Description"
msgstr "Kuvaus"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "May"
msgstr "Toukokuu"
#. module: crm_helpdesk
#: field:crm.helpdesk,probability:0
msgid "Probability (%)"
msgstr "Todennäköisyys (%)"
#. module: crm_helpdesk
#: field:crm.helpdesk.report,email:0
msgid "# Emails"
msgstr "Sähköpostien määrä"
#. module: crm_helpdesk
#: model:ir.actions.act_window,help:crm_helpdesk.action_report_crm_helpdesk
msgid ""
"Have a general overview of all support requests by sorting them with "
"specific criteria such as the processing time, number of requests answered, "
"emails sent and costs."
msgstr ""
#. module: crm_helpdesk
#: help:crm.helpdesk,canal_id:0
msgid ""
"The channels represent the different communication modes available with the "
"customer."
msgstr ""
"Kanavat kuvaavat erilaisia kommunikaatiomuotoja joiden kautta voidaan "
"viestiä asiakkaan kanssa."
#. module: crm_helpdesk
#: help:crm.helpdesk,state:0
msgid ""
"The state is set to 'Draft', when a case is created. "
" \n"
"If the case is in progress the state is set to 'Open'. "
" \n"
"When the case is over, the state is set to 'Done'. "
" \n"
"If the case needs to be reviewed then the state is set to 'Pending'."
msgstr ""
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "February"
msgstr "Helmikuu"
#. module: crm_helpdesk
#: field:crm.helpdesk,name:0
msgid "Name"
msgstr "Nimi"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "Lost"
msgstr "Hävitty"
#. module: crm_helpdesk
#: model:ir.ui.menu,name:crm_helpdesk.menu_help_support_main
msgid "Helpdesk and Support"
msgstr "Helpdesk ja tuki"
#. module: crm_helpdesk
#: selection:crm.helpdesk.report,month:0
msgid "April"
msgstr "Huhtikuu"
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
msgid "My Case(s)"
msgstr "Omat tapaukset"
#. module: crm_helpdesk
#: field:crm.helpdesk,id:0
msgid "ID"
msgstr ""
#. module: crm_helpdesk
#: model:ir.actions.act_window,help:crm_helpdesk.crm_helpdesk_categ_action
msgid ""
"Create and manage helpdesk categories to better manage and classify your "
"support requests."
msgstr ""
#. module: crm_helpdesk
#: selection:crm.helpdesk,priority:0
#: selection:crm.helpdesk.report,priority:0
msgid "High"
msgstr "Korkea"
#. module: crm_helpdesk
#: view:crm.helpdesk:0
#: field:crm.helpdesk,section_id:0
#: view:crm.helpdesk.report:0
msgid "Sales Team"
msgstr "Myyntitiimi"
#. module: crm_helpdesk
#: field:crm.helpdesk,date_action_last:0
msgid "Last Action"
msgstr "Viimeisin tapahtuma"
#. module: crm_helpdesk
#: model:ir.actions.act_window,help:crm_helpdesk.crm_case_helpdesk_act111
msgid ""
"Helpdesk and Support allow you to track your interventions. Select a "
"customer, add notes and categorize interventions with partners if necessary. "
"You can also assign a priority level. Use the OpenERP Issues system to "
"manage your support activities. Issues can be connected to the email "
"gateway: new emails may create issues, each of them automatically gets the "
"history of the conversation with the customer."
msgstr ""
#. module: crm_helpdesk
#: view:crm.helpdesk.report:0
#: field:crm.helpdesk.report,name:0
msgid "Year"
msgstr "Vuosi"
#. module: crm_helpdesk
#: field:crm.helpdesk,duration:0
msgid "Duration"
msgstr "Kesto"

View File

@ -20,11 +20,9 @@
#
##############################################################################
import base64
import time
import re
from osv import osv, fields
import tools
from tools.translate import _
class crm_lead_forward_to_partner(osv.osv_memory):

View File

@ -68,7 +68,7 @@ class abstracted_fs(object):
db, cr = None, None
try:
try:
db = pooler.get_db_only(db_name)
db = pooler.get_db(db_name)
cr = db.cursor()
cr.execute("SELECT 1 FROM pg_class WHERE relkind = 'r' AND relname = 'ir_module_module'")
if not cr.fetchone():

View File

@ -0,0 +1,138 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-06-27 06:20+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-28 04:40+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: document_ftp
#: model:ir.model,name:document_ftp.model_document_ftp_configuration
msgid "Auto Directory Configuration"
msgstr "Automaattinen hakemistojen konfigurointi"
#. module: document_ftp
#: view:document.ftp.configuration:0
msgid ""
"Indicate the network address on which your OpenERP server should be "
"reachable for end-users. This depends on your network topology and "
"configuration, and will only affect the links displayed to the users. The "
"format is HOST:PORT and the default host (localhost) is only suitable for "
"access from the server machine itself.."
msgstr ""
#. module: document_ftp
#: field:document.ftp.configuration,progress:0
msgid "Configuration Progress"
msgstr "Konfiguraation eteneminen"
#. module: document_ftp
#: model:ir.actions.url,name:document_ftp.action_document_browse
msgid "Browse Files"
msgstr "Selaa tiedostoja"
#. module: document_ftp
#: field:document.ftp.configuration,config_logo:0
msgid "Image"
msgstr "Kuva"
#. module: document_ftp
#: field:document.ftp.configuration,host:0
msgid "Address"
msgstr "Osoite"
#. module: document_ftp
#: field:document.ftp.browse,url:0
msgid "FTP Server"
msgstr "FTP-palvelin"
#. module: document_ftp
#: model:ir.actions.act_window,name:document_ftp.action_config_auto_directory
msgid "FTP Server Configuration"
msgstr "FTP palvelimen konfiguraatio"
#. module: document_ftp
#: model:ir.module.module,description:document_ftp.module_meta_information
msgid ""
"This is a support FTP Interface with document management system.\n"
" With this module you would not only be able to access documents through "
"OpenERP\n"
" but you would also be able to connect with them through the file system "
"using the\n"
" FTP client.\n"
msgstr ""
#. module: document_ftp
#: view:document.ftp.browse:0
msgid "_Browse"
msgstr "Selaa"
#. module: document_ftp
#: help:document.ftp.configuration,host:0
msgid ""
"Server address or IP and port to which users should connect to for DMS access"
msgstr ""
"Palvelimen osoite tai IP ja portti mihin käyttäjien tulisi ottaa yhteyttä "
"DMS:n käyttöä varten"
#. module: document_ftp
#: model:ir.ui.menu,name:document_ftp.menu_document_browse
msgid "Shared Repository (FTP)"
msgstr "Jaettu tietolähde (FTP)"
#. module: document_ftp
#: view:document.ftp.browse:0
msgid "_Cancel"
msgstr "_Peruuta"
#. module: document_ftp
#: view:document.ftp.configuration:0
msgid "Configure FTP Server"
msgstr "Konfiguroi FTP palvelin"
#. module: document_ftp
#: model:ir.module.module,shortdesc:document_ftp.module_meta_information
msgid "Integrated FTP Server with Document Management System"
msgstr ""
"Integroitu FTP palvelin dokumenttienhallintajärjestelmällä varustettuna"
#. module: document_ftp
#: view:document.ftp.configuration:0
msgid "title"
msgstr "otsikko"
#. module: document_ftp
#: model:ir.model,name:document_ftp.model_document_ftp_browse
msgid "Document FTP Browse"
msgstr "Dokumenttien FTP selailu"
#. module: document_ftp
#: view:document.ftp.configuration:0
msgid "Knowledge Application Configuration"
msgstr "Tiedonhallintaohjelmiston konfiguraatio"
#. module: document_ftp
#: model:ir.actions.act_window,name:document_ftp.action_ftp_browse
msgid "Document Browse"
msgstr "Dokumenttien selailu"
#. module: document_ftp
#: view:document.ftp.browse:0
msgid "Browse Document"
msgstr "Selaa dokumenttia"
#. module: document_ftp
#: view:document.ftp.configuration:0
msgid "res_config_contents"
msgstr ""

View File

@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-06-20 20:45+0000\n"
"PO-Revision-Date: 2011-06-23 19:32+0000\n"
"Last-Translator: Ayhan KIZILTAN <Unknown>\n"
"Language-Team: Turkish <tr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-21 04:37+0000\n"
"X-Launchpad-Export-Date: 2011-06-24 05:00+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: document_ftp
@ -31,6 +31,10 @@ msgid ""
"format is HOST:PORT and the default host (localhost) is only suitable for "
"access from the server machine itself.."
msgstr ""
"OpenERP sunucusunda son kullanıcıların erişebileceği ağ adresini belirtir. "
"Bu, ağ yapınıza ve yapılandırmasına bağlıdır ve yalnızca kullanıcılara "
"gösterilen ağları etkiler. Formatı HOST:PORT şeklindedir ve varsayılan "
"sunucu (localhost) yalnızca sunucu cihazından erişim için uygundur."
#. module: document_ftp
#: field:document.ftp.configuration,progress:0

View File

@ -361,7 +361,7 @@ class openerp_dav_handler(dav_interface):
for db_name in result:
cr = None
try:
db = pooler.get_db_only(db_name)
db = pooler.get_db(db_name)
cr = db.cursor()
cr.execute("SELECT id FROM ir_module_module WHERE name = 'document' AND state='installed' ")
res=cr.fetchone()

View File

@ -8,30 +8,30 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-01-13 23:13+0000\n"
"Last-Translator: Arif Aydogmus <arifaydogmus@gmail.com>\n"
"PO-Revision-Date: 2011-06-27 18:17+0000\n"
"Last-Translator: Ayhan KIZILTAN <Unknown>\n"
"Language-Team: Turkish <tr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-04-29 05:46+0000\n"
"X-Generator: Launchpad (build 12758)\n"
"X-Launchpad-Export-Date: 2011-06-28 04:40+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: email_template
#: help:email_template.account,auto_delete:0
msgid "Permanently delete emails after sending"
msgstr "Gönderdikten sonra e-postayı sil."
msgstr "Gönderdikten sonra epostaları kalıcı olarak sil."
#. module: email_template
#: view:email_template.account:0
msgid "Email Account Configuration"
msgstr "E-posta Hesapları Yapılandırma"
msgstr "Eposta Hesapları Yapılandırma"
#. module: email_template
#: code:addons/email_template/wizard/email_template_send_wizard.py:195
#, python-format
msgid "Emails for multiple items saved in outbox."
msgstr "Çoklu öğeler için e-postalar giden kutusuna kaydedildi."
msgstr "Çoklu öğeler için epostalar giden kutusuna kaydedildi."
#. module: email_template
#: code:addons/email_template/wizard/email_template_send_wizard.py:59
@ -54,22 +54,22 @@ msgstr "Kişisel E-postalar"
#. module: email_template
#: field:email.template,file_name:0
msgid "Report Filename"
msgstr "Rapor dosyasının adı"
msgstr "Rapor Dosyasının adı"
#. module: email_template
#: view:email.template:0
msgid "Email Content "
msgstr "E-posta içeriği "
msgstr "Eposta İçeriği "
#. module: email_template
#: view:email_template.send.wizard:0
msgid "Send mail Wizard"
msgstr "E-Posta Gönderim Sihirbazı"
msgstr "Posta Gönderim Sihirbazı"
#. module: email_template
#: selection:email_template.mailbox,mail_type:0
msgid "Plain Text & HTML with no attachments"
msgstr "Salt Metin ve Eklentisiz HTML"
msgstr "Düz Metin ve Eklentisiz HTML"
#. module: email_template
#: help:email.template,model_object_field:0
@ -81,7 +81,7 @@ msgid ""
msgstr ""
"Kullanmak istediğiniz modelden alanı seçiniz.\n"
"Eğer ilintili bir alansa içiçe değerleri aşağıdaki kutudan seçebilirsiniz.\n"
"(Not: Eğer herhangi bir değer yoksa mutlaka doğru modeli seçiniz)"
"(Not: Eğer herhangi bir değer yoksa doğru modeli seçtiğinizden emin olun)"
#. module: email_template
#: field:email_template.preview,body_html:0
@ -89,13 +89,13 @@ msgstr ""
#: field:email_template.send.wizard,body_html:0
#: field:email_template.send.wizard,body_text:0
msgid "Body"
msgstr "İleti metni"
msgstr "Gövde"
#. module: email_template
#: code:addons/email_template/email_template.py:304
#, python-format
msgid "Deletion of Record failed"
msgstr "Kayıt silinemedi"
msgstr "Kayıt Silinemedi"
#. module: email_template
#: help:email_template.account,company:0
@ -103,8 +103,8 @@ msgid ""
"Select if this mail account does not belong to specific user but to the "
"organization as a whole. eg: info@companydomain.com"
msgstr ""
"Bu e-posta hesabı belirli bir kullanıcıya ait değilde birçok kişinin üyesi "
"olduğu bir grup hesabı ise seçin. Ör: info@companydomain.com"
"Bu posta hesabı belirli bir kullanıcıya ait değilde bir kurumun geneline "
"aitse seçin. Ör: info@companydomain.com"
#. module: email_template
#: view:email_template.send.wizard:0
@ -114,19 +114,19 @@ msgstr "Şimdi gönder"
#. module: email_template
#: selection:email_template.mailbox,state:0
msgid "Not Applicable"
msgstr "Uygun Değil"
msgstr "Uygulanabilir Değil"
#. module: email_template
#: view:email_template.account:0
#: model:ir.ui.menu,name:email_template.menu_email_account_all_tools
#: model:ir.ui.menu,name:email_template.menu_email_template_account_all
msgid "Email Accounts"
msgstr "E-posta Hesapları"
msgstr "Eposta Hesapları"
#. module: email_template
#: view:email_template.send.wizard:0
msgid "Send all mails"
msgstr "Tüm E-Postaları gönder"
msgstr "Tüm postaları gönder"
#. module: email_template
#: help:email_template.account,smtpuname:0
@ -134,13 +134,13 @@ msgid ""
"Specify the username if your SMTP server requires authentication, otherwise "
"leave it empty."
msgstr ""
"SMTP sunucunuz kimlik doğrulama gerektiriyorsa kullanıcı adınızı yazınız "
"SMTP sunucunuz kimlik doğrulama gerektiriyorsa kullanıcı adınızı yazınız, "
"gerektirmiyorsa boş bırakınız."
#. module: email_template
#: field:email_template.mailbox,server_ref:0
msgid "Server Reference of mail"
msgstr "E-Posta Sunucu Referansı"
msgstr "Posta Sunucu Referansı"
#. module: email_template
#: view:email_template.account:0
@ -154,8 +154,8 @@ msgid ""
"Carbon Copy address(es), comma-separated. Placeholders can be used here. "
"e.g. ${object.email_cc}"
msgstr ""
"Kopya alıcıları virgülle ayrılır. Yertutucular kullanılabilir. Ör: "
"${object.email_cc}"
"Karbon Kopya adres(ler) virgülle ayrılı. Yertutucular burada kullanılabilir. "
"Örn. ${object.email_cc}"
#. module: email_template
#: view:email.template:0
@ -183,13 +183,13 @@ msgstr ""
#. module: email_template
#: field:email.template,from_account:0
msgid "Email Account"
msgstr "E-Posta Hesabı"
msgstr "Eposta Hesabı"
#. module: email_template
#: code:addons/email_template/wizard/email_template_send_wizard.py:201
#, python-format
msgid "Email sending failed for one or more objects."
msgstr "Bir ya da daha çok nesne için e-posta gönderimi başarısız."
msgstr "Bir ya da daha çok nesne için eposta gönderimi başarısız."
#. module: email_template
#: view:email_template.send.wizard:0
@ -197,7 +197,7 @@ msgid ""
"Add here all attachments of the current document you want to include in the "
"Email."
msgstr ""
"E-postada yer almasını istediğiniz dökümana ait tüm ekleri buraya ekleyiniz."
"Epostada yer almasını istediğiniz dökümana ait tüm ekleri buraya ekleyiniz."
#. module: email_template
#: help:email.template,lang:0
@ -205,7 +205,7 @@ msgid ""
"The default language for the email. Placeholders can be used here. eg. "
"${object.partner_id.lang}"
msgstr ""
"E-Posta için öntanımlı dil. Burada yer tutucular kullanılabilir. Örneğin, "
"Eposta için varsayılan dil. Burada yertutucular kullanılabilir. Örneğin, "
"${object.partner_id.lang}"
#. module: email_template
@ -214,7 +214,7 @@ msgid ""
"When you choose relationship fields this field will specify the sub value "
"you can use."
msgstr ""
"İlintili alanlar seçtiğinizde bu alan kullanabileceğiniz alt değeri "
"İlişkili alanları seçtiğinizde bu alan kullanabileceğiniz alt değeri "
"belirtecektir"
#. module: email_template
@ -951,7 +951,7 @@ msgid "Close"
msgstr "Kapat"
#. module: email_template
#: code:addons/email_template/email_template_mailbox.py:49
#: code:addons/email_template/email_template_mailbox.py:48
#, python-format
msgid "Error sending mail: %s"
msgstr "İleti gönderiminde hata: %s"
@ -1043,7 +1043,7 @@ msgid "Email Mailbox"
msgstr "E-Posta Kutusu"
#. module: email_template
#: code:addons/email_template/email_template_mailbox.py:116
#: code:addons/email_template/email_template_mailbox.py:104
#, python-format
msgid ""
"Sending of Mail %s failed. Probable Reason:Could not login to server\n"
@ -1158,7 +1158,9 @@ msgstr ""
#. module: email_template
#: view:email_template.mailbox:0
#: model:ir.actions.act_window,name:email_template.action_email_template_mailbox
#: model:ir.ui.menu,name:email_template.menu_email_template_mails_tools
#: model:ir.ui.menu,name:email_template.menu_email_template_personal_mails
msgid "Emails"
msgstr "E-postalar"
@ -1213,6 +1215,10 @@ msgid ""
"emails.\n"
" "
msgstr ""
"\n"
" Eposta Şablonu, temel olarak epostaların gönderimi için Power Epostanın "
"özüdür.\n"
" "
#. module: email_template
#: view:email_template.send.wizard:0

View File

@ -0,0 +1,122 @@
# Finnish translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-06-29 07:23+0000\n"
"Last-Translator: Jussi Mikkola <Unknown>\n"
"Language-Team: Finnish <fi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-30 04:34+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: event_project
#: model:ir.model,name:event_project.model_event_project
msgid "Event Project"
msgstr "Tapahtumaprojekti"
#. module: event_project
#: field:event.project,date:0
msgid "Date End"
msgstr "Loppupäiväys"
#. module: event_project
#: view:event.project:0
msgid "Ok"
msgstr "OK"
#. module: event_project
#: model:ir.module.module,description:event_project.module_meta_information
msgid ""
"Organization and management of events.\n"
"\n"
" This module allows you to create retro planning for managing your "
"events.\n"
msgstr ""
#. module: event_project
#: help:event.project,project_id:0
msgid ""
"This is Template Project. Project of event is a duplicate of this Template. "
"After click on 'Create Retro-planning', New Project will be duplicated from "
"this template project."
msgstr ""
#. module: event_project
#: view:event.project:0
#: model:ir.actions.act_window,name:event_project.action_event_project
msgid "Retro-Planning"
msgstr "Retro suunnittelu"
#. module: event_project
#: constraint:event.event:0
msgid "Error ! Closing Date cannot be set before Beginning Date."
msgstr "Virhe ! Päättymispäivä ei voi olla aikaisempi kuin alkupäivä"
#. module: event_project
#: field:event.event,project_id:0
msgid "Project"
msgstr "Projekti"
#. module: event_project
#: view:event.event:0
#: model:ir.actions.act_window,name:event_project.act_event_task
msgid "Tasks"
msgstr "Tehtävät"
#. module: event_project
#: view:event.event:0
msgid "All tasks"
msgstr "Kaikki tehtävät"
#. module: event_project
#: model:ir.module.module,shortdesc:event_project.module_meta_information
msgid "Event Project - Create Retro-Planning to manage your Events"
msgstr "Tapahtumaprojekti - luo retro suunitelma tapahtumien hallintaan"
#. module: event_project
#: field:event.project,project_id:0
msgid "Template of Project"
msgstr "Projektin mallipohja"
#. module: event_project
#: constraint:event.event:0
msgid "Error ! You cannot create recursive event."
msgstr "Virhe ! et voi luoda rekursiivisia tapahtumia."
#. module: event_project
#: field:event.event,task_ids:0
msgid "Project tasks"
msgstr "Projektin tehtävät"
#. module: event_project
#: view:event.project:0
msgid "Close"
msgstr "Sulje"
#. module: event_project
#: field:event.project,date_start:0
msgid "Date Start"
msgstr "Aloituspäivämäärä"
#. module: event_project
#: view:event.event:0
msgid "Create Retro-Planning"
msgstr "Luo retrosuunnitelma"
#. module: event_project
#: model:ir.model,name:event_project.model_event_event
msgid "Event"
msgstr "Tapahtuma"
#. module: event_project
#: view:event.event:0
msgid "Tasks management"
msgstr "Tehtävienhallinta"

View File

@ -116,7 +116,7 @@ class email_server(osv.osv):
if context is None:
context = {}
for server in self.browse(cr, uid, ids, context=context):
logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail start checking for new emails on %s' % (server.name))
logger.notifyChannel(server.type, netsvc.LOG_INFO, 'fetchmail start checking for new emails on %s' % (server.name))
context.update({'server_id': server.id, 'server_type': server.type})
try:
if server.type == 'imap':
@ -199,7 +199,7 @@ class email_server(osv.osv):
pop_server.quit()
logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail fetch %s email(s) from %s' % (numMsgs, server.name))
logger.notifyChannel(server.type, netsvc.LOG_INFO, 'fetchmail fetch %s email(s) from %s' % (numMsgs, server.name))
except Exception, e:
logger.notifyChannel(server.type, netsvc.LOG_WARNING, '%s' % (tools.ustr(e)))

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import google_base_account
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Google user',
'version': '1.0',
'category': 'Generic Modules/Others',
'description': """The module adds google user in res user""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['base'],
'init_xml': [],
'update_xml': [
'google_base_account_view.xml',
'wizard/google_login_view.xml',
],
'demo_xml': [],
'installable': True,
'active': False,
'certificate': '',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields,osv
class res_users(osv.osv):
_inherit = "res.users"
_columns = {
'gmail_user': fields.char('Username', size=64,),
'gmail_password': fields.char('Password', size=64),
}
res_users()
# vim:expandtab:smartindent:toabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="view_users_gogole_form" model="ir.ui.view">
<field name="name">res.users.google.form1</field>
<field name="model">res.users</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook[last()]" position="inside">
<page string=" Synchronization ">
<separator string="Google Account" colspan="4" />
<field name="gmail_user"/>
<field name="gmail_password" password="True"/>
</page>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import google_login
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields,osv
from tools.translate import _
try:
import gdata.contacts.service
import gdata.contacts.client
import gdata.calendar.service
except ImportError:
raise osv.except_osv(_('Google Contacts Import Error!'), _('Please install gdata-python-client from http://code.google.com/p/gdata-python-client/downloads/list'))
class google_login(osv.osv_memory):
_description ='Google Contact'
_name = 'google.login'
_columns = {
'user': fields.char('Google Username', size=64, required=True),
'password': fields.char('Google Password', size=64),
}
def google_login(self, user, password, type='', context=None):
if type == 'group':
gd_client = gdata.contacts.client.ContactsClient(source='OpenERP')
if type == 'contact' :
gd_client = gdata.contacts.service.ContactsService()
if type == 'calendar':
gd_client = gdata.calendar.service.CalendarService()
else:
gd_client = gdata.contacts.service.ContactsService()
try:
gd_client.ClientLogin(user, password,gd_client.source)
except Exception:
return False
return gd_client
def default_get(self, cr, uid, fields, context=None):
res = super(google_login, self).default_get(cr, uid, fields, context=context)
user_obj = self.pool.get('res.users').browse(cr, uid, uid)
if 'user' in fields:
res.update({'user': user_obj.gmail_user})
if 'password' in fields:
res.update({'password': user_obj.gmail_password})
return res
def login(self, cr, uid, ids, context=None):
data = self.read(cr, uid, ids)[0]
user = data['user']
password = data['password']
if self.google_login(user, password):
res = {
'gmail_user': user,
'gmail_password': password
}
self.pool.get('res.users').write(cr, uid, uid, res, context=context)
else:
raise osv.except_osv(_('Error'), _("Authentication fail check the user and password !"))
return self._get_next_action(cr, uid, context=context)
def _get_next_action(self, cr, uid, context=None):
return {'type': 'ir.actions.act_window_close'}
google_login()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_google_login_form">
<field name="name">google.login.form</field>
<field name="model">google.login</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Google login" >
<group colspan="4" col="4" width="300">
<field name="user" />
<newline/>
<label string="ex: user@gmail.com" align="1.0" colspan="2"/>
<newline/>
<field name="password" password="True"/>
</group>
<separator string="" colspan="4"/>
<group colspan="4" col="4">
<group colspan="2"/>
<group colspan="2">
<button special="cancel" string="_Cancel" icon="gtk-cancel"/>
<button name="login" string="_Login" type="object" icon="terp-check"/>
</group>
</group>
</form>
</field>
</record>
<!--
Login Action
-->
<record model="ir.actions.act_window" id="act_google_login_form">
<field name="name">Google Login</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">google.login</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="view_id" ref="view_google_login_form" />
</record>
</data>
</openerp>

View File

@ -7,14 +7,14 @@ 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-01-26 12:19+0000\n"
"Last-Translator: Vinicius Dittgen - Proge.com.br <vinicius@gnucode.com>\n"
"PO-Revision-Date: 2011-06-22 23:24+0000\n"
"Last-Translator: Gustavo T <Unknown>\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: 2011-04-29 05:31+0000\n"
"X-Generator: Launchpad (build 12758)\n"
"X-Launchpad-Export-Date: 2011-06-24 04:59+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: hr
#: model:process.node,name:hr.process_node_openerpuser0
@ -562,6 +562,13 @@ msgid ""
" * HR Jobs\n"
" "
msgstr ""
"\n"
" Módulo de gestão de recursos humanos. Você pode gerenciar:\n"
" * Funcionários e hierarquias: você pode definir seu funcionário com um "
"usuário e exibir hierarquias\n"
" * Departamentos de RH\n"
" * Cargos de RH\n"
" "
#. module: hr
#: model:process.transition,note:hr.process_transition_contactofemployee0
@ -569,6 +576,8 @@ msgid ""
"In the Employee form, there are different kind of information like Contact "
"information."
msgstr ""
"No formulário de empregado, existem diferentes tipos de informação, como "
"contato, por exemplo."
#. module: hr
#: help:hr.job,expected_employees:0

View File

@ -7,14 +7,14 @@ 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: 2010-10-30 12:04+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"PO-Revision-Date: 2011-06-23 19:33+0000\n"
"Last-Translator: Ayhan KIZILTAN <Unknown>\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: 2011-04-29 05:31+0000\n"
"X-Generator: Launchpad (build 12758)\n"
"X-Launchpad-Export-Date: 2011-06-24 04:59+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: hr
#: model:process.node,name:hr.process_node_openerpuser0
@ -25,17 +25,17 @@ msgstr "Openerp kullanıcısı"
#: view:hr.job:0
#: field:hr.job,requirements:0
msgid "Requirements"
msgstr ""
msgstr "Gereksinimler"
#. module: hr
#: constraint:hr.department:0
msgid "Error! You can not create recursive departments."
msgstr ""
msgstr "Hata! Yinelenen bölümler oluşturamazsınız."
#. module: hr
#: model:process.transition,name:hr.process_transition_contactofemployee0
msgid "Link the employee to information"
msgstr ""
msgstr "Personeli danışmaya bağla"
#. module: hr
#: field:hr.employee,sinid:0
@ -55,7 +55,7 @@ msgstr "İnsan Kaynakları"
#: view:hr.employee:0
#: view:hr.job:0
msgid "Group By..."
msgstr ""
msgstr "Gruplandır..."
#. module: hr
#: model:ir.actions.act_window,help:hr.action_hr_job
@ -66,6 +66,11 @@ msgid ""
"will be used in the recruitment process to evaluate the applicants for this "
"job position."
msgstr ""
"İş Durumları, işlerin ve gereksinimlerinin tanımlanması için kullanılır. Her "
"iş durumunda kullanılan personel sayısını ve gelecekte kaç personel "
"beklediğinizin kayıtlarını tutabilirsiniz. Bu iş durumu için başvuranların "
"değerlendirilmesi için seçme işleminde kullanmak üzere bir anket de "
"ekleyebilirsiniz."
#. module: hr
#: view:hr.employee:0
@ -79,27 +84,27 @@ msgstr "Bölüm"
#. module: hr
#: help:hr.installer,hr_attendance:0
msgid "Simplifies the management of employee's attendances."
msgstr ""
msgstr "Personelin devam durumunu yönetmeyi basitleştirir."
#. module: hr
#: view:hr.job:0
msgid "Mark as Old"
msgstr ""
msgstr "Eski olarak İşaretle"
#. module: hr
#: view:hr.job:0
msgid "Jobs"
msgstr ""
msgstr "İşler"
#. module: hr
#: view:hr.job:0
msgid "In Recruitment"
msgstr ""
msgstr "Seçme İşleminde"
#. module: hr
#: view:hr.installer:0
msgid "title"
msgstr ""
msgstr "unvan"
#. module: hr
#: field:hr.department,company_id:0
@ -112,22 +117,22 @@ msgstr "Firma"
#. module: hr
#: field:hr.job,no_of_recruitment:0
msgid "Expected in Recruitment"
msgstr ""
msgstr "Seçim için Bekleniyor"
#. module: hr
#: model:ir.ui.menu,name:hr.menu_open_view_attendance_reason_config
msgid "Holidays"
msgstr ""
msgstr "Tatiller"
#. module: hr
#: help:hr.installer,hr_holidays:0
msgid "Tracks employee leaves, allocation requests and planning."
msgstr ""
msgstr "Personel izinlerini, tahsis istekleri ve planlamalrı izler"
#. module: hr
#: model:ir.model,name:hr.model_hr_employee_marital_status
msgid "Employee Marital Status"
msgstr ""
msgstr "Personel Medeni Durumu"
#. module: hr
#: help:hr.employee,partner_id:0
@ -135,42 +140,44 @@ msgid ""
"Partner that is related to the current employee. Accounting transaction will "
"be written on this partner belongs to employee."
msgstr ""
"Geçerli personelle ilgili Paydaştır. Muhasebe işlemi personelle ilişkili bu "
"paydaşa yazılacaktır."
#. module: hr
#: model:process.transition,name:hr.process_transition_employeeuser0
msgid "Link a user to an employee"
msgstr ""
msgstr "Kullanıcıyı bir personele bağla"
#. module: hr
#: field:hr.installer,hr_contract:0
msgid "Employee's Contracts"
msgstr ""
msgstr "Personel Sözleşmeleri"
#. module: hr
#: help:hr.installer,hr_payroll:0
msgid "Generic Payroll system."
msgstr ""
msgstr "Genel Bordro Sistemi"
#. module: hr
#: view:hr.employee:0
msgid "My Departments Employee"
msgstr ""
msgstr "Bölümümdeki Personel"
#. module: hr
#: model:hr.employee.marital.status,name:hr.hr_employee_marital_status_married
msgid "Married"
msgstr ""
msgstr "Evli"
#. module: hr
#: constraint:hr.employee:0
msgid ""
"Error ! You cannot select a department for which the employee is the manager."
msgstr ""
msgstr "Hata ! Personelin müdür olduğu bir bölümü seçemezsiniz."
#. module: hr
#: help:hr.employee,passport_id:0
msgid "Employee Passport Information"
msgstr ""
msgstr "Personel Pasaport Bilgisi"
#. module: hr
#: model:ir.actions.act_window,help:hr.open_module_tree_department
@ -179,16 +186,19 @@ msgid ""
"to employees by departments: expenses and timesheet validation, leaves "
"management, recruitments, etc."
msgstr ""
"Firmanızın Bölüm Yapısı, bölümlere göre personelle ilgili belgelerin "
"yönetilmesinde kullanılır: giderler, zaman çizelgesi onayları, izin "
"yönetimi, seçme işlemlemleri, v.b"
#. module: hr
#: view:hr.employee:0
msgid "Position"
msgstr ""
msgstr "Durum"
#. module: hr
#: model:ir.actions.act_window,name:hr.action2
msgid "Employee Hierarchy"
msgstr "Personel Hiyerarşisi"
msgstr "Personel Sıradüzeni"
#. module: hr
#: model:process.transition,note:hr.process_transition_employeeuser0
@ -196,43 +206,47 @@ msgid ""
"The Related user field on the Employee form allows to link the OpenERP user "
"(and her rights) to the employee."
msgstr ""
"Personel formundaki İlişkili Kullanıcı alanı OpenERP kullanıcısının "
"personele bağlanmasını sağlar."
#. module: hr
#: view:hr.job:0
#: selection:hr.job,state:0
msgid "In Recruitement"
msgstr ""
msgstr "Seçim durumunda"
#. module: hr
#: field:hr.employee,identification_id:0
msgid "Identification No"
msgstr ""
msgstr "Kimlik No"
#. module: hr
#: field:hr.job,no_of_employee:0
msgid "No of Employee"
msgstr ""
msgstr "Personel No"
#. module: hr
#: selection:hr.employee,gender:0
msgid "Female"
msgstr "Bayan"
msgstr "Kadın"
#. module: hr
#: help:hr.installer,hr_timesheet_sheet:0
msgid ""
"Tracks and helps employees encode and validate timesheets and attendances."
msgstr ""
"Personelin zaman çizelgeleri ve devamlılıkları onaylamasını ve "
"şifrelendirmesini sağlar."
#. module: hr
#: field:hr.installer,hr_evaluation:0
msgid "Periodic Evaluations"
msgstr ""
msgstr "Süreli Değerlendirmeler"
#. module: hr
#: field:hr.installer,hr_timesheet_sheet:0
msgid "Timesheets"
msgstr ""
msgstr "Zaman Çizelgeleri"
#. module: hr
#: model:ir.actions.act_window,name:hr.open_view_employee_tree
@ -247,12 +261,12 @@ msgstr "SGK Bilgisi"
#. module: hr
#: help:hr.job,no_of_employee:0
msgid "Number of employee with that job."
msgstr ""
msgstr "O işteki personel sayısı"
#. module: hr
#: field:hr.employee,work_phone:0
msgid "Work Phone"
msgstr "İş Telefon No."
msgstr "İş Telefonu"
#. module: hr
#: field:hr.employee.category,child_ids:0
@ -264,12 +278,12 @@ msgstr "Alt Kategoriler"
#: field:hr.job,description:0
#: model:ir.model,name:hr.model_hr_job
msgid "Job Description"
msgstr ""
msgstr "İş Tanımı"
#. module: hr
#: field:hr.employee,work_location:0
msgid "Office Location"
msgstr "Ofis Lokasyonu"
msgstr "Ofis Konumu"
#. module: hr
#: view:hr.employee:0
@ -282,12 +296,12 @@ msgstr "Personel"
#. module: hr
#: model:process.node,note:hr.process_node_employeecontact0
msgid "Other information"
msgstr ""
msgstr "Diğer Bilgiler"
#. module: hr
#: field:hr.employee,work_email:0
msgid "Work E-mail"
msgstr ""
msgstr "İş E-postası"
#. module: hr
#: field:hr.department,complete_name:0
@ -298,7 +312,7 @@ msgstr "Adı"
#. module: hr
#: field:hr.employee,birthday:0
msgid "Date of Birth"
msgstr ""
msgstr "Doğum Tarihi"
#. module: hr
#: model:ir.ui.menu,name:hr.menu_hr_reporting
@ -308,19 +322,19 @@ msgstr "Raporlama"
#. module: hr
#: model:ir.model,name:hr.model_ir_actions_act_window
msgid "ir.actions.act_window"
msgstr ""
msgstr "ir.actions.act_window"
#. module: hr
#: model:ir.actions.act_window,name:hr.open_board_hr
msgid "Human Resources Dashboard"
msgstr ""
msgstr "İnsan Kaynakları Kontrol Paneli"
#. module: hr
#: view:hr.employee:0
#: field:hr.employee,job_id:0
#: view:hr.job:0
msgid "Job"
msgstr ""
msgstr "İş"
#. module: hr
#: view:hr.department:0
@ -331,7 +345,7 @@ msgstr "Üyeler"
#. module: hr
#: model:ir.ui.menu,name:hr.menu_hr_configuration
msgid "Configuration"
msgstr "Ayarlar"
msgstr "Yapılandırma"
#. module: hr
#: view:hr.installer:0
@ -339,21 +353,23 @@ msgid ""
"You can enhance the base HR Application by installing few HR-related "
"functionalities."
msgstr ""
"Bir kaç İK-ilişkili işlevsellik kurarak temel İK Uygulamasını "
"geliştirebilirsiniz."
#. module: hr
#: view:hr.employee:0
msgid "Categories"
msgstr ""
msgstr "Kategoriler"
#. module: hr
#: field:hr.job,expected_employees:0
msgid "Expected Employees"
msgstr ""
msgstr "Beklenen Personel"
#. module: hr
#: help:hr.employee,sinid:0
msgid "Social Insurance Number"
msgstr ""
msgstr "Sosyal Sigorta Numarası"
#. module: hr
#: model:hr.employee.marital.status,name:hr.hr_employee_marital_status_divorced
@ -368,7 +384,7 @@ msgstr "Ana Kategori"
#. module: hr
#: constraint:hr.employee.category:0
msgid "Error ! You cannot create recursive Categories."
msgstr ""
msgstr "Hata ! Yinelenen Kategoriler oluşturamazsınız."
#. module: hr
#: view:hr.department:0
@ -377,7 +393,7 @@ msgstr ""
#: view:res.users:0
#: field:res.users,context_department_id:0
msgid "Departments"
msgstr "Departmanlar"
msgstr "Bölümler"
#. module: hr
#: model:process.node,name:hr.process_node_employeecontact0
@ -387,23 +403,23 @@ msgstr "Personel İletişimi"
#. module: hr
#: view:board.board:0
msgid "My Board"
msgstr ""
msgstr "Kontrol Panelim"
#. module: hr
#: selection:hr.employee,gender:0
msgid "Male"
msgstr "Bay"
msgstr "Erkek"
#. module: hr
#: field:hr.installer,progress:0
msgid "Configuration Progress"
msgstr ""
msgstr "Yapılandırma İşlemi"
#. module: hr
#: model:ir.actions.act_window,name:hr.open_view_categ_form
#: model:ir.ui.menu,name:hr.menu_view_employee_category_form
msgid "Categories of Employee"
msgstr "Personel Kategorisi"
msgstr "Personel Kategorileri"
#. module: hr
#: view:hr.employee.category:0
@ -414,12 +430,12 @@ msgstr "Personel Kategorisi"
#. module: hr
#: field:hr.installer,config_logo:0
msgid "Image"
msgstr ""
msgstr "Resim"
#. module: hr
#: model:process.process,name:hr.process_process_employeecontractprocess0
msgid "Employee Contract"
msgstr ""
msgstr "Personel Sözleşmesi"
#. module: hr
#: help:hr.installer,hr_evaluation:0
@ -427,21 +443,23 @@ msgid ""
"Lets you create and manage the periodic evaluation and performance review of "
"employees."
msgstr ""
"Çalışanlarınızın süreli değerlendirme ve verimlilik incelemelerini "
"oluşturmanızı ve yönetmenizi sağlar."
#. module: hr
#: model:ir.model,name:hr.model_hr_department
msgid "hr.department"
msgstr ""
msgstr "ik.bölümü"
#. module: hr
#: help:hr.employee,parent_id:0
msgid "It is linked with manager of Department"
msgstr ""
msgstr "Bölümün Müdürüne bağlanmıştır"
#. module: hr
#: field:hr.installer,hr_recruitment:0
msgid "Recruitment Process"
msgstr ""
msgstr "Seçme İşlemi"
#. module: hr
#: field:hr.employee,category_ids:0
@ -463,11 +481,22 @@ msgid ""
"they will be able to enter time through the system. In the note tab, you can "
"enter text data that should be recorded for a specific employee."
msgstr ""
"Burada, çalışanlar oluşturarak ve onları sistemde belirli niteliklere "
"atayarak iş gücünüzü yönetebilirsiniz. Çalışanlarınızla ilgili bilgileri "
"elde edin ve onlarla ilgili kayıt edilmesi gereken her şeyin kaydını tutun. "
"Personel bilgisi sekmesi, personelin kimlik bilgilerini elde etmenizi "
"sağlar. Kategori sekmesi, şirket içindeki durumlarına ve etkinliklerine "
"bağlı olarak personelinizi ilgili çaşıan kategorisine atamanıza fırsat "
"sağlar. Bir kategori şirket içinde veya bir bölümde bir kıdemlilik "
"kategorisi olabilir. Zaman Çizelgesi sekmesi onların sistemden zaman "
"girişlerini yapabilecekleri, belirli bir zaman çizelgesine ve analitik "
"yevmiyeye atamanızı sağlar. Not sekmesinde, belirli bir çalışan için kayıt "
"etmeniz gereken bir metin girmenizi sağlar."
#. module: hr
#: help:hr.employee,bank_account_id:0
msgid "Employee bank salary account"
msgstr ""
msgstr "Personel maaş banka hesabı"
#. module: hr
#: field:hr.department,note:0
@ -477,7 +506,7 @@ msgstr "Not"
#. module: hr
#: constraint:res.users:0
msgid "The chosen company is not in the allowed companies for this user"
msgstr ""
msgstr "Seçilen firma bu kullanıcı için izin verilen şirketler arasında yok"
#. module: hr
#: view:hr.employee:0
@ -492,7 +521,7 @@ msgstr "İş Adresi"
#. module: hr
#: model:ir.actions.act_window,name:hr.open_board_hr_manager
msgid "HR Manager Dashboard"
msgstr ""
msgstr "İK Yönetici Kontrol Paneli"
#. module: hr
#: view:hr.employee:0
@ -502,7 +531,7 @@ msgstr "Durum"
#. module: hr
#: view:hr.installer:0
msgid "Configure"
msgstr ""
msgstr "Yapılandırma"
#. module: hr
#: model:ir.actions.act_window,name:hr.open_view_categ_tree
@ -513,12 +542,12 @@ msgstr "Kategori Yapısı"
#. module: hr
#: field:hr.employee,partner_id:0
msgid "unknown"
msgstr ""
msgstr "bilinmeyen"
#. module: hr
#: field:hr.installer,hr_holidays:0
msgid "Holidays / Leaves Management"
msgstr ""
msgstr "Tatil / İzin Yöneticisi"
#. module: hr
#: field:hr.employee,ssnid:0
@ -528,12 +557,12 @@ msgstr "SGK No"
#. module: hr
#: view:hr.employee:0
msgid "Active"
msgstr "Aktif"
msgstr "Etkin"
#. module: hr
#: constraint:hr.employee:0
msgid "Error ! You cannot create recursive Hierarchy of Employees."
msgstr "Hata ! You cannot create recursive Hierarchy of Employees."
msgstr "Hata ! Yinelemeli Personel Sıradizini yaratamazsınız."
#. module: hr
#: view:hr.department:0
@ -551,39 +580,46 @@ msgid ""
" * HR Jobs\n"
" "
msgstr ""
"\n"
" İnsan kaynakları yönetimi modülü. Şunları yönetebilirsiniz:\n"
" * Çalışanlar ve sıradüzeni : Çalışanlarınızı Kullanıcı ve sıradüzenleri "
"ile birlikte tanımlayabilirsiniz\n"
" * İK Bölümleri\n"
" * İK İşleri\n"
" "
#. module: hr
#: model:process.transition,note:hr.process_transition_contactofemployee0
msgid ""
"In the Employee form, there are different kind of information like Contact "
"information."
msgstr ""
msgstr "Personel formunda sözleşme bilgileri gibi farklı bilgiler vardır."
#. module: hr
#: help:hr.job,expected_employees:0
msgid "Required number of Employees in total for that job."
msgstr ""
msgstr "O iş için gerekli toplam Personel sayısı"
#. module: hr
#: selection:hr.job,state:0
msgid "Old"
msgstr ""
msgstr "Eski"
#. module: hr
#: field:hr.employee.marital.status,description:0
msgid "Status Description"
msgstr ""
msgstr "Durum Açıklaması"
#. module: hr
#: sql_constraint:res.users:0
msgid "You can not have two users with the same login !"
msgstr ""
msgstr "Aynı kullanıcı adı ile iki kullanıcı oluşturamazsınız !"
#. module: hr
#: view:hr.job:0
#: field:hr.job,state:0
msgid "State"
msgstr ""
msgstr "Durum"
#. module: hr
#: field:hr.employee,marital:0
@ -597,42 +633,42 @@ msgstr "Medeni Durumu"
#. module: hr
#: help:hr.installer,hr_recruitment:0
msgid "Helps you manage and streamline your recruitment process."
msgstr ""
msgstr "Eleman seçme işleminizi yönetmenizi ve yürütmenizi sağlar."
#. module: hr
#: model:process.node,note:hr.process_node_employee0
msgid "Employee form and structure"
msgstr ""
msgstr "Personel formu ve yapısı"
#. module: hr
#: field:hr.employee,photo:0
msgid "Photo"
msgstr ""
msgstr "Fotoğraf"
#. module: hr
#: model:ir.model,name:hr.model_res_users
msgid "res.users"
msgstr ""
msgstr "res.users"
#. module: hr
#: field:hr.installer,hr_payroll_account:0
msgid "Payroll Accounting"
msgstr ""
msgstr "Bordro Muhasebesi"
#. module: hr
#: view:hr.employee:0
msgid "Personal Information"
msgstr "Personel Bilgileri"
msgstr "Kişisel Bilgiler"
#. module: hr
#: field:hr.employee,passport_id:0
msgid "Passport No"
msgstr ""
msgstr "Pasaport No"
#. module: hr
#: view:res.users:0
msgid "Current Activity"
msgstr ""
msgstr "Güncel Etkinlik"
#. module: hr
#: help:hr.installer,hr_expense:0
@ -640,21 +676,23 @@ msgid ""
"Tracks and manages employee expenses, and can automatically re-invoice "
"clients if the expenses are project-related."
msgstr ""
"Personel harcamalarını izler ve yönetir, ve eğer harcamalar projeyle ilgili "
"ise müşteriler otomatik olarak yeniden faturalandırılabilir."
#. module: hr
#: view:hr.job:0
msgid "Current"
msgstr ""
msgstr "Geçerli"
#. module: hr
#: field:hr.department,parent_id:0
msgid "Parent Department"
msgstr ""
msgstr "Ana Bölüm"
#. module: hr
#: view:hr.employee.category:0
msgid "Employees Categories"
msgstr "Personel Kategorisi"
msgstr "Personel Kategorileri"
#. module: hr
#: field:hr.employee,address_home_id:0
@ -665,54 +703,54 @@ msgstr "Ev Adresi"
#: field:hr.installer,hr_attendance:0
#: model:ir.ui.menu,name:hr.menu_open_view_attendance_reason_new_config
msgid "Attendances"
msgstr ""
msgstr "Devamlılık"
#. module: hr
#: view:hr.employee.marital.status:0
#: view:hr.job:0
msgid "Description"
msgstr ""
msgstr "ıklama"
#. module: hr
#: help:hr.installer,hr_contract:0
msgid "Extends employee profiles to help manage their contracts."
msgstr ""
msgstr "Sözleşmelerinin yönetimi için personel profillerini açar."
#. module: hr
#: field:hr.installer,hr_payroll:0
msgid "Payroll"
msgstr ""
msgstr "Bordro"
#. module: hr
#: model:hr.employee.marital.status,name:hr.hr_employee_marital_status_single
msgid "Single"
msgstr ""
msgstr "Bekar"
#. module: hr
#: field:hr.job,name:0
msgid "Job Name"
msgstr ""
msgstr "İş Adı"
#. module: hr
#: view:hr.job:0
#: selection:hr.job,state:0
msgid "In Position"
msgstr ""
msgstr "Durumunda"
#. module: hr
#: field:hr.employee,mobile_phone:0
msgid "Mobile"
msgstr ""
msgstr "Cep"
#. module: hr
#: view:hr.department:0
msgid "department"
msgstr ""
msgstr "bölüm"
#. module: hr
#: field:hr.employee,country_id:0
msgid "Nationality"
msgstr "Uyruk"
msgstr "Uyruğu"
#. module: hr
#: view:hr.department:0
@ -724,23 +762,23 @@ msgstr "Notlar"
#. module: hr
#: model:ir.model,name:hr.model_hr_installer
msgid "hr.installer"
msgstr ""
msgstr "ik.kurucu"
#. module: hr
#: view:board.board:0
msgid "HR Manager Board"
msgstr ""
msgstr "İK Yönetim Paneli"
#. module: hr
#: field:hr.employee,resource_id:0
msgid "Resource"
msgstr ""
msgstr "Kaynak"
#. module: hr
#: view:hr.installer:0
#: model:ir.actions.act_window,name:hr.action_hr_installer
msgid "Human Resources Application Configuration"
msgstr ""
msgstr "İnsan Kaynakları Uygulama Yapılandırması"
#. module: hr
#: field:hr.employee,gender:0
@ -761,49 +799,49 @@ msgstr "Personeller"
#. module: hr
#: field:hr.employee,bank_account_id:0
msgid "Bank Account"
msgstr ""
msgstr "Banka Hesabı"
#. module: hr
#: field:hr.department,name:0
msgid "Department Name"
msgstr ""
msgstr "Bölüm Adı"
#. module: hr
#: help:hr.employee,ssnid:0
msgid "Social Security Number"
msgstr ""
msgstr "Sosyal Güvenlik Numarası"
#. module: hr
#: model:process.node,note:hr.process_node_openerpuser0
msgid "Creation of a OpenERP user"
msgstr ""
msgstr "OpenERP kullanıcısı Oluşturma"
#. module: hr
#: field:hr.department,child_ids:0
msgid "Child Departments"
msgstr "Alt Departmanlar"
msgstr "Alt Bölümler"
#. module: hr
#: model:ir.actions.act_window,name:hr.action_hr_job
#: model:ir.ui.menu,name:hr.menu_hr_job
msgid "Job Positions"
msgstr ""
msgstr "İş Durumları"
#. module: hr
#: view:hr.employee:0
#: field:hr.employee,coach_id:0
msgid "Coach"
msgstr ""
msgstr "Çalıştırıcı"
#. module: hr
#: view:hr.installer:0
msgid "Configure Your Human Resources Application"
msgstr ""
msgstr "İnsan Kaynakları Uygulamanızı yapılandırın"
#. module: hr
#: field:hr.installer,hr_expense:0
msgid "Expenses"
msgstr ""
msgstr "Giderler"
#. module: hr
#: field:hr.department,manager_id:0
@ -815,17 +853,17 @@ msgstr "Yönetici"
#. module: hr
#: model:hr.employee.marital.status,name:hr.hr_employee_marital_status_widower
msgid "Widower"
msgstr ""
msgstr "Dul"
#. module: hr
#: help:hr.installer,hr_payroll_account:0
msgid "Generic Payroll system Integrated with Accountings."
msgstr ""
msgstr "Muhasebe ile bütünleşik Genel Bordro sistemi."
#. module: hr
#: field:hr.employee,child_ids:0
msgid "Subordinates"
msgstr ""
msgstr "Emrindekiler"
#~ msgid "Invalid XML for View Architecture!"
#~ msgstr "Görüntüleme mimarisi için Geçersiz XML"

View File

@ -7,14 +7,14 @@ 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-01-14 08:42+0000\n"
"Last-Translator: Alexey Y. Fedotov <Unknown>\n"
"PO-Revision-Date: 2011-06-27 05:15+0000\n"
"Last-Translator: Stanislav Hanzhin <Unknown>\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: 2011-04-29 05:27+0000\n"
"X-Generator: Launchpad (build 12758)\n"
"X-Launchpad-Export-Date: 2011-06-28 04:40+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: hr_contract
#: view:hr.contract.wage.type:0
@ -74,7 +74,7 @@ msgstr "Множитель стоимости часа"
#. module: hr_contract
#: view:hr.contract:0
msgid "Overpassed"
msgstr ""
msgstr "Переведён"
#. module: hr_contract
#: view:hr.contract.wage.type:0
@ -145,7 +145,7 @@ msgstr "Поиск договора"
#. module: hr_contract
#: help:hr.employee,contract_id:0
msgid "Latest contract of the employee"
msgstr ""
msgstr "Последний договор с сотрудником"
#. module: hr_contract
#: field:hr.contract,advantages_net:0
@ -163,6 +163,13 @@ msgid ""
" You can assign several contracts per employee.\n"
" "
msgstr ""
"\n"
" Добавляйте информацию в форму сотрудника для управления договорами:\n"
" * Семейное положение,\n"
" * Номер свидетельства социального страхования,\n"
" * Место рождения, дата рождения, ...\n"
" Можно назначить несколько договоров одному сотруднику.\n"
" "
#. module: hr_contract
#: view:hr.contract:0
@ -218,7 +225,7 @@ msgstr "Зарплата"
#. module: hr_contract
#: field:hr.contract,name:0
msgid "Contract Reference"
msgstr ""
msgstr "Ссылка на договор"
#. module: hr_contract
#: help:hr.employee,vehicle_distance:0
@ -259,7 +266,7 @@ msgstr "Тип договора"
#. module: hr_contract
#: view:hr.contract.wage.type.period:0
msgid "Search Wage Period"
msgstr ""
msgstr "Поиск по периоду выплаты"
#. module: hr_contract
#: view:hr.contract:0
@ -303,7 +310,7 @@ msgstr ""
#. module: hr_contract
#: view:hr.contract.wage.type:0
msgid "Search Wage Type"
msgstr ""
msgstr "Поиск по типу выплаты"
#. module: hr_contract
#: field:hr.contract.wage.type,type:0
@ -375,7 +382,7 @@ msgstr "Основные данные"
#. module: hr_contract
#: view:hr.contract.type:0
msgid "Search Contract Type"
msgstr ""
msgstr "Поиск по типу договора"
#~ msgid ""
#~ "The Object name must start with x_ and not contain any special character !"

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2010-10-16 08:48+0000\n"
"Last-Translator: Nikolay Chesnokov <chesnokov_n@msn.com>\n"
"PO-Revision-Date: 2011-06-27 05:30+0000\n"
"Last-Translator: Bulat Shafigullin <Unknown>\n"
"Language-Team: Russian <ru@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-04-29 05:41+0000\n"
"X-Generator: Launchpad (build 12758)\n"
"X-Launchpad-Export-Date: 2011-06-28 04:40+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: hr_evaluation
#: selection:hr.evaluation.report,state:0
@ -26,26 +26,26 @@ msgstr ""
#. module: hr_evaluation
#: field:hr_evaluation.plan.phase,wait:0
msgid "Wait Previous Phases"
msgstr ""
msgstr "Дождатья предыдущей фазы"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
#: view:hr.evaluation.report:0
#: view:hr_evaluation.plan:0
msgid "Group By..."
msgstr ""
msgstr "Группировать по ..."
#. module: hr_evaluation
#: field:hr.evaluation.interview,request_id:0
#: field:hr.evaluation.report,request_id:0
msgid "Request_id"
msgstr ""
msgstr "Идентификатор запроса"
#. module: hr_evaluation
#: field:hr.evaluation.report,progress_bar:0
#: field:hr_evaluation.evaluation,progress:0
msgid "Progress"
msgstr ""
msgstr "Выполнено"
#. module: hr_evaluation
#: view:board.board:0
@ -67,58 +67,58 @@ msgstr ""
#. module: hr_evaluation
#: selection:hr.evaluation.report,month:0
msgid "March"
msgstr ""
msgstr "Март"
#. module: hr_evaluation
#: field:hr.evaluation.report,delay_date:0
msgid "Delay to Start"
msgstr ""
msgstr "Задержка начала"
#. module: hr_evaluation
#: view:hr.evaluation.report:0
#: field:hr_evaluation.evaluation,rating:0
msgid "Appreciation"
msgstr ""
msgstr "Оценка"
#. module: hr_evaluation
#: code:addons/hr_evaluation/hr_evaluation.py:242
#: code:addons/hr_evaluation/hr_evaluation.py:311
#, python-format
msgid "Warning !"
msgstr ""
msgstr "Warning !"
#. module: hr_evaluation
#: view:hr_evaluation.plan:0
#: field:hr_evaluation.plan,company_id:0
#: field:hr_evaluation.plan.phase,company_id:0
msgid "Company"
msgstr ""
msgstr "Организация"
#. module: hr_evaluation
#: model:ir.actions.act_window,name:hr_evaluation.act_hr_employee_2_hr__evaluation_interview
msgid "Evaluation Interviews"
msgstr ""
msgstr "Испытательные собеседования"
#. module: hr_evaluation
#: field:hr_evaluation.plan.phase,survey_id:0
msgid "Appraisal Form"
msgstr ""
msgstr "Оценочная форма"
#. module: hr_evaluation
#: view:hr.evaluation.report:0
#: field:hr.evaluation.report,day:0
msgid "Day"
msgstr ""
msgstr "День"
#. module: hr_evaluation
#: field:hr.evaluation.interview,evaluation_id:0
msgid "Evaluation Form"
msgstr ""
msgstr "Испытательная форма"
#. module: hr_evaluation
#: help:hr_evaluation.plan.phase,send_anonymous_employee:0
msgid "Send an anonymous summary to the employee"
msgstr ""
msgstr "Отправить анонимную сводку сотруднику"
#. module: hr_evaluation
#: help:hr_evaluation.plan,month_first:0
@ -126,34 +126,38 @@ msgid ""
"This number of months will be used to schedule the first evaluation date of "
"the employee when selecting an evaluation plan. "
msgstr ""
"Указанное количество месяцев будет использоваться при планировании первого "
"испытательного дня при выборе испытательного плана. "
#. module: hr_evaluation
#: view:hr.employee:0
msgid "Notes"
msgstr ""
msgstr "Заметки"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
msgid "Interview Request"
msgstr ""
msgstr "Запрос на собеседование"
#. module: hr_evaluation
#: constraint:hr.employee:0
msgid ""
"Error ! You cannot select a department for which the employee is the manager."
msgstr ""
"Ошибка! Вы не можете выбрать подразделение, руководителем которого является "
"этот сотрудник."
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
msgid "Mail Body"
msgstr ""
msgstr "Тело письма"
#. module: hr_evaluation
#: view:hr.evaluation.report:0
#: model:ir.actions.act_window,name:hr_evaluation.action_evaluation_report_all
#: model:ir.ui.menu,name:hr_evaluation.menu_evaluation_report_all
msgid "Evaluations Analysis"
msgstr ""
msgstr "Анализ испытаний"
#. module: hr_evaluation
#: selection:hr.evaluation.report,state:0
@ -170,7 +174,7 @@ msgstr ""
#: selection:hr.evaluation.report,rating:0
#: selection:hr_evaluation.evaluation,rating:0
msgid "Did not meet expectations"
msgstr ""
msgstr "Не оправдал ожиданий"
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
@ -185,7 +189,7 @@ msgstr ""
#. module: hr_evaluation
#: field:hr_evaluation.plan,month_next:0
msgid "Periodicity of Evaluations (months)"
msgstr ""
msgstr "Периодичность испытаний (мес.)"
#. module: hr_evaluation
#: code:addons/hr_evaluation/hr_evaluation.py:242
@ -203,7 +207,7 @@ msgstr ""
#. module: hr_evaluation
#: field:hr_evaluation.plan,month_first:0
msgid "First Evaluation in (months)"
msgstr ""
msgstr "Первое испытание через (мес.)"
#. module: hr_evaluation
#: code:addons/hr_evaluation/hr_evaluation.py:81
@ -229,7 +233,7 @@ msgstr ""
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
msgid "Send to Employees"
msgstr ""
msgstr "Отправить сотрудникам"
#. module: hr_evaluation
#: field:hr.evaluation.report,deadline:0
@ -324,18 +328,20 @@ msgstr ""
#: selection:hr.evaluation.report,rating:0
#: selection:hr_evaluation.evaluation,rating:0
msgid "Exceeds expectations"
msgstr ""
msgstr "Превосходит ожидания"
#. module: hr_evaluation
#: help:hr_evaluation.plan.phase,mail_feature:0
msgid ""
"Check this box if you want to send mail to employees coming under this phase"
msgstr ""
"Отметьте, если хотите отправлять письма сотрудникам, приходящим в текущей "
"фазе"
#. module: hr_evaluation
#: help:hr_evaluation.plan.phase,send_answer_manager:0
msgid "Send all answers to the manager"
msgstr ""
msgstr "Отправить все ответы менеджеру"
#. module: hr_evaluation
#: view:hr.evaluation.report:0
@ -350,13 +356,13 @@ msgstr ""
#. module: hr_evaluation
#: field:hr_evaluation.evaluation,date:0
msgid "Evaluation Deadline"
msgstr ""
msgstr "Дата завершения испытания"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
#: view:hr_evaluation.evaluation:0
msgid "Print Interview"
msgstr ""
msgstr "Распечатать собеседование"
#. module: hr_evaluation
#: field:hr.evaluation.report,closed:0
@ -367,13 +373,13 @@ msgstr ""
#: selection:hr.evaluation.report,rating:0
#: selection:hr_evaluation.evaluation,rating:0
msgid "Meet expectations"
msgstr ""
msgstr "Соответствует ожиданиям"
#. module: hr_evaluation
#: view:hr.evaluation.report:0
#: field:hr.evaluation.report,nbr:0
msgid "# of Requests"
msgstr ""
msgstr "# запросов"
#. module: hr_evaluation
#: model:ir.actions.act_window,name:hr_evaluation.open_view_hr_evaluation_tree
@ -391,16 +397,20 @@ msgid ""
"manages all kind of evaluations: bottom-up, top-down, self-evaluation and "
"final evaluation by the manager."
msgstr ""
"Каждому сотруднику может быть назначен испытательный план. Данный план "
"определяет частоту и порядок персональных испытаний. Вы можете определить "
"этапы и прикрепить к ним собеседования. OpenERP поддерживает все виды "
"оценок: снизу-вверх, сверху-вниз, самооценка и конечная оценка менеджером."
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
msgid "Action to Perform"
msgstr ""
msgstr "Действие к выполнению"
#. module: hr_evaluation
#: field:hr_evaluation.evaluation,note_action:0
msgid "Action Plan"
msgstr ""
msgstr "План действия"
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
@ -410,13 +420,13 @@ msgstr ""
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
msgid "Ending Summary"
msgstr ""
msgstr "Заключительная сводка"
#. module: hr_evaluation
#: selection:hr.evaluation.report,rating:0
#: selection:hr_evaluation.evaluation,rating:0
msgid "Significantly exceeds expectations"
msgstr ""
msgstr "Значительно превосходит ожидания"
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
@ -427,7 +437,7 @@ msgstr ""
#: field:hr_evaluation.plan.phase,send_answer_employee:0
#: field:hr_evaluation.plan.phase,send_answer_manager:0
msgid "All Answers"
msgstr ""
msgstr "Все ответы"
#. module: hr_evaluation
#: selection:hr.evaluation.report,month:0
@ -448,7 +458,7 @@ msgstr ""
#. module: hr_evaluation
#: model:ir.module.module,shortdesc:hr_evaluation.module_meta_information
msgid "Human Resources Evaluation"
msgstr ""
msgstr "Оценка человеческих ресурсов"
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
@ -458,23 +468,23 @@ msgstr ""
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
msgid "Mail Settings"
msgstr ""
msgstr "Настройки почты"
#. module: hr_evaluation
#: field:hr.evaluation.interview,user_to_review_id:0
msgid "Employee to Interview"
msgstr ""
msgstr "Сотрудник на собеседование"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
#: view:hr_evaluation.evaluation:0
msgid "Interview Question"
msgstr ""
msgstr "Вопрос собеседования"
#. module: hr_evaluation
#: field:survey.request,is_evaluation:0
msgid "Is Evaluation?"
msgstr ""
msgstr "Является оценкой?"
#. module: hr_evaluation
#: model:ir.model,name:hr_evaluation.model_survey_request
@ -487,11 +497,13 @@ msgid ""
"Check this box if you want to wait that all preceding phases are finished "
"before launching this phase."
msgstr ""
"Отметьте, если необходимо, чтобы перед началом данной фазы все предыдущие "
"были завершены."
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
msgid "Evaluation Data"
msgstr ""
msgstr "Данные испытания"
#. module: hr_evaluation
#: help:hr_evaluation.evaluation,note_action:0
@ -509,13 +521,13 @@ msgstr "Черновик"
#. module: hr_evaluation
#: field:hr_evaluation.evaluation,note_summary:0
msgid "Evaluation Summary"
msgstr ""
msgstr "Сводка испытания"
#. module: hr_evaluation
#: field:hr_evaluation.plan.phase,send_anonymous_employee:0
#: field:hr_evaluation.plan.phase,send_anonymous_manager:0
msgid "Anonymous Summary"
msgstr ""
msgstr "Анонимная сводка"
#. module: hr_evaluation
#: view:hr.employee:0
@ -541,7 +553,7 @@ msgstr ""
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
msgid "Start Evaluation"
msgstr ""
msgstr "Начало испытания"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
@ -557,7 +569,7 @@ msgstr ""
#: selection:hr.evaluation.report,rating:0
#: selection:hr_evaluation.evaluation,rating:0
msgid "Significantly bellow expectations"
msgstr ""
msgstr "Значительно ниже ожиданий"
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
@ -610,19 +622,19 @@ msgstr ""
#. module: hr_evaluation
#: help:hr_evaluation.plan.phase,send_anonymous_manager:0
msgid "Send an anonymous summary to the manager"
msgstr ""
msgstr "Отправить анонимную сводку менеджеру"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
#: view:hr_evaluation.evaluation:0
msgid "Interview Evaluation"
msgstr ""
msgstr "Оценка собеседования"
#. module: hr_evaluation
#: model:ir.actions.act_window,name:hr_evaluation.open_view_hr_evaluation_plan_tree
#: model:ir.ui.menu,name:hr_evaluation.menu_open_view_hr_evaluation_plan_tree
msgid "Evaluation Plans"
msgstr ""
msgstr "Планы испытаний"
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
@ -648,22 +660,22 @@ msgstr ""
#: view:hr.evaluation.report:0
#: selection:hr.evaluation.report,state:0
msgid "Final Validation"
msgstr ""
msgstr "Конечная проверка"
#. module: hr_evaluation
#: selection:hr_evaluation.evaluation,state:0
msgid "Waiting Appreciation"
msgstr ""
msgstr "Ожидание оценки"
#. module: hr_evaluation
#: field:hr_evaluation.plan.phase,mail_feature:0
msgid "Send mail for this phase"
msgstr ""
msgstr "Отправить письмо по данной фазе"
#. module: hr_evaluation
#: field:hr.evaluation.report,rating:0
msgid "Overall Rating"
msgstr ""
msgstr "Общий рейтинг"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
@ -675,22 +687,22 @@ msgstr ""
#: view:hr.evaluation.interview:0
#: view:hr_evaluation.evaluation:0
msgid "Interviewer"
msgstr ""
msgstr "Интервьюер"
#. module: hr_evaluation
#: model:ir.model,name:hr_evaluation.model_hr_evaluation_report
msgid "Evaluations Statistics"
msgstr ""
msgstr "Статистика испытаний"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
msgid "Deadline Date"
msgstr ""
msgstr "Конечная дата"
#. module: hr_evaluation
#: selection:hr_evaluation.plan.phase,action:0
msgid "Top-Down Appraisal Requests"
msgstr ""
msgstr "Запросы на оценку сверху вниз"
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
@ -700,12 +712,12 @@ msgstr ""
#. module: hr_evaluation
#: help:hr_evaluation.plan.phase,send_answer_employee:0
msgid "Send all answers to the employee"
msgstr ""
msgstr "Отправить все ответы сотруднику"
#. module: hr_evaluation
#: field:hr.employee,evaluation_date:0
msgid "Next Evaluation Date"
msgstr ""
msgstr "Следующая дата испытания"
#. module: hr_evaluation
#: view:hr.evaluation.report:0
@ -718,7 +730,7 @@ msgstr ""
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
msgid "Evaluation Plan Phases"
msgstr ""
msgstr "Фазы плана оценки"
#. module: hr_evaluation
#: view:hr.evaluation.reminder:0
@ -794,12 +806,12 @@ msgstr ""
#. module: hr_evaluation
#: view:hr_evaluation.evaluation:0
msgid "Validate Evaluation"
msgstr ""
msgstr "Проверить оценку"
#. module: hr_evaluation
#: selection:hr_evaluation.plan.phase,action:0
msgid "Final Interview"
msgstr ""
msgstr "Завершающее собеседование"
#. module: hr_evaluation
#: field:hr_evaluation.plan.phase,name:0
@ -809,13 +821,13 @@ msgstr ""
#. module: hr_evaluation
#: selection:hr_evaluation.plan.phase,action:0
msgid "Bottom-Up Appraisal Requests"
msgstr ""
msgstr "Запросы оценки снизу вверх"
#. module: hr_evaluation
#: view:hr.evaluation.interview:0
#: view:hr_evaluation.evaluation:0
msgid "Search Evaluation"
msgstr ""
msgstr "Поиск оценки"
#. module: hr_evaluation
#: field:hr.employee,evaluation_plan_id:0
@ -824,7 +836,7 @@ msgstr ""
#: field:hr_evaluation.plan.phase,plan_id:0
#: model:ir.model,name:hr_evaluation.model_hr_evaluation_plan
msgid "Evaluation Plan"
msgstr ""
msgstr "План оценки"
#. module: hr_evaluation
#: selection:hr.evaluation.report,month:0
@ -834,7 +846,7 @@ msgstr ""
#. module: hr_evaluation
#: view:hr_evaluation.plan.phase:0
msgid "Send to Managers"
msgstr ""
msgstr "Отправить менеджерам"
#. module: hr_evaluation
#: model:ir.actions.act_window,name:hr_evaluation.action_hr_evaluation_send_mail
@ -849,12 +861,12 @@ msgstr ""
#. module: hr_evaluation
#: model:ir.model,name:hr_evaluation.model_hr_evaluation_evaluation
msgid "Employee Evaluation"
msgstr ""
msgstr "Оценка сотрудника"
#. module: hr_evaluation
#: view:hr_evaluation.plan:0
msgid "Search Evaluation Plan"
msgstr ""
msgstr "Поиск по плану оценки"
#. module: hr_evaluation
#: view:hr_evaluation.plan:0
@ -875,7 +887,7 @@ msgstr ""
#: model:ir.actions.act_window,name:hr_evaluation.action_hr_evaluation_interview_tree
#: model:ir.ui.menu,name:hr_evaluation.menu_open_hr_evaluation_interview_requests
msgid "Interview Requests"
msgstr ""
msgstr "Запросы на собеседование"
#. module: hr_evaluation
#: field:hr.evaluation.report,create_date:0
@ -894,6 +906,8 @@ msgid ""
"The date of the next evaluation is computed by the evaluation plan's dates "
"(first evaluation + periodicity)."
msgstr ""
"Дата следующей оценки вычисляется согласно плану (первая оценка + "
"периодичность)."
#~ msgid "Score"
#~ msgstr "Оценка"

View File

@ -0,0 +1,344 @@
# Chinese (Simplified) translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-06-27 13:51+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-28 04:40+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: hr_payroll_account
#: field:hr.payslip,move_line_ids:0
msgid "Accounting Lines"
msgstr "会计明细"
#. module: hr_payroll_account
#: field:hr.payroll.register,bank_journal_id:0
#: field:hr.payslip,bank_journal_id:0
msgid "Bank Journal"
msgstr "银行日记帐"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_contibution_register_line
msgid "Contribution Register Line"
msgstr "捐款记录明细"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_contibution_register
msgid "Contribution Register"
msgstr "捐款记录"
#. module: hr_payroll_account
#: help:hr.employee,analytic_account:0
msgid "Analytic Account for Salary Analysis"
msgstr "薪酬分析的辅助核算项"
#. module: hr_payroll_account
#: field:hr.payroll.register,journal_id:0
#: field:hr.payslip,journal_id:0
msgid "Expense Journal"
msgstr "费用日记帐"
#. module: hr_payroll_account
#: field:hr.contibution.register.line,period_id:0
msgid "Period"
msgstr "期间"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_employee
msgid "Employee"
msgstr "员工"
#. module: hr_payroll_account
#: view:hr.payslip:0
msgid "Other Informations"
msgstr "其它信息"
#. module: hr_payroll_account
#: field:hr.employee,salary_account:0
msgid "Salary Account"
msgstr "薪酬科目"
#. module: hr_payroll_account
#: help:hr.employee,property_bank_account:0
msgid "Select Bank Account from where Salary Expense will be Paid"
msgstr ""
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_payroll_register
msgid "Payroll Register"
msgstr "工资表记录"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_payslip_account_move
msgid "Account Move Link to Pay Slip"
msgstr "分录链接到工资表"
#. module: hr_payroll_account
#: view:hr.payslip:0
msgid "Description"
msgstr "描述"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:331
#, python-format
msgid "Please Confirm all Expense Invoice appear for Reimbursement"
msgstr "请确认所有报销的费用发票"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:432
#, python-format
msgid "Please defined partner in bank account for %s !"
msgstr ""
#. module: hr_payroll_account
#: view:hr.payslip:0
msgid "Accounting Informations"
msgstr "会计信息"
#. module: hr_payroll_account
#: help:hr.employee,salary_account:0
msgid "Expense account when Salary Expense will be recorded"
msgstr "开支科目将记录薪酬开支"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:429
#, python-format
msgid "Please defined bank account for %s !"
msgstr ""
#. module: hr_payroll_account
#: model:ir.module.module,description:hr_payroll_account.module_meta_information
msgid ""
"Generic Payroll system Integrated with Accountings\n"
" * Expanse Encoding\n"
" * Payment Encoding\n"
" * Comany Contribution Managemet\n"
" "
msgstr ""
#. module: hr_payroll_account
#: model:ir.module.module,shortdesc:hr_payroll_account.module_meta_information
msgid "Human Resource Payroll Accounting"
msgstr "人力资源工资表会计部分"
#. module: hr_payroll_account
#: view:hr.payslip:0
#: field:hr.payslip,move_payment_ids:0
msgid "Payment Lines"
msgstr "付款明细"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:270
#: code:addons/hr_payroll_account/hr_payroll_account.py:445
#, python-format
msgid "Please define fiscal year for perticular contract"
msgstr "请定义财务年的会计期间"
#. module: hr_payroll_account
#: field:hr.payslip.account.move,slip_id:0
#: model:ir.model,name:hr_payroll_account.model_hr_payslip
msgid "Pay Slip"
msgstr "工资表"
#. module: hr_payroll_account
#: constraint:hr.employee:0
msgid "Error ! You cannot create recursive Hierarchy of Employees."
msgstr "错误!您不能创建递归的员工等级。"
#. module: hr_payroll_account
#: view:hr.payslip:0
msgid "Account Lines"
msgstr "明细"
#. module: hr_payroll_account
#: field:hr.contibution.register,account_id:0
#: field:hr.holidays.status,account_id:0
#: field:hr.payroll.advice,account_id:0
msgid "Account"
msgstr "科目"
#. module: hr_payroll_account
#: field:hr.employee,property_bank_account:0
msgid "Bank Account"
msgstr "银行帐户"
#. module: hr_payroll_account
#: field:hr.payslip.account.move,name:0
msgid "Name"
msgstr "名称"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_payslip_line
msgid "Payslip Line"
msgstr "工资表明细"
#. module: hr_payroll_account
#: view:hr.payslip:0
msgid "Accounting Vouchers"
msgstr "会计凭证"
#. module: hr_payroll_account
#: constraint:hr.employee:0
msgid ""
"Error ! You cannot select a department for which the employee is the manager."
msgstr "错误!您不能选择一部门因为该员工是经理。"
#. module: hr_payroll_account
#: help:hr.payroll.register,period_id:0
#: help:hr.payslip,period_id:0
msgid "Keep empty to use the period of the validation(Payslip) date."
msgstr "为空使用这个期间审核(工资表)日期"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_payroll_advice
msgid "Bank Advice Note"
msgstr "银行通知单备注"
#. module: hr_payroll_account
#: field:hr.payslip.account.move,move_id:0
msgid "Expense Entries"
msgstr "费用分录"
#. module: hr_payroll_account
#: field:hr.payslip,move_ids:0
msgid "Accounting vouchers"
msgstr "会计凭证"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:270
#: code:addons/hr_payroll_account/hr_payroll_account.py:277
#: code:addons/hr_payroll_account/hr_payroll_account.py:280
#: code:addons/hr_payroll_account/hr_payroll_account.py:297
#: code:addons/hr_payroll_account/hr_payroll_account.py:331
#: code:addons/hr_payroll_account/hr_payroll_account.py:445
#: code:addons/hr_payroll_account/hr_payroll_account.py:452
#: code:addons/hr_payroll_account/hr_payroll_account.py:455
#: code:addons/hr_payroll_account/hr_payroll_account.py:469
#: code:addons/hr_payroll_account/hr_payroll_account.py:492
#, python-format
msgid "Warning !"
msgstr "警告!"
#. module: hr_payroll_account
#: field:hr.employee,employee_account:0
msgid "Employee Account"
msgstr "员工帐户"
#. module: hr_payroll_account
#: field:hr.payslip.line,account_id:0
msgid "General Account"
msgstr "一般科目"
#. module: hr_payroll_account
#: field:hr.contibution.register,yearly_total_by_emp:0
msgid "Total By Employee"
msgstr "员工合计"
#. module: hr_payroll_account
#: field:hr.payslip.account.move,sequence:0
msgid "Sequence"
msgstr "序列"
#. module: hr_payroll_account
#: field:hr.payroll.register,period_id:0
#: field:hr.payslip,period_id:0
msgid "Force Period"
msgstr "强制会计期间"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_holidays_status
msgid "Leave Type"
msgstr "假期类型"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:277
#: code:addons/hr_payroll_account/hr_payroll_account.py:452
#, python-format
msgid "Fiscal Year is not defined for slip date %s"
msgstr "这薪酬日期 %s 财务年度没定义"
#. module: hr_payroll_account
#: field:hr.contibution.register,analytic_account_id:0
#: field:hr.employee,analytic_account:0
#: field:hr.holidays.status,analytic_account_id:0
#: field:hr.payroll.structure,account_id:0
#: field:hr.payslip.line,analytic_account_id:0
msgid "Analytic Account"
msgstr "辅助核算项"
#. module: hr_payroll_account
#: help:hr.employee,employee_account:0
msgid "Employee Payable Account"
msgstr "员工应付帐户"
#. module: hr_payroll_account
#: field:hr.contibution.register,yearly_total_by_comp:0
msgid "Total By Company"
msgstr "公司合计"
#. module: hr_payroll_account
#: model:ir.model,name:hr_payroll_account.model_hr_payroll_structure
msgid "Salary Structure"
msgstr "薪酬结构"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:557
#, python-format
msgid "Please Configure Partners Receivable Account!!"
msgstr "请定义业务伙伴应收款帐户!"
#. module: hr_payroll_account
#: view:hr.contibution.register:0
msgid "Year"
msgstr "年"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:280
#: code:addons/hr_payroll_account/hr_payroll_account.py:455
#, python-format
msgid "Period is not defined for slip date %s"
msgstr "这薪酬日期 %s 会计期间没定义。"
#. module: hr_payroll_account
#: view:hr.payslip:0
msgid "Accounting Details"
msgstr "会计细节"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:540
#, python-format
msgid "Please Configure Partners Payable Account!!"
msgstr "请定义业务伙伴应付款帐户!"
#. module: hr_payroll_account
#: code:addons/hr_payroll_account/hr_payroll_account.py:429
#: code:addons/hr_payroll_account/hr_payroll_account.py:432
#: code:addons/hr_payroll_account/hr_payroll_account.py:533
#: code:addons/hr_payroll_account/hr_payroll_account.py:550
#, python-format
msgid "Integrity Error !"
msgstr ""
#~ msgid ""
#~ "Generic Payroll system Integrated with Accountings\n"
#~ " * Expense Encoding\n"
#~ " * Payment Encoding\n"
#~ " * Company Contribution Management\n"
#~ " "
#~ msgstr ""
#~ "通用工资系统整合会计\n"
#~ " * 费用编码\n"
#~ " * 付款编码\n"
#~ " * 公司捐款管理\n"
#~ " "

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Openerp sa (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import import_framework
import mapper

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Base framework for module that need to import complex data',
'version': '0.9',
'category': 'Generic Modules',
'description': """
This module provide a class import_framework to help importing
complex data from other software
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['base'],
'init_xml': [],
'update_xml': [],
'demo_xml': [],
'test': [], #TODO provide test
'installable': True,
'active': False,
}

View File

@ -0,0 +1,432 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import pprint
import mapper
import pooler
import tools
from threading import Thread
import datetime
import logging
pp = pprint.PrettyPrinter(indent=4)
class import_framework(Thread):
"""
This class should be extends,
get_data and get_mapping have to extends
get_state_map and initialize can be extended
for advanced purpose get_default_hook can also be extended
@see dummy import for a minimal exemple
"""
"""
for import_object, this domain will avoid to find an already existing object
"""
DO_NOT_FIND_DOMAIN = [('id', '=', 0)]
def __init__(self, obj, cr, uid, instance_name, module_name, email_to_notify=False, context=None):
Thread.__init__(self)
self.obj = obj
self.cr = cr
self.uid = uid
self.instance_name = instance_name
self.module_name = module_name
self.context = context or {}
self.email = email_to_notify
self.table_list = []
self.initialize()
"""
Abstract Method to be implemented in
the real instance
"""
def initialize(self):
"""
init before import
usually for the login
"""
pass
def get_data(self, table):
"""
@return: a list of dictionaries
each dictionnaries contains the list of pair external_field_name : value
"""
return [{}]
def get_mapping(self):
"""
@return: { TABLE_NAME : {
'model' : 'openerp.model.name',
#if true import the table if not just resolve dependencies, use for meta package, by default => True
#Not required
'import' : True or False,
#Not required
'dependencies' : [TABLE_1, TABLE_2],
#Not required
'hook' : self.function_name, #get the val dict of the object, return the same val dict or False
'map' : { @see mapper
'openerp_field_name' : 'external_field_name', or val('external_field_name')
'openerp_field_id/id' : ref(TABLE_1, 'external_id_field'), #make the mapping between the external id and the xml on the right
'openerp_field2_id/id_parent' : ref(TABLE_1,'external_id_field') #indicate a self dependencies on openerp_field2_id
'state' : map_val('state_equivalent_field', mapping), # use get_state_map to make the mapping between the value of the field and the value of the state
'text_field' : concat('field_1', 'field_2', .., delimiter=':'), #concat the value of the list of field in one
'description_field' : ppconcat('field_1', 'field_2', .., delimiter='\n\t'), #same as above but with a prettier formatting
'field' : call(callable, arg1, arg2, ..), #call the function with all the value, the function should send the value : self.callable
'field' : callable
'field' : call(method, val('external_field') interface of method is self, val where val is the value of the field
'field' : const(value) #always set this field to value
+ any custom mapper that you will define
}
},
}
"""
return {}
def default_hook(self, val):
"""
this hook will be apply on each table that don't have hook
here we define the identity hook
"""
return val
def _import_table(self, table):
data = self.get_data(table)
map = self.get_mapping()[table]['map']
hook = self.get_mapping()[table].get('hook', self.default_hook)
model = self.get_mapping()[table]['model']
final_data = []
for val in data:
res = hook(val)
if res:
final_data.append(res)
return self._save_data(model, dict(map), final_data, table)
def _save_data(self, model, mapping, datas, table):
"""
@param model: the model of the object to import
@param table : the external table where the data come from
@param mapping : definition of the mapping
@see: get_mapping
@param datas : list of dictionnaries
datas = [data_1, data_2, ..]
data_i is a map external field_name => value
and each data_i have a external id => in data_id['id']
"""
if not datas:
return (0, 'No data in this table')
mapping['id'] = 'id_new'
res = []
self_dependencies = []
for k in mapping.keys():
if '_parent' in k:
self_dependencies.append((k[:-7], mapping.pop(k)))
for data in datas:
for k, field_name in self_dependencies:
data[k] = data.get(field_name) and self._generate_xml_id(data.get(field_name), table)
data['id_new'] = self._generate_xml_id(data['id'], table)
fields, values = self._fields_mapp(data, mapping, table)
res.append(values)
model_obj = self.obj.pool.get(model)
if not model_obj:
raise ValueError("%s is not a valid model name" % model)
(p, r, warning, s) = model_obj.import_data(self.cr, self.uid, fields, res, mode='update', current_module=self.module_name, noupdate=True, context=self.context)
for (field, field_name) in self_dependencies:
self._import_self_dependencies(model_obj, field, datas)
return (len(res), warning)
def _import_self_dependencies(self, obj, parent_field, datas):
"""
@param parent_field: the name of the field that generate a self_dependencies, we call the object referenced in this
field the parent of the object
@param datas: a list of dictionnaries
Dictionnaries need to contains
id_new : the xml_id of the object
field_new : the xml_id of the parent
"""
fields = ['id', parent_field]
for data in datas:
if data.get(parent_field):
values = [data['id_new'], data[parent_field]]
obj.import_data(self.cr, self.uid, fields, [values], mode='update', current_module=self.module_name, noupdate=True, context=self.context)
def _preprocess_mapping(self, mapping):
"""
Preprocess the mapping :
after the preprocces, everything is
callable in the val of the dictionary
use to allow syntaxical sugar like 'field': 'external_field'
instead of 'field' : value('external_field')
"""
map = dict(mapping)
for key, value in map.items():
if isinstance(value, basestring):
map[key] = mapper.value(value)
#set parent for instance of dbmapper
elif isinstance(value, mapper.dbmapper):
value.set_parent(self)
return map
def _fields_mapp(self,dict_sugar, openerp_dict, table):
"""
call all the mapper and transform data
to be compatible with import_data
"""
fields=[]
data_lst = []
mapping = self._preprocess_mapping(openerp_dict)
for key,val in mapping.items():
if key not in fields and dict_sugar:
fields.append(key)
value = val(dict(dict_sugar))
data_lst.append(value)
return fields, data_lst
def _generate_xml_id(self, name, table):
"""
@param name: name of the object, has to be unique in for a given table
@param table : table where the record we want generate come from
@return: a unique xml id for record, the xml_id will be the same given the same table and same name
To be used to avoid duplication of data that don't have ids
"""
sugar_instance = self.instance_name
name = name.replace('.', '_').replace(',', '_')
return sugar_instance + "_" + table + "_" + name
"""
Public interface of the framework
those function can be use in the callable function defined in the mapping
"""
def xml_id_exist(self, table, external_id):
"""
Check if the external id exist in the openerp database
in order to check if the id exist the table where it come from
should be provide
@return the xml_id generated if the external_id exist in the database or false
"""
if not external_id:
return False
xml_id = self._generate_xml_id(external_id, table)
id = self.obj.pool.get('ir.model.data').search(self.cr, self.uid, [('name', '=', xml_id), ('module', '=', self.module_name)])
return id and xml_id or False
def name_exist(self, table, name, model):
"""
Check if the object with the name exist in the openerp database
in order to check if the id exist the table where it come from
should be provide and the model of the object
"""
fields = ['name']
data = [name]
return self.import_object(fields, data, model, table, name, [('name', '=', name)])
def get_mapped_id(self, table, external_id, context=None):
"""
@return return the databse id linked with the external_id
"""
if not external_id:
return False
xml_id = self._generate_xml_id(external_id, table)
return self.obj.pool.get('ir.model.data').get_object_reference(self.cr, self.uid, self.module_name, xml_id)[1]
def import_object_mapping(self, mapping, data, model, table, name, domain_search=False):
"""
same as import_objects but instead of two list fields and data,
this method take a dictionnaries : external_field : value
and the mapping similar to the one define in 'map' key
@see import_object, get_mapping
"""
fields, datas = self._fields_mapp(data, mapping, table)
return self.import_object(fields, datas, model, table, name, domain_search)
def import_object(self, fields, data, model, table, name, domain_search=False):
"""
This method will import an object in the openerp, usefull for field that is only a char in sugar and is an object in openerp
use import_data that will take care to create/update or do nothing with the data
this method return the xml_id
To be use, when you want to create an object or link if already exist
use DO_NOT_LINK_DOMAIN to create always a new object
@param fields: list of fields needed to create the object without id
@param data: the list of the data, in the same order as the field
ex : fields = ['firstname', 'lastname'] ; data = ['John', 'Mc donalds']
@param model: the openerp's model of the create/update object
@param table: the table where data come from in sugarcrm, no need to fit the real name of openerp name, just need to be unique
@param unique_name: the name of the object that we want to create/update get the id
@param domain_search : the domain that should find the unique existing record
@return: the xml_id of the ressources
"""
domain_search = not domain_search and [('name', 'ilike', name)] or domain_search
obj = self.obj.pool.get(model)
xml_id = self._generate_xml_id(name, table)
xml_ref = self.mapped_id_if_exist(model, domain_search, table, name)
fields.append('id')
data.append(xml_id)
obj.import_data(self.cr, self.uid, fields, [data], mode='update', current_module=self.module_name, noupdate=True, context=self.context)
return xml_ref or xml_id
def mapped_id_if_exist(self, model, domain, table, name):
"""
To be use when we want link with and existing object, if the object don't exist
just ignore.
@param domain : search domain to find existing record, should return a unique record
@param xml_id: xml_id give to the mapping
@param name: external_id or name of the object to create if there is no id
@param table: the name of the table of the object to map
@return : the xml_id if the record exist in the db, False otherwise
"""
obj = self.obj.pool.get(model)
ids = obj.search(self.cr, self.uid, domain, context=self.context)
if ids:
xml_id = self._generate_xml_id(name, table)
ir_model_data_obj = obj.pool.get('ir.model.data')
id = ir_model_data_obj._update(self.cr, self.uid, model,
self.module_name, {}, mode='update', xml_id=xml_id,
noupdate=True, res_id=ids[0], context=self.context)
return xml_id
return False
def set_table_list(self, table_list):
"""
Set the list of table to import, this method should be call before run
@param table_list: the list of external table to import
['Leads', 'Opportunity']
"""
self.table_list = table_list
def run(self):
"""
Import all data into openerp,
this is the Entry point to launch the process of import
"""
self.data_started = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.cr = pooler.get_db(self.cr.dbname).cursor()
try:
result = []
imported = set() #to invoid importing 2 times the sames modules
for table in self.table_list:
to_import = self.get_mapping()[table].get('import', True)
if not table in imported:
res = self._resolve_dependencies(self.get_mapping()[table].get('dependencies', []), imported)
result.extend(res)
if to_import:
(position, warning) = self._import_table(table)
result.append((table, position, warning))
imported.add(table)
self.cr.commit()
finally:
self.cr.close()
self.date_ended = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self._send_notification_email(result)
def _resolve_dependencies(self, dep, imported):
"""
import dependencies recursively
and avoid to import twice the same table
"""
result = []
for dependency in dep:
if not dependency in imported:
to_import = self.get_mapping()[dependency].get('import', True)
res = self._resolve_dependencies(self.get_mapping()[dependency].get('dependencies', []), imported)
result.extend(res)
if to_import:
r = self._import_table(dependency)
(position, warning) = r
result.append((dependency, position, warning))
imported.add(dependency)
return result
def _send_notification_email(self, result):
if not self.email:
return
tools.email_send(
'import_sugarcrm@module.openerp',
self.email,
self.get_email_subject(result),
self.get_email_body(result),
)
logger = logging.getLogger('import_sugarcam')
logger.info("Import finished, notification email sended")
def get_email_subject(self, result):
"""
This method define the subject of the email send by openerp at the end of import
@param result: a list of tuple
(table_name, number_of_record_created/updated, warning) for each table
@return the subject of the mail
"""
return "Import of your data finished at %s" % self.date_ended
def get_email_body(self, result):
"""
This method define the body of the email send by openerp at the end of import. The body is separated in two part
the header (@see get_body_header), and the generate body with the list of table and number of record imported.
If you want to keep this it's better to overwrite get_body_header
@param result: a list of tuple
(table_name, number_of_record_created/updated, warning) for each table
@return the subject of the mail
"""
body = "started at %s and finished at %s \n" % (self.data_started, self.date_ended)
for (table, nb, warning) in result:
if not warning:
warning = "with no warning"
else:
warning = "with warning : %s" % warning
body += "%s records were imported from table %s, %s \n" % (nb, table, warning)
return self.get_body_header(result) + "\n\n" + body
def get_body_header(self, result):
"""
@return the first sentences written in the mail's body
"""
return "The import of data \n instance name : %s \n" % self.instance_name
#For example of use see import_sugarcrm

View File

@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
class mapper(object):
"""
super class for all mapper class
They are call before import data
to transform the mapping into real value that we
will import
the call function receive a dictionary with external data
'external_field' : value
"""
def __call__(self, external_values):
raise NotImplementedError()
class dbmapper(mapper):
"""
Super class for mapper that need to access to
data base or any function of the import_framework
self.parent contains a reference to the instance of
the import framework
"""
def set_parent(self, parent):
self.parent = parent
class concat(mapper):
"""
Use : contact('field_name1', 'field_name2', delimiter='_')
concat value of fields using the delimiter, delimiter is optional
and by default is a space
"""
def __init__(self, *arg, **delimiter):
self.arg = arg
self.delimiter = delimiter and delimiter.get('delimiter', ' ') or ' '
def __call__(self, external_values):
return self.delimiter.join(map(lambda x : external_values.get(x,''), self.arg))
class ppconcat(mapper):
"""
Use : contact('field_name1', 'field_name2', delimiter='_')
concat external field name and value of fields using the delimiter,
delimiter is optional and by default is a two line feeds
"""
def __init__(self, *arg, **delimiter):
self.arg = arg
self.delimiter = delimiter and delimiter.get('delimiter', ' ') or '\n\n'
def __call__(self, external_values):
return self.delimiter.join(map(lambda x : x + ": " + external_values.get(x,''), self.arg))
class const(mapper):
"""
Use : const(arg)
return always arg
"""
def __init__(self, val):
self.val = val
def __call__(self, external_values):
return self.val
class value(mapper):
"""
Use : value(external_field_name)
Return the value of the external field name
this is equivalent to the a single string
usefull for call if you want your call get the value
and don't care about the name of the field
call(self.method, value('field1'))
"""
def __init__(self, val, default='', fallback=False):
self.val = val
self.default = default
self.fallback = fallback
def __call__(self, external_values):
val = external_values.get(self.val, self.default)
if self.fallback and (not val or val == self.default):
val = external_values.get(self.fallback, self.default)
return val
class map_val(mapper):
"""
Use : map_val(external_field, val_mapping)
where val_mapping is a dictionary
with external_val : openerp_val
usefull for selection field like state
to map value
"""
def __init__(self, val, map, default='draft'):
self.val = value(val)
self.map = map
self.default = default
def __call__(self, external_values):
return self.map.get(self.val(external_values), self.default)
class ref(dbmapper):
"""
Use : ref(table_name, external_id)
return the xml_id of the ressource
to associate an already imported object with the current object
"""
def __init__(self, table, field_name):
self.table = table
self.field_name = field_name
def __call__(self, external_values):
return self.parent.xml_id_exist(self.table, external_values.get(self.field_name))
class refbyname(dbmapper):
"""
Use : refbyname(table_name, external_name, res.model)
same as ref but use the name of the ressource to find it
"""
def __init__(self, table, field_name, model):
self.table = table
self.field_name = field_name
self.model = model
def __call__(self, external_values):
v = external_values.get(self.field_name, '')
return self.parent.name_exist(self.table, v , self.model)
class call(mapper):
"""
Use : call(function, arg1, arg2)
to call the function with external val follow by the arg specified
"""
def __init__(self, fun, *arg):
self.fun = fun
self.arg = arg
def __call__(self, external_values):
args = []
for arg in self.arg:
if isinstance(arg, mapper):
args.append(arg(external_values))
else:
args.append(arg)
return self.fun(external_values, *args)

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import partner
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Google Import',
'version': '1.0',
'category': 'Generic Modules/Others',
'description': """The module adds google contact in partner address and add google calendar events details in Meeting""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['base', 'google_base_account','crm'],
'init_xml': [],
'update_xml': ['security/ir.model.access.csv',
'sync_google_calendar_view.xml',
'wizard/import_google_data_view.xml',
'wizard/google_import_message_view.xml'
],
'demo_xml': [],
'test': [
#'test/test_sync_google_contact_import_partner.yml',
# 'test/test_sync_google_contact_import_address.yml',
#'test/test_sync_google_calendar.yml',
],
'installable': True,
'active': False,
'certificate': '',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields,osv
class crm_case_categ(osv.osv):
""" Category of Case """
_inherit = "crm.case.categ"
_columns = {
'user_id': fields.many2one('res.users', 'User')
}
crm_case_categ()
# vim:expandtab:smartindent:toabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,5 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_res_users_partner_manager","google.res.partner.manager","base.model_ir_model_data","base.group_partner_manager",1,1,1,0
"access_ir_model_data_partner_manager","ir.model.data.partner.manager","base.model_res_users","base.group_partner_manager",1,1,0,0
"access_google_import_message_partner_manager","google.import.message.partner.manager","model_google_import_message","base.group_partner_manager",1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_res_users_partner_manager google.res.partner.manager base.model_ir_model_data base.group_partner_manager 1 1 1 0
3 access_ir_model_data_partner_manager ir.model.data.partner.manager base.model_res_users base.group_partner_manager 1 1 0 0
4 access_google_import_message_partner_manager google.import.message.partner.manager model_google_import_message base.group_partner_manager 1 1 0 0

View File

@ -0,0 +1,32 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="crm_case_form_view_meet_inherit">
<field name="name">CRM - Meetings Form (Inherited)</field>
<field name="model">crm.meeting</field>
<field name="type">form</field>
<field name="inherit_id" ref="crm.crm_case_form_view_meet"/>
<field name="arch" type="xml">
<field name="categ_id" position="replace">
<field name="categ_id" widget="selection"
string="Meeting Type" groups="base.group_extended"
domain="[('object_id.model', '=', 'crm.meeting'),('user_id','in',[uid, False])]" />
</field>
</field>
</record>
<record model="ir.ui.view" id="crm_case_tree_view_meet_inherit">
<field name="name">CRM - Meetings Tree (Inherited)</field>
<field name="model">crm.meeting</field>
<field name="type">tree</field>
<field name="inherit_id" ref="crm.crm_case_tree_view_meet"/>
<field name="arch" type="xml">
<field name="categ_id" position="replace">
<field name="categ_id" widget="selection"
string="Meeting Type" groups="base.group_extended"
domain="[('object_id.model', '=', 'crm.meeting'),('user_id','in',[uid, False])]" />
</field>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,36 @@
-
In order to test google calendar feature with OpenERP, I import events from
a google account and store them in Meetings.
- |
I create a record for the gmail account for which I want to import the contacts.
-
!record {model: google.login, id: google_login_id0}:
user: testmail.openerp@gmail.com
password: openerptiny
- |
I login into that account.
-
!python {model: google.login}: |
self.login(cr, uid, [ref('google_login_id0')], context)
- |
Now I want to import all the events from all the calendars in the user account.
- |
I select all calendars.
-
!record {model: synchronize.google.import, id: synchronize_google_import_id0}:
calendar_name: all
- |
I import the events from the google calendar.
-
!python {model: synchronize.google.import}: |
self.import_google(cr, uid, [ref('synchronize_google_import_id0')], context={'calendar':True})
- |
Now I check my meetings are created or not.
-
!python {model: crm.meeting}: |
model_obj = self.pool.get('ir.model.data')
meeting_ids = self.search(cr, uid, [])
model_ids = model_obj.search(cr, uid, [('res_id','in',meeting_ids),('model','=','crm.meeting'),('module','=','synchronize_google')])
assert model_ids, 'Meetings not created !'

View File

@ -0,0 +1,34 @@
-
In order to test Importing contacts from any google account into OpenERP,
I use a gmail account and import the contact details and store them as Partner addresses.
- |
I create a record for the gmail account for which I want to import the contacts.
-
!record {model: google.login, id: google_login_id0}:
user: testmail.openerp@gmail.com
password: openerptiny
- |
I login into that account.
-
!python {model: google.login}: |
self.login(cr, uid, [ref('google_login_id0')], context)
- |
Now I select from which group I want to get the contact details.
-
!record {model: synchronize.google.import, id: synchronize_google_import_id0}:
create_partner: create_address
group_name: all
calendar_name: all
- |
I import the contacts and I also check if the contact already exists in db and updates the address.
-
!python {model: synchronize.google.import}: |
self.import_google(cr, uid, [ref('synchronize_google_import_id0')], context={'contact':True})
- |
I check whether the Contacts are created in Partner address or not.
-
!python {model: res.partner.address}: |
addr_obj = self.pool.get('ir.model.data')
data_ids = addr_obj.search(cr, uid, [('model','=','res.partner.address'),('module','=','synchronize_google')])
assert data_ids, 'Addresses not created !'

View File

@ -0,0 +1,36 @@
-
In order to test Importing contacts from any google account into OpenERP,
I use a gmail account and import the contact details and create Partners.
- |
I create a record for the gmail account for which I want to import the contacts.
-
!record {model: google.login, id: google_login_id1}:
user: testmail.openerp@gmail.com
password: openerptiny
- |
I login into that account.
-
!python {model: google.login}: |
self.login(cr, uid, [ref('google_login_id1')], context)
- |
Now I select from which group I want to get the contact details and I want to create partner for all contacts.
-
!record {model: synchronize.google.import, id: synchronize_google_import_id1}:
create_partner: create_all
group_name: all
- |
I import the contacts.
-
!python {model: synchronize.google.import}: |
self.import_google(cr, uid, [ref('synchronize_google_import_id1')], context={'contact':True})
- |
I check whether the Partners are created or not.
-
!python {model: res.partner.address }: |
addr_obj = self.pool.get('ir.model.data')
addr_ids = addr_obj.search(cr, uid, [])
data_ids = addr_obj.search(cr, uid, [('model','=','res.partner.address'),('module','=','synchronize_google')])
address_ids = map(lambda x: x.res_id, [child for child in addr_obj.browse(cr, uid, data_ids) if child.res_id])
partner_ids = map(lambda x: x.partner_id.id, [addr for addr in self.browse(cr, uid, address_ids) if addr.partner_id])
assert partner_ids, 'Partners not created !'

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import import_google
import import_google_data
import google_import_message
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv
from osv import fields
class google_import_message(osv.osv):
"""Import Message"""
_name = "google.import.message"
_description = "Import Message"
_columns = {
'name': fields.text('Message', readonly=True),
}
def default_get(self, cr, uid, fields, context=None):
if context == None:
context = {}
res = super(google_import_message, self).default_get(cr, uid, fields, context=context)
res.update({'name': context.get('message')})
return res
google_import_message()

View File

@ -0,0 +1,25 @@
<?xml version="1.0"?>
<openerp>
<data>
<!-- Import Message Form View -->
<record model="ir.ui.view" id="view_google_import_message_form">
<field name="name">google.import.message.form</field>
<field name="model">google.import.message</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Import Google Data">
<group colspan="4" col="4" width="300">
<field name='name' nolabel='1'/>
</group>
<separator string="" colspan="4"/>
<group colspan="4">
<group colspan="2"/>
<group colspan="2">
<button icon="gtk-ok" special="cancel" string="_Ok"/>
</group>
</group>
</form>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,355 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import re
import urllib
import dateutil
import pytz
from dateutil import *
from pytz import timezone
from datetime import datetime
import time
from osv import *
try:
import gdata
import gdata.contacts.service
import gdata.calendar.service
import gdata.contacts
import gdata.calendar
except ImportError:
raise osv.except_osv(_('Google Contacts Import Error!'), _('Please install gdata-python-client from http://code.google.com/p/gdata-python-client/downloads/list'))
from import_base.import_framework import *
from import_base.mapper import *
class google_import(import_framework):
gd_client = False
calendars = False
contact = False
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
TABLE_CONTACT = 'Contact'
TABLE_ADDRESS ='Address'
TABLE_EVENT = 'Events'
def initialize(self):
google = self.obj.pool.get('google.login')
self.external_id_field = 'Id'
self.gd_client = google.google_login(self.context.get('user'),
self.context.get('password'),
self.context.get('instance'))
if self.context.get('instance') and self.context.get('instance') == 'contact':
self.contact = self.context.get('contact')
if self.context.get('instance') and self.context.get('instance') == 'calendar':
self.calendars = self.context.get('calendars')
def get_mapping(self):
return {
self.TABLE_EVENT: self.get_event_mapping(),
self.TABLE_CONTACT: self.get_contact_mapping(),
self.TABLE_ADDRESS: self.get_address_mapping(),
}
def get_data(self, table):
data_fetching_function = {
self.TABLE_CONTACT: self.get_contact,
self.TABLE_ADDRESS: self.get_contact,
self.TABLE_EVENT: self.get_events,
}
return data_fetching_function.get(table)()
def _get_tinydates(self, stime, etime, au_tz):
stime = dateutil.parser.parse(stime)
etime = dateutil.parser.parse(etime)
try:
au_dt = au_tz.normalize(stime.replace(tzinfo=pytz.utc).astimezone(au_tz))
timestring = datetime.datetime(*au_dt.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
au_dt = au_tz.normalize(etime.replace(tzinfo=pytz.utc).astimezone(au_tz))
timestring_end = datetime.datetime(*au_dt.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
except:
timestring = datetime.datetime(*stime.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
timestring_end = datetime.datetime(*etime.timetuple()[:6]).strftime('%Y-%m-%d %H:%M:%S')
return (timestring, timestring_end)
def _get_rules(self, datas):
new_val = {}
if datas['FREQ'] == 'WEEKLY' and datas.get('BYDAY'):
for day in datas['BYDAY'].split(','):
new_val[day.lower()] = True
datas.pop('BYDAY')
if datas.get('UNTIL'):
until = parser.parse(''.join((re.compile('\d')).findall(datas.get('UNTIL'))))
new_val['end_date'] = until.strftime('%Y-%m-%d')
new_val['end_type'] = 'end_date'
datas.pop('UNTIL')
if datas.get('COUNT'):
new_val['count'] = datas.get('COUNT')
new_val['end_type'] = 'count'
datas.pop('COUNT')
if datas.get('INTERVAL'):
new_val['interval'] = datas.get('INTERVAL')
else:
new_val['interval'] = 1
if datas.get('BYMONTHDAY'):
new_val['day'] = datas.get('BYMONTHDAY')
datas.pop('BYMONTHDAY')
new_val['select1'] = 'date'
if datas.get('BYDAY'):
d = datas.get('BYDAY')
if '-' in d:
new_val['byday'] = d[:2]
new_val['week_list'] = d[2:4].upper()
else:
new_val['byday'] = d[:1]
new_val['week_list'] = d[1:3].upper()
new_val['select1'] = 'day'
if datas.get('BYMONTH'):
new_val['month_list'] = datas.get('BYMONTH')
datas.pop('bymonth')
return new_val
def _get_repeat_status(self, str_google):
rrule = str_google[str_google.find('FREQ'):str_google.find('\nBEGIN')]
status = {}
for rule in rrule.split(';'):
status[rule.split('=')[0]] = rule.split('=')[-1:] and rule.split('=')[-1:][0] or ''
rules = self._get_rules(status)
if status.get('FREQ') == 'WEEKLY':
status.update({'rrule_type': 'weekly'})
status.pop('FREQ')
elif status.get('FREQ') == 'DAILY':
status.update({'rrule_type': 'daily'})
status.pop('FREQ')
elif status.get('FREQ') == 'MONTHLY':
status.update({'rrule_type': 'monthly'})
status.pop('FREQ')
elif status.get('FREQ') == 'YEARLY':
status.update({'rrule_type': 'yearly'})
status.pop('FREQ')
status.update(rules)
return status
def _get_repeat_dates(self, x):
if len(x) > 4:
if x[3].startswith('BY'):
zone_time = x[4].split('+')[-1:][0].split(':')[0][:4]
else:
zone_time = x[3].split('+')[-1:][0].split(':')[0][:4]
else:
zone_time = x[2].split('+')[-1:][0].split(':')[0][:4]
tz_format = zone_time[:2]+':'+zone_time[2:]
repeat_start = x[1].split('\n')[0].split(':')[1]
repeat_end = x[2].split('\n')[0].split(':')[1]
o = repeat_start.split('T')
repeat_start = str(o[0][:4]) + '-' + str(o[0][4:6]) + '-' + str(o[0][6:8])
if len(o) == 2:
repeat_start += ' ' + str(o[1][:2]) + ':' + str(o[1][2:4]) + ':' + str(o[1][4:6])
else:
repeat_start += ' ' + '00' + ':' + '00' + ':' + '00'
p = repeat_end.split('T')
repeat_end = str(p[0][:4]) + '-' + str(p[0][4:6]) + '-' + str(p[0][6:8])
if len(p) == 2:
repeat_end += ' ' + str(p[1][:2]) + ':' + str(p[1][2:4]) + ':' + str(p[1][4:6])
else:
repeat_end += ' ' + '00' + ':' + '00' + ':' + '00'
return (repeat_start, repeat_end, tz_format)
def get_events(self):
if 'tz' in self.context and self.context['tz']:
time_zone = self.context['tz']
else:
time_zone = tools.get_server_timezone()
au_tz = timezone(time_zone)
event_vals = []
for cal in self.calendars:
events_query = gdata.calendar.service.CalendarEventQuery(user=urllib.unquote(cal.split('/')[~0]))
events_query.start_index = 1
events_query.max_results = 1000
event_feed = self.gd_client.GetCalendarEventFeed(events_query.ToUri())
for feed in event_feed.entry:
event = {
'recurrency': False,
'end_date' : False,
'end_type' : False,
'byday': 0,
'count' : 0,
'interval': 1,
'day': False,
'select1': False,
'week_list': "",
'month_list': False,
'rrule_type': False,
}
timestring = timestring_end = datetime.datetime.now().strftime(self.DATETIME_FORMAT)
if feed.when:
timestring, timestring_end = self._get_tinydates(feed.when[0].start_time, feed.when[0].end_time, au_tz)
else:
x = feed.recurrence.text.split(';')
repeat_status = self._get_repeat_status(feed.recurrence.text)
repeat_start, repeat_end, zone_time = self._get_repeat_dates(x)
timestring = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(repeat_start, "%Y-%m-%d %H:%M:%S"))
timestring_end = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(repeat_end, "%Y-%m-%d %H:%M:%S"))
if repeat_status:
repeat_status.update({'recurrency': True})
event.update(repeat_status)
event.update({'id' : feed.id.text,
'DateStart': timestring,
'DateEnd': timestring_end,
'Category':event_feed.title.text,
'Name': feed.title.text or 'No title',
'Description': feed.content.text,
})
event_vals.append(event)
return event_vals
def get_event_category(self, val, name):
fields = ['name', 'object_id']
nameid = 'event_category_'+name
data = [name, 'crm.meeting']
return self.import_object(fields, data, 'crm.case.categ', "crm_case_categ", nameid, [('name', 'ilike', name)])
def get_rec(self, val):
if val.get("recurrency"):
return "1"
return "0"
def get_event_mapping(self):
return {
'model': 'crm.meeting',
'map': {
'id': 'id',
'name': 'Name',
'description': 'Description',
'email_from': 'Email',
'date': 'DateStart',
'date_deadline': 'DateEnd',
'categ_id/id': call(self.get_event_category, value('Category')),
'recurrency': self.get_rec,
'end_date' : 'end_date',
'end_type' : 'end_type',
'byday':'byday',
'count' : 'count',
'interval': 'interval',
'day': 'day',
'select1': 'date',
'week_list': 'week_list',
'month_list':'month_list',
'rrule_type': 'rrule_type',
}
}
def get_contact(self):
table = self.context.get('table')[0]
datas = []
if self.context.get('group_name'):
query = gdata.contacts.service.ContactsQuery()
query.group = self.context.get('group_name')
self.contact = self.gd_client.GetContactsFeed(query.ToUri())
else:
self.contact = self.gd_client.GetContactsFeed()
while self.contact:
for entry in self.contact.entry:
data = {}
data['id'] = entry.id.text
name = tools.ustr(entry.title.text)
if name == "None":
name = entry.email[0].address
data['name'] = name
emails = ','.join(email.address for email in entry.email)
data['email'] = emails
if table == 'Contact':
data.update({'customer': str(self.context.get('customer')),
'supplier': str(self.context.get('supplier'))})
if entry.organization:
if entry.organization.org_name:
data.update({'company': entry.organization.org_name.text})
if entry.organization.org_title:
data.update ({'function': entry.organization.org_title.text})
if entry.phone_number:
for phone in entry.phone_number:
if phone.rel == gdata.contacts.REL_WORK:
data['phone'] = phone.text
if phone.rel == gdata.contacts.PHONE_MOBILE:
data['mobile'] = phone.text
if phone.rel == gdata.contacts.PHONE_WORK_FAX:
data['fax'] = phone.text
datas.append(data)
next = self.contact.GetNextLink()
self.contact = next and self.gd_client.GetContactsFeed(next.href) or None
return datas
def get_contact_mapping(self):
return {
'model': 'res.partner',
'dependencies': [self.TABLE_ADDRESS],
'map': {
'id':'id',
'name': value('company', fallback='name'),
'customer': 'customer',
'supplier': 'supplier',
'address/id': ref(self.TABLE_ADDRESS, 'id'),
}
}
def get_partner_id(self, val):
partner_id = False
company_pool = self.obj.pool.get('res.partner')
if 'company' in val:
partner_ids = company_pool.search(self.cr, self.uid, [('name', '=', val.get('company'))])
return partner_ids and partner_ids[0] or False
contact = self.xml_id_exist(self.TABLE_CONTACT, val.get('id'))
if contact:
partner_id = self.get_mapped_id(self.TABLE_CONTACT, val.get('id'))
return partner_id
def get_address_mapping(self):
return {
'model': 'res.partner.address',
'dependencies': [],
'map': {
'id':'id',
'partner_id/.id': self.get_partner_id,
'name': 'name',
'city': 'city',
'phone': 'phone',
'mobile': 'mobile',
'email': 'email',
'fax': 'fax',
'function': 'function'
}
}

View File

@ -0,0 +1,182 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
try:
import gdata
import gdata.contacts.service
import gdata.contacts
except ImportError:
raise osv.except_osv(_('Google Contacts Import Error!'), _('Please install gdata-python-client from http://code.google.com/p/gdata-python-client/downloads/list'))
from osv import fields
from osv import osv
from tools.translate import _
from import_google import google_import
class google_login_contact(osv.osv_memory):
_inherit = 'google.login'
def _get_next_action(self, cr, uid, context=None):
data_obj = self.pool.get('ir.model.data')
data_id = data_obj._get_id(cr, uid, 'import_google', 'view_synchronize_google_contact_import_form')
view_id = False
if context.get('contact'):
data_id = data_obj._get_id(cr, uid, 'import_google', 'view_synchronize_google_contact_import_form')
if context.get('calendar'):
data_id = data_obj._get_id(cr, uid, 'import_google', 'view_synchronize_google_calendar_import_form')
if data_id:
view_id = data_obj.browse(cr, uid, data_id, context=context).res_id
value = {
'name': _('Import google'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'synchronize.google.import',
'view_id': False,
'context': context,
'views': [(view_id, 'form')],
'type': 'ir.actions.act_window',
'target': 'new',
}
return value
google_login_contact()
class synchronize_google(osv.osv_memory):
_name = 'synchronize.google.import'
def _get_group(self, cr, uid, context=None):
user_obj = self.pool.get('res.users').browse(cr, uid, uid)
google=self.pool.get('google.login')
if not user_obj.gmail_user or not user_obj.gmail_password:
raise osv.except_osv(_('Warning !'), _("No Google Username or password Defined for user.\nPlease define in user view"))
gd_client = google.google_login(user_obj.gmail_user,user_obj.gmail_password,type='group')
if not gd_client:
raise osv.except_osv(_('Error'), _("Authentication fail check the user and password !"))
res = []
query = gdata.contacts.service.GroupsQuery(feed='/m8/feeds/groups/default/full')
if gd_client:
groups = gd_client.GetFeed(query.ToUri())
for grp in groups.entry:
res.append((grp.id.text, grp.title.text))
res.append(('all','All Groups'))
return res
def _get_calendars(self, cr, uid, context=None):
user_obj = self.pool.get('res.users').browse(cr, uid, uid)
google = self.pool.get('google.login')
res = []
try:
gd_client = google.google_login(user_obj.gmail_user, user_obj.gmail_password, type='calendar')
calendars = gd_client.GetAllCalendarsFeed()
for cal in calendars.entry:
res.append((cal.id.text, cal.title.text))
except Exception, e:
raise osv.except_osv('Error !', e.args[0].get('body'))
res.append(('all', 'All Calendars'))
return res
_columns = {
'create_partner': fields.selection([('create_all','Create partner for each contact'),('create_address','Import only address')],'Options'),
'customer': fields.boolean('Customer', help="Check this box to set newly created partner as Customer."),
'supplier': fields.boolean('Supplier', help="Check this box to set newly created partner as Supplier."),
'group_name': fields.selection(_get_group, "Group Name", size=32,help="Choose which group to import, By default it takes all."),
'calendar_name': fields.selection(_get_calendars, "Calendar Name", size=32),
}
_defaults = {
'create_partner': 'create_all',
'group_name': 'all',
'calendar_name': 'all',
}
def import_google(self, cr, uid, ids, context=None):
if context == None:
context = {}
if not ids:
return {'type': 'ir.actions.act_window_close'}
obj = self.browse(cr, uid, ids, context=context)[0]
cust = obj.customer
sup = obj.supplier
tables=[]
user_obj = self.pool.get('res.users').browse(cr, uid, uid)
gmail_user = user_obj.gmail_user
gmail_pwd = user_obj.gmail_password
google = self.pool.get('google.login')
if not gmail_user or not gmail_pwd:
raise osv.except_osv(_('Error'), _("Invalid login detail !\n Specify Username/Password."))
if context.get('contact'):
msg = " You're Contact are import in background, a email will be send when the process is finished to %s"%(user_obj.gmail_user)
gd_client = google.google_login(gmail_user, gmail_pwd, type='contact')
if not gd_client:
raise osv.except_osv(_('Error'), _("Please specify correct user and password !"))
if obj.group_name not in ['all']:
context.update({ 'group_name': obj.group_name})
if obj.create_partner=='create_all':
tables.append('Contact')
else:
tables.append('Address')
context.update({'user': gmail_user,
'password': gmail_pwd,
'instance': 'contact',
'table':tables,
'customer':cust,
'supplier':sup})
elif context.get('calendar'):
msg = " You're Meeting are import in background, a email will be send when the process is finished to %s"%(user_obj.gmail_user)
tables.append('Events')
current_rec = self.browse(cr, uid, ids, context=context)
calendars = False
for rec in current_rec:
if rec.calendar_name != 'all':
calendars = [rec.calendar_name]
else:
calendars = map(lambda x: x[0], [cal for cal in self._get_calendars(cr, uid, context) if cal[0] != 'all'])
context.update({'user': gmail_user,
'password': gmail_pwd,
'calendars': calendars,
'instance': 'calendar'})
imp = google_import(self, cr, uid,'import_google' , "synchronize_google", gmail_user, context)
imp.set_table_list(tables)
imp.start()
context.update({'message': msg})
obj_model = self.pool.get('ir.model.data')
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_google_import_message_form')])
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'google.import.message',
'views': [(resource_id,'form')],
'type': 'ir.actions.act_window',
'target': 'new',
'context': context,
}
synchronize_google()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,91 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_synchronize_google_contact_import_form">
<field name="name">synchronize.base.form</field>
<field name="model">synchronize.google.import</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Import contacts from a google account">
<group colspan="4" col="4" width="430">
<field name="group_name" colspan="4"/>
<separator string="Import Options" colspan="4"/>
<field name="create_partner" colspan="4"/>
<newline/>
<group attrs="{'invisible': [('create_partner','!=','create_all')]}" colspan="4" col="4">
<separator string="Partner status for this group:" colspan="4"/>
<field name="customer" colspan="4"/>
<field name="supplier" colspan="4"/>
</group>
</group>
<separator string="" colspan="4"/>
<group colspan="4" col="4">
<group colspan="2" col="2"/>
<group colspan="2" col="2">
<button special="cancel" string="_Cancel" icon="gtk-cancel"/>
<button name="import_google" string="_Import Contacts" type="object" icon="terp-personal+"/>
</group>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_synchronize_google_calendar_import_form">
<field name="name">synchronize.google.calendar.form</field>
<field name="model">synchronize.google.import</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Import Google Calendar Events">
<group colspan="4" col="4" width="320">
<field name="calendar_name" />
</group>
<separator string="" colspan="4"/>
<group colspan="4" col="4">
<group colspan="2" col="2"/>
<group colspan="2" col="2">
<button special="cancel" string="_Cancel" icon="gtk-cancel"/>
<button name="import_google" string="_Import Events" type="object" icon="terp-calendar"/>
</group>
</group>
</form>
</field>
</record>
<!--
Login Action
-->
<record model="ir.actions.act_window" id="act_google_login_form">
<field name="name">Import Google Calendar</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">google.login</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{'calendar':True}</field>
<field name="view_id" ref="google_base_account.view_google_login_form" />
</record>
<record model="ir.actions.act_window" id="act_google_login_contact_form">
<field name="name">Import Google Contacts</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">google.login</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{'contact':True}</field>
<field name="view_id" ref="google_base_account.view_google_login_form" />
</record>
<menuitem id="menu_sync_contact"
parent="base.menu_address_book"
action="act_google_login_contact_form"
sequence="40" />
<menuitem id="menu_sync_calendar"
parent="crm.menu_meeting_sale"
action="act_google_login_form"
sequence="20" />
</data>
</openerp>

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-05-19 19:08+0000\n"
"Last-Translator: Daniel Fai <Unknown>\n"
"PO-Revision-Date: 2011-06-24 17:11+0000\n"
"Last-Translator: Marco Dieckhoff <Unknown>\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: 2011-05-20 04:34+0000\n"
"X-Generator: Launchpad (build 12959)\n"
"X-Launchpad-Export-Date: 2011-06-25 04:58+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: l10n_be
#: field:partner.vat,test_xml:0
@ -42,7 +42,7 @@ msgstr "Umsatzsteuernummer ist keinem Partner zugeordnet."
#. module: l10n_be
#: constraint:res.company:0
msgid "Error! You can not create recursive companies."
msgstr ""
msgstr "Fehler! Sie können keine rekursiven Unternehmen erzeugen."
#. module: l10n_be
#: code:addons/l10n_be/wizard/l10_be_partner_vat_listing.py:155
@ -149,6 +149,7 @@ msgstr "Jährlicher Bericht über umsatzsteuerpflichtige Kunden"
#: model:ir.module.module,shortdesc:l10n_be.module_meta_information
msgid "Belgium - Plan Comptable Minimum Normalise"
msgstr ""
"Belgien - Genormter minimaler Kontenrahmen (Plan Comptable Minimum Normalise)"
#. module: l10n_be
#: view:partner.vat.list:0
@ -266,7 +267,7 @@ msgstr "Anzahl"
#. module: l10n_be
#: view:l1on_be.vat.declaration:0
msgid "Is Last Declaration"
msgstr ""
msgstr "Letzte Erklärung"
#. module: l10n_be
#: model:ir.model,name:l10n_be.model_partner_vat
@ -304,7 +305,7 @@ msgstr ""
#. module: l10n_be
#: field:vat.listing.clients,turnover:0
msgid "Turnover"
msgstr ""
msgstr "Umsatz"
#. module: l10n_be
#: view:l1on_be.vat.declaration:0

View File

@ -80,7 +80,7 @@ class mailgate_thread(osv.osv):
for thread in self.browse(cr, uid, ids, context=context):
l=[]
for message in thread.message_ids:
l.append((message.user_id and message.user_id.email) or '')
l.append((message.user_id and message.user_id.user_email) or '')
l.append(message.email_from or '')
l.append(message.email_cc or '')
res[thread.id] = l
@ -519,7 +519,7 @@ class mailgate_tool(osv.osv_memory):
body = content
has_plain_text = True
elif part.get_content_maintype() in ('application', 'image'):
if filename :
if filename and attach:
attachments[filename] = part.get_payload(decode=True)
else:
res = part.get_payload(decode=True)

View File

@ -0,0 +1,179 @@
# Chinese (Simplified) translation for openobject-addons
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-01-11 11:15+0000\n"
"PO-Revision-Date: 2011-06-29 16:49+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-06-30 04:34+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: marketing_campaign_crm_demo
#: model:ir.actions.report.xml,name:marketing_campaign_crm_demo.mc_crm_lead_demo_report
msgid "Marketing campaign demo report"
msgstr "市场营销活动显示报表"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_1
msgid ""
"Hello,Thanks for generous interest you have shown in the "
"openERP.Regards,OpenERP Team,"
msgstr "你好感谢你对OpenERP很感兴趣。 OpenERP团队敬上。"
#. module: marketing_campaign_crm_demo
#: model:ir.module.module,description:marketing_campaign_crm_demo.module_meta_information
msgid "Demo data for the module marketing_campaign."
msgstr "模块marketing_campaign的演示数据。"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_4
msgid ""
"Hello,Thanks for showing intrest and buying the OpenERP book.\n"
" If any further information required kindly revert back.\n"
" I really appreciate your co-operation on this.\n"
" Regards,OpenERP Team,"
msgstr ""
"你好感谢你喜欢和购买OpenERP的书。\n"
" 如果需要进一步的消息,请告诉我们。\n"
" 欢迎垂询进一步的信息。\n"
" 敬上!\n"
" OpenERP团队"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_2
msgid "Propose to subscribe to the OpenERP Discovery Day on May 2010"
msgstr "推荐订购2010年5月的OpenERP 发现日 OpenERP Discovery Day"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_6
msgid "Propose paid training to Silver partners"
msgstr "推荐银牌合作伙伴参加付费的培训"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_1
msgid "Thanks for showing interest in OpenERP"
msgstr "感谢您喜欢OpenERP"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_4
msgid "Thanks for buying the OpenERP book"
msgstr "感谢您购买OpenERP book"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_5
msgid "Propose a free technical training to Gold partners"
msgstr "推荐金牌合作伙伴参加免费的技术培训"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_7
msgid ""
"Hello, We have very good offer that might suit you.\n"
" For our silver partners,We are offering Gold partnership.\n"
" If any further information required kindly revert back.\n"
" I really appreciate your co-operation on this.\n"
" Regards,OpenERP Team,"
msgstr ""
"您好,我们有一些很好的服务可能很适合您。\n"
" 对于我们的银牌合作伙伴,我们提供金牌合作伙伴的服务。\n"
" 欢迎垂询进一步的信息。\n"
"\n"
" 敬上!\n"
" OpenERP团队"
#. module: marketing_campaign_crm_demo
#: report:crm.lead.demo:0
msgid "Partner :"
msgstr "合作伙伴:"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_8
msgid ""
"Hello, Thanks for showing intrest and for subscribing to technical "
"training.If any further information required kindly revert back.I really "
"appreciate your co-operation on this.\n"
" Regards,OpenERP Team,"
msgstr ""
"您好, 感谢您有兴趣订购技术培训课程。欢迎垂询进一步的信息。我衷心的感谢您的合作。\n"
" OpenERP团队敬上。"
#. module: marketing_campaign_crm_demo
#: report:crm.lead.demo:0
msgid "Company :"
msgstr "公司:"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_8
msgid "Thanks for subscribing to technical training"
msgstr "感谢您订购技术培训课程"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_3
msgid "Thanks for subscribing to the OpenERP Discovery Day"
msgstr "感谢您订购OpenERP发现日OpenERP Discovery Day"
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_5
msgid ""
"Hello, We have very good offer that might suit you.\n"
" For our gold partners,We are arranging free technical training "
"on june,2010.\n"
" If any further information required kindly revert back.\n"
" I really appreciate your co-operation on this.\n"
" Regards,OpenERP Team,"
msgstr ""
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_3
msgid ""
"Hello,Thanks for showing intrest and for subscribing to the OpenERP "
"Discovery Day.\n"
" If any further information required kindly revert back.\n"
" I really appreciate your co-operation on this.\n"
" Regards,OpenERP Team,"
msgstr ""
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_2
msgid ""
"Hello,We have very good offer that might suit you.\n"
" We propose you to subscribe to the OpenERP Discovery Day on May "
"2010.\n"
" If any further information required kindly revert back.\n"
" We really appreciate your co-operation on this.\n"
" Regards,OpenERP Team,"
msgstr ""
#. module: marketing_campaign_crm_demo
#: model:email.template,def_body_text:marketing_campaign_crm_demo.email_template_6
msgid ""
"Hello, We have very good offer that might suit you.\n"
" For our silver partners,We are paid technical training on "
"june,2010.\n"
" If any further information required kindly revert back.\n"
" I really appreciate your co-operation on this.\n"
" Regards,OpenERP Team,"
msgstr ""
#. module: marketing_campaign_crm_demo
#: model:ir.actions.server,name:marketing_campaign_crm_demo.action_dummy
msgid "Dummy Action"
msgstr ""
#. module: marketing_campaign_crm_demo
#: model:ir.module.module,shortdesc:marketing_campaign_crm_demo.module_meta_information
msgid "marketing_campaign_crm_demo"
msgstr ""
#. module: marketing_campaign_crm_demo
#: model:email.template,def_subject:marketing_campaign_crm_demo.email_template_7
msgid "Propose gold partnership to silver partners"
msgstr ""

View File

@ -7,20 +7,20 @@ 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-05-16 20:21+0000\n"
"PO-Revision-Date: 2011-06-27 18:38+0000\n"
"Last-Translator: Ayhan KIZILTAN <Unknown>\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: 2011-05-17 04:39+0000\n"
"X-Generator: Launchpad (build 12959)\n"
"X-Launchpad-Export-Date: 2011-06-28 04:39+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: mrp
#: field:mrp.production,move_created_ids:0
#: field:mrp.production,move_created_ids2:0
msgid "Moves Created"
msgstr "Oluşan Hareketler"
msgstr "Oluşturulan Hareketler"
#. module: mrp
#: model:ir.actions.act_window,help:mrp.mrp_production_action
@ -40,7 +40,7 @@ msgstr ""
#. module: mrp
#: help:mrp.production,location_src_id:0
msgid "Location where the system will look for components."
msgstr "Sistemin bileşenleri arayacağı lokasyon."
msgstr "Sistemin bileşenleri arayacağı konum."
#. module: mrp
#: field:mrp.production,workcenter_lines:0
@ -50,7 +50,7 @@ msgstr "İş Merkezi Kullanımı"
#. module: mrp
#: view:mrp.routing.workcenter:0
msgid "Routing Work Centers"
msgstr "Rota İş Merkezleri"
msgstr "İş Merkezleri Yönlendirme"
#. module: mrp
#: model:ir.module.module,shortdesc:mrp.module_meta_information
@ -73,14 +73,14 @@ msgid ""
"The 'Minimum stock rule' allows the system to create procurement orders "
"automatically as soon as the minimum stock is reached."
msgstr ""
"'Minimum stok kuralı', minimum stok sayısına erişildiğinde sistemin "
"satınalma emirlerini otomatik olarak oluşturmasına izin verir."
"'Enaz stok kuralı', enaz stok sayısına erişildiğinde sistemin satınalma "
"emirlerini otomatik olarak oluşturmasına izin verir."
#. module: mrp
#: field:mrp.production,picking_id:0
#: field:mrp.production.order,picking_id:0
msgid "Picking list"
msgstr "Seçim listesi"
msgstr "Toplama Listesi"
#. module: mrp
#: code:addons/mrp/report/price.py:121
@ -2114,7 +2114,7 @@ msgstr "Ayar için saat cinsinden süre."
#. module: mrp
#: selection:mrp.production.order,month:0
msgid "December"
msgstr "Eylül"
msgstr "Aralık"
#. module: mrp
#: field:mrp.installer,config_logo:0

View File

@ -7,19 +7,19 @@ 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: 2010-09-09 07:21+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2011-06-23 20:16+0000\n"
"Last-Translator: Ayhan KIZILTAN <Unknown>\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: 2011-04-29 05:38+0000\n"
"X-Generator: Launchpad (build 12758)\n"
"X-Launchpad-Export-Date: 2011-06-24 04:59+0000\n"
"X-Generator: Launchpad (build 13168)\n"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Fees Line"
msgstr ""
msgstr "Ücret Kallemleri"
#. module: mrp_repair
#: help:mrp.repair,state:0
@ -35,6 +35,17 @@ msgid ""
"* The 'Done' state is set when repairing is completed. \n"
"* The 'Cancelled' state is used when user cancel repair order."
msgstr ""
" * 'Taslak' durumu, bir kullanıcı yeni ve onaylanmamış bir onarım siparişi "
"girerken kullanılır. \n"
"* 'Onaylı' durumu, bir kullanıcı bir onarım siparişini onaylarken "
"kullanılır. \n"
"* 'Onarıma Hazır' durumu, kullanıcı onarıma başlarken kullanılır, kullanıcı "
"ancak onarım siparişi onaylandıktan sonra onarıma başlayabilir. "
"\n"
"* 'Faturalandırılacak' durumu, onarımdan önce ya da sonra fatura oluşturmak "
"için kullanılır. \n"
"* 'Bitti' durumu, onarım bittiğinde kullanılır. \n"
"* 'İptal' durumu, onarım siparişi iptal edildiğinde kullanılır."
#. module: mrp_repair
#: field:mrp.repair.line,move_id:0
@ -50,11 +61,16 @@ msgid ""
"date on the production lot in order to know if whether the repair should be "
"invoiced to the customer or not."
msgstr ""
"Onarım siparişleri ürün onarımlarınızı düzenlemenizi sağlar. Bir onarım "
"siparişinde, kaldırılacak bileşenleri ayrıntılayabilir, farklı işlemler için "
"harcadığınız süreleri ekleyebilir, çıkarabilir ve kayıt edebilirsiniz. "
"Onarım siparişi, müşteriye kesilip kesilmeyeceğini belirlemek için ürün "
"partisine ait garanti tarihini kullanır."
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Group By..."
msgstr ""
msgstr "Şuna göre grupla"
#. module: mrp_repair
#: view:mrp.repair:0
@ -69,18 +85,21 @@ msgid ""
"that you can select the locations in the Info tab, if you have the extended "
"view."
msgstr ""
"Bu kutuyu, ürün onarılır onarılmaz teslimatı yapmak isterseniz işaretleyin. "
"İşaretlenirse, seçilen ürün için toplama oluşturulacaktır. Genişletilmiş "
"görünümdeyseniz, Bilgi Sekmesinde konumları seçebileceğinize dikkat edin."
#. module: mrp_repair
#: model:ir.actions.act_window,name:mrp_repair.action_cancel_repair
#: view:mrp.repair.cancel:0
msgid "Cancel Repair Order"
msgstr ""
msgstr "Onarım Siparişini İptal Et"
#. module: mrp_repair
#: field:mrp.repair.fee,to_invoice:0
#: field:mrp.repair.line,to_invoice:0
msgid "To Invoice"
msgstr "Fatura Adresi"
msgstr "Faturalandırılacak"
#. module: mrp_repair
#: report:repair.order:0
@ -90,18 +109,18 @@ msgstr "Yazdırma Tarihi"
#. module: mrp_repair
#: field:mrp.repair.make_invoice,group:0
msgid "Group by partner invoice address"
msgstr "Cari Fatura Adreslerine göre Gruplandı"
msgstr "Paydaş Fatura Adreslerine göre Gruplandır"
#. module: mrp_repair
#: code:addons/mrp_repair/mrp_repair.py:427
#: code:addons/mrp_repair/mrp_repair.py:430
#, python-format
msgid "No product defined on Fees!"
msgstr ""
msgstr "Ücretlerde tanımlanmış ürün yok!"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Set to Draft"
msgstr "Taslak olarak Ayarla"
msgstr "Taslağa Ayarla"
#. module: mrp_repair
#: selection:mrp.repair,state:0
@ -118,13 +137,13 @@ msgstr "Teslimat Adresi"
#: model:ir.model,name:mrp_repair.model_mrp_repair_make_invoice
#: view:mrp.repair:0
msgid "Make Invoice"
msgstr ""
msgstr "Fatura Oluştur"
#. module: mrp_repair
#: field:mrp.repair.fee,price_subtotal:0
#: field:mrp.repair.line,price_subtotal:0
msgid "Subtotal"
msgstr "Alt Toplam"
msgstr "Ara Toplam"
#. module: mrp_repair
#: report:repair.order:0
@ -134,12 +153,12 @@ msgstr "Fatura Adresi:"
#. module: mrp_repair
#: field:mrp.repair,guarantee_limit:0
msgid "Guarantee limit"
msgstr "Garanti limiti"
msgstr "Garanti sınırı"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Notes"
msgstr ""
msgstr "Notlar"
#. module: mrp_repair
#: model:ir.module.module,description:mrp_repair.module_meta_information
@ -154,13 +173,22 @@ msgid ""
" * Repair quotation report\n"
" * Notes for the technician and for the final customer\n"
msgstr ""
"\n"
" Amaç, bütün ürün onarımlarını yapmak için tam bir modül elde "
"etmektir. Aşağıdaki konular bu modülün kapsamındadır:\n"
" * Onarımdaki ürünleri ekle/kaldır\n"
" * Stokları etkile\n"
" * Faturalama (ürünler ve/veya hizmetler)\n"
" * Garanti kavramı\n"
" * Onarım teklifi raporu\n"
" * Teknisyen ve son müşteri için notlar\n"
#. module: mrp_repair
#: field:mrp.repair,amount_tax:0
#: field:mrp.repair.fee,tax_id:0
#: field:mrp.repair.line,tax_id:0
msgid "Taxes"
msgstr "Vergi"
msgstr "Vergiler"
#. module: mrp_repair
#: report:repair.order:0
@ -168,10 +196,10 @@ msgid "Net Total :"
msgstr "Net Toplam :"
#. module: mrp_repair
#: code:addons/mrp_repair/mrp_repair.py:427
#: code:addons/mrp_repair/mrp_repair.py:430
#, python-format
msgid "Warning !"
msgstr ""
msgstr "Uyarı !"
#. module: mrp_repair
#: report:repair.order:0
@ -181,7 +209,7 @@ msgstr "KDV"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Operations"
msgstr "Operasyonlar"
msgstr "İşlemler"
#. module: mrp_repair
#: field:mrp.repair,move_id:0
@ -189,16 +217,16 @@ msgid "Move"
msgstr "Hareket"
#. module: mrp_repair
#: code:addons/mrp_repair/mrp_repair.py:362
#: code:addons/mrp_repair/mrp_repair.py:365
#, python-format
msgid "You have to select a Partner Invoice Address in the repair form !"
msgstr ""
msgstr "Onarım formundan bir Paydaş Adresi seçmelisiniz !"
#. module: mrp_repair
#: model:ir.actions.act_window,name:mrp_repair.action_repair_order_tree
#: model:ir.ui.menu,name:mrp_repair.menu_repair_order
msgid "Repair Orders"
msgstr "Onarım Emirleri"
msgstr "Onarım Siparişleri"
#. module: mrp_repair
#: model:ir.actions.report.xml,name:mrp_repair.report_mrp_repair
@ -208,13 +236,13 @@ msgstr "Teklif / Sipariş"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Extra Info"
msgstr "Extra Bilgi"
msgstr "Ek Bilgi"
#. module: mrp_repair
#: field:mrp.repair.fee,repair_id:0
#: field:mrp.repair.line,repair_id:0
msgid "Repair Order Reference"
msgstr ""
msgstr "Onarım Siparişi Referansı"
#. module: mrp_repair
#: selection:mrp.repair.line,state:0
@ -222,10 +250,10 @@ msgid "Draft"
msgstr "Taslak"
#. module: mrp_repair
#: code:addons/mrp_repair/mrp_repair.py:376
#: code:addons/mrp_repair/mrp_repair.py:379
#, python-format
msgid "No account defined for partner \"%s\"."
msgstr ""
msgstr "\"%s\" Paydaşı için tanımlanmış bir hesap yok."
#. module: mrp_repair
#: view:mrp.repair:0
@ -237,33 +265,34 @@ msgstr "Onaylandı"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Repairs order"
msgstr "Onarım Emri"
msgstr "Onarım Siparişi"
#. module: mrp_repair
#: report:repair.order:0
msgid "Repair Order N° :"
msgstr "Onarım Emri N° :"
msgstr "Onarım Siparişi N° :"
#. module: mrp_repair
#: field:mrp.repair,prodlot_id:0
#: field:mrp.repair.line,prodlot_id:0
#: report:repair.order:0
msgid "Lot Number"
msgstr "Lot Numarası"
msgstr "Parti Numarası"
#. module: mrp_repair
#: field:mrp.repair,fees_lines:0
msgid "Fees Lines"
msgstr ""
msgstr "Ücret Kalemleri"
#. module: mrp_repair
#: field:mrp.repair.line,type:0
msgid "Type"
msgstr "Tipi"
msgstr "Tür"
#. module: mrp_repair
#: report:repair.order:0
msgid "Fees Line(s)"
msgstr ""
msgstr "Ücret Kalemi(leri)"
#. module: mrp_repair
#: selection:mrp.repair,state:0
@ -276,17 +305,17 @@ msgid "Shipping address :"
msgstr "Sevk Adresi :"
#. module: mrp_repair
#: code:addons/mrp_repair/mrp_repair.py:376
#: code:addons/mrp_repair/mrp_repair.py:405
#: code:addons/mrp_repair/mrp_repair.py:434
#: code:addons/mrp_repair/mrp_repair.py:379
#: code:addons/mrp_repair/mrp_repair.py:408
#: code:addons/mrp_repair/mrp_repair.py:437
#, python-format
msgid "Error !"
msgstr ""
msgstr "Hata !"
#. module: mrp_repair
#: field:mrp.repair.line,product_uom_qty:0
msgid "Quantity (UoM)"
msgstr "Miktar (Birim)"
msgstr "Miktar (Ölçü Birimi)"
#. module: mrp_repair
#: help:mrp.repair.line,state:0
@ -299,6 +328,14 @@ msgid ""
" \n"
"* The 'Cancelled' state is set automatically when user cancel repair order."
msgstr ""
" * 'Taslak' durumu, onarım siparişi taslak durumundayken otomatik olarak "
"ayarlanır. \n"
"* 'Onaylı' durumu, onarım siparişi onaylı durumdayken otomatik olarak "
"ayarlanır. \n"
"* 'Done' durumu, onarım siparişi tamamlandığında otomatik olarak ayarlanır. "
" \n"
"* 'Cancelled' durumu, kullanıcı onarım siparişini iptal ettiğinde otomatik "
"olarak ayarlanır."
#. module: mrp_repair
#: report:repair.order:0
@ -311,6 +348,8 @@ msgid ""
"This operation will cancel the Repair process, but will not cancel it's "
"Invoice. Do you want to continue?"
msgstr ""
"Bu eylem Onarım işlemini iptal edecektir ama faturasını iptal etmeyecektir. "
"Devam etmek istiyor musunuz?"
#. module: mrp_repair
#: field:mrp.repair,pricelist_id:0
@ -327,17 +366,17 @@ msgstr "Teklif Notları"
#: code:addons/mrp_repair/wizard/cancel_repair.py:49
#, python-format
msgid "Warning!"
msgstr ""
msgstr "Uyarı!"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Search Reair Orders"
msgstr ""
msgstr "Onarım Siparişi Ara"
#. module: mrp_repair
#: report:repair.order:0
msgid "(Add)"
msgstr ""
msgstr "(Ekle)"
#. module: mrp_repair
#: model:ir.model,name:mrp_repair.model_mrp_repair_line
@ -349,7 +388,7 @@ msgstr "Onarım Kalemi"
#: view:mrp.repair:0
#: field:mrp.repair,partner_id:0
msgid "Partner"
msgstr "Ortak"
msgstr "Paydaş"
#. module: mrp_repair
#: field:mrp.repair,invoice_method:0
@ -364,7 +403,7 @@ msgstr "Onarıldı"
#. module: mrp_repair
#: model:ir.module.module,shortdesc:mrp_repair.module_meta_information
msgid "Products Repairs Module - Manage All products Repairs"
msgstr ""
msgstr "Ürün Onarımları Modülü - Bütün ürün Onarımlarını Yönet"
#. module: mrp_repair
#: field:mrp.repair.fee,invoice_line_id:0
@ -385,7 +424,7 @@ msgstr "Onarım Öncesi"
#. module: mrp_repair
#: field:mrp.repair,location_id:0
msgid "Current Location"
msgstr "Geçerli Lokasyon"
msgstr "Geçerli Konum"
#. module: mrp_repair
#: view:mrp.repair.cancel:0
@ -402,7 +441,7 @@ msgstr "Faturalandı"
#. module: mrp_repair
#: view:mrp.repair.cancel:0
msgid "No"
msgstr "Hayır"
msgstr "No"
#. module: mrp_repair
#: view:mrp.repair.make_invoice:0
@ -412,78 +451,78 @@ msgstr "Faturaları Oluştur"
#. module: mrp_repair
#: report:repair.order:0
msgid "(Remove)"
msgstr ""
msgstr "(Kaldır)"
#. module: mrp_repair
#: selection:mrp.repair.line,type:0
msgid "Add"
msgstr ""
msgstr "Ekle"
#. module: mrp_repair
#: view:mrp.repair.make_invoice:0
msgid "Do you really want to create the invoice(s) ?"
msgstr ""
msgstr "Gerçekten fatura(ları) oluşturmak istiyor musunuz?"
#. module: mrp_repair
#: field:mrp.repair,name:0
msgid "Repair Reference"
msgstr ""
msgstr "Onarım Referansı"
#. module: mrp_repair
#: model:ir.model,name:mrp_repair.model_mrp_repair
msgid "Repair Order"
msgstr ""
msgstr "Onarım Siparişi"
#. module: mrp_repair
#: selection:mrp.repair,state:0
msgid "Under Repair"
msgstr "Onarımdakiler"
msgstr "Onarımda"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Ready To Repair"
msgstr ""
msgstr "Onarıma Hazır"
#. module: mrp_repair
#: field:mrp.repair,amount_untaxed:0
msgid "Untaxed Amount"
msgstr "Tutar"
msgstr "Vergisiz Tutar"
#. module: mrp_repair
#: report:repair.order:0
msgid "Guarantee Limit"
msgstr "Garanti Limiti"
msgstr "Garanti Sınırı"
#. module: mrp_repair
#: field:mrp.repair,default_address_id:0
msgid "unknown"
msgstr ""
msgstr "bilinmeyen"
#. module: mrp_repair
#: field:mrp.repair,product_id:0
#: report:repair.order:0
msgid "Product to Repair"
msgstr "Ürün Onarımı"
msgstr "Onarılacak Ürün"
#. module: mrp_repair
#: report:repair.order:0
msgid "N° :"
msgstr ""
msgstr "N° :"
#. module: mrp_repair
#: help:mrp.repair,pricelist_id:0
msgid "The pricelist comes from the selected partner, by default."
msgstr ""
msgstr "Fiyat Listesi, varsayılan olarak seçilen paydaşa aittir."
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Date"
msgstr ""
msgstr "Tarih"
#. module: mrp_repair
#: model:ir.model,name:mrp_repair.model_mrp_repair_fee
msgid "Repair Fees Line"
msgstr ""
msgstr "Onarım Ücretleri Kalemi"
#. module: mrp_repair
#: selection:mrp.repair,state:0
@ -498,7 +537,7 @@ msgstr "Hesapla"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Confirm Repair"
msgstr "Düzeltmeyi Onayla"
msgstr "Onarımı Onayla"
#. module: mrp_repair
#: report:repair.order:0
@ -511,16 +550,16 @@ msgid "End Repair"
msgstr "Onarım Bitir"
#. module: mrp_repair
#: code:addons/mrp_repair/mrp_repair.py:405
#: code:addons/mrp_repair/mrp_repair.py:434
#: code:addons/mrp_repair/mrp_repair.py:408
#: code:addons/mrp_repair/mrp_repair.py:437
#, python-format
msgid "No account defined for product \"%s\"."
msgstr ""
msgstr "\"%s\" Ürünü için tanımlı hesap yok."
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Quotations"
msgstr ""
msgstr "Teklifler"
#. module: mrp_repair
#: field:mrp.repair.fee,product_uom_qty:0
@ -538,7 +577,7 @@ msgstr "Onarımı Başlat"
#: field:mrp.repair,state:0
#: field:mrp.repair.line,state:0
msgid "State"
msgstr ""
msgstr "Durum"
#. module: mrp_repair
#: view:mrp.repair:0
@ -566,6 +605,10 @@ msgid ""
"operation and fee you will add will be set as 'not to invoiced' by default. "
"Note that you can change manually afterwards."
msgstr ""
"Garanti sınırı şöyle hesaplanır: son işlem tarihi + seçilen ürüne ait "
"tanımlı garanti. Eğer geçerli tarih garanti sınırının altındaysa, "
"ekleyeceğiniz her işlem ve ücret varsayılan olarak faturalandırılmayacak "
"olarak işaretlenir. Daha sonra el ile değiştirebileceğinizi unutmayın."
#. module: mrp_repair
#: field:mrp.repair,invoice_id:0
@ -575,18 +618,18 @@ msgstr "Fatura"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Fees"
msgstr ""
msgstr "Ücretler"
#. module: mrp_repair
#: selection:mrp.repair,state:0
#: view:mrp.repair.make_invoice:0
msgid "Cancel"
msgstr "İptal"
msgstr "Vazgeç"
#. module: mrp_repair
#: field:mrp.repair.line,location_dest_id:0
msgid "Dest. Location"
msgstr "Hedef Lokasyon"
msgstr "Hedef Konum"
#. module: mrp_repair
#: report:repair.order:0
@ -596,12 +639,12 @@ msgstr "Operasyon Kalemi (leri)"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "History"
msgstr "Geçmiş Bilgisi"
msgstr "Geçmiş"
#. module: mrp_repair
#: field:mrp.repair,location_dest_id:0
msgid "Delivery Location"
msgstr "Teslimat Lokasyonu"
msgstr "Teslimat Konumu"
#. module: mrp_repair
#: help:mrp.repair,invoice_method:0
@ -610,11 +653,14 @@ msgid ""
"selected is different from 'No Invoice', it also allow you to select the "
"pricelist and invoicing address."
msgstr ""
"Bu alan, sipariş emrine ait işakışını değiştirmenizi sağlar. Seçilen değer "
"'Faturasız' dan farklı ise, fiyat listesi ve fatura adresi seçmenize izin "
"verir."
#. module: mrp_repair
#: view:mrp.repair.make_invoice:0
msgid "Create Invoice"
msgstr ""
msgstr "Fatura Oluştur"
#. module: mrp_repair
#: field:mrp.repair.fee,name:0
@ -626,12 +672,12 @@ msgstr "Açıklama"
#. module: mrp_repair
#: field:mrp.repair,operations:0
msgid "Operation Lines"
msgstr "Operasyon Kalemleri"
msgstr "İşlem Kalemleri"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "invoiced"
msgstr ""
msgstr "faturalanmış"
#. module: mrp_repair
#: view:mrp.repair:0
@ -643,7 +689,7 @@ msgstr "Ürün"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Invoice Corrected"
msgstr ""
msgstr "Fatura Düzeltildi"
#. module: mrp_repair
#: report:repair.order:0
@ -653,13 +699,13 @@ msgstr "Fiyat"
#. module: mrp_repair
#: field:mrp.repair,deliver_bool:0
msgid "Deliver"
msgstr "Teslimat"
msgstr "Teslim Et"
#. module: mrp_repair
#: view:mrp.repair:0
#: field:mrp.repair,internal_notes:0
msgid "Internal Notes"
msgstr "Dahili Notlar"
msgstr "İç Notlar"
#. module: mrp_repair
#: report:repair.order:0
@ -669,24 +715,24 @@ msgstr "Vergi:"
#. module: mrp_repair
#: field:mrp.repair,picking_id:0
msgid "Picking"
msgstr ""
msgstr "Toplama"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "Untaxed amount"
msgstr "Tutar"
msgstr "Vergisiz Tutar"
#. module: mrp_repair
#: code:addons/mrp_repair/wizard/cancel_repair.py:41
#, python-format
msgid "Active ID is not Found"
msgstr ""
msgstr "Etkin No Bulunmadı"
#. module: mrp_repair
#: code:addons/mrp_repair/wizard/cancel_repair.py:49
#, python-format
msgid "Repair order is not invoiced."
msgstr ""
msgstr "Onarım siparişi faturanladırılmamış"
#. module: mrp_repair
#: view:mrp.repair:0
@ -696,12 +742,12 @@ msgstr "Toplam Tutar"
#. module: mrp_repair
#: view:mrp.repair:0
msgid "UoM"
msgstr "Birim"
msgstr "Ölçü Birimi"
#. module: mrp_repair
#: selection:mrp.repair.line,type:0
msgid "Remove"
msgstr ""
msgstr "Kaldır"
#. module: mrp_repair
#: field:mrp.repair.fee,product_uom:0
@ -750,6 +796,7 @@ msgstr "Durumlar"
msgid ""
"This field allow you to choose the parner that will be invoiced and delivered"
msgstr ""
"Bu alan faturalandırılacak ve teslimat yapılacak paydaşı seçmenizi sağlar"
#. module: mrp_repair
#: field:mrp.repair,amount_total:0
@ -762,10 +809,10 @@ msgid "Ready to Repair"
msgstr "Onarıma Hazır"
#. module: mrp_repair
#: code:addons/mrp_repair/mrp_repair.py:362
#: code:addons/mrp_repair/mrp_repair.py:365
#, python-format
msgid "No partner !"
msgstr ""
msgstr "Paydaş Yok !"
#~ msgid "Invalid XML for View Architecture!"
#~ msgstr "Görüntüleme mimarisi için Geçersiz XML"

File diff suppressed because it is too large Load Diff

24
addons/portal/__init__.py Normal file
View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 OpenERP S.A (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import portal
import wizard
import ir_ui_menu

View File

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 OpenERP S.A (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name" : "Portal",
"version" : "0.3",
"depends" : ["base", "share"],
"author" : "OpenERP SA",
"category": 'Tools',
"description": """
This module defines 'portals' to customize the access to your OpenERP database
for external users.
A portal defines customized user menu and access rights for a group of users
(the ones associated to that portal). It also associates user groups to the
portal users (adding a group in the portal automatically adds it to the portal
users, etc). That feature is very handy when used in combination with the
module 'share'.
""",
'website': 'http://www.openerp.com',
'data': ['security/portal_security.xml',
'security/ir.model.access.csv',
'portal_view.xml',
'wizard_view.xml',
'wizard/share_wizard_view.xml',
],
'installable': True,
'certificate' : '',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 OpenERP S.A (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv, fields
class portal_menu(osv.osv):
"""Inherited menu class to customized the login search for menus,
as web client 6.0 does not support the menu action properly yet"""
_inherit = 'ir.ui.menu'
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
if context is None:
context = {}
# if the current user belongs to a portal, we have to
# rewrite any search on the top menus to be under the
# portal's root menu:
if not context.get('ir.ui.menu.full_list') and uid != 1 and \
args and len(args) == 1 and \
len(args[0]) == 3 and \
(args[0][0] == 'parent_id' \
and args[0][1] == '=' \
and args[0][2] == False):
Portals = self.pool.get('res.portal')
portal_id = Portals.search(cr, uid, [('group_id.users', 'in', uid)])
if portal_id:
assert len(portal_id) == 1, "Users may only belong to one portal at a time!"
portal_data = Portals.read(cr, uid, portal_id[0], ['parent_menu_id'])
menu_id_pair = portal_data.get('parent_menu_id') # (ID, Name)
if menu_id_pair:
args = [('parent_id', '=', menu_id_pair[0])]
ids = super(portal_menu, self).search(cr, uid, args, offset=0,
limit=None, order=order, context=context, count=False)
return len(ids) if count else ids
portal_menu()

246
addons/portal/portal.py Normal file
View File

@ -0,0 +1,246 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 OpenERP S.A (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv, fields
from tools.translate import _
class portal(osv.osv):
_name = 'res.portal'
_description = 'Portal'
_rec_name = 'group_id'
_columns = {
'group_id': fields.many2one('res.groups', required=True,
string='Portal Group',
help=_('This group defines the users associated to this portal')),
'user_ids': fields.related('group_id', 'users',
type='many2many', relation='res.users', store=False,
string='Portal Users'),
'menu_action_id': fields.many2one('ir.actions.actions', readonly=True,
string='Menu Action',
help=_("What replaces the standard menu for the portal's users")),
'parent_menu_id': fields.many2one('ir.ui.menu',
string='Parent Menu',
help=_('The menu action opens the submenus of this menu item')),
'widget_ids': fields.one2many('res.portal.widget', 'portal_id',
string='Widgets',
help=_('Widgets assigned to portal users')),
}
_sql_constraints = [
('unique_group', 'UNIQUE(group_id)', _('Portals must have distinct groups.'))
]
def copy(self, cr, uid, id, default={}, context=None):
""" override copy(): group_id and menu_action_id must be different """
# copy the former group_id
groups_obj = self.pool.get('res.groups')
group_id = self.browse(cr, uid, id, context).group_id.id
default['group_id'] = groups_obj.copy(cr, uid, group_id, {}, context)
default['menu_action_id'] = None
return super(portal, self).copy(cr, uid, id, default, context)
def create(self, cr, uid, values, context=None):
""" extend create() to assign the portal group and menu to users """
# first create the 'menu_action_id'
assert not values.get('menu_action_id')
values['menu_action_id'] = self._create_menu_action(cr, uid, values, context)
if 'user_ids' in values:
# set menu action of users
user_values = {'menu_id': values['menu_action_id']}
# values['user_ids'] should match [(6, 0, IDs)]
for id in get_many2many(values['user_ids']):
values['user_ids'].append((1, id, user_values))
# create portal
portal_id = super(portal, self).create(cr, uid, values, context)
# assign widgets to users
if 'user_ids' in values:
self._assign_widgets_to_users(cr, uid, [portal_id], context)
return portal_id
def name_get(self, cr, uid, ids, context=None):
portals = self.browse(cr, uid, ids, context)
return [(p.id, p.group_id.name) for p in portals]
def name_search(self, cr, uid, name='', args=None, operator='ilike', context=None, limit=100):
# first search for group names that match
groups_obj = self.pool.get('res.groups')
group_names = groups_obj.name_search(cr, uid, name, args, operator, context, limit)
# then search for portals that match the groups found so far
domain = [('group_id', 'in', [gn[0] for gn in group_names])]
ids = self.search(cr, uid, domain, context=context)
return self.name_get(cr, uid, ids, context)
def write(self, cr, uid, ids, values, context=None):
""" extend write() to reflect menu and groups changes on users """
# first apply portal changes
super(portal, self).write(cr, uid, ids, values, context)
portals = self.browse(cr, uid, ids, context)
# if 'menu_action_id' has changed, set menu_id on users
if 'menu_action_id' in values:
user_values = {'menu_id': values['menu_action_id']}
user_ids = [u.id for p in portals for u in p.user_ids if u.id != 1]
self.pool.get('res.users').write(cr, uid, user_ids, user_values, context)
# if parent_menu_id has changed, apply the change on menu_action_id
if 'parent_menu_id' in values:
act_window_obj = self.pool.get('ir.actions.act_window')
action_ids = [p.menu_action_id.id for p in portals]
action_values = {'domain': [('parent_id', '=', values['parent_menu_id'])]}
act_window_obj.write(cr, uid, action_ids, action_values, context)
# assign portal widgets to users, if widgets or users changed
if ('user_ids' in values) or ('widget_ids' in values):
self._assign_widgets_to_users(cr, uid, ids, context)
return True
def _create_menu_action(self, cr, uid, values, context=None):
# create a menu action that opens the menu items below parent_menu_id
groups_obj = self.pool.get('res.groups')
group_name = groups_obj.browse(cr, uid, values['group_id'], context).name
actions_obj = self.pool.get('ir.actions.act_window')
action_values = {
'name': group_name + ' Menu',
'type': 'ir.actions.act_window',
'usage': 'menu',
'res_model': 'ir.ui.menu',
'view_type': 'tree',
'view_id': self._res_xml_id(cr, uid, 'base', 'view_menu'),
'domain': [('parent_id', '=', values.get('parent_menu_id', False))],
}
return actions_obj.create(cr, uid, action_values, context)
def do_create_menu(self, cr, uid, ids, context=None):
""" create a parent menu for the given portals """
menu_obj = self.pool.get('ir.ui.menu')
menu_root = self._res_xml_id(cr, uid, 'portal', 'portal_menu')
for p in self.browse(cr, uid, ids, context):
# create a menuitem under 'portal.portal_menu'
menu_values = {
'name': p.group_id.name + ' Menu',
'parent_id': menu_root,
'groups_id': [(6, 0, [p.group_id.id])],
}
menu_id = menu_obj.create(cr, uid, menu_values, context)
# set the parent_menu_id to item_id
self.write(cr, uid, [p.id], {'parent_menu_id': menu_id}, context)
return True
def _assign_widgets_to_users(self, cr, uid, ids, context=None):
""" assign portal widgets to users for the given portal ids """
widget_user_obj = self.pool.get('res.widget.user')
portals = self.browse(cr, uid, ids, context)
for p in portals:
for w in p.widget_ids:
values = {'sequence': w.sequence, 'widget_id': w.widget_id.id}
for u in p.user_ids:
if u.id == 1: continue
values['user_id'] = u.id
widget_user_obj.create(cr, uid, values, context)
def onchange_group(self, cr, uid, ids, group_id, context=None):
""" update the users list when the group changes """
user_ids = False
if group_id:
group = self.pool.get('res.groups').browse(cr, uid, group_id, context)
user_ids = [u.id for u in group.users]
return {
'value': {'user_ids': user_ids}
}
def _res_xml_id(self, cr, uid, module, xml_id):
""" return the resource id associated to the given xml_id """
data_obj = self.pool.get('ir.model.data')
data_id = data_obj._get_id(cr, uid, module, xml_id)
return data_obj.browse(cr, uid, data_id).res_id
portal()
class users(osv.osv):
_name = 'res.users'
_inherit = 'res.users'
def default_get(self, cr, uid, fields, context=None):
""" override default value of menu_id for portal users """
defs = super(users, self).default_get(cr, uid, fields, context)
# the value of 'menu_id' is passed in context by the portal form view
if ('menu_id' in context) and ('menu_id' in fields):
defs['menu_id'] = context['menu_id']
return defs
users()
class portal_widget(osv.osv):
"""
Similar to res.widget.user (res_widget.py), but with a portal instead.
New users in a portal are assigned the portal's widgets.
"""
_name='res.portal.widget'
_description = 'Portal Widgets'
_order = 'sequence'
_columns = {
'sequence': fields.integer('Sequence'),
'portal_id': fields.many2one('res.portal', select=1,
string='Portal'),
'widget_id': fields.many2one('res.widget', required=True, ondelete='cascade',
string='Widget'),
}
def create(self, cr, uid, values, context=None):
domain = [('portal_id', '=', values.get('portal_id')),
('widget_id', '=', values.get('widget_id'))]
existing = self.search(cr, uid, domain, context=context)
if existing:
res = existing[0]
else:
res = super(portal_widget, self).create(cr, uid, values, context=context)
return res
portal_widget()
# utils
def get_browse_id(obj):
""" return the id of a browse() object, or None """
return (obj and obj.id or None)
def get_browse_ids(objs):
""" return the ids of a list of browse() objects """
return map(get_browse_id, objs)
def get_many2many(arg):
""" get the list of ids from a many2many 'values' field """
assert len(arg) == 1 and arg[0][0] == 6 # arg = [(6, _, IDs)]
return arg[0][2]

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- menu Administration/Portals -->
<menuitem name="Portals" id="portal_menu" parent="base.menu_administration" groups="group_portal_manager"/>
<!-- menu Administration/Portals/Portals -->
<record id="portal_list_action" model="ir.actions.act_window">
<field name="name">Portals</field>
<field name="res_model">res.portal</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help">
A portal helps defining specific views and rules for a group of users (the
portal group). A portal is associated with a menu; when changed, the portal menu
is assigned to the portal's users. Groups can be added to or removed from the
portal's users.
</field>
</record>
<menuitem name="Portals" id="portal_list_menu"
parent="portal_menu" sequence="1" action="portal_list_action"/>
<!-- portal list view -->
<record id="portal_list" model="ir.ui.view">
<field name="name">Portal List</field>
<field name="model">res.portal</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Portal List">
<field name="group_id"/>
<field name="user_ids"/>
</tree>
</field>
</record>
<!-- portal search view -->
<record id="portal_search" model="ir.ui.view">
<field name="name">Portal Search</field>
<field name="model">res.portal</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Portal Search">
<field name="group_id"/>
<field name="user_ids"/>
<field name="menu_action_id"/>
<field name="parent_menu_id"/>
</search>
</field>
</record>
<!-- portal form view -->
<record id="portal_form" model="ir.ui.view">
<field name="name">Portal Form</field>
<field name="model">res.portal</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Portal Form">
<field name="group_id" on_change="onchange_group(group_id)"/>
<notebook>
<page string="Users">
<field name="user_ids" nolabel="1" colspan="3"
context="{'menu_id': menu_action_id}"/>
<group name="user_panel" colspan="1"/>
<!-- wizards insert buttons inside the group 'user_panel' -->
</page>
<page string="Menu &amp; Widgets">
<group colspan="2" col="2">
<separator string="Portal Menu" colspan="2"/>
<group colspan="2" col="2">
<field name="menu_action_id"/>
<field name="parent_menu_id"
context="{'ir.ui.menu.full_list': True}"/>
</group>
<button name="do_create_menu" type="object"
string="Create Parent Menu"/>
</group>
<group colspan="2" col="2">
<separator string="Portal Widgets" colspan="2"/>
<field name="widget_ids" nolabel="1" rowspan="7">
<tree string="Widgets" editable="bottom">
<field name="sequence"/>
<field name="widget_id"/>
</tree>
</field>
</group>
</page>
</notebook>
</form>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,5 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_portal_manager","access.portal.manager","model_res_portal","group_portal_manager",1,1,1,1
"access_portal_all","access.portal.all","model_res_portal",,1,0,0,0
"access_portal_widget_all","access.portal.widget.all","model_res_portal_widget",,1,0,0,0
"access_portal_widget_manager","access.portal.widget.manager","model_res_portal_widget",group_portal_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_portal_manager access.portal.manager model_res_portal group_portal_manager 1 1 1 1
3 access_portal_all access.portal.all model_res_portal 1 0 0 0
4 access_portal_widget_all access.portal.widget.all model_res_portal_widget 1 0 0 0
5 access_portal_widget_manager access.portal.widget.manager model_res_portal_widget group_portal_manager 1 1 1 1

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="group_portal_manager" model="res.groups">
<field name="name">Portal / Manager</field>
<field name="comment">
Members of this groups have access to the portal definitions, and can easily manage the users, access right and menus of portal users.
Members of this group who are also members of the Sharing/User group get additional options in the sharing wizard:
- they may select a list of existing users to share with, without having to give a list of emails
- they may choose to share with a Portal group instead of sharing with users, effectively extending the Portal content
These features are useful for setting up Portals, but this could result in an alteration of the system's security policy.
Therefore this should be granted only to trustworthy users who know the security policy very well.
This group must not be deleted.</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 OpenERP S.A (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import share_wizard
import groups_wizard

View File

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 OpenERP S.A (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv, fields
from tools.translate import _
class groups_wizard(osv.osv_memory):
_name = 'res.portal.groups'
_description = 'Portal Groups Wizard'
_columns = {
'portal_id': fields.many2one('res.portal', required=True, readonly=True,
string='Portal'),
'add_group_ids': fields.many2many('res.groups',
'portal_groups_add', 'portal_groups_id', 'group_ids',
string='Add Groups'),
'remove_group_ids': fields.many2many('res.groups',
'portal_groups_remove', 'portal_groups_id', 'group_ids',
string='Remove Groups'),
}
_defaults = {
'portal_id': (lambda self,cr,uid,context: context and context.get('active_id'))
}
def do_apply(self, cr, uid, ids, context=None, *args):
assert len(ids) == 1
wizard = self.browse(cr, uid, ids[0], context)
# select all portal users except admin
user_ids = [u.id for u in wizard.portal_id.user_ids if u.id != 1]
# apply group adds and removals to portal users
add_gids = [(4, g.id) for g in wizard.add_group_ids]
rem_gids = [(3, g.id) for g in wizard.remove_group_ids]
user_values = {'groups_id': add_gids + rem_gids}
self.pool.get('res.users').write(cr, uid, user_ids, user_values, context)
# return an empty dictionary to close the wizard window
return {}
groups_wizard()

View File

@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2011 OpenERP S.A (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv, fields
from tools.translate import _
UID_ROOT = 1
SHARED_DOCS_MENU = "Documents"
SHARED_DOCS_CHILD_MENU = "Shared Documents"
class share_wizard_portal(osv.osv_memory):
"""Inherited share wizard to automatically create appropriate
menus in the selected portal upon sharing with a portal group."""
_inherit = "share.wizard"
def _user_type_selection(self, cr, uid, context=None):
selection = super(share_wizard_portal, self)._user_type_selection(cr, uid, context=context)
selection.extend([('existing','Users you already shared with'),
('groups','Existing Groups (e.g Portal Groups)')])
return selection
_columns = {
'user_ids': fields.many2many('res.users', 'share_wizard_res_user_rel', 'share_id', 'user_id', 'Existing users', domain=[('share', '=', True)]),
'group_ids': fields.many2many('res.groups', 'share_wizard_res_group_rel', 'share_id', 'group_id', 'Existing groups', domain=[('share', '=', False)]),
# no clean way to extend selection yet, copy the field.
'user_type': fields.selection(_user_type_selection,'Users to share with',
help="Select the type of user(s) you would like to share data with."),
}
def is_portal_manager(self, cr, uid, context=None):
return self.has_group(cr, uid, module='portal', group_xml_id='group_portal_manager', context=context)
def _check_preconditions(self, cr, uid, wizard_data, context=None):
if wizard_data.user_type == 'existing':
self._assert(wizard_data.user_ids,
_('Please select at least one user to share with'),
context=context)
elif wizard_data.user_type == 'groups':
self._assert(wizard_data.group_ids,
_('Please select at least one group to share with'),
context=context)
return super(share_wizard_portal, self)._check_preconditions(cr, uid, wizard_data, context=context)
def _create_or_get_submenu_named(self, cr, uid, parent_menu_id, menu_name, context=None):
if not parent_menu_id:
return
Menus = self.pool.get('ir.ui.menu')
parent_menu = Menus.browse(cr, uid, parent_menu_id) # No context
menu_id = None
max_seq = 10
for child_menu in parent_menu.child_id:
max_seq = max(max_seq, child_menu.sequence)
if child_menu.name == menu_name:
menu_id = child_menu.id
break
if not menu_id:
# not found, create it
menu_id = Menus.create(cr, UID_ROOT,
{'name': menu_name,
'parent_id': parent_menu.id,
'sequence': max_seq + 10, # at the bottom
})
return menu_id
def _sharing_root_menu_id(self, cr, uid, portal, context=None):
"""Create or retrieve root ID of sharing menu in portal menu
:param portal: browse_record of portal, constructed with a context WITHOUT language
"""
parent_menu_id = self._create_or_get_submenu_named(cr, uid, portal.parent_menu_id.id, SHARED_DOCS_MENU, context=context)
if parent_menu_id:
child_menu_id = self._create_or_get_submenu_named(cr, uid, parent_menu_id, SHARED_DOCS_CHILD_MENU, context=context)
return child_menu_id
def _create_shared_data_menu(self, cr, uid, wizard_data, portal, context=None):
"""Create sharing menus in portal menu according to share wizard options.
:param wizard_data: browse_record of share.wizard
:param portal: browse_record of portal, constructed with a context WITHOUT language
"""
root_menu_id = self._sharing_root_menu_id(cr, uid, portal, context=context)
if not root_menu_id:
# no specific parent menu, cannot create the sharing menu at all.
return
# Create the shared action and menu
action_def = self._shared_action_def(cr, uid, wizard_data, context=None)
action_id = self.pool.get('ir.actions.act_window').create(cr, UID_ROOT, action_def)
menu_data = {'name': action_def['name'],
'sequence': 10,
'action': 'ir.actions.act_window,'+str(action_id),
'parent_id': root_menu_id,
'icon': 'STOCK_JUSTIFY_FILL'}
menu_id = self.pool.get('ir.ui.menu').create(cr, UID_ROOT, menu_data)
return menu_id
def _create_share_users_group(self, cr, uid, wizard_data, context=None):
# Override of super() to handle the possibly selected "existing users"
# and "existing groups".
# In both cases, we call super() to create the share group, but when
# sharing with existing groups, we will later delete it, and copy its
# access rights and rules to the selected groups.
group_id = super(share_wizard_portal,self)._create_share_users_group(cr, uid, wizard_data, context=context)
# For sharing with existing groups, we don't create a share group, instead we'll
# alter the rules of the groups so they can see the shared data
if wizard_data.group_ids:
# get the list of portals and the related groups to install their menus.
Portals = self.pool.get('res.portal')
all_portals = Portals.browse(cr, UID_ROOT, Portals.search(cr, UID_ROOT, [])) #no context!
all_portal_group_ids = [p.group_id.id for p in all_portals]
# populate result lines with the users of each group and
# setup the menu for portal groups
for group in wizard_data.group_ids:
if group.id in all_portal_group_ids:
portal = all_portals[all_portal_group_ids.index(group.id)]
self._create_shared_data_menu(cr, uid, wizard_data, portal, context=context)
for user in group.users:
new_line = {'user_id': user.id,
'newly_created': False}
wizard_data.write({'result_line_ids': [(0,0,new_line)]})
elif wizard_data.user_ids:
# must take care of existing users, by adding them to the new group, which is group_ids[0],
# and adding the shortcut
selected_user_ids = [x.id for x in wizard_data.user_ids]
self.pool.get('res.users').write(cr, UID_ROOT, selected_user_ids, {'groups_id': [(4,group_id)]})
self._setup_action_and_shortcut(cr, uid, wizard_data, selected_user_ids, make_home=False, context=context)
# populate the result lines for existing users too
for user in wizard_data.user_ids:
new_line = { 'user_id': user.id,
'newly_created': False}
wizard_data.write({'result_line_ids': [(0,0,new_line)]})
return group_id
def copy_share_group_access_and_delete(self, cr, wizard_data, share_group_id, context=None):
# In the case of sharing with existing groups, the strategy is to copy
# access rights and rules from the share group, so that we can
if not wizard_data.group_ids: return
Groups = self.pool.get('res.groups')
Rules = self.pool.get('ir.rule')
Rights = self.pool.get('ir.model.access')
share_group = Groups.browse(cr, UID_ROOT, share_group_id)
share_rule_ids = [r.id for r in share_group.rule_groups]
for target_group in wizard_data.group_ids:
# Link the rules to the group. This is appropriate because as of
# v6.1, the algorithm for combining them will OR the rules, hence
# extending the visible data.
Rules.write(cr, UID_ROOT, share_rule_ids, {'groups': [(4,target_group.id)]})
self._logger.debug("Linked sharing rules from temporary sharing group to group %s", target_group)
# Copy the access rights. This is appropriate too because
# groups have the UNION of all permissions granted by their
# access right lines.
for access_line in share_group.model_access:
Rights.copy(cr, UID_ROOT, access_line.id, default={'group_id': target_group.id})
self._logger.debug("Copied access rights from temporary sharing group to group %s", target_group)
# finally, delete it after removing its users
Groups.write(cr, UID_ROOT, [share_group_id], {'users': [(6,0,[])]})
Groups.unlink(cr, UID_ROOT, [share_group_id])
self._logger.debug("Deleted temporary sharing group %s", share_group_id)
def _finish_result_lines(self, cr, uid, wizard_data, share_group_id, context=None):
super(share_wizard_portal,self)._finish_result_lines(cr, uid, wizard_data, share_group_id, context=context)
self.copy_share_group_access_and_delete(cr, wizard_data, share_group_id, context=context)
share_wizard_portal()

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