<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: <NAME>, <NAME>
#    Copyright (C) 2011 <NAME> <<EMAIL>>
#    Copyright 2013 Camptocamp SA (<NAME>)
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import logging
from openerp import api, models, fields, exceptions, _
import openerp.addons.decimal_precision as dp

_logger = logging.getLogger(__name__)


class SaleOrder(models.Model):
    _inherit = 'sale.order'

    @api.one
    @api.depends('amount_total', 'payment_ids.credit', 'payment_ids.debit')
    def _compute_amount(self):
        paid_amount = sum(line.credit - line.debit
                          for line in self.payment_ids)
        self.amount_paid = paid_amount
        self.residual = self.amount_total - paid_amount

    payment_ids = fields.Many2many(
        comodel_name='account.move.line',
        string='Payments Entries',
        domain=[('account_id.type', '=', 'receivable')],
        copy=False,
    )
    payment_method_id = fields.Many2one(
        comodel_name='payment.method',
        string='Payment Method',
        ondelete='restrict',
    )
    residual = fields.Float(
        compute='_compute_amount',
        digits_compute=dp.get_precision('Account'),
        string='Balance',
        store=False,
    )
    amount_paid = fields.Float(
        compute='_compute_amount',
        digits_compute=dp.get_precision('Account'),
        string='Amount Paid',
        store=False,
    )

    @api.multi
    def action_cancel(self):
        for sale in self:
            if sale.payment_ids:
                raise exceptions.Warning(_('Cannot cancel this sales order '
                                           'because automatic payment entries '
                                           'are linked with it.'))
        return super(SaleOrder, self).action_cancel()

    @api.multi
    def automatic_payment(self, amount=None):
        """ Create the payment entries to pay a sale order, respecting
        the payment terms.
        If no amount is defined, it will pay the residual amount of the sale
        order.
        """
        self.ensure_one()
        method = self.payment_method_id
        if not method:
            raise exceptions.Warning(
                _("An automatic payment can not be created for the sale "
                  "order %s because it has no payment method.") % self.name
            )

        if not method.journal_id:
            raise exceptions.Warning(
                _("An automatic payment should be created for the sale order"
                  " %s but the payment method '%s' has no journal defined.") %
                (self.name, method.name)
            )

        journal = method.journal_id
        date = self.date_order[:10]
        if amount is None:
            amount = self.residual
        if self.payment_term:
            amounts = self.payment_term.compute(amount, date_ref=date)[0]
        else:
            amounts = [(date, amount)]

        # reversed is cosmetic, compute returns terms in the 'wrong' order
        for date, amount in reversed(amounts):
            self._add_payment(journal, amount, date)
        return True

    @api.multi
    def add_payment(self, journal_id, amount, date=None, description=None):
        """ Generate payment move lines of a certain amount linked
        with the sale order.
        """
        self.ensure_one()
        journal_model = self.env['account.journal']
        if date is None:
            date = self.date_order
        journal = journal_model.browse(journal_id)
        self._add_payment(journal, amount, date, description)
        return True

    @api.multi
    def _add_payment(self, journal, amount, date, description=None):
        """ Generate move lines entries to pay the sale order. """
        move_model = self.env['account.move']
        period_model = self.env['account.period']
        period = period_model.find(dt=date)
        move_name = description or self._get_payment_move_name(journal, period)
        move_vals = self._prepare_payment_move(move_name, journal,
                                               period, date)
        move_lines = self._prepare_payment_move_lines(move_name, journal,
                                                      period, amount, date)

        move_vals['line_id'] = [(0, 0, line) for line in move_lines]
        move_model.create(move_vals)<commit_msg>[FIX] do not generate payment if amount=0<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: <NAME>, <NAME>
#    Copyright (C) 2011 <NAME> <<EMAIL>>
#    Copyright 2013 Camptocamp SA (<NAME>)
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import logging
from openerp import api, models, fields, exceptions, _
import openerp.addons.decimal_precision as dp

_logger = logging.getLogger(__name__)


class SaleOrder(models.Model):
    _inherit = 'sale.order'

    @api.one
    @api.depends('amount_total', 'payment_ids.credit', 'payment_ids.debit')
    def _compute_amount(self):
        paid_amount = sum(line.credit - line.debit
                          for line in self.payment_ids)
        self.amount_paid = paid_amount
        self.residual = self.amount_total - paid_amount

    payment_ids = fields.Many2many(
        comodel_name='account.move.line',
        string='Payments Entries',
        domain=[('account_id.type', '=', 'receivable')],
        copy=False,
    )
    payment_method_id = fields.Many2one(
        comodel_name='payment.method',
        string='Payment Method',
        ondelete='restrict',
    )
    residual = fields.Float(
        compute='_compute_amount',
        digits_compute=dp.get_precision('Account'),
        string='Balance',
        store=False,
    )
    amount_paid = fields.Float(
        compute='_compute_amount',
        digits_compute=dp.get_precision('Account'),
        string='Amount Paid',
        store=False,
    )

    @api.multi
    def action_cancel(self):
        for sale in self:
            if sale.payment_ids:
                raise exceptions.Warning(_('Cannot cancel this sales order '
                                           'because automatic payment entries '
                                           'are linked with it.'))
        return super(SaleOrder, self).action_cancel()

    @api.multi
    def automatic_payment(self, amount=None):
        """ Create the payment entries to pay a sale order, respecting
        the payment terms.
        If no amount is defined, it will pay the residual amount of the sale
        order.
        """
        self.ensure_one()
        method = self.payment_method_id
        if not method:
            raise exceptions.Warning(
                _("An automatic payment can not be created for the sale "
                  "order %s because it has no payment method.") % self.name
            )

        if not method.journal_id:
            raise exceptions.Warning(
                _("An automatic payment should be created for the sale order"
                  " %s but the payment method '%s' has no journal defined.") %
                (self.name, method.name)
            )

        journal = method.journal_id
        date = self.date_order[:10]
        if amount is None:
            amount = self.residual
        if self.payment_term:
            amounts = self.payment_term.compute(amount, date_ref=date)[0]
        else:
            amounts = [(date, amount)]

        # reversed is cosmetic, compute returns terms in the 'wrong' order
        for date, amount in reversed(amounts):
            if amount:
                self._add_payment(journal, amount, date)
        return True

    @api.multi
    def add_payment(self, journal_id, amount, date=None, description=None):
        """ Generate payment move lines of a certain amount linked
        with the sale order.
        """
        self.ensure_one()
        journal_model = self.env['account.journal']
        if date is None:
            date = self.date_order
        journal = journal_model.browse(journal_id)
        self._add_payment(journal, amount, date, description)
        return True

    @api.multi
    def _add_payment(self, journal, amount, date, description=None):
        """ Generate move lines entries to pay the sale order. """
        move_model = self.env['account.move']
        period_model = self.env['account.period']
        period = period_model.find(dt=date)
        move_name = description or self._get_payment_move_name(journal, period)
        move_vals = self._prepare_payment_move(move_name, journal,
                                               period, date)
        move_lines = self._prepare_payment_move_lines(move_name, journal,
                                                      period, amount, date)

        move_vals['line_id'] = [(0, 0, line) for line in move_lines]
        move_model.create(move_vals)
{'fraction_non_alphanumeric': 0.1163929703255546, 'fraction_numerical': 0.003361183136464035, 'mean_word_length': 2.2656005017246788, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3683371', 'n_tokens_mistral': 2767, 'n_tokens_neox': 2653, 'n_words': 841}