def get_wishlist(self, count=False, **kw): values = request.env['product.wishlist'].with_context( display_default_code=False).current() if count: return request.make_response( json.dumps(values.mapped('product_id').ids)) if not len(values): return request.redirect("/shop") return request.render("website_sale_wishlist.product_wishlist", dict(wishes=values))
def slide_download(self, slide, **kw): slide = slide.sudo() if slide.download_security == 'public' or (slide.download_security == 'user' and request.session.uid): filecontent = base64.b64decode(slide.datas) disposition = 'attachment; filename=%s.pdf' % werkzeug.urls.url_quote(slide.name) return request.make_response( filecontent, [('Content-Type', 'application/pdf'), ('Content-Length', len(filecontent)), ('Content-Disposition', disposition)]) elif not request.session.uid and slide.download_security == 'user': return request.redirect('/web/login?redirect=/slides/slide/%s' % (slide.id)) return request.render("website.403")
def livechat_lib(self, ext, **kwargs): # _get_asset return the bundle html code (script and link list) but we want to use the attachment content xmlid = 'im_livechat.external_lib' files, remains = request.env["ir.qweb"]._get_asset_content(xmlid, options=request.context) asset = AssetsBundle(xmlid, files) mock_attachment = getattr(asset, ext)() if isinstance(mock_attachment, list): # suppose that CSS asset will not required to be split in pages mock_attachment = mock_attachment[0] # can't use /web/content directly because we don't have attachment ids (attachments must be created) status, headers, content = binary_content(id=mock_attachment.id, unique=asset.checksum) content_base64 = base64.b64decode(content) if content else '' headers.append(('Content-Length', len(content_base64))) return request.make_response(content_base64, headers)
def report(self, output_format, report_name, token, report_id=False, **kw): uid = request.session.uid domain = [('create_uid', '=', uid)] stock_traceability = request.env['stock.traceability.report'].sudo( uid).search(domain, limit=1) line_data = json.loads(kw['data']) try: if output_format == 'pdf': response = request.make_response( stock_traceability.with_context( active_id=report_id).get_pdf(line_data), headers=[('Content-Type', 'application/pdf'), ('Content-Disposition', 'attachment; filename=' + 'stock_traceability' + '.pdf;')]) response.set_cookie('fileToken', token) return response except Exception as e: se = _serialize_exception(e) error = { 'code': 200, 'message': 'GECOERP Server Error', 'data': se } return request.make_response(html_escape(json.dumps(error)))
def portal_order_report(self, order_id, access_token=None, **kw): try: order_sudo = self._order_check_access(order_id, access_token) except AccessError: return request.redirect('/my') # print report as sudo, since it require access to taxes, payment term, ... and portal # does not have those access rights. pdf = request.env.ref( 'sale.action_report_saleorder').sudo().render_qweb_pdf( [order_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def portal_my_picking_report(self, picking_id, access_token=None, **kw): """ Print delivery slip for customer, using either access rights or access token to be sure customer has access """ try: picking_sudo = self._stock_picking_check_access( picking_id, access_token=access_token) except exceptions.AccessError: return request.redirect('/my') # print report as sudo, since it require access to product, taxes, payment term etc.. and portal does not have those access rights. pdf = request.env.ref( 'stock.action_report_delivery').sudo().render_qweb_pdf( [picking_sudo.id])[0] pdfhttpheaders = [ ('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] return request.make_response(pdf, headers=pdfhttpheaders)
def user_avatar(self, user_id=0, **post): status, headers, content = binary_content( model='res.users', id=user_id, field='image_medium', default_mimetype='image/png', env=request.env(user=SUPERUSER_ID)) if not content: img_path = modules.get_module_resource('web', 'static/src/img', 'placeholder.png') with open(img_path, 'rb') as f: image = f.read() content = base64.b64encode(image) if status == 304: return werkzeug.wrappers.Response(status=304) image_base64 = base64.b64decode(content) headers.append(('Content-Length', len(image_base64))) response = request.make_response(image_base64, headers) response.status = str(status) return response
def avatar(self, res_model, res_id, partner_id): headers = [('Content-Type', 'image/png')] status = 200 content = 'R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' # default image is one white pixel if res_model in request.env: try: # if the current user has access to the document, get the partner avatar as sudo() request.env[res_model].browse(res_id).check_access_rule('read') if partner_id in request.env[res_model].browse(res_id).sudo().exists().message_ids.mapped('author_id').ids: status, headers, _content = binary_content(model='res.partner', id=partner_id, field='image_medium', default_mimetype='image/png', env=request.env(user=SUPERUSER_ID)) # binary content return an empty string and not a placeholder if obj[field] is False if _content != '': content = _content if status == 304: return werkzeug.wrappers.Response(status=304) except AccessError: pass image_base64 = base64.b64decode(content) headers.append(('Content-Length', len(image_base64))) response = request.make_response(image_base64, headers) response.status = str(status) return response
def view(self, db, token, action, id, view='calendar'): registry = registry_get(db) with registry.cursor() as cr: # Since we are in auth=none, create an env with SUPERUSER_ID env = Environment(cr, SUPERUSER_ID, {}) attendee = env['calendar.attendee'].search([ ('access_token', '=', token), ('event_id', '=', int(id)) ]) if not attendee: return request.not_found() timezone = attendee.partner_id.tz lang = attendee.partner_id.lang or 'en_US' event = env['calendar.event'].with_context(tz=timezone, lang=lang).browse( int(id)) # If user is internal and logged, redirect to form view of event # otherwise, display the simplifyed web page with event informations if request.session.uid and request.env['res.users'].browse( request.session.uid).user_has_groups('base.group_user'): return werkzeug.utils.redirect( '/web?db=%s#id=%s&view_type=form&model=calendar.event' % (db, id)) # NOTE : we don't use request.render() since: # - we need a template rendering which is not lazy, to render before cursor closing # - we need to display the template in the language of the user (not possible with # request.render()) response_content = env['ir.ui.view'].with_context( lang=lang).render_template( 'calendar.invitation_page_anonymous', { 'event': event, 'attendee': attendee, }) return request.make_response(response_content, headers=[('Content-Type', 'text/html') ])
def export_xls(self, data, token): jdata = json.loads(data) nbr_measures = jdata['nbr_measures'] workbook = xlwt.Workbook() worksheet = workbook.add_sheet(jdata['title']) header_bold = xlwt.easyxf( "font: bold on; pattern: pattern solid, fore_colour gray25;") header_plain = xlwt.easyxf( "pattern: pattern solid, fore_colour gray25;") bold = xlwt.easyxf("font: bold on;") # Step 1: writing headers headers = jdata['headers'] # x,y: current coordinates # carry: queue containing cell information when a cell has a >= 2 height # and the drawing code needs to add empty cells below x, y, carry = 1, 0, deque() for i, header_row in enumerate(headers): worksheet.write(i, 0, '', header_plain) for header in header_row: while (carry and carry[0]['x'] == x): cell = carry.popleft() for i in range(nbr_measures): worksheet.write(y, x + i, '', header_plain) if cell['height'] > 1: carry.append({'x': x, 'height': cell['height'] - 1}) x = x + nbr_measures style = header_plain if 'expanded' in header else header_bold for i in range(header['width']): worksheet.write(y, x + i, header['title'] if i == 0 else '', style) if header['height'] > 1: carry.append({'x': x, 'height': header['height'] - 1}) x = x + header['width'] while (carry and carry[0]['x'] == x): cell = carry.popleft() for i in range(nbr_measures): worksheet.write(y, x + i, '', header_plain) if cell['height'] > 1: carry.append({'x': x, 'height': cell['height'] - 1}) x = x + nbr_measures x, y = 1, y + 1 # Step 2: measure row if nbr_measures > 1: worksheet.write(y, 0, '', header_plain) for measure in jdata['measure_row']: style = header_bold if measure['is_bold'] else header_plain worksheet.write(y, x, measure['measure'], style) x = x + 1 y = y + 1 # Step 3: writing data x = 0 for row in jdata['rows']: worksheet.write(y, x, row['indent'] * ' ' + ustr(row['title']), header_plain) for cell in row['values']: x = x + 1 if cell.get('is_bold', False): worksheet.write(y, x, cell['value'], bold) else: worksheet.write(y, x, cell['value']) x, y = 0, y + 1 response = request.make_response( None, headers=[('Content-Type', 'application/vnd.ms-excel'), ('Content-Disposition', 'attachment; filename=table.xls;') ], cookies={'fileToken': token}) workbook.save(response.stream) return response
def sitemap_xml_index(self, **kwargs): current_website = request.website Attachment = request.env['ir.attachment'].sudo() View = request.env['ir.ui.view'].sudo() mimetype = 'application/xml;charset=utf-8' content = None def create_sitemap(url, content): return Attachment.create({ 'datas': base64.b64encode(content), 'mimetype': mimetype, 'type': 'binary', 'name': url, 'url': url, }) dom = [('url', '=', '/sitemap-%d.xml' % current_website.id), ('type', '=', 'binary')] sitemap = Attachment.search(dom, limit=1) if sitemap: # Check if stored version is still valid create_date = fields.Datetime.from_string(sitemap.create_date) delta = datetime.datetime.now() - create_date if delta < SITEMAP_CACHE_TIME: content = base64.b64decode(sitemap.datas) if not content: # Remove all sitemaps in ir.attachments as we're going to regenerated them dom = [('type', '=', 'binary'), '|', ('url', '=like', '/sitemap-%d-%%.xml' % current_website.id), ('url', '=', '/sitemap-%d.xml' % current_website.id)] sitemaps = Attachment.search(dom) sitemaps.unlink() pages = 0 locs = request.website.sudo( user=request.website.user_id.id).enumerate_pages() while True: values = { 'locs': islice(locs, 0, LOC_PER_SITEMAP), 'url_root': request.httprequest.url_root[:-1], } urls = View.render_template('website.sitemap_locs', values) if urls.strip(): content = View.render_template('website.sitemap_xml', {'content': urls}) pages += 1 last_sitemap = create_sitemap( '/sitemap-%d-%d.xml' % (current_website.id, pages), content) else: break if not pages: return request.not_found() elif pages == 1: # rename the -id-page.xml => -id.xml last_sitemap.write({ 'url': "/sitemap-%d.xml" % current_website.id, 'name': "/sitemap-%d.xml" % current_website.id, }) else: # TODO: in master/saas-15, move current_website_id in template directly pages_with_website = [ "%d-%d" % (current_website.id, p) for p in range(1, pages + 1) ] # Sitemaps must be split in several smaller files with a sitemap index content = View.render_template( 'website.sitemap_index_xml', { 'pages': pages_with_website, 'url_root': request.httprequest.url_root, }) create_sitemap('/sitemap-%d.xml' % current_website.id, content) return request.make_response(content, [('Content-Type', mimetype)])
def status_http(self, debug=None, **kwargs): resp = """ <!DOCTYPE HTML> <html> <head> <title>GECOERP's PosBox</title> <style> body { width: 480px; margin: 60px auto; font-family: sans-serif; text-align: justify; color: #6B6B6B; } .device { border-bottom: solid 1px rgb(216,216,216); padding: 9px; } .device:nth-child(2n) { background:rgb(240,240,240); } </style> </head> <body> <h1>Hardware Status</h1> <p>The list of enabled drivers and their status</p> """ statuses = self.get_status() for driver in statuses: status = statuses[driver] if status['status'] == 'connecting': color = 'black' elif status['status'] == 'connected': color = 'green' else: color = 'red' resp += "<h3 style='color:" + color + ";'>" + driver + ' : ' + status[ 'status'] + "</h3>\n" resp += "<ul>\n" for msg in status['messages']: resp += '<li>' + msg + '</li>\n' resp += "</ul>\n" resp += """ <h2>Connected Devices</h2> <p>The list of connected USB devices as seen by the posbox</p> """ if debug is None: resp += """(<a href="/hw_proxy/status?debug">debug version</a>)""" devices = subprocess.check_output("lsusb").decode('utf-8').split('\n') count = 0 resp += "<div class='devices'>\n" for device in devices: device_name = device[device.find('ID') + 2:] if device_name: # to avoid last empty line device_id = device_name.split()[0] if not (device_id in BANNED_DEVICES): resp += "<div class='device' data-device='" + device + "'>" + device_name + "</div>\n" count += 1 if count == 0: resp += "<div class='device'>No USB Device Found</div>" resp += "</div>\n</body>\n</html>\n\n" if debug is not None: resp += """ <h3>Debug version</h3> <p><tt>lsusb -v</tt> output:</p> <pre> %s </pre> """ % subprocess.check_output('lsusb -v', shell=True).decode('utf-8') return request.make_response( resp, { 'Cache-Control': 'no-cache', 'Content-Type': 'text/html; charset=utf-8', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET', })
def print_sale_details(self, date_start=False, date_stop=False, **kw): r = request.env['report.point_of_sale.report_saledetails'] pdf, _ = request.env.ref('point_of_sale.sale_details_report').with_context(date_start=date_start, date_stop=date_stop).render_qweb_pdf(r) pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] return request.make_response(pdf, headers=pdfhttpheaders)