Skip to content

Commit

Permalink
Tracking pull request to merge the changes on release-1.2.0 to main. (#…
Browse files Browse the repository at this point in the history
…148)

* Update to 1.2.0

* create super user

* itvr 317, 325, 320, 321, 319 (#149)

* -updates styles
-updates eligibilty page
-removes unused code from pages and css

* -switches login to log in on bceid button

* -adds drivers license and email to application serializer so it is passed to the frontend for the confirmation page

* -updates application summary to match designs for each application type
-updates fontsize in confirmation table

* -started storybook for confirmation pages (does not currently work because of issues with idp)

* -updates identification examples page to match new designs

* -adds 'name and' to secondary identification 'The secondary piece of identification gives further proof of your name and address.'

* -adds extra line to next steps for summary

* -adds component for I Need Help section as it is reused so much

* -updates variable for dark grey, removes 'background' from name because its used for text too

* -updates spouse form
-updates file drop area
-updates household login
-updates title of household login story
-adds margin and width to file drop area css

* -adds back accidentally removed }

* -increases font size for consent checkbox labels

* -adds tax information to consent

* -adds table border variable
-adds css for rebate table

* -changes label text for spouse email
-makes form changes
-updates spouse form, some casing
-adds component for upload to form and spouse form

* -removes summary story (not working)

* -adds variables to consent tax

* itvr-327--loading-screen (#152)

* itvr-327--loading-screen

* itvr-327--disable-submit-buttons-when-loading

* itvr-331--complete-cra-workflow (#151)

* itvr-331--complete-cra-workflow

* itvr-331--use-not-approved-status-and-fix-emails

* new design changes/fixes (#154)

* -correct capitalization on titles for consent
-spacing between fields on form
-spouse email text drops to newline
-removes margin from p.error

* -fixes condition in application type
-removes eligibility pages and creates new individualLogin page, renames Household to householdLogin

* itvr-328--add-footer (#153)

* itvr328--add-footer

* itvr-328--css-changes

* itvr-328--move-footer-to-layout

* change class to className

* itvr 314 -changes alt text to identification examples (#156)

* -changes alt text to identification examples

* -fixed alt tags which were swapped for drivers licence and bc service card

* design changes, stories (#155)

* -story for application summary

* -adds tax consent story for spouse

* -fixes rebate amount for household table
-adds new line to spouse email input, to say that the spouse has authorized the applicant to use their email

* -adds story for new i need help component

* -adds story for spouse form

* -comments out not working stories

* By pass django auth (#150)

* update backend deployment readme

* itvr-324--consent-changes (#159)

* itvr-309-300--bcsc (#158)

* itvr-309-300--bcsc

* itvr-309--bcsc-houshold-application

* fix details page issue

* fix email variables (#160)

Co-authored-by: Emily <[email protected]>
Co-authored-by: tim738745 <[email protected]>
  • Loading branch information
3 people authored Jun 16, 2022
1 parent df3c3de commit 7ab9c15
Show file tree
Hide file tree
Showing 81 changed files with 2,179 additions and 1,140 deletions.
5 changes: 5 additions & 0 deletions .pipeline/build-k6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';
const task = require('./lib/build-k6.js')
const settings = require('./lib/config.js')

task(Object.assign(settings, { phase: 'build'}))
5 changes: 5 additions & 0 deletions .pipeline/deploy-k6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';
const settings = require('./lib/config.js')
const task = require('./lib/deploy-k6.js')

task(Object.assign(settings, { phase: settings.options.env}));
36 changes: 36 additions & 0 deletions .pipeline/lib/build-k6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict";
const { OpenShiftClientX } = require("@bcgov/pipeline-cli");
const path = require("path");

module.exports = settings => {
const phases = settings.phases;
const options = settings.options;
const oc = new OpenShiftClientX(Object.assign({ namespace: phases.build.namespace }, options));
const phase = "build";
let objects = [];
const templatesLocalBaseUrl = oc.toFileUrl(path.resolve(__dirname, "../../openshift"));

// The building of your cool app goes here ▼▼▼

// build frontend

//build backend
objects = objects.concat(oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/templates/backend/backend-bc.yaml`, {
'param':{
'NAME': phases[phase].name,
'SUFFIX': phases[phase].suffix,
'VERSION': phases[phase].tag,
'GIT_URL': oc.git.http_url,
'GIT_REF': oc.git.ref
}
}))

oc.applyRecommendedLabels(
objects,
phases[phase].name,
phase,
phases[phase].changeId,
phases[phase].instance,
);
oc.applyAndBuild(objects);
};
56 changes: 56 additions & 0 deletions .pipeline/lib/deploy-k6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"use strict";
const { OpenShiftClientX } = require("@bcgov/pipeline-cli");
const path = require("path");
//const KeyCloakClient = require('./keycloak');

module.exports = settings => {
const phases = settings.phases;
const options = settings.options;
const phase = options.env;
const changeId = phases[phase].changeId;
const oc = new OpenShiftClientX(Object.assign({namespace: phases[phase].namespace}, options));

//add Valid Redirect URIs for the pull request to keycloak
/************
if(phase === 'dev') {
const kc = new KeyCloakClient(settings, oc);
kc.addUris();
}
*************/

const templatesLocalBaseUrl = oc.toFileUrl(path.resolve(__dirname, "../../openshift"));
var objects = [];

// The deployment of your cool app goes here ▼▼▼

//before deploy k6 backend, copy backend-dc.yaml to backend-k6-dc.yaml and add BYPASS_AUTHENTICATION and gove value True
//sample image files are available at https://www.learningcontainer.com/sample-jpeg-file-download-for-testing/
objects = objects.concat(oc.processDeploymentTemplate(`${templatesLocalBaseUrl}/templates/backend/backend-k6-dc.yaml`, {
'param': {
'NAME': phases[phase].name,
'SUFFIX': phases[phase].suffix,
'VERSION': phases[phase].tag,
'ENV_NAME': phases[phase].phase,
'BACKEND_HOST_NAME': phases[phase].backendHost,
'CPU_REQUEST': phases[phase].backendCpuRequest,
'CPU_LIMIT': phases[phase].backendCpuLimit,
'MEMORY_REQUEST': phases[phase].backendMemoryRequest,
'MEMORY_LIMIT': phases[phase].backendMemoryLimit,
'HEALTH_CHECK_DELAY': phases[phase].backendHealthCheckDelay,
'REPLICAS': phases[phase].backendReplicas,
'DJANGO_DEBUG': phases[phase].backendDjangoDebug,
'BUCKET_NAME': phases[phase].bucketName
}
}))

oc.applyRecommendedLabels(
objects,
phases[phase].name,
phase,
`${changeId}`,
phases[phase].instance,
);
oc.importImageStreams(objects, phases[phase].tag, phases.build.namespace, phases.build.tag);
oc.applyAndDeploy(objects, phases[phase].instance);

};
1 change: 1 addition & 0 deletions .pipeline/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"deploy-metabase": "node deploy-metabase.js",
"deploy-patroni": "node deploy-patroni.js",
"deploy-knp": "node deploy-knp.js",
"deploy-k6": "node deploy-k6.js",
"version": "echo \"node@$(node --version) ($(which node))\" && echo \"npm@$(npm --version) ($(which npm))\" && npm ls"
},
"repository": {
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import base64
from api.utility import format_postal_code
from keycloak import KeycloakOpenID
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
Expand Down Expand Up @@ -78,5 +79,13 @@ def authenticate_credentials(self, token):
user.set_unusable_password()
user.save()

if token_info.get("identity_provider") == "bcsc":
user.last_name = token_info.get("family_name")
user.first_name = token_info.get("given_name")
user.date_of_birth = token_info.get("birthdate")
user.street_address = token_info.get("street_address")
user.locality = token_info.get("locality")
user.postal_code = format_postal_code(token_info.get("postal_code"))

return user, token
raise AuthenticationFailed("Invalid token")
16 changes: 16 additions & 0 deletions django/api/authentication/testing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.contrib.auth import get_user_model
from rest_framework.authentication import TokenAuthentication


ITVRUser = get_user_model()


class LoadTestingAuthentication(TokenAuthentication):
# Use any kind of token in the front end
# ex. Authorization: Bearer testtoken
keyword = "Bearer"

def authenticate_credentials(self, token):
# This requires a user to be present in the database.
user = ITVRUser.objects.first()
return user, token
14 changes: 7 additions & 7 deletions django/api/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 4.0.1 on 2022-06-02 15:48
# Generated by Django 4.0.1 on 2022-06-12 23:01

import api.validators
from django.conf import settings
Expand Down Expand Up @@ -26,7 +26,7 @@ class Migration(migrations.Migration):
('modified', django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name='modified')),
('id', shortuuid.django_fields.ShortUUIDField(alphabet=None, editable=False, length=16, max_length=16, prefix='', primary_key=True, serialize=False)),
('sin', encrypted_fields.fields.EncryptedCharField(max_length=9, validators=[api.validators.validate_sin])),
('status', models.CharField(choices=[('household_initiated', 'Household Initiated'), ('submitted', 'Submitted'), ('verified', 'Verified'), ('declined', 'Declined'), ('approved', 'Approved'), ('cra_error', 'CRA Error'), ('redeemed', 'Redeemed'), ('expired', 'Expired')], max_length=250)),
('status', models.CharField(choices=[('household_initiated', 'Household Initiated'), ('submitted', 'Submitted'), ('verified', 'Verified'), ('declined', 'Declined'), ('approved', 'Approved'), ('not_approved', 'Not Approved'), ('redeemed', 'Redeemed'), ('expired', 'Expired')], max_length=250)),
('last_name', models.CharField(max_length=250)),
('first_name', models.CharField(max_length=250)),
('middle_names', models.CharField(blank=True, max_length=250, null=True)),
Expand All @@ -37,8 +37,8 @@ class Migration(migrations.Migration):
('drivers_licence', models.CharField(max_length=8, validators=[django.core.validators.MinLengthValidator(7)])),
('date_of_birth', models.DateField(validators=[api.validators.validate_driving_age])),
('tax_year', models.IntegerField()),
('doc1', models.ImageField(upload_to='docs', validators=[api.validators.validate_file_size])),
('doc2', models.ImageField(upload_to='docs', validators=[api.validators.validate_file_size])),
('doc1', models.ImageField(blank=True, null=True, upload_to='docs')),
('doc2', models.ImageField(blank=True, null=True, upload_to='docs')),
('application_type', models.CharField(max_length=25)),
('consent_personal', models.BooleanField(validators=[api.validators.validate_consent])),
('consent_tax', models.BooleanField(validators=[api.validators.validate_consent])),
Expand All @@ -59,8 +59,8 @@ class Migration(migrations.Migration):
('first_name', models.CharField(max_length=250)),
('middle_names', models.CharField(blank=True, max_length=250, null=True)),
('date_of_birth', models.DateField(validators=[api.validators.validate_driving_age])),
('doc1', models.ImageField(upload_to='docs', validators=[api.validators.validate_file_size])),
('doc2', models.ImageField(upload_to='docs', validators=[api.validators.validate_file_size])),
('doc1', models.ImageField(blank=True, null=True, upload_to='docs')),
('doc2', models.ImageField(blank=True, null=True, upload_to='docs')),
('consent_personal', models.BooleanField(validators=[api.validators.validate_consent])),
('consent_tax', models.BooleanField(validators=[api.validators.validate_consent])),
('application', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='api.goelectricrebateapplication')),
Expand All @@ -81,7 +81,7 @@ class Migration(migrations.Migration):
('expiry_date', models.DateField()),
('rebate_max_amount', models.IntegerField(default=0)),
('rebate_state', models.BooleanField(default=False)),
('application_id', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='api.goelectricrebateapplication')),
('application', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='api.goelectricrebateapplication')),
],
options={
'get_latest_by': 'modified',
Expand Down
7 changes: 4 additions & 3 deletions django/api/models/go_electric_rebate.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
BooleanField,
PROTECT,
ForeignKey,
AutoField
AutoField,
)

from django.core.validators import MinLengthValidator
Expand All @@ -15,10 +15,11 @@
from api.models.go_electric_rebate_application import GoElectricRebateApplication



class GoElectricRebate(TimeStampedModel):
id = AutoField(primary_key=True)
application_id = ForeignKey(GoElectricRebateApplication, on_delete=PROTECT, blank=True, null=True)
application = ForeignKey(
GoElectricRebateApplication, on_delete=PROTECT, blank=True, null=True
)
drivers_licence = CharField(
max_length=8, unique=False, validators=[MinLengthValidator(7)]
)
Expand Down
7 changes: 3 additions & 4 deletions django/api/models/go_electric_rebate_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
validate_driving_age,
validate_sin,
validate_consent,
validate_file_size,
)
from django_extensions.db.models import TimeStampedModel
from django.utils.translation import gettext_lazy as _
Expand Down Expand Up @@ -48,7 +47,7 @@ class Status(TextChoices):
VERIFIED = ("verified", _("Verified"))
DECLINED = ("declined", _("Declined"))
APPROVED = ("approved", _("Approved"))
CRA_ERROR = ("cra_error", _("CRA Error"))
NOT_APPROVED = ("not_approved", _("Not Approved"))
REDEEMED = ("redeemed", _("Redeemed"))
EXPIRED = ("expired", _("Expired"))

Expand All @@ -71,7 +70,7 @@ class Status(TextChoices):
)
date_of_birth = DateField(validators=[validate_driving_age])
tax_year = IntegerField()
doc1 = ImageField(upload_to="docs", validators=[validate_file_size])
doc1 = ImageField(upload_to="docs", blank=True, null=True)

def doc1_tag(self):
return mark_safe(
Expand All @@ -81,7 +80,7 @@ def doc1_tag(self):

doc1_tag.short_description = "First Uploaded Document"

doc2 = ImageField(upload_to="docs", validators=[validate_file_size])
doc2 = ImageField(upload_to="docs", blank=True, null=True)

def doc2_tag(self):
return mark_safe(
Expand Down
5 changes: 2 additions & 3 deletions django/api/models/household_member.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
validate_driving_age,
validate_sin,
validate_consent,
validate_file_size,
)

media_storage = get_storage_class()()
Expand All @@ -36,7 +35,7 @@ class HouseholdMember(TimeStampedModel):
first_name = CharField(max_length=250, unique=False)
middle_names = CharField(max_length=250, unique=False, blank=True, null=True)
date_of_birth = DateField(validators=[validate_driving_age])
doc1 = ImageField(upload_to="docs", validators=[validate_file_size])
doc1 = ImageField(upload_to="docs", blank=True, null=True)

def doc1_tag(self):
return mark_safe(
Expand All @@ -46,7 +45,7 @@ def doc1_tag(self):

doc1_tag.short_description = "First Uploaded Document"

doc2 = ImageField(upload_to="docs", validators=[validate_file_size])
doc2 = ImageField(upload_to="docs", blank=True, null=True)

def doc2_tag(self):
return mark_safe(
Expand Down
79 changes: 67 additions & 12 deletions django/api/serializers/application_form.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from api.validators import validate_file_size
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from api.models.go_electric_rebate_application import GoElectricRebateApplication
from rest_framework.parsers import FormParser, MultiPartParser
from datetime import date
from django.core.exceptions import ValidationError


class ApplicationFormCreateSerializer(ModelSerializer):
Expand All @@ -14,10 +16,22 @@ class Meta:
model = GoElectricRebateApplication
exclude = ["user", "status", "tax_year"]

def get_serializer_context(self):
context = super().get_serializer_context()
context["request"] = self.request
return context
def _get_tax_year(self):
today = date.today()
month = today.month
year = today.year
if month < 7:
return year - 2
return year - 1


class ApplicationFormCreateSerializerDefault(ApplicationFormCreateSerializer):
def validate(self, data):
if data.get("doc1") is None or data.get("doc2") is None:
raise ValidationError("Missing required document.")
validate_file_size(data["doc1"])
validate_file_size(data["doc2"])
return data

def create(self, validated_data):
request = self.context["request"]
Expand Down Expand Up @@ -47,14 +61,6 @@ def create(self, validated_data):
)
return obj

def _get_tax_year(self):
today = date.today()
month = today.month
year = today.year
if month < 7:
return year - 2
return year - 1

def _get_status(self, validated_data):
application_type = validated_data["application_type"]
# TODO use enum type here like status.
Expand All @@ -63,6 +69,53 @@ def _get_status(self, validated_data):
return GoElectricRebateApplication.Status.SUBMITTED


class ApplicationFormCreateSerializerBCSC(ApplicationFormCreateSerializer):
class Meta(ApplicationFormCreateSerializer.Meta):
exclude = [
"last_name",
"first_name",
"middle_names",
"date_of_birth",
"address",
"city",
"postal_code",
"doc1",
"doc2",
] + ApplicationFormCreateSerializer.Meta.exclude

def create(self, validated_data):
request = self.context["request"]
user = request.user
spouse_email = request.data.get("spouse_email")

obj = GoElectricRebateApplication.objects.create(
sin=validated_data["sin"],
status=self._get_status(validated_data),
email=validated_data["email"],
drivers_licence=validated_data["drivers_licence"],
last_name=user.last_name,
first_name=user.first_name,
date_of_birth=user.date_of_birth,
address=user.street_address,
city=user.locality,
postal_code=user.postal_code,
tax_year=self._get_tax_year(),
application_type=validated_data["application_type"],
spouse_email=spouse_email,
user=user,
consent_personal=validated_data["consent_personal"],
consent_tax=validated_data["consent_tax"],
)
return obj

def _get_status(self, validated_data):
application_type = validated_data["application_type"]
# TODO use enum type here like status.
if application_type == "household":
return GoElectricRebateApplication.Status.HOUSEHOLD_INITIATED
return GoElectricRebateApplication.Status.VERIFIED


class ApplicationFormSerializer(ModelSerializer):
sin = SerializerMethodField()

Expand All @@ -87,6 +140,8 @@ class Meta:
"consent_personal",
"consent_tax",
"created",
"email",
"drivers_licence",
)


Expand Down
Loading

0 comments on commit 7ab9c15

Please sign in to comment.