summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindoteknik_custom/models/__init__.py3
-rw-r--r--indoteknik_custom/models/apache_solr.py118
-rw-r--r--indoteknik_custom/models/base_import_import.py55
-rw-r--r--indoteknik_custom/models/po_sync_price.py14
-rw-r--r--indoteknik_custom/models/procurement_monitoring_detail.py6
-rw-r--r--indoteknik_custom/models/product_attribute.py15
-rw-r--r--indoteknik_custom/models/product_pricelist.py133
-rwxr-xr-xindoteknik_custom/models/product_template.py160
-rwxr-xr-xindoteknik_custom/models/purchase_order.py75
-rwxr-xr-xindoteknik_custom/models/sale_monitoring_detail.py2
-rwxr-xr-xindoteknik_custom/models/sale_order.py4
-rwxr-xr-xindoteknik_custom/models/stock_vendor.py6
-rw-r--r--indoteknik_custom/models/website_categories_homepage.py32
-rwxr-xr-xindoteknik_custom/models/x_manufactures.py10
-rwxr-xr-xindoteknik_custom/security/ir.model.access.csv2
-rw-r--r--indoteknik_custom/views/mail_template_po.xml100
-rw-r--r--indoteknik_custom/views/procurement_monitoring_detail.xml7
-rw-r--r--indoteknik_custom/views/product_pricelist.xml8
-rwxr-xr-xindoteknik_custom/views/product_template.xml2
-rw-r--r--indoteknik_custom/views/website_categories_homepage.xml8
20 files changed, 319 insertions, 441 deletions
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py
index 255a12f6..3a5079f6 100755
--- a/indoteknik_custom/models/__init__.py
+++ b/indoteknik_custom/models/__init__.py
@@ -81,3 +81,6 @@ from . import account_general_ledger
from . import account_report_financial
from . import account_report_general_ledger
from . import price_group
+from . import po_sync_price
+from . import base_import_import
+from . import product_attribute
diff --git a/indoteknik_custom/models/apache_solr.py b/indoteknik_custom/models/apache_solr.py
index bd4dd3dc..086fb6d0 100644
--- a/indoteknik_custom/models/apache_solr.py
+++ b/indoteknik_custom/models/apache_solr.py
@@ -4,7 +4,6 @@ from datetime import datetime, timedelta
import logging
import pysolr
import time
-from odoo.tools.config import config
_logger = logging.getLogger(__name__)
_solr = pysolr.Solr('http://10.148.0.5:8983/solr/product/', always_commit=True, timeout=30)
@@ -13,26 +12,9 @@ _variants_solr = pysolr.Solr('http://10.148.0.5:8983/solr/variants/', always_com
class ApacheSolr(models.Model):
- _name = 'apache.solr'
+ _name = 'apache.solr'
_order = 'id desc'
- def get_single_doc(self, schema, id):
- try:
- return self.connect(schema).search(f'id:{id}').docs[0]
- except:
- return {}
-
- def connect(self, schema):
- env = config.get('solr_env', 'development')
-
- url = ''
- if env == 'development':
- url = 'http://192.168.23.5:8983/solr/'
- elif env == 'production':
- url = 'http://10.148.0.5:8983/solr/'
-
- return pysolr.Solr(url + schema, always_commit=True, timeout=30)
-
def _update_stock_product_to_solr(self, limit=10000):
current_time = datetime.now()
delta_time = current_time - timedelta(days=3)
@@ -85,67 +67,11 @@ class ApacheSolr(models.Model):
_logger.info(documents)
_solr.add(documents, fieldUpdates={'product_rating_f':'set'})
- def _sync_product_template_to_solr(self, limit=500):
- start_time = time.time()
- _logger.info('run sync to solr...')
- query = ["&","&",("type","=","product"),("active","=",True),"|",("solr_flag","=",0),("solr_flag","=",2)]
-
- templates = self.env['product.template'].search(query, limit=limit)
- documents = []
- counter = 0
- for template in templates:
- template_time = time.time()
- counter += 1
- variants_name = variants_code = ''
- if template.product_variant_count > 1:
- for variant in template.product_variant_ids:
- variants_name += variant.display_name or ''+', '
- variants_code += variant.default_code or ''+', '
-
- category_id = ''
- category_name = ''
- for category in template.public_categ_ids:
- category_id = category.id
- category_name = category.name
-
- document = {
- # Start Product Template
- 'id': template.id,
- 'display_name_s': template.display_name,
- 'name_s': template.name,
- 'default_code_s': template.default_code or '',
- 'product_rating_f': template.virtual_rating,
- 'product_id_i': template.id,
- 'image_s': self.env['ir.attachment'].api_image('product.template', 'image_512', template.id),
- 'variant_total_i': template.product_variant_count,
- 'stock_total_f': template.qty_stock_vendor,
- 'weight_f': template.weight,
- 'manufacture_id_i': template.x_manufacture.id or 0,
- 'manufacture_name_s': template.x_manufacture.x_name or '',
- 'manufacture_name': template.x_manufacture.x_name or '',
- 'image_promotion_1_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_1', template.x_manufacture.id),
- 'image_promotion_2_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_2', template.x_manufacture.id),
- 'variants_name_t': variants_name,
- 'variants_code_t': variants_code,
- 'search_rank_i': template.search_rank,
- 'search_rank_weekly_i': template.search_rank_weekly,
- 'category_id_i': category_id or 0,
- 'category_name_s': category_name or '',
- 'category_name': category_name or '',
- # End Product Template
- }
- documents.append(document)
- template.solr_flag = 1
- _logger.info('[SYNC_PRODUCT_TO_SOLR] {}/{} {:.6f}'.format(counter, limit, time.time() - template_time))
- _logger.info('[SYNC_PRODUCT_TO_SOLR] Success add to solr product %s' % template.id)
- _solr.add(documents)
- end_time = time.time()
- _logger.info("[SYNC_PRODUCT_TO_SOLR] Finish task add to solr. Time taken: {:.6f} seconds".format(end_time - start_time))
-
- def _sync_product_pricelist_to_solr(self, limit=500):
+ def _sync_product_to_solr(self, limit=500):
start_time = time.time()
_logger.info('run sync to solr...')
query = ["&","&",("type","=","product"),("active","=",True),"|",("solr_flag","=",0),("solr_flag","=",2)]
+ # query = [('id', '=', 97942)]
templates = self.env['product.template'].search(query, limit=limit)
documents = []
@@ -190,25 +116,51 @@ class ApacheSolr(models.Model):
tier2 = template.product_variant_id._get_pricelist_tier2()
tier3 = template.product_variant_id._get_pricelist_tier3()
+ category_id = ''
+ category_name = ''
+ for category in template.public_categ_ids:
+ category_id = category.id
+ category_name = category.name
+
document = {
- # Start Product Pricelist
+ 'id': template.id,
+ 'display_name_s': template.display_name,
+ 'name_s': template.name,
+ 'default_code_s': template.default_code or '',
+ 'product_rating_f': template.virtual_rating,
+ 'product_id_i': template.id,
+ 'image_s': self.env['ir.attachment'].api_image('product.template', 'image_512', template.id),
+ 'price_f': price_excl,
+ 'discount_f': discount,
+ 'price_discount_f': price_excl_after_disc,
+ 'tax_f': tax,
+ 'variant_total_i': template.product_variant_count,
+ 'stock_total_f': template.qty_stock_vendor,
+ 'weight_f': template.weight,
+ 'manufacture_id_i': template.x_manufacture.id or 0,
+ 'manufacture_name_s': template.x_manufacture.x_name or '',
+ 'manufacture_name': template.x_manufacture.x_name or '',
+ 'image_promotion_1_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_1', template.x_manufacture.id),
+ 'image_promotion_2_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_2', template.x_manufacture.id),
+ 'category_id_i': category_id or 0,
+ 'category_name_s': category_name or '',
+ 'category_name': category_name or '',
+ 'variants_name_t': variants_name,
+ 'variants_code_t': variants_code,
+ 'search_rank_i': template.search_rank,
+ 'search_rank_weekly_i': template.search_rank_weekly,
'flashsale_id_i': flashsale_data['flashsale_id'] or 0,
'flashsale_tag_s': flashsale_data['flashsale_tag'] or '',
'flashsale_name_s': flashsale_data['flashsale_name'] or '',
'flashsale_base_price_f': flashsale_data['flashsale_base_price'] or 0,
'flashsale_discount_f': flashsale_data['flashsale_discount'] or 0,
'flashsale_price_f': flashsale_data['flashsale_price'] or 0,
- 'price_f': price_excl,
- 'discount_f': discount,
- 'price_discount_f': price_excl_after_disc,
- 'tax_f': tax,
'discount_tier1_f': tier1['discount_tier1'] or 0,
'price_tier1_f': tier1['price_tier1'] or 0,
'discount_tier2_f': tier2['discount_tier2'] or 0,
'price_tier2_f': tier2['price_tier2'] or 0,
'discount_tier3_f': tier3['discount_tier3'] or 0,
'price_tier3_f': tier3['price_tier3'] or 0
- # End Product Pricelist
}
documents.append(document)
template.solr_flag = 1
diff --git a/indoteknik_custom/models/base_import_import.py b/indoteknik_custom/models/base_import_import.py
new file mode 100644
index 00000000..9cffa6e6
--- /dev/null
+++ b/indoteknik_custom/models/base_import_import.py
@@ -0,0 +1,55 @@
+from odoo import models
+from odoo.exceptions import UserError
+from datetime import datetime
+
+class Import(models.TransientModel):
+ _inherit = 'base_import.import'
+
+ def _get_config_enable_import(self):
+ return self.env['ir.config_parameter'].sudo().get_param('base_import.import.enable_import', '')
+
+ def _get_config_restrict_model(self):
+ return self.env['ir.config_parameter'].sudo().get_param('base_import.import.restrict_model', '')
+
+ def _check_time_range(self, config_string):
+ current_time = datetime.now().time()
+ ranges = config_string.split(' / ')
+
+ for time_range in ranges:
+ start_str, end_str = time_range.split(' - ')
+ start_time = datetime.strptime(start_str, '%H:%M:%S').time()
+ end_time = datetime.strptime(end_str, '%H:%M:%S').time()
+
+ if start_time <= current_time and current_time <= end_time:
+ return True
+
+ return False
+
+ def _check_enable_import(self):
+ enable_import = self._get_config_enable_import()
+ restrict_model = self._get_config_restrict_model()
+
+ if self.res_model not in restrict_model:
+ return True
+
+ if enable_import.lower() == 'true':
+ return True
+ elif enable_import.lower() == 'false':
+ return False
+ elif '-' in enable_import:
+ return self._check_time_range(enable_import)
+
+ return True
+
+ def _unable_import_notif(self):
+ enable_import_config = self._get_config_enable_import()
+ message = 'Import tidak dapat dilakukan saat ini. Hubungi Tim IT.'
+ if '-' in enable_import_config:
+ message = f'Import tidak dapat dilakukan saat ini. Anda bisa melakukannya di rentang waktu berikut: {enable_import_config}.'
+ 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()
+ return super(Import, self).do(fields, columns, options, dryrun)
diff --git a/indoteknik_custom/models/po_sync_price.py b/indoteknik_custom/models/po_sync_price.py
new file mode 100644
index 00000000..3e0ef621
--- /dev/null
+++ b/indoteknik_custom/models/po_sync_price.py
@@ -0,0 +1,14 @@
+from odoo import fields, models, api
+
+
+class POSyncPrice(models.Model):
+ _name = "po.sync.price"
+ _description = "PO Sync Price"
+
+ order_line_id = fields.Many2one('purchase.order.line', string='Purchase Order')
+ # purchase_order_id = fields.Many2one('purchase.order', string='Purchase Order')
+ # product_variant_id = fields.Many2one('product.product', string='Product Variant')
+ # manufacture_id = fields.Many2one('x_manufactures',string="Brand")
+ # unit_price = fields.Float(string="Unit Price")
+ # vendor_price = fields.Float(string="Vendor Price")
+ # created = fields.Datetime(string="Create Date") \ No newline at end of file
diff --git a/indoteknik_custom/models/procurement_monitoring_detail.py b/indoteknik_custom/models/procurement_monitoring_detail.py
index 6031e04a..80e71304 100644
--- a/indoteknik_custom/models/procurement_monitoring_detail.py
+++ b/indoteknik_custom/models/procurement_monitoring_detail.py
@@ -22,6 +22,7 @@ class SaleMonitoringDetail(models.Model):
date_order = fields.Datetime(string="Date Order")
status = fields.Char(string="Status")
po_ids = fields.Many2many('purchase.order', string='PO', compute='_compute_po')
+ note = fields.Char(string="Note")
def _compute_po(self):
for line in self:
@@ -58,7 +59,8 @@ class SaleMonitoringDetail(models.Model):
get_qty_available(sol.product_id) as qty_available,
get_qty_reserved(so.id, sol.product_id) as qty_reserved,
get_qty_po(so.id, sol.product_id) AS qty_po,
- so.date_order AS date_order
+ so.date_order AS date_order,
+ sol.note_procurement as note
FROM sale_order so
JOIN sale_order_line sol ON sol.order_id = so.id
JOIN product_product p ON p.id = sol.product_id
@@ -66,7 +68,7 @@ class SaleMonitoringDetail(models.Model):
WHERE pt.type IN ('consu','product')
AND so.state IN ('sale','done')
AND so.create_date >= '2022-08-10'
- and so.so_status not in ('terproses')
+ and so.so_status not in('terproses')
) a
--where a.qty_po < a.qty_so
)
diff --git a/indoteknik_custom/models/product_attribute.py b/indoteknik_custom/models/product_attribute.py
new file mode 100644
index 00000000..784ccd81
--- /dev/null
+++ b/indoteknik_custom/models/product_attribute.py
@@ -0,0 +1,15 @@
+from odoo import fields, models, api, _
+from odoo.exceptions import AccessError, UserError, ValidationError
+import re
+
+class ProductAttributeValue(models.Model):
+ _inherit = 'product.attribute.value'
+
+ @api.constrains('name')
+ def _validate_name(self):
+ pattern = r'^[a-zA-Z0-9\[\]\(\)\.\s/%]+$'
+ if not re.match(pattern, self.name):
+ pattern_suggest = r'[a-zA-Z0-9\[\]\(\)\.\s/%]+'
+ 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}')
+ \ No newline at end of file
diff --git a/indoteknik_custom/models/product_pricelist.py b/indoteknik_custom/models/product_pricelist.py
index 73eebdcf..2053accc 100644
--- a/indoteknik_custom/models/product_pricelist.py
+++ b/indoteknik_custom/models/product_pricelist.py
@@ -1,10 +1,8 @@
from odoo import models, fields, api
from odoo.exceptions import UserError
from datetime import datetime
-import logging
-import time
-_logger = logging.getLogger(__name__)
+
class ProductPricelist(models.Model):
_inherit = 'product.pricelist'
@@ -26,125 +24,22 @@ class ProductPricelist(models.Model):
remaining_time = (self.end_date - datetime.now()).total_seconds()
remaining_time = round(remaining_time)
return max(remaining_time, 0)
+
+ def update_product_solr_flag(self):
+ for item in self.item_ids:
+ item.product_id.product_tmpl_id.solr_flag = 2
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': { 'title': 'Notification', 'message': f'{len(self.item_ids)} produk akan diupdate ke SOLR' }
+ }
class ProductPricelistItem(models.Model):
_inherit = 'product.pricelist.item'
manufacture_id = fields.Many2one('x_manufactures', string='Manufacture')
- @api.constrains('applied_on', 'product_id', 'base', 'base_pricelist_id', 'price_discount')
- def _constrains_related_solr_field(self):
- self.update_template_solr()
- self.update_variant_solr()
-
- def update_template_solr(self):
- price_excl_after_disc = price_excl = discount = tax = 0
- flashsale_data = tier1 = tier2 = tier3 = {}
-
- template = self.product_id.product_tmpl_id
- if template.product_variant_count > 1:
- for variant in template.product_variant_ids:
- 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()
- 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()
- else:
- price_excl_after_disc = price_excl_after_disc
- price_excl = price_excl
- discount = discount
- tax = tax
- flashsale_data = flashsale_data
- tier1 = tier1
- tier2 = tier2
- tier3 = tier3
- else:
- price_excl = template.product_variant_id._get_website_price_exclude_tax()
- discount = template.product_variant_id._get_website_disc(0)
- price_excl_after_disc = template.product_variant_id._get_website_price_after_disc_and_tax()
- tax = template.product_variant_id._get_website_tax()
- flashsale_data = template.product_variant_id._get_flashsale_price()
- tier1 = template.product_variant_id._get_pricelist_tier1()
- tier2 = template.product_variant_id._get_pricelist_tier2()
- tier3 = template.product_variant_id._get_pricelist_tier3()
-
- solr_model = self.env['apache.solr']
- solr = solr_model.connect('product')
- document = solr_model.get_single_doc('product', template.id)
- document.update({
- 'id': template.id,
- 'flashsale_id_i': flashsale_data['flashsale_id'] or 0,
- 'flashsale_tag_s': flashsale_data['flashsale_tag'] or '',
- 'flashsale_name_s': flashsale_data['flashsale_name'] or '',
- 'flashsale_base_price_f': flashsale_data['flashsale_base_price'] or 0,
- 'flashsale_discount_f': flashsale_data['flashsale_discount'] or 0,
- 'flashsale_price_f': flashsale_data['flashsale_price'] or 0,
- 'price_f': price_excl,
- 'discount_f': discount,
- 'price_discount_f': price_excl_after_disc,
- 'tax_f': tax,
- 'discount_tier1_f': tier1['discount_tier1'] or 0,
- 'price_tier1_f': tier1['price_tier1'] or 0,
- 'discount_tier2_f': tier2['discount_tier2'] or 0,
- 'price_tier2_f': tier2['price_tier2'] or 0,
- 'discount_tier3_f': tier3['discount_tier3'] or 0,
- 'price_tier3_f': tier3['price_tier3'] or 0
- })
- solr.add([document])
- template.change_solr_data('Ada perubahan pada harga product')
-
- def update_variant_solr(self):
- price_excl_after_disc = price_excl = discount = tax = 0
- flashsale_data = tier1 = tier2 = tier3 = {}
-
- product = self.product_id
- for variant in product:
- 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()
- 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()
- else:
- price_excl_after_disc = price_excl_after_disc
- price_excl = price_excl
- discount = discount
- tax = tax
- flashsale_data = flashsale_data
- tier1 = tier1
- tier2 = tier2
- tier3 = tier3
-
- solr_model = self.env['apache.solr']
- solr = solr_model.connect('variants')
- document = solr_model.get_single_doc('variants', product.id)
- document.update({
- 'id': product.id,
- 'flashsale_id_i': flashsale_data['flashsale_id'] or 0,
- 'flashsale_tag_s': flashsale_data['flashsale_tag'] or '',
- 'flashsale_name_s': flashsale_data['flashsale_name'] or '',
- 'flashsale_base_price_f': flashsale_data['flashsale_base_price'] or 0,
- 'flashsale_discount_f': flashsale_data['flashsale_discount'] or 0,
- 'flashsale_price_f': flashsale_data['flashsale_price'] or 0,
- 'price_f': price_excl,
- 'discount_f': discount,
- 'price_discount_f': price_excl_after_disc,
- 'tax_f': tax,
- 'discount_tier1_f': tier1['discount_tier1'] or 0,
- 'price_tier1_f': tier1['price_tier1'] or 0,
- 'discount_tier2_f': tier2['discount_tier2'] or 0,
- 'price_tier2_f': tier2['price_tier2'] or 0,
- 'discount_tier3_f': tier3['discount_tier3'] or 0,
- 'price_tier3_f': tier3['price_tier3'] or 0
- })
- solr.add([document])
- product.change_solr_data('Ada perubahan pada harga product') \ No newline at end of file
+ @api.constrains('fixed_price','price_discount')
+ def update_product_solr_flag(self):
+ for item in self:
+ item.product_id.product_tmpl_id.solr_flag = 2 \ No newline at end of file
diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py
index 3caa3125..52f72729 100755
--- a/indoteknik_custom/models/product_template.py
+++ b/indoteknik_custom/models/product_template.py
@@ -1,9 +1,10 @@
from odoo import fields, models, api
-from datetime import datetime, timedelta, timezone
+from datetime import datetime, timedelta
from odoo.exceptions import AccessError, UserError, ValidationError
import logging
import requests
import json
+import re
_logger = logging.getLogger(__name__)
@@ -50,13 +51,19 @@ class ProductTemplate(models.Model):
is_new_product = fields.Boolean(string='Produk Baru',
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')
- last_update_solr = fields.Datetime(string='Last Update Solr')
- desc_update_solr = fields.Char(string='Desc Update Solr')
- def change_solr_data(self, desc):
- current_time = datetime.utcnow()
- self.desc_update_solr = desc
- self.last_update_solr = current_time
+ @api.constrains('name')
+ def _validate_name(self):
+ pattern = r'^[a-zA-Z0-9\[\]\(\)\.\s/%]+$'
+ if not re.match(pattern, self.name):
+ pattern_suggest = r'[a-zA-Z0-9\[\]\(\)\.\s/%]+'
+ 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}')
+
+ # def write(self, vals):
+ # if 'solr_flag' not in vals and self.solr_flag == 1:
+ # vals['solr_flag'] = 2
+ # return super().write(vals)
def _compute_virtual_rating(self):
for product in self:
@@ -121,6 +128,12 @@ class ProductTemplate(models.Model):
product.default_code = 'ITV.'+str(product.id)
_logger.info('Updated Variant %s' % product.name)
+ @api.onchange('name','default_code','x_manufacture','product_rating','website_description','image_1920','weight','public_categ_ids')
+ def update_solr_flag(self):
+ for tmpl in self:
+ if tmpl.solr_flag == 1:
+ tmpl.solr_flag = 2
+
def _compute_qty_stock_vendor(self):
for product_template in self:
product_template.qty_stock_vendor = 0
@@ -252,62 +265,7 @@ class ProductTemplate(models.Model):
self.env['token.storage'].create([values])
return values
- @api.constrains(
- 'name',
- 'default_code',
- 'weight',
- 'x_manufacture',
- 'public_categ_ids',
- 'product_variant_ids.display_name',
- 'product_variant_ids.default_code',
- 'search_rank',
- 'search_rank_weekly',
- 'image_1920'
- )
- def _sync_product_template_to_solr(self, limit=500):
- template = self
- if not template.active or template.type != 'product':
- return
-
- 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])
-
- category_id = 0
- category_name = ''
- for category in template.public_categ_ids:
- category_id, category_name = category.id, category.name
- break
-
- solr_model = self.env['apache.solr']
- solr = solr_model.connect('product')
- document = solr_model.get_single_doc('product', template.id)
- document.update({
- 'id': template.id,
- 'display_name_s': template.display_name,
- 'name_s': template.name,
- 'default_code_s': template.default_code or '',
- 'product_rating_f': template.virtual_rating,
- 'product_id_i': template.id,
- 'image_s': self.env['ir.attachment'].api_image('product.template', 'image_512', template.id),
- 'variant_total_i': template.product_variant_count,
- 'stock_total_f': template.qty_stock_vendor,
- 'weight_f': template.weight,
- 'manufacture_id_i': template.x_manufacture.id or 0,
- 'manufacture_name_s': template.x_manufacture.x_name or '',
- 'manufacture_name': template.x_manufacture.x_name or '',
- 'image_promotion_1_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_1', template.x_manufacture.id),
- 'image_promotion_2_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_2', template.x_manufacture.id),
- 'variants_name_t': variant_names,
- 'variants_code_t': variant_codes,
- 'search_rank_i': template.search_rank,
- 'search_rank_weekly_i': template.search_rank_weekly,
- 'category_id_i': category_id,
- 'category_name_s': category_name,
- 'category_name': category_name,
- })
- solr.add([document])
- self.change_solr_data('Perubahan pada data product')
-
+
class ProductProduct(models.Model):
_inherit = "product.product"
web_price = fields.Float(
@@ -329,13 +287,14 @@ class ProductProduct(models.Model):
qty_onhand_bandengan = fields.Float(string='Qty Incoming Bandengan', compute='_get_qty_onhand_bandengan')
qty_incoming_bandengan = fields.Float(string='Qty Incoming Bandengan', compute='_get_qty_incoming_bandengan')
sla_version = fields.Integer(string="SLA Version", default=0)
- last_update_solr = fields.Datetime(string='Last Update Solr')
- desc_update_solr = fields.Char(string='Desc Update Solr')
- def change_solr_data(self, desc):
- current_time = datetime.now()
- self.desc_update_solr = desc
- self.last_update_solr = current_time
+ @api.constrains('name')
+ def _validate_name(self):
+ pattern = r'^[a-zA-Z0-9\[\]\(\)\.\s/%]+$'
+ if not re.match(pattern, self.name):
+ pattern_suggest = r'[a-zA-Z0-9\[\]\(\)\.\s/%]+'
+ 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}')
def _get_qty_incoming_bandengan(self):
for product in self:
@@ -356,6 +315,14 @@ class ProductProduct(models.Model):
qty = sum(qty_onhand.mapped('quantity'))
product.qty_onhand_bandengan = qty
+ # def write(self, vals):
+ # if 'solr_flag' not in vals:
+ # for variant in self:
+ # if variant.solr_flag == 1:
+ # variant.product_tmpl_id.solr_flag = 2
+ # vals['solr_flag'] = 2
+ # return super().write(vals)
+
def _compute_web_price(self):
for product in self:
product_pricelist_item = self.env['product.pricelist.item'].search(
@@ -379,57 +346,4 @@ class ProductProduct(models.Model):
('start_date', '<=', current_time),
('end_date', '>=', current_time)
], limit=1)
- return pricelist
-
- @api.constrains(
- 'name',
- 'default_code',
- 'virtual_rating',
- 'weight',
- 'x_manufacture',
- 'public_categ_ids',
- 'product_tmpl_id.default_code',
- 'product_tmpl_id.image_1920',
- 'search_rank',
- 'search_rank_weekly',
- 'image_1920'
- )
- def _sync_variants_to_solr(self):
- variant = self
- if not variant.product_tmpl_id.active and variant.product_tmpl_id.type != 'product':
- return
-
- category_id = 0
- category_name = ''
- for category in variant.product_tmpl_id.public_categ_ids:
- category_id = category.id
- category_name = category.name
- break
-
- solr_model = self.env['apache.solr']
- solr = solr_model.connect('variants')
- document = solr_model.get_single_doc('variants', variant.id)
- document.update({
- 'id': variant.id,
- 'display_name_s': variant.display_name,
- 'name_s': variant.name,
- 'default_code_s': variant.default_code or '',
- 'product_rating_f': variant.product_tmpl_id.virtual_rating,
- 'product_id_i': variant.id,
- 'template_id_i': variant.product_tmpl_id.id,
- 'image_s': self.env['ir.attachment'].api_image('product.template', 'image_512', variant.product_tmpl_id.id),
- 'stock_total_f': variant.qty_stock_vendor,
- 'weight_f': variant.product_tmpl_id.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 '',
- 'image_promotion_1_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_1', variant.product_tmpl_id.x_manufacture.id),
- 'image_promotion_2_s': self.env['ir.attachment'].api_image('x_manufactures', 'image_promotion_2', variant.product_tmpl_id.x_manufacture.id),
- 'category_id_i': category_id,
- 'category_name_s': category_name,
- 'category_name': category_name,
- 'search_rank_i': variant.product_tmpl_id.search_rank,
- 'search_rank_weekly_i': variant.product_tmpl_id.search_rank_weekly,
- })
- solr.add([document])
- self.change_solr_data('Perubahan pada data product') \ No newline at end of file
+ return pricelist \ No newline at end of file
diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py
index c968ed53..3fb61955 100755
--- a/indoteknik_custom/models/purchase_order.py
+++ b/indoteknik_custom/models/purchase_order.py
@@ -2,7 +2,13 @@ from odoo import fields, models, api, _
from odoo.exceptions import AccessError, UserError, ValidationError
from datetime import datetime, timedelta
import logging
-from pytz import timezone
+from pytz import timezone, utc
+import io
+import base64
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
_logger = logging.getLogger(__name__)
@@ -43,7 +49,7 @@ class PurchaseOrder(models.Model):
def add_product_to_pricelist(self):
for line in self.order_line:
- current_time = fields.Datetime.now(timezone('Asia/Jakarta')).strftime('%Y-%m-%d %H:%M:%S')
+ current_time = datetime.utcnow()
purchase_pricelist = self.env['purchase.pricelist'].search([
('product_id', '=', line.product_id.id),
@@ -224,7 +230,8 @@ class PurchaseOrder(models.Model):
raise UserError("Terdapat barang yang tidak bisa diproses")
if line.product_id:
self.add_product_to_pricelist()
- if line.price_unit != line.price_vendor:
+ if line.price_unit != line.price_vendor and line.price_vendor != 0:
+ self._send_po_not_sync()
send_email = True
break
@@ -244,9 +251,67 @@ class PurchaseOrder(models.Model):
return res
+ def _send_po_not_sync(self):
+ # Mengirim data ke model Po Sync Price jika harga po dan purchase pricelist tidak singkron
+ for line in self.order_line:
+ if line.price_unit != line.price_vendor and line.price_vendor != 0:
+ self.env['po.sync.price'].create([{
+ 'order_line_id': line.id,
+ }])
+
+
+
def _send_mail(self):
- template_id = self.env.ref('indoteknik_custom.mail_template_po_sync_price').id
- template = self.env['mail.template'].browse(template_id)
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ worksheet = workbook.add_worksheet()
+
+ format6 = workbook.add_format({'font_size': 12, 'align': 'center', 'bg_color': '#D3D3D3', 'bold': True})
+ format1 = workbook.add_format({'font_size': 11, 'align': 'center', 'valign': 'vcenter'})
+
+ worksheet.set_column(0, 0, 10)
+ worksheet.set_column(1, 1, 20)
+ worksheet.set_column(2, 2, 20)
+ worksheet.set_column(3, 3, 20)
+ worksheet.set_column(4, 4, 15)
+ worksheet.set_column(5, 5, 15)
+
+ worksheet.write('A1', 'PO', format6)
+ worksheet.write('B1', 'SKU', format6)
+ worksheet.write('C1', 'Product', format6)
+ worksheet.write('D1', 'Brand', format6)
+ worksheet.write('E1', 'PO Price', format6)
+ worksheet.write('F1', 'Purchase Pricelist', format6)
+ worksheet.write('G1', 'Created On', format6)
+
+ row_number = 1
+ po_sync = self.env['po.sync.price'].search([], order='create_date desc')
+ for po in po_sync:
+ worksheet.write(row_number, 0, po.order_line_id.order_id.name, format1)
+ worksheet.write(row_number, 1, po.order_line_id.product_id.default_code, format1)
+ worksheet.write(row_number, 2, po.order_line_id.product_id.name, format1)
+ worksheet.write(row_number, 3, po.order_line_id.product_id.x_manufacture.x_name, format1)
+ worksheet.write(row_number, 4, po.order_line_id.price_unit, format1)
+ worksheet.write(row_number, 5, po.order_line_id.price_vendor, format1)
+ worksheet.write(row_number, 6, po.create_date.replace(tzinfo=utc).astimezone(timezone('Asia/Jakarta')).strftime('%Y-%m-%d %H:%M:%S'), format1)
+ row_number += 1
+
+ workbook.close()
+
+ output.seek(0)
+
+ template = self.env.ref('indoteknik_custom.mail_template_po_sync_price')
+ template.attachment_ids.unlink()
+ attachment_vals = {
+ 'name': 'Purchase Order.xlsx',
+ 'datas': base64.b64encode(output.read()),
+ 'mimetype': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'res_model': 'mail.template',
+ 'res_id': template.id,
+ }
+ attachment_id = self.env['ir.attachment'].create(attachment_vals)
+
+ template.attachment_ids = [(4, attachment_id.id)]
template.send_mail(self.id, force_send=True)
def po_approve(self):
diff --git a/indoteknik_custom/models/sale_monitoring_detail.py b/indoteknik_custom/models/sale_monitoring_detail.py
index 43a8aeb0..dc4caa14 100755
--- a/indoteknik_custom/models/sale_monitoring_detail.py
+++ b/indoteknik_custom/models/sale_monitoring_detail.py
@@ -55,7 +55,7 @@ class SaleMonitoringDetail(models.Model):
get_qty_received(so.id, sol.product_id) AS qty_po_received,
get_qty_reserved(so.id, sol.product_id) as qty_reserved,
sol.note_procurement as note
- FROM sale_order so
+ FROM sale_order so
JOIN sale_order_line sol ON sol.order_id = so.id
JOIN product_product p ON p.id = sol.product_id
JOIN product_template pt ON pt.id = p.product_tmpl_id
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index ca98cde4..a0bc54b8 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -1,6 +1,6 @@
from odoo import fields, models, api, _
from odoo.exceptions import UserError
-import logging, random, string, requests, math, json, re
+import logging, random, string, requests, math, json, re
_logger = logging.getLogger(__name__)
@@ -342,7 +342,7 @@ class SaleOrder(models.Model):
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
- 'params': { 'title': title, 'message': message }
+ 'params': { 'title': title, 'message': message, 'next': {'type': 'ir.actions.act_window_close'} },
}
def _set_sppkp_npwp_contact(self):
diff --git a/indoteknik_custom/models/stock_vendor.py b/indoteknik_custom/models/stock_vendor.py
index 075b63d2..f214a5e1 100755
--- a/indoteknik_custom/models/stock_vendor.py
+++ b/indoteknik_custom/models/stock_vendor.py
@@ -50,3 +50,9 @@ class StockVendor(models.Model):
for template in templates:
template.virtual_qty = template.qty_stock_vendor or 0
_logger.info("Update Stock Product Template %s : %s" % (template.id, template.virtual_qty))
+
+ # @api.onchange('quantity')
+ # def update_solr_flag(self):
+ # for stock in self:
+ # if stock.product_variant_id.product_tmpl_id.solr_flag == 1:
+ # stock.product_variant_id.product_tmpl_id.solr_flag = 2
diff --git a/indoteknik_custom/models/website_categories_homepage.py b/indoteknik_custom/models/website_categories_homepage.py
index 2f5b3d92..a0fc1011 100644
--- a/indoteknik_custom/models/website_categories_homepage.py
+++ b/indoteknik_custom/models/website_categories_homepage.py
@@ -1,5 +1,4 @@
-from odoo import fields, models, api
-import json
+from odoo import fields, models
class WebsiteCategoriesHomepage(models.Model):
@@ -14,31 +13,4 @@ class WebsiteCategoriesHomepage(models.Model):
('tayang', 'Tayang'),
('tidak_tayang', 'Tidak Tayang')
], string='Status')
- product_ids = fields.Many2many('product.template', string='Product category')
-
-
- @api.constrains('category_id', 'image', 'url', 'sequence', 'status', 'product_ids')
- def _sync_category_homepage_to_solr(self):
- solr_model = self.env['apache.solr']
- solr = solr_model.connect('product_category_homepage')
-
- for category in self:
- document = solr_model.get_single_doc(solr, category.id)
- result = [self.env['product.template'].api_single_response(x) for x in category.product_ids]
- products = json.dumps(result, indent=None)
-
- document.update({
- 'id': category.id,
- 'category_id_i': category.category_id.id,
- 'name_s': category.category_id.name,
- 'image_s': self.env['ir.attachment'].api_image('website.categories.homepage', 'image', category.id),
- 'sequence_i': category.sequence or '',
- 'url_s': category.url or '',
- 'products_s': products,
- })
- solr.add([document])
-
- def sync_to_solr(self):
- categories_ids = self.env.context.get('active_ids', [])
- categories = self.env['website.categories.homepage'].search([('id', 'in', categories_ids)])
- categories._sync_category_homepage_to_solr()
+ product_ids = fields.Many2many('product.template', string='Product Template')
diff --git a/indoteknik_custom/models/x_manufactures.py b/indoteknik_custom/models/x_manufactures.py
index 1d0870a5..e48a5367 100755
--- a/indoteknik_custom/models/x_manufactures.py
+++ b/indoteknik_custom/models/x_manufactures.py
@@ -72,3 +72,13 @@ class XManufactures(models.Model):
variant.solr_flag = 2
_logger.info("Reset Solr Flag variant to 2 %s" % variant.id)
manufacture.cache_reset_status = 'done'
+
+ @api.onchange('x_name','image_promotion_1','image_promotion_2')
+ def update_solr_flag(self):
+ for manufacture in self:
+ templates = self.env['product.template'].search([
+ ('x_manufacture', '=', manufacture.id)
+ ])
+ for template in templates:
+ if template.solr_flag == 1:
+ template.solr_flag = 2
diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv
index 6f9ba9e4..c5dbdb19 100755
--- a/indoteknik_custom/security/ir.model.access.csv
+++ b/indoteknik_custom/security/ir.model.access.csv
@@ -67,3 +67,5 @@ access_account_move_multi_update,access.account.move.multi_update,model_account_
access_airway_bill,access.airway.bill,model_airway_bill,,1,1,1,1
access_airway_bill_manifest,access.airway.bill.manifest,model_airway_bill_manifest,,1,1,1,1
access_price_group,access.price.group,model_price_group,,1,1,1,1
+access_po_sync_price,access.po.sync.price,model_po_sync_price,,1,1,1,1
+access_product_attribute_value,access.product.attribute.value,model_product_attribute_value,,1,1,1,1
diff --git a/indoteknik_custom/views/mail_template_po.xml b/indoteknik_custom/views/mail_template_po.xml
index 02053767..f4eb3577 100644
--- a/indoteknik_custom/views/mail_template_po.xml
+++ b/indoteknik_custom/views/mail_template_po.xml
@@ -12,69 +12,43 @@
style="padding-top: 16px; background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;">
<tr>
<td align="center">
- <table border="0" cellpadding="0" cellspacing="0" width="590"
- style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;">
- <tbody>
- <!-- HEADER -->
- <tr>
- <td align="center" style="min-width: 590px;">
- <table border="0" cellpadding="0" cellspacing="0" width="590"
- style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;">
- <tr>
- <td valign="middle">
- <span style="font-size: 10px;">PO</span><br />
- <span style="font-size: 20px; font-weight: bold;">
- ${object.name}
- </span>
- </td>
- </tr>
- <tr>
- <td colspan="2" style="text-align:center;">
- <hr width="100%"
- style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;" />
- </td>
- </tr>
- </table>
- </td>
- </tr>
- <!-- CONTENT -->
- <tr>
- <td align="center" style="min-width: 590px;">
- <table border="0" cellpadding="0" cellspacing="0" width="590"
- style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;">
- <tr>
- <td valign="top" style="font-size: 13px;">
- <div>
- Dear Stefanus Darren &amp; Tyas K Putra,
- <br/><br/>
- Terdapat PO yang harga Unit Price nya tidak sama dengan yang ada di purchase pricelist nya.
- <br/><br/>
- Berikut adalah rincian PO:
- % for line in object.order_line:
- % if line.price_unit != line.price_vendor
- <ul>
- <li>Nama Produk: ${line.product_id.name}</li>
- <li>Harga Unit dalam PO: Rp ${'{:,.2f}'.format(line.price_unit)}</li>
- <li>Harga Unit dalam Purchase Pricelist: Rp ${'{:,.2f}'.format(line.price_vendor)}</li>
- </ul>
- % endif
- % endfor
- Silahkan periksa dan lakukan koreksi jika diperlukan.
- <br/><br/>
- Terima kasih.
- </div>
- </td>
- </tr>
- <tr>
- <td style="text-align:center;">
- <hr width="100%"
- style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 16px 0px;" />
- </td>
- </tr>
- </table>
- </td>
- </tr>
- </tbody>
+ <table border="0" cellpadding="0" cellspacing="0" width="100%"
+ style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse: separate;">
+ <tr>
+ <td valign="top" style="font-size: 13px;">
+ <div>
+ Dear Stefanus Darren &amp; Tyas K Putra,
+ <br /><br />
+ Terdapat PO yang harga Unit Price nya tidak sama dengan yang ada di purchase pricelist nya.
+ <br /><br />
+ Berikut adalah rincian PO:
+ </div>
+ <table border="1" cellpadding="5" cellspacing="0"
+ style="border-collapse: collapse; width: 100%; font-size: 13px;">
+ <tr>
+ <th>Nama Produk</th>
+ <th>Brand</th>
+ <th>Harga Unit dalam PO</th>
+ <th>Harga Unit dalam Purchase Pricelist</th>
+ </tr>
+ % for line in object.order_line:
+ % if line.price_vendor != 0 and line.price_unit != line.price_vendor
+ <tr>
+ <td>${line.product_id.name}</td>
+ <td>${line.product_id.x_manufacture.x_name}</td>
+ <td>Rp ${'{:,.2f}'.format(line.price_unit)}</td>
+ <td>Rp ${'{:,.2f}'.format(line.price_vendor)}</td>
+ </tr>
+ % endif
+ % endfor
+ </table>
+ <div>
+ Silahkan periksa dan lakukan koreksi jika diperlukan.
+ <br /><br />
+ Terima kasih.
+ </div>
+ </td>
+ </tr>
</table>
</td>
</tr>
diff --git a/indoteknik_custom/views/procurement_monitoring_detail.xml b/indoteknik_custom/views/procurement_monitoring_detail.xml
index 8f3827c1..e4939213 100644
--- a/indoteknik_custom/views/procurement_monitoring_detail.xml
+++ b/indoteknik_custom/views/procurement_monitoring_detail.xml
@@ -17,10 +17,11 @@
<field name="po_ids" widget="many2many_tags"/>
<field name="qty_po"/>
<field name="status"
- widget="badge"
- decoration-danger="status == 'harus beli'"
- decoration-success="status == 'cukup'"
+ widget="badge"
+ decoration-danger="status == 'harus beli'"
+ decoration-success="status == 'cukup'"
/>
+ <field name="note" optional="hide"/>
</tree>
</field>
</record>
diff --git a/indoteknik_custom/views/product_pricelist.xml b/indoteknik_custom/views/product_pricelist.xml
index 55139a24..34876cc4 100644
--- a/indoteknik_custom/views/product_pricelist.xml
+++ b/indoteknik_custom/views/product_pricelist.xml
@@ -25,4 +25,12 @@
</page>
</field>
</record>
+
+ <record id="product_pricelist_sync_product_solr_ir_actions_server" model="ir.actions.server">
+ <field name="name">Sync Product to SOLR</field>
+ <field name="model_id" ref="product.model_product_pricelist"/>
+ <field name="binding_model_id" ref="product.model_product_pricelist"/>
+ <field name="state">code</field>
+ <field name="code">action = records.update_product_solr_flag()</field>
+ </record>
</odoo> \ No newline at end of file
diff --git a/indoteknik_custom/views/product_template.xml b/indoteknik_custom/views/product_template.xml
index 82b7ce4d..558805b1 100755
--- a/indoteknik_custom/views/product_template.xml
+++ b/indoteknik_custom/views/product_template.xml
@@ -9,8 +9,6 @@
<field name="categ_id" position="after">
<field name="web_tax_id"/>
<field name="x_manufacture"/>
- <field name="desc_update_solr"/>
- <field name="last_update_solr"/>
<field name="x_model_product"/>
<field name="x_studio_field_tGhJR" widget="many2many_tags"/>
</field>
diff --git a/indoteknik_custom/views/website_categories_homepage.xml b/indoteknik_custom/views/website_categories_homepage.xml
index 0a3f684b..0a7ef2c2 100644
--- a/indoteknik_custom/views/website_categories_homepage.xml
+++ b/indoteknik_custom/views/website_categories_homepage.xml
@@ -49,14 +49,6 @@
</field>
</record>
- <record id="website_categories_homepage_ir_actions_server" model="ir.actions.server">
- <field name="name">Sync To Solr</field>
- <field name="model_id" ref="indoteknik_custom.model_website_categories_homepage"/>
- <field name="binding_model_id" ref="indoteknik_custom.model_website_categories_homepage"/>
- <field name="state">code</field>
- <field name="code">model.sync_to_solr()</field>
- </record>
-
<menuitem
id="website_categories_homepage"
name="Website Categories Homepage"