def update_account_move_line(cr, move_lines, full_reconcile_id): """Update move lines.""" for line in move_lines: # Compute reconciled similar to what happens in model, but using # data retrieved using SQL: reconciled = False digits_rounding_precision = line.company_currency_rounding if float_is_zero( line.amount_residual, precision_rounding=digits_rounding_precision): if line.line_currency_id and line.amount_residual_currency: # if there is an amount in another currency, it must # be zero as well: currency_zero = float_is_zero( line.amount_residual_currency, precision_rounding=line.line_currency_rounding ) if currency_zero: reconciled = True else: # no currency involved: reconciled = True cr.execute( """ UPDATE account_move_line SET amount_residual = %s, amount_residual_currency = %s, reconciled = %s, balance = %s, company_currency_id = %s, full_reconcile_id = %s, write_date = CURRENT_TIMESTAMP, write_uid = %s WHERE id = %s """, params=( float_round( line.amount_residual, precision_rounding=line.company_currency_rounding ), float_round( line.amount_residual_currency, precision_rounding=line.company_currency_rounding ), reconciled, line.balance, line.company_currency_id, full_reconcile_id or None, SUPERUSER_ID, line.id ) )
def testReopen(self): """Test re-opening a petty cash fund""" # Create a fund and close it # pcf1 = self.create_fund('Petty Cash Fund 01') self.assertEqual(pcf1.state, 'open') # Run the close wizard Wizard = self.env['account.pettycash.fund.close'] ctx = self.env.context.copy() ctx.update({'active_id': pcf1.id}) wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({ 'receivable_account': self.receivable_account.id, 'effective_date': datetime.today().date(), }) self.assertEqual(wiz.fund.id, pcf1.id) wiz.sudo(self.uidFinMgr).close_fund() self.assertEqual(pcf1.state, 'closed') self.assertFalse(pcf1.active) # Re-open the fund Wizard = self.env['account.pettycash.fund.reopen'] ctx = self.env.context.copy() ctx.update({'active_id': pcf1.id}) wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({ 'payable_account': self.payable_account.id, 'effective_date': datetime.today().date(), }) wiz.sudo(self.uidFinMgr).reopen_fund() self.assertEqual(pcf1.state, 'open') self.assertTrue(pcf1.active) self.assertEqual(wiz.payable_move.state, 'posted') # Check ledger accounts have been updated properly: # Accounts payable should have a credit for the fund amount. # The fund account should have a debit for same amount. move = wiz.payable_move ml1 = move.line_id[0] ml2 = move.line_id[1] self.assertEqual( float_compare(ml1.debit, wiz.fund_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml1.credit, precision_digits=2)) self.assertEqual(ml1.account_id.id, self.account.id) self.assertEqual( float_compare(ml2.credit, wiz.fund_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml2.debit, precision_digits=2)) self.assertEqual(ml2.account_id.id, self.payable_account.id)
def testIncreaseFundAmount(self): """Test increasing the fund amount""" # Create a fund pcf1 = self.create_fund('Petty Cash Fund 01') self.assertEqual(pcf1.state, 'open') # Increase the fund Wizard = self.env['account.pettycash.fund.change'] ctx = self.env.context.copy() ctx.update({'active_id': pcf1.id}) wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({ 'new_amount': 10000.00, 'payable_account': self.payable_account.id, 'effective_date': datetime.today().date(), 'custodian': self.uidInv.id, 'fund_name': 'Changed name', }) self.assertEqual(wiz.fund.id, pcf1.id) self.assertEqual( float_compare(wiz.fund_amount, pcf1.amount, precision_digits=2), 0) diff_amount = wiz.new_amount - wiz.fund_amount wiz.sudo(self.uidFinMgr).change_fund() self.assertEqual(pcf1.name, 'Changed name') self.assertEqual(pcf1.custodian.id, self.uidInv.id) self.assertEqual( float_compare(pcf1.amount, 10000.00, precision_digits=2), 0) self.assertEqual(wiz.move.state, 'posted') # Check ledger accounts have been updated properly: # Accounts payable should have a credit for the fund amount. # The fund account should have a debit for same amount. move = wiz.move ml1 = move.line_id[0] ml2 = move.line_id[1] self.assertEqual( float_compare(ml1.debit, diff_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml1.credit, precision_digits=2)) self.assertEqual(ml1.account_id.id, self.account.id) self.assertEqual( float_compare(ml2.credit, diff_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml2.debit, precision_digits=2)) self.assertEqual(ml2.account_id.id, self.payable_account.id)
def _compute_get_outstanding_info_JSON(self): """ Get information for the outstanding payments and return it to the widget. This function has been re-used from 9.0. @attention: Source in https://github.com/OCA/OCB/blob/9.0/addons/ account/models/account_invoice.py#L110 @author: Authors credited at README.rst """ for record in self: record.outstanding_credits_debits_widget = json.dumps(False) if record.state == 'open': domain = [('account_id', '=', record.account_id.id), ('partner_id', '=', self.env['res.partner']._find_accounting_partner( record.partner_id).id), ('reconcile_ref', '=', False)] if record.type in ('out_invoice', 'in_refund'): domain.extend([('credit', '>', 0), ('debit', '=', 0)]) type_payment = _('Outstanding credits') else: domain.extend([('credit', '=', 0), ('debit', '>', 0)]) type_payment = _('Outstanding debits') info = { 'title': '', 'outstanding': True, 'content': [], 'invoice_id': record.id } lines = self.env['account.move.line'].search(domain) currency_id = record.currency_id if len(lines) != 0: for line in lines: if line.currency_id and line.currency_id == \ record.currency_id: amount_to_show = abs(line.amount_residual_currency) else: amount_to_show = line.company_id.currency_id. \ with_context(date=line.date).compute(abs( line.amount_residual), record.currency_id) if float_is_zero(amount_to_show, precision_rounding=record.currency_id. rounding): continue info['content'].append({ 'journal_name': line.ref or line.move_id.name, 'amount': amount_to_show, 'currency': currency_id.symbol, 'id': line.id, 'position': currency_id.position, 'digits': [69, record.currency_id.accuracy], }) info['title'] = type_payment record.outstanding_credits_debits_widget = json.dumps(info) record.has_outstanding = True
def propagate_cancels(self): result = super(ProcurementOrder, self).propagate_cancels() for procurement in self: if procurement.rule_id.action == 'buy' and procurement.purchase_line_id: if procurement.purchase_line_id.order_id.state not in ('draft', 'cancel', 'sent', 'to validate'): raise UserError( _('Can not cancel a procurement related to a purchase order. Please cancel the purchase order first.')) if procurement.purchase_line_id: price_unit = 0.0 product_qty = 0.0 others_procs = procurement.purchase_line_id.procurement_ids.filtered(lambda r: r != procurement) for other_proc in others_procs: if other_proc.state not in ['cancel', 'draft']: product_qty += other_proc.product_uom._compute_qty_obj(other_proc.product_uom, other_proc.product_qty, procurement.purchase_line_id.product_uom) precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') if not float_is_zero(product_qty, precision_digits=precision): res = self.env['purchase.order.line']._get_name_price_quantity_date( procurement.product_id, procurement.purchase_line_id.partner_id, procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id.date_order[:10], product_qty, procurement.product_uom, procurement.purchase_line_id.order_id.currency_id) product_qty = res['quantity'] price_unit = res['price_unit'] procurement.purchase_line_id.product_qty = product_qty procurement.purchase_line_id.price_unit = price_unit return result
def f(mo): field, mode, acc_domain, ml_domain = self._parse_match_object(mo) key = (ml_domain, mode) account_ids_data = self._data[key] v = AccountingNone account_ids = self._account_ids_by_acc_domain[acc_domain] for account_id in account_ids: debit, credit = \ account_ids_data.get(account_id, (AccountingNone, AccountingNone)) if field == 'bal': v += debit - credit elif field == 'pbal' and debit >= credit: v += debit - credit elif field == 'nbal' and debit < credit: v += debit - credit elif field == 'deb': v += debit elif field == 'crd': v += credit # in initial balance mode, assume 0 is None # as it does not make sense to distinguish 0 from "no data" if v is not AccountingNone and \ mode in (self.MODE_INITIAL, self.MODE_UNALLOCATED) and \ float_is_zero(v, precision_digits=self.dp): v = AccountingNone return '(' + repr(v) + ')'
def propagate_cancels(self): result = super(ProcurementOrder, self).propagate_cancels() for procurement in self: if procurement.rule_id.action == 'buy' and procurement.purchase_line_id: if procurement.purchase_line_id.order_id.state not in ('draft', 'cancel', 'sent', 'to validate'): raise UserError( _('Can not cancel a procurement related to a purchase order. Please cancel the purchase order first.')) if procurement.purchase_line_id: price_unit = 0.0 product_qty = 0.0 others_procs = procurement.purchase_line_id.procurement_ids.filtered(lambda r: r != procurement) for other_proc in others_procs: if other_proc.state not in ['cancel', 'draft']: product_qty += other_proc.product_uom._compute_qty_obj(other_proc.product_uom, other_proc.product_qty, procurement.purchase_line_id.product_uom) precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') if not float_is_zero(product_qty, precision_digits=precision): seller = procurement.product_id._select_seller( procurement.product_id, partner_id=procurement.purchase_line_id.partner_id, quantity=product_qty, date=procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id.date_order[:10], uom_id=procurement.product_uom) price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, procurement.purchase_line_id.product_id.supplier_taxes_id, procurement.purchase_line_id.taxes_id) if seller else 0.0 if price_unit and seller and procurement.purchase_line_id.order_id.currency_id and seller.currency_id != procurement.purchase_line_id.order_id.currency_id: price_unit = seller.currency_id.compute(price_unit, procurement.purchase_line_id.order_id.currency_id) if seller and seller.product_uom != procurement.product_uom: price_unit = self.env['product.uom']._compute_price(seller.product_uom.id, price_unit, to_uom_id=procurement.product_uom.id) procurement.purchase_line_id.product_qty = product_qty procurement.purchase_line_id.price_unit = price_unit return result
def compute(self, value, date_ref=False): """Complete overwrite of compute method to add rounding on line computing and also to handle weeks and months """ date_ref = date_ref or fields.Date.today() amount = value result = [] if self.env.context.get('currency_id'): currency = self.env['res.currency'].browse( self.env.context['currency_id']) else: currency = self.env.user.company_id.currency_id prec = currency.decimal_places next_date = fields.Date.from_string(date_ref) for line in self.line_ids: amt = line.compute_line_amount(value, amount) if not self.sequential_lines: # For all lines, the beginning date is `date_ref` next_date = fields.Date.from_string(date_ref) if float_is_zero(amt, precision_rounding=prec): continue if line.option == 'day_after_invoice_date': next_date += relativedelta(days=line.days, weeks=line.weeks, months=line.months) elif line.option == 'fix_day_following_month': # Getting 1st of next month next_first_date = next_date + relativedelta(day=1, months=1) next_date = next_first_date + relativedelta(days=line.days - 1, weeks=line.weeks, months=line.months) elif line.option == 'last_day_following_month': # Getting last day of next month next_date += relativedelta(day=31, months=1) elif line.option == 'last_day_current_month': # Getting last day of next month next_date += relativedelta(day=31, months=0) next_date = self.apply_payment_days(line, next_date) if not float_is_zero(amt, precision_rounding=prec): result.append((fields.Date.to_string(next_date), amt)) amount -= amt amount = reduce(lambda x, y: x + y[1], result, 0.0) dist = round(value - amount, prec) if dist: last_date = result and result[-1][0] or fields.Date.today() result.append((last_date, dist)) return result
def _get_account_partners_details(self, account_by_ids, main_filter, target_move, start, stop, initial_balance_mode, partner_filter_ids=False, display_partner='all'): res = {} filter_from = False if main_filter in ('filter_period', 'filter_no', 'filter_opening'): filter_from = 'period' elif main_filter == 'filter_date': filter_from = 'date' partners_init_balances_by_ids = {} for account_id, account_details in account_by_ids.iteritems(): partners_init_balances_by_ids.update( self._get_partners_initial_balances( account_id, start, initial_balance_mode, partner_filter_ids=partner_filter_ids, # we'll never exclude reconciled entries in the legal # reports exclude_reconcile=False)) opening_mode = 'exclude_opening' if main_filter == 'filter_opening': opening_mode = 'include_opening' # get credit and debit for partner details = self._get_partners_totals_account( filter_from, account_id, start, stop, target_move, partner_filter_ids=partner_filter_ids, mode=opening_mode) # merge initial balances in partner details if partners_init_balances_by_ids.get(account_id): for partner_id, initial_balances in \ partners_init_balances_by_ids[account_id].iteritems(): if initial_balances.get('init_balance'): details[partner_id].update( {'init_balance': initial_balances['init_balance']}) # compute balance for the partner for partner_id, partner_details in details.iteritems(): details[partner_id]['balance'] = details[partner_id].\ get('init_balance', 0.0) + \ details[partner_id].get('debit', 0.0) - \ details[partner_id].get('credit', 0.0) if display_partner == 'non-zero_balance': details = { k: v for k, v in details.iteritems() if not float_is_zero(v['balance'], precision_digits=5) } res[account_id] = details return res
def do_queries(self, date_from, date_to, target_move='posted', additional_move_line_filter=None): """Query sums of debit and credit for all accounts and domains used in expressions. This method must be executed after done_parsing(). """ aml_model = self.company.env['account.move.line'] # {(domain, mode): {account_id: (debit, credit)}} self._data = defaultdict(dict) domain_by_mode = {} ends = [] for key in self._map_account_ids: domain, mode = key if mode == self.MODE_END and self.smart_end: # postpone computation of ending balance ends.append((domain, mode)) continue if mode not in domain_by_mode: domain_by_mode[mode] = \ self.get_aml_domain_for_dates(date_from, date_to, mode, target_move) domain = list(domain) + domain_by_mode[mode] domain.append(('account_id', 'in', self._map_account_ids[key])) if additional_move_line_filter: domain.extend(additional_move_line_filter) # fetch sum of debit/credit, grouped by account_id accs = aml_model.read_group(domain, ['debit', 'credit', 'account_id'], ['account_id']) for acc in accs: debit = acc['debit'] or 0.0 credit = acc['credit'] or 0.0 if mode in (self.MODE_INITIAL, self.MODE_UNALLOCATED) and \ float_is_zero(debit-credit, precision_rounding=self.dp): # in initial mode, ignore accounts with 0 balance continue self._data[key][acc['account_id'][0]] = (debit, credit) # compute ending balances by summing initial and variation for key in ends: domain, mode = key initial_data = self._data[(domain, self.MODE_INITIAL)] variation_data = self._data[(domain, self.MODE_VARIATION)] account_ids = set(initial_data.keys()) | set(variation_data.keys()) for account_id in account_ids: di, ci = initial_data.get(account_id, (AccountingNone, AccountingNone)) dv, cv = variation_data.get(account_id, (AccountingNone, AccountingNone)) self._data[key][account_id] = (di + dv, ci + cv)
def testClose(self): """Test closing a petty cash fund works""" pcf1 = self.create_fund('Petty Cash Fund 01') self.assertEqual(pcf1.state, 'open') # Run the close wizard Wizard = self.env['account.pettycash.fund.close'] ctx = self.env.context.copy() ctx.update({'active_id': pcf1.id}) wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({ 'receivable_account': self.receivable_account.id, 'effective_date': datetime.today().date(), }) self.assertEqual(wiz.fund.id, pcf1.id) fund_amount = pcf1.amount wiz.sudo(self.uidFinMgr).close_fund() self.assertEqual(pcf1.state, 'closed') self.assertFalse(pcf1.active) self.assertTrue(float_is_zero(pcf1.amount, precision_digits=2)) # Check ledger accounts have been updated properly: # Accounts receivable should have a debit for the fund amount. # The fund account should have a credit for same amount. move = None for m in pcf1.journal_entries: if move is None or m.id > move.id: move = m ml1 = move.line_id[0] ml2 = move.line_id[1] self.assertEqual( float_compare(ml1.debit, fund_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml1.credit, precision_digits=2)) self.assertEqual(ml1.account_id.id, self.receivable_account.id) self.assertEqual( float_compare(ml2.credit, fund_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml2.debit, precision_digits=2)) self.assertEqual(ml2.account_id.id, self.account.id)
def testCreateFundWizard(self): """Test fund creation wizard""" fundName = "Petty Cash - Test01" code = "PTY01" fund_amount = 1000.00 Wizard = self.env['account.pettycash.fund.create'] wiz = Wizard.sudo(self.uidFinMgr).create({ 'fund_name': fundName, 'fund_code': code, 'fund_amount': fund_amount, 'custodian': self.uidOwner.id, 'account': self.account.id, 'payable_account': self.payable_account.id, 'effective_date': datetime.today().date(), }) wiz.initialize_fund() self.assertEqual(wiz.payable_move.state, 'posted') # Check ledger accounts have been updated properly: # Accounts payable should have a credit for the fund amount. # The fund account should have a debit for same amount. move = wiz.payable_move ml1 = move.line_id[0] ml2 = move.line_id[1] self.assertEqual( float_compare(ml1.debit, fund_amount, precision_digits=2), 0.00) self.assertTrue(float_is_zero(ml1.credit, precision_digits=2)) self.assertEqual(ml1.account_id.id, self.account.id) self.assertEqual( float_compare(ml2.credit, fund_amount, precision_digits=2), 0.00) self.assertTrue(float_is_zero(ml2.debit, precision_digits=2)) self.assertEqual(ml2.account_id.id, self.payable_account.id)
def propagate_cancels(self): result = super(ProcurementOrder, self).propagate_cancels() for procurement in self: if procurement.rule_id.action == "buy" and procurement.purchase_line_id: if procurement.purchase_line_id.order_id.state not in ("draft", "cancel", "sent", "to validate"): raise UserError( _( "Can not cancel a procurement related to a purchase order. Please cancel the purchase order first." ) ) if procurement.purchase_line_id: price_unit = 0.0 product_qty = 0.0 others_procs = procurement.purchase_line_id.procurement_ids.filtered(lambda r: r != procurement) for other_proc in others_procs: if other_proc.state not in ["cancel", "draft"]: product_qty += other_proc.product_uom._compute_qty_obj( other_proc.product_uom, other_proc.product_qty, procurement.purchase_line_id.product_uom ) precision = self.env["decimal.precision"].precision_get("Product Unit of Measure") if not float_is_zero(product_qty, precision_digits=precision): seller = procurement.product_id._select_seller( procurement.product_id, partner_id=procurement.purchase_line_id.partner_id, quantity=product_qty, date=procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id.date_order[:10], uom_id=procurement.product_uom, ) price_unit = seller.price if seller else 0.0 if ( price_unit and seller and procurement.purchase_line_id.order_id.currency_id and seller.currency_id != procurement.purchase_line_id.order_id.currency_id ): price_unit = seller.currency_id.compute( price_unit, procurement.purchase_line_id.order_id.currency_id ) procurement.purchase_line_id.product_qty = product_qty procurement.purchase_line_id.price_unit = price_unit return result
def _compute_get_payment_info_JSON(self): """ Returns the payment info for the invoice to the widget @attention: Source in https://github.com/OCA/OCB/blob/9.0/addons/ account/models/account_invoice.py#L146 @author: Authors credited at README.rst """ for record in self: record.payments_widget = json.dumps(False) if record.payment_ids: info = { 'title': _('Less Payment'), 'outstanding': False, 'content': [] } currency_id = record.currency_id for payment in record.payment_ids: if record.type in ('out_invoice', 'in_refund'): amount = payment.credit elif record.type in ('in_invoice', 'out_refund'): amount = payment.debit if float_is_zero( amount, precision_rounding=record.currency_id.rounding): continue payment_ref = payment.move_id.name if payment.move_id.ref: payment_ref += ' (' + payment.move_id.ref + ')' info['content'].append({ 'name': payment.name, 'journal_name': payment.journal_id.name, 'amount': amount, 'currency': currency_id.symbol, 'digits': [69, currency_id.accuracy], 'position': currency_id.position, 'date': payment.date, 'payment_id': payment.id, 'move_id': payment.move_id.id, 'ref': payment_ref, }) record.payments_widget = json.dumps(info)
def f(mo): field, mode, account_codes, domain = self._parse_match_object(mo) key = (domain, mode) account_ids_data = self._data[key] debit, credit = \ account_ids_data.get(account_id, (AccountingNone, AccountingNone)) if field == 'bal': v = debit - credit elif field == 'deb': v = debit elif field == 'crd': v = credit # in initial balance mode, assume 0 is None # as it does not make sense to distinguish 0 from "no data" if v is not AccountingNone and \ mode in (self.MODE_INITIAL, self.MODE_UNALLOCATED) and \ float_is_zero(v, precision_rounding=self.dp): v = AccountingNone return '(' + repr(v) + ')'
def propagate_cancels(self): result = super(ProcurementOrder, self).propagate_cancels() for procurement in self: if procurement.rule_id.action == 'buy' and procurement.purchase_line_id: if procurement.purchase_line_id.order_id.state not in ( 'draft', 'cancel', 'sent', 'to validate'): raise UserError( _('Can not cancel a procurement related to a purchase order. Please cancel the purchase order first.' )) if procurement.purchase_line_id: price_unit = 0.0 product_qty = 0.0 others_procs = procurement.purchase_line_id.procurement_ids.filtered( lambda r: r != procurement) for other_proc in others_procs: if other_proc.state not in ['cancel', 'draft']: product_qty += other_proc.product_uom._compute_qty_obj( other_proc.product_uom, other_proc.product_qty, procurement.purchase_line_id.product_uom) precision = self.env['decimal.precision'].precision_get( 'Product Unit of Measure') if not float_is_zero(product_qty, precision_digits=precision): res = self.env[ 'purchase.order.line']._get_name_price_quantity_date( procurement.product_id, procurement.purchase_line_id.partner_id, procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id. date_order[:10], product_qty, procurement.product_uom, procurement.purchase_line_id.order_id.currency_id) product_qty = res['quantity'] price_unit = res['price_unit'] procurement.purchase_line_id.product_qty = product_qty procurement.purchase_line_id.price_unit = price_unit return result
def product_segmentation_fetch_before_done(self, cr, uid, ids, context=None): ''' Fetch standard_price and segmentation cost for every product that was purchased and is average costing method prior to change its values. Returns a dictionary. ''' res = {} precision = self.pool.get('decimal.precision').precision_get( cr, uid, 'Account') for move in self.browse(cr, uid, ids, context=context): # adapt standard price on incoming moves if the product # cost_method is 'average' if move.location_id.usage == 'supplier' and \ move.product_id.cost_method == 'average': std = move.product_id.standard_price qty_available = move.product_id.product_tmpl_id.qty_available prod_id = move.product_id.id if prod_id not in res: # /!\ TODO: Fetch segmentation for product sgmnt = {} res[prod_id] = {} res[prod_id]['qty'] = qty_available res[prod_id]['standard_price'] = std sum_sgmnt = 0.0 for fieldname in SEGMENTATION_COST: fn_cost = getattr(move.product_id, fieldname) sum_sgmnt += fn_cost sgmnt[fieldname] = fn_cost if not sum_sgmnt or \ not float_is_zero(sum_sgmnt - std, precision): sgmnt = {}.fromkeys(SEGMENTATION_COST, 0.0) res[prod_id].update(sgmnt) res[prod_id]['material_cost'] = std else: res[prod_id].update(sgmnt) return res
def f(mo): field, mode, acc_domain, ml_domain = \ self._parse_match_object(mo) key = (ml_domain, mode) # first check if account_id is involved in # the current expression part if account_id not in self._account_ids_by_acc_domain[acc_domain]: return '(AccountingNone)' # here we know account_id is involved in acc_domain account_ids_data = self._data[key] debit, credit = \ account_ids_data.get(account_id, (AccountingNone, AccountingNone)) if field == 'bal': v = debit - credit elif field == 'pbal': if debit >= credit: v = debit - credit else: v = AccountingNone elif field == 'nbal': if debit < credit: v = debit - credit else: v = AccountingNone elif field == 'deb': v = debit elif field == 'crd': v = credit # in initial balance mode, assume 0 is None # as it does not make sense to distinguish 0 from "no data" if v is not AccountingNone and \ mode in (self.MODE_INITIAL, self.MODE_UNALLOCATED) and \ float_is_zero(v, precision_digits=self.dp): v = AccountingNone return '(' + repr(v) + ')'
def change_price_vals(self, vals): if len(self) > 1: return vals else: if vals.get('chanel', False) != 'tablet' and self.chanel != 'tablet': return vals sol_obj = self.env['sale.order.line'] pricelist = vals.get( 'pricelist_id', False) or self.pricelist_id and self.pricelist_id.id partner_id = vals.get('partner_id', False) or self.partner_id and self.partner_id.id if vals.get('order_line', False): for line_est in vals['order_line']: if line_est[0] in [0, 1]: line = line_est[2] if line_est[0] == 1: line_obj = sol_obj.browse(line_est[1]) product_id = line.get( 'product_id', False ) or line_obj.product_id and line_obj.product_id.id product_uom_qty = line.get( 'product_uom_qty', False) or line_obj.product_uom_qty product_uos_qty = line.get( 'product_uom_qty', False) or line_obj.product_uos_qty product_uom = line.get( 'product_uom', False ) or line_obj.product_uom and line_obj.product_uom.id product_uos = line.get( 'product_uos', False ) or line_obj.product_uos and line_obj.product_uos.id else: product_id = line.get('product_id', False) product_uom_qty = line.get('product_uom_qty', False) product_uom = line.get('product_uom', False) product_uos = line.get('product_uos', False) product_uos_qty = line.get('product_uos_qty', False) vals_mod = sol_obj.product_id_change_with_wh( pricelist, product_id, product_uom_qty, product_uom, line.get('product_uos_qty', False), product_uos, partner_id=partner_id) if vals_mod['value'].get('discount', False): line['discount'] = vals_mod['value']['discount'] if vals_mod['value'].get('tourism', False): line['tourism'] = vals_mod['value']['tourism'] if vals_mod['value'].get('price_unit', False): if line.get('price_unit', False) and not float_is_zero( line['price_unit'], precision_digits=2): # Si es cero # no se cambia el precio line['price_unit'] = vals_mod['value'][ 'price_unit'] res = sol_obj.no_onchange_price_unit( product_id, line['price_unit'], product_uos) line['price_udv'] = res return vals
def fast_returns(self): move_obj = self.env['stock.move'] res = [] for pick in self: # Cancel assignment of existing chained assigned move invoice_st = 'none' if pick.invoice_state in ['invoiced']: invoice_st = '2binvoiced' else: invoice_st = 'none' moves_to_unreserve = [] if pick.picking_type_id.code != 'outgoing': raise except_orm(_('Error!'), _('Fast return' ' is only available with' ' outgoing pickings!')) for move in pick.move_lines: to_check_moves = [move.move_dest_id] if move.move_dest_id.id \ else [] while to_check_moves: current_move = to_check_moves.pop() if current_move.state not in ('done', 'cancel') and \ current_move.reserved_quant_ids: moves_to_unreserve.append(current_move.id) split_move_ids = move_obj.search([('split_from', '=', current_move.id)]) if split_move_ids: to_check_moves += move_obj.browse(split_move_ids) if moves_to_unreserve: move_obj.do_unreserve(moves_to_unreserve) # break the link between moves in order to be able to fix # them later if needed move_obj.write(moves_to_unreserve, {'move_orig_ids': False}) # Create new picking for returned products pick_type_id = pick.picking_type_id.return_picking_type_id and \ pick.picking_type_id.return_picking_type_id.id or \ pick.picking_type_id.id moves = self.env['stock.move'] if pick.invoice_state in ['invoiced']: invoice_st = '2binvoiced' else: invoice_st = 'none' for move in pick.move_lines: new_qty = move.product_uos_qty - move.accepted_qty new_uom_qty = move.product_uom_qty - move.product_uom_acc_qty if pick.invoice_state == '2binvoiced' and \ pick.state in ['done'] and \ float_is_zero(move.product_uom_acc_qty, precision_digits=0): # Si la cantidad aceptada es cero esta linea no debe # facturarse move.invoice_state = 'none' if new_uom_qty: # The return of a return should be linked with # the original's destination move if it was not cancelled if move.origin_returned_move_id.move_dest_id.id and \ move.origin_returned_move_id.move_dest_id.state \ != 'cancel': move_dest_id = \ move.origin_returned_move_id.move_dest_id.id else: move_dest_id = False if len(move.linked_move_operation_ids) == 1: lot_id = \ move.linked_move_operation_ids[0].\ operation_id.lot_id and \ move.linked_move_operation_ids[0].\ operation_id.lot_id.id else: lot_id = False # returned_lines += 1 new_move_id = move.copy({ 'product_id': move.product_id.id, 'product_uom_qty': new_uom_qty, 'product_uos_qty': new_qty, 'picking_id': False, 'state': 'draft', 'accepted_qty': new_qty, 'product_uom_acc_qty': new_uom_qty, 'location_id': move.location_dest_id.id, 'location_dest_id': move.location_id.id, 'picking_type_id': pick_type_id, 'warehouse_id': pick.picking_type_id.warehouse_id.id, 'origin_returned_move_id': move.id, 'procure_method': 'make_to_stock', 'restrict_lot_id': lot_id, 'move_dest_id': move_dest_id, 'invoice_state': invoice_st }) moves += new_move_id if len(moves): new_picking = pick.copy({ 'move_lines': [], 'picking_type_id': pick_type_id, 'state': 'draft', 'origin': pick.name, 'task_type': 'ubication', 'invoice_id': False, 'invoice_state': invoice_st }) res.append(new_picking.id) for move in moves: move.picking_id = new_picking.id new_picking.action_confirm() new_picking.action_assign() self.write({'reviewed': True}) return res
def testReconcileSuccess(self): """Test that all vouchers of a fund are reconciled successfully""" VoucherWiz = self.env['account.pettycash.fund.voucher'] ReconcileWiz = self.env['account.pettycash.fund.reconcile'] # Create first fund and voucher # pcf1 = self.create_fund('Petty Cash Fund 01') vwiz_vals = { 'fund': pcf1.id, 'date': datetime.today().date(), 'partner': pcf1.custodian_partner.id, 'lines': [ (0, 0, { 'expense_account': self.expense_account.id, 'amount': 100.00}), ] } vwiz1 = VoucherWiz.sudo(self.uidOwner).create(vwiz_vals) vwiz1.sudo(self.uidOwner).create_voucher() vwiz2_vals = { 'fund': pcf1.id, 'date': datetime.today().date(), 'lines': [ (0, 0, { 'expense_account': self.expense_account.id, 'amount': 150.16}), ] } vwiz2 = VoucherWiz.sudo(self.uidOwner).create(vwiz2_vals) vwiz2.sudo(self.uidOwner).create_voucher() receipts_total = 100.00 + 150.16 self.assertEqual(pcf1.vouchers[0].state, 'draft') self.assertEqual(pcf1.vouchers[1].state, 'draft') self.assertEqual(len(pcf1.vouchers_history), 0) ctx = self.env.context.copy() ctx.update({'active_id': pcf1.id}) wiz = ReconcileWiz.sudo(self.uidAccountant).with_context(ctx).create({ 'payable_account': self.payable_account.id, 'date': datetime.today().date(), }) self.assertEqual(len(wiz.vouchers), 2) wiz.sudo(self.uidAccountant).reconcile_vouchers() self.assertEqual(pcf1.vouchers_history[0].state, 'posted') self.assertEqual(pcf1.vouchers_history[1].state, 'posted') self.assertEqual(len(pcf1.vouchers), 0) self.assertEqual(pcf1.balance, pcf1.amount) # Check journal entries # self.assertEqual(wiz.move.state, 'posted') # Check ledger accounts have been updated properly: # Accounts payable should have a credit for the fund amount. # The fund account should have a debit for same amount. move = wiz.move ml1 = move.line_id[0] ml2 = move.line_id[1] self.assertEqual( float_compare(ml1.debit, receipts_total, precision_digits=2), 0.00) self.assertTrue(float_is_zero(ml1.credit, precision_digits=2)) self.assertEqual(ml1.account_id.id, self.account.id) self.assertEqual( float_compare(ml2.credit, receipts_total, precision_digits=2), 0.00) self.assertTrue(float_is_zero(ml2.debit, precision_digits=2)) self.assertEqual(ml2.account_id.id, self.payable_account.id) self.assertEqual( float_compare(pcf1.balance, pcf1.amount, precision_digits=2), 0.00)
def testReopenWithChanges(self): """Test re-opening a petty cash fund and changing some values""" # Create a fund and close it # pcf1 = self.create_fund('Petty Cash Fund 01') self.assertEqual(pcf1.state, 'open') # Run the close wizard Wizard = self.env['account.pettycash.fund.close'] ctx = self.env.context.copy() ctx.update({'active_id': pcf1.id}) wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({ 'receivable_account': self.receivable_account.id, 'effective_date': datetime.today().date(), }) self.assertEqual(wiz.fund.id, pcf1.id) wiz.sudo(self.uidFinMgr).close_fund() self.assertEqual(pcf1.state, 'closed') self.assertFalse(pcf1.active) # Re-open the fund # uidOtherOwner = self.user_model.create({ 'name': 'Other Petty Cash Fund Owner', 'login': '******', 'email': 'pcfowner2@localhost', }) uidOtherOwner.write({ 'groups_id': [(4, self.ref('account.group_pettycash_custodian'))] }) Wizard = self.env['account.pettycash.fund.reopen'] ctx = self.env.context.copy() ctx.update({'active_id': pcf1.id}) wiz = Wizard.sudo(self.uidFinMgr).with_context(ctx).create({ 'custodian': uidOtherOwner.id, 'fund_amount': 5000.000, 'payable_account': self.payable_account.id, 'effective_date': datetime.today().date(), }) wiz.sudo(self.uidFinMgr).reopen_fund() self.assertEqual(pcf1.state, 'open') self.assertTrue(pcf1.active) self.assertEqual(wiz.payable_move.state, 'posted') # Check ledger accounts have been updated properly: # Accounts payable should have a credit for the fund amount. # The fund account should have a debit for same amount. move = wiz.payable_move ml1 = move.line_id[0] ml2 = move.line_id[1] self.assertEqual( float_compare(ml1.debit, wiz.fund_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml1.credit, precision_digits=2)) self.assertEqual(ml1.account_id.id, self.account.id) self.assertEqual( float_compare(ml2.credit, wiz.fund_amount, precision_digits=2), 0) self.assertTrue(float_is_zero(ml2.debit, precision_digits=2)) self.assertEqual(ml2.account_id.id, self.payable_account.id)
def _calculate_records(self, cr, uid, ids, context=None, recalculate=True): report_obj = self.pool['l10n.es.aeat.mod340.report'] mod340 = report_obj.browse(cr, uid, ids)[0] invoices340 = self.pool['l10n.es.aeat.mod340.issued'] invoices340_rec = self.pool['l10n.es.aeat.mod340.received'] issued_obj = self.pool['l10n.es.aeat.mod340.tax_line_issued'] received_obj = self.pool['l10n.es.aeat.mod340.tax_line_received'] sequence_obj = self.pool['ir.sequence'] mod340.write({ 'state': 'calculated', 'calculation_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) }) if not mod340.company_id.partner_id.vat: raise orm.except_orm(mod340.company_id.partner_id.name, _("This company doesn't have NIF")) account_period_ids = [x.id for x in mod340.periods] # Limpieza de las facturas calculadas anteriormente del_ids = invoices340.search(cr, uid, [('mod340_id', '=', mod340.id)]) if del_ids: invoices340.unlink(cr, uid, del_ids, context=context) del_ids = invoices340_rec.search(cr, uid, [('mod340_id', '=', mod340.id)]) if del_ids: invoices340_rec.unlink(cr, uid, del_ids, context=context) domain = [('period_id', 'in', account_period_ids), ('state', 'in', ('open', 'paid'))] invoice_obj = self.pool['account.invoice'] invoice_ids = invoice_obj.search(cr, uid, domain, context=context) tax_code_rec_totals = {} tax_code_isu_totals = {} for invoice in invoice_obj.browse(cr, uid, invoice_ids, context): sign = 1 if invoice.type in ('out_refund', 'in_refund'): sign = -1 include = False if invoice.currency_id.id != invoice.company_id.currency_id.id: cur_rate = invoice.cc_amount_untaxed / invoice.amount_untaxed else: cur_rate = 1 for tax_line in invoice.tax_line: if tax_line.base_code_id and tax_line.base: if tax_line.base_code_id.mod340: include = True break partner = invoice.partner_id.commercial_partner_id if include: exception_text = "" country_code = False nif = False if partner.vat: country_code, nif = (re.match(r"([A-Z]{0,2})(.*)", partner.vat).groups()) if country_code and country_code == 'EL': country_code = 'GR' else: if partner.country_id: country_code = partner.country_id.code else: exception_text += _( 'La siguiente empresa no' 'tiene un pais relacionado: %s')\ % partner.name values = { 'mod340_id': mod340.id, 'partner_id': partner.id, 'partner_vat': (partner.vat and partner.vat.replace('ES', '')) or '', 'representative_vat': '', 'partner_country_code': country_code, 'invoice_id': invoice.id, 'base_tax': invoice.cc_amount_untaxed * sign, 'amount_tax': invoice.cc_amount_tax * sign, 'total': invoice.cc_amount_total * sign, 'date_invoice': invoice.date_invoice, 'record_number': sequence_obj.get(cr, uid, 'mod340'), } key_identification = '6' if not partner.vat: key_identification = '6' else: if country_code: if country_code == 'ES': key_identification = '1' else: group_country_europe = self.pool[ 'res.country.group'].search( cr, uid, [('name', '=', 'Europe')], context=context) if group_country_europe: if country_code == 'EL': country_code = 'GR' country_ids = self.pool['res.country'].search( cr, uid, [('code', '=', country_code), ('country_group_ids', '=', group_country_europe[0])], context=context) if country_ids and invoice.fiscal_position.\ intracommunity_operations: key_identification = '2' # Clave de operación key_operation = ' ' if invoice.type in ['out_invoice', 'out_refund']: if invoice.type == 'out_refund': key_operation = 'D' elif invoice.is_ticket_summary == 1: key_operation = 'B' elif invoice.is_leasing_invoice()[0]: key_operation = 'R' else: if invoice.is_reverse_charge_invoice()[0]: key_operation = 'I' elif invoice.fiscal_position.intracommunity_operations: key_operation = 'P' elif invoice.type == 'in_refund': key_operation = 'D' elif invoice.is_leasing_invoice()[0]: key_operation = 'R' values.update({ 'vat_type': key_identification, 'key_operation': key_operation }) if invoice.type in ['out_invoice', 'out_refund']: invoice_created = invoices340.create(cr, uid, values) if invoice.type in ['in_invoice', 'in_refund']: values.update({ 'supplier_invoice_number': invoice.supplier_invoice_number or invoice.reference or '' }) invoice_created = invoices340_rec.create(cr, uid, values) tot_invoice = invoice.cc_amount_untaxed * sign check_base = 0 invoice_base_tax = 0 invoice_amount_tax = 0 # Add the invoices detail to the partner record surcharge_taxes_lines = [] adqu_intra = False lines_created = 0 if invoice.fiscal_position.intracommunity_operations \ and invoice.type in ("in_invoice", "in_refund"): adqu_intra = True for tax_line in invoice.tax_line: if tax_line.base_code_id and tax_line.base: if tax_line.base_code_id.mod340: # Si es una linea de recargo la gurada para # gestionarla al acabar con las lienas normales" if tax_line.base_code_id.surcharge_tax_id: surcharge_taxes_lines.append(tax_line) else: tax_percentage = self.proximo( round(abs(tax_line.amount / tax_line.base), 4), VALID_TYPES) values = { 'name': tax_line.name, 'tax_percentage': tax_percentage, 'tax_amount': tax_line.amount * sign * cur_rate, 'base_amount': tax_line.base_amount, 'invoice_record_id': invoice_created, 'tax_code_id': tax_line.base_code_id.id } invoice_base_tax = invoice_base_tax +\ values['base_amount'] invoice_amount_tax = invoice_amount_tax +\ values['tax_amount'] domain = [ ('invoice_record_id', '=', invoice_created), ('tax_code_id', '=', tax_line.base_code_id.id), ('tax_percentage', '=', tax_percentage), ] if sign == 1: domain.append(('tax_amount', '>=', 0)) else: domain.append(('tax_amount', '<=', 0)) if invoice.type in ("out_invoice", "out_refund"): line_id = issued_obj.search( cr, uid, domain, context=context) if line_id: issue = issued_obj.browse( cr, uid, line_id[0], context=context) values.update({ 'name': "%s/%s" % (issue.name, values['name']), 'tax_amount': issue.tax_amount + values['tax_amount'], 'base_amount': issue.base_amount + values['base_amount'] }) issued_obj.write( cr, uid, line_id[0], values) else: lines_created = lines_created + 1 issued_obj.create(cr, uid, values) if not tax_code_isu_totals.get( tax_line.base_code_id.id): tax_code_isu_totals.update({ tax_line.base_code_id.id: [ tax_line.base_amount, tax_line.amount * sign * cur_rate, tax_percentage ], }) else: tax_code_isu_totals[ tax_line.base_code_id.id][ 0] +=\ tax_line.base_amount tax_code_isu_totals[ tax_line.base_code_id.id][ 1] +=\ tax_line.amount * sign * cur_rate if invoice.type in ("in_invoice", "in_refund"): line_id = received_obj.search( cr, uid, domain, context=context) if line_id: recei = received_obj.browse( cr, uid, line_id[0], context=context) values['name'] = "%s/%s" % ( recei.name, values['name']) values['tax_amount'] =\ recei.tax_amount +\ values['tax_amount'] values['base_amount'] =\ recei.base_amount +\ values['base_amount'] received_obj.write( cr, uid, line_id[0], values) else: lines_created = lines_created + 1 received_obj.create(cr, uid, values) if not tax_code_rec_totals.get( tax_line.base_code_id.id): tax_code_rec_totals.update({ tax_line.base_code_id.id: [ tax_line.base_amount, tax_line.amount * sign * cur_rate, tax_percentage ] }) else: tax_code_rec_totals[ tax_line.base_code_id. id][0] += tax_line.base_amount tax_code_rec_totals[ tax_line.base_code_id.id][ 1] +=\ tax_line.amount * sign * cur_rate if tax_line.amount >= 0: check_base += tax_line.base_amount # Control problem with extracomunitary # purchase invoices if not adqu_intra: tot_invoice +=\ tax_line.amount * sign * \ cur_rate values = { 'base_tax': invoice_base_tax, 'amount_tax': invoice_amount_tax } if lines_created > 1 and key_operation == ' ': values.update({'key_operation': 'C'}) if tot_invoice != invoice.cc_amount_total: values.update({'total': tot_invoice}) if values: if invoice.type in ['out_invoice', 'out_refund']: invoices340.write(cr, uid, invoice_created, values) if invoice.type in ['in_invoice', 'in_refund']: invoices340_rec.write(cr, uid, invoice_created, values) rec_tax_invoice = 0 for surcharge in surcharge_taxes_lines: rec_tax_percentage = round( surcharge.amount / surcharge.base, 3) rec_tax_invoice += surcharge.amount * sign * cur_rate tot_invoice += surcharge.amount * sign * cur_rate values = { 'rec_tax_percentage': rec_tax_percentage, 'rec_tax_amount': surcharge.amount * sign * cur_rate } # GET correct tax_line from created in previous step domain = [('invoice_record_id', '=', invoice_created), ('tax_code_id', '=', surcharge.base_code_id.surcharge_tax_id.id)] line_id = issued_obj.search(cr, uid, domain, context=context) issued_obj.write(cr, uid, line_id, values) if invoice.type in ['out_invoice', 'out_refund']: vals2 = {'rec_amount_tax': rec_tax_invoice} if rec_tax_invoice: vals2.update({'total': tot_invoice}) invoices340.write(cr, uid, invoice_created, vals2) if invoice.type in ['in_invoice', 'in_refund']: invoices340_rec.write(cr, uid, invoice_created, {'amount_tax': invoice_amount_tax}) sign = 1 if invoice.type in ('out_refund', 'in_refund'): sign = -1 if not float_is_zero( invoice.cc_amount_untaxed * sign - check_base, precision_digits=1): exception_text += _('Invoice %s, Amount untaxed Lines ' '%.2f do not correspond to ' 'AmountUntaxed on Invoice %.2f')\ % ( invoice.number, check_base, invoice.cc_amount_untaxed * sign) if exception_text: if invoice.type in ['out_invoice', 'out_refund']: invoices340.write(cr, uid, invoice_created, { 'txt_exception': exception_text, 'exception': True }) if invoice.type in ['in_invoice', 'in_refund']: invoices340_rec.write(cr, uid, invoice_created, { 'txt_exception': exception_text, 'exception': True }) summary_obj = self.pool['l10n.es.aeat.mod340.tax_summary'] sum_ids = summary_obj.search(cr, uid, [('mod340_id', '=', mod340.id)]) summary_obj.unlink(cr, uid, sum_ids) for tax_code_id, values in tax_code_isu_totals.items(): vals = { 'tax_code_id': tax_code_id, 'sum_base_amount': values[0], 'sum_tax_amount': values[1], 'tax_percent': values[2], 'mod340_id': mod340.id, 'type': 'issued' } summary_obj.create(cr, uid, vals) for tax_code_id, values in tax_code_rec_totals.items(): vals = { 'tax_code_id': tax_code_id, 'sum_base_amount': values[0], 'sum_tax_amount': values[1], 'tax_percent': values[2], 'mod340_id': mod340.id, 'type': 'received' } summary_obj.create(cr, uid, vals) if recalculate: mod340.write({ 'state': 'calculated', 'calculation_date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) }) return True
def _calculate_records(self, report_id): report = self.env['l10n.es.aeat.mod340.report'].browse(report_id) invoices340 = self.env['l10n.es.aeat.mod340.issued'] invoices340_rec = self.env['l10n.es.aeat.mod340.received'] issued_obj = self.env['l10n.es.aeat.mod340.tax_line_issued'] received_obj = self.env['l10n.es.aeat.mod340.tax_line_received'] sequence_obj = self.env['ir.sequence'] country_group_europe = self.env.ref('base.europe') report.write({ 'state': 'calculated', 'calculation_date': fields.Datetime.now(), }) if not report.company_id.partner_id.vat: raise UserError(_("This company doesn't have NIF")) # Limpieza de las facturas calculadas anteriormente report.issued.unlink() report.received.unlink() domain = [('period_id', 'in', report.periods.ids), ('state', 'in', ('open', 'paid'))] tax_code_rec_totals = {} tax_code_isu_totals = {} for invoice in report.env['account.invoice'].search(domain): sign = 1 if invoice.type in ('out_refund', 'in_refund'): sign = -1 if not any( invoice.tax_line.filtered('base').mapped( 'base_code_id.mod340')): continue if invoice.currency_id.id != invoice.company_id.currency_id.id \ and invoice.amount_untaxed: cur_rate = invoice.cc_amount_untaxed / invoice.amount_untaxed else: cur_rate = 1 partner = invoice.partner_id.commercial_partner_id exception_text = "" country_code = False if partner.vat: country_code, nif = (re.match(r"([A-Z]{0,2})(.*)", partner.vat).groups()) if country_code and country_code == 'EL': country_code = 'GR' else: if partner.country_id: country_code = partner.country_id.code else: exception_text += _( 'La siguiente empresa no tiene un pais relacionado: %s' ) % partner.name values = { 'mod340_id': report.id, 'partner_id': partner.id, 'partner_vat': (partner.vat and partner.vat.replace('ES', '')) or '', 'representative_vat': '', 'partner_country_code': country_code, 'invoice_id': invoice.id, 'base_tax': invoice.cc_amount_untaxed * sign, 'amount_tax': invoice.cc_amount_tax * sign, 'total': invoice.cc_amount_total * sign, 'date_invoice': invoice.date_invoice, 'record_number': sequence_obj.next_by_code('mod340'), } key_identification = '6' if not partner.vat: key_identification = '6' else: if country_code == 'EL': country_code = 'GR' if country_code == 'ES': key_identification = '1' elif country_code: eu_country = report.env['res.country'].search([ ('code', '=', country_code), ('country_group_ids', 'in', country_group_europe.id) ]) if eu_country and invoice.fiscal_position.\ intracommunity_operations: key_identification = '2' # Clave de operación key_operation = ' ' if invoice.type in ['out_invoice', 'out_refund']: if invoice.type == 'out_refund': key_operation = 'D' elif invoice.is_ticket_summary == 1: key_operation = 'B' elif invoice.is_leasing_invoice()[0]: key_operation = 'R' else: if invoice.is_reverse_charge_invoice()[0]: key_operation = 'I' elif invoice.fiscal_position.intracommunity_operations: key_operation = 'P' elif invoice.type == 'in_refund': key_operation = 'D' elif invoice.is_leasing_invoice()[0]: key_operation = 'R' values.update({ 'vat_type': key_identification, 'key_operation': key_operation, }) if invoice.type in ['out_invoice', 'out_refund']: invoice_created = invoices340.create(values) if invoice.type in ['in_invoice', 'in_refund']: values.update({ 'supplier_invoice_number': (invoice.supplier_invoice_number or invoice.reference or ''), }) invoice_created = invoices340_rec.create(values) tot_invoice = invoice.cc_amount_untaxed * sign check_base = 0 invoice_base_tax = 0 invoice_amount_tax = 0 # Add the invoices detail to the partner record surcharge_taxes_lines = [] adqu_intra = False lines_created = 0 if invoice.fiscal_position.intracommunity_operations \ and invoice.type in ("in_invoice", "in_refund"): adqu_intra = True tax_lines = invoice.tax_line.filtered( lambda x: x.base_code_id.mod340 and x.base) for tax_line in tax_lines: if tax_line.base_code_id.surcharge_tax_id: # Si es una linea de recargo la guarda para # gestionarla al acabar con las líneas normales surcharge_taxes_lines.append(tax_line) else: tax_percentage = self.proximo( round(abs(tax_line.amount / tax_line.base), 4), VALID_TYPES, ) values = { 'name': tax_line.name, 'tax_percentage': tax_percentage, 'tax_amount': tax_line.amount * sign * cur_rate, 'base_amount': tax_line.base_amount, 'invoice_record_id': invoice_created.id, 'tax_code_id': tax_line.base_code_id.id } invoice_base_tax += values['base_amount'] invoice_amount_tax += values['tax_amount'] domain = [ ('invoice_record_id', '=', invoice_created.id), ('tax_code_id', '=', tax_line.base_code_id.id), ('tax_percentage', '=', tax_percentage), ] if sign == 1: domain.append(('tax_amount', '>=', 0)) else: domain.append(('tax_amount', '<=', 0)) if invoice.type in ("out_invoice", "out_refund"): obj = issued_obj dic = tax_code_isu_totals key = 'issued' else: obj = received_obj dic = tax_code_rec_totals key = 'received' record = obj.search(domain) if record: values['name'] += '/' + record.name values['tax_amount'] += record.tax_amount values['base_amount'] += record.base_amount record.write(values) else: lines_created += 1 obj.create(values) base_code = tax_line.base_code_id if not dic.get(base_code): dic[base_code] = { 'base': tax_line.base_amount, 'tax': tax_line.amount * sign * cur_rate, 'perc': tax_percentage, key: invoice_created, } else: dic[base_code]['base'] += tax_line.base_amount dic[base_code]['tax'] += (tax_line.amount * sign * cur_rate) dic[base_code][key] += invoice_created if tax_line.amount >= 0: check_base += tax_line.base_amount # Control problem with extracommunitary purchase invoices if not adqu_intra: tot_invoice += tax_line.amount * sign * cur_rate values = { 'base_tax': invoice_base_tax, 'amount_tax': invoice_amount_tax, } if lines_created > 1 and key_operation == ' ': values['key_operation'] = 'C' if tot_invoice != invoice.cc_amount_total: values['total'] = tot_invoice if invoice.type in ['out_invoice', 'out_refund']: invoice_created.write(values) if invoice.type in ['in_invoice', 'in_refund']: invoice_created.write(values) rec_tax_invoice = 0 for surcharge in surcharge_taxes_lines: rec_tax_percentage = round(surcharge.amount / surcharge.base, 3) rec_tax_invoice += surcharge.amount * sign * cur_rate tot_invoice += surcharge.amount * sign * cur_rate values = { 'rec_tax_percentage': rec_tax_percentage, 'rec_tax_amount': surcharge.amount * sign * cur_rate } # GET correct tax_line from created in previous step domain = [('invoice_record_id', '=', invoice_created.id), ('tax_code_id', '=', surcharge.base_code_id.surcharge_tax_id.id)] issued_obj.search(domain).write(values) # Se añade al resumen de facturas emitidas # el detalle de los recargos de equivalencia dic = tax_code_isu_totals key = 'issued' base_code = surcharge.base_code_id if not dic.get(base_code): dic[base_code] = { 'base': surcharge.base_amount, 'tax': surcharge.amount * sign * cur_rate, 'perc': rec_tax_percentage, key: invoice_created, } else: dic[base_code]['base'] += surcharge.base_amount dic[base_code]['tax'] += (surcharge.amount * sign * cur_rate) dic[base_code][key] += invoice_created if invoice.type in ['out_invoice', 'out_refund']: vals2 = {'rec_amount_tax': rec_tax_invoice} if rec_tax_invoice: vals2.update({'total': tot_invoice}) invoice_created.write(vals2) if invoice.type in ['in_invoice', 'in_refund']: invoice_created.write({'amount_tax': invoice_amount_tax}) sign = 1 if invoice.type in ('out_refund', 'in_refund'): sign = -1 if not float_is_zero(invoice.cc_amount_untaxed * sign - check_base, precision_digits=1): exception_text += _( 'Invoice %s, Amount untaxed Lines %.2f do not correspond ' 'to AmountUntaxed on Invoice %.2f') % ( invoice.number, check_base, invoice.cc_amount_untaxed * sign, ) if exception_text: invoice_created.write({ 'txt_exception': exception_text, 'exception': True, }) summary_obj = report.env['l10n.es.aeat.mod340.tax_summary'] report.summary_issued.unlink() report.summary_received.unlink() summary_types = { 'issued': tax_code_isu_totals, 'received': tax_code_rec_totals, } for summary_type, summary in summary_types.iteritems(): for tax_code, values in summary.iteritems(): summary_obj.create({ 'tax_code_id': tax_code.id, 'sum_base_amount': values['base'], 'sum_tax_amount': values['tax'], 'tax_percent': values['perc'], 'mod340_id': report.id, 'issue_ids': [(6, 0, values.get('issued', invoices340).ids)], 'received_ids': [(6, 0, values.get('received', invoices340_rec).ids)], 'summary_type': summary_type, }) return True
def _get_account_partners_details( self, account_by_ids, main_filter, target_move, start, stop, initial_balance_mode, partner_filter_ids=False, display_partner="all", ): res = {} filter_from = False if main_filter in ("filter_period", "filter_no", "filter_opening"): filter_from = "period" elif main_filter == "filter_date": filter_from = "date" partners_init_balances_by_ids = {} for account_id, account_details in account_by_ids.iteritems(): partners_init_balances_by_ids.update( self._get_partners_initial_balances( account_id, start, initial_balance_mode, partner_filter_ids=partner_filter_ids, # we'll never exclude reconciled entries in the legal # reports exclude_reconcile=False, ) ) opening_mode = "exclude_opening" if main_filter == "filter_opening": opening_mode = "include_opening" # get credit and debit for partner details = self._get_partners_totals_account( filter_from, account_id, start, stop, target_move, partner_filter_ids=partner_filter_ids, mode=opening_mode, ) # merge initial balances in partner details if partners_init_balances_by_ids.get(account_id): for partner_id, initial_balances in partners_init_balances_by_ids[account_id].iteritems(): if initial_balances.get("init_balance"): details[partner_id].update({"init_balance": initial_balances["init_balance"]}) # compute balance for the partner for partner_id, partner_details in details.iteritems(): details[partner_id]["balance"] = ( details[partner_id].get("init_balance", 0.0) + details[partner_id].get("debit", 0.0) - details[partner_id].get("credit", 0.0) ) if display_partner == "non-zero_balance": details = {k: v for k, v in details.iteritems() if not float_is_zero(v["balance"], precision_digits=5)} res[account_id] = details return res