summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models/promotion/sale_order.py
blob: 1c31d060cfe2fc5f5c3e6851af9286e593ba624e (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
from odoo import fields, models


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

    order_promotion_ids = fields.One2many('sale.order.promotion', 'order_id', 'Promotions')

    def add_free_product(self, promotions):
        for promotion in promotions:
            program_line = self.env['promotion.program.line'].browse(promotion['program_line_id'])
            for free_product in program_line.free_product_ids:
                if free_product.product_id.merchandise_ok:
                    self.env['sale.order.line'].create({
                        'order_id': self.id,
                        'name': f"Free Product {free_product.product_id.display_name} Quantity ({free_product.qty})",
                        'display_type': 'line_note'
                    })

    def apply_promotion_program(self):
        userdata = {
            'user_id': self.partner_id.user_id.id,
            'partner_id': self.partner_id.id
        }
        
        order_lines = []
        iu_products = [] # Internal Use products
        for line in self.order_promotion_ids:
            promotion = line.program_line_id.format(user=userdata, qty=line.quantity)

            products = promotion['products']
            free_products = promotion['free_products']
            all_products = products.copy()

            if promotion['promotion_type']['value'] == 'merchandise':
                iu_products += filter(lambda x: x['qty'] > 0, free_products)
            else:
                all_products = self._merge_promotion_products(promotion)

            promotion_price = promotion['price']['price_discount'] * line.quantity * 1.11
            promotion_amt_total = sum(product['price']['price'] * product['qty'] for product in all_products)

            promotion_used_price = 0
            for index, product in enumerate(all_products):
                order_line_default = {
                    'company_id': 1,
                    'order_id': self.id,
                    'order_promotion_id': line.id,
                    'product_id': product['id'],
                    'product_uom_qty': product['qty'],
                }
                if promotion['promotion_type']['value'] == 'special_price':
                    order_lines.append({
                        **order_line_default,
                        'price_unit': product['price']['price'],
                        'discount': product['price']['discount_percentage']
                    })
                    continue

                product_price = product['price']['price']
                contrib_decimal = product_price * product['qty'] / promotion_amt_total

                if index < len(all_products) - 1:
                    contrib_price = contrib_decimal * promotion_price
                else:
                    contrib_price = promotion_price - promotion_used_price
                
                contrib_price_unit = contrib_price / product['qty']
                contrib_disc_unit = round((product_price - contrib_price_unit) / product_price * 100, 2)
                
                product_subtotal = round((100 - contrib_disc_unit) / 100 * product_price, 2) * product['qty']
                promotion_used_price += product_subtotal

                order_lines.append({
                    **order_line_default,
                    'price_unit': product_price,
                    'discount': contrib_disc_unit
                })

        self.env['sale.order.line'].create(order_lines)
        self._create_promotion_program_iu_docs(iu_products)

    def _merge_promotion_products(self, promotion):
        """
            Merges the products and free products from a promotion into a single dictionary.

            Parameters:
                promotion (dict): A dictionary representing a promotion with 'products' and 'free_products' keys.

            Returns:
                list: A list containing the merged products from the promotion.
        """
        merged_products = {}

        for product in promotion['products'] + promotion['free_products']:
            product_id = product['id']
            product_qty = product['qty']
            if product_id in merged_products:
                merged_products[product_id]['qty'] += product_qty
            else:
                merged_products[product_id] = product
        
        return list(merged_products.values())

    def _create_promotion_program_iu_docs(self, products):
        if len(products) == 0:
            return False
        
        default = {
            'picking_type_id': 33, # PT Indoteknik (Bandengan): Internal Transfers
            'location_id': 57, # BU/Stock
            'location_dest_id': 49, # Virtual Locations/Internal Use
            'account_id': 596, # Biaya awareness
            'product_uom': 1 # Unit
        }
        
        picking_type = self.env['stock.picking.type'].browse(default['picking_type_id'])
        picking = self.env['stock.picking'].create({
            'name': picking_type.sequence_id.next_by_id(),
            'picking_type_id': default['picking_type_id'],
            'partner_id': self.partner_id.id,
            'real_shipping_id': self.real_shipping_id.id,
            'location_id': default['location_id'],
            'location_dest_id': default['location_dest_id'],
            'account_id': default['account_id'],
            'origin': self.display_name,
            'is_internal_use': True
        })

        for product in products:
            picking.move_ids_without_package.create({
                'product_id': product['id'],
                'name': product['display_name'],
                'product_uom_qty': product['qty'],
                'product_uom': default['product_uom'],
                'location_id': default['location_id'],
                'location_dest_id': default['location_dest_id'],
                'picking_id': picking.id
            })

        self.picking_iu_id = picking.id