diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py index 9869f42e7c0..c5b8012c89e 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py @@ -20,10 +20,11 @@ ############################################################################## import time -from datetime import datetime, timedelta +from datetime import datetime from dateutil.relativedelta import relativedelta from openerp.osv import fields, osv +from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT from openerp.tools.translate import _ class hr_timesheet_sheet(osv.osv): @@ -385,18 +386,22 @@ class hr_attendance(osv.osv): attendance_ids.extend([row[0] for row in cr.fetchall()]) return attendance_ids + def _get_current_sheet(self, cr, uid, employee_id, date=False, context=None): + if not date: + date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + # ending date with no time to avoid timesheet with early date_to + date_to = date[0:10]+' 00:00:00' + # limit=1 because only one sheet possible for an employee between 2 dates + sheet_ids = self.pool.get('hr_timesheet_sheet.sheet').search(cr, uid, [ + ('date_to', '>=', date_to), ('date_from', '<=', date), + ('employee_id', '=', employee_id) + ], limit=1, context=context) + return sheet_ids and sheet_ids[0] or False + def _sheet(self, cursor, user, ids, name, args, context=None): - sheet_obj = self.pool.get('hr_timesheet_sheet.sheet') res = {}.fromkeys(ids, False) for attendance in self.browse(cursor, user, ids, context=context): - date_to = datetime.strftime(datetime.strptime(attendance.name[0:10], '%Y-%m-%d'), '%Y-%m-%d %H:%M:%S') - sheet_ids = sheet_obj.search(cursor, user, - [('date_to', '>=', date_to), ('date_from', '<=', attendance.name), - ('employee_id', '=', attendance.employee_id.id)], - context=context) - if sheet_ids: - # [0] because only one sheet possible for an employee between 2 dates - res[attendance.id] = sheet_obj.name_get(cursor, user, sheet_ids, context=context)[0] + res[attendance.id] = self._get_current_sheet(cursor, user, attendance.employee_id.id, attendance.name, context=context) return res _columns = { @@ -415,16 +420,15 @@ class hr_attendance(osv.osv): def create(self, cr, uid, vals, context=None): if context is None: context = {} - if 'sheet_id' in context: - ts = self.pool.get('hr_timesheet_sheet.sheet').browse(cr, uid, context['sheet_id'], context=context) + + sheet_id = context.get('sheet_id') or self._get_current_sheet(cr, uid, vals.get('employee_id'), vals.get('name'), context=context) + if sheet_id: + ts = self.pool.get('hr_timesheet_sheet.sheet').browse(cr, uid, sheet_id, context=context) if ts.state not in ('draft', 'new'): - raise osv.except_osv(_('Error!'), _('You cannot modify an entry in a confirmed timesheet.')) - res = super(hr_attendance,self).create(cr, uid, vals, context=context) - if 'sheet_id' in context: - if context['sheet_id'] != self.browse(cr, uid, res, context=context).sheet_id.id: - raise osv.except_osv(_('User Error!'), _('You cannot enter an attendance ' \ - 'date outside the current timesheet dates.')) - return res + raise osv.except_osv(_('Error!'), _('You can not enter an attendance in a submitted timesheet. Ask your manager to reset it before adding attendance.')) + elif ts.date_from > vals.get('name') or ts.date_to < vals.get('name'): + raise osv.except_osv(_('User Error!'), _('You can not enter an attendance date outside the current timesheet dates.')) + return super(hr_attendance,self).create(cr, uid, vals, context=context) def unlink(self, cr, uid, ids, *args, **kwargs): if isinstance(ids, (int, long)): diff --git a/addons/product/product.py b/addons/product/product.py index eed8859bd94..523aae8b076 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -805,9 +805,17 @@ class product_product(osv.osv): price_type_currency_id = pricetype_obj.browse(cr,uid,price_type_id).currency_id.id res = {} + # standard_price field can only be seen by users in base.group_user + # Thus, in order to compute the sale price from the cost price for users not in this group + # We fetch the standard price as the superuser + for product in products: + if ptype != 'standard_price': + res[product.id] = product[ptype] or 0.0 + else: + res[product.id] = self.read(cr, SUPERUSER_ID, product.id, [ptype], context=context)[ptype] or 0.0 + product_uom_obj = self.pool.get('product.uom') for product in products: - res[product.id] = product[ptype] or 0.0 if ptype == 'list_price': res[product.id] = (res[product.id] * (product.price_margin or 1.0)) + \ product.price_extra diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 26d9d80f13e..bdd5ac9fd6f 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -357,7 +357,6 @@ class sale_order(osv.osv): } def ship_recreate(self, cr, uid, order, line, move_id, proc_id): - # FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot) """ Define ship_recreate for process after shipping exception param order: sales order to which the order lines belong @@ -366,16 +365,25 @@ class sale_order(osv.osv): param proc_id: the ID of procurement """ move_obj = self.pool.get('stock.move') - if order.state == 'shipping_except': - for pick in order.picking_ids: - for move in pick.move_lines: - if move.state == 'cancel': - mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)]) - if mov_ids: - for mov in move_obj.browse(cr, uid, mov_ids): - # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum? - move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty}) - self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty}) + proc_obj = self.pool.get('procurement.order') + if move_id and order.state == 'shipping_except': + current_move = move_obj.browse(cr, uid, move_id) + moves = [] + for picking in order.picking_ids: + if picking.id != current_move.picking_id.id and picking.state != 'cancel': + moves.extend(move for move in picking.move_lines if move.state != 'cancel' and move.sale_line_id.id == line.id) + if moves: + product_qty = current_move.product_qty + product_uos_qty = current_move.product_uos_qty + for move in moves: + product_qty -= move.product_qty + product_uos_qty -= move.product_uos_qty + if product_qty > 0 or product_uos_qty > 0: + move_obj.write(cr, uid, [move_id], {'product_qty': product_qty, 'product_uos_qty': product_uos_qty}) + proc_obj.write(cr, uid, [proc_id], {'product_qty': product_qty, 'product_uos_qty': product_uos_qty}) + else: + current_move.unlink() + proc_obj.unlink(cr, uid, [proc_id]) return True def _get_date_planned(self, cr, uid, order, line, start_date, context=None): diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index e96652c11aa..4707da2bbb0 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1271,7 +1271,7 @@ + groups="stock.group_tracking_lot,stock.group_production_lot">