19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:12 +01:00
parent 79f83631d5
commit 73afc09215
6267 changed files with 1534193 additions and 1130106 deletions

View file

@ -0,0 +1,3 @@
from . import catalog
from . import product_document
from . import pricelist_report

View file

@ -0,0 +1,48 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.http import request, route, Controller
class ProductCatalogController(Controller):
@route('/product/catalog/order_lines_info', auth='user', type='jsonrpc', readonly=True)
def product_catalog_get_order_lines_info(self, res_model, order_id, product_ids, **kwargs):
""" Returns products information to be shown in the catalog.
:param string res_model: The order model.
:param int order_id: The order id.
:param list product_ids: The products currently displayed in the product catalog, as a list
of `product.product` ids.
:rtype: dict
:return: A dict with the following structure:
{
product.id: {
'productId': int
'quantity': float (optional)
'price': float
'uomDisplayName': string
'code': string (optional)
'readOnly': bool (optional)
}
}
"""
order = request.env[res_model].browse(order_id)
return order.with_company(order.company_id)._get_product_catalog_order_line_info(
product_ids, **kwargs,
)
@route('/product/catalog/update_order_line_info', auth='user', type='jsonrpc')
def product_catalog_update_order_line_info(self, res_model, order_id, product_id, quantity=0, **kwargs):
""" Update order line information on a given order for a given product.
:param string res_model: The order model.
:param int order_id: The order id.
:param int product_id: The product, as a `product.product` id.
:return: The unit price price of the product, based on the pricelist of the order and
the quantity selected.
:rtype: float
"""
order = request.env[res_model].browse(order_id)
return order.with_company(order.company_id)._update_order_line_info(
product_id, quantity, **kwargs,
)

View file

@ -0,0 +1,77 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import csv
import io
import json
from odoo import _
from odoo.http import Controller, request, route, content_disposition
class ProductPricelistExportController(Controller):
@route('/product/export/pricelist/', type='http', auth='user', readonly=True)
def export_pricelist(self, report_data, export_format):
json_data = json.loads(report_data)
report_data = request.env['report.product.report_pricelist']._get_report_data(json_data)
pricelist_name = report_data['pricelist']['name']
quantities = report_data['quantities']
products = report_data['products']
headers = [
_("Product"),
_("UOM"),
] + [_("Quantity (%s UoM)", qty) for qty in quantities]
if export_format == 'csv':
return self._generate_csv(pricelist_name, quantities, products, headers)
else:
return self._generate_xlsx(pricelist_name, quantities, products, headers)
def _generate_rows(self, products, quantities):
rows = []
for product in products:
variants = product.get('variants', [product])
for variant in variants:
row = [
variant['name'],
variant['uom']
] + [variant['price'].get(qty, 0.0) for qty in quantities]
rows.append(row)
return rows
def _generate_csv(self, pricelist_name, quantities, products, headers):
buffer = io.StringIO()
writer = csv.writer(buffer)
writer.writerow(headers)
rows = self._generate_rows(products, quantities)
writer.writerows(rows)
content = buffer.getvalue()
buffer.close()
headers = [
('Content-Type', 'text/csv'),
('Content-Disposition', content_disposition(f'Pricelist - {pricelist_name}.csv'))
]
return request.make_response(content, headers)
def _generate_xlsx(self, pricelist_name, quantities, products, headers):
buffer = io.BytesIO()
import xlsxwriter # noqa: PLC0415
workbook = xlsxwriter.Workbook(buffer, {'in_memory': True})
worksheet = workbook.add_worksheet()
worksheet.write_row(0, 0, headers)
rows = self._generate_rows(products, quantities)
column_widths = [len(header) for header in headers]
for row_idx, row in enumerate(rows, start=1):
worksheet.write_row(row_idx, 0, row)
for col_idx, cell_value in enumerate(row):
column_widths[col_idx] = max(column_widths[col_idx], len(str(cell_value)))
for col_idx, width in enumerate(column_widths):
worksheet.set_column(col_idx, col_idx, width)
workbook.close()
content = buffer.getvalue()
buffer.close()
headers = [
('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'),
('Content-Disposition', content_disposition(f'Pricelist - {pricelist_name}.xlsx'))
]
return request.make_response(content, headers)

View file

@ -0,0 +1,49 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import json
import logging
from odoo import _
from odoo.http import request, route, Controller
logger = logging.getLogger(__name__)
class ProductDocumentController(Controller):
@route('/product/document/upload', type='http', methods=['POST'], auth='user')
def upload_document(self, ufile, res_model, res_id, **kwargs):
if not self.is_model_valid(res_model):
return
record = request.env[res_model].browse(int(res_id)).exists()
if not record or not record.browse().has_access('write'):
return
files = request.httprequest.files.getlist('ufile')
result = {'success': _("All files uploaded")}
for ufile in files:
try:
mimetype = ufile.content_type
request.env['product.document'].create({
'name': ufile.filename,
'res_model': record._name,
'res_id': record.id,
'company_id': record.company_id.id,
'mimetype': mimetype,
'raw': ufile.read(),
**self.get_additional_create_params(**kwargs)
})
except Exception as e:
logger.exception("Failed to upload document %s", ufile.filename)
result = {'error': str(e)}
return json.dumps(result)
# mrp hook
def get_additional_create_params(self, **kwargs):
return {}
# eco hook
def is_model_valid(self, res_model):
return res_model in ('product.product', 'product.template')