From caae31d0376d62ca62a6d4e3fa5aaa0842fc9c88 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Wed, 31 May 2023 15:36:00 +0700 Subject: new module of requisition --- indoteknik_custom/__manifest__.py | 1 + indoteknik_custom/models/__init__.py | 1 + indoteknik_custom/models/automatic_purchase.py | 2 +- indoteknik_custom/models/requisition.py | 179 +++++++++++++++++++++++++ indoteknik_custom/security/ir.model.access.csv | 5 +- indoteknik_custom/views/ir_sequence.xml | 10 ++ indoteknik_custom/views/requisition.xml | 101 ++++++++++++++ 7 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 indoteknik_custom/models/requisition.py create mode 100644 indoteknik_custom/views/requisition.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index c52e27b7..e1c2ec7b 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -74,6 +74,7 @@ 'views/procurement_monitoring_detail.xml', 'views/product_product.xml', 'views/brand_vendor.xml', + 'views/requisition.xml', 'report/report.xml', 'report/report_banner_banner.xml', 'report/report_banner_banner2.xml', diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 18f46d34..9764e0c0 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -62,3 +62,4 @@ from . import raja_ongkir from . import procurement_monitoring_detail from . import brand_vendor from . import manufacturing +from . import requisition diff --git a/indoteknik_custom/models/automatic_purchase.py b/indoteknik_custom/models/automatic_purchase.py index eea66b99..87319bf6 100644 --- a/indoteknik_custom/models/automatic_purchase.py +++ b/indoteknik_custom/models/automatic_purchase.py @@ -88,7 +88,7 @@ class AutomaticPurchase(models.Model): if point.product_id.virtual_available > point.product_min_qty: continue qty_purchase = point.product_max_qty - point.product_id.virtual_available - po_line = self.env['purchase.order.line'].search([('product_id', '=', point.product_id.id), ('order_id.state', '=', 'done')], limit=1) + po_line = self.env['purchase.order.line'].search([('product_id', '=', point.product_id.id), ('order_id.state', '=', 'done')], order='id desc', limit=1) if self.vendor_id: purchase_price = self.env['purchase.pricelist'].search([ diff --git a/indoteknik_custom/models/requisition.py b/indoteknik_custom/models/requisition.py new file mode 100644 index 00000000..01d5ef55 --- /dev/null +++ b/indoteknik_custom/models/requisition.py @@ -0,0 +1,179 @@ +from odoo import models, fields, api +from odoo.exceptions import UserError +from datetime import datetime +import logging + +_logger = logging.getLogger(__name__) + + +class Requisition(models.Model): + _name = 'requisition' + _order = 'id desc' + + number = fields.Char(string='Document No', index=True, copy=False, readonly=True) + date_doc = fields.Date(string='Date', help='isi tanggal hari ini') + description = fields.Char(string='Description', help='bebas isinya apa aja') + requisition_lines = fields.One2many('requisition.line', 'requisition_id', string='Lines', auto_join=True) + notification = fields.Char(string='Notification') + is_po = fields.Boolean(string='Is PO') + requisition_match = fields.One2many('requisition.purchase.match', 'requisition_id', string='Matches', auto_join=True) + sale_order_id = fields.Many2one('sale.order', string='SO', help='harus diisi nomor SO yang ingin digenerate', + domain="[('state', '=', 'sale')]") + + @api.model + def create(self, vals): + vals['number'] = self.env['ir.sequence'].next_by_code('requisition') or '0' + result = super(Requisition, self).create(vals) + return result + + def create_requisition_from_sales(self): + if self.requisition_lines: + raise UserError('Sudah digenerate sebelumnya, hapus line terlebih dahulu') + if not self.sale_order_id: + raise UserError('Sale Order harus diisi') + if self.is_po: + raise UserError('Sudah jadi PO, tidak bisa di create ulang PO nya') + + old_requisition = self.env['requisition'].search([('sale_order_id', '=', self.sale_order_id.id)], limit=1) + if old_requisition: + raise UserError('Sudah pernah jadi Requisition') + + count = 0 + for order_line in self.sale_order_id.order_line: + # get purchase price altama, if nothing, then get other cheaper, if nothing then last po + purchase_price = 0 + vendor_id = 0 + + purchase_pricelist = self.env['purchase.pricelist'].search([ + ('product_id.id', '=', order_line.product_id.id), + ('vendor_id.id', '=', 5571) + ], order='product_price asc', limit=1) + purchase_price = purchase_pricelist.product_price + vendor_id = purchase_pricelist.vendor_id.id + source = 'PriceList' + + if not purchase_price or purchase_price <= 0: + purchase_pricelist = self.env['purchase.pricelist'].search([('product_id', '=', order_line.product_id.id)], order='product_price asc', limit=1) + purchase_price = purchase_pricelist.product_price + vendor_id = purchase_pricelist.vendor_id.id + source = 'PriceList' + + if not purchase_price or purchase_price <= 0: + last_po_line = self.env['purchase.order.line'].search([('product_id', '=', order_line.product_id.id), ('order_id.state', '=', 'done')], order='id desc', limit=1) + purchase_price = last_po_line.price_unit + vendor_id = last_po_line.order_id.partner_id.id + source = 'LastPO' + + if not purchase_price or purchase_price <= 0: + purchase_price = 0 + vendor_id = 5571 + source = 'Nothing' + + self.env['requisition.line'].create([{ + 'requisition_id': self.id, + 'partner_id': vendor_id, + 'brand_id': order_line.product_id.product_tmpl_id.x_manufacture.id, + 'product_id': order_line.product_id.id, + 'qty_purchase': order_line.product_uom_qty, + 'tax_id': order_line.purchase_tax_id.id, + 'price_unit': purchase_price, + 'subtotal': purchase_price * order_line.product_uom_qty, + 'source': source + }]) + count+=1 + _logger.info('Create Requisition %s' % order_line.product_id.name) + self.notification = "Requisition Created %s lines" % count + + def create_po_from_requisition(self): + if not self.requisition_lines: + raise UserError('Tidak ada Lines, belum bisa create PO') + if self.is_po: + raise UserError('Sudah pernah di create PO') + current_time = datetime.now() + vendor_ids = self.env['requisition.line'].read_group([('requisition_id', '=', self.id), ('partner_id', '!=', False)], fields=['partner_id'], groupby=['partner_id']) + + counter_po_number = 0 + for vendor in vendor_ids: + param_header = { + 'partner_id': vendor['partner_id'][0], + 'partner_ref': self.sale_order_id.name, + 'currency_id': 12, + 'user_id': self.env.user.id, + 'company_id': 1, # indoteknik dotcom gemilang + 'picking_type_id': 28, # indoteknik bandengan receipts + 'date_order': current_time, + 'sale_order_id': self.sale_order_id.id + } + # new_po = self.env['purchase.order'].create([param_header]) + products_vendors = self.env['requisition.line'].search([ + ('requisition_id', '=', self.id), + ('partner_id', '=', vendor['partner_id'][0]), + ('qty_purchase', '>', 0) + ], order='brand_id') + count = brand_id = 0 + new_po = '' + for product in products_vendors: + if not new_po or ((count == 200 or brand_id != product.brand_id.id) and vendor['partner_id'][0] == 5571): + count = 0 + counter_po_number += 1 + new_po = self.env['purchase.order'].create([param_header]) + new_po.name = new_po.name + "/R/"+str(counter_po_number) + self.env['requisition.purchase.match'].create([{ + 'requisition_id': self.id, + 'order_id': new_po.id + }]) + self.env.cr.commit() + # else: + # new_po = self.env['purchase.order'].create([param_header]) + brand_id = product.brand_id.id + count += 10 + param_line = { + 'order_id': new_po.id, + 'sequence': count, + 'product_id': product.product_id.id, + 'product_qty': product.qty_purchase, + 'product_uom_qty': product.qty_purchase, + 'price_unit': product.last_price, + 'taxes_id': product.tax_id + } + new_line = self.env['purchase.order.line'].create([param_line]) + product.current_po_id = new_po.id + product.current_po_line_id = new_line.id + _logger.info('Create PO Line %s' % product.product_id.name) + self.notification = self.notification + ' %s' % new_po.name + self.is_po = True + +class RequisitionLine(models.Model): + _name = 'requisition.line' + _description = 'Requisition Line' + _order = 'requisition_id, id' + + requisition_id = fields.Many2one('requisition', string='Ref', required=True, ondelete='cascade', index=True, copy=False) + brand_id = fields.Many2one('x_manufactures', string='Brand') + product_id = fields.Many2one('product.product', string='Product') + partner_id = fields.Many2one('res.partner', string='Vendor') + qty_purchase = fields.Float(string='Qty Purchase') + price_unit = fields.Float(string='Price') + tax_id = fields.Many2one('account.tax', help='isi tax pembelian include atau exclude', domain="[('type_tax_use', '=', 'purchase')]") + subtotal = fields.Float(string='Subtotal') + last_price = fields.Float(string='Last Price') + last_order_id = fields.Many2one('purchase.order', string='Last Order') + last_orderline_id = fields.Many2one('purchase.order.line', string='Last Order Line') + is_po = fields.Boolean(String='Is PO') + current_po_id = fields.Many2one('purchase.order', string='Current') + current_po_line_id = fields.Many2one('purchase.order.line', string='Current Line') + source = fields.Char(string='Source', help='data harga diambil darimana') + +class RequisitionPurchaseMatch(models.Model): + _name = 'requisition.purchase.match' + _order = 'requisition_id, id' + + requisition_id = fields.Many2one('requisition', string='Ref', required=True, ondelete='cascade', index=True, copy=False) + order_id = fields.Many2one('purchase.order', string='Purchase Order') + vendor = fields.Char(string='Vendor', compute='_compute_info_po') + total = fields.Float(string='Total', compute='_compute_info_po') + + def _compute_info_po(self): + for match in self: + match.vendor = match.order_id.partner_id.name + match.total = match.order_id.amount_total diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 39504393..26e852f1 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -48,4 +48,7 @@ access_apache_solr,access.apache.solr,model_apache_solr,,1,1,1,1 access_group_partner,access.group.partner,model_group_partner,,1,1,1,1 access_procurement_monitoring_detail,access.procurement.monitoring.detail,model_procurement_monitoring_detail,,1,1,1,1 access_rajaongkir_kurir,access.rajaongkir.kurir,model_rajaongkir_kurir,,1,1,1,1 -access_brand_vendor,access.brand.vendor,model_brand_vendor,,1,1,1,1 \ No newline at end of file +access_brand_vendor,access.brand.vendor,model_brand_vendor,,1,1,1,1 +access_requisition,access.requisition,model_requisition,,1,1,1,1 +access_requisition_line,access.requisition.line,model_requisition_line,,1,1,1,1 +access_requisition_purchase_match,access.requisition.purchase.match,model_requisition_purchase_match,,1,1,1,1 \ No newline at end of file diff --git a/indoteknik_custom/views/ir_sequence.xml b/indoteknik_custom/views/ir_sequence.xml index 6a6f474d..9af85408 100644 --- a/indoteknik_custom/views/ir_sequence.xml +++ b/indoteknik_custom/views/ir_sequence.xml @@ -30,5 +30,15 @@ 1 1 + + + Requisition + requisition + TRUE + RPO/%(year)s/ + 5 + 1 + 1 + \ No newline at end of file diff --git a/indoteknik_custom/views/requisition.xml b/indoteknik_custom/views/requisition.xml new file mode 100644 index 00000000..6e61ce1e --- /dev/null +++ b/indoteknik_custom/views/requisition.xml @@ -0,0 +1,101 @@ + + + + requisition.tree + requisition + + + + + + + + + + + + + requisition.line.tree + requisition.line + + + + + + + + + + + + + + + + requisition.purchase.match.tree + requisition.purchase.match + + + + + + + + + + + requisition.form + requisition + +
+ +
+ + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + Requisition + ir.actions.act_window + requisition + tree,form + + + + \ No newline at end of file -- cgit v1.2.3