示例#1
0
 def _check_build_page_info(self, i, p):
     multi_stub = self.company_id.account_check_printing_multi_stub
     return {
         'sequence_number':
         self.check_number if (self.journal_id.check_manual_sequencing
                               and self.check_number != 0) else False,
         'payment_date':
         format_date(self.env, self.payment_date),
         'partner_id':
         self.partner_id,
         'partner_name':
         self.partner_id.name,
         'currency':
         self.currency_id,
         'state':
         self.state,
         'amount':
         formatLang(self.env, self.amount, currency_obj=self.currency_id)
         if i == 0 else 'VOID',
         'amount_in_word':
         self._check_fill_line(self.check_amount_in_words)
         if i == 0 else 'VOID',
         'memo':
         self.communication,
         'stub_cropped':
         not multi_stub and len(self.invoice_ids) > INV_LINES_PER_STUB,
         # If the payment does not reference an invoice, there is no stub line to display
         'stub_lines':
         p,
     }
示例#2
0
    def _compute_invoice_taxes_by_group(self):
        report_or_portal_view = 'commit_assetsbundle' in self.env.context or \
            not self.env.context.get('params', {}).get('view_type') == 'form'
        if not report_or_portal_view:
            return super()._compute_invoice_taxes_by_group()

        move_with_doc_type = self.filtered('l10n_latam_document_type_id')
        for move in move_with_doc_type:
            lang_env = move.with_context(lang=move.partner_id.lang).env
            tax_lines = move.l10n_latam_tax_ids
            res = {}
            # There are as many tax line as there are repartition lines
            done_taxes = set()
            for line in tax_lines:
                res.setdefault(line.tax_line_id.tax_group_id, {
                    'base': 0.0,
                    'amount': 0.0
                })
                res[line.tax_line_id.
                    tax_group_id]['amount'] += line.price_subtotal
                tax_key_add_base = tuple(
                    move._get_tax_key_for_group_add_base(line))
                if tax_key_add_base not in done_taxes:
                    # The base should be added ONCE
                    res[line.tax_line_id.
                        tax_group_id]['base'] += line.tax_base_amount
                    done_taxes.add(tax_key_add_base)
            res = sorted(res.items(), key=lambda l: l[0].sequence)
            move.amount_by_group = [(
                group.name,
                amounts['amount'],
                amounts['base'],
                formatLang(lang_env,
                           amounts['amount'],
                           currency_obj=move.currency_id),
                formatLang(lang_env,
                           amounts['base'],
                           currency_obj=move.currency_id),
                len(res),
                group.id,
            ) for group, amounts in res]
        super(AccountMove,
              self - move_with_doc_type)._compute_invoice_taxes_by_group()
示例#3
0
 def name_get(self):
     result = []
     for po in self:
         name = po.name
         if po.partner_ref:
             name += ' (' + po.partner_ref + ')'
         if self.env.context.get('show_total_amount') and po.amount_total:
             name += ': ' + formatLang(self.env, po.amount_total, currency_obj=po.currency_id)
         result.append((po.id, name))
     return result
示例#4
0
    def _check_make_stub_line(self, invoice):
        """ Return the dict used to display an invoice/refund in the stub
        """
        # Find the account.partial.reconcile which are common to the invoice and the payment
        if invoice.type in ['in_invoice', 'out_refund']:
            invoice_sign = 1
            invoice_payment_reconcile = invoice.line_ids.mapped(
                'matched_debit_ids').filtered(
                    lambda r: r.debit_move_id in self.move_line_ids)
        else:
            invoice_sign = -1
            invoice_payment_reconcile = invoice.line_ids.mapped(
                'matched_credit_ids').filtered(
                    lambda r: r.credit_move_id in self.move_line_ids)

        if self.currency_id != self.journal_id.company_id.currency_id:
            amount_paid = abs(
                sum(invoice_payment_reconcile.mapped('amount_currency')))
        else:
            amount_paid = abs(sum(invoice_payment_reconcile.mapped('amount')))

        amount_residual = invoice_sign * invoice.amount_residual

        return {
            'due_date':
            format_date(self.env, invoice.invoice_date_due),
            'number':
            invoice.ref and invoice.name + ' - ' + invoice.ref or invoice.name,
            'amount_total':
            formatLang(self.env,
                       invoice_sign * invoice.amount_total,
                       currency_obj=invoice.currency_id),
            'amount_residual':
            formatLang(
                self.env, amount_residual, currency_obj=invoice.currency_id)
            if amount_residual * 10**4 != 0 else '-',
            'amount_paid':
            formatLang(self.env,
                       invoice_sign * amount_paid,
                       currency_obj=invoice.currency_id),
            'currency':
            invoice.currency_id,
        }
示例#5
0
 def get_journal_dashboard_datas(self):
     res = super(AccountJournal, self).get_journal_dashboard_datas()
     #add the number and sum of expenses to pay to the json defining the accounting dashboard data
     (query, query_args) = self._get_expenses_to_pay_query()
     self.env.cr.execute(query, query_args)
     query_results_to_pay = self.env.cr.dictfetchall()
     (number_to_pay, sum_to_pay) = self._count_results_and_sum_amounts(
         query_results_to_pay, self.company_id.currency_id)
     res['number_expenses_to_pay'] = number_to_pay
     res['sum_expenses_to_pay'] = formatLang(self.env,
                                             sum_to_pay or 0.0,
                                             currency_obj=self.currency_id
                                             or self.company_id.currency_id)
     return res
示例#6
0
    def _get_reward_values_discount(self, program):
        if program.discount_type == 'fixed_amount':
            return [{
                'name':
                _("Discount: ") + program.name,
                'product_id':
                program.discount_line_product_id.id,
                'price_unit':
                -self._get_reward_values_discount_fixed_amount(program),
                'product_uom_qty':
                1.0,
                'product_uom':
                program.discount_line_product_id.uom_id.id,
                'is_reward_line':
                True,
                'tax_id':
                [(4, tax.id, False)
                 for tax in program.discount_line_product_id.taxes_id],
            }]
        reward_dict = {}
        lines = self._get_paid_order_lines()
        if program.discount_apply_on == 'cheapest_product':
            line = self._get_cheapest_line()
            if line:
                discount_line_amount = line.price_reduce * (
                    program.discount_percentage / 100)
                if discount_line_amount:
                    taxes = line.tax_id
                    if self.fiscal_position_id:
                        taxes = self.fiscal_position_id.map_tax(taxes)

                    reward_dict[line.tax_id] = {
                        'name': _("Discount: ") + program.name,
                        'product_id': program.discount_line_product_id.id,
                        'price_unit': -discount_line_amount,
                        'product_uom_qty': 1.0,
                        'product_uom':
                        program.discount_line_product_id.uom_id.id,
                        'is_reward_line': True,
                        'tax_id': [(4, tax.id, False) for tax in taxes],
                    }
        elif program.discount_apply_on in ['specific_products', 'on_order']:
            if program.discount_apply_on == 'specific_products':
                # We should not exclude reward line that offer this product since we need to offer only the discount on the real paid product (regular product - free product)
                free_product_lines = self.env['sale.coupon.program'].search([
                    ('reward_type', '=', 'product'),
                    ('reward_product_id', 'in',
                     program.discount_specific_product_ids.ids)
                ]).mapped('discount_line_product_id')
                lines = lines.filtered(lambda x: x.product_id in
                                       (program.discount_specific_product_ids |
                                        free_product_lines))

            for line in lines:
                discount_line_amount = self._get_reward_values_discount_percentage_per_line(
                    program, line)

                if discount_line_amount:

                    if line.tax_id in reward_dict:
                        reward_dict[
                            line.tax_id]['price_unit'] -= discount_line_amount
                    else:
                        taxes = line.tax_id
                        if self.fiscal_position_id:
                            taxes = self.fiscal_position_id.map_tax(taxes)

                        tax_name = ""
                        if len(taxes) == 1:
                            tax_name = " - " + _(
                                "On product with following tax: ") + ', '.join(
                                    taxes.mapped('name'))
                        elif len(taxes) > 1:
                            tax_name = " - " + _(
                                "On product with following taxes: "
                            ) + ', '.join(taxes.mapped('name'))

                        reward_dict[line.tax_id] = {
                            'name':
                            _("Discount: ") + program.name + tax_name,
                            'product_id':
                            program.discount_line_product_id.id,
                            'price_unit':
                            -discount_line_amount,
                            'product_uom_qty':
                            1.0,
                            'product_uom':
                            program.discount_line_product_id.uom_id.id,
                            'is_reward_line':
                            True,
                            'tax_id': [(4, tax.id, False) for tax in taxes],
                        }

        # If there is a max amount for discount, we might have to limit some discount lines or completely remove some lines
        max_amount = program._compute_program_amount('discount_max_amount',
                                                     self.currency_id)
        if max_amount > 0:
            amount_already_given = 0
            for val in list(reward_dict):
                amount_to_discount = amount_already_given + reward_dict[val][
                    "price_unit"]
                if abs(amount_to_discount) > max_amount:
                    reward_dict[val]["price_unit"] = -(
                        max_amount - abs(amount_already_given))
                    add_name = formatLang(self.env,
                                          max_amount,
                                          currency_obj=self.currency_id)
                    reward_dict[val]["name"] += "( " + _(
                        "limited to ") + add_name + ")"
                amount_already_given += reward_dict[val]["price_unit"]
                if reward_dict[val]["price_unit"] == 0:
                    del reward_dict[val]
        return reward_dict.values()
    def get_journal_dashboard_datas(self):
        currency = self.currency_id or self.company_id.currency_id
        number_to_reconcile = number_to_check = last_balance = account_sum = 0
        title = ''
        number_draft = number_waiting = number_late = to_check_balance = 0
        sum_draft = sum_waiting = sum_late = 0.0
        if self.type in ['bank', 'cash']:
            last_bank_stmt = self.env['account.bank.statement'].search([('journal_id', 'in', self.ids)], order="date desc, id desc", limit=1)
            last_balance = last_bank_stmt and last_bank_stmt[0].balance_end or 0
            #Get the number of items to reconcile for that bank journal
            self.env.cr.execute("""SELECT COUNT(DISTINCT(line.id))
                            FROM account_bank_statement_line AS line
                            LEFT JOIN account_bank_statement AS st
                            ON line.statement_id = st.id
                            WHERE st.journal_id IN %s AND st.state = 'open' AND line.amount != 0.0 AND line.account_id IS NULL
                            AND not exists (select 1 from account_move_line aml where aml.statement_line_id = line.id)
                        """, (tuple(self.ids),))
            number_to_reconcile = self.env.cr.fetchone()[0]
            to_check_ids = self.to_check_ids()
            number_to_check = len(to_check_ids)
            to_check_balance = sum([r.amount for r in to_check_ids])
            # optimization to read sum of balance from account_move_line
            account_ids = tuple(ac for ac in [self.default_debit_account_id.id, self.default_credit_account_id.id] if ac)
            if account_ids:
                amount_field = 'aml.balance' if (not self.currency_id or self.currency_id == self.company_id.currency_id) else 'aml.amount_currency'
                query = """SELECT sum(%s) FROM account_move_line aml
                           LEFT JOIN account_move move ON aml.move_id = move.id
                           WHERE aml.account_id in %%s
                           AND move.date <= %%s AND move.state = 'posted';""" % (amount_field,)
                self.env.cr.execute(query, (account_ids, fields.Date.context_today(self),))
                query_results = self.env.cr.dictfetchall()
                if query_results and query_results[0].get('sum') != None:
                    account_sum = query_results[0].get('sum')
        #TODO need to check if all invoices are in the same currency than the journal!!!!
        elif self.type in ['sale', 'purchase']:
            title = _('Bills to pay') if self.type == 'purchase' else _('Invoices owed to you')
            self.env['account.move'].flush(['amount_residual', 'currency_id', 'type', 'invoice_date', 'company_id', 'journal_id', 'date', 'state', 'invoice_payment_state'])

            (query, query_args) = self._get_open_bills_to_pay_query()
            self.env.cr.execute(query, query_args)
            query_results_to_pay = self.env.cr.dictfetchall()

            (query, query_args) = self._get_draft_bills_query()
            self.env.cr.execute(query, query_args)
            query_results_drafts = self.env.cr.dictfetchall()

            today = fields.Date.today()
            query = '''
                SELECT
                    (CASE WHEN type IN ('out_refund', 'in_refund') THEN -1 ELSE 1 END) * amount_residual AS amount_total,
                    currency_id AS currency,
                    type,
                    invoice_date,
                    company_id
                FROM account_move move
                WHERE journal_id = %s
                AND date <= %s
                AND state = 'posted'
                AND invoice_payment_state = 'not_paid'
                AND type IN ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt');
            '''
            self.env.cr.execute(query, (self.id, today))
            late_query_results = self.env.cr.dictfetchall()
            curr_cache = {}
            (number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay, currency, curr_cache=curr_cache)
            (number_draft, sum_draft) = self._count_results_and_sum_amounts(query_results_drafts, currency, curr_cache=curr_cache)
            (number_late, sum_late) = self._count_results_and_sum_amounts(late_query_results, currency, curr_cache=curr_cache)
            read = self.env['account.move'].read_group([('journal_id', '=', self.id), ('to_check', '=', True)], ['amount_total'], 'journal_id', lazy=False)
            if read:
                number_to_check = read[0]['__count']
                to_check_balance = read[0]['amount_total']
        elif self.type == 'general':
            read = self.env['account.move'].read_group([('journal_id', '=', self.id), ('to_check', '=', True)], ['amount_total'], 'journal_id', lazy=False)
            if read:
                number_to_check = read[0]['__count']
                to_check_balance = read[0]['amount_total']

        difference = currency.round(last_balance-account_sum) + 0.0

        is_sample_data = self.kanban_dashboard_graph and any(data.get('is_sample_data', False) for data in json.loads(self.kanban_dashboard_graph))

        return {
            'number_to_check': number_to_check,
            'to_check_balance': formatLang(self.env, to_check_balance, currency_obj=currency),
            'number_to_reconcile': number_to_reconcile,
            'account_balance': formatLang(self.env, currency.round(account_sum) + 0.0, currency_obj=currency),
            'last_balance': formatLang(self.env, currency.round(last_balance) + 0.0, currency_obj=currency),
            'difference': formatLang(self.env, difference, currency_obj=currency) if difference else False,
            'number_draft': number_draft,
            'number_waiting': number_waiting,
            'number_late': number_late,
            'sum_draft': formatLang(self.env, currency.round(sum_draft) + 0.0, currency_obj=currency),
            'sum_waiting': formatLang(self.env, currency.round(sum_waiting) + 0.0, currency_obj=currency),
            'sum_late': formatLang(self.env, currency.round(sum_late) + 0.0, currency_obj=currency),
            'currency_id': currency.id,
            'bank_statements_source': self.bank_statements_source,
            'title': title,
            'is_sample_data': is_sample_data,
        }
示例#8
0
    def _get_statement_line(self, st_line):
        """ Returns the data required by the bank statement reconciliation widget to display a statement line """

        statement_currency = st_line.journal_id.currency_id or st_line.journal_id.company_id.currency_id
        if st_line.amount_currency and st_line.currency_id:
            amount = st_line.amount_currency
            amount_currency = st_line.amount
            amount_currency_str = formatLang(self.env,
                                             abs(amount_currency),
                                             currency_obj=statement_currency)
        else:
            amount = st_line.amount
            amount_currency = amount
            amount_currency_str = ""
        amount_str = formatLang(self.env,
                                abs(amount),
                                currency_obj=st_line.currency_id
                                or statement_currency)

        data = {
            'id':
            st_line.id,
            'ref':
            st_line.ref,
            'note':
            st_line.note or "",
            'name':
            st_line.name,
            'date':
            format_date(self.env, st_line.date),
            'amount':
            amount,
            'amount_str':
            amount_str,  # Amount in the statement line currency
            'currency_id':
            st_line.currency_id.id or statement_currency.id,
            'partner_id':
            st_line.partner_id.id,
            'journal_id':
            st_line.journal_id.id,
            'statement_id':
            st_line.statement_id.id,
            'account_id': [
                st_line.journal_id.default_debit_account_id.id,
                st_line.journal_id.default_debit_account_id.display_name
            ],
            'account_code':
            st_line.journal_id.default_debit_account_id.code,
            'account_name':
            st_line.journal_id.default_debit_account_id.name,
            'partner_name':
            st_line.partner_id.name,
            'communication_partner_name':
            st_line.partner_name,
            'amount_currency_str':
            amount_currency_str,  # Amount in the statement currency
            'amount_currency':
            amount_currency,  # Amount in the statement currency
            'has_no_partner':
            not st_line.partner_id.id,
            'company_id':
            st_line.company_id.id,
        }
        if st_line.partner_id:
            data[
                'open_balance_account_id'] = amount > 0 and st_line.partner_id.property_account_receivable_id.id or st_line.partner_id.property_account_payable_id.id

        return data
示例#9
0
    def _prepare_move_lines(self,
                            move_lines,
                            target_currency=False,
                            target_date=False,
                            recs_count=0):
        """ Returns move lines formatted for the manual/bank reconciliation widget

            :param move_line_ids:
            :param target_currency: currency (browse) you want the move line debit/credit converted into
            :param target_date: date to use for the monetary conversion
        """
        context = dict(self._context or {})
        ret = []

        for line in move_lines:
            company_currency = line.company_id.currency_id
            line_currency = (line.currency_id and line.amount_currency
                             ) and line.currency_id or company_currency
            ret_line = {
                'id':
                line.id,
                'name':
                line.name and line.name != '/'
                and line.move_id.name != line.name
                and line.move_id.name + ': ' + line.name or line.move_id.name,
                'ref':
                line.move_id.ref or '',
                # For reconciliation between statement transactions and already registered payments (eg. checks)
                # NB : we don't use the 'reconciled' field because the line we're selecting is not the one that gets reconciled
                'account_id':
                [line.account_id.id, line.account_id.display_name],
                'already_paid':
                line.account_id.internal_type == 'liquidity',
                'account_code':
                line.account_id.code,
                'account_name':
                line.account_id.name,
                'account_type':
                line.account_id.internal_type,
                'date_maturity':
                format_date(self.env, line.date_maturity),
                'date':
                format_date(self.env, line.date),
                'journal_id':
                [line.journal_id.id, line.journal_id.display_name],
                'partner_id':
                line.partner_id.id,
                'partner_name':
                line.partner_id.name,
                'currency_id':
                line_currency.id,
            }

            debit = line.debit
            credit = line.credit
            amount = line.amount_residual
            amount_currency = line.amount_residual_currency

            # For already reconciled lines, don't use amount_residual(_currency)
            if line.account_id.internal_type == 'liquidity':
                amount = debit - credit
                amount_currency = line.amount_currency

            target_currency = target_currency or company_currency

            # Use case:
            # Let's assume that company currency is in USD and that we have the 3 following move lines
            #      Debit  Credit  Amount currency  Currency
            # 1)    25      0            0            NULL
            # 2)    17      0           25             EUR
            # 3)    33      0           25             YEN
            #
            # If we ask to see the information in the reconciliation widget in company currency, we want to see
            # The following information
            # 1) 25 USD (no currency information)
            # 2) 17 USD [25 EUR] (show 25 euro in currency information, in the little bill)
            # 3) 33 USD [25 YEN] (show 25 yen in currency information)
            #
            # If we ask to see the information in another currency than the company let's say EUR
            # 1) 35 EUR [25 USD]
            # 2) 25 EUR (no currency information)
            # 3) 50 EUR [25 YEN]
            # In that case, we have to convert the debit-credit to the currency we want and we show next to it
            # the value of the amount_currency or the debit-credit if no amount currency
            if target_currency == company_currency:
                if line_currency == target_currency:
                    amount = amount
                    amount_currency = ""
                    total_amount = debit - credit
                    total_amount_currency = ""
                else:
                    amount = amount
                    amount_currency = amount_currency
                    total_amount = debit - credit
                    total_amount_currency = line.amount_currency

            if target_currency != company_currency:
                if line_currency == target_currency:
                    amount = amount_currency
                    amount_currency = ""
                    total_amount = line.amount_currency
                    total_amount_currency = ""
                else:
                    amount_currency = line.currency_id and amount_currency or amount
                    company = line.account_id.company_id
                    date = target_date or line.date
                    amount = company_currency._convert(amount, target_currency,
                                                       company, date)
                    total_amount = company_currency._convert(
                        (line.debit - line.credit), target_currency, company,
                        date)
                    total_amount_currency = line.currency_id and line.amount_currency or (
                        line.debit - line.credit)

            ret_line['recs_count'] = recs_count
            ret_line['debit'] = amount > 0 and amount or 0
            ret_line['credit'] = amount < 0 and -amount or 0
            ret_line['amount_currency'] = amount_currency
            ret_line['amount_str'] = formatLang(self.env,
                                                abs(amount),
                                                currency_obj=target_currency)
            ret_line['total_amount_str'] = formatLang(
                self.env, abs(total_amount), currency_obj=target_currency)
            ret_line['amount_currency_str'] = amount_currency and formatLang(
                self.env, abs(amount_currency),
                currency_obj=line_currency) or ""
            ret_line[
                'total_amount_currency_str'] = total_amount_currency and formatLang(
                    self.env,
                    abs(total_amount_currency),
                    currency_obj=line_currency) or ""
            ret.append(ret_line)
        return ret