merge upstream
bzr revid: chs@openerp.com-20140129190834-xfcat3ulfbg5omhn
This commit is contained in:
commit
c202dc1c52
|
@ -3187,12 +3187,15 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
||||||
def _get_analytic_journal(journal_type):
|
def _get_analytic_journal(journal_type):
|
||||||
# Get the analytic journal
|
# Get the analytic journal
|
||||||
data = False
|
data = False
|
||||||
|
try:
|
||||||
if journal_type in ('sale', 'sale_refund'):
|
if journal_type in ('sale', 'sale_refund'):
|
||||||
data = obj_data.get_object_reference(cr, uid, 'account', 'analytic_journal_sale')
|
data = obj_data.get_object_reference(cr, uid, 'account', 'analytic_journal_sale')
|
||||||
elif journal_type in ('purchase', 'purchase_refund'):
|
elif journal_type in ('purchase', 'purchase_refund'):
|
||||||
pass
|
data = obj_data.get_object_reference(cr, uid, 'account', 'exp')
|
||||||
elif journal_type == 'general':
|
elif journal_type == 'general':
|
||||||
pass
|
pass
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
return data and data[1] or False
|
return data and data[1] or False
|
||||||
|
|
||||||
def _get_default_account(journal_type, type='debit'):
|
def _get_default_account(journal_type, type='debit'):
|
||||||
|
|
|
@ -23,6 +23,7 @@ import time
|
||||||
|
|
||||||
from openerp.osv import fields, osv
|
from openerp.osv import fields, osv
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
from openerp.tools.float_utils import float_round
|
||||||
import openerp.addons.decimal_precision as dp
|
import openerp.addons.decimal_precision as dp
|
||||||
|
|
||||||
class account_move_line_reconcile(osv.osv_memory):
|
class account_move_line_reconcile(osv.osv_memory):
|
||||||
|
@ -64,7 +65,11 @@ class account_move_line_reconcile(osv.osv_memory):
|
||||||
credit += line.credit
|
credit += line.credit
|
||||||
debit += line.debit
|
debit += line.debit
|
||||||
account_id = line.account_id.id
|
account_id = line.account_id.id
|
||||||
return {'trans_nbr': count, 'account_id': account_id, 'credit': credit, 'debit': debit, 'writeoff': debit - credit}
|
precision = self.pool['decimal.precision'].precision_get(cr, uid, 'Account')
|
||||||
|
writeoff = float_round(debit-credit, precision_digits=precision)
|
||||||
|
credit = float_round(credit, precision_digits=precision)
|
||||||
|
debit = float_round(debit, precision_digits=precision)
|
||||||
|
return {'trans_nbr': count, 'account_id': account_id, 'credit': credit, 'debit': debit, 'writeoff': writeoff}
|
||||||
|
|
||||||
def trans_rec_addendum_writeoff(self, cr, uid, ids, context=None):
|
def trans_rec_addendum_writeoff(self, cr, uid, ids, context=None):
|
||||||
return self.pool.get('account.move.line.reconcile.writeoff').trans_rec_addendum(cr, uid, ids, context)
|
return self.pool.get('account.move.line.reconcile.writeoff').trans_rec_addendum(cr, uid, ids, context)
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
</group>
|
</group>
|
||||||
<footer>
|
<footer>
|
||||||
<button string="Reconcile" name="trans_rec_reconcile_full" type="object" default_focus="1" attrs="{'invisible':[('writeoff','!=',0)]}" class="oe_highlight"/>
|
<button string="Reconcile" name="trans_rec_reconcile_full" type="object" default_focus="1" attrs="{'invisible':[('writeoff','!=',0)]}" class="oe_highlight"/>
|
||||||
<button string="Reconcile With Write-Off" name="trans_rec_addendum_writeoff" type="object" attrs="{'invisible':[('writeoff','==',0)]}" class="oe_highlight"/>
|
<button string="Reconcile With Write-Off" name="trans_rec_addendum_writeoff" type="object" attrs="{'invisible':[('writeoff','=',0)]}" class="oe_highlight"/>
|
||||||
<button string="Partial Reconcile" name="trans_rec_reconcile_partial_reconcile" type="object" attrs="{'invisible':[('writeoff','==',0)]}" class="oe_highlight"/>
|
<button string="Partial Reconcile" name="trans_rec_reconcile_partial_reconcile" type="object" attrs="{'invisible':[('writeoff','=',0)]}" class="oe_highlight"/>
|
||||||
or
|
or
|
||||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -219,7 +219,7 @@
|
||||||
<filter name="open" string="In Progress" domain="[('state','in',('open','draft'))]" help="Contracts in progress (open, draft)"/>
|
<filter name="open" string="In Progress" domain="[('state','in',('open','draft'))]" help="Contracts in progress (open, draft)"/>
|
||||||
<filter name="pending" string="To Renew" domain="[('state','=','pending')]" help="Pending contracts"/>
|
<filter name="pending" string="To Renew" domain="[('state','=','pending')]" help="Pending contracts"/>
|
||||||
<filter name="closed" string="Closed" domain="[('state','=','close')]" help="Closed contracts"/>
|
<filter name="closed" string="Closed" domain="[('state','=','close')]" help="Closed contracts"/>
|
||||||
<filter name="cancelled" string="Cancelled" domain="[('state','=','cancel')]" help="Cancelled contracts"/>
|
<filter name="cancelled" string="Cancelled" domain="[('state','=','cancelled')]" help="Cancelled contracts"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter
|
<filter
|
||||||
string="Expired or consumed"
|
string="Expired or consumed"
|
||||||
|
|
|
@ -35,9 +35,9 @@ class account_asset_category(osv.osv):
|
||||||
'name': fields.char('Name', size=64, required=True, select=1),
|
'name': fields.char('Name', size=64, required=True, select=1),
|
||||||
'note': fields.text('Note'),
|
'note': fields.text('Note'),
|
||||||
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),
|
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),
|
||||||
'account_asset_id': fields.many2one('account.account', 'Asset Account', required=True),
|
'account_asset_id': fields.many2one('account.account', 'Asset Account', required=True, domain=[('type','=','other')]),
|
||||||
'account_depreciation_id': fields.many2one('account.account', 'Depreciation Account', required=True),
|
'account_depreciation_id': fields.many2one('account.account', 'Depreciation Account', required=True, domain=[('type','=','other')]),
|
||||||
'account_expense_depreciation_id': fields.many2one('account.account', 'Depr. Expense Account', required=True),
|
'account_expense_depreciation_id': fields.many2one('account.account', 'Depr. Expense Account', required=True, domain=[('type','=','other')]),
|
||||||
'journal_id': fields.many2one('account.journal', 'Journal', required=True),
|
'journal_id': fields.many2one('account.journal', 'Journal', required=True),
|
||||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||||
'method': fields.selection([('linear','Linear'),('degressive','Degressive')], 'Computation Method', required=True, help="Choose the method to use to compute the amount of depreciation lines.\n"\
|
'method': fields.selection([('linear','Linear'),('degressive','Degressive')], 'Computation Method', required=True, help="Choose the method to use to compute the amount of depreciation lines.\n"\
|
||||||
|
|
|
@ -149,7 +149,7 @@
|
||||||
<para style="terp_default_8">
|
<para style="terp_default_8">
|
||||||
<font color="white"> </font>
|
<font color="white"> </font>
|
||||||
</para>
|
</para>
|
||||||
<para style="terp_default_9_followup_id">[[ format(get_text(o,data['form']['followup_id'])) ]]</para>
|
<pre style="terp_default_9_followup_id">[[ format(get_text(o,data['form']['followup_id'])) ]]</pre>
|
||||||
<para style="terp_default_9">
|
<para style="terp_default_9">
|
||||||
<font color="white"> </font>
|
<font color="white"> </font>
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -99,6 +99,9 @@ class CompanyLDAP(osv.osv):
|
||||||
filter = filter_format(conf['ldap_filter'], (login,))
|
filter = filter_format(conf['ldap_filter'], (login,))
|
||||||
try:
|
try:
|
||||||
results = self.query(conf, filter)
|
results = self.query(conf, filter)
|
||||||
|
|
||||||
|
# Get rid of (None, attrs) for searchResultReference replies
|
||||||
|
results = [i for i in results if i[0]]
|
||||||
if results and len(results) == 1:
|
if results and len(results) == 1:
|
||||||
dn = results[0][0]
|
dn = results[0][0]
|
||||||
conn = self.connect(conf)
|
conn = self.connect(conf)
|
||||||
|
|
|
@ -1330,13 +1330,13 @@ class calendar_event(osv.Model):
|
||||||
new_id = get_real_ids(arg[2])
|
new_id = get_real_ids(arg[2])
|
||||||
new_arg = (arg[0], arg[1], new_id)
|
new_arg = (arg[0], arg[1], new_id)
|
||||||
new_args.append(new_arg)
|
new_args.append(new_arg)
|
||||||
#offset, limit and count must be treated separately as we may need to deal with virtual ids
|
|
||||||
|
|
||||||
if context.get('virtual_id', True):
|
if not context.get('virtual_id', True):
|
||||||
|
return super(calendar_event, self).search(cr, uid, new_args, offset=offset, limit=limit, order=order, context=context, count=count)
|
||||||
|
|
||||||
|
# offset, limit, order and count must be treated separately as we may need to deal with virtual ids
|
||||||
res = super(calendar_event, self).search(cr, uid, new_args, offset=0, limit=0, order=None, context=context, count=False)
|
res = super(calendar_event, self).search(cr, uid, new_args, offset=0, limit=0, order=None, context=context, count=False)
|
||||||
res = self.get_recurrent_ids(cr, uid, res, args, order=order, context=context)
|
res = self.get_recurrent_ids(cr, uid, res, args, order=order, context=context)
|
||||||
else:
|
|
||||||
res = super(calendar_event, self).search(cr, uid, new_args, offset=0, limit=0, order=order, context=context, count=False)
|
|
||||||
if count:
|
if count:
|
||||||
return len(res)
|
return len(res)
|
||||||
elif limit:
|
elif limit:
|
||||||
|
|
|
@ -313,7 +313,7 @@
|
||||||
<field name="name">Meetings</field>
|
<field name="name">Meetings</field>
|
||||||
<field name="res_model">calendar.event</field>
|
<field name="res_model">calendar.event</field>
|
||||||
<field name="view_mode">form,calendar,tree,gantt</field>
|
<field name="view_mode">form,calendar,tree,gantt</field>
|
||||||
<field name="view_id" ref="action_view_calendar_event_form"/>
|
<field name="view_id" ref="view_calendar_event_form"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,9 @@ class decimal_precision(orm.Model):
|
||||||
self.precision_get.clear_cache(self)
|
self.precision_get.clear_cache(self)
|
||||||
for obj in self.pool.obj_list():
|
for obj in self.pool.obj_list():
|
||||||
for colname, col in self.pool.get(obj)._columns.items():
|
for colname, col in self.pool.get(obj)._columns.items():
|
||||||
if isinstance(col, (fields.float, fields.function)):
|
if hasattr(col, 'digits_change'):
|
||||||
col.digits_change(cr)
|
col.digits_change(cr)
|
||||||
RegistryManager.signal_registry_change(cr.dbname)
|
RegistryManager.signal_caches_change(cr.dbname)
|
||||||
|
|
||||||
def create(self, cr, uid, data, context=None):
|
def create(self, cr, uid, data, context=None):
|
||||||
res = super(decimal_precision, self).create(cr, uid, data, context=context)
|
res = super(decimal_precision, self).create(cr, uid, data, context=context)
|
||||||
|
|
|
@ -262,6 +262,7 @@ class abstracted_fs(object):
|
||||||
if path == '/' and mode in ('list', 'cwd'):
|
if path == '/' and mode in ('list', 'cwd'):
|
||||||
return (None, None, None )
|
return (None, None, None )
|
||||||
|
|
||||||
|
if path == '..': path = self.cwd + '/..'
|
||||||
path = _to_unicode(os.path.normpath(path)) # again, for '/db/../ss'
|
path = _to_unicode(os.path.normpath(path)) # again, for '/db/../ss'
|
||||||
if path == '.': path = ''
|
if path == '.': path = ''
|
||||||
|
|
||||||
|
|
|
@ -417,8 +417,8 @@ class email_template(osv.osv):
|
||||||
|
|
||||||
# create a mail_mail based on values, without attachments
|
# create a mail_mail based on values, without attachments
|
||||||
values = self.generate_email(cr, uid, template_id, res_id, context=context)
|
values = self.generate_email(cr, uid, template_id, res_id, context=context)
|
||||||
assert values.get('email_from'), 'email_from is missing or empty after template rendering, send_mail() cannot proceed'
|
if not values.get('email_from'):
|
||||||
|
raise osv.except_osv(_('Warning!'),_("Sender email is missing or empty after template rendering. Specify one to deliver your message"))
|
||||||
# process partner_to field that is a comma separated list of partner_ids -> recipient_ids
|
# process partner_to field that is a comma separated list of partner_ids -> recipient_ids
|
||||||
# NOTE: only usable if force_send is True, because otherwise the value is
|
# NOTE: only usable if force_send is True, because otherwise the value is
|
||||||
# not stored on the mail_mail, and therefore lost -> fixed in v8
|
# not stored on the mail_mail, and therefore lost -> fixed in v8
|
||||||
|
|
|
@ -21,6 +21,7 @@ except ImportError:
|
||||||
try:
|
try:
|
||||||
from .. import escpos
|
from .. import escpos
|
||||||
from ..escpos import printer
|
from ..escpos import printer
|
||||||
|
from ..escpos import supported_devices
|
||||||
except ImportError:
|
except ImportError:
|
||||||
escpos = printer = None
|
escpos = printer = None
|
||||||
|
|
||||||
|
@ -39,21 +40,16 @@ class EscposDriver(Thread):
|
||||||
self.queue = Queue()
|
self.queue = Queue()
|
||||||
self.status = {'status':'connecting', 'messages':[]}
|
self.status = {'status':'connecting', 'messages':[]}
|
||||||
|
|
||||||
self.supported_printers = [
|
def connected_usb_devices(self):
|
||||||
{ 'vendor' : 0x04b8, 'product' : 0x0e03, 'name' : 'Epson TM-T20' },
|
|
||||||
{ 'vendor' : 0x04b8, 'product' : 0x0202, 'name' : 'Epson TM-T70' },
|
|
||||||
]
|
|
||||||
|
|
||||||
def connected_usb_devices(self,devices):
|
|
||||||
connected = []
|
connected = []
|
||||||
for device in devices:
|
for device in supported_devices.device_list:
|
||||||
if usb.core.find(idVendor=device['vendor'], idProduct=device['product']) != None:
|
if usb.core.find(idVendor=device['vendor'], idProduct=device['product']) != None:
|
||||||
connected.append(device)
|
connected.append(device)
|
||||||
return connected
|
return connected
|
||||||
|
|
||||||
def get_escpos_printer(self):
|
def get_escpos_printer(self):
|
||||||
try:
|
try:
|
||||||
printers = self.connected_usb_devices(self.supported_printers)
|
printers = self.connected_usb_devices()
|
||||||
if len(printers) > 0:
|
if len(printers) > 0:
|
||||||
self.set_status('connected','Connected to '+printers[0]['name'])
|
self.set_status('connected','Connected to '+printers[0]['name'])
|
||||||
return escpos.printer.Usb(printers[0]['vendor'], printers[0]['product'])
|
return escpos.printer.Usb(printers[0]['vendor'], printers[0]['product'])
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__all__ = ["constants","escpos","exceptions","printer"]
|
__all__ = ["constants","escpos","exceptions","printer","supported_devices"]
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# This is a list of esc/pos compatible usb printers. The vendor and product ids can be found by
|
||||||
|
# typing lsusb in a linux terminal, this will give you the ids in the form ID VENDOR:PRODUCT
|
||||||
|
|
||||||
|
device_list = [
|
||||||
|
{ 'vendor' : 0x04b8, 'product' : 0x0e03, 'name' : 'Epson TM-T20' },
|
||||||
|
{ 'vendor' : 0x04b8, 'product' : 0x0202, 'name' : 'Epson TM-T70' },
|
||||||
|
]
|
||||||
|
|
|
@ -185,8 +185,8 @@ class im_message(osv.osv):
|
||||||
def post(self, cr, uid, message, to_session_id, technical=False, uuid=None, context=None):
|
def post(self, cr, uid, message, to_session_id, technical=False, uuid=None, context=None):
|
||||||
assert_uuid(uuid)
|
assert_uuid(uuid)
|
||||||
my_id = self.pool.get('im.user').get_my_id(cr, uid, uuid)
|
my_id = self.pool.get('im.user').get_my_id(cr, uid, uuid)
|
||||||
session = self.pool.get('im.session').browse(cr, uid, to_session_id, context)
|
session_user_ids = self.pool.get('im.session').get_session_users(cr, uid, to_session_id, context=context).get("user_ids", [])
|
||||||
to_ids = [x.id for x in session.user_ids if x.id != my_id]
|
to_ids = [user_id for user_id in session_user_ids if user_id != my_id]
|
||||||
self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id,
|
self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id,
|
||||||
'to_id': [(6, 0, to_ids)], 'session_id': to_session_id, 'technical': technical}, context=context)
|
'to_id': [(6, 0, to_ids)], 'session_id': to_session_id, 'technical': technical}, context=context)
|
||||||
notify_channel(cr, "im_channel", {'type': 'message', 'receivers': [my_id] + to_ids})
|
notify_channel(cr, "im_channel", {'type': 'message', 'receivers': [my_id] + to_ids})
|
||||||
|
@ -202,7 +202,7 @@ class im_session(osv.osv):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'user_ids': fields.many2many('im.user'),
|
'user_ids': fields.many2many('im.user', 'im_session_im_user_rel', 'im_session_id', 'im_user_id', 'Users'),
|
||||||
"name": fields.function(_calc_name, string="Name", type='char'),
|
"name": fields.function(_calc_name, string="Name", type='char'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +225,9 @@ class im_session(osv.osv):
|
||||||
}, context=context)
|
}, context=context)
|
||||||
return self.read(cr, uid, session_id, context=context)
|
return self.read(cr, uid, session_id, context=context)
|
||||||
|
|
||||||
|
def get_session_users(self, cr, uid, session_id, context=None):
|
||||||
|
return self.read(cr, openerp.SUPERUSER_ID, session_id, ['user_ids'], context=context)
|
||||||
|
|
||||||
def add_to_session(self, cr, uid, session_id, user_id, uuid=None, context=None):
|
def add_to_session(self, cr, uid, session_id, user_id, uuid=None, context=None):
|
||||||
my_id = self.pool.get("im.user").get_my_id(cr, uid, uuid, context=context)
|
my_id = self.pool.get("im.user").get_my_id(cr, uid, uuid, context=context)
|
||||||
session = self.read(cr, uid, session_id, context=context)
|
session = self.read(cr, uid, session_id, context=context)
|
||||||
|
@ -259,7 +262,7 @@ class im_user(osv.osv):
|
||||||
return ['&', ('im_last_status', '=', True), ('im_last_status_update', '>', (current - delta).strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
|
return ['&', ('im_last_status', '=', True), ('im_last_status_update', '>', (current - delta).strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
|
||||||
else:
|
else:
|
||||||
return ['|', ('im_last_status', '=', False), ('im_last_status_update', '<=', (current - delta).strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
|
return ['|', ('im_last_status', '=', False), ('im_last_status_update', '<=', (current - delta).strftime(DEFAULT_SERVER_DATETIME_FORMAT))]
|
||||||
|
# TODO: Remove fields arg in trunk. Also in im.js.
|
||||||
def search_users(self, cr, uid, text_search, fields, limit, context=None):
|
def search_users(self, cr, uid, text_search, fields, limit, context=None):
|
||||||
my_id = self.get_my_id(cr, uid, None, context)
|
my_id = self.get_my_id(cr, uid, None, context)
|
||||||
group_employee = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_user')[1]
|
group_employee = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_user')[1]
|
||||||
|
@ -271,7 +274,7 @@ class im_user(osv.osv):
|
||||||
if len(found) < limit:
|
if len(found) < limit:
|
||||||
found += self.search(cr, uid, [["name", "ilike", text_search], ["id", "<>", my_id], ["uuid", "=", False], ["im_status", "=", False], ["id", "not in", found]],
|
found += self.search(cr, uid, [["name", "ilike", text_search], ["id", "<>", my_id], ["uuid", "=", False], ["im_status", "=", False], ["id", "not in", found]],
|
||||||
order="name asc", limit=limit-len(found), context=context)
|
order="name asc", limit=limit-len(found), context=context)
|
||||||
users = self.read(cr, uid, found, fields, context=context)
|
users = self.read(cr,openerp.SUPERUSER_ID, found, ["name", "user_id", "uuid", "im_status"], context=context)
|
||||||
users.sort(key=lambda obj: found.index(obj['id']))
|
users.sort(key=lambda obj: found.index(obj['id']))
|
||||||
return users
|
return users
|
||||||
|
|
||||||
|
@ -319,6 +322,9 @@ class im_user(osv.osv):
|
||||||
continue
|
continue
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def get_users(self, cr, uid, ids, context=None):
|
||||||
|
return self.read(cr,openerp.SUPERUSER_ID, ids, ["name", "im_status", "uuid"], context=context)
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.function(_get_name, type='char', size=200, string="Name", store=True, readonly=True),
|
'name': fields.function(_get_name, type='char', size=200, string="Name", store=True, readonly=True),
|
||||||
'assigned_name': fields.char(string="Assigned Name", size=200, required=False),
|
'assigned_name': fields.char(string="Assigned Name", size=200, required=False),
|
||||||
|
@ -341,3 +347,16 @@ class im_user(osv.osv):
|
||||||
('user_uniq', 'unique (user_id)', 'Only one chat user per OpenERP user.'),
|
('user_uniq', 'unique (user_id)', 'Only one chat user per OpenERP user.'),
|
||||||
('uuid_uniq', 'unique (uuid)', 'Chat identifier already used.'),
|
('uuid_uniq', 'unique (uuid)', 'Chat identifier already used.'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class res_users(osv.osv):
|
||||||
|
_inherit = "res.users"
|
||||||
|
|
||||||
|
def _get_im_user(self, cr, uid, ids, field_name, arg, context=None):
|
||||||
|
result = dict.fromkeys(ids, False)
|
||||||
|
for index, im_user in enumerate(self.pool['im.user'].search_read(cr, uid, domain=[('user_id', 'in', ids)], fields=['name', 'user_id'], context=context)):
|
||||||
|
result[ids[index]] = im_user.get('user_id') and (im_user['user_id'][0], im_user['name']) or False
|
||||||
|
return result
|
||||||
|
|
||||||
|
_columns = {
|
||||||
|
'im_user_id' : fields.function(_get_im_user, type='many2one', string="IM User", relation="im.user"),
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
<openerp>
|
<openerp>
|
||||||
<data>
|
<data>
|
||||||
<record id="message_rule_1" model="ir.rule">
|
<record id="message_rule_1" model="ir.rule">
|
||||||
<field name="name">Can only read messages that you sent or messages sent to you</field>
|
<field name="name">Can only read messages from a session where user is</field>
|
||||||
<field name="model_id" ref="model_im_message"/>
|
<field name="model_id" ref="model_im_message"/>
|
||||||
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
|
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
|
||||||
<field name="domain_force">["|", ('to_id.user_id', 'in', [user.id]), ('from_id.user_id', '=', user.id)]</field>
|
<field name="domain_force">[('session_id.user_ids', 'in', user.im_user_id.id)]</field>
|
||||||
<field name="perm_read" eval="1"/>
|
<field name="perm_read" eval="1"/>
|
||||||
<field name="perm_write" eval="0"/>
|
<field name="perm_write" eval="0"/>
|
||||||
<field name="perm_create" eval="0"/>
|
<field name="perm_create" eval="0"/>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
access_im_message,im.message,model_im_message,base.group_user,1,0,1,0
|
access_im_message,im.message,model_im_message,,1,0,1,0
|
||||||
access_im_user,im.user,model_im_user,,1,1,1,0
|
access_im_user,im.user,model_im_user,,1,1,1,0
|
||||||
access_im_session,im.session,model_im_session,,1,0,0,0
|
access_im_session,im.session,model_im_session,,1,0,0,0
|
|
|
@ -92,6 +92,7 @@
|
||||||
search_changed: function(e) {
|
search_changed: function(e) {
|
||||||
var users = new instance.web.Model("im.user");
|
var users = new instance.web.Model("im.user");
|
||||||
var self = this;
|
var self = this;
|
||||||
|
// TODO: Remove fields arg in trunk. Also in im.js.
|
||||||
return this.user_search_dm.add(users.call("search_users", [this.get("current_search"), ["name", "user_id", "uuid", "im_status"],
|
return this.user_search_dm.add(users.call("search_users", [this.get("current_search"), ["name", "user_id", "uuid", "im_status"],
|
||||||
USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(users) {
|
USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(users) {
|
||||||
var logged_users = _.filter(users, function(u) { return !!u.im_status; });
|
var logged_users = _.filter(users, function(u) { return !!u.im_status; });
|
||||||
|
|
|
@ -145,7 +145,7 @@ function declare($, _, openerp) {
|
||||||
if (_.size(no_cache) === 0)
|
if (_.size(no_cache) === 0)
|
||||||
def = $.when();
|
def = $.when();
|
||||||
else
|
else
|
||||||
def = im_common.connection.model("im.user").call("read", [_.values(no_cache), []]).then(function(users) {
|
def = im_common.connection.model("im.user").call("get_users", [_.values(no_cache)]).then(function(users) {
|
||||||
self.add_to_user_cache(users);
|
self.add_to_user_cache(users);
|
||||||
});
|
});
|
||||||
return def.then(function() {
|
return def.then(function() {
|
||||||
|
@ -230,7 +230,8 @@ function declare($, _, openerp) {
|
||||||
return self.chat_with_users(users);
|
return self.chat_with_users(users);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
activate_session: function(session_id, focus) {
|
activate_session: function(session_id, focus, message) {
|
||||||
|
var self = this;
|
||||||
var conv = _.find(this.conversations, function(conv) {return conv.session_id == session_id;});
|
var conv = _.find(this.conversations, function(conv) {return conv.session_id == session_id;});
|
||||||
var def = $.when();
|
var def = $.when();
|
||||||
if (! conv) {
|
if (! conv) {
|
||||||
|
@ -244,6 +245,9 @@ function declare($, _, openerp) {
|
||||||
this.calc_positions();
|
this.calc_positions();
|
||||||
this.trigger("new_conversation", conv);
|
this.trigger("new_conversation", conv);
|
||||||
}, this));
|
}, this));
|
||||||
|
def = def.then(function(){
|
||||||
|
return self.load_history(conv, message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (focus) {
|
if (focus) {
|
||||||
def = def.then(function() {
|
def = def.then(function() {
|
||||||
|
@ -252,13 +256,32 @@ function declare($, _, openerp) {
|
||||||
}
|
}
|
||||||
return def.then(function() {return conv});
|
return def.then(function() {return conv});
|
||||||
},
|
},
|
||||||
received_messages: function(messages) {
|
load_history: function(conv, message){
|
||||||
|
var self = this;
|
||||||
|
var domain = [["session_id", "=", conv.session_id]];
|
||||||
|
if (!_.isUndefined(message)){
|
||||||
|
domain.push(["date", "<", message.date]);
|
||||||
|
}
|
||||||
|
return im_common.connection.model("im.message").call("search_read", [domain, [], 0, 10]).then(function(messages){
|
||||||
|
messages.reverse();
|
||||||
|
var users = _.unique(_.map(messages, function(message){
|
||||||
|
return message.from_id[0];
|
||||||
|
}));
|
||||||
|
return self.ensure_users(users).then(function(){
|
||||||
|
return self.received_messages(messages, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
received_messages: function(messages, seen) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var defs = [];
|
var defs = [];
|
||||||
var received = false;
|
var received = false;
|
||||||
|
if (_.isUndefined(seen)){
|
||||||
|
seen = false;
|
||||||
|
}
|
||||||
_.each(messages, function(message) {
|
_.each(messages, function(message) {
|
||||||
if (! message.technical) {
|
if (! message.technical) {
|
||||||
defs.push(self.activate_session(message.session_id[0]).then(function(conv) {
|
defs.push(self.activate_session(message.session_id[0], false, message).then(function(conv) {
|
||||||
received = self.my_id !== message.from_id[0];
|
received = self.my_id !== message.from_id[0];
|
||||||
return conv.received_message(message);
|
return conv.received_message(message);
|
||||||
}));
|
}));
|
||||||
|
@ -269,7 +292,7 @@ function declare($, _, openerp) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return $.when.apply($, defs).then(function(){
|
return $.when.apply($, defs).then(function(){
|
||||||
if (! self.get("window_focus") && received) {
|
if (! self.get("window_focus") && received && !seen) {
|
||||||
self.set("waiting_messages", self.get("waiting_messages") + messages.length);
|
self.set("waiting_messages", self.get("waiting_messages") + messages.length);
|
||||||
self.ting.play();
|
self.ting.play();
|
||||||
self.create_ting();
|
self.create_ting();
|
||||||
|
@ -368,7 +391,7 @@ function declare($, _, openerp) {
|
||||||
refresh_users: function() {
|
refresh_users: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var user_ids;
|
var user_ids;
|
||||||
return im_common.connection.model("im.session").call("read", [self.session_id]).then(function(session) {
|
return im_common.connection.model("im.session").call("get_session_users", [self.session_id]).then(function(session) {
|
||||||
user_ids = _.without(session.user_ids, self.c_manager.me.get("id"));
|
user_ids = _.without(session.user_ids, self.c_manager.me.get("id"));
|
||||||
return self.c_manager.ensure_users(user_ids);
|
return self.c_manager.ensure_users(user_ids);
|
||||||
}).then(function(users) {
|
}).then(function(users) {
|
||||||
|
@ -449,7 +472,7 @@ function declare($, _, openerp) {
|
||||||
date = "" + zpad(date.getHours(), 2) + ":" + zpad(date.getMinutes(), 2);
|
date = "" + zpad(date.getHours(), 2) + ":" + zpad(date.getMinutes(), 2);
|
||||||
var to_show = _.map(items, im_common.escape_keep_url);
|
var to_show = _.map(items, im_common.escape_keep_url);
|
||||||
this.last_bubble = $(openerp.qweb.render("im_common.conversation_bubble", {"items": to_show, "user": user, "time": date}));
|
this.last_bubble = $(openerp.qweb.render("im_common.conversation_bubble", {"items": to_show, "user": user, "time": date}));
|
||||||
$(this.$(".oe_im_chatview_content").children()[0]).append(this.last_bubble);
|
$(this.$(".oe_im_chatview_conversation")).append(this.last_bubble);
|
||||||
this._go_bottom();
|
this._go_bottom();
|
||||||
},
|
},
|
||||||
_go_bottom: function() {
|
_go_bottom: function() {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
All users are offline. They will receive your messages on their next connection.
|
All users are offline. They will receive your messages on their next connection.
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_im_chatview_content">
|
<div class="oe_im_chatview_content">
|
||||||
<div></div>
|
<div class="oe_im_chatview_conversation"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_im_chatview_footer">
|
<div class="oe_im_chatview_footer">
|
||||||
<input class="oe_im_chatview_input" t-att-placeholder="widget.inputPlaceholder" />
|
<input class="oe_im_chatview_input" t-att-placeholder="widget.inputPlaceholder" />
|
||||||
|
|
|
@ -171,8 +171,8 @@ class im_livechat_channel(osv.osv):
|
||||||
return users
|
return users
|
||||||
|
|
||||||
def get_session(self, cr, uid, channel_id, uuid, context=None):
|
def get_session(self, cr, uid, channel_id, uuid, context=None):
|
||||||
my_id = self.pool.get("im.user").get_my_id(cr, uid, uuid, context=context)
|
self.pool.get("im.user").get_my_id(cr, uid, uuid, context=context)
|
||||||
users = self.get_available_users(cr, uid, channel_id, context=context)
|
users = self.get_available_users(cr, openerp.SUPERUSER_ID, channel_id, context=context)
|
||||||
if len(users) == 0:
|
if len(users) == 0:
|
||||||
return False
|
return False
|
||||||
user_id = random.choice(users).id
|
user_id = random.choice(users).id
|
||||||
|
|
|
@ -125,6 +125,7 @@
|
||||||
<field name="res_model">im.message</field>
|
<field name="res_model">im.message</field>
|
||||||
<field name="view_mode">list</field>
|
<field name="view_mode">list</field>
|
||||||
<field name="domain">[('session_id.channel_id', '!=', None)]</field>
|
<field name="domain">[('session_id.channel_id', '!=', None)]</field>
|
||||||
|
<field name="context">{'search_default_group_by_session_id': 1, 'search_default_group_by_date': 1, 'search_default_session_id': 1}</field>
|
||||||
</record>
|
</record>
|
||||||
<menuitem name="History" parent="im_livechat" id="history" action="action_history" groups="group_im_livechat_manager"/>
|
<menuitem name="History" parent="im_livechat" id="history" action="action_history" groups="group_im_livechat_manager"/>
|
||||||
|
|
||||||
|
@ -141,5 +142,21 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="im_message_search" model="ir.ui.view">
|
||||||
|
<field name="name">im.message.search</field>
|
||||||
|
<field name="model">im.message</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="Search history">
|
||||||
|
<filter name="session_id" string="My Sessions" domain="[('session_id.user_ids','in', uid)]"/>
|
||||||
|
<field name="from_id"/>
|
||||||
|
<field name="to_id"/>
|
||||||
|
<group expand="0" string="Group By...">
|
||||||
|
<filter name="group_by_session_id" string="Session" domain="[]" context="{'group_by':'session_id'}"/>
|
||||||
|
<filter name="group_by_date" string="Date" domain="[]" context="{'group_by':'date'}"/>
|
||||||
|
</group>
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -2,7 +2,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
access_ls_chann1,im_livechat.channel,model_im_livechat_channel,,1,0,0,0
|
access_ls_chann1,im_livechat.channel,model_im_livechat_channel,,1,0,0,0
|
||||||
access_ls_chann2,im_livechat.channel,model_im_livechat_channel,group_im_livechat,1,1,1,0
|
access_ls_chann2,im_livechat.channel,model_im_livechat_channel,group_im_livechat,1,1,1,0
|
||||||
access_ls_chann3,im_livechat.channel,model_im_livechat_channel,group_im_livechat_manager,1,1,1,1
|
access_ls_chann3,im_livechat.channel,model_im_livechat_channel,group_im_livechat_manager,1,1,1,1
|
||||||
access_ls_message_portal,im_livechat.im.message.portal,im.model_im_message,base.group_portal,0,0,0,0
|
|
||||||
access_im_user_portal,im_livechat.im.user.portal,im.model_im_user,base.group_portal,1,0,0,0
|
access_im_user_portal,im_livechat.im.user.portal,im.model_im_user,base.group_portal,1,0,0,0
|
||||||
access_ls_message,im_livechat.im.message,im.model_im_message,base.group_public,0,0,0,0
|
|
||||||
access_im_user,im_livechat.im.user,im.model_im_user,base.group_public,1,0,0,0
|
access_im_user,im_livechat.im.user,im.model_im_user,base.group_public,1,0,0,0
|
|
|
@ -107,11 +107,14 @@ define(["openerp", "im_common", "underscore", "require", "jquery",
|
||||||
}
|
}
|
||||||
self.manager.activate_session(session_id, true).then(function(conv) {
|
self.manager.activate_session(session_id, true).then(function(conv) {
|
||||||
if (self.options.defaultMessage) {
|
if (self.options.defaultMessage) {
|
||||||
|
setTimeout(function(){
|
||||||
conv.received_message({
|
conv.received_message({
|
||||||
message: self.options.defaultMessage,
|
message: self.options.defaultMessage,
|
||||||
date: openerp.datetime_to_str(new Date()),
|
date: openerp.datetime_to_str(new Date()),
|
||||||
from_id: [conv.get("users")[0].get("id"), "Unknown"]
|
from_id: [conv.get("users")[0].get("id"), "Unknown"]
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
2500);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -83,7 +83,7 @@ class res_users(osv.Model):
|
||||||
|
|
||||||
def copy_data(self, *args, **kwargs):
|
def copy_data(self, *args, **kwargs):
|
||||||
data = super(res_users, self).copy_data(*args, **kwargs)
|
data = super(res_users, self).copy_data(*args, **kwargs)
|
||||||
if data.get('alias_name'):
|
if data and data.get('alias_name'):
|
||||||
data['alias_name'] = data['login']
|
data['alias_name'] = data['login']
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
|
@ -322,9 +322,9 @@ class mail_compose_message(osv.TransientModel):
|
||||||
mail_values['email_from'] = email_dict.pop('email_from')
|
mail_values['email_from'] = email_dict.pop('email_from')
|
||||||
# replies redirection: mass mailing only
|
# replies redirection: mass mailing only
|
||||||
if not wizard.same_thread:
|
if not wizard.same_thread:
|
||||||
mail_values['reply_to'] = email_dict.pop('reply_to')
|
mail_values['reply_to'] = email_dict.pop('reply_to', None)
|
||||||
else:
|
else:
|
||||||
email_dict.pop('reply_to')
|
email_dict.pop('reply_to', None)
|
||||||
mail_values.update(email_dict)
|
mail_values.update(email_dict)
|
||||||
# mass mailing without post: mail_mail values
|
# mass mailing without post: mail_mail values
|
||||||
if mass_mail_mode and not wizard.post:
|
if mass_mail_mode and not wizard.post:
|
||||||
|
|
|
@ -320,10 +320,9 @@ class mrp_bom(osv.osv):
|
||||||
"""
|
"""
|
||||||
routing_obj = self.pool.get('mrp.routing')
|
routing_obj = self.pool.get('mrp.routing')
|
||||||
factor = factor / (bom.product_efficiency or 1.0)
|
factor = factor / (bom.product_efficiency or 1.0)
|
||||||
max_rounding = max(bom.product_rounding, bom.product_uom.rounding)
|
factor = rounding(factor, bom.product_rounding)
|
||||||
factor = rounding(factor, max_rounding)
|
if factor < bom.product_rounding:
|
||||||
if factor < max_rounding:
|
factor = bom.product_rounding
|
||||||
factor = max_rounding
|
|
||||||
result = []
|
result = []
|
||||||
result2 = []
|
result2 = []
|
||||||
phantom = False
|
phantom = False
|
||||||
|
@ -772,7 +771,7 @@ class mrp_production(osv.osv):
|
||||||
# qty available for consume and produce
|
# qty available for consume and produce
|
||||||
qty_avail = scheduled.product_qty - consumed_data.get(scheduled.product_id.id, 0.0)
|
qty_avail = scheduled.product_qty - consumed_data.get(scheduled.product_id.id, 0.0)
|
||||||
|
|
||||||
if qty_avail <= 0.0:
|
if float_compare(qty_avail, 0, precision_rounding=scheduled.product_id.uom_id.rounding) <= 0:
|
||||||
# there will be nothing to consume for this raw material
|
# there will be nothing to consume for this raw material
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -784,7 +783,7 @@ class mrp_production(osv.osv):
|
||||||
# if qtys we have to consume is more than qtys available to consume
|
# if qtys we have to consume is more than qtys available to consume
|
||||||
prod_name = scheduled.product_id.name_get()[0][1]
|
prod_name = scheduled.product_id.name_get()[0][1]
|
||||||
raise osv.except_osv(_('Warning!'), _('You are going to consume total %s quantities of "%s".\nBut you can only consume up to total %s quantities.') % (qty, prod_name, qty_avail))
|
raise osv.except_osv(_('Warning!'), _('You are going to consume total %s quantities of "%s".\nBut you can only consume up to total %s quantities.') % (qty, prod_name, qty_avail))
|
||||||
if qty <= 0.0:
|
if float_compare(qty, 0, precision_rounding=scheduled.product_id.uom_id.rounding) <= 0:
|
||||||
# we already have more qtys consumed than we need
|
# we already have more qtys consumed than we need
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -764,7 +764,7 @@
|
||||||
<field name="workcenter_id"/>
|
<field name="workcenter_id"/>
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name="cycle"/>
|
<field name="cycle"/>
|
||||||
<field name="hour"/>
|
<field name="hour" widget="float_time"/>
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
<tree string="Production Work Centers">
|
<tree string="Production Work Centers">
|
||||||
|
@ -772,7 +772,7 @@
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="workcenter_id"/>
|
<field name="workcenter_id"/>
|
||||||
<field name="cycle"/>
|
<field name="cycle"/>
|
||||||
<field name="hour"/>
|
<field name="hour" widget="float_time"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</page>
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="workcenter_id" widget="selection"/>
|
<field name="workcenter_id" widget="selection"/>
|
||||||
<field name="cycle"/>
|
<field name="cycle"/>
|
||||||
<field name="hour"/>
|
<field name="hour" widget="float_time"/>
|
||||||
<field name="state" />
|
<field name="state" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
|
@ -93,8 +93,9 @@ class plugin_handler(osv.osv_memory):
|
||||||
"""
|
"""
|
||||||
mail_message = self.pool.get('mail.message')
|
mail_message = self.pool.get('mail.message')
|
||||||
model_obj = self.pool[model]
|
model_obj = self.pool[model]
|
||||||
msg = self.pool.get('mail.thread').message_parse(cr, uid, email)
|
mail_thread_obj = self.pool.get('mail.thread')
|
||||||
message_id = msg.get('message-id')
|
msg = mail_thread_obj.message_parse(cr, uid, email)
|
||||||
|
message_id = msg.get('message_id')
|
||||||
mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)])
|
mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)])
|
||||||
if message_id and mail_ids:
|
if message_id and mail_ids:
|
||||||
mail_record = mail_message.browse(cr, uid, mail_ids)[0]
|
mail_record = mail_message.browse(cr, uid, mail_ids)[0]
|
||||||
|
@ -107,12 +108,22 @@ class plugin_handler(osv.osv_memory):
|
||||||
res_id = model_obj.message_process(cr, uid, model, email)
|
res_id = model_obj.message_process(cr, uid, model, email)
|
||||||
notify = _("Mail successfully pushed, a new %s has been created.") % model
|
notify = _("Mail successfully pushed, a new %s has been created.") % model
|
||||||
else:
|
else:
|
||||||
|
email_from = msg.get('email_from')
|
||||||
|
if not email_from:
|
||||||
|
author_id = False
|
||||||
|
else:
|
||||||
|
authors = mail_thread_obj.message_find_partner_from_emails(cr, uid, [res_id], [email_from])
|
||||||
|
author_id = authors and authors[0].get('partner_id') or False
|
||||||
|
|
||||||
model_obj.message_post(cr, uid, [res_id],
|
model_obj.message_post(cr, uid, [res_id],
|
||||||
body=msg.get('body'),
|
body=msg.get('body'),
|
||||||
subject=msg.get('subject'),
|
subject=msg.get('subject'),
|
||||||
type='comment' if model == 'res.partner' else 'email',
|
type='comment' if model == 'res.partner' else 'email',
|
||||||
parent_id=msg.get('parent_id'),
|
parent_id=msg.get('parent_id'),
|
||||||
attachments=msg.get('attachments'))
|
attachments=msg.get('attachments'),
|
||||||
|
message_id=message_id,
|
||||||
|
email_from=email_from,
|
||||||
|
author_id=author_id)
|
||||||
notify = _("Mail successfully pushed")
|
notify = _("Mail successfully pushed")
|
||||||
url = self._make_url(cr, uid, res_id, model)
|
url = self._make_url(cr, uid, res_id, model)
|
||||||
return (model, res_id, url, notify)
|
return (model, res_id, url, notify)
|
||||||
|
@ -151,7 +162,7 @@ class plugin_handler(osv.osv_memory):
|
||||||
ir_attachment_obj = self.pool.get('ir.attachment')
|
ir_attachment_obj = self.pool.get('ir.attachment')
|
||||||
attach_ids = []
|
attach_ids = []
|
||||||
msg = self.pool.get('mail.thread').message_parse(cr, uid, headers)
|
msg = self.pool.get('mail.thread').message_parse(cr, uid, headers)
|
||||||
message_id = msg.get('message-id')
|
message_id = msg.get('message_id')
|
||||||
push_mail = self.push_message(cr, uid, model, headers, res_id)
|
push_mail = self.push_message(cr, uid, model, headers, res_id)
|
||||||
res_id = push_mail[1]
|
res_id = push_mail[1]
|
||||||
model = push_mail[0]
|
model = push_mail[0]
|
||||||
|
@ -165,6 +176,6 @@ class plugin_handler(osv.osv_memory):
|
||||||
attach_ids.append(ir_attachment_obj.create(cr, uid, vals))
|
attach_ids.append(ir_attachment_obj.create(cr, uid, vals))
|
||||||
mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)])
|
mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)])
|
||||||
if mail_ids:
|
if mail_ids:
|
||||||
mail_message.write(cr, uid, mail_ids[0], {'attachment_ids': [(6, 0, attach_ids)], 'body': body, 'body_html': body_html})
|
mail_message.write(cr, uid, mail_ids[0], {'attachment_ids': [(6, 0, attach_ids)], 'body': body_html})
|
||||||
url = self._make_url(cr, uid, res_id, model)
|
url = self._make_url(cr, uid, res_id, model)
|
||||||
return (model, res_id, url, notify)
|
return (model, res_id, url, notify)
|
||||||
|
|
|
@ -52,6 +52,7 @@ class project_compute_phases(osv.osv_memory):
|
||||||
else:
|
else:
|
||||||
project_ids = project_pool.search(cr, uid, [('user_id','=',uid)], context=context)
|
project_ids = project_pool.search(cr, uid, [('user_id','=',uid)], context=context)
|
||||||
|
|
||||||
|
if project_ids:
|
||||||
project_pool.schedule_phases(cr, uid, project_ids, context=context)
|
project_pool.schedule_phases(cr, uid, project_ids, context=context)
|
||||||
return self._open_phases_list(cr, uid, data, context=context)
|
return self._open_phases_list(cr, uid, data, context=context)
|
||||||
|
|
||||||
|
|
|
@ -695,7 +695,7 @@ class purchase_order(osv.osv):
|
||||||
continue
|
continue
|
||||||
if order_line.product_id.type in ('product', 'consu'):
|
if order_line.product_id.type in ('product', 'consu'):
|
||||||
move = stock_move.create(cr, uid, self._prepare_order_line_move(cr, uid, order, order_line, picking_id, context=context))
|
move = stock_move.create(cr, uid, self._prepare_order_line_move(cr, uid, order, order_line, picking_id, context=context))
|
||||||
if order_line.move_dest_id:
|
if order_line.move_dest_id and order_line.move_dest_id.state != 'done':
|
||||||
order_line.move_dest_id.write({'location_id': order.location_id.id})
|
order_line.move_dest_id.write({'location_id': order.location_id.id})
|
||||||
todo_moves.append(move)
|
todo_moves.append(move)
|
||||||
stock_move.action_confirm(cr, uid, todo_moves)
|
stock_move.action_confirm(cr, uid, todo_moves)
|
||||||
|
@ -909,6 +909,15 @@ class purchase_order_line(osv.osv):
|
||||||
default.update({'state':'draft', 'move_ids':[],'invoiced':0,'invoice_lines':[]})
|
default.update({'state':'draft', 'move_ids':[],'invoiced':0,'invoice_lines':[]})
|
||||||
return super(purchase_order_line, self).copy_data(cr, uid, id, default, context)
|
return super(purchase_order_line, self).copy_data(cr, uid, id, default, context)
|
||||||
|
|
||||||
|
def unlink(self, cr, uid, ids, context=None):
|
||||||
|
procurement_ids_to_cancel = []
|
||||||
|
for line in self.browse(cr, uid, ids, context=context):
|
||||||
|
if line.move_dest_id:
|
||||||
|
procurement_ids_to_cancel.extend(procurement.id for procurement in line.move_dest_id.procurements)
|
||||||
|
if procurement_ids_to_cancel:
|
||||||
|
self.pool['procurement.order'].action_cancel(cr, uid, procurement_ids_to_cancel)
|
||||||
|
return super(purchase_order_line, self).unlink(cr, uid, ids, context=context)
|
||||||
|
|
||||||
def onchange_product_uom(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
|
def onchange_product_uom(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
|
||||||
partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
|
partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
|
||||||
name=False, price_unit=False, context=None):
|
name=False, price_unit=False, context=None):
|
||||||
|
|
|
@ -208,7 +208,7 @@
|
||||||
<page string="Purchase Order">
|
<page string="Purchase Order">
|
||||||
<field name="order_line">
|
<field name="order_line">
|
||||||
<tree string="Purchase Order Lines" editable="bottom">
|
<tree string="Purchase Order Lines" editable="bottom">
|
||||||
<field name="product_id" on_change="onchange_product_id(parent.pricelist_id,product_id,0,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
|
<field name="product_id" on_change="onchange_product_id(parent.pricelist_id,product_id,0,False,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="date_planned"/>
|
<field name="date_planned"/>
|
||||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||||
|
@ -387,7 +387,7 @@
|
||||||
<sheet>
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="product_id" on_change="onchange_product_id(parent.pricelist_id,product_id,0,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
|
<field name="product_id" on_change="onchange_product_id(parent.pricelist_id,product_id,0,False,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
|
||||||
<label for="product_qty"/>
|
<label for="product_qty"/>
|
||||||
<div>
|
<div>
|
||||||
<field name="product_qty" on_change="onchange_product_id(parent.pricelist_id,product_id,product_qty,product_uom,parent.partner_id,parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)" class="oe_inline"/>
|
<field name="product_qty" on_change="onchange_product_id(parent.pricelist_id,product_id,product_qty,product_uom,parent.partner_id,parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)" class="oe_inline"/>
|
||||||
|
|
|
@ -24,3 +24,13 @@
|
||||||
!python {model: procurement.order}: |
|
!python {model: procurement.order}: |
|
||||||
procurement = self.browse(cr, uid, ref('procurement_order_testcase0'))
|
procurement = self.browse(cr, uid, ref('procurement_order_testcase0'))
|
||||||
assert procurement.purchase_id, 'RFQ should be generated!'
|
assert procurement.purchase_id, 'RFQ should be generated!'
|
||||||
|
-
|
||||||
|
I delete the line from the purchase order and check that the move and the procurement are cancelled
|
||||||
|
-
|
||||||
|
!python {model: procurement.order}: |
|
||||||
|
procurement = self.browse(cr, uid, ref('procurement_order_testcase0'))
|
||||||
|
move = procurement.purchase_id.order_line[0].move_dest_id
|
||||||
|
procurement.purchase_id.order_line[0].unlink()
|
||||||
|
assert move.state == 'cancel', 'Move should be cancelled'
|
||||||
|
procurement.refresh()
|
||||||
|
assert procurement.state == 'cancel', 'Procurement should be cancelled'
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
<field name="product_id"
|
<field name="product_id"
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
||||||
groups="base.group_user"
|
groups="base.group_user"
|
||||||
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
|
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, False, product_uos_qty, False, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
|
||||||
<label for="product_uom_qty"/>
|
<label for="product_uom_qty"/>
|
||||||
<div>
|
<div>
|
||||||
<field
|
<field
|
||||||
|
@ -169,7 +169,7 @@
|
||||||
<field name="product_id"
|
<field name="product_id"
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
||||||
groups="base.group_user"
|
groups="base.group_user"
|
||||||
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
|
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, False, product_uos_qty, False, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="product_uom_qty"
|
<field name="product_uom_qty"
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
<field name="product_id"
|
<field name="product_id"
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
||||||
groups="base.group_user"
|
groups="base.group_user"
|
||||||
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, True, parent.date_order, product_packaging, parent.fiscal_position, False, context)"/>
|
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,False,product_uos_qty,False,name,parent.partner_id, False, True, parent.date_order, product_packaging, parent.fiscal_position, False, context)"/>
|
||||||
</field>
|
</field>
|
||||||
<field name="product_uom_qty" position="replace">
|
<field name="product_uom_qty" position="replace">
|
||||||
<field context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
<field context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'uom':product_uom}"
|
||||||
|
|
|
@ -90,13 +90,14 @@ class product_product(osv.osv):
|
||||||
stock_output_acc = datas.get('stock_output_account', False)
|
stock_output_acc = datas.get('stock_output_account', False)
|
||||||
stock_input_acc = datas.get('stock_input_account', False)
|
stock_input_acc = datas.get('stock_input_account', False)
|
||||||
journal_id = datas.get('stock_journal', False)
|
journal_id = datas.get('stock_journal', False)
|
||||||
product_obj=self.browse(cr, uid, ids, context=context)[0]
|
|
||||||
account_valuation = product_obj.categ_id.property_stock_valuation_account_id
|
|
||||||
account_valuation_id = account_valuation and account_valuation.id or False
|
|
||||||
if not account_valuation_id: raise osv.except_osv(_('Error!'), _('Specify valuation Account for Product Category: %s.') % (product_obj.categ_id.name))
|
|
||||||
move_ids = []
|
move_ids = []
|
||||||
loc_ids = location_obj.search(cr, uid,[('usage','=','internal')])
|
loc_ids = location_obj.search(cr, uid,[('usage','=','internal')])
|
||||||
for rec_id in ids:
|
for product in self.browse(cr, uid, ids, context=context):
|
||||||
|
if product.valuation != 'real_time':
|
||||||
|
continue
|
||||||
|
account_valuation = product.categ_id.property_stock_valuation_account_id
|
||||||
|
account_valuation_id = account_valuation and account_valuation.id or False
|
||||||
|
if not account_valuation_id: raise osv.except_osv(_('Error!'), _('Specify valuation Account for Product Category: %s.') % (product.categ_id.name))
|
||||||
for location in location_obj.browse(cr, uid, loc_ids, context=context):
|
for location in location_obj.browse(cr, uid, loc_ids, context=context):
|
||||||
c = context.copy()
|
c = context.copy()
|
||||||
c.update({
|
c.update({
|
||||||
|
@ -104,7 +105,6 @@ class product_product(osv.osv):
|
||||||
'compute_child': False
|
'compute_child': False
|
||||||
})
|
})
|
||||||
|
|
||||||
product = self.browse(cr, uid, rec_id, context=c)
|
|
||||||
qty = product.qty_available
|
qty = product.qty_available
|
||||||
diff = product.standard_price - new_price
|
diff = product.standard_price - new_price
|
||||||
if not diff: raise osv.except_osv(_('Error!'), _("No difference between standard price and new price!"))
|
if not diff: raise osv.except_osv(_('Error!'), _("No difference between standard price and new price!"))
|
||||||
|
@ -182,8 +182,7 @@ class product_product(osv.osv):
|
||||||
'debit': amount_diff,
|
'debit': amount_diff,
|
||||||
'move_id': move_id
|
'move_id': move_id
|
||||||
})
|
})
|
||||||
|
self.write(cr, uid, ids, {'standard_price': new_price})
|
||||||
self.write(cr, uid, rec_id, {'standard_price': new_price})
|
|
||||||
|
|
||||||
return move_ids
|
return move_ids
|
||||||
|
|
||||||
|
|
|
@ -2625,7 +2625,7 @@ class stock_move(osv.osv):
|
||||||
quantity = move.product_qty
|
quantity = move.product_qty
|
||||||
|
|
||||||
uos_qty = quantity / move_qty * move.product_uos_qty
|
uos_qty = quantity / move_qty * move.product_uos_qty
|
||||||
if quantity_rest > 0:
|
if float_compare(quantity_rest, 0, precision_rounding=move.product_id.uom_id.rounding):
|
||||||
default_val = {
|
default_val = {
|
||||||
'product_qty': quantity,
|
'product_qty': quantity,
|
||||||
'product_uos_qty': uos_qty,
|
'product_uos_qty': uos_qty,
|
||||||
|
|
Loading…
Reference in New Issue