From 98e81e0c84f6625aab09bb3b5c5e5137d68c61a0 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 24 Mar 2023 09:32:19 +0700 Subject: development create bill from receipt --- indoteknik_custom/models/stock_move.py | 23 +++++++++++++++++++++++ indoteknik_custom/models/stock_picking.py | 23 ++++++++++++++--------- indoteknik_custom/views/stock_picking.xml | 2 +- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/indoteknik_custom/models/stock_move.py b/indoteknik_custom/models/stock_move.py index 22a73010..8be05630 100644 --- a/indoteknik_custom/models/stock_move.py +++ b/indoteknik_custom/models/stock_move.py @@ -6,6 +6,29 @@ class StockMove(models.Model): line_no = fields.Integer('No', default=0) + def _prepare_lines_bill(self, po_line): + res = { + 'display_type': po_line.display_type, + 'sequence': po_line.sequence, + 'name': '%s: %s' % (po_line.order_id.name, po_line.name), + 'product_id': self.product_id.id, + 'product_uom_id': self.product_uom.id, + 'quantity': self.quantity_done, + 'price_unit': po_line.price_unit, + 'tax_ids': [(6, 0, po_line.taxes_id.ids)], + 'analytic_account_id': po_line.account_analytic_id.id, + 'analytic_tag_ids': [(6, 0, po_line.analytic_tag_ids.ids)], + 'purchase_line_id': po_line.id, + } + + res.update({ + 'move_id': self.move_id, + 'currency_id': self.move_id.currency_id, + 'date_maturity': self.move_id.invoice_date_due, + 'partner_id': self.move_id.partner_id.id, + }) + return res + def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id, qty, description, svl_id, cost): self.ensure_one() if self.picking_id.is_internal_use: diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 77af676c..f59534d2 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -84,16 +84,21 @@ class StockPicking(models.Model): # Invoice values. invoice_vals = order._prepare_invoice() # Invoice line values (keep only necessary sections). - for line in order.order_line: - if line.display_type == 'line_section': - pending_section = line - continue - if not float_is_zero(line.qty_to_invoice, precision_digits=precision): - if pending_section: - invoice_vals['invoice_line_ids'].append((0, 0, pending_section._prepare_account_move_line())) - pending_section = None - invoice_vals['invoice_line_ids'].append((0, 0, line._prepare_account_move_line())) + # for line in order.order_line: + # if line.display_type == 'line_section': + # pending_section = line + # continue + # if not float_is_zero(line.qty_to_invoice, precision_digits=precision): + # if pending_section: + # invoice_vals['invoice_line_ids'].append((0, 0, pending_section._prepare_lines_bill())) + # pending_section = None + # invoice_vals['invoice_line_ids'].append((0, 0, line._prepare_lines_bill())) + + for in_line in self.move_lines: + invoice_vals['invoice_line_ids'].append((0,0, in_line._prepare_lines_bill)) invoice_vals_list.append(invoice_vals) + print('---cek disini---') + print(invoice_vals_list) if not invoice_vals_list: raise UserError(_('There is no invoiceable line. If a product has a control policy based on received quantity, please make sure that a quantity has been received.')) diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml index 0ff79ea8..e4e9f722 100644 --- a/indoteknik_custom/views/stock_picking.xml +++ b/indoteknik_custom/views/stock_picking.xml @@ -34,7 +34,7 @@ -- cgit v1.2.3 From a9fd6502729bbd337c0ba762d2cc88fcd8f60900 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 24 Mar 2023 15:48:24 +0700 Subject: rest api for website pricelist --- indoteknik_api/controllers/api_v1/product.py | 110 +++++++++++++++++++++++++++ indoteknik_api/models/product_product.py | 66 +++++++++++++++- indoteknik_custom/models/res_partner.py | 1 + 3 files changed, 176 insertions(+), 1 deletion(-) diff --git a/indoteknik_api/controllers/api_v1/product.py b/indoteknik_api/controllers/api_v1/product.py index dc941f13..22030eab 100644 --- a/indoteknik_api/controllers/api_v1/product.py +++ b/indoteknik_api/controllers/api_v1/product.py @@ -4,6 +4,7 @@ from odoo.http import request from datetime import datetime, timedelta import ast import logging +import math _logger = logging.getLogger(__name__) @@ -11,6 +12,115 @@ _logger = logging.getLogger(__name__) class Product(controller.Controller): prefix = '/api/v1/' + @http.route(prefix + 'product/template/price/', auth='public', methods=['GET']) + def get_product_template_price_by_id(self, **kw): + if not self.authenticate(): + return self.response(code=401, description='Unauthorized') + id = kw.get('id') + partner_id = int(kw.get('partner_id', 0)) + product_template = request.env['product.template'].search([('id', '=', id)], limit=1) + + data = self.get_product_price_for_website(product_template.product_variant_id.id, partner_id) + data = { + 'price_include': product_template.product_variant_id._get_website_price_include_tax(), + 'price_exclude': product_template.product_variant_id._get_website_price_exclude_tax(), + 'discount': product_template.product_variant_id._get_website_disc(partner_id), + 'price_include_after_discount': product_template.product_variant_id._get_website_price_after_disc(), + 'price_exclude_after_discount': product_template.product_variant_id._get_website_price_after_disc_and_tax(), + 'tax': product_template.product_variant_id._get_website_tax(), + } + + if product_template.product_variant_count > 1: + price_excl_after_disc = price_excl = 0 + for variant in product_template.product_variant_ids: + if price_excl_after_disc == 0: + price_excl = variant._get_website_price_exclude_tax() + price_excl_after_disc = variant._get_website_price_after_disc_and_tax() + elif variant._get_website_price_after_disc_and_tax() < price_excl_after_disc: + price_excl_after_disc = variant._get_website_price_after_disc_and_tax() + price_excl = variant._get_website_price_exclude_tax() + else: + price_excl_after_disc = price_excl_after_disc + price_excl = price_excl + + start_from = { + 'price_start_from': price_excl, + 'price_disc_start_from': price_excl_after_disc + } + data.update(start_from) + + return self.response(data) + + def get_product_price_for_website(self, product_id, partner_id=0): + # default_pricelist_id = request.env['ir.config_parameter'].get_param('product.pricelist.default_price_id') + # default_discount_id = request.env['ir.config.parameter'].get_param('product.pricelist.default_discount_id') + # default_divide_tax = request.env['ir.config.parameter'].get_param('product.pricelist.default_divide_tax') + default_pricelist_id = int(1) + default_discount_id = int(4) + default_divide_tax = float(1.11) + + # compile partner + partner = request.env['res.partner'].search([('id', '=', partner_id)], limit=1) + + if partner: + if not partner.parent_id: # it means this is a parent + default_discount_id = partner.custom_pricelist_id + else: # it means this is NOT parent + default_discount_id = partner.parent_id.custom_pricelist_id + + query = [ + ('pricelist_id.id', '=', default_pricelist_id), + ('product_id.id', '=', product_id) + ] + pl_item1 = request.env['product.pricelist.item'].search(query, limit=1) + query = [ + ('pricelist_id.id', '=', default_discount_id), + ('product_id.id', '=', product_id) + ] + pl_item2 = request.env['product.pricelist.item'].search(query, limit=1) + + price_coret = float(pl_item1.fixed_price) + price_include = math.floor(price_coret) + discount = float(pl_item2.price_discount) + + data = [] + if price_coret > 0 and discount > 0: + price_coret = price_coret / default_divide_tax + price_coret = math.floor(price_coret) + price_discount = price_coret - (price_coret * discount / 100) + price_discount = math.floor(price_discount) + ppn = price_discount * 11/100 + ppn = math.floor(ppn) + + data = { + 'price_include': price_include, + 'price': price_coret, + 'discount': discount, + 'price_discount': price_discount, + 'ppn': ppn + } + elif price_coret > 0: + price_coret = price_coret / default_divide_tax + price_coret = math.floor(price_coret) + ppn = price_coret * 11/100 + ppn = math.floor(ppn) + data = { + 'price_include': price_include, + 'price': price_coret, + 'discount': 0, + 'price_discount': price_coret, + 'ppn': ppn + } + else: + data = { + 'price': 0, + 'discount': 0, + 'price_discount': 0, + 'ppn': 0 + } + return data + + @http.route(prefix + 'new_product', auth='public', methods=['GET', 'OPTIONS']) def get_new_product(self, **kw): if not self.authenticate(): diff --git a/indoteknik_api/models/product_product.py b/indoteknik_api/models/product_product.py index 2e84b9f4..f83ede27 100644 --- a/indoteknik_api/models/product_product.py +++ b/indoteknik_api/models/product_product.py @@ -1,4 +1,5 @@ from odoo import models +import math class ProductProduct(models.Model): @@ -34,4 +35,67 @@ class ProductProduct(models.Model): 'image_promotion_1': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_1', manufacture.id), 'image_promotion_2': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_2', manufacture.id), } - return {} \ No newline at end of file + return {} + + def _get_website_price_include_tax(self): + default_pricelist_id = int(1) + + query = [ + ('pricelist_id.id', '=', default_pricelist_id), + ('product_id.id', '=', self.id) + ] + pl_item1 = self.env['product.pricelist.item'].search(query, limit=1) + + retValue = pl_item1.fixed_price + retValue = math.floor(retValue) + return retValue + + def _get_website_price_exclude_tax(self): + default_divide_tax = float(1.11) + price_incl = self._get_website_price_include_tax() + res = price_incl / default_divide_tax + return math.floor(res) + + def _get_website_disc(self, partner_id): + default_discount_id = int(4) + + # compile partner + partner = self.env['res.partner'].search([('id', '=', partner_id)], limit=1) + + if partner: + if not partner.parent_id: # it means this is a parent + default_discount_id = partner.custom_pricelist_id + else: # it means this is NOT parent + default_discount_id = partner.parent_id.custom_pricelist_id + query = [ + ('pricelist_id.id', '=', default_discount_id), + ('product_id.id', '=', self.id) + ] + + pl_item2 = self.env['product.pricelist.item'].search(query, limit=1) + + retValue = pl_item2.price_discount + return retValue + + def _get_website_price_after_disc_and_tax(self): + default_divide_tax = float(1.11) + price_after_disc = self._get_website_price_after_disc() + res = price_after_disc / default_divide_tax + res = math.floor(res) + return res + + def _get_website_price_after_disc(self): + discount = self._get_website_disc(0) + price_incl = self._get_website_price_include_tax() + res = 0 + if discount > 0: + res = price_incl - (price_incl * discount / 100) + else: + res = price_incl + return math.floor(res) + + def _get_website_tax(self): + default_percent_tax = float(11) + price_after_disc = self._get_website_price_after_disc_and_tax() + res = price_after_disc * default_percent_tax / 100 + return math.floor(res) diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py index 1cdf7c72..ad88957f 100644 --- a/indoteknik_custom/models/res_partner.py +++ b/indoteknik_custom/models/res_partner.py @@ -6,3 +6,4 @@ class ResPartner(models.Model): reference_number = fields.Char(string="Reference Number") company_type_id = fields.Many2one('res.partner.company_type', string='Company Type') + custom_pricelist_id = fields.Many2one('product.pricelist', string='Price Matrix') -- cgit v1.2.3 From 05c2c86f0f82ab42f9eb23b0aaaf838eb52da435 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 24 Mar 2023 15:54:25 +0700 Subject: revert create bill from received --- indoteknik_custom/models/stock_move.py | 23 ----------------------- indoteknik_custom/models/stock_picking.py | 23 +++++++++-------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/indoteknik_custom/models/stock_move.py b/indoteknik_custom/models/stock_move.py index 8be05630..22a73010 100644 --- a/indoteknik_custom/models/stock_move.py +++ b/indoteknik_custom/models/stock_move.py @@ -6,29 +6,6 @@ class StockMove(models.Model): line_no = fields.Integer('No', default=0) - def _prepare_lines_bill(self, po_line): - res = { - 'display_type': po_line.display_type, - 'sequence': po_line.sequence, - 'name': '%s: %s' % (po_line.order_id.name, po_line.name), - 'product_id': self.product_id.id, - 'product_uom_id': self.product_uom.id, - 'quantity': self.quantity_done, - 'price_unit': po_line.price_unit, - 'tax_ids': [(6, 0, po_line.taxes_id.ids)], - 'analytic_account_id': po_line.account_analytic_id.id, - 'analytic_tag_ids': [(6, 0, po_line.analytic_tag_ids.ids)], - 'purchase_line_id': po_line.id, - } - - res.update({ - 'move_id': self.move_id, - 'currency_id': self.move_id.currency_id, - 'date_maturity': self.move_id.invoice_date_due, - 'partner_id': self.move_id.partner_id.id, - }) - return res - def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id, qty, description, svl_id, cost): self.ensure_one() if self.picking_id.is_internal_use: diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index f59534d2..77af676c 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -84,21 +84,16 @@ class StockPicking(models.Model): # Invoice values. invoice_vals = order._prepare_invoice() # Invoice line values (keep only necessary sections). - # for line in order.order_line: - # if line.display_type == 'line_section': - # pending_section = line - # continue - # if not float_is_zero(line.qty_to_invoice, precision_digits=precision): - # if pending_section: - # invoice_vals['invoice_line_ids'].append((0, 0, pending_section._prepare_lines_bill())) - # pending_section = None - # invoice_vals['invoice_line_ids'].append((0, 0, line._prepare_lines_bill())) - - for in_line in self.move_lines: - invoice_vals['invoice_line_ids'].append((0,0, in_line._prepare_lines_bill)) + for line in order.order_line: + if line.display_type == 'line_section': + pending_section = line + continue + if not float_is_zero(line.qty_to_invoice, precision_digits=precision): + if pending_section: + invoice_vals['invoice_line_ids'].append((0, 0, pending_section._prepare_account_move_line())) + pending_section = None + invoice_vals['invoice_line_ids'].append((0, 0, line._prepare_account_move_line())) invoice_vals_list.append(invoice_vals) - print('---cek disini---') - print(invoice_vals_list) if not invoice_vals_list: raise UserError(_('There is no invoiceable line. If a product has a control policy based on received quantity, please make sure that a quantity has been received.')) -- cgit v1.2.3 From 567da97c5ed74db8e06d2bf846479d14fdc34c13 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 24 Mar 2023 16:04:54 +0700 Subject: add missing api product product price --- indoteknik_api/controllers/api_v1/product.py | 86 ++++++---------------------- 1 file changed, 17 insertions(+), 69 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/product.py b/indoteknik_api/controllers/api_v1/product.py index 22030eab..b8a44f5b 100644 --- a/indoteknik_api/controllers/api_v1/product.py +++ b/indoteknik_api/controllers/api_v1/product.py @@ -20,7 +20,6 @@ class Product(controller.Controller): partner_id = int(kw.get('partner_id', 0)) product_template = request.env['product.template'].search([('id', '=', id)], limit=1) - data = self.get_product_price_for_website(product_template.product_variant_id.id, partner_id) data = { 'price_include': product_template.product_variant_id._get_website_price_include_tax(), 'price_exclude': product_template.product_variant_id._get_website_price_exclude_tax(), @@ -50,76 +49,25 @@ class Product(controller.Controller): data.update(start_from) return self.response(data) + + @http.route(prefix + 'product/product/price/', auth='public', methods=['GET']) + def get_product_product_price_by_id(self, **kw): + if not self.authenticate(): + return self.response(code=401, description='Unauthorized') + id = kw.get('id') + partner_id = int(kw.get('partner_id', 0)) + product_product = request.env['product.product'].search([('id', '=', id)], limit=1) - def get_product_price_for_website(self, product_id, partner_id=0): - # default_pricelist_id = request.env['ir.config_parameter'].get_param('product.pricelist.default_price_id') - # default_discount_id = request.env['ir.config.parameter'].get_param('product.pricelist.default_discount_id') - # default_divide_tax = request.env['ir.config.parameter'].get_param('product.pricelist.default_divide_tax') - default_pricelist_id = int(1) - default_discount_id = int(4) - default_divide_tax = float(1.11) - - # compile partner - partner = request.env['res.partner'].search([('id', '=', partner_id)], limit=1) - - if partner: - if not partner.parent_id: # it means this is a parent - default_discount_id = partner.custom_pricelist_id - else: # it means this is NOT parent - default_discount_id = partner.parent_id.custom_pricelist_id - - query = [ - ('pricelist_id.id', '=', default_pricelist_id), - ('product_id.id', '=', product_id) - ] - pl_item1 = request.env['product.pricelist.item'].search(query, limit=1) - query = [ - ('pricelist_id.id', '=', default_discount_id), - ('product_id.id', '=', product_id) - ] - pl_item2 = request.env['product.pricelist.item'].search(query, limit=1) - - price_coret = float(pl_item1.fixed_price) - price_include = math.floor(price_coret) - discount = float(pl_item2.price_discount) - - data = [] - if price_coret > 0 and discount > 0: - price_coret = price_coret / default_divide_tax - price_coret = math.floor(price_coret) - price_discount = price_coret - (price_coret * discount / 100) - price_discount = math.floor(price_discount) - ppn = price_discount * 11/100 - ppn = math.floor(ppn) - - data = { - 'price_include': price_include, - 'price': price_coret, - 'discount': discount, - 'price_discount': price_discount, - 'ppn': ppn - } - elif price_coret > 0: - price_coret = price_coret / default_divide_tax - price_coret = math.floor(price_coret) - ppn = price_coret * 11/100 - ppn = math.floor(ppn) - data = { - 'price_include': price_include, - 'price': price_coret, - 'discount': 0, - 'price_discount': price_coret, - 'ppn': ppn - } - else: - data = { - 'price': 0, - 'discount': 0, - 'price_discount': 0, - 'ppn': 0 - } - return data + data = { + 'price_include': product_product._get_website_price_include_tax(), + 'price_exclude': product_product._get_website_price_exclude_tax(), + 'discount': product_product._get_website_disc(partner_id), + 'price_include_after_discount': product_product._get_website_price_after_disc(), + 'price_exclude_after_discount': product_product._get_website_price_after_disc_and_tax(), + 'tax': product_product._get_website_tax() + } + return self.response(data) @http.route(prefix + 'new_product', auth='public', methods=['GET', 'OPTIONS']) def get_new_product(self, **kw): -- cgit v1.2.3