From a38cd9e5b3a4f7f7a38a46b9dc2ed53cc89ad875 Mon Sep 17 00:00:00 2001 From: Sebastian Henschel Date: Mon, 29 May 2017 12:58:06 +0200 Subject: [PATCH] Added app to create customers #25 --- apimanager/apimanager/settings.py | 9 + apimanager/apimanager/urls.py | 1 + apimanager/base/templates/base.html | 2 + apimanager/customers/__init__.py | 0 apimanager/customers/apps.py | 5 + apimanager/customers/forms.py | 216 ++++++++++++++++++ .../static/customers/css/customers.css | 8 + .../static/customers/js/customers.js | 2 + .../customers/templates/customers/create.html | 201 ++++++++++++++++ apimanager/customers/urls.py | 14 ++ apimanager/customers/views.py | 101 ++++++++ 11 files changed, 559 insertions(+) create mode 100644 apimanager/customers/__init__.py create mode 100644 apimanager/customers/apps.py create mode 100644 apimanager/customers/forms.py create mode 100644 apimanager/customers/static/customers/css/customers.css create mode 100644 apimanager/customers/static/customers/js/customers.js create mode 100644 apimanager/customers/templates/customers/create.html create mode 100644 apimanager/customers/urls.py create mode 100644 apimanager/customers/views.py diff --git a/apimanager/apimanager/settings.py b/apimanager/apimanager/settings.py index 7ee3427..11aac38 100644 --- a/apimanager/apimanager/settings.py +++ b/apimanager/apimanager/settings.py @@ -48,6 +48,7 @@ INSTALLED_APPS = [ 'oauth', 'consumers', 'users', + 'customers', 'metrics', #'api_config', ] @@ -167,6 +168,14 @@ LOGGING = { 'handlers': ['console'], 'level': 'INFO', }, + 'customers': { + 'handlers': ['console'], + 'level': 'INFO', + }, + 'metrics': { + 'handlers': ['console'], + 'level': 'INFO', + }, }, } diff --git a/apimanager/apimanager/urls.py b/apimanager/apimanager/urls.py index 4079a9e..87d9fe8 100644 --- a/apimanager/apimanager/urls.py +++ b/apimanager/apimanager/urls.py @@ -13,6 +13,7 @@ urlpatterns = [ url(r'^oauth/', include('oauth.urls')), url(r'^consumers/', include('consumers.urls')), url(r'^users/', include('users.urls')), + url(r'^customers/', include('customers.urls')), url(r'^metrics/', include('metrics.urls')), #url(r'^api_config/', include('api_config.urls')), ] diff --git a/apimanager/base/templates/base.html b/apimanager/base/templates/base.html index efe4c4d..846bbc3 100644 --- a/apimanager/base/templates/base.html +++ b/apimanager/base/templates/base.html @@ -31,6 +31,8 @@ Consumers {% url "users-index" as users_index_url %} Users + {% url "customers-create" as customers_create_url %} + Customers {% url "metrics-index" as metrics_index_url %} Metrics {% comment %} diff --git a/apimanager/customers/__init__.py b/apimanager/customers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apimanager/customers/apps.py b/apimanager/customers/apps.py new file mode 100644 index 0000000..01aabb7 --- /dev/null +++ b/apimanager/customers/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CustomersConfig(AppConfig): + name = 'customers' diff --git a/apimanager/customers/forms.py b/apimanager/customers/forms.py new file mode 100644 index 0000000..b9c159c --- /dev/null +++ b/apimanager/customers/forms.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +""" +Forms of customers app +""" + +from django import forms + +DATETIME_INPUT_FORMAT = '%Y-%m-%dT%H:%M:%SZ' + + +class CreateCustomerForm(forms.Form): + bank_id = forms.ChoiceField( + label='Bank', + widget=forms.Select( + attrs={ + 'class': 'form-control', + } + ), + choices=[], + ) + user_id = forms.ChoiceField( + label='User', + widget=forms.Select( + attrs={ + 'class': 'form-control', + } + ), + choices=[], + ) + customer_number = forms.CharField( + label='Customer Number', + widget=forms.TextInput( + attrs={ + 'placeholder': 'new customer number, e.g. 687687678', + 'class': 'form-control', + } + ), + ) + legal_name = forms.CharField( + label='Legal Name', + widget=forms.TextInput( + attrs={ + 'placeholder': 'NONE', + 'class': 'form-control', + } + ), + required=False, + ) + mobile_phone_number = forms.CharField( + label='Mobile Phone Number', + widget=forms.TextInput( + attrs={ + 'placeholder': '+49 123 456 78 90 12', + 'class': 'form-control', + } + ), + required=False, + ) + email = forms.CharField( + label='Email', + widget=forms.TextInput( + attrs={ + 'placeholder': 'person@example.com', + 'class': 'form-control', + } + ), + required=False, + ) + face_image_url = forms.CharField( + label='Face Image URL', + widget=forms.TextInput( + attrs={ + 'placeholder': 'https://static.openbankproject.com/images/OBP/favicon.png', + 'class': 'form-control', + } + ), + required=False, + ) + face_image_date = forms.DateTimeField( + label='Face Image Date', + input_formats=[DATETIME_INPUT_FORMAT], + widget=forms.DateTimeInput( + attrs={ + 'placeholder': '2013-01-22T00:08:00Z', + 'class': 'form-control', + } + ), + required=True, + ) + date_of_birth = forms.DateTimeField( + label='Date of Birth', + input_formats=[DATETIME_INPUT_FORMAT], + widget=forms.DateTimeInput( + attrs={ + 'placeholder': '2013-01-22T00:08:00Z', + 'class': 'form-control', + } + ), + required=True, + ) + relationship_status = forms.CharField( + label='Relationship Status', + widget=forms.TextInput( + attrs={ + 'placeholder': 'Single', + 'class': 'form-control', + } + ), + required=False, + ) + dependants = forms.IntegerField( + label='Dependants', + widget=forms.TextInput( + attrs={ + 'placeholder': '0', + 'class': 'form-control', + } + ), + initial=0, + required=True, + ) + dob_of_dependants = forms.CharField( + label='Date of Birth of Dependants', + widget=forms.TextInput( + attrs={ + 'placeholder': '2013-01-22T00:08:00Z, 2010-01-22T00:08:00Z', + 'class': 'form-control', + } + ), + required=False, + ) + credit_rating_rating = forms.CharField( + label='Credit Rating (Rating)', + widget=forms.TextInput( + attrs={ + 'placeholder': 'OBP', + 'class': 'form-control', + } + ), + required=False, + ) + credit_rating_source = forms.CharField( + label='Credit Rating (Source)', + widget=forms.TextInput( + attrs={ + 'placeholder': 'OBP', + 'class': 'form-control', + } + ), + required=False, + ) + credit_limit_currency = forms.CharField( + label='Credit Limit (Currency)', + widget=forms.TextInput( + attrs={ + 'placeholder': 'EUR', + 'class': 'form-control', + } + ), + required=False, + ) + credit_limit_amount = forms.CharField( + label='Credit Limit (Amount)', + widget=forms.TextInput( + attrs={ + 'placeholder': '10', + 'class': 'form-control', + } + ), + required=False, + ) + highest_education_attained = forms.CharField( + label='Highest Education Attained', + widget=forms.TextInput( + attrs={ + 'placeholder': 'Bachelor’s Degree', + 'class': 'form-control', + } + ), + required=False, + ) + employment_status = forms.CharField( + label='Employment Status', + widget=forms.TextInput( + attrs={ + 'placeholder': 'Employed', + 'class': 'form-control', + } + ), + required=False, + ) + kyc_status = forms.BooleanField( + label='KYC Status', + widget=forms.CheckboxInput( + attrs={ + 'class': 'form-control', + } + ), + initial=True, + required=False, + ) + last_ok_date = forms.DateTimeField( + label='Last OK Date', + input_formats=[DATETIME_INPUT_FORMAT], + widget=forms.DateTimeInput( + attrs={ + 'placeholder': '2013-01-22T00:08:00Z', + 'class': 'form-control', + } + ), + required=True, + ) + + def __init__(self, *args, **kwargs): + kwargs.setdefault('label_suffix', '') + super(CreateCustomerForm, self).__init__(*args, **kwargs) diff --git a/apimanager/customers/static/customers/css/customers.css b/apimanager/customers/static/customers/css/customers.css new file mode 100644 index 0000000..94ec978 --- /dev/null +++ b/apimanager/customers/static/customers/css/customers.css @@ -0,0 +1,8 @@ +#customers { + margin-bottom: 10px; +} + +input#id_kyc_status { + width: auto; + margin: -4px 0; +} diff --git a/apimanager/customers/static/customers/js/customers.js b/apimanager/customers/static/customers/js/customers.js new file mode 100644 index 0000000..8da0463 --- /dev/null +++ b/apimanager/customers/static/customers/js/customers.js @@ -0,0 +1,2 @@ +$(document).ready(function($) { +}); diff --git a/apimanager/customers/templates/customers/create.html b/apimanager/customers/templates/customers/create.html new file mode 100644 index 0000000..dc4da99 --- /dev/null +++ b/apimanager/customers/templates/customers/create.html @@ -0,0 +1,201 @@ +{% extends 'base.html' %} +{% load static %} + +{% block page_title %}{{ block.super }} / Customers{% endblock page_title %} + + +{% block content %} +
+

Create Customer

+ +
+ {% csrf_token %} + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} + +
+
+ {% if form.bank_id.errors %}
{{ form.bank_id.errors }}
{% endif %} +
+ {{ form.bank_id.label_tag }} + {{ form.bank_id }} +
+
+
+ {% if form.user_id.errors %}
{{ form.user_id.errors }}
{% endif %} +
+ {{ form.user_id.label_tag }} + {{ form.user_id }} +
+
+
+ {% if form.customer_number.errors %}
{{ form.customer_number.errors }}
{% endif %} +
+ {{ form.customer_number.label_tag }} + {{ form.customer_number }} +
+
+
+ +
+
+ {% if form.legal_name.errors %}
{{ form.legal_name.errors }}
{% endif %} +
+ {{ form.legal_name.label_tag }} + {{ form.legal_name }} +
+
+
+ {% if form.mobile_phone_number.errors %}
{{ form.mobile_phone_number.errors }}
{% endif %} +
+ {{ form.mobile_phone_number.label_tag }} + {{ form.mobile_phone_number }} +
+
+
+ {% if form.email.errors %}
{{ form.email.errors }}
{% endif %} +
+ {{ form.email.label_tag }} + {{ form.email }} +
+
+
+ +
+
+ {% if form.face_image_url.errors %}
{{ form.face_image_url.errors }}
{% endif %} +
+ {{ form.face_image_url.label_tag }} + {{ form.face_image_url }} +
+
+
+ {% if form.face_image_date.errors %}
{{ form.face_image_date.errors }}
{% endif %} +
+ {{ form.face_image_date.label_tag }} + {{ form.face_image_date }} +
+
+
+ +
+
+ {% if form.date_of_birth.errors %}
{{ form.date_of_birth.errors }}
{% endif %} +
+ {{ form.date_of_birth.label_tag }} + {{ form.date_of_birth }} +
+
+
+ {% if form.relationship_status.errors %}
{{ form.relationship_status.errors }}
{% endif %} +
+ {{ form.relationship_status.label_tag }} + {{ form.relationship_status }} +
+
+
+ +
+
+ {% if form.dependants.errors %}
{{ form.dependants.errors }}
{% endif %} +
+ {{ form.dependants.label_tag }} + {{ form.dependants }} +
+
+
+ {% if form.dob_of_dependants.errors %}
{{ form.dob_of_dependants.errors }}
{% endif %} +
+ {{ form.dob_of_dependants.label_tag }} + {{ form.dob_of_dependants }} +
+
+
+ +
+
+ {% if form.credit_rating_rating.errors %}
{{ form.credit_rating_rating.errors }}
{% endif %} +
+ {{ form.credit_rating_rating.label_tag }} + {{ form.credit_rating_rating }} +
+
+
+ {% if form.credit_rating_source.errors %}
{{ form.credit_rating_source.errors }}
{% endif %} +
+ {{ form.credit_rating_source.label_tag }} + {{ form.credit_rating_source }} +
+
+ +
+ {% if form.credit_limit_currency.errors %}
{{ form.credit_limit_currency.errors }}
{% endif %} +
+ {{ form.credit_limit_currency.label_tag }} + {{ form.credit_limit_currency }} +
+
+
+ {% if form.credit_limit_amount.errors %}
{{ form.credit_limit_amount.errors }}
{% endif %} +
+ {{ form.credit_limit_amount.label_tag }} + {{ form.credit_limit_amount }} +
+
+
+ +
+
+ {% if form.highest_education_attained.errors %}
{{ form.highest_education_attained.errors }}
{% endif %} +
+ {{ form.highest_education_attained.label_tag }} + {{ form.highest_education_attained }} +
+
+
+ {% if form.employment_status.errors %}
{{ form.employment_status.errors }}
{% endif %} +
+ {{ form.employment_status.label_tag }} + {{ form.employment_status }} +
+
+
+ +
+
+ {% if form.kyc_status.errors %}
{{ form.kyc_status.errors }}
{% endif %} +
+ {{ form.kyc_status.label_tag }} + {{ form.kyc_status }} +
+
+
+ {% if form.last_ok_date.errors %}
{{ form.last_ok_date.errors }}
{% endif %} +
+ {{ form.last_ok_date.label_tag }} + {{ form.last_ok_date }} +
+
+
+ + +
+
+{% endblock content %} + + +{% block extrajs %} +{% comment %} + + +{% endcomment %} +{% endblock extrajs %} + + +{% block extracss %} + +{% endblock extracss %} diff --git a/apimanager/customers/urls.py b/apimanager/customers/urls.py new file mode 100644 index 0000000..b0d72c6 --- /dev/null +++ b/apimanager/customers/urls.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +""" +URLs for customers app +""" + +from django.conf.urls import url + +from .views import CreateView + +urlpatterns = [ + url(r'^$', + CreateView.as_view(), + name='customers-create'), +] diff --git a/apimanager/customers/views.py b/apimanager/customers/views.py new file mode 100644 index 0000000..a091b6d --- /dev/null +++ b/apimanager/customers/views.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +""" +Views of customers app +""" + +import datetime + +from django.contrib import messages +from django.contrib.auth.mixins import LoginRequiredMixin +from django.http import HttpResponseRedirect +from django.urls import reverse_lazy +from django.views.generic import FormView + +from base.api import api, APIError + +from .forms import CreateCustomerForm, DATETIME_INPUT_FORMAT + + +class CreateView(LoginRequiredMixin, FormView): + """View to create a customer""" + form_class = CreateCustomerForm + template_name = 'customers/create.html' + success_url = reverse_lazy('customers-create') + + def get_bank_id_choices(self): + choices = [('', 'Choose ...')] + try: + result = api.get(self.request, '/banks') + for bank in result['banks']: + choices.append((bank['id'], bank['short_name'])) + except APIError as err: + messages.error(err) + return choices + + def get_user_id_choices(self): + choices = [('', 'Choose ...')] + try: + result = api.get(self.request, '/users') + for user in result['users']: + choices.append((user['user_id'], user['username'])) + except APIError as err: + messages.error(err) + return choices + + def get_form(self, *args, **kwargs): + form = super(CreateView, self).get_form(*args, **kwargs) + fields = form.fields + fields['bank_id'].choices = self.get_bank_id_choices() + fields['user_id'].choices = self.get_user_id_choices() + fields['last_ok_date'].initial =\ + datetime.datetime.now().strftime(DATETIME_INPUT_FORMAT) + return form + + def form_valid(self, form): + try: + data = form.cleaned_data + urlpath = '/banks/{}/customers'.format(data['bank_id']) + if data['dob_of_dependants']: + dob_of_dependants = data['dob_of_dependants'].split(',') + else: + dob_of_dependants = [] + payload = { + 'user_id': data['user_id'], + 'customer_number': data['customer_number'], + 'legal_name': data['legal_name'], + 'mobile_phone_number': data['mobile_phone_number'], + 'email': data['email'], + 'face_image': { + 'url': data['face_image_url'], + 'date': + data['face_image_date'].strftime(DATETIME_INPUT_FORMAT), + }, + 'date_of_birth': + data['date_of_birth'].strftime(DATETIME_INPUT_FORMAT), + 'relationship_status': data['relationship_status'], + 'dependants': data['dependants'], + 'dob_of_dependants': dob_of_dependants, + 'credit_rating': { + 'rating': data['credit_rating_rating'], + 'source': data['credit_rating_source'], + }, + 'credit_limit': { + 'currency': data['credit_limit_currency'], + 'amount': data['credit_limit_amount'], + }, + 'highest_education_attained': + data['highest_education_attained'], + 'employment_status': data['employment_status'], + 'kyc_status': data['kyc_status'], + 'last_ok_date': + data['last_ok_date'].strftime(DATETIME_INPUT_FORMAT), + } + result = api.post(self.request, urlpath, payload=payload) + except APIError as err: + messages.error(self.request, err) + return super(CreateView, self).form_invalid(form) + + msg = 'Customer number {} has been created successfully!'.format( + result['customer_number']) + messages.success(self.request, msg) + return super(CreateView, self).form_valid(form)