diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index 4eca707b863..954e6f0bbce 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -73,7 +73,7 @@
-
+
diff --git a/addons/account/wizard/pos_box.py b/addons/account/wizard/pos_box.py
index ce68d3ec586..8a3e563f94a 100644
--- a/addons/account/wizard/pos_box.py
+++ b/addons/account/wizard/pos_box.py
@@ -40,7 +40,7 @@ class CashBox(osv.osv_memory):
def _create_bank_statement_line(self, cr, uid, box, record, context=None):
values = self._compute_values_for_statement_line(cr, uid, box, record, context=context)
- return self.pool.get('account.bank.statement.line').create(cr, uid, values, context=context)
+ return self.pool.get('account.bank.statement').write(cr, uid, [record.id], {'line_ids': [(0, False, values)]}, context=context)
class CashBoxIn(CashBox):
diff --git a/addons/account_bank_statement_extensions/account_bank_statement.py b/addons/account_bank_statement_extensions/account_bank_statement.py
index 069dff25a1f..d1e85de81d1 100644
--- a/addons/account_bank_statement_extensions/account_bank_statement.py
+++ b/addons/account_bank_statement_extensions/account_bank_statement.py
@@ -39,9 +39,8 @@ class account_bank_statement(osv.osv):
res = super(account_bank_statement, self).write(cr, uid, ids, vals, context=context)
return res
- def button_confirm_bank(self, cr, uid, ids, context=None):
+ def confirm_statement_lines(self, cr, uid, ids, context=None):
bank_statement_line_obj = self.pool.get('account.bank.statement.line')
- super(account_bank_statement, self).button_confirm_bank(cr, uid, ids, context=context)
for st in self.browse(cr, uid, ids, context=context):
if st.line_ids:
line_ids = [l.id for l in st.line_ids]
@@ -51,6 +50,16 @@ class account_bank_statement(osv.osv):
bank_statement_line_obj.invalidate_cache(cr, uid, ['state'], line_ids, context=context)
return True
+ def button_confirm_bank(self, cr, uid, ids, context=None):
+ res = super(account_bank_statement, self).button_confirm_bank(cr, uid, ids, context=context)
+ self.confirm_statement_lines(cr, uid, ids, context=context)
+ return res
+
+ def button_confirm_cash(self, cr, uid, ids, context=None):
+ res = super(account_bank_statement, self).button_confirm_cash(cr, uid, ids, context=context)
+ self.confirm_statement_lines(cr, uid, ids, context=context)
+ return res
+
def button_cancel(self, cr, uid, ids, context=None):
bank_statement_line_obj = self.pool.get('account.bank.statement.line')
super(account_bank_statement, self).button_cancel(cr, uid, ids, context=context)
diff --git a/addons/analytic/models/analytic.py b/addons/analytic/models/analytic.py
index 6edb7b73076..6f6e3c91fda 100644
--- a/addons/analytic/models/analytic.py
+++ b/addons/analytic/models/analytic.py
@@ -252,7 +252,7 @@ class account_analytic_account(osv.osv):
_defaults = {
'type': 'normal',
'company_id': _default_company,
- 'code' : lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'account.analytic.account'),
+ 'code' : lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'account.analytic.account', context=context),
'state': 'open',
'user_id': lambda self, cr, uid, ctx: uid,
'partner_id': lambda self, cr, uid, ctx: ctx.get('partner_id', False),
diff --git a/addons/delivery/delivery.py b/addons/delivery/delivery.py
index 428b00253de..4ac88771d3b 100644
--- a/addons/delivery/delivery.py
+++ b/addons/delivery/delivery.py
@@ -210,6 +210,9 @@ class delivery_grid(osv.osv):
quantity += q
total = (order.amount_total or 0.0) - total_delivery
+ ctx = context.copy()
+ ctx['date'] = order.date_order
+ total = self.pool['res.currency'].compute(cr, uid, order.currency_id.id, order.company_id.currency_id.id, total, context=ctx)
return self.get_price_from_picking(cr, uid, id, total,weight, volume, quantity, context=context)
def get_price_from_picking(self, cr, uid, id, total, weight, volume, quantity, context=None):
diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml
index 6f912d71d17..7db96135ddb 100644
--- a/addons/hr_recruitment/hr_recruitment_view.xml
+++ b/addons/hr_recruitment/hr_recruitment_view.xml
@@ -389,7 +389,7 @@
-
+
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py
index 1dc7e83dc19..6be3ba3b885 100644
--- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py
@@ -201,7 +201,7 @@ class hr_timesheet_sheet(osv.osv):
return (datetime.today() + relativedelta(weekday=0, days=-6)).strftime('%Y-%m-%d')
elif r=='year':
return time.strftime('%Y-01-01')
- return time.strftime('%Y-%m-%d')
+ return fields.date.context_today(self, cr, uid, context)
def _default_date_to(self, cr, uid, context=None):
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
@@ -212,7 +212,7 @@ class hr_timesheet_sheet(osv.osv):
return (datetime.today() + relativedelta(weekday=6)).strftime('%Y-%m-%d')
elif r=='year':
return time.strftime('%Y-12-31')
- return time.strftime('%Y-%m-%d')
+ return fields.date.context_today(self, cr, uid, context)
def _default_employee(self, cr, uid, context=None):
emp_ids = self.pool.get('hr.employee').search(cr, uid, [('user_id','=',uid)], context=context)
@@ -418,8 +418,12 @@ class hr_attendance(osv.osv):
INNER JOIN resource_resource r
ON (e.resource_id = r.id)
ON (a.employee_id = e.id)
- WHERE %(date_to)s >= date_trunc('day', a.name)
- AND %(date_from)s <= a.name
+ LEFT JOIN res_users u
+ ON r.user_id = u.id
+ LEFT JOIN res_partner p
+ ON u.partner_id = p.id
+ WHERE %(date_to)s >= date_trunc('day', a.name AT TIME ZONE 'UTC' AT TIME ZONE coalesce(p.tz, 'UTC'))
+ AND %(date_from)s <= date_trunc('day', a.name AT TIME ZONE 'UTC' AT TIME ZONE coalesce(p.tz, 'UTC'))
AND %(user_id)s = r.user_id
GROUP BY a.id""", {'date_from': ts.date_from,
'date_to': ts.date_to,
diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index 1ac80be885a..219c04b91fe 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -1408,7 +1408,7 @@ class pos_order_line(osv.osv):
}
_defaults = {
- 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'pos.order.line'),
+ 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'pos.order.line', context=context),
'qty': lambda *a: 1,
'discount': lambda *a: 0.0,
'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 24e11fb599d..b48c7b4aea1 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -346,7 +346,7 @@ class purchase_order(osv.osv):
def create(self, cr, uid, vals, context=None):
if vals.get('name','/')=='/':
- vals['name'] = self.pool.get('ir.sequence').next_by_code(cr, uid, 'purchase.order') or '/'
+ vals['name'] = self.pool.get('ir.sequence').next_by_code(cr, uid, 'purchase.order', context=context) or '/'
context = dict(context or {}, mail_create_nolog=True)
order = super(purchase_order, self).create(cr, uid, vals, context=context)
self.message_post(cr, uid, [order], body=_("RFQ created"), context=context)
@@ -1642,7 +1642,7 @@ class procurement_order(osv.osv):
value_lines = self._get_po_line_values_from_procs(cr, uid, procurements, partner, schedule_date, context=context)
line_values += [(0, 0, value_lines[x]) for x in value_lines.keys()]
- name = seq_obj.next_by_code(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name
+ name = seq_obj.next_by_code(cr, uid, 'purchase.order', context=context) or _('PO: %s') % procurement.name
gpo = procurement.rule_id.group_propagation_option
group = (gpo == 'fixed' and procurement.rule_id.group_id.id) or (gpo == 'propagate' and procurement.group_id.id) or False
fp = acc_pos_obj.get_fiscal_position(cr, uid, None, partner.id, context=context)
diff --git a/addons/resource/resource.py b/addons/resource/resource.py
index f3f4d67e9c7..c9429ac07c2 100644
--- a/addons/resource/resource.py
+++ b/addons/resource/resource.py
@@ -30,6 +30,7 @@ from openerp.osv import fields, osv
from openerp.tools.float_utils import float_compare
from openerp.tools.translate import _
from openerp.exceptions import UserError
+import pytz
class resource_calendar(osv.osv):
""" Calendar model for a resource. It has
@@ -345,22 +346,23 @@ class resource_calendar(osv.osv):
return intervals
working_intervals = []
+ tz_info = fields.datetime.context_timestamp(cr, uid, work_dt, context=context).tzinfo
for calendar_working_day in self.get_attendances_for_weekday(cr, uid, id, start_dt, context=context):
if context and context.get('no_round_hours'):
min_from = int((calendar_working_day.hour_from - int(calendar_working_day.hour_from)) * 60)
min_to = int((calendar_working_day.hour_to - int(calendar_working_day.hour_to)) * 60)
- working_interval = (
- work_dt.replace(hour=int(calendar_working_day.hour_from), minute=min_from),
- work_dt.replace(hour=int(calendar_working_day.hour_to), minute=min_to),
- calendar_working_day.id,
- )
+ dt_f = work_dt.replace(hour=int(calendar_working_day.hour_from), minute=min_from)
+ dt_t = work_dt.replace(hour=int(calendar_working_day.hour_to), minute=min_to)
else:
- working_interval = (
- work_dt.replace(hour=int(calendar_working_day.hour_from)),
- work_dt.replace(hour=int(calendar_working_day.hour_to)),
- calendar_working_day.id,
- )
+ dt_f = work_dt.replace(hour=int(calendar_working_day.hour_from))
+ dt_t = work_dt.replace(hour=int(calendar_working_day.hour_to))
+ # adapt tz
+ working_interval = (
+ dt_f.replace(tzinfo=tz_info).astimezone(pytz.UTC).replace(tzinfo=None),
+ dt_t.replace(tzinfo=tz_info).astimezone(pytz.UTC).replace(tzinfo=None),
+ calendar_working_day.id
+ )
working_intervals += self.interval_remove_leaves(cr, uid, working_interval, work_limits, context=context)
# find leave intervals
@@ -620,7 +622,7 @@ class resource_calendar(osv.osv):
for dt_str, hours, calendar_id in date_and_hours_by_cal:
result = self.schedule_hours(
cr, uid, calendar_id, hours,
- day_dt=datetime.datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S').replace(minute=0, second=0),
+ day_dt=datetime.datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S').replace(second=0),
compute_leaves=True, resource_id=resource,
default_interval=(8, 16)
)
diff --git a/addons/resource/tests/test_resource.py b/addons/resource/tests/test_resource.py
index 34eef002a3c..a26fd55caf2 100644
--- a/addons/resource/tests/test_resource.py
+++ b/addons/resource/tests/test_resource.py
@@ -154,13 +154,13 @@ class TestResource(TestResourceCommon):
_format = '%Y-%m-%d %H:%M:%S'
# Test: day0 without leaves: 1 interval
- intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1)
+ intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1, context={'tz': 'UTC'})
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-12 09:08:07', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong working intervals')
# Test: day3 without leaves: 2 interval
- intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date2)
+ intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date2, context={'tz': 'UTC'})
self.assertEqual(len(intervals), 2, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-15 10:11:12', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-15 13:00:00', _format), 'resource_calendar: wrong working intervals')
@@ -168,7 +168,7 @@ class TestResource(TestResourceCommon):
self.assertEqual(intervals[1][1], datetime.strptime('2013-02-15 23:00:00', _format), 'resource_calendar: wrong working intervals')
# Test: day0 with leaves outside range: 1 interval
- intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=0), compute_leaves=True)
+ intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=0), compute_leaves=True, context={'tz': 'UTC'})
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-12 08:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong working intervals')
@@ -177,7 +177,7 @@ class TestResource(TestResourceCommon):
intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id,
start_dt=self.date1.replace(hour=8) + relativedelta(days=7),
end_dt=self.date1.replace(hour=15, minute=45, second=30) + relativedelta(days=7),
- compute_leaves=True)
+ compute_leaves=True, context={'tz': 'UTC'})
self.assertEqual(len(intervals), 2, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-19 08:08:07', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-19 09:00:00', _format), 'resource_calendar: wrong working intervals')
@@ -190,18 +190,18 @@ class TestResource(TestResourceCommon):
_format = '%Y-%m-%d %H:%M:%S'
# Test: day1, beginning at 10:30 -> work from 10:30 (arrival) until 16:00
- intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=10, minute=30, second=0))
+ intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=10, minute=30, second=0), context={'tz': 'UTC'})
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-12 10:30:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong working interval / day computing')
# Test: hour computation for same interval, should give 5.5
- wh = self.resource_calendar.get_working_hours_of_date(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=10, minute=30, second=0))
+ wh = self.resource_calendar.get_working_hours_of_date(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=10, minute=30, second=0), context={'tz': 'UTC'})
self.assertEqual(wh, 5.5, 'resource_calendar: wrong working interval / day time computing')
# Test: day1+7 on leave, without leave computation
intervals = self.resource_calendar.get_working_intervals_of_day(
cr, uid, self.calendar_id,
- start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=7)
+ start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=7), context={'tz': 'UTC'}
)
# Result: day1 (08->16)
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working interval/day computing')
@@ -212,7 +212,7 @@ class TestResource(TestResourceCommon):
intervals = self.resource_calendar.get_working_intervals_of_day(
cr, uid, self.calendar_id,
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=7),
- compute_leaves=True
+ compute_leaves=True, context={'tz': 'UTC'}
)
# Result: day1 (08->09 + 12->16)
self.assertEqual(len(intervals), 2, 'resource_calendar: wrong working interval/day computing')
@@ -225,7 +225,7 @@ class TestResource(TestResourceCommon):
intervals = self.resource_calendar.get_working_intervals_of_day(
cr, uid, self.calendar_id,
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=14),
- compute_leaves=True
+ compute_leaves=True, context={'tz': 'UTC'}
)
# Result: day1 (08->16)
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working interval/day computing')
@@ -237,7 +237,7 @@ class TestResource(TestResourceCommon):
cr, uid, self.calendar_id,
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=14),
compute_leaves=True,
- resource_id=self.resource1_id
+ resource_id=self.resource1_id, context={'tz': 'UTC'}
)
# Result: nothing, because on leave
self.assertEqual(len(intervals), 0, 'resource_calendar: wrong working interval/day computing')
@@ -269,7 +269,7 @@ class TestResource(TestResourceCommon):
# (datetime.datetime(2013, 2, 8, 16, 0), datetime.datetime(2013, 2, 8, 23, 0))
# (datetime.datetime(2013, 2, 12, 8, 0), datetime.datetime(2013, 2, 12, 9, 0))
- res = self.resource_calendar.schedule_hours(cr, uid, self.calendar_id, -40, day_dt=self.date1.replace(minute=0, second=0))
+ res = self.resource_calendar.schedule_hours(cr, uid, self.calendar_id, -40, day_dt=self.date1.replace(minute=0, second=0), context={'tz': 'UTC'})
# current day, limited at 09:00 because of day_dt specified -> 1 hour
self.assertEqual(res[-1][0], datetime.strptime('2013-02-12 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-1][1], datetime.strptime('2013-02-12 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
@@ -308,7 +308,7 @@ class TestResource(TestResourceCommon):
res = self.resource_calendar.schedule_hours(
cr, uid, self.calendar_id, 40,
- day_dt=self.date1.replace(minute=0, second=0)
+ day_dt=self.date1.replace(minute=0, second=0), context={'tz': 'UTC'}
)
self.assertEqual(res[0][0], datetime.strptime('2013-02-12 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
@@ -342,7 +342,8 @@ class TestResource(TestResourceCommon):
cr, uid, self.calendar_id, 40,
day_dt=self.date1.replace(minute=0, second=0),
compute_leaves=True,
- resource_id=self.resource1_id
+ resource_id=self.resource1_id,
+ context={'tz': 'UTC'}
)
self.assertEqual(res[0][0], datetime.strptime('2013-02-12 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
@@ -377,7 +378,7 @@ class TestResource(TestResourceCommon):
cr, uid, self.calendar_id,
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
- resource_id=self.resource1_id, exclude_leaves=True)
+ resource_id=self.resource1_id, exclude_leaves=True, context={'tz': 'UTC'})
self.assertEqual(res, 40.0, 'resource_calendar: wrong _interval_hours_get compatibility computation')
# new API: resource without leaves
@@ -386,7 +387,7 @@ class TestResource(TestResourceCommon):
cr, uid, self.calendar_id,
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
- compute_leaves=False, resource_id=self.resource1_id)
+ compute_leaves=False, resource_id=self.resource1_id, context={'tz': 'UTC'})
self.assertEqual(res, 40.0, 'resource_calendar: wrong get_working_hours computation')
# old API: resource and leaves
@@ -395,7 +396,7 @@ class TestResource(TestResourceCommon):
cr, uid, self.calendar_id,
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
- resource_id=self.resource1_id, exclude_leaves=False)
+ resource_id=self.resource1_id, exclude_leaves=False, context={'tz': 'UTC'})
self.assertEqual(res, 33.0, 'resource_calendar: wrong _interval_hours_get compatibility computation')
# new API: resource and leaves
@@ -404,7 +405,7 @@ class TestResource(TestResourceCommon):
cr, uid, self.calendar_id,
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
- compute_leaves=True, resource_id=self.resource1_id)
+ compute_leaves=True, resource_id=self.resource1_id, context={'tz': 'UTC'})
self.assertEqual(res, 33.0, 'resource_calendar: wrong get_working_hours computation')
# --------------------------------------------------
@@ -417,7 +418,7 @@ class TestResource(TestResourceCommon):
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0),
compute_leaves=True, resource_id=self.resource1_id,
- default_interval=(8, 16))
+ default_interval=(8, 16), context={'tz': 'UTC'})
self.assertEqual(res, 32.0, 'resource_calendar: wrong get_working_hours computation')
def test_50_calendar_schedule_days(self):
@@ -429,14 +430,14 @@ class TestResource(TestResourceCommon):
# Test1: with calendar
# --------------------------------------------------
- res = self.resource_calendar.schedule_days_get_date(cr, uid, self.calendar_id, 5, day_date=self.date1)
+ res = self.resource_calendar.schedule_days_get_date(cr, uid, self.calendar_id, 5, day_date=self.date1, context={'tz': 'UTC'})
self.assertEqual(res.date(), datetime.strptime('2013-02-26 00:0:00', _format).date(), 'resource_calendar: wrong days scheduling')
- res = self.resource_calendar.schedule_days_get_date(cr, uid, self.calendar_id, -2, day_date=self.date1)
+ res = self.resource_calendar.schedule_days_get_date(cr, uid, self.calendar_id, -2, day_date=self.date1, context={'tz': 'UTC'})
self.assertEqual(res.date(), datetime.strptime('2013-02-08 00:00:00', _format).date(), 'resource_calendar: wrong days scheduling')
res = self.resource_calendar.schedule_days_get_date(
cr, uid, self.calendar_id, 5, day_date=self.date1,
- compute_leaves=True, resource_id=self.resource1_id)
+ compute_leaves=True, resource_id=self.resource1_id, context={'tz': 'UTC'})
self.assertEqual(res.date(), datetime.strptime('2013-03-01 00:0:00', _format).date(), 'resource_calendar: wrong days scheduling')
# --------------------------------------------------
@@ -444,7 +445,7 @@ class TestResource(TestResourceCommon):
# --------------------------------------------------
# Without calendar, should only count days -> 12 -> 16, 5 days with default intervals
- res = self.resource_calendar.schedule_days_get_date(cr, uid, None, 5, day_date=self.date1, default_interval=(8, 16))
+ res = self.resource_calendar.schedule_days_get_date(cr, uid, None, 5, day_date=self.date1, default_interval=(8, 16), context={'tz': 'UTC'})
self.assertEqual(res, datetime.strptime('2013-02-16 16:00:00', _format), 'resource_calendar: wrong days scheduling')
def seconds(td):
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 1f68efe9e08..ad171caf306 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -2702,9 +2702,9 @@ class stock_inventory(osv.osv):
if stock_settings.group_stock_tracking_owner:
res_filter.append(('owner', _('One owner only')))
res_filter.append(('product_owner', _('One product for a specific owner')))
- if stock_settings.group_stock_tracking_lot:
+ if stock_settings.group_stock_production_lot:
res_filter.append(('lot', _('One Lot/Serial Number')))
- if stock_settings.group_stock_packaging:
+ if stock_settings.group_stock_tracking_lot:
res_filter.append(('pack', _('A Pack')))
return res_filter
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 13a856907af..690e977e9f6 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -33,6 +33,7 @@ import openerp
import openerp.modules.registry
from openerp.addons.base.ir.ir_qweb import AssetsBundle, QWebTemplateNotFound
from openerp.modules import get_module_resource
+from openerp.service import model as service_model
from openerp.tools import topological_sort
from openerp.tools.translate import _
from openerp.tools import ustr
@@ -953,7 +954,10 @@ class DataSet(http.Controller):
if method.startswith('_'):
raise AccessError(_("Underscore prefixed methods cannot be remotely called"))
- return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
+ @service_model.check
+ def checked_call(__dbname, *args, **kwargs):
+ return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
+ return checked_call(request.db, *args, **kwargs)
@http.route('/web/dataset/call', type='json', auth="user")
def call(self, model, method, args, domain_id=None, context_id=None):
diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js
index 985a5ac5237..ef35b7be98d 100644
--- a/addons/website/static/src/js/website.editor.js
+++ b/addons/website/static/src/js/website.editor.js
@@ -1121,9 +1121,11 @@ define(['summernote/summernote'], function () {
saveElement: function ($el) {
// escape text nodes for xml saving
var escaped_el = $el.clone();
- escaped_el.find('*').addBack().not('script,style').contents().each(function(){
+ var to_escape = escaped_el.find('*').addBack();
+ to_escape = to_escape.not(to_escape.filter('script,style,[data-oe-model][data-oe-model!="ir.ui.view"]').find('*').addBack());
+ to_escape.contents().each(function(){
if(this.nodeType == 3) {
- this.nodeValue = _.escape(this.nodeValue);
+ this.nodeValue = $('').text(this.nodeValue).html();
}
});
var markup = escaped_el.prop('outerHTML');
diff --git a/addons/website_hr_recruitment/controllers/main.py b/addons/website_hr_recruitment/controllers/main.py
index 4bef1dfe0d8..e8a8170943c 100644
--- a/addons/website_hr_recruitment/controllers/main.py
+++ b/addons/website_hr_recruitment/controllers/main.py
@@ -90,6 +90,12 @@ class website_hr_recruitment(http.Controller):
'default': default,
})
+ def _get_applicant_char_fields(self):
+ return ['email_from', 'partner_name', 'description']
+
+ def _get_applicant_relational_fields(self):
+ return ['department_id', 'job_id']
+
@http.route('/jobs/thankyou', methods=['POST'], type='http', auth="public", website=True)
def jobs_thankyou(self, **post):
error = {}
@@ -109,9 +115,9 @@ class website_hr_recruitment(http.Controller):
value = {
'name': '%s\'s Application' % post.get('partner_name'),
}
- for f in ['email_from', 'partner_name', 'description']:
+ for f in self._get_applicant_char_fields():
value[f] = post.get(f)
- for f in ['department_id', 'job_id']:
+ for f in self._get_applicant_relational_fields():
value[f] = int(post.get(f) or 0)
# Retro-compatibility for saas-3. "phone" field should be replace by "partner_phone" in the template in trunk.
value['partner_phone'] = post.pop('phone', False)
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index b7054e527ca..563e66809b0 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -138,24 +138,17 @@ class website_sale(http.Controller):
return attribute_value_ids
- @http.route(['/shop',
- '/shop/page/',
- '/shop/category/',
- '/shop/category//page/'
- ], type='http', auth="public", website=True)
- def shop(self, page=0, category=None, search='', **post):
- cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
-
+ def _get_search_domain(self, search, category, attrib_values):
domain = request.website.sale_product_domain()
+
if search:
for srch in search.split(" "):
- domain += ['|', '|', '|', ('name', 'ilike', srch), ('description', 'ilike', srch),
+ domain += [
+ '|', '|', '|', ('name', 'ilike', srch), ('description', 'ilike', srch),
('description_sale', 'ilike', srch), ('product_variant_ids.default_code', 'ilike', srch)]
+
if category:
domain += [('public_categ_ids', 'child_of', int(category))]
- attrib_list = request.httprequest.args.getlist('attrib')
- attrib_values = [map(int,v.split("-")) for v in attrib_list if v]
- attrib_set = set([v[1] for v in attrib_values])
if attrib_values:
attrib = None
@@ -173,6 +166,23 @@ class website_sale(http.Controller):
if attrib:
domain += [('attribute_line_ids.value_ids', 'in', ids)]
+ return domain
+
+ @http.route([
+ '/shop',
+ '/shop/page/',
+ '/shop/category/',
+ '/shop/category//page/'
+ ], type='http', auth="public", website=True)
+ def shop(self, page=0, category=None, search='', **post):
+ cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
+
+ attrib_list = request.httprequest.args.getlist('attrib')
+ attrib_values = [map(int, v.split("-")) for v in attrib_list if v]
+ attrib_set = set([v[1] for v in attrib_values])
+
+ domain = self._get_search_domain(search, category, attrib_values)
+
keep = QueryURL('/shop', category=category and int(category), search=search, attrib=attrib_list)
if not context.get('pricelist'):
diff --git a/openerp/addons/test_inherit/models.py b/openerp/addons/test_inherit/models.py
index 7313e12c2a3..f783b42fb4c 100644
--- a/openerp/addons/test_inherit/models.py
+++ b/openerp/addons/test_inherit/models.py
@@ -38,6 +38,7 @@ class mother(models.Model):
_inherit = 'test.inherit.mother'
field_in_mother = fields.Char()
+ partner_id = fields.Many2one('res.partner')
# extend the name field: make it required and change its default value
name = fields.Char(required=True, default='Bar')
@@ -70,3 +71,10 @@ class daughter(models.Model):
# change the default value of an inherited field
name = fields.Char(default='Baz')
+
+
+class res_partner(models.Model):
+ _inherit = 'res.partner'
+
+ # define a one2many field based on the inherited field partner_id
+ daughter_ids = fields.One2many('test.inherit.daughter', 'partner_id')
diff --git a/openerp/addons/test_inherit/tests/test_inherit.py b/openerp/addons/test_inherit/tests/test_inherit.py
index c277692b7d3..56a0b319794 100644
--- a/openerp/addons/test_inherit/tests/test_inherit.py
+++ b/openerp/addons/test_inherit/tests/test_inherit.py
@@ -64,3 +64,15 @@ class test_inherits(common.TransactionCase):
[('a', 'A'), ('b', 'B'), ('c', 'C'), ('d', 'D')])
self.assertEqual(mother._columns['state'].selection,
[('a', 'A'), ('b', 'B'), ('c', 'C'), ('d', 'D')])
+
+ def test_50_search_one2many(self):
+ """ check search on one2many field based on inherited many2one field. """
+ # create a daughter record attached to partner Demo
+ partner_demo = self.env.ref('base.partner_demo')
+ daughter = self.env['test.inherit.daughter'].create({'partner_id': partner_demo.id})
+ self.assertEqual(daughter.partner_id, partner_demo)
+ self.assertIn(daughter, partner_demo.daughter_ids)
+
+ # search the partner from the daughter record
+ partners = self.env['res.partner'].search([('daughter_ids', 'in', daughter.ids)])
+ self.assertIn(partner_demo, partners)
diff --git a/openerp/models.py b/openerp/models.py
index 3ac768f49a5..d16ab4475ba 100644
--- a/openerp/models.py
+++ b/openerp/models.py
@@ -4728,8 +4728,10 @@ class BaseModel(object):
context = {}
# avoid recursion through already copied records in case of circular relationship
- seen_map = context.setdefault('__copy_data_seen', {})
- if id in seen_map.setdefault(self._name, []):
+ if '__copy_data_seen' not in context:
+ context = dict(context, __copy_data_seen=defaultdict(list))
+ seen_map = context['__copy_data_seen']
+ if id in seen_map[self._name]:
return
seen_map[self._name].append(id)
@@ -4799,8 +4801,10 @@ class BaseModel(object):
context = {}
# avoid recursion through already copied records in case of circular relationship
- seen_map = context.setdefault('__copy_translations_seen',{})
- if old_id in seen_map.setdefault(self._name,[]):
+ if '__copy_translations_seen' not in context:
+ context = dict(context, __copy_translations_seen=defaultdict(list))
+ seen_map = context['__copy_translations_seen']
+ if old_id in seen_map[self._name]:
return
seen_map[self._name].append(old_id)
@@ -5369,7 +5373,11 @@ class BaseModel(object):
"""
if self:
vals = [func(rec) for rec in self]
- return reduce(operator.or_, vals) if isinstance(vals[0], BaseModel) else vals
+ if isinstance(vals[0], BaseModel):
+ # return the union of all recordsets in O(n)
+ ids = set(itertools.chain(*[rec._ids for rec in vals]))
+ return vals[0].browse(ids)
+ return vals
else:
vals = func(self)
return vals if isinstance(vals, BaseModel) else []
diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py
index ee4317f1a69..642adc81b96 100644
--- a/openerp/osv/expression.py
+++ b/openerp/osv/expression.py
@@ -138,6 +138,7 @@ import traceback
import openerp.modules
from . import fields
+from .. import SUPERUSER_ID
from ..models import MAGIC_COLUMNS, BaseModel
import openerp.tools as tools
@@ -942,11 +943,16 @@ class expression(object):
call_null = False
push(create_substitution_leaf(leaf, FALSE_LEAF, model))
else:
- ids2 = select_from_where(cr, column._fields_id, comodel._table, 'id', ids2, operator)
- if ids2:
+ # determine ids1 <-- column._fields_id --- ids2
+ if comodel._fields[column._fields_id].store:
+ ids1 = select_from_where(cr, column._fields_id, comodel._table, 'id', ids2, operator)
+ else:
+ recs = comodel.browse(cr, SUPERUSER_ID, ids2, {'prefetch_fields': False})
+ ids1 = recs.mapped(column._fields_id).ids
+ if ids1:
call_null = False
o2m_op = 'not in' if operator in NEGATIVE_TERM_OPERATORS else 'in'
- push(create_substitution_leaf(leaf, ('id', o2m_op, ids2), model))
+ push(create_substitution_leaf(leaf, ('id', o2m_op, ids1), model))
if call_null:
o2m_op = 'in' if operator in NEGATIVE_TERM_OPERATORS else 'not in'