Skip to content

Commit

Permalink
[ADD] add import bom method
Browse files Browse the repository at this point in the history
  • Loading branch information
jayraj-omnia committed Jan 21, 2025
1 parent bd6e005 commit 2fc4e1b
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 35 deletions.
152 changes: 122 additions & 30 deletions plm_box/models/ir_attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@
Created on Mar 8, 2017
@author: daniel
"""
import base64
import csv
import datetime
import logging
import pytz
import json
import logging
import os
import base64
import csv
import pytz

from dateutil import parser

from odoo import _, api, fields, models
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -174,8 +176,10 @@ def returnDocsOfFilesChanged(self, valuesDict):
outDocs = []
for docName, (docContent, _writeDateClient) in valuesDict.items():
for ir_attachment_id in self.search([("name", "=", docName)]):
if ir_attachment_id.datas != docContent \
and ir_attachment_id.getDocumentState() == "check-out-by-me":
if (
ir_attachment_id.datas != docContent
and ir_attachment_id.getDocumentState() == "check-out-by-me"
):
outDocs.append(docName)
return outDocs

Expand All @@ -184,11 +188,11 @@ def getDocumentState(self):
checkedOutByMe = self._is_checkedout_for_me()
checkedIn = self.ischecked_in()
if checkedOutByMe:
return 'check-out-by-me'
return "check-out-by-me"
if checkedIn:
return 'check-in'
return "check-in"
else:
return 'check-out'
return "check-out"

@api.model
def checkDocumentPresent(self, doc_dict={}):
Expand Down Expand Up @@ -234,40 +238,128 @@ def getDocumentStateMulty(self):

@api.model
def import_bom_from_csv(self, box_id, doc_id):
"""
This method processes a CSV file attached to a specific box, extracts
product details, and creates BOM lines based on the column mapping defined
in the box.
Args:
box_id (int): The ID of the PLM box containing the CSV structure mapping.
doc_id (int): The ID of the attachment (CSV file) to be processed.
"""
if doc_id and box_id:
attachment_id = self.env['ir.attachment'].browse(doc_id)
attachment_id = self.env["ir.attachment"].browse(doc_id)
product_details = self.parse_file_name(attachment_id.name)
if product_details and product_details.get('prefix') == "IMP_BOM":
product_id = self.env['product.product'].search([
("engineering_code","=", product_details.get('part_number'))
])

box_id = self.env['plm.box'].browse(box_id)
csv_column_mapping = json.loads(box_id.csv_structure)
file_content = base64.b64decode(attachment_id.datas)
csv_reader = csv.reader(file_content.decode('utf-8').splitlines())
bom_lines = []
for row in csv_reader:
bom_line_data = {}

if product_details and product_details.get("prefix") == "IMP_BOM":
product_id = self.product_by_engcode(
product_details.get("part_number"), product_details.get("revision")
)
bom_ids = self.get_create_bom(product_id)
if bom_ids:
box_id = self.env["plm.box"].browse(box_id)
csv_column_mapping = json.loads(box_id.csv_structure)
file_content = base64.b64decode(attachment_id.datas)
csv_reader = csv.reader(file_content.decode("utf-8").splitlines())
headers = next(csv_reader)
existing_bom_lines = self.env["mrp.bom.line"].search(
[("bom_id", "=", bom_ids[0].id)]
)
existing_bom_lines.unlink()
bom_lines = []
for row in csv_reader:
bom_line_data = {}
for odoo_field, csv_column in csv_column_mapping.items():
if csv_column in headers:
index = headers.index(csv_column)
bom_line_data[odoo_field] = row[index]
bom_lines.append(
self.create_bom_line_data(
bom_line_data, bom_ids[0], product_id, attachment_id
)
)
self.env["mrp.bom.line"].create(bom_lines)
return True

@api.model
def create_bom_line_data(self, bom_line_data, bom_id, product_id, attachment_id):
"""
a custom method will use to prepare BOM line data and return dictionary of
updated data which will directly use to create BoM line recode.
"""

if bom_line_data and bom_id and product_id and attachment_id:
line_product_id = self.product_by_engcode(
engcode=bom_line_data.get("engineering_code"),
revision=bom_line_data.get("engineering_revision"),
)
bom_line_data["bom_id"] = bom_id.id
bom_line_data["product_id"] = line_product_id.id
bom_line_data["product_qty"] = bom_line_data.get("qty", 1)
bom_line_data["product_uom_id"] = line_product_id.uom_id.id
bom_line_data["source_id"] = attachment_id.id
# bom_line_id = self.env['mrp.bom.line'].create(bom_line_data)
# return _logger.info(f"{bom_line_id} Created Successfully")
return bom_line_data

# Function to validate and extract details from the file name
@api.model
def parse_file_name(self,fname):
if fname.endswith('.csv'):
parts = fname.split('_')
if parts[0] == 'IMP' or parts[1] == 'BOM':
def parse_file_name(self, fname):
"""
a custom method take file name as string and extract details from the file name.
return product_details dictionary
"""
if fname.endswith(".csv"):
parts = fname.split("_")
if parts[0] == "IMP" or parts[1] == "BOM":
try:
part_number = parts[2]
revision = parts[3].split('.')[0]
revision = parts[3].split(".")[0]
except IndexError:
return "Invalid file: missing part number or revision"

return {
"prefix": f"{parts[0]}_{parts[1]}",
"part_number": part_number,
"revision": revision,
"file_extension": os.path.splitext(fname)[1]
"file_extension": os.path.splitext(fname)[1],
}

@api.model
def product_by_engcode(self, engcode, revision):
"""
a custom method takes engcode and revision as parameter and return product_id
if product not available then create it and return product_id.
"""

if engcode and revision:
product_id = self.env["product.product"].search(
[
("engineering_code", "=", engcode),
("engineering_revision", "=", revision),
],
limit=1,
)
if not product_id:
product_id = self.env["product.product"].create(
{
"engineering_code": engcode,
"name": f"{engcode}_{revision}",
"engineering_revision": revision,
}
)
return product_id
raise UserError(_("Invalid File Name: missing part number or revision"))

def get_create_bom(self, product_id):
"""
a custom method takes product_id as parameter and return bom_ids
if bom not available then create it and return bom_ids.
"""
if not product_id.bom_ids:
self.env["mrp.bom"].create(
{
"product_tmpl_id": product_id.product_tmpl_id.id,
"product_id": product_id.id,
"type": "normal",
}
)
return product_id.bom_ids
5 changes: 4 additions & 1 deletion plm_box/models/plm_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ class Plm_box(models.Model):
box_id = fields.Integer(_("Box ID"))
version = fields.Integer(_("Version"))
description = fields.Text(_("Description"))
csv_structure = fields.Text(_('CSV Structure'), default="""{"engineering_code":"","engineering_revision": "","qty":""}""")
csv_structure = fields.Text(
_("CSV Structure"),
default="""{"engineering_code": "","engineering_revision": "","qty": ""}""",
)

document_rel = fields.One2many("ir.attachment", "plm_box_id", "Documents")
plm_box_rel = fields.Many2many(
Expand Down
3 changes: 0 additions & 3 deletions plm_box/views/ir_attachment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,4 @@
(0, 0, {'view_mode': 'form', 'view_id': ref('plm_box.view_attachment_form_plm_box')})
]"/>
</record>



</odoo>
1 change: 0 additions & 1 deletion plm_box/views/non_cad_doc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,5 @@
<field name="view_id" ref="plm_box_list"/>
</record>


</data>
</odoo>

0 comments on commit 2fc4e1b

Please sign in to comment.