From 1563299905b3e0cf97129739c0ee0a6269ce4bc8 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 28 Jul 2023 16:53:32 +0700 Subject: Add flash sale remaining time API response --- indoteknik_api/controllers/api_v1/flash_sale.py | 5 ++--- indoteknik_api/models/product_template.py | 1 + indoteknik_custom/models/product_pricelist.py | 6 ++++++ indoteknik_custom/models/product_template.py | 13 +++++++++++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/flash_sale.py b/indoteknik_api/controllers/api_v1/flash_sale.py index dc7c3928..dff8bec3 100644 --- a/indoteknik_api/controllers/api_v1/flash_sale.py +++ b/indoteknik_api/controllers/api_v1/flash_sale.py @@ -1,4 +1,3 @@ -from datetime import datetime import logging from .. import controller from odoo import http @@ -28,7 +27,7 @@ class FlashSale(controller.Controller): 'banner': request.env['ir.attachment'].api_image('product.pricelist', 'banner', pricelist.id), 'banner_mobile': request.env['ir.attachment'].api_image('product.pricelist', 'banner_mobile', pricelist.id), 'banner_top': request.env['ir.attachment'].api_image('product.pricelist', 'banner_top', pricelist.id), - 'duration': round((pricelist.end_date - datetime.now()).total_seconds()), + 'duration': pricelist._remaining_time_in_second(), 'product_total': request.env['product.pricelist.item'].search_count(query), }) return self.response(data) @@ -94,7 +93,7 @@ class FlashSale(controller.Controller): 'name': active_flash_sale.name, 'banner': base_url + 'api/image/product.pricelist/banner/' + str(active_flash_sale.id) if active_flash_sale.banner else '', 'banner_mobile': base_url + 'api/image/product.pricelist/banner_mobile/' + str(active_flash_sale.id) if active_flash_sale.banner_mobile else '', - 'duration': round((active_flash_sale.end_date - datetime.now()).total_seconds()), + 'duration': active_flash_sale._remaining_time_in_second(), 'flashsale_option': active_flash_sale.flashsale_option, 'product_total': request.env['product.template'].search_count(query), 'products': [request.env['product.template'].api_single_response(x) for x in product_templates] diff --git a/indoteknik_api/models/product_template.py b/indoteknik_api/models/product_template.py index 68ab79c2..b01e957b 100644 --- a/indoteknik_api/models/product_template.py +++ b/indoteknik_api/models/product_template.py @@ -72,6 +72,7 @@ class ProductTemplate(models.Model): lowest_price = variant['price'] data_with_detail = { + 'flash_sale_remaining_time': product_template._get_flash_sale_remaining_time(), 'lowest_price': lowest_price, 'image': self.env['ir.attachment'].api_image('product.template', 'image_512', product_template.id), 'display_name': product_template.display_name, diff --git a/indoteknik_custom/models/product_pricelist.py b/indoteknik_custom/models/product_pricelist.py index 2edaeb80..49927d6b 100644 --- a/indoteknik_custom/models/product_pricelist.py +++ b/indoteknik_custom/models/product_pricelist.py @@ -1,5 +1,6 @@ from odoo import models, fields, api from odoo.exceptions import UserError +from datetime import datetime class ProductPricelist(models.Model): @@ -16,6 +17,11 @@ class ProductPricelist(models.Model): ], string='Flashsale Option') banner_top = fields.Binary(string='Banner Top') + def _remaining_time_in_second(self): + if not self.end_date: + return 0 + return round((self.end_date - datetime.now()).total_seconds()) + class ProductPricelistItem(models.Model): _inherit = 'product.pricelist.item' diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index 1a83b702..24264366 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -29,8 +29,7 @@ class ProductTemplate(models.Model): digits='Product Price', inverse='_set_product_lst_price', help="Web Price with pricelist_id = 1") qty_stock_vendor = fields.Float('QTY Stock Vendor', compute='_compute_qty_stock_vendor') - have_promotion_program = fields.Boolean('Have Promotion Program', compute='_have_promotion_program', - help="Punya promotion program gak?") + have_promotion_program = fields.Boolean('Have Promotion Program', compute='_have_promotion_program', help="Punya promotion program gak?") product_rating = fields.Float('Product Rating', help="Digunakan untuk sorting product di website", default=0.0) virtual_rating = fields.Float('Virtual Rating', compute='_compute_virtual_rating', help="Column Virtual untuk product rating, digunakan oleh Solr", default=0.0) last_calculate_rating = fields.Datetime("Last Calculate Rating") @@ -155,6 +154,16 @@ class ProductTemplate(models.Model): else: template.have_promotion_program = False + def _get_flash_sale_remaining_time(self): + variant_ids = [x.id for x in self.product_variant_ids] + pricelist = self.env['product.pricelist'].search([ + ('is_flash_sale', '=', True), + ('item_ids.product_id', 'in', variant_ids) + ]) + if not pricelist: + return 0 + return pricelist._remaining_time_in_second() + @api.model def _calculate_rating_product(self): #["&","&",["type","=","product"],["active","=",True],"|",["last_calculate_rating","=",False],["last_calculate_rating","<","2023-01-01 00:00:00"]] -- cgit v1.2.3 From f785e7605f4d0151a0f48e3d871b996c40e51351 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 31 Jul 2023 16:31:42 +0700 Subject: Add flash sale tag on model, view, api response --- indoteknik_api/models/product_template.py | 7 +++-- indoteknik_custom/models/product_pricelist.py | 7 +++-- indoteknik_custom/models/product_template.py | 8 +++--- indoteknik_custom/views/product_pricelist.xml | 37 +++++++++++---------------- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/indoteknik_api/models/product_template.py b/indoteknik_api/models/product_template.py index b01e957b..fb77769f 100644 --- a/indoteknik_api/models/product_template.py +++ b/indoteknik_api/models/product_template.py @@ -70,9 +70,12 @@ class ProductTemplate(models.Model): for variant in variants: if variant["price"]["price_discount"] < lowest_price["price_discount"]: lowest_price = variant['price'] - + template_pricelist = product_template._get_active_flash_sale() data_with_detail = { - 'flash_sale_remaining_time': product_template._get_flash_sale_remaining_time(), + 'flash_sale': { + 'remaining_time': template_pricelist._remaining_time_in_second() if template_pricelist else 0, + 'tag': template_pricelist.flashsale_tag if template_pricelist else None + }, 'lowest_price': lowest_price, 'image': self.env['ir.attachment'].api_image('product.template', 'image_512', product_template.id), 'display_name': product_template.display_name, diff --git a/indoteknik_custom/models/product_pricelist.py b/indoteknik_custom/models/product_pricelist.py index 49927d6b..95e63cf0 100644 --- a/indoteknik_custom/models/product_pricelist.py +++ b/indoteknik_custom/models/product_pricelist.py @@ -14,13 +14,16 @@ class ProductPricelist(models.Model): flashsale_option = fields.Selection([ ('all', 'For All User'), ('registered_user', 'Only for Registered User') - ], string='Flashsale Option') + ], string='Flash Sale Option') banner_top = fields.Binary(string='Banner Top') + flashsale_tag = fields.Char(string='Flash Sale Tag') def _remaining_time_in_second(self): if not self.end_date: return 0 - return round((self.end_date - datetime.now()).total_seconds()) + remaining_time = (self.end_date - datetime.now()).total_seconds() + remaining_time = round(remaining_time) + return max(remaining_time, 0) class ProductPricelistItem(models.Model): diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index 24264366..0b9b1945 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -154,15 +154,13 @@ class ProductTemplate(models.Model): else: template.have_promotion_program = False - def _get_flash_sale_remaining_time(self): + def _get_active_flash_sale(self): variant_ids = [x.id for x in self.product_variant_ids] pricelist = self.env['product.pricelist'].search([ ('is_flash_sale', '=', True), ('item_ids.product_id', 'in', variant_ids) - ]) - if not pricelist: - return 0 - return pricelist._remaining_time_in_second() + ], limit=1) + return pricelist @api.model def _calculate_rating_product(self): diff --git a/indoteknik_custom/views/product_pricelist.xml b/indoteknik_custom/views/product_pricelist.xml index 0ad9e200..55139a24 100644 --- a/indoteknik_custom/views/product_pricelist.xml +++ b/indoteknik_custom/views/product_pricelist.xml @@ -7,29 +7,22 @@ - - - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From f8e0259289c728b11a373601e569f6e64ca803f8 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 1 Aug 2023 11:32:11 +0700 Subject: Update voucher can't combined with other promotions --- indoteknik_api/controllers/api_v1/voucher.py | 30 ++++++++++++++++++--------- indoteknik_custom/models/product_template.py | 9 +++++++- indoteknik_custom/models/website_user_cart.py | 2 ++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/voucher.py b/indoteknik_api/controllers/api_v1/voucher.py index 4baa93b7..e6fdca68 100644 --- a/indoteknik_api/controllers/api_v1/voucher.py +++ b/indoteknik_api/controllers/api_v1/voucher.py @@ -31,9 +31,9 @@ class Voucher(controller.Controller): apply_status = '' products = checkout['products'] min_purchase_amount = voucher['min_purchase_amount'] - can_apply = True + can_apply = False difference_to_apply = 0 - + manufacture_ids = voucher['manufacture_ids'] subtotal = 0 has_match_manufacture = False @@ -44,17 +44,26 @@ class Voucher(controller.Controller): manufacture_id = product['manufacture']['id'] or False if len(manufacture_ids) == 0 or manufacture_id in manufacture_ids: - purchase_amt = price * quantity - discount_amt = (price - price_discount) * quantity - subtotal += purchase_amt - discount_amt has_match_manufacture = True - + + if product['has_flashsale']: + continue + + purchase_amt = price * quantity + discount_amt = (price - price_discount) * quantity + subtotal += purchase_amt - discount_amt + + has_flashsale_products = any(product['has_flashsale'] for product in products) if not has_match_manufacture: - can_apply = False - apply_status = 'UM' + apply_status = 'UM' # Unqualified Manufacture elif subtotal < min_purchase_amount: - can_apply = False - apply_status = 'MPA' + apply_status = 'MPA' # Minimum Purchase Amount + elif has_flashsale_products: + apply_status = 'HF' # Has Flashsale + else: + can_apply = True + + if subtotal < min_purchase_amount: difference_to_apply = min_purchase_amount - subtotal obj_voucher = request.env['voucher'].browse(voucher['id']) @@ -62,6 +71,7 @@ class Voucher(controller.Controller): voucher['can_apply'] = can_apply voucher['apply_status'] = apply_status + voucher['has_flashsale_products'] = has_flashsale_products voucher['discount_voucher'] = discount_voucher voucher['difference_to_apply'] = difference_to_apply diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index 0b9b1945..e07adf30 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -327,4 +327,11 @@ class ProductProduct(models.Model): def unlink(self): if self._name == 'product.product': - raise UserError('Maaf anda tidak bisa delete product') \ No newline at end of file + raise UserError('Maaf anda tidak bisa delete product') + + def _get_active_flash_sale(self): + pricelist = self.env['product.pricelist'].search([ + ('is_flash_sale', '=', True), + ('item_ids.product_id', '=', self.id) + ], limit=1) + return pricelist \ No newline at end of file diff --git a/indoteknik_custom/models/website_user_cart.py b/indoteknik_custom/models/website_user_cart.py index 4d85e64d..9b82aa93 100644 --- a/indoteknik_custom/models/website_user_cart.py +++ b/indoteknik_custom/models/website_user_cart.py @@ -27,6 +27,8 @@ class WebsiteUserCart(models.Model): product['selected'] = self.is_selected product['program'] = None product['can_buy'] = True + product_flashsale = self.product_id._get_active_flash_sale() + product['has_flashsale'] = True if len(product_flashsale) > 0 else False if self.program_line_id: product['program'] = self.program_line_id.res_format_cart(user=user_data, quantity=self.qty) -- cgit v1.2.3 From f0f30aa566c0e49b03fd86f86bbcd80d6c7383ce Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 3 Aug 2023 09:37:08 +0700 Subject: Fix get active flashsale on variant --- indoteknik_custom/models/product_template.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index 72fb4dea..bc54b703 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -322,8 +322,11 @@ class ProductProduct(models.Model): raise UserError('Maaf anda tidak bisa delete product') def _get_active_flash_sale(self): + current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') pricelist = self.env['product.pricelist'].search([ ('is_flash_sale', '=', True), - ('item_ids.product_id', '=', self.id) + ('item_ids.product_id', '=', self.id), + ('start_date', '<=', current_time), + ('end_date', '>=', current_time) ], limit=1) return pricelist \ No newline at end of file -- cgit v1.2.3 From 59806fddc84133717fc78b2a50a09d7638a8e79b Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 3 Aug 2023 14:01:34 +0700 Subject: Update get voucher API --- indoteknik_api/controllers/api_v1/voucher.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/voucher.py b/indoteknik_api/controllers/api_v1/voucher.py index e6fdca68..6dbf8c32 100644 --- a/indoteknik_api/controllers/api_v1/voucher.py +++ b/indoteknik_api/controllers/api_v1/voucher.py @@ -58,8 +58,6 @@ class Voucher(controller.Controller): apply_status = 'UM' # Unqualified Manufacture elif subtotal < min_purchase_amount: apply_status = 'MPA' # Minimum Purchase Amount - elif has_flashsale_products: - apply_status = 'HF' # Has Flashsale else: can_apply = True -- cgit v1.2.3 From 769ce2949ad4a3f03e0a05c6298d7299bc5b0d67 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 3 Aug 2023 14:11:01 +0700 Subject: Fix get voucher API logic --- indoteknik_api/controllers/api_v1/voucher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_api/controllers/api_v1/voucher.py b/indoteknik_api/controllers/api_v1/voucher.py index 6dbf8c32..f82e1aef 100644 --- a/indoteknik_api/controllers/api_v1/voucher.py +++ b/indoteknik_api/controllers/api_v1/voucher.py @@ -43,7 +43,7 @@ class Voucher(controller.Controller): quantity = product['quantity'] manufacture_id = product['manufacture']['id'] or False - if len(manufacture_ids) == 0 or manufacture_id in manufacture_ids: + if len(manufacture_ids) == 0 or (not product['has_flashsale'] and manufacture_id in manufacture_ids): has_match_manufacture = True if product['has_flashsale']: -- cgit v1.2.3