From 14cb30c3f2fb8b15baaf32ab9fca7bb9bda73845 Mon Sep 17 00:00:00 2001 From: IT Fixcomart Date: Wed, 5 Oct 2022 15:19:27 +0700 Subject: Update struktur API and fitur API flash sale --- indoteknik_api/__init__.py | 2 + indoteknik_api/__manifest__.py | 19 +++ indoteknik_api/controllers/__init__.py | 3 + indoteknik_api/controllers/controller.py | 48 +++++++ indoteknik_api/controllers/product_controller.py | 142 +++++++++++++++++++++ .../controllers/sale_order_controller.py | 110 ++++++++++++++++ indoteknik_api/models/__init__.py | 2 + indoteknik_api/models/product_pricelist.py | 108 ++++++++++++++++ indoteknik_api/models/product_template.py | 0 indoteknik_custom/__init__.py | 1 - indoteknik_custom/__manifest__.py | 2 + indoteknik_custom/controllers/__init__.py | 2 - indoteknik_custom/controllers/api/__init__.py | 2 - indoteknik_custom/controllers/api/product.py | 95 -------------- indoteknik_custom/controllers/api/sale_order.py | 110 ---------------- indoteknik_custom/controllers/api_controller.py | 51 -------- indoteknik_custom/models/__init__.py | 1 + indoteknik_custom/models/product_pricelist.py | 12 ++ indoteknik_custom/views/product_pricelist.xml | 28 ++++ indoteknik_custom/views/product_pricelist_item.xml | 37 ++++++ 20 files changed, 514 insertions(+), 261 deletions(-) create mode 100644 indoteknik_api/__init__.py create mode 100644 indoteknik_api/__manifest__.py create mode 100644 indoteknik_api/controllers/__init__.py create mode 100644 indoteknik_api/controllers/controller.py create mode 100644 indoteknik_api/controllers/product_controller.py create mode 100644 indoteknik_api/controllers/sale_order_controller.py create mode 100644 indoteknik_api/models/__init__.py create mode 100644 indoteknik_api/models/product_pricelist.py create mode 100644 indoteknik_api/models/product_template.py delete mode 100644 indoteknik_custom/controllers/__init__.py delete mode 100644 indoteknik_custom/controllers/api/__init__.py delete mode 100644 indoteknik_custom/controllers/api/product.py delete mode 100644 indoteknik_custom/controllers/api/sale_order.py delete mode 100644 indoteknik_custom/controllers/api_controller.py create mode 100644 indoteknik_custom/models/product_pricelist.py create mode 100644 indoteknik_custom/views/product_pricelist.xml create mode 100755 indoteknik_custom/views/product_pricelist_item.xml diff --git a/indoteknik_api/__init__.py b/indoteknik_api/__init__.py new file mode 100644 index 00000000..91c5580f --- /dev/null +++ b/indoteknik_api/__init__.py @@ -0,0 +1,2 @@ +from . import controllers +from . import models diff --git a/indoteknik_api/__manifest__.py b/indoteknik_api/__manifest__.py new file mode 100644 index 00000000..b1ebd9a1 --- /dev/null +++ b/indoteknik_api/__manifest__.py @@ -0,0 +1,19 @@ +{ + 'name': 'API Indoteknik', + 'version': '1.0', + 'category': '', + 'sequence': 1, + 'summary': 'API Indoteknik', + 'description': '', + 'author': 'PT. Indoteknik Dotcom Gemilang', + 'website': '', + 'images': ['assets/favicon.ico'], + 'depends': ['base', 'sale'], + 'data': [], + 'demo': [], + 'css': [], + 'installable': True, + 'application': False, + 'auto_install': False, + 'license': '', +} diff --git a/indoteknik_api/controllers/__init__.py b/indoteknik_api/controllers/__init__.py new file mode 100644 index 00000000..4c317fdc --- /dev/null +++ b/indoteknik_api/controllers/__init__.py @@ -0,0 +1,3 @@ +from . import controller +from . import product_controller +from . import sale_order_controller diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py new file mode 100644 index 00000000..fb5f1fce --- /dev/null +++ b/indoteknik_api/controllers/controller.py @@ -0,0 +1,48 @@ +import datetime +import base64 +import json + +from odoo import http +from odoo.http import request +from pytz import timezone + + +class Controller(http.Controller): + def authenticate(self, kw): + db = kw.get('db') + username = kw.get('username') + password = kw.get('password') + request.session.authenticate(db, username, password) + + def time_to_str(self, object, format): + time = '' + if isinstance(object, datetime.datetime): + time = object.astimezone(timezone('Asia/Jakarta')).strftime(format) + return time + + def response(self, data=[], code=200, description='OK'): + response = { + 'status': { + 'code': code, + 'description': description + } + } + if code == 200: + response.update({'result': data}) + + response = json.dumps(response) + return request.make_response(response, [('Content-Type', 'application/json')]) + + def search_with_api_params(self, model: str, kw, domain=[]): + """ To search data by default API Params if exist """ + limit = kw.get('limit', 0) + offset = kw.get('offset', 0) + order = kw.get('order', '') + + return request.env[model].search(domain, limit=int(limit), offset=int(offset), order=order) + + @http.route('/api/image///', auth='public', methods=['GET']) + def get_image(self, model, field, id): + model = request.env[model].sudo().search([('id', '=', id)], limit=1) + image = model[field] if model[field] else '' + return request.make_response(base64.b64decode(image), [('Content-Type', 'image/jpg')]) diff --git a/indoteknik_api/controllers/product_controller.py b/indoteknik_api/controllers/product_controller.py new file mode 100644 index 00000000..a127b790 --- /dev/null +++ b/indoteknik_api/controllers/product_controller.py @@ -0,0 +1,142 @@ +from datetime import datetime +from . import controller +from odoo import http +from odoo.http import request + + +class ProductController(controller.Controller): + prefix_url = '/api/product' + + # TODO: separate function for get manufacture and promotion by product_id + @http.route(prefix_url + '/search', auth='public', methods=['GET']) + def search_product(self, **kw): + self.authenticate(kw) + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + + query = kw.get('query') + if not query: + return self.response(code=400, description='Field query is required') + + query = '%' + query.replace(' ', '%') + '%' + domain = [ + ('sale_ok', '=', True), + '|', + ('default_code', 'ilike', query), + ('name', 'ilike', query) + ] + + manufactures = kw.get('manufactures') + if manufactures: + manufactures = [int(x) for x in manufactures.split(',')] + domain.append(('x_manufacture', 'in', manufactures)) + + categories = kw.get('categories') + if categories: + categories = [int(x) for x in categories.split(',')] + domain.append(('public_categ_ids', 'child_of', categories)) + + product_variants = request.env['product.product'].search(domain) + product_variant_ids = [x.id for x in product_variants] + + domain = [('product_variant_ids', 'in', product_variant_ids)] + product_templates = self.search_with_api_params('product.template', kw, domain) + data = { + 'total_records': len(request.env['product.template'].search(domain)), + 'products': [] + } + for product_template in product_templates: + discount_price = 0 + price = product_template.web_price + if price > 0: + if product_template.taxes_id: + if not product_template.taxes_id.price_include: + price += (price * product_template.taxes_id.amount / 100) + else: + price += (price * 11 / 100) + + promotion = self.get_promotion_by_product(product_template) + if len(promotion) > 0: + discount_price = price - (price * promotion['discount_percentage'] / 100) + + manufacture = self.get_manufacture_by_product(product_template) + stock = self.get_stock_by_product(product_template) + + # TODO: remove price and discount_price if old indoteknik not use + data['products'].append({ + 'id': product_template.id, + 'image': base_url + 'api/image/product.template/image_128/' + str(product_template.id) if product_template.image_128 else '', + 'name': product_template.name, + # 'lowest_price': request.env['product.pricelist'].get_lowest_product_variant_price(product_template.id, 4), + 'price': price, + 'discount_price': discount_price, + 'total_variant': len(product_template.product_variant_ids), + 'stock': stock, + 'manufacture': manufacture, + 'promotion': promotion, + }) + return self.response(data) + + @http.route(prefix_url + '/flash_sale', auth='public', methods=['GET']) + def get_flash_sale_product(self, **kw): + self.authenticate(kw) + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + product_pricelist_default = request.env['ir.config_parameter'].sudo().get_param('product.pricelist.default') + active_flash_sale = request.env['product.pricelist'].get_active_flash_sale() + data = {} + if active_flash_sale: + flash_sale = { + 'banner': base_url + 'api/image/product.pricelist/banner/' + str(active_flash_sale.id) if active_flash_sale.banner else '', + 'duration': (active_flash_sale.end_date - datetime.now()).total_seconds(), + 'products': [] + } + product_pricelist_item = request.env['product.pricelist.item'].search([('pricelist_id', '=', active_flash_sale.id)]) + product_variant_ids = [x.product_id.id for x in product_pricelist_item] + product_templates = self.search_with_api_params('product.template', kw, [('product_variant_ids', 'in', product_variant_ids)]) + for product in product_templates: + flash_sale['products'].append({ + 'id': product.id, + 'name': product.name, + 'image': base_url + 'api/image/product.template/image_128/' + str(product.id) if product.image_128 else '', + 'lowest_price': request.env['product.pricelist'].get_lowest_product_variant_price(product.id, int(product_pricelist_default)), + 'stock': self.get_stock_by_product(product), + 'total_variant': len(product.product_variant_ids), + 'manufacture': self.get_manufacture_by_product(product), + 'promotion': self.get_promotion_by_product(product), + }) + data.update({'flash_sale': flash_sale}) + return self.response(data) + + def get_stock_by_product(self, product_template: object): + stock = 0 + for product_variant in product_template.product_variant_ids: + stock += product_variant.qty_stock_vendor + return stock + + def get_manufacture_by_product(self, product_template: object): + manufacture = {} + if product_template.x_manufacture: + manufacture.update({ + 'id': product_template.x_manufacture.id, + 'name': product_template.x_manufacture.x_name, + }) + return manufacture + + def get_promotion_by_product(self, product_template: object): + base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') + promotion = {} + if product_template.x_manufacture: + domain = [ + ('rule_products_domain', 'ilike', product_template.x_manufacture.x_name), + ('active', '=', True) + ] + coupon_program = request.env['coupon.program'].search(domain, limit=1) + if coupon_program: + icon_1 = (base_url + 'api/image/coupon.program/x_studio_field_Ifopn/' + str(coupon_program.id)) if coupon_program.x_studio_field_Ifopn else '' + icon_2 = (base_url + 'api/image/coupon.program/x_studio_field_2Ul77/' + str(coupon_program.id)) if coupon_program.x_studio_field_2Ul77 else '' + promotion.update({ + 'name': coupon_program.name, + 'discount_percentage': coupon_program.discount_percentage, + 'icon_1': icon_1, + 'icon_2': icon_2 + }) + return promotion \ No newline at end of file diff --git a/indoteknik_api/controllers/sale_order_controller.py b/indoteknik_api/controllers/sale_order_controller.py new file mode 100644 index 00000000..741d4bf8 --- /dev/null +++ b/indoteknik_api/controllers/sale_order_controller.py @@ -0,0 +1,110 @@ +from . import controller +from odoo import http +from odoo.http import request + + +class SaleOrderController(controller.Controller): + @http.route('/api/sale_order/invoiced', auth='public', methods=['GET']) + def get_sale_order_invoiced_by_partner_id(self, **kw): + self.authenticate(kw) + partner_id = kw.get('partner_id') + if not partner_id: + return self.response(code=400, description='Field partner_id is required') + + partner_id = int(partner_id) + # Get company member by partner_id + parent_partner_id = request.env['res.partner'].search([('id', '=', partner_id)], limit=1).parent_id.id + partner_childs = request.env['res.partner'].search([('parent_id', '=', int(parent_partner_id))]) + partner_child_ids = [v['id'] for v in partner_childs] + [partner_id] + + # Get sale order by company member and invoiced + data = [] + default_domain = [ + ('partner_id', 'in', partner_child_ids), + '|', + ('invoice_status', '=', 'invoiced'), + ('invoice_status', '=', 'to_invoice') + ] + sale_orders = self.search_with_api_params('sale.order', kw, default_domain) + for sale_order in sale_orders: + pickings = [] + for picking in sale_order.picking_ids: + if picking.state in ['confirmed', 'assigned', 'done']: + pickings.append({ + 'id': picking.id, + 'name': picking.name, + 'delivery_address': picking.partner_id.street, + 'delivery_tracking_no': picking.delivery_tracking_no, + 'delivery_status': picking.delivery_status + }) + + data.append({ + 'id': sale_order.id, + 'name': sale_order.name, + 'amount_total': sale_order.amount_total, + 'salesperson': sale_order.user_id.name, + 'date_order': self.time_to_str(sale_order.date_order, '%d/%m/%Y'), + 'pickings': pickings, + 'access_token': sale_order.access_token + }) + return self.response(data) + + @http.route('/api/sale_order/invoiced/detail', auth='public', methods=['GET']) + def get_sale_order_invoiced_detail_by_partner(self, **kw): + self.authenticate(kw) + + id = kw.get('id') + partner_id = kw.get('partner_id') + if not id: + return self.response(code=400, description='Field id is required') + if not partner_id: + return self.response(code=400, description='Field partner_id is required') + + default_domain = [ + ('id', '=', id), + '|', + ('invoice_status', '=', 'invoiced'), + ('invoice_status', '=', 'to_invoice') + ] + parent_partner_id = request.env['res.partner'].search([('id', '=', int(partner_id))], limit=1).parent_id.id + partner_childs = request.env['res.partner'].search([('parent_id', '=', int(parent_partner_id))]) + partner_child_ids = [v['id'] for v in partner_childs] + [int(partner_id)] + default_domain.append(('partner_id', 'in', partner_child_ids)) + + sale_order = self.search_with_api_params('sale.order', kw, default_domain) + orders = [] + for order in sale_order.order_line: + orders.append({ + 'name': order.name, + 'product_qty': order.product_qty, + 'price_unit': order.price_unit, + 'price_tax': order.price_tax, + 'price_total': order.price_total, + 'price_subtotal': order.price_subtotal, + 'tax': order.tax_id.name, + 'discount': order.discount, + }) + + data = { + 'id': sale_order.id, + 'name': sale_order.name, + 'carrier': sale_order.carrier_id.name, + 'partner': { + 'id': sale_order.partner_id.id, + 'name': sale_order.partner_id.name, + 'mobile': sale_order.partner_id.mobile, + 'email': sale_order.partner_id.email + }, + 'delivery_address': sale_order.partner_shipping_id.street, + 'delivery_method': sale_order.carrier_id.name, + 'payment_term': sale_order.payment_term_id.name, + 'salesperson': sale_order.user_id.name, + 'date_order': self.time_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), + 'note': sale_order.note, + 'amount_untaxed': sale_order.amount_untaxed, + 'amount_tax': sale_order.amount_tax, + 'amount_total': sale_order.amount_total, + 'orders': orders + } + + return self.response(data) diff --git a/indoteknik_api/models/__init__.py b/indoteknik_api/models/__init__.py new file mode 100644 index 00000000..06f1e1da --- /dev/null +++ b/indoteknik_api/models/__init__.py @@ -0,0 +1,2 @@ +from . import product_pricelist +from . import product_template diff --git a/indoteknik_api/models/product_pricelist.py b/indoteknik_api/models/product_pricelist.py new file mode 100644 index 00000000..3a807f3a --- /dev/null +++ b/indoteknik_api/models/product_pricelist.py @@ -0,0 +1,108 @@ +from odoo import models +from pytz import timezone +from datetime import datetime + + +class ProductPricelist(models.Model): + _inherit = 'product.pricelist' + + def compute_price(self, pricelist_id: int, product_id: int): + """ + Compute price with tax, discount formula, and fixed_price + @param pricelist_id: id of product.pricelist + @param product_id: id of product.product + @return: returns price value from pricelist. + """ + price = 0 + discounts = [] + + is_flash_sale_product = self.is_flash_sale_product(product_id) + if is_flash_sale_product: + pricelist_id = is_flash_sale_product + + is_compute_formula = True + while is_compute_formula: + pricelist = self.env['product.pricelist.item'].search([ + ('pricelist_id', '=', pricelist_id), + ('product_id', '=', product_id) + ], limit=1) + if pricelist: + if pricelist.compute_price == 'formula': + pricelist_id = pricelist.base_pricelist_id.id + discounts.append(pricelist.price_discount) + else: + price = pricelist.fixed_price + is_compute_formula = False + else: + is_compute_formula = False + + product = self.env['product.product'].browse(product_id) + if product: + for tax in product.taxes_id: + if not tax.price_include: + price *= (100 + tax.amount) / 100 + + price_discount = price + for discount in discounts: + price_discount *= (100 - discount) / 100 + + discount_percentage = 0 + if len(discounts) > 0: + discount_percentage = (price - price_discount) / price * 100 + + return { + 'price': price, + 'price_discount': price_discount, + 'discount_percentage': discount_percentage + } + + def get_lowest_product_variant_price(self, product_id, pricelist_id): + """ + @param product_id: id of product.template + @param pricelist_id: id of pricelist which have default price + @return price: object + """ + product_template = self.env['product.template'].browse(product_id) + product_variant_ids = [x.id for x in product_template.product_variant_ids] + product = self.env['product.pricelist.item'].search([ + ('pricelist_id', '=', pricelist_id), + ('product_id', 'in', product_variant_ids) + ], order='fixed_price asc', limit=1) + product_id = 0 + if product: + product_id = product.product_id.id + return self.compute_price(pricelist_id, product_id) + + def get_active_flash_sale(self): + """ + Check whether have active flash sale in range of date + @return: returns pricelist: object + """ + current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + pricelist = self.search([ + ('is_flash_sale', '=', True), + ('start_date', '<=', current_time), + ('end_date', '>=', current_time) + ], limit=1) + return pricelist + + def is_flash_sale_product(self, product_id: int): + """ + Check whether product is flash sale. + @param product_id: id of product.product + @return: returns pricelist_id: int, if product is flash sale. + """ + pricelist = self.get_active_flash_sale() + if pricelist: + pricelist_product_ids = [x.product_id.id for x in pricelist.item_ids] + if product_id in pricelist_product_ids: + return pricelist.id + return False + + # TODO: need testing + def get_active_flash_sale_items(self): + pricelist = self.get_active_flash_sale() + pricelist_item = False + if pricelist: + pricelist_item = [x.product_id for x in pricelist.item_ids] + return pricelist_item diff --git a/indoteknik_api/models/product_template.py b/indoteknik_api/models/product_template.py new file mode 100644 index 00000000..e69de29b diff --git a/indoteknik_custom/__init__.py b/indoteknik_custom/__init__.py index 38718f08..0650744f 100755 --- a/indoteknik_custom/__init__.py +++ b/indoteknik_custom/__init__.py @@ -1,2 +1 @@ from . import models -from . import controllers \ No newline at end of file diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 937fb0c9..8d7ddeca 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -14,6 +14,8 @@ 'views/blog_post.xml', 'views/coupon_program.xml', 'views/delivery_order.xml', + 'views/product_pricelist.xml', + 'views/product_pricelist_item.xml', 'views/product_public_category.xml', 'views/product_template.xml', 'views/purchase_order.xml', diff --git a/indoteknik_custom/controllers/__init__.py b/indoteknik_custom/controllers/__init__.py deleted file mode 100644 index 2fd318df..00000000 --- a/indoteknik_custom/controllers/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import api_controller -from . import api diff --git a/indoteknik_custom/controllers/api/__init__.py b/indoteknik_custom/controllers/api/__init__.py deleted file mode 100644 index bd901bd4..00000000 --- a/indoteknik_custom/controllers/api/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import sale_order -from . import product diff --git a/indoteknik_custom/controllers/api/product.py b/indoteknik_custom/controllers/api/product.py deleted file mode 100644 index 3b1c4ce8..00000000 --- a/indoteknik_custom/controllers/api/product.py +++ /dev/null @@ -1,95 +0,0 @@ -import base64 - -from .. import api_controller -from odoo import http -from odoo.http import request - - -class ProductApi(api_controller.ApiController): - @http.route('/api/product/search', auth='public', methods=['GET']) - def search_product(self, **kw): - self.authenticate(kw) - query = kw.get('query') - if not query: - return self.response(code=400, description='Field query is required') - - query = '%' + query.replace(' ', '%') + '%' - domain = [ - ('sale_ok', '=', True), - '|', - ('default_code', 'ilike', query), - ('name', 'ilike', query) - ] - - manufactures = kw.get('manufactures') - if manufactures: - manufactures = [int(x) for x in manufactures.split(',')] - domain.append(('x_manufacture', 'in', manufactures)) - - categories = kw.get('categories') - if categories: - categories = [int(x) for x in categories.split(',')] - domain.append(('public_categ_ids', 'child_of', categories)) - - product_variants = request.env['product.product'].search(domain) - product_variant_ids = [v['id'] for v in product_variants] - - base_url = request.env['ir.config_parameter'].sudo().get_param('web.base.url') - domain = [ - ('product_variant_ids', 'in', product_variant_ids) - ] - product_templates = self.search_with_api_params('product.template', kw, domain) - data = { - 'total_records': len(request.env['product.template'].search(domain)), - 'products': [] - } - for product_template in product_templates: - stock = 0 - for product_variant in product_template.product_variant_ids: - stock += product_variant.qty_stock_vendor - - discount_price = 0 - price = product_template.web_price - if price > 0: - if product_template.taxes_id: - if not product_template.taxes_id.price_include: - price += (price * product_template.taxes_id.amount / 100) - else: - price += (price * 11 / 100) - - promotion = {} - manufacture = {} - if product_template.x_manufacture: - manufacture.update({ - 'id': product_template.x_manufacture.id, - 'name': product_template.x_manufacture.x_name, - }) - domain = [ - ('rule_products_domain', 'ilike', product_template.x_manufacture.x_name), - ('active', '=', True) - ] - coupon_program = request.env['coupon.program'].search(domain, limit=1) - if coupon_program: - discount_price = price - (price * coupon_program.discount_percentage / 100) - icon_1 = (base_url + 'api/image/coupon.program/x_studio_field_Ifopn/' + str(coupon_program.id)) if coupon_program.x_studio_field_Ifopn else '' - icon_2 = (base_url + 'api/image/coupon.program/x_studio_field_2Ul77/' + str(coupon_program.id)) if coupon_program.x_studio_field_2Ul77 else '' - promotion.update({ - 'name': coupon_program.name, - 'discount_percentage': coupon_program.discount_percentage, - 'icon_1': icon_1, - 'icon_2': icon_2 - }) - - data['products'].append({ - 'id': product_template.id, - 'image': base_url + 'api/image/product.template/image_128/' + str(product_template.id) if product_template.image_128 else '', - 'name': product_template.name, - 'price': price, - 'discount_price': discount_price, - 'total_variant': len(product_template.product_variant_ids), - 'stock': stock, - 'manufacture': manufacture, - 'promotion': promotion, - }) - - return self.response(data) diff --git a/indoteknik_custom/controllers/api/sale_order.py b/indoteknik_custom/controllers/api/sale_order.py deleted file mode 100644 index c00a94d3..00000000 --- a/indoteknik_custom/controllers/api/sale_order.py +++ /dev/null @@ -1,110 +0,0 @@ -from .. import api_controller -from odoo import http -from odoo.http import request - - -class SaleOrderApi(api_controller.ApiController): - @http.route('/api/sale_order/invoiced', auth='public', methods=['GET']) - def get_sale_order_invoiced_by_partner_id(self, **kw): - self.authenticate(kw) - partner_id = kw.get('partner_id') - if not partner_id: - return self.response(code=400, description='Field partner_id is required') - - partner_id = int(partner_id) - # Get company member by partner_id - parent_partner_id = request.env['res.partner'].search([('id', '=', partner_id)], limit=1).parent_id.id - partner_childs = request.env['res.partner'].search([('parent_id', '=', int(parent_partner_id))]) - partner_child_ids = [v['id'] for v in partner_childs] + [partner_id] - - # Get sale order by company member and invoiced - data = [] - default_domain = [ - ('partner_id', 'in', partner_child_ids), - '|', - ('invoice_status', '=', 'invoiced'), - ('invoice_status', '=', 'to_invoice') - ] - sale_orders = self.search_with_api_params('sale.order', kw, default_domain) - for sale_order in sale_orders: - pickings = [] - for picking in sale_order.picking_ids: - if picking.state in ['confirmed', 'assigned', 'done']: - pickings.append({ - 'id': picking.id, - 'name': picking.name, - 'delivery_address': picking.partner_id.street, - 'delivery_tracking_no': picking.delivery_tracking_no, - 'delivery_status': picking.delivery_status - }) - - data.append({ - 'id': sale_order.id, - 'name': sale_order.name, - 'amount_total': sale_order.amount_total, - 'salesperson': sale_order.user_id.name, - 'date_order': self.time_to_str(sale_order.date_order, '%d/%m/%Y'), - 'pickings': pickings, - 'access_token': sale_order.access_token - }) - return self.response(data) - - @http.route('/api/sale_order/invoiced/detail', auth='public', methods=['GET']) - def get_sale_order_invoiced_detail_by_partner(self, **kw): - self.authenticate(kw) - - id = kw.get('id') - partner_id = kw.get('partner_id') - if not id: - return self.response(code=400, description='Field id is required') - if not partner_id: - return self.response(code=400, description='Field partner_id is required') - - default_domain = [ - ('id', '=', id), - '|', - ('invoice_status', '=', 'invoiced'), - ('invoice_status', '=', 'to_invoice') - ] - parent_partner_id = request.env['res.partner'].search([('id', '=', int(partner_id))], limit=1).parent_id.id - partner_childs = request.env['res.partner'].search([('parent_id', '=', int(parent_partner_id))]) - partner_child_ids = [v['id'] for v in partner_childs] + [int(partner_id)] - default_domain.append(('partner_id', 'in', partner_child_ids)) - - sale_order = self.search_with_api_params('sale.order', kw, default_domain) - orders = [] - for order in sale_order.order_line: - orders.append({ - 'name': order.name, - 'product_qty': order.product_qty, - 'price_unit': order.price_unit, - 'price_tax': order.price_tax, - 'price_total': order.price_total, - 'price_subtotal': order.price_subtotal, - 'tax': order.tax_id.name, - 'discount': order.discount, - }) - - data = { - 'id': sale_order.id, - 'name': sale_order.name, - 'carrier': sale_order.carrier_id.name, - 'partner': { - 'id': sale_order.partner_id.id, - 'name': sale_order.partner_id.name, - 'mobile': sale_order.partner_id.mobile, - 'email': sale_order.partner_id.email - }, - 'delivery_address': sale_order.partner_shipping_id.street, - 'delivery_method': sale_order.carrier_id.name, - 'payment_term': sale_order.payment_term_id.name, - 'salesperson': sale_order.user_id.name, - 'date_order': self.time_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), - 'note': sale_order.note, - 'amount_untaxed': sale_order.amount_untaxed, - 'amount_tax': sale_order.amount_tax, - 'amount_total': sale_order.amount_total, - 'orders': orders - } - - return self.response(data) diff --git a/indoteknik_custom/controllers/api_controller.py b/indoteknik_custom/controllers/api_controller.py deleted file mode 100644 index faf8b640..00000000 --- a/indoteknik_custom/controllers/api_controller.py +++ /dev/null @@ -1,51 +0,0 @@ -import datetime -import base64 - -from odoo import http -from odoo.http import request -import json -from pytz import timezone - - -class ApiController(http.Controller): - def authenticate(self, kw): - db = kw.get('db') - username = kw.get('username') - password = kw.get('password') - request.session.authenticate(db, username, password) - - def time_to_str(self, object, format): - time = '' - if isinstance(object, datetime.datetime): - time = object.astimezone(timezone('Asia/Jakarta')).strftime(format) - return time - - def response(self, data=[], code=200, description='OK'): - response = { - 'status': { - 'code': code, - 'description': description - } - } - if code == 200: - response.update({'result': data}) - - response = json.dumps(response) - return request.make_response(response, [('Content-Type', 'application/json')]) - - def search_with_api_params(self, model: str, kw, domain=[]): - limit = kw.get('limit', 0) - offset = kw.get('offset', 0) - order = kw.get('order', '') - # domain = kw.get('domain', []) - # if domain: - # domain = json.loads(domain) - # domain += default_domain - - return request.env[model].search(domain, limit=int(limit), offset=int(offset), order=order) - - @http.route('/api/image///', auth='public', methods=['GET']) - def get_image(self, model, field, id): - model = request.env[model].sudo().search([('id', '=', id)], limit=1) - image = model[field] if model[field] else '' - return request.make_response(base64.b64decode(image), [('Content-Type', 'image/jpg')]) diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index e4913205..36ff7b5e 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -24,3 +24,4 @@ from . import stock_move from . import stock_picking from . import stock_picking_type from . import delivery_order +from . import product_pricelist diff --git a/indoteknik_custom/models/product_pricelist.py b/indoteknik_custom/models/product_pricelist.py new file mode 100644 index 00000000..b70eb6e6 --- /dev/null +++ b/indoteknik_custom/models/product_pricelist.py @@ -0,0 +1,12 @@ +from odoo import models, fields, api +from odoo.exceptions import UserError + + +class ProductPricelist(models.Model): + _inherit = 'product.pricelist' + + is_flash_sale = fields.Boolean(string='Flash Sale', default=False) + banner = fields.Binary(string='Banner') + start_date = fields.Datetime(string='Start Date') + end_date = fields.Datetime(string='End Date') + diff --git a/indoteknik_custom/views/product_pricelist.xml b/indoteknik_custom/views/product_pricelist.xml new file mode 100644 index 00000000..18e9835a --- /dev/null +++ b/indoteknik_custom/views/product_pricelist.xml @@ -0,0 +1,28 @@ + + + + product.pricelist.view.inherit + product.pricelist + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/indoteknik_custom/views/product_pricelist_item.xml b/indoteknik_custom/views/product_pricelist_item.xml new file mode 100755 index 00000000..94ba9e4f --- /dev/null +++ b/indoteknik_custom/views/product_pricelist_item.xml @@ -0,0 +1,37 @@ + + + + Product Pricelist Item + product.pricelist.item + tree,form + + + + product.pricelist.item.form.view.inherit + product.pricelist.item + + + + + + + + + + product.pricelist.item.search.inherit + product.pricelist.item + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3