[MERGE] new v8 api by rco

A squashed merge is required as the conversion of the apiculture branch from
bzr to git was not correctly done. The git history contains irrelevant blobs
and commits. This branch brings a lot of changes and fixes, too many to list
exhaustively.

- New orm api, objects are now used instead of ids
- Environements to encapsulates cr uid context while maintaining backward compatibility
- Field compute attribute is a new object oriented way to define function fields
- Shared browse record cache
- New onchange protocol
- Optional copy flag on fields
- Documentation update
- Dead code cleanup
- Lots of fixes
This commit is contained in:
Raphael Collet 2014-07-06 16:44:26 +02:00 committed by Antony Lesuisse
parent d78192c489
commit cbe2dbb672
426 changed files with 14918 additions and 12581 deletions

View File

@ -26,7 +26,7 @@ from operator import itemgetter
import time
import openerp
from openerp import SUPERUSER_ID
from openerp import SUPERUSER_ID, api
from openerp import tools
from openerp.osv import fields, osv, expression
from openerp.tools.translate import _
@ -62,7 +62,7 @@ class account_payment_term(osv.osv):
'name': fields.char('Payment Term', translate=True, required=True),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the payment term without removing it."),
'note': fields.text('Description', translate=True),
'line_ids': fields.one2many('account.payment.term.line', 'payment_id', 'Terms'),
'line_ids': fields.one2many('account.payment.term.line', 'payment_id', 'Terms', copy=True),
}
_defaults = {
'active': 1,
@ -213,9 +213,6 @@ def _code_get(self, cr, uid, context=None):
# Accounts
#----------------------------------------------------------
class account_tax(osv.osv):
_name = 'account.tax'
class account_account(osv.osv):
_order = "parent_left"
_parent_order = "code"
@ -640,16 +637,16 @@ class account_account(osv.osv):
def _check_moves(self, cr, uid, ids, method, context=None):
line_obj = self.pool.get('account.move.line')
account_ids = self.search(cr, uid, [('id', 'child_of', ids)])
account_ids = self.search(cr, uid, [('id', 'child_of', ids)], context=context)
if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]):
if line_obj.search(cr, uid, [('account_id', 'in', account_ids)], context=context):
if method == 'write':
raise osv.except_osv(_('Error!'), _('You cannot deactivate an account that contains journal items.'))
elif method == 'unlink':
raise osv.except_osv(_('Error!'), _('You cannot remove an account that contains journal items.'))
#Checking whether the account is set as a property to any Partner or not
value = 'account.account,' + str(ids[0])
partner_prop_acc = self.pool.get('ir.property').search(cr, uid, [('value_reference','=',value)], context=context)
values = ['account.account,%s' % (account_id,) for account_id in ids]
partner_prop_acc = self.pool.get('ir.property').search(cr, uid, [('value_reference','in', values)], context=context)
if partner_prop_acc:
raise osv.except_osv(_('Warning!'), _('You cannot remove/deactivate an account which is set on a customer or supplier.'))
return True
@ -691,10 +688,10 @@ class account_account(osv.osv):
# Dont allow changing the company_id when account_move_line already exist
if 'company_id' in vals:
move_lines = self.pool.get('account.move.line').search(cr, uid, [('account_id', 'in', ids)])
move_lines = self.pool.get('account.move.line').search(cr, uid, [('account_id', 'in', ids)], context=context)
if move_lines:
# Allow the write if the value is the same
for i in [i['company_id'][0] for i in self.read(cr,uid,ids,['company_id'])]:
for i in [i['company_id'][0] for i in self.read(cr,uid,ids,['company_id'], context=context)]:
if vals['company_id']!=i:
raise osv.except_osv(_('Warning!'), _('You cannot change the owner company of an account that already contains journal items.'))
if 'active' in vals and not vals['active']:
@ -730,7 +727,7 @@ class account_journal(osv.osv):
'centralisation': fields.boolean('Centralized Counterpart', help="Check this box to determine that each entry of this journal won't create a new counterpart but will share the same counterpart. This is used in fiscal year closing."),
'update_posted': fields.boolean('Allow Cancelling Entries', help="Check this box if you want to allow the cancellation the entries related to this journal or of the invoice related to this journal"),
'group_invoice_lines': fields.boolean('Group Invoice Lines', help="If this box is checked, the system will try to group the accounting lines when generating them from invoices."),
'sequence_id': fields.many2one('ir.sequence', 'Entry Sequence', help="This field contains the information related to the numbering of the journal entries of this journal.", required=True),
'sequence_id': fields.many2one('ir.sequence', 'Entry Sequence', help="This field contains the information related to the numbering of the journal entries of this journal.", required=True, copy=False),
'user_id': fields.many2one('res.users', 'User', help="The user responsible for this journal"),
'groups_id': fields.many2many('res.groups', 'account_journal_group_rel', 'journal_id', 'group_id', 'Groups'),
'currency': fields.many2one('res.currency', 'Currency', help='The currency used to enter statement'),
@ -769,15 +766,12 @@ class account_journal(osv.osv):
(_check_currency, 'Configuration error!\nThe currency chosen should be shared by the default accounts too.', ['currency','default_debit_account_id','default_credit_account_id']),
]
def copy(self, cr, uid, id, default=None, context=None, done_list=None, local=False):
default = {} if default is None else default.copy()
if done_list is None:
done_list = []
def copy(self, cr, uid, id, default=None, context=None):
default = dict(context or {})
journal = self.browse(cr, uid, id, context=context)
default.update(
code=_("%s (copy)") % (journal['code'] or ''),
name=_("%s (copy)") % (journal['name'] or ''),
sequence_id=False)
name=_("%s (copy)") % (journal['name'] or ''))
return super(account_journal, self).copy(cr, uid, id, default, context=context)
def write(self, cr, uid, ids, vals, context=None):
@ -865,7 +859,10 @@ class account_fiscalyear(osv.osv):
'date_start': fields.date('Start Date', required=True),
'date_stop': fields.date('End Date', required=True),
'period_ids': fields.one2many('account.period', 'fiscalyear_id', 'Periods'),
'state': fields.selection([('draft','Open'), ('done','Closed')], 'Status', readonly=True),
'state': fields.selection([('draft','Open'), ('done','Closed')], 'Status', readonly=True, copy=False),
'end_journal_period_id': fields.many2one(
'account.journal.period', 'End of Year Entries Journal',
readonly=True, copy=False),
}
_defaults = {
'state': 'draft',
@ -960,7 +957,7 @@ class account_period(osv.osv):
'date_start': fields.date('Start of Period', required=True, states={'done':[('readonly',True)]}),
'date_stop': fields.date('End of Period', required=True, states={'done':[('readonly',True)]}),
'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year', required=True, states={'done':[('readonly',True)]}, select=True),
'state': fields.selection([('draft','Open'), ('done','Closed')], 'Status', readonly=True,
'state': fields.selection([('draft','Open'), ('done','Closed')], 'Status', readonly=True, copy=False,
help='When monthly periods are created. The status is \'Draft\'. At the end of monthly period it is in \'Done\' status.'),
'company_id': fields.related('fiscalyear_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True)
}
@ -1000,12 +997,14 @@ class account_period(osv.osv):
(_check_year_limit, 'Error!\nThe period is invalid. Either some periods are overlapping or the period\'s dates are not matching the scope of the fiscal year.', ['date_stop'])
]
@api.returns('self')
def next(self, cr, uid, period, step, context=None):
ids = self.search(cr, uid, [('date_start','>',period.date_start)])
if len(ids)>=step:
return ids[step-1]
return False
@api.returns('self')
def find(self, cr, uid, dt=None, context=None):
if context is None: context = {}
if not dt:
@ -1028,13 +1027,14 @@ class account_period(osv.osv):
raise openerp.exceptions.RedirectWarning(msg, action_id, _('Go to the configuration panel'))
return result
def action_draft(self, cr, uid, ids, *args):
def action_draft(self, cr, uid, ids, context=None):
mode = 'draft'
for period in self.browse(cr, uid, ids):
if period.fiscalyear_id.state == 'done':
raise osv.except_osv(_('Warning!'), _('You can not re-open a period which belongs to closed fiscal year'))
cr.execute('update account_journal_period set state=%s where period_id in %s', (mode, tuple(ids),))
cr.execute('update account_period set state=%s where id in %s', (mode, tuple(ids),))
self.invalidate_cache(cr, uid, context=context)
return True
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
@ -1132,22 +1132,6 @@ class account_journal_period(osv.osv):
}
_order = "period_id"
class account_fiscalyear(osv.osv):
_inherit = "account.fiscalyear"
_description = "Fiscal Year"
_columns = {
'end_journal_period_id':fields.many2one('account.journal.period','End of Year Entries Journal', readonly=True),
}
def copy(self, cr, uid, id, default=None, context=None):
default = {} if default is None else default.copy()
default.update({
'period_ids': [],
'end_journal_period_id': False
})
return super(account_fiscalyear, self).copy(cr, uid, id, default=default, context=context)
#----------------------------------------------------------
# Entries
#----------------------------------------------------------
@ -1235,13 +1219,21 @@ class account_move(osv.osv):
return [line.move_id.id for line in line_obj.browse(cr, uid, ids, context=context)]
_columns = {
'name': fields.char('Number', required=True),
'ref': fields.char('Reference'),
'name': fields.char('Number', required=True, copy=False),
'ref': fields.char('Reference', copy=False),
'period_id': fields.many2one('account.period', 'Period', required=True, states={'posted':[('readonly',True)]}),
'journal_id': fields.many2one('account.journal', 'Journal', required=True, states={'posted':[('readonly',True)]}),
'state': fields.selection([('draft','Unposted'), ('posted','Posted')], 'Status', required=True, readonly=True,
help='All manually created new journal entries are usually in the status \'Unposted\', but you can set the option to skip that status on the related journal. In that case, they will behave as journal entries automatically created by the system on document validation (invoices, bank statements...) and will be created in \'Posted\' status.'),
'line_id': fields.one2many('account.move.line', 'move_id', 'Entries', states={'posted':[('readonly',True)]}),
'state': fields.selection(
[('draft','Unposted'), ('posted','Posted')], 'Status',
required=True, readonly=True, copy=False,
help='All manually created new journal entries are usually in the status \'Unposted\', '
'but you can set the option to skip that status on the related journal. '
'In that case, they will behave as journal entries automatically created by the '
'system on document validation (invoices, bank statements...) and will be created '
'in \'Posted\' status.'),
'line_id': fields.one2many('account.move.line', 'move_id', 'Entries',
states={'posted':[('readonly',True)]},
copy=True),
'to_check': fields.boolean('To Review', help='Check this box if you are unsure of that journal entry and if you want to note it as \'to be reviewed\' by an accounting expert.'),
'partner_id': fields.related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner", store={
_name: (lambda self, cr,uid,ids,c: ids, ['line_id'], 10),
@ -1309,6 +1301,7 @@ class account_move(osv.osv):
'SET state=%s '\
'WHERE id IN %s',
('posted', tuple(valid_moves),))
self.invalidate_cache(cr, uid, context=context)
return True
def button_validate(self, cursor, user, ids, context=None):
@ -1335,6 +1328,7 @@ class account_move(osv.osv):
cr.execute('UPDATE account_move '\
'SET state=%s '\
'WHERE id IN %s', ('draft', tuple(ids),))
self.invalidate_cache(cr, uid, context=context)
return True
def write(self, cr, uid, ids, vals, context=None):
@ -1350,23 +1344,9 @@ class account_move(osv.osv):
# TODO: Check if period is closed !
#
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
if 'line_id' in vals and context.get('copy'):
for l in vals['line_id']:
if not l[0]:
l[2].update({
'reconcile_id':False,
'reconcile_partial_id':False,
'analytic_lines':False,
'invoice':False,
'ref':False,
'balance':False,
'account_tax_id':False,
'statement_id': False,
})
if 'journal_id' in vals and vals.get('journal_id', False):
context = dict(context or {})
if vals.get('line_id'):
if vals.get('journal_id'):
for l in vals['line_id']:
if not l[0]:
l[2]['journal_id'] = vals['journal_id']
@ -1383,7 +1363,6 @@ class account_move(osv.osv):
l[2]['period_id'] = default_period
context['period_id'] = default_period
if vals.get('line_id', False):
c = context.copy()
c['novalidate'] = True
c['period_id'] = vals['period_id'] if 'period_id' in vals else self._get_period(cr, uid, context)
@ -1398,22 +1377,8 @@ class account_move(osv.osv):
result = super(account_move, self).create(cr, uid, vals, context)
return result
def copy(self, cr, uid, id, default=None, context=None):
default = {} if default is None else default.copy()
context = {} if context is None else context.copy()
default.update({
'state':'draft',
'ref': False,
'name':'/',
})
context.update({
'copy':True
})
return super(account_move, self).copy(cr, uid, id, default, context)
def unlink(self, cr, uid, ids, context=None, check=True):
if context is None:
context = {}
context = dict(context or {})
if isinstance(ids, (int, long)):
ids = [ids]
toremove = []
@ -1447,8 +1412,8 @@ 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 = {}
account_move_line_obj = self.pool.get('account.move.line')
context = dict(context or {})
if mode=='credit':
account_id = move.journal_id.default_debit_account_id.id
@ -1473,7 +1438,7 @@ class account_move(osv.osv):
line_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, {
line_id = account_move_line_obj.create(cr, uid, {
'name': _(mode.capitalize()+' Centralisation'),
'centralisation': mode,
'partner_id': False,
@ -1498,6 +1463,7 @@ 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))
account_move_line_obj.invalidate_cache(cr, uid, [mode2], [line_id], context=context)
#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,))
@ -1510,9 +1476,10 @@ class account_move(osv.osv):
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]))
account_move_line_obj.invalidate_cache(cr, uid, ['amount_currency', 'account_id'], [res[0]], context=context)
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, {
line_id = account_move_line_obj.create(cr, uid, {
'name': _('Currency Adjustment'),
'centralisation': 'currency',
'partner_id': False,
@ -1818,7 +1785,7 @@ class account_tax_code(osv.osv):
return []
if isinstance(ids, (int, long)):
ids = [ids]
reads = self.read(cr, uid, ids, ['name','code'], context, load='_classic_write')
reads = self.read(cr, uid, ids, ['name','code'], context=context, load='_classic_write')
return [(x['id'], (x['code'] and (x['code'] + ' - ') or '') + x['name']) \
for x in reads]
@ -1827,19 +1794,13 @@ class account_tax_code(osv.osv):
if user.company_id:
return user.company_id.id
return self.pool.get('res.company').search(cr, uid, [('parent_id', '=', False)])[0]
_defaults = {
'company_id': _default_company,
'sign': 1.0,
'notprintable': False,
}
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
default = default.copy()
default.update({'line_ids': []})
return super(account_tax_code, self).copy(cr, uid, id, default, context)
_check_recursion = check_cycle
_constraints = [
(_check_recursion, 'Error!\nYou cannot create recursive accounts.', ['parent_id'])
@ -1868,10 +1829,9 @@ class account_tax(osv.osv):
def copy_data(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
name = self.read(cr, uid, id, ['name'], context=context)['name']
default = default.copy()
default.update({'name': name + _(' (Copy)')})
return super(account_tax, self).copy_data(cr, uid, id, default=default, context=context)
this = self.browse(cr, uid, id, context=context)
tmp_default = dict(default, name=_("%s (Copy)") % this.name)
return super(account_tax, self).copy_data(cr, uid, id, default=tmp_default, context=context)
_name = 'account.tax'
_description = 'Tax'
@ -2087,6 +2047,7 @@ class account_tax(osv.osv):
tax = self.browse(cr, uid, tax_id, context=context)
return self.compute_all(cr, uid, [tax], amount, 1) # TOCHECK may use force_exclude parameter
@api.v7
def compute_all(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, force_excluded=False):
"""
:param force_excluded: boolean used to say that we don't want to consider the value of field price_include of
@ -2137,6 +2098,12 @@ class account_tax(osv.osv):
'taxes': tin + tex
}
@api.v8
def compute_all(self, price_unit, quantity, product=None, partner=None, force_excluded=False):
return self._model.compute_all(
self._cr, self._uid, self, price_unit, quantity,
product=product, partner=partner, force_excluded=force_excluded)
def compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None):
_logger.warning("Deprecated, use compute_all(...)['taxes'] instead of compute(...) to manage prices with tax included.")
return self._compute(cr, uid, taxes, price_unit, quantity, product, partner)
@ -2270,7 +2237,7 @@ class account_model(osv.osv):
'name': fields.char('Model Name', required=True, help="This is a model for recurring accounting entries"),
'journal_id': fields.many2one('account.journal', 'Journal', required=True),
'company_id': fields.related('journal_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
'lines_id': fields.one2many('account.model.line', 'model_id', 'Model Entries'),
'lines_id': fields.one2many('account.model.line', 'model_id', 'Model Entries', copy=True),
'legend': fields.text('Legend', readonly=True, size=100),
}
@ -2292,6 +2259,7 @@ class account_model(osv.osv):
context = {}
if data.get('date', False):
context = dict(context)
context.update({'date': data['date']})
move_date = context.get('date', time.strftime('%Y-%m-%d'))
@ -2409,8 +2377,8 @@ class account_subscription(osv.osv):
'period_total': fields.integer('Number of Periods', required=True),
'period_nbr': fields.integer('Period', required=True),
'period_type': fields.selection([('day','days'),('month','month'),('year','year')], 'Period Type', required=True),
'state': fields.selection([('draft','Draft'),('running','Running'),('done','Done')], 'Status', required=True, readonly=True),
'lines_id': fields.one2many('account.subscription.line', 'subscription_id', 'Subscription Lines')
'state': fields.selection([('draft','Draft'),('running','Running'),('done','Done')], 'Status', required=True, readonly=True, copy=False),
'lines_id': fields.one2many('account.subscription.line', 'subscription_id', 'Subscription Lines', copy=True)
}
_defaults = {
'date_start': fields.date.context_today,
@ -2742,7 +2710,7 @@ class account_tax_code_template(osv.osv):
return []
if isinstance(ids, (int, long)):
ids = [ids]
reads = self.read(cr, uid, ids, ['name','code'], context, load='_classic_write')
reads = self.read(cr, uid, ids, ['name','code'], context=context, load='_classic_write')
return [(x['id'], (x['code'] and x['code'] + ' - ' or '') + x['name']) \
for x in reads]

View File

@ -69,8 +69,7 @@ class account_bank_statement(osv.osv):
return False
def _compute_default_statement_name(self, cr, uid, journal_id, context=None):
if context is None:
context = {}
context = dict(context or {})
obj_seq = self.pool.get('ir.sequence')
period = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, context=context), context=context)
context['fiscalyear_id'] = period.fiscalyear_id.id
@ -114,8 +113,16 @@ class account_bank_statement(osv.osv):
_description = "Bank Statement"
_inherit = ['mail.thread']
_columns = {
'name': fields.char('Reference', states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement
'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]}, select=True),
'name': fields.char(
'Reference', states={'draft': [('readonly', False)]},
readonly=True, # readonly for account_cash_statement
copy=False,
help='if you give the Name other then /, its created Accounting Entries Move '
'will be with same name as statement name. '
'This allows the statement entries to have the same references than the '
'statement itself'),
'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]},
select=True, copy=False),
'journal_id': fields.many2one('account.journal', 'Journal', required=True,
readonly=True, states={'draft':[('readonly',False)]}),
'period_id': fields.many2one('account.period', 'Period', required=True,
@ -132,14 +139,15 @@ class account_bank_statement(osv.osv):
string="Computed Balance", help='Balance as calculated based on Opening Balance and transaction lines'),
'company_id': fields.related('journal_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
'line_ids': fields.one2many('account.bank.statement.line',
'statement_id', 'Statement lines',
states={'confirm':[('readonly', True)]}),
'statement_id', 'Statement lines',
states={'confirm':[('readonly', True)]}, copy=True),
'move_line_ids': fields.one2many('account.move.line', 'statement_id',
'Entry lines', states={'confirm':[('readonly',True)]}),
'Entry lines', states={'confirm':[('readonly',True)]}),
'state': fields.selection([('draft', 'New'),
('open','Open'), # used by cash statements
('confirm', 'Closed')],
'Status', required=True, readonly="1",
copy=False,
help='When new statement is created the status will be \'Draft\'.\n'
'And after getting confirmation from the bank it will be in \'Confirmed\' status.'),
'currency': fields.function(_currency, string='Currency',
@ -182,7 +190,7 @@ class account_bank_statement(osv.osv):
pids = period_pool.find(cr, uid, dt=date, context=ctx)
if pids:
res.update({'period_id': pids[0]})
context.update({'period_id': pids[0]})
context = dict(context, period_id=pids[0])
return {
'value':res,
@ -363,24 +371,13 @@ class account_bank_statement(osv.osv):
return {'value': res}
def unlink(self, cr, uid, ids, context=None):
stat = self.read(cr, uid, ids, ['state'], context=context)
unlink_ids = []
for t in stat:
if t['state'] in ('draft'):
unlink_ids.append(t['id'])
else:
raise osv.except_osv(_('Invalid Action!'), _('In order to delete a bank statement, you must first cancel it to delete related journal items.'))
osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
return True
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
if context is None:
context = {}
default = default.copy()
default['move_line_ids'] = []
return super(account_bank_statement, self).copy(cr, uid, id, default, context=context)
for item in self.browse(cr, uid, ids, context=context):
if item.state != 'draft':
raise osv.except_osv(
_('Invalid Action!'),
_('In order to delete a bank statement, you must first cancel it to delete related journal items.')
)
return super(account_bank_statement, self).unlink(cr, uid, ids, context=context)
def button_journal_entries(self, cr, uid, ids, context=None):
ctx = (context or {}).copy()
@ -806,8 +803,8 @@ class account_bank_statement_line(osv.osv):
_description = "Bank Statement Line"
_inherit = ['ir.needaction_mixin']
_columns = {
'name': fields.char('Description', required=True),
'date': fields.date('Date', required=True),
'name': fields.char('Description', required=True, copy=False),
'date': fields.date('Date', required=True, copy=False),
'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
'partner_id': fields.many2one('res.partner', 'Partner'),
'bank_account_id': fields.many2one('res.partner.bank','Bank Account'),

View File

@ -179,7 +179,7 @@ class account_cash_statement(osv.osv):
},
help="Total of cash transaction lines."),
'closing_date': fields.datetime("Closed On"),
'details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='CashBox Lines'),
'details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='CashBox Lines', copy=True),
'opening_details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='Opening Cashbox Lines'),
'closing_details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='Closing Cashbox Lines'),
'user_id': fields.many2one('res.users', 'Responsible', required=False),
@ -337,7 +337,7 @@ class account_journal(osv.osv):
return result
_columns = {
'cashbox_line_ids' : fields.one2many('account.journal.cashbox.line', 'journal_id', 'CashBox'),
'cashbox_line_ids' : fields.one2many('account.journal.cashbox.line', 'journal_id', 'CashBox', copy=True),
}
_defaults = {

File diff suppressed because it is too large Load Diff

View File

@ -183,7 +183,7 @@
<field domain="[('company_id', '=', company_id), ('type', '=', 'payable')]"
name="account_id" groups="account.group_account_user"/>
<field name="journal_id" groups="account.group_account_user"
on_change="onchange_journal_id(journal_id, context)" options="{'no_create': True}"/>
on_change="onchange_journal_id(journal_id)" options="{'no_create': True}"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="check_total" groups="account.group_supplier_inv_check_total"/>
</group>
@ -258,7 +258,7 @@
<group>
<field name="move_id" groups="account.group_account_user"/>
<field name="period_id" domain="[('state', '=', 'draft'), ('company_id', '=', company_id)]" groups="account.group_account_user"/>
<field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id,context)" widget="selection" groups="base.group_multi_company"/>
<field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id)" widget="selection" groups="base.group_multi_company"/>
</group>
</group>
</page>
@ -329,7 +329,7 @@
<group>
<field name="date_invoice"/>
<field name="journal_id" groups="account.group_account_user"
on_change="onchange_journal_id(journal_id, context)" options="{'no_create': True}"/>
on_change="onchange_journal_id(journal_id)" options="{'no_create': True}"/>
<field domain="[('company_id', '=', company_id),('type','=', 'receivable')]"
name="account_id" groups="account.group_account_user"/>
@ -393,7 +393,7 @@
<page string="Other Info">
<group col="4">
<group>
<field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id,context)" widget="selection" groups="base.group_multi_company"/>
<field name="company_id" on_change="onchange_company_id(company_id,partner_id,type,invoice_line,currency_id)" widget="selection" groups="base.group_multi_company"/>
<field name="user_id" groups="base.group_user" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'account.group_account_invoice']}"/>
<field domain="[('partner_id.ref_companies', 'in', [company_id])]" name="partner_bank_id"/>
<field name="period_id" domain="[('state', '=', 'draft'), ('company_id', '=', company_id)]"

View File

@ -19,15 +19,12 @@
#
##############################################################################
import sys
import time
from datetime import datetime
from operator import itemgetter
from lxml import etree
from openerp import workflow
from openerp.osv import fields, osv, orm
from openerp.osv import fields, osv
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp
from openerp import tools
@ -42,8 +39,7 @@ class account_move_line(osv.osv):
fiscalperiod_obj = self.pool.get('account.period')
account_obj = self.pool.get('account.account')
fiscalyear_ids = []
if context is None:
context = {}
context = dict(context or {})
initial_bal = context.get('initial_bal', False)
company_clause = " "
if context.get('company_id', False):
@ -217,17 +213,14 @@ class account_move_line(osv.osv):
period_id = context.get('period_id')
if type(period_id) == str:
ids = period_obj.search(cr, uid, [('name', 'ilike', period_id)])
context.update({
'period_id': ids and ids[0] or False
})
context = dict(context, period_id=ids and ids[0] or False)
return context
def _default_get(self, cr, uid, fields, context=None):
#default_get should only do the following:
# -propose the next amount in debit/credit in order to balance the move
# -propose the next account from the journal (default debit/credit account) accordingly
if context is None:
context = {}
context = dict(context or {})
account_obj = self.pool.get('account.account')
period_obj = self.pool.get('account.period')
journal_obj = self.pool.get('account.journal')
@ -456,10 +449,10 @@ class account_move_line(osv.osv):
'move_id': fields.many2one('account.move', 'Journal Entry', ondelete="cascade", help="The move of this entry line.", select=2, required=True),
'narration': fields.related('move_id','narration', type='text', relation='account.move', string='Internal Note'),
'ref': fields.related('move_id', 'ref', string='Reference', type='char', store=True),
'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1),
'reconcile_id': fields.many2one('account.move.reconcile', 'Reconcile', readonly=True, ondelete='set null', select=2),
'reconcile_partial_id': fields.many2one('account.move.reconcile', 'Partial Reconcile', readonly=True, ondelete='set null', select=2),
'reconcile': fields.function(_get_reconcile, type='char', string='Reconcile Ref', store={
'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1, copy=False),
'reconcile_id': fields.many2one('account.move.reconcile', 'Reconcile', readonly=True, ondelete='set null', select=2, copy=False),
'reconcile_partial_id': fields.many2one('account.move.reconcile', 'Partial Reconcile', readonly=True, ondelete='set null', select=2, copy=False),
'reconcile_ref': fields.function(_get_reconcile, type='char', string='Reconcile Ref', oldname='reconcile', store={
'account.move.line': (lambda self, cr, uid, ids, c={}: ids, ['reconcile_id','reconcile_partial_id'], 50),'account.move.reconcile': (_get_move_from_reconcile, None, 50)}),
'amount_currency': fields.float('Amount Currency', help="The amount expressed in an optional other currency if it is a multi-currency entry.", digits_compute=dp.get_precision('Account')),
'amount_residual_currency': fields.function(_amount_residual, string='Residual Amount in Currency', multi="residual", help="The residual amount on a receivable or payable of a journal entry expressed in its currency (maybe different of the company currency)."),
@ -484,13 +477,13 @@ class account_move_line(osv.osv):
'analytic_lines': fields.one2many('account.analytic.line', 'move_id', 'Analytic lines'),
'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, string='Balance'),
'state': fields.selection([('draft','Unbalanced'), ('valid','Balanced')], 'Status', readonly=True),
'state': fields.selection([('draft','Unbalanced'), ('valid','Balanced')], 'Status', readonly=True, copy=False),
'tax_code_id': fields.many2one('account.tax.code', 'Tax Account', help="The Account can either be a base tax code or a tax code account."),
'tax_amount': fields.float('Tax/Base Amount', digits_compute=dp.get_precision('Account'), select=True, help="If the Tax account is a tax code account, this field will contain the taxed amount.If the tax account is base tax code, "\
"this field will contain the basic amount(without tax)."),
'invoice': fields.function(_invoice, string='Invoice',
type='many2one', relation='account.invoice', fnct_search=_invoice_search),
'account_tax_id':fields.many2one('account.tax', 'Tax'),
'account_tax_id':fields.many2one('account.tax', 'Tax', copy=False),
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),
'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company',
string='Company', store=True, readonly=True)
@ -666,6 +659,7 @@ class account_move_line(osv.osv):
if (amount>0) and journal:
x = journal_obj.browse(cr, uid, journal).default_credit_account_id
if x: acc = x
context = dict(context)
context.update({
'date': date,
'res.currency.compute.account': acc,
@ -1006,12 +1000,8 @@ class account_move_line(osv.osv):
period_pool = self.pool.get('account.period')
pids = period_pool.find(cr, user, date, context=context)
if pids:
res.update({
'period_id':pids[0]
})
context.update({
'period_id':pids[0]
})
res.update({'period_id':pids[0]})
context = dict(context, period_id=pids[0])
return {
'value':res,
'context':context,
@ -1158,15 +1148,14 @@ class account_move_line(osv.osv):
move_obj = self.pool.get('account.move')
cur_obj = self.pool.get('res.currency')
journal_obj = self.pool.get('account.journal')
if context is None:
context = {}
context = dict(context or {})
if vals.get('move_id', False):
move = self.pool.get('account.move').browse(cr, uid, vals['move_id'], context=context)
if move.company_id:
vals['company_id'] = move.company_id.id
if move.date and not vals.get('date'):
vals['date'] = move.date
if ('account_id' in vals) and not account_obj.read(cr, uid, vals['account_id'], ['active'])['active']:
if ('account_id' in vals) and not account_obj.read(cr, uid, [vals['account_id']], ['active'])[0]['active']:
raise osv.except_osv(_('Bad Account!'), _('You cannot use an inactive account.'))
if 'journal_id' in vals and vals['journal_id']:
context['journal_id'] = vals['journal_id']

View File

@ -1209,7 +1209,7 @@
<field name="debit" sum="Total Debit"/>
<field name="credit" sum="Total Credit"/>
<field name="date_maturity" invisible="context.get('journal_type', False) not in ['sale','sale_refund','purchase','purchase_refund']"/>
<field name="reconcile"/>
<field name="reconcile_ref"/>
<field name="invoice" invisible="1"/>
<field name="amount_currency" readonly="True" invisible="not context.get('currency',False)"/>
<field name="currency_id" readonly="True" invisible="not context.get('currency',False)" />

View File

@ -208,7 +208,7 @@ class account_invoice(osv.osv, EDIMixin):
edi_document.pop('partner_ref', None)
# journal_id: should be selected based on type: simply put the 'type' in the context when calling create(), will be selected correctly
context.update(type=invoice_type)
context = dict(context, type=invoice_type)
# for invoice lines, the account_id value should be taken from the product's default, i.e. from the default category, as it will not be provided.
for edi_invoice_line in edi_document['invoice_line']:

View File

@ -18,7 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import api
from openerp.osv import fields, osv
class ir_sequence_fiscalyear(osv.osv):
@ -43,9 +43,10 @@ class ir_sequence(osv.osv):
_inherit = 'ir.sequence'
_columns = {
'fiscal_ids': fields.one2many('account.sequence.fiscalyear',
'sequence_main_id', 'Sequences')
'sequence_main_id', 'Sequences', copy=True)
}
@api.cr_uid_ids_context
def _next(self, cr, uid, seq_ids, context=None):
if context is None:
context = {}

View File

@ -23,6 +23,7 @@ from operator import itemgetter
import time
from openerp.osv import fields, osv
from openerp import api
class account_fiscal_position(osv.osv):
_name = 'account.fiscal.position'
@ -33,8 +34,8 @@ class account_fiscal_position(osv.osv):
'name': fields.char('Fiscal Position', required=True),
'active': fields.boolean('Active', help="By unchecking the active field, you may hide a fiscal position without deleting it."),
'company_id': fields.many2one('res.company', 'Company'),
'account_ids': fields.one2many('account.fiscal.position.account', 'position_id', 'Account Mapping'),
'tax_ids': fields.one2many('account.fiscal.position.tax', 'position_id', 'Tax Mapping'),
'account_ids': fields.one2many('account.fiscal.position.account', 'position_id', 'Account Mapping', copy=True),
'tax_ids': fields.one2many('account.fiscal.position.tax', 'position_id', 'Tax Mapping', copy=True),
'note': fields.text('Notes'),
'auto_apply': fields.boolean('Automatic', help="Apply automatically this fiscal position."),
'vat_required': fields.boolean('VAT required', help="Apply only if partner has a VAT number."),
@ -46,6 +47,7 @@ class account_fiscal_position(osv.osv):
'active': True,
}
@api.v7
def map_tax(self, cr, uid, fposition_id, taxes, context=None):
if not taxes:
return []
@ -63,6 +65,20 @@ class account_fiscal_position(osv.osv):
result.add(t.id)
return list(result)
@api.v8
def map_tax(self, taxes):
result = taxes.browse()
for tax in taxes:
found = False
for t in self.tax_ids:
if t.tax_src_id == tax:
result |= t.tax_dest_id
found = True
if not found:
result |= tax
return result
@api.v7
def map_account(self, cr, uid, fposition_id, account_id, context=None):
if not fposition_id:
return account_id
@ -72,6 +88,13 @@ class account_fiscal_position(osv.osv):
break
return account_id
@api.v8
def map_account(self, account):
for pos in self.account_ids:
if pos.account_src_id == account:
return pos.account_dest_id
return account
def get_fiscal_position(self, cr, uid, company_id, partner_id, delivery_id=None, context=None):
if not partner_id:
return False
@ -279,7 +302,14 @@ class res_partner(osv.osv):
help="This payment term will be used instead of the default one for purchase orders and supplier invoices"),
'ref_companies': fields.one2many('res.company', 'partner_id',
'Companies that refers to partner'),
'last_reconciliation_date': fields.datetime('Latest Full Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the last date where a reconciliation has been made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 different ways: either the last unreconciled debit/credit entry of this partner was reconciled, either the user pressed the button "Nothing more to reconcile" during the manual reconciliation process.')
'last_reconciliation_date': fields.datetime(
'Latest Full Reconciliation Date', copy=False,
help='Date on which the partner accounting entries were fully reconciled last time. '
'It differs from the last date where a reconciliation has been made for this partner, '
'as here we depict the fact that nothing more was to be reconciled at this date. '
'This can be achieved in 2 different ways: either the last unreconciled debit/credit '
'entry of this partner was reconciled, either the user pressed the button '
'"Nothing more to reconcile" during the manual reconciliation process.')
}
def _commercial_fields(self, cr, uid, context=None):

View File

@ -156,6 +156,7 @@ class journal_print(report_sxw.rml_parse, common_report_header):
journal_id = [journal_id]
obj_mline = self.pool.get('account.move.line')
self.cr.execute('update account_journal_period set state=%s where journal_id IN %s and period_id=%s and state=%s', ('printed', self.journal_ids, period_id, 'draft'))
self.pool.get('account.journal.period').invalidate_cache(self.cr, self.uid, ['state'], context=self.context)
move_state = ['draft','posted']
if self.target_move == 'posted':

View File

@ -20,7 +20,7 @@
##############################################################################
import time
from datetime import datetime
import datetime
from dateutil.relativedelta import relativedelta
from openerp import tools
@ -91,7 +91,7 @@ class report_aged_receivable(osv.osv):
"""
if context is None:context = {}
if not self.called:
self.init(cr, user)
self._init(cr, user)
self.called = True # To make sure that init doesn't get called multiple times
res = super(report_aged_receivable, self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
@ -116,29 +116,37 @@ class report_aged_receivable(osv.osv):
'balance': fields.function(_calc_bal, string='Balance', readonly=True),
}
def init(self, cr, uid=1):
def init(self, cr):
return self._init(cr, 1)
def _init(self, cr, uid):
""" This view will be used in dashboard
The reason writing this code here is, we need to check date range from today to first date of fiscal year.
"""
pool_obj_fy = self.pool['account.fiscalyear']
today = time.strftime('%Y-%m-%d')
current_date = datetime.date.today()
fy_id = pool_obj_fy.find(cr, uid, exception=False)
LIST_RANGES = []
names = []
def add(names, start_on, stop_on):
names.append(start_on.strftime("%Y-%m-%d") + ' to ' + stop_on.strftime('%Y-%m-%d'))
return names
if fy_id:
fy_start_date = pool_obj_fy.read(cr, uid, fy_id, ['date_start'])['date_start']
fy_start_date = datetime.strptime(fy_start_date, '%Y-%m-%d')
last_month_date = datetime.strptime(today, '%Y-%m-%d') - relativedelta(months=1)
fiscal_year = pool_obj_fy.browse(cr, uid, fy_id)
fy_start_date = datetime.datetime.strptime(fiscal_year.date_start, '%Y-%m-%d').date()
last_month_date = current_date - relativedelta(months=1)
while (last_month_date > fy_start_date):
LIST_RANGES.append(today + " to " + last_month_date.strftime('%Y-%m-%d'))
today = (last_month_date- relativedelta(days=1)).strftime('%Y-%m-%d')
last_month_date = datetime.strptime(today, '%Y-%m-%d') - relativedelta(months=1)
add(names, current_date, last_month_date)
current_date = last_month_date - relativedelta(days=1)
last_month_date = current_date - relativedelta(months=1)
LIST_RANGES.append(today +" to " + fy_start_date.strftime('%Y-%m-%d'))
add(names, current_date, fy_start_date)
cr.execute('delete from temp_range')
for range in LIST_RANGES:
self.pool['temp.range'].create(cr, uid, {'name':range})
for name in names:
self.pool['temp.range'].create(cr, uid, {'name':name})
cr.execute("""
create or replace view report_aged_receivable as (

View File

@ -239,7 +239,7 @@ class account_automatic_reconcile(osv.osv_memory):
(account_id.id,))
additional_unrec = cr.fetchone()[0]
unreconciled = unreconciled + additional_unrec
context.update({'reconciled': reconciled, 'unreconciled': unreconciled})
context = dict(context, reconciled=reconciled, unreconciled=unreconciled)
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','account_automatic_reconcile_view1')])
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
return {

View File

@ -85,7 +85,7 @@ class account_chart(osv.osv_memory):
fy_obj = self.pool.get('account.fiscalyear')
if context is None:
context = {}
data = self.read(cr, uid, ids, [], context=context)[0]
data = self.read(cr, uid, ids, context=context)[0]
result = mod_obj.get_object_reference(cr, uid, 'account', 'action_account_tree')
id = result and result[1] or False
result = act_obj.read(cr, uid, [id], context=context)[0]

View File

@ -62,6 +62,7 @@ class account_fiscalyear_close(osv.osv_memory):
raise osv.except_osv(_('Warning!'), _('The entries to reconcile should belong to the same company.'))
r_id = self.pool.get('account.move.reconcile').create(cr, uid, {'type': 'auto', 'opening_reconciliation': True})
cr.execute('update account_move_line set reconcile_id = %s where id in %s',(r_id, tuple(ids),))
obj_acc_move_line.invalidate_cache(cr, uid, ['reconcile_id'], ids, context=context)
return r_id
obj_acc_period = self.pool.get('account.period')
@ -175,6 +176,7 @@ class account_fiscalyear_close(osv.osv_memory):
AND b.reconcile_id IN (SELECT DISTINCT(reconcile_id)
FROM account_move_line a
WHERE a.period_id IN ('''+fy2_period_set+''')))''', (new_journal.id, period.id, period.date_start, move_id, tuple(account_ids),))
self.invalidate_cache(cr, uid, context=context)
#2. report of the accounts with defferal method == 'detail'
cr.execute('''
@ -203,7 +205,7 @@ class account_fiscalyear_close(osv.osv_memory):
WHERE account_id IN %s
AND ''' + query_line + ''')
''', (new_journal.id, period.id, period.date_start, move_id, tuple(account_ids),))
self.invalidate_cache(cr, uid, context=context)
#3. report of the accounts with defferal method == 'balance'
cr.execute('''
@ -243,6 +245,7 @@ class account_fiscalyear_close(osv.osv_memory):
'draft')
if query_2nd_part:
cr.execute(query_1st_part + query_2nd_part, tuple(query_2nd_part_args))
self.invalidate_cache(cr, uid, context=context)
#validate and centralize the opening move
obj_acc_move.validate(cr, uid, [move_id], context=context)
@ -267,6 +270,7 @@ class account_fiscalyear_close(osv.osv_memory):
cr.execute('UPDATE account_fiscalyear ' \
'SET end_journal_period_id = %s ' \
'WHERE id = %s', (ids[0], old_fyear.id))
obj_acc_fiscalyear.invalidate_cache(cr, uid, ['end_journal_period_id'], [old_fyear.id], context=context)
return {'type': 'ir.actions.act_window_close'}

View File

@ -41,6 +41,10 @@ class account_fiscalyear_close_state(osv.osv_memory):
@param ids: List of Account fiscalyear close states IDs
"""
journal_period_obj = self.pool.get('account.journal.period')
period_obj = self.pool.get('account.period')
fiscalyear_obj = self.pool.get('account.fiscalyear')
for data in self.read(cr, uid, ids, context=context):
fy_id = data['fy_id'][0]
@ -53,6 +57,7 @@ class account_fiscalyear_close_state(osv.osv_memory):
'WHERE fiscalyear_id = %s', ('done', fy_id))
cr.execute('UPDATE account_fiscalyear ' \
'SET state = %s WHERE id = %s', ('done', fy_id))
self.invalidate_cache(cr, uid, context=context)
return {'type': 'ir.actions.act_window_close'}

View File

@ -68,10 +68,10 @@ class account_invoice_refund(osv.osv_memory):
}
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
if context is None:context = {}
journal_obj = self.pool.get('account.journal')
user_obj = self.pool.get('res.users')
# remove the entry with key 'form_view_ref', otherwise fields_view_get crashes
context = dict(context or {})
context.pop('form_view_ref', None)
res = super(account_invoice_refund,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
type = context.get('type', 'out_invoice')
@ -168,7 +168,7 @@ class account_invoice_refund(osv.osv_memory):
to_reconcile_ids.setdefault(line.account_id.id, []).append(line.id)
if line.reconcile_id:
line.reconcile_id.unlink()
inv_obj.signal_invoice_open(cr, uid, [refund.id])
refund.signal_workflow('invoice_open')
refund = inv_obj.browse(cr, uid, refund_id[0], context=context)
for tmpline in refund.move_id.line_id:
if tmpline.account_id.id == inv.account_id.id:
@ -212,13 +212,15 @@ class account_invoice_refund(osv.osv_memory):
if 'value' in data and data['value']:
inv_obj.write(cr, uid, [inv_id], data['value'])
created_inv.append(inv_id)
xml_id = (inv.type == 'out_refund') and 'action_invoice_tree1' or \
(inv.type == 'in_refund') and 'action_invoice_tree2' or \
(inv.type == 'out_invoice') and 'action_invoice_tree3' or \
(inv.type == 'in_invoice') and 'action_invoice_tree4'
result = mod_obj.get_object_reference(cr, uid, 'account', xml_id)
id = result and result[1] or False
result = act_obj.read(cr, uid, id, context=context)
result = act_obj.read(cr, uid, [id], context=context)[0]
invoice_domain = eval(result['domain'])
invoice_domain.append(('id', 'in', created_inv))
result['domain'] = invoice_domain

View File

@ -33,12 +33,13 @@ class account_invoice_confirm(osv.osv_memory):
def invoice_confirm(self, cr, uid, ids, context=None):
if context is None:
context = {}
account_invoice_obj = self.pool['account.invoice']
data_inv = account_invoice_obj.read(cr, uid, context['active_ids'], ['state'], context=context)
for record in data_inv:
if record['state'] not in ('draft','proforma','proforma2'):
active_ids = context.get('active_ids', []) or []
proxy = self.pool['account.invoice']
for record in proxy.browse(cr, uid, active_ids, context=context):
if record.state not in ('draft', 'proforma', 'proforma2'):
raise osv.except_osv(_('Warning!'), _("Selected invoice(s) cannot be confirmed as they are not in 'Draft' or 'Pro-Forma' state."))
account_invoice_obj.signal_invoice_open(cr, uid, [ record['id'] ])
record.signal_workflow('invoice_open')
return {'type': 'ir.actions.act_window_close'}
@ -55,12 +56,13 @@ class account_invoice_cancel(osv.osv_memory):
def invoice_cancel(self, cr, uid, ids, context=None):
if context is None:
context = {}
account_invoice_obj = self.pool['account.invoice']
data_inv = account_invoice_obj.read(cr, uid, context['active_ids'], ['state'], context=context)
for record in data_inv:
if record['state'] in ('cancel','paid'):
proxy = self.pool['account.invoice']
active_ids = context.get('active_ids', []) or []
for record in proxy.browse(cr, uid, active_ids, context=context):
if record.state in ('cancel','paid'):
raise osv.except_osv(_('Warning!'), _("Selected invoice(s) cannot be cancelled as they are already in 'Cancelled' or 'Done' state."))
account_invoice_obj.signal_invoice_cancel(cr , uid, [record['id']])
record.signal_workflow('invoice_cancel')
return {'type': 'ir.actions.act_window_close'}

View File

@ -41,6 +41,7 @@ class account_open_closed_fiscalyear(osv.osv_memory):
ids_move = move_obj.search(cr, uid, [('journal_id','=',period_journal.journal_id.id),('period_id','=',period_journal.period_id.id)])
if ids_move:
cr.execute('delete from account_move where id IN %s', (tuple(ids_move),))
self.invalidate_cache(cr, uid, context=context)
return {'type': 'ir.actions.act_window_close'}

View File

@ -39,6 +39,7 @@ class account_period_close(osv.osv_memory):
@param uid: the current users ID for security checks,
@param ids: account period closes ID or list of IDs
"""
journal_period_pool = self.pool.get('account.journal.period')
period_pool = self.pool.get('account.period')
account_move_obj = self.pool.get('account.move')
@ -52,6 +53,7 @@ class account_period_close(osv.osv_memory):
cr.execute('update account_journal_period set state=%s where period_id=%s', (mode, id))
cr.execute('update account_period set state=%s where id=%s', (mode, id))
self.invalidate_cache(cr, uid, context=context)
return {'type': 'ir.actions.act_window_close'}

View File

@ -140,6 +140,7 @@ class account_move_line_reconcile_writeoff(osv.osv_memory):
return {'type': 'ir.actions.act_window_close'}
def trans_rec_reconcile(self, cr, uid, ids, context=None):
context = dict(context or {})
account_move_line_obj = self.pool.get('account.move.line')
period_obj = self.pool.get('account.period')
if context is None:

View File

@ -27,14 +27,16 @@ class account_state_open(osv.osv_memory):
_description = 'Account State Open'
def change_inv_state(self, cr, uid, ids, context=None):
obj_invoice = self.pool.get('account.invoice')
proxy = self.pool.get('account.invoice')
if context is None:
context = {}
if 'active_ids' in context:
data_inv = obj_invoice.browse(cr, uid, context['active_ids'][0], context=context)
if data_inv.reconciled:
active_ids = context.get('active_ids')
if isinstance(active_ids, list):
invoice = proxy.browse(cr, uid, active_ids[0], context=context)
if invoice.reconciled:
raise osv.except_osv(_('Warning!'), _('Invoice is already reconciled.'))
obj_invoice.signal_open_test(cr, uid, context['active_ids'][0])
invoice.signal_workflow('open_test')
return {'type': 'ir.actions.act_window_close'}

View File

@ -34,8 +34,7 @@ class account_statement_from_invoice_lines(osv.osv_memory):
}
def populate_statement(self, cr, uid, ids, context=None):
if context is None:
context = {}
context = dict(context or {})
statement_id = context.get('statement_id', False)
if not statement_id:
return {'type': 'ir.actions.act_window_close'}

View File

@ -58,7 +58,7 @@ class account_use_model(osv.osv_memory):
model_ids = context['active_ids']
move_ids = account_model_obj.generate(cr, uid, model_ids, context=context)
context.update({'move_ids':move_ids})
context = dict(context, move_ids=move_ids)
model_data_ids = mod_obj.search(cr, uid,[('model','=','ir.ui.view'),('name','=','view_move_form')], context=context)
resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {

View File

@ -24,7 +24,6 @@ import logging
import time
from openerp.osv import osv, fields
from openerp.osv.orm import intersect, except_orm
import openerp.tools
from openerp.tools.translate import _
@ -518,7 +517,7 @@ class account_analytic_account(osv.osv):
'invoiced_total' : fields.function(_sum_of_fields, type="float",multi="sum_of_all", string="Total Invoiced"),
'remaining_total' : fields.function(_sum_of_fields, type="float",multi="sum_of_all", string="Total Remaining", help="Expectation of remaining income for this contract. Computed as the sum of remaining subtotals which, in turn, are computed as the maximum between '(Estimation - Invoiced)' and 'To Invoice' amounts"),
'toinvoice_total' : fields.function(_sum_of_fields, type="float",multi="sum_of_all", string="Total to Invoice", help=" Sum of everything that could be invoiced for this contract."),
'recurring_invoice_line_ids': fields.one2many('account.analytic.invoice.line', 'analytic_account_id', 'Invoice Lines'),
'recurring_invoice_line_ids': fields.one2many('account.analytic.invoice.line', 'analytic_account_id', 'Invoice Lines', copy=True),
'recurring_invoices' : fields.boolean('Generate recurring invoices automatically'),
'recurring_rule_type': fields.selection([
('daily', 'Day(s)'),
@ -595,8 +594,7 @@ class account_analytic_account(osv.osv):
return value
def cron_account_analytic_account(self, cr, uid, context=None):
if context is None:
context = {}
context = dict(context or {})
remind = {}
def fill_remind(key, domain, write_pending=False):
@ -612,7 +610,7 @@ class account_analytic_account(osv.osv):
accounts = self.browse(cr, uid, accounts_ids, context=context)
for account in accounts:
if write_pending:
account.write({'state' : 'pending'}, context=context)
account.write({'state' : 'pending'})
remind_user = remind.setdefault(account.manager_id.id, {})
remind_type = remind_user.setdefault(key, {})
remind_partner = remind_type.setdefault(account.partner_id, []).append(account)

View File

@ -43,8 +43,15 @@ class one2many_mod2(fields.one2many):
ids2 = obj.pool[self._obj].search(cr, user, [(self._fields_id,'in',ids),('analytic_account_id','child_of',[acc_id])], limit=self._limit)
if ids2 is None:
ids2 = obj.pool[self._obj].search(cr, user, [(self._fields_id,'in',ids)], limit=self._limit)
for r in obj.pool[self._obj]._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
res[r[self._fields_id]].append( r['id'] )
for r in obj.pool[self._obj].read(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
key = r[self._fields_id]
if isinstance(key, tuple):
# Read return a tuple in the case where the field is a many2one
# but we want to get the id of this field.
key = key[0]
res[key].append( r['id'] )
return res
class account_analytic_line(osv.osv):
@ -71,7 +78,7 @@ class account_analytic_plan(osv.osv):
_description = "Analytic Plan"
_columns = {
'name': fields.char('Analytic Plan', required=True, select=True),
'plan_ids': fields.one2many('account.analytic.plan.line', 'plan_id', 'Analytic Plans'),
'plan_ids': fields.one2many('account.analytic.plan.line', 'plan_id', 'Analytic Plans', copy=True),
}
@ -100,7 +107,7 @@ class account_analytic_plan_instance(osv.osv):
'name': fields.char('Analytic Distribution'),
'code': fields.char('Distribution Code', size=16),
'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal' ),
'account_ids': fields.one2many('account.analytic.plan.instance.line', 'plan_id', 'Account Id'),
'account_ids': fields.one2many('account.analytic.plan.instance.line', 'plan_id', 'Account Id', copy=True),
'account1_ids': one2many_mod2('account.analytic.plan.instance.line', 'plan_id', 'Account1 Id'),
'account2_ids': one2many_mod2('account.analytic.plan.instance.line', 'plan_id', 'Account2 Id'),
'account3_ids': one2many_mod2('account.analytic.plan.instance.line', 'plan_id', 'Account3 Id'),
@ -124,13 +131,6 @@ class account_analytic_plan_instance(osv.osv):
context=context, count=count)
return res
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
default.update({'account1_ids':False, 'account2_ids':False, 'account3_ids':False,
'account4_ids':False, 'account5_ids':False, 'account6_ids':False})
return super(account_analytic_plan_instance, self).copy(cr, uid, id, default, context=context)
def _default_journal(self, cr, uid, context=None):
if context is None:
context = {}
@ -373,8 +373,8 @@ class account_invoice(osv.osv):
res['analytics_id'] = x.get('analytics_id', False)
return res
def _get_analytic_lines(self, cr, uid, id, context=None):
inv = self.browse(cr, uid, [id])[0]
def _get_analytic_lines(self, cr, uid, ids, context=None):
inv = self.browse(cr, uid, ids)[0]
cur_obj = self.pool.get('res.currency')
invoice_line_obj = self.pool.get('account.invoice.line')
acct_ins_obj = self.pool.get('account.analytic.plan.instance')

View File

@ -45,7 +45,7 @@ class account_crossovered_analytic(osv.osv_memory):
res = cr.fetchall()
acc_ids = [x[0] for x in res]
data = self.read(cr, uid, ids, [], context=context)[0]
data = self.read(cr, uid, ids, context=context)[0]
data['ref'] = data['ref'][0]
obj_acc = self.pool.get('account.analytic.account').browse(cr, uid, data['ref'], context=context)

View File

@ -127,8 +127,8 @@
Reception is ready for process so now done the reception.
-
!python {model: stock.picking}: |
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001")).picking_ids[0]
picking_id.do_transfer(context=context)
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001"), context=context).picking_ids[0]
picking_id.do_transfer()
-
I check the Stock Interim account (Received) is credited successfully.
-
@ -144,7 +144,7 @@
-
!python {model: purchase.order}: |
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001")).invoice_ids]
self.pool.get('account.invoice').signal_invoice_open(cr, uid, invoice_ids)
self.pool.get('account.invoice').signal_workflow(cr, uid, invoice_ids, 'invoice_open')
-
I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
-
@ -166,7 +166,7 @@
!python {model: purchase.order}: |
po = self.browse(cr, uid, ref("purchase_order_001"))
for invoice in po.invoice_ids:
self.pool.get('account.invoice').signal_invoice_open(cr, uid, [invoice.id])
invoice.signal_workflow('invoice_open')
-
I pay the invoice.
-
@ -220,8 +220,8 @@
I process the delivery.
-
!python {model: stock.picking}: |
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001"))
picking.do_transfer(context=context)
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001"), context=context)
picking.do_transfer()
-
I check Stock Interim account (Delivery) is debited successfully.
-
@ -252,7 +252,7 @@
!python {model: stock.picking}: |
move_name = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001')).name
account_invoice = self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)])
self.pool.get('account.invoice').signal_invoice_open(cr, uid, account_invoice)
self.pool.get('account.invoice').signal_workflow(cr, uid, account_invoice, 'invoice_open')
-
I check Income Account is Credited sucessfully when Invoice validated.
-

View File

@ -135,8 +135,8 @@
Reception is ready for process so now done the reception.
-
!python {model: stock.picking}: |
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001_fifo")).picking_ids[0]
picking_id.do_transfer(context=context)
picking_id = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001_fifo"), context=context).picking_ids[0]
picking_id.do_transfer()
-
I check the Stock Interim account (Received) is credit successfully.
-
@ -154,7 +154,7 @@
invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids]
line_ids = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', invoice_ids)])
self.pool.get('account.invoice.line').write(cr, uid, line_ids, {'price_unit': 10})
self.pool.get('account.invoice').signal_invoice_open(cr, uid, invoice_ids)
self.pool.get('account.invoice').signal_workflow(cr, uid, invoice_ids, 'invoice_open')
-
I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
-
@ -220,8 +220,8 @@
I process the delivery.
-
!python {model: stock.picking}: |
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001_fifo"))
picking.do_transfer(context=context)
picking = self.pool.get('stock.picking').browse(cr, uid, ref("stock_picking_out001_fifo"), context=context)
picking.do_transfer()
-
I check Stock Interim account (Delivery) is debited successfully.
-
@ -257,7 +257,7 @@
account_invoice_line = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', account_invoice)])
self.pool.get('account.invoice.line').write(cr, uid, account_invoice_line, {'invoice_line_tax_id': [(6, 0, [])]})
self.pool.get('account.invoice').button_reset_taxes(cr, uid, account_invoice)
self.pool.get('account.invoice').signal_invoice_open(cr, uid, account_invoice)
self.pool.get('account.invoice').signal_workflow(cr, uid, account_invoice, 'invoice_open')
-
I check Income Account is Credited sucessfully when Invoice validated.
-

View File

@ -254,9 +254,9 @@ class account_asset_asset(osv.osv):
'note': fields.text('Note'),
'category_id': fields.many2one('account.asset.category', 'Asset Category', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
'parent_id': fields.many2one('account.asset.asset', 'Parent Asset', readonly=True, states={'draft':[('readonly',False)]}),
'child_ids': fields.one2many('account.asset.asset', 'parent_id', 'Children Assets'),
'child_ids': fields.one2many('account.asset.asset', 'parent_id', 'Children Assets', copy=True),
'purchase_date': fields.date('Purchase Date', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'state': fields.selection([('draft','Draft'),('open','Running'),('close','Close')], 'Status', required=True,
'state': fields.selection([('draft','Draft'),('open','Running'),('close','Close')], 'Status', required=True, copy=False,
help="When an asset is created, the status is 'Draft'.\n" \
"If the asset is confirmed, the status goes in 'Running' and the depreciation lines can be posted in the accounting.\n" \
"You can manually close an asset when the depreciation is over. If the last line of depreciation is posted, the asset automatically goes in that status."),
@ -329,23 +329,13 @@ class account_asset_asset(osv.osv):
res['value'] = {'prorata': False}
return res
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
if context is None:
context = {}
default.update({'depreciation_line_ids': [], 'account_move_line_ids': [], 'history_ids': [], 'state': 'draft'})
return super(account_asset_asset, self).copy(cr, uid, id, default, context=context)
def _compute_entries(self, cr, uid, ids, period_id, context=None):
result = []
period_obj = self.pool.get('account.period')
depreciation_obj = self.pool.get('account.asset.depreciation.line')
period = period_obj.browse(cr, uid, period_id, context=context)
depreciation_ids = depreciation_obj.search(cr, uid, [('asset_id', 'in', ids), ('depreciation_date', '<=', period.date_stop), ('depreciation_date', '>=', period.date_start), ('move_check', '=', False)], context=context)
if context is None:
context = {}
context.update({'depreciation_date':period.date_stop})
context = dict(context or {}, depreciation_date=period.date_stop)
return depreciation_obj.create_move(cr, uid, depreciation_ids, context=context)
def create(self, cr, uid, vals, context=None):
@ -354,9 +344,7 @@ class account_asset_asset(osv.osv):
return asset_id
def open_entries(self, cr, uid, ids, context=None):
if context is None:
context = {}
context.update({'search_default_asset_id': ids, 'default_asset_id': ids})
context = dict(context or {}, search_default_asset_id=ids, default_asset_id=ids)
return {
'name': _('Journal Items'),
'view_type': 'form',
@ -392,9 +380,8 @@ class account_asset_depreciation_line(osv.osv):
}
def create_move(self, cr, uid, ids, context=None):
context = dict(context or {})
can_close = False
if context is None:
context = {}
asset_obj = self.pool.get('account.asset.asset')
period_obj = self.pool.get('account.period')
move_obj = self.pool.get('account.move')
@ -466,8 +453,6 @@ class account_move_line(osv.osv):
_inherit = 'account.move.line'
_columns = {
'asset_id': fields.many2one('account.asset.asset', 'Asset', ondelete="restrict"),
'entry_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}),
}
class account_asset_history(osv.osv):

View File

@ -39,21 +39,27 @@ class account_bank_statement(osv.osv):
return res
def button_confirm_bank(self, cr, uid, ids, context=None):
bank_statement_line_obj = self.pool.get('account.bank.statement.line')
super(account_bank_statement, self).button_confirm_bank(cr, uid, ids, context=context)
for st in self.browse(cr, uid, ids, context=context):
if st.line_ids:
line_ids = [l.id for l in st.line_ids]
cr.execute("UPDATE account_bank_statement_line \
SET state='confirm' WHERE id in %s ",
(tuple([x.id for x in st.line_ids]),))
(tuple(line_ids),))
bank_statement_line_obj.invalidate_cache(cr, uid, ['state'], line_ids, context=context)
return True
def button_cancel(self, cr, uid, ids, context=None):
bank_statement_line_obj = self.pool.get('account.bank.statement.line')
super(account_bank_statement, self).button_cancel(cr, uid, ids, context=context)
for st in self.browse(cr, uid, ids, context=context):
if st.line_ids:
line_ids = [l.id for l in st.line_ids]
cr.execute("UPDATE account_bank_statement_line \
SET state='draft' WHERE id in %s ",
(tuple([x.id for x in st.line_ids]),))
(tuple([line_ids]),))
bank_statement_line_obj.invalidate_cache(cr, uid, ['state'], line_ids, context=context)
return True
@ -65,7 +71,7 @@ class account_bank_statement_line_global(osv.osv):
'name': fields.char('OBI', required=True, help="Originator to Beneficiary Information"),
'code': fields.char('Code', size=64, required=True),
'parent_id': fields.many2one('account.bank.statement.line.global', 'Parent Code', ondelete='cascade'),
'child_ids': fields.one2many('account.bank.statement.line.global', 'parent_id', 'Child Codes'),
'child_ids': fields.one2many('account.bank.statement.line.global', 'parent_id', 'Child Codes', copy=True),
'type': fields.selection([
('iso20022', 'ISO 20022'),
('coda', 'CODA'),
@ -110,7 +116,7 @@ class account_bank_statement_line(osv.osv):
'globalisation_amount': fields.related('globalisation_id', 'amount', type='float',
relation='account.bank.statement.line.global', string='Glob. Amount', readonly=True),
'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed')],
'Status', required=True, readonly=True),
'Status', required=True, readonly=True, copy=False),
'counterparty_name': fields.char('Counterparty Name', size=35),
'counterparty_bic': fields.char('Counterparty BIC', size=11),
'counterparty_number': fields.char('Counterparty Number', size=34),

View File

@ -62,8 +62,8 @@ class crossovered_budget(osv.osv):
'validating_user_id': fields.many2one('res.users', 'Validate User', readonly=True),
'date_from': fields.date('Start Date', required=True, states={'done':[('readonly',True)]}),
'date_to': fields.date('End Date', required=True, states={'done':[('readonly',True)]}),
'state' : fields.selection([('draft','Draft'),('cancel', 'Cancelled'),('confirm','Confirmed'),('validate','Validated'),('done','Done')], 'Status', select=True, required=True, readonly=True),
'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'crossovered_budget_id', 'Budget Lines', states={'done':[('readonly',True)]}),
'state' : fields.selection([('draft','Draft'),('cancel', 'Cancelled'),('confirm','Confirmed'),('validate','Validated'),('done','Done')], 'Status', select=True, required=True, readonly=True, copy=False),
'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'crossovered_budget_id', 'Budget Lines', states={'done':[('readonly',True)]}, copy=True),
'company_id': fields.many2one('res.company', 'Company', required=True),
}

View File

@ -33,7 +33,7 @@ class account_check_write(osv.osv_memory):
def _get_next_number(self, cr, uid, context=None):
dummy, sequence_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_check_writing', 'sequence_check_number')
return self.pool.get('ir.sequence').read(cr, uid, sequence_id, ['number_next'])['number_next']
return self.pool.get('ir.sequence').read(cr, uid, [sequence_id], ['number_next'])[0]['number_next']
_defaults = {
'check_number': _get_next_number,
@ -47,7 +47,7 @@ class account_check_write(osv.osv_memory):
#update the sequence to number the checks from the value encoded in the wizard
dummy, sequence_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_check_writing', 'sequence_check_number')
increment = ir_sequence_obj.read(cr, uid, sequence_id, ['number_increment'])['number_increment']
increment = ir_sequence_obj.read(cr, uid, [sequence_id], ['number_increment'])[0]['number_increment']
new_value = self.browse(cr, uid, ids[0], context=context).check_number
ir_sequence_obj.write(cr, uid, sequence_id, {'number_next': new_value})

View File

@ -19,6 +19,7 @@
#
##############################################################################
from openerp import api
from openerp.osv import fields, osv
from lxml import etree
from openerp.tools.translate import _
@ -28,7 +29,7 @@ class followup(osv.osv):
_description = 'Account Follow-up'
_rec_name = 'name'
_columns = {
'followup_line': fields.one2many('account_followup.followup.line', 'followup_id', 'Follow-up'),
'followup_line': fields.one2many('account_followup.followup.line', 'followup_id', 'Follow-up', copy=True),
'company_id': fields.many2one('res.company', 'Company', required=True),
'name': fields.related('company_id', 'name', string = "Name", readonly=True, type="char"),
}
@ -154,6 +155,7 @@ class res_partner(osv.osv):
'latest_followup_level_id_without_lit': latest_level_without_lit}
return res
@api.cr_uid_ids_context
def do_partner_manual_action(self, cr, uid, partner_ids, context=None):
#partner_ids -> res.partner
for partner in self.browse(cr, uid, partner_ids, context=context):
@ -190,6 +192,7 @@ class res_partner(osv.osv):
}
return self.pool['report'].get_action(cr, uid, [], 'account_followup.report_followup', data=datas, context=context)
@api.cr_uid_ids_context
def do_partner_mail(self, cr, uid, partner_ids, context=None):
if context is None:
context = {}
@ -268,7 +271,7 @@ class res_partner(osv.osv):
if date <= current_date and aml['balance'] > 0:
strbegin = "<TD><B>"
strend = "</B></TD>"
followup_table +="<TR>" + strbegin + str(aml['date']) + strend + strbegin + aml['name'] + strend + strbegin + aml['ref'] + strend + strbegin + str(date) + strend + strbegin + str(aml['balance']) + strend + strbegin + block + strend + "</TR>"
followup_table +="<TR>" + strbegin + str(aml['date']) + strend + strbegin + aml['name'] + strend + strbegin + (aml['ref'] or '') + strend + strbegin + str(date) + strend + strbegin + str(aml['balance']) + strend + strbegin + block + strend + "</TR>"
total = reduce(lambda x, y: x+y['balance'], currency_dict['line'], 0.00)
@ -434,15 +437,17 @@ class res_partner(osv.osv):
_columns = {
'payment_responsible_id':fields.many2one('res.users', ondelete='set null', string='Follow-up Responsible',
help="Optionally you can assign a user to this field, which will make him responsible for the action.",
track_visibility="onchange"),
'payment_note':fields.text('Customer Payment Promise', help="Payment Note", track_visibility="onchange"),
'payment_next_action':fields.text('Next Action',
track_visibility="onchange", copy=False),
'payment_note':fields.text('Customer Payment Promise', help="Payment Note", track_visibility="onchange", copy=False),
'payment_next_action':fields.text('Next Action', copy=False,
help="This is the next action to be taken. It will automatically be set when the partner gets a follow-up level that requires a manual action. ",
track_visibility="onchange"),
'payment_next_action_date':fields.date('Next Action Date',
help="This is when the manual follow-up is needed. " \
"The date will be set to the current date when the partner gets a follow-up level that requires a manual action. "\
"Can be practical to set manually e.g. to see if he keeps his promises."),
'payment_next_action_date': fields.date('Next Action Date', copy=False,
help="This is when the manual follow-up is needed. "
"The date will be set to the current date when the partner "
"gets a follow-up level that requires a manual action. "
"Can be practical to set manually e.g. to see if he keeps "
"his promises."),
'unreconciled_aml_ids':fields.one2many('account.move.line', 'partner_id', domain=['&', ('reconcile_id', '=', False), '&',
('account_id.active','=', True), '&', ('account_id.type', '=', 'receivable'), ('state', '!=', 'draft')]),
'latest_followup_date':fields.function(_get_latest, method=True, type='date', string="Latest Follow-up Date",

View File

@ -75,9 +75,7 @@ class report_rappel(report_sxw.rml_parse):
return [{'line': lines} for lines in lines_per_currency.values()]
def _get_text(self, stat_line, followup_id, context=None):
if context is None:
context = {}
context.update({'lang': stat_line.partner_id.lang})
context = dict(context or {}, lang=stat_line.partner_id.lang)
fp_obj = self.pool['account_followup.followup']
fp_line = fp_obj.browse(self.cr, self.uid, followup_id, context=context).followup_line
if not fp_line:

View File

@ -42,7 +42,7 @@ class TestAccountFollowup(TransactionCase):
'quantity': 5,
'price_unit':200
})]})
self.registry('account.invoice').signal_invoice_open(cr, uid, [self.invoice_id])
self.registry('account.invoice').signal_workflow(cr, uid, [self.invoice_id], 'invoice_open')
self.voucher = self.registry("account.voucher")
@ -112,8 +112,7 @@ class TestAccountFollowup(TransactionCase):
partner_rec = self.partner.browse(cr, uid, self.partner_id)
self.run_wizard_three_times()
self.partner.action_done(cr, uid, self.partner_id)
self.assertEqual(partner_rec.payment_next_action,
"", "Manual action not emptied")
self.assertFalse(partner_rec.payment_next_action, "Manual action not emptied")
self.assertFalse(partner_rec.payment_responsible_id)
self.assertFalse(partner_rec.payment_next_action_date)

View File

@ -204,15 +204,14 @@ class account_followup_print(osv.osv_memory):
return len(partners_to_clear)
def do_process(self, cr, uid, ids, context=None):
if context is None:
context = {}
context = dict(context or {})
#Get partners
tmp = self._get_partners_followp(cr, uid, ids, context=context)
partner_list = tmp['partner_ids']
to_update = tmp['to_update']
date = self.browse(cr, uid, ids, context=context)[0].date
data = self.read(cr, uid, ids, [], context=context)[0]
data = self.read(cr, uid, ids, context=context)[0]
data['followup_id'] = data['followup_id'][0]
#Update partners

View File

@ -87,13 +87,13 @@ class payment_order(osv.osv):
_columns = {
'date_scheduled': fields.date('Scheduled Date', states={'done':[('readonly', True)]}, help='Select a date if you have chosen Preferred Date to be fixed.'),
'reference': fields.char('Reference', required=1, states={'done': [('readonly', True)]}),
'reference': fields.char('Reference', required=1, states={'done': [('readonly', True)]}, copy=False),
'mode': fields.many2one('payment.mode', 'Payment Mode', select=True, required=1, states={'done': [('readonly', True)]}, help='Select the Payment Mode to be applied.'),
'state': fields.selection([
('draft', 'Draft'),
('cancel', 'Cancelled'),
('open', 'Confirmed'),
('done', 'Done')], 'Status', select=True,
('done', 'Done')], 'Status', select=True, copy=False,
help='When an order is placed the status is \'Draft\'.\n Once the bank is confirmed the status is set to \'Confirmed\'.\n Then the order is paid the status is \'Done\'.'),
'line_ids': fields.one2many('payment.line', 'order_id', 'Payment lines', states={'done': [('readonly', True)]}),
'total': fields.function(_total, string="Total", type='float'),
@ -132,19 +132,9 @@ class payment_order(osv.osv):
def set_done(self, cr, uid, ids, *args):
self.write(cr, uid, ids, {'date_done': time.strftime('%Y-%m-%d')})
self.signal_done(cr, uid, [ids[0]])
self.signal_workflow(cr, uid, ids, 'done')
return True
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
default.update({
'state': 'draft',
'line_ids': [],
'reference': self.pool.get('ir.sequence').get(cr, uid, 'payment.order')
})
return super(payment_order, self).copy(cr, uid, id, default, context=context)
def write(self, cr, uid, ids, vals, context=None):
if context is None:
context = {}
@ -179,7 +169,7 @@ class payment_line(osv.osv):
"due_date": "date_maturity",
"reference": "ref"}.get(orig, orig)
def info_owner(self, cr, uid, ids, name=None, args=None, context=None):
def _info_owner(self, cr, uid, ids, name=None, args=None, context=None):
result = {}
for line in self.browse(cr, uid, ids, context=context):
owner = line.order_id.mode.bank_id.partner_id
@ -197,7 +187,7 @@ class payment_line(osv.osv):
cntry = partner_record.country_id and partner_record.country_id.name or ''
return partner_record.name + "\n" + st + " " + st1 + "\n" + zip_city + "\n" +cntry
def info_partner(self, cr, uid, ids, name=None, args=None, context=None):
def _info_partner(self, cr, uid, ids, name=None, args=None, context=None):
result = {}
for line in self.browse(cr, uid, ids, context=context):
result[line.id] = False
@ -322,8 +312,8 @@ class payment_line(osv.osv):
type='date', help="Invoice Effective Date"),
'ml_maturity_date': fields.function(_get_ml_maturity_date, type='date', string='Due Date'),
'ml_inv_ref': fields.function(_get_ml_inv_ref, type='many2one', relation='account.invoice', string='Invoice Ref.'),
'info_owner': fields.function(info_owner, string="Owner Account", type="text", help='Address of the Main Partner'),
'info_partner': fields.function(info_partner, string="Destination Account", type="text", help='Address of the Ordering Customer.'),
'info_owner': fields.function(_info_owner, string="Owner Account", type="text", help='Address of the Main Partner'),
'info_partner': fields.function(_info_partner, string="Destination Account", type="text", help='Address of the Ordering Customer.'),
'date': fields.date('Payment Date', help="If no payment date is specified, the bank will treat this payment line directly"),
'create_date': fields.datetime('Created', readonly=True),
'state': fields.selection([('normal','Free'), ('structured','Structured')], 'Communication Type', required=True),

View File

@ -79,7 +79,7 @@
-
I create a bank statement.
-
!record {model: account.bank.statement, id: account_bank_statement_1}:
!record {model: account.bank.statement, id: account_bank_statement_1, view: False}:
balance_end_real: 0.0
balance_start: 0.0
date: !eval time.strftime('%Y-%m-%d')

View File

@ -107,7 +107,7 @@ class payment_order_create(osv.osv_memory):
domain = [('reconcile_id', '=', False), ('account_id.type', '=', 'payable'), ('credit', '>', 0), ('account_id.reconcile', '=', True)]
domain = domain + ['|', ('date_maturity', '<=', search_due_date), ('date_maturity', '=', False)]
line_ids = line_obj.search(cr, uid, domain, context=context)
context.update({'line_ids': line_ids})
context = dict(context, line_ids=line_ids)
model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_create_payment_order_lines')], context=context)
resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {'name': _('Entry Lines'),

View File

@ -62,7 +62,7 @@ class account_payment_populate_statement(osv.osv_memory):
if context is None:
context = {}
data = self.read(cr, uid, ids, [], context=context)[0]
data = self.read(cr, uid, ids, context=context)[0]
line_ids = data['lines']
if not line_ids:
return {'type': 'ir.actions.act_window_close'}
@ -77,7 +77,7 @@ class account_payment_populate_statement(osv.osv_memory):
if not line.move_line_id.id:
continue
context.update({'move_line_ids': [line.move_line_id.id]})
context = dict(context, move_line_ids=[line.move_line_id.id])
result = voucher_obj.onchange_partner_id(cr, uid, [], partner_id=line.partner_id.id, journal_id=statement.journal_id.id, amount=abs(amount), currency_id= statement.currency.id, ttype='payment', date=line.ml_maturity_date, context=context)
if line.move_line_id:

View File

@ -26,7 +26,9 @@ class account_move(osv.osv):
_inherit = 'account.move'
_columns = {
'internal_sequence_number': fields.char('Internal Number', readonly=True, help='Internal Sequence Number'),
'internal_sequence_number': fields.char('Internal Number',
readonly=True, copy=False,
help='Internal Sequence Number'),
}
def post(self, cr, uid, ids, context=None):

View File

@ -335,10 +335,13 @@ class account_voucher(osv.osv):
('receipt','Receipt'),
],'Default Type', readonly=True, states={'draft':[('readonly',False)]}),
'name':fields.char('Memo', readonly=True, states={'draft':[('readonly',False)]}),
'date':fields.date('Date', readonly=True, select=True, states={'draft':[('readonly',False)]}, help="Effective date for accounting entries"),
'date':fields.date('Date', readonly=True, select=True, states={'draft':[('readonly',False)]},
help="Effective date for accounting entries", copy=False),
'journal_id':fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'account_id':fields.many2one('account.account', 'Account', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'line_ids':fields.one2many('account.voucher.line','voucher_id','Voucher Lines', readonly=True, states={'draft':[('readonly',False)]}),
'line_ids':fields.one2many('account.voucher.line', 'voucher_id', 'Voucher Lines',
readonly=True, copy=True,
states={'draft':[('readonly',False)]}),
'line_cr_ids':fields.one2many('account.voucher.line','voucher_id','Credits',
domain=[('type','=','cr')], context={'default_type':'cr'}, readonly=True, states={'draft':[('readonly',False)]}),
'line_dr_ids':fields.one2many('account.voucher.line','voucher_id','Debits',
@ -352,16 +355,17 @@ class account_voucher(osv.osv):
('cancel','Cancelled'),
('proforma','Pro-forma'),
('posted','Posted')
], 'Status', readonly=True, track_visibility='onchange',
], 'Status', readonly=True, track_visibility='onchange', copy=False,
help=' * The \'Draft\' status is used when a user is encoding a new and unconfirmed Voucher. \
\n* The \'Pro-forma\' when voucher is in Pro-forma status,voucher does not have an voucher number. \
\n* The \'Posted\' status is used when user create voucher,a voucher number is generated and voucher entries are created in account \
\n* The \'Cancelled\' status is used when user cancel voucher.'),
'amount': fields.float('Total', digits_compute=dp.get_precision('Account'), required=True, readonly=True, states={'draft':[('readonly',False)]}),
'tax_amount':fields.float('Tax Amount', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
'reference': fields.char('Ref #', readonly=True, states={'draft':[('readonly',False)]}, help="Transaction reference number."),
'number': fields.char('Number', readonly=True,),
'move_id':fields.many2one('account.move', 'Account Entry'),
'reference': fields.char('Ref #', readonly=True, states={'draft':[('readonly',False)]},
help="Transaction reference number.", copy=False),
'number': fields.char('Number', readonly=True, copy=False),
'move_id':fields.many2one('account.move', 'Account Entry', copy=False),
'move_ids': fields.related('move_id','line_id', type='one2many', relation='account.move.line', string='Journal Items', readonly=True),
'partner_id':fields.many2one('res.partner', 'Partner', change_default=1, readonly=True, states={'draft':[('readonly',False)]}),
'audit': fields.related('move_id','to_check', type='boolean', help='Check this box if you are unsure of that journal entry and if you want to note it as \'to be reviewed\' by an accounting expert.', relation='account.move', string='To Review'),
@ -573,7 +577,7 @@ class account_voucher(osv.osv):
ctx.update({'date': date})
#read the voucher rate with the right date in the context
currency_id = currency_id or self.pool.get('res.company').browse(cr, uid, company_id, context=ctx).currency_id.id
voucher_rate = self.pool.get('res.currency').read(cr, uid, currency_id, ['rate'], context=ctx)['rate']
voucher_rate = self.pool.get('res.currency').read(cr, uid, [currency_id], ['rate'], context=ctx)[0]['rate']
ctx.update({
'voucher_special_currency': payment_rate_currency_id,
'voucher_special_currency_rate': rate * voucher_rate})
@ -615,7 +619,7 @@ class account_voucher(osv.osv):
'payment_rate_currency_id': payment_rate_currency_id
})
#read the voucher rate with the right date in the context
voucher_rate = self.pool.get('res.currency').read(cr, uid, currency_id, ['rate'], context=ctx)['rate']
voucher_rate = self.pool.get('res.currency').read(cr, uid, [currency_id], ['rate'], context=ctx)[0]['rate']
ctx.update({
'voucher_special_currency_rate': payment_rate * voucher_rate,
'voucher_special_currency': payment_rate_currency_id})
@ -847,7 +851,7 @@ class account_voucher(osv.osv):
ctx = context.copy()
ctx.update({'date': date})
#read the voucher rate with the right date in the context
voucher_rate = self.pool.get('res.currency').read(cr, uid, currency_id, ['rate'], context=ctx)['rate']
voucher_rate = self.pool.get('res.currency').read(cr, uid, [currency_id], ['rate'], context=ctx)[0]['rate']
ctx.update({
'voucher_special_currency_rate': payment_rate * voucher_rate,
'voucher_special_currency': payment_rate_currency_id})
@ -922,7 +926,7 @@ class account_voucher(osv.osv):
return vals
def button_proforma_voucher(self, cr, uid, ids, context=None):
self.signal_proforma_voucher(cr, uid, ids)
self.signal_workflow(cr, uid, ids, 'proforma_voucher')
return {'type': 'ir.actions.act_window_close'}
def proforma_voucher(self, cr, uid, ids, context=None):
@ -1182,7 +1186,7 @@ class account_voucher(osv.osv):
tot_line = line_total
rec_lst_ids = []
date = self.read(cr, uid, voucher_id, ['date'], context=context)['date']
date = self.read(cr, uid, [voucher_id], ['date'], context=context)[0]['date']
ctx = context.copy()
ctx.update({'date': date})
voucher = self.pool.get('account.voucher').browse(cr, uid, voucher_id, context=ctx)
@ -1419,22 +1423,6 @@ class account_voucher(osv.osv):
reconcile = move_line_pool.reconcile_partial(cr, uid, rec_ids, writeoff_acc_id=voucher.writeoff_acc_id.id, writeoff_period_id=voucher.period_id.id, writeoff_journal_id=voucher.journal_id.id)
return True
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
default.update({
'state': 'draft',
'number': False,
'move_id': False,
'line_cr_ids': False,
'line_dr_ids': False,
'reference': False
})
if 'date' not in default:
default['date'] = time.strftime('%Y-%m-%d')
return super(account_voucher, self).copy(cr, uid, id, default, context)
class account_voucher_line(osv.osv):
_name = 'account.voucher.line'
_description = 'Voucher Lines'
@ -1495,7 +1483,7 @@ class account_voucher_line(osv.osv):
'reconcile': fields.boolean('Full Reconcile'),
'type':fields.selection([('dr','Debit'),('cr','Credit')], 'Dr/Cr'),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
'move_line_id': fields.many2one('account.move.line', 'Journal Item'),
'move_line_id': fields.many2one('account.move.line', 'Journal Item', copy=False),
'date_original': fields.related('move_line_id','date', type='date', relation='account.move.line', string='Date', readonly=1),
'date_due': fields.related('move_line_id','date_maturity', type='date', relation='account.move.line', string='Due Date', readonly=1),
'amount_original': fields.function(_compute_balance, multi='dc', type='float', string='Original Amount', store=True, digits_compute=dp.get_precision('Account')),

View File

@ -182,7 +182,7 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 1 USD/USD'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my first voucher is valid
-
@ -276,7 +276,7 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'Second payment: Case 1'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my second voucher is valid
-

View File

@ -191,7 +191,7 @@
-
!python {model: account.voucher}: |
voucher = ref('account_voucher_1_case1_payment_rate')
self.signal_proforma_voucher(cr, uid, [voucher])
self.signal_workflow(cr, uid, [voucher], 'proforma_voucher')
-
I check that the move of my first voucher is valid
-

View File

@ -161,7 +161,7 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 2 SUPPL USD/EUR'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my voucher is valid
-
@ -263,7 +263,7 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'Second payment: Case 2 SUPPL USD/EUR'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that my voucher state is posted
-

View File

@ -182,7 +182,7 @@
!python {model: account.voucher}: |
from openerp import netsvc
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 2 USD/EUR DR EUR'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my voucher is valid
-
@ -257,7 +257,7 @@
!python {model: account.voucher}: |
from openerp import netsvc
voucher = self.search(cr, uid, [('name', '=', 'Second payment: Case 2 SUPPL USD/EUR DR EUR'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that my voucher state is posted
-

View File

@ -179,7 +179,7 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 2 USD/EUR DR USD'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my voucher is valid
-
@ -266,7 +266,7 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'Second payment: Case 2 SUPPL USD/EUR DR USD'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that my voucher state is posted
-

View File

@ -141,7 +141,7 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 3'),('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my first voucher is valid
-
@ -228,7 +228,8 @@
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'Second payment: Case 3'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my second voucher is valid
-

View File

@ -88,12 +88,13 @@
I check that first invoice move is correct for debtor account (debit - credit == 149.39)
-
!python {model: account.invoice}: |
from openerp.tools import float_compare
invoice_id = self.browse(cr, uid, ref("account_first_invoice_jan_cad"))
assert invoice_id.move_id, "Move not created for open invoice"
move_line_obj = self.pool.get('account.move.line')
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)])
move_line = move_line_obj.browse(cr, uid, move_lines[0])
assert (move_line.debit - move_line.credit == 149.39), "Invoice move is incorrect for debtors account"
assert float_compare(move_line.debit - move_line.credit, 149.39, 2) == 0, "Invoice move is incorrect for debtors account"
-
I set the context that will be used for the encoding of all the vouchers of this file
-
@ -142,9 +143,9 @@
I confirm the voucher
-
!python {model: account.voucher}: |
from openerp import netsvc
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 4'), ('partner_id', '=', ref('base.res_partner_19'))])
self.signal_proforma_voucher(cr, uid, voucher)
self.signal_workflow(cr, uid, voucher, 'proforma_voucher')
-
I check that the move of my voucher is valid
-
@ -166,15 +167,17 @@
I check that my writeoff is correct. 11.05 credit and -13.26 amount_currency
-
!python {model: account.voucher}: |
from openerp.tools import float_compare
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 4'), ('partner_id', '=', ref('base.res_partner_19'))])
voucher_id = self.browse(cr, uid, voucher[0])
move_line_obj = self.pool.get('account.move.line')
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', voucher_id.move_id.id)])
assert move_lines, "Voucher move has no lines"
for move_line in move_line_obj.browse(cr, uid, move_lines):
if move_line.amount_currency == 200:
assert move_line.debit == 160.00, "Bank account has wrong entry."
elif move_line.amount_currency == -298.78:
assert move_line.credit == 149.39, "Debtor account has wrong entry."
if float_compare(move_line.amount_currency, 200, 2) == 0:
assert float_compare(move_line.debit, 160.00, 2) == 0, "Bank account has wrong entry."
elif float_compare(move_line.amount_currency, -298.78, 2) == 0:
assert float_compare(move_line.credit, 149.39, 2) == 0, "Debtor account has wrong entry."
elif move_line.debit == 0.00 and move_line.credit == 0.00:
assert move_line.amount_currency == 98.78, "Incorrect Currency Difference, got %s as amount_currency (expected 98.78)." % (move_line.amount_currency)
assert move_line.currency_id.id == ref('base.CAD'), "Incorrect Currency Difference, got %s (expected 'CAD')" % (move_line.currency_id.name)

View File

@ -16,14 +16,14 @@
-
!record {model: res.currency.rate, id: nov_usd}:
currency_id: base.USD
name: !eval "'%s-11-01' %(datetime.now().year)"
name: !eval "'%s-11-01 00:00:00' %(datetime.now().year)"
rate: 1.8
-
I create currency USD in OpenERP for December of 1.5 Rate
-
!record {model: res.currency.rate, id: dec_usd}:
currency_id: base.USD
name: !eval "'%s-12-01' %(datetime.now().year)"
name: !eval "'%s-12-01 00:00:00' %(datetime.now().year)"
rate: 1.5
-
I set the income and expense currency accounts on the main company
@ -92,13 +92,16 @@
I check that first invoice move is correct for creditor account(debit - credit == -555.56)
-
!python {model: account.invoice}: |
from openerp.tools import float_compare
invoice_id = self.browse(cr, uid, ref("account_supplier_invoice_november"))
assert invoice_id.move_id, "Move not created for open invoice"
move_line_obj = self.pool.get('account.move.line')
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('account_id', '=', invoice_id.account_id.id)])
move_line = move_line_obj.browse(cr, uid, move_lines[0])
assert (move_line.debit - move_line.credit == -555.56), "Invoice move is incorrect for creditor account"
assert (move_line.amount_currency == -1000), "Amount currency is incorrect for creditor account"
assert float_compare(move_line.debit - move_line.credit, -555.56, 2) == 0, \
"Invoice move is incorrect for creditor account"
assert float_compare(move_line.amount_currency, -1000, 2) == 0, \
"Amount currency is incorrect for creditor account"
-
I set the context that will be used for the encoding of all the vouchers of this file
-

View File

@ -107,6 +107,7 @@
for item in voucher.line_cr_ids:
if item.amount_unreconciled == 1400:
data += [(item.id, 1400)]
assert data, "Credit line not found"
for line_id, amount in data:
self.pool.get('account.voucher.line').write(cr, uid, [line_id], {'amount': amount})
assert (voucher.state=='draft'), "Voucher is not in draft state"
@ -170,5 +171,6 @@
move_line_obj = self.pool.get('account.move.line')
move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
move_line = move_line_obj.browse(cr, uid, move_lines[0])
assert (move_line.amount_residual_currency == 0.0 and move_line.amount_residual == 0.0 and invoice_id.state == 'paid') , "Residual amount is not correct for Invoice"
assert move_line.amount_residual_currency == 0.0, "Residual amount is not correct for Invoice"
assert move_line.amount_residual == 0.0, "Residual amount is not correct for Invoice"
assert invoice_id.state == 'paid', "Invoice is not paid"

View File

@ -68,7 +68,7 @@
voucher_id = self.browse(cr, uid, id)
assert (voucher_id.writeoff_amount == 0.0), "Writeoff amount is not 0.0"
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
self.signal_proforma_voucher(cr, uid, [voucher_id.id])
voucher_id.signal_workflow('proforma_voucher')
-
Finally i will Confirm the state of the invoice is paid

View File

@ -69,7 +69,7 @@
id = self.create(cr, uid, vals)
voucher_id = self.browse(cr, uid, id)
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
self.signal_proforma_voucher(cr, uid, [voucher_id.id])
voucher_id.signal_workflow('proforma_voucher')
-
I check that move lines are reconciled meaning voucher is paid
-

View File

@ -159,7 +159,8 @@ class account_analytic_account(osv.osv):
if account.company_id.currency_id.id != value:
raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really useful for consolidation purposes of several companies charts with different currencies, for example."))
if value:
return cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id, ))
cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id))
self.invalidate_cache(cr, uid, ['currency_id'], [account.id], context=context)
def _currency(self, cr, uid, ids, field_name, arg, context=None):
result = {}
@ -173,7 +174,7 @@ class account_analytic_account(osv.osv):
_columns = {
'name': fields.char('Account/Contract Name', required=True, track_visibility='onchange'),
'complete_name': fields.function(_get_full_name, type='char', string='Full Name'),
'code': fields.char('Reference', select=True, track_visibility='onchange'),
'code': fields.char('Reference', select=True, track_visibility='onchange', copy=False),
'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Contract')], 'Type of Account', required=True,
help="If you select the View Type, it means you won\'t allow to create journal entries using that account.\n"\
"The type 'Analytic account' stands for usual accounts that you only want to use in accounting.\n"\
@ -196,7 +197,14 @@ class account_analytic_account(osv.osv):
'date_start': fields.date('Start Date'),
'date': fields.date('Expiration Date', select=True, track_visibility='onchange'),
'company_id': fields.many2one('res.company', 'Company', required=False), #not required because we want to allow different companies to use the same chart of account, except for leaf accounts.
'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'),('pending','To Renew'),('close','Closed'),('cancelled', 'Cancelled')], 'Status', required=True, track_visibility='onchange'),
'state': fields.selection([('template', 'Template'),
('draft','New'),
('open','In Progress'),
('pending','To Renew'),
('close','Closed'),
('cancelled', 'Cancelled')],
'Status', required=True,
track_visibility='onchange', copy=False),
'currency_id': fields.function(_currency, fnct_inv=_set_company_currency, #the currency_id field is readonly except if it's a view account and if there is no company
store = {
'res.company': (_get_analytic_account, ['currency_id'], 10),
@ -266,10 +274,7 @@ class account_analytic_account(osv.osv):
if not default:
default = {}
analytic = self.browse(cr, uid, id, context=context)
default.update(
code=False,
line_ids=[],
name=_("%s (copy)") % (analytic['name']))
default['name'] = _("%s (copy)") % analytic['name']
return super(account_analytic_account, self).copy(cr, uid, id, default, context=context)
def on_change_company(self, cr, uid, id, company_id):

View File

@ -19,7 +19,6 @@
#
##############################################################################
from openerp.osv import fields, osv
from openerp.osv.orm import intersect
from openerp.tools.translate import _
from openerp.addons.decimal_precision import decimal_precision as dp
@ -128,7 +127,7 @@ class account_analytic_account(osv.osv):
act_obj = self.pool.get('ir.actions.act_window')
dummy, act_window_id = mod_obj.get_object_reference(cr, uid, 'hr_expense', 'expense_all')
result = act_obj.read(cr, uid, act_window_id, context=context)
result = act_obj.read(cr, uid, [act_window_id], context=context)[0]
line_ids = self.pool.get('hr.expense.line').search(cr,uid,[('analytic_account', 'in', ids)])
result['domain'] = [('line_ids', 'in', line_ids)]

View File

@ -59,7 +59,7 @@ class analytic_user_funct_grid(osv.osv):
class account_analytic_account(osv.osv):
_inherit = "account.analytic.account"
_columns = {
'user_product_ids': fields.one2many('analytic.user.funct.grid', 'account_id', 'Users/Products Rel.'),
'user_product_ids': fields.one2many('analytic.user.funct.grid', 'account_id', 'Users/Products Rel.', copy=True),
}

View File

@ -32,6 +32,7 @@ class res_users(osv.osv):
def set_pw(self, cr, uid, id, name, value, args, context):
if value:
self._set_password(cr, uid, id, value, context=context)
self.invalidate_cache(cr, uid, context=context)
def get_pw( self, cr, uid, ids, name, args, context ):
cr.execute('select id, password from res_users where id in %s', (tuple(map(int, ids)),))
@ -39,7 +40,7 @@ class res_users(osv.osv):
_columns = {
'password': fields.function(get_pw, fnct_inv=set_pw, type='char', string='Password', invisible=True, store=True),
'password_crypt': fields.char(string='Encrypted Password', invisible=True),
'password_crypt': fields.char(string='Encrypted Password', invisible=True, copy=False),
}
def check_credentials(self, cr, uid, password):
@ -50,6 +51,7 @@ class res_users(osv.osv):
stored, encrypted = cr.fetchone()
if stored and not encrypted:
self._set_password(cr, uid, uid, stored)
self.invalidate_cache(cr, uid)
try:
return super(res_users, self).check_credentials(cr, uid, password)
except openerp.exceptions.AccessDenied:

View File

@ -1,22 +0,0 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * base_crypt
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2012-12-03 16:03+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""

View File

@ -1,76 +0,0 @@
# Bulgarian 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-02-18 09:47+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Bulgarian <bg@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#~ 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"
#~ " за предотвратяване прочита на оригиналната парола.\n"
#~ " За съществуващата потребителска база, когато премахването на паролите в "
#~ "чист текст се случва за първи път,\n"
#~ " влизане на потребител става, след инсталиране на base_crypt.\n"
#~ " След като инсталирате този модул няма да бъде възможно да се възстанови "
#~ "забравена парола за\n"
#~ " потребители, единственото решение е администратор, да зададе нова парола.\n"
#~ "\n"
#~ " Забележка: инсталиране на този модул не значи, че може да пренебрегне "
#~ "основните мерки за сигурност,\n"
#~ " като парола все още е изпратена в прав текст в мрежата (от клиента),\n"
#~ " освен ако не използвате защитен протокол, като XML-RPCS.\n"
#~ " "
#, python-format
#~ msgid "Error"
#~ msgstr "Грешка"
#~ msgid "Base - Password Encryption"
#~ msgstr "База - Криптиране на пароли"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Моля изберете парола!"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr "Избраната фирма не е измежду разрешените фирми за този потребител"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Не може да има двама потребители с един и същ \"логин\"!"

View File

@ -1,78 +0,0 @@
# Catalan 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-03-26 18:08+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Catalan <ca@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#~ 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 ""
#~ "Aquest mòdul substitueix la contrasenya en text pla per un hash codificat,\n"
#~ "prevenint que algú pugui llegir la contrasenya original.\n"
#~ "Per a un usuari existent, l'esborrat de la contrasenya en text pla es "
#~ "realitza la primera\n"
#~ "vegada que l'usuari es connecta després d'instal·lar base_crypt.\n"
#~ "Després d'instal·lar aquest mòdul, els usuaris no podran recuperar la seva "
#~ "contrasenya,\n"
#~ "un administrador haurà d'introduir una nova contrasenya.\n"
#~ "\n"
#~ "Nota: Instal·lar aquest mòdul no significa que podeu ignorar les mesures "
#~ "bàsiques de seguretat,\n"
#~ "perquè la contrasenya és enviada sense codificar pel client,\n"
#~ "a menys que utilitzeu un protocol segur com XML-RPCS.\n"
#~ " "
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Si us plau, escriviu una contrasenya!"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "La companyia seleccionada no està en les companyies permeses per aquest "
#~ "usuari"
#~ msgid "res.users"
#~ msgstr "res.usuaris"
#, python-format
#~ msgid "Error"
#~ msgstr "Error"
#~ msgid "Base - Password Encryption"
#~ msgstr "Base - Encriptació de la Contrasenya"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "No podeu tenir dos usuaris amb el mateix identificador d'usuari!"

View File

@ -1,24 +0,0 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * base_crypt
#
# Copyright (C) 2008,2009 P. Christeas <p_christ@hol.gr>
# <> <>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-02-15 15:37+0000\n"
"Last-Translator: <> <>\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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""

View File

@ -1,80 +0,0 @@
# Spanish (Chile) 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-10-03 17:17+0000\n"
"Last-Translator: David Acevedo Toledo <Unknown>\n"
"Language-Team: Spanish (Chile) <es_CL@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#, python-format
#~ msgid "Error"
#~ msgstr "Error!"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "Base - Password Encryption"
#~ msgstr "Base - Encriptación de la Contraseña"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "¡Por favor, escriba una contraseña!"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "La compañía seleccionada no está dentro de las compañías autorizadas para "
#~ "este usuario"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "¡No puede tener dos usuarios con el mismo nombre!"
#~ 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 ""
#~ "Este módulo sustituye la contraseña escrita en texto plano por una "
#~ "codificada,\n"
#~ "previniendo que alguien pueda leer la contraseña original.\n"
#~ "Para un usuario existente, el sustitución de la contraseña en texto plano se "
#~ "realiza la primera vez\n"
#~ "que el usuario se conecte después de instalar base_crypt.\n"
#~ "Después de instalar este módulo los usuarios no podrán recuperar su "
#~ "contraseña olvidada,\n"
#~ "un administrador tendrá que cambiarla por una nueva.\n"
#~ "\n"
#~ "Nota: instalar este módulo no significa que pueda ignorar las medidas "
#~ "básicas de seguridad,\n"
#~ "como la contraseña que es enviada por el cliente que sigue sin ser "
#~ "codificada en la red,\n"
#~ "a menos que utilice un protocolo seguro como XML-RPCS.\n"
#~ " "

View File

@ -1,79 +0,0 @@
# Spanish 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: \n"
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2012-02-13 19:04+0000\n"
"Last-Translator: Carlos Vásquez (CLEARCORP) "
"<carlos.vasquez@clearcorp.co.cr>\n"
"Language-Team: Spanish <es@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
"Language: es\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#~ msgid "res.users"
#~ msgstr "res.usuarios"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "¡No puede tener dos usuarios con el mismo identificador de usuario!"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "La compañía seleccionada no está autorizada como compañía para este usuario"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "¡Por favor, escriba una contraseña!"
#, python-format
#~ msgid "Error"
#~ msgstr "Error"
#~ 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 ""
#~ "Este módulo sustituye la contraseña en texto plano por un hash codificado,\n"
#~ "previniendo que alguien pueda leer la contraseña original.\n"
#~ "Para un usuario existente, el borrado de la contraseña en texto plano se "
#~ "realiza la primera vez\n"
#~ "que el usuario se conecte después de instalar base_crypt.\n"
#~ "Después de instalar este módulo los usuarios no podrán recuperar su "
#~ "contraseña,\n"
#~ "un administrador tendrá que introducir una nueva contraseña.\n"
#~ "\n"
#~ "Nota: instalar este módulo no significa que pueda ignorar las medidas "
#~ "básicas de seguridad,\n"
#~ "porque la contraseña es enviada sin codificar por el cliente,\n"
#~ "a menos que utilice un protocolo seguro como XML-RPCS.\n"
#~ " "
#~ msgid "Base - Password Encryption"
#~ msgstr "Base - Encriptación de la Contraseña"

View File

@ -1,86 +0,0 @@
# Spanish 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-02-15 15:37+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish <es@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-09-05 05:58+0000\n"
"X-Generator: Launchpad (build 13830)\n"
#. module: base_crypt
#: sql_constraint:res.users:0
msgid "You can not have two users with the same login !"
msgstr "¡No puede tener dos usuarios con el mismo identificador de usuario!"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "res.users"
msgstr "res.usuarios"
#. module: base_crypt
#: constraint:res.users:0
msgid "The chosen company is not in the allowed companies for this user"
msgstr ""
"La compañía seleccionada no está autorizada como compañía para este usuario"
#. module: base_crypt
#: code:addons/base_crypt/crypt.py:132
#, python-format
msgid "Please specify the password !"
msgstr "¡Por favor, escriba una contraseña!"
#. module: base_crypt
#: model:ir.module.module,shortdesc:base_crypt.module_meta_information
msgid "Base - Password Encryption"
msgstr "Base - Encriptación de la Contraseña"
#. module: base_crypt
#: code:addons/base_crypt/crypt.py:132
#, python-format
msgid "Error"
msgstr "Error"
#. 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 ""
"Este módulo sustituye la contraseña en texto plano por un hash codificado,\n"
"previniendo que alguien pueda leer la contraseña original.\n"
"Para un usuario existente, el borrado de la contraseña en texto plano se "
"realiza la primera vez\n"
"que el usuario se conecte después de instalar base_crypt.\n"
"Después de instalar este módulo los usuarios no podrán recuperar su "
"contraseña,\n"
"un administrador tendrá que introducir una nueva contraseña.\n"
"\n"
"Nota: instalar este módulo no significa que pueda ignorar las medidas "
"básicas de seguridad,\n"
"porque la contraseña es enviada sin codificar por el cliente,\n"
"a menos que utilice un protocolo seguro como XML-RPCS.\n"
" "

View File

@ -1,78 +0,0 @@
# Spanish (Paraguay) 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-03-08 17:36+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish (Paraguay) <es_PY@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#~ 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 ""
#~ "Este módulo sustituye la contraseña en texto plano por un hash codificado,\n"
#~ "previniendo que alguien pueda leer la contraseña original.\n"
#~ "Para un usuario existente, el borrado de la contraseña en texto plano se "
#~ "realiza la primera vez\n"
#~ "que el usuario se conecte después de instalar base_crypt.\n"
#~ "Después de instalar este módulo los usuarios no podrán recuperar su "
#~ "contraseña,\n"
#~ "un administrador tendrá que introducir una nueva contraseña.\n"
#~ "\n"
#~ "Nota: instalar este módulo no significa que pueda ignorar las medidas "
#~ "básicas de seguridad,\n"
#~ "porque la contraseña es enviada sin codificar por el cliente,\n"
#~ "a menos que utilice un protocolo seguro como XML-RPCS.\n"
#~ " "
#, python-format
#~ msgid "Error"
#~ msgstr "Error!"
#~ msgid "Base - Password Encryption"
#~ msgstr "Base - Encriptación de la Contraseña"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "¡Por favor, escriba una contraseña!"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "La compañía seleccionada no está en las compañías permitidas para este "
#~ "usuario"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "¡No puede tener dos usuarios con el mismo identificador de usuario!"

View File

@ -1,86 +0,0 @@
# Spanish 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-02-15 15:37+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Spanish <es@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-09-05 05:58+0000\n"
"X-Generator: Launchpad (build 13830)\n"
#. module: base_crypt
#: sql_constraint:res.users:0
msgid "You can not have two users with the same login !"
msgstr "¡No puede tener dos usuarios con el mismo identificador de usuario!"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "res.users"
msgstr "res.usuarios"
#. module: base_crypt
#: constraint:res.users:0
msgid "The chosen company is not in the allowed companies for this user"
msgstr ""
"La compañía seleccionada no está autorizada como compañía para este usuario"
#. module: base_crypt
#: code:addons/base_crypt/crypt.py:132
#, python-format
msgid "Please specify the password !"
msgstr "¡Por favor, escriba una contraseña!"
#. module: base_crypt
#: model:ir.module.module,shortdesc:base_crypt.module_meta_information
msgid "Base - Password Encryption"
msgstr "Base - Encriptación de la Contraseña"
#. module: base_crypt
#: code:addons/base_crypt/crypt.py:132
#, python-format
msgid "Error"
msgstr "Error"
#. 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 ""
"Este módulo sustituye la contraseña en texto plano por un hash codificado,\n"
"previniendo que alguien pueda leer la contraseña original.\n"
"Para un usuario existente, el borrado de la contraseña en texto plano se "
"realiza la primera vez\n"
"que el usuario se conecte después de instalar base_crypt.\n"
"Después de instalar este módulo los usuarios no podrán recuperar su "
"contraseña,\n"
"un administrador tendrá que introducir una nueva contraseña.\n"
"\n"
"Nota: instalar este módulo no significa que pueda ignorar las medidas "
"básicas de seguridad,\n"
"porque la contraseña es enviada sin codificar por el cliente,\n"
"a menos que utilice un protocolo seguro como XML-RPCS.\n"
" "

View File

@ -1,23 +0,0 @@
# Persian 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-12-18 20:12+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Persian <fa@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""

View File

@ -1,40 +0,0 @@
# 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-06-08 10:57+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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#, python-format
#~ msgid "Error"
#~ msgstr "Virhe"
#~ msgid "Base - Password Encryption"
#~ msgstr "Base - Salasanan kryptaus"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Määrittele salasana !"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr "Valittu yritys ei ole sallittu tälle käyttäjälle"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Kahdella eri käyttäjällä ei voi olla samaa käyttäjätunnusta!"

View File

@ -1,37 +0,0 @@
# Gujarati translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2012-04-19 08:51+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Gujarati <gu@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#~ msgid "You can not have two users with the same login !"
#~ msgstr "તમે બે વપરાશકર્તાઓને એક જ લોગીન ન કરી શકો!"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "પાસવર્ડ સ્પષ્ટ કરો!"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr "પસંદ કરેલ કંપની માન્ય કંપનીઓમાં આ વપરાશકર્તા માટે નથી"
#, python-format
#~ msgid "Error"
#~ msgstr "ભૂલ"

View File

@ -1,23 +0,0 @@
# Indonesian translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2012-12-09 08:46+0000\n"
"Last-Translator: Budhi Hartono <klikmaxima@gmail.com>\n"
"Language-Team: Indonesian <id@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: 2012-12-10 04:39+0000\n"
"X-Generator: Launchpad (build 16341)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr "Pengguna"

View File

@ -1,40 +0,0 @@
# Japanese translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2012-04-01 06:05+0000\n"
"Last-Translator: Masaki Yamaya <Unknown>\n"
"Language-Team: Japanese <ja@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#~ msgid "You can not have two users with the same login !"
#~ msgstr "同一のログインに2つのユーザを持つことはできません!"
#, python-format
#~ msgid "Error"
#~ msgstr "エラー"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr "選択した会社は、このユーザに許された会社ではありません。"
#~ msgid "res.users"
#~ msgstr "res.users"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "パスワードを指定してください!"

View File

@ -1,40 +0,0 @@
# Latvian translation for openobject-addons
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2012-10-16 16:11+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Latvian <lv@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Nevar būt divi lietotāji ar vienādu pieteikuma vārdu!"
#, python-format
#~ msgid "Error"
#~ msgstr "Kļūda"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr "Izvēlētais uzņēmums nav šim lietotājam atļauto uzņēmumu sarakstā"
#~ msgid "res.users"
#~ msgstr "res.users"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Lūdzu norādiet paroli!"

View File

@ -1,44 +0,0 @@
# 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2012-12-04 20:38+0000\n"
"Last-Translator: Kaare Pettersen <Unknown>\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: 2012-12-05 05:20+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr "Brukere."
#, python-format
#~ msgid "Error"
#~ msgstr "Feil"
#~ msgid "Base - Password Encryption"
#~ msgstr "Basis - Passord kryptering"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Vennligst angi passordet !"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "Det valgte firmaet er ikke i listen over tillatte firmaer for denne brukeren"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Du kan ikke ha to brukere med samme login !"

View File

@ -1,45 +0,0 @@
# Occitan (post 1500) 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-11-20 09:17+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Occitan (post 1500) <oc@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#, python-format
#~ msgid "Error"
#~ msgstr "Error"
#~ msgid "Base - Password Encryption"
#~ msgstr "Basa - Chifratge del senhal"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Entratz un senhal"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "La societat causida fa pas partida de las societats autorizadas per aqueste "
#~ "utilizaire"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Podètz pas aver dos utilizaires amb lo meteis identificant !"

View File

@ -1,41 +0,0 @@
# Slovak 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-02-21 08:14+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Slovak <sk@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#, python-format
#~ msgid "Error"
#~ msgstr "Chyba"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Prosím, zadajte heslo!"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "Vybraná spoločnosť nie je medzi schválenými spoločnosťami tohto používateľa"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Nemôžte mať dvoch používateľov s rovnakým pristúpovým menom!"

View File

@ -1,23 +0,0 @@
# Albanian 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-03-28 15:26+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Albanian <sq@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""

View File

@ -1,76 +0,0 @@
# Serbian Latin 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-10-05 13:25+0000\n"
"Last-Translator: Milan Milosevic <Unknown>\n"
"Language-Team: Serbian Latin <sr@latin@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#, python-format
#~ msgid "Error"
#~ msgstr "Greška"
#~ msgid "Base - Password Encryption"
#~ msgstr "Baza - Šifrovanje lozinke"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Molimo odredite lozinku"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Ne možete imati dva korisnika sa istom prijavom!"
#~ 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 ""
#~ "Ovaj modul zamenjuje vidljivu lozinku u bazi podataka znacima,\n"
#~ "što onemogućava bilo koga da pročita originalnu lozinku.\n"
#~ "Što se tiče Vaše baze podataka, ukidanje vidljive lozinke dešava se prvi put "
#~ "pošto se korisnik prijavi u bazu podataka, po instalaciji base_crypt.\n"
#~ "Po instalaciji ovog modula neće biti moguće izmeniti zaboravljenu lozinku za "
#~ "Vaše korisnike, jedino rešenje će biti da im administrator postavi novu "
#~ "lozinku.\n"
#~ "\n"
#~ "Beleška: Instaliranje ovog modula ne znači da možete ignorisati osnovne "
#~ "sigurnosne mere,\n"
#~ "budući da se lozinka i dalje prenosi nešifrovana u mreži (od strane "
#~ "klijenta),\n"
#~ "ukoliko ne koristite siguran protokol kao XML-RPCS.\n"
#~ " "
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr "Odabrano preduzeće nije u dozvoljenim preduzećima za ovog korisnioka"

View File

@ -1,80 +0,0 @@
# Vietnamese 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: 2012-12-03 16:03+0000\n"
"PO-Revision-Date: 2011-07-20 09:55+0000\n"
"Last-Translator: OpenBMS JSC <Unknown>\n"
"Language-Team: Vietnamese <vi@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: 2012-12-04 05:53+0000\n"
"X-Generator: Launchpad (build 16335)\n"
#. module: base_crypt
#: model:ir.model,name:base_crypt.model_res_users
msgid "Users"
msgstr ""
#, python-format
#~ msgid "Error"
#~ msgstr "Lỗi"
#~ msgid "Base - Password Encryption"
#~ msgstr "Cơ sở - Mã hóa Mật khẩu"
#, python-format
#~ msgid "Please specify the password !"
#~ msgstr "Vui lòng xác định mật khẩu !"
#~ msgid "The chosen company is not in the allowed companies for this user"
#~ msgstr ""
#~ "Công ty được lựa chọn không nằm trong các công ty mà người sử dụng này được "
#~ "phép"
#~ msgid "res.users"
#~ msgstr "res.users"
#~ msgid "You can not have two users with the same login !"
#~ msgstr "Bạn không thể có hai người sử dụng với cùng tên đăng nhập !"
#~ 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 ""
#~ "Mô-đun này thay thế mật khẩu dạng tường minh (cleartext) trong cơ sở dữ liệu "
#~ "với một mật khẩu băm (hash),\n"
#~ "ngăn chặn bất cứ ai đọc các mật khẩu ban đầu.\n"
#~ "Đối với người dùng hiện tại của bạn, việc loại bỏ các mật khẩu tường minh "
#~ "xảy ra lần đầu tiên\n"
#~ "người dùng đăng nhập vào cơ sở dữ liệu, sau khi cài đặt base_crypt.\n"
#~ "Sau khi cài đặt mô-đun này, sẽ không thể khôi phục lại một mật khẩu bị lãng "
#~ "quên cho\n"
#~ "người sử dụng của bạn, giải pháp duy nhất là để một quản trị viên thiết lập "
#~ "một mật khẩu mới.\n"
#~ "\n"
#~ "Lưu ý: cài đặt mô-đun này không có nghĩa là bạn có thể bỏ qua các biện pháp "
#~ "bảo mật cơ bản,\n"
#~ "như mật khẩu vẫn được truyền không mã hóa trên mạng (từ máy khách),\n"
#~ "trừ khi bạn sử dụng một giao thức an toàn chẳng hạn như XML-RPCS.\n"
#~ " "

View File

@ -237,14 +237,14 @@ class res_company(osv.osv):
_inherit = "res.company"
_columns = {
'ldaps': fields.one2many(
'res.company.ldap', 'company', 'LDAP Parameters'),
'res.company.ldap', 'company', 'LDAP Parameters', copy=True),
}
class users(osv.osv):
_inherit = "res.users"
def login(self, db, login, password):
user_id = super(users, self).login(db, login, password)
def _login(self, db, login, password):
user_id = super(users, self)._login(db, login, password)
if user_id:
return user_id
registry = RegistryManager.get(db)

View File

@ -17,8 +17,8 @@ class res_users(osv.Model):
_columns = {
'oauth_provider_id': fields.many2one('auth.oauth.provider', 'OAuth Provider'),
'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id"),
'oauth_access_token': fields.char('OAuth Access Token', readonly=True),
'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id", copy=False),
'oauth_access_token': fields.char('OAuth Access Token', readonly=True, copy=False),
}
_sql_constraints = [

View File

@ -30,11 +30,11 @@ class res_users(osv.osv):
# TODO create helper fields for autofill openid_url and openid_email -> http://pad.openerp.com/web-openid
_columns = {
'openid_url': fields.char('OpenID URL', size=1024),
'openid_email': fields.char('OpenID Email', size=256,
'openid_url': fields.char('OpenID URL', size=1024, copy=False),
'openid_email': fields.char('OpenID Email', size=256, copy=False,
help="Used for disambiguation in case of a shared OpenID URL"),
'openid_key': fields.char('OpenID Key', size=utils.KEY_LENGTH,
readonly=True),
readonly=True, copy=False),
}
def _check_openid_url_email(self, cr, uid, ids, context=None):
@ -48,19 +48,8 @@ class res_users(osv.osv):
(_check_openid_url_email, lambda self, *a, **kw: self._check_openid_url_email_msg(*a, **kw), ['active', 'openid_url', 'openid_email']),
]
def copy(self, cr, uid, rid, defaults=None, context=None):
reset_fields = 'openid_url openid_email'.split()
reset_values = dict.fromkeys(reset_fields, False)
if defaults is None:
defaults = reset_values
else:
defaults = dict(reset_values, **defaults)
defaults['openid_key'] = False
return super(res_users, self).copy(cr, uid, rid, defaults, context)
def login(self, db, login, password):
result = super(res_users, self).login(db, login, password)
def _login(self, db, login, password):
result = super(res_users, self)._login(db, login, password)
if result:
return result
else:
@ -69,6 +58,7 @@ class res_users(osv.osv):
SET login_date=now() AT TIME ZONE 'UTC'
WHERE login=%s AND openid_key=%s AND active=%s RETURNING id""",
(tools.ustr(login), tools.ustr(password), True))
# beware: record cache may be invalid
res = cr.fetchone()
cr.commit()
return res[0] if res else False

View File

@ -104,9 +104,9 @@ class res_partner(osv.Model):
return self._get_signup_url_for_action(cr, uid, ids, context=context)
_columns = {
'signup_token': fields.char('Signup Token'),
'signup_type': fields.char('Signup Token Type'),
'signup_expiration': fields.datetime('Signup Expiration'),
'signup_token': fields.char('Signup Token', copy=False),
'signup_type': fields.char('Signup Token Type', copy=False),
'signup_expiration': fields.datetime('Signup Expiration', copy=False),
'signup_valid': fields.function(_get_signup_valid, type='boolean', string='Signup Token is Valid'),
'signup_url': fields.function(_get_signup_url, type='char', string='Signup URL'),
}
@ -302,7 +302,7 @@ class res_users(osv.Model):
user_id = super(res_users, self).create(cr, uid, values, context=context)
user = self.browse(cr, uid, user_id, context=context)
if user.email and not context.get('no_reset_password'):
context.update({'create_user': True})
context = dict(context, create_user=True)
try:
self.action_reset_password(cr, uid, [user.id], context=context)
except MailDeliveryException:

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="signup_form_view" model="ir.ui.view">
<field name="name">signup.signup.form</field>
<field name="model">signup.signup</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Signup">
<field name="state" invisible="1"/>
<group colspan="4" states="draft,missmatch">
<field name="name" required="1"/>
<field name="email" required="1"/>
<field name="password" required='1' on_change="onchange_pw(password,password_confirmation)"/>
<field name="password_confirmation" required='1' on_change="onchange_pw(password,password_confirmation)"/>
<group colspan="4" states="missmatch">
<div>Passwords missmatch</div>
</group>
<group colspan="2" col="1">
<button string="Sign Up" name="signup" attrs="{'readonly': [('state', '=', 'missmatch')]}" type="object"/>
</group>
</group>
<group colspan="4" states="done" col="1">
<div>You can now login.</div>
<button special="cancel" string="Close"/>
</group>
</form>
</field>
</record>
<record id="signup_action" model="ir.actions.act_window">
<field name="name">signup.signup</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">signup.signup</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@ -57,7 +57,7 @@ class base_action_rule(osv.osv):
'name': fields.char('Rule Name', required=True),
'model_id': fields.many2one('ir.model', 'Related Document Model',
required=True, domain=[('osv_memory', '=', False)]),
'model': fields.related('model_id', 'model', type="char", size=256, string='Model'),
'model': fields.related('model_id', 'model', type="char", string='Model'),
'create_date': fields.datetime('Create Date', readonly=1),
'active': fields.boolean('Active',
help="When unchecked, the rule is hidden and will not be executed."),
@ -96,7 +96,7 @@ class base_action_rule(osv.osv):
ondelete='restrict',
domain="[('model_id', '=', model_id.model)]",
help="If present, this condition must be satisfied before executing the action rule."),
'last_run': fields.datetime('Last Run', readonly=1),
'last_run': fields.datetime('Last Run', readonly=1, copy=False),
}
_defaults = {
@ -152,64 +152,6 @@ class base_action_rule(osv.osv):
return True
def _wrap_create(self, old_create, model):
""" Return a wrapper around `old_create` calling both `old_create` and
`_process`, in that order.
"""
def create(cr, uid, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return old_create(cr, uid, vals, context=context)
context = dict(context or {}, action=True)
new_id = old_create(cr, uid, vals, context=context, **kwargs)
# retrieve the action rules to run on creation
action_dom = [('model', '=', model), ('kind', 'in', ['on_create', 'on_create_or_write'])]
action_ids = self.search(cr, uid, action_dom, context=context)
# check postconditions, and execute actions on the records that satisfy them
for action in self.browse(cr, uid, action_ids, context=context):
if self._filter(cr, uid, action, action.filter_id, [new_id], context=context):
self._process(cr, uid, action, [new_id], context=context)
return new_id
return create
def _wrap_write(self, old_write, model):
""" Return a wrapper around `old_write` calling both `old_write` and
`_process`, in that order.
"""
def write(cr, uid, ids, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return old_write(cr, uid, ids, vals, context=context, **kwargs)
context = dict(context or {}, action=True)
ids = [ids] if isinstance(ids, (int, long, str)) else ids
# retrieve the action rules to run on update
action_dom = [('model', '=', model), ('kind', 'in', ['on_write', 'on_create_or_write'])]
action_ids = self.search(cr, uid, action_dom, context=context)
actions = self.browse(cr, uid, action_ids, context=context)
# check preconditions
pre_ids = {}
for action in actions:
pre_ids[action] = self._filter(cr, uid, action, action.filter_pre_id, ids, context=context)
# execute write
old_write(cr, uid, ids, vals, context=context, **kwargs)
# check postconditions, and execute actions on the records that satisfy them
for action in actions:
post_ids = self._filter(cr, uid, action, action.filter_id, pre_ids[action], context=context)
if post_ids:
self._process(cr, uid, action, post_ids, context=context)
return True
return write
def _register_hook(self, cr, ids=None):
""" Wrap the methods `create` and `write` of the models specified by
the rules given by `ids` (or all existing rules if `ids` is `None`.)
@ -221,10 +163,65 @@ class base_action_rule(osv.osv):
model = action_rule.model_id.model
model_obj = self.pool[model]
if not hasattr(model_obj, 'base_action_ruled'):
model_obj.create = self._wrap_create(model_obj.create, model)
model_obj.write = self._wrap_write(model_obj.write, model)
# monkey-patch methods create and write
def create(self, cr, uid, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return create.origin(self, cr, uid, vals, context=context)
# call original method with a modified context
context = dict(context or {}, action=True)
new_id = create.origin(self, cr, uid, vals, context=context, **kwargs)
# as it is a new record, we do not consider the actions that have a prefilter
action_model = self.pool.get('base.action.rule')
action_dom = [('model', '=', self._name),
('kind', 'in', ['on_create', 'on_create_or_write'])]
action_ids = action_model.search(cr, uid, action_dom, context=context)
# check postconditions, and execute actions on the records that satisfy them
for action in action_model.browse(cr, uid, action_ids, context=context):
if action_model._filter(cr, uid, action, action.filter_id, [new_id], context=context):
action_model._process(cr, uid, action, [new_id], context=context)
return new_id
def write(self, cr, uid, ids, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return write.origin(self, cr, uid, ids, vals, context=context)
# modify context
context = dict(context or {}, action=True)
ids = [ids] if isinstance(ids, (int, long, str)) else ids
# retrieve the action rules to possibly execute
action_model = self.pool.get('base.action.rule')
action_dom = [('model', '=', self._name),
('kind', 'in', ['on_write', 'on_create_or_write'])]
action_ids = action_model.search(cr, uid, action_dom, context=context)
actions = action_model.browse(cr, uid, action_ids, context=context)
# check preconditions
pre_ids = {}
for action in actions:
pre_ids[action] = action_model._filter(cr, uid, action, action.filter_pre_id, ids, context=context)
# call original method
write.origin(self, cr, uid, ids, vals, context=context, **kwargs)
# check postconditions, and execute actions on the records that satisfy them
for action in actions:
post_ids = action_model._filter(cr, uid, action, action.filter_id, pre_ids[action], context=context)
if post_ids:
action_model._process(cr, uid, action, post_ids, context=context)
return True
model_obj._patch_method('create', create)
model_obj._patch_method('write', write)
model_obj.base_action_ruled = True
updated = True
return updated
def create(self, cr, uid, vals, context=None):
@ -283,7 +280,7 @@ class base_action_rule(osv.osv):
if 'lang' not in ctx:
# Filters might be language-sensitive, attempt to reuse creator lang
# as we are usually running this as super-user in background
[filter_meta] = action.filter_id.perm_read()
[filter_meta] = action.filter_id.get_metadata()
user_id = filter_meta['write_uid'] and filter_meta['write_uid'][0] or \
filter_meta['create_uid'][0]
ctx['lang'] = self.pool['res.users'].browse(cr, uid, user_id).lang

View File

@ -26,8 +26,8 @@ class res_company(osv.Model):
_name = "res.company"
_inherit = "res.company"
_columns = {
"gengo_private_key": fields.text("Gengo Private Key"),
"gengo_public_key": fields.text("Gengo Public Key"),
"gengo_private_key": fields.text("Gengo Private Key", copy=False),
"gengo_public_key": fields.text("Gengo Public Key", copy=False),
"gengo_comment": fields.text("Comments", help="This comment will be automatically be enclosed in each an every request sent to Gengo"),
"gengo_auto_approve": fields.boolean("Auto Approve Translation ?", help="Jobs are Automatically Approved by Gengo."),
"gengo_sandbox": fields.boolean("Sandbox Mode", help="Check this box if you're using the sandbox mode of Gengo, mainly used for testing purpose."),

View File

@ -74,6 +74,7 @@ class ir_import(orm.TransientModel):
:param str model: name of the model to get fields form
:param int landing: depth of recursion into o2m fields
"""
model_obj = self.pool[model]
fields = [{
'id': 'id',
'name': 'id',
@ -81,8 +82,11 @@ class ir_import(orm.TransientModel):
'required': False,
'fields': [],
}]
fields_got = self.pool[model].fields_get(cr, uid, context=context)
fields_got = model_obj.fields_get(cr, uid, context=context)
blacklist = orm.MAGIC_COLUMNS + [model_obj.CONCURRENCY_CHECK_FIELD]
for name, field in fields_got.iteritems():
if name in blacklist:
continue
# an empty string means the field is deprecated, @deprecated must
# be absent or False to mean not-deprecated
if field.get('deprecated', False) is not False:

View File

@ -4,48 +4,72 @@ from openerp.tests.common import TransactionCase
from .. import models
ID_FIELD = {'id': 'id', 'name': 'id', 'string': "External ID", 'required': False, 'fields': []}
ID_FIELD = {
'id': 'id',
'name': 'id',
'string': "External ID",
'required': False,
'fields': [],
}
DISPLAY_NAME_FIELD = {
'id': 'display_name',
'name': 'display_name',
'string': "Name",
'required': False,
'fields': [],
}
def make_field(name='value', string='unknown', required=False, fields=[]):
return [
ID_FIELD,
DISPLAY_NAME_FIELD,
{'id': name, 'name': name, 'string': string, 'required': required, 'fields': fields},
]
class test_basic_fields(TransactionCase):
def sorted_fields(fields):
""" recursively sort field lists to ease comparison """
recursed = [dict(field, fields=sorted_fields(field['fields'])) for field in fields]
return sorted(recursed, key=lambda field: field['id'])
class BaseImportCase(TransactionCase):
def assertEqualFields(self, fields1, fields2):
self.assertEqual(sorted_fields(fields1), sorted_fields(fields2))
class test_basic_fields(BaseImportCase):
def get_fields(self, field):
return self.registry('base_import.import')\
.get_fields(self.cr, self.uid, 'base_import.tests.models.' + field)
def test_base(self):
""" A basic field is not required """
self.assertEqual(self.get_fields('char'), make_field())
self.assertEqualFields(self.get_fields('char'), make_field())
def test_required(self):
""" Required fields should be flagged (so they can be fill-required) """
self.assertEqual(self.get_fields('char.required'), make_field(required=True))
self.assertEqualFields(self.get_fields('char.required'), make_field(required=True))
def test_readonly(self):
""" Readonly fields should be filtered out"""
self.assertEqual(self.get_fields('char.readonly'), [ID_FIELD])
self.assertEqualFields(self.get_fields('char.readonly'), [ID_FIELD, DISPLAY_NAME_FIELD])
def test_readonly_states(self):
""" Readonly fields with states should not be filtered out"""
self.assertEqual(self.get_fields('char.states'), make_field())
self.assertEqualFields(self.get_fields('char.states'), make_field())
def test_readonly_states_noreadonly(self):
""" Readonly fields with states having nothing to do with
readonly should still be filtered out"""
self.assertEqual(self.get_fields('char.noreadonly'), [ID_FIELD])
self.assertEqualFields(self.get_fields('char.noreadonly'), [ID_FIELD, DISPLAY_NAME_FIELD])
def test_readonly_states_stillreadonly(self):
""" Readonly fields with readonly states leaving them readonly
always... filtered out"""
self.assertEqual(self.get_fields('char.stillreadonly'), [ID_FIELD])
self.assertEqualFields(self.get_fields('char.stillreadonly'), [ID_FIELD, DISPLAY_NAME_FIELD])
def test_m2o(self):
""" M2O fields should allow import of themselves (name_get),
their id and their xid"""
self.assertEqual(self.get_fields('m2o'), make_field(fields=[
self.assertEqualFields(self.get_fields('m2o'), make_field(fields=[
{'id': 'value', 'name': 'id', 'string': 'External ID', 'required': False, 'fields': []},
{'id': 'value', 'name': '.id', 'string': 'Database ID', 'required': False, 'fields': []},
]))
@ -55,19 +79,20 @@ class test_basic_fields(TransactionCase):
required as well (the client has to handle that: requiredness
is id-based)
"""
self.assertEqual(self.get_fields('m2o.required'), make_field(required=True, fields=[
self.assertEqualFields(self.get_fields('m2o.required'), make_field(required=True, fields=[
{'id': 'value', 'name': 'id', 'string': 'External ID', 'required': True, 'fields': []},
{'id': 'value', 'name': '.id', 'string': 'Database ID', 'required': True, 'fields': []},
]))
class test_o2m(TransactionCase):
class test_o2m(BaseImportCase):
def get_fields(self, field):
return self.registry('base_import.import')\
.get_fields(self.cr, self.uid, 'base_import.tests.models.' + field)
def test_shallow(self):
self.assertEqual(self.get_fields('o2m'), make_field(fields=[
{'id': 'id', 'name': 'id', 'string': 'External ID', 'required': False, 'fields': []},
self.assertEqualFields(self.get_fields('o2m'), make_field(fields=[
ID_FIELD,
DISPLAY_NAME_FIELD,
# FIXME: should reverse field be ignored?
{'id': 'parent_id', 'name': 'parent_id', 'string': 'unknown', 'required': False, 'fields': [
{'id': 'parent_id', 'name': 'id', 'string': 'External ID', 'required': False, 'fields': []},
@ -224,7 +249,8 @@ class test_preview(TransactionCase):
self.assertEqual(result['headers'], ['name', 'Some Value', 'Counter'])
# Order depends on iteration order of fields_get
self.assertItemsEqual(result['fields'], [
{'id': 'id', 'name': 'id', 'string': 'External ID', 'required':False, 'fields': []},
ID_FIELD,
DISPLAY_NAME_FIELD,
{'id': 'name', 'name': 'name', 'string': 'Name', 'required':False, 'fields': []},
{'id': 'somevalue', 'name': 'somevalue', 'string': 'Some Value', 'required':True, 'fields': []},
{'id': 'othervalue', 'name': 'othervalue', 'string': 'Other Variable', 'required':False, 'fields': []},

View File

@ -59,10 +59,8 @@ class report_xml(osv.osv):
return True
def report_get(self, cr, uid, report_id, context=None):
if context is None:
context = {}
# skip osv.fields.sanitize_binary_value() because we want the raw bytes in all cases
context.update(bin_raw=True)
context = dict(context or {}, bin_raw=True)
report = self.browse(cr, uid, report_id, context=context)
sxw_data = report.report_sxw_content
rml_data = report.report_rml_content

View File

@ -133,16 +133,19 @@ class base_report_rml_save(osv.osv_memory):
"""
res = super(base_report_rml_save, self).default_get(cr, uid, fields, context=context)
report_id = self.pool['base.report.sxw'].search(cr,uid,[])
data = self.pool['base.report.file.sxw'].read(cr, uid, report_id, context=context)[0]
report_ids = self.pool['base.report.sxw'].search(cr,uid,[], context=context)
data = self.pool['base.report.file.sxw'].read(cr, uid, report_ids, context=context)[0]
report = self.pool['ir.actions.report.xml'].browse(cr, uid, data['report_id'], context=context)
if 'file_rml' in fields:
res['file_rml'] = base64.encodestring(report.report_rml_content)
return res
_columns = {
'file_rml':fields.binary('Save As'),
}
'file_rml':fields.binary('Save As'),
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -2,7 +2,7 @@
from xml.etree import ElementTree
from openerp.addons.web.controllers.main import load_actions_from_ir_values
from openerp.addons.web.http import Controller, route, request
from openerp.http import Controller, route, request
class Board(Controller):
@route('/board/add_to_dashboard', type='json', auth='user')

View File

@ -1,291 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Calendar's menu -->
<menuitem id="base.menu_calendar_configuration" name="Calendar"
parent="base.menu_base_config" sequence="50" groups="base.group_no_one"/>
<!-- Alarm form view -->
<record id="res_alarm_form_view" model="ir.ui.view">
<field name="name">res.alarm.form</field>
<field name="model">res.alarm</field>
<field name="arch" type="xml">
<form string="Reminder details">
<group col="4">
<field name="name"/>
<field name="active"/>
<separator string="Reminder Details" colspan="4"/>
<field name="trigger_duration"/>
<field name="trigger_interval"/>
<field name="trigger_occurs"/>
<field name="trigger_related"/>
</group>
</form>
</field>
</record>
<!-- Alarm list view -->
<record id="res_alarm_tree_view" model="ir.ui.view">
<field name="name">res.alarm.tree</field>
<field name="model">res.alarm</field>
<field name="arch" type="xml">
<tree string="Reminder details">
<field name="name"/>
<field name="trigger_interval"/>
<field name="trigger_duration"/>
<field name="trigger_occurs"/>
<field name="trigger_related"/>
</tree>
</field>
</record>
<record id="action_res_alarm_view" model="ir.actions.act_window">
<field name="name">Alarms</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.alarm</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to setup a new alarm type.
</p><p>
You can define a customized type of calendar alarm that may be
assigned to calendar events or meetings.
</p>
</field>
</record>
<!-- Alarms menu -->
<menuitem id="menu_crm_meeting_avail_alarm"
groups="base.group_no_one"
action="base_calendar.action_res_alarm_view"
parent="base.menu_calendar_configuration" sequence="5"/>
<!-- Event form view -->
<record model="ir.ui.view" id="event_form_view">
<field name="name">Event Form</field>
<field name="model">calendar.event</field>
<field name="arch" type="xml">
<form string="Events">
<header>
<button name="do_confirm" string="Confirm" states="tentative,cancelled" type="object" class="oe_highlight"/>
<button name="do_tentative" states="confirmed,cancelled" string="Uncertain" type="object" class="oe_highlight"/>
<button name="do_cancel" string="Cancel Event" states="tentative,confirmed" type="object"/>
<field name="state" widget="statusbar"
statusbar_visible="tentative,confirmed" statusbar_colors='{"proforma":"blue"}'/>
</header>
<sheet>
<group col="6">
<field name="name" string="Summary"
colspan="4" required="1"/>
<field name="allday" colspan="2" on_change="onchange_dates(date,False,False,allday)"/>
<newline/>
<field name="date" string="Start Date" required="1"
on_change="onchange_dates(date,duration,False,allday)"/>
<field name="duration" widget="float_time"
on_change="onchange_dates(date,duration,False,allday)" attrs="{'invisible': [('allday', '=', True)]}"/>
<field name="date_deadline" string="End Date" required="1"
on_change="onchange_dates(date,False,date_deadline)"/>
<field name="location"/>
<field name="alarm_id" string="Reminder"
widget="selection"/>
<group colspan="2" col="4" attrs="{'readonly': [('state','=','done')]}">
<field name="recurrency"/>
</group>
</group>
<notebook>
<page string="Event">
<group col="6" colspan="4">
<separator colspan="6" string="Visibility"/>
<field name="user_id" string="Responsible User"/>
<field name="show_as" string="Show Time as"/>
<field name="class" string="Privacy"/>
<field name="recurrent_id_date" invisible="1"/>
<field name="recurrent_id" invisible="1"/>
</group>
<separator string="Description"/>
<field name="description"/>
</page>
<page string="Invitation Detail">
<field name="attendee_ids" colspan="4"
nolabel="1" widget="one2many" mode="tree">
<tree string="Invitation details" editable="top">
<field name="sent_by_uid" string="From"/>
<field name="user_id" string="To"/>
<field name="email"/>
<field name="role" width="200"/>
<field name="state"/>
<button name="do_tentative"
states="needs-action,declined,accepted"
string="Uncertain" type="object"
icon="terp-crm"/>
<button name="do_accept" string="Accept"
states="needs-action,tentative,declined"
type="object" icon="gtk-apply"/>
<button name="do_decline" string="Decline"
states="needs-action,tentative,accepted"
type="object" icon="gtk-cancel"/>
</tree>
<form string="Invitation details">
<notebook colspan="4">
<page string="Details">
<group col="4">
<field name="email"/>
<field name="rsvp"/>
<field name="cutype"/>
<field name="role"/>
</group>
<group col="4">
<field name="state"/>
<button name="do_tentative"
states="needs-action,declined,accepted"
string="Uncertain"
type="object"
icon="terp-crm"/>
<button name="do_accept"
string="Accept"
states="needs-action,tentative,declined"
type="object"
icon="gtk-apply"/>
<button name="do_decline"
string="Decline"
states="needs-action,tentative,accepted"
type="object"
icon="gtk-cancel"/>
</group>
</page>
</notebook>
</form>
</field>
</page>
<page string="Recurrency Option" attrs="{'invisible': [('recurrency','=',False)]}">
<group col="4" colspan="4" name="rrule">
<group col="4" colspan="4">
<field name="rrule_type" string="Recurrency period"
attrs="{'readonly':[('recurrent_id','!=',False)]}"/>
<field name="interval"/>
<separator string="End of Recurrence" colspan="4"/>
<field name="end_type"/>
<label string=" " colspan="2"/>
<newline/>
<field name="count" attrs="{'invisible' : [('end_type', '!=', 'count')] }"/>
<label string=" " colspan="2"/>
<newline/>
<field name="end_date" attrs="{'invisible' : [('end_type', '!=', 'end_date')] }"/>
<newline/>
</group>
<group col="8" colspan="4" name="Select weekdays" attrs="{'invisible' :[('rrule_type','not in', ['weekly'])]}">
<separator string="Choose day where repeat the meeting" colspan="8"/>
<field name="mo" colspan="1"/>
<field name="tu" colspan="1"/>
<field name="we" colspan="1"/>
<field name="th" colspan="1"/>
<newline/>
<field name="fr" colspan="1"/>
<field name="sa" colspan="1" />
<field name="su" colspan="1" />
<newline/>
</group>
<group col="10" colspan="4"
attrs="{'invisible' : [('rrule_type','!=','monthly')]}">
<separator string="Choose day in the month where repeat the meeting" colspan="12"/>
<group col="2" colspan="1">
<field name="select1"/>
</group>
<group col="2" colspan="1">
<field name="day"
attrs="{'required' : [('select1','=','date'), ('rrule_type','=','monthly')],
'invisible' : ['|', ('select1','=','day'), ('rrule_type','!=','monthly')]}"/>
</group>
<group col="3" colspan="1"
attrs="{'invisible' : ['|', ('select1','=','date'), ('rrule_type','!=','monthly')]}">
<field name="byday" string="The"
attrs="{'required' : [('select1','=','day'), ('rrule_type','=','monthly')]}"/>
<field name="week_list" nolabel="1"
attrs="{'required' : [('select1','=','day'), ('rrule_type','=','monthly')]}"/>
</group>
</group>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Event list view -->
<record model="ir.ui.view" id="event_tree_view">
<field name="name">Event Tree</field>
<field name="model">calendar.event</field>
<field name="arch" type="xml">
<tree string="Events">
<field name="name" string="Subject"/>
<field name="date" string="Event Date"/>
<field name="location"/>
<field name="show_as"/>
<field name="class" string="Privacy"/>
<field name="user_id" invisible="1"/>
<field name="state" invisible="1"/>
</tree>
</field>
</record>
<!-- Event calendar view -->
<record model="ir.ui.view" id="event_calendar_view">
<field name="name">Events Calendar</field>
<field name="model">calendar.event</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Events" date_start="date" color="show_as" date_delay="duration">
<field name="name"/>
<field name="class"/>
<field name="show_as"/>
</calendar>
</field>
</record>
<!-- Event search view -->
<record id="view_calendar_event_filter" model="ir.ui.view">
<field name="name">Calendar Events Search</field>
<field name="model">calendar.event</field>
<field name="arch" type="xml">
<search string="Search Events">
<field name="name" filter_domain="['|',('name','ilike',self),('location','ilike',self)]" string="Event"/>
<field name="show_as"/>
<field name="class" string="Privacy"/>
<filter icon="terp-go-today" string="My Events" domain="[('user_id','=',uid)]" help="My Events"/>
<separator/>
<filter icon="terp-check" string="Confirmed" domain="[('state','=','confirmed')]" help="Confirmed Events"/>
<field name="user_id"/>
<group expand="0" string="Group By">
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Availability" icon="terp-camera_test" domain="[]" context="{'group_by':'show_as'}"/>
<filter string="Privacy" icon="terp-locked" domain="[]" context="{'group_by':'class'}"/>
<filter string="Status" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
<filter string="Event Month" icon="terp-go-month" domain="[]" context="{'group_by':'date'}" help="Start Date of Event by Month"/>
</group>
</search>
</field>
</record>
<!-- Event action -->
<record id="action_view_event" model="ir.actions.act_window">
<field name="name">Events</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">calendar.event</field>
<field name="view_type">form</field>
<field name="view_mode">calendar,tree,form</field>
<field name="search_view_id" ref="view_calendar_event_filter"/>
</record>
<!-- Event menu -->
<menuitem id="menu_events"
name="Events" parent="base.menu_calendar_configuration"
sequence="15" action="action_view_event"/>
</data>
</openerp>

View File

@ -297,7 +297,7 @@ class res_partner(osv.Model):
Used by web_calendar.js : Many2ManyAttendee
"""
datas = []
meeting = False
meeting = None
if meeting_id:
meeting = self.pool['calendar.event'].browse(cr, uid, get_real_ids(meeting_id), context=context)
for partner in self.browse(cr, uid, ids, context=context):
@ -309,7 +309,7 @@ class res_partner(osv.Model):
datas.append(data)
return datas
def calendar_last_notif_ack(self, cr, uid, context=None):
def _set_calendar_last_notif_ack(self, cr, uid, context=None):
partner = self.pool['res.users'].browse(cr, uid, uid, context=context).partner_id
self.write(cr, uid, partner.id, {'calendar_last_notif_ack': datetime.now()}, context=context)
return
@ -708,6 +708,7 @@ class calendar_event(osv.Model):
return (format_date, format_time)
def get_display_time_tz(self, cr, uid, ids, tz=False, context=None):
context = dict(context or {})
if tz:
context["tz"] = tz
ev = self.browse(cr, uid, ids, context=context)[0]
@ -720,8 +721,7 @@ class calendar_event(osv.Model):
1) if user add duration for 2 hours, return : August-23-2013 at (04-30 To 06-30) (Europe/Brussels)
2) if event all day ,return : AllDay, July-31-2013
"""
if context is None:
context = {}
context = dict(context or {})
tz = context.get('tz', False)
if not tz: # tz can have a value False, so dont do it in the default value of get !
@ -782,7 +782,7 @@ class calendar_event(osv.Model):
if data.count and data.count <= 0:
raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 0.'))
data = self.read(cr, uid, id, ['id', 'byday', 'recurrency', 'month_list', 'final_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list'], context=context)
data = self.read(cr, uid, id, ['id', 'byday', 'recurrency', 'final_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list'], context=context)
event = data['id']
if data['recurrency']:
result[event] = self.compute_rule_string(data)
@ -900,7 +900,7 @@ class calendar_event(osv.Model):
'categ_ids': fields.many2many('calendar.event.type', 'meeting_category_rel', 'event_id', 'type_id', 'Tags'),
'attendee_ids': fields.one2many('calendar.attendee', 'event_id', 'Attendees', ondelete='cascade'),
'partner_ids': fields.many2many('res.partner', 'calendar_event_res_partner_rel', string='Attendees', states={'done': [('readonly', True)]}),
'alarm_ids': fields.many2many('calendar.alarm', 'calendar_alarm_calendar_event_rel', string='Reminders', ondelete="restrict"),
'alarm_ids': fields.many2many('calendar.alarm', 'calendar_alarm_calendar_event_rel', string='Reminders', ondelete="restrict", copy=False),
}
_defaults = {
'end_type': 'count',
@ -1404,16 +1404,9 @@ class calendar_event(osv.Model):
return res
def copy(self, cr, uid, id, default=None, context=None):
if context is None:
context = {}
default = default or {}
self._set_date(cr, uid, default, id=default.get('id'), context=context)
default['attendee_ids'] = False
res = super(calendar_event, self).copy(cr, uid, calendar_id2real_id(id), default, context)
return res
return super(calendar_event, self).copy(cr, uid, calendar_id2real_id(id), default, context)
def _detach_one_event(self, cr, uid, id, values=dict(), context=None):
real_event_id = calendar_id2real_id(id)
@ -1547,8 +1540,7 @@ class calendar_event(osv.Model):
return res
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True):
if not context:
context = {}
context = dict(context or {})
if 'date' in groupby:
raise osv.except_osv(_('Warning!'), _('Group by date is not supported, use the calendar view instead.'))

View File

@ -1,7 +1,7 @@
import simplejson
import openerp
import openerp.addons.web.http as http
from openerp.addons.web.http import request
import openerp.http as http
from openerp.http import request
import openerp.addons.web.controllers.main as webmain
import json
@ -67,5 +67,5 @@ class meeting_invitation(http.Controller):
uid = request.session.uid
context = request.session.context
with registry.cursor() as cr:
res = registry.get("res.partner").calendar_last_notif_ack(cr, uid, context=context)
res = registry.get("res.partner")._set_calendar_last_notif_ack(cr, uid, context=context)
return res

View File

@ -1,176 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-today OpenERP SA (<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 time
from openerp.osv import fields, osv
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from openerp.tools.translate import _
from base_calendar import get_real_ids, base_calendar_id2real_id
#
# crm.meeting is defined here so that it may be used by modules other than crm,
# without forcing the installation of crm.
#
class crm_meeting_type(osv.Model):
_name = 'crm.meeting.type'
_description = 'Meeting Type'
_columns = {
'name': fields.char('Name', size=64, required=True, translate=True),
}
class crm_meeting(osv.Model):
""" Model for CRM meetings """
_name = 'crm.meeting'
_description = "Meeting"
_order = "id desc"
_inherit = ["calendar.event", "mail.thread", "ir.needaction_mixin"]
_columns = {
'create_date': fields.datetime('Creation Date', readonly=True),
'write_date': fields.datetime('Write Date', readonly=True),
'date_open': fields.datetime('Confirmed', readonly=True),
'date_closed': fields.datetime('Closed', readonly=True),
'partner_ids': fields.many2many('res.partner', 'crm_meeting_partner_rel', 'meeting_id', 'partner_id',
string='Attendees', states={'done': [('readonly', True)]}),
'state': fields.selection(
[('draft', 'Unconfirmed'), ('open', 'Confirmed')],
string='Status', size=16, readonly=True, track_visibility='onchange'),
# Meeting fields
'name': fields.char('Meeting Subject', size=128, required=True, states={'done': [('readonly', True)]}),
'categ_ids': fields.many2many('crm.meeting.type', 'meeting_category_rel',
'event_id', 'type_id', 'Tags'),
'attendee_ids': fields.many2many('calendar.attendee', 'meeting_attendee_rel',\
'event_id', 'attendee_id', 'Invited People', states={'done': [('readonly', True)]}),
}
_defaults = {
'state': 'open',
}
def message_get_subscription_data(self, cr, uid, ids, context=None):
res = {}
for virtual_id in ids:
real_id = base_calendar_id2real_id(virtual_id)
result = super(crm_meeting, self).message_get_subscription_data(cr, uid, [real_id], context=context)
res[virtual_id] = result[real_id]
return res
def copy(self, cr, uid, id, default=None, context=None):
default = default or {}
default['attendee_ids'] = False
return super(crm_meeting, self).copy(cr, uid, id, default, context)
def write(self, cr, uid, ids, values, context=None):
""" Override to add case management: open/close dates """
if values.get('state')and values.get('state') == 'open':
values['date_open'] = fields.datetime.now()
return super(crm_meeting, self).write(cr, uid, ids, values, context=context)
def onchange_partner_ids(self, cr, uid, ids, value, context=None):
""" The basic purpose of this method is to check that destination partners
effectively have email addresses. Otherwise a warning is thrown.
:param value: value format: [[6, 0, [3, 4]]]
"""
res = {'value': {}}
if not value or not value[0] or not value[0][0] == 6:
return
res.update(self.check_partners_email(cr, uid, value[0][2], context=context))
return res
def check_partners_email(self, cr, uid, partner_ids, context=None):
""" Verify that selected partner_ids have an email_address defined.
Otherwise throw a warning. """
partner_wo_email_lst = []
for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
if not partner.email:
partner_wo_email_lst.append(partner)
if not partner_wo_email_lst:
return {}
warning_msg = _('The following contacts have no email address :')
for partner in partner_wo_email_lst:
warning_msg += '\n- %s' % (partner.name)
return {'warning': {
'title': _('Email addresses not found'),
'message': warning_msg,
}
}
# ----------------------------------------
# OpenChatter
# ----------------------------------------
# shows events of the day for this user
def _needaction_domain_get(self, cr, uid, context=None):
return [('date', '<=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')), ('date_deadline', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT + ' 23:59:59')), ('user_id', '=', uid)]
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification',
subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
if isinstance(thread_id, str):
thread_id = get_real_ids(thread_id)
return super(crm_meeting, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, **kwargs)
class mail_message(osv.osv):
_inherit = "mail.message"
def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False):
'''
convert the search on real ids in the case it was asked on virtual ids, then call super()
'''
for index in range(len(args)):
if args[index][0] == "res_id" and isinstance(args[index][2], str):
args[index][2] = get_real_ids(args[index][2])
return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None):
if doc_model == 'crm.meeting':
for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], context=context):
doc_dict.setdefault(virtual_id, doc_dict[get_real_ids(virtual_id)])
return super(mail_message, self)._find_allowed_model_wise(cr, uid, doc_model, doc_dict, context=context)
class ir_attachment(osv.osv):
_inherit = "ir.attachment"
def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False):
'''
convert the search on real ids in the case it was asked on virtual ids, then call super()
'''
for index in range(len(args)):
if args[index][0] == "res_id" and isinstance(args[index][2], str):
args[index][2] = get_real_ids(args[index][2])
return super(ir_attachment, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count)
def write(self, cr, uid, ids, vals, context=None):
'''
when posting an attachment (new or not), convert the virtual ids in real ids.
'''
if isinstance(vals.get('res_id'), str):
vals['res_id'] = get_real_ids(vals.get('res_id'))
return super(ir_attachment, self).write(cr, uid, ids, vals, context=context)
class invite_wizard(osv.osv_memory):
_inherit = 'mail.wizard.invite'
def default_get(self, cr, uid, fields, context=None):
'''
in case someone clicked on 'invite others' wizard in the followers widget, transform virtual ids in real ids
'''
result = super(invite_wizard, self).default_get(cr, uid, fields, context=context)
if 'res_id' in result:
result['res_id'] = get_real_ids(result['res_id'])
return result

View File

@ -1,32 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<!-- CASE CATEGORY(categ_id) -->
<record model="crm.meeting.type" id="categ_meet1">
<field name="name">Customer Meeting</field>
</record>
<record model="crm.meeting.type" id="categ_meet2">
<field name="name">Internal Meeting</field>
</record>
<record model="crm.meeting.type" id="categ_meet3">
<field name="name">Off-site Meeting</field>
</record>
<record model="crm.meeting.type" id="categ_meet4">
<field name="name">Open Discussion</field>
</record>
<record model="crm.meeting.type" id="categ_meet5">
<field name="name">Feedback Meeting</field>
</record>
<record model="res.request.link" id="request_link_meeting">
<field name="name">Meeting</field>
<field name="object">crm.meeting</field>
</record>
</data>
</openerp>

View File

@ -281,7 +281,7 @@ class MergePartnerAutomatic(osv.TransientModel):
except (osv.except_osv, orm.except_orm):
_logger.info('Skip recursive partner hierarchies for parent_id %s of partner: %s', parent_id, dst_partner.id)
@mute_logger('openerp.osv.expression', 'openerp.osv.orm')
@mute_logger('openerp.osv.expression', 'openerp.models')
def _merge(self, cr, uid, partner_ids, dst_partner=None, context=None):
proxy = self.pool.get('res.partner')
@ -327,8 +327,7 @@ class MergePartnerAutomatic(osv.TransientModel):
information of the previous one and will copy the new cleaned email into
the email field.
"""
if context is None:
context = {}
context = dict(context or {})
proxy_model = self.pool['ir.model.fields']
field_ids = proxy_model.search(cr, uid, [('model', '=', 'res.partner'),

View File

@ -28,7 +28,6 @@ from openerp import SUPERUSER_ID
from openerp import tools
from openerp.addons.base.res.res_partner import format_address
from openerp.osv import fields, osv, orm
from openerp.tools import html2plaintext
from openerp.tools.translate import _
CRM_LEAD_FIELDS_TO_MERGE = ['name',
@ -82,6 +81,7 @@ class crm_lead(format_address, osv.osv):
_mail_mass_mailing = _('Leads / Opportunities')
def get_empty_list_help(self, cr, uid, help, context=None):
context = dict(context or {})
if context.get('default_type') == 'lead':
context['empty_list_help_model'] = 'crm.case.section'
context['empty_list_help_id'] = context.get('default_section_id')
@ -224,7 +224,7 @@ class crm_lead(format_address, osv.osv):
"Filter 'Available for Mass Mailing' allows users to filter the leads when performing mass mailing."),
'type': fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', select=True, help="Type is used to separate Leads and Opportunities"),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True),
'date_closed': fields.datetime('Closed', readonly=True),
'date_closed': fields.datetime('Closed', readonly=True, copy=False),
'stage_id': fields.many2one('crm.case.stage', 'Stage', track_visibility='onchange', select=True,
domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"),
'user_id': fields.many2one('res.users', 'Salesperson', select=True, track_visibility='onchange'),
@ -883,8 +883,7 @@ class crm_lead(format_address, osv.osv):
return res
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
context = dict(context or {})
if vals.get('type') and not context.get('default_type'):
context['default_type'] = vals.get('type')
if vals.get('section_id') and not context.get('default_section_id'):
@ -917,11 +916,10 @@ class crm_lead(format_address, osv.osv):
default['date_open'] = fields.datetime.now()
else:
default['date_open'] = False
default['date_closed'] = False
default['stage_id'] = self._get_default_stage_id(cr, uid, local_context)
return super(crm_lead, self).copy(cr, uid, id, default, context=context)
return super(crm_lead, self).copy(cr, uid, id, default, context=local_context)
def get_empty_list_help(self, cr, uid, help, context=None):
context = dict(context or {})
context['empty_list_help_model'] = 'crm.case.section'
context['empty_list_help_id'] = context.get('default_section_id', None)
context['empty_list_help_document_name'] = _("opportunity")

View File

@ -41,7 +41,7 @@ added to partners that match the segmentation criterions after computation.'),
('running','Running')], 'Execution Status', readonly=True),
'partner_id': fields.integer('Max Partner ID processed'),
'segmentation_line': fields.one2many('crm.segmentation.line', \
'segmentation_id', 'Criteria', required=True),
'segmentation_id', 'Criteria', required=True, copy=True),
'sales_purchase_active': fields.boolean('Use The Sales Purchase Rules', help='Check if you want to use this tab as part of the segmentation rule. If not checked, the criteria beneath will be ignored')
}
_defaults = {
@ -57,13 +57,13 @@ added to partners that match the segmentation criterions after computation.'),
@param ids: List of Process continues IDs"""
partner_obj = self.pool.get('res.partner')
categs = self.read(cr, uid, ids, ['categ_id', 'exclusif', 'partner_id',\
'sales_purchase_active', 'profiling_active'])
categs = self.read(cr, uid, ids, ['categ_id', 'exclusif', 'sales_purchase_active'])
for categ in categs:
if start:
if categ['exclusif']:
cr.execute('delete from res_partner_res_partner_category_rel \
where category_id=%s', (categ['categ_id'][0],))
partner_obj.invalidate_cache(cr, uid, ['category_id'])
id = categ['id']
@ -86,6 +86,7 @@ added to partners that match the segmentation criterions after computation.'),
if categ['categ_id'][0] not in category_ids:
cr.execute('insert into res_partner_res_partner_category_rel (category_id,partner_id) \
values (%s,%s)', (categ['categ_id'][0], partner.id))
partner_obj.invalidate_cache(cr, uid, ['category_id'], [partner.id])
self.write(cr, uid, [id], {'state':'not running', 'partner_id':0})
return True

View File

@ -53,14 +53,6 @@ class res_partner(osv.osv):
'phonecall_count': fields.function(_opportunity_meeting_phonecall_count, string="Phonecalls", type="integer", multi='opp_meet'),
}
def copy(self, cr, uid, record_id, default=None, context=None):
if default is None:
default = {}
default.update({'opportunity_ids': [], 'meeting_ids' : [], 'phonecall_ids' : []})
return super(res_partner, self).copy(cr, uid, record_id, default, context)
def redirect_partner_form(self, cr, uid, partner_id, context=None):
search_view = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'view_res_partner_filter')
value = {

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