diff options
| author | Azka Nathan <darizkyfaz@gmail.com> | 2025-07-04 15:23:18 +0700 |
|---|---|---|
| committer | Azka Nathan <darizkyfaz@gmail.com> | 2025-07-04 15:23:18 +0700 |
| commit | 0b16acf14c58fe224557d843101b256f7028fb5b (patch) | |
| tree | 8bdccd2e80072fb28dcaf879fd1a5d704cb8498b | |
| parent | dd93d36b4c7cec4e1681d69e296a7cff559386a0 (diff) | |
shipment group
| -rwxr-xr-x | fixco_custom/__manifest__.py | 2 | ||||
| -rwxr-xr-x | fixco_custom/models/__init__.py | 1 | ||||
| -rw-r--r-- | fixco_custom/models/requisition.py | 383 | ||||
| -rw-r--r-- | fixco_custom/models/shipment_group.py | 149 | ||||
| -rwxr-xr-x | fixco_custom/security/ir.model.access.csv | 7 | ||||
| -rw-r--r-- | fixco_custom/views/requisition.xml | 126 | ||||
| -rw-r--r-- | fixco_custom/views/shipment_group.xml | 25 | ||||
| -rw-r--r-- | fixco_custom/views/shipment_line.xml | 109 |
8 files changed, 792 insertions, 10 deletions
diff --git a/fixco_custom/__manifest__.py b/fixco_custom/__manifest__.py index 53df90a..9c943e0 100755 --- a/fixco_custom/__manifest__.py +++ b/fixco_custom/__manifest__.py @@ -32,6 +32,8 @@ 'views/upload_ginee.xml', 'views/report_picking_list.xml', 'views/purchase_order.xml', + 'views/requisition.xml', + 'views/shipment_line.xml', ], 'demo': [], 'css': [], diff --git a/fixco_custom/models/__init__.py b/fixco_custom/models/__init__.py index 226e6b9..4bc9e44 100755 --- a/fixco_custom/models/__init__.py +++ b/fixco_custom/models/__init__.py @@ -18,3 +18,4 @@ from . import uangmuka_penjualan from . import upload_ginee from . import purchase_order_line from . import purchase_order +from . import requisition diff --git a/fixco_custom/models/requisition.py b/fixco_custom/models/requisition.py new file mode 100644 index 0000000..1734abd --- /dev/null +++ b/fixco_custom/models/requisition.py @@ -0,0 +1,383 @@ +from odoo import models, fields, api, tools, _ +from odoo.exceptions import UserError +from datetime import datetime +import math +import logging + +_logger = logging.getLogger(__name__) + + +class RequisitionMatchPO(models.Model): + _name = 'v.requisition.match.po' + _auto = False + _rec_name = 'product_id' + + id = fields.Integer(string='ID') + product_id = fields.Many2one('product.product', string='Product') + qty_rpo = fields.Float(string='Qty RPO', help='Qty RPO yang sudah di PO namun SO masih Draft') + + # def init(self): + # tools.drop_view_if_exists(self.env.cr, self._table) + # self.env.cr.execute(""" + # create or replace view %s as + # select rl.product_id as id, rl.product_id, sum(rl.qty_purchase) as qty_rpo + # from requisition_line rl + # join requisition r on r.id = rl.requisition_id + # join requisition_purchase_match rpm on rpm.requisition_id = r.id + # join purchase_order po on po.id = rpm.order_id + # join sale_order so on so.id = r.sale_order_id + # where 1=1 + # and r.date_doc >= '2024-11-11' + # and po.state in ('done', 'purchase') + # and so.state in ('draft', 'sent') + # group by rl.product_id + # """ % self._table) + + +class Requisition(models.Model): + _name = 'requisition' + _order = 'id desc' + _inherit = ['mail.thread'] + _rec_name = 'number' + + 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') + sales_approve = fields.Boolean(string='Approval Status', tracking=3, copy=False) + merchandise_approve = fields.Boolean(string='Approval Status', tracking=3, copy=False) + + def generate_requisition_from_so(self): + state = ['done', 'sale'] + if not self.sale_order_id: + raise UserError('Sale Order Wajib Diisi dan Harus Draft') + if self.sale_order_id.state in state: + raise UserError('SO sudah Confirm, akan berakibat double Purchase melalui PJ') + if not self.sale_order_id.order_line: + raise UserError('Line SO masih kosong, harus diisi dulu') + for order_line in self.sale_order_id.order_line: + param = { + 'requisition_id': self.id, + 'product_id': order_line.product_id.id, + 'partner_id': order_line.vendor_id.id, + 'qty_purchase': order_line.product_uom_qty, + 'price_unit': order_line.purchase_price, + 'taxes_id': order_line.purchase_tax_id.id, + 'subtotal': order_line.purchase_price * order_line.product_uom_qty, + 'brand_id': order_line.product_id.x_manufacture.id + } + self.env['requisition.line'].create([param]) + + @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 button_approve(self): + state = ['done', 'sale'] + if self.sale_order_id.state in state: + raise UserError('SO sudah Confirm, akan berakibat double Purchase melalui PJ') + if self.env.user.id not in [21, 19, 28]: + raise UserError('Hanya Rafly dan Darren Yang Bisa Approve') + if self.env.user.id == 19 or self.env.user.id == 28: + self.sales_approve = True + elif self.env.user.id == 21 or self.env.user.id == 28: + self.merchandise_approve = True + + def create_po_from_requisition(self): + if not self.sales_approve and not self.merchandise_approve: + raise UserError('Harus Di Approve oleh Darren atau Rafly') + 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') + if not self.sale_order_id: + raise UserError('Tidak ada link dengan Sales Order, tidak bisa dihitung sebagai Plafon Qty di PO') + + vendor_ids = self.env['requisition.line'].read_group([ + ('requisition_id', '=', self.id), + ('partner_id', '!=', False) + ], fields=['partner_id'], groupby=['partner_id']) + + po_ids = [] + for vendor in vendor_ids: + result_po = self.create_po_by_vendor(vendor['partner_id'][0]) + po_ids += result_po + return { + 'name': _('Purchase Order'), + 'view_mode': 'tree,form', + 'res_model': 'purchase.order', + 'target': 'current', + 'type': 'ir.actions.act_window', + 'domain': [('id', 'in', po_ids)], + } + + def create_po_by_vendor(self, vendor_id): + current_time = datetime.now() + + PRODUCT_PER_PO = 20 + + requisition_line = self.env['requisition.line'] + + param_header = { + 'partner_id': vendor_id, + # '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, + 'note_description': 'from Purchase Requisition' + } + + domain = [ + ('requisition_id', '=', self.id), + ('partner_id', '=', vendor_id), + ('qty_purchase', '>', 0) + ] + + products_len = requisition_line.search_count(domain) + page = math.ceil(products_len / PRODUCT_PER_PO) + po_ids = [] + # i start from zero (0) + for i in range(page): + new_po = self.env['purchase.order'].create([param_header]) + new_po.name = new_po.name + "/R/" + str(i + 1) + po_ids.append(new_po.id) + lines = requisition_line.search( + domain, + offset=i * PRODUCT_PER_PO, + limit=PRODUCT_PER_PO + ) + tax = [22] + + for line in lines: + product = line.product_id + param_line = { + 'order_id' : new_po.id, + 'product_id': product.id, + 'product_qty': line.qty_purchase, + 'product_uom_qty': line.qty_purchase, + 'name': product.display_name, + 'price_unit': line.price_unit, + 'taxes_id': tax, + } + new_po_line = self.env['purchase.order.line'].create([param_line]) + line.current_po_id = new_po.id + line.current_po_line_id = new_po_line.id + + self.env['requisition.purchase.match'].create([{ + 'requisition_id': self.id, + 'order_id': new_po.id + }]) + self.is_po = True + + return po_ids + + # 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 + # po_ids = [] + # 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, + # 'note_description': 'from Purchase Requisition' + # } + # param_requisition_line = [ + # ('requisition_id', '=', self.id), + # ('partner_id', '=', vendor['partner_id'][0]), + # ('qty_purchase', '>', 0) + # ] + # # new_po = self.env['purchase.order'].create([param_header]) + # products_vendors = self.env['requisition.line'].search(, order='brand_id') + # count = brand_id = 0 + + # for product in products_vendors: + # if count > 200 or brand_id != product.brand_id.id: + # continue + + # 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 + # }]) + # po_ids.append(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 + + # # qty_available = product.product_id.qty_onhand_bandengan + product.product_id.qty_incoming_bandengan - product.product_id.outgoing_qty + # # suggest = 'harus beli' + # # if qty_available > product.qty_purchase: + # # suggest = 'masih cukup' + + # tax = [22] + + # param_line = { + + # 'sequence': count, + # 'product_id': product.product_id.id, + # 'product_qty': product.qty_purchase, + # 'product_uom_qty': product.qty_purchase, + # 'price_unit': product.price_unit, + # 'taxes_id': tax, + # # 'qty_available_store': qty_available, + # # 'suggest': suggest, + # } + # new_line = self.env['purchase.order.line'].create([param_line]) + # if new_po: + # new_line.write({ + # 'order_id': new_po.id, + # }) + # 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 + # if po_ids: + # return { + # 'name': _('Purchase Order'), + # 'view_mode': 'tree,form', + # 'res_model': 'purchase.order', + # 'target': 'current', + # 'type': 'ir.actions.act_window', + # 'domain': [('id', 'in', po_ids)], + # } + +class RequisitionLine(models.Model): + _name = 'requisition.line' + _description = 'Requisition Line' + _order = 'requisition_id, id' + _inherit = ['mail.thread'] + + 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', tracking=3,) + 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') + taxes_id = fields.Many2one('account.tax', string='Tax') + 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') + qty_available_store = fields.Float(string='Available') + suggest = fields.Char(string='Suggest') + + def _get_valid_purchase_price(self, purchase_price): + price = 0 + taxes = 24 + human_last_update = purchase_price.human_last_update or datetime.min + system_last_update = purchase_price.system_last_update or datetime.min + + #if purchase_price.taxes_product_id.type_tax_use == 'purchase': + price = purchase_price.product_price + taxes = purchase_price.taxes_product_id.id or 24 + + if system_last_update > human_last_update: + #if purchase_price.taxes_system_id.type_tax_use == 'purchase': + price = purchase_price.system_price + taxes = purchase_price.taxes_system_id.id or 24 + + return price, taxes + + @api.onchange('price_unit') + def _onchange_price_unit(self): + for line in self: + line.subtotal = line.price_unit * line.qty_purchase + + @api.onchange('product_id') + def _onchange_product(self): + for line in self: + line.brand_id = line.product_id.product_tmpl_id.x_manufacture.id + purchase_pricelist = self.env['purchase.pricelist'].search([ + ('product_id', '=', line.product_id.id) + ],order='count_trx_po desc, count_trx_po_vendor desc', limit=1) + + price, taxes = line._get_valid_purchase_price(purchase_pricelist) + line.price_unit = price + line.taxes_id = taxes + line.partner_id = purchase_pricelist.vendor_id.id + + @api.model + def create(self, vals): + record = super(RequisitionLine, self).create(vals) + record._track_changes('Tambah') + return record + + def write(self, vals): + for record in self: + old_values = {field: record[field] for field in vals if field in record} + + result = super(RequisitionLine, self).write(vals) + + for record in self: + record._track_changes('Updated', old_values) + + return result + + def unlink(self): + for record in self: + record._track_changes('Hapus') + return super(RequisitionLine, self).unlink() + + def _track_changes(self, action, old_values=None): + message = f"Produk telah di-{action} : <br/>" + if action == 'Tambah': + # message += f"<br/> Product: {self.product_id.name}" + message += f"Product: {self.product_id.name} <br/> Vendor: {self.partner_id.name} <br/> Qty: {self.qty_purchase} <br/> Price: {self.price_unit} <br/> Tax: {self.tax_id.name} <br/> Subtotal: {self.subtotal} <br/> Brand: {self.brand_id.x_name}" + elif action == 'Hapus': + # message += f"<br/> Deleted Product: {self.product_id.name}" + message += f"<br/> Deleted Product: {self.product_id.name} <br/> Vendor: {self.partner_id.name} Qty: {self.qty_purchase} <br/> Price: {self.price_unit} <br/> Tax: {self.tax_id.name} <br/> Subtotal: {self.subtotal} <br/> Brand: {self.brand_id.x_name}" + else: # Updated + for field, old_value in old_values.items(): + new_value = self[field] + if old_value != new_value: + field_label = self._fields[field].string # Ambil nama label field + message += f"{field_label}: {old_value} -> {new_value}<br/>" + + if self.requisition_id: + self.requisition_id.message_post(body=message) + +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/fixco_custom/models/shipment_group.py b/fixco_custom/models/shipment_group.py index 3d60840..228306f 100644 --- a/fixco_custom/models/shipment_group.py +++ b/fixco_custom/models/shipment_group.py @@ -1,10 +1,29 @@ -from odoo import models, api, fields +from odoo import fields, models, api, _ from odoo.exceptions import AccessError, UserError, ValidationError -from datetime import timedelta, date +from odoo.tools.float_utils import float_is_zero +from collections import defaultdict +from datetime import timedelta, datetime +from datetime import timedelta, datetime as waktu +from itertools import groupby +import pytz, requests, json, requests +from dateutil import parser +import datetime +import hmac +import hashlib +import base64 +import requests +import time import logging +import re +from hashlib import sha256 _logger = logging.getLogger(__name__) + +Request_URI = '/openapi/order/v2/list-order' +ACCESS_KEY = '24bb6a1ec618ec6a' +SECRET_KEY = '32e4a78ad05ee230' + class ShipmentGroup(models.Model): _name = "shipment.group" _description = "Shipment Group" @@ -14,11 +33,56 @@ class ShipmentGroup(models.Model): number = fields.Char(string='Document No', index=True, copy=False, readonly=True, tracking=True) shipment_line = fields.One2many('shipment.group.line', 'shipment_id', string='Shipment Group Lines', auto_join=True) picking_lines = fields.One2many('picking.line', 'shipment_id', string='Picking Lines', auto_join=True) + related_count = fields.Integer(compute='_compute_related_count', string='Related Count') + + def sync_product_to_picking_line(self): + for shipment in self: + for picking_line in shipment.picking_lines: + shipment_lines = self.env['shipment.group.line'].search([ + ('shipment_id', '=', shipment.id), + ('invoice_marketplace', '=', picking_line.invoice_marketplace), + ('picking_id', '=', picking_line.picking_id.id) + ]) + + picking_line.product_shipment_lines.unlink() + + for sl in shipment_lines: + self.env['product.shipment.line'].create({ + 'picking_line_id': picking_line.id, + 'product_id': sl.product_id.id, + 'carrier': sl.carrier or picking_line.carrier, + 'invoice_marketplace': sl.invoice_marketplace, + 'picking_id': sl.picking_id.id, + 'order_reference': sl.order_reference, + }) + + def _compute_related_count(self): + for record in self: + record.related_count = len(record.picking_lines) + + def action_view_related_line(self): + self.ensure_one() + + pickingLines = self.env['picking.line'] + + base_bu = pickingLines.search([ + ('shipment_id', '=', self.id) + ]) + + all_bu = base_bu + + return { + 'name': 'Related', + 'type': 'ir.actions.act_window', + 'res_model': 'picking.line', + 'view_mode': 'tree,form', + 'target': 'current', + 'domain': [('id', 'in', list(all_bu.ids))], + } @api.constrains('picking_lines') def _check_picking_lines(self): for record in self: - record.shipment_line.unlink() for picking_line in record.picking_lines: if not picking_line.picking_id: @@ -37,8 +101,59 @@ class ShipmentGroup(models.Model): 'product_id': move.product_id.id, 'carrier': picking_line.picking_id.carrier, 'invoice_marketplace': picking_line.picking_id.invoice_mp, + 'order_reference': picking_line.order_reference, 'picking_id': picking_line.picking_id.id }) + + def get_status(self): + for picking_line in self.picking_lines: + try: + order_id = picking_line.invoice_marketplace + + authorization = self.sign_request() + headers = { + 'Content-Type': 'application/json', + 'X-Advai-Country': 'ID', + 'Authorization': authorization + } + payload = { + "orderNumbers": [order_id], + } + url = "https://api.ginee.com/openapi/order/v2/list-order" + + response = requests.post( + url, + headers=headers, + data=json.dumps(payload) + ) + + if response.status_code == 200: + data = response.json() + if data.get('code') == 'SUCCESS' and data.get('message') == 'OK': + content = data.get('data', {}).get('content', []) + + if not content: + raise UserError(_("No List Order information found in response")) + + content_info = content[0] + if content_info.get('orderStatus') == 'CANCELLED': + picking_line.status = content_info.get('orderStatus') + else: + picking_line.status = '' + else: + raise UserError(_("API Error: %s - %s") % (data.get('code', 'UNKNOWN'), data.get('message', 'No error message'))) + else: + raise UserError(_("API request failed with status code: %s") % response.status_code) + + except Exception as e: + raise UserError(_("Error: %s") % str(e)) + + def sign_request(self): + signData = '$'.join(['POST', Request_URI]) + '$' + authorization = ACCESS_KEY + ':' + base64.b64encode( + hmac.new(SECRET_KEY.encode('utf-8'), signData.encode('utf-8'), digestmod=sha256).digest() + ).decode('ascii') + return authorization @api.model @@ -57,6 +172,7 @@ class ShipmentGroupLine(models.Model): carrier = fields.Char(string='Shipping Method') invoice_marketplace = fields.Char(string='Invoice Marketplace') picking_id = fields.Many2one('stock.picking', string='Picking') + order_reference = fields.Char(string='Order Reference') class PickingLine(models.Model): @@ -65,16 +181,33 @@ class PickingLine(models.Model): _order = 'shipment_id, id' shipment_id = fields.Many2one('shipment.group', string='Shipment Ref', required=True, ondelete='cascade') + product_shipment_lines = fields.One2many('product.shipment.line', 'picking_line_id', string='Product Shipment Lines', auto_join=True) picking_id = fields.Many2one('stock.picking', string='Picking') - scan_invoice_marketplace = fields.Char(string="Scan Invoice Marketplace") + scan_receipt = fields.Char(string="Scan Receipt") + invoice_marketplace = fields.Char(string='Invoice Marketplace') carrier = fields.Char(string='Ekspedisi') + order_reference = fields.Char(string='Order Reference') + status = fields.Char(string='Status') - @api.onchange('scan_invoice_marketplace') - def _onchange_scan_invoice_marketplace(self): + @api.onchange('scan_receipt') + def _onchange_scan_receipt(self): for line in self: - if line.scan_invoice_marketplace: - picking = self.env['stock.picking'].search([('invoice_mp', '=', line.scan_invoice_marketplace)], limit=1) + if line.scan_receipt: + picking = self.env['stock.picking'].search([('tracking_number', '=', line.scan_receipt)], limit=1) line.picking_id = picking.id line.carrier = picking.carrier + line.order_reference = picking.order_reference + line.invoice_marketplace = picking.invoice_mp + +class ProductShipmentLine(models.Model): + _name = 'product.shipment.line' + _description = 'Product Shipment Line' + _order = 'picking_line_id, id' + picking_line_id = fields.Many2one('picking.line', string='Picking Line', required=True, ondelete='cascade') + product_id = fields.Many2one('product.product', string='Product') + carrier = fields.Char(string='Shipping Method') + invoice_marketplace = fields.Char(string='Invoice Marketplace') + picking_id = fields.Many2one('stock.picking', string='Picking') + order_reference = fields.Char(string='Order Reference') diff --git a/fixco_custom/security/ir.model.access.csv b/fixco_custom/security/ir.model.access.csv index 1fa0a59..14a8780 100755 --- a/fixco_custom/security/ir.model.access.csv +++ b/fixco_custom/security/ir.model.access.csv @@ -21,4 +21,9 @@ access_stock_picking_print_picking_list,access.stock.picking.print_picking_list, access_uangmuka_penjualan,access.uangmuka.penjualan,model_uangmuka_penjualan,,1,1,1,1 access_picking_line,access.picking.line,model_picking_line,,1,1,1,1 access_upload_ginee,access.upload.ginee,model_upload_ginee,,1,1,1,1 -access_upload_ginee_line,access.upload.ginee.line,model_upload_ginee_line,,1,1,1,1
\ No newline at end of file +access_upload_ginee_line,access.upload.ginee.line,model_upload_ginee_line,,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 +access_v_requisition_match_po,access.v.requisition.match.po,model_v_requisition_match_po,,1,1,1,1 +access_product_shipment_line,access.product.shipment.line,model_product_shipment_line,,1,1,1,1
\ No newline at end of file diff --git a/fixco_custom/views/requisition.xml b/fixco_custom/views/requisition.xml new file mode 100644 index 0000000..957113a --- /dev/null +++ b/fixco_custom/views/requisition.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <record id="requisition_tree" model="ir.ui.view"> + <field name="name">requisition.tree</field> + <field name="model">requisition</field> + <field name="arch" type="xml"> + <tree> + <field name="date_doc"/> + <field name="number"/> + <field name="description"/> + <field name="notification" readonly="1"/> + <field name="is_po" readonly="1"/> + </tree> + </field> + </record> + + <record id="requisition_line_tree" model="ir.ui.view"> + <field name="name">requisition.line.tree</field> + <field name="model">requisition.line</field> + <field name="arch" type="xml"> + <tree> + <field name="brand_id"/> + <field name="product_id"/> + <field name="partner_id"/> + <field name="qty_purchase"/> + <field name="price_unit"/> + <field name="tax_id"/> + <field name="subtotal"/> + <field name="source"/> + <field name="qty_available_store"/> + <field name="suggest"/> + </tree> + </field> + </record> + + <record id="requisition_purchase_match_tree" model="ir.ui.view"> + <field name="name">requisition.purchase.match.tree</field> + <field name="model">requisition.purchase.match</field> + <field name="arch" type="xml"> + <tree> + <field name="order_id" readonly="1"/> + <field name="vendor" readonly="1"/> + <field name="total" readonly="1"/> + </tree> + </field> + </record> + + <record id="requisition_form" model="ir.ui.view"> + <field name="name">requisition.form</field> + <field name="model">requisition</field> + <field name="arch" type="xml"> + <form> + <header> + <button name="button_approve" + string="Approve" + type="object" + class="mr-2 oe_highlight" + /> + </header> + <sheet string="Requisition"> + <div class="oe_button_box" name="button_box"/> + <group> + <group> + <field name="number"/> + <field name="date_doc"/> + <field name="sale_order_id"/> + <field name="description"/> + <field name="notification" readonly="1"/> + </group> + <group> + <div> + <button name="generate_requisition_from_so" + string="Create Line from SO" + type="object" + class="mr-2 oe_highlight" + /> + </div> + <div> + <button name="create_po_from_requisition" + string="Create PO" + type="object" + class="mr-2 oe_highlight" + /> + </div> + </group> + </group> + <notebook> + <page string="Lines"> + <field name="requisition_lines"> + <tree editable="line"> + <field name="product_id" required="1"/> + <field name="partner_id" required="1" /> + <field name="qty_purchase" required="1" /> + <field name="price_unit" required="1" /> + <field name="taxes_id" readonly="1" /> + <field name="subtotal" readonly="1" /> + <field name="brand_id" /> + </tree> + </field> + </page> + <page string="Matches"> + <field name="requisition_match"/> + </page> + </notebook> + </sheet> + <div class="oe_chatter"> + <field name="message_follower_ids" widget="mail_followers"/> + <field name="message_ids" widget="mail_thread"/> + </div> + </form> + </field> + </record> + + <record id="requisition_action" model="ir.actions.act_window"> + <field name="name">Requisition</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">requisition</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem id="menu_requisition" + name="Requisition" + action="requisition_action" + parent="purchase.menu_procurement_management" + sequence="300"/> +</odoo>
\ No newline at end of file diff --git a/fixco_custom/views/shipment_group.xml b/fixco_custom/views/shipment_group.xml index 8a6c303..8ebcef9 100644 --- a/fixco_custom/views/shipment_group.xml +++ b/fixco_custom/views/shipment_group.xml @@ -15,7 +15,26 @@ <field name="model">shipment.group</field> <field name="arch" type="xml"> <form> + <header> + <button name="get_status" + string="Get Status" + type="object" + class="oe_highlight" + /> + <button name="sync_product_to_picking_line" + string="Sync Picking Line" + type="object" + class="oe_highlight" + /> + </header> <sheet> + <div class="oe_button_box" name="button_box"> + <button type="object" name="action_view_related_line" + class="oe_stat_button" + icon="fa-pencil-square-o"> + <field name="related_count" widget="statinfo" string="Related Line"/> + </button> + </div> <group> <group> <field name="number" readonly="1"/> @@ -25,9 +44,12 @@ <page string="Picking Line"> <field name="picking_lines"> <tree editable="bottom"> - <field name="scan_invoice_marketplace"/> + <field name="scan_receipt"/> <field name="picking_id"/> <field name="carrier"/> + <field name="invoice_marketplace"/> + <field name="order_reference" optional="hide"/> + <field name="status"/> </tree> </field> </page> @@ -37,6 +59,7 @@ <field name="product_id"/> <field name="carrier"/> <field name="invoice_marketplace"/> + <field name="order_reference" optional="hide"/> <field name="picking_id"/> </tree> </field> diff --git a/fixco_custom/views/shipment_line.xml b/fixco_custom/views/shipment_line.xml new file mode 100644 index 0000000..dbeb1bb --- /dev/null +++ b/fixco_custom/views/shipment_line.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data> + <record id="view_picking_line_search" model="ir.ui.view"> + <field name="name">picking.line.search</field> + <field name="model">picking.line</field> + <field name="arch" type="xml"> + <search> + <field name="carrier"/> + <filter string="Carrier" name="carrier_filter" domain="[('carrier','!=',False)]"/> + <filter string="Group by Carrier" name="group_carrier" context="{'group_by':'carrier'}"/> + </search> + </field> + </record> + + <record id="view_product_shipment_line_search" model="ir.ui.view"> + <field name="name">product.shipment.line.search</field> + <field name="model">product.shipment.line</field> + <field name="arch" type="xml"> + <search> + <field name="carrier"/> + <filter string="Carrier" name="carrier_filter" domain="[('carrier','!=',False)]"/> + <filter string="Group by Carrier" name="group_carrier" context="{'group_by':'carrier'}"/> + </search> + </field> + </record> + + <record id="view_picking_line_tree" model="ir.ui.view"> + <field name="name">picking.line.tree</field> + <field name="model">picking.line</field> + <field name="arch" type="xml"> + <tree> + <field name="shipment_id"/> + <field name="picking_id" widget="many2one_clickable"/> + <field name="scan_receipt"/> + <field name="invoice_marketplace"/> + <field name="carrier"/> + <field name="order_reference"/> + <field name="status"/> + </tree> + </field> + </record> + + <record id="view_picking_line_form" model="ir.ui.view"> + <field name="name">picking.line.form</field> + <field name="model">picking.line</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <group> + <field name="shipment_id"/> + <field name="picking_id" widget="many2one_clickable"/> + <field name="scan_receipt"/> + </group> + <group> + <field name="invoice_marketplace"/> + <field name="carrier"/> + <field name="order_reference"/> + <field name="status"/> + </group> + </group> + <field name="product_shipment_lines" mode="tree"> + <tree editable="bottom"> + <field name="product_id"/> + <field name="carrier"/> + <field name="invoice_marketplace"/> + <field name="picking_id" widget="many2one_clickable"/> + <field name="order_reference"/> + </tree> + </field> + </sheet> + </form> + </field> + </record> + + <record id="action_picking_line" model="ir.actions.act_window"> + <field name="name">Shipment Lines</field> + <field name="res_model">picking.line</field> + <field name="view_mode">tree,form</field> + <field name="help" type="html"> + <p class="o_view_nocontent_smiling_face">Create a new shipment line</p> + </field> + </record> + + <menuitem + action="action_picking_line" + id="shipment_lines" + parent="stock.menu_stock_warehouse_mgmt" + name="Shipment Lines" + sequence="1" + /> + + <record id="view_product_shipment_line_tree" model="ir.ui.view"> + <field name="name">product.shipment.line.tree</field> + <field name="model">product.shipment.line</field> + <field name="arch" type="xml"> + <tree> + <field name="picking_line_id"/> + <field name="product_id"/> + <field name="carrier"/> + <field name="invoice_marketplace"/> + <field name="picking_id" widget="many2one_clickable"/> + <field name="order_reference"/> + </tree> + </field> + </record> + </data> +</odoo>
\ No newline at end of file |
