summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indoteknik_api/controllers/api_v1/product.py48
-rwxr-xr-xindoteknik_custom/__manifest__.py1
-rwxr-xr-xindoteknik_custom/models/__init__.py2
-rw-r--r--indoteknik_custom/models/account_move.py17
-rw-r--r--indoteknik_custom/models/account_move_due_extension.py142
-rw-r--r--indoteknik_custom/models/automatic_purchase.py7
-rw-r--r--indoteknik_custom/models/product_sla.py87
-rwxr-xr-xindoteknik_custom/models/product_template.py66
-rwxr-xr-xindoteknik_custom/models/purchase_order.py10
-rw-r--r--indoteknik_custom/models/res_partner.py9
-rwxr-xr-xindoteknik_custom/models/sale_order.py43
-rw-r--r--indoteknik_custom/models/token_storage.py9
-rwxr-xr-xindoteknik_custom/security/ir.model.access.csv4
-rw-r--r--indoteknik_custom/views/account_move.xml25
-rw-r--r--indoteknik_custom/views/account_move_views.xml3
-rw-r--r--indoteknik_custom/views/product_sla.xml59
-rwxr-xr-xindoteknik_custom/views/purchase_order.xml7
-rw-r--r--indoteknik_custom/views/res_partner.xml1
18 files changed, 454 insertions, 86 deletions
diff --git a/indoteknik_api/controllers/api_v1/product.py b/indoteknik_api/controllers/api_v1/product.py
index 54b039c7..8803bae3 100644
--- a/indoteknik_api/controllers/api_v1/product.py
+++ b/indoteknik_api/controllers/api_v1/product.py
@@ -4,6 +4,7 @@ from odoo.http import request
from datetime import datetime, timedelta
import ast
import logging
+import math
_logger = logging.getLogger(__name__)
@@ -11,6 +12,49 @@ _logger = logging.getLogger(__name__)
class Product(controller.Controller):
prefix = '/api/v1/'
+ @http.route(prefix + 'product_variant/<id>/stock', auth='public', methods=['GET', 'OPTIONS'])
+ @controller.Controller.must_authorized()
+ def get_product_template_stock_by_id(self, **kw):
+ id = int(kw.get('id'))
+ product = request.env['product.product'].search([('id', '=', id)], limit=1)
+ product_sla = request.env['product.sla'].search([('product_variant_id', '=', id)], limit=1)
+
+ qty_available = product.qty_onhand_bandengan
+ qty_available -= 10
+ if qty_available < 10:
+ qty_available = 0
+
+ qty = 0
+ sla_date = '-'
+
+ is_altama_product = product.x_manufacture.id in [10,122,89]
+ if is_altama_product:
+ try:
+ qty_altama = request.env['product.template'].get_stock_altama(product.default_code)
+ qty_altama -= int(qty_altama * 0.1)
+ qty_altama = math.ceil(float(qty_altama))
+ qty = qty_altama
+ if qty_available > 10:
+ qty += qty_available
+ sla_date = '1 Hari'
+ elif qty_altama > 0:
+ sla_date = '2-4 Hari'
+ else:
+ sla_date = 'Indent'
+ except:
+ print('error')
+ else:
+ qty = qty_available
+ sla_date = product_sla.sla or '-'
+
+ data = {
+ 'qty': qty,
+ 'sla_date': sla_date,
+ }
+
+ return self.response(data, headers=[('Cache-Control', 'max-age=180, private')])
+
+
@http.route(prefix + 'product/template/price/<id>', auth='public', methods=['GET', 'OPTIONS'])
def get_product_template_price_by_id(self, **kw):
if not self.authenticate():
@@ -54,7 +98,7 @@ class Product(controller.Controller):
if not self.authenticate():
return self.response(code=401, description='Unauthorized')
id = kw.get('id')
- partner_id = int(kw.get('partner_id', 0))
+ partner_id = int(kw.get('partner_id', 0))
product_product = request.env['product.product'].search([('id', '=', id)], limit=1)
data = {
@@ -90,7 +134,7 @@ class Product(controller.Controller):
# ('create_date', '>=', delta_time),
]
new_products = request.env['product.template'].search(query_products, order='create_date desc', limit=limit_new_products)
- brands = []
+ brands = []
for product in new_products:
brands.append(product.x_manufacture)
brands = list(dict.fromkeys(brands))
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index 5b0c4e41..4fa736f6 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -77,6 +77,7 @@
'views/brand_vendor.xml',
'views/requisition.xml',
'views/landedcost.xml',
+ 'views/product_sla.xml',
'views/voucher.xml',
'report/report.xml',
'report/report_banner_banner.xml',
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py
index 3a27072c..9e4d2cf9 100755
--- a/indoteknik_custom/models/__init__.py
+++ b/indoteknik_custom/models/__init__.py
@@ -63,5 +63,7 @@ from . import procurement_monitoring_detail
from . import brand_vendor
from . import manufacturing
from . import requisition
+from . import token_storage
+from . import product_sla
from . import account_move_due_extension
from . import voucher \ No newline at end of file
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index c2e93632..bc6061ee 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -1,6 +1,9 @@
from odoo import models, api, fields
from odoo.exceptions import AccessError, UserError, ValidationError
from datetime import timedelta, date
+import logging
+
+_logger = logging.getLogger(__name__)
class AccountMove(models.Model):
@@ -13,6 +16,17 @@ class AccountMove(models.Model):
resi_tukar_faktur = fields.Char(string='Resi Faktur')
date_terima_tukar_faktur = fields.Date(string='Terima Faktur')
shipper_faktur_id = fields.Many2one('delivery.carrier', string='Shipper Faktur')
+ due_extension = fields.Integer(string='Due Extension', default=0)
+ new_due_date = fields.Date(string='New Due')
+ counter = fields.Integer(string="Counter", default=0)
+ due_line = fields.One2many('due.extension.line', 'invoice_id', compute='_compute_due_line', string='Due Extension Lines')
+
+ def _compute_due_line(self):
+ for invoice in self:
+ invoice.due_line = self.env['due.extension.line'].search([
+ ('invoice_id', '=', invoice.id),
+ ('due_id.approval_status', '=', 'approved')
+ ])
def unlink(self):
res = super(AccountMove, self).unlink()
@@ -70,6 +84,8 @@ class AccountMove(models.Model):
invoice_day_to_due = 0
if invoice.payment_state not in ['paid', 'in_payment', 'reversed'] and invoice.invoice_date_due:
invoice_day_to_due = invoice.invoice_date_due - date.today()
+ if invoice.new_due_date:
+ invoice_day_to_due = invoice.new_due_date - date.today()
invoice_day_to_due = invoice_day_to_due.days
invoice.invoice_day_to_due = invoice_day_to_due
@@ -98,3 +114,4 @@ class AccountMove(models.Model):
add_days += line.days
due_date = tukar_date + timedelta(days=add_days)
invoice.invoice_date_due = due_date
+ \ No newline at end of file
diff --git a/indoteknik_custom/models/account_move_due_extension.py b/indoteknik_custom/models/account_move_due_extension.py
index 93dfe62b..43207534 100644
--- a/indoteknik_custom/models/account_move_due_extension.py
+++ b/indoteknik_custom/models/account_move_due_extension.py
@@ -27,6 +27,11 @@ class DueExtension(models.Model):
('7', '7 Hari'),
('14', '14 Hari'),
], string='Day Extension', help='Menambah Due Date yang sudah limit dari hari ini', tracking=True)
+ counter = fields.Integer(string="Counter", compute='_compute_counter')
+
+ def _compute_counter(self):
+ for due in self:
+ due.counter = due.partner_id.counter
@api.model
def create(self, vals):
@@ -57,67 +62,69 @@ class DueExtension(models.Model):
raise UserError('Hanya Finance yang bisa cancel')
def approve_new_due(self):
- if self.env.user.is_accounting:
- self.is_approve = True
- self.approval_status = 'approved'
+ if not self.env.user.is_accounting:
+ raise UserError('Hanya Finance Yang Bisa Approve')
+
+ if self.approval_status == 'approved':
+ raise UserError('Document ini sudah di approve')
+
+ self.is_approve = True
+ self.approval_status = 'approved'
- if self.partner_id:
- if self.day_extension:
- day_extension = int(self.day_extension)
- new_due = date.today() + timedelta(days=day_extension)
-
- for line in self.due_line:
- line.invoice_id.invoice_date_due = new_due
-
- if self.order_id._notification_margin_leader():
- self.order_id.approval_status = 'pengajuan2'
- return self.order_id._notification_has_margin_leader()
+ self.partner_id.counter+=1
- if self.order_id._notification_margin_manager():
- self.order_id.approval_status = 'pengajuan1'
- return self.order_id._notification_has_margin_manager()
+ day_extension = int(self.day_extension)
+ if self.partner_id:
+ new_due = date.today() + timedelta(days=day_extension)
- sales = self.env['sale.order'].search([
- ('id', '=', self.order_id.id)
- ])
-
- # sales.state = 'sale'
- sales.action_confirm()
- self.order_id.due_id = self.id
- else:
- raise UserError('Hanya Finance Yang Bisa Approve')
+ for line in self.due_line:
+ line.invoice_id.new_due_date = new_due
+ line.invoice_id.due_extension = day_extension
+
+ if self.order_id._notification_margin_leader():
+ self.order_id.approval_status = 'pengajuan2'
+ return self.order_id._notification_has_margin_leader()
+
+ if self.order_id._notification_margin_manager():
+ self.order_id.approval_status = 'pengajuan1'
+ return self.order_id._notification_has_margin_manager()
+
+ sales = self.env['sale.order'].browse(self.order_id.id)
+
+ sales.action_confirm()
+ self.order_id.due_id = self.id
def generate_due_line(self):
- partners = []
- partners += self.partner_id.child_ids
- partners.append(self.partner_id)
-
-
- for partner in partners:
- query = [
- ('partner_id', '=', partner.id),
- ('state', '=', 'posted'),
- ('move_type', '=', 'out_invoice'),
- ('amount_residual_signed', '>', 0)
- ]
- invoices = self.env['account.move'].search(query, order='invoice_date')
- count = 0
-
- for invoice in invoices:
- if invoice.invoice_day_to_due < 0:
- self.env['due.extension.line'].create([{
- 'due_id': self.id,
- 'partner_id': invoice.partner_id.id,
- 'invoice_id': invoice.id,
- 'date_invoice': invoice.invoice_date,
- 'efaktur_id': invoice.efaktur_id.id,
- 'reference': invoice.ref,
- 'total_amt': invoice.amount_total,
- 'open_amt': invoice.amount_residual_signed,
- 'due_date': invoice.invoice_date_due
- }])
- count += 1
- _logger.info("Due Extension Line generated %s" % count)
+ partners = self.partner_id.get_child_ids()
+
+ query = [
+ ('partner_id', 'in', partners),
+ ('state', '=', 'posted'),
+ ('move_type', '=', 'out_invoice'),
+ ('amount_residual_signed', '>', 0)
+ ]
+ invoices = self.env['account.move'].search(query, order='invoice_date')
+ count = 0
+
+ for invoice in invoices:
+ day_to_due = invoice.invoice_day_to_due + invoice.due_extension
+ if day_to_due < 0:
+ self.env['due.extension.line'].create([{
+ 'due_id': self.id,
+ 'partner_id': invoice.partner_id.id,
+ 'invoice_id': invoice.id,
+ 'date_invoice': invoice.invoice_date,
+ 'efaktur_id': invoice.efaktur_id.id,
+ 'reference': invoice.ref,
+ 'total_amt': invoice.amount_total,
+ 'open_amt': invoice.amount_residual_signed
+ }])
+ count += 1
+ invoice.counter+=1
+
+ _logger.info("Due Extension Line generated %s" % count)
+
+
def unlink(self):
res = super(DueExtension, self).unlink()
if not self._name == 'due.extension':
@@ -131,6 +138,12 @@ class DueExtensionLine(models.Model):
_order = 'due_id, id'
due_id = fields.Many2one('due.extension', string='Due Ref', required=True, ondelete='cascade', index=True, copy=False)
+ due_description = fields.Text(string="Description", compute="_compute_due_description")
+ due_approval_status = fields.Selection([
+ ('pengajuan', 'Pengajuan'),
+ ('approved', 'Approved'),
+ ], string="Approval Status", compute="_compute_due_approval_status")
+ due_day_extension = fields.Char(string="Day Extension", compute="_compute_due_day_extension")
partner_id = fields.Many2one('res.partner', string='Customer')
invoice_id = fields.Many2one('account.move', string='Invoice')
date_invoice = fields.Date(string='Invoice Date')
@@ -141,11 +154,26 @@ class DueExtensionLine(models.Model):
due_date = fields.Date(string='Due Date', compute="_compute_due_date")
day_to_due = fields.Integer(string='Day To Due', compute="_compute_day_to_due")
+ def _compute_due_description(self):
+ for line in self:
+ line.due_description = line.due_id.description
+
+ def _compute_due_approval_status(self):
+ for line in self:
+ line.due_approval_status = line.due_id.approval_status
+
+ def _compute_due_day_extension(self):
+ for line in self:
+ line.due_day_extension = line.due_id.day_extension
+
def _compute_day_to_due(self):
for line in self:
line.day_to_due = line.invoice_id.invoice_day_to_due
def _compute_due_date(self):
for line in self:
- line.due_date = line.invoice_id.invoice_date_due
+ if line.invoice_id.new_due_date:
+ line.due_date = line.invoice_id.new_due_date
+ else:
+ line.due_date = line.invoice_id.invoice_date_due
diff --git a/indoteknik_custom/models/automatic_purchase.py b/indoteknik_custom/models/automatic_purchase.py
index 87319bf6..e21b411d 100644
--- a/indoteknik_custom/models/automatic_purchase.py
+++ b/indoteknik_custom/models/automatic_purchase.py
@@ -59,11 +59,18 @@ class AutomaticPurchase(models.Model):
# new_po = self.env['purchase.order'].create([param_header])
brand_id = product.brand_id.id
count += 10
+
+ qty_available = product.product_id.qty_onhand_bandengan + product.product_id.qty_incoming_bandengan - product.product_id.outgoing_qty
+ suggest = 'harus beli'
+ if qty_available > product.qty_purchase:
+ suggest = 'masih cukup'
param_line = {
'order_id': new_po.id,
'sequence': count,
'product_id': product.product_id.id,
'product_qty': product.qty_purchase,
+ 'qty_available_store': qty_available,
+ 'suggest': suggest,
'product_uom_qty': product.qty_purchase,
'price_unit': product.last_price,
}
diff --git a/indoteknik_custom/models/product_sla.py b/indoteknik_custom/models/product_sla.py
new file mode 100644
index 00000000..f969502f
--- /dev/null
+++ b/indoteknik_custom/models/product_sla.py
@@ -0,0 +1,87 @@
+from odoo import models, api, fields
+from odoo.exceptions import AccessError, UserError, ValidationError
+from datetime import timedelta, date
+import logging
+import math
+_logger = logging.getLogger(__name__)
+
+
+class ProductSla(models.Model):
+ _name = 'product.sla'
+ _description = 'Product Sla'
+ _rec_name = 'product_variant_id'
+
+ product_variant_id = fields.Many2one('product.product',string='Product')
+ avg_leadtime = fields.Char(string='AVG Leadtime', readonly=True)
+ leadtime = fields.Char(string='Leadtime', readonly=True)
+ sla = fields.Char(string='SLA', readonly=True)
+ version = fields.Integer(string="Version", compute="_compute_version")
+
+ def _compute_version(self):
+ for sla in self:
+ sla.version = sla.product_variant_id.sla_version
+
+ def generate_product_variant_id_sla(self, limit=5000):
+ # Filter produk non-Altama
+ products = self.env['product.product'].search([
+ ('x_manufacture', 'not in', [10, 122, 89]),
+ ('location_id', '=', 57),
+ ('stock_move_ids', '!=', False),
+ ], order='sla_version asc', limit=limit)
+
+ i = 1
+ for product in products:
+ _logger.info(f'Product SLA: {i}/{len(products)}')
+ i += 1
+ product.sla_version += 1
+
+ product_sla = self.search([('product_variant_id', '=', product.id)], limit=1)
+ if not product_sla:
+ product_sla = self.env['product.sla'].create({
+ 'product_variant_id': product.id,
+ })
+
+ product_sla.generate_product_sla()
+
+ def generate_product_sla(self):
+ self.avg_leadtime = '-'
+ self.sla = '-'
+
+ product = self.product_variant_id
+
+ qty_available = 0
+ qty_available = product.qty_onhand_bandengan
+ qty_available -= 10
+
+ if qty_available < 10:
+ qty_available = 0
+
+ if qty_available > 10:
+ self.sla = '1 Hari'
+
+ query = [
+ ('product_id', '=', product.id),
+ ('picking_id', '!=', False),
+ ('picking_id.location_id', '=', 57),
+ ('picking_id.state', 'not in', ['cancel'])
+ ]
+ picking = self.env['stock.move.line'].search(query)
+ leadtimes=[]
+ for stock in picking:
+ date_delivered = stock.picking_id.driver_departure_date
+ date_so_confirmed = stock.picking_id.sale_id.date_order
+ if date_delivered and date_so_confirmed:
+ leadtime = date_delivered - date_so_confirmed
+ leadtime_in_days = leadtime.days
+ leadtimes.append(leadtime_in_days)
+
+ if len(leadtimes) > 0:
+ avg_leadtime = sum(leadtimes) / len(leadtimes)
+ rounded_leadtime = math.ceil(avg_leadtime)
+ self.avg_leadtime = rounded_leadtime
+ if rounded_leadtime >= 1 and rounded_leadtime <= 5:
+ self.sla = '3-6 Hari'
+ elif rounded_leadtime >= 6 and rounded_leadtime <= 10:
+ self.sla = '4-12 Hari'
+ elif rounded_leadtime >= 11:
+ self.sla = 'Indent' \ No newline at end of file
diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py
index a4f8f031..1a83b702 100755
--- a/indoteknik_custom/models/product_template.py
+++ b/indoteknik_custom/models/product_template.py
@@ -2,6 +2,8 @@ from odoo import fields, models, api
from datetime import datetime, timedelta
from odoo.exceptions import AccessError, UserError, ValidationError
import logging
+import requests
+import json
_logger = logging.getLogger(__name__)
@@ -190,7 +192,70 @@ class ProductTemplate(models.Model):
product.product_rating = rate
product.last_calculate_rating = current_time
+ def _get_stock_website(self):
+ qty = self._get_stock_altama()
+ print(qty)
+ def get_stock_altama(self, item_code):
+ current_time = datetime.now()
+ current_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
+ query = [('source', '=', 'altama'), ('expired_date', '>', current_time)]
+ token_data = self.env['token.storage'].search(query, order='expired_date desc',limit=1)
+ if not token_data:
+ token_data = self._get_new_token_altama()
+ token = token_data['access_token']
+ else:
+ token = token_data.access_token
+
+ url = "https://erpapi.altama.co.id/erp/api/stock/buffer/btob"
+ auth = "Bearer "+token
+ headers = {
+ 'Content-Type': 'application/json',
+ 'Authorization': auth,
+ }
+ json_data = {
+ 'type_search': 'Item_code',
+ 'search_key':[item_code],
+ }
+ response = requests.post(url, headers=headers, json=json_data)
+ datas = json.loads(response.text)['data']
+ qty = 0
+ for data in datas:
+ availability = int(data['availability']) # Mengonversi ke tipe data int
+ qty += availability # Mengakumulasi qty dari setiap data
+
+ return qty
+
+ def _get_new_token_altama(self):
+ url = "https://kc.altama.co.id/realms/altama/protocol/openid-connect/token"
+ auth = 'Basic SW5kb3Rla25pa19DbGllbnQ6Vm1iZExER1ZUS3RuVlRQdkU1MXRvRzdiTW51TE1WRVI='
+ headers = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Authorization': auth,
+ }
+ data = {
+ 'grant_type': 'client_credentials',
+ }
+
+ response = requests.post(url, headers=headers, data=data).json()
+ lookup_json = json.dumps(response, indent=4, sort_keys=True)
+ token = json.loads(lookup_json)['access_token']
+ expires_in = json.loads(lookup_json)['expires_in']
+
+ current_time = datetime.now()
+ delta_time = current_time + timedelta(seconds=int(expires_in))
+
+ current_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
+ delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S')
+
+ values = {
+ 'source': 'altama',
+ 'access_token': token,
+ 'expires_in': expires_in,
+ 'expired_date': delta_time,
+ }
+ self.env['token.storage'].create([values])
+ return values
class ProductProduct(models.Model):
@@ -213,6 +278,7 @@ class ProductProduct(models.Model):
material = fields.Char(string='Material')
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)
def _get_qty_incoming_bandengan(self):
for product in self:
diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py
index 1eb76370..7091bb72 100755
--- a/indoteknik_custom/models/purchase_order.py
+++ b/indoteknik_custom/models/purchase_order.py
@@ -215,6 +215,16 @@ class PurchaseOrder(models.Model):
else:
self.approval_status = 'pengajuan1'
+ def re_calculate(self):
+ for line in self.order_line:
+ sale_order_line = self.env['sale.order.line'].search([
+ ('product_id', '=', line.product_id.id),
+ ('order_id', '=', line.order_id.sale_order_id.id)
+ ], limit=1, order='price_reduce_taxexcl')
+ for so_line in sale_order_line:
+ unit_price = line.price_unit
+ so_line.purchase_price = unit_price
+
def button_cancel(self):
res = super(PurchaseOrder, self).button_cancel()
self.approval_status = False
diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py
index bdeb8a2c..1695639d 100644
--- a/indoteknik_custom/models/res_partner.py
+++ b/indoteknik_custom/models/res_partner.py
@@ -18,6 +18,15 @@ class ResPartner(models.Model):
('nonpkp', 'Non PKP')
])
sppkp = fields.Char(string="SPPKP")
+ counter = fields.Integer(string="Counter", default=0)
+
+ def get_child_ids(self):
+ partner = self.env['res.partner'].search([('id', '=', self.id)], limit=1)
+ partner_child_ids = [x['id'] for x in partner.child_ids] + [partner.id]
+ if partner.parent_id:
+ partner_child_ids += [x['id'] for x in partner.parent_id.child_ids]
+ partner_child_ids += [partner.parent_id.id]
+ return partner_child_ids
def unlink(self):
if self._name == 'res.partner':
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 1bdc0cb6..e151bf22 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -8,6 +8,7 @@ import string
import requests
import math
import json
+from datetime import timedelta, date
_logger = logging.getLogger(__name__)
@@ -391,26 +392,28 @@ class SaleOrder(models.Model):
if self.due_id and self.due_id.is_approve == False:
raise UserError('Document Over Due Yang Anda Buat Belum Di Approve')
- if not self.env.user.is_leader and not self.env.user.is_sales_manager:
- query = [
- ('partner_id', '=', parent_id),
- ('state', '=', 'posted'),
- ('move_type', '=', 'out_invoice'),
- ('amount_residual_signed', '>', 0)
- ]
- invoices = self.env['account.move'].search(query, order='invoice_date')
- due_extension = self.env['due.extension'].create([{
- 'partner_id': parent_id,
- 'day_extension': '3',
- 'order_id': self.id,
- }])
- due_extension.generate_due_line()
- self.due_id = due_extension.id
- if len(self.due_id.due_line) > 0:
- return True
- else:
- due_extension.unlink()
- return False
+ query = [
+ ('partner_id', '=', parent_id),
+ ('state', '=', 'posted'),
+ ('move_type', '=', 'out_invoice'),
+ ('amount_residual_signed', '>', 0)
+ ]
+ invoices = self.env['account.move'].search(query, order='invoice_date')
+
+ if invoices:
+ if not self.env.user.is_leader and not self.env.user.is_sales_manager:
+ due_extension = self.env['due.extension'].create([{
+ 'partner_id': parent_id,
+ 'day_extension': '3',
+ 'order_id': self.id,
+ }])
+ due_extension.generate_due_line()
+ self.due_id = due_extension.id
+ if len(self.due_id.due_line) > 0:
+ return True
+ else:
+ due_extension.unlink()
+ return False
def _notification_margin_leader(self):
if self.total_percent_margin <= 15 and not self.env.user.is_leader:
diff --git a/indoteknik_custom/models/token_storage.py b/indoteknik_custom/models/token_storage.py
new file mode 100644
index 00000000..0eef7f20
--- /dev/null
+++ b/indoteknik_custom/models/token_storage.py
@@ -0,0 +1,9 @@
+from odoo import fields, models
+
+class TokenStorage(models.Model):
+
+ _name = 'token.storage'
+ source = fields.Char(string='Source')
+ access_token = fields.Char(string='Access Token')
+ expires_in = fields.Integer(string='Expires In')
+ expired_date = fields.Datetime(string='Expired Date')
diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv
index 7cacf2bb..2b269417 100755
--- a/indoteknik_custom/security/ir.model.access.csv
+++ b/indoteknik_custom/security/ir.model.access.csv
@@ -54,4 +54,6 @@ access_brand_vendor,access.brand.vendor,model_brand_vendor,,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
-access_voucher,access.voucher,model_voucher,,1,1,1,1 \ No newline at end of file
+access_token_storage,access.token_storage,model_token_storage,,1,1,1,1
+access_product_sla,access.product_sla,model_product_sla,,1,1,1,1
+access_voucher,access.voucher,model_voucher,,1,1,1,1
diff --git a/indoteknik_custom/views/account_move.xml b/indoteknik_custom/views/account_move.xml
index 9faf3149..a1d3eaaa 100644
--- a/indoteknik_custom/views/account_move.xml
+++ b/indoteknik_custom/views/account_move.xml
@@ -15,7 +15,21 @@
<field name="shipper_faktur_id"/>
<field name="resi_tukar_faktur"/>
<field name="date_terima_tukar_faktur"/>
+ <field name="due_extension"/>
+ <field name="counter"/>
</field>
+ <notebook position="inside">
+ <page string="Due Extension">
+ <field name="due_line">
+ <tree>
+ <field name="due_id"/>
+ <field name="due_description"/>
+ <field name="due_day_extension"/>
+ <field name="due_approval_status"/>
+ </tree>
+ </field>
+ </page>
+ </notebook>
</field>
</record>
@@ -30,13 +44,14 @@
</field>
<field name="invoice_date_due" position="after">
<field name="invoice_day_to_due" attrs="{'invisible': [['payment_state', 'in', ('paid', 'in_payment', 'reversed')]]}"/>
+ <field name="due_extension" optional="hide"/>
</field>
<field name="payment_state" position="after">
- <field name="invoice_payment_term_id"/>
- <field name="date_kirim_tukar_faktur"/>
- <field name="shipper_faktur_id" optional="1"/>
- <field name="resi_tukar_faktur" optional="1"/>
- <field name="date_terima_tukar_faktur"/>
+ <field name="invoice_payment_term_id" optional="hide"/>
+ <field name="date_kirim_tukar_faktur" optional="hide"/>
+ <field name="shipper_faktur_id" optional="hide"/>
+ <field name="resi_tukar_faktur" optional="hide"/>
+ <field name="date_terima_tukar_faktur" optional="hide"/>
</field>
</field>
</record>
diff --git a/indoteknik_custom/views/account_move_views.xml b/indoteknik_custom/views/account_move_views.xml
index 02926682..fee94b42 100644
--- a/indoteknik_custom/views/account_move_views.xml
+++ b/indoteknik_custom/views/account_move_views.xml
@@ -4,7 +4,7 @@
<field name="name">due.extension.tree</field>
<field name="model">due.extension</field>
<field name="arch" type="xml">
- <tree create="false">
+ <tree default_order="create_date desc" create="0">
<field name="number"/>
<field name="partner_id"/>
<field name="day_extension"/>
@@ -61,6 +61,7 @@
<group>
<field name="is_approve" readonly="1"/>
<field name="order_id" readonly="1"/>
+ <field name="counter" readonly="1"/>
<field name="approval_status" readonly="1"/>
</group>
</group>
diff --git a/indoteknik_custom/views/product_sla.xml b/indoteknik_custom/views/product_sla.xml
new file mode 100644
index 00000000..59d58568
--- /dev/null
+++ b/indoteknik_custom/views/product_sla.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+ <record id="product_sla_tree" model="ir.ui.view">
+ <field name="name">product.sla.tree</field>
+ <field name="model">product.sla</field>
+ <field name="arch" type="xml">
+ <tree create="false">
+ <field name="product_variant_id"/>
+ <field name="avg_leadtime"/>
+ <field name="sla"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="product_sla_form" model="ir.ui.view">
+ <field name="name">product.sla.form</field>
+ <field name="model">product.sla</field>
+ <field name="arch" type="xml">
+ <form>
+ <sheet string="Product Sla">
+ <group>
+ <group>
+ <field name="product_variant_id"/>
+ <field name="avg_leadtime"/>
+ <field name="sla"/>
+ <field name="version"/>
+ </group>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <record id="product_sla_action" model="ir.actions.act_window">
+ <field name="name">Product Sla</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">product.sla</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <record id="product_sla_generate_cron" model="ir.cron">
+ <field name="name">Product SLA: Generate</field>
+ <field name="interval_number">8</field>
+ <field name="interval_type">minutes</field>
+ <field name="numbercall">-1</field>
+ <field name="doall" eval="False"/>
+ <field name="model_id" ref="model_product_sla"/>
+ <field name="code">model.generate_product_variant_id_sla(limit=150)</field>
+ <field name="state">code</field>
+ <field name="priority">100</field>
+ <field name="active">True</field>
+ </record>
+
+ <menuitem id="menu_product_sla"
+ name="Product Sla"
+ action="product_sla_action"
+ parent="sale.product_menu_catalog"
+ sequence="7"/>
+</odoo> \ No newline at end of file
diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml
index 5b0c99ef..4efa8cf4 100755
--- a/indoteknik_custom/views/purchase_order.xml
+++ b/indoteknik_custom/views/purchase_order.xml
@@ -42,6 +42,11 @@
<field name="total_so_margin"/>
<field name="total_percent_margin"/>
<field name="total_so_percent_margin"/>
+ <button name="re_calculate"
+ string="Re Calculate"
+ type="object"
+ attrs="{'invisible': [('approval_status', '=', 'approved')]}"
+ />
</field>
<field name="product_id" position="before">
<field name="line_no" attrs="{'readonly': 1}" optional="hide"/>
@@ -59,6 +64,8 @@
</page>
<field name="fiscal_position_id" position="after">
<field name="note_description"/>
+ <field name="total_so_percent_margin"/>
+
</field>
</field>
</record>
diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml
index c77d942b..d609fdd5 100644
--- a/indoteknik_custom/views/res_partner.xml
+++ b/indoteknik_custom/views/res_partner.xml
@@ -8,6 +8,7 @@
<field name="arch" type="xml">
<field name="npwp" position="after">
<field name="sppkp"/>
+ <field name="counter"/>
<field name="reference_number"/>
</field>
<field name="industry_id" position="after">