diff --git a/shimatta_kenkyusho/parts/forms.py b/shimatta_kenkyusho/parts/forms.py index 149e771..1cbfbae 100644 --- a/shimatta_kenkyusho/parts/forms.py +++ b/shimatta_kenkyusho/parts/forms.py @@ -296,4 +296,13 @@ class DistributorNumberFormSet(forms.BaseModelFormSet): class PackageForm(forms.ModelForm): class Meta: model = parts_models.Package + fields = '__all__' + +class DistributorForm(forms.ModelForm): + class Meta: + model = parts_models.Distributor + fields = '__all__' +class ManufacturerForm(forms.ModelForm): + class Meta: + model = parts_models.Manufacturer fields = '__all__' \ No newline at end of file diff --git a/shimatta_kenkyusho/parts/navbar.py b/shimatta_kenkyusho/parts/navbar.py index fd2f45b..e330d5e 100644 --- a/shimatta_kenkyusho/parts/navbar.py +++ b/shimatta_kenkyusho/parts/navbar.py @@ -36,6 +36,8 @@ class NavBar(): 'Components':BsNavBarItem('Components', reverse('parts-components'), False), 'Packages': BsNavBarItem('Packages', reverse('parts-packages'), False), 'Stocks':BsNavBarItem('Stocks', reverse('parts-stocks'), False), + 'Distributors':BsNavBarItem('Distributors', reverse('parts-distributors'), False), + 'Manufacturers':BsNavBarItem('Manufacturers', reverse('parts-manufacturers'), False), } try: @@ -48,6 +50,8 @@ class NavBar(): items['Components'], items['Packages'], items['Stocks'], + items['Distributors'], + items['Manufacturers'], #items['Login'], ] nb = NavBar() diff --git a/shimatta_kenkyusho/parts/urls.py b/shimatta_kenkyusho/parts/urls.py index e448178..a693f79 100644 --- a/shimatta_kenkyusho/parts/urls.py +++ b/shimatta_kenkyusho/parts/urls.py @@ -5,6 +5,7 @@ urlpatterns = [ path('', parts_views.MainView.as_view(), name='parts-main'), path('components/', parts_views.ComponentView.as_view(), name='parts-components'), path('packages/', parts_views.PackageView.as_view(), name='parts-packages'), + path('distributors/', parts_views.DistributorView.as_view(), name='parts-distributors'), path('stocks/', parts_views.StockView.as_view(), name='parts-stocks'), path('logout/', parts_views.logout_view, name='logout'), path('login/', parts_views.login_view, name='login'), @@ -12,4 +13,7 @@ urlpatterns = [ path('stocks//', parts_views.StockViewDetail.as_view(), name='parts-stocks-detail'), path('components//', parts_views.ComponentDetailView.as_view(), name='parts-components-detail'), path('packages//', parts_views.PackageDetailView.as_view(), name='parts-packages-detail'), + path('distributors//', parts_views.DistributorDetailView.as_view(), name='parts-distributors-detail'), + path('manufacturers/', parts_views.ManufacturersViewSet.as_view(), name='parts-manufacturers'), + path("manufacturers//", parts_views.ManufacturerDetailViewSet.as_view(), name='parts-manufacturers-detail'), ] diff --git a/shimatta_kenkyusho/parts/views.py b/shimatta_kenkyusho/parts/views.py index 6e9b4e7..0e10f19 100644 --- a/shimatta_kenkyusho/parts/views.py +++ b/shimatta_kenkyusho/parts/views.py @@ -202,6 +202,58 @@ class PackageView(LoginRequiredMixin, BaseTemplateMixin, TemplateView): return super().post(request, *args, **kwargs) +class DistributorView(LoginRequiredMixin, BaseTemplateMixin, TemplateView): + template_name = 'parts/distributors.html' + base_title = 'Distributors' + navbar_selected = 'Distributors' + default_page_size = 25 + + def search_distributors(self, search): + qs = Distributor.objects.all() + + if not search: + return qs + + search = search.strip() + + qs = qs.filter(Q(name__contains = search) | Q(website__contains = search)) + return qs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + page_num = self.request.GET.get('page', default=1) + search_string = self.request.GET.get('search', default=None) + + queryset = self.search_distributors(search_string) + + paginator = Paginator(queryset, self.default_page_size) + + + context['search_string'] = search_string + context['distributors'] = paginator.get_page(page_num) + context['new_distri_form'] = DistributorForm() + + return context + + def handle_add_new_distributor(self, request): + + form = DistributorForm(data=request.POST, files=request.FILES) + if form.is_valid(): + form.save() + + context = self.get_context_data() + + if not form.is_valid(): + context['new_distri_form'] = form + + return self.render_to_response(context) + + def post(self, request, *args, **kwargs): + if 'submit-distri-add-new' in request.POST: + return self.handle_add_new_distributor(request) + + return super().post(request, *args, **kwargs) + class StockView(LoginRequiredMixin, BaseTemplateMixin, TemplateView): template_name = 'parts/stocks.html' base_title = 'Stocks' @@ -440,8 +492,6 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView): base_title = '' navbar_selected = 'Components' - - def prepare_initial_param_formset_data(self): parameters = ComponentParameter.objects.filter(component=self.object) initdata = [] @@ -620,4 +670,170 @@ class PackageDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView): elif 'submit-pkg-edit' in request.POST: return self.edit_package(request) + return super().post(request, *args, **kwargs) + +class DistributorDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView): + template_name = 'parts/distributors-detail.html' + model = Distributor + pk_url_kwarg = 'uuid' + base_title = '' + navbar_selected = 'Distributors' + + def get_context_data(self, **kwargs): + self.base_title = 'Distributor / '+self.object.name + context = super().get_context_data(**kwargs) + context['distributor'] = self.object + context['edit_form'] = DistributorForm(instance=self.object) + + return context + + def handle_delete_distributor(self, request): + delete_error = None + protected_objects = None + + # Try to delete this instance + try: + self.object.delete() + except ProtectedError as pe: + delete_error = 'Cannot delete this distributor. It is referenced by a component.' + protected_objects = pe.protected_objects + except: + delete_error = 'Cannot delete this distributor. Unknown error' + + if delete_error: + context = self.get_context_data() + context['delete_error'] = delete_error + context['protected_components'] = protected_objects + return self.render_to_response(context) + else: + return redirect('parts-distributors') + + def edit_distributor(self, request): + edit_form = DistributorForm(data=request.POST, files=request.FILES, instance=self.object) + + if edit_form.is_valid(): + edit_form.save() + + context = self.get_context_data() + if not edit_form.is_valid(): + context['edit_form'] = edit_form + return self.render_to_response(context) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + + if 'submit-distri-delete' in request.POST: + return self.handle_delete_distributor(request) + elif 'submit-distri-edit' in request.POST: + return self.edit_distributor(request) + + return super().post(request, *args, **kwargs) + +class ManufacturersViewSet(LoginRequiredMixin, BaseTemplateMixin, TemplateView): + template_name = 'parts/manufacturers.html' + base_title = 'Manufacturers' + navbar_selected = 'Manufacturers' + default_page_size = 25 + + def search_manufacturers(self, search): + qs = Manufacturer.objects.all() + + if not search: + return qs + + search = search.strip() + + qs = qs.filter(Q(name__contains = search) | Q(website__contains = search)) + return qs + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + page_num = self.request.GET.get('page', default=1) + search_string = self.request.GET.get('search', default=None) + + queryset = self.search_manufacturers(search_string) + + paginator = Paginator(queryset, self.default_page_size) + + + context['search_string'] = search_string + context['manufacturers'] = paginator.get_page(page_num) + context['new_manufacturer_form'] = ManufacturerForm() + + return context + + def handle_add_new_manufacturer(self, request): + + form = ManufacturerForm(data=request.POST, files=request.FILES) + if form.is_valid(): + form.save() + + context = self.get_context_data() + + if not form.is_valid(): + context['new_manufacturer_form'] = form + + return self.render_to_response(context) + + def post(self, request, *args, **kwargs): + if 'submit-manufacturer-add-new' in request.POST: + return self.handle_add_new_manufacturer(request) + + return super().post(request, *args, **kwargs) + +class ManufacturerDetailViewSet(LoginRequiredMixin, BaseTemplateMixin, DetailView): + template_name = 'parts/manufacturers-detail.html' + model = Manufacturer + pk_url_kwarg = 'uuid' + base_title = '' + navbar_selected = 'Manufacturers' + + def get_context_data(self, **kwargs): + self.base_title = 'Manufacturer / '+self.object.name + context = super().get_context_data(**kwargs) + context['manufacturer'] = self.object + context['edit_form'] = ManufacturerForm(instance=self.object) + + return context + + def handle_delete_manufacturer(self, request): + delete_error = None + protected_objects = None + + # Try to delete this instance + try: + self.object.delete() + except ProtectedError as pe: + delete_error = 'Cannot delete this distributor. It is referenced by a component.' + protected_objects = pe.protected_objects + except: + delete_error = 'Cannot delete this distributor. Unknown error' + + if delete_error: + context = self.get_context_data() + context['delete_error'] = delete_error + context['protected_components'] = protected_objects + return self.render_to_response(context) + else: + return redirect('parts-manufacturers') + + def edit_manufacturer(self, request): + edit_form = ManufacturerForm(data=request.POST, files=request.FILES, instance=self.object) + + if edit_form.is_valid(): + edit_form.save() + + context = self.get_context_data() + if not edit_form.is_valid(): + context['edit_form'] = edit_form + return self.render_to_response(context) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + + if 'submit-manufacturer-delete' in request.POST: + return self.handle_delete_manufacturer(request) + elif 'submit-manufacturer-edit' in request.POST: + return self.edit_manufacturer(request) + return super().post(request, *args, **kwargs) \ No newline at end of file diff --git a/shimatta_kenkyusho/templates/parts/components-detail.html b/shimatta_kenkyusho/templates/parts/components-detail.html index 6d5ea7a..566a2e5 100644 --- a/shimatta_kenkyusho/templates/parts/components-detail.html +++ b/shimatta_kenkyusho/templates/parts/components-detail.html @@ -50,7 +50,7 @@ {% if component.manufacturer %} - {{component.manufacturer.name}} + {{component.manufacturer.name}} {% if component.manufacturer.image %} {% endif %} diff --git a/shimatta_kenkyusho/templates/parts/distributors-detail.html b/shimatta_kenkyusho/templates/parts/distributors-detail.html new file mode 100644 index 0000000..39f49c6 --- /dev/null +++ b/shimatta_kenkyusho/templates/parts/distributors-detail.html @@ -0,0 +1,94 @@ +{% extends 'base.html' %} + +{% load static %} +{% load crispy_forms_tags %} + +{% block content %} +
+
+
+
+ {% if distributor.image %} + {{distributor.name}} + {% else %} + {{distributor.name}} + {% endif %} +
+
+ +
+
+
+

Distributor {{distributor.name}}

+
+ {% csrf_token %} + {{edit_form|crispy}} + +
+
+
+
+ +{% if distributor.image %} + +{% endif %} + + + + + +{% endblock content %} + +{% block custom_scripts %} + + +{% endblock custom_scripts %} \ No newline at end of file diff --git a/shimatta_kenkyusho/templates/parts/distributors.html b/shimatta_kenkyusho/templates/parts/distributors.html new file mode 100644 index 0000000..adbf2ae --- /dev/null +++ b/shimatta_kenkyusho/templates/parts/distributors.html @@ -0,0 +1,75 @@ +{% extends 'base.html' %} + +{% load static %} +{% load crispy_forms_tags %} + +{% block content %} +
+
+
+

Distributors

+
+
+ + + +
+
+
+ {% include 'paginator.html' with paginator=distributors get_param='page' aria_label='Distributor Page Navigation' %} +
+ + {% include 'paginator.html' with paginator=distributors get_param='page' aria_label='Distributor Page Navigation' %} +
+
+
+ + + +{% endblock content %} + +{% block custom_scripts %} + +{% endblock custom_scripts %} \ No newline at end of file diff --git a/shimatta_kenkyusho/templates/parts/manufacturers-detail.html b/shimatta_kenkyusho/templates/parts/manufacturers-detail.html new file mode 100644 index 0000000..0f32cc6 --- /dev/null +++ b/shimatta_kenkyusho/templates/parts/manufacturers-detail.html @@ -0,0 +1,94 @@ +{% extends 'base.html' %} + +{% load static %} +{% load crispy_forms_tags %} + +{% block content %} +
+
+
+
+ {% if manufacturer.image %} + {{manufacturer.name}} + {% else %} + {{manufacturer.name}} + {% endif %} +
+
+ +
+
+
+

Manufacturer {{manufacturer.name}}

+
+ {% csrf_token %} + {{edit_form|crispy}} + +
+
+
+
+ +{% if manufacturer.image %} + +{% endif %} + + + + + +{% endblock content %} + +{% block custom_scripts %} + + +{% endblock custom_scripts %} \ No newline at end of file diff --git a/shimatta_kenkyusho/templates/parts/manufacturers.html b/shimatta_kenkyusho/templates/parts/manufacturers.html new file mode 100644 index 0000000..6515f4b --- /dev/null +++ b/shimatta_kenkyusho/templates/parts/manufacturers.html @@ -0,0 +1,74 @@ +{% extends 'base.html' %} +{% load static %} +{% load crispy_forms_tags %} + +{% block content %} +
+
+
+

Manufacturers

+
+
+ + + +
+
+
+ {% include 'paginator.html' with paginator=manufacturers get_param='page' aria_label='Manufacturer Page Navigation' %} +
+ + {% include 'paginator.html' with paginator=manufacturers get_param='page' aria_label='Manufacturer Page Navigation' %} +
+
+
+ + + +{% endblock content %} + +{% block custom_scripts %} + +{% endblock custom_scripts %} \ No newline at end of file