diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index c2e3758aae2..a70684df1ad 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -783,6 +783,7 @@ class account_voucher(osv.osv): total_credit += line.credit and line.amount_currency or 0.0 total_debit += line.debit and line.amount_currency or 0.0 + remaining_amount = price #voucher line creation for line in account_move_lines: @@ -803,13 +804,13 @@ class account_voucher(osv.osv): 'move_line_id':line.id, 'account_id':line.account_id.id, 'amount_original': amount_original, - 'amount': (line.id in move_lines_found) and min(abs(price), amount_unreconciled) or 0.0, + 'amount': (line.id in move_lines_found) and min(abs(remaining_amount), amount_unreconciled) or 0.0, 'date_original':line.date, 'date_due':line.date_maturity, 'amount_unreconciled': amount_unreconciled, 'currency_id': line_currency_id, } - price -= rs['amount'] + remaining_amount -= rs['amount'] #in case a corresponding move_line hasn't been found, we now try to assign the voucher amount #on existing invoices: we split voucher amount by most old first, but only for lines in the same currency if not move_lines_found: diff --git a/addons/account_voucher/test/sales_payment.yml b/addons/account_voucher/test/sales_payment.yml index 3679c34dc52..ed9305a320c 100644 --- a/addons/account_voucher/test/sales_payment.yml +++ b/addons/account_voucher/test/sales_payment.yml @@ -44,6 +44,8 @@ !python {model: account.voucher}: | vals = {} journal_id = self.default_get(cr, uid, ['journal_id']).get('journal_id',None) + voucher = self.recompute_voucher_lines(cr, uid, [], ref("base.res_partner_19"), journal_id, 450.0, ref('base.EUR'), 'receipt', False) + assert (voucher['value'].get('writeoff_amount') == 0.0), "Writeoff amount calculated by recompute_voucher_lines() is not 0.0" res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_19"), journal_id, 0.0, 1, ttype='receipt', date=False) vals = { 'account_id': ref('account.cash'), @@ -64,6 +66,7 @@ vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']] id = self.create(cr, uid, vals) voucher_id = self.browse(cr, uid, id) + assert (voucher_id.writeoff_amount == 0.0), "Writeoff amount is not 0.0" assert (voucher_id.state=='draft'), "Voucher is not in draft state" self.signal_proforma_voucher(cr, uid, [voucher_id.id]) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py index 9226787e908..9869f42e7c0 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py @@ -62,28 +62,56 @@ class hr_timesheet_sheet(osv.osv): def copy(self, cr, uid, ids, *args, **argv): raise osv.except_osv(_('Error!'), _('You cannot duplicate a timesheet.')) - def create(self, cr, uid, vals, *args, **argv): + def create(self, cr, uid, vals, context=None): if 'employee_id' in vals: - if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).user_id: + if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).user_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must assign it to a user.')) - if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).product_id: + if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).product_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link the employee to a product, like \'Consultant\'.')) - if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).journal_id: + if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).journal_id: raise osv.except_osv(_('Configuration Error!'), _('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.')) - return super(hr_timesheet_sheet, self).create(cr, uid, vals, *args, **argv) + if vals.get('attendances_ids'): + # If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint + vals['attendances_ids'] = self.sort_attendances(cr, uid, vals['attendances_ids'], context=context) + return super(hr_timesheet_sheet, self).create(cr, uid, vals, context=context) - def write(self, cr, uid, ids, vals, *args, **argv): + def write(self, cr, uid, ids, vals, context=None): if 'employee_id' in vals: - new_user_id = self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).user_id.id or False + new_user_id = self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).user_id.id or False if not new_user_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must assign it to a user.')) - if not self._sheet_date(cr, uid, ids, forced_user_id=new_user_id): + if not self._sheet_date(cr, uid, ids, forced_user_id=new_user_id, context=context): raise osv.except_osv(_('Error!'), _('You cannot have 2 timesheets that overlap!\nYou should use the menu \'My Timesheet\' to avoid this problem.')) - if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).product_id: + if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).product_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link the employee to a product.')) - if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).journal_id: + if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).journal_id: raise osv.except_osv(_('Configuration Error!'), _('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.')) - return super(hr_timesheet_sheet, self).write(cr, uid, ids, vals, *args, **argv) + if vals.get('attendances_ids'): + # If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint + # In addition to the date order, deleting attendances are done before inserting attendances + vals['attendances_ids'] = self.sort_attendances(cr, uid, vals['attendances_ids'], context=context) + res = super(hr_timesheet_sheet, self).write(cr, uid, ids, vals, context=context) + if vals.get('attendances_ids'): + for timesheet in self.browse(cr, uid, ids): + if not self.pool['hr.attendance']._altern_si_so(cr, uid, [att.id for att in timesheet.attendances_ids]): + raise osv.except_osv(_('Warning !'), _('Error ! Sign in (resp. Sign out) must follow Sign out (resp. Sign in)')) + return res + + def sort_attendances(self, cr, uid, attendance_tuples, context=None): + date_attendances = [] + for att_tuple in attendance_tuples: + if att_tuple[0] in [0,1,4]: + if att_tuple[0] in [0,1]: + name = att_tuple[2]['name'] + else: + name = self.pool['hr.attendance'].browse(cr, uid, att_tuple[1]).name + date_attendances.append((1, name, att_tuple)) + elif att_tuple[0] in [2,3]: + date_attendances.append((0, self.pool['hr.attendance'].browse(cr, uid, att_tuple[1]).name, att_tuple)) + else: + date_attendances.append((0, False, att_tuple)) + date_attendances.sort() + return [att[2] for att in date_attendances] def button_confirm(self, cr, uid, ids, context=None): for sheet in self.browse(cr, uid, ids, context=context): diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 1e7076d9c8f..e7a2e6a1c86 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -558,14 +558,14 @@ class stock_warehouse_orderpoint(osv.osv): ] def default_get(self, cr, uid, fields, context=None): + warehouse_obj = self.pool.get('stock.warehouse') res = super(stock_warehouse_orderpoint, self).default_get(cr, uid, fields, context) # default 'warehouse_id' and 'location_id' if 'warehouse_id' not in res: - warehouse = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'warehouse0', context) - res['warehouse_id'] = warehouse.id + warehouse_ids = res.get('company_id') and warehouse_obj.search(cr, uid, [('company_id', '=', res['company_id'])], limit=1, context=context) or [] + res['warehouse_id'] = warehouse_ids and warehouse_ids[0] or False if 'location_id' not in res: - warehouse = self.pool.get('stock.warehouse').browse(cr, uid, res['warehouse_id'], context) - res['location_id'] = warehouse.lot_stock_id.id + res['location_id'] = res.get('warehouse_id') and warehouse_obj.browse(cr, uid, res['warehouse_id'], context).lot_stock_id.id or False return res def onchange_warehouse_id(self, cr, uid, ids, warehouse_id, context=None): diff --git a/addons/stock/stock.py b/addons/stock/stock.py index eb14287ed96..5276e7f21e5 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2999,6 +2999,9 @@ class stock_picking_in(osv.osv): def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): return self.pool.get('stock.picking').read(cr, uid, ids, fields=fields, context=context, load=load) + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + return self.pool['stock.picking'].read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) + def check_access_rights(self, cr, uid, operation, raise_exception=True): #override in order to redirect the check of acces rights on the stock.picking object return self.pool.get('stock.picking').check_access_rights(cr, uid, operation, raise_exception=raise_exception) @@ -3079,6 +3082,9 @@ class stock_picking_out(osv.osv): def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): return self.pool.get('stock.picking').read(cr, uid, ids, fields=fields, context=context, load=load) + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + return self.pool['stock.picking'].read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) + def check_access_rights(self, cr, uid, operation, raise_exception=True): #override in order to redirect the check of acces rights on the stock.picking object return self.pool.get('stock.picking').check_access_rights(cr, uid, operation, raise_exception=raise_exception)