From 01f3d0939a1aed6717425bad182575fea5a4cd26 Mon Sep 17 00:00:00 2001 From: ajay Date: Tue, 9 May 2023 14:18:41 +0530 Subject: [PATCH] first commit1 --- .idea/.gitignore | 8 + .idea/GitLink.xml | 6 + .idea/SolarCalculator.iml | 30 ++++ .idea/inspectionProfiles/Project_Default.xml | 35 ++++ .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + SolarCalculator/__init__.py | 0 SolarCalculator/asgi.py | 16 ++ SolarCalculator/forms.py | 19 +++ SolarCalculator/settings.py | 132 +++++++++++++++ SolarCalculator/urls.py | 23 +++ SolarCalculator/views.py | 150 ++++++++++++++++++ SolarCalculator/wsgi.py | 16 ++ db.sqlite3 | Bin 0 -> 131072 bytes manage.py | 22 +++ requirements.txt | 10 ++ templates/Input.html | 38 +++++ templates/Output.html | 67 ++++++++ 20 files changed, 596 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/GitLink.xml create mode 100644 .idea/SolarCalculator.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 SolarCalculator/__init__.py create mode 100644 SolarCalculator/asgi.py create mode 100644 SolarCalculator/forms.py create mode 100644 SolarCalculator/settings.py create mode 100644 SolarCalculator/urls.py create mode 100644 SolarCalculator/views.py create mode 100644 SolarCalculator/wsgi.py create mode 100644 db.sqlite3 create mode 100755 manage.py create mode 100644 requirements.txt create mode 100644 templates/Input.html create mode 100644 templates/Output.html diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/GitLink.xml b/.idea/GitLink.xml new file mode 100644 index 0000000..5143819 --- /dev/null +++ b/.idea/GitLink.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/SolarCalculator.iml b/.idea/SolarCalculator.iml new file mode 100644 index 0000000..094d9e2 --- /dev/null +++ b/.idea/SolarCalculator.iml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..da4ddb7 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,35 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..b091c37 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..33bd5aa --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SolarCalculator/__init__.py b/SolarCalculator/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/SolarCalculator/asgi.py b/SolarCalculator/asgi.py new file mode 100644 index 0000000..c56f72e --- /dev/null +++ b/SolarCalculator/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for SolarCalculator project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SolarCalculator.settings') + +application = get_asgi_application() diff --git a/SolarCalculator/forms.py b/SolarCalculator/forms.py new file mode 100644 index 0000000..142fb6b --- /dev/null +++ b/SolarCalculator/forms.py @@ -0,0 +1,19 @@ +from django import forms +from material import * + +class SolarForm(forms.Form): + name = forms.CharField(required=True, label="Name", initial='Mr.ABC') + kw_installed = forms.FloatField(required=True, label="KW Installed", min_value=0, max_value=1e100, initial=4.81) + initial_cost = forms.IntegerField(required=True, label="Initial Cost of Installation", initial=415000) + amc = forms.IntegerField(required=True, label="Annual Recurring Cost", initial=9000) + units1 = forms.IntegerField(required=True, label="Units Consumed (Jan-Feb)", initial=1200) + units2 = forms.IntegerField(required=True, label="Units Consumed (Mar-Apr)", initial=1600) + units3 = forms.IntegerField(required=True, label="Units Consumed (May-Jun)", initial=1800) + units4 = forms.IntegerField(required=True, label="Units Consumed (Jul-Aug)", initial=1400) + units5 = forms.IntegerField(required=True, label="Units Consumed (Sep-Oct)", initial=1600) + units6 = forms.IntegerField(required=True, label="Units Consumed (Nov-Dec)", initial=1000) + + layout = Layout( + Row('name', 'kw_installed', 'initial_cost', 'amc'), + Row('units1', 'units2', 'units3', 'units4', 'units5', 'units6'), + ) diff --git a/SolarCalculator/settings.py b/SolarCalculator/settings.py new file mode 100644 index 0000000..819e269 --- /dev/null +++ b/SolarCalculator/settings.py @@ -0,0 +1,132 @@ +""" +Django settings for SolarCalculator project. + +Generated by 'django-admin startproject' using Django 4.1.2. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-w&c9bz6fof7-amo)&tvl%9mcz_hl744sos5pv-q0#ua&kaspt_' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + # Installed Apps + 'material', + 'material.frontend', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'SolarCalculator.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [BASE_DIR / 'templates'] + , + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'SolarCalculator.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ +# STATIC_ROOT = "/var/www/solarcalc.duckdns.org/static/" +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO','https') + +CSRF_TRUSTED_ORIGINS=[ + 'https://solarcalc.duckdns.org', +] diff --git a/SolarCalculator/urls.py b/SolarCalculator/urls.py new file mode 100644 index 0000000..fce007c --- /dev/null +++ b/SolarCalculator/urls.py @@ -0,0 +1,23 @@ +"""SolarCalculator URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path +from . import views + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', views.SolarCalculatorView, name='SolarCalculator'), +] diff --git a/SolarCalculator/views.py b/SolarCalculator/views.py new file mode 100644 index 0000000..d5d1ef4 --- /dev/null +++ b/SolarCalculator/views.py @@ -0,0 +1,150 @@ +# Create your views here. +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import get_object_or_404, render, reverse +from django.template import loader +import pandas as pd +import numpy as np +from .forms import * +import io +import numpy_financial as npf + +def PrC(units_consumed): + cutoff = 500 + price_data1 = pd.DataFrame(np.array([[100, 0], [200, 2.25], [400, 4.5], + [500, 6]]), + columns=['Unit_Ceiling', 'Rate']) + + price_data2 = pd.DataFrame(np.array([[100, 0], [400, 4.5], [500, 6], + [600, 8], [800, 9], [1000, 10], + [np.inf, 11]]), + columns=['Unit_Ceiling', 'Rate']) + + if units_consumed < 0: + return 0 + elif units_consumed > cutoff: + DB = price_data2 + else: + DB = price_data1 + + DB['prev_slab'] = DB['Unit_Ceiling'].shift(1).fillna(0) + DB['cutoff'] = units_consumed - DB['prev_slab'] + DB = DB.loc[DB['cutoff'] > 0, :].drop(['cutoff'], axis=1).reset_index(drop=True) + DB.at[DB.index[-1], 'Unit_Ceiling'] = units_consumed + + bill = np.sum((DB['Unit_Ceiling'] - DB['prev_slab']) * DB['Rate']) + return bill + + +def SolarCalculatorView(request): + if request.method == 'GET': + form = SolarForm() + + return render(request, 'Input.html', { + 'form': form, + 'Title': 'TNEB Solar Returns Calculator' + }) + else: + # A POST request: Handle Form Upload + form = SolarForm(request.POST) # Bind data from request.POST into a PostForm + + name = request.POST.get('name', '') + kw_installed = float(request.POST.get('kw_installed', '')) + initial_cost = int(request.POST.get('initial_cost', '')) + amc = int(request.POST.get('amc', '')) + units1 = int(request.POST.get('units1', '')) + units2 = int(request.POST.get('units2', '')) + units3 = int(request.POST.get('units3', '')) + units4 = int(request.POST.get('units4', '')) + units5 = int(request.POST.get('units5', '')) + units6 = int(request.POST.get('units6', '')) + + # Savings Calculator + SolarSavings = pd.DataFrame([units1 + units2 + units3 + units4 + units5 + units6] + , columns=['Units Consumed']) + SolarSavings['Solar Units Generated'] = kw_installed * (4 * 6 + 3.5 * 4 + 3 * 2) * 30 + SolarSavings['Bill Without Solar'] = PrC(units1) + PrC(units2) + PrC(units3) + PrC(units4) + PrC(units5) + PrC( + units6) + SolarSavings['Gross Bill With Solar'] = PrC(units1 - kw_installed * 3.5 * 60) + \ + PrC(units2 - kw_installed * 4 * 60) + \ + PrC(units3 - kw_installed * 4 * 60) + \ + PrC(units4 - kw_installed * 4 * 60) + \ + PrC(units5 - kw_installed * 3.5 * 60) + \ + PrC(units6 - kw_installed * 3 * 60) + SolarSavings['Network Charges'] = SolarSavings['Solar Units Generated'] * .6 * .85 + SolarSavings['Net Bill With Solar'] = SolarSavings['Gross Bill With Solar'] + SolarSavings['Network Charges'] + SolarSavings['Annual Savings'] = SolarSavings['Bill Without Solar'] - SolarSavings['Net Bill With Solar'] + + # Cashflow at Inflation 4%, 6%, 8% + Cashflow = pd.DataFrame(list(range(1, 26)), columns=['Year']) + Cashflow['Investment & Charges'] = amc*1.0 + # Initial Charges + Cashflow.loc[-1] = [0, initial_cost] + Cashflow.index = Cashflow.index + 1 # shifting index + Cashflow.sort_index(inplace=True) + + Cashflow['Annual Savings'] = SolarSavings['Annual Savings'][0] + Cashflow.loc[0, 'Annual Savings'] = 0 + Cashflow['Net Cashflow'] = Cashflow['Annual Savings'] - Cashflow['Investment & Charges'] + Cashflow['4% Inflation'] = Cashflow['Annual Savings']*(1.04 ** Cashflow['Year']) - \ + Cashflow['Investment & Charges']*(1.04 ** Cashflow['Year']) + Cashflow['6% Inflation'] = Cashflow['Annual Savings']*(1.06 ** Cashflow['Year']) - \ + Cashflow['Investment & Charges']*(1.06 ** Cashflow['Year']) + Cashflow['8% Inflation'] = Cashflow['Annual Savings']*(1.08 ** Cashflow['Year']) - \ + Cashflow['Investment & Charges']*(1.08 ** Cashflow['Year']) + + P4Inf = pd.DataFrame(['4% Inflation'], columns=['Scenario']) + P4Inf['25 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['4% Inflation']), 4)) + P4Inf['20 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['4% Inflation'][:21]), 4)) + P4Inf['15 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['4% Inflation'][:16]), 4)) + P4Inf['10 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['4% Inflation'][:11]), 4)) + P4Inf['Payback Period'] = '{0} years'.format(len(np.cumsum(Cashflow['4% Inflation'] + [np.cumsum(Cashflow['4% Inflation']) < 0]))) + P4Inf['NPV @ 7% FD'] = "{:,.0f}".format(round(npf.npv(.07, Cashflow['4% Inflation']), 4)) + + P6Inf = pd.DataFrame(['6% Inflation'], columns=['Scenario']) + P6Inf['25 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['6% Inflation']), 4)) + P6Inf['20 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['6% Inflation'][:21]), 4)) + P6Inf['15 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['6% Inflation'][:16]), 4)) + P6Inf['10 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['6% Inflation'][:11]), 4)) + P6Inf['Payback Period'] = '{0} years'.format(len(np.cumsum(Cashflow['6% Inflation'] + [np.cumsum(Cashflow['6% Inflation']) < 0]))) + P6Inf['NPV @ 7% FD'] = "{:,.0f}".format(round(npf.npv(.07, Cashflow['6% Inflation']), 4)) + + P8Inf = pd.DataFrame(['8% Inflation'], columns=['Scenario']) + P8Inf['25 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['8% Inflation']), 4)) + P8Inf['20 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['8% Inflation'][:21]), 4)) + P8Inf['15 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['8% Inflation'][:16]), 4)) + P8Inf['10 Year Return'] = "{0:.2%}".format(round(npf.irr(Cashflow['8% Inflation'][:11]), 4)) + P8Inf['Payback Period'] = '{0} years'.format(len(np.cumsum(Cashflow['8% Inflation'] + [np.cumsum(Cashflow['8% Inflation']) < 0]))) + P8Inf['NPV @ 7% FD'] = "{:,.0f}".format(round(npf.npv(.07, Cashflow['8% Inflation']), 4)) + + Metric = pd.concat([P4Inf, P6Inf, P8Inf], axis=0, ignore_index=True) + + # , '20 YEAR IRR', '15 YEAR IRR', '10 YEAR IRR', 'Payback Period', + # 'Discounted Payback' + # round(np.irr(Cashflow['Net Cashflow']), 2) + pd.options.display.float_format = '{:,.0f}'.format + + buf = io.StringIO() + Metric.to_html(buf, escape=False, index=False, classes='" id = "table0') + Metric_HTML = buf.getvalue() + + buf = io.StringIO() + Cashflow.to_html(buf, escape=False, index=False, classes='" id = "table1') + Cashflow_HTML = buf.getvalue() + + buf = io.StringIO() + SolarSavings.to_html(buf, escape=False, index=False, classes='" id = "table2') + SolarSavings_HTML = buf.getvalue() + + # IRR at 25, 20, 15, 10 Years + + # Discounted Payback Period & Payback Period + return render(request, 'Output.html', { + 'form': form, + 'Title': f'Analysis of Investment in Solar Installation for {name}', + 'DF_0': Metric_HTML, + 'DF_1': Cashflow_HTML, + 'DF_2': SolarSavings_HTML, + }) diff --git a/SolarCalculator/wsgi.py b/SolarCalculator/wsgi.py new file mode 100644 index 0000000..c37a077 --- /dev/null +++ b/SolarCalculator/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for SolarCalculator project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SolarCalculator.settings') + +application = get_wsgi_application() diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..a24f4d6059d876b57020438f5868e2f67becc3a2 GIT binary patch literal 131072 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 literal 0 HcmV?d00001 diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..a415cac --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SolarCalculator.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e40ee27 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +asgiref==3.5.2 +Django==4.1.2 +django-material==1.11.3 +numpy==1.23.4 +numpy-financial==1.0.0 +pandas==1.5.0 +python-dateutil==2.8.2 +pytz==2022.5 +six==1.16.0 +sqlparse==0.4.3 diff --git a/templates/Input.html b/templates/Input.html new file mode 100644 index 0000000..a2b64c5 --- /dev/null +++ b/templates/Input.html @@ -0,0 +1,38 @@ + + +{% load static %} +{% load material_form %} + + {% include 'material/includes/material_css.html' %} + {% include 'material/includes/material_js.html' %} + + + + + + +
+
{{ Title }}
+ +
+
{% csrf_token %} + {% form form=form %}{% endform %} + +
+
+ +
+
+
+ {{ DF_1|safe }} +
+
+ + + \ No newline at end of file diff --git a/templates/Output.html b/templates/Output.html new file mode 100644 index 0000000..2736428 --- /dev/null +++ b/templates/Output.html @@ -0,0 +1,67 @@ + + +{% load static %} +{% load material_form %} + + {% include 'material/includes/material_css.html' %} + {% include 'material/includes/material_js.html' %} + + + + + + +
+
{{ Title }}
+ +
+
{% csrf_token %} + {% form form=form %}{% endform %} + +
+
+ +
+
+
+ {{ DF_0|safe }} +
+
+
+ {{ DF_2|safe }} +
+
+
+ {{ DF_1|safe }} +
+ +
+ The above is a financial simulation of reality which may turn out to be different based on a number of factors + including but not restricted to policy changes, unit generaton variations, revision in tariff and net metering guidelines etc. + Network charges is assumed to be charged at 60% of generated units at Rs.0.85/unit. + Solar power is assumed to be generated at 4KWH/KW of installation between Mar and Aug, 3.5 KW between Sep-Oct & Jan-Feb and 3 KW during Nov-Dec. + Tariff used is as per TNEB guidelines as at Oct 18, 2022. + +
+
+ + + + \ No newline at end of file