Browse Source

Feb 12 : [FIX] License Updated 'ocr_data_retrieval'

pull/267/merge
RisvanaCybro 1 year ago
parent
commit
b6be56cbab
  1. 10
      ocr_data_retrieval/README.rst
  2. 12
      ocr_data_retrieval/__init__.py
  3. 59
      ocr_data_retrieval/__manifest__.py
  4. 12
      ocr_data_retrieval/models/__init__.py
  5. 466
      ocr_data_retrieval/models/ocr_data_template.py

10
ocr_data_retrieval/README.rst

@ -1,6 +1,6 @@
.. image:: https://img.shields.io/badge/licence-LGPL--3-green.svg
:target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
OCR Data Retrieval
==================
@ -18,8 +18,8 @@ Company
License
-------
General Public License, Version 3 (LGPL v3).
(https://www.gnu.org/licenses/lgpl-3.0-standalone.html)
GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPLv3)
(https://www.gnu.org/licenses/agpl-3.0-standalone.html)
Credits
-------

12
ocr_data_retrieval/__init__.py

@ -3,19 +3,19 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Sruthi Renjith (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################

59
ocr_data_retrieval/__manifest__.py

@ -3,49 +3,46 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Sruthi Renjith (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
{
'name': 'OCR Data Retrieval',
'version': '16.0.1.0.0',
'category': 'Productivity',
'summary': 'Data retrieval from scanned documents',
'description': """Data retrieval from scanned documents with .jpg,
"name": "OCR Data Retrieval",
"version": "16.0.1.0.0",
"category": "Productivity",
"summary": "Data retrieval from scanned documents",
"description": """Data retrieval from scanned documents with .jpg,
.jpeg, .png and .pdf files. Also mapping them to appropriate models""",
'author': "Cybrosys Techno Solutions",
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': "https://www.cybrosys.com",
'depends': ['base', 'hr_expense', 'bill_digitization', 'contacts',
'purchase'],
'assets': {
'web.assets_backend': [
'/ocr_data_retrieval/static/src/js/image_field.js',
"author": "Cybrosys Techno Solutions",
"company": "Cybrosys Techno Solutions",
"maintainer": "Cybrosys Techno Solutions",
"website": "https://www.cybrosys.com",
"depends": ["base", "hr_expense", "bill_digitization", "contacts", "purchase"],
"assets": {
"web.assets_backend": [
"/ocr_data_retrieval/static/src/js/image_field.js",
],
},
'data': ['security/ir.model.access.csv',
'views/ocr_data_template_views.xml'],
'external_dependencies': {
'python': ['pdf2image', 'PIL', 'pytesseract', 'spacy',
'en_core_web_sm']
"data": ["security/ir.model.access.csv", "views/ocr_data_template_views.xml"],
"external_dependencies": {
"python": ["pdf2image", "PIL", "pytesseract", "spacy", "en_core_web_sm"]
},
'images': ['static/description/banner.jpg'],
'license': 'LGPL-3',
'installable': True,
'auto_install': False,
'application': False,
}
"images": ["static/description/banner.jpg"],
"license": "AGPL-3",
"installable": True,
"auto_install": False,
"application": False,
}

12
ocr_data_retrieval/models/__init__.py

@ -3,19 +3,19 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Sruthi Renjith (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################

466
ocr_data_retrieval/models/ocr_data_template.py

@ -3,19 +3,19 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Sruthi Renjith (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
@ -31,31 +31,36 @@ from odoo.exceptions import ValidationError
class OCRDataTemplate(models.TransientModel):
""" Class to read document and extract the text from JPG, JPEG, PNG and
PDF files. """
"""Class to read document and extract the text from JPG, JPEG, PNG and
PDF files."""
_name = "ocr.data.template"
_description = "Data Retrieving Template"
_rec_name = "file_name"
image = fields.Binary(string="Document", required=True,
help="Upload .jpg, .jpeg, .png or .pdf files")
image = fields.Binary(
string="Document", required=True, help="Upload .jpg, .jpeg, .png or .pdf files"
)
file_name = fields.Char(string="Document Name", help="Name of document")
image2 = fields.Image(string="Document",
help="Uploaded document", store=True)
flag = fields.Boolean(string="Flag", default=False,
help="Flag to check document read or not")
data = fields.Text(string="Data", readonly=True,
help="Content from the document")
image2 = fields.Image(string="Document", help="Uploaded document", store=True)
flag = fields.Boolean(
string="Flag", default=False, help="Flag to check document read or not"
)
data = fields.Text(string="Data", readonly=True, help="Content from the document")
model_name_id = fields.Many2one(
'ir.model', string="Model",
"ir.model",
string="Model",
domain="[('model', 'in', ['res.partner', 'account.move', "
"'hr.employee', 'hr.expense', 'sale.order', "
"'purchase.order'])]",
help="Model to which the data want to map")
help="Model to which the data want to map",
)
model_field_ids = fields.Many2many(
'ir.model.fields', string="Fields",
"ir.model.fields",
string="Fields",
domain="[('model_id', '=', model_name_id)]",
help="Fields names to map data")
help="Fields names to map data",
)
def data_segmentation(self, img):
"""
@ -64,7 +69,7 @@ class OCRDataTemplate(models.TransientModel):
"""
img = ImageOps.grayscale(img)
threshold_value = 176
img = img.point(lambda x: 255 if x > threshold_value else 0, '1')
img = img.point(lambda x: 255 if x > threshold_value else 0, "1")
img_rgb = ImageOps.invert(img.convert("RGB"))
segments = []
segment_bounds = img_rgb.getbbox()
@ -84,23 +89,31 @@ class OCRDataTemplate(models.TransientModel):
try:
# Getting the file path from ir.attachments
file_attachment = self.env["ir.attachment"].search(
['|', ('res_field', '!=', False), ('res_field', '=', False),
('res_id', '=', self.id),
('res_model', '=', 'ocr.data.template')],
limit=1)
[
"|",
("res_field", "!=", False),
("res_field", "=", False),
("res_id", "=", self.id),
("res_model", "=", "ocr.data.template"),
],
limit=1,
)
file_path = file_attachment._full_path(file_attachment.store_fname)
segmented_data = []
# Reading files in the format .jpg, .jpeg and .png
if (split_tup[1] == '.jpg' or split_tup[1] == '.jpeg' or
split_tup[1] == '.png'):
with open(file_path, mode='rb') as f:
if (
split_tup[1] == ".jpg"
or split_tup[1] == ".jpeg"
or split_tup[1] == ".png"
):
with open(file_path, mode="rb") as f:
binary_data = f.read()
img = Image.open(io.BytesIO(binary_data))
# Calling the function to do segmentation
segmented_data = self.data_segmentation(img)
elif split_tup[1] == '.pdf':
elif split_tup[1] == ".pdf":
# Reading files in the format .pdf
with open(file_path, mode='rb') as f:
with open(file_path, mode="rb") as f:
pdf_data = f.read()
pages = convert_from_bytes(pdf_data)
# Making the contents in 2 or more pages into combined page
@ -110,7 +123,7 @@ class OCRDataTemplate(models.TransientModel):
for page in pages:
resized_page = page.resize((2400, 1800))
resized_images.append(resized_page)
combined_image = Image.new('RGB', (max_width, total_height))
combined_image = Image.new("RGB", (max_width, total_height))
y_offset = 0
for resized_page in resized_images:
combined_image.paste(resized_page, (0, y_offset))
@ -118,8 +131,7 @@ class OCRDataTemplate(models.TransientModel):
# Calling the segmentation function
segmented_data = self.data_segmentation(combined_image)
except Exception:
self.env['ocr.data.template'].search([], order="id desc",
limit=1).unlink()
self.env["ocr.data.template"].search([], order="id desc", limit=1).unlink()
raise ValidationError(_("Cannot identify data"))
# Converting the segmented image into text using pytesseract
text = ""
@ -133,16 +145,16 @@ class OCRDataTemplate(models.TransientModel):
self.data = text
self.flag = True
@api.onchange('model_name_id')
@api.onchange("model_name_id")
def onchange_model_name_id(self):
""" Function to update the Many2many field to empty """
self.write({'model_field_ids': [(6, 0, [])]})
"""Function to update the Many2many field to empty"""
self.write({"model_field_ids": [(6, 0, [])]})
def find_person_name(self):
"""
Function to find person name from the retrieved text using 'spacy'
"""
person = ''
person = ""
nlp = spacy.load("en_core_web_sm")
doc = nlp(self.data)
for entity in doc.ents:
@ -158,7 +170,7 @@ class OCRDataTemplate(models.TransientModel):
product_line_list = []
quantities = []
unit_prices = []
product_regex = r'\[?(.+?)\]?\s*(.+)\n(?:HSN/SAC Code):\s+(\d+)'
product_regex = r"\[?(.+?)\]?\s*(.+)\n(?:HSN/SAC Code):\s+(\d+)"
quantity_regex = r"Quantity Unit\n([\d.\s\S]+)"
unit_price_regex = r"Amount\n([\d.\s\S]+)"
# Matching the pattern with the data
@ -183,19 +195,25 @@ class OCRDataTemplate(models.TransientModel):
if number_of_product == number_of_qty == number_of_price:
for i in range(number_of_product):
product_line_list.append(
{'product': products[i], 'quantity': quantities[i],
'price': unit_prices[i]})
{
"product": products[i],
"quantity": quantities[i],
"price": unit_prices[i],
}
)
elif number_of_product == number_of_qty:
for i in range(number_of_product):
product_line_list.append(
{'product': products[i], 'quantity': quantities[i]})
{"product": products[i], "quantity": quantities[i]}
)
elif number_of_product == number_of_price:
for i in range(number_of_product):
product_line_list.append(
{'product': products[i], 'price': unit_prices[i]})
{"product": products[i], "price": unit_prices[i]}
)
elif products:
for i in range(number_of_product):
product_line_list.append({'product': products[i]})
product_line_list.append({"product": products[i]})
return product_line_list
def action_process_data(self):
@ -203,27 +221,27 @@ class OCRDataTemplate(models.TransientModel):
Function to process the data after fetching it.
The fetched data are mapping into some models.
"""
phone_number = ''
email_address = ''
person = ''
phone_pattern = r'\(\d{3}\) \d{3}-\d{4}|\d{3}-\d{3}-\d{4}|\+\d{1}-\d{3}-\d{3}-\d{4}|\d{11}|P \+\d{3} \d{6}'
email_pattern = r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}'
if self.model_name_id.name == 'Contact':
phone_number = ""
email_address = ""
person = ""
phone_pattern = r"\(\d{3}\) \d{3}-\d{4}|\d{3}-\d{3}-\d{4}|\+\d{1}-\d{3}-\d{3}-\d{4}|\d{11}|P \+\d{3} \d{6}"
email_pattern = r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}"
if self.model_name_id.name == "Contact":
# Mapping the data into Contact module by fetching person name,
# phone number and email id from data
field_value = False
non_field_count = 0
for field in self.model_field_ids:
if field.name == 'name' or field.name == 'display_name':
if field.name == "name" or field.name == "display_name":
person = self.find_person_name()
if not person:
raise ValidationError(_("Partner name cannot find"))
field_value = True
elif field.name == 'phone':
elif field.name == "phone":
phone = re.findall(phone_pattern, self.data)
if phone:
phone_number = phone[0]
elif field.name == 'email':
elif field.name == "email":
email = re.findall(email_pattern, self.data)
if email:
email_address = email[0]
@ -232,54 +250,59 @@ class OCRDataTemplate(models.TransientModel):
if not field_value and non_field_count == 1:
raise ValidationError(_("No data to map into the field"))
if person:
partner = self.env['res.partner'].search(
[('name', '=', person)], limit=1)
partner = self.env["res.partner"].search(
[("name", "=", person)], limit=1
)
if not partner:
# Creating record in res.partner
partner_record = self.env['res.partner'].create({
'name': person,
'email': email_address,
'phone': phone_number
})
partner_record = self.env["res.partner"].create(
{"name": person, "email": email_address, "phone": phone_number}
)
else:
raise ValidationError(_("Partner already exist"))
else:
raise ValidationError(_("Name field is not chosen to create"
" partner"))
raise ValidationError(
_("Name field is not chosen to create" " partner")
)
if partner_record:
return {
'name': "Partner",
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'res.partner',
'res_id': partner_record.id,
'view_id': self.env.ref('base.view_partner_form').id,
'target': 'current',
"name": "Partner",
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "res.partner",
"res_id": partner_record.id,
"view_id": self.env.ref("base.view_partner_form").id,
"target": "current",
}
elif self.model_name_id.name == 'Journal Entry':
elif self.model_name_id.name == "Journal Entry":
# Mapping data into Journal Entry. Creating a record in vendor bill
vendor_bill_flag = False
for field in self.model_field_ids:
# Taking the file path from ir.attachment
if field.name == 'invoice_vendor_bill_id':
if field.name == "invoice_vendor_bill_id":
vendor_bill_flag = True
try:
file_attachment = self.env["ir.attachment"].search(
['|', ('res_field', '!=', False),
('res_field', '=', False),
('res_id', '=', self.id),
('res_model', '=', 'ocr.data.template')],
limit=1)
[
"|",
("res_field", "!=", False),
("res_field", "=", False),
("res_id", "=", self.id),
("res_model", "=", "ocr.data.template"),
],
limit=1,
)
file_path = file_attachment._full_path(
file_attachment.store_fname)
with open(file_path, mode='rb') as f:
file_attachment.store_fname
)
with open(file_path, mode="rb") as f:
binary_data = f.read()
img = Image.open(io.BytesIO(binary_data))
# Resizing the image to improve the clarity
resized_img = img.resize(
(img.width * 2, img.height * 2),
resample=Image.BICUBIC)
(img.width * 2, img.height * 2), resample=Image.BICUBIC
)
except Exception:
raise ValidationError(_("Can't create vendor bill"))
# Converting the image into text using OCR python package
@ -288,41 +311,46 @@ class OCRDataTemplate(models.TransientModel):
text = pytesseract.image_to_string(resized_img)
except Exception:
raise ValidationError(_("Can't create vendor bill"))
bill = self.env['digitize.bill']
bill = self.env["digitize.bill"]
# Calling the function to create vendor bill
# from model digitize.bill
bill_record = bill.create_record(text)
return {
'name': "Bill",
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'account.move',
'res_id': bill_record.id,
'view_id': self.env.ref('account.view_move_form').id,
'target': 'current',
"name": "Bill",
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "account.move",
"res_id": bill_record.id,
"view_id": self.env.ref("account.view_move_form").id,
"target": "current",
}
if not vendor_bill_flag:
raise ValidationError(_("No data to map into the field"))
elif self.model_name_id.name == 'Employee':
elif self.model_name_id.name == "Employee":
# Mapping the data into Employee module by fetching person name,
# phone number and email
field_value = False
non_field_count = 0
for field in self.model_field_ids:
if field.name == 'name' or field.name == 'display_name' or \
field.name == 'emergency_contact':
if (
field.name == "name"
or field.name == "display_name"
or field.name == "emergency_contact"
):
person = self.find_person_name()
if not person:
raise ValidationError(_("Employee name cannot find"))
field_value = True
elif field.name == 'work_phone' or field.name == 'phone' or \
field.name == 'emergency_phone':
elif (
field.name == "work_phone"
or field.name == "phone"
or field.name == "emergency_phone"
):
phone = re.findall(phone_pattern, self.data)
if phone:
phone_number = phone[0]
elif field.name == 'private_email' or \
field.name == 'work_email':
elif field.name == "private_email" or field.name == "work_email":
email = re.findall(email_pattern, self.data)
if email:
email_address = email[0]
@ -331,177 +359,197 @@ class OCRDataTemplate(models.TransientModel):
if not field_value and non_field_count == 1:
raise ValidationError(_("No data to map into the field"))
if person:
partner = self.env['hr.employee'].search(
[('name', '=', person)], limit=1)
partner = self.env["hr.employee"].search(
[("name", "=", person)], limit=1
)
if not partner:
# Creating a record in hr.employee by mapping the
# data into employee name, work phone and work email
employee_record = self.env['hr.employee'].create({
'name': person,
'work_email': email_address,
'work_phone': phone_number
})
employee_record = self.env["hr.employee"].create(
{
"name": person,
"work_email": email_address,
"work_phone": phone_number,
}
)
else:
raise ValidationError(_("Employee already exist"))
else:
raise ValidationError(
_("Name field is not chosen to create employee"))
raise ValidationError(_("Name field is not chosen to create employee"))
if employee_record:
return {
'name': "Employee",
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'hr.employee',
'res_id': employee_record.id,
'view_id': self.env.ref('hr.view_employee_form').id,
'target': 'current',
"name": "Employee",
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "hr.employee",
"res_id": employee_record.id,
"view_id": self.env.ref("hr.view_employee_form").id,
"target": "current",
}
elif self.model_name_id.name == 'Expense':
elif self.model_name_id.name == "Expense":
# Mapping the data into Expense module
expense_product = False
for field in self.model_field_ids:
if field.name == 'name' or field.name == 'product_id':
if field.name == "name" or field.name == "product_id":
expense_product = True
product = self.env['product.product'].search(
[('name', '=', 'BILL EXPENSE')], limit=1)
product = self.env["product.product"].search(
[("name", "=", "BILL EXPENSE")], limit=1
)
if not product:
product = self.env['product.product'].create({
'name': 'BILL EXPENSE',
})
expense_record = self.env['hr.expense'].create({
'product_id': product.id,
})
product = self.env["product.product"].create(
{
"name": "BILL EXPENSE",
}
)
expense_record = self.env["hr.expense"].create(
{
"product_id": product.id,
}
)
return {
'name': "Expense",
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'hr.expense',
'res_id': expense_record.id,
'view_id': self.env.ref(
'hr_expense.hr_expense_view_form').id,
'target': 'current',
"name": "Expense",
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "hr.expense",
"res_id": expense_record.id,
"view_id": self.env.ref("hr_expense.hr_expense_view_form").id,
"target": "current",
}
if not expense_product:
raise ValidationError(_("Can't create an expense without "
"description or category"))
elif self.model_name_id.name == 'Sales Order':
raise ValidationError(
_("Can't create an expense without " "description or category")
)
elif self.model_name_id.name == "Sales Order":
# Mapping the data from PDF with proper format into Sale Order
sale_order = ''
sale_order = ""
partner = False
field_value = False
non_field_value = 0
for field in self.model_field_ids:
if field.name == 'order_line':
if field.name == "order_line":
field_value = True
person = self.find_person_name()
if person:
partner = self.env['hr.employee'].search(
[('name', '=', person)], limit=1)
partner = self.env["hr.employee"].search(
[("name", "=", person)], limit=1
)
if not partner:
partner = self.env['hr.employee'].create({
'name': person,
})
partner = self.env["hr.employee"].create(
{
"name": person,
}
)
# Calling the function to get order lines
product_line = self.get_order_line(self.data)
sale_order = self.env['sale.order'].create({
'partner_id': partner.id,
})
sale_order = self.env["sale.order"].create(
{
"partner_id": partner.id,
}
)
if product_line:
for item in product_line:
if 'quantity' not in item.keys():
item.update({'quantity': 0})
if 'price' not in item.keys():
item.update({'price': 0})
product = self.env['product.product'].search(
[('name', '=', item['product'])], limit=1)
if "quantity" not in item.keys():
item.update({"quantity": 0})
if "price" not in item.keys():
item.update({"price": 0})
product = self.env["product.product"].search(
[("name", "=", item["product"])], limit=1
)
if not product:
product = self.env['product.product'].create({
'name': item['product']
})
item.update({'product': product.id})
self.env['sale.order.line'].create({
'order_id': sale_order.id,
'product_id': item['product'],
'product_uom_qty': item['quantity'],
'price_unit': item['price']
})
product = self.env["product.product"].create(
{"name": item["product"]}
)
item.update({"product": product.id})
self.env["sale.order.line"].create(
{
"order_id": sale_order.id,
"product_id": item["product"],
"product_uom_qty": item["quantity"],
"price_unit": item["price"],
}
)
else:
non_field_value = 1
if sale_order:
return {
'name': "Sale order",
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'sale.order',
'res_id': sale_order.id,
'view_id': self.env.ref('sale.view_order_form').id,
'target': 'current',
"name": "Sale order",
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "sale.order",
"res_id": sale_order.id,
"view_id": self.env.ref("sale.view_order_form").id,
"target": "current",
}
if not field_value and non_field_value == 1:
raise ValidationError(_("No data to map into the field"))
elif self.model_name_id.name == 'Purchase Order':
elif self.model_name_id.name == "Purchase Order":
# Mapping the data from PDF with proper format into Purchase Order
purchase_order = ''
purchase_order = ""
field_value = False
non_field_value = 0
partner = False
for field in self.model_field_ids:
if field.name == 'order_line':
if field.name == "order_line":
field_value = True
person = self.find_person_name()
if person:
partner = self.env['hr.employee'].search(
[('name', '=', person)], limit=1)
partner = self.env["hr.employee"].search(
[("name", "=", person)], limit=1
)
if not partner:
partner = self.env['hr.employee'].create({
'name': person,
})
partner = self.env["hr.employee"].create(
{
"name": person,
}
)
# Calling the function to get order lines
product_line = self.get_order_line(self.data)
purchase_order = self.env['purchase.order'].create({
'partner_id': partner.id,
})
purchase_order = self.env["purchase.order"].create(
{
"partner_id": partner.id,
}
)
if product_line:
for item in product_line:
if 'quantity' not in item.keys():
item.update({'quantity': 0})
if 'price' not in item.keys():
item.update({'price': 0})
product = self.env['product.product'].search(
[('name', '=', item['product'])], limit=1)
if "quantity" not in item.keys():
item.update({"quantity": 0})
if "price" not in item.keys():
item.update({"price": 0})
product = self.env["product.product"].search(
[("name", "=", item["product"])], limit=1
)
if not product:
product = self.env['product.product'].create({
'name': item['product']
})
item.update({'product': product.id})
self.env['purchase.order.line'].create({
'order_id': purchase_order.id,
'product_id': item['product'],
'product_uom_qty': item['quantity'],
'price_unit': item['price']
})
product = self.env["product.product"].create(
{"name": item["product"]}
)
item.update({"product": product.id})
self.env["purchase.order.line"].create(
{
"order_id": purchase_order.id,
"product_id": item["product"],
"product_uom_qty": item["quantity"],
"price_unit": item["price"],
}
)
else:
non_field_value = 1
if purchase_order:
return {
'name': "Purchase order",
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'purchase.order',
'res_id': purchase_order.id,
'view_id': self.env.ref(
'purchase.purchase_order_form').id,
'target': 'current',
"name": "Purchase order",
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": "purchase.order",
"res_id": purchase_order.id,
"view_id": self.env.ref("purchase.purchase_order_form").id,
"target": "current",
}
if not field_value and non_field_value == 1:
raise ValidationError(_("No data to map into the field"))
@api.onchange('image')
@api.onchange("image")
def _onchange_image(self):
self.write({
'image2': self.image
})
self.write({"image2": self.image})

Loading…
Cancel
Save