@ -0,0 +1,48 @@ |
|||||
|
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
||||
|
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
Export Product Images |
||||
|
===================== |
||||
|
This module helps to export product images as an excel file along with other details. |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
* No additional configuration required. |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
Affero General Public License, v3.0 (AGPL v3). |
||||
|
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* Developers: (V16) Ajmunnisa KP, |
||||
|
(V17) Aysha Shalin, |
||||
|
(V18) Javid A, Contact: odoo@cybrosys.com |
||||
|
|
||||
|
Contacts |
||||
|
-------- |
||||
|
* Mail Contact : odoo@cybrosys.com |
||||
|
* Website : https://cybrosys.com |
||||
|
|
||||
|
Bug Tracker |
||||
|
----------- |
||||
|
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
||||
|
|
||||
|
Maintainer |
||||
|
========== |
||||
|
.. image:: https://cybrosys.com/images/logo.png |
||||
|
:target: https://cybrosys.com |
||||
|
|
||||
|
This module is maintained by Cybrosys Technologies. |
||||
|
|
||||
|
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Further information |
||||
|
=================== |
||||
|
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################### |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# 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/>. |
||||
|
# |
||||
|
############################################################################### |
||||
|
from . import controllers |
||||
|
from . import wizard |
@ -0,0 +1,44 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################### |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# 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": "Export Product Images", |
||||
|
"version": "18.0.1.0.0", |
||||
|
"category": "Warehouse", |
||||
|
"summary": """To export product details along with the product images.""", |
||||
|
"description": "The allowed users can download the product details " |
||||
|
"along with the product images.", |
||||
|
"author": "Cybrosys Techno Solutions", |
||||
|
"website": "https://www.cybrosys.com", |
||||
|
"company": "Cybrosys Techno Solutions", |
||||
|
"maintainer": "Cybrosys Techno Solutions", |
||||
|
"depends": ["stock", "product", "web"], |
||||
|
"data": [ |
||||
|
"security/product_export_with_images_groups.xml", |
||||
|
"security/ir.model.access.csv", |
||||
|
"data/product_export_with_images_data.xml", |
||||
|
], |
||||
|
"images": ["static/description/banner.png"], |
||||
|
"license": "AGPL-3", |
||||
|
"installable": True, |
||||
|
"auto_install": False, |
||||
|
"application": False, |
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################### |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# 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/>. |
||||
|
# |
||||
|
############################################################################### |
||||
|
from . import product_export_with_images |
@ -0,0 +1,126 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################### |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# 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/>. |
||||
|
# |
||||
|
############################################################################### |
||||
|
import base64 |
||||
|
import io |
||||
|
import xlsxwriter |
||||
|
from io import BytesIO |
||||
|
from odoo import http |
||||
|
from odoo.http import content_disposition, request |
||||
|
from odoo.tools import image_process |
||||
|
|
||||
|
|
||||
|
class ExcelReportController(http.Controller): |
||||
|
""" This class includes the function to downloads excel report """ |
||||
|
@http.route( |
||||
|
[ |
||||
|
'/products_download/excel_report/<model("product.export"):wizards>', |
||||
|
], |
||||
|
type="http", |
||||
|
auth="public", |
||||
|
csrf=False, |
||||
|
) |
||||
|
def get_product_excel_report(self, wizards=None): |
||||
|
""" Downloads the Excel document with the details of products """ |
||||
|
response = request.make_response( |
||||
|
None, |
||||
|
headers=[ |
||||
|
("Content-Type", "application/vnd.ms-excel"), |
||||
|
("Content-Disposition", content_disposition("Products" + ".xlsx")), |
||||
|
], |
||||
|
) |
||||
|
# Create workbook object from xlsxwriter library |
||||
|
output = io.BytesIO() |
||||
|
workbook = xlsxwriter.Workbook(output, {"in_memory": True}) |
||||
|
# Create styles to set up the font type, the font size, the border, |
||||
|
# and the alignment |
||||
|
header_style = workbook.add_format( |
||||
|
{ |
||||
|
"text_wrap": True, |
||||
|
"font_name": "Times", |
||||
|
"bold": True, |
||||
|
"left": 1, |
||||
|
"bottom": 1, |
||||
|
"right": 1, |
||||
|
"top": 1, |
||||
|
"align": "center", |
||||
|
} |
||||
|
) |
||||
|
text_style = workbook.add_format( |
||||
|
{ |
||||
|
"text_wrap": True, |
||||
|
"font_name": "Times", |
||||
|
"left": 1, |
||||
|
"bottom": 1, |
||||
|
"right": 1, |
||||
|
"top": 1, |
||||
|
"align": "left", |
||||
|
} |
||||
|
) |
||||
|
product_lines = wizards.get_product_lines() |
||||
|
sheet = workbook.add_worksheet("Products") |
||||
|
sheet.set_landscape() |
||||
|
sheet.set_paper(9) |
||||
|
sheet.merge_range("A1:G1", "PRODUCTS", header_style) |
||||
|
sheet.set_margins(0.5, 0.5, 0.5, 0.5) |
||||
|
sheet.set_column("A:A", 5) |
||||
|
sheet.set_column("B:F", 15) |
||||
|
sheet.set_column("G:G", 20) |
||||
|
sheet.set_row(1, 30) |
||||
|
sheet.set_row(0, 30) |
||||
|
# table title |
||||
|
sheet.write(2, 0, "ID", header_style) |
||||
|
sheet.write(2, 1, "Internal Reference", header_style) |
||||
|
sheet.write(2, 2, "Name", header_style) |
||||
|
sheet.write(2, 3, "Cost", header_style) |
||||
|
sheet.write(2, 4, "Sales Price", header_style) |
||||
|
sheet.write(2, 5, "Product Category", header_style) |
||||
|
sheet.write(2, 6, "Image", header_style) |
||||
|
row = 3 |
||||
|
number = 1 |
||||
|
count = 0 |
||||
|
for line in product_lines: |
||||
|
sheet.set_row(row, 128) |
||||
|
# the report content |
||||
|
count += 1 |
||||
|
sheet.write(row, 0, count, text_style) |
||||
|
if line["internal_reference"]: |
||||
|
sheet.write(row, 1, line["internal_reference"], text_style) |
||||
|
elif not line["internal_reference"]: |
||||
|
sheet.write(row, 1, "", text_style) |
||||
|
sheet.write(row, 2, line["name"], text_style) |
||||
|
sheet.write(row, 3, str(line["currency"]) + str(line["cost"]), text_style) |
||||
|
sheet.write( |
||||
|
row, 4, str(line["currency"]) + str(line["sales_price"]), text_style |
||||
|
) |
||||
|
sheet.write(row, 5, line["category"], text_style) |
||||
|
if line["image"]: |
||||
|
source = base64.b64decode(line["image"]) |
||||
|
image_data = BytesIO(image_process(source, size=(300, 300))) |
||||
|
sheet.write(row, 6, "", text_style) |
||||
|
sheet.insert_image(row, 6, "product.png", {"image_data": image_data}) |
||||
|
row += 1 |
||||
|
number += 1 |
||||
|
workbook.close() |
||||
|
output.seek(0) |
||||
|
response.stream.write(output.read()) |
||||
|
output.close() |
||||
|
return response |
@ -0,0 +1,35 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Record for server action button to export product images in product template --> |
||||
|
<record id="action_export_product_template_images" |
||||
|
model="ir.actions.server"> |
||||
|
<field name="name">Export Product Images</field> |
||||
|
<field name="model_id" ref="model_product_export"/> |
||||
|
<field name="binding_model_id" |
||||
|
ref="product.model_product_template"/> |
||||
|
<field name="binding_view_types">form,list</field> |
||||
|
<field name="state">code</field> |
||||
|
<field name="code"> |
||||
|
action = model.action_export_products() |
||||
|
</field> |
||||
|
<field name="groups_id" |
||||
|
eval="[(4, ref('product_export_with_images.group_product_export_with_images'))]"/> |
||||
|
</record> |
||||
|
|
||||
|
<!-- Record for server action button to export product images in product --> |
||||
|
<record id="action_export_product_images" model="ir.actions.server"> |
||||
|
<field name="name">Export Product Images</field> |
||||
|
<field name="model_id" ref="model_product_export"/> |
||||
|
<field name="binding_model_id" |
||||
|
ref="product.model_product_product"/> |
||||
|
<field name="binding_view_types">form,list</field> |
||||
|
<field name="state">code</field> |
||||
|
<field name="code"> |
||||
|
action = model.action_export_products() |
||||
|
</field> |
||||
|
<field name="groups_id" |
||||
|
eval="[(4, ref('product_export_with_images.group_product_export_with_images'))]"/> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,6 @@ |
|||||
|
## Module <product_export_with_images> |
||||
|
|
||||
|
#### 19.10.2024 |
||||
|
#### Version 18.0.1.0.0 |
||||
|
##### ADD |
||||
|
- Initial commit for Export Product Images |
|
@ -0,0 +1,8 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" ?> |
||||
|
<odoo> |
||||
|
<!-- Only users in this group are allowed to export product images --> |
||||
|
<record id="group_product_export_with_images" model="res.groups"> |
||||
|
<field name="name">Export products Images</field> |
||||
|
<field name="category_id" ref="base.module_category_hidden"/> |
||||
|
</record> |
||||
|
</odoo> |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 738 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 912 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 144 KiB |
After Width: | Height: | Size: 219 KiB |
After Width: | Height: | Size: 880 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 8.9 KiB |
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################### |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# 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/>. |
||||
|
# |
||||
|
############################################################################### |
||||
|
from . import product_export |
@ -0,0 +1,80 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################### |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) |
||||
|
# |
||||
|
# 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
||||
|
# |
||||
|
# 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/>. |
||||
|
# |
||||
|
############################################################################### |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class ExportWizard(models.TransientModel): |
||||
|
""" This class contains the functions to get selected product ids and |
||||
|
redirect to excel download URL. """ |
||||
|
|
||||
|
_name = "product.export" |
||||
|
_description = "Export Products and Make an Excel Download URL." |
||||
|
|
||||
|
name = fields.Char(string="Name", help="Name of the record") |
||||
|
product_tmp_ids = fields.Many2many( |
||||
|
"product.template", string="Products", |
||||
|
help="Products for exporting") |
||||
|
product_ids = fields.Many2many( |
||||
|
"product.product", string="Products Variants", |
||||
|
help="Product variants for exporting") |
||||
|
|
||||
|
def action_export_products(self): |
||||
|
""" Select the active product/ product template ids. Return URL action |
||||
|
to download excel report. """ |
||||
|
active_products = self.env.context["active_ids"] |
||||
|
active_model = self.env.context["active_model"] |
||||
|
if active_model == "product.template": |
||||
|
export_wizard = self.env["product.export"].create( |
||||
|
{"product_tmp_ids": [(6, 0, active_products)]} |
||||
|
) |
||||
|
if active_model == "product.product": |
||||
|
export_wizard = self.env["product.export"].create( |
||||
|
{"product_ids": [(6, 0, active_products)]} |
||||
|
) |
||||
|
if export_wizard: |
||||
|
return { |
||||
|
"type": "ir.actions.act_url", |
||||
|
"url": "/products_download/excel_report/%s" % export_wizard.id, |
||||
|
"target": "new", |
||||
|
"context": {"active_ids": active_products}, |
||||
|
} |
||||
|
|
||||
|
def get_product_lines(self): |
||||
|
""" Returns the product details like name, default code, category, |
||||
|
image etc. """ |
||||
|
rec_list = [] |
||||
|
if self.product_ids: |
||||
|
active_records = self.product_ids |
||||
|
elif self.product_tmp_ids: |
||||
|
active_records = self.product_tmp_ids |
||||
|
for rec in active_records: |
||||
|
vals = { |
||||
|
"name": rec.name, |
||||
|
"internal_reference": rec.default_code, |
||||
|
"category": rec.categ_id.display_name, |
||||
|
"currency": self.env.company.currency_id.symbol, |
||||
|
"cost": rec.standard_price, |
||||
|
"sales_price": rec.list_price, |
||||
|
"image": rec.image_128, |
||||
|
} |
||||
|
rec_list.append(vals) |
||||
|
return rec_list |