diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 40daace4eda..91e960c97be 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,7 +5,10 @@ Contributing to Odoo
TL;DR
-* Use this [template](https://github.com/odoo/odoo/wiki/Contributing#reporting-issues) when reporting issues, and please search for duplicates first!
-* The issues not linked to pull requests will be handled with a low priority.
+* If you [make a pull request](https://github.com/odoo/odoo/wiki/Contributing#making-pull-requests),
+ do not create an issue! Use the PR description for that
+* Issues are handled with a much lower priority than pull requests
+* Use this [template](https://github.com/odoo/odoo/wiki/Contributing#reporting-issues)
+ when reporting issues. Please search for duplicates first!
* Pull requests must be made against the [correct version](https://github.com/odoo/odoo/wiki/Contributing#against-which-version-should-i-submit-a-patch)
* There are restrictions on the kind of [changes allowed in stable series](https://github.com/odoo/odoo/wiki/Contributing#what-does-stable-mean)
diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index 57adb817be8..d91d7696162 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -1155,9 +1155,10 @@ class account_move_line(osv.osv):
move_ids = set()
for line in self.browse(cr, uid, ids, context=context):
move_ids.add(line.move_id.id)
- context['journal_id'] = line.journal_id.id
- context['period_id'] = line.period_id.id
- result = super(account_move_line, self).unlink(cr, uid, [line.id], context=context)
+ localcontext = dict(context)
+ localcontext['journal_id'] = line.journal_id.id
+ localcontext['period_id'] = line.period_id.id
+ result = super(account_move_line, self).unlink(cr, uid, [line.id], context=localcontext)
move_ids = list(move_ids)
if check and move_ids:
move_obj.validate(cr, uid, move_ids, context=context)
diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py
index ef6767713b6..aa31a536df1 100644
--- a/addons/calendar/calendar.py
+++ b/addons/calendar/calendar.py
@@ -125,9 +125,9 @@ class calendar_attendee(osv.Model):
def ics_datetime(idate, allday=False):
if idate:
if allday:
- return datetime.strptime(idate.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT).replace(tzinfo=pytz.timezone('UTC'))
+ return openerp.fields.Date.from_string(idate)
else:
- return datetime.strptime(idate.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT).replace(tzinfo=pytz.timezone('UTC'))
+ return openerp.fields.Datetime.from_string(idate).replace(tzinfo=pytz.timezone('UTC'))
return False
try:
@@ -374,12 +374,12 @@ class calendar_alarm_manager(osv.AbstractModel):
tuple_params += (partner_id, )
#Add filter on hours
- tuple_params += (seconds, seconds,)
+ tuple_params += (seconds,)
cr.execute("""SELECT *
FROM ( %s WHERE cal.active = True ) AS ALL_EVENTS
WHERE ALL_EVENTS.first_alarm < (now() at time zone 'utc' + interval '%%s' second )
- AND ALL_EVENTS.last_alarm > (now() at time zone 'utc' - interval '%%s' second )
+ AND ALL_EVENTS.last_event_date > (now() at time zone 'utc')
""" % base_request, tuple_params)
for event_id, first_alarm, last_alarm, first_meeting, last_meeting, min_duration, max_duration, rule in cr.fetchall():
@@ -396,20 +396,30 @@ class calendar_alarm_manager(osv.AbstractModel):
return res
- def do_check_alarm_for_one_date(self, cr, uid, one_date, event, event_maxdelta, in_the_next_X_seconds, after=False, notif=True, mail=True, context=None):
- res = []
- alarm_type = []
+ def do_check_alarm_for_one_date(self, cr, uid, one_date, event, event_maxdelta, in_the_next_X_seconds, after=False, notif=True, mail=True, missing=False, context=None):
+ # one_date: date of the event to check (not the same that in the event browse if recurrent)
+ # event: Event browse record
+ # event_maxdelta: biggest duration from alarms for this event
+ # in_the_next_X_seconds: looking in the future (in seconds)
+ # after: if not False: will return alert if after this date (date as string - todo: change in master)
+ # missing: if not False: will return alert even if we are too late
+ # notif: Looking for type notification
+ # mail: looking for type email
+ res = []
+
+ # TODO: replace notif and email in master by alarm_type + remove event_maxdelta and if using it
+ alarm_type = []
if notif:
alarm_type.append('notification')
if mail:
alarm_type.append('email')
- if one_date - timedelta(minutes=event_maxdelta) < datetime.now() + timedelta(seconds=in_the_next_X_seconds): # if an alarm is possible for this date
+ if one_date - timedelta(minutes=(missing and 0 or event_maxdelta)) < datetime.now() + timedelta(seconds=in_the_next_X_seconds): # if an alarm is possible for this date
for alarm in event.alarm_ids:
if alarm.type in alarm_type and \
- one_date - timedelta(minutes=alarm.duration_minutes) < datetime.now() + timedelta(seconds=in_the_next_X_seconds) and \
- (not after or one_date - timedelta(minutes=alarm.duration_minutes) > datetime.strptime(after.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT)):
+ one_date - timedelta(minutes=(missing and 0 or alarm.duration_minutes)) < datetime.now() + timedelta(seconds=in_the_next_X_seconds) and \
+ (not after or one_date - timedelta(minutes=alarm.duration_minutes) > openerp.fields.Datetime.from_string(after)):
alert = {
'alarm_id': alarm.id,
'event_id': event.id,
@@ -419,55 +429,53 @@ class calendar_alarm_manager(osv.AbstractModel):
return res
def get_next_mail(self, cr, uid, context=None):
+ now = openerp.fields.Datetime.to_string(datetime.now())
+
+ icp = self.pool['ir.config_parameter']
+ last_notif_mail = icp.get_param(cr, SUPERUSER_ID, 'calendar.last_notif_mail', default=False) or now
+
try:
- cron = self.pool['ir.model.data'].get_object(
- cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context)
+ cron = self.pool['ir.model.data'].get_object(cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context)
except ValueError:
_logger.error("Cron for " + self._name + " can not be identified !")
return False
- if cron.interval_type == "weeks":
- cron_interval = cron.interval_number * 7 * 24 * 60 * 60
- elif cron.interval_type == "days":
- cron_interval = cron.interval_number * 24 * 60 * 60
- elif cron.interval_type == "hours":
- cron_interval = cron.interval_number * 60 * 60
- elif cron.interval_type == "minutes":
- cron_interval = cron.interval_number * 60
- elif cron.interval_type == "seconds":
- cron_interval = cron.interval_number
- else:
- cron_interval = False
+ interval_to_second = {
+ "weeks": 7 * 24 * 60 * 60,
+ "days": 24 * 60 * 60,
+ "hours": 60 * 60,
+ "minutes": 60,
+ "seconds": 1
+ }
- if not cron_interval:
+ if cron.interval_type not in interval_to_second.keys():
_logger.error("Cron delay can not be computed !")
return False
+ cron_interval = cron.interval_number * interval_to_second[cron.interval_type]
+
all_events = self.get_next_potential_limit_alarm(cr, uid, cron_interval, notif=False, context=context)
- for event in all_events: # .values()
- max_delta = all_events[event]['max_duration']
- curEvent = self.pool.get('calendar.event').browse(cr, uid, event, context=context)
+ for curEvent in self.pool.get('calendar.event').browse(cr, uid, all_events.keys(), context=context):
+ max_delta = all_events[curEvent.id]['max_duration']
+
if curEvent.recurrency:
- bFound = False
- LastFound = False
+ at_least_one = False
+ last_found = False
for one_date in self.pool.get('calendar.event').get_recurrent_date_by_event(cr, uid, curEvent, context=context):
in_date_format = one_date.replace(tzinfo=None)
- LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context)
- if LastFound:
- for alert in LastFound:
- self.do_mail_reminder(cr, uid, alert, context=context)
-
- if not bFound: # if it's the first alarm for this recurrent event
- bFound = True
- if bFound and not LastFound: # if the precedent event had an alarm but not this one, we can stop the search for this event
+ last_found = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, 0, after=last_notif_mail, notif=False, missing=True, context=context)
+ for alert in last_found:
+ self.do_mail_reminder(cr, uid, alert, context=context)
+ at_least_one = True # if it's the first alarm for this recurrent event
+ if at_least_one and not last_found: # if the precedent event had an alarm but not this one, we can stop the search for this event
break
else:
in_date_format = datetime.strptime(curEvent.start, DEFAULT_SERVER_DATETIME_FORMAT)
- LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, cron_interval, notif=False, context=context)
- if LastFound:
- for alert in LastFound:
- self.do_mail_reminder(cr, uid, alert, context=context)
+ last_found = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, 0, after=last_notif_mail, notif=False, missing=True, context=context)
+ for alert in last_found:
+ self.do_mail_reminder(cr, uid, alert, context=context)
+ icp.set_param(cr, SUPERUSER_ID, 'calendar.last_notif_mail', now)
def get_next_notif(self, cr, uid, context=None):
ajax_check_every_seconds = 300
@@ -497,7 +505,7 @@ class calendar_alarm_manager(osv.AbstractModel):
break
else:
in_date_format = datetime.strptime(curEvent.start, DEFAULT_SERVER_DATETIME_FORMAT)
- LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, ajax_check_every_seconds, partner.calendar_last_notif_ack, mail=False, context=context)
+ LastFound = self.do_check_alarm_for_one_date(cr, uid, in_date_format, curEvent, max_delta, ajax_check_every_seconds, after=partner.calendar_last_notif_ack, mail=False, context=context)
if LastFound:
for alert in LastFound:
all_notif.append(self.do_notif_reminder(cr, uid, alert, context=context))
@@ -516,6 +524,7 @@ class calendar_alarm_manager(osv.AbstractModel):
cr,
uid,
[att.id for att in event.attendee_ids],
+ email_from=event.user_id.partner_id.email,
template_xmlid='calendar_template_meeting_reminder',
force=True,
context=context
@@ -885,12 +894,12 @@ class calendar_event(osv.Model):
stop_date = values.get('stop_date') or event.stop_date
start_date = values.get('start_date') or event.start_date
if stop_date and start_date:
- diff = datetime.strptime(stop_date.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT) - datetime.strptime(start_date.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
+ diff = openerp.fields.Date.from_string(stop_date) - openerp.fields.Date.from_string(start_date)
elif values.get('stop_datetime') or values.get('start_datetime'):
stop_datetime = values.get('stop_datetime') or event.stop_datetime
start_datetime = values.get('start_datetime') or event.start_datetime
if stop_datetime and start_datetime:
- diff = datetime.strptime(stop_datetime.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT) - datetime.strptime(start_datetime.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT)
+ diff = openerp.fields.Datetime.from_string(stop_datetime) - openerp.fields.Datetime.from_string(start_datetime)
if diff:
duration = float(diff.days) * 24 + (float(diff.seconds) / 3600)
values['duration'] = round(duration, 2)
@@ -1012,7 +1021,7 @@ class calendar_event(osv.Model):
tz = pytz.timezone(user.tz) if user.tz else pytz.utc
if starttime:
- start = datetime.strptime(starttime.split(' ')[0], DEFAULT_SERVER_DATE_FORMAT)
+ start = openerp.fields.Datetime.from_string(starttime)
startdate = tz.localize(start) # Add "+hh:mm" timezone
startdate = startdate.replace(hour=8) # Set 8 AM in localtime
startdate = startdate.astimezone(pytz.utc) # Convert to UTC
@@ -1433,7 +1442,7 @@ class calendar_event(osv.Model):
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)
+ date = openerp.fields.Datetime.from_string(date)
if tz:
timezone = pytz.timezone(tz or 'UTC')
diff --git a/addons/calendar/calendar_data.xml b/addons/calendar/calendar_data.xml
index 71c4e77e289..d23713efca4 100644
--- a/addons/calendar/calendar_data.xml
+++ b/addons/calendar/calendar_data.xml
@@ -38,39 +38,19 @@
days
notification
-
-
-
+
- 15 min mail
-
- minutes
+ 2~3 hours mail
+
+ hours
email
- 30 min mail
-
- minutes
- email
-
-
- 1 hour mail
-
+ 5~6 hours mail
+
hours
email
-
- 2 hours mail
-
- hours
- email
-
-
- 1 day mail
-
- days
- email
-
Customer Meeting
diff --git a/addons/calendar/calendar_view.xml b/addons/calendar/calendar_view.xml
index 155292c3e4e..725a7b7f48e 100644
--- a/addons/calendar/calendar_view.xml
+++ b/addons/calendar/calendar_view.xml
@@ -21,6 +21,27 @@
form
+
+
+
+ Calendar Alarm Tree
+ calendar.alarm
+
+
+
+
+
+
+
+
+
+
+
+ Calendar Alarm
+ calendar.alarm
+ form
+
+
@@ -226,7 +247,6 @@
-
@@ -311,10 +331,13 @@
+
+
-
+
+
Meetings
diff --git a/addons/event_sale/event_sale_data.xml b/addons/event_sale/event_sale_data.xml
index 9c5dae6042b..38e1f2434fb 100644
--- a/addons/event_sale/event_sale_data.xml
+++ b/addons/event_sale/event_sale_data.xml
@@ -1,6 +1,6 @@
-
+
Generic Events
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index b10a118406a..dae2f0d82ce 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -324,6 +324,11 @@ class stock_quant(osv.osv):
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.quant', context=c),
}
+ def init(self, cr):
+ cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('stock_quant_product_location_index',))
+ if not cr.fetchone():
+ cr.execute('CREATE INDEX stock_quant_product_location_index ON stock_quant (product_id, location_id, company_id, qty, in_date, reservation_id)')
+
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True):
''' Overwrite the read_group in order to sum the function field 'inventory_value' in group by'''
res = super(stock_quant, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby, lazy=lazy)
@@ -415,7 +420,12 @@ class stock_quant(osv.osv):
self.move_quants_write(cr, uid, to_move_quants, move, location_to, dest_package_id, context=context)
self.pool.get('stock.move').recalculate_move_state(cr, uid, to_recompute_move_ids, context=context)
if location_to.usage == 'internal':
- if self.search(cr, uid, [('product_id', '=', move.product_id.id), ('qty','<', 0)], limit=1, context=context):
+ # Do manual search for quant to avoid full table scan (order by id)
+ cr.execute("""
+ SELECT 0 FROM stock_quant, stock_location WHERE product_id = %s AND stock_location.id = stock_quant.location_id AND
+ ((stock_location.parent_left >= %s AND stock_location.parent_left < %s) OR stock_location.id = %s) AND qty < 0.0 LIMIT 1
+ """, (move.product_id.id, location_to.parent_left, location_to.parent_right, location_to.id))
+ if cr.fetchone():
for quant in quants_reconcile:
self._quant_reconcile_negative(cr, uid, quant, move, context=context)
@@ -529,7 +539,10 @@ class stock_quant(osv.osv):
return False
qty_round = float_round(qty, precision_rounding=rounding)
new_qty_round = float_round(quant.qty - qty, precision_rounding=rounding)
- new_quant = self.copy(cr, SUPERUSER_ID, quant.id, default={'qty': new_qty_round, 'history_ids': [(4, x.id) for x in quant.history_ids]}, context=context)
+ # Fetch the history_ids manually as it will not do a join with the stock moves then (=> a lot faster)
+ cr.execute("""SELECT move_id FROM stock_quant_move_rel WHERE quant_id = %s""", (quant.id,))
+ res = cr.fetchall()
+ new_quant = self.copy(cr, SUPERUSER_ID, quant.id, default={'qty': new_qty_round, 'history_ids': [(4, x[0]) for x in res]}, context=context)
self.write(cr, SUPERUSER_ID, quant.id, {'qty': qty_round}, context=context)
return self.browse(cr, uid, new_quant, context=context)
@@ -1858,6 +1871,10 @@ class stock_move(osv.osv):
'You try to move a product using a UoM that is not compatible with the UoM of the product moved. Please use an UoM in the same UoM category.',
['product_uom']),
]
+ def init(self, cr):
+ cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('stock_move_product_location_index',))
+ if not cr.fetchone():
+ cr.execute('CREATE INDEX stock_move_product_location_index ON stock_move (product_id, location_id, location_dest_id, company_id, state)')
@api.cr_uid_ids_context
def do_unreserve(self, cr, uid, move_ids, context=None):
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index 755d11061cd..62d7d0c745d 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -1250,7 +1250,7 @@ instance.web.Client = instance.web.Widget.extend({
this.crashmanager = new instance.web.CrashManager();
instance.session.on('error', this.crashmanager, this.crashmanager.rpc_error);
self.notification = new instance.web.Notification(this);
- self.notification.appendTo(self.$el);
+ self.notification.appendTo(self.$el.find('.openerp'));
self.loading = new instance.web.Loading(self);
self.loading.appendTo(self.$('.openerp_webclient_container'));
self.action_manager = new instance.web.ActionManager(self);
diff --git a/addons/website/tests/test_crawl.py b/addons/website/tests/test_crawl.py
index 7078a8c79d0..52865e23a2a 100644
--- a/addons/website/tests/test_crawl.py
+++ b/addons/website/tests/test_crawl.py
@@ -1,15 +1,12 @@
# -*- coding: utf-8 -*-
import logging
import urlparse
-import unittest2
-import urllib2
import time
-import werkzeug.urls
import lxml.html
import openerp
-from openerp import tools
+import re
_logger = logging.getLogger(__name__)
@@ -25,12 +22,15 @@ class Crawler(openerp.tests.HttpCase):
post_install = True
def crawl(self, url, seen=None, msg=''):
- if seen == None:
+ if seen == None:
seen = set()
- if url in seen:
+
+ url_slug = re.sub(r"[/](([^/=?&]+-)?[0-9]+)([/]|$)", '//', url)
+ url_slug = re.sub(r"([^/=?&]+)=[^/=?&]+", '\g<1>=param', url_slug)
+ if url_slug in seen:
return seen
else:
- seen.add(url)
+ seen.add(url_slug)
_logger.info("%s %s", msg, url)
r = self.url_open(url)
diff --git a/addons/website_membership/controllers/main.py b/addons/website_membership/controllers/main.py
index c88fb43da9d..942c3f13267 100644
--- a/addons/website_membership/controllers/main.py
+++ b/addons/website_membership/controllers/main.py
@@ -14,18 +14,18 @@ class WebsiteMembership(http.Controller):
@http.route([
'/members',
'/members/page/',
- '/members/association/',
- '/members/association//page/',
+ '/members/association/',
+ '/members/association//page/',
'/members/country/',
'/members/country/-',
'/members/country//page/',
'/members/country/-/page/',
- '/members/association//country/-',
- '/members/association//country/',
- '/members/association//country/-/page/',
- '/members/association//country//page/',
+ '/members/association//country/-',
+ '/members/association//country/',
+ '/members/association//country/-/page/',
+ '/members/association//country//page/',
], type='http', auth="public", website=True)
def members(self, membership_id=None, country_name=None, country_id=0, page=0, **post):
cr, uid, context = request.cr, request.uid, request.context
@@ -38,7 +38,8 @@ class WebsiteMembership(http.Controller):
# base domain for groupby / searches
base_line_domain = [("partner.website_published", "=", True), ('state', 'in', ['free', 'paid'])]
- if membership_id:
+ if membership_id and membership_id != 'free':
+ membership_id = int(membership_id)
base_line_domain.append(('membership_id', '=', membership_id))
membership = product_obj.browse(cr, uid, membership_id, context=context)
else:
@@ -48,9 +49,14 @@ class WebsiteMembership(http.Controller):
('partner.website_description', 'ilike', post_name)]
# group by country, based on all customers (base domain)
- membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, base_line_domain, context=context)
+ if membership_id != 'free':
+ membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, base_line_domain, context=context)
+ country_domain = ('member_lines', 'in', membership_line_ids)
+ else:
+ membership_line_ids = []
+ country_domain = ('free_member', '=', True)
countries = partner_obj.read_group(
- cr, uid, [('member_lines', 'in', membership_line_ids), ("website_published", "=", True)], ["id", "country_id"],
+ cr, uid, [country_domain, ("website_published", "=", True)], ["id", "country_id"],
groupby="country_id", orderby="country_id", context=request.context)
countries_total = sum(country_dict['country_id_count'] for country_dict in countries)
@@ -77,22 +83,38 @@ class WebsiteMembership(http.Controller):
line_domain.append(('membership_id', 'in', membership_ids))
# displayed membership lines
- membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, line_domain, context=context)
+ if membership_id != 'free':
+ membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, line_domain, context=context)
membership_lines = membership_line_obj.browse(cr, uid, membership_line_ids, context=context)
+ # TODO: Following line can be deleted in master. Kept for retrocompatibility.
membership_lines = sorted(membership_lines, key=lambda x: x.membership_id.website_sequence)
partner_ids = [m.partner.id for m in membership_lines]
+ free_partner_ids = partner_obj.search(cr, uid, [('free_member', '=', True), ('website_published', '=', True)], context=context)
google_map_partner_ids = ",".join(map(str, partner_ids))
+ memberships_data = []
+ for membership_record in memberships:
+ memberships_data.append({'id': membership_record.id, 'name': membership_record.name})
+ memberships_partner_ids = {}
+ for line in membership_lines:
+ memberships_partner_ids.setdefault(line.membership_id.id, []).append(line.partner.id)
+ if free_partner_ids:
+ memberships_data.append({'id': 'free', 'name': _('Free Members')})
+ if not membership_id or membership_id == 'free':
+ memberships_partner_ids['free'] = free_partner_ids
- partners = dict((p.id, p) for p in partner_obj.browse(request.cr, SUPERUSER_ID, partner_ids, request.context))
+ partners = dict((p.id, p) for p in partner_obj.browse(request.cr, SUPERUSER_ID, list(set(partner_ids + free_partner_ids)), request.context))
# request pager for lines
pager = request.website.pager(url="/members", total=len(membership_line_ids), page=page, step=self._references_per_page, scope=7, url_args=post)
values = {
'partners': partners,
- 'membership_lines': membership_lines,
- 'memberships': memberships,
- 'membership': membership,
+ 'membership_lines': membership_lines, # TODO: This line can be deleted in master. Kept for retrocompatibility.
+ 'memberships': memberships, # TODO: This line too.
+ 'membership': membership, # TODO: This line too.
+ 'memberships_data': memberships_data,
+ 'memberships_partner_ids': memberships_partner_ids,
+ 'membership_id': membership_id,
'countries': countries,
'current_country': current_country and [current_country['id'], current_country['name']] or None,
'current_country_id': current_country and current_country['id'] or 0,
diff --git a/addons/website_membership/views/website_membership.xml b/addons/website_membership/views/website_membership.xml
index 4f5e98faaf4..a5b5b4af062 100644
--- a/addons/website_membership/views/website_membership.xml
+++ b/addons/website_membership/views/website_membership.xml
@@ -31,10 +31,10 @@
-
+
No result found.
-
-
-
-
+
+
+
+
+
+
+
-
-