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
             )
         )
Beispiel #2
0
    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)
Beispiel #3
0
    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
Beispiel #5
0
    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
Beispiel #6
0
 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) + ')'
Beispiel #7
0
    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
Beispiel #8
0
    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
Beispiel #10
0
    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)
Beispiel #12
0
    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 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)
Beispiel #14
0
    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)
Beispiel #15
0
    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 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) + ')'
Beispiel #19
0
    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
Beispiel #20
0
 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
Beispiel #21
0
 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) + ')'
Beispiel #22
0
    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
Beispiel #23
0
    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
Beispiel #24
0
    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)
Beispiel #25
0
    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
Beispiel #27
0
    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