summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIT Fixcomart <it@fixcomart.co.id>2022-10-04 13:42:30 +0700
committerIT Fixcomart <it@fixcomart.co.id>2022-10-04 13:42:30 +0700
commitc4f30a0164ada85a9a4a25cdd03ee7c4e42774a0 (patch)
tree30d246e2cdf3cb1925d88a039926fcd06f2ee82c
parentd1bc570eae2818bc4b535840f2eb3061b99ca98b (diff)
parent1d6351cbab4df3a5f5ceff92c53560437d7b40a4 (diff)
Merge commit '1d6351cbab4df3a5f5ceff92c53560437d7b40a4'
-rwxr-xr-xindoteknik_custom/__manifest__.py3
-rwxr-xr-xindoteknik_custom/models/__init__.py1
-rwxr-xr-xindoteknik_custom/models/purchase_order.py165
-rwxr-xr-xindoteknik_custom/models/purchase_order_line.py53
-rwxr-xr-xindoteknik_custom/models/sale_order.py297
-rw-r--r--indoteknik_custom/models/users.py10
-rwxr-xr-xindoteknik_custom/views/purchase_order.xml37
-rwxr-xr-xindoteknik_custom/views/sale_order.xml17
-rw-r--r--indoteknik_custom/views/users.xml17
9 files changed, 529 insertions, 71 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index 937fb0c9..0d6da7f1 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -38,10 +38,11 @@
'views/stock_location.xml',
'views/stock_picking.xml',
'views/stock_picking_type.xml',
+ 'views/users.xml',
'report/report.xml',
'report/report_banner_banner.xml',
'report/report_banner_banner2.xml',
- 'report/purchase_order.xml'
+ 'report/purchase_order.xml',
],
'demo': [],
'css': [],
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py
index e4913205..19916fd4 100755
--- a/indoteknik_custom/models/__init__.py
+++ b/indoteknik_custom/models/__init__.py
@@ -24,3 +24,4 @@ from . import stock_move
from . import stock_picking
from . import stock_picking_type
from . import delivery_order
+from . import users
diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py
index cb048182..54ef60af 100755
--- a/indoteknik_custom/models/purchase_order.py
+++ b/indoteknik_custom/models/purchase_order.py
@@ -1,11 +1,31 @@
-from odoo import fields, models, api
+from odoo import fields, models, api, _
+from odoo.exceptions import AccessError, UserError, ValidationError
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
sale_order_id = fields.Many2one('sale.order', string='Sale Order')
- procurement_status = fields.Char(string='Procurement Status', compute='get_procurement_status',readonly=True)
+ procurement_status = fields.Char(string='Procurement Status', compute='get_procurement_status', readonly=True)
+ approval_status = fields.Selection([
+ ('pengajuan1', 'Approval Manager'), #siapa? darren - 11
+ ('pengajuan2', 'Approval Pimpinan'), #akbar - 7 temporary not used
+ ('approved', 'Approved'),
+ ], string='Approval Status', readonly=True, copy=False, index=True, tracking=3)
+ delivery_amount = fields.Float('Delivery Amount', compute='compute_delivery_amount')
+ total_margin = fields.Float(
+ 'Margin', compute='compute_total_margin',
+ help="Total Margin in Sales Order Header")
+ total_percent_margin = fields.Float(
+ 'Margin%', compute='compute_total_margin',
+ help="Total % Margin in Sales Order Header")
+ total_so_margin = fields.Float(
+ 'SO Margin', compute='compute_total_margin',
+ help="Total Margin in Sales Order Header")
+ total_so_percent_margin = fields.Float(
+ 'SO Margin%', compute='compute_total_margin',
+ help="Total % Margin in Sales Order Header")
+ amount_total_without_service = fields.Float('AmtTotalWithoutService', compute='compute_amt_total_without_service')
def get_procurement_status(self):
for purchase_order in self:
@@ -44,3 +64,144 @@ class PurchaseOrder(models.Model):
}
self.env['purchase.order.line'].sudo().create(values)
+ # def compute_count_line_product(self):
+ # for order in self:
+ # count = 0
+ # for line in order.order_line:
+ # if line.product_id.type == 'product':
+ # count += 1
+ # if count == 0:
+ # order.count_line_product = 1
+ # else:
+ # order.count_line_product = count
+
+ def compute_delivery_amount(self):
+ for order in self:
+ amount = 0
+ for line in order.order_line:
+ if line.product_id.type == 'service':
+ amount += line.price_total
+ order.delivery_amount = amount
+
+ def button_confirm(self):
+ res = super(PurchaseOrder, self).button_confirm()
+ test = self.env.user.is_leader
+ test2 = self.env.user.is_purchasing_manager
+ if self.total_percent_margin < self.total_so_percent_margin and not self.env.user.is_purchasing_manager and not self.env.user.is_leader:
+ raise UserError("Beda Margin dengan Sales, harus approval Manager")
+ if not self.sale_order_id and not self.env.user.is_purchasing_manager and not self.env.user.is_leader:
+ raise UserError("Tidak ada link dengan SO, harus approval Manager")
+ self.approval_status = 'approved'
+
+ # for line in self.order_line:
+ # if not line.product_id:
+ # continue
+ # if line.product_id.type == 'service' and self.env.user.id != 6:
+ # raise UserError("Ada tambahan Ongkos kirim, harus Approval Manager")
+ # 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')
+ #
+ # est_purchase_price = sale_order_line.purchase_price
+ # real_purchase_price = line.price_unit
+ # real_tax = real_tax_amount = count_real_tax = 0
+ # for tax in line.taxes_id:
+ # count_real_tax += 1
+ # real_tax = tax
+ # real_tax_amount += tax.amount
+ # if (sale_order_line.purchase_tax_id.amount != real_tax_amount or count_real_tax > 1 \
+ # or real_tax.price_include != sale_order_line.purchase_tax_id.price_include) \
+ # and (self.env.user.id != 6 and self.env.user.id != 7):
+ # raise UserError("Beda tax amount dengan Sales, harus Approval Manager")
+ # elif est_purchase_price < real_purchase_price and self.env.user.id != 6 and self.env.user.id != 7:
+ # raise UserError("Beda Price dengan Sales, harus Approval Manager")
+ # self.approval_status = 'approved'
+
+ return res
+
+ def po_approve(self):
+ if self.env.user.is_leader or self.env.user.is_purchasing_manager:
+ raise UserError("Bisa langsung Confirm")
+ elif self.total_percent_margin == self.total_so_percent_margin and self.sale_order_id:
+ raise UserError("Bisa langsung Confirm")
+ else:
+ self.approval_status = 'pengajuan1'
+ # approval = 0
+ # for line in self.order_line:
+ # if not line.product_id:
+ # continue
+ # elif line.product_id.type == 'service' and self.env.user.id != 6:
+ # approval += 1
+ # else:
+ # 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')
+ #
+ # est_purchase_price = sale_order_line.purchase_price
+ # real_purchase_price = line.price_unit
+ # real_tax = real_tax_amount = count_real_tax = 0
+ # for tax in line.taxes_id:
+ # count_real_tax += 1
+ # real_tax = tax
+ # real_tax_amount += tax.amount
+ # if (sale_order_line.purchase_tax_id.amount != real_tax_amount or count_real_tax > 1 \
+ # or real_tax.price_include != sale_order_line.purchase_tax_id.price_include) \
+ # and (self.env.user.id != 6 and self.env.user.id != 7):
+ # approval += 1
+ # elif est_purchase_price != real_purchase_price and self.env.user.id != 6 and self.env.user.id != 7:
+ # approval += 1
+ # elif line.product_id.type == 'service' and self.env.user.id != 6 and self.env.user.id != 7:
+ # approval += 1
+ # if approval > 0:
+ # self.approval_status = "pengajuan1"
+ # else:
+ # raise UserError("Bisa langsung Confirm")
+
+ def button_cancel(self):
+ res = super(PurchaseOrder, self).button_cancel()
+ self.approval_status = False
+ return res
+
+ def compute_total_margin(self):
+ sum_so_margin = sum_sales_price = sum_margin = 0
+ for line in self.order_line:
+ sale_order_line = self.env['sale.order.line'].search(
+ [('product_id', '=', line.product_id.id),
+ ('order_id', '=', line.order_id.sale_order_id.id)], limit=1, order='price_reduce_taxexcl')
+ sum_so_margin += sale_order_line.item_margin
+ sales_price = sale_order_line.price_reduce_taxexcl * sale_order_line.product_uom_qty
+ if sale_order_line.order_id.shipping_cost_covered == 'indoteknik':
+ sales_price -= sale_order_line.delivery_amt_line
+ sum_sales_price += sales_price
+ purchase_price = line.price_subtotal
+ if line.order_id.delivery_amount > 0:
+ purchase_price += line.delivery_amt_line
+ real_item_margin = sales_price - purchase_price
+ sum_margin += real_item_margin
+
+ if sum_so_margin != 0 and sum_sales_price != 0 and sum_margin != 0:
+ self.total_so_margin = sum_so_margin
+ self.total_so_percent_margin = round((sum_so_margin / sum_sales_price), 2) * 100
+ self.total_margin = sum_margin
+ self.total_percent_margin = round((sum_margin / sum_sales_price), 2) * 100
+ else:
+ self.total_margin = 0
+ self.total_percent_margin = 0
+ self.total_so_margin = 0
+ self.total_so_percent_margin = 0
+ # if not self.order_line or not self.sale_order_id:
+ # self.total_margin = 0
+ # self.total_percent_margin = 0
+ # self.total_so_margin = 0
+ # self.total_so_percent_margin = 0
+ # return
+ # for line in self.order_line:
+ # line.compute_item_margin()
+
+ def compute_amt_total_without_service(self):
+ for order in self:
+ sum_price_total = 0
+ for line in order.order_line:
+ if line.product_id.type == 'product':
+ sum_price_total += line.price_total
+ order.amount_total_without_service = sum_price_total
diff --git a/indoteknik_custom/models/purchase_order_line.py b/indoteknik_custom/models/purchase_order_line.py
index b4be9ffc..bd758055 100755
--- a/indoteknik_custom/models/purchase_order_line.py
+++ b/indoteknik_custom/models/purchase_order_line.py
@@ -1,9 +1,23 @@
-from odoo import fields, models, api
+from odoo import fields, models, api, _
+from odoo.exceptions import AccessError, UserError, ValidationError
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line'
+ item_margin = fields.Float(
+ 'Margin', compute='compute_item_margin',
+ help="Total Margin in Sales Order Header")
+ item_percent_margin = fields.Float(
+ 'Margin%', compute='compute_item_margin',
+ help="Total % Margin in Sales Order Header")
+ so_item_margin = fields.Float(
+ 'SO Margin', compute='compute_item_margin',
+ help="Total Margin in Sales Order Header")
+ so_item_percent_margin = fields.Float(
+ 'SO Margin%', compute='compute_item_margin',
+ help="Total % Margin in Sales Order Header")
+ delivery_amt_line = fields.Float('DeliveryAmtLine', compute='compute_delivery_amt_line')
# Override method from addons/purchase/models/purchase.py
@api.onchange('product_qty', 'product_uom')
@@ -25,3 +39,40 @@ class PurchaseOrderLine(models.Model):
self.price_unit = price_unit
return res
+
+ def compute_item_margin(self):
+ sum_so_margin = sum_sales_price = sum_margin = 0
+ for line in self:
+ if not line.product_id or line.product_id.type == 'service' or not self.order_id.sale_order_id:
+ line.so_item_margin = 0
+ line.so_item_percent_margin = 0
+ line.item_margin = 0
+ line.item_percent_margin = 0
+ continue
+ 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')
+ line.so_item_margin = sale_order_line.item_margin
+ line.so_item_percent_margin = sale_order_line.item_percent_margin
+ sum_so_margin += sale_order_line.item_margin
+ sales_price = sale_order_line.price_reduce_taxexcl * sale_order_line.product_uom_qty
+ if sale_order_line.order_id.shipping_cost_covered == 'indoteknik':
+ sales_price -= sale_order_line.delivery_amt_line
+ sum_sales_price += sales_price
+ purchase_price = line.price_subtotal
+ if line.order_id.delivery_amount > 0:
+ purchase_price += line.delivery_amt_line
+ real_item_margin = sales_price - purchase_price
+ real_item_percent_margin = round((real_item_margin/sales_price), 2) * 100
+ line.item_margin = real_item_margin
+ line.item_percent_margin = real_item_percent_margin
+ sum_margin += real_item_margin
+
+ def compute_delivery_amt_line(self):
+ for line in self:
+ if line.product_id.type == 'product':
+ contribution = round((line.price_total / line.order_id.amount_total_without_service), 2)
+ delivery_amt = line.order_id.delivery_amount
+ line.delivery_amt_line = delivery_amt * contribution
+ else:
+ line.delivery_amt_line = 0
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 1db8a445..87ed0047 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -1,5 +1,6 @@
from odoo import fields, models, api, _
from odoo.exceptions import AccessError, UserError, ValidationError
+from odoo.tools.misc import formatLang, get_lang
import warnings
@@ -13,12 +14,24 @@ class SaleOrder(models.Model):
'Total Percent Margin', compute='compute_total_margin',
help="Total % Margin in Sales Order Header")
approval_status = fields.Selection([
- ('pengajuan1', 'Approval Adela'),
- ('pengajuan2', 'Approval Tyas'),
+ ('pengajuan1', 'Approval Manager'),
+ ('pengajuan2', 'Approval Pimpinan'),
('approved', 'Approved'),
], string='Approval Status', readonly=True, copy=False, index=True, tracking=3)
carrier_id = fields.Many2one('delivery.carrier', string='Shipping Method')
- have_visit_service = fields.Boolean(string='Have Visit Service', help='To compute is customer get visit service', compute='_compute_have_visit_service')
+ have_visit_service = fields.Boolean(string='Have Visit Service', help='To compute is customer get visit service',
+ compute='_compute_have_visit_service')
+ delivery_amt = fields.Float('Delivery Amt')
+ shipping_cost_covered = fields.Selection([
+ ('indoteknik', 'Indoteknik'),
+ ('customer', 'Customer')
+ ], string='Shipping Covered by', help='Siapa yang menanggung biaya ekspedisi?', copy=False)
+ shipping_paid_by = fields.Selection([
+ ('indoteknik', 'Indoteknik'),
+ ('customer', 'Customer')
+ ], string='Shipping Paid by', help='Siapa yang talangin dulu Biaya ekspedisi-nya?', copy=False)
+ sales_tax_id = fields.Many2one('account.tax', string='Tax',
+ domain=['|', ('active', '=', False), ('active', '=', True)])
def _compute_have_visit_service(self):
limit = 20000000
@@ -26,98 +39,250 @@ class SaleOrder(models.Model):
if self.amount_total > limit:
self.have_visit_service = True
- # def sale_order_approve(self):
- # for order in self:
- # if order.state == 'cancel' or order.state == 'done' or order.state == 'sale':
- # raise UserError("Status harus draft atau sent")
- # approval1 = approval2 = 0
- # for line in order.order_line:
- # if not line.product_id:
- # continue
- # if (line.item_percent_margin <= 15 or line.item_percent_margin == 100) and (
- # self.env.user.id != 6 and self.env.user.id != 7):
- # approval2 += 1
- # # order.approval_status = "pengajuan2"
- # # break
- # elif line.item_percent_margin <= 40 and (self.env.user.id != 8 and self.env.user.id != 6 and self.env.user.id != 7):
- # approval1 += 1
- # # order.approval_status = 'pengajuan1'
- # # break
- # if approval2 > 0:
- # order.approval_status = 'pengajuan2'
- # elif approval1 > 0:
- # order.approval_status = 'pengajuan1'
- # else:
- # raise UserError("Bisa langsung Confirm")
-
- # def action_cancel(self):
- # self.approval_status = False
- # return super(SaleOrder, self).action_cancel()
+ def sale_order_approve(self):
+ # raise UserError("Bisa langsung Confirm")
+ for order in self:
+ if order.state == 'cancel' or order.state == 'done' or order.state == 'sale':
+ raise UserError("Status harus draft atau sent")
+ if not order.sales_tax_id:
+ raise UserError("Tax di Header harus diisi")
+ if not order.carrier_id:
+ raise UserError("Shipping Method harus diisi")
+ # approval1 = approval2 = 0
+ for line in order.order_line:
+ if not line.product_id or line.product_id.type == 'service':
+ continue
+ if line.product_id.id == 232383:
+ raise UserError(_('Tidak bisa Confirm menggunakan Produk Sementara'))
+ if not line.vendor_id or not line.purchase_price or not line.purchase_tax_id:
+ raise UserError(_('Isi Vendor, Harga Beli, dan Tax sebelum Request Approval'))
+ # if line.item_percent_margin <= 15 and not self.env.user.is_leader: # akbar or tyas
+ # approval2 += 1
+ # elif line.item_percent_margin <= 25 and not self.env.user.is_leader and not self.env.user.is_sales_manager:
+ # approval1 += 1
+ # if approval2 > 0:
+ # order.approval_status = 'pengajuan2'
+ # elif approval1 > 0:
+ # order.approval_status = 'pengajuan1'
+ # else:
+ # raise UserError("Bisa langsung Confirm")
+ if order.total_percent_margin <= 15 and not self.env.user.is_leader:
+ order.approval_status = 'pengajuan2'
+ elif order.total_percent_margin <= 25 and not self.env.user.is_leader and not self.env.user.is_sales_manager:
+ order.approval_status = 'pengajuan1'
+ else:
+ raise UserError("Bisa langsung Confirm")
+
+ def action_cancel(self):
+ self.approval_status = False
+ return super(SaleOrder, self).action_cancel()
def action_confirm(self):
- for line in self.order_line:
- if line.product_id.id == 232383:
- raise UserError(_('Tidak bisa Confirm menggunakan Produk Sementara'))
res = super(SaleOrder, self).action_confirm()
+ for order in self:
+ if not order.sales_tax_id:
+ raise UserError("Tax di Header harus diisi")
+ if not order.carrier_id:
+ raise UserError("Shipping Method harus diisi")
+ # approval1 = approval2 = 0
+ for line in order.order_line:
+ if not line.product_id or line.product_id.type == 'service':
+ continue
+ if line.product_id.id == 232383:
+ raise UserError(_('Tidak bisa Confirm menggunakan Produk Sementara'))
+ if not line.vendor_id or not line.purchase_price or not line.purchase_tax_id:
+ raise UserError(_('Isi Vendor, Harga Beli, dan Tax sebelum Request Approval'))
+ # if line.item_percent_margin <= 15 and not self.env.user.is_leader:
+ # approval2 += 1
+ # elif line.item_percent_margin <= 25 and not self.env.user.is_leader and not self.env.user.is_sales_manager:
+ # approval1 += 1
+ # if approval2 > 0:
+ # raise UserError("Harus diapprove oleh Pimpinan")
+ # elif approval1 > 0:
+ # raise UserError("Harus diapprove oleh Manager")
+ # order.approval_status = 'approved'
+ if order.total_percent_margin <= 15 and not self.env.user.is_leader:
+ raise UserError("Harus diapprove oleh Pimpinan")
+ elif order.total_percent_margin <= 25 and not self.env.user.is_leader and not self.env.user.is_sales_manager:
+ raise UserError("Harus diapprove oleh Manager")
+ else:
+ order.approval_status = 'approved'
+
return res
def compute_total_margin(self):
for order in self:
- total_margin = total_percent_margin = 0
+ total_margin = total_percent_margin = sum_sales_price = 0
for line in order.order_line:
if not line.product_id:
order.total_margin = 0
order.total_percent_margin = 0
continue
total_margin += line.item_margin
+ sales_price = line.price_reduce_taxexcl * line.product_uom_qty
+ if line.order_id.shipping_cost_covered == 'indoteknik':
+ sales_price -= line.delivery_amt_line
+ sum_sales_price += sales_price
order.total_margin = total_margin
if order.amount_untaxed > 0:
- total_percent_margin = round((total_margin / order.amount_untaxed), 4) * 100
+ total_percent_margin = round((total_margin / sum_sales_price), 2) * 100
order.total_percent_margin = total_percent_margin
- # def action_confirm(self):
- # res = super(SaleOrder, self).action_confirm()
- # for order in self:
- # approval1 = approval2 = 0
- # for line in order.order_line:
- # if not line.product_id:
- # continue
- # if (line.item_percent_margin <= 15 or line.item_percent_margin == 100) and (
- # self.env.user.id != 6 and self.env.user.id != 7):
- # approval2 += 1
- # elif line.item_percent_margin <= 40 and (
- # self.env.user.id != 8 and self.env.user.id != 6 and self.env.user.id != 7):
- # approval1 += 1
- # if approval2 > 0:
- # raise UserError("Need Tyas / Akbar Approval, atau Approval manual dan lampirkan di Log Internal")
- # elif approval1 > 0:
- # raise UserError("Need Adela Approval")
- # order.approval_status = 'approved'
- # return res
+ def compute_count_line_product(self):
+ for order in self:
+ count = 0
+ for line in order.order_line:
+ if line.product_id.type == 'product':
+ count += 1
+ if count == 0:
+ order.count_line_product = 1
+ else:
+ order.count_line_product = count
+
+ @api.onchange('sales_tax_id')
+ def onchange_sales_tax_id(self):
+ for line in self.order_line:
+ line.product_id_change()
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
item_margin = fields.Float(
- 'Total Margin', compute='compute_item_margin',
+ 'Margin', compute='compute_item_margin',
help="Total Margin in Sales Order Header")
item_percent_margin = fields.Float(
- 'Total Percent Margin', compute='compute_item_margin',
+ '%Margin', compute='compute_item_margin',
help="Total % Margin in Sales Order Header")
+ vendor_id = fields.Many2one(
+ 'res.partner', string='Vendor', readonly=True,
+ states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
+ change_default=True, index=True, tracking=1,
+ domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", )
+ purchase_price = fields.Float('Purchase', required=True, digits='Product Price', default=0.0)
+ purchase_tax_id = fields.Many2one('account.tax', string='Tax',
+ domain=['|', ('active', '=', False), ('active', '=', True)])
+ delivery_amt_line = fields.Float('DeliveryAmtLine', compute='compute_delivery_amt_line')
def compute_item_margin(self):
for line in self:
- if not line.product_id or line.price_unit <= 0 or line.product_uom_qty <= 0:
+ if not line.product_id or line.product_id.type == 'service' \
+ or line.price_unit <= 0 or line.product_uom_qty <= 0 \
+ or not line.vendor_id or not line.purchase_tax_id:
line.item_margin = 0
line.item_percent_margin = 0
continue
- subtotal_untaxed = line.price_subtotal
- purchase_pricelist = self.env['purchase.pricelist'].search(
- [('product_id', '=', line.product_id.id)], limit=1, order='product_price')
- purchase_pricelist_untaxed = 0
- if purchase_pricelist.product_price > 0:
- purchase_pricelist_untaxed = purchase_pricelist.product_price / 1.11
- margin_per_item = subtotal_untaxed - (purchase_pricelist_untaxed * line.product_uom_qty)
+ # calculate margin without tax
+ sales_price = line.price_reduce_taxexcl * line.product_uom_qty
+ # minus with delivery if covered by indoteknik
+ if line.order_id.shipping_cost_covered == 'indoteknik':
+ sales_price -= line.delivery_amt_line
+ # sales_price -= round((line.order_id.delivery_amt / line.order_id.count_line_product), 2)
+
+ purchase_price = line.purchase_price
+ if line.purchase_tax_id.price_include:
+ purchase_price = line.purchase_price / 1.11
+
+ purchase_price = purchase_price * line.product_uom_qty
+ margin_per_item = sales_price - purchase_price
line.item_margin = margin_per_item
- if subtotal_untaxed > 0:
- line.item_percent_margin = round((margin_per_item / subtotal_untaxed), 4) * 100
+ # if sales_price > 0:
+ line.item_percent_margin = round((margin_per_item / sales_price), 2) * 100
+
+ @api.onchange('vendor_id')
+ def onchange_vendor_id(self):
+ if not self.product_id or self.product_id.type == 'service':
+ return
+ purchase_price = self.env['purchase.pricelist'].search(
+ [('vendor_id', '=', self.vendor_id.id), ('product_id', '=', self.product_id.id)], limit=1)
+ self.purchase_price = purchase_price.product_price
+ self.purchase_tax_id = 22
+
+ @api.onchange('product_id')
+ def product_id_change(self):
+ super(SaleOrderLine, self).product_id_change()
+ for line in self:
+ if line.product_id and line.product_id.type == 'product':
+ purchase_price = self.env['purchase.pricelist'].search(
+ [('product_id', '=', self.product_id.id)], limit=1, order='product_price ASC')
+ line.vendor_id = purchase_price.vendor_id
+ line.tax_id = line.order_id.sales_tax_id
+
+ def compute_delivery_amt_line(self):
+ for line in self:
+ contribution = round((line.price_total / line.order_id.amount_total), 2)
+ delivery_amt = line.order_id.delivery_amt
+ line.delivery_amt_line = delivery_amt * contribution
+
+ @api.onchange('product_id', 'price_unit', 'product_uom', 'product_uom_qty', 'tax_id')
+ def _onchange_discount(self):
+ if not (self.product_id and self.product_uom and
+ self.order_id.partner_id and self.order_id.pricelist_id and
+ self.order_id.pricelist_id.discount_policy == 'without_discount' and
+ self.env.user.has_group('product.group_discount_per_so_line')):
+ return
+
+ self.discount = 0.0
+ product = self.product_id.with_context(
+ lang=self.order_id.partner_id.lang,
+ partner=self.order_id.partner_id,
+ quantity=self.product_uom_qty,
+ date=self.order_id.date_order,
+ pricelist=self.order_id.pricelist_id.id,
+ uom=self.product_uom.id,
+ fiscal_position=self.env.context.get('fiscal_position')
+ )
+
+ product_context = dict(self.env.context, partner_id=self.order_id.partner_id.id, date=self.order_id.date_order,
+ uom=self.product_uom.id)
+
+ price, rule_id = self.order_id.pricelist_id.with_context(product_context).get_product_price_rule(
+ self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id)
+ new_list_price, currency = self.with_context(product_context)._get_real_price_currency(product, rule_id,
+ self.product_uom_qty,
+ self.product_uom,
+ self.order_id.pricelist_id.id)
+ new_list_price = product.web_price
+
+ if new_list_price != 0:
+ if self.order_id.pricelist_id.currency_id != currency:
+ # we need new_list_price in the same currency as price, which is in the SO's pricelist's currency
+ new_list_price = currency._convert(
+ new_list_price, self.order_id.pricelist_id.currency_id,
+ self.order_id.company_id or self.env.company, self.order_id.date_order or fields.Date.today())
+ discount = (new_list_price - price) / new_list_price * 100
+ if (discount > 0 and new_list_price > 0) or (discount < 0 and new_list_price < 0):
+ self.discount = discount
+
+ def _get_display_price(self, product):
+ # TO DO: move me in master/saas-16 on sale.order
+ # awa: don't know if it's still the case since we need the "product_no_variant_attribute_value_ids" field now
+ # to be able to compute the full price
+
+ # it is possible that a no_variant attribute is still in a variant if
+ # the type of the attribute has been changed after creation.
+ no_variant_attributes_price_extra = [
+ ptav.price_extra for ptav in self.product_no_variant_attribute_value_ids.filtered(
+ lambda ptav:
+ ptav.price_extra and
+ ptav not in product.product_template_attribute_value_ids
+ )
+ ]
+ if no_variant_attributes_price_extra:
+ product = product.with_context(
+ no_variant_attributes_price_extra=tuple(no_variant_attributes_price_extra)
+ )
+
+ if self.order_id.pricelist_id.discount_policy == 'with_discount':
+ return product.with_context(pricelist=self.order_id.pricelist_id.id, uom=self.product_uom.id).price
+ product_context = dict(self.env.context, partner_id=self.order_id.partner_id.id, date=self.order_id.date_order, uom=self.product_uom.id)
+
+ final_price, rule_id = self.order_id.pricelist_id.with_context(product_context).get_product_price_rule(product or self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id)
+ base_price, currency = self.with_context(product_context)._get_real_price_currency(product, rule_id, self.product_uom_qty, self.product_uom, self.order_id.pricelist_id.id)
+ base_price = product.web_price
+ if currency != self.order_id.pricelist_id.currency_id:
+ base_price = currency._convert(
+ base_price, self.order_id.pricelist_id.currency_id,
+ self.order_id.company_id or self.env.company, self.order_id.date_order or fields.Date.today())
+ # negative discounts (= surcharge) are included in the display price
+
+ return max(base_price, final_price)
diff --git a/indoteknik_custom/models/users.py b/indoteknik_custom/models/users.py
new file mode 100644
index 00000000..bc56fe54
--- /dev/null
+++ b/indoteknik_custom/models/users.py
@@ -0,0 +1,10 @@
+from odoo import fields, models, api, _
+from odoo.exceptions import AccessError, UserError, ValidationError
+
+
+class Users(models.Model):
+ _inherit = 'res.users'
+
+ is_purchasing_manager = fields.Boolean(String='Purchasing Manager', help='Berhak melakukan Approval PO')
+ is_sales_manager = fields.Boolean(String='Sales Manager', help='Berhak melakukan Approval SO dengan margin 15-25')
+ is_leader = fields.Boolean(String='Leader', help='Berhak Approval SO Margin < 15 dan Approval PO')
diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml
index f209d18a..a8b71d5a 100755
--- a/indoteknik_custom/views/purchase_order.xml
+++ b/indoteknik_custom/views/purchase_order.xml
@@ -14,8 +14,45 @@
attrs="{'invisible': ['|', ('sale_order_id', '=', False), ('state', 'not in', ['draft'])]}"
/>
</div>
+ <button id="draft_confirm" position="after">
+ <button name="po_approve"
+ string="Ask Approval"
+ type="object"
+ />
+ </button>
<field name="date_order" position="before">
<field name="sale_order_id" attrs="{'readonly': [('state', 'not in', ['draft'])]}"/>
+ <field name="approval_status"/>
+ </field>
+ <field name="amount_total" position="after">
+ <field name="total_margin"/>
+ <field name="total_so_margin"/>
+ <field name="total_percent_margin"/>
+ <field name="total_so_percent_margin"/>
+ </field>
+ </field>
+ </record>
+ </data>
+ <data>
+ <record id="rfq_order_tree_view_inherit" model="ir.ui.view">
+ <field name="name">Purchase</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_kpis_tree"/>
+ <field name="arch" type="xml">
+ <field name="create_date" position="after">
+ <field name="approval_status" />
+ </field>
+ </field>
+ </record>
+ </data>
+ <data>
+ <record id="purchase_order_tree_view_inherit" model="ir.ui.view">
+ <field name="name">Purchase</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_view_tree"/>
+ <field name="arch" type="xml">
+ <field name="invoice_status" position="after">
+ <field name="procurement_status" />
</field>
</field>
</record>
diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml
index 19182a6b..0abbae94 100755
--- a/indoteknik_custom/views/sale_order.xml
+++ b/indoteknik_custom/views/sale_order.xml
@@ -6,11 +6,26 @@
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
+ <button id="action_confirm" position="after">
+ <button name="sale_order_approve"
+ string="Ask Approval"
+ type="object"
+ />
+ </button>
<field name="payment_term_id" position="after">
+ <field name="shipping_cost_covered"/>
+ <field name="shipping_paid_by"/>
+ <field name="delivery_amt"/>
+ </field>
+ <field name="partner_shipping_id" position="after">
<field name="approval_status" />
+ <field name="sales_tax_id" domain="[('type_tax_use','=','sale')]"/>
+ <field name="carrier_id"/>
</field>
<xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='price_total']" position="after">
- <field name="item_margin" groups="sales_team.group_sale_manager"/>
+ <field name="vendor_id" attrs="{'readonly': [('parent.state', 'not in', ['draft', 'sent', 'sale'])]}"/>
+ <field name="purchase_price" attrs="{'readonly': [('parent.state', 'not in', ['draft', 'sent', 'sale'])]}"/>
+ <field name="purchase_tax_id" attrs="{'readonly': [('parent.state', 'not in', ['draft', 'sent', 'sale'])]}"/>
<field name="item_percent_margin" groups="sales_team.group_sale_manager"/>
</xpath>
<field name="amount_total" position="after">
diff --git a/indoteknik_custom/views/users.xml b/indoteknik_custom/views/users.xml
new file mode 100644
index 00000000..d75b35fc
--- /dev/null
+++ b/indoteknik_custom/views/users.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+ <data>
+ <record id="users_form_view_inherit" model="ir.ui.view">
+ <field name="name">User</field>
+ <field name="model">res.users</field>
+ <field name="inherit_id" ref="base.view_users_form"/>
+ <field name="arch" type="xml">
+ <field name="tz_offset" position="after">
+ <field name="is_purchasing_manager"/>
+ <field name="is_sales_manager"/>
+ <field name="is_leader"/>
+ </field>
+ </field>
+ </record>
+ </data>
+</odoo> \ No newline at end of file