diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2023-09-29 02:32:56 +0000 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2023-09-29 02:32:56 +0000 |
| commit | 78f205302c35cab2512971d64c8152aab2dcfa95 (patch) | |
| tree | 72be75ad949fe9efaf7b55c8f7f5722225538b28 | |
| parent | 50b5bd7bd984ef108e8bd324440050a222d8262f (diff) | |
| parent | 0bb47005022b33c79ecfb5924d41f35ce794c5fb (diff) | |
Merged in production (pull request #126)
Production
36 files changed, 539 insertions, 184 deletions
diff --git a/indoteknik_api/controllers/api_v1/cart.py b/indoteknik_api/controllers/api_v1/cart.py index 2243ec0f..cb0f5a99 100644 --- a/indoteknik_api/controllers/api_v1/cart.py +++ b/indoteknik_api/controllers/api_v1/cart.py @@ -101,4 +101,17 @@ class Cart(controller.Controller): query += [('product_id', 'in', [int(x) for x in product_ids.split(',')])] cart = request.env['website.user.cart'].search(query).unlink() return self.response(cart) + + @http.route(PREFIX_USER + 'cart/select-all', auth='public', methods=['POST', 'OPTIONS'], csrf=False) + @controller.Controller.must_authorized(private=True, private_key='user_id') + def select_all_cart_by_user_id(self, user_id): + user_id = int(user_id) + + website_user_cart = request.env['website.user.cart'] + query = [('user_id', '=', user_id)] + website_user_cart.search(query).write({ + 'is_selected': True + }) + + return self.response(True)
\ No newline at end of file diff --git a/indoteknik_api/models/product_product.py b/indoteknik_api/models/product_product.py index 057b449c..78e32762 100644 --- a/indoteknik_api/models/product_product.py +++ b/indoteknik_api/models/product_product.py @@ -64,9 +64,9 @@ class ProductProduct(models.Model): price_discount = self._get_website_price_after_disc_and_tax() pricelists = { - 'tier1': self._get_pricelist_tier1, - 'tier2': self._get_pricelist_tier2, - 'tier3': self._get_pricelist_tier3, + 'tier1': self._get_pricelist_tier(1), + 'tier2': self._get_pricelist_tier(2), + 'tier3': self._get_pricelist_tier(3), } price_tier = pricelist.get_tier_name() @@ -122,33 +122,31 @@ class ProductProduct(models.Model): 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) + def _v2_get_website_price_include_tax(self): + default_pricelist_id = int(17022) - # 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), + ('pricelist_id.id', '=', default_pricelist_id), ('product_id.id', '=', self.id) ] - - pl_item2 = self.env['product.pricelist.item'].search(query, limit=1) + pl_item1 = self.env['product.pricelist.item'].search(query, limit=1) - retValue = pl_item2.price_discount + 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 _v2_get_website_price_exclude_tax(self): + default_divide_tax = float(1.11) + price_incl = self._v2_get_website_price_include_tax() + res = price_incl / default_divide_tax + return math.floor(res) + def _get_website_price_after_disc_and_tax(self): default_divide_tax = float(1.11) price_after_disc = self._get_website_price_after_disc() @@ -156,6 +154,25 @@ class ProductProduct(models.Model): res = math.ceil(res) return res + def _v2_get_website_price_after_disc_and_tax(self): + default_divide_tax = float(1.11) + price_after_disc = self._v2_get_website_price_after_disc() + res = price_after_disc / default_divide_tax + res = math.ceil(res) + return 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) + + def _v2_get_website_tax(self): + default_percent_tax = float(11) + price_after_disc = self._v2_get_website_price_after_disc_and_tax() + res = price_after_disc * default_percent_tax / 100 + return math.floor(res) + def _get_website_price_after_disc(self): discount = self._get_website_disc(0) price_incl = self._get_website_price_include_tax() @@ -166,75 +183,59 @@ class ProductProduct(models.Model): 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 + def _v2_get_website_price_after_disc(self): + discount = self._get_website_disc(0) + price_incl = self._v2_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_pricelist_tier1(self): - product_pricelist_tier1 = int(self.env['ir.config_parameter'].get_param('product.pricelist.tier1')) - default_divide_tax = float(1.11) - base_price = discount = price = 0 - pricelist_item = self.env['product.pricelist.item'].search([ - ('pricelist_id', '=', product_pricelist_tier1), - ('product_id', '=', self.id) - ], limit=1) - if pricelist_item: - # base_price = self._get_website_price_exclude_tax() - base_price_incl = self._get_website_price_include_tax() - discount = pricelist_item.price_discount - price = base_price_incl - (base_price_incl * discount / 100) - price = price / default_divide_tax - price = math.floor(price) - data = { - # 'base_price_tier1': base_price or 0, - 'discount_tier1': discount or 0, - 'price_tier1': price or 0 - } - return data - - def _get_pricelist_tier2(self): - product_pricelist_tier2 = int(self.env['ir.config_parameter'].get_param('product.pricelist.tier2')) - default_divide_tax = float(1.11) - base_price = discount = price = 0 - pricelist_item = self.env['product.pricelist.item'].search([ - ('pricelist_id', '=', product_pricelist_tier2), - ('product_id', '=', self.id) - ], limit=1) - if pricelist_item: - # base_price = self._get_website_price_exclude_tax() - base_price_incl = self._get_website_price_include_tax() - discount = pricelist_item.price_discount - price = base_price_incl - (base_price_incl * discount / 100) - price = price / default_divide_tax - price = math.floor(price) - data = { - # 'base_price_tier2': base_price or 0, - 'discount_tier2': discount or 0, - 'price_tier2': price or 0 - } - return data + 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_pricelist_tier3(self): - product_pricelist_tier3 = int(self.env['ir.config_parameter'].get_param('product.pricelist.tier3')) + def _get_pricelist_tier(self, tier_number): + config_param_name = f'product.pricelist.tier{tier_number}' + product_pricelist_tier = int(self.env['ir.config_parameter'].get_param(config_param_name)) default_divide_tax = float(1.11) base_price = discount = price = 0 pricelist_item = self.env['product.pricelist.item'].search([ - ('pricelist_id', '=', product_pricelist_tier3), + ('pricelist_id', '=', int(product_pricelist_tier)), ('product_id', '=', self.id) ], limit=1) if pricelist_item: # base_price = self._get_website_price_exclude_tax() base_price_incl = self._get_website_price_include_tax() + if tier_number in ['1_v2', '2_v2', '3_v2', '4_v2', '5_v2']: + base_price_incl = self._v2_get_website_price_include_tax() + discount = pricelist_item.price_discount price = base_price_incl - (base_price_incl * discount / 100) price = price / default_divide_tax price = math.floor(price) data = { - # 'base_price_tier3': base_price or 0, - 'discount_tier3': discount or 0, - 'price_tier3': price or 0 + f'discount_tier{tier_number}': discount or 0, + f'price_tier{tier_number}': price or 0 } return data diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 10878e32..48434845 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -95,6 +95,8 @@ 'views/cost_centre.xml', 'views/account_account_views.xml', 'views/account_move_line.xml', + 'views/sale_orders_multi_update.xml', + 'views/quotation_so_multi_update.xml', 'report/report.xml', 'report/report_banner_banner.xml', 'report/report_banner_banner2.xml', diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index f51f95af..95defed6 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -86,4 +86,6 @@ from . import cost_centre from . import account_account from . import account_move_line from . import stock_scheduler_compute -from . import promotion
\ No newline at end of file +from . import promotion +from . import sale_orders_multi_update +from . import quotation_so_multi_update
\ No newline at end of file diff --git a/indoteknik_custom/models/price_group.py b/indoteknik_custom/models/price_group.py index 50f0520f..2a1bbc91 100644 --- a/indoteknik_custom/models/price_group.py +++ b/indoteknik_custom/models/price_group.py @@ -15,6 +15,9 @@ class PriceGroup(models.Model): group3 = fields.Float(string='Kelompok 3 (%)') group4 = fields.Float(string='Kelompok 4 (%)') group5 = fields.Float(string='Kelompok 5 (%)') + group6 = fields.Float(string='Kelompok 6 (%)') + group7 = fields.Float(string='Kelompok 7 (%)') + group8 = fields.Float(string='Kelompok 8 (%)') class Manufacture(models.Model): _inherit = 'x_manufactures' @@ -25,4 +28,7 @@ class Manufacture(models.Model): ('group3', 'Kelompok 3'), ('group4', 'Kelompok 4'), ('group5', 'Kelompok 5'), + ('group6', 'Kelompok 6'), + ('group7', 'Kelompok 7'), + ('group8', 'Kelompok 8'), ], string='Pricing Group', copy=False) diff --git a/indoteknik_custom/models/product_attribute.py b/indoteknik_custom/models/product_attribute.py index 784ccd81..e3076805 100644 --- a/indoteknik_custom/models/product_attribute.py +++ b/indoteknik_custom/models/product_attribute.py @@ -5,11 +5,16 @@ import re class ProductAttributeValue(models.Model): _inherit = 'product.attribute.value' + @api.constrains('name') def _validate_name(self): - pattern = r'^[a-zA-Z0-9\[\]\(\)\.\s/%]+$' + rule_regex = self.env['ir.config_parameter'].sudo().get_param('product.product.rule_name_regex') or '' + pattern = rf'^{rule_regex}$' if not re.match(pattern, self.name): - pattern_suggest = r'[a-zA-Z0-9\[\]\(\)\.\s/%]+' + pattern_suggest = rf"{rule_regex}" suggest = ''.join(re.findall(pattern_suggest, self.name)) - raise UserError(f'Nama hanya bisa menggunakan angka, huruf kecil, huruf besar, titik, kurung lengkung, kurung siku, garis miring. Contoh: {suggest}') + raise UserError(f'Contoh yang benar adalah {suggest}') + + +
\ No newline at end of file diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index 4c11dcef..d35188b4 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -1,5 +1,5 @@ from odoo import fields, models, api -from datetime import datetime, timedelta +from datetime import datetime, timedelta, date from odoo.exceptions import UserError import logging import requests @@ -52,11 +52,30 @@ class ProductTemplate(models.Model): help='Centang jika ingin ditammpilkan di website sebagai segment Produk Baru') seq_new_product = fields.Integer(string='Seq New Product', help='Urutan Sequence New Product') is_edited = fields.Boolean(string='Is Edited') + publish = fields.Boolean(string='Publish', default=True) + + @api.constrains('active') + def constrains_active_publish(self): + if not self.active or self.type != 'product': + self.publish = False + else: + self.publish = True + + self._create_solr_queue('_sync_product_template_to_solr') + + def day_product_to_edit(self): + day_products = [] + + for product in self: + day_product = (product.write_date - product.create_date).days + day_products.append(day_product) + + return day_products @api.constrains('name', 'default_code') def _check_duplicate_product(self): for product in self: - if not self.env.user.is_purchasing_manager: + if not self.env.user.is_purchasing_manager and not self.env.user.is_editor_product: domain = [('default_code', '!=', False)] if product.product_variant_ids: @@ -76,22 +95,21 @@ class ProductTemplate(models.Model): if product.write_date == product.create_date: message = "SKU atau Name yang Anda gunakan sudah digunakan di produk lain" - else: + elif all(day_product > 0 for day_product in product.day_product_to_edit()): domain = [('id', '=', product.id)] message = "Hanya Pak Tyas yang dapat merubah data produk" - existing_purchase = self.search(domain, limit=1) - if existing_purchase: raise UserError(message) @api.constrains('name') def _validate_name(self): - pattern = r'^[a-zA-Z0-9\[\]\(\)\.\s/%-]+$' + rule_regex = self.env['ir.config_parameter'].sudo().get_param('product.product.rule_name_regex') or '' + pattern = rf'^{rule_regex}$' if not re.match(pattern, self.name): - pattern_suggest = r'[a-zA-Z0-9\[\]\(\)\.\s/%-]+' + pattern_suggest = rf"{rule_regex}" suggest = ''.join(re.findall(pattern_suggest, self.name)) - raise UserError(f'Nama hanya bisa menggunakan angka, strip, huruf kecil, huruf besar, titik, kurung lengkung, kurung siku, garis miring. Contoh: {suggest}') + raise UserError(f'Contoh yang benar adalah {suggest}') # def write(self, vals): # if 'solr_flag' not in vals and self.solr_flag == 1: @@ -175,13 +193,7 @@ class ProductTemplate(models.Model): def _compute_web_price(self): for template in self: - # product = self.env['product.product'].search([('product_tmpl_id', '=', template.id)], limit=1) - - product_pricelist_item = self.env['product.pricelist.item'].search([ - ('pricelist_id', '=', 1), - ('product_id', '=', template.product_variant_id.id)], limit=1) - price = product_pricelist_item.fixed_price - template.web_price = price + template.web_price = template.product_variant_ids[0].web_price def _have_promotion_program(self): for template in self: @@ -324,10 +336,19 @@ class ProductProduct(models.Model): sla_version = fields.Integer(string="SLA Version", default=0) is_edited = fields.Boolean(string='Is Edited') + def day_product_to_edit(self): + day_products = [] + + for product in self: + day_product = (product.write_date - product.create_date).days + day_products.append(day_product) + + return day_products + @api.constrains('name','default_code') def _check_duplicate_product(self): - if not self.env.user.is_purchasing_manager: - for product in self: + for product in self: + if not self.env.user.is_purchasing_manager and not self.env.user.is_editor_product: if product.write_date == product.create_date: domain = [ ('default_code', '!=', False), @@ -340,25 +361,20 @@ class ProductProduct(models.Model): existing_purchase = self.search(domain, limit=1) if existing_purchase: raise UserError(massage) - else: - domain = [ - ('id', '=', product.id), - ('is_edited', '=', True), - ] + elif all(day_product > 0 for day_product in product.day_product_to_edit()): + domain = [('id', '=', product.id)] existing_purchase = self.search(domain) if existing_purchase: raise UserError('Hanya Pak Tyas Yang Dapat Merubah Data Product') - if not existing_purchase: - true = True - self.is_edited = true - + @api.constrains('name') def _validate_name(self): - pattern = r'^[a-zA-Z0-9\[\]\(\)\.\s/%-]+$' + rule_regex = self.env['ir.config_parameter'].sudo().get_param('product.product.rule_name_regex') or '' + pattern = rf'^{rule_regex}$' if not re.match(pattern, self.name): - pattern_suggest = r'[a-zA-Z0-9\[\]\(\)\.\s/%-]+' + pattern_suggest = rf"{rule_regex}" suggest = ''.join(re.findall(pattern_suggest, self.name)) - raise UserError(f'Nama hanya bisa menggunakan angka, strip, huruf kecil, huruf besar, titik, kurung lengkung, kurung siku, garis miring. Contoh: {suggest}') + raise UserError(f'Contoh yang benar adalah {suggest}') def _get_qty_incoming_bandengan(self): for product in self: @@ -389,8 +405,16 @@ class ProductProduct(models.Model): def _compute_web_price(self): for product in self: - product_pricelist_item = self.env['product.pricelist.item'].search( - [('pricelist_id', '=', 1), ('product_id', '=', product.id)], limit=1) + pricelist_id = self.env.context.get('pricelist') + + domain = [('pricelist_id', '=', pricelist_id or 1), ('product_id', '=', product.id)] + product_pricelist_item = self.env['product.pricelist.item'].search(domain, limit=1) + + if product_pricelist_item.base_pricelist_id: + base_pricelist_id = product_pricelist_item.base_pricelist_id.id + domain = [('pricelist_id', '=', base_pricelist_id), ('product_id', '=', product.id)] + product_pricelist_item = self.env['product.pricelist.item'].search(domain, limit=1) + product.web_price = product_pricelist_item.fixed_price def _compute_stock_vendor(self): diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 3fb61955..8ad25228 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -46,6 +46,11 @@ class PurchaseOrder(models.Model): summary_qty_receipt = fields.Float('Summary Qty Receipt', compute='_compute_summary_qty') count_line_product = fields.Float('Total Item', compute='compute_count_line_product') note_description = fields.Char(string='Note', help='bisa diisi sebagai informasi indent barang tertentu atau apapun') + has_active_invoice = fields.Boolean(string='Has Active Invoice', compute='_compute_has_active_invoice') + + def _compute_has_active_invoice(self): + for order in self: + order.has_active_invoice = any(invoice.state != 'cancel' for invoice in order.invoice_ids) def add_product_to_pricelist(self): for line in self.order_line: @@ -195,6 +200,7 @@ class PurchaseOrder(models.Model): 'product_qty': order_line.product_qty, 'qty_available_store': qty_available, 'suggest': suggest, + 'so_line_id': order_line.id, } self.order_line.create(values) @@ -258,8 +264,6 @@ class PurchaseOrder(models.Model): self.env['po.sync.price'].create([{ 'order_line_id': line.id, }]) - - def _send_mail(self): output = io.BytesIO() @@ -325,7 +329,7 @@ class PurchaseOrder(models.Model): def re_calculate(self): for line in self.order_line: sale_order_line = self.env['sale.order.line'].search([ - ('product_id', '=', line.product_id.id), + ('id', '=', line.so_line_id.id), ('order_id', '=', line.order_id.sale_order_id.id) ], limit=1, order='price_reduce_taxexcl') for so_line in sale_order_line: @@ -340,9 +344,13 @@ class PurchaseOrder(models.Model): def compute_total_margin(self): sum_so_margin = sum_sales_price = sum_margin = 0 for line in self.order_line: - sale_order_line = self.env['sale.order.line'].search( - [('product_id', '=', line.product_id.id), - ('order_id', '=', line.order_id.sale_order_id.id)], limit=1, order='price_reduce_taxexcl') + sale_order_line = line.so_line_id + if not sale_order_line: + sale_order_line = self.env['sale.order.line'].search([ + ('product_id', '=', line.product_id.id), + ('order_id', '=', line.order_id.sale_order_id.id) + ], limit=1, order='price_reduce_taxexcl') + sum_so_margin += sale_order_line.item_margin sales_price = sale_order_line.price_reduce_taxexcl * sale_order_line.product_uom_qty if sale_order_line.order_id.shipping_cost_covered == 'indoteknik': diff --git a/indoteknik_custom/models/purchase_order_line.py b/indoteknik_custom/models/purchase_order_line.py index 39aeba0f..95e85122 100755 --- a/indoteknik_custom/models/purchase_order_line.py +++ b/indoteknik_custom/models/purchase_order_line.py @@ -29,6 +29,7 @@ class PurchaseOrderLine(models.Model): qty_available_store = fields.Float(string='Available') suggest = fields.Char(string='Suggest') price_vendor = fields.Float(string='Price Vendor', compute='compute_price_vendor') + so_line_id = fields.Many2one('sale.order.line', string='ID SO Line') def compute_price_vendor(self): for line in self: diff --git a/indoteknik_custom/models/quotation_so_multi_update.py b/indoteknik_custom/models/quotation_so_multi_update.py new file mode 100644 index 00000000..105b7963 --- /dev/null +++ b/indoteknik_custom/models/quotation_so_multi_update.py @@ -0,0 +1,22 @@ +from odoo import models, fields +import logging + +_logger = logging.getLogger(__name__) + + +class QuotationSoMultiUpdate(models.TransientModel): + _name = 'quotation.so.multi_update' + + def save_multi_update_quotation(self): + quotation_ids = self._context['quotation_ids'] + sales = self.env['sale.order'].browse(quotation_ids) + sales.action_multi_update_state() + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': 'Notification', + 'message': 'Status berhasil diubah', + 'next': {'type': 'ir.actions.act_window_close'}, + } + }
\ No newline at end of file diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 376b8e40..71163fa4 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -58,7 +58,7 @@ class SaleOrder(models.Model): ('partial_chargeback', 'Partial Chargeback'), ('authorize', 'Authorize'), ], tracking=True, string='Payment Status', help='Payment Gateway Status / Midtrans / Web, https://docs.midtrans.com/en/after-payment/status-cycle') - date_doc_kirim = fields.Datetime(string='Tanggal Kirim di SJ', help="Tanggal Kirim di cetakan SJ yang terakhir, tidak berpengaruh ke Accounting") + date_doc_kirim = fields.Datetime(string='Tanggal Kirim di SJ', help="Tanggal Kirim di cetakan SJ yang terakhir, tidak berpengaruh ke Accounting", tracking=True) payment_type = fields.Char(string='Payment Type', help='Jenis pembayaran dengan Midtrans') gross_amount = fields.Float(string='Gross Amount', help='Jumlah pembayaran yang dilakukan dengan Midtrans') notification = fields.Char(string='Notification', help='Dapat membantu error dari approval') @@ -78,8 +78,41 @@ class SaleOrder(models.Model): amount_voucher_disc = fields.Float(string='Voucher Discount') source_id = fields.Many2one('utm.source', 'Source', domain="[('id', 'in', [32, 59, 60, 61])]") estimated_arrival_days = fields.Integer('Estimated Arrival Days', default=0) + email = fields.Char(string='Email') picking_iu_id = fields.Many2one('stock.picking', 'Picking IU') + @api.model + def action_multi_update_state(self): + for sale in self: + sale.update({ + 'state': 'cancel', + }) + + if sale.state == 'cancel': + sale.update({ + 'approval_status': False, + }) + + def open_form_multi_update_status(self): + action = self.env['ir.actions.act_window']._for_xml_id('indoteknik_custom.action_sale_orders_multi_update') + action['context'] = { + 'sale_ids': [x.id for x in self] + } + return action + + def open_form_multi_update_state(self): + action = self.env['ir.actions.act_window']._for_xml_id('indoteknik_custom.action_quotation_so_multi_update') + action['context'] = { + 'quotation_ids': [x.id for x in self] + } + return action + + def action_multi_update_invoice_status(self): + for sale in self: + sale.update({ + 'invoice_status': 'invoiced', + }) + def _compute_purchase_total(self): for order in self: total = 0 @@ -173,6 +206,7 @@ class SaleOrder(models.Model): self.npwp = parent_id.npwp self.sppkp = parent_id.sppkp self.customer_type = parent_id.customer_type + self.email = parent_id.email @api.onchange('partner_id') def onchange_partner_id(self): diff --git a/indoteknik_custom/models/sale_orders_multi_update.py b/indoteknik_custom/models/sale_orders_multi_update.py new file mode 100644 index 00000000..95cfde21 --- /dev/null +++ b/indoteknik_custom/models/sale_orders_multi_update.py @@ -0,0 +1,22 @@ +from odoo import models, fields +import logging + +_logger = logging.getLogger(__name__) + + +class SaleOrdersMultiUpdate(models.TransientModel): + _name = 'sale.orders.multi_update' + + def save_multi_update_so(self): + sale_ids = self._context['sale_ids'] + sales = self.env['sale.order'].browse(sale_ids) + sales.action_multi_update_invoice_status() + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': 'Notification', + 'message': 'Invoice Status berhasil diubah', + 'next': {'type': 'ir.actions.act_window_close'}, + } + }
\ No newline at end of file diff --git a/indoteknik_custom/models/solr/__init__.py b/indoteknik_custom/models/solr/__init__.py index 16da73af..f2d13116 100644 --- a/indoteknik_custom/models/solr/__init__.py +++ b/indoteknik_custom/models/solr/__init__.py @@ -7,4 +7,5 @@ from . import product_template from . import website_categories_homepage from . import x_manufactures from . import x_banner_banner -from . import product_public_category
\ No newline at end of file +from . import product_public_category +from . import x_banner_category
\ No newline at end of file diff --git a/indoteknik_custom/models/solr/apache_solr.py b/indoteknik_custom/models/solr/apache_solr.py index eb02cb57..5acfded8 100644 --- a/indoteknik_custom/models/solr/apache_solr.py +++ b/indoteknik_custom/models/solr/apache_solr.py @@ -213,6 +213,8 @@ class ApacheSolr(models.Model): end_time = time.time() _logger.info("[SYNC_PRODUCT_TO_SOLR] Finish task add to solr. Time taken: {:.6f} seconds".format(end_time - start_time)) + return True + def _test_product_price(self, product_id=228178): product = self.env['product.product'].search([('id', '=', product_id)], limit=1) _logger.info('price incl tax: %s' % product._get_website_price_include_tax()) @@ -287,3 +289,5 @@ class ApacheSolr(models.Model): _variants_solr.add(documents) end_time = time.time() _logger.info("[SYNC_VARIANTS_TO_SOLR] Finish task add to solr. Time taken: {:.6f} seconds".format(end_time - start_time)) + + return False diff --git a/indoteknik_custom/models/solr/product_product.py b/indoteknik_custom/models/solr/product_product.py index 93e26793..41af2d0e 100644 --- a/indoteknik_custom/models/solr/product_product.py +++ b/indoteknik_custom/models/solr/product_product.py @@ -31,8 +31,6 @@ class ProductProduct(models.Model): solr_model = self.env['apache.solr'] for variant in self: - if not variant.product_tmpl_id.active and variant.product_tmpl_id.type != 'product': - continue category_id = 0 category_name = '' @@ -64,7 +62,8 @@ class ProductProduct(models.Model): 'search_rank_i': variant.product_tmpl_id.search_rank, 'search_rank_weekly_i': variant.product_tmpl_id.search_rank_weekly, 'attributes': [x.name for x in variant.product_template_attribute_value_ids], - 'has_product_info_b': True + 'has_product_info_b': True, + 'publish_b': variant.product_tmpl_id.publish, }) self.solr().add(docs=[document], softCommit=True) @@ -78,18 +77,18 @@ class ProductProduct(models.Model): for variant in self: price_excl_after_disc = price_excl = discount = tax = 0 - flashsale_data = tier1 = tier2 = tier3 = {} + flashsale_data = {} 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() + discount = variant._get_website_disc(0) 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() + + price_excl_v2 = variant._v2_get_website_price_exclude_tax() + price_excl_after_disc_v2 = variant._v2_get_website_price_after_disc_and_tax() + tax_v2 = variant._v2_get_website_tax() document = solr_model.get_doc('variants', variant.id) document.update({ @@ -106,14 +105,23 @@ class ProductProduct(models.Model): "discount_f": discount, "price_discount_f": price_excl_after_disc, "tax_f": tax, - "discount_tier1_f": tier1.get('discount_tier1', 0), - "price_tier1_f": tier1.get('price_tier1', 0), - "discount_tier2_f": tier2.get('discount_tier2', 0), - "price_tier2_f": tier2.get('price_tier2', 0), - "discount_tier3_f": tier3.get('discount_tier3', 0), - "price_tier3_f": tier3.get('price_tier3', 0), - "has_price_info_b": True + "price_v2_f": price_excl_v2, + "price_discount_v2_f": price_excl_after_disc_v2, + "tax_v2_f": tax_v2, }) + + for tier_number in [1, 2, 3, '1_v2', '2_v2', '3_v2', '4_v2', '5_v2']: + tier = variant._get_pricelist_tier(tier_number) + document.update({ + f"discount_tier{tier_number}_f": tier.get(f'discount_tier{tier_number}', 0), + f"price_tier{tier_number}_f": tier.get(f'price_tier{tier_number}', 0), + }) + + # for tier_number in [1, 2, 3, '1_v2', '2_v2', '3_v2', '4_v2', '5_v2']: + # tier = tier_data[tier_number] + + document.update({"has_price_info_b": True}) + self.solr().add(docs=[document], softCommit=True) variant.change_solr_data('Ada perubahan pada harga product') diff --git a/indoteknik_custom/models/solr/product_template.py b/indoteknik_custom/models/solr/product_template.py index ea976359..b4782d1c 100644 --- a/indoteknik_custom/models/solr/product_template.py +++ b/indoteknik_custom/models/solr/product_template.py @@ -23,9 +23,21 @@ class ProductTemplate(models.Model): 'function_name': function_name }) - @api.constrains('active') - def _create_solr_queue_sync_active(self): - self._create_solr_queue('_sync_active_template_solr') + @api.constrains('active', 'type') + def constrains_active(self): + for template in self: + template.publish = template.active and template.type == 'product' + self._create_solr_queue('_sync_product_template_to_solr') + + @api.constrains('publish') + def constrains_publish(self): + for template in self: + if template.active and template.type == 'product': + continue + template.product_variant_ids.publish = template.publish + self._create_solr_queue('_sync_product_template_to_solr') + + constrains_active._priority = 1 @api.constrains('name', 'default_code', 'weight', 'x_manufacture', 'public_categ_ids', 'search_rank', 'search_rank_weekly', 'image_1920') def _create_solr_queue_sync_product_template(self): @@ -42,25 +54,10 @@ class ProductTemplate(models.Model): product._create_solr_queue('_sync_price_to_solr') product.solr_flag = 1 - def _sync_active_template_solr(self): - for template in self: - if not template.active or template.type != 'product': - template._sync_delete_solr() - else: - template._sync_product_template_to_solr() - template._sync_price_to_solr() - - products = self.env['product.product'].search( - [('product_tmpl_id', '=', template.id), ('active', 'in', [True, False])]) - products._sync_variants_to_solr() - def _sync_product_template_to_solr(self): solr_model = self.env['apache.solr'] for template in self: - if not template.active or template.type != 'product': - continue - variant_names = ', '.join([x.display_name or '' for x in template.product_variant_ids]) variant_codes = ', '.join([x.default_code or '' for x in template.product_variant_ids]) @@ -96,10 +93,15 @@ class ProductTemplate(models.Model): "category_name": category_name, "description_t": template.website_description or '', 'has_product_info_b': True, + 'publish_b': template.publish }) self.solr().add(docs=[document], softCommit=True) - template.product_variant_ids._sync_variants_to_solr() + products = self.env['product.product'].search([ + ('product_tmpl_id', '=', template.id), + ('active', 'in', [True, False]) + ]) + products._sync_variants_to_solr() self.change_solr_data('Perubahan pada data product') if not document.get('has_price_info_b'): @@ -110,6 +112,8 @@ class ProductTemplate(models.Model): for template in self: flashsale_data = {} + price_excl = price_excl_after_disc = discount = tax = 0 + tier_data = {} for variant in template.product_variant_ids: variant_flashsale = variant._get_flashsale_price() @@ -123,9 +127,10 @@ class ProductTemplate(models.Model): price_excl_after_disc = variant._get_website_price_after_disc_and_tax() discount = variant._get_website_disc(0) tax = variant._get_website_tax() - tier1 = variant._get_pricelist_tier1() - tier2 = variant._get_pricelist_tier2() - tier3 = variant._get_pricelist_tier3() + + price_excl_v2 = variant._v2_get_website_price_exclude_tax() + price_excl_after_disc_v2 = variant._v2_get_website_price_after_disc_and_tax() + tax_v2 = variant._v2_get_website_tax() document = solr_model.get_doc('product', template.id) document.update({ @@ -142,28 +147,27 @@ class ProductTemplate(models.Model): "discount_f": discount, "price_discount_f": price_excl_after_disc, "tax_f": tax, - "discount_tier1_f": tier1.get('discount_tier1', 0), - "price_tier1_f": tier1.get('price_tier1', 0), - "discount_tier2_f": tier2.get('discount_tier2', 0), - "price_tier2_f": tier2.get('price_tier2', 0), - "discount_tier3_f": tier3.get('discount_tier3', 0), - "price_tier3_f": tier3.get('price_tier3', 0), - "has_price_info_b": True + "price_v2_f": price_excl_v2, + "price_discount_v2_f": price_excl_after_disc_v2, + "tax_v2_f": tax_v2, }) + for tier_number in [1, 2, 3, '1_v2', '2_v2', '3_v2', '4_v2', '5_v2']: + tier = variant._get_pricelist_tier(tier_number) + document.update({ + f"discount_tier{tier_number}_f": tier.get(f'discount_tier{tier_number}', 0), + f"price_tier{tier_number}_f": tier.get(f'price_tier{tier_number}', 0), + }) + + document.update({"has_price_info_b": True}) + self.solr().add(docs=[document], softCommit=True) template.product_variant_ids._sync_price_to_solr() template.change_solr_data('Ada perubahan pada harga product') if not document.get('has_product_info_b'): template._sync_product_template_to_solr() - - def _sync_delete_solr(self): - for rec in self: - self.solr().delete(rec.id) - for variant in rec.product_variant_ids: - variant._sync_delete_solr() - + def solr_results(self, detail=False): solr_model = self.env['apache.solr'] pricelist = self.env.user_pricelist diff --git a/indoteknik_custom/models/solr/x_banner_banner.py b/indoteknik_custom/models/solr/x_banner_banner.py index 5608a3d7..67739d47 100644 --- a/indoteknik_custom/models/solr/x_banner_banner.py +++ b/indoteknik_custom/models/solr/x_banner_banner.py @@ -46,8 +46,8 @@ class XBannerBanner(models.Model): 'background_color_s': banners.background_color or '', 'image_s': self.env['ir.attachment'].api_image('x_banner.banner', 'x_banner_image', banners.id), 'status_s': banners.x_status_banner or '', - 'categories': banners.x_banner_category.id or '', - 'manufactures': banners.x_relasi_manufacture.id or '', + 'category_id_i': banners.x_banner_category.id or '', + 'manufacture_id_i': banners.x_relasi_manufacture.id or '', 'group_by_week': banners.group_by_week or '', }) self.solr().add([document]) diff --git a/indoteknik_custom/models/solr/x_banner_category.py b/indoteknik_custom/models/solr/x_banner_category.py new file mode 100644 index 00000000..c73f6722 --- /dev/null +++ b/indoteknik_custom/models/solr/x_banner_category.py @@ -0,0 +1,54 @@ +from odoo import fields, models, api +from datetime import datetime + +class XBannerCategory(models.Model): + _inherit = "x_banner.category" + + last_update_solr = fields.Datetime(string='Last Update Solr') + + def update_last_update_solr(self): + self.last_update_solr = datetime.utcnow() + + def solr(self): + return self.env['apache.solr'].connect('banner_categories') + + def _create_solr_queue(self, function_name): + for rec in self: + self.env['apache.solr.queue'].create_unique({ + 'res_model': self._name, + 'res_id': rec.id, + 'function_name': function_name + }) + + @api.constrains('x_name', 'x_banner_subtitle', 'x_studio_field_KKVl4', 'banner_ids') + def _create_solr_queue_sync_banner_categories(self): + self._create_solr_queue('_sync_banner_categories_to_solr') + + def action_sync_to_solr(self): + banner_ids = self.env.context.get('active_ids', []) + banners = self.search([('id', 'in', banner_ids)]) + banners._create_solr_queue('_sync_banner_categories_to_solr') + + def _sync_banner_categories_to_solr(self): + for banners in self: + document = {} + document.update({ + 'id': banners.id, + 'display_name_s': banners.display_name, + 'name_s': banners.x_name, + 'banner_subtitle_s': banners.x_banner_subtitle or '', + 'x_studio_field_KKVl4_s': banners.x_studio_field_KKVl4 or '', + 'banners': [x.id for x in banners.banner_ids], + }) + self.solr().add([document]) + banners.update_last_update_solr() + + self.solr().commit() + + def unlink(self): + res = super(XBannerCategory, self).unlink() + for rec in self: + self.solr().delete(rec.id) + self.solr().optimize() + self.solr().commit() + return res
\ No newline at end of file diff --git a/indoteknik_custom/models/solr/x_manufactures.py b/indoteknik_custom/models/solr/x_manufactures.py index c0c321e4..375b7708 100644 --- a/indoteknik_custom/models/solr/x_manufactures.py +++ b/indoteknik_custom/models/solr/x_manufactures.py @@ -44,10 +44,11 @@ class XManufactures(models.Model): 'sequence_i': brands.sequence or '', 'negara_asal_s': brands.x_negara_asal or '', 'short_desc_s': brands.x_short_desc or '', + 'level_s': brands.x_manufacture_level or '', 'image_s': self.env['ir.attachment'].api_image('x_manufactures', 'x_logo_manufacture', brands.id), 'produk_aksesoris_sparepart_s': brands.x_produk_aksesoris_sparepart or '', - 'categories': [x.id for x in brands.category_ids], - 'banners': [x.id for x in brands.x_manufactures_banners], + 'category_ids': [x.id for x in brands.category_ids], + 'banner_ids': [x.id for x in brands.x_manufactures_banners], }) self.solr().add([document]) brands.update_last_update_solr() diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index e1564ca9..181f2a59 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -64,7 +64,7 @@ class StockPicking(models.Model): ('pengajuan1', 'Approval Finance'), ('approved', 'Approved'), ], string='Approval Return Status', readonly=True, copy=False, index=True, tracking=3, help="Approval Status untuk Return") - date_doc_kirim = fields.Datetime(string='Tanggal Kirim di SJ', help="Tanggal Kirim di cetakan SJ, tidak berpengaruh ke Accounting") + date_doc_kirim = fields.Datetime(string='Tanggal Kirim di SJ', help="Tanggal Kirim di cetakan SJ, tidak berpengaruh ke Accounting", tracking=True) note_logistic = fields.Selection([ ('hold', 'Hold by Sales'), ('not_paid', 'Customer belum bayar'), diff --git a/indoteknik_custom/models/users.py b/indoteknik_custom/models/users.py index 14fcae98..b90c0097 100644 --- a/indoteknik_custom/models/users.py +++ b/indoteknik_custom/models/users.py @@ -10,6 +10,7 @@ class Users(models.Model): is_leader = fields.Boolean(string='Leader', help='Berhak Approval SO Margin < 15 dan Approval PO') is_accounting = fields.Boolean(string='Accounting', help='Berhak Approval Internal Use') is_logistic_approver = fields.Boolean(string='Logistic Approver', help='Berhak Approval Penerimaan Barang') + is_editor_product = fields.Boolean(string='Editor Product', help='Berhak Mengedit Data Product') def notify_internal_users(self, message, title): users = self.search([('share', '=', False)]) diff --git a/indoteknik_custom/models/voucher.py b/indoteknik_custom/models/voucher.py index 4865db2f..8486fca0 100644 --- a/indoteknik_custom/models/voucher.py +++ b/indoteknik_custom/models/voucher.py @@ -218,6 +218,7 @@ class Voucher(models.Model): tnc.append('<ol>') tnc.append('<li>Voucher hanya berlaku apabila pembelian Pengguna sudah memenuhi syarat dan ketentuan yang tertera pada voucher</li>') tnc.append(f'<li>Voucher berlaku {self._res_remaining_time()} lagi</li>') + tnc.append(f'<li>Voucher tidak bisa digunakan apabila terdapat produk flash sale</li>') if len(self.voucher_line) > 0: brand_names = ', '.join([x.manufacture_id.x_name for x in self.voucher_line]) tnc.append(f'<li>Voucher berlaku untuk produk dari brand {brand_names}</li>') diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index da92f81f..e362e546 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -76,3 +76,5 @@ access_apache_solr_queue,access.apache.solr.queue,model_apache_solr_queue,,1,1,1 access_cost_centre,access.cost.centre,model_cost_centre,,1,1,1,1 access_stock_scheduler_compute,access.stock.scheduler.compute,model_stock_scheduler_compute,,1,1,1,1 access_sale_order_promotion,access.sale.order.promotion,model_sale_order_promotion,,1,1,1,1 +access_sale_orders_multi_update,access.sale.orders.multi_update,model_sale_orders_multi_update,,1,1,1,1 +access_quotation_so_multi_update,access.quotation.so.multi_update,model_quotation_so_multi_update,,1,1,1,1
\ No newline at end of file diff --git a/indoteknik_custom/views/account_move_line.xml b/indoteknik_custom/views/account_move_line.xml index 5b5f73cd..02b936f1 100644 --- a/indoteknik_custom/views/account_move_line.xml +++ b/indoteknik_custom/views/account_move_line.xml @@ -11,6 +11,7 @@ </xpath> <xpath expr="//page[@id='aml_tab']/field[@name='line_ids']/tree/field[@name='analytic_tag_ids']" position="attributes"> <attribute name="groups"/> + <attribute name="options">{'no_create': True}</attribute> </xpath> </field> </record> diff --git a/indoteknik_custom/views/apache_solr_queue.xml b/indoteknik_custom/views/apache_solr_queue.xml index 56ab2713..3861fd20 100644 --- a/indoteknik_custom/views/apache_solr_queue.xml +++ b/indoteknik_custom/views/apache_solr_queue.xml @@ -3,7 +3,7 @@ <field name="name">apache.solr.queue.tree</field> <field name="model">apache.solr.queue</field> <field name="arch" type="xml"> - <tree editable="top" default_order="execute_date desc"> + <tree editable="top" default_order="create_date desc"> <field name="display_name" readonly="1" /> <field name="res_model" readonly="1" /> <field name="res_id" readonly="1" /> diff --git a/indoteknik_custom/views/invoice_reklas.xml b/indoteknik_custom/views/invoice_reklas.xml index e807dca5..a29139ad 100644 --- a/indoteknik_custom/views/invoice_reklas.xml +++ b/indoteknik_custom/views/invoice_reklas.xml @@ -10,7 +10,7 @@ </p> <group> <field name="reklas_type"/> - <field name="reklas_id"/> + <field name="reklas_id" options="{'no_create': True}"/> <field name="pay_amt"/> </group> <footer> diff --git a/indoteknik_custom/views/price_group.xml b/indoteknik_custom/views/price_group.xml index 7ee8d422..5db8756e 100644 --- a/indoteknik_custom/views/price_group.xml +++ b/indoteknik_custom/views/price_group.xml @@ -23,6 +23,9 @@ <field name="group3"/> <field name="group4"/> <field name="group5"/> + <field name="group6"/> + <field name="group7"/> + <field name="group8"/> </tree> </field> </record> @@ -42,6 +45,9 @@ <field name="group3"/> <field name="group4"/> <field name="group5"/> + <field name="group6"/> + <field name="group7"/> + <field name="group8"/> </group> </group> </sheet> diff --git a/indoteknik_custom/views/product_template.xml b/indoteknik_custom/views/product_template.xml index a3a23101..e09fee77 100755 --- a/indoteknik_custom/views/product_template.xml +++ b/indoteknik_custom/views/product_template.xml @@ -15,6 +15,7 @@ <field name="uom_po_id" position="after"> <field name="desc_update_solr" readonly="1" /> <field name="last_update_solr" readonly="1" /> + <field name="publish" /> </field> <page name="inventory" position="after"> <page string="Marketplace" name="marketplace"> diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index 7d436c46..0ad76ae5 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -37,6 +37,7 @@ <field name="currency_id" position="after"> <field name="summary_qty_po"/> <field name="count_line_product"/> + <field name="payment_term_id"/> </field> <field name="amount_total" position="after"> <field name="total_margin"/> @@ -52,13 +53,19 @@ <field name="product_id" position="before"> <field name="line_no" attrs="{'readonly': 1}" optional="hide"/> </field> + <field name="product_id" position="attributes"> + <attribute name="options">{'no_create': True}</attribute> + </field> <field name="product_qty" position="before"> - <field name="qty_available_store"/> - <field name="suggest"/> + <field name="qty_available_store" readonly="1" /> + <field name="suggest" readonly="1" /> </field> <field name="price_unit" position="after"> <field name="price_vendor" attrs="{'readonly': 1}" optional="hide"/> </field> + <field name="price_subtotal" position="after"> + <field name="so_line_id" attrs="{'readonly': 1}" optional="hide"/> + </field> <page name="purchase_delivery_invoice" position="after"> <page name="purchase_vendor_bills" string="Vendor Bills" groups="indoteknik_custom.technical_administrator"> <group> @@ -69,11 +76,28 @@ <field name="fiscal_position_id" position="after"> <field name="note_description"/> <field name="total_so_percent_margin"/> - + <field name="has_active_invoice" invisible="1" /> + </field> + + <field name="order_line" position="attributes"> + <attribute name="attrs">{'readonly': ['|', ('state', 'in', ['done', 'cancel']), ('has_active_invoice', '=', True)]}</attribute> </field> + + <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='price_unit']" position="attributes"> + <attribute name="attrs">{'readonly': [], 'required': True}</attribute> + </xpath> + + <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='taxes_id']" position="attributes"> + <attribute name="attrs">{'readonly': []}</attribute> + </xpath> + + <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='product_qty']" position="attributes"> + <attribute name="attrs">{'readonly': [], 'required': True}</attribute> + </xpath> </field> </record> </data> + <data> <record id="rfq_order_tree_view_inherit" model="ir.ui.view"> <field name="name">Purchase</field> @@ -86,6 +110,7 @@ </field> </record> </data> + <data> <record id="purchase_order_tree_view_inherit" model="ir.ui.view"> <field name="name">Purchase</field> @@ -95,6 +120,19 @@ <field name="invoice_status" position="after"> <field name="po_status"/> <field name="note_description" optional="hide"/> + <field name="sale_order_id" optional="hide"/> + </field> + </field> + </record> + </data> + <data> + <record id="purchase_order_search_inherit" model="ir.ui.view"> + <field name="name">purchase.order.select.inherit</field> + <field name="model">purchase.order</field> + <field name="inherit_id" ref="purchase.purchase_order_view_search"/> + <field name="arch" type="xml"> + <field name="name" position="after"> + <field name="sale_order_id" string="Sale Order"/> </field> </field> </record> diff --git a/indoteknik_custom/views/quotation_so_multi_update.xml b/indoteknik_custom/views/quotation_so_multi_update.xml new file mode 100644 index 00000000..d3d310d5 --- /dev/null +++ b/indoteknik_custom/views/quotation_so_multi_update.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <data> + <record id="view_quotation_so_multi_update_form" model="ir.ui.view"> + <field name="name">Quotation Multi Update</field> + <field name="model">quotation.so.multi_update</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <span>Apakah Anda Yakin Ingin Mengubah Status Menjadi Cancel?</span> + </group> + </sheet> + <footer> + <button name="save_multi_update_quotation" string="Update" type="object" default_focus="1" class="oe_highlight"/> + <button string="Cancel" class="btn btn-secondary" special="cancel" /> + </footer> + </form> + </field> + </record> + + <record id="action_quotation_so_multi_update" model="ir.actions.act_window"> + <field name="name">Quotation Multi Update</field> + <field name="res_model">quotation.so.multi_update</field> + <field name="type">ir.actions.act_window</field> + <field name="view_mode">form</field> + <field name="view_id" ref="view_quotation_so_multi_update_form"/> + <field name="target">new</field> + </record> + </data> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 04d4b854..bc098f18 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -45,6 +45,7 @@ <field name="customer_type" attrs="{'required': ['|', ('create_date', '>', '2023-06-28'), ('create_date', '=', False)]}"/> <field name="npwp" placeholder='99.999.999.9-999.999' attrs="{'required': ['|', ('create_date', '>', '2023-06-28'), ('create_date', '=', False)]}"/> <field name="sppkp" attrs="{'invisible': [('customer_type','!=','pkp')], 'required': [('customer_type', '=', 'pkp')]}"/> + <field name="email" attrs="{'required': [('create_date', '>', '2023-09-28')]}"/> <field name="due_id" readonly="1"/> <field name="source_id" domain="[('id', 'in', [32, 59, 60, 61])]" attrs="{'required':[('create_date', '>', '2023-09-10')]}"/> </field> @@ -61,7 +62,7 @@ </field> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']" position="attributes"> <attribute name="attrs"> - {'readonly': ['|', ('applied_voucher_id', '!=', False), ('state', 'in', ('done','cancel'))]} + {'readonly': [('state', 'in', ('done','cancel'))]} </attribute> </xpath> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='price_unit']" position="attributes"> @@ -96,6 +97,9 @@ <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"/> </xpath> + <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='product_id']" position="attributes"> + <attribute name="options">{'no_create': True}</attribute> + </xpath> <field name="amount_total" position="after"> <field name="grand_total"/> <label for="amount_voucher_disc" string="Voucher" /> @@ -182,5 +186,22 @@ </field> </field> </record> + + <record id="sale_order_multi_update_ir_actions_server" model="ir.actions.server"> + <field name="name">Mark As Cancel</field> + <field name="model_id" ref="sale.model_sale_order"/> + <field name="binding_model_id" ref="sale.model_sale_order"/> + <field name="binding_view_types">form,list</field> + <field name="state">code</field> + <field name="code">action = records.open_form_multi_update_state()</field> + </record> + + <record id="sale_order_update_multi_actions_server" model="ir.actions.server"> + <field name="name">Mark As Completed</field> + <field name="model_id" ref="sale.model_sale_order"/> + <field name="binding_model_id" ref="sale.model_sale_order"/> + <field name="state">code</field> + <field name="code">action = records.open_form_multi_update_status()</field> + </record> </data> </odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/sale_orders_multi_update.xml b/indoteknik_custom/views/sale_orders_multi_update.xml new file mode 100644 index 00000000..7f8d6a04 --- /dev/null +++ b/indoteknik_custom/views/sale_orders_multi_update.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <data> + <record id="view_sale_orders_multi_update_form" model="ir.ui.view"> + <field name="name">Sale Orders Multi Update</field> + <field name="model">sale.orders.multi_update</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <span>Apakah Anda Yakin Ingin Mengubah Invoice Status?</span> + </group> + </sheet> + <footer> + <button name="save_multi_update_so" string="Multi Update" type="object" default_focus="1" class="oe_highlight"/> + <button string="Cancel" class="btn btn-secondary" special="cancel" /> + </footer> + </form> + </field> + </record> + + <record id="action_sale_orders_multi_update" model="ir.actions.act_window"> + <field name="name">Sale Orders Multi Update</field> + <field name="res_model">sale.orders.multi_update</field> + <field name="type">ir.actions.act_window</field> + <field name="view_mode">form</field> + <field name="view_id" ref="view_sale_orders_multi_update_form"/> + <field name="target">new</field> + </record> + </data> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/users.xml b/indoteknik_custom/views/users.xml index 25e7f90c..d67b4474 100644 --- a/indoteknik_custom/views/users.xml +++ b/indoteknik_custom/views/users.xml @@ -12,6 +12,7 @@ <field name="is_sales_manager"/> <field name="is_leader"/> <field name="is_logistic_approver"/> + <field name="is_editor_product"/> </field> </field> </record> diff --git a/indoteknik_custom/views/voucher.xml b/indoteknik_custom/views/voucher.xml index 97634d7d..a2f5557a 100755 --- a/indoteknik_custom/views/voucher.xml +++ b/indoteknik_custom/views/voucher.xml @@ -39,7 +39,7 @@ </group> <group string="Discount Settings" attrs="{'invisible': [('apply_type', '!=', 'all')]}"> <field name="min_purchase_amount" widget="monetary" required="1" /> - <field name="discount_type" required="1" /> + <field name="discount_type" attrs="{'invisible': [('apply_type','!=','all')], 'required': [('apply_type', '=', 'all')]}" /> <label for="max_discount_amount" string="Discount Amount" /> <div class="d-flex align-items-center"> diff --git a/indoteknik_custom/views/x_banner_banner.xml b/indoteknik_custom/views/x_banner_banner.xml index be9ae951..c90e718b 100755 --- a/indoteknik_custom/views/x_banner_banner.xml +++ b/indoteknik_custom/views/x_banner_banner.xml @@ -31,7 +31,7 @@ <field name="x_status_banner" /> <field name="sequence" /> <field name="group_by_week" /> - <field name="last_update_solr" /> + <field name="last_update_solr" readonly="1"/> </group> <group> <field name="background_color" /> diff --git a/indoteknik_custom/views/x_banner_category.xml b/indoteknik_custom/views/x_banner_category.xml index 45ad7940..11feb207 100755 --- a/indoteknik_custom/views/x_banner_category.xml +++ b/indoteknik_custom/views/x_banner_category.xml @@ -24,6 +24,7 @@ <field name="x_name"/> <field name="x_banner_subtitle"/> <field name="x_studio_field_KKVl4"/> + <field name="last_update_solr" readonly="1"/> </group> <group></group> </group> @@ -49,6 +50,14 @@ </field> </record> + <record id="ir_actions_server_x_banner_category_sync_to_solr" model="ir.actions.server"> + <field name="name">Sync to solr</field> + <field name="model_id" ref="indoteknik_custom.model_x_banner_category"/> + <field name="binding_model_id" ref="indoteknik_custom.model_x_banner_category"/> + <field name="state">code</field> + <field name="code">model.action_sync_to_solr()</field> + </record> + <menuitem id="menu_banner_category" name="Banner Category" |
