summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models/sale_advance_payment_inv.py
blob: bea9a9008d859085cfbd266b20c4c8f9415050cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
from odoo import models, fields
from odoo.exceptions import UserError


class SaleAdvancePaymentInv(models.TransientModel):
    _inherit = 'sale.advance.payment.inv'

    def _prepare_invoice_values(self, order, name, amount, so_line):
        parent_id = order.partner_id.parent_id
        parent_id =  parent_id if parent_id else order.partner_id

        invoice_vals = {
            'ref': order.client_order_ref,
            'move_type': 'out_invoice',
            'invoice_origin': order.name,
            'invoice_user_id': order.user_id.id,
            'narration': order.note,
            'partner_id': parent_id,
            'sale_id': order.id,
            'fiscal_position_id': (order.fiscal_position_id or order.fiscal_position_id.get_fiscal_position(order.partner_id.id)).id,
            'partner_shipping_id': parent_id.id,
            'real_invoice_id': order.real_invoice_id.id,
            'currency_id': order.pricelist_id.currency_id.id,
            'payment_reference': order.reference,
            'invoice_payment_term_id': order.payment_term_id.id,
            'partner_bank_id': order.company_id.partner_id.bank_ids[:1].id,
            'team_id': order.team_id.id,
            'campaign_id': order.campaign_id.id,
            'medium_id': order.medium_id.id,
            'source_id': order.source_id.id,
            'invoice_line_ids': [(0, 0, {
                'name': name,
                'price_unit': amount,
                'quantity': 1.0,
                'product_id': self.product_id.id,
                'product_uom_id': so_line.product_uom.id,
                'tax_ids': [(6, 0, so_line.tax_id.ids)],
                'sale_line_ids': [(6, 0, [so_line.id])],
                'analytic_tag_ids': [(6, 0, so_line.analytic_tag_ids.ids)],
                'analytic_account_id': order.analytic_account_id.id or False,
            })],
        }

        return invoice_vals

    def create_invoices(self):
        sale_orders = self.env['sale.order'].browse(self._context.get('active_ids', []))

        if self.advance_payment_method == 'delivered':
            sale_orders._create_invoices(final=self.deduct_down_payments)
        else:
            # Create deposit product if necessary
            if not self.product_id:
                vals = self._prepare_deposit_product()
                self.product_id = self.env['product.product'].create(vals)
                self.env['ir.config_parameter'].sudo().set_param('sale.default_deposit_product_id', self.product_id.id)

            sale_line_obj = self.env['sale.order.line']
            for order in sale_orders:
                amount, name = self._get_advance_details(order)

                if self.product_id.invoice_policy != 'order':
                    raise UserError(
                        _('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'))
                if self.product_id.type != 'service':
                    raise UserError(
                        _("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."))
                taxes = self.product_id.taxes_id.filtered(
                    lambda r: not order.company_id or r.company_id == order.company_id)
                tax_ids = order.fiscal_position_id.map_tax(taxes, self.product_id, order.partner_shipping_id).ids
                analytic_tag_ids = []
                for line in order.order_line:
                    analytic_tag_ids = [(4, analytic_tag.id, None) for analytic_tag in line.analytic_tag_ids]

                so_line_values = self._prepare_so_line(order, analytic_tag_ids, tax_ids, amount)
                so_line = sale_line_obj.create(so_line_values)
                self._create_invoice(order, so_line, amount)
        if self._context.get('open_invoices', False):
            return sale_orders.action_view_invoice()
        return {'type': 'ir.actions.act_window_close'}
    # def _create_invoices(self, grouped=False, final=False, date=None):
    #     """
    #     Create the invoice associated to the SO.
    #     :param grouped: if True, invoices are grouped by SO id. If False, invoices are grouped by
    #                     (partner_invoice_id, currency)
    #     :param final: if True, refunds will be generated if necessary
    #     :returns: list of created invoices
    #     """
    #     if not self.env['account.move'].check_access_rights('create', False):
    #         try:
    #             self.check_access_rights('write')
    #             self.check_access_rule('write')
    #         except AccessError:
    #             return self.env['account.move']
    #
    #     # 1) Create invoices.
    #     invoice_vals_list = []
    #     invoice_item_sequence = 0 # Incremental sequencing to keep the lines order on the invoice.
    #     for order in self:
    #         order = order.with_company(order.company_id)
    #         current_section_vals = None
    #         down_payments = order.env['sale.order.line']
    #
    #         invoice_vals = order._prepare_invoice()
    #         invoiceable_lines = order._get_invoiceable_lines(final)
    #
    #         if not any(not line.display_type for line in invoiceable_lines):
    #             continue
    #
    #         invoice_line_vals = []
    #         down_payment_section_added = False
    #         for line in invoiceable_lines:
    #             if not down_payment_section_added and line.is_downpayment:
    #                 # Create a dedicated section for the down payments
    #                 # (put at the end of the invoiceable_lines)
    #                 invoice_line_vals.append(
    #                     (0, 0, order._prepare_down_payment_section_line(
    #                         sequence=invoice_item_sequence,
    #                     )),
    #                 )
    #                 down_payment_section_added = True
    #                 invoice_item_sequence += 1
    #             invoice_line_vals.append(
    #                 (0, 0, line._prepare_invoice_line(
    #                     sequence=invoice_item_sequence,
    #                 )),
    #             )
    #             invoice_item_sequence += 1
    #
    #         invoice_vals['invoice_line_ids'] += invoice_line_vals
    #         invoice_vals_list.append(invoice_vals)
    #
    #     if not invoice_vals_list:
    #         raise self._nothing_to_invoice_error()
    #
    #     # 2) Manage 'grouped' parameter: group by (partner_id, currency_id).
    #     if not grouped:
    #         new_invoice_vals_list = []
    #         invoice_grouping_keys = self._get_invoice_grouping_keys()
    #         invoice_vals_list = sorted(invoice_vals_list, key=lambda x: [x.get(grouping_key) for grouping_key in invoice_grouping_keys])
    #         for grouping_keys, invoices in groupby(invoice_vals_list, key=lambda x: [x.get(grouping_key) for grouping_key in invoice_grouping_keys]):
    #             origins = set()
    #             payment_refs = set()
    #             refs = set()
    #             ref_invoice_vals = None
    #             for invoice_vals in invoices:
    #                 if not ref_invoice_vals:
    #                     ref_invoice_vals = invoice_vals
    #                 else:
    #                     ref_invoice_vals['invoice_line_ids'] += invoice_vals['invoice_line_ids']
    #                 origins.add(invoice_vals['invoice_origin'])
    #                 payment_refs.add(invoice_vals['payment_reference'])
    #                 refs.add(invoice_vals['ref'])
    #             ref_invoice_vals.update({
    #                 'ref': ', '.join(refs)[:2000],
    #                 'invoice_origin': ', '.join(origins),
    #                 'payment_reference': len(payment_refs) == 1 and payment_refs.pop() or False,
    #             })
    #             new_invoice_vals_list.append(ref_invoice_vals)
    #         invoice_vals_list = new_invoice_vals_list
    #
    #     # 3) Create invoices.
    #
    #     # As part of the invoice creation, we make sure the sequence of multiple SO do not interfere
    #     # in a single invoice. Example:
    #     # SO 1:
    #     # - Section A (sequence: 10)
    #     # - Product A (sequence: 11)
    #     # SO 2:
    #     # - Section B (sequence: 10)
    #     # - Product B (sequence: 11)
    #     #
    #     # If SO 1 & 2 are grouped in the same invoice, the result will be:
    #     # - Section A (sequence: 10)
    #     # - Section B (sequence: 10)
    #     # - Product A (sequence: 11)
    #     # - Product B (sequence: 11)
    #     #
    #     # Resequencing should be safe, however we resequence only if there are less invoices than
    #     # orders, meaning a grouping might have been done. This could also mean that only a part
    #     # of the selected SO are invoiceable, but resequencing in this case shouldn't be an issue.
    #     if len(invoice_vals_list) < len(self):
    #         SaleOrderLine = self.env['sale.order.line']
    #         for invoice in invoice_vals_list:
    #             sequence = 1
    #             for line in invoice['invoice_line_ids']:
    #                 line[2]['sequence'] = SaleOrderLine._get_invoice_line_sequence(new=sequence, old=line[2]['sequence'])
    #                 sequence += 1
    #
    #     # Manage the creation of invoices in sudo because a salesperson must be able to generate an invoice from a
    #     # sale order without "billing" access rights. However, he should not be able to create an invoice from scratch.
    #     moves = self.env['account.move'].sudo().with_context(default_move_type='out_invoice').create(invoice_vals_list)
    #
    #     # 4) Some moves might actually be refunds: convert them if the total amount is negative
    #     # We do this after the moves have been created since we need taxes, etc. to know if the total
    #     # is actually negative or not
    #     if final:
    #         moves.sudo().filtered(lambda m: m.amount_total < 0).action_switch_invoice_into_refund_credit_note()
    #     for move in moves:
    #         move.message_post_with_view('mail.message_origin_link',
    #             values={'self': move, 'origin': move.line_ids.mapped('sale_line_ids.order_id')},
    #             subtype_id=self.env.ref('mail.mt_note').id
    #         )
    #     return moves