summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indoteknik_custom/models/commision.py16
-rwxr-xr-xindoteknik_custom/models/sale_order.py93
-rw-r--r--indoteknik_custom/models/sale_order_line.py19
-rw-r--r--indoteknik_custom/models/solr/product_template.py2
-rw-r--r--indoteknik_custom/models/stock_move.py1
-rw-r--r--indoteknik_custom/models/stock_picking.py6
-rwxr-xr-xindoteknik_custom/views/sale_order.xml19
7 files changed, 130 insertions, 26 deletions
diff --git a/indoteknik_custom/models/commision.py b/indoteknik_custom/models/commision.py
index 32e81b9a..bd4c06a4 100644
--- a/indoteknik_custom/models/commision.py
+++ b/indoteknik_custom/models/commision.py
@@ -1,8 +1,10 @@
from odoo import models, api, fields, _
from odoo.exceptions import UserError
from datetime import datetime
+# import datetime
import logging
from terbilang import Terbilang
+import pytz
_logger = logging.getLogger(__name__)
@@ -301,30 +303,34 @@ class CustomerCommision(models.Model):
return result
def action_confirm_customer_commision(self):
- now = datetime.utcnow()
+ jakarta_tz = pytz.timezone('Asia/Jakarta')
+ now = datetime.now(jakarta_tz)
+
+ now_naive = now.replace(tzinfo=None)
+
if not self.status or self.status == 'draft':
self.status = 'pengajuan1'
elif self.status == 'pengajuan1' and self.env.user.is_sales_manager:
self.status = 'pengajuan2'
self.approved_by = (self.approved_by + ', ' if self.approved_by else '') + self.env.user.name
- self.date_approved_sales = now
+ self.date_approved_sales = now_naive
self.position_sales = 'Sales Manager'
elif self.status == 'pengajuan2' and self.env.user.id == 19:
self.status = 'pengajuan3'
self.approved_by = (self.approved_by + ', ' if self.approved_by else '') + self.env.user.name
- self.date_approved_marketing = now
+ self.date_approved_marketing = now_naive
self.position_marketing = 'Marketing Manager'
elif self.status == 'pengajuan3' and self.env.user.is_leader:
self.status = 'pengajuan4'
self.approved_by = (self.approved_by + ', ' if self.approved_by else '') + self.env.user.name
- self.date_approved_pimpinan = now
+ self.date_approved_pimpinan = now_naive
self.position_pimpinan = 'Pimpinan'
elif self.status == 'pengajuan4' and self.env.user.id == 1272:
for line in self.commision_lines:
line.invoice_id.is_customer_commision = True
self.status = 'approved'
self.approved_by = (self.approved_by + ', ' if self.approved_by else '') + self.env.user.name
- self.date_approved_accounting = now
+ self.date_approved_accounting = now_naive
self.position_accounting = 'Accounting'
else:
raise UserError('Harus di approved oleh yang bersangkutan')
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 4c48684d..f99058ea 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -133,8 +133,9 @@ class SaleOrder(models.Model):
reject_line = fields.One2many('sales.order.reject', 'sale_order_id', string='Reject Lines')
order_sales_match_line = fields.One2many('sales.order.purchase.match', 'sales_order_id', string='Purchase Match Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True)
total_margin = fields.Float('Total Margin', compute='_compute_total_margin', help="Total Margin in Sales Order Header")
+ total_before_margin = fields.Float('Total Before Margin', compute='_compute_total_before_margin', help="Total Margin in Sales Order Header")
total_percent_margin = fields.Float('Total Percent Margin', compute='_compute_total_percent_margin', help="Total % Margin in Sales Order Header")
- total_margin_excl_third_party = fields.Float('Before Margin', help="Before Margin in Sales Order Header")
+ total_margin_excl_third_party = fields.Float('Before Margin', help="Before Margin in Sales Order Header", compute='_compute_total_margin_excl_third_party')
approval_status = fields.Selection([
('pengajuan1', 'Approval Manager'),
('pengajuan2', 'Approval Pimpinan'),
@@ -202,9 +203,9 @@ class SaleOrder(models.Model):
customer_type = fields.Selection([
('pkp', 'PKP'),
('nonpkp', 'Non PKP')
- ], required=True)
- sppkp = fields.Char(string="SPPKP", required=True, tracking=True)
- npwp = fields.Char(string="NPWP", required=True, tracking=True)
+ ], required=True, compute='_compute_partner_field')
+ sppkp = fields.Char(string="SPPKP", required=True, tracking=True, compute='_compute_partner_field')
+ npwp = fields.Char(string="NPWP", required=True, tracking=True, compute='_compute_partner_field')
purchase_total = fields.Monetary(string='Purchase Total', compute='_compute_purchase_total')
voucher_id = fields.Many2one(comodel_name='voucher', string='Voucher', copy=False)
applied_voucher_id = fields.Many2one(comodel_name='voucher', string='Applied Voucher', copy=False)
@@ -296,6 +297,54 @@ class SaleOrder(models.Model):
)
nomor_so_pengganti = fields.Char(string='Nomor SO Pengganti', copy=False, tracking=3)
shipping_option_id = fields.Many2one("shipping.option", string="Selected Shipping Option", domain="['|', ('sale_order_id', '=', False), ('sale_order_id', '=', id)]")
+ hold_outgoing = fields.Boolean('Hold Outgoing SO')
+ state_ask_cancel = fields.Selection([
+ ('hold', 'Hold'),
+ ('approve', 'Approve')
+ ], tracking=True, string='State Cancel', copy=False)
+
+ def _compute_total_margin_excl_third_party(self):
+ for order in self:
+ if order.amount_untaxed == 0:
+ order.total_margin_excl_third_party = 0
+ continue
+
+ # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed-delivery_amt-order.fee_third_party)) * 100, 2)
+ order.total_margin_excl_third_party = round((order.total_before_margin / (order.amount_untaxed)) * 100, 2)
+ # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed)) * 100, 2)
+
+ def ask_retur_cancel_purchasing(self):
+ for rec in self:
+ if self.env.user.has_group('indoteknik_custom.group_role_purchasing'):
+ rec.state_ask_cancel = 'approve'
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': 'Persetujuan Diberikan',
+ 'message': 'Proses cancel sudah disetujui',
+ 'type': 'success',
+ 'sticky': True
+ }
+ }
+ else:
+ rec.state_ask_cancel = 'hold'
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': 'Menunggu Persetujuan',
+ 'message': 'Tim Purchasing akan memproses permintaan Anda',
+ 'type': 'warning',
+ 'sticky': False
+ }
+ }
+
+ def hold_unhold_qty_outgoing_so(self):
+ if self.hold_outgoing == True:
+ self.hold_outgoing = False
+ else:
+ self.hold_outgoing = True
def _validate_uniform_taxes(self):
for order in self:
@@ -307,17 +356,17 @@ class SaleOrder(models.Model):
if len(tax_sets) > 1:
raise ValidationError("Semua produk dalam Sales Order harus memiliki kombinasi pajak yang sama.")
- @api.constrains('fee_third_party', 'delivery_amt', 'biaya_lain_lain')
- def _check_total_margin_excl_third_party(self):
- for rec in self:
- if rec.fee_third_party == 0 and rec.total_margin_excl_third_party != rec.total_percent_margin:
- # Gunakan direct SQL atau flag context untuk menghindari rekursi
- self.env.cr.execute("""
- UPDATE sale_order
- SET total_margin_excl_third_party = %s
- WHERE id = %s
- """, (rec.total_percent_margin, rec.id))
- self.invalidate_cache()
+ # @api.constrains('fee_third_party', 'delivery_amt', 'biaya_lain_lain')
+ # def _check_total_margin_excl_third_party(self):
+ # for rec in self:
+ # if rec.fee_third_party == 0 and rec.total_margin_excl_third_party != rec.total_percent_margin:
+ # # Gunakan direct SQL atau flag context untuk menghindari rekursi
+ # self.env.cr.execute("""
+ # UPDATE sale_order
+ # SET total_margin_excl_third_party = %s
+ # WHERE id = %s
+ # """, (rec.total_percent_margin, rec.id))
+ # self.invalidate_cache()
@api.constrains('shipping_option_id')
def _check_shipping_option(self):
@@ -994,6 +1043,13 @@ class SaleOrder(models.Model):
# return [('id', 'not in', order_ids)]
# return ['&', ('order_line.invoice_lines.move_id.move_type', 'in', ('out_invoice', 'out_refund')), ('order_line.invoice_lines.move_id', operator, value)]
+ @api.depends('partner_id')
+ def _compute_partner_field(self):
+ for order in self:
+ partner = order.partner_id.parent_id or order.partner_id
+ order.npwp = partner.npwp
+ order.sppkp = partner.sppkp
+ order.customer_type = partner.customer_type
@api.onchange('partner_id')
def onchange_partner_contact(self):
@@ -1441,6 +1497,8 @@ class SaleOrder(models.Model):
def action_cancel(self):
# TODO stephan prevent cancel if have invoice, do, and po
+ if self.state_ask_cancel != 'approve' and self.state not in ['draft', 'sent']:
+ raise UserError("Anda harus approval purchasing terlebih dahulu")
main_parent = self.partner_id.get_main_parent()
if self._name != 'sale.order':
return super(SaleOrder, self).action_cancel()
@@ -1560,6 +1618,11 @@ class SaleOrder(models.Model):
order.total_margin = total_margin
+ def _compute_total_before_margin(self):
+ for order in self:
+ total_before_margin = sum(line.item_before_margin for line in order.order_line if line.product_id)
+ order.total_before_margin = total_before_margin
+
def _compute_total_percent_margin(self):
for order in self:
if order.amount_untaxed == 0:
diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py
index aed95aab..2450abd4 100644
--- a/indoteknik_custom/models/sale_order_line.py
+++ b/indoteknik_custom/models/sale_order_line.py
@@ -6,6 +6,7 @@ from datetime import datetime, timedelta
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
item_margin = fields.Float('Margin', compute='compute_item_margin', help="Total Margin in Sales Order Header")
+ item_before_margin = fields.Float('Before Margin', compute='compute_item_before_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")
initial_discount = fields.Float('Initial Discount')
vendor_id = fields.Many2one(
@@ -146,6 +147,24 @@ class SaleOrderLine(models.Model):
if not line.margin_md:
line.margin_md = line.item_percent_margin
+ def compute_item_before_margin(self):
+ for line in self:
+ 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:
+ line.item_before_margin = 0
+ continue
+ # calculate margin without tax
+ sales_price = line.price_reduce_taxexcl * line.product_uom_qty
+
+ 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_before_margin = margin_per_item
+
@api.onchange('vendor_id')
def onchange_vendor_id(self):
# TODO : need to change this logic @stephan
diff --git a/indoteknik_custom/models/solr/product_template.py b/indoteknik_custom/models/solr/product_template.py
index 20402c84..c4aefe19 100644
--- a/indoteknik_custom/models/solr/product_template.py
+++ b/indoteknik_custom/models/solr/product_template.py
@@ -100,7 +100,7 @@ class ProductTemplate(models.Model):
"product_rating_f": template.virtual_rating,
"product_id_i": template.id,
"image_s": self.env['ir.attachment'].api_image('product.template', 'image_512', template.id),
- "image_carousel_ss": carousel_images,
+ "image_carousel_ss": carousel_images if carousel_images else [],
'image_mobile_s': self.env['ir.attachment'].api_image('product.template', 'image_256', template.id),
"variant_total_i": template.product_variant_count,
"stock_total_f": template.qty_stock_vendor,
diff --git a/indoteknik_custom/models/stock_move.py b/indoteknik_custom/models/stock_move.py
index 3c765244..90ab30a4 100644
--- a/indoteknik_custom/models/stock_move.py
+++ b/indoteknik_custom/models/stock_move.py
@@ -14,6 +14,7 @@ class StockMove(models.Model):
qr_code_variant = fields.Binary("QR Code Variant", compute='_compute_qr_code_variant')
barcode = fields.Char(string='Barcode', related='product_id.barcode')
vendor_id = fields.Many2one('res.partner' ,string='Vendor')
+ hold_outgoingg = fields.Boolean('Hold Outgoing', default=False)
# @api.model_create_multi
# def create(self, vals_list):
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index ce1399fe..f431d817 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -973,6 +973,8 @@ class StockPicking(models.Model):
if self.env.user.is_accounting:
pick.approval_return_status = 'approved'
continue
+ else:
+ pick.approval_return_status = 'pengajuan1'
action = self.env['ir.actions.act_window']._for_xml_id('indoteknik_custom.action_stock_return_note_wizard')
@@ -1241,8 +1243,8 @@ class StockPicking(models.Model):
if not invoice:
continue
-
- if not picking.so_lama and (not picking.date_doc_kirim or not invoice.invoice_date):
+
+ if not picking.so_lama and invoice and (not picking.date_doc_kirim or not invoice.invoice_date):
raise UserError("Tanggal Kirim atau Tanggal Invoice belum diisi!")
picking_date = fields.Date.to_date(picking.date_doc_kirim)
diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml
index 10c60e24..ed389b4c 100755
--- a/indoteknik_custom/views/sale_order.xml
+++ b/indoteknik_custom/views/sale_order.xml
@@ -16,6 +16,16 @@
type="object"
attrs="{'invisible': [('approval_status', '=', ['approved'])]}"
/>
+ <button name="hold_unhold_qty_outgoing_so"
+ string="Hold/Unhold Outgoing"
+ type="object"
+ attrs="{'invisible': [('state', 'in', ['cancel'])]}"
+ />
+ <button name="ask_retur_cancel_purchasing"
+ string="Ask Cancel Purchasing"
+ type="object"
+ attrs="{'invisible': [('state', 'in', ['cancel'])]}"
+ />
<button name="action_web_approve"
string="Web Approve"
type="object"
@@ -83,6 +93,7 @@
<attribute name="invisible">1</attribute>
</field>
<field name="user_id" position="after">
+ <field name="hold_outgoing" readonly="1" />
<field name="helper_by_id" readonly="1" />
<field name="compute_fullfillment" invisible="1" />
</field>
@@ -98,9 +109,9 @@
<field name="pareto_status" />
</field>
<field name="analytic_account_id" position="after">
- <field name="customer_type" required="1" />
- <field name="npwp" placeholder='99.999.999.9-999.999' required="1" />
- <field name="sppkp" attrs="{'required': [('customer_type', '=', 'pkp')]}" />
+ <field name="customer_type" readonly="1" />
+ <field name="npwp" placeholder='99.999.999.9-999.999' readonly="1" />
+ <field name="sppkp" attrs="{'required': [('customer_type', '=', 'pkp')]}" readonly="1" />
<field name="email" required="1" />
<field name="unreserve_id" />
<field name="due_id" readonly="1" />
@@ -271,6 +282,7 @@
</div>
<field name="total_margin" />
<field name="total_percent_margin" />
+ <field name="total_before_margin" />
</field>
<field name="effective_date" position="after">
<field name="carrier_id" />
@@ -383,6 +395,7 @@
<field name="payment_status" optional="hide" />
<field name="pareto_status" optional="hide" />
<field name="shipping_method_picking" optional="hide" />
+ <field name="hold_outgoing" optional="hide" />
</field>
</field>
</record>