diff options
| author | Azka Nathan <darizkyfaz@gmail.com> | 2024-02-28 14:07:47 +0700 |
|---|---|---|
| committer | Azka Nathan <darizkyfaz@gmail.com> | 2024-02-28 14:07:47 +0700 |
| commit | 00b6739e4f4228c1cc66de0ef63312bc633ae21f (patch) | |
| tree | 85f8fc83d4030878893599abb2a949e5d478e3e7 | |
| parent | 0738a192409687790c16c757f85fe440cb1f377d (diff) | |
| parent | 46a7cc5601ceab2a7a6cdf4d74e0fa26ce13ab8a (diff) | |
Merge branch 'production' into purchasing-job
44 files changed, 742 insertions, 161 deletions
diff --git a/indoteknik_api/controllers/__init__.py b/indoteknik_api/controllers/__init__.py index 237f4135..34bba89f 100644 --- a/indoteknik_api/controllers/__init__.py +++ b/indoteknik_api/controllers/__init__.py @@ -1,4 +1,5 @@ from . import controller +from . import export from . import api_v1 from . import api_v2 from . import api_v3
\ No newline at end of file diff --git a/indoteknik_api/controllers/api_v1/cart.py b/indoteknik_api/controllers/api_v1/cart.py index 907c8288..f472a9b0 100644 --- a/indoteknik_api/controllers/api_v1/cart.py +++ b/indoteknik_api/controllers/api_v1/cart.py @@ -44,6 +44,7 @@ class Cart(controller.Controller): qty = int(kw.get('qty', 0)) source = kw.get('source') + qty_append = kw.get('qty_append', False) is_selected = kw.get('selected', False) is_selected = is_selected in ('true', True) @@ -52,6 +53,9 @@ class Cart(controller.Controller): if not user_id: return self.response(code=400, description='user_id is required') + if not product_id and not program_line_id: + return self.response(code=400, description='product_id or program_line_id is required') + website_user_cart = request.env['website.user.cart'] # Remove previous 'buy' entries for the user @@ -68,32 +72,36 @@ class Cart(controller.Controller): cart = website_user_cart.search(query, limit=1) data_to_update = { + 'user_id': user_id, 'qty': qty, 'is_selected': is_selected, 'program_line_id': program_line_id, - 'product_id': product_id + 'product_id': product_id, + 'source': source or False } + + if isinstance(qty_append, str) and qty_append.lower() == "true" and cart: + data_to_update['qty'] += cart.qty - if program_line_id: - data_to_update['product_id'] = False - - if source: - data_to_update['source'] = source - - result = {} if cart: - # Update existing cart entry cart.write(data_to_update) - result['id'] = cart.id else: - # Create a new cart entry if it doesn't exist - create = website_user_cart.create({ - 'user_id': user_id, - **data_to_update - }) - result['id'] = create.id + cart = website_user_cart.create(data_to_update) - return self.response(result) + return self.response({ + 'id': cart.id, + 'product': { + 'id': cart.product_id.id, + 'name': cart.product_id.name + } if cart.product_id else None, + 'program_line': { + 'id': cart.program_line_id.id, + 'name': cart.program_line_id.name + } if cart.program_line_id else None, + 'qty': cart.qty, + 'is_selected': cart.is_selected, + 'source': cart.source + }) @http.route(PREFIX_USER + 'cart', auth='public', methods=['DELETE', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized() diff --git a/indoteknik_api/controllers/api_v1/voucher.py b/indoteknik_api/controllers/api_v1/voucher.py index 3c056ecd..53f118ec 100644 --- a/indoteknik_api/controllers/api_v1/voucher.py +++ b/indoteknik_api/controllers/api_v1/voucher.py @@ -1,31 +1,39 @@ -from .. import controller +from bs4 import BeautifulSoup from odoo import http from odoo.http import request -from bs4 import BeautifulSoup + +from .. import controller class Voucher(controller.Controller): - prefix = '/api/v1/' + PREFIX_API = '/api/v1/' + + @http.route(PREFIX_API + 'voucher', auth='public', methods=['GET', 'OPTIONS']) + @controller.Controller.must_authorized() + def get_vouchers(self, **kw): + vouchers = request.env['voucher'].get_active_voucher([('visibility', 'in', ['public'])]) + vouchers = vouchers.res_format() + return self.response(vouchers) - @http.route(prefix + 'user/<user_id>/voucher', auth='public', methods=['GET', 'OPTIONS']) + @http.route(PREFIX_API + 'user/<user_id>/voucher', auth='public', methods=['GET', 'OPTIONS']) @controller.Controller.must_authorized(private=True, private_key='user_id') - def get_vouchers(self, **kw): + def get_vouchers_by_user_id(self, **kw): cart = request.env['website.user.cart'] code = kw.get('code') user_id = int(kw.get('user_id', 0)) source = kw.get('source') visibility = ['public'] - parameter = [] + domain = [] if code: visibility.append('private') - parameter += [('code', '=', code)] + domain += [('code', '=', code)] user_pricelist = request.env.context.get('user_pricelist') if user_pricelist: - parameter += [('excl_pricelist_ids', 'not in', [user_pricelist.id])] + domain += [('excl_pricelist_ids', 'not in', [user_pricelist.id])] - parameter += [('visibility', 'in', visibility)] - vouchers = request.env['voucher'].get_active_voucher(parameter) + domain += [('visibility', 'in', visibility)] + vouchers = request.env['voucher'].get_active_voucher(domain) checkout = cart.get_user_checkout(user_id, source=source) products = checkout['products'] @@ -35,6 +43,7 @@ class Voucher(controller.Controller): order_line = [] for product in products: + if product['cart_type'] == 'promotion': continue order_line.append({ 'product_id': request.env['product.product'].browse(product['id']), 'price': product['price']['price'], diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py index 50e86b68..c4f323fe 100644 --- a/indoteknik_api/controllers/controller.py +++ b/indoteknik_api/controllers/controller.py @@ -193,8 +193,11 @@ class Controller(http.Controller): if model_name in ['product.template']: version = '1' if field in ['image_256', 'image_512', 'image_1024', 'image_1920'] else '2' ratio = kw.get('ratio', '') + variant = kw.get('variant', False) + image = model['image_256'] or '' - image = self.add_watermark_to_image(image, ratio, version) + if not variant: + image = self.add_watermark_to_image(image, ratio, version) response_headers = [ ('Content-Type', 'image/jpg'), @@ -210,7 +213,12 @@ class Controller(http.Controller): def add_watermark_to_image(self, image, ratio, version = '1'): if not image: return '' - logo_path = get_module_resource('indoteknik_api', 'static', 'src', 'images', 'logo-indoteknik-gray.png') + LOGO_FILENAME = { + '1': 'logo-indoteknik-gray.png', + '2': 'logo-indoteknik.png' + } + + logo_path = get_module_resource('indoteknik_api', 'static', 'src', 'images', LOGO_FILENAME.get(version)) logo_img = Image.open(logo_path).convert('RGBA') img_data = io.BytesIO(base64.b64decode(image)) @@ -238,13 +246,15 @@ class Controller(http.Controller): logo_footer_img = Image.open(logo__footer_path).convert('RGBA') logo_footer_img.thumbnail((img_width, img_height // 1)) logo_footer_w, logo_footer_h = logo_footer_img.size - new_img.paste(logo_footer_img, (0, img_height - logo_footer_h - 20), logo_footer_img) + new_img.paste(logo_footer_img, (0, img_height - logo_footer_h), logo_footer_img) + + logo_img_w = img_width // 1.8 + logo_img_h = img_height // 1.8 logo_img.thumbnail((logo_img_w, logo_img_h)) - if version == '1': - # Add watermark - new_img.paste(logo_img, (12, 10), logo_img) + # Add watermark + new_img.paste(logo_img, (12, 10), logo_img) buffered = io.BytesIO() new_img.save(buffered, format="PNG") diff --git a/indoteknik_api/controllers/export.py b/indoteknik_api/controllers/export.py new file mode 100644 index 00000000..c29c82c7 --- /dev/null +++ b/indoteknik_api/controllers/export.py @@ -0,0 +1,46 @@ +import json + +from odoo.tools import pycompat +from odoo.exceptions import Warning +from odoo import http +from odoo.http import request +from odoo.addons.web.controllers.main import ExportFormat, GroupExportXlsxWriter, ExportXlsxWriter, serialize_exception, clean_action + +class Export(ExportFormat, http.Controller): + @http.route('/web/export/xlsx', type='http', auth="public", csrf=False) + @serialize_exception + def export_xlsx(self, data, token, **kw): + data_obj = json.loads(data) + model = data_obj['model'] + can_export = request.env.user.check_access(model, 'export') + + if not can_export: + raise Warning('You are not allowed to export') + + return self.base(data, token) + + @property + def content_type(self): + return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + + def filename(self, base): + return base + '.xlsx' + + def from_group_data(self, fields, groups): + with GroupExportXlsxWriter(fields, groups.count) as xlsx_writer: + x, y = 1, 0 + for group_name, group in groups.children.items(): + x, y = xlsx_writer.write_group(x, y, group_name, group) + + return xlsx_writer.value + + def from_data(self, fields, rows): + with ExportXlsxWriter(fields, len(rows)) as xlsx_writer: + for row_index, row in enumerate(rows): + for cell_index, cell_value in enumerate(row): + if isinstance(cell_value, (list, tuple)): + cell_value = pycompat.to_text(cell_value) + xlsx_writer.write_cell(row_index + 1, cell_index, cell_value) + + return xlsx_writer.value +
\ No newline at end of file diff --git a/indoteknik_api/models/product_pricelist.py b/indoteknik_api/models/product_pricelist.py index f05fa82d..0d4247c8 100644 --- a/indoteknik_api/models/product_pricelist.py +++ b/indoteknik_api/models/product_pricelist.py @@ -92,7 +92,7 @@ class ProductPricelist(models.Model): ('is_flash_sale', '=', True), ('start_date', '<=', current_time), ('end_date', '>=', current_time) - ], limit=1) + ], limit=1, order='start_date asc') return pricelist def is_flash_sale_product(self, product_id: int): diff --git a/indoteknik_api/models/product_product.py b/indoteknik_api/models/product_product.py index 1db58d8e..3ecad627 100644 --- a/indoteknik_api/models/product_product.py +++ b/indoteknik_api/models/product_product.py @@ -278,12 +278,19 @@ class ProductProduct(models.Model): discount = 0 price_flashsale = 0 + default_divide_tax = float(1.11) + default_tax = float(11) if item.price_discount > 0: discount = item.price_discount price_flashsale = base_price - (base_price * discount // 100) + price_flashsale = price_flashsale / default_divide_tax elif item.fixed_price > 0: price_flashsale = item.fixed_price # ask darren for include or exclude - discount = (base_price - price_flashsale) // base_price * 100 + price_flashsale = price_flashsale + (price_flashsale * default_tax / 100) + discount = (base_price - price_flashsale) * 100 / base_price + discount = (math.ceil(discount*100)/100) + price_flashsale = item.fixed_price + # price_flashsale = price_flashsale / default_divide_tax # darren must fill the fixed price with price exclude if price_for == 'odoo': base_price = self._v2_get_website_price_exclude_tax() diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 333596a3..fe6955fd 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -77,6 +77,8 @@ 'views/brand_vendor.xml', 'views/promotion/promotion_program.xml', 'views/promotion/promotion_program_line.xml', + 'views/promotion/promotion_product.xml', + 'views/promotion/promotion_monitoring.xml', 'views/requisition.xml', 'views/landedcost.xml', 'views/product_sla.xml', @@ -113,6 +115,9 @@ 'views/po_multi_cancel.xml', 'views/logbook_sj.xml', 'views/report_logbook_sj.xml', + 'views/role_permission/ir_model_access.xml', + 'views/role_permission/res_groups.xml', + 'views/cust_commision.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 720a4f91..9d8b9bea 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -106,3 +106,6 @@ from . import stock_quant from . import po_multi_cancel from . import logbook_sj from . import report_logbook_sj +from . import role_permission +from . import cust_commision +from . import report_stock_forecasted diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index a9db212f..7eb65e9f 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -122,7 +122,7 @@ class AccountMove(models.Model): sum_qty_invoice = sum_qty_order = 0 for line in purchase_order.order_line: sum_qty_invoice += line.qty_invoiced - sum_qty_order += line.product_uom_qty + sum_qty_order += line.product_qty if sum_qty_invoice > sum_qty_order: raise UserError('Error Qty Invoice akan lebih besar dari Qty Order jika lanjut Posting') diff --git a/indoteknik_custom/models/base_import_import.py b/indoteknik_custom/models/base_import_import.py index 6a100cb8..01e02a4a 100644 --- a/indoteknik_custom/models/base_import_import.py +++ b/indoteknik_custom/models/base_import_import.py @@ -56,7 +56,10 @@ class Import(models.TransientModel): raise UserError(message) def do(self, fields, columns, options, dryrun=False): - enable_import = self._check_enable_import() - if not enable_import: - self._unable_import_notif() + model = self.res_model + can_import = self.env.user.check_access(model, 'import') + + if not can_import: + raise UserError('You are not allowed to import') + return super(Import, self).do(fields, columns, options, dryrun) diff --git a/indoteknik_custom/models/commision.py b/indoteknik_custom/models/commision.py index 955d1634..094aa66e 100644 --- a/indoteknik_custom/models/commision.py +++ b/indoteknik_custom/models/commision.py @@ -156,7 +156,17 @@ class CustomerCommision(models.Model): # add status for type of commision, fee, rebate / cashback # include child or not? - @api.constrains('commision_percent') + @api.constrains('partner_ids') + def _onchange_partner_ids(self): + commision = self.env['cust.commision'].search([ + ('partner_id', 'in', [rec.id for rec in self.partner_ids]), + ]) + + if commision: + max_commision = max(commision.mapped('commision_percent')) + self.commision_percent = max_commision + + @api.constrains('commision_percent', 'partner_ids') def _onchange_commision_percent(self): print('masuk onchange commision percent') if self.commision_amt == 0: @@ -165,8 +175,8 @@ class CustomerCommision(models.Model): @api.constrains('commision_amt') def _onchange_commision_amt(self): print('masuk onchange commision amt') - if self.commision_percent == 0: - self.commision_percent = (self.commision_amt / self.total_dpp * 100) + if self.total_dpp > 0: + self.commision_percent = (self.commision_amt / self.total_dpp) * 100 def _compute_total_dpp(self): for data in self: @@ -208,6 +218,9 @@ class CustomerCommision(models.Model): else: self._generate_customer_commision_rebate() + self._onchange_commision_percent() + self._onchange_commision_amt() + def _generate_customer_commision_rebate(self): for rec in self: # partners = rec.partner_ids.child_ids + rec.partner_ids diff --git a/indoteknik_custom/models/cust_commision.py b/indoteknik_custom/models/cust_commision.py new file mode 100644 index 00000000..eeb255cd --- /dev/null +++ b/indoteknik_custom/models/cust_commision.py @@ -0,0 +1,25 @@ +from odoo import models, api, fields +from odoo.exceptions import UserError +from datetime import datetime +import logging + +_logger = logging.getLogger(__name__) + + +class CustCommision(models.Model): + _name = 'cust.commision' + _order = 'id desc' + + partner_id = fields.Many2one('res.partner', String='Customer', required=True) + commision_percent = fields.Float(string='Commision %', tracking=3) + + @api.constrains('partner_id') + def _check_partner_id(self): + for rec in self: + duplicate_partner = self.search([ + ('partner_id', '=', rec.partner_id.id), + ('id', '!=', rec.id) + ]) + if duplicate_partner: + raise UserError('Partner already exists') +
\ No newline at end of file diff --git a/indoteknik_custom/models/logbook_sj.py b/indoteknik_custom/models/logbook_sj.py index 567f1ae3..bf4acd14 100644 --- a/indoteknik_custom/models/logbook_sj.py +++ b/indoteknik_custom/models/logbook_sj.py @@ -18,31 +18,27 @@ class LogbookSJ(models.TransientModel): current_time = datetime.utcnow() report_logbook_ids = [] + parameters_header = { + 'date': current_time, + } + + report_logbook = self.env['report.logbook.sj'].create([parameters_header]) for line in logbook_line: - nomor_sj = line.name - picking = self.env['stock.picking'].search([ - ('picking_code', '=', nomor_sj), - ]) - parameters_header = { - 'name': nomor_sj, - 'date': current_time, - 'name_picking': picking.name, - 'partner_id': picking.partner_id.id, + picking = self.env['stock.picking'].search([('picking_code', '=', line.name)], limit=1) + stock = picking + + data = { + 'picking_id': stock.id, + 'name': stock.name, + 'driver_id': stock.driver_id.id, + 'departure_date': stock.driver_departure_date, + 'arrival_date': stock.driver_arrival_date, + 'carrier_id': stock.carrier_id.id, + 'tracking_no': stock.delivery_tracking_no, + 'partner_id': stock.partner_id.id, + 'report_logbook_sj_id': report_logbook.id } - - report_logbook = self.env['report.logbook.sj'].create([parameters_header]) - - - for stock in picking.move_line_ids_without_package: - data = { - 'product_id': stock.product_id.id, - 'location_id': stock.location_id.id, - 'product_uom_qty': stock.product_uom_qty, - 'qty_done': stock.qty_done, - 'product_uom_id': stock.product_uom_id.id, - 'report_logbook_sj_id': report_logbook.id - } - self.env['report.logbook.sj.line'].create([data]) + self.env['report.logbook.sj.line'].create([data]) report_logbook_ids.append(report_logbook.id) line.unlink() @@ -68,6 +64,7 @@ class LogbookSJLine(models.TransientModel): tracking_no = fields.Char(string='Tracking No') logbook_sj_id = fields.Many2one('logbook.sj', string='Logbook SJ') partner_id = fields.Many2one('res.partner', string='Customer') + picking_id = fields.Many2one('res.partner', string='Customer') @api.onchange('name') def onchange_name(self): @@ -94,6 +91,8 @@ class LogbookSJLine(models.TransientModel): self.partner_id = picking.partner_id + self.picking_id = picking.id + delivery_type = self.get_delivery_type(picking.driver_departure_date, picking.driver_arrival_date) if delivery_type != 'departure': self.departure_date = picking.driver_departure_date.astimezone(timezone('Asia/Jakarta')).strftime('%Y-%m-%d %H:%M:%S') diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index d2fa793a..4bab2cad 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -74,34 +74,27 @@ class ProductTemplate(models.Model): @api.constrains('name', 'default_code') def _check_duplicate_product(self): for product in self: - if self.env.user.is_purchasing_manager or self.env.user.is_editor_product or self.env.user.id in [1, 25]: - continue - - domain = [('default_code', '!=', False)] + variants = product.product_variant_ids + names = [x.name for x in variants] if variants else [product.name] + default_codes = [x.default_code for x in variants] if variants else [product.default_code] - if product.product_variant_ids: - domain.extend([ - '|', - ('name', 'in', [variants.name for variants in product.product_variant_ids]), - ('default_code', 'in', [variants.default_code for variants in product.product_variant_ids]) - ]) - else: - domain.extend([ - '|', - ('name', 'in', [product.name]), - ('default_code', 'in', [product.default_code]) - ]) + domain = [ + ('default_code', '!=', False), + ('id', '!=', product.id), + '|', + ('name', 'in', names), + ('default_code', 'in', default_codes) + ] + + product_exist = self.search(domain, limit=1) + if len(product_exist) > 0: + raise UserError('Name atau Internal Reference sudah digunakan pada produk lain') - domain.append(('id', '!=', product.id)) + if self.env.user.is_purchasing_manager or self.env.user.is_editor_product or self.env.user.id in [1, 25]: + continue - if product.write_date == product.create_date: - message = "SKU atau Name yang Anda gunakan sudah digunakan di produk lain" - elif all(day_product > 0 for day_product in product.day_product_to_edit()): - domain = [('id', '=', product.id)] - message = "Anda tidak berhak merubah data produk ini" - existing_purchase = self.search(domain, limit=1) - if existing_purchase: - raise UserError(message) + if sum(product.day_product_to_edit()) > 0: + raise UserError('Produk ini tidak dapat diubah') @api.constrains('name') def _validate_name(self): @@ -382,30 +375,6 @@ class ProductProduct(models.Model): day_products.append(day_product) return day_products - - @api.constrains('name','default_code') - def _check_duplicate_product(self): - for product in self: - if self.env.user.is_purchasing_manager or self.env.user.is_editor_product or self.env.user.id in [1, 25]: - continue - - if product.write_date == product.create_date: - domain = [ - ('default_code', '!=', False), - '|', - ('name', 'in', [template.name for template in product.product_tmpl_id] or [product.name]), - ('default_code', 'in', [template.default_code for template in product.product_tmpl_id] or [product.default_code])] - - domain.append(('id', '!=', product.id)) - massage="SKU atau Name yang anda pakai sudah digunakan di product lain" - existing_purchase = self.search(domain, limit=1) - if existing_purchase: - raise UserError(massage) - 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('Anda tidak berhak merubah data product ini') @api.constrains('name') def _validate_name(self): diff --git a/indoteknik_custom/models/promotion/__init__.py b/indoteknik_custom/models/promotion/__init__.py index 1e15d714..82628d31 100644 --- a/indoteknik_custom/models/promotion/__init__.py +++ b/indoteknik_custom/models/promotion/__init__.py @@ -5,4 +5,5 @@ from . import promotion_free_product from . import sale_order_promotion from . import sale_order_line from . import sale_order -from . import promotion_keyword
\ No newline at end of file +from . import promotion_keyword +from . import promotion_monitoring
\ No newline at end of file diff --git a/indoteknik_custom/models/promotion/promotion_free_product.py b/indoteknik_custom/models/promotion/promotion_free_product.py index c5055562..e91d5137 100644 --- a/indoteknik_custom/models/promotion/promotion_free_product.py +++ b/indoteknik_custom/models/promotion/promotion_free_product.py @@ -17,6 +17,10 @@ class PromotionFreeProduct(models.Model): weight = rec.product_id.weight or 0 result.append({ 'id': rec.product_id.id, + 'parent': { + 'id': rec.product_id.product_tmpl_id.id, + 'name': rec.product_id.product_tmpl_id.name, + }, 'image': ir_attachment.api_image('product.template', 'image_256', rec.product_id.product_tmpl_id.id), 'display_name': rec.product_id.display_name, 'name': rec.product_id.name, diff --git a/indoteknik_custom/models/promotion/promotion_monitoring.py b/indoteknik_custom/models/promotion/promotion_monitoring.py new file mode 100644 index 00000000..9df0825d --- /dev/null +++ b/indoteknik_custom/models/promotion/promotion_monitoring.py @@ -0,0 +1,45 @@ +from odoo import fields, models, tools + + +class PromotionMonitoring(models.Model): + _name = "promotion.monitoring" + _auto = False + _rec_name = "product_id" + + product_id = fields.Many2one(comodel_name="product.product", string="Product") + manufacture_id = fields.Many2one(comodel_name="x_manufactures", string="Manufacture", related="product_id.x_manufacture") + price = fields.Float(string="Price", help="Computed Price di Product Pricelist (Tier 1 New)") + has_promo = fields.Boolean(string="Has Promo") + count_active = fields.Integer(string="Count Active") + count_inactive = fields.Integer(string="Count Inactive") + + def init(self): + tools.drop_view_if_exists(self.env.cr, self._table) + sql = { + 'count_active': "COUNT(CASE WHEN ppl.active = True THEN ppl.id ELSE NULL END)", + 'count_inactive': "COUNT(CASE WHEN ppl.active = False THEN ppl.id ELSE NULL END)" + } + self.env.cr.execute(""" + CREATE OR REPLACE VIEW {table} AS ( + SELECT + p.id as id, + p.id as product_id, + ppi.computed_price as price, + ({count_active} > 0) as has_promo, + {count_active} as count_active, + {count_inactive} as count_inactive + FROM product_product p + LEFT JOIN product_template pt ON pt.id = p.product_tmpl_id + LEFT JOIN promotion_product pp ON pp.product_id = p.id + LEFT JOIN promotion_program_line ppl ON ppl.id = pp.program_line_id + LEFT JOIN product_pricelist_item ppi ON ppi.product_id = p.id + WHERE p.active = True + AND pt.sale_ok = True + AND ppi.pricelist_id = 17023 + GROUP BY p.id, ppi.id + ) + """.format( + table=self._table, + count_active=sql['count_active'], + count_inactive=sql['count_inactive'] + ))
\ No newline at end of file diff --git a/indoteknik_custom/models/promotion/promotion_product.py b/indoteknik_custom/models/promotion/promotion_product.py index 2fad0f0d..ae26e888 100644 --- a/indoteknik_custom/models/promotion/promotion_product.py +++ b/indoteknik_custom/models/promotion/promotion_product.py @@ -17,6 +17,10 @@ class PromotionProduct(models.Model): weight = rec.product_id.weight or 0 result.append({ 'id': rec.product_id.id, + 'parent': { + 'id': rec.product_id.product_tmpl_id.id, + 'name': rec.product_id.product_tmpl_id.name, + }, 'image': ir_attachment.api_image('product.template', 'image_256', rec.product_id.product_tmpl_id.id), 'display_name': rec.product_id.display_name, 'name': rec.product_id.name, diff --git a/indoteknik_custom/models/promotion/promotion_program_line.py b/indoteknik_custom/models/promotion/promotion_program_line.py index 18a7e184..cb231889 100644 --- a/indoteknik_custom/models/promotion/promotion_program_line.py +++ b/indoteknik_custom/models/promotion/promotion_program_line.py @@ -30,6 +30,8 @@ class PromotionProgramLine(models.Model): discount_amount = fields.Float('Discount Amount') order_promotion_ids = fields.One2many('sale.order.promotion', 'program_line_id', 'Promotions') + active = fields.Boolean(string="Active", default=True) + solr_flag = fields.Integer(string="Solr Flag", default=1) def get_active_promotions(self, product_id): current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') @@ -74,6 +76,9 @@ class PromotionProgramLine(models.Model): } def _get_remaining_time(self): + if not self.program_id.end_time: + return 0 + calculate_time = self.program_id.end_time - datetime.now() return round(calculate_time.total_seconds()) @@ -93,9 +98,7 @@ class PromotionProgramLine(models.Model): free_products = self.free_product_ids.formats(purchase_qty=qty) merged_products = products + free_products - weight = 0 - if not any(x['package_weight'] == 0 for x in merged_products): - weight = sum(x['package_weight'] for x in merged_products) + weight = sum(x['package_weight'] for x in merged_products) # Sum of products and free products in 1 package quantity products_total = sum(x['price']['price_discount'] * x['qty'] / qty for x in products) diff --git a/indoteknik_custom/models/purchase_pricelist.py b/indoteknik_custom/models/purchase_pricelist.py index 67b22e4c..d9c9a51d 100755 --- a/indoteknik_custom/models/purchase_pricelist.py +++ b/indoteknik_custom/models/purchase_pricelist.py @@ -17,7 +17,7 @@ class PurchasePricelist(models.Model): count_trx_po = fields.Integer(string='Count Trx Product') count_trx_po_vendor = fields.Integer(string='Count Trx Vendor') taxes_product_id = fields.Many2one('account.tax', string='Taxes Human', domain=[('type_tax_use', '=', 'purchase')]) - taxes_system_id = fields.Many2one('account.tax', string='Taxes System', readonly=True) + taxes_system_id = fields.Many2one('account.tax', string='Taxes System') include_price = fields.Float(string='Final Price', readonly=True) @api.depends('product_id', 'vendor_id') def _compute_name(self): diff --git a/indoteknik_custom/models/report_logbook_sj.py b/indoteknik_custom/models/report_logbook_sj.py index d2008608..5ff56c9a 100644 --- a/indoteknik_custom/models/report_logbook_sj.py +++ b/indoteknik_custom/models/report_logbook_sj.py @@ -6,29 +6,59 @@ from datetime import datetime class ReportLogbookSJ(models.Model): _name = 'report.logbook.sj' - name = fields.Char(string='Nomor SJ', default='Logbook SJ') - date = fields.Datetime(string='Date') - name_picking = fields.Char(string='Picking Name') - partner_id = fields.Many2one('res.partner', string='Customer') + name = fields.Char(string='Name', default='Logbook SJ') + date = fields.Datetime(string='Date Created') + date_approve = fields.Datetime(string='Date Approve') approve_by_finance = fields.Boolean(string='Approve By Finance') + approve_by = fields.Many2one(comodel_name='res.users', string='Approve By') report_logbook_sj_line = fields.One2many( comodel_name='report.logbook.sj.line', inverse_name='report_logbook_sj_id', string='Logbook SJ Line' ) + state = fields.Selection( + [('belum_terima', 'Belum Terima'), + ('terima_sebagian', 'Terima Sebagian'), + ('terima_semua', 'Sudah di terima semua'), + ], + default='terima_semua', + string='Status', + tracking=True + ) + + @api.model + def create(self, vals): + vals['name'] = self.env['ir.sequence'].next_by_code('report.logbook.sj') or '0' + result = super(ReportLogbookSJ, self).create(vals) + return result def approve(self): + current_time = datetime.utcnow() if self.env.user.is_accounting: self.approve_by_finance = True + self.date_approve = current_time + self.approve_by = self.env.user.id + if any(line.not_exist for line in self.report_logbook_sj_line): + if all(line.not_exist for line in self.report_logbook_sj_line): + self.state = 'belum_terima' + else: + self.state = 'terima_sebagian' + else: + self.state = 'terima_semua' else: raise UserError('Hanya Accounting yang bisa Approve') class ReportLogbookSJLine(models.Model): _name = 'report.logbook.sj.line' - product_id = fields.Many2one(comodel_name='product.product', string='Product') - location_id = fields.Many2one(comodel_name='stock.location', string='From') - product_uom_qty = fields.Float(string='Reserved') - qty_done = fields.Float(string='Done') - product_uom_id = fields.Many2one('uom.uom', string='Unit of Measure') - report_logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ')
\ No newline at end of file + name = fields.Char(string='SJ Number') + driver_id = fields.Many2one(comodel_name='res.users', string='Driver') + departure_date = fields.Char(string='Departure Date') + arrival_date = fields.Char(string='Arrival Date') + carrier_id = fields.Many2one('delivery.carrier', string='Shipping Method') + tracking_no = fields.Char(string='Tracking No') + logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') # Corrected model name + partner_id = fields.Many2one('res.partner', string='Customer') + picking_id = fields.Many2one('stock.picking', string='Picking') + report_logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') + not_exist = fields.Boolean(string='Not Exist') diff --git a/indoteknik_custom/models/report_stock_forecasted.py b/indoteknik_custom/models/report_stock_forecasted.py new file mode 100644 index 00000000..48a17095 --- /dev/null +++ b/indoteknik_custom/models/report_stock_forecasted.py @@ -0,0 +1,45 @@ +from odoo import api, models + +class ReplenishmentReport(models.AbstractModel): + _inherit = 'report.stock.report_product_product_replenishment' + + @api.model + def _get_report_lines(self, product_template_ids, product_variant_ids, wh_location_ids): + lines = super(ReplenishmentReport, self)._get_report_lines(product_template_ids, product_variant_ids, wh_location_ids) + + result_dict = {} + + for line in lines: + product_id = line.get('product', {}).get('id') + query = [('product_id', '=', product_id)] + document_out = line.get('document_out') + order_id = document_out.id if document_out else None + + if order_id: + result = self._calculate_result(line) + result_dict.setdefault(order_id, []).append(result) + + for order_id, results in result_dict.items(): + sale_order_lines = self.env['sale.order.line'].search([('order_id', '=', order_id)]) + + concatenated_result = ' ,'.join(results) + + for sale_order_line in sale_order_lines: + sale_order_line.reserved_from = concatenated_result + + return lines + + def _calculate_result(self, line): + if line['document_in']: + return str(line["document_in"].name) + elif line['reservation'] and not line['document_in']: + return 'Reserved from stock' + elif line['replenishment_filled']: + if line['document_out']: + return 'Inventory On Hand' + else: + return 'Free Stock' + else: + return 'Not Available' + + diff --git a/indoteknik_custom/models/res_users.py b/indoteknik_custom/models/res_users.py index 09321fc6..33f64ce3 100755 --- a/indoteknik_custom/models/res_users.py +++ b/indoteknik_custom/models/res_users.py @@ -39,3 +39,20 @@ class ResUsers(models.Model): if not vouchers: return None return ', '.join(x.code for x in vouchers) return None + + def check_access(self, model, mode): + assert mode in ('read', 'write', 'create', 'unlink', 'import', 'export'), 'Invalid access mode' + + self._cr.execute(""" + SELECT MAX(CASE WHEN perm_{mode} THEN 1 ELSE 0 END) + FROM ir_model_access a + JOIN ir_model m ON (m.id = a.model_id) + JOIN res_groups_users_rel gu ON (gu.gid = a.group_id) + WHERE m.model = %s + AND gu.uid = %s + AND a.active IS TRUE + """.format(mode=mode), (model, self._uid,)) + r = self._cr.fetchone()[0] + + return bool(r) + diff --git a/indoteknik_custom/models/role_permission/__init__.py b/indoteknik_custom/models/role_permission/__init__.py new file mode 100644 index 00000000..da36bc1e --- /dev/null +++ b/indoteknik_custom/models/role_permission/__init__.py @@ -0,0 +1 @@ +from . import ir_model_access
\ No newline at end of file diff --git a/indoteknik_custom/models/role_permission/ir_model_access.py b/indoteknik_custom/models/role_permission/ir_model_access.py new file mode 100644 index 00000000..c77e9b79 --- /dev/null +++ b/indoteknik_custom/models/role_permission/ir_model_access.py @@ -0,0 +1,9 @@ +from odoo import fields, models + + +class IrModelAccess(models.Model): + _inherit = 'ir.model.access' + + perm_import = fields.Boolean(string='Import Access') + perm_export = fields.Boolean(string='Export Access') +
\ No newline at end of file diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 362ca574..8b789976 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -453,6 +453,7 @@ class SaleOrder(models.Model): order.approval_status = 'approved' order._set_sppkp_npwp_contact() order.calculate_line_no() + # order.order_line.get_reserved_from() res = super(SaleOrder, self).action_confirm() return res diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py index 62f4a6b4..a140468c 100644 --- a/indoteknik_custom/models/sale_order_line.py +++ b/indoteknik_custom/models/sale_order_line.py @@ -29,6 +29,32 @@ class SaleOrderLine(models.Model): vendor_subtotal = fields.Float(string='Vendor Subtotal', compute="_compute_vendor_subtotal") amount_voucher_disc = fields.Float(string='Voucher Discount') qty_reserved = fields.Float(string='Qty Reserved', compute='_compute_qty_reserved') + reserved_from = fields.Char(string='Reserved From', copy=False) + + # def get_reserved_from(self): + # for line in self: + # current_stock = self.env['stock.quant'].search([ + # ('product_id', '=', line.product_id.id), + # ('location_id', '=', line.order_id.warehouse_id.lot_stock_id.id) + # ]) + + # po_stock = self.env['purchase.order.line'].search([ + # ('product_id', '=', line.product_id.id), + # ('order_id.sale_order_id', '=', line.order_id.id), + # ('state', '=', 'done') + # ]) + + # available_quantity = current_stock.available_quantity if current_stock else 0 + # product_qty = po_stock.product_qty if po_stock else 0 + + # if available_quantity >= line.product_uom_qty: + # line.reserved_from = 'From Stock' + # elif product_qty >= line.product_uom_qty: + # line.reserved_from = 'From PO' + # elif (available_quantity + product_qty) >= line.product_uom_qty: + # line.reserved_from = 'From Stock and PO' + # else: + # line.reserved_from = None def _compute_qty_reserved(self): for line in self: @@ -41,6 +67,16 @@ class SaleOrderLine(models.Model): reserved_qty = sum(move.product_uom_qty for move in stock_moves) line.qty_reserved = reserved_qty + if reserved_qty > 0: + line._compute_reserved_from() + + + def _compute_reserved_from(self): + for line in self: + # continue + report_stock_forecasted = self.env['report.stock.report_product_product_replenishment'] + report_stock_forecasted._get_report_data(False, [line.product_id.id]) + def _compute_vendor_subtotal(self): for line in self: if line.purchase_price > 0 and line.product_uom_qty > 0: diff --git a/indoteknik_custom/models/solr/apache_solr_queue.py b/indoteknik_custom/models/solr/apache_solr_queue.py index 07274295..1b51538f 100644 --- a/indoteknik_custom/models/solr/apache_solr_queue.py +++ b/indoteknik_custom/models/solr/apache_solr_queue.py @@ -18,6 +18,7 @@ class ApacheSolrQueue(models.Model): ('not_found', 'Record not found') ], 'Execute Status') execute_date = fields.Datetime('Execute Date') + description = fields.Text('Description') def _compute_display_name(self): for rec in self: @@ -38,6 +39,16 @@ class ApacheSolrQueue(models.Model): if elapsed_time > max_exec_time: break rec.execute_queue() + + def open_target_record(self): + return { + 'name': '', + 'view_mode': 'form', + 'res_model': self.res_model, + 'target': 'current', + 'type': 'ir.actions.act_window', + 'res_id': self.res_id + } def execute_queue(self): for rec in self: @@ -48,7 +59,8 @@ class ApacheSolrQueue(models.Model): _logger.info(f'Execute Queue: {res_model}.{function_name}() -> {res_id}') domain = [('id', '=', res_id)] - if res_model in ['product.template']: + model_incl_archive = ['product.template', 'promotion.program.line'] + if res_model in model_incl_archive: domain.append(('active', 'in', [True, False])) model_instance = self.env[res_model].search(domain) @@ -57,7 +69,8 @@ class ApacheSolrQueue(models.Model): rec.execute_status = 'success' else: rec.execute_status = 'not_found' - except: + except Exception as e: + rec.description = e rec.execute_status = 'failed' rec.execute_date = datetime.utcnow() self.env.cr.commit() diff --git a/indoteknik_custom/models/solr/product_product.py b/indoteknik_custom/models/solr/product_product.py index ac41dbff..c14f6b98 100644 --- a/indoteknik_custom/models/solr/product_product.py +++ b/indoteknik_custom/models/solr/product_product.py @@ -49,12 +49,6 @@ class ProductProduct(models.Model): document = solr_model.get_doc('variants', variant.id) - image = '' - if variant.image_256: - image = ir_attachment.api_image('product.product', 'image_256', variant.id) - else: - image = ir_attachment.api_image('product.template', 'image_256', variant.product_tmpl_id.id) - document.update({ 'id': variant.id, 'display_name_s': variant.display_name, @@ -63,9 +57,9 @@ class ProductProduct(models.Model): 'product_rating_f': variant.product_tmpl_id.virtual_rating, 'product_id_i': variant.id, 'template_id_i': variant.product_tmpl_id.id, - "image_s": image, + 'image_s': ir_attachment.api_image('product.template', 'image_256', variant.product_tmpl_id.id), 'stock_total_f': variant.qty_stock_vendor, - 'weight_f': variant.product_tmpl_id.weight, + 'weight_f': variant.weight, 'manufacture_id_i': variant.product_tmpl_id.x_manufacture.id or 0, 'manufacture_name_s': variant.product_tmpl_id.x_manufacture.x_name or '', 'manufacture_name': variant.product_tmpl_id.x_manufacture.x_name or '', diff --git a/indoteknik_custom/models/solr/promotion_program_line.py b/indoteknik_custom/models/solr/promotion_program_line.py index 6e182324..9cd226fb 100644 --- a/indoteknik_custom/models/solr/promotion_program_line.py +++ b/indoteknik_custom/models/solr/promotion_program_line.py @@ -39,9 +39,8 @@ class PromotionProgramLine(models.Model): document.update({ 'id': rec.id, - 'program_id_i': rec.program_id.id, + 'program_id_i': rec.program_id.id or 0, 'name_s': rec.name, - 'image_s': self.env['ir.attachment'].api_image(self._name, 'image', rec.id) if rec.image else '', 'type_value_s': promotion_type['value'], 'type_label_s': promotion_type['label'], 'package_limit_i': rec.package_limit, @@ -53,10 +52,9 @@ class PromotionProgramLine(models.Model): 'free_product_ids': [x.product_id.id for x in rec.free_product_ids], 'free_products_s': json.dumps(free_products), 'total_qty_i': sum([x.qty for x in rec.product_ids] + [x.qty for x in rec.free_product_ids]), + 'active_b': rec.active }) - self.solr().add([document]) - self.solr().commit() @api.model @@ -67,3 +65,13 @@ class PromotionProgramLine(models.Model): def write(self, vals): self._create_solr_queue('_sync_to_solr') return super(PromotionProgramLine, self).write(vals) + + def solr_flag_to_queue(self, limit=500): + domain = [ + ('solr_flag', '=', 2), + ('active', 'in', [True, False]) + ] + records = self.search(domain, limit=limit) + for record in records: + record._create_solr_queue('_sync_to_solr') + record.solr_flag = 1 diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index a8888b64..3ef1aa35 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -52,10 +52,11 @@ access_procurement_monitoring_detail,access.procurement.monitoring.detail,model_ access_rajaongkir_kurir,access.rajaongkir.kurir,model_rajaongkir_kurir,,1,1,1,1 access_brand_vendor,access.brand.vendor,model_brand_vendor,,1,1,1,1 access_promotion_program,access.promotion.program,model_promotion_program,,1,1,1,1 -access_promotion_program_line,access.promotion.program.line,model_promotion_program_line,,1,1,1,1 +access_promotion_program_line,access.promotion.program.line,model_promotion_program_line,,1,1,1,0 access_promotion_product,access.promotion.product,model_promotion_product,,1,1,1,1 access_promotion_free_product,access.promotion.free_product,model_promotion_free_product,,1,1,1,1 access_promotion_keyword,access.promotion.keyword,model_promotion_keyword,,1,1,1,1 +access_promotion_monitoring,access.promotion.monitoring,model_promotion_monitoring,,1,1,1,1 access_requisition,access.requisition,model_requisition,,1,1,1,1 access_requisition_line,access.requisition.line,model_requisition_line,,1,1,1,1 access_requisition_purchase_match,access.requisition.purchase.match,model_requisition_purchase_match,,1,1,1,1 @@ -103,3 +104,6 @@ access_logbook_sj,access.logbook.sj,model_logbook_sj,,1,1,1,1 access_logbook_sj_line,access.logbook.sj.line,model_logbook_sj_line,,1,1,1,1 access_report_logbook_sj,access.report.logbook.sj,model_report_logbook_sj,,1,1,1,1 access_report_logbook_sj_line,access.report.logbook.sj.line,model_report_logbook_sj_line,,1,1,1,1 +access_report_logbook_sj_line,access.report.logbook.sj.line,model_report_logbook_sj_line,,1,1,1,1 +access_cust_commision,access.cust.commision,model_cust_commision,,1,1,1,1 +access_report_stock_report_product_product_replenishment,access.report.stock.report_product_product_replenishment,model_report_stock_report_product_product_replenishment,,1,1,1,1 diff --git a/indoteknik_custom/views/apache_solr_queue.xml b/indoteknik_custom/views/apache_solr_queue.xml index 13869b4c..4c145b9f 100644 --- a/indoteknik_custom/views/apache_solr_queue.xml +++ b/indoteknik_custom/views/apache_solr_queue.xml @@ -4,11 +4,16 @@ <field name="model">apache.solr.queue</field> <field name="arch" type="xml"> <tree editable="top" default_order="create_date desc"> + <button type="object" name="open_target_record" string="" icon="fa-external-link" /> + <field name="id" readonly="1" /> <field name="display_name" readonly="1" /> <field name="res_model" readonly="1" /> <field name="res_id" readonly="1" /> <field name="function_name" readonly="1" /> - <field name="execute_status" widget="badge" readonly="1" + <field + name="execute_status" + widget="badge" + readonly="1" decoration-danger="execute_status == 'failed'" decoration-success="execute_status == 'success'" decoration-primary="execute_status == 'not_found'" diff --git a/indoteknik_custom/views/cust_commision.xml b/indoteknik_custom/views/cust_commision.xml new file mode 100644 index 00000000..dfa4adfb --- /dev/null +++ b/indoteknik_custom/views/cust_commision.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <record id="cust_commision_tree" model="ir.ui.view"> + <field name="name">cust.commision.tree</field> + <field name="model">cust.commision</field> + <field name="arch" type="xml"> + <tree editable="bottom"> + <field name="partner_id"/> + <field name="commision_percent"/> + </tree> + </field> + </record> + + <record id="cust_commision_form" model="ir.ui.view"> + <field name="name">cust.commision.form</field> + <field name="model">cust.commision</field> + <field name="arch" type="xml"> + <form> + <sheet string="Commision"> + <group> + <group> + <field name="partner_id"/> + <field name="commision_percent"/> + </group> + </group> + </sheet> + </form> + </field> + </record> + + <record id="cust_commision_action" model="ir.actions.act_window"> + <field name="name">Commision</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">cust.commision</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem id="menu_cust_commision_sales" + name="Commision" + action="cust_commision_action" + parent="sale.product_menu_catalog" + sequence="101" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/customer_commision.xml b/indoteknik_custom/views/customer_commision.xml index 88fe1cf1..600ad192 100644 --- a/indoteknik_custom/views/customer_commision.xml +++ b/indoteknik_custom/views/customer_commision.xml @@ -8,9 +8,9 @@ <field name="number"/> <field name="date_from"/> <field name="date_to"/> - <field name="partner_ids"/> - <field name="description"/> - <field name="notification" readonly="1"/> + <field name="partner_ids" widget="many2many_tags"/> + <field name="commision_percent"/> + <field name="commision_amt" readonly="1"/> <field name="status" readonly="1"/> </tree> </field> @@ -90,10 +90,22 @@ </field> </record> + <record id="view_customer_commision_filter" model="ir.ui.view"> + <field name="name">customer.commision.list.select</field> + <field name="model">customer.commision</field> + <field name="priority" eval="15"/> + <field name="arch" type="xml"> + <search string="Search Customer Commision"> + <field name="partner_ids"/> + </search> + </field> + </record> + <record id="customer_commision_action" model="ir.actions.act_window"> <field name="name">Customer Commision</field> <field name="type">ir.actions.act_window</field> <field name="res_model">customer.commision</field> + <field name="search_view_id" ref="view_customer_commision_filter"/> <field name="view_mode">tree,form</field> </record> diff --git a/indoteknik_custom/views/ir_sequence.xml b/indoteknik_custom/views/ir_sequence.xml index f276275d..d52f55ca 100644 --- a/indoteknik_custom/views/ir_sequence.xml +++ b/indoteknik_custom/views/ir_sequence.xml @@ -10,6 +10,16 @@ <field name="number_next">1</field> <field name="number_increment">1</field> </record> + + <record id="sequence_logbook_sj" model="ir.sequence"> + <field name="name">Logbook SJ</field> + <field name="code">report.logbook.sj</field> + <field name="active">TRUE</field> + <field name="prefix">LSJ/%(year)s/</field> + <field name="padding">5</field> + <field name="number_next">1</field> + <field name="number_increment">1</field> + </record> <record id="sequence_stock_picking_code" model="ir.sequence"> <field name="name">Stock Picking Code</field> diff --git a/indoteknik_custom/views/promotion/promotion_monitoring.xml b/indoteknik_custom/views/promotion/promotion_monitoring.xml new file mode 100644 index 00000000..88325c52 --- /dev/null +++ b/indoteknik_custom/views/promotion/promotion_monitoring.xml @@ -0,0 +1,64 @@ +<odoo> + <record id="promotion_monitoring_tree" model="ir.ui.view"> + <field name="name">Promotion Monitoring Tree</field> + <field name="model">promotion.monitoring</field> + <field name="arch" type="xml"> + <tree create="0"> + <field name="product_id" /> + <field name="manufacture_id" /> + <field name="price" /> + <field name="has_promo" /> + <field name="count_active" /> + <field name="count_inactive" /> + </tree> + </field> + </record> + + <record id="promotion_monitoring_form" model="ir.ui.view"> + <field name="name">Promotion Monitoring Form</field> + <field name="model">promotion.monitoring</field> + <field name="arch" type="xml"> + <form create="0" edit="0"> + <sheet> + <group> + <group> + <field name="product_id" /> + <field name="manufacture_id" /> + <field name="price" /> + <field name="has_promo" /> + <field name="count_active" /> + <field name="count_inactive" /> + </group> + </group> + </sheet> + </form> + </field> + </record> + + <record id="promotion_monitoring_view_search" model="ir.ui.view"> + <field name="name">promotion.monitoring.search</field> + <field name="model">promotion.monitoring</field> + <field name="mode">primary</field> + <field name="arch" type="xml"> + <search string="Search"> + <field name="product_id" /> + <field name="manufacture_id" /> + </search> + </field> + </record> + + <record id="promotion_monitoring_action" model="ir.actions.act_window"> + <field name="name">Promotion Monitoring</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">promotion.monitoring</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem + id="menu_promotion_monitoring" + name="Monitoring" + parent="indoteknik_custom.menu_promotion_program_parent" + sequence="3" + action="promotion_monitoring_action" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/promotion/promotion_product.xml b/indoteknik_custom/views/promotion/promotion_product.xml new file mode 100644 index 00000000..eac42a45 --- /dev/null +++ b/indoteknik_custom/views/promotion/promotion_product.xml @@ -0,0 +1,45 @@ +<odoo> + <record id="promotion_product_tree" model="ir.ui.view"> + <field name="name">Promotion Product Tree</field> + <field name="model">promotion.product</field> + <field name="arch" type="xml"> + <tree> + <field name="product_id" /> + <field name="qty" /> + </tree> + </field> + </record> + + <record id="promotion_product_form" model="ir.ui.view"> + <field name="name">Promotion Product Form</field> + <field name="model">promotion.product</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <group> + <field name="program_line_id" /> + <field name="product_id" /> + <field name="qty" /> + </group> + </group> + </sheet> + </form> + </field> + </record> + + <record id="promotion_product_action" model="ir.actions.act_window"> + <field name="name">Promotion Product</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">promotion.product</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem + id="menu_promotion_product" + name="Product" + parent="indoteknik_custom.menu_promotion_program_parent" + sequence="3" + action="promotion_product_action" + /> +</odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/promotion/promotion_program_line.xml b/indoteknik_custom/views/promotion/promotion_program_line.xml index 346a08c9..025ea35a 100644 --- a/indoteknik_custom/views/promotion/promotion_program_line.xml +++ b/indoteknik_custom/views/promotion/promotion_program_line.xml @@ -22,7 +22,9 @@ <group> <group> <field name="name" /> + <field name="program_id" /> <field name="promotion_type" /> + <field name="active" readonly="1" /> </group> <group> <field name="package_limit" /> @@ -70,4 +72,19 @@ sequence="2" action="promotion_program_line_action" /> + + <data noupdate="1"> + <record id="cron_program_line_solr_flag_solr" model="ir.cron"> + <field name="name">Program Line: Solr Flag to Queue</field> + <field name="interval_number">1</field> + <field name="interval_type">hours</field> + <field name="numbercall">-1</field> + <field name="doall" eval="False"/> + <field name="model_id" ref="model_promotion_program_line"/> + <field name="code">model.solr_flag_to_queue()</field> + <field name="state">code</field> + <field name="priority">55</field> + <field name="active">True</field> + </record> + </data> </odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index 3f7ca5a7..baff620c 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -102,7 +102,7 @@ </xpath> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='product_qty']" position="attributes"> - <attribute name="attrs">{'readonly': [('is_edit_product_qty', '=', False)], 'required': True}</attribute> + <attribute name="attrs">{'required': True}</attribute> </xpath> <xpath expr="//form/sheet/notebook/page[@name='purchase_delivery_invoice']" position="before"> diff --git a/indoteknik_custom/views/report_logbook_sj.xml b/indoteknik_custom/views/report_logbook_sj.xml index 52e00d17..ea58aefd 100644 --- a/indoteknik_custom/views/report_logbook_sj.xml +++ b/indoteknik_custom/views/report_logbook_sj.xml @@ -6,10 +6,11 @@ <field name="arch" type="xml"> <tree create="0"> <field name="name"/> + <field name="approve_by"/> <field name="date"/> - <field name="name_picking"/> + <field name="date_approve"/> <field name="approve_by_finance"/> - <field name="partner_id"/> + <field name="state"/> </tree> </field> </record> @@ -18,12 +19,16 @@ <field name="name">report.logbook.sj.line.tree</field> <field name="model">report.logbook.sj.line</field> <field name="arch" type="xml"> - <tree> - <field name="product_id"/> - <field name="location_id"/> - <field name="product_uom_qty"/> - <field name="qty_done"/> - <field name="product_uom_id"/> + <tree editable="bottom"> + <field name="name"/> + <field name="driver_id"/> + <field name="departure_date"/> + <field name="arrival_date"/> + <field name="carrier_id"/> + <field name="tracking_no"/> + <field name="partner_id"/> + <field name="picking_id"/> + <field name="not_exist"/> </tree> </field> </record> @@ -35,7 +40,7 @@ <form> <header> <button name="approve" - string="Approve" + string="Validate" type="object" /> </header> @@ -45,11 +50,12 @@ <group> <field name="name" readonly="1"/> <field name="date" readonly="1"/> + <field name="date_approve" readonly="1"/> </group> <group> - <field name="name_picking" readonly="1"/> - <field name="partner_id" readonly="1"/> <field name="approve_by_finance" readonly="1"/> + <field name="state" readonly="1"/> + <field name="approve_by" readonly="1"/> </group> </group> <notebook> diff --git a/indoteknik_custom/views/role_permission/ir_model_access.xml b/indoteknik_custom/views/role_permission/ir_model_access.xml new file mode 100644 index 00000000..0c74d5e2 --- /dev/null +++ b/indoteknik_custom/views/role_permission/ir_model_access.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <data> + <record id="ir_model_access_tree_view_inherit" model="ir.ui.view"> + <field name="name">Access Rights</field> + <field name="model">ir.model.access</field> + <field name="inherit_id" ref="base.ir_access_view_tree_edition"/> + <field name="arch" type="xml"> + <field name="perm_unlink" position="after"> + <field name="perm_import"/> + <field name="perm_export"/> + </field> + </field> + </record> + </data> +</odoo> diff --git a/indoteknik_custom/views/role_permission/res_groups.xml b/indoteknik_custom/views/role_permission/res_groups.xml new file mode 100644 index 00000000..910469fd --- /dev/null +++ b/indoteknik_custom/views/role_permission/res_groups.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <data> + <record model="ir.module.category" id="module_category_roles"> + <field name="name">Roles</field> + <field name="sequence">70</field> + <field name="visible" eval="0" /> + </record> + + <record id="group_role_it" model="res.groups"> + <field name="name">IT</field> + <field name="category_id" ref="module_category_roles" /> + </record> + + <record id="group_role_fat" model="res.groups"> + <field name="name">FAT</field> + <field name="category_id" ref="module_category_roles" /> + </record> + + <record id="group_role_sales" model="res.groups"> + <field name="name">Sales</field> + <field name="category_id" ref="module_category_roles" /> + </record> + + <record id="group_role_marketing" model="res.groups"> + <field name="name">Marketing</field> + <field name="category_id" ref="module_category_roles" /> + </record> + + <record id="group_role_purchasing" model="res.groups"> + <field name="name">Purchasing</field> + <field name="category_id" ref="module_category_roles" /> + </record> + + <record id="group_role_logistic" model="res.groups"> + <field name="name">Logistic</field> + <field name="category_id" ref="module_category_roles" /> + </record> + + <record id="group_role_merchandiser" model="res.groups"> + <field name="name">Merchandiser</field> + <field name="category_id" ref="module_category_roles" /> + </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 02dba7d5..aa508443 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -109,11 +109,15 @@ <field name="line_no" readonly="1" optional="hide"/> </xpath> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='qty_delivered']" position="before"> - <field name="qty_reserved" readonly="1"/> + <field name="qty_reserved" invisible="1"/> + <field name="reserved_from" 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> + <!-- <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='tax_id']" position="attributes"> + <attribute name="required">1</attribute> + </xpath> --> <field name="amount_total" position="after"> <field name="grand_total"/> <label for="amount_voucher_disc" string="Voucher" /> |
