def action_cancel(self): ''' This action_cancel overidden to avoid the cascading cancellation @param self : Object Pointer @param cr : Database Cursor @param uid : Current Logged in User @param ids : Current Records @param context : standard Dictionary @return : True ''' if not len(self.ids): return True pickings = {} for move in self: if move.state in ('confirmed', 'waiting', 'assigned', 'draft'): if move.picking_id: pickings[move.picking_id.id] = True self.write({'state': 'cancel'}) for pick_id in pickings: workflow.trg_validate(self._uid, 'stock.picking', pick_id, 'button_cancel', self._cr) ids2 = [] for res in self.read(['move_dest_id']): if res['move_dest_id']: ids2.append(res['move_dest_id'][0]) for stock_id in self.ids: workflow.trg_trigger(self._uid, 'stock.move', stock_id, self._cr) # self.action_cancel(cr,uid, ids2, context) # $$ # [removed to avoid cascading cancellation] return True
def write(self, cr, uid, ids, vals, context=None): if isinstance(ids, (int, long)): ids = [ids] res = super(StockMove, self).write(cr, uid, ids, vals, context=context) from openerp import workflow for move in self.browse(cr, uid, ids, context=context): if move.raw_material_production_id and move.raw_material_production_id.state == 'confirmed': workflow.trg_trigger(uid, 'stock.move', move.id, cr) return res
def debit_reconcile(self, cr, uid, payment_line_id, context=None): """ Reconcile a debit order's payment line with the the move line that it is based on. Called from payment_order.action_sent(). As the amount is derived directly from the counterpart move line, we do not expect a write off. Take partial reconciliations into account though. :param payment_line_id: the single id of the canceled payment line """ if isinstance(payment_line_id, (list, tuple)): payment_line_id = payment_line_id[0] reconcile_obj = self.pool.get("account.move.reconcile") move_line_obj = self.pool.get("account.move.line") payment_line = self.browse(cr, uid, payment_line_id, context=context) transit_move_line = payment_line.transit_move_line_id torec_move_line = payment_line.move_line_id if not transit_move_line or not torec_move_line: raise orm.except_orm(_("Can not reconcile"), _("No move line for line %s") % payment_line.name) if torec_move_line.reconcile_id: raise orm.except_orm(_("Error"), _("Move line %s has already been reconciled") % torec_move_line.name) if transit_move_line.reconcile_id or transit_move_line.reconcile_partial_id: raise orm.except_orm(_("Error"), _("Move line %s has already been reconciled") % transit_move_line.name) def is_zero(total): return self.pool.get("res.currency").is_zero(cr, uid, transit_move_line.company_id.currency_id, total) line_ids = [transit_move_line.id, torec_move_line.id] if torec_move_line.reconcile_partial_id: line_ids = [x.id for x in torec_move_line.reconcile_partial_id.line_partial_ids] + [transit_move_line.id] total = move_line_obj.get_balance(cr, uid, line_ids) vals = { "type": "auto", "line_id": is_zero(total) and [(6, 0, line_ids)] or [(6, 0, [])], "line_partial_ids": (is_zero(total) and [(6, 0, [])] or [(6, 0, line_ids)]), } if torec_move_line.reconcile_partial_id: reconcile_obj.write(cr, uid, [torec_move_line.reconcile_partial_id.id], vals, context=context) else: reconcile_obj.create(cr, uid, vals, context=context) for line_id in line_ids: workflow.trg_trigger(uid, "account.move.line", line_id, cr) # If a bank transaction of a storno was first confirmed # and now canceled (the invoice is now in state 'debit_denied' if torec_move_line.invoice: workflow.trg_validate(uid, "account.invoice", torec_move_line.invoice.id, "undo_debit_denied", cr)
def action_done(self, cr, uid, ids): """ Changes procurement state to Done and writes Closed date. @return: True """ move_obj = self.pool.get('stock.move') for procurement in self.browse(cr, uid, ids): if procurement.move_id: if procurement.close_move and (procurement.move_id.state <> 'done'): move_obj.action_done(cr, uid, [procurement.move_id.id]) res = self.write(cr, uid, ids, {'state': 'done', 'date_close': time.strftime('%Y-%m-%d')}) for id in ids: workflow.trg_trigger(uid, 'procurement.order', id, cr) return res
def action_done(self, cr, uid, ids): """ Changes procurement state to Done and writes Closed date. @return: True """ move_obj = self.pool.get("stock.move") for procurement in self.browse(cr, uid, ids): if procurement.move_id: if procurement.close_move and (procurement.move_id.state <> "done"): move_obj.action_done(cr, uid, [procurement.move_id.id]) res = self.write(cr, uid, ids, {"state": "done", "date_close": time.strftime("%Y-%m-%d")}) for id in ids: workflow.trg_trigger(uid, "procurement.order", id, cr) return res
def unlink(self): """ Workflow triggers upon unreconcile. This should go into the core. """ line_ids = [] for reconcile in self: for move_line in reconcile.line_id: line_ids.append(move_line.id) res = super(AccountMoveReconcile, self).unlink() for line_id in line_ids: workflow.trg_trigger( self._uid, 'account.move.line', line_id, self._cr) return res
def action_cancel(self, cr, uid, ids): """Cancel Procurements and either cancel or assign the related Stock Moves, depending on the procurement configuration. @return: True """ to_assign = [] to_cancel = [] move_obj = self.pool.get('stock.move') for proc in self.browse(cr, uid, ids): if proc.close_move and proc.move_id: if proc.move_id.state not in ('done', 'cancel'): to_cancel.append(proc.move_id.id) else: if proc.move_id and proc.move_id.state == 'waiting': to_assign.append(proc.move_id.id) if len(to_cancel): move_obj.action_cancel(cr, uid, to_cancel) if len(to_assign): move_obj.write(cr, uid, to_assign, {'state': 'assigned'}) self.write(cr, uid, ids, {'state': 'cancel'}) for id in ids: workflow.trg_trigger(uid, 'procurement.order', id, cr) return True
def action_cancel(self, cr, uid, ids): """Cancel Procurements and either cancel or assign the related Stock Moves, depending on the procurement configuration. @return: True """ to_assign = [] to_cancel = [] move_obj = self.pool.get("stock.move") for proc in self.browse(cr, uid, ids): if proc.close_move and proc.move_id: if proc.move_id.state not in ("done", "cancel"): to_cancel.append(proc.move_id.id) else: if proc.move_id and proc.move_id.state == "waiting": to_assign.append(proc.move_id.id) if len(to_cancel): move_obj.action_cancel(cr, uid, to_cancel) if len(to_assign): move_obj.write(cr, uid, to_assign, {"state": "confirmed"}) move_obj.action_assign(cr, uid, to_assign) self.write(cr, uid, ids, {"state": "cancel"}) for id in ids: workflow.trg_trigger(uid, "procurement.order", id, cr) return True
def reconcile(self, cr, uid, ids, type='auto', writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False, context=None): account_obj = self.pool.get('account.account') move_obj = self.pool.get('account.move') move_rec_obj = self.pool.get('account.move.reconcile') partner_obj = self.pool.get('res.partner') currency_obj = self.pool.get('res.currency') lines = self.browse(cr, uid, ids, context=context) unrec_lines = filter(lambda x: not x['reconcile_id'], lines) credit = debit = 0.0 currency = 0.0 account_id = False partner_id = False invoice_id = False tax_amount = False base_amount = False if context is None: context = {} company_list = [] for line in self.browse(cr, uid, ids, context=context): if company_list and not line.company_id.id in company_list: raise osv.except_osv(_('Warning!'), _('To reconcile the entries company should be the same for all entries.')) company_list.append(line.company_id.id) for line in unrec_lines: if line.state <> 'valid': raise osv.except_osv(_('Error!'), _('Entry "%s" is not valid !') % line.name) credit += line['credit'] debit += line['debit'] currency += line['amount_currency'] or 0.0 account_id = line['account_id']['id'] partner_id = (line['partner_id'] and line['partner_id']['id']) or False invoice_id = line.invoice_id.id or False tax_amount = line['tax_amount'] or 0.0 base_amount = line['base_amount'] or 0.0 writeoff = debit - credit # Ifdate_p in context => take this date if context.has_key('date_p') and context['date_p']: date=context['date_p'] else: date = time.strftime('%Y-%m-%d') cr.execute('SELECT account_id, reconcile_id '\ 'FROM account_move_line '\ 'WHERE id IN %s '\ 'GROUP BY account_id,reconcile_id', (tuple(ids), )) r = cr.fetchall() #TODO: move this check to a constraint in the account_move_reconcile object if len(r) != 1: raise osv.except_osv(_('Error'), _('Entries are not of the same account or already reconciled ! ')) if not unrec_lines: raise osv.except_osv(_('Error!'), _('Entry is already reconciled.')) account = account_obj.browse(cr, uid, account_id, context=context) if not account.reconcile: raise osv.except_osv(_('Error'), _('The account is not defined to be reconciled !')) if r[0][1] != None: raise osv.except_osv(_('Error!'), _('Some entries are already reconciled.')) if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \ (account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))): if not writeoff_acc_id: raise osv.except_osv(_('Warning!'), _('You have to provide an account for the write off/exchange difference entry.')) if writeoff > 0: debit = writeoff credit = 0.0 self_credit = writeoff self_debit = 0.0 else: debit = 0.0 credit = -writeoff self_credit = 0.0 self_debit = -writeoff # If comment exist in context, take it if 'comment' in context and context['comment']: libelle = context['comment'] else: libelle = _('Write-Off') cur_obj = self.pool.get('res.currency') cur_id = False amount_currency_writeoff = 0.0 if context.get('company_currency_id',False) != context.get('currency_id',False): cur_id = context.get('currency_id',False) for line in unrec_lines: if line.currency_id and line.currency_id.id == context.get('currency_id',False): amount_currency_writeoff += line.amount_currency else: tmp_amount = cur_obj.compute(cr, uid, line.account_id.company_id.currency_id.id, context.get('currency_id',False), abs(line.debit-line.credit), context={'date': line.date}) amount_currency_writeoff += (line.debit > 0) and tmp_amount or -tmp_amount writeoff_lines = [ (0, 0, { 'name': libelle, 'debit': self_debit, 'credit': self_credit, 'account_id': account_id, 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': amount_currency_writeoff and -1 * amount_currency_writeoff or (account.currency_id.id and -1 * currency or 0.0), 'invoice_id': invoice_id, 'tax_amount': tax_amount, 'base_amount': base_amount, }), (0, 0, { 'name': libelle, 'debit': debit, 'credit': credit, 'account_id': writeoff_acc_id, 'analytic_account_id': context.get('analytic_id', False), 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': amount_currency_writeoff and amount_currency_writeoff or (account.currency_id.id and currency or 0.0), 'invoice_id': invoice_id, 'tax_amount': tax_amount, 'base_amount': base_amount, }) ] #2015-06-22 writeoff_lines = [] for line in unrec_lines: if line.state <> 'valid': raise osv.except_osv(_('Error!'), _('Entry "%s" is not valid !') % line.name) writeoff_lines.append( (0,0,{ 'name': line.name, 'debit': line.credit, 'credit': line.debit, 'account_id': line.account_id.id, 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': line.amount_currency or 0.0, 'invoice_id': line.invoice_id.id, 'tax_amount': line.tax_amount or 0.0, 'base_amount' : line.base_amount or 0.0 }) ) writeoff_lines.append( (0, 0, { 'name': libelle, 'debit': debit, 'credit': credit, 'account_id': writeoff_acc_id, 'analytic_account_id': context.get('analytic_id', False), 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': amount_currency_writeoff and amount_currency_writeoff or (account.currency_id.id and currency or 0.0), 'invoice_id': False, }) ) writeoff_move_id = move_obj.create(cr, uid, { 'period_id': writeoff_period_id, 'journal_id': writeoff_journal_id, 'date':date, 'state': 'draft', 'line_id': writeoff_lines }) writeoff_line_ids = self.search(cr, uid, [('move_id', '=', writeoff_move_id), ('account_id', '=', account_id)]) if account_id == writeoff_acc_id: writeoff_line_ids = [writeoff_line_ids[1]] ids += writeoff_line_ids # marking the lines as reconciled does not change their validity, so there is no need # to revalidate their moves completely. reconcile_context = dict(context, novalidate=True) r_id = move_rec_obj.create(cr, uid, { 'type': type, 'line_id': map(lambda x: (4, x, False), ids), 'line_partial_ids': map(lambda x: (3, x, False), ids) }, context=reconcile_context) # the id of the move.reconcile is written in the move.line (self) by the create method above # because of the way the line_id are defined: (4, x, False) for id in ids: workflow.trg_trigger(uid, 'account.move.line', id, cr) if lines and lines[0]: partner_id = lines[0].partner_id and lines[0].partner_id.id or False if partner_id and not partner_obj.has_something_to_reconcile(cr, uid, partner_id, context=context): partner_obj.mark_as_reconciled(cr, uid, [partner_id], context=context) return r_id
def mtd_reconcile(self, cr, uid, ids, type='auto', writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False, context=None): account_obj = self.pool.get('account.account') move_obj = self.pool.get('account.move') move_rec_obj = self.pool.get('account.move.reconcile') partner_obj = self.pool.get('res.partner') currency_obj = self.pool.get('res.currency') lines = self.browse(cr, uid, ids, context=context) unrec_lines = filter(lambda x: not x['reconcile_id'], lines) credit = debit = 0.0 currency = 0.0 account_id = False partner_id = False if context is None: context = {} company_list = [] for line in lines: if company_list and not line.company_id.id in company_list: raise osv.except_osv( _('Warning!'), _('To reconcile the entries company should be the same for all entries.' )) company_list.append(line.company_id.id) for line in unrec_lines: if line.state != 'valid': raise osv.except_osv( _('Error!'), _('Entry "%s" is not valid !') % line.name) credit += line['credit'] debit += line['debit'] currency += line['amount_currency'] or 0.0 account_id = line['account_id']['id'] partner_id = (line['partner_id'] and line['partner_id']['id']) or False writeoff = debit - credit # Ifdate_p in context => take this date if context.has_key('date_p') and context['date_p']: date = context['date_p'] else: date = time.strftime('%Y-%m-%d') cr.execute('SELECT account_id, reconcile_id '\ 'FROM account_move_line '\ 'WHERE id IN %s '\ 'GROUP BY account_id,reconcile_id', (tuple(ids), )) r = cr.fetchall() #TODO: move this check to a constraint in the account_move_reconcile object if len(r) != 1: raise osv.except_osv( _('Error'), _('Entries are not of the same account or already reconciled ! ' )) if not unrec_lines: raise osv.except_osv(_('Error!'), _('Entry is already reconciled.')) account = account_obj.browse(cr, uid, account_id, context=context) if r[0][1] != None: raise osv.except_osv(_('Error!'), _('Some entries are already reconciled.')) if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \ (account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))): # DO NOT FORWARD PORT if not writeoff_acc_id: if writeoff > 0: writeoff_acc_id = account.company_id.expense_currency_exchange_account_id.id else: writeoff_acc_id = account.company_id.income_currency_exchange_account_id.id if not writeoff_acc_id: raise osv.except_osv( _('Warning!'), _('You have to provide an account for the write off/exchange difference entry.' )) if writeoff > 0: debit = writeoff credit = 0.0 self_credit = writeoff self_debit = 0.0 else: debit = 0.0 credit = -writeoff self_credit = 0.0 self_debit = -writeoff # If comment exist in context, take it if 'comment' in context and context['comment']: libelle = context['comment'] else: libelle = _('Write-Off') cur_obj = self.pool.get('res.currency') cur_id = False amount_currency_writeoff = 0.0 if context.get('company_currency_id', False) != context.get( 'currency_id', False): cur_id = context.get('currency_id', False) for line in unrec_lines: if line.currency_id and line.currency_id.id == context.get( 'currency_id', False): amount_currency_writeoff += line.amount_currency else: tmp_amount = cur_obj.compute( cr, uid, line.account_id.company_id.currency_id.id, context.get('currency_id', False), abs(line.debit - line.credit), context={'date': line.date}) amount_currency_writeoff += ( line.debit > 0) and tmp_amount or -tmp_amount writeoff_lines = [ (0, 0, { 'name': libelle, 'debit': self_debit, 'credit': self_credit, 'account_id': account_id, 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': amount_currency_writeoff and -1 * amount_currency_writeoff or (account.currency_id.id and -1 * currency or 0.0) }), (0, 0, { 'name': libelle, 'debit': debit, 'credit': credit, 'account_id': writeoff_acc_id, 'analytic_account_id': context.get('analytic_id', False), 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': amount_currency_writeoff and amount_currency_writeoff or (account.currency_id.id and currency or 0.0) }) ] # DO NOT FORWARD PORT # In some exceptional situations (partial payment from a bank statement in foreign # currency), a write-off can be introduced at the very last moment due to currency # conversion. We record it on the bank statement account move. if context.get('bs_move_id'): writeoff_move_id = context['bs_move_id'] for l in writeoff_lines: self.create(cr, uid, dict(l[2], move_id=writeoff_move_id), dict(context, novalidate=True)) if not move_obj.validate( cr, uid, writeoff_move_id, context=context): raise osv.except_osv( _('Error!'), _('You cannot validate a non-balanced entry.')) else: writeoff_move_id = move_obj.create( cr, uid, { 'period_id': writeoff_period_id, 'journal_id': writeoff_journal_id, 'date': date, 'state': 'draft', 'line_id': writeoff_lines }) writeoff_line_ids = self.search( cr, uid, [('move_id', '=', writeoff_move_id), ('account_id', '=', account_id)]) if account_id == writeoff_acc_id: writeoff_line_ids = [writeoff_line_ids[1]] ids += writeoff_line_ids # marking the lines as reconciled does not change their validity, so there is no need # to revalidate their moves completely. reconcile_context = dict(context, novalidate=True) r_id = move_rec_obj.create(cr, uid, {'type': type}, context=reconcile_context) self.write(cr, uid, ids, { 'reconcile_id': r_id, 'reconcile_partial_id': False }, context=reconcile_context) # the id of the move.reconcile is written in the move.line (self) by the create method above # because of the way the line_id are defined: (4, x, False) for id in ids: workflow.trg_trigger(uid, 'account.move.line', id, cr) if lines and lines[0]: partner_id = lines[0].partner_id and lines[0].partner_id.id or False if partner_id and not partner_obj.has_something_to_reconcile( cr, uid, partner_id, context=context): partner_obj.mark_as_reconciled(cr, uid, [partner_id], context=context) return r_id