[MERGE] Forward port of addons 7.0 until 8584.
bzr revid: tde@openerp.com-20130115100302-rhhla88naie18hug bzr revid: tde@openerp.com-20130115141932-60y8i1mbi2x88ess
This commit is contained in:
commit
1f050cd40e
|
@ -1137,9 +1137,11 @@ class account_move_line(osv.osv):
|
|||
if context is None:
|
||||
context = {}
|
||||
if vals.get('move_id', False):
|
||||
company_id = self.pool.get('account.move').read(cr, uid, vals['move_id'], ['company_id']).get('company_id', False)
|
||||
if company_id:
|
||||
vals['company_id'] = company_id[0]
|
||||
move = self.pool.get('account.move').browse(cr, uid, vals['move_id'], context=context)
|
||||
if move.company_id:
|
||||
vals['company_id'] = move.company_id.id
|
||||
if move.date and not vals.get('date'):
|
||||
vals['date'] = move.date
|
||||
if ('account_id' in vals) and not account_obj.read(cr, uid, vals['account_id'], ['active'])['active']:
|
||||
raise osv.except_osv(_('Bad Account!'), _('You cannot use an inactive account.'))
|
||||
if 'journal_id' in vals and vals['journal_id']:
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
<label for="quantity_max"/>
|
||||
<div>
|
||||
<field name="quantity_max"/>
|
||||
<div attrs="{'invisible': [('quantity','=',0)]}" class="oe_grey">
|
||||
<field name="quantity" class="oe_inline"/> Units Done
|
||||
<div attrs="{'invisible': [('hours_quantity','=',0)]}" class="oe_grey">
|
||||
<field name="hours_quantity" class="oe_inline"/> Units Consumed
|
||||
</div>
|
||||
<div attrs="{'invisible': [('quantity_max','=',0)]}" class="oe_grey">
|
||||
<field name="remaining_hours" class="oe_inline"/> Units Remaining
|
||||
|
|
|
@ -166,8 +166,8 @@ class res_partner(osv.osv):
|
|||
action_text = partner.latest_followup_level_id_without_lit.manual_action_note or ''
|
||||
|
||||
#Check date: put the minimum date if it existed already
|
||||
action_date = (partner.payment_next_action_date and min(partner.payment_next_action_date, fields.date.context_today(cr, uid, context))
|
||||
) or fields.date.context_today(cr, uid, context)
|
||||
action_date = (partner.payment_next_action_date and min(partner.payment_next_action_date, fields.date.context_today(self, cr, uid, context=context))
|
||||
) or fields.date.context_today(self, cr, uid, context=context)
|
||||
|
||||
# Check responsible: if partner has not got a responsible already, take from follow-up
|
||||
responsible_id = False
|
||||
|
@ -218,9 +218,9 @@ class res_partner(osv.osv):
|
|||
unknown_mails = unknown_mails + 1
|
||||
action_text = _("Email not sent because of email address of partner not filled in")
|
||||
if partner.payment_next_action_date:
|
||||
payment_action_date = min(fields.date.context_today(cr, uid, ctx), partner.payment_next_action_date)
|
||||
payment_action_date = min(fields.date.context_today(self, cr, uid, context=ctx), partner.payment_next_action_date)
|
||||
else:
|
||||
payment_action_date = fields.date.context_today(cr, uid, ctx)
|
||||
payment_action_date = fields.date.context_today(self, cr, uid, context=ctx)
|
||||
if partner.payment_next_action:
|
||||
payment_next_action = partner.payment_next_action + " \n " + action_text
|
||||
else:
|
||||
|
@ -242,7 +242,7 @@ class res_partner(osv.osv):
|
|||
followup_table = ''
|
||||
if partner.unreconciled_aml_ids:
|
||||
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
|
||||
current_date = fields.date.context_today(cr, uid, context)
|
||||
current_date = fields.date.context_today(self, cr, uid, context=context)
|
||||
rml_parse = account_followup_print.report_rappel(cr, uid, "followup_rml_parser")
|
||||
final_res = rml_parse._lines_get_with_partner(partner, company.id)
|
||||
|
||||
|
@ -311,7 +311,7 @@ class res_partner(osv.osv):
|
|||
'''
|
||||
res = {}
|
||||
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
|
||||
current_date = fields.date.context_today(cr, uid, context)
|
||||
current_date = fields.date.context_today(self, cr, uid, context=context)
|
||||
for partner in self.browse(cr, uid, ids, context=context):
|
||||
worst_due_date = False
|
||||
amount_due = amount_overdue = 0.0
|
||||
|
|
|
@ -87,12 +87,13 @@ class crm_lead(base_stage, format_address, osv.osv):
|
|||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if not vals.get('stage_id') and vals.get('section_id'):
|
||||
if not vals.get('stage_id'):
|
||||
ctx = context.copy()
|
||||
ctx['default_section_id'] = vals['section_id']
|
||||
if vals.get('section_id'):
|
||||
ctx['default_section_id'] = vals['section_id']
|
||||
if vals.get('type'):
|
||||
ctx['default_type'] = vals['type']
|
||||
vals['stage_id'] = self._get_default_stage_id(cr, uid, context=ctx)
|
||||
elif not vals.get('stage_id') and context.get('default_section_id'):
|
||||
vals['stage_id'] = self._get_default_stage_id(cr, uid, context=context)
|
||||
return super(crm_lead, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def _get_default_section_id(self, cr, uid, context=None):
|
||||
|
@ -974,16 +975,17 @@ class crm_lead(base_stage, format_address, osv.osv):
|
|||
if custom_values is None: custom_values = {}
|
||||
|
||||
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
||||
custom_values.update({
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
'description': desc,
|
||||
'email_from': msg.get('from'),
|
||||
'email_cc': msg.get('cc'),
|
||||
'user_id': False,
|
||||
})
|
||||
}
|
||||
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
|
||||
custom_values['priority'] = msg.get('priority')
|
||||
return super(crm_lead, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
|
||||
defaults['priority'] = msg.get('priority')
|
||||
defaults.update(custom_values)
|
||||
return super(crm_lead, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
||||
""" Overrides mail_thread message_update that is called by the mailgateway
|
||||
|
|
|
@ -190,15 +190,16 @@ class crm_claim(base_stage, osv.osv):
|
|||
"""
|
||||
if custom_values is None: custom_values = {}
|
||||
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
||||
custom_values.update({
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
'description': desc,
|
||||
'email_from': msg.get('from'),
|
||||
'email_cc': msg.get('cc'),
|
||||
})
|
||||
}
|
||||
if msg.get('priority'):
|
||||
custom_values['priority'] = msg.get('priority')
|
||||
return super(crm_claim,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
|
||||
defaults['priority'] = msg.get('priority')
|
||||
defaults.update(custom_values)
|
||||
return super(crm_claim,self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
||||
""" Overrides mail_thread message_update that is called by the mailgateway
|
||||
|
|
|
@ -100,14 +100,15 @@ class crm_helpdesk(base_state, base_stage, osv.osv):
|
|||
"""
|
||||
if custom_values is None: custom_values = {}
|
||||
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
||||
custom_values.update({
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
'description': desc,
|
||||
'email_from': msg.get('from'),
|
||||
'email_cc': msg.get('cc'),
|
||||
'user_id': False,
|
||||
})
|
||||
return super(crm_helpdesk,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
|
||||
}
|
||||
defaults.update(custom_values)
|
||||
return super(crm_helpdesk,self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
||||
""" Overrides mail_thread message_update that is called by the mailgateway
|
||||
|
|
|
@ -347,16 +347,17 @@ class hr_applicant(base_stage, osv.Model):
|
|||
"""
|
||||
if custom_values is None: custom_values = {}
|
||||
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
||||
custom_values.update({
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
'description': desc,
|
||||
'email_from': msg.get('from'),
|
||||
'email_cc': msg.get('cc'),
|
||||
'user_id': False,
|
||||
})
|
||||
}
|
||||
if msg.get('priority'):
|
||||
custom_values['priority'] = msg.get('priority')
|
||||
return super(hr_applicant,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
|
||||
defaults['priority'] = msg.get('priority')
|
||||
defaults.update(custom_values)
|
||||
return super(hr_applicant,self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
||||
""" Override mail_thread message_update that is called by the mailgateway
|
||||
|
|
|
@ -107,6 +107,7 @@ class lunch_order(osv.Model):
|
|||
elif alert.alter_type == 'week':
|
||||
#the alert is activated during some days of the week
|
||||
return self.check_day(alert)
|
||||
return True # alter_type == 'days' (every day)
|
||||
|
||||
def _default_alerts_get(self, cr, uid, context=None):
|
||||
"""
|
||||
|
|
|
@ -66,7 +66,7 @@ class mail_alias(osv.Model):
|
|||
'alias_name': fields.char('Alias', required=True,
|
||||
help="The name of the email alias, e.g. 'jobs' "
|
||||
"if you want to catch emails for <jobs@example.my.openerp.com>",),
|
||||
'alias_model_id': fields.many2one('ir.model', 'Aliased Model', required=True,
|
||||
'alias_model_id': fields.many2one('ir.model', 'Aliased Model', required=True, ondelete="cascade",
|
||||
help="The model (OpenERP Document Kind) to which this alias "
|
||||
"corresponds. Any incoming email that does not reply to an "
|
||||
"existing record will cause the creation of a new record "
|
||||
|
|
|
@ -78,7 +78,7 @@ class mail_message(osv.Model):
|
|||
for message in self.read(cr, uid, ids, ['model', 'res_id'], context=context):
|
||||
if not message.get('model') or not message.get('res_id') or not self.pool.get(message['model']):
|
||||
continue
|
||||
result[message['id']] = self._shorten_name(self.pool.get(message['model']).name_get(cr, SUPERUSER_ID, [message['res_id']], context=context)[0][1])
|
||||
result[message['id']] = self.pool.get(message['model']).name_get(cr, SUPERUSER_ID, [message['res_id']], context=context)[0][1]
|
||||
return result
|
||||
|
||||
def _get_to_read(self, cr, uid, ids, name, arg, context=None):
|
||||
|
|
|
@ -839,6 +839,7 @@ class mail_thread(osv.AbstractModel):
|
|||
ids = partner_obj.search(cr, SUPERUSER_ID, [('email', '=', email)], context=context)
|
||||
if ids:
|
||||
partner_ids.append(ids[0])
|
||||
partner_id = ids[0]
|
||||
else:
|
||||
partner_id = partner_obj.create(cr, uid, {
|
||||
'name': name or email,
|
||||
|
|
|
@ -62,16 +62,6 @@ class res_users(osv.Model):
|
|||
# create aliases for all users and avoid constraint errors
|
||||
self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(res_users, self)._auto_init,
|
||||
self._columns['alias_id'], 'login', alias_force_key='id', context=context)
|
||||
# make already existing users follow themselves, using SQL to avoid using the ORM during the auto_init
|
||||
cr.execute(""" SELECT p.id FROM res_partner p
|
||||
LEFT JOIN mail_followers n
|
||||
ON (n.partner_id = p.id AND n.res_model = 'res.partner' AND n.res_id = p.id)
|
||||
WHERE n.id IS NULL
|
||||
""")
|
||||
params = [(res[0], res[0]) for res in cr.fetchall()]
|
||||
cr.executemany(""" INSERT INTO mail_followers (partner_id, res_model, res_id)
|
||||
VALUES (%s, 'res.partner', %s)
|
||||
""", params)
|
||||
|
||||
def create(self, cr, uid, data, context=None):
|
||||
# create default alias same as the login
|
||||
|
@ -81,12 +71,11 @@ class res_users(osv.Model):
|
|||
mail_alias = self.pool.get('mail.alias')
|
||||
alias_id = mail_alias.create_unique_alias(cr, uid, {'alias_name': data['login']}, model_name=self._name, context=context)
|
||||
data['alias_id'] = alias_id
|
||||
data.pop('alias_name', None) # prevent errors during copy()
|
||||
data.pop('alias_name', None) # prevent errors during copy()
|
||||
|
||||
# create user that follows its related partner
|
||||
# create user
|
||||
user_id = super(res_users, self).create(cr, uid, data, context=context)
|
||||
user = self.browse(cr, uid, user_id, context=context)
|
||||
self.pool.get('res.partner').message_subscribe(cr, uid, [user.partner_id.id], [user.partner_id.id], context=context)
|
||||
# alias
|
||||
mail_alias.write(cr, SUPERUSER_ID, [alias_id], {"alias_force_thread_id": user_id}, context)
|
||||
# create a welcome message
|
||||
|
@ -150,6 +139,9 @@ class res_users(osv.Model):
|
|||
self.pool.get('res.partner').message_subscribe(cr, uid, [partner_id], partner_ids, subtype_ids=subtype_ids, context=context)
|
||||
return True
|
||||
|
||||
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)
|
||||
|
||||
|
||||
class res_users_mail_group(osv.Model):
|
||||
""" Update of res.users class
|
||||
|
|
|
@ -580,6 +580,9 @@ openerp.mail = function (session) {
|
|||
}
|
||||
});
|
||||
var deferred_check = $.Deferred();
|
||||
if (emails.length == 0) {
|
||||
return deferred_check.resolve(partners_from);
|
||||
}
|
||||
self.parent_thread.ds_thread._model.call('message_create_partners_from_emails', [emails]).then(function (partners) {
|
||||
partners_from = _.clone(partners.partner_ids);
|
||||
var deferreds = [];
|
||||
|
|
|
@ -365,11 +365,3 @@ class test_mail_access_rights(TestMailBase):
|
|||
{'subject': 'Subject', 'body': 'Body text'},
|
||||
{'default_composition_mode': 'reply', 'default_parent_id': pigs_msg_id})
|
||||
mail_compose.send_mail(cr, user_raoul_id, [compose_id])
|
||||
|
||||
# Do: Raoul writes on its own profile, ok because follower of its partner
|
||||
self.res_users.message_post(cr, user_raoul_id, user_raoul_id, body='I love Raoul')
|
||||
self.res_partner.message_post(cr, user_raoul_id, partner_raoul_id, body='I love Raoul')
|
||||
compose_id = mail_compose.create(cr, user_raoul_id,
|
||||
{'subject': 'Subject', 'body': 'Body text', 'partner_ids': []},
|
||||
{'default_composition_mode': 'comment', 'default_model': 'res.users', 'default_res_id': self.user_raoul_id})
|
||||
mail_compose.send_mail(cr, user_raoul_id, [compose_id])
|
||||
|
|
|
@ -1,8 +1,34 @@
|
|||
function openerp_pos_db(instance, module){
|
||||
|
||||
/* PosLS is a LocalStorage based implementation of the point of sale database,
|
||||
it performs better for few products, but does not scale beyond 500 products.
|
||||
*/
|
||||
/* The db module was intended to be used to store all the data needed to run the Point
|
||||
* of Sale in offline mode. (Products, Categories, Orders, ...) It would also use WebSQL
|
||||
* or IndexedDB to make the searching and sorting products faster. It turned out not to be
|
||||
* a so good idea after all.
|
||||
*
|
||||
* First it is difficult to make the Point of Sale truly independant of the server. A lot
|
||||
* of functionality cannot realistically run offline, like generating invoices.
|
||||
*
|
||||
* IndexedDB turned out to be complicated and slow as hell, and loading all the data at the
|
||||
* start made the point of sale take forever to load over small connections.
|
||||
*
|
||||
* LocalStorage has a hard 5.0MB on chrome. For those kind of sizes, it is just better
|
||||
* to put the data in memory and it's not too big to download each time you launch the PoS.
|
||||
*
|
||||
* So at this point we are dropping the support for offline mode, and this module doesn't really
|
||||
* make sense anymore. But if at some point you want to store millions of products and if at
|
||||
* that point indexedDB has improved to the point it is usable, you can just implement this API.
|
||||
*
|
||||
* You would also need to change the way the models are loaded at the start to not reload all your
|
||||
* product data.
|
||||
*/
|
||||
|
||||
/* PosLS is a localstorage based implementation of the point of sale database.
|
||||
* FIXME: The Products definitions and categories are stored on the locastorage even tough they're
|
||||
* always reloaded at launch. This could induce a slowdown because the data needs to be reparsed from
|
||||
* JSON before each operation. If you have a huge amount of products (around 25000) it can also
|
||||
* blow the 5.0MB localstorage limit.
|
||||
*/
|
||||
|
||||
module.PosLS = instance.web.Class.extend({
|
||||
name: 'openerp_pos_ls', //the prefix of the localstorage data
|
||||
limit: 100, // the maximum number of results returned by a search
|
||||
|
@ -110,6 +136,8 @@ function openerp_pos_db(instance, module){
|
|||
},
|
||||
/* saves a record store to the database */
|
||||
save: function(store,data){
|
||||
var str_data = JSON.stringify(data);
|
||||
console.log('Storing '+ Math.round(str_data.length/1024.0)+' KB of data to store: '+store);
|
||||
localStorage[this.name + '_' + store] = JSON.stringify(data);
|
||||
this.cache[store] = data;
|
||||
},
|
||||
|
|
|
@ -438,7 +438,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
// The barcode readers acts as a keyboard, we catch all keyup events and try to find a
|
||||
// barcode sequence in the typed keys, then act accordingly.
|
||||
$('body').delegate('','keyup', function (e){
|
||||
console.log('keyup:'+String.fromCharCode(e.keyCode)+' '+e.keyCode,e);
|
||||
//console.log('keyup:'+String.fromCharCode(e.keyCode)+' '+e.keyCode,e);
|
||||
//We only care about numbers
|
||||
if (e.keyCode >= 48 && e.keyCode < 58){
|
||||
|
||||
|
|
|
@ -125,7 +125,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
return self.fetch('res.partner', ['name','ean13'], [['ean13', '!=', false]]);
|
||||
}).then(function(partners){
|
||||
self.set('partner_list',partners);
|
||||
console.log('Loaded partners:',partners);
|
||||
|
||||
return self.fetch('account.tax', ['amount', 'price_include', 'type']);
|
||||
}).then(function(taxes){
|
||||
|
@ -242,7 +241,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
|
||||
// saves the order locally and try to send it to the backend. 'record' is a bizzarely defined JSON version of the Order
|
||||
push_order: function(record) {
|
||||
console.log('PUSHING NEW ORDER:',record);
|
||||
this.db.add_order(record);
|
||||
this.flush();
|
||||
},
|
||||
|
@ -259,7 +257,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
// it has been confirmed that they have been sent correctly.
|
||||
flush: function() {
|
||||
//TODO make the mutex work
|
||||
console.log('FLUSH');
|
||||
//this makes sure only one _int_flush is called at the same time
|
||||
/*
|
||||
return this.flush_mutex.exec(_.bind(function() {
|
||||
|
@ -275,7 +272,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
var self = this;
|
||||
var orders = this.db.get_orders();
|
||||
self.set('nbr_pending_operations',orders.length);
|
||||
console.log('TRYING TO FLUSH ORDER:',index,'Of',orders.length);
|
||||
|
||||
var order = orders[index];
|
||||
if(!order){
|
||||
|
@ -291,7 +287,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
})
|
||||
.done(function(){
|
||||
//remove from db if success
|
||||
console.log('Order successfully sent');
|
||||
self.db.remove_order(order.id);
|
||||
self._flush(index);
|
||||
});
|
||||
|
|
|
@ -864,6 +864,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.pos.bind('change:selectedOrder', this.change_selected_order, this);
|
||||
this.bindPaymentLineEvents();
|
||||
this.bind_orderline_events();
|
||||
this.paymentlinewidgets = [];
|
||||
},
|
||||
show: function(){
|
||||
this._super();
|
||||
|
@ -932,18 +933,24 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
addPaymentLine: function(newPaymentLine) {
|
||||
var self = this;
|
||||
var x = new module.PaymentlineWidget(null, {
|
||||
var l = new module.PaymentlineWidget(null, {
|
||||
payment_line: newPaymentLine
|
||||
});
|
||||
x.on('delete_payment_line', self, function(r) {
|
||||
l.on('delete_payment_line', self, function(r) {
|
||||
self.deleteLine(r);
|
||||
});
|
||||
x.appendTo(this.$('#paymentlines'));
|
||||
l.appendTo(this.$('#paymentlines'));
|
||||
this.paymentlinewidgets.push(l);
|
||||
this.$('.paymentline-amount input:last').focus();
|
||||
},
|
||||
renderElement: function() {
|
||||
this._super();
|
||||
this.$('#paymentlines').empty();
|
||||
for(var i = 0, len = this.paymentlinewidgets.length; i < len; i++){
|
||||
this.paymentlinewidgets[i].destroy();
|
||||
}
|
||||
this.paymentlinewidgets = [];
|
||||
|
||||
this.currentPaymentLines.each(_.bind( function(paymentLine) {
|
||||
this.addPaymentLine(paymentLine);
|
||||
}, this));
|
||||
|
|
|
@ -165,6 +165,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.set_numpad_state(options.numpadState);
|
||||
this.pos.bind('change:selectedOrder', this.change_selected_order, this);
|
||||
this.bind_orderline_events();
|
||||
this.orderlinewidgets = [];
|
||||
},
|
||||
set_numpad_state: function(numpadState) {
|
||||
if (this.numpadState) {
|
||||
|
@ -210,6 +211,16 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
var self = this;
|
||||
this._super();
|
||||
|
||||
// freeing subwidgets
|
||||
|
||||
if(this.scrollbar){
|
||||
this.scrollbar.destroy();
|
||||
}
|
||||
for(var i = 0, len = this.orderlinewidgets.length; i < len; i++){
|
||||
this.orderlinewidgets[i].destroy();
|
||||
}
|
||||
this.orderlinewidgets = [];
|
||||
|
||||
if(this.display_mode === 'maximized'){
|
||||
$('.point-of-sale .order-container').css({'bottom':'0px'});
|
||||
}else if(this.display_mode === 'actionbar'){
|
||||
|
@ -227,6 +238,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
line.on('order_line_selected', self, self.update_numpad);
|
||||
line.on('order_line_refreshed', self, self.update_summary);
|
||||
line.appendTo($content);
|
||||
self.orderlinewidgets.push(line);
|
||||
}, this));
|
||||
this.update_numpad();
|
||||
this.update_summary();
|
||||
|
@ -571,7 +583,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
var self = this;
|
||||
this._super(parent,options);
|
||||
this.model = options.model;
|
||||
this.product_list = [];
|
||||
this.productwidgets = [];
|
||||
this.weight = options.weight || 0;
|
||||
this.show_scale = options.show_scale || false;
|
||||
this.next_screen = options.next_screen || false;
|
||||
|
@ -584,7 +596,17 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
renderElement: function() {
|
||||
var self = this;
|
||||
this._super();
|
||||
this.product_list = [];
|
||||
|
||||
// free subwidgets memory from previous renders
|
||||
|
||||
for(var i = 0, len = this.productwidgets.length; i < len; i++){
|
||||
this.productwidgets[i].destroy();
|
||||
}
|
||||
this.productwidgets = [];
|
||||
if(this.scrollbar){
|
||||
this.scrollbar.destroy();
|
||||
}
|
||||
|
||||
this.pos.get('products')
|
||||
.chain()
|
||||
.map(function(product) {
|
||||
|
@ -593,7 +615,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
weight: self.weight,
|
||||
click_product_action: self.click_product_action,
|
||||
})
|
||||
self.product_list.push(product);
|
||||
self.productwidgets.push(product);
|
||||
return product;
|
||||
})
|
||||
.invoke('appendTo', this.$('.product-list'));
|
||||
|
|
|
@ -1091,12 +1091,11 @@ class task(base_stage, osv.osv):
|
|||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if not vals.get('stage_id') and vals.get('project_id'):
|
||||
if not vals.get('stage_id'):
|
||||
ctx = context.copy()
|
||||
ctx['default_project_id'] = vals['project_id']
|
||||
if vals.get('project_id'):
|
||||
ctx['default_project_id'] = vals['project_id']
|
||||
vals['stage_id'] = self._get_default_stage_id(cr, uid, context=ctx)
|
||||
elif not vals.get('stage_id') and context.get('default_project_id'):
|
||||
vals['stage_id'] = self._get_default_stage_id(cr, uid, context=context)
|
||||
task_id = super(task, self).create(cr, uid, vals, context=context)
|
||||
self._store_history(cr, uid, [task_id], context=context)
|
||||
return task_id
|
||||
|
@ -1174,11 +1173,12 @@ class task(base_stage, osv.osv):
|
|||
def message_new(self, cr, uid, msg, custom_values=None, context=None):
|
||||
""" Override to updates the document according to the email. """
|
||||
if custom_values is None: custom_values = {}
|
||||
custom_values.update({
|
||||
defaults = {
|
||||
'name': msg.get('subject'),
|
||||
'planned_hours': 0.0,
|
||||
})
|
||||
return super(task,self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
|
||||
}
|
||||
defaults.update(custom_values)
|
||||
return super(task,self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
||||
""" Override to update the task according to the email. """
|
||||
|
|
|
@ -11,12 +11,56 @@
|
|||
<menuitem id="menu_project_management" name="Project" parent="base.menu_main_pm" sequence="1"/>
|
||||
<menuitem id="base.menu_definitions" name="Configuration" parent="base.menu_main_pm" sequence="60"/>
|
||||
|
||||
<record id="view_task_search_form" model="ir.ui.view">
|
||||
<field name="name">project.task.search.form</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Tasks">
|
||||
<field name="name" string="Tasks"/>
|
||||
<field name="categ_ids"/>
|
||||
<separator/>
|
||||
<filter icon="terp-mail-message-new" string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<separator/>
|
||||
<filter name="draft" string="New" domain="[('state','=','draft')]" help="New Tasks" icon="terp-check"/>
|
||||
<filter name="open" string="In Progress" domain="[('state','=','open')]" help="In Progress Tasks" icon="terp-camera_test"/>
|
||||
<filter string="Pending" domain="[('state','=','pending')]" context="{'show_delegated':False}" help="Pending Tasks" icon="terp-gtk-media-pause"/>
|
||||
<separator/>
|
||||
<filter name="My project" string="Project" domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-check"/>
|
||||
<separator/>
|
||||
<filter string="My Tasks" domain="[('user_id','=',uid)]" help="My Tasks" icon="terp-personal"/>
|
||||
<filter string="Unassigned Tasks" domain="[('user_id','=',False)]" help="Unassigned Tasks" icon="terp-personal-"/>
|
||||
<separator/>
|
||||
<filter string="Deadlines" context="{'deadline_visible': False}" domain="[('date_deadline','<>',False)]"
|
||||
help="Show only tasks having a deadline" icon="terp-gnome-cpu-frequency-applet+"/>
|
||||
<field name="project_id"/>
|
||||
<field name="user_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Users" name="group_user_id" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Project" name="group_project_id" icon="terp-folder-violet" domain="[]" context="{'group_by':'project_id'}"/>
|
||||
<filter string="Stage" name="group_stage_id" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Deadline" icon="terp-gnome-cpu-frequency-applet+" domain="[]" context="{'group_by':'date_deadline'}"/>
|
||||
<filter string="Start Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_start'}" groups="base.group_no_one"/>
|
||||
<filter string="End Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_end'}" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="act_project_project_2_project_task_all" model="ir.actions.act_window">
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="name">Tasks</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,graph</field>
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,gantt,graph</field>
|
||||
<field name="context">{'search_default_project_id': [active_id], 'default_project_id': active_id}</field>
|
||||
<field name="search_view_id" ref="view_task_search_form"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new task.
|
||||
</p><p>
|
||||
OpenERP's project management allows you to manage the pipeline
|
||||
of tasks in order to get things done efficiently. You can
|
||||
track progress, discuss on tasks, attach documents, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Project -->
|
||||
|
@ -334,7 +378,6 @@
|
|||
<group>
|
||||
<field name="project_id" on_change="onchange_project(project_id)" context="{'default_use_tasks':1}"/>
|
||||
<field name="user_id" attrs="{'readonly':[('state','in',['done', 'cancelled'])]}" options='{"no_open": True}'/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<field name="planned_hours" widget="float_time"
|
||||
groups="project.group_time_work_estimation_tasks"
|
||||
on_change="onchange_planned(planned_hours, effective_hours)"/>
|
||||
|
@ -394,6 +437,15 @@
|
|||
<field name="sequence"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
</group>
|
||||
<group>
|
||||
<group string="Gantt View">
|
||||
<field name="date_start"/>
|
||||
<field name="date_end"/>
|
||||
</group>
|
||||
<group>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
|
@ -501,8 +553,8 @@
|
|||
<field name="date_deadline" invisible="context.get('deadline_visible',True)"/>
|
||||
<field name="stage_id" invisible="context.get('set_visible',False)"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="date_start" invisible="1" groups="base.group_no_one"/>
|
||||
<field name="date_end" invisible="1" groups="base.group_no_one"/>
|
||||
<field name="date_start" groups="base.group_no_one"/>
|
||||
<field name="date_end" groups="base.group_no_one"/>
|
||||
<field name="progress" widget="progressbar" invisible="context.get('set_visible',False)"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
@ -542,41 +594,6 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_task_search_form" model="ir.ui.view">
|
||||
<field name="name">project.task.search.form</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Tasks">
|
||||
<field name="name" string="Tasks"/>
|
||||
<field name="categ_ids"/>
|
||||
<separator/>
|
||||
<filter icon="terp-mail-message-new" string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<separator/>
|
||||
<filter name="draft" string="New" domain="[('state','=','draft')]" help="New Tasks" icon="terp-check"/>
|
||||
<filter name="open" string="In Progress" domain="[('state','=','open')]" help="In Progress Tasks" icon="terp-camera_test"/>
|
||||
<filter string="Pending" domain="[('state','=','pending')]" context="{'show_delegated':False}" help="Pending Tasks" icon="terp-gtk-media-pause"/>
|
||||
<separator/>
|
||||
<filter name="My project" string="Project" domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-check"/>
|
||||
<separator/>
|
||||
<filter string="My Tasks" domain="[('user_id','=',uid)]" help="My Tasks" icon="terp-personal"/>
|
||||
<filter string="Unassigned Tasks" domain="[('user_id','=',False)]" help="Unassigned Tasks" icon="terp-personal-"/>
|
||||
<separator/>
|
||||
<filter string="Deadlines" context="{'deadline_visible': False}" domain="[('date_deadline','<>',False)]"
|
||||
help="Show only tasks having a deadline" icon="terp-gnome-cpu-frequency-applet+"/>
|
||||
<field name="project_id"/>
|
||||
<field name="user_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Users" name="group_user_id" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Project" name="group_project_id" icon="terp-folder-violet" domain="[]" context="{'group_by':'project_id'}"/>
|
||||
<filter string="Stage" name="group_stage_id" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Deadline" icon="terp-gnome-cpu-frequency-applet+" domain="[]" context="{'group_by':'date_deadline'}"/>
|
||||
<filter string="Start Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_start'}" groups="base.group_no_one"/>
|
||||
<filter string="End Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_end'}" groups="base.group_no_one"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="analytic_account_inherited_form" model="ir.ui.view">
|
||||
<field name="name">account.analytic.account.form.inherit</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
|
@ -593,11 +610,7 @@
|
|||
<record id="action_view_task" model="ir.actions.act_window">
|
||||
<field name="name">Tasks</field>
|
||||
<field name="res_model">project.task</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form,calendar,gantt,graph</field>
|
||||
<field eval="False" name="filter"/>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="view_task_search_form"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
|
|
|
@ -67,12 +67,11 @@ class project_issue(base_stage, osv.osv):
|
|||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if not vals.get('stage_id') and vals.get('project_id'):
|
||||
if not vals.get('stage_id'):
|
||||
ctx = context.copy()
|
||||
ctx['default_project_id'] = vals['project_id']
|
||||
if vals.get('project_id'):
|
||||
ctx['default_project_id'] = vals['project_id']
|
||||
vals['stage_id'] = self._get_default_stage_id(cr, uid, context=ctx)
|
||||
elif not vals.get('stage_id') and context.get('default_project_id'):
|
||||
vals['stage_id'] = self._get_default_stage_id(cr, uid, context=context)
|
||||
return super(project_issue, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def _get_default_project_id(self, cr, uid, context=None):
|
||||
|
@ -497,17 +496,18 @@ class project_issue(base_stage, osv.osv):
|
|||
|
||||
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
||||
|
||||
custom_values.update({
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
'description': desc,
|
||||
'email_from': msg.get('from'),
|
||||
'email_cc': msg.get('cc'),
|
||||
'user_id': False,
|
||||
})
|
||||
}
|
||||
if msg.get('priority'):
|
||||
custom_values['priority'] = msg.get('priority')
|
||||
defaults['priority'] = msg.get('priority')
|
||||
|
||||
res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
|
||||
defaults.update(custom_values)
|
||||
res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
return res_id
|
||||
|
||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
||||
|
|
|
@ -98,13 +98,20 @@ Example: Product: this product is deprecated, do not purchase more than 5.
|
|||
wizard = self.browse(cr, uid, ids)[0]
|
||||
|
||||
if wizard.time_unit:
|
||||
product = ir_model_data.get_object(cr, uid, 'product', 'product_product_consultant')
|
||||
product.write({'uom_id': wizard.time_unit.id, 'uom_po_id': wizard.time_unit.id})
|
||||
product = False
|
||||
try:
|
||||
product = ir_model_data.get_object(cr, uid, 'product', 'product_product_consultant')
|
||||
except:
|
||||
#product with xml_id product_product_consultant has not been found. Don't do anything except logging the exception
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
_logger.warning("Warning, product with xml_id 'product_product_consultant' hasn't been found")
|
||||
if product:
|
||||
product.write({'uom_id': wizard.time_unit.id, 'uom_po_id': wizard.time_unit.id})
|
||||
|
||||
if wizard.module_project and wizard.time_unit:
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||
user.company_id.write({'project_time_mode_id': wizard.time_unit.id})
|
||||
|
||||
return {}
|
||||
|
||||
def onchange_task_work(self, cr, uid, ids, task_work, context=None):
|
||||
|
|
|
@ -38,7 +38,8 @@ openerp.web_analytics = function(instance) {
|
|||
},
|
||||
/*
|
||||
* This method MUST be overriden by saas_demo and saas_trial in order to
|
||||
* set the correct user type. By default, the user connected is local to the DB.
|
||||
* set the correct user type. By default, the user connected is local to
|
||||
* the DB (like in accounts).
|
||||
*/
|
||||
_get_user_type: function() {
|
||||
return 'Local User';
|
||||
|
@ -67,22 +68,28 @@ openerp.web_analytics = function(instance) {
|
|||
* stored in GA. Also other modules can override it to add new custom variables
|
||||
*/
|
||||
initialize_custom: function() {
|
||||
// Track User Access Level, Custom Variable 4 in GA with visitor level scope
|
||||
// Values: 'Admin User', 'Normal User', 'Portal User', 'Anonymous User'
|
||||
_gaq.push(['_setCustomVar', 4, 'User Access Level', this.user_access_level, 1]);
|
||||
|
||||
// Track User Type Conversion, Custom Variable 3 in GA with session level scope
|
||||
// Values: 'Visitor', 'Demo', 'Online Trial', 'Online Paying', 'Local User'
|
||||
_gaq.push(['_setCustomVar', 1, 'User Type Conversion', this._get_user_type(), 2]);
|
||||
|
||||
var self = this;
|
||||
return instance.session.rpc("/web/webclient/version_info", {})
|
||||
.done(function(res) {
|
||||
_gaq.push(['_setCustomVar', 5, 'Version', res.server_version, 3]);
|
||||
// Track User Access Level, Custom Variable 4 in GA with visitor level scope
|
||||
// Values: 'Admin User', 'Normal User', 'Portal User', 'Anonymous User'
|
||||
_gaq.push(['_setCustomVar', 4, 'User Access Level', self.user_access_level, 1]);
|
||||
|
||||
// Track User Type Conversion, Custom Variable 3 in GA with session level scope
|
||||
// Values: 'Visitor', 'Demo', 'Online Trial', 'Online Paying', 'Local User'
|
||||
_gaq.push(['_setCustomVar', 1, 'User Type Conversion', self._get_user_type(), 2]);
|
||||
_gaq.push(['_trackPageview']);
|
||||
return;
|
||||
});
|
||||
},
|
||||
/*
|
||||
* Method called in order to send _trackPageview to GA
|
||||
*/
|
||||
_push_pageview: function(url) {
|
||||
_gaq.push(['_trackPageview', url]);
|
||||
},
|
||||
/*
|
||||
* Method called in order to send _trackEvent to GA
|
||||
*/
|
||||
_push_event: function(options) {
|
||||
|
@ -155,6 +162,7 @@ openerp.web_analytics = function(instance) {
|
|||
'category': r.model,
|
||||
'action': 'form',
|
||||
'label': url,
|
||||
'noninteraction': true,
|
||||
});
|
||||
});
|
||||
this.on('record_saved', self, function(r) {
|
||||
|
@ -163,6 +171,7 @@ openerp.web_analytics = function(instance) {
|
|||
'category': r.model,
|
||||
'action': 'form',
|
||||
'label': url,
|
||||
'noninteraction': true,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -197,6 +206,7 @@ openerp.web_analytics = function(instance) {
|
|||
'category': category,
|
||||
'action': action,
|
||||
'label': url,
|
||||
'noninteraction': true,
|
||||
});
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue