diff --git a/addons/account/wizard/account_validate_account_move.py b/addons/account/wizard/account_validate_account_move.py index 297f3445606..7a7a74be04b 100644 --- a/addons/account/wizard/account_validate_account_move.py +++ b/addons/account/wizard/account_validate_account_move.py @@ -34,7 +34,7 @@ class validate_account_move(osv.osv_memory): if context is None: context = {} data = self.read(cr, uid, ids[0], context=context) - ids_move = obj_move.search(cr, uid, [('state','=','draft'),('journal_id','in',tuple(data['journal_ids'])),('period_id','in',tuple(data['period_ids']))]) + ids_move = obj_move.search(cr, uid, [('state','=','draft'),('journal_id','in',tuple(data['journal_ids'])),('period_id','in',tuple(data['period_ids']))], order='date') if not ids_move: raise osv.except_osv(_('Warning!'), _('Specified journals do not have any account move entries in draft state for the specified periods.')) obj_move.button_validate(cr, uid, ids_move, context=context) diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 5d0ed8297c2..771c6e15bd8 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -732,13 +732,17 @@ class account_voucher(osv.osv): total_credit = 0.0 total_debit = 0.0 - account_type = 'receivable' + account_type = None + if context.get('account_id'): + account_type = self.pool['account.account'].browse(cr, uid, context['account_id'], context=context).type if ttype == 'payment': - account_type = 'payable' + if not account_type: + account_type = 'payable' total_debit = price or 0.0 else: total_credit = price or 0.0 - account_type = 'receivable' + if not account_type: + account_type = 'receivable' if not context.get('move_line_ids', False): ids = move_line_pool.search(cr, uid, [('state','=','valid'), ('account_id.type', '=', account_type), ('reconcile_id', '=', False), ('partner_id', '=', partner_id)], context=context) @@ -827,9 +831,9 @@ class account_voucher(osv.osv): else: default['value']['line_dr_ids'].append(rs) - if ttype == 'payment' and len(default['value']['line_cr_ids']) > 0: + if len(default['value']['line_cr_ids']) > 0: default['value']['pre_line'] = 1 - elif ttype == 'receipt' and len(default['value']['line_dr_ids']) > 0: + elif len(default['value']['line_dr_ids']) > 0: default['value']['pre_line'] = 1 default['value']['writeoff_amount'] = self._compute_writeoff_amount(cr, uid, default['value']['line_dr_ids'], default['value']['line_cr_ids'], price, ttype) return default @@ -1662,7 +1666,7 @@ class account_bank_statement_line(osv.osv): def _check_amount(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): if obj.voucher_id: - diff = abs(obj.amount) - obj.voucher_id.amount + diff = abs(obj.amount) - abs(obj.voucher_id.amount) if not self.pool.get('res.currency').is_zero(cr, uid, obj.statement_id.currency, diff): return False return True diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index 288f8ce9332..3e4f1635914 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -213,10 +213,10 @@ - + - + onchange_amount(amount) @@ -230,7 +230,7 @@ - + @@ -241,7 +241,7 @@ - + diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index 1238bc9570f..78cb09001a9 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -285,7 +285,7 @@ openerp.base_import = function (instance) { callback(item_finder(default_value)); }, - + placeholder: _t('Don\'t import'), width: 'resolve', dropdownCssClass: 'oe_import_selector' }); diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml index 97bf3e66f7a..8d7155912e6 100644 --- a/addons/base_import/static/src/xml/import.xml +++ b/addons/base_import/static/src/xml/import.xml @@ -347,8 +347,7 @@ - + diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py index e9ecf70b39b..9b3862508b0 100644 --- a/addons/base_vat/base_vat.py +++ b/addons/base_vat/base_vat.py @@ -126,6 +126,7 @@ class res_partner(osv.osv): continue vat_country, vat_number = self._split_vat(partner.vat) if not check_func(cr, uid, vat_country, vat_number, context=context): + _logger.info(_("Importing VAT Number [%s] is not valid !" % vat_number)) return False return True @@ -149,7 +150,9 @@ class res_partner(osv.osv): vat_no = "'CC##' (CC=Country Code, ##=VAT Number)" if default_vat_check(vat_country, vat_number): vat_no = _ref_vat[vat_country] if vat_country in _ref_vat else vat_no - return '\n' + _('This VAT number does not seem to be valid.\nNote: the expected format is %s') % vat_no + #Retrieve the current partner for wich the VAT is not valid + error_partner = self.browse(cr, uid, ids, context=context) + return '\n' + _('The VAT number [%s] for partner [%s] does not seem to be valid. \nNote: the expected format is %s') % (error_partner[0].vat, error_partner[0].name, vat_no) _constraints = [(check_vat, _construct_constraint_msg, ["vat"])] diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 3dc1fa75b8d..e928432821b 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -714,7 +714,7 @@ class calendar_event(osv.Model): """ Return date and time (from to from) based on duration with timezone in string : eg. - 1) if user add duration for 2 hours, return : August-23-2013 at ( 04-30 To 06-30) (Europe/Brussels) + 1) if user add duration for 2 hours, return : August-23-2013 at (04-30 To 06-30) (Europe/Brussels) 2) if event all day ,return : AllDay, July-31-2013 """ if context is None: @@ -733,7 +733,7 @@ class calendar_event(osv.Model): time = _("AllDay , %s") % (event_date) elif meeting.duration < 24: duration = date + timedelta(hours=meeting.duration) - time = ("%s at ( %s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz) + time = ("%s at (%s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz) else: time = ("%s at %s To\n %s at %s (%s)") % (event_date, display_time, date_deadline.strftime('%B-%d-%Y'), date_deadline.strftime('%H-%M'), tz) return time @@ -1298,9 +1298,14 @@ class calendar_event(osv.Model): invitation['attendee'].append({'name': attendee.cn, 'status': attendee.state}) return invitation - def get_interval(self, cr, uid, ids, date, interval, context=None): + def get_interval(self, cr, uid, ids, date, interval, tz=None, context=None): #Function used only in calendar_event_data.xml for email template date = datetime.strptime(date.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT) + + if tz: + timezone = pytz.timezone(tz or 'UTC') + date = date.replace(tzinfo=pytz.timezone('UTC')).astimezone(timezone) + if interval == 'day': res = str(date.day) elif interval == 'month': @@ -1582,6 +1587,8 @@ class mail_message(osv.Model): return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None): + if context is None: + context = {} if doc_model == 'calendar.event': order = context.get('order', self._order) for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], order=order, context=context): diff --git a/addons/calendar/calendar_data.xml b/addons/calendar/calendar_data.xml index 268c4b96bed..ef413ee3bb5 100644 --- a/addons/calendar/calendar_data.xml +++ b/addons/calendar/calendar_data.xml @@ -147,7 +147,7 @@ ${object.event_id.get_interval(object.event_id.date,'day')}
${object.event_id.get_interval(object.event_id.date, 'month')}
-
${object.event_id.get_interval(object.event_id.date, 'time')}
+
${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}
@@ -212,7 +212,7 @@
: % for attendee in object.event_id.attendee_ids: -
+
% if attendee.cn != object.cn: ${attendee.cn} % else: @@ -227,9 +227,9 @@
@@ -280,7 +280,7 @@ ${object.event_id.get_interval(object.event_id.date,'day')}
${object.event_id.get_interval(object.event_id.date, 'month')}
-
${object.event_id.get_interval(object.event_id.date, 'time')}
+
${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}
@@ -345,7 +345,7 @@
: % for attendee in object.event_id.attendee_ids: -
+
% if attendee.cn != object.cn: ${attendee.cn} % else: @@ -360,9 +360,9 @@
@@ -412,7 +412,7 @@ ${object.event_id.get_interval(object.event_id.date,'day')}
${object.event_id.get_interval(object.event_id.date, 'month')}
-
${object.event_id.get_interval(object.event_id.date, 'time')}
+
${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}
@@ -477,7 +477,7 @@
: % for attendee in object.event_id.attendee_ids: -
+
% if attendee.cn != object.cn: ${attendee.cn} % else: diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 4da0a509ed1..9dfe22202ec 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -241,10 +241,10 @@ class crm_lead(format_address, osv.osv): 'opt_out': fields.boolean('Opt-Out', oldname='optout', help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. " "Filter 'Available for Mass Mailing' allows users to filter the leads when performing mass mailing."), - 'type':fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', help="Type is used to separate Leads and Opportunities"), + 'type': fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', select=True, help="Type is used to separate Leads and Opportunities"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True), 'date_closed': fields.datetime('Closed', readonly=True), - 'stage_id': fields.many2one('crm.case.stage', 'Stage', track_visibility='onchange', + 'stage_id': fields.many2one('crm.case.stage', 'Stage', track_visibility='onchange', select=True, domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"), 'user_id': fields.many2one('res.users', 'Salesperson', select=True, track_visibility='onchange'), 'referred': fields.char('Referred By', size=64), diff --git a/addons/crm_partner_assign/static/src/js/next.js b/addons/crm_partner_assign/static/src/js/next.js deleted file mode 100644 index b3a4fff2732..00000000000 --- a/addons/crm_partner_assign/static/src/js/next.js +++ /dev/null @@ -1,19 +0,0 @@ -openerp.crm_partner_assign = function (instance) { - instance.crm_partner_assign = instance.crm_partner_assign || {}; - instance.crm_partner_assign.next_or_list = function(parent) { - var view = parent.inner_widget.active_view; - var controller = parent.inner_widget.views[view].controller; - if (view === "form"){ - if (controller.dataset.size()) { - controller.execute_pager_action('next'); - } else { - controller.do_action('history_back'); - } - } - controller.do_action({ type: 'ir.actions.act_window_close' }); - if (view === "list"){ - controller.records.remove(controller.records.get(parent.dialog_widget.action.context.active_id)); - } - }; - instance.web.client_actions.add("next_or_list", "instance.crm_partner_assign.next_or_list"); -} \ No newline at end of file diff --git a/addons/crm_partner_assign/wizard/crm_channel_interested.py b/addons/crm_partner_assign/wizard/crm_channel_interested.py index a407ca7b910..a23de29d766 100644 --- a/addons/crm_partner_assign/wizard/crm_channel_interested.py +++ b/addons/crm_partner_assign/wizard/crm_channel_interested.py @@ -63,15 +63,12 @@ class crm_lead_forward_to_partner(osv.TransientModel): if wizard.comment: message += '

%s

' % wizard.comment for active_id in context.get('active_ids', []): - lead_obj.message_post(cr, uid, active_id, body=message, context=context) + lead_obj.message_post(cr, uid, active_id, body=message, subtype="mail.mt_comment", context=context) if values: lead_obj.write(cr, SUPERUSER_ID, context.get('active_ids', []), values) if wizard.interested: for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context): lead_obj.convert_opportunity(cr, SUPERUSER_ID, [lead.id], lead.partner_id and lead.partner_id.id or None, context=None) return { - 'type': 'ir.actions.client', - 'tag': 'next_or_list', - 'params': { - }, + 'type': 'ir.actions.act_window_close', } diff --git a/addons/delivery/sale.py b/addons/delivery/sale.py index dbebd01ef1e..c5d032ca8a8 100644 --- a/addons/delivery/sale.py +++ b/addons/delivery/sale.py @@ -58,20 +58,18 @@ class sale_order(osv.Model): result.update(carrier_id=order.carrier_id.id) return result - def _delivery_unset(self, cr, uid, order, context=None): - line_ids = [line.id for line in order.order_line if line.is_delivery] - self.pool['sale.order.line'].unlink(cr, uid, line_ids, context=context) - order.refresh() - return True + def _delivery_unset(self, cr, uid, ids, context=None): + sale_obj = self.pool['sale.order.line'] + line_ids = sale_obj.search(cr, uid, [('order_id', 'in', ids), ('is_delivery', '=', True)],context=context) + sale_obj.unlink(cr, uid, line_ids, context=context) def delivery_set(self, cr, uid, ids, context=None): line_obj = self.pool.get('sale.order.line') grid_obj = self.pool.get('delivery.grid') carrier_obj = self.pool.get('delivery.carrier') acc_fp_obj = self.pool.get('account.fiscal.position') - + self._delivery_unset(cr, uid, ids, context=context) for order in self.browse(cr, uid, ids, context=context): - self._delivery_unset(cr, uid, order, context=context) grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id) if not grid_id: raise osv.except_osv(_('No Grid Available!'), _('No grid matching for this carrier!')) diff --git a/addons/event/res_partner_view.xml b/addons/event/res_partner_view.xml index 7e97f80e30d..19eb2517131 100644 --- a/addons/event/res_partner_view.xml +++ b/addons/event/res_partner_view.xml @@ -10,6 +10,7 @@ + diff --git a/addons/google_drive/__openerp__.py b/addons/google_drive/__openerp__.py index 8f135c5f9d1..e486c2c2d34 100644 --- a/addons/google_drive/__openerp__.py +++ b/addons/google_drive/__openerp__.py @@ -28,7 +28,6 @@ 'installable': True, 'auto_install': False, 'js': [ - 'static/lib/gapi/client.js', 'static/src/js/gdrive.js', ], 'data': [ diff --git a/addons/google_drive/static/lib/gapi/client.js b/addons/google_drive/static/lib/gapi/client.js deleted file mode 100644 index 7f40ec55ef9..00000000000 --- a/addons/google_drive/static/lib/gapi/client.js +++ /dev/null @@ -1,7 +0,0 @@ -var gapi=window.gapi=window.gapi||{};gapi._bs=new Date().getTime();(function(){var f=null,g=encodeURIComponent,k=window,m=decodeURIComponent,n="push",r="test",t="shift",u="replace",y="length",B="split",C="join";var D=k,E=document,aa=D.location,ba=function(){},ca=/\[native code\]/,G=function(a,b,c){return a[b]=a[b]||c},da=function(a){for(var b=0;bda.call(b,e)&&c[n](e)}return c},sa=function(a){"loading"!=E.readyState?Z(a):E.write("<"+X+' src="'+encodeURI(a)+'">")},Z=function(a){var b=E.createElement(X);b.setAttribute("src",a);b.async="true";(a=E.getElementsByTagName(X)[0])?a.parentNode.insertBefore(b,a):(E.head||E.body||E.documentElement).appendChild(b)},ta=function(a,b){var c=b&&b._c;if(c)for(var d=0;dOrganize your vacancies and applications
-
- - - - -
+

diff --git a/addons/hw_escpos/controllers/main.py b/addons/hw_escpos/controllers/main.py index b6c302aa9e9..938fa064d52 100644 --- a/addons/hw_escpos/controllers/main.py +++ b/addons/hw_escpos/controllers/main.py @@ -54,11 +54,10 @@ class EscposDriver(Thread): return connected def lockedstart(self): - self.lock.acquire() - if not self.isAlive(): - self.daemon = True - self.start() - self.lock.release() + with self.lock: + if not self.isAlive(): + self.daemon = True + self.start() def get_escpos_printer(self): try: diff --git a/addons/hw_scanner/controllers/main.py b/addons/hw_scanner/controllers/main.py index 64daf20fccb..a0f225ab42f 100644 --- a/addons/hw_scanner/controllers/main.py +++ b/addons/hw_scanner/controllers/main.py @@ -88,10 +88,10 @@ class Scanner(Thread): } def lockedstart(self): - self.lock.acquire() - if not self.isAlive(): - self.start() - self.lock.release() + with self.lock: + if not self.isAlive(): + self.daemon = True + self.start() def set_status(self, status, message = None): if status == self.status['status']: diff --git a/addons/l10n_be/account_tax_template.xml b/addons/l10n_be/account_tax_template.xml index 7dfd37b2f40..6958673ae8b 100644 --- a/addons/l10n_be/account_tax_template.xml +++ b/addons/l10n_be/account_tax_template.xml @@ -2052,6 +2052,8 @@ VAT-IN-V82-CAR-EXC-C1 Frais de voiture - VAT 50% Non Deductible + + 0.105 percent diff --git a/addons/l10n_fr/fr_fiscal_templates.xml b/addons/l10n_fr/fr_fiscal_templates.xml index bf49d15e08c..cca96422c22 100644 --- a/addons/l10n_fr/fr_fiscal_templates.xml +++ b/addons/l10n_fr/fr_fiscal_templates.xml @@ -40,11 +40,6 @@ - - - - - @@ -57,22 +52,12 @@ - - - - - - - - - - @@ -91,17 +76,6 @@ - - - - - - - - - - - @@ -124,17 +98,6 @@ - - - - - - - - - - - @@ -146,17 +109,6 @@ - - - - - - - - - - - @@ -177,11 +129,6 @@ - - - - - @@ -194,22 +141,12 @@ - - - - - - - - - - @@ -224,11 +161,6 @@ - - - - - @@ -241,23 +173,12 @@ - - - - - - - - - - - diff --git a/addons/l10n_fr/fr_tax.xml b/addons/l10n_fr/fr_tax.xml index 8633cca7141..22e1e12f03c 100644 --- a/addons/l10n_fr/fr_tax.xml +++ b/addons/l10n_fr/fr_tax.xml @@ -29,28 +29,6 @@ sale - - - - TVA collectée (vente) 19,6% - 19.6 - - percent - - - - - - - - - - - - - - sale - @@ -96,51 +74,7 @@ sale - - - TVA collectée (vente) 7,0% - 7.0 - - percent - - - - - - - - - - - - - - sale - - - - TVA collectée (vente) 5,0% - 5.0 - - percent - - - - - - - - - - - - - - sale - - - TVA collectée (vente) 5,5% 5.5 @@ -208,28 +142,6 @@ purchase - - - TVA déductible (achat) 19,6% - ACH-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA déductible (achat) 8,5% @@ -274,51 +186,7 @@ purchase - - - TVA déductible (achat) 7,0% - ACH-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA déductible (achat) 5,0% - ACH-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA déductible (achat) 5,5% ACH-5.5 @@ -387,29 +255,6 @@ purchase - - - TVA déductible (achat) 19,6% TTC - ACH-19.6-TTC - - - percent - - - - - - - - - - - - - - purchase - - TVA déductible (achat) 8,5% TTC @@ -456,53 +301,7 @@ purchase - - - TVA déductible (achat) 7,0% TTC - ACH-7.0-TTC - - - percent - - - - - - - - - - - - - - purchase - - - - TVA déductible (achat) 5,0% TTC - ACH-5.0-TTC - - - percent - - - - - - - - - - - - - - purchase - - - TVA déductible (achat) 5,5% TTC ACH-5.5-TTC @@ -573,28 +372,6 @@ purchase - - - TVA déd./immobilisation (achat) 19,6% - IMMO-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA déd./immobilisation (achat) 8,5% @@ -639,51 +416,7 @@ purchase - - - TVA déd./immobilisation (achat) 7,0% - IMMO-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA déd./immobilisation (achat) 5,0% - IMMO-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA déd./immobilisation (achat) 5,5% IMMO-5.5 @@ -751,28 +484,6 @@ purchase - - - TVA due s/ acq. intracommunautaire (achat) 19,6% - ACH_UE_due-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA due s/ acq. intracommunautaire (achat) 8,5% @@ -817,51 +528,7 @@ purchase - - - TVA due s/ acq. intracommunautaire (achat) 7,0% - ACH_UE_due-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA due s/ acq. intracommunautaire (achat) 5,0% - ACH_UE_due-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA due s/ acq. intracommunautaire (achat) 5,5% ACH_UE_due-5.5 @@ -925,24 +592,6 @@ purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 19,6% - ACH_UE_ded.-19.6 - - percent - - - - - - - - - - purchase - - TVA déd. s/ acq. intracommunautaire (achat) 8,5% @@ -979,43 +628,7 @@ purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 7,0% - ACH_UE_ded.-7.0 - - percent - - - - - - - - - - purchase - - - - TVA déd. s/ acq. intracommunautaire (achat) 5,0% - ACH_UE_ded.-5.0 - - percent - - - - - - - - - - purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 5,5% ACH_UE_ded.-5.5 diff --git a/addons/l10n_pa/__openerp__.py b/addons/l10n_pa/__openerp__.py index 05e7ad5aefc..792c3de07ea 100644 --- a/addons/l10n_pa/__openerp__.py +++ b/addons/l10n_pa/__openerp__.py @@ -44,8 +44,6 @@ Con la Colaboración de ], "demo_xml": [ ], - "data": [ - ], "active": False, "installable": True, "certificate" : "", diff --git a/addons/mrp/__openerp__.py b/addons/mrp/__openerp__.py index ef68b27a489..cc661f2bf7f 100644 --- a/addons/mrp/__openerp__.py +++ b/addons/mrp/__openerp__.py @@ -76,8 +76,6 @@ Dashboard / Reports for MRP will include: 'views/report_mrpbomstructure.xml', ], 'demo': ['mrp_demo.xml'], - #TODO: This yml tests are needed to be completely reviewed again because the product wood panel is removed in product demo as it does not suit for new demo context of computer and consultant company - # so the ymls are too complex to change at this stage 'test': [ 'test/bom_with_service_type_product.yml', 'test/mrp_users.yml', diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv index 8cfe7b17939..9ddc4324659 100644 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_account_analytic_line_user,account.analytic.line,account.model_account_analytic_line,group_mrp_user,1,1,1,0 access_mrp_workcenter,mrp.workcenter,model_mrp_workcenter,mrp.group_mrp_user,1,0,0,0 access_mrp_routing,mrp.routing,model_mrp_routing,mrp.group_mrp_user,1,0,0,0 access_mrp_routing_workcenter,mrp.routing.workcenter,model_mrp_routing_workcenter,mrp.group_mrp_user,1,0,0,0 diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 99752c864fa..f18edf39e85 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -517,7 +517,8 @@ class pos_order(osv.osv): # Keep only new orders submitted_references = [o['data']['name'] for o in orders] - existing_orders = self.search_read(cr, uid, domain=[('pos_reference', 'in', submitted_references)], fields=['pos_reference'], context=context) + existing_order_ids = self.search(cr, uid, [('pos_reference', 'in', submitted_references)], context=context) + existing_orders = self.read(cr, uid, existing_order_ids, ['pos_reference'], context=context) existing_references = set([o['pos_reference'] for o in existing_orders]) orders_to_save = [o for o in orders if o['data']['name'] not in existing_references] diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 5e3f8b54752..1e7076d9c8f 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -439,7 +439,8 @@ class procurement_order(osv.osv): if len(to_cancel): move_obj.action_cancel(cr, uid, to_cancel) if len(to_assign): - move_obj.write(cr, uid, to_assign, {'state': 'assigned'}) + move_obj.write(cr, uid, to_assign, {'state': 'confirmed'}) + move_obj.action_assign(cr, uid, to_assign) self.write(cr, uid, ids, {'state': 'cancel'}) for id in ids: workflow.trg_trigger(uid, 'procurement.order', id, cr) diff --git a/addons/product_email_template/__openerp__.py b/addons/product_email_template/__openerp__.py index 2fdce7f2889..9b7af6f992b 100644 --- a/addons/product_email_template/__openerp__.py +++ b/addons/product_email_template/__openerp__.py @@ -10,7 +10,7 @@ Add email templates to products to be send on invoice confirmation ================================================================== With this module, link your products to a template to send complete information and tools to your customer. -For instance when invoicing a training, the training agenda and materials will automatically be send to your customers.' +For instance when invoicing a training, the training agenda and materials will automatically be sent to your customers.' """, 'website': 'http://www.openerp.com', 'demo': [ diff --git a/addons/product_email_template/models/product.py b/addons/product_email_template/models/product.py index cafdef7ab9d..6b463ffbeb5 100644 --- a/addons/product_email_template/models/product.py +++ b/addons/product_email_template/models/product.py @@ -13,7 +13,7 @@ class product_template(osv.Model): _columns = { 'email_template_id': fields.many2one( 'email.template', 'Product Email Template', - help='When validating an invoice, an email will be send to the customer' + help='When validating an invoice, an email will be sent to the customer' 'based on this template. The customer will receive an email for each' 'product linked to an email template.'), } diff --git a/addons/project/project.py b/addons/project/project.py index 9dcf069a856..5c6143148d4 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -287,7 +287,9 @@ class project(osv.osv): "- Followers Only: employees see only the followed tasks or issues; if portal\n" " is activated, portal users see the followed tasks or issues."), 'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','Pending'),('close','Closed')], 'Status', required=True,), - 'doc_count':fields.function(_get_attached_docs, string="Number of documents attached", type='int') + 'doc_count': fields.function( + _get_attached_docs, string="Number of documents attached", type='integer' + ) } def _get_type_common(self, cr, uid, context): @@ -723,9 +725,10 @@ class task(osv.osv): context = {} if default is None: default = {} - stage = self._get_default_stage_id(cr, uid, context=context) - if stage: - default['stage_id'] = stage + if not context.get('copy', False): + stage = self._get_default_stage_id(cr, uid, context=context) + if stage: + default['stage_id'] = stage return super(task, self).copy(cr, uid, id, default, context) def _is_template(self, cr, uid, ids, field_name, arg, context=None): @@ -749,7 +752,7 @@ class task(osv.osv): 'description': fields.text('Description'), 'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True), 'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."), - 'stage_id': fields.many2one('project.task.type', 'Stage', track_visibility='onchange', + 'stage_id': fields.many2one('project.task.type', 'Stage', track_visibility='onchange', select=True, domain="[('project_ids', '=', project_id)]"), 'categ_ids': fields.many2many('project.category', string='Tags'), 'kanban_state': fields.selection([('normal', 'Normal'),('blocked', 'Blocked'),('done', 'Ready for next stage')], 'Kanban State', @@ -765,7 +768,7 @@ class task(osv.osv): 'date_end': fields.datetime('Ending Date',select=True), 'date_deadline': fields.date('Deadline',select=True), 'date_last_stage_update': fields.datetime('Last Stage Update', select=True), - 'project_id': fields.many2one('project.project', 'Project', ondelete='set null', select="1", track_visibility='onchange', change_default=True), + 'project_id': fields.many2one('project.project', 'Project', ondelete='set null', select=True, track_visibility='onchange', change_default=True), 'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'), 'child_ids': fields.many2many('project.task', 'project_task_parent_rel', 'parent_id', 'task_id', 'Delegated Tasks'), 'notes': fields.text('Notes'), @@ -791,7 +794,7 @@ class task(osv.osv): 'project.task': (lambda self, cr, uid, ids, c={}: ids, ['work_ids', 'remaining_hours', 'planned_hours'], 10), 'project.task.work': (_get_task, ['hours'], 10), }), - 'user_id': fields.many2one('res.users', 'Assigned to', track_visibility='onchange'), + 'user_id': fields.many2one('res.users', 'Assigned to', select=True, track_visibility='onchange'), 'delegated_user_id': fields.related('child_ids', 'user_id', type='many2one', relation='res.users', string='Delegated To'), 'partner_id': fields.many2one('res.partner', 'Customer'), 'work_ids': fields.one2many('project.task.work', 'task_id', 'Work done'), @@ -1045,7 +1048,7 @@ class task(osv.osv): if vals.get('project_id') and not context.get('default_project_id'): context['default_project_id'] = vals.get('project_id') # user_id change: update date_start - if vals.get('user_id'): + if vals.get('user_id') and not vals.get('start_date'): vals['date_start'] = fields.datetime.now() # context: no_log, because subtype already handle this @@ -1062,7 +1065,7 @@ class task(osv.osv): if 'stage_id' in vals: vals['date_last_stage_update'] = fields.datetime.now() # user_id change: update date_start - if vals.get('user_id'): + if vals.get('user_id') and 'date_start' not in vals: vals['date_start'] = fields.datetime.now() # Overridden to reset the kanban_state to normal whenever diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 08738227f5a..3ee673a4d2f 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -381,7 +381,7 @@ - + diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 84abc33a7e6..bfc65ca7d88 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -264,9 +264,9 @@ class project_issue(osv.Model): 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True), 'version_id': fields.many2one('project.issue.version', 'Version'), 'stage_id': fields.many2one ('project.task.type', 'Stage', - track_visibility='onchange', + track_visibility='onchange', select=True, domain="[('project_ids', '=', project_id)]"), - 'project_id':fields.many2one('project.project', 'Project', track_visibility='onchange'), + 'project_id': fields.many2one('project.project', 'Project', track_visibility='onchange', select=True), 'duration': fields.float('Duration'), 'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]"), 'day_open': fields.function(_compute_day, string='Days to Open', \ diff --git a/addons/purchase/res_config.py b/addons/purchase/res_config.py index 87db14c5a90..0d293631a1a 100644 --- a/addons/purchase/res_config.py +++ b/addons/purchase/res_config.py @@ -62,7 +62,7 @@ class purchase_config_settings(osv.osv_memory): } _defaults = { - 'default_invoice_method': 'manual', + 'default_invoice_method': 'order', } def onchange_purchase_analytic_plans(self, cr, uid, ids, module_purchase_analytic_plans, context=None): diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index 5ce57dab811..319cceb1e1a 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -107,7 +107,7 @@ class purchase_requisition(osv.osv): seller_delay = product_supplier.delay seller_qty = product_supplier.qty supplier_pricelist = supplier.property_product_pricelist_purchase or False - seller_price = pricelist.price_get(cr, uid, [supplier_pricelist.id], product.id, qty, False, {'uom': default_uom_po_id})[supplier_pricelist.id] + seller_price = pricelist.price_get(cr, uid, [supplier_pricelist.id], product.id, qty, supplier.id, {'uom': default_uom_po_id})[supplier_pricelist.id] if seller_qty: qty = max(qty,seller_qty) date_planned = self._planned_date(requisition_line.requisition_id, seller_delay) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 667f15a375d..48b09ec7493 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -500,7 +500,7 @@ class sale_order(osv.osv): lines.append(line.id) created_lines = obj_sale_order_line.invoice_line_create(cr, uid, lines) if created_lines: - invoices.setdefault(o.partner_id.id, []).append((o, created_lines)) + invoices.setdefault(o.partner_invoice_id.id or o.partner_id.id, []).append((o, created_lines)) if not invoices: for o in self.browse(cr, uid, ids, context=context): for i in o.invoice_ids: diff --git a/addons/sale/wizard/sale_line_invoice.py b/addons/sale/wizard/sale_line_invoice.py index cd199760e9e..fa0b46daa7f 100644 --- a/addons/sale/wizard/sale_line_invoice.py +++ b/addons/sale/wizard/sale_line_invoice.py @@ -101,7 +101,6 @@ class sale_order_line_make_invoice(osv.osv_memory): break if flag: workflow.trg_validate(uid, 'sale.order', order.id, 'manual_invoice', cr) - sales_order_obj.write(cr, uid, [order.id], {'state': 'progress'}) if not invoices: raise osv.except_osv(_('Warning!'), _('Invoice cannot be created for this Sales Order Line due to one of the following reasons:\n1.The state of this sales order line is either "draft" or "cancel"!\n2.The Sales Order Line is Invoiced!')) diff --git a/addons/share/res_users.py b/addons/share/res_users.py index 702522478dd..9c9ae0034e2 100644 --- a/addons/share/res_users.py +++ b/addons/share/res_users.py @@ -19,21 +19,7 @@ # ############################################################################## from openerp.osv import fields, osv - -class res_groups(osv.osv): - _name = "res.groups" - _inherit = 'res.groups' - _columns = { - 'share': fields.boolean('Share Group', readonly=True, - help="Group created to set access rights for sharing data with some users.") - } - - def get_application_groups(self, cr, uid, domain=None, context=None): - if domain is None: - domain = [] - domain.append(('share', '=', False)) - return super(res_groups, self).get_application_groups(cr, uid, domain=domain, context=context) - +from openerp import SUPERUSER_ID class res_users(osv.osv): _name = 'res.users' @@ -59,4 +45,28 @@ class res_users(osv.osv): }, help="External user with limited access, created only for the purpose of sharing data."), } + +class res_groups(osv.osv): + _name = "res.groups" + _inherit = 'res.groups' + _columns = { + 'share': fields.boolean('Share Group', readonly=True, + help="Group created to set access rights for sharing data with some users.") + } + + def init(self, cr): + # force re-generation of the user groups view without the shared groups + self.update_user_groups_view(cr, SUPERUSER_ID) + parent_class = super(res_groups, self) + if hasattr(parent_class, 'init'): + parent_class.init(cr) + + def get_application_groups(self, cr, uid, domain=None, context=None): + if domain is None: + domain = [] + domain.append(('share', '=', False)) + return super(res_groups, self).get_application_groups(cr, uid, domain=domain, context=context) + + + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 272e3480fb5..17e34bd6895 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -66,7 +66,7 @@ class ir_http(orm.AbstractModel): def reroute(self, path): if not hasattr(request, 'rerouting'): - request.rerouting = [] + request.rerouting = [request.httprequest.path] if path in request.rerouting: raise Exception("Rerouting loop is forbidden") request.rerouting.append(path) diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py index ef60aefbeff..8916968f7ca 100644 --- a/addons/website/models/ir_qweb.py +++ b/addons/website/models/ir_qweb.py @@ -157,7 +157,7 @@ class DateTime(orm.AbstractModel): value = datetime.datetime.strptime( value, DEFAULT_SERVER_DATETIME_FORMAT) if value: - value = column.context_timestamp( + value = fields.datetime.context_timestamp( cr, uid, timestamp=value, context=context) value = value.strftime(openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT) diff --git a/addons/website_blog/static/description/index.html b/addons/website_blog/static/description/index.html index 1f198c11678..171fe942843 100644 --- a/addons/website_blog/static/description/index.html +++ b/addons/website_blog/static/description/index.html @@ -6,10 +6,7 @@

- - - - +
diff --git a/addons/website_crm/static/description/index.html b/addons/website_crm/static/description/index.html index 897bee4011e..334e6932bf4 100644 --- a/addons/website_crm/static/description/index.html +++ b/addons/website_crm/static/description/index.html @@ -6,10 +6,7 @@
- - - - +
diff --git a/addons/website_event/static/description/index.html b/addons/website_event/static/description/index.html index b47dfc493a8..34669aa4da8 100644 --- a/addons/website_event/static/description/index.html +++ b/addons/website_event/static/description/index.html @@ -6,10 +6,7 @@
- - - - +
diff --git a/addons/website_event_track/static/description/index.html b/addons/website_event_track/static/description/index.html index 2612f75d5d3..1bdcb1edd77 100644 --- a/addons/website_event_track/static/description/index.html +++ b/addons/website_event_track/static/description/index.html @@ -6,10 +6,7 @@
- - - - +
diff --git a/addons/website_hr_recruitment/static/description/index.html b/addons/website_hr_recruitment/static/description/index.html index 7af603b64dc..f1b255a0758 100644 --- a/addons/website_hr_recruitment/static/description/index.html +++ b/addons/website_hr_recruitment/static/description/index.html @@ -6,10 +6,7 @@
- - - - +
diff --git a/addons/website_mail/models/mail_message.py b/addons/website_mail/models/mail_message.py index a376d391a33..1e50611fa00 100644 --- a/addons/website_mail/models/mail_message.py +++ b/addons/website_mail/models/mail_message.py @@ -19,10 +19,10 @@ # ############################################################################## +from openerp import SUPERUSER_ID from openerp.tools import html2plaintext from openerp.tools.translate import _ -from openerp.osv import osv, fields - +from openerp.osv import osv, fields, expression class MailMessage(osv.Model): _inherit = 'mail.message' @@ -63,10 +63,11 @@ class MailMessage(osv.Model): context=None, count=False, access_rights_uid=None): """ Override that adds specific access rights of mail.message, to restrict messages to published messages for public users. """ - group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id - group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_public')[1] - if group_user_id in [group.id for group in group_ids]: - args = ['&', ('website_published', '=', True)] + list(args) + if uid != SUPERUSER_ID: + group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id + group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_public')[1] + if group_user_id in [group.id for group in group_ids]: + args = expression.AND([[('website_published', '=', True)], list(args)]) return super(MailMessage, self)._search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count, access_rights_uid=access_rights_uid) diff --git a/addons/website_mail/models/mail_thread.py b/addons/website_mail/models/mail_thread.py index c88fd032271..d7f750872ca 100644 --- a/addons/website_mail/models/mail_thread.py +++ b/addons/website_mail/models/mail_thread.py @@ -21,7 +21,7 @@ from openerp.osv import osv, fields - +# TODO for trunk, remove me class MailThread(osv.Model): _inherit = 'mail.thread' @@ -35,3 +35,7 @@ class MailThread(osv.Model): help="Website communication history", ), } + + def copy(self, cr, uid, id, default=None, context=None): + default['website_message_ids'] = [] + return super(MailThread, self).copy(cr, uid, id, default=default, context=context) \ No newline at end of file diff --git a/addons/website_quote/models/order.py b/addons/website_quote/models/order.py index f515ef0fd05..3614fd63919 100644 --- a/addons/website_quote/models/order.py +++ b/addons/website_quote/models/order.py @@ -131,6 +131,8 @@ class sale_order(osv.osv): } def onchange_template_id(self, cr, uid, ids, template_id, partner=False, fiscal_position=False, context=None): + if not template_id: + return True lines = [] quote_template = self.pool.get('sale.quote.template').browse(cr, uid, template_id, context=context) for line in quote_template.quote_line: diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 7511e308b95..bdf1ca7eaf2 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -275,6 +275,7 @@ class Ecommerce(http.Controller): all_categories.add(parent) parent = parent.parent_id categories = list(all_categories) + categories.sort(key=lambda x: x.sequence) values = { 'products': products, @@ -584,6 +585,7 @@ class Ecommerce(http.Controller): """ cr, uid, context = request.cr, request.uid, request.context payment_obj = request.registry.get('payment.acquirer') + sale_order_obj = request.registry['sale.order'] # if no sale order at this stage: back to checkout beginning order = self.get_order() @@ -602,30 +604,31 @@ class Ecommerce(http.Controller): else: shipping_partner_id = order.partner_invoice_id.id - values = { - 'order': request.registry['sale.order'].browse(cr, SUPERUSER_ID, order.id, context=context) - } - values.update(request.registry.get('sale.order')._get_website_data(cr, uid, order, context)) + values = {} + values['website_sale_order'] = values['order'] = sale_order_obj.browse(cr, SUPERUSER_ID, order.id, context=context) + values['errors'] = sale_order_obj._get_errors(cr, uid, order, context=context) + values.update(sale_order_obj._get_website_data(cr, uid, order, context=context)) - # fetch all registered payment means - if tx: - acquirer_ids = [tx.acquirer_id.id] - else: - acquirer_ids = payment_obj.search(cr, SUPERUSER_ID, [('website_published', '=', True), '|', ('company_id', '=', order.company_id.id), ('company_id', '=', False)], context=context) - values['acquirers'] = payment_obj.browse(cr, uid, acquirer_ids, context=context) - render_ctx = dict(context, submit_class='btn btn-primary', submit_txt='Pay Now') - for acquirer in values['acquirers']: - render_ctx['tx_url'] = '/shop/payment/transaction/%s' % acquirer.id - acquirer.button = payment_obj.render( - cr, SUPERUSER_ID, acquirer.id, - order.name, - order.amount_total, - order.pricelist_id.currency_id.id, - partner_id=shipping_partner_id, - tx_values={ - 'return_url': '/shop/payment/validate', - }, - context=render_ctx) + if not values['errors']: + # fetch all registered payment means + if tx: + acquirer_ids = [tx.acquirer_id.id] + else: + acquirer_ids = payment_obj.search(cr, SUPERUSER_ID, [('website_published', '=', True), '|', ('company_id', '=', order.company_id.id), ('company_id', '=', False)], context=context) + values['acquirers'] = payment_obj.browse(cr, uid, acquirer_ids, context=context) + render_ctx = dict(context, submit_class='btn btn-primary', submit_txt='Pay Now') + for acquirer in values['acquirers']: + render_ctx['tx_url'] = '/shop/payment/transaction/%s' % acquirer.id + acquirer.button = payment_obj.render( + cr, SUPERUSER_ID, acquirer.id, + order.name, + order.amount_total, + order.pricelist_id.currency_id.id, + partner_id=shipping_partner_id, + tx_values={ + 'return_url': '/shop/payment/validate', + }, + context=render_ctx) return request.website.render("website_sale.payment", values) diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 604b944969d..8d0027337ff 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -16,6 +16,9 @@ class SaleOrder(osv.Model): ), } + def _get_errors(self, cr, uid, order, context=None): + return [] + def _get_website_data(self, cr, uid, order, context): return { 'partner': order.partner_id.id, diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index 0f973c51424..542147a0b2e 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -443,14 +443,20 @@
-
- -
- - Post -
-
+ + Log in to post comments + + +
+ +
+ + + Post +
+
+
@@ -886,6 +892,12 @@
  • Confirmation
  • Validate Order

    + +
    +

    + +
    +
    @@ -973,7 +985,7 @@ -
    +
    diff --git a/addons/website_sale_delivery/controllers/main.py b/addons/website_sale_delivery/controllers/main.py index b5402c3e285..913fbfb76ae 100644 --- a/addons/website_sale_delivery/controllers/main.py +++ b/addons/website_sale_delivery/controllers/main.py @@ -12,11 +12,12 @@ class Ecommerce(Ecommerce): cr, uid, context = request.cr, request.uid, request.context order = self.get_order() carrier_id = post.get('carrier_id') - - if order and carrier_id: - # recompute delivery costs - request.registry['website']._check_carrier_quotation(cr,uid,order,carrier_id,context=context) - return request.redirect("/shop/payment") + if carrier_id: + carrier_id = int(carrier_id) + if order: + request.registry['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=carrier_id, context=context) + if carrier_id: + return request.redirect("/shop/payment") res = super(Ecommerce, self).payment(**post) return res diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 9074e6768ea..c6ac851d9d4 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -56,6 +56,57 @@ class SaleOrder(orm.Model): ), } + def _check_carrier_quotation(self, cr, uid, order, force_carrier_id=None, context=None): + carrier_obj = self.pool.get('delivery.carrier') + + # check to add or remove carrier_id + if not order: + return False + if all(line.product_id.type == "service" for line in order.website_order_line): + order.write({'carrier_id': None}, context=context) + self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, [order.id], context=context) + return True + else: + carrier_id = force_carrier_id or order.carrier_id.id + carrier_ids = self._get_delivery_methods(cr, uid, order, context=context) + if carrier_id: + if carrier_id not in carrier_ids: + carrier_id = False + else: + carrier_ids.remove(carrier_id) + carrier_ids.insert(0, carrier_id) + if force_carrier_id or not carrier_id or not carrier_id in carrier_ids: + for delivery_id in carrier_ids: + grid_id = carrier_obj.grid_get(cr, SUPERUSER_ID, [delivery_id], order.partner_shipping_id.id) + if grid_id: + carrier_id = delivery_id + break + order.write({'carrier_id': carrier_id}, context=context) + if carrier_id: + order.delivery_set(context=context) + else: + order._delivery_unset(context=context) + + return bool(carrier_id) + + def _get_delivery_methods(self, cr, uid, order, context=None): + carrier_obj = self.pool.get('delivery.carrier') + delivery_ids = carrier_obj.search(cr, uid, [('website_published','=',True)], context=context) + # Following loop is done to avoid displaying delivery methods who are not available for this order + # This can surely be done in a more efficient way, but at the moment, it mimics the way it's + # done in delivery_set method of sale.py, from delivery module + for delivery_id in list(delivery_ids): + grid_id = carrier_obj.grid_get(cr, SUPERUSER_ID, [delivery_id], order.partner_shipping_id.id) + if not grid_id: + delivery_ids.remove(delivery_id) + return delivery_ids + + def _get_errors(self, cr, uid, order, context=None): + errors = super(SaleOrder, self)._get_errors(cr, uid, order, context=context) + if not self._get_delivery_methods(cr, uid, order, context=context): + errors.append(('No delivery method available', 'There is no available delivery method for your order')) + return errors + def _get_website_data(self, cr, uid, order, context=None): """ Override to add delivery-related website data. """ values = super(SaleOrder, self)._get_website_data(cr, uid, order, context=context) @@ -69,6 +120,7 @@ class SaleOrder(orm.Model): delivery_ctx = dict(context, order_id=order.id) DeliveryCarrier = self.pool.get('delivery.carrier') - delivery_ids = DeliveryCarrier.search(cr, uid, [('website_published','=',True)], context=context) + delivery_ids = self._get_delivery_methods(cr, uid, order, context=context) + values['deliveries'] = DeliveryCarrier.browse(cr, SUPERUSER_ID, delivery_ids, context=delivery_ctx) return values diff --git a/addons/website_sale_delivery/models/website.py b/addons/website_sale_delivery/models/website.py index 5c4585de17f..efd8b2233d2 100644 --- a/addons/website_sale_delivery/models/website.py +++ b/addons/website_sale_delivery/models/website.py @@ -9,7 +9,7 @@ class Website(orm.Model): def _ecommerce_create_quotation(self, cr, uid, context=None): order_id = super(Website, self)._ecommerce_create_quotation(cr, uid, context=context) order = self.pool['sale.order'].browse(cr, SUPERUSER_ID, order_id, context=context) - self._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) + self.pool['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) return order_id def _ecommerce_add_product_to_cart(self, cr, uid, product_id=0, order_line_id=0, number=1, set_number=-1, context=None): @@ -17,31 +17,4 @@ class Website(orm.Model): product_id=product_id, order_line_id=order_line_id, number=number, set_number=set_number, context=context) order = self.ecommerce_get_current_order(cr, uid, context=context) - return self._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) and quantity or None - - def _check_carrier_quotation(self, cr, uid, order, force_carrier_id=None, context=None): - # check to add or remove carrier_id - carrier_id = False - for line in order.website_order_line: - if line.product_id.type != "service": - carrier_id = True - break - - if not carrier_id: - order.write({'carrier_id': None}, context=context) - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - return True - else: - if order.carrier_id: - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - - carrier_ids = self.pool.get('delivery.carrier').search(cr, uid, [('website_published','=',True)], context=context) - carrier_id = force_carrier_id or (carrier_ids and carrier_ids[0]) - order.write({'carrier_id': carrier_id}, context=context) - #If carrier_id have no grid, we don't have delivery ! - if carrier_id: - order.delivery_set(context=context) - else: - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - - return bool(carrier_id) + return self.pool['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) and quantity or None