[MERGE]: Merged with addons
bzr revid: atp@tinyerp.com-20130613090244-f5of1maz4acpy1fp
This commit is contained in:
@@ -648,10 +648,10 @@ class account_account(osv.osv):
|
||||
if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]):
|
||||
#Check for 'Closed' type
|
||||
if old_type == 'closed' and new_type !='closed':
|
||||
raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type as it contains journal items!"))
|
||||
raise osv.except_osv(_('Warning!'), _("You cannot change the type of account from 'Closed' to any other type as it contains journal items!"))
|
||||
# Forbid to change an account type for restricted_groups as it contains journal items (or if one of its children does)
|
||||
if (new_type in restricted_groups):
|
||||
raise osv.except_osv(_('Warning !'), _("You cannot change the type of account to '%s' type as it contains journal items!") % (new_type,))
|
||||
raise osv.except_osv(_('Warning!'), _("You cannot change the type of account to '%s' type as it contains journal items!") % (new_type,))
|
||||
|
||||
return True
|
||||
|
||||
@@ -1015,14 +1015,14 @@ class account_period(osv.osv):
|
||||
if not result:
|
||||
result = self.search(cr, uid, args, context=context)
|
||||
if not result:
|
||||
raise osv.except_osv(_('Error !'), _('There is no period defined for this date: %s.\nPlease create one.')%dt)
|
||||
raise osv.except_osv(_('Error!'), _('There is no period defined for this date: %s.\nPlease create one.')%dt)
|
||||
return result
|
||||
|
||||
def action_draft(self, cr, uid, ids, *args):
|
||||
mode = 'draft'
|
||||
for period in self.browse(cr, uid, ids):
|
||||
if period.fiscalyear_id.state == 'done':
|
||||
raise osv.except_osv(_('Warning !'), _('You can not re-open a period which belongs to closed fiscal year'))
|
||||
raise osv.except_osv(_('Warning!'), _('You can not re-open a period which belongs to closed fiscal year'))
|
||||
cr.execute('update account_journal_period set state=%s where period_id in %s', (mode, tuple(ids),))
|
||||
cr.execute('update account_period set state=%s where id in %s', (mode, tuple(ids),))
|
||||
return True
|
||||
@@ -2317,7 +2317,7 @@ class account_model(osv.osv):
|
||||
try:
|
||||
entry['name'] = model.name%{'year': move_date.strftime('%Y'), 'month': move_date.strftime('%m'), 'date': move_date.strftime('%Y-%m')}
|
||||
except:
|
||||
raise osv.except_osv(_('Wrong model !'), _('You have a wrong expression "%(...)s" in your model !'))
|
||||
raise osv.except_osv(_('Wrong Model!'), _('You have a wrong expression "%(...)s" in your model!'))
|
||||
move_id = account_move_obj.create(cr, uid, {
|
||||
'ref': entry['name'],
|
||||
'period_id': period_id,
|
||||
@@ -2329,7 +2329,7 @@ class account_model(osv.osv):
|
||||
analytic_account_id = False
|
||||
if line.analytic_account_id:
|
||||
if not model.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (model.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (model.journal_id.name,))
|
||||
analytic_account_id = line.analytic_account_id.id
|
||||
val = {
|
||||
'move_id': move_id,
|
||||
|
||||
@@ -420,7 +420,7 @@ class account_bank_statement(osv.osv):
|
||||
for st_line in st.line_ids:
|
||||
if st_line.analytic_account_id:
|
||||
if not st.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,))
|
||||
if not st_line.amount:
|
||||
continue
|
||||
st_line_number = self.get_next_st_line_number(cr, uid, st_number, st_line, context)
|
||||
|
||||
@@ -252,7 +252,7 @@ class account_cash_statement(osv.osv):
|
||||
for statement in statement_pool.browse(cr, uid, ids, context=context):
|
||||
vals = {}
|
||||
if not self._user_allow(cr, uid, statement.id, context=context):
|
||||
raise osv.except_osv(_('Error!'), (_('You do not have rights to open this %s journal !') % (statement.journal_id.name, )))
|
||||
raise osv.except_osv(_('Error!'), (_('You do not have rights to open this %s journal!') % (statement.journal_id.name, )))
|
||||
|
||||
if statement.name and statement.name == '/':
|
||||
c = {'fiscalyear_id': statement.period_id.fiscalyear_id.id}
|
||||
|
||||
@@ -69,7 +69,7 @@ class account_invoice(osv.osv):
|
||||
tt = type2journal.get(type_inv, 'sale')
|
||||
result = self.pool.get('account.analytic.journal').search(cr, uid, [('type','=',tt)], context=context)
|
||||
if not result:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You must define an analytic journal of type '%s'!") % (tt,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You must define an analytic journal of type '%s'!") % (tt,))
|
||||
return result[0]
|
||||
|
||||
def _get_type(self, cr, uid, context=None):
|
||||
@@ -630,7 +630,7 @@ class account_invoice(osv.osv):
|
||||
obj_l = account_obj.browse(cr, uid, inv_line[2]['account_id'])
|
||||
if obj_l.company_id.id != company_id:
|
||||
raise osv.except_osv(_('Configuration Error!'),
|
||||
_('Invoice line account\'s company and invoice\'s compnay does not match.'))
|
||||
_('Invoice line account\'s company and invoice\'s company does not match.'))
|
||||
else:
|
||||
continue
|
||||
if company_id and type:
|
||||
@@ -786,7 +786,7 @@ class account_invoice(osv.osv):
|
||||
else:
|
||||
ref = self._convert_ref(cr, uid, inv.number)
|
||||
if not inv.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (inv.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (inv.journal_id.name,))
|
||||
il['analytic_lines'] = [(0,0, {
|
||||
'name': il['name'],
|
||||
'date': inv['date_invoice'],
|
||||
@@ -912,7 +912,7 @@ class account_invoice(osv.osv):
|
||||
if not inv.journal_id.sequence_id:
|
||||
raise osv.except_osv(_('Error!'), _('Please define sequence on the journal related to this invoice.'))
|
||||
if not inv.invoice_line:
|
||||
raise osv.except_osv(_('No Invoice Lines !'), _('Please create some invoice lines.'))
|
||||
raise osv.except_osv(_('No Invoice Lines!'), _('Please create some invoice lines.'))
|
||||
if inv.move_id:
|
||||
continue
|
||||
|
||||
@@ -933,7 +933,7 @@ class account_invoice(osv.osv):
|
||||
group_check_total = self.pool.get('res.groups').browse(cr, uid, group_check_total_id, context=context)
|
||||
if group_check_total and uid in [x.id for x in group_check_total.users]:
|
||||
if (inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0)):
|
||||
raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe encoded total does not match the computed total.'))
|
||||
raise osv.except_osv(_('Bad Total!'), _('Please verify the price of the invoice!\nThe encoded total does not match the computed total.'))
|
||||
|
||||
if inv.payment_term:
|
||||
total_fixed = total_percent = 0
|
||||
@@ -1475,7 +1475,7 @@ class account_invoice_line(osv.osv):
|
||||
context = dict(context)
|
||||
context.update({'company_id': company_id, 'force_company': company_id})
|
||||
if not partner_id:
|
||||
raise osv.except_osv(_('No Partner Defined !'),_("You must first select a partner !") )
|
||||
raise osv.except_osv(_('No Partner Defined!'),_("You must first select a partner!") )
|
||||
if not product:
|
||||
if type in ('in_invoice', 'in_refund'):
|
||||
return {'value': {}, 'domain':{'product_uom':[]}}
|
||||
|
||||
@@ -192,7 +192,7 @@ class account_move_line(osv.osv):
|
||||
for obj_line in self.browse(cr, uid, ids, context=context):
|
||||
if obj_line.analytic_account_id:
|
||||
if not obj_line.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (obj_line.journal_id.name, ))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (obj_line.journal_id.name, ))
|
||||
vals_line = self._prepare_analytic_line(cr, uid, obj_line, context=context)
|
||||
acc_ana_line_obj.create(cr, uid, vals_line)
|
||||
return True
|
||||
@@ -1101,7 +1101,7 @@ class account_move_line(osv.osv):
|
||||
period = period_obj.browse(cr, uid, period_id, context=context)
|
||||
for (state,) in result:
|
||||
if state == 'done':
|
||||
raise osv.except_osv(_('Error !'), _('You can not add/modify entries in a closed period %s of journal %s.' % (period.name,journal.name)))
|
||||
raise osv.except_osv(_('Error!'), _('You can not add/modify entries in a closed period %s of journal %s.' % (period.name,journal.name)))
|
||||
if not result:
|
||||
jour_period_obj.create(cr, uid, {
|
||||
'name': (journal.code or journal.name)+':'+(period.name or ''),
|
||||
@@ -1181,7 +1181,7 @@ class account_move_line(osv.osv):
|
||||
move_id = move_obj.create(cr, uid, v, context)
|
||||
vals['move_id'] = move_id
|
||||
else:
|
||||
raise osv.except_osv(_('No piece number !'), _('Cannot create an automatic sequence for this piece.\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.'))
|
||||
raise osv.except_osv(_('No Piece Number!'), _('Cannot create an automatic sequence for this piece.\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.'))
|
||||
ok = not (journal.type_control_ids or journal.account_control_ids)
|
||||
if ('account_id' in vals):
|
||||
account = account_obj.browse(cr, uid, vals['account_id'], context=context)
|
||||
|
||||
+208
-175
File diff suppressed because it is too large
Load Diff
+183
-168
File diff suppressed because it is too large
Load Diff
@@ -111,7 +111,7 @@ class account_installer(osv.osv_memory):
|
||||
def check_unconfigured_cmp(self, cr, uid, context=None):
|
||||
""" check if there are still unconfigured companies """
|
||||
if not self.get_unconfigured_cmp(cr, uid, context=context):
|
||||
raise osv.except_osv(_('No unconfigured company !'), _("There is currently no company without chart of account. The wizard will therefore not be executed."))
|
||||
raise osv.except_osv(_('No Unconfigured Company!'), _("There is currently no company without chart of account. The wizard will therefore not be executed."))
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
if context is None: context = {}
|
||||
|
||||
@@ -57,7 +57,7 @@ class validate_account_move_lines(osv.osv_memory):
|
||||
move_ids.append(line.move_id.id)
|
||||
move_ids = list(set(move_ids))
|
||||
if not move_ids:
|
||||
raise osv.except_osv(_('Warning!'), _('Selected Entry Lines does not have any account move enties in draft state.'))
|
||||
raise osv.except_osv(_('Warning!'), _('Selected Entry Lines does not have any account move entries in draft state.'))
|
||||
obj_move.button_validate(cr, uid, move_ids, context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
@@ -653,7 +653,7 @@ class account_analytic_account(osv.osv):
|
||||
fpos_obj = self.pool.get('account.fiscal.position')
|
||||
|
||||
if not contract.partner_id:
|
||||
raise osv.except_osv(_('No Customer Defined !'),_("You must first select a Customer for Contract %s!") % contract.name )
|
||||
raise osv.except_osv(_('No Customer Defined!'),_("You must first select a Customer for Contract %s!") % contract.name )
|
||||
|
||||
fpos = contract.partner_id.property_account_position.id or False
|
||||
journal_ids = journal_obj.search(cr, uid, [('type', '=','sale'),('company_id', '=', contract.company_id.id or False)], limit=1)
|
||||
|
||||
@@ -332,7 +332,7 @@ class account_move_line(osv.osv):
|
||||
for line in self.browse(cr, uid, ids, context=context):
|
||||
if line.analytics_id:
|
||||
if not line.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal.") % (line.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal.") % (line.journal_id.name,))
|
||||
|
||||
toremove = analytic_line_obj.search(cr, uid, [('move_id','=',line.id)], context=context)
|
||||
if toremove:
|
||||
@@ -471,7 +471,7 @@ class account_bank_statement(osv.osv):
|
||||
for st_line in st.line_ids:
|
||||
if st_line.analytics_id:
|
||||
if not st.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal.") % (st.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal.") % (st.journal_id.name,))
|
||||
if not st_line.amount:
|
||||
continue
|
||||
return True
|
||||
|
||||
@@ -1622,7 +1622,7 @@ class account_bank_statement(osv.osv):
|
||||
for bk_st in self.browse(cr, uid, ids, context=context):
|
||||
if vals.get('journal_id') and bk_st.line_ids:
|
||||
if any([x.voucher_id and True or False for x in bk_st.line_ids]):
|
||||
raise osv.except_osv(_('Unable to change journal !'), _('You can not change the journal as you already reconciled some statement lines!'))
|
||||
raise osv.except_osv(_('Unable to Change Journal!'), _('You can not change the journal as you already reconciled some statement lines!'))
|
||||
return super(account_bank_statement, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ class account_analytic_account(osv.osv):
|
||||
for account in self.browse(cr, uid, ids, context=context):
|
||||
if account.company_id:
|
||||
if account.company_id.currency_id.id != value:
|
||||
raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really usefull for consolidation purposes of several companies charts with different currencies, for example."))
|
||||
raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really useful for consolidation purposes of several companies charts with different currencies, for example."))
|
||||
if value:
|
||||
return cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id, ))
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ class hr_analytic_timesheet(osv.osv):
|
||||
a = r.product_id.categ_id.property_account_expense_categ.id
|
||||
if not a:
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_('There is no expense account define ' \
|
||||
_('There is no expense account defined ' \
|
||||
'for this product: "%s" (id:%d)') % \
|
||||
(r.product_id.name, r.product_id.id,))
|
||||
# Compute based on pricetype
|
||||
@@ -133,7 +133,7 @@ class hr_analytic_timesheet(osv.osv):
|
||||
a = r.product_id.categ_id.property_account_expense_categ.id
|
||||
if not a:
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_('There is no expense account define ' \
|
||||
_('There is no expense account defined ' \
|
||||
'for this product: "%s" (id:%d)') % \
|
||||
(r.product_id.name, r.product_id.id,))
|
||||
# Compute based on pricetype
|
||||
|
||||
@@ -86,11 +86,11 @@ class ir_model_fields_anonymization(osv.osv):
|
||||
if context.get('manual'):
|
||||
global_state = self._get_global_state(cr, uid, context=context)
|
||||
if global_state == 'anonymized':
|
||||
raise osv.except_osv('Error !', "The database is currently anonymized, you cannot create, modify or delete fields.")
|
||||
raise osv.except_osv('Error!', "The database is currently anonymized, you cannot create, modify or delete fields.")
|
||||
elif global_state == 'unstable':
|
||||
msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \
|
||||
" while some fields are not anonymized. You should try to solve this problem before trying to create, write or delete fields.")
|
||||
raise osv.except_osv('Error !', msg)
|
||||
raise osv.except_osv('Error!', msg)
|
||||
|
||||
return True
|
||||
|
||||
@@ -357,7 +357,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
else:
|
||||
msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \
|
||||
" while some fields are not anonymized. You should try to solve this problem before trying to do anything else.")
|
||||
raise osv.except_osv('Error !', msg)
|
||||
raise osv.except_osv('Error!', msg)
|
||||
|
||||
res['arch'] = etree.tostring(eview)
|
||||
|
||||
@@ -521,11 +521,11 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
||||
# check that all the defined fields are in the 'anonymized' state
|
||||
state = ir_model_fields_anonymization_model._get_global_state(cr, uid, context=context)
|
||||
if state == 'clear':
|
||||
raise osv.except_osv_('Error !', "The database is not currently anonymized, you cannot reverse the anonymization.")
|
||||
raise osv.except_osv_('Error!', "The database is not currently anonymized, you cannot reverse the anonymization.")
|
||||
elif state == 'unstable':
|
||||
msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \
|
||||
" while some fields are not anonymized. You should try to solve this problem before trying to do anything.")
|
||||
raise osv.except_osv('Error !', msg)
|
||||
raise osv.except_osv('Error!', msg)
|
||||
|
||||
wizards = self.browse(cr, uid, ids, context=context)
|
||||
for wizard in wizards:
|
||||
|
||||
@@ -104,7 +104,7 @@ class base_state(object):
|
||||
if parent_id.change_responsible and parent_id.user_id:
|
||||
data['user_id'] = parent_id.user_id.id
|
||||
else:
|
||||
raise osv.except_osv(_('Error !'), _('You can not escalate, you are already at the top level regarding your sales-team category.'))
|
||||
raise osv.except_osv(_('Error!'), _('You can not escalate, you are already at the top level regarding your sales-team category.'))
|
||||
self.write(cr, uid, [case.id], data, context=context)
|
||||
case.case_escalate_send_note(parent_id, context=context)
|
||||
return True
|
||||
|
||||
@@ -86,7 +86,7 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context):
|
||||
if lead.state in ['done', 'cancel']:
|
||||
raise osv.except_osv(_("Warning !"), _("Closed/Cancelled leads cannot be converted into opportunities."))
|
||||
raise osv.except_osv(_("Warning!"), _("Closed/Cancelled leads cannot be converted into opportunities."))
|
||||
return False
|
||||
|
||||
def _convert_opportunity(self, cr, uid, ids, vals, context=None):
|
||||
|
||||
@@ -14,7 +14,7 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-06-07 05:48+0000\n"
|
||||
"X-Launchpad-Export-Date: 2013-06-08 05:52+0000\n"
|
||||
"X-Generator: Launchpad (build 16667)\n"
|
||||
|
||||
#. module: crm_helpdesk
|
||||
|
||||
@@ -51,10 +51,10 @@ class sale_order(osv.osv):
|
||||
for order in self.browse(cr, uid, ids, context=context):
|
||||
grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id)
|
||||
if not grid_id:
|
||||
raise osv.except_osv(_('No grid available !'), _('No grid matching for this carrier !'))
|
||||
raise osv.except_osv(_('No Grid Available!'), _('No grid matching for this carrier!'))
|
||||
|
||||
if not order.state in ('draft'):
|
||||
raise osv.except_osv(_('Order not in draft state !'), _('The order state have to be draft to add delivery lines.'))
|
||||
raise osv.except_osv(_('Order not in Draft State!'), _('The order state have to be draft to add delivery lines.'))
|
||||
|
||||
grid = grid_obj.browse(cr, uid, grid_id, context=context)
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ class edi(osv.AbstractModel):
|
||||
module = edi_document.get('__import_module') or edi_document.get('__module')
|
||||
assert module, 'a `__module` or `__import_module` attribute is required in each EDI document.'
|
||||
if module != 'base' and not ir_module.search(cr, uid, [('name','=',module),('state','=','installed')]):
|
||||
raise osv.except_osv(_('Missing application.'),
|
||||
raise osv.except_osv(_('Missing Application.'),
|
||||
_("The document you are trying to import requires the OpenERP `%s` application. "
|
||||
"You can install it by connecting as the administrator and opening the configuration assistant.")%(module,))
|
||||
model = edi_document.get('__import_model') or edi_document.get('__model')
|
||||
|
||||
@@ -23,5 +23,6 @@ import hr_department
|
||||
import hr
|
||||
|
||||
import res_config
|
||||
import res_users
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -59,6 +59,8 @@ You can manage:
|
||||
'hr_installer.xml',
|
||||
'hr_data.xml',
|
||||
'res_config_view.xml',
|
||||
'mail_hr_view.xml',
|
||||
'res_users_view.xml',
|
||||
],
|
||||
'demo': ['hr_demo.xml'],
|
||||
'test': [
|
||||
@@ -69,5 +71,7 @@ You can manage:
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
'css': [ 'static/src/css/hr.css' ],
|
||||
'js': [ 'static/src/js/suggestions.js' ],
|
||||
'qweb': [ 'static/src/xml/suggestions.xml' ],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
+81
-26
@@ -25,9 +25,11 @@ from openerp.modules.module import get_module_resource
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp import tools
|
||||
from openerp.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class hr_employee_category(osv.osv):
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
@@ -150,6 +152,7 @@ class hr_job(osv.osv):
|
||||
class hr_employee(osv.osv):
|
||||
_name = "hr.employee"
|
||||
_description = "Employee"
|
||||
_order = 'name_related'
|
||||
_inherits = {'resource.resource': "resource_id"}
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
@@ -158,10 +161,10 @@ class hr_employee(osv.osv):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
result[obj.id] = tools.image_get_resized_images(obj.image)
|
||||
return result
|
||||
|
||||
|
||||
def _set_image(self, cr, uid, id, name, value, args, context=None):
|
||||
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
|
||||
|
||||
|
||||
_columns = {
|
||||
#we need a related field in order to be able to sort the employee by name
|
||||
'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
|
||||
@@ -171,12 +174,12 @@ class hr_employee(osv.osv):
|
||||
'sinid': fields.char('SIN No', size=32, help="Social Insurance Number"),
|
||||
'identification_id': fields.char('Identification No', size=32),
|
||||
'otherid': fields.char('Other Id', size=64),
|
||||
'gender': fields.selection([('male', 'Male'),('female', 'Female')], 'Gender'),
|
||||
'gender': fields.selection([('male', 'Male'), ('female', 'Female')], 'Gender'),
|
||||
'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'),
|
||||
'department_id':fields.many2one('hr.department', 'Department'),
|
||||
'department_id': fields.many2one('hr.department', 'Department'),
|
||||
'address_id': fields.many2one('res.partner', 'Working Address'),
|
||||
'address_home_id': fields.many2one('res.partner', 'Home Address'),
|
||||
'bank_account_id':fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
|
||||
'bank_account_id': fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
|
||||
'work_phone': fields.char('Work Phone', size=32, readonly=False),
|
||||
'mobile_phone': fields.char('Work Mobile', size=32, readonly=False),
|
||||
'work_email': fields.char('Work Email', size=240),
|
||||
@@ -207,25 +210,42 @@ class hr_employee(osv.osv):
|
||||
help="Small-sized photo of the employee. It is automatically "\
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "\
|
||||
"Use this field anywhere a small image is required."),
|
||||
'passport_id':fields.char('Passport No', size=64),
|
||||
'passport_id': fields.char('Passport No', size=64),
|
||||
'color': fields.integer('Color Index'),
|
||||
'city': fields.related('address_id', 'city', type='char', string='City'),
|
||||
'login': fields.related('user_id', 'login', type='char', string='Login', readonly=1),
|
||||
'last_login': fields.related('user_id', 'date', type='datetime', string='Latest Connection', readonly=1),
|
||||
}
|
||||
|
||||
_order='name_related'
|
||||
def _get_default_image(self, cr, uid, context=None):
|
||||
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
|
||||
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
|
||||
|
||||
defaults = {
|
||||
'active': 1,
|
||||
'image': _get_default_image,
|
||||
'color': 0,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, data, context=None):
|
||||
employee_id = super(hr_employee, self).create(cr, uid, data, context=context)
|
||||
try:
|
||||
(model, mail_group_id) = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'group_all_employees')
|
||||
employee = self.browse(cr, uid, employee_id, context=context)
|
||||
self.pool.get('mail.group').message_post(cr, uid, [mail_group_id],
|
||||
body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
|
||||
subtype='mail.mt_comment', context=context)
|
||||
except:
|
||||
pass # group deleted: do not push a message
|
||||
if context is None:
|
||||
context = {}
|
||||
create_ctx = dict(context, mail_create_nolog=True)
|
||||
employee_id = super(hr_employee, self).create(cr, uid, data, context=create_ctx)
|
||||
employee = self.browse(cr, uid, employee_id, context=context)
|
||||
if employee.user_id:
|
||||
# send a copy to every user of the company
|
||||
company_id = employee.user_id.partner_id.company_id.id
|
||||
partner_ids = self.pool.get('res.partner').search(cr, uid, [
|
||||
('company_id', '=', company_id),
|
||||
('user_ids', '!=', False)], context=context)
|
||||
else:
|
||||
partner_ids = []
|
||||
self.message_post(cr, uid, [employee_id],
|
||||
body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
|
||||
partner_ids=partner_ids,
|
||||
subtype='mail.mt_comment', context=context
|
||||
)
|
||||
return employee_id
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
@@ -246,7 +266,7 @@ class hr_employee(osv.osv):
|
||||
company_id = self.pool.get('res.company').browse(cr, uid, company, context=context)
|
||||
address = self.pool.get('res.partner').address_get(cr, uid, [company_id.partner_id.id], ['default'])
|
||||
address_id = address and address['default'] or False
|
||||
return {'value': {'address_id' : address_id}}
|
||||
return {'value': {'address_id': address_id}}
|
||||
|
||||
def onchange_department_id(self, cr, uid, ids, department_id, context=None):
|
||||
value = {'parent_id': False}
|
||||
@@ -259,17 +279,36 @@ class hr_employee(osv.osv):
|
||||
work_email = False
|
||||
if user_id:
|
||||
work_email = self.pool.get('res.users').browse(cr, uid, user_id, context=context).email
|
||||
return {'value': {'work_email' : work_email}}
|
||||
return {'value': {'work_email': work_email}}
|
||||
|
||||
def _get_default_image(self, cr, uid, context=None):
|
||||
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
|
||||
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
|
||||
def action_follow(self, cr, uid, ids, context=None):
|
||||
""" Wrapper because message_subscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_subscribe_users(cr, uid, ids, context=context)
|
||||
|
||||
_defaults = {
|
||||
'active': 1,
|
||||
'image': _get_default_image,
|
||||
'color': 0,
|
||||
}
|
||||
def action_unfollow(self, cr, uid, ids, context=None):
|
||||
""" Wrapper because message_unsubscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_unsubscribe_users(cr, uid, ids, context=context)
|
||||
|
||||
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
|
||||
"""Show the suggestion of employees if display_employees_suggestions if the
|
||||
user perference allows it. """
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||
if not user.display_employees_suggestions:
|
||||
return []
|
||||
else:
|
||||
return super(hr_employee, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)
|
||||
|
||||
def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
|
||||
""" Overwrite of the original method to always follow user_id field,
|
||||
even when not track_visibility so that a user will follow it's employee
|
||||
"""
|
||||
user_field_lst = []
|
||||
for name, column_info in self._all_columns.items():
|
||||
if name in auto_follow_fields and name in updated_fields and column_info.column._obj == 'res.users':
|
||||
user_field_lst.append(name)
|
||||
return user_field_lst
|
||||
|
||||
def _check_recursion(self, cr, uid, ids, context=None):
|
||||
level = 100
|
||||
@@ -285,6 +324,22 @@ class hr_employee(osv.osv):
|
||||
(_check_recursion, 'Error! You cannot create recursive hierarchy of Employee(s).', ['parent_id']),
|
||||
]
|
||||
|
||||
# ---------------------------------------------------
|
||||
# Mail gateway
|
||||
# ---------------------------------------------------
|
||||
|
||||
def check_mail_message_access(self, cr, uid, mids, operation, model_obj=None, context=None):
|
||||
""" mail.message document permission rule: can post a new message if can read
|
||||
because of portal document. """
|
||||
if not model_obj:
|
||||
model_obj = self
|
||||
employee_ids = model_obj.search(cr, uid, [('user_id', '=', uid)], context=context)
|
||||
if employee_ids and operation == 'create':
|
||||
model_obj.check_access_rights(cr, uid, 'read')
|
||||
model_obj.check_access_rule(cr, uid, mids, 'read', context=context)
|
||||
else:
|
||||
return super(hr_employee, self).check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context)
|
||||
|
||||
|
||||
class hr_department(osv.osv):
|
||||
_description = "Department"
|
||||
|
||||
+18
-4
@@ -27,6 +27,10 @@
|
||||
</h1>
|
||||
<label for="category_ids" class="oe_edit_only" groups="base.group_hr_user"/>
|
||||
<field name="category_ids" widget="many2many_tags" placeholder="e.g. Part Time" groups="base.group_hr_user"/>
|
||||
<label for="work_email" class="oe_edit_only"/>
|
||||
<field name="work_email" widget="email"/>
|
||||
<label for="work_phone" class="oe_edit_only"/>
|
||||
<field name="work_phone"/>
|
||||
</div>
|
||||
<div class="oe_right oe_button_box" name="button_box">
|
||||
<!-- Put here related buttons -->
|
||||
@@ -36,8 +40,6 @@
|
||||
<group>
|
||||
<group string="Contact Information">
|
||||
<field name="address_id" on_change="onchange_address_id(address_id)" context="{'show_address': 1}" options='{"always_reload": True, "highlight_first_line": True}'/>
|
||||
<field name="work_email" widget="email"/>
|
||||
<field name="work_phone"/>
|
||||
<field name="mobile_phone"/>
|
||||
<field name="work_location"/>
|
||||
</group>
|
||||
@@ -136,6 +138,9 @@
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="last_login"/>
|
||||
<field name="message_is_follower"/>
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_employee_vignette">
|
||||
@@ -154,10 +159,19 @@
|
||||
</li>
|
||||
<li t-if="record.job_id.raw_value"><field name="job_id"/></li>
|
||||
<li t-if="record.work_location.raw_value"><field name="work_location"/></li>
|
||||
<li t-if="record.work_phone.raw_value">Tel: <field name="work_phone"/></li>
|
||||
<li t-if="record.mobile_phone.raw_value">Mobile: <field name="mobile_phone"/></li>
|
||||
<li t-if="record.work_email.raw_value"><a t-attf-href="mailto:#{record.work_email.value}"><field name="work_email"/></a></li>
|
||||
</ul>
|
||||
<div class="oe_kanban_footer_left">
|
||||
<span title='Messages'><span class='oe_e'>9</span><t t-esc="record.message_ids.raw_value.length"/></span>
|
||||
<span title='Followers'><span class='oe_e'>+</span><t t-esc="record.message_follower_ids.raw_value.length"/></span>
|
||||
</div>
|
||||
<div class="oe_followers" groups="base.group_user">
|
||||
<button t-if="record.message_is_follower.raw_value" name="action_unfollow" type="object" class="oe_follower oe_following">
|
||||
<span class="oe_unfollow">Unfollow</span>
|
||||
<span class="oe_following">Following</span>
|
||||
</button>
|
||||
<button t-if="! record.message_is_follower.raw_value" name="action_follow" type="object" class="oe_follower oe_notfollow">Follow</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="mail.action_mail_inbox_feeds" model="ir.actions.client">
|
||||
<field name="params" eval=""{
|
||||
'domain': [
|
||||
('to_read', '=', True),
|
||||
('starred', '=', False),
|
||||
],
|
||||
'view_mailbox': True,
|
||||
'view_inbox': True,
|
||||
'read_action': 'read',
|
||||
'show_compose_message': True
|
||||
}""/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,65 @@
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class res_users(osv.Model):
|
||||
""" Update of res.users class
|
||||
- if adding groups to an user, check if base.group_user is in it
|
||||
(member of 'Employee'), create an employee form linked to it.
|
||||
"""
|
||||
_name = 'res.users'
|
||||
_inherit = ['res.users']
|
||||
|
||||
_columns = {
|
||||
'display_employees_suggestions': fields.boolean("Display Employees Suggestions"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'display_employees_suggestions': True,
|
||||
}
|
||||
|
||||
def __init__(self, pool, cr):
|
||||
""" Override of __init__ to add access rights on
|
||||
display_employees_suggestions fields. Access rights are disabled by
|
||||
default, but allowed on some specific fields defined in
|
||||
self.SELF_{READ/WRITE}ABLE_FIELDS.
|
||||
"""
|
||||
init_res = super(res_users, self).__init__(pool, cr)
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
|
||||
self.SELF_WRITEABLE_FIELDS.append('display_employees_suggestions')
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
|
||||
self.SELF_READABLE_FIELDS.append('display_employees_suggestions')
|
||||
return init_res
|
||||
|
||||
def stop_showing_employees_suggestions(self, cr, uid, user_id, context=None):
|
||||
"""Update display_employees_suggestions value to False"""
|
||||
if context is None:
|
||||
context = {}
|
||||
self.write(cr, uid, user_id, {"display_employees_suggestions": False}, context)
|
||||
|
||||
def _create_welcome_message(self, cr, uid, user, context=None):
|
||||
"""Do not welcome new users anymore, welcome new employees instead"""
|
||||
return True
|
||||
|
||||
def _message_post_get_eid(self, cr, uid, thread_id, context=None):
|
||||
assert thread_id, "res.users does not support posting global messages"
|
||||
if context and 'thread_model' in context:
|
||||
context['thread_model'] = 'hr.employee'
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
return self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', thread_id)], context=context)
|
||||
|
||||
def message_post(self, cr, uid, thread_id, context=None, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related employee.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
if kwargs.get('type') == 'email':
|
||||
return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
|
||||
employee_ids = self._message_post_get_eid(cr, uid, thread_id, context=context)
|
||||
if not employee_ids:
|
||||
pass # dpo something
|
||||
for employee_id in employee_ids:
|
||||
res = self.pool.get('hr.employee').message_post(cr, uid, employee_id, context=context, **kwargs)
|
||||
return res
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Update user form !-->
|
||||
<record id="view_users_form_mail" model="ir.ui.view">
|
||||
<field name="name">res.users.form.hr</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="mail.view_users_form_mail"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<field name="display_groups_suggestions" position="after">
|
||||
<field name="display_employees_suggestions"/>
|
||||
</field>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -68,3 +68,8 @@
|
||||
margin: 2px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.openerp .oe_employee_vignette .oe_followers {
|
||||
width: auto;
|
||||
float: none;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
openerp.hr = function(session) {
|
||||
var _t = session.web._t;
|
||||
var QWeb = session.web.qweb;
|
||||
|
||||
var suggestions = session.suggestions;
|
||||
var removed_suggested_employee = session.suggestions.removed_suggested_employee = [];
|
||||
|
||||
suggestions.Employees = session.web.Widget.extend({
|
||||
events: {
|
||||
'click .oe_suggestion_remove.oe_suggestion_employee': 'stop_employee_suggestion',
|
||||
'click .oe_suggestion_remove_item.oe_suggestion_employee': 'remove_employee_suggestion',
|
||||
'click .oe_suggestion_follow': 'follow_employee',
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this._super(this, arguments);
|
||||
this.hr_employee = new session.web.DataSetSearch(this, 'hr.employee');
|
||||
this.res_users = new session.web.DataSetSearch(this, 'res.users');
|
||||
this.employees = [];
|
||||
},
|
||||
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
return this.fetch_suggested_employee();
|
||||
},
|
||||
|
||||
fetch_suggested_employee: function () {
|
||||
var self = this;
|
||||
var employee = self.hr_employee.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_employee}).then(function (res) {
|
||||
_(res).each(function (result) {
|
||||
result['image']=self.session.url('/web/binary/image', {model: 'hr.employee', field: 'image_small', id: result.id});
|
||||
});
|
||||
self.employees = res;
|
||||
});
|
||||
return $.when(employee).done(this.proxy('display_suggested_employees'));
|
||||
},
|
||||
|
||||
display_suggested_employees: function () {
|
||||
var suggested_employees = this.$('.oe_sidebar_suggestion.oe_suggestion_employee');
|
||||
if (suggested_employees) {
|
||||
suggested_employees.remove();
|
||||
}
|
||||
if (this.employees.length === 0) {
|
||||
return this.$el.empty();
|
||||
}
|
||||
return this.$el.empty().html(QWeb.render('hr.suggestions.employees', {'widget': this}));
|
||||
},
|
||||
|
||||
follow_employee: function (event) {
|
||||
var self = this;
|
||||
var employee_id = parseInt($(event.currentTarget).attr('id'), 10);
|
||||
return this.hr_employee.call('message_subscribe_users', [[employee_id], [this.session.uid], undefined]).then(function(res) {
|
||||
self.fetch_suggested_employee();
|
||||
});
|
||||
},
|
||||
|
||||
remove_employee_suggestion: function (event) {
|
||||
removed_suggested_employee.push($(event.currentTarget).attr('id'));
|
||||
return this.fetch_suggested_employee();
|
||||
},
|
||||
|
||||
stop_employee_suggestion: function (event) {
|
||||
var self = this;
|
||||
return this.res_users.call('stop_showing_employees_suggestions', [this.session.uid]).then(function(res) {
|
||||
self.$(".oe_sidebar_suggestion.oe_suggestion_employee").hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
session.mail.WallSidebar.include({
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
var sug_employees = new suggestions.Employees(this);
|
||||
return sug_employees.appendTo(this.$('.oe_suggestions_employees'));
|
||||
},
|
||||
});
|
||||
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<template>
|
||||
|
||||
<!-- Employees placeholder in sidebar -->
|
||||
<t t-extend="mail.wall.sidebar">
|
||||
<t t-jquery=".oe_mail_wall_sidebar" t-operation="append">
|
||||
<div class="oe_suggestions_employees"></div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Suggested employees -->
|
||||
<div t-name="hr.suggestions.employees" class="oe_sidebar_suggestion oe_suggestion_employee">
|
||||
<div class="oe_suggest_title">
|
||||
<a class="oe_suggestion_remove oe_suggestion_employee oe_e">X</a>
|
||||
<h2>Suggested Employees</h2>
|
||||
</div>
|
||||
<div class="oe_suggest_items">
|
||||
<t t-foreach="widget.employees" t-as="result">
|
||||
<div class="oe_suggested_item">
|
||||
<div class="oe_suggested_item_image">
|
||||
<a t-attf-href="#model=hr.employee&id=#{result.id}">
|
||||
<img t-attf-src="{result.image}" t-attf-alt="{result.name}"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="oe_suggested_item_content">
|
||||
<a class="oe_suggestion_item_name" t-attf-href="#model=hr.employee&id=#{result.id}"><t t-esc="result.name"/></a>
|
||||
<a class="oe_suggestion_remove_item oe_suggestion_employee oe_e" t-attf-id="{result.id}">X</a>
|
||||
<br/>
|
||||
<button class="oe_suggestion_follow" t-att-id="result.id">Follow</button>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
@@ -46,7 +46,7 @@ class hr_attendance_error(osv.osv_memory):
|
||||
cr.execute("SELECT id FROM hr_attendance WHERE employee_id IN %s AND to_char(name,'YYYY-mm-dd')<=%s AND to_char(name,'YYYY-mm-dd')>=%s AND action IN %s ORDER BY name" ,(tuple(context['active_ids']), date_to, date_from, tuple(['sign_in','sign_out'])))
|
||||
attendance_ids = [x[0] for x in cr.fetchall()]
|
||||
if not attendance_ids:
|
||||
raise osv.except_osv(_('No Data Available !'), _('No records are found for your selection!'))
|
||||
raise osv.except_osv(_('No Data Available!'), _('No records are found for your selection!'))
|
||||
attendance_records = self.pool.get('hr.attendance').browse(cr, uid, attendance_ids, context=context)
|
||||
|
||||
for rec in attendance_records:
|
||||
|
||||
@@ -49,7 +49,7 @@ class hr_payslip_employees(osv.osv_memory):
|
||||
to_date = run_data.get('date_end', False)
|
||||
credit_note = run_data.get('credit_note', False)
|
||||
if not data['employee_ids']:
|
||||
raise osv.except_osv(_("Warning !"), _("You must select employee(s) to generate payslip(s)."))
|
||||
raise osv.except_osv(_("Warning!"), _("You must select employee(s) to generate payslip(s)."))
|
||||
for emp in emp_pool.browse(cr, uid, data['employee_ids'], context=context):
|
||||
slip_data = slip_pool.onchange_employee_id(cr, uid, [], from_date, to_date, emp.id, contract_id=False, context=context)
|
||||
res = {
|
||||
|
||||
@@ -181,7 +181,7 @@ class account_analytic_line(osv.osv):
|
||||
for account in analytic_account_obj.browse(cr, uid, list(account_ids), context=context):
|
||||
partner = account.partner_id
|
||||
if (not partner) or not (account.pricelist_id):
|
||||
raise osv.except_osv(_('Analytic Account incomplete !'),
|
||||
raise osv.except_osv(_('Analytic Account Incomplete!'),
|
||||
_('Contract incomplete. Please fill in the Customer and Pricelist fields.'))
|
||||
|
||||
date_due = False
|
||||
|
||||
@@ -84,7 +84,7 @@ class l10n_be_vat_declaration(osv.osv_memory):
|
||||
obj_company = obj_user.browse(cr, uid, uid, context=context).company_id
|
||||
vat_no = obj_company.partner_id.vat
|
||||
if not vat_no:
|
||||
raise osv.except_osv(_('insufficient data!'), _('No VAT number associated with your company.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No VAT number associated with your company.'))
|
||||
vat_no = vat_no.replace(' ','').upper()
|
||||
vat = vat_no[2:]
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@ class partner_vat(osv.osv_memory):
|
||||
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
|
||||
period_ids = obj_period.search(cr, uid, [('date_start' ,'>=', date_start), ('date_stop','<=',date_stop), ('company_id','=',company_id)])
|
||||
if not period_ids:
|
||||
raise osv.except_osv(_('insufficient data!'), _('No data for the selected year.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No data for the selected year.'))
|
||||
|
||||
partners = []
|
||||
partner_ids = obj_partner.search(cr, uid, [('vat_subjected', '!=', False), ('vat','ilike','BE%')], context=context)
|
||||
if not partner_ids:
|
||||
raise osv.except_osv(_('Error'),_('No belgian contact with a VAT number in your database.'))
|
||||
raise osv.except_osv(_('Error'),_('No belgium contact with a VAT number in your database.'))
|
||||
cr.execute("""SELECT sub1.partner_id, sub1.name, sub1.vat, sub1.turnover, sub2.vat_amount
|
||||
FROM (SELECT l.partner_id, p.name, p.vat, SUM(CASE WHEN c.code ='49' THEN -l.tax_amount ELSE l.tax_amount END) as turnover
|
||||
FROM account_move_line l
|
||||
@@ -90,7 +90,7 @@ class partner_vat(osv.osv_memory):
|
||||
partners.append(id_client)
|
||||
|
||||
if not partners:
|
||||
raise osv.except_osv(_('insufficient data!'), _('No data found for the selected year.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No data found for the selected year.'))
|
||||
context.update({'partner_ids': partners, 'year': data['year'], 'limit_amount': data['limit_amount']})
|
||||
model_data_ids = obj_model_data.search(cr, uid, [('model','=','ir.ui.view'), ('name','=','view_vat_listing')])
|
||||
resource_id = obj_model_data.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
|
||||
|
||||
@@ -108,7 +108,7 @@ class partner_vat_intra(osv.osv_memory):
|
||||
# Get Company vat
|
||||
company_vat = data_company.partner_id.vat
|
||||
if not company_vat:
|
||||
raise osv.except_osv(_('insufficient data!'),_('No VAT number associated with your company.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'),_('No VAT number associated with your company.'))
|
||||
company_vat = company_vat.replace(' ','').upper()
|
||||
issued_by = company_vat[:2]
|
||||
|
||||
@@ -120,7 +120,7 @@ class partner_vat_intra(osv.osv_memory):
|
||||
|
||||
p_id_list = obj_partner.search(cr, uid, [('vat','!=',False)], context=context)
|
||||
if not p_id_list:
|
||||
raise osv.except_osv(_('Insufficient Data!'),_('No partner has a VAT number asociated with him.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'),_('No partner has a VAT number associated with him.'))
|
||||
|
||||
seq_declarantnum = obj_sequence.get(cr, uid, 'declarantnum')
|
||||
dnum = company_vat[2:] + seq_declarantnum[-4:]
|
||||
|
||||
@@ -103,7 +103,7 @@ class payroll_advice(osv.osv):
|
||||
slip_ids = payslip_pool.search(cr, uid, [('date_from', '<=', advice.date), ('date_to', '>=', advice.date), ('state', '=', 'done')], context=context)
|
||||
for slip in payslip_pool.browse(cr, uid, slip_ids, context=context):
|
||||
if not slip.employee_id.bank_account_id and not slip.employee_id.bank_account_id.acc_number:
|
||||
raise osv.except_osv(_('Error !'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
raise osv.except_osv(_('Error!'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
line_ids = payslip_line_pool.search(cr, uid, [ ('slip_id', '=', slip.id), ('code', '=', 'NET')], context=context)
|
||||
if line_ids:
|
||||
line = payslip_line_pool.browse(cr, uid, line_ids, context=context)[0]
|
||||
@@ -129,7 +129,7 @@ class payroll_advice(osv.osv):
|
||||
seq_obj = self.pool.get('ir.sequence')
|
||||
for advice in self.browse(cr, uid, ids, context=context):
|
||||
if not advice.line_ids:
|
||||
raise osv.except_osv(_('Error !'), _('You can not confirm Payment advice without advice lines.'))
|
||||
raise osv.except_osv(_('Error!'), _('You can not confirm Payment advice without advice lines.'))
|
||||
advice_date = datetime.strptime(advice.date, DATETIME_FORMAT)
|
||||
advice_year = advice_date.strftime('%m') + '-' + advice_date.strftime('%Y')
|
||||
number = seq_obj.get(cr, uid, 'payment.advice')
|
||||
@@ -183,7 +183,7 @@ class hr_payslip_run(osv.osv):
|
||||
users = self.pool.get('res.users').browse(cr, uid, [uid], context=context)
|
||||
for run in self.browse(cr, uid, ids, context=context):
|
||||
if run.available_advice:
|
||||
raise osv.except_osv(_('Error !'), _("Payment advice already exists for %s, 'Set to Draft' to create a new advice.") %(run.name))
|
||||
raise osv.except_osv(_('Error!'), _("Payment advice already exists for %s, 'Set to Draft' to create a new advice.") %(run.name))
|
||||
advice_data = {
|
||||
'batch_id': run.id,
|
||||
'company_id': users[0].company_id.id,
|
||||
@@ -201,7 +201,7 @@ class hr_payslip_run(osv.osv):
|
||||
|
||||
for slip in payslip_pool.browse(cr, uid, slip_ids, context=context):
|
||||
if not slip.employee_id.bank_account_id or not slip.employee_id.bank_account_id.acc_number:
|
||||
raise osv.except_osv(_('Error !'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
raise osv.except_osv(_('Error!'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
line_ids = payslip_line_pool.search(cr, uid, [('slip_id', '=', slip.id), ('code', '=', 'NET')], context=context)
|
||||
if line_ids:
|
||||
line = payslip_line_pool.browse(cr, uid, line_ids, context=context)[0]
|
||||
|
||||
@@ -64,7 +64,7 @@ class report_custom(report_int):
|
||||
self.obj.render()
|
||||
return (self.obj.pdf, 'pdf')
|
||||
except Exception:
|
||||
raise osv.except_osv(_('pdf not created !'), _('Please check if package pdftk is installed!'))
|
||||
raise osv.except_osv(_('PDF Not Created!'), _('Please check if package pdftk is installed!'))
|
||||
|
||||
report_custom('report.l10n_lu.tax.report.print')
|
||||
|
||||
|
||||
@@ -87,10 +87,12 @@ Main Features
|
||||
'static/src/js/mail.js',
|
||||
'static/src/js/mail_followers.js',
|
||||
'static/src/js/many2many_tags_email.js',
|
||||
'static/src/js/suggestions.js',
|
||||
],
|
||||
'qweb': [
|
||||
'static/src/xml/mail.xml',
|
||||
'static/src/xml/mail_followers.xml',
|
||||
'static/src/xml/suggestions.xml',
|
||||
],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -208,3 +208,12 @@ class mail_group(osv.Model):
|
||||
""" Wrapper because message_unsubscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_unsubscribe_users(cr, uid, ids, context=context)
|
||||
|
||||
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
|
||||
"""Show the suggestion of groups if display_groups_suggestions if the
|
||||
user perference allows it."""
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||
if not user.display_groups_suggestions:
|
||||
return []
|
||||
else:
|
||||
return super(mail_group, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)
|
||||
|
||||
@@ -240,21 +240,42 @@ class mail_thread(osv.AbstractModel):
|
||||
fol_obj.create(cr, SUPERUSER_ID, {'res_model': self._name, 'res_id': id, 'partner_id': partner_id})
|
||||
|
||||
def _search_followers(self, cr, uid, obj, name, args, context):
|
||||
"""Search function for message_follower_ids
|
||||
|
||||
Do not use with operator 'not in'. Use instead message_is_followers
|
||||
"""
|
||||
fol_obj = self.pool.get('mail.followers')
|
||||
res = []
|
||||
for field, operator, value in args:
|
||||
assert field == name
|
||||
# TOFIX make it work with not in
|
||||
assert operator != "not in", "Do not search message_follower_ids with 'not in'"
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('partner_id', operator, value)])
|
||||
res_ids = [fol.res_id for fol in fol_obj.browse(cr, SUPERUSER_ID, fol_ids)]
|
||||
res.append(('id', 'in', res_ids))
|
||||
return res
|
||||
|
||||
def _search_is_follower(self, cr, uid, obj, name, args, context):
|
||||
"""Search function for message_is_follower"""
|
||||
fol_obj = self.pool.get('mail.followers')
|
||||
res = []
|
||||
for field, operator, value in args:
|
||||
assert field == name
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
if (operator == '=' and value) or (operator == '!=' and not value): # is a follower
|
||||
res_ids = self.search(cr, uid, [('message_follower_ids', 'in', [partner_id])], context=context)
|
||||
else: # is not a follower or unknown domain
|
||||
mail_ids = self.search(cr, uid, [('message_follower_ids', 'in', [partner_id])], context=context)
|
||||
res_ids = self.search(cr, uid, [('id', 'not in', mail_ids)], context=context)
|
||||
res.append(('id', 'in', res_ids))
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'message_is_follower': fields.function(_get_followers,
|
||||
type='boolean', string='Is a Follower', multi='_get_followers,'),
|
||||
'message_is_follower': fields.function(_get_followers, type='boolean',
|
||||
fnct_search=_search_is_follower, string='Is a Follower', multi='_get_followers,'),
|
||||
'message_follower_ids': fields.function(_get_followers, fnct_inv=_set_followers,
|
||||
fnct_search=_search_followers, type='many2many',
|
||||
obj='res.partner', string='Followers', multi='_get_followers'),
|
||||
fnct_search=_search_followers, type='many2many',
|
||||
obj='res.partner', string='Followers', multi='_get_followers'),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id',
|
||||
domain=lambda self: [('model', '=', self._name)],
|
||||
auto_join=True,
|
||||
@@ -1454,4 +1475,33 @@ class mail_thread(osv.AbstractModel):
|
||||
''', (ids, self._name, partner_id))
|
||||
return True
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
#------------------------------------------------------
|
||||
# Thread suggestion
|
||||
#------------------------------------------------------
|
||||
|
||||
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
|
||||
"""Return a list of suggested threads, sorted by the numbers of followers"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
# TDE HACK: originally by MAT from portal/mail_mail.py but not working until the inheritance graph bug is not solved in trunk
|
||||
# TDE FIXME: relocate in portal when it won't be necessary to reload the hr.employee model in an additional bridge module
|
||||
if self.pool['res.groups']._all_columns.get('is_portal'):
|
||||
user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
if any(group.is_portal for group in user.groups_id):
|
||||
return []
|
||||
|
||||
threads = []
|
||||
if removed_suggested_threads is None:
|
||||
removed_suggested_threads = []
|
||||
|
||||
thread_ids = self.search(cr, uid, [('id', 'not in', removed_suggested_threads), ('message_is_follower', '=', False)], context=context)
|
||||
for thread in self.browse(cr, uid, thread_ids, context=context):
|
||||
data = {
|
||||
'id': thread.id,
|
||||
'popularity': len(thread.message_follower_ids),
|
||||
'name': thread.name,
|
||||
'image_small': thread.image_small
|
||||
}
|
||||
threads.append(data)
|
||||
return sorted(threads, key=lambda x: (x['popularity'], x['id']), reverse=True)[:3]
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
],
|
||||
'view_mailbox': True,
|
||||
'view_inbox': True,
|
||||
'read_action': 'read'
|
||||
'read_action': 'read',
|
||||
'show_compose_message': False
|
||||
}""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
@@ -52,21 +53,4 @@ class res_partner_mail(osv.Model):
|
||||
self._message_add_suggested_recipient(cr, uid, recipients, partner, partner=partner, reason=_('Partner Profile'))
|
||||
return recipients
|
||||
|
||||
def message_post(self, cr, uid, thread_id, **kwargs):
|
||||
""" Override related to res.partner. In case of email message, set it as
|
||||
private:
|
||||
- add the target partner in the message partner_ids
|
||||
- set thread_id as None, because this will trigger the 'private'
|
||||
aspect of the message (model=False, res_id=False)
|
||||
"""
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
if kwargs.get('type') == 'email':
|
||||
partner_ids = kwargs.get('partner_ids', [])
|
||||
if thread_id not in [command[1] for command in partner_ids]:
|
||||
partner_ids.append((4, thread_id))
|
||||
kwargs['partner_ids'] = partner_ids
|
||||
thread_id = False
|
||||
return super(res_partner_mail, self).message_post(cr, uid, thread_id, **kwargs)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
+20
-29
@@ -28,6 +28,7 @@ class res_users(osv.Model):
|
||||
- add a preference about sending emails about notifications
|
||||
- make a new user follow itself
|
||||
- add a welcome message
|
||||
- add suggestion preference
|
||||
"""
|
||||
_name = 'res.users'
|
||||
_inherit = ['res.users']
|
||||
@@ -37,10 +38,12 @@ class res_users(osv.Model):
|
||||
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
|
||||
help="Email address internally associated with this user. Incoming "\
|
||||
"emails will appear in the user's notifications."),
|
||||
'display_groups_suggestions': fields.boolean("Display Groups Suggestions"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'alias_domain': False, # always hide alias during creation
|
||||
'display_groups_suggestions': True,
|
||||
}
|
||||
|
||||
def __init__(self, pool, cr):
|
||||
@@ -51,10 +54,10 @@ class res_users(osv.Model):
|
||||
init_res = super(res_users, self).__init__(pool, cr)
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
|
||||
self.SELF_WRITEABLE_FIELDS.append('notification_email_send')
|
||||
self.SELF_WRITEABLE_FIELDS.extend(['notification_email_send', 'display_groups_suggestions'])
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
|
||||
self.SELF_READABLE_FIELDS.extend(['notification_email_send', 'alias_domain', 'alias_name'])
|
||||
self.SELF_READABLE_FIELDS.extend(['notification_email_send', 'alias_domain', 'alias_name', 'display_groups_suggestions'])
|
||||
return init_res
|
||||
|
||||
def _auto_init(self, cr, context=None):
|
||||
@@ -109,7 +112,7 @@ class res_users(osv.Model):
|
||||
def _message_post_get_pid(self, cr, uid, thread_id, context=None):
|
||||
assert thread_id, "res.users does not support posting global messages"
|
||||
if context and 'thread_model' in context:
|
||||
context['thread_model'] = 'res.partner'
|
||||
context['thread_model'] = 'res.users'
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
return self.browse(cr, SUPERUSER_ID, thread_id).partner_id.id
|
||||
@@ -118,44 +121,32 @@ class res_users(osv.Model):
|
||||
""" Redirect the posting of message on res.users to the related partner.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
partner_ids = kwargs.get('partner_ids', [])
|
||||
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
|
||||
return self.pool.get('res.partner').message_post(cr, uid, partner_id, context=context, **kwargs)
|
||||
if partner_id not in [command[1] for command in partner_ids]:
|
||||
partner_ids.append(partner_id)
|
||||
kwargs['partner_ids'] = partner_ids
|
||||
return self.pool.get('mail.thread').message_post(cr, uid, False, **kwargs)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
|
||||
for id in ids:
|
||||
partner_id = self.browse(cr, SUPERUSER_ID, id).partner_id.id
|
||||
self.pool.get('res.partner').message_update(cr, uid, [partner_id], msg_dict, update_vals=update_vals, context=context)
|
||||
return True
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
||||
for id in ids:
|
||||
partner_id = self.browse(cr, SUPERUSER_ID, id).partner_id.id
|
||||
self.pool.get('res.partner').message_subscribe(cr, uid, [partner_id], partner_ids, subtype_ids=subtype_ids, context=context)
|
||||
return True
|
||||
|
||||
def message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None):
|
||||
return self.pool.get('res.partner').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
|
||||
return self.pool.get('mail.thread').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
|
||||
|
||||
def message_get_suggested_recipients(self, cr, uid, ids, context=None):
|
||||
partner_ids = []
|
||||
for id in ids:
|
||||
partner_ids.append(self.browse(cr, SUPERUSER_ID, id).partner_id.id)
|
||||
return self.pool.get('res.partner').message_get_suggested_recipients(cr, uid, partner_ids, context=context)
|
||||
return dict.fromkeys(ids, list())
|
||||
|
||||
#------------------------------------------------------
|
||||
# Compatibility methods: do not use
|
||||
# TDE TODO: remove me in 8.0
|
||||
#------------------------------------------------------
|
||||
|
||||
def message_post_user_api(self, cr, uid, thread_id, context=None, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related partner.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
|
||||
return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, context=context, **kwargs)
|
||||
|
||||
def message_create_partners_from_emails(self, cr, uid, emails, context=None):
|
||||
return self.pool.get('res.partner').message_create_partners_from_emails(cr, uid, emails, context=context)
|
||||
def stop_showing_groups_suggestions(self, cr, uid, user_id, context=None):
|
||||
"""Update display_groups_suggestions value to False"""
|
||||
if context is None:
|
||||
context = {}
|
||||
self.write(cr, uid, user_id, {"display_groups_suggestions": False}, context)
|
||||
|
||||
|
||||
class res_users_mail_group(osv.Model):
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
<field name="alias_domain" invisible="1"/>
|
||||
<field name="alias_id" readonly="1" required="0" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
|
||||
</field>
|
||||
<group string="Email preferences" position="after">
|
||||
<group name="misc" string="Miscellaneous"
|
||||
groups="base.group_no_one">
|
||||
<field name="display_groups_suggestions"/>
|
||||
</group>
|
||||
</group>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0px;
|
||||
margin: 0px
|
||||
margin: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
@@ -665,8 +665,72 @@
|
||||
.openerp .oe_mail_wall .oe_mail{
|
||||
margin: 16px;
|
||||
width: 600px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_view_nocontent > p {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* ------------- WALL SIDEBAR ------------- */
|
||||
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside {
|
||||
margin: 16px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 260px;
|
||||
}
|
||||
.openerp .oe_mail_wall_aside .oe_sidebar_suggestion {
|
||||
background-color: #EDEDF6;
|
||||
border-radius: 2px;
|
||||
padding-top: 1px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_title h2 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
padding: 0px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item {
|
||||
border-radius: 2px;
|
||||
width: 100%;
|
||||
margin-left: 10px;
|
||||
min-height: 67px; /* image_small 66x66px */
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_image {
|
||||
float: left;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_image img {
|
||||
border-radius: 2px;
|
||||
border: solid 1px rgba(0,0,0,0.03);
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content button {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content a.oe_suggestion_item_name {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 90%;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_title a.oe_suggestion_remove {
|
||||
line-height: 15px;
|
||||
margin-top: -2px;
|
||||
float: right;
|
||||
visibility: hidden;
|
||||
margin-right: 7px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content a.oe_suggestion_remove_item {
|
||||
line-height: 15px;
|
||||
margin-top: -2px;
|
||||
float: right;
|
||||
visibility: hidden;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_title:hover a.oe_suggestion_remove,
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items:hover a.oe_suggestion_remove_item {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
-moz-border-radius: 3px;
|
||||
border-collapse: separate;
|
||||
-webkit-border-radius: 3px;
|
||||
-o-border-radius: 3px;
|
||||
-ms-border-radius: 3px;
|
||||
|
||||
@@ -4,8 +4,8 @@ openerp.mail = function (session) {
|
||||
|
||||
var mail = session.mail = {};
|
||||
|
||||
openerp_mail_followers(session, mail); // import mail_followers.js
|
||||
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js
|
||||
openerp_mail_followers(session, mail); // import mail_followers.js
|
||||
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
@@ -237,8 +237,15 @@ openerp.mail = function (session) {
|
||||
|
||||
this.format_data();
|
||||
|
||||
// update record_name: Partner profile
|
||||
if (this.model == 'res.partner') {
|
||||
this.record_name = 'Partner Profile of ' + this.record_name;
|
||||
}
|
||||
else if (this.model == 'hr.employee') {
|
||||
this.record_name = 'News from ' + this.record_name;
|
||||
}
|
||||
// record options and data
|
||||
this.show_record_name = this.options.show_record_name && this.record_name && !this.thread_level && this.model != 'res.partner';
|
||||
this.show_record_name = this.options.show_record_name && this.record_name && !this.thread_level;
|
||||
this.options.show_read = false;
|
||||
this.options.show_unread = false;
|
||||
if (this.options.show_read_unread_button) {
|
||||
@@ -257,6 +264,7 @@ openerp.mail = function (session) {
|
||||
|
||||
/* Convert date, timerelative and avatar in displayable data. */
|
||||
format_data: function () {
|
||||
|
||||
//formating and add some fields for render
|
||||
this.date = this.date ? session.web.str_to_datetime(this.date) : false;
|
||||
if (this.date && new Date().getTime()-this.date.getTime() < 7*24*60*60*1000) {
|
||||
@@ -745,7 +753,7 @@ openerp.mail = function (session) {
|
||||
}
|
||||
// create object and attach to the thread object
|
||||
thread.message_fetch([["id", "=", message_id]], false, [message_id], function (arg, data) {
|
||||
var message = thread.create_message_object( data[0] );
|
||||
var message = thread.create_message_object( data.slice(-1)[0] );
|
||||
// insert the message on dom
|
||||
thread.insert_message( message, root ? undefined : self.$el, root );
|
||||
});
|
||||
@@ -1840,6 +1848,19 @@ openerp.mail = function (session) {
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* Aside Widget
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* This widget handles the display of a sidebar on the Wall. Its main use
|
||||
* is to display group and employees suggestion (if hr is installed).
|
||||
*/
|
||||
mail.WallSidebar = session.web.Widget.extend({
|
||||
template: 'mail.wall.sidebar',
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* Wall Widget
|
||||
@@ -1901,6 +1922,9 @@ openerp.mail = function (session) {
|
||||
if (! this.searchview.has_defaults) {
|
||||
this.message_render();
|
||||
}
|
||||
// render sidebar
|
||||
var wall_sidebar = new mail.WallSidebar(this);
|
||||
wall_sidebar.appendTo(this.$el.find('.oe_mail_wall_aside'));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -2018,4 +2042,16 @@ openerp.mail = function (session) {
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* Sub-widgets loading
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* Load here widgets that could depend on widgets defined in mail.js
|
||||
*/
|
||||
|
||||
openerp.mail.suggestions(session, mail); // import suggestion.js (suggestion widget)
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
openerp.mail.suggestions = function(session, mail) {
|
||||
var _t = session.web._t;
|
||||
var QWeb = session.web.qweb;
|
||||
|
||||
var suggestions = session.suggestions = {};
|
||||
var removed_suggested_group = session.suggestions.removed_suggested_group = [];
|
||||
|
||||
suggestions.Groups = session.web.Widget.extend({
|
||||
events: {
|
||||
'click .oe_suggestion_remove.oe_suggestion_group': 'stop_group_suggestion',
|
||||
'click .oe_suggestion_remove_item.oe_suggestion_group': 'remove_group_suggestion',
|
||||
'click .oe_suggestion_join': 'join_group',
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.mail_group = new session.web.DataSetSearch(this, 'mail.group');
|
||||
this.res_users = new session.web.DataSetSearch(this, 'res.users');
|
||||
this.groups = [];
|
||||
},
|
||||
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
return this.fetch_suggested_groups();
|
||||
},
|
||||
|
||||
fetch_suggested_groups: function () {
|
||||
var self = this;
|
||||
var group = self.mail_group.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_group}).then(function (res) {
|
||||
_(res).each(function (result) {
|
||||
result['image']=self.session.url('/web/binary/image', {model: 'mail.group', field: 'image_small', id: result.id});
|
||||
});
|
||||
self.groups = res;
|
||||
});
|
||||
return $.when(group).then(this.proxy('display_suggested_groups'));
|
||||
},
|
||||
|
||||
display_suggested_groups: function () {
|
||||
var suggested_groups = this.$('.oe_sidebar_suggestion.oe_suggestion_group');
|
||||
if (suggested_groups) {
|
||||
suggested_groups.empty();
|
||||
}
|
||||
if (this.groups.length === 0) {
|
||||
return this.$el.empty();
|
||||
}
|
||||
return this.$el.empty().html(QWeb.render('mail.suggestions.groups', {'widget': this}));
|
||||
},
|
||||
|
||||
join_group: function (event) {
|
||||
var self = this;
|
||||
return this.mail_group.call('message_subscribe_users', [[$(event.currentTarget).attr('id')],[this.session.uid]]).then(function(res) {
|
||||
self.fetch_suggested_groups();
|
||||
});
|
||||
},
|
||||
|
||||
remove_group_suggestion: function (event) {
|
||||
removed_suggested_group.push($(event.currentTarget).attr('id'));
|
||||
return this.fetch_suggested_groups();
|
||||
},
|
||||
|
||||
stop_group_suggestion: function (event) {
|
||||
var self = this;
|
||||
return this.res_users.call('stop_showing_groups_suggestions', [this.session.uid]).then(function(res) {
|
||||
self.$(".oe_sidebar_suggestion.oe_suggestion_group").hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
session.mail.WallSidebar.include({
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
var sug_groups = new suggestions.Groups(this);
|
||||
return sug_groups.appendTo(this.$('.oe_suggestions_groups'));
|
||||
},
|
||||
});
|
||||
|
||||
};
|
||||
@@ -121,9 +121,11 @@
|
||||
To:
|
||||
<t t-if="!widget.is_private">
|
||||
<span class="oe_all_follower">
|
||||
Followers of
|
||||
<t t-if="widget.parent_thread.parent_message.record_name" t-raw="'"' + widget.parent_thread.parent_message.record_name + '"'"/>
|
||||
<t t-if="!widget.parent_thread.parent_message.record_name">this document</t>
|
||||
<t t-if="widget.parent_thread.parent_message.record_name" t-raw="'"' + widget.parent_thread.parent_message.record_name + '"'">
|
||||
Followers of <t t-raw="'"' + widget.parent_thread.parent_message.record_name + '"'"/>
|
||||
</t>
|
||||
<t t-if="!widget.parent_thread.parent_message.record_name and widget.options.view_inbox">My Followers</t>
|
||||
<t t-if="!widget.parent_thread.parent_message.record_name and !widget.options.view_inbox">Followers of this document</t>
|
||||
</span>
|
||||
</t>
|
||||
<t t-if="!widget.is_private and (widget.partner_ids.length or (widget.author_id and widget.author_id[0]))"> and </t>
|
||||
@@ -197,8 +199,16 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="oe_mail-placeholder"></div>
|
||||
<aside class="oe_mail_wall_aside"></aside>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
Empty template that holds the sidebar of the Wall
|
||||
-->
|
||||
<t t-name="mail.wall.sidebar">
|
||||
<div class="oe_mail_wall_sidebar"></div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
display message on the wall when there are no message
|
||||
-->
|
||||
@@ -339,7 +349,4 @@
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<!-- mail.thread.message.star
|
||||
Template used to display stared/unstared message in a mail.message
|
||||
-->
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<template>
|
||||
|
||||
<!-- Groups placeholder in sidebar -->
|
||||
<t t-extend="mail.wall.sidebar">
|
||||
<t t-jquery=".oe_mail_wall_sidebar" t-operation="append">
|
||||
<div class="oe_suggestions_groups"></div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
|
||||
<!-- Suggested groups -->
|
||||
<div t-name="mail.suggestions.groups" class="oe_sidebar_suggestion oe_suggestion_group">
|
||||
<div class="oe_suggest_title">
|
||||
<a class="oe_suggestion_remove oe_suggestion_group oe_e">X</a>
|
||||
<h2>Suggested Groups</h2>
|
||||
</div>
|
||||
<div class="oe_suggest_items">
|
||||
<t t-foreach="widget.groups" t-as="result">
|
||||
<div class="oe_suggested_item">
|
||||
<div class="oe_suggested_item_image">
|
||||
<a t-attf-href="#model=mail.group&id=#{result.id}">
|
||||
<img t-attf-src="{result.image}" t-attf-alt="{result.name}"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="oe_suggested_item_content">
|
||||
<a class="oe_suggestion_item_name" t-attf-href="#model=mail.group&id=#{result.id}"><t t-esc="result.name"/></a>
|
||||
<a class="oe_suggestion_remove_item oe_suggestion_group oe_e" t-attf-id="{result.id}">X</a>
|
||||
<br/>
|
||||
<button t-att-id="result.id" class="oe_suggestion_join">Join Group</button>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
@@ -440,7 +440,7 @@
|
||||
<field name="model">mrp.bom</field>
|
||||
<field name="field_parent">child_complete_ids</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Bill of Materials" colors="blue:method">
|
||||
<tree string="Bill of Materials">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="product_id"/>
|
||||
@@ -448,7 +448,6 @@
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="code"/>
|
||||
<field name="type"/>
|
||||
<field name="method"/>
|
||||
<field name="routing_id" groups="mrp.group_mrp_routings"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
@@ -460,19 +459,18 @@
|
||||
<field name="model">mrp.bom</field>
|
||||
<field name="field_parent">child_complete_ids</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="BoM Structure" colors="blue:method">
|
||||
<tree string="BoM Structure">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="name" groups="base.group_no_one"/>
|
||||
<field name="code"/>
|
||||
<field name="product_id"/>
|
||||
<field name="bom_id"/>
|
||||
<field name="bom_id" groups="product.group_mrp_properties"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom" groups="product.group_uom"/>
|
||||
<field name="type"/>
|
||||
<field name="method"/>
|
||||
<field name="routing_id" groups="mrp.group_mrp_routings"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
<field name="date_start" groups="product.group_mrp_properties"/>
|
||||
<field name="date_stop" groups="product.group_mrp_properties"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -128,7 +128,7 @@ class mrp_production_workcenter_line(osv.osv):
|
||||
elif prod_obj.state =='in_production':
|
||||
return
|
||||
else:
|
||||
raise osv.except_osv(_('Error!'),_('Manufacturing order cannot start in state "%s"!') % (prod_obj.state,))
|
||||
raise osv.except_osv(_('Error!'),_('Manufacturing order cannot be started in state "%s"!') % (prod_obj.state,))
|
||||
else:
|
||||
oper_ids = self.search(cr,uid,[('production_id','=',prod_obj.id)])
|
||||
obj = self.browse(cr,uid,oper_ids)
|
||||
@@ -443,7 +443,7 @@ class mrp_operations_operation(osv.osv):
|
||||
|
||||
if not oper_objs:
|
||||
if code.start_stop!='start':
|
||||
raise osv.except_osv(_('Sorry!'),_('Operation is not started yet !'))
|
||||
raise osv.except_osv(_('Sorry!'),_('Operation is not started yet!'))
|
||||
return False
|
||||
else:
|
||||
for oper in oper_objs:
|
||||
|
||||
@@ -365,7 +365,7 @@ class mrp_repair(osv.osv):
|
||||
if repair.state in ('draft','cancel') or repair.invoice_id:
|
||||
continue
|
||||
if not (repair.partner_id.id and repair.partner_invoice_id.id):
|
||||
raise osv.except_osv(_('No partner !'),_('You have to select a Partner Invoice Address in the repair form !'))
|
||||
raise osv.except_osv(_('No partner!'),_('You have to select a Partner Invoice Address in the repair form!'))
|
||||
comment = repair.quotation_notes
|
||||
if (repair.invoice_method != 'none'):
|
||||
if group and repair.partner_invoice_id.id in invoices_group:
|
||||
@@ -582,7 +582,7 @@ class ProductChangeMixin(object):
|
||||
result['product_uom'] = product_obj.uom_id and product_obj.uom_id.id or False
|
||||
if not pricelist:
|
||||
warning = {
|
||||
'title':'No Pricelist !',
|
||||
'title':'No Pricelist!',
|
||||
'message':
|
||||
'You have to select a pricelist in the Repair form !\n'
|
||||
'Please set one before choosing a product.'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -407,7 +407,7 @@ class pos_session(osv.osv):
|
||||
# The pos manager can close statements with maximums.
|
||||
if not self.pool.get('ir.model.access').check_groups(cr, uid, "point_of_sale.group_pos_manager"):
|
||||
raise osv.except_osv( _('Error!'),
|
||||
_("Your ending balance is too different from the theorical cash closing (%.2f), the maximum allowed is: %.2f. You can contact your manager to force it.") % (st.difference, st.journal_id.amount_authorized_diff))
|
||||
_("Your ending balance is too different from the theoretical cash closing (%.2f), the maximum allowed is: %.2f. You can contact your manager to force it.") % (st.difference, st.journal_id.amount_authorized_diff))
|
||||
if (st.journal_id.type not in ['bank', 'cash']):
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_("The type of the journal for your payment method should be bank or cash "))
|
||||
@@ -545,7 +545,7 @@ class pos_order(osv.osv):
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
for rec in self.browse(cr, uid, ids, context=context):
|
||||
if rec.state not in ('draft','cancel'):
|
||||
raise osv.except_osv(_('Unable to Delete !'), _('In order to delete a sale, it must be new or cancelled.'))
|
||||
raise osv.except_osv(_('Unable to Delete!'), _('In order to delete a sale, it must be new or cancelled.'))
|
||||
return super(pos_order, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, part=False, context=None):
|
||||
@@ -1163,7 +1163,7 @@ class pos_order_line(osv.osv):
|
||||
if not product_id:
|
||||
return {}
|
||||
if not pricelist:
|
||||
raise osv.except_osv(_('No Pricelist !'),
|
||||
raise osv.except_osv(_('No Pricelist!'),
|
||||
_('You have to select a pricelist in the sale form !\n' \
|
||||
'Please set one before choosing a product.'))
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class pos_open_statement(osv.osv_memory):
|
||||
st_ids = []
|
||||
j_ids = journal_obj.search(cr, uid, [('journal_user','=',1)], context=context)
|
||||
if not j_ids:
|
||||
raise osv.except_osv(_('No Cash Register Defined !'), _('You have to define which payment method must be available in the point of sale by reusing existing bank and cash through "Accounting / Configuration / Journals / Journals". Select a journal and check the field "PoS Payment Method" from the "Point of Sale" tab. You can also create new payment methods directly from menu "PoS Backend / Configuration / Payment Methods".'))
|
||||
raise osv.except_osv(_('No Cash Register Defined!'), _('You have to define which payment method must be available in the point of sale by reusing existing bank and cash through "Accounting / Configuration / Journals / Journals". Select a journal and check the field "PoS Payment Method" from the "Point of Sale" tab. You can also create new payment methods directly from menu "PoS Backend / Configuration / Payment Methods".'))
|
||||
|
||||
for journal in journal_obj.browse(cr, uid, j_ids, context=context):
|
||||
ids = statement_obj.search(cr, uid, [('state', '!=', 'confirm'), ('user_id', '=', uid), ('journal_id', '=', journal.id)], context=context)
|
||||
|
||||
@@ -223,7 +223,7 @@ class wizard_user(osv.osv_memory):
|
||||
this_context = context
|
||||
this_user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context)
|
||||
if not this_user.email:
|
||||
raise osv.except_osv(_('Email required'),
|
||||
raise osv.except_osv(_('Email Required'),
|
||||
_('You must have an email address in your User Preferences to send emails.'))
|
||||
|
||||
# determine subject and body in the portal user's language
|
||||
|
||||
@@ -307,7 +307,7 @@ class procurement_order(osv.osv):
|
||||
move_obj = self.pool.get('stock.move')
|
||||
for procurement in self.browse(cr, uid, ids, context=context):
|
||||
if procurement.product_qty <= 0.00:
|
||||
raise osv.except_osv(_('Data Insufficient !'),
|
||||
raise osv.except_osv(_('Data Insufficient!'),
|
||||
_('Please check the quantity in procurement order(s) for the product "%s", it should not be 0 or less!' % procurement.product_id.name))
|
||||
if procurement.product_id.type in ('product', 'consu'):
|
||||
if not procurement.move_id:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Resource: product.uom.categ
|
||||
-->
|
||||
<record id="product_category_all" model="product.category">
|
||||
<field name="name">All products</field>
|
||||
<field name="name">All</field>
|
||||
</record>
|
||||
<record id="product_category_1" model="product.category">
|
||||
<field name="parent_id" ref="product_category_all"/>
|
||||
|
||||
@@ -450,7 +450,7 @@ class project(osv.osv):
|
||||
|
||||
for project in projects:
|
||||
if (not project.members) and force_members:
|
||||
raise osv.except_osv(_('Warning!'),_("You must assign members on the project '%s' !") % (project.name,))
|
||||
raise osv.except_osv(_('Warning!'),_("You must assign members on the project '%s'!") % (project.name,))
|
||||
|
||||
resource_pool = self.pool.get('resource.resource')
|
||||
|
||||
@@ -956,7 +956,7 @@ class task(base_stage, osv.osv):
|
||||
if task.child_ids:
|
||||
for child in task.child_ids:
|
||||
if child.state in ['draft', 'open', 'pending']:
|
||||
raise osv.except_osv(_("Warning !"), _("Child task still open.\nPlease cancel or complete child task first."))
|
||||
raise osv.except_osv(_("Warning!"), _("Child task still open.\nPlease cancel or complete child task first."))
|
||||
return True
|
||||
|
||||
def action_close(self, cr, uid, ids, context=None):
|
||||
|
||||
@@ -49,7 +49,7 @@ class project_timebox_empty(osv.osv_memory):
|
||||
|
||||
ids = obj_tb.search(cr, uid, [], context=context)
|
||||
if not len(ids):
|
||||
raise osv.except_osv(_('Error!'), _('No timebox child of this one !'))
|
||||
raise osv.except_osv(_('Error!'), _('No timebox child of this one!'))
|
||||
tids = obj_task.search(cr, uid, [('timebox_id', '=', context['active_id'])])
|
||||
for task in obj_task.browse(cr, uid, tids, context):
|
||||
if (task.state in ('cancel','done')) or (task.user_id.id <> uid):
|
||||
|
||||
@@ -79,22 +79,22 @@ class project_work(osv.osv):
|
||||
emp_id = emp_obj.search(cr, uid, [('user_id', '=', user_id)])
|
||||
if not emp_id:
|
||||
user_name = self.pool.get('res.users').read(cr, uid, [user_id], ['name'])[0]['name']
|
||||
raise osv.except_osv(_('Bad Configuration !'),
|
||||
raise osv.except_osv(_('Bad Configuration!'),
|
||||
_('Please define employee for user "%s". You must create one.')% (user_name,))
|
||||
emp = emp_obj.browse(cr, uid, emp_id[0])
|
||||
if not emp.product_id:
|
||||
raise osv.except_osv(_('Bad Configuration !'),
|
||||
raise osv.except_osv(_('Bad Configuration!'),
|
||||
_('Please define product and product category property account on the related employee.\nFill in the HR Settings tab of the employee form.'))
|
||||
|
||||
if not emp.journal_id:
|
||||
raise osv.except_osv(_('Bad Configuration !'),
|
||||
raise osv.except_osv(_('Bad Configuration!'),
|
||||
_('Please define journal on the related employee.\nFill in the timesheet tab of the employee form.'))
|
||||
|
||||
acc_id = emp.product_id.property_account_expense.id
|
||||
if not acc_id:
|
||||
acc_id = emp.product_id.categ_id.property_account_expense_categ.id
|
||||
if not acc_id:
|
||||
raise osv.except_osv(_('Bad Configuration !'),
|
||||
raise osv.except_osv(_('Bad Configuration!'),
|
||||
_('Please define product and product category property account on the related employee.\nFill in the timesheet tab of the employee form.'))
|
||||
|
||||
res['product_id'] = emp.product_id.id
|
||||
@@ -286,7 +286,7 @@ class account_analytic_line(osv.osv):
|
||||
st = acc.to_invoice.id
|
||||
res['value']['to_invoice'] = st or False
|
||||
if acc.state == 'close' or acc.state == 'cancelled':
|
||||
raise osv.except_osv(_('Invalid Analytic Account !'), _('You cannot select a Analytic Account which is in Close or Cancelled state.'))
|
||||
raise osv.except_osv(_('Invalid Analytic Account!'), _('You cannot select a Analytic Account which is in Close or Cancelled state.'))
|
||||
return res
|
||||
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ class purchase_order(osv.osv):
|
||||
'warehouse_id': fields.many2one('stock.warehouse', 'Destination Warehouse'),
|
||||
'location_id': fields.many2one('stock.location', 'Destination', required=True, domain=[('usage','<>','view')], states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]} ),
|
||||
'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', required=True, states={'confirmed':[('readonly',True)], 'approved':[('readonly',True)],'done':[('readonly',True)]}, help="The pricelist sets the currency used for this purchase order. It also computes the supplier price for the selected products/quantities."),
|
||||
'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", string="Currency",readonly=True, required=True),
|
||||
'currency_id': fields.many2one('res.currency','Currency', readonly=True, required=True,states={'draft': [('readonly', False)],'sent': [('readonly', False)]}),
|
||||
'state': fields.selection(STATE_SELECTION, 'Status', readonly=True, help="The status of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' status. Then the order has to be confirmed by the user, the status switch to 'Confirmed'. Then the supplier must confirm the order to change the status to 'Approved'. When the purchase order is paid and received, the status becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the status becomes in exception.", select=True),
|
||||
'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'approved':[('readonly',True)],'done':[('readonly',True)]}),
|
||||
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
|
||||
@@ -237,6 +237,7 @@ class purchase_order(osv.osv):
|
||||
'pricelist_id': lambda self, cr, uid, context: context.get('partner_id', False) and self.pool.get('res.partner').browse(cr, uid, context['partner_id']).property_product_pricelist_purchase.id,
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'purchase.order', context=c),
|
||||
'journal_id': _get_journal,
|
||||
'currency_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
|
||||
}
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique(name, company_id)', 'Order Reference must be unique per Company!'),
|
||||
@@ -544,7 +545,7 @@ class purchase_order(osv.osv):
|
||||
'account_id': pay_acc_id,
|
||||
'type': 'in_invoice',
|
||||
'partner_id': order.partner_id.id,
|
||||
'currency_id': order.pricelist_id.currency_id.id,
|
||||
'currency_id': order.currency_id.id,
|
||||
'journal_id': len(journal_ids) and journal_ids[0] or False,
|
||||
'invoice_line': [(6, 0, inv_lines)],
|
||||
'origin': order.name,
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)" context="{'search_default_supplier':1,'default_supplier':1,'default_customer':0}" domain="[('supplier','=',True)]"/>
|
||||
<field name="partner_ref"/>
|
||||
<field domain="[('type','=','purchase')]" name="pricelist_id" groups="product.group_purchase_pricelist" on_change="onchange_pricelist(pricelist_id, context)"/>
|
||||
<field name="currency_id" invisible='1'/>
|
||||
<field name="currency_id" groups="base.group_multi_currency"/>
|
||||
<field name="journal_id" invisible='1'/>
|
||||
</group>
|
||||
<group>
|
||||
|
||||
@@ -70,7 +70,7 @@ class stock_picking(osv.osv):
|
||||
|
||||
def get_currency_id(self, cursor, user, picking):
|
||||
if picking.purchase_id:
|
||||
return picking.purchase_id.pricelist_id.currency_id.id
|
||||
return picking.purchase_id.currency_id.id
|
||||
else:
|
||||
return super(stock_picking, self).get_currency_id(cursor, user, picking)
|
||||
|
||||
@@ -129,7 +129,7 @@ class stock_partial_picking(osv.osv_memory):
|
||||
def _product_cost_for_average_update(self, cr, uid, move):
|
||||
if move.picking_id.purchase_id:
|
||||
return {'cost': move.purchase_line_id.price_unit,
|
||||
'currency': move.picking_id.purchase_id.pricelist_id.currency_id.id}
|
||||
'currency': move.picking_id.purchase_id.currency_id.id}
|
||||
return super(stock_partial_picking, self)._product_cost_for_average_update(cr, uid, move)
|
||||
|
||||
# Redefinition of the new field in order to update the model stock.picking.in in the orm
|
||||
|
||||
@@ -83,7 +83,7 @@ class purchase_line_invoice(osv.osv_memory):
|
||||
'account_id': a,
|
||||
'partner_id': partner.id,
|
||||
'invoice_line': [(6,0,lines_ids)],
|
||||
'currency_id' : orders[0].pricelist_id.currency_id.id,
|
||||
'currency_id' : orders[0].currency_id.id,
|
||||
'comment': multiple_order_invoice_notes(orders),
|
||||
'payment_term': orders[0].payment_term_id.id,
|
||||
'fiscal_position': partner.property_account_position.id
|
||||
|
||||
+2
-2
@@ -273,7 +273,7 @@ class sale_order(osv.osv):
|
||||
if s['state'] in ['draft', 'cancel']:
|
||||
unlink_ids.append(s['id'])
|
||||
else:
|
||||
raise osv.except_osv(_('Invalid Action!'), _('In order to delete a confirmed sales order, you must cancel it before !'))
|
||||
raise osv.except_osv(_('Invalid Action!'), _('In order to delete a confirmed sales order, you must cancel it before!'))
|
||||
|
||||
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
|
||||
|
||||
@@ -870,7 +870,7 @@ class sale_order_line(osv.osv):
|
||||
context = context or {}
|
||||
lang = lang or context.get('lang',False)
|
||||
if not partner_id:
|
||||
raise osv.except_osv(_('No Customer Defined !'), _('Before choosing a product,\n select a customer in the sales form.'))
|
||||
raise osv.except_osv(_('No Customer Defined!'), _('Before choosing a product,\n select a customer in the sales form.'))
|
||||
warning = {}
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
|
||||
@@ -87,7 +87,7 @@ class crm_make_sale(osv.osv_memory):
|
||||
['default', 'invoice', 'delivery', 'contact'])
|
||||
pricelist = partner.property_product_pricelist.id
|
||||
if False in partner_addr.values():
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No addresse(s) defined for this customer.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No address(es) defined for this customer.'))
|
||||
|
||||
vals = {
|
||||
'origin': _('Opportunity: %s') % str(case.id),
|
||||
|
||||
@@ -833,7 +833,7 @@ class share_wizard(osv.TransientModel):
|
||||
notification_obj = self.pool.get('mail.notification')
|
||||
user = self.pool.get('res.users').browse(cr, UID_ROOT, uid)
|
||||
if not user.email:
|
||||
raise osv.except_osv(_('Email required'), _('The current user must have an email address configured in User Preferences to be able to send outgoing emails.'))
|
||||
raise osv.except_osv(_('Email Required'), _('The current user must have an email address configured in User Preferences to be able to send outgoing emails.'))
|
||||
|
||||
# TODO: also send an HTML version of this mail
|
||||
for result_line in wizard_data.result_line_ids:
|
||||
@@ -864,7 +864,7 @@ class share_wizard(osv.TransientModel):
|
||||
mail_mail = self.pool.get('mail.mail')
|
||||
user = self.pool.get('res.users').browse(cr, UID_ROOT, uid)
|
||||
if not user.email:
|
||||
raise osv.except_osv(_('Email required'), _('The current user must have an email address configured in User Preferences to be able to send outgoing emails.'))
|
||||
raise osv.except_osv(_('Email Required'), _('The current user must have an email address configured in User Preferences to be able to send outgoing emails.'))
|
||||
|
||||
# TODO: also send an HTML version of this mail
|
||||
mail_ids = []
|
||||
|
||||
@@ -1110,7 +1110,7 @@ class stock_picking(osv.osv):
|
||||
if isinstance(partner, int):
|
||||
partner = partner_obj.browse(cr, uid, [partner], context=context)[0]
|
||||
if not partner:
|
||||
raise osv.except_osv(_('Error, no partner !'),
|
||||
raise osv.except_osv(_('Error, no partner!'),
|
||||
_('Please put a partner on the picking list if you want to generate invoice.'))
|
||||
|
||||
if not inv_type:
|
||||
@@ -1764,7 +1764,7 @@ class stock_move(osv.osv):
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
if move.state == 'done':
|
||||
if frozen_fields.intersection(vals):
|
||||
raise osv.except_osv(_('Operation forbidden !'),
|
||||
raise osv.except_osv(_('Operation Forbidden!'),
|
||||
_('Quantities, Units of Measure, Products and Locations cannot be modified on stock moves that have already been processed (except by the Administrator).'))
|
||||
return super(stock_move, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ class stock_partial_picking(osv.osv_memory):
|
||||
|
||||
if line_uom.factor and line_uom.factor <> 0:
|
||||
if float_compare(qty_in_line_uom, wizard_line.quantity, precision_rounding=line_uom.rounding) != 0:
|
||||
raise osv.except_osv(_('Warning!'), _('The unit of measure rounding does not allow you to ship "%s %s", only roundings of "%s %s" is accepted by the Unit of Measure.') % (wizard_line.quantity, line_uom.name, line_uom.rounding, line_uom.name))
|
||||
raise osv.except_osv(_('Warning!'), _('The unit of measure rounding does not allow you to ship "%s %s", only rounding of "%s %s" is accepted by the Unit of Measure.') % (wizard_line.quantity, line_uom.name, line_uom.rounding, line_uom.name))
|
||||
if move_id:
|
||||
#Check rounding Quantity.ex.
|
||||
#picking: 1kg, uom kg rounding = 0.01 (rounding to 10g),
|
||||
@@ -189,7 +189,7 @@ class stock_partial_picking(osv.osv_memory):
|
||||
qty_in_initial_uom = uom_obj._compute_qty(cr, uid, line_uom.id, wizard_line.quantity, initial_uom.id)
|
||||
without_rounding_qty = (wizard_line.quantity / line_uom.factor) * initial_uom.factor
|
||||
if float_compare(qty_in_initial_uom, without_rounding_qty, precision_rounding=initial_uom.rounding) != 0:
|
||||
raise osv.except_osv(_('Warning!'), _('The rounding of the initial uom does not allow you to ship "%s %s", as it would let a quantity of "%s %s" to ship and only roundings of "%s %s" is accepted by the uom.') % (wizard_line.quantity, line_uom.name, wizard_line.move_id.product_qty - without_rounding_qty, initial_uom.name, initial_uom.rounding, initial_uom.name))
|
||||
raise osv.except_osv(_('Warning!'), _('The rounding of the initial uom does not allow you to ship "%s %s", as it would let a quantity of "%s %s" to ship and only rounding of "%s %s" is accepted by the uom.') % (wizard_line.quantity, line_uom.name, wizard_line.move_id.product_qty - without_rounding_qty, initial_uom.name, initial_uom.rounding, initial_uom.name))
|
||||
else:
|
||||
seq_obj_name = 'stock.picking.' + picking_type
|
||||
move_id = stock_move.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name),
|
||||
|
||||
@@ -115,7 +115,7 @@ class subscription_subscription(osv.osv):
|
||||
id = int(id)
|
||||
model = self.pool[model_name]
|
||||
except:
|
||||
raise osv.except_osv(_('Wrong Source Document !'), _('Please provide another source document.\nThis one does not exist !'))
|
||||
raise osv.except_osv(_('Wrong Source Document!'), _('Please provide another source document.\nThis one does not exist!'))
|
||||
|
||||
default = {'state':'draft'}
|
||||
doc_obj = self.pool.get('subscription.document')
|
||||
@@ -142,7 +142,7 @@ class subscription_subscription(osv.osv):
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
for record in self.browse(cr, uid, ids, context or {}):
|
||||
if record.state=="running":
|
||||
raise osv.except_osv(_('Error!'),_('You cannot delete an active subscription !'))
|
||||
raise osv.except_osv(_('Error!'),_('You cannot delete an active subscription!'))
|
||||
return super(subscription_subscription, self).unlink(cr, uid, ids, context)
|
||||
|
||||
def set_done(self, cr, uid, ids, context=None):
|
||||
|
||||
@@ -63,7 +63,7 @@ class sale_order(osv.osv):
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, part, context=context)
|
||||
if partner.sale_warn != 'no-message':
|
||||
if partner.sale_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (partner.name), partner.sale_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.sale_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.sale_warn_msg
|
||||
warning = {
|
||||
@@ -91,7 +91,7 @@ class purchase_order(osv.osv):
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, part)
|
||||
if partner.purchase_warn != 'no-message':
|
||||
if partner.purchase_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (partner.name), partner.purchase_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.purchase_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.purchase_warn_msg
|
||||
warning = {
|
||||
@@ -124,7 +124,7 @@ class account_invoice(osv.osv):
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, partner_id)
|
||||
if partner.invoice_warn != 'no-message':
|
||||
if partner.invoice_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (partner.name), partner.invoice_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.invoice_warn_msg)
|
||||
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.invoice_warn_msg
|
||||
@@ -155,7 +155,7 @@ class stock_picking(osv.osv):
|
||||
message = False
|
||||
if partner.picking_warn != 'no-message':
|
||||
if partner.picking_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (partner.name), partner.picking_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.picking_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.picking_warn_msg
|
||||
warning = {
|
||||
@@ -184,7 +184,7 @@ class stock_picking_in(osv.osv):
|
||||
message = False
|
||||
if partner.picking_warn != 'no-message':
|
||||
if partner.picking_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (partner.name), partner.picking_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.picking_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.picking_warn_msg
|
||||
warning = {
|
||||
@@ -210,7 +210,7 @@ class stock_picking_out(osv.osv):
|
||||
message = False
|
||||
if partner.picking_warn != 'no-message':
|
||||
if partner.picking_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (partner.name), partner.picking_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.picking_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.picking_warn_msg
|
||||
warning = {
|
||||
@@ -257,7 +257,7 @@ class sale_order_line(osv.osv):
|
||||
|
||||
if product_info.sale_line_warn != 'no-message':
|
||||
if product_info.sale_line_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (product_info.name), product_info.sale_line_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (product_info.name), product_info.sale_line_warn_msg)
|
||||
title = _("Warning for %s") % product_info.name
|
||||
message = product_info.sale_line_warn_msg
|
||||
warning['title'] = title
|
||||
@@ -289,7 +289,7 @@ class purchase_order_line(osv.osv):
|
||||
|
||||
if product_info.purchase_line_warn != 'no-message':
|
||||
if product_info.purchase_line_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s !') % (product_info.name), product_info.purchase_line_warn_msg)
|
||||
raise osv.except_osv(_('Alert for %s!') % (product_info.name), product_info.purchase_line_warn_msg)
|
||||
title = _("Warning for %s") % product_info.name
|
||||
message = product_info.purchase_line_warn_msg
|
||||
warning['title'] = title
|
||||
|
||||
Reference in New Issue
Block a user