[MERGE] forward port of branch 8.0 up to 9c8b99a
This commit is contained in:
@@ -73,7 +73,7 @@
|
||||
<group>
|
||||
<field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '<>', 'view')]" name="account_id" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id, parent.date_invoice)" groups="account.group_account_user"/>
|
||||
<field name="invoice_line_tax_id" context="{'type':parent.get('type')}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
|
||||
<field domain="[('type','<>','view'), ('company_id', '=', parent.company_id)], ('state','not in',('close','cancelled'))]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field domain="[('type','<>','view'), ('company_id', '=', parent.company_id), ('state','not in',('close','cancelled'))]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -389,7 +389,7 @@
|
||||
</div>
|
||||
<label for="address_id"/>
|
||||
<div>
|
||||
<field name="address_id" context="{'show_address': 1}" domain= "[('is_company', '=', True )]"/>
|
||||
<field name="address_id" context="{'show_address': 1}" domain= "[('is_company', '=', True )]" options="{'always_reload': True}"/>
|
||||
</div>
|
||||
</group>
|
||||
<xpath expr="//field[@name='department_id']" position="after">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
+13
-11
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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 = $('<div />').text(this.nodeValue).html();
|
||||
}
|
||||
});
|
||||
var markup = escaped_el.prop('outerHTML');
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -138,24 +138,17 @@ class website_sale(http.Controller):
|
||||
|
||||
return attribute_value_ids
|
||||
|
||||
@http.route(['/shop',
|
||||
'/shop/page/<int:page>',
|
||||
'/shop/category/<model("product.public.category"):category>',
|
||||
'/shop/category/<model("product.public.category"):category>/page/<int: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/<int:page>',
|
||||
'/shop/category/<model("product.public.category"):category>',
|
||||
'/shop/category/<model("product.public.category"):category>/page/<int: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'):
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
|
||||
+13
-5
@@ -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 []
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user