##############################################################################
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):
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 = {
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)):
}
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
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):