""" Django views for interacting with Company app """ # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.utils.translation import ugettext_lazy as _ from django.views.generic import DetailView, ListView from django.urls import reverse from django.core.files.base import ContentFile from PIL import Image import requests import io from InvenTree.views import AjaxUpdateView from InvenTree.views import InvenTreeRoleMixin from .models import Company from .models import ManufacturerPart from .models import SupplierPart from .forms import CompanyImageDownloadForm class CompanyIndex(InvenTreeRoleMixin, ListView): """ View for displaying list of companies """ model = Company template_name = 'company/index.html' context_object_name = 'companies' paginate_by = 50 permission_required = 'company.view_company' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) # Provide custom context data to the template, # based on the URL we use to access this page lookup = { reverse('supplier-index'): { 'title': _('Suppliers'), 'button_text': _('New Supplier'), 'filters': {'is_supplier': 'true'}, 'pagetype': 'suppliers', }, reverse('manufacturer-index'): { 'title': _('Manufacturers'), 'button_text': _('New Manufacturer'), 'filters': {'is_manufacturer': 'true'}, 'pagetype': 'manufacturers', }, reverse('customer-index'): { 'title': _('Customers'), 'button_text': _('New Customer'), 'filters': {'is_customer': 'true'}, 'pagetype': 'customers', } } default = { 'title': _('Companies'), 'button_text': _('New Company'), 'filters': {}, 'pagetype': 'companies' } context = None for item in lookup: if self.request.path == item: context = lookup[item] break if context is None: context = default for key, value in context.items(): ctx[key] = value return ctx def get_queryset(self): """ Retrieve the Company queryset based on HTTP request parameters. - supplier: Filter by supplier - customer: Filter by customer """ queryset = Company.objects.all().order_by('name') if self.request.GET.get('supplier', None): queryset = queryset.filter(is_supplier=True) if self.request.GET.get('customer', None): queryset = queryset.filter(is_customer=True) return queryset class CompanyDetail(DetailView): """ Detail view for Company object """ context_obect_name = 'company' template_name = 'company/detail.html' queryset = Company.objects.all() model = Company permission_required = 'company.view_company' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) return ctx class CompanyImageDownloadFromURL(AjaxUpdateView): """ View for downloading an image from a provided URL """ model = Company ajax_template_name = 'image_download.html' form_class = CompanyImageDownloadForm ajax_form_title = _('Download Image') def validate(self, company, form): """ Validate that the image data are correct """ # First ensure that the normal validation routines pass if not form.is_valid(): return # We can now extract a valid URL from the form data url = form.cleaned_data.get('url', None) # Download the file response = requests.get(url, stream=True) # Look at response header, reject if too large content_length = response.headers.get('Content-Length', '0') try: content_length = int(content_length) except (ValueError): # If we cannot extract meaningful length, just assume it's "small enough" content_length = 0 # TODO: Factor this out into a configurable setting MAX_IMG_LENGTH = 10 * 1024 * 1024 if content_length > MAX_IMG_LENGTH: form.add_error('url', _('Image size exceeds maximum allowable size for download')) return self.response = response # Check for valid response code if not response.status_code == 200: form.add_error('url', _('Invalid response: {code}').format(code=response.status_code)) return response.raw.decode_content = True try: self.image = Image.open(response.raw).convert() self.image.verify() except: form.add_error('url', _("Supplied URL is not a valid image file")) return def save(self, company, form, **kwargs): """ Save the downloaded image to the company """ fmt = self.image.format if not fmt: fmt = 'PNG' buffer = io.BytesIO() self.image.save(buffer, format=fmt) # Construct a simplified name for the image filename = f"company_{company.pk}_image.{fmt.lower()}" company.image.save( filename, ContentFile(buffer.getvalue()), ) class ManufacturerPartDetail(DetailView): """ Detail view for ManufacturerPart """ model = ManufacturerPart template_name = 'company/manufacturer_part_detail.html' context_object_name = 'part' queryset = ManufacturerPart.objects.all() permission_required = 'purchase_order.view' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) return ctx class SupplierPartDetail(DetailView): """ Detail view for SupplierPart """ model = SupplierPart template_name = 'company/supplier_part_detail.html' context_object_name = 'part' queryset = SupplierPart.objects.all() permission_required = 'purchase_order.view' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) return ctx