diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2022-10-04 13:42:30 +0700 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2022-10-04 13:42:30 +0700 |
| commit | c4f30a0164ada85a9a4a25cdd03ee7c4e42774a0 (patch) | |
| tree | 30d246e2cdf3cb1925d88a039926fcd06f2ee82c | |
| parent | d1bc570eae2818bc4b535840f2eb3061b99ca98b (diff) | |
| parent | 1d6351cbab4df3a5f5ceff92c53560437d7b40a4 (diff) | |
Merge commit '1d6351cbab4df3a5f5ceff92c53560437d7b40a4'
| -rwxr-xr-x | indoteknik_custom/__manifest__.py | 3 | ||||
| -rwxr-xr-x | indoteknik_custom/models/__init__.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/models/purchase_order.py | 165 | ||||
| -rwxr-xr-x | indoteknik_custom/models/purchase_order_line.py | 53 | ||||
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 297 | ||||
| -rw-r--r-- | indoteknik_custom/models/users.py | 10 | ||||
| -rwxr-xr-x | indoteknik_custom/views/purchase_order.xml | 37 | ||||
| -rwxr-xr-x | indoteknik_custom/views/sale_order.xml | 17 | ||||
| -rw-r--r-- | indoteknik_custom/views/users.xml | 17 |
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 |
