purchase_export_bc/models/purchase_order.py

103 lines
3.7 KiB
Python

import base64
import io
import logging
try:
import xlsxwriter
except ImportError:
xlsxwriter = None
from odoo import models, _
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
def action_export_bc(self):
self.ensure_one()
if not xlsxwriter:
raise UserError(_("The Python library 'xlsxwriter' is required. Please install it."))
output = io.BytesIO()
workbook = xlsxwriter.Workbook(output, {'in_memory': True})
header_format = workbook.add_format({
'bold': True, 'align': 'center', 'valign': 'vcenter', 'border': 1
})
headers = ["Type", "Item No.", "Description", "Qty", "Satuan"]
lines_by_category = {}
for line in self.order_line:
# Handle display_type like line_section or line_note which shouldn't be exported as items
if line.display_type in ('line_section', 'line_note'):
continue
categ_name = line.product_id.categ_id.name or 'Uncategorized'
# Sheet names in Excel cannot exceed 31 characters
categ_name = str(categ_name)[:31]
# Excel sheet names cannot contain certain characters like :, \\, /, ?, *, [, ]
invalid_chars = [':', '\\', '/', '?', '*', '[', ']']
for char in invalid_chars:
categ_name = categ_name.replace(char, ' ')
if categ_name not in lines_by_category:
lines_by_category[categ_name] = []
lines_by_category[categ_name].append(line)
if not lines_by_category:
raise UserError(_("There are no order lines to export."))
for categ_name, lines in lines_by_category.items():
sheet = workbook.add_worksheet(categ_name)
for col_num, header in enumerate(headers):
sheet.write(0, col_num, header, header_format)
row_num = 1
for line in lines:
item_type = "Item"
# Check custom field x_studio_bc_item_id on product
if 'x_studio_bc_item_id' in line.product_id._fields and line.product_id.x_studio_bc_item_id:
item_no = line.product_id.x_studio_bc_item_id
else:
item_no = ''
description = line.product_id.name or line.name or ''
qty = line.product_qty
# Determine packaging or unit
if 'product_packaging_id' in line._fields and line.product_packaging_id:
satuan = line.product_packaging_id.name
else:
satuan = line.product_uom_id.name or ''
sheet.write(row_num, 0, item_type)
sheet.write(row_num, 1, item_no)
sheet.write(row_num, 2, description)
sheet.write(row_num, 3, qty)
sheet.write(row_num, 4, satuan)
row_num += 1
workbook.close()
output.seek(0)
attachment_name = f"PO_Export_BC_{self.name.replace('/', '_')}.xlsx"
attachment = self.env['ir.attachment'].create({
'name': attachment_name,
'type': 'binary',
'datas': base64.b64encode(output.read()),
'mimetype': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
return {
'type': 'ir.actions.act_url',
'url': f'/web/content/{attachment.id}?download=true',
'target': 'self',
}