diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2024-10-16 15:47:07 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2024-10-16 15:47:07 +0700 |
| commit | 8914f55dba0a2d4a1e992c9d0635ae993950bcf1 (patch) | |
| tree | f41be6b8474db4f61e0122c68614a191829e39cf | |
| parent | d7f4569c5d2dcda1316ca4ef37fed53f467df9df (diff) | |
| parent | a1b2542ebc2d527d07edbcbaab467152a46f1d33 (diff) | |
Merge branch 'production' into feature/generate_url
| -rw-r--r-- | indoteknik_api/controllers/api_v1/product.py | 1 | ||||
| -rw-r--r-- | indoteknik_api/controllers/api_v1/user.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/models/approval_unreserve.py | 7 | ||||
| -rwxr-xr-x | indoteknik_custom/models/crm_lead.py | 91 | ||||
| -rwxr-xr-x | indoteknik_custom/models/purchase_order.py | 10 | ||||
| -rw-r--r-- | indoteknik_custom/models/report_stock_forecasted.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 22 | ||||
| -rw-r--r-- | indoteknik_custom/models/stock_picking.py | 24 | ||||
| -rwxr-xr-x | indoteknik_custom/views/sale_order.xml | 4 | ||||
| -rw-r--r-- | indoteknik_custom/views/stock_picking.xml | 1 |
10 files changed, 147 insertions, 16 deletions
diff --git a/indoteknik_api/controllers/api_v1/product.py b/indoteknik_api/controllers/api_v1/product.py index e779e623..9673b3ef 100644 --- a/indoteknik_api/controllers/api_v1/product.py +++ b/indoteknik_api/controllers/api_v1/product.py @@ -74,7 +74,6 @@ class Product(controller.Controller): if qty_available > 0: qty = qty_available + total_adem + total_excell - sla_date = '1 Hari' elif qty_altama > 0 or qty_vendor > 0: qty = total_adem if qty_altama > 0 else total_excell sla_date = '2-4 Hari' diff --git a/indoteknik_api/controllers/api_v1/user.py b/indoteknik_api/controllers/api_v1/user.py index c7bfe91a..e4f8b97f 100644 --- a/indoteknik_api/controllers/api_v1/user.py +++ b/indoteknik_api/controllers/api_v1/user.py @@ -248,7 +248,7 @@ class User(controller.Controller): if type_acc == 'individu': user.partner_id.customer_type = 'nonpkp' - user.partner_id.npwp = '0.000.000.0-000.000' + user.partner_id.npwp = '00.000.000.0-000.000' user.partner_id.sppkp = '-' user.partner_id.nama_wajib_pajak = name user.partner_id.user_id = 3222 diff --git a/indoteknik_custom/models/approval_unreserve.py b/indoteknik_custom/models/approval_unreserve.py index 88409c37..07ddda1f 100644 --- a/indoteknik_custom/models/approval_unreserve.py +++ b/indoteknik_custom/models/approval_unreserve.py @@ -31,12 +31,12 @@ class ApprovalUnreserve(models.Model): if not self.picking_id: raise ValidationError("Picking is required") - stock_move = self.env['stock.move'].search([('picking_id', '=', self.picking_id.id), ('state', '=', 'assigned')]) + stock_move = self.env['stock.move'].search([('picking_id', '=', self.picking_id.id), ('state', 'in', ['assigned', 'partially_available'])]) if not stock_move: raise ValidationError("Picking is not found") - for move in stock_move: + for move in stock_move: self.approval_line.create({ 'approval_id': self.id, 'move_id': move.id @@ -68,7 +68,7 @@ class ApprovalUnreserve(models.Model): if not move: raise UserError("Product tidak ada di destination picking") - qty_unreserve = line.unreserve_qty + move.forecast_availability + qty_unreserve = line.unreserve_qty + move.reserved_availability if move.product_uom_qty < qty_unreserve: raise UserError("Quantity yang di unreserve melebihi quantity yang ada") @@ -86,6 +86,7 @@ class ApprovalUnreserve(models.Model): }) # Trigger the unreserve function self._trigger_unreserve() + self.picking_id.check_state_reserve() def action_reject(self, reason): if self.env.user.id != self.user_id.id: diff --git a/indoteknik_custom/models/crm_lead.py b/indoteknik_custom/models/crm_lead.py index 9ffd607c..de2bdb12 100755 --- a/indoteknik_custom/models/crm_lead.py +++ b/indoteknik_custom/models/crm_lead.py @@ -2,6 +2,7 @@ from odoo import fields, models, api import logging import random from odoo.exceptions import AccessError, UserError, ValidationError +from datetime import datetime, timedelta _logger = logging.getLogger(__name__) @@ -97,4 +98,92 @@ class CrmLead(models.Model): lead.user_id = salesperson_id - + def _update_pipeline(self, delta=48, limit=100): + # Get the current time + current_time = datetime.now() + + # Calculate the time 24 hours ago + time_48_hours_ago = current_time - timedelta(hours=delta) + + # Define the allowed states + allowed_states = ['sale', 'done'] + + # Search for sale orders with date_order greater than 24 hours ago and opportunity_id is null + orders = self.env['sale.order'].search([ + ('write_date', '>=', time_48_hours_ago), + ('opportunity_id', '!=', False), + ('state', 'in', allowed_states) + ], limit=limit) + for order in orders: + order.opportunity_id.stage_id = 4 + _logger.info('finish order stage pipeline %s' % order.id) + + def _cancel_pipeline(self, delta=48, limit=100): + # Get the current time + current_time = datetime.now() + + # Calculate the time 24 hours ago + time_48_hours_ago = current_time - timedelta(hours=delta) + + # Define the allowed states + allowed_states = ['cancel'] + + # Search for sale orders with date_order greater than 24 hours ago and opportunity_id is null + orders = self.env['sale.order'].search([ + ('write_date', '>=', time_48_hours_ago), + ('opportunity_id', '!=', False), + ('state', 'in', allowed_states) + ], limit=limit) + for order in orders: + order.opportunity_id.stage_id = 7 + _logger.info('cancel order stage pipeline %s' % order.id) + + def _convert_to_pipeline(self, delta=48, limit=100): + # Get the current time + current_time = datetime.now() + + # Calculate the time 24 hours ago + time_48_hours_ago = current_time - timedelta(hours=delta) + + # Define the allowed states + allowed_states = ['draft', 'done', 'sale', 'sent', 'cancel'] + + # Search for sale orders with date_order greater than 24 hours ago and opportunity_id is null + orders = self.env['sale.order'].search([ + ('write_date', '>=', time_48_hours_ago), + ('opportunity_id', '=', False), + ('state', 'in', allowed_states) + ], limit=limit) + # stage + # 1 potensi baru, 2 proses quotation, 3 proses lain visit, 4 proses berhasil, 5 proses negosiasi, 7 tidak terpakai / gagal + for order in orders: + # stage_id = 2 + if order.state == 'sale' or order.state == 'done': + stage_id = 4 + elif order.state == 'sent': + stage_id = 5 + elif order.state == 'cancel': + stage_id = 7 + else: + stage_id = 2 + crm_lead = self.env['crm.lead'].create([{ + 'email_normalized': order.email, + 'name': order.name, + 'user_id': order.user_id.id, + 'company_id': 1, + 'type': 'opportunity', + 'priority': 0, + 'team_id': order.team_id.id, + 'stage_id': stage_id, + 'expected_revenue': order.amount_untaxed, + 'partner_id': order.partner_id.parent_id.id or order.partner_id.id, + 'contact_name': order.partner_id.name, + 'partner_name': order.partner_id.parent_id.name or order.partner_id.name, + 'phone': order.partner_id.mobile, + 'street': order.partner_id.street, + 'street2': order.partner_id.street2, + 'zip': order.partner_id.zip, + 'order_id': order.id + }]) + order.opportunity_id = crm_lead.id + _logger.info('convert order to opportunity %s' % crm_lead.id) diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 340df49e..f8af409f 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -508,11 +508,11 @@ class PurchaseOrder(models.Model): if self.amount_untaxed >= 50000000 and not self.env.user.has_group('indoteknik_custom.group_role_merchandiser'): raise UserError("Hanya Merchandiser yang bisa approve") - 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 self.total_percent_margin < self.total_so_percent_margin and not self.env.user.has_group('indoteknik_custom.group_role_merchandiser') and not self.env.user.is_leader: + raise UserError("Beda Margin dengan Sales, harus approval Merchandise") if not self.from_apo: - 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") + if not self.sale_order_id and self.env.user.has_group('indoteknik_custom.group_role_merchandiser') and not self.env.user.is_leader: + raise UserError("Tidak ada link dengan SO, harus approval Merchandise") send_email = False self.add_product_to_pricelist() @@ -641,7 +641,7 @@ class PurchaseOrder(models.Model): def po_approve(self): if self.amount_untaxed >= 50000000 and not self.env.user.has_group('indoteknik_custom.group_role_merchandiser'): raise UserError("Hanya Merchandiser yang bisa approve") - if self.env.user.is_leader or self.env.user.is_purchasing_manager: + if self.env.user.is_leader or self.env.user.has_group('indoteknik_custom.group_role_merchandiser'): 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") diff --git a/indoteknik_custom/models/report_stock_forecasted.py b/indoteknik_custom/models/report_stock_forecasted.py index 5f9427f8..ebdc7d4a 100644 --- a/indoteknik_custom/models/report_stock_forecasted.py +++ b/indoteknik_custom/models/report_stock_forecasted.py @@ -33,7 +33,6 @@ class ReplenishmentReport(models.AbstractModel): 'reserved_from': result, 'qty_fullfillment': quantity, }) - return lines def _calculate_result(self, line): diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index c1c2c267..22130ac3 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -136,6 +136,12 @@ class SaleOrder(models.Model): domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", tracking=True) total_weight = fields.Float(string='Total Weight', compute='_compute_total_weight') + pareto_status = fields.Selection([ + ('PR', 'Pareto Repeating'), + ('PPR', 'Potensi Pareto Repeating'), + ('PNR', 'Pareto Non Repeating'), + ('NP', 'Non Pareto') + ]) def _compute_total_weight(self): total_weight = 0 @@ -642,6 +648,7 @@ class SaleOrder(models.Model): self.sppkp = parent_id.sppkp self.customer_type = parent_id.customer_type self.email = parent_id.email + self.pareto_status = parent_id.pareto_status @api.onchange('partner_id') def onchange_partner_id(self): @@ -1024,11 +1031,20 @@ class SaleOrder(models.Model): def _set_sppkp_npwp_contact(self): partner = self.partner_id.parent_id or self.partner_id - if not partner.sppkp or not partner.npwp or not partner.email or partner.customer_type: - partner.customer_type = self.customer_type - partner.npwp = self.npwp + if not partner.sppkp: partner.sppkp = self.sppkp + if not partner.npwp: + partner.npwp = self.npwp + if not partner.email: partner.email = self.email + if not partner.customer_type: + partner.customer_type = self.customer_type + + # if not partner.sppkp or not partner.npwp or not partner.email or partner.customer_type: + # partner.customer_type = self.customer_type + # partner.npwp = self.npwp + # partner.sppkp = self.sppkp + # partner.email = self.email def _compute_total_margin(self): for order in self: diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 14190474..1b2baea7 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -101,6 +101,13 @@ class StockPicking(models.Model): ('no', 'Nothing to Invoice') ], string='Invoice Status', related="sale_id.invoice_status") + state_reserve = fields.Selection([ + ('waiting', 'Waiting For Fullfilment'), + ('ready', 'Ready to Ship'), + ('done', 'Done'), + ('cancel', 'Cancelled'), + ], string='Status Reserve', readonly=True, tracking=True, help="The current state of the stock picking.") + @api.constrains('driver_departure_date') def constrains_driver_departure_date(self): self.date_doc_kirim = self.driver_departure_date @@ -134,9 +141,24 @@ class StockPicking(models.Model): res = super(StockPicking, self).do_unreserve() current_time = datetime.datetime.utcnow() self.date_unreserve = current_time + # self.check_state_reserve() return res + def check_state_reserve(self): + do = self.search([ + ('state', 'not in', ['cancel', 'draft', 'done']), + ('picking_type_code', '=', 'outgoing') + ]) + + for rec in do: + rec.state_reserve = 'ready' + + for line in rec.move_ids_without_package: + if line.product_uom_qty > line.reserved_availability: + rec.state_reserve = 'waiting' + break + def _create_approval_notification(self, approval_role): title = 'Warning' message = f'Butuh approval sales untuk unreserved' @@ -275,6 +297,7 @@ class StockPicking(models.Model): current_time = datetime.datetime.utcnow() self.real_shipping_id = self.sale_id.real_shipping_id self.date_availability = current_time + # self.check_state_reserve() return res def ask_approval(self): @@ -421,6 +444,7 @@ class StockPicking(models.Model): res = super(StockPicking, self).button_validate() self.calculate_line_no() self.date_done = datetime.datetime.utcnow() + self.state_reserve = 'done' return res @api.model diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 895b242c..98001589 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -73,6 +73,7 @@ <field name="margin_after_delivery_purchase"/> <field name="percent_margin_after_delivery_purchase"/> <field name="total_weight"/> + <field name="pareto_status"/> </field> <field name="analytic_account_id" position="after"> <field name="customer_type" required="1"/> @@ -140,7 +141,6 @@ <field name="weight" optional="hide"/> <field name="amount_voucher_disc" string="Voucher" readonly="1" optional="hide"/> <field name="order_promotion_id" string="Promotion" readonly="1" optional="hide"/> - <field name="md_vendor_id" string="MD Vendor" readonly="1" optional="hide"/> </xpath> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='product_id']" position="before"> <field name="line_no" readonly="1" optional="hide"/> @@ -245,6 +245,7 @@ <field name="client_order_ref"/> <field name="payment_type" optional="hide"/> <field name="payment_status" optional="hide"/> + <field name="pareto_status" optional="hide"/> </field> </field> </record> @@ -263,6 +264,7 @@ <field name="date_driver_arrival"/> <field name="payment_type" optional="hide"/> <field name="payment_status" optional="hide"/> + <field name="pareto_status" optional="hide"/> </field> </field> </record> diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml index 899d29eb..af1af563 100644 --- a/indoteknik_custom/views/stock_picking.xml +++ b/indoteknik_custom/views/stock_picking.xml @@ -16,6 +16,7 @@ <field name="driver_arrival_date" optional="hide"/> <field name="note_logistic" optional="hide"/> <field name="note" optional="hide"/> + <field name="state_reserve" optional="hide"/> </field> <field name="partner_id" position="after"> <field name="purchase_representative_id"/> |
