diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-07-18 13:59:18 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-07-18 13:59:18 +0700 |
| commit | 45fd501a53c6997bf74d5927d7c0eecf387caa51 (patch) | |
| tree | fa20bdff3e95d943b0f4846b9746767f87f70f31 /indoteknik_custom | |
| parent | 999725ea036840d74c7fdeebbd3aefac772bd8d3 (diff) | |
| parent | d418bd8dd84b91b9dc031819cfa9a2446e77acd2 (diff) | |
Merge branch 'origin/feature/promotion-program' into feature/voucher-cart
Diffstat (limited to 'indoteknik_custom')
| -rwxr-xr-x | indoteknik_custom/__manifest__.py | 4 | ||||
| -rwxr-xr-x | indoteknik_custom/models/__init__.py | 4 | ||||
| -rw-r--r-- | indoteknik_custom/models/ir_attachment.py | 5 | ||||
| -rw-r--r-- | indoteknik_custom/models/promotion_program.py | 22 | ||||
| -rw-r--r-- | indoteknik_custom/models/promotion_program_free_item.py | 12 | ||||
| -rw-r--r-- | indoteknik_custom/models/promotion_program_keyword.py | 8 | ||||
| -rw-r--r-- | indoteknik_custom/models/promotion_program_line.py | 158 | ||||
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 1 | ||||
| -rw-r--r-- | indoteknik_custom/models/typesense_client.py | 150 | ||||
| -rw-r--r-- | indoteknik_custom/models/website_user_cart.py | 33 | ||||
| -rwxr-xr-x | indoteknik_custom/security/ir.model.access.csv | 4 | ||||
| -rw-r--r-- | indoteknik_custom/views/promotion_program.xml | 73 | ||||
| -rw-r--r-- | indoteknik_custom/views/promotion_program_free_item.xml | 44 | ||||
| -rw-r--r-- | indoteknik_custom/views/promotion_program_keyword.xml | 44 | ||||
| -rw-r--r-- | indoteknik_custom/views/promotion_program_line.xml | 98 | ||||
| -rwxr-xr-x | indoteknik_custom/views/sale_order.xml | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/views/website_user_cart.xml | 4 |
17 files changed, 663 insertions, 2 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 4fa736f6..2b6edffe 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -75,6 +75,10 @@ 'views/procurement_monitoring_detail.xml', 'views/product_product.xml', 'views/brand_vendor.xml', + 'views/promotion_program.xml', + 'views/promotion_program_line.xml', + 'views/promotion_program_free_item.xml', + 'views/promotion_program_keyword.xml', 'views/requisition.xml', 'views/landedcost.xml', 'views/product_sla.xml', diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 9e4d2cf9..e91eadf2 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -15,6 +15,10 @@ from . import product_pricelist from . import product_public_category from . import product_spec from . import product_template +from . import promotion_program +from . import promotion_program_line +from . import promotion_program_free_item +from . import promotion_program_keyword from . import purchase_order_line from . import purchase_order from . import purchase_outstanding diff --git a/indoteknik_custom/models/ir_attachment.py b/indoteknik_custom/models/ir_attachment.py index fd86ab1b..6417fa3f 100644 --- a/indoteknik_custom/models/ir_attachment.py +++ b/indoteknik_custom/models/ir_attachment.py @@ -22,4 +22,9 @@ class Attachment(models.Model): def api_image(self, model, field, id): base_url = self.env['ir.config_parameter'].get_param('web.base.url') is_found = self.is_found(model, field, id) + return base_url + 'api/image/' + model + '/' + field + '/' + str(id) if is_found else '' + + def api_image_local(self, model, field, id): + base_url = self.env['ir.config_parameter'].get_param('web.base.local_url') + is_found = self.is_found(model, field, id) return base_url + 'api/image/' + model + '/' + field + '/' + str(id) if is_found else ''
\ No newline at end of file diff --git a/indoteknik_custom/models/promotion_program.py b/indoteknik_custom/models/promotion_program.py new file mode 100644 index 00000000..bc7f2c49 --- /dev/null +++ b/indoteknik_custom/models/promotion_program.py @@ -0,0 +1,22 @@ +from odoo import fields, models + + +class PromotionProgram(models.Model): + _name = "promotion.program" + + name = fields.Char(string="Name") + banner = fields.Binary(string="Banner") + icon = fields.Binary(string="Icon", help="Image 1:1 ratio") + icon_top = fields.Binary(string="Icon Top", help="Icon ini ditampilkan sebagai atribut pada atas gambar di product card pada website") + icon_bottom = fields.Binary(string="Icon Bottom", help="Icon ini ditampilkan sebagai atribut pada bawah gambar di product card pada website") + start_time = fields.Datetime(string="Start Time") + end_time = fields.Datetime(string="End Time") + applies_to = fields.Selection(selection=[ + ("all_user", "All User"), + ("login_user", "Login User") + ]) + program_line = fields.One2many( + comodel_name="promotion.program.line", inverse_name="program_id", string="Program Line") + keywords = fields.One2many( + comodel_name="promotion.program.keyword", inverse_name="program_id", string="Keywords" + ) diff --git a/indoteknik_custom/models/promotion_program_free_item.py b/indoteknik_custom/models/promotion_program_free_item.py new file mode 100644 index 00000000..ddd97765 --- /dev/null +++ b/indoteknik_custom/models/promotion_program_free_item.py @@ -0,0 +1,12 @@ +from odoo import fields, models + + +class PromotionProgramFreeItem(models.Model): + _name = "promotion.program.free_item" + _rec_name = "product_id" + + product_id = fields.Many2one( + comodel_name="product.product", string="Product Variant") + qty = fields.Integer(string="Qty") + line_id = fields.Many2one( + comodel_name="promotion.program.line", string="Program Line") diff --git a/indoteknik_custom/models/promotion_program_keyword.py b/indoteknik_custom/models/promotion_program_keyword.py new file mode 100644 index 00000000..79b938e2 --- /dev/null +++ b/indoteknik_custom/models/promotion_program_keyword.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class PromotionProgramKeyword(models.Model): + _name = "promotion.program.keyword" + + name = fields.Char(string="Keyword") + program_id = fields.Many2one(comodel_name="promotion.program") diff --git a/indoteknik_custom/models/promotion_program_line.py b/indoteknik_custom/models/promotion_program_line.py new file mode 100644 index 00000000..7aaff4c4 --- /dev/null +++ b/indoteknik_custom/models/promotion_program_line.py @@ -0,0 +1,158 @@ +from odoo import fields, models, api +from datetime import datetime + + +class PromotionProgramLine(models.Model): + _name = "promotion.program.line" + + name = fields.Char(string="Name") + image = fields.Binary(string="Image") + product_id = fields.Many2one( + comodel_name="product.product", string="Product Variant") + program_id = fields.Many2one( + comodel_name="promotion.program", string="Program") + discount_type = fields.Selection(selection=[ + ("percentage", "Percentage"), + ("fixed_price", "Fixed Price"), + ], string="Discount Type") + discount_amount = fields.Float(string="Discount Amount") + promotion_type = fields.Selection(selection=[ + ("special_price", "Special Price"), + ("bundling", "Bundling"), + ("discount_loading", "Discount Loading"), + ("merchandise", "Merchandise") + ], string="Promotion Type") + minimum_purchase_qty = fields.Integer( + string="Minimum Purchase Qty", help="Minimum Qty to applied discount loading") + applies_multiply = fields.Boolean( + string="Applies Multiply", help="Is applies multiply") + limit_qty = fields.Integer( + string="Limit Qty", help="Limit Qty product in promotion") + limit_qty_user = fields.Integer( + string="Limit Qty / User", help="Limit Qty per User") + limit_qty_transaction = fields.Integer( + string="Limit Qty / Transaction", help="Limit Qty per Transaction") + line_free_item = fields.One2many( + comodel_name="promotion.program.free_item", inverse_name="line_id", string="Line Free Item") + display_on_homepage = fields.Boolean(string="Display on Homepage") + order_line_ids = fields.One2many('sale.order.line', 'program_line_id') + + @api.onchange('product_id') + def _onchange_product_id(self): + if self.product_id and not self.name: + self.name = self.product_id.display_name + self._discount_loading_auto() + + @api.onchange('promotion_type') + def onchange_promotion_type(self): + self._discount_loading_auto() + + def _discount_loading_auto(self): + program_line = self + product = program_line.product_id + promotion_type = program_line.promotion_type + + if promotion_type != 'discount_loading' or not product: + return + + line = self.browse(self.ids) + line.product_id = self.product_id.id + line.promotion_type = self.promotion_type + + product_added = False + line_free_item = program_line.line_free_item + for line in line_free_item: + if line.product_id.id == product.id: + product_added = True + continue + line.unlink() + if not product_added: + data = {'product_id': product.id, + 'qty': 1, 'line_id': program_line.id} + line_free_item.create(data) + + def calculate_price(self, price): + initial_price = price['price'] + if self.discount_type == 'percentage': + price['discount_percentage'] = self.discount_amount + price['price_discount'] = initial_price - (initial_price * self.discount_amount / 100) + elif self.discount_type == 'fixed_price': + price['price_discount'] = self.discount_amount + price['discount_percentage'] = round((initial_price - self.discount_amount) / initial_price * 100) + return price + + def get_active_promotions(self, product_id): + current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + return self.search([ + ('program_id.start_time', '<=', current_time), + ('program_id.end_time', '>=', current_time), + ('product_id', '=', product_id) + ]) + + def _get_remaining_qty(self, user): + remaining_qty = { + 'all': self.limit_qty, + 'user': self.limit_qty_user, + 'transaction': self.limit_qty_transaction + } + for order in self.order_line_ids: + parent_order = order.order_id + if parent_order.state != 'cancel': + remaining_qty['all'] -= order.product_uom_qty + if user and parent_order.partner_id.id == user['partner_id']: + remaining_qty['user'] -= order.product_uom_qty + + if remaining_qty['all'] < remaining_qty['user']: + remaining_qty['user'] = remaining_qty['all'] + if remaining_qty['user'] < remaining_qty['transaction']: + remaining_qty['transaction'] = remaining_qty['user'] + + return remaining_qty + + def _get_remaining_time(self): + calculate_time = self.program_id.end_time - datetime.now() + return round(calculate_time.total_seconds()) + + def _res_limit_qty(self): + return { + 'all': self.limit_qty, + 'user': self.limit_qty_user, + 'transaction': self.limit_qty_transaction, + } + + def _res_promotion_type(self): + return { + 'value': self.promotion_type, + 'label': dict(self._fields['promotion_type'].selection).get(self.promotion_type) + } + + def format(self, user = None): + ir_attachment = self.env['ir.attachment'] + product_price = self.product_id.calculate_website_price() + limit_qty = self._res_limit_qty() + remaining_qty = self._get_remaining_qty(user) + percent_remaining = 0 + if limit_qty['all'] > 0: + percent_remaining = (limit_qty['all'] - remaining_qty['all']) / limit_qty['all'] * 100 + return { + 'id': self.id, + 'name': self.name, + 'image': ir_attachment.api_image('promotion.program.line', 'image', self.id), + 'minimum_purchase_qty': self.minimum_purchase_qty, + 'applies_multiply': self.applies_multiply, + 'remaining_time': self._get_remaining_time(), + 'type': self._res_promotion_type(), + 'limit_qty': limit_qty, + 'remaining_qty': remaining_qty, + 'used_percentage': percent_remaining, + 'price': self.calculate_price(price=product_price) + } + + def res_format(self, user): + data = [x.format(user) for x in self] + return data + + def res_format_cart(self, user): + data = self.format(user) + return data + diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index e151bf22..deea64a1 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -591,6 +591,7 @@ class SaleOrderLine(models.Model): note_procurement = fields.Char(string='Note', help="Harap diisi jika ada keterangan tambahan dari Procurement, agar dapat dimonitoring") vendor_subtotal = fields.Float(string='Vendor Subtotal', compute="_compute_vendor_subtotal") amount_voucher_disc = fields.Float(string='Voucher Discount') + program_line_id = fields.Many2one('promotion.program.line', 'Program Line') def _compute_vendor_subtotal(self): for line in self: diff --git a/indoteknik_custom/models/typesense_client.py b/indoteknik_custom/models/typesense_client.py new file mode 100644 index 00000000..fccd04e3 --- /dev/null +++ b/indoteknik_custom/models/typesense_client.py @@ -0,0 +1,150 @@ +from odoo import models +import typesense +import logging +import time + + +_logger = logging.getLogger(__name__) +_typesense = typesense.Client({ + 'nodes': [{ + 'host': 'localhost', + 'port': '9090', + 'protocol': 'http' + }], + 'api_key': 'WKWKdwakdjopwakfoij21321fkdmvaskamd' +}) + +class Typesense(models.Model): + _name = 'typesense.client' + + def _check_collection(self, name): + collections = _typesense.collections.retrieve() + for collection in collections: + if collection['name'] == name: + return True + return False + + def _init_collection(self, name): + is_exist = self._check_collection(name) + if is_exist: + return False + + schema = { + "name": name, + "fields": [ + {"name": ".*", "type": "auto" }, + {"name": ".*_facet", "type": "auto", "facet": True } + ] + } + _typesense.collections.create(schema) + return True + + def _indexing_product(self, limit=500): + start_time = time.time() + self._init_collection('products') + + query = ["&", "&", ("type", "=", "product"), ("active", "=", True), "|", ("solr_flag", "=", 0), ("solr_flag", "=", 2)] + product_templates = self.env['product.template'].search(query, limit=limit) + + counter = 0 + documents = [] + for product_template in product_templates: + counter += 1 + template_time = time.time() + document = self._map_product_document(product_template) + documents.append(document) + product_template.solr_flag = 1 + _logger.info('[SYNC_PRODUCT_TO_TYPESENSE] {}/{} {:.6f}'.format(counter, limit, time.time() - template_time)) + _logger.info('[SYNC_PRODUCT_TO_TYPESENSE] Success add to typesense product %s' % product_template.id) + + _typesense.collections['products'].documents.import_(documents, {'action': 'upsert'}) + end_time = time.time() + _logger.info("[SYNC_PRODUCT_TO_SOLR] Finish task add to solr. Time taken: {:.6f} seconds".format(end_time - start_time)) + + def _map_product_document(self, product_template): + price_excl_after_disc = price_excl = discount = tax = 0 + variants_name = variants_code = '' + flashsale_data = tier1 = tier2 = tier3 = {} + if product_template.product_variant_count > 1: + for variant in product_template.product_variant_ids: + if price_excl_after_disc == 0 or variant._get_website_price_after_disc_and_tax() < price_excl_after_disc: + price_excl = variant._get_website_price_exclude_tax() + price_excl_after_disc = variant._get_website_price_after_disc_and_tax() + discount = variant._get_website_disc(0) + tax = variant._get_website_tax() + flashsale_data = variant._get_flashsale_price() + # add price tiering for base price, discount, and price after discount (tier 1 - 3) + tier1 = variant._get_pricelist_tier1() + tier2 = variant._get_pricelist_tier2() + tier3 = variant._get_pricelist_tier3() + else: + price_excl_after_disc = price_excl_after_disc + price_excl = price_excl + discount = discount + tax = tax + flashsale_data = flashsale_data + tier1 = tier1 + tier2 = tier2 + tier3 = tier3 + variants_name += variant.display_name or ''+', ' + variants_code += variant.default_code or ''+', ' + else: + variants_name = product_template.display_name + price_excl = product_template.product_variant_id._get_website_price_exclude_tax() + discount = product_template.product_variant_id._get_website_disc(0) + price_excl_after_disc = product_template.product_variant_id._get_website_price_after_disc_and_tax() + tax = product_template.product_variant_id._get_website_tax() + flashsale_data = product_template.product_variant_id._get_flashsale_price() + tier1 = product_template.product_variant_id._get_pricelist_tier1() + tier2 = product_template.product_variant_id._get_pricelist_tier2() + tier3 = product_template.product_variant_id._get_pricelist_tier3() + + category_id = '' + category_name = '' + for category in product_template.public_categ_ids: + category_id = category.id + category_name = category.name + + document = { + 'id': str(product_template.id), + 'display_name': product_template.display_name, + 'name': product_template.name, + 'default_code': product_template.default_code or '', + 'product_rating': product_template.virtual_rating, + 'product_id': product_template.id, + 'image': self.env['ir.attachment'].api_image('product.template', 'image_512', product_template.id), + 'price': price_excl, + 'discount': discount, + 'price_discount': price_excl_after_disc, + 'tax': tax, + 'variant_total': product_template.product_variant_count, + 'stock_total': product_template.qty_stock_vendor, + 'weight': product_template.weight, + 'manufacture_id': product_template.x_manufacture.id or 0, + 'manufacture_name': product_template.x_manufacture.x_name or '', + 'manufacture_name': product_template.x_manufacture.x_name or '', + 'image_promotion_1': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_1', product_template.x_manufacture.id), + 'image_promotion_2': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_2', product_template.x_manufacture.id), + 'category_id': category_id or 0, + 'category_name': category_name or '', + 'category_name': category_name or '', + 'variants_name_t': variants_name, + 'variants_code_t': variants_code, + 'search_rank': product_template.search_rank, + 'search_rank_weekly': product_template.search_rank_weekly, + 'flashsale_id': flashsale_data['flashsale_id'] or 0, + 'flashsale_name': flashsale_data['flashsale_name'] or '', + 'flashsale_base_price': flashsale_data['flashsale_base_price'] or 0, + 'flashsale_discount': flashsale_data['flashsale_discount'] or 0, + 'flashsale_price': flashsale_data['flashsale_price'] or 0, + 'discount_tier1': tier1['discount_tier1'] or 0, + 'price_tier1': tier1['price_tier1'] or 0, + 'discount_tier2': tier2['discount_tier2'] or 0, + 'price_tier2': tier2['price_tier2'] or 0, + 'discount_tier3': tier3['discount_tier3'] or 0, + 'price_tier3': tier3['price_tier3'] or 0 + } + + return document + + diff --git a/indoteknik_custom/models/website_user_cart.py b/indoteknik_custom/models/website_user_cart.py index 8046469f..388151ab 100644 --- a/indoteknik_custom/models/website_user_cart.py +++ b/indoteknik_custom/models/website_user_cart.py @@ -5,6 +5,35 @@ class WebsiteUserCart(models.Model): _name = 'website.user.cart' _rec_name = 'user_id' - user_id = fields.Many2one('res.users', string='User', help="User ID yang terdaftar di table res.users") - product_id = fields.Many2one('product.product', string='Product', help="Product yang terdaftar di table product.product") + user_id = fields.Many2one('res.users', string='User') + product_id = fields.Many2one('product.product', string='Product') + program_line_id = fields.Many2one('promotion.program.line', string='Program', help="Apply program") qty = fields.Float(string='Quantity', digits='Product Unit of Measure') + is_selected = fields.Boolean(string='Selected?', digits='Is selected to process checkout') + + def get_product(self): + user_data = { + 'partner_id': self.user_id.partner_id.id, + 'user_id': self.user_id.id + } + product_product = self.env['product.product'] + product = product_product.v2_api_single_response(self.product_id) + product['quantity'] = self.qty + product['subtotal'] = self.qty * product['price']['price_discount'] + product['selected'] = self.is_selected + product['program'] = None + if self.program_line_id: + product['program'] = self.program_line_id.res_format_cart(user_data) + return product + + def get_products(self): + return [x.get_product() for x in self] + + def get_product_by_user(self, user_id, selected = False): + user_id = int(user_id) + parameters = [('user_id', '=', user_id)] + if selected: + parameters.append(('is_selected', '=', True)) + carts = self.search(parameters) + products = carts.get_products() + return products
\ No newline at end of file diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 2b269417..94c8a7d1 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -51,6 +51,10 @@ access_group_partner,access.group.partner,model_group_partner,,1,1,1,1 access_procurement_monitoring_detail,access.procurement.monitoring.detail,model_procurement_monitoring_detail,,1,1,1,1 access_rajaongkir_kurir,access.rajaongkir.kurir,model_rajaongkir_kurir,,1,1,1,1 access_brand_vendor,access.brand.vendor,model_brand_vendor,,1,1,1,1 +access_promotion_program,access.promotion.program,model_promotion_program,,1,1,1,1 +access_promotion_program_line,access.promotion.program.line,model_promotion_program_line,,1,1,1,1 +access_promotion_program_free_item,access.promotion.program.free_item,model_promotion_program_free_item,,1,1,1,1 +access_promotion_program_keyword,access.promotion.program.keyword,model_promotion_program_keyword,,1,1,1,1 access_requisition,access.requisition,model_requisition,,1,1,1,1 access_requisition_line,access.requisition.line,model_requisition_line,,1,1,1,1 access_requisition_purchase_match,access.requisition.purchase.match,model_requisition_purchase_match,,1,1,1,1 diff --git a/indoteknik_custom/views/promotion_program.xml b/indoteknik_custom/views/promotion_program.xml new file mode 100644 index 00000000..5dff80e6 --- /dev/null +++ b/indoteknik_custom/views/promotion_program.xml @@ -0,0 +1,73 @@ +<odoo> + <record id="promotion_program_tree" model="ir.ui.view"> + <field name="name">Promotion Program Tree</field> + <field name="model">promotion.program</field> + <field name="arch" type="xml"> + <tree> + <field name="name" /> + <field name="start_time" /> + <field name="end_time" /> + <field name="applies_to" /> + </tree> + </field> + </record> + + <record id="promotion_program_form" model="ir.ui.view"> + <field name="name">Promotion Program Form</field> + <field name="model">promotion.program</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <group> + <field name="name" /> + <field name="keywords" widget="many2many_tags" /> + <field name="banner" widget="image" height="160" /> + </group> + <group> + <field name="start_time" /> + <field name="end_time" /> + <field name="applies_to" /> + </group> + </group> + <notebook> + <page string="Program Lines" name="program_lines"> + <field name="program_line" /> + </page> + <page string="Image Properties" name="image_properties"> + <group> + <group> + <field name="icon" widget="image" height="120" /> + <field name="icon_top" widget="image" height="80" /> + <field name="icon_bottom" widget="image" height="80" /> + </group> + </group> + </page> + </notebook> + </sheet> + </form> + </field> + </record> + + <record id="promotion_program_action" model="ir.actions.act_window"> + <field name="name">Promotion Program</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">promotion.program</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem + id="menu_promotion_program_parent" + name="Promotion Program" + parent="website.menu_website_configuration" + sequence="7" + /> + + <menuitem + id="menu_promotion_program" + name="Program" + parent="indoteknik_custom.menu_promotion_program_parent" + sequence="1" + action="promotion_program_action" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/promotion_program_free_item.xml b/indoteknik_custom/views/promotion_program_free_item.xml new file mode 100644 index 00000000..52d421fe --- /dev/null +++ b/indoteknik_custom/views/promotion_program_free_item.xml @@ -0,0 +1,44 @@ +<odoo> + <record id="promotion_program_free_item_tree" model="ir.ui.view"> + <field name="name">Promotion Program Free Item Tree</field> + <field name="model">promotion.program.free_item</field> + <field name="arch" type="xml"> + <tree> + <field name="product_id" /> + <field name="qty" /> + </tree> + </field> + </record> + + <record id="promotion_program_free_item_form" model="ir.ui.view"> + <field name="name">Promotion Program Free Item Form</field> + <field name="model">promotion.program.free_item</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <group> + <field name="product_id" /> + <field name="qty" /> + </group> + </group> + </sheet> + </form> + </field> + </record> + + <record id="promotion_program_free_item_action" model="ir.actions.act_window"> + <field name="name">Promotion Program Free Item</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">promotion.program.free_item</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem + id="menu_promotion_program_free_item" + name="Program Free Item" + parent="indoteknik_custom.menu_promotion_program_parent" + sequence="3" + action="promotion_program_free_item_action" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/promotion_program_keyword.xml b/indoteknik_custom/views/promotion_program_keyword.xml new file mode 100644 index 00000000..fd279665 --- /dev/null +++ b/indoteknik_custom/views/promotion_program_keyword.xml @@ -0,0 +1,44 @@ +<odoo> + <record id="promotion_program_keyword_tree" model="ir.ui.view"> + <field name="name">Promotion Program Keyword Tree</field> + <field name="model">promotion.program.keyword</field> + <field name="arch" type="xml"> + <tree> + <field name="name" /> + <field name="program_id" /> + </tree> + </field> + </record> + + <record id="promotion_program_keyword_form" model="ir.ui.view"> + <field name="name">Promotion Program Keyword Form</field> + <field name="model">promotion.program.keyword</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <group> + <field name="name" /> + <field name="program_id" /> + </group> + </group> + </sheet> + </form> + </field> + </record> + + <record id="promotion_program_keyword_action" model="ir.actions.act_window"> + <field name="name">Promotion Program Keyword</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">promotion.program.keyword</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem + id="menu_promotion_program_keyword" + name="Program Keyword" + parent="indoteknik_custom.menu_promotion_program_parent" + sequence="4" + action="promotion_program_keyword_action" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/promotion_program_line.xml b/indoteknik_custom/views/promotion_program_line.xml new file mode 100644 index 00000000..5963d0dd --- /dev/null +++ b/indoteknik_custom/views/promotion_program_line.xml @@ -0,0 +1,98 @@ +<odoo> + <record id="promotion_program_line_tree" model="ir.ui.view"> + <field name="name">Promotion Program Line Tree</field> + <field name="model">promotion.program.line</field> + <field name="arch" type="xml"> + <tree> + <field name="name" /> + <field name="promotion_type" /> + <field name="limit_qty" /> + <field name="limit_qty_user" /> + <field name="limit_qty_transaction" /> + <field name="line_free_item" /> + <field name="display_on_homepage" /> + </tree> + </field> + </record> + + <record id="promotion_program_line_form" model="ir.ui.view"> + <field name="name">Promotion Program Line Form</field> + <field name="model">promotion.program.line</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <group> + <field name="name" /> + <field name="promotion_type"/> + <field name="product_id" /> + <field name="image" widget="image" height="160" /> + </group> + <group> + <field name="limit_qty" /> + <field name="limit_qty_user" /> + <field name="limit_qty_transaction" /> + <field + name="discount_type" + attrs="{'invisible': [('promotion_type', '!=', 'special_price')]}" + /> + <field + name="discount_amount" + attrs="{'invisible': [('promotion_type', '!=', 'special_price')]}" + /> + <field + name="minimum_purchase_qty" + attrs="{'invisible': [('promotion_type', 'not in', ['discount_loading', 'bundling', 'merchandise'])]}" + /> + <field + name="applies_multiply" + attrs="{'invisible': [('promotion_type', 'not in', ['discount_loading', 'bundling', 'merchandise'])]}" + /> + <field + name="display_on_homepage" + attrs="{'invisible': [('promotion_type', '!=', 'special_price')]}" + /> + </group> + </group> + <notebook> + <page + string="Line Free Item" + name="line_free_items" + attrs="{'invisible': [('promotion_type', '=', 'special_price')]}" + > + <field name="line_free_item" /> + </page> + <page + string="Order Line" + name="order_line" + > + <field name="order_line_ids" readonly="1"> + <tree> + <field name="order_id" /> + <field name="name" /> + <field name="product_id" /> + <field name="product_uom_qty" /> + </tree> + </field> + </page> + </notebook> + </sheet> + </form> + </field> + </record> + + <record id="promotion_program_line_action" model="ir.actions.act_window"> + <field name="name">Promotion Program Line</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">promotion.program.line</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem + id="menu_promotion_program_line" + name="Program Line" + parent="indoteknik_custom.menu_promotion_program_parent" + sequence="2" + action="promotion_program_line_action" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 7679f92d..7f4cc4ae 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -72,6 +72,7 @@ <field name="note_procurement" optional="hide"/> <field name="vendor_subtotal" optional="hide"/> <field name="amount_voucher_disc" string="Voucher" optional="hide"/> + <field name="program_line_id" optional="1" /> </xpath> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='product_id']" position="before"> <field name="line_no" readonly="1" optional="hide"/> diff --git a/indoteknik_custom/views/website_user_cart.xml b/indoteknik_custom/views/website_user_cart.xml index 890d801c..fbd08acb 100755 --- a/indoteknik_custom/views/website_user_cart.xml +++ b/indoteknik_custom/views/website_user_cart.xml @@ -13,7 +13,9 @@ <tree> <field name="user_id"/> <field name="product_id"/> + <field name="program_line_id"/> <field name="qty"/> + <field name="is_selected"/> </tree> </field> </record> @@ -28,7 +30,9 @@ <group> <field name="user_id"/> <field name="product_id"/> + <field name="program_line_id" domain="[('product_id', '=', product_id)]"/> <field name="qty"/> + <field name="is_selected"/> </group> <group></group> </group> |
