Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HL-897, HL-943, HL-942, HL-977: New terms application forms #2286

Merged
merged 26 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
dbb987e
feat: new benefit terms modifications (handler)
mjturt Sep 7, 2023
715a5d3
feat: new subsidy options
mjturt Sep 8, 2023
60bf182
feat: continue new terms changes
mjturt Sep 8, 2023
468f4f1
feat: fix date inputs
mjturt Sep 13, 2023
805856a
fix: wrong i18n import and usage of static props errored in nextjs co…
sirtawast Sep 5, 2023
662ca35
fix: koros id SSR / client mismatch; use correct bg color for footer
sirtawast Sep 5, 2023
4c5cc67
feat: add font weight and heading level prop to form section
sirtawast Sep 5, 2023
d2ccff2
feat: restructure application step 1
sirtawast Sep 5, 2023
6c4a9fd
docs: add some notes to .env example
sirtawast Sep 7, 2023
972f703
fix: de_minimis_aid can be either False or None
sirtawast Sep 8, 2023
ad8b312
feat!: restructure frontend of application step 2
sirtawast Sep 13, 2023
80f59fd
refactor!: only use one benefit type; pay_subsidy_granted as string
sirtawast Sep 13, 2023
09e39ae
refactor: localization update per new translations
JanneJuhola Sep 15, 2023
9ab6357
feat: use env to set TestCafe timeouts for local testing
sirtawast Sep 14, 2023
d66bed3
refactor: browser tests are on par with step 1 and 2 changes
sirtawast Sep 14, 2023
f3635a9
refactor: backend tests compatible with pay_subsidy_granted type change
sirtawast Sep 15, 2023
052a329
feat: merge 943 and companysection
mjturt Sep 19, 2023
a2c9ea3
feat: first handler app with new terms
mjturt Sep 20, 2023
86bd6ca
feat!: database migration to new terms
mjturt Sep 21, 2023
0035a83
fix: correct translations
mjturt Sep 21, 2023
9dcdce3
fix: linter
mjturt Sep 21, 2023
932d53f
fix: remove employee phone_number test
sirtawast Sep 22, 2023
638f841
fix: lint, ts, i18n
sirtawast Sep 22, 2023
502029e
fix: skip flaking ahjo test
sirtawast Sep 22, 2023
3d6850a
fix: merged feature backend tests
sirtawast Sep 22, 2023
271c9c5
fix: bugs related to step 2
mjturt Sep 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.benefit-backend.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ CORS_ALLOW_ALL_ORIGINS=1
# Debugging options
#
# if changing DUMMY_COMPANY_FORM_CODE, also set NEXT_PUBLIC_MOCK_FLAG=1
# DUMMY_COMPANY_FORM_CODE=16
# DUMMY_COMPANY_FORM_CODE=16 # or 29 for association (requires db flush and compose down & up)
NEXT_PUBLIC_MOCK_FLAG=1
DISABLE_TOS_APPROVAL_CHECK=1

Expand Down
66 changes: 51 additions & 15 deletions backend/benefit/applications/api/v1/serializers/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
AttachmentType,
BenefitType,
OrganizationType,
PaySubsidyGranted,
)
from applications.models import (
Application,
Expand Down Expand Up @@ -657,7 +658,7 @@ def _validate_de_minimis_aid_set(
if (
OrganizationType.resolve_organization_type(company.company_form_code)
== OrganizationType.ASSOCIATION
and de_minimis_aid is not None
and de_minimis_aid not in [None, False]
and not association_has_business_activities
):
raise serializers.ValidationError(
Expand Down Expand Up @@ -752,11 +753,7 @@ def _validate_co_operation_negotiations(
def _validate_pay_subsidy(
self, pay_subsidy_granted, pay_subsidy_percent, additional_pay_subsidy_percent
):
if pay_subsidy_granted and pay_subsidy_percent is None:
raise serializers.ValidationError(
{"pay_subsidy_percent": _("Pay subsidy percent required")}
)
if not pay_subsidy_granted:
if pay_subsidy_granted == PaySubsidyGranted.NOT_GRANTED:
for key in ["pay_subsidy_percent", "additional_pay_subsidy_percent"]:
if locals()[key] is not None:
raise serializers.ValidationError(
Expand Down Expand Up @@ -813,7 +810,10 @@ def _validate_non_draft_required_fields(self, data):

# if pay_subsidy_granted is selected, then the applicant needs to also select if
# it's an apprenticeship_program or not
if data["pay_subsidy_granted"]:
if data["pay_subsidy_granted"] in [
PaySubsidyGranted.GRANTED_AGED,
PaySubsidyGranted.GRANTED,
]:
required_fields.append("apprenticeship_program")

for field_name in required_fields:
Expand Down Expand Up @@ -862,7 +862,7 @@ def _validate_benefit_type(
apprenticeship_program,
pay_subsidy_granted,
):
if benefit_type == "":
if benefit_type == BenefitType.SALARY_BENEFIT or benefit_type == "":
return
if (
benefit_type
Expand All @@ -877,6 +877,36 @@ def _validate_benefit_type(
{"benefit_type": _("This benefit type can not be selected")}
)

def _validate_apprenticeship_program(
self, apprenticeship_program, pay_subsidy_granted, status
):
if status == ApplicationStatus.DRAFT:
return
if (
pay_subsidy_granted == PaySubsidyGranted.NOT_GRANTED
and apprenticeship_program is not None
):
raise serializers.ValidationError(
{
"apprenticeship_program": _(
"Apprenticeship program can not be selected if there is no granted pay subsidy"
)
}
)

if (
pay_subsidy_granted
in [PaySubsidyGranted.GRANTED_AGED, PaySubsidyGranted.GRANTED]
and apprenticeship_program is None
):
raise serializers.ValidationError(
{
"apprenticeship_program": _(
"Apprenticeship program has to be yes or no if there is a granted pay subsidy"
)
}
)

@staticmethod
def _get_available_benefit_types(
company,
Expand All @@ -888,25 +918,26 @@ def _get_available_benefit_types(
Make the logic of determining available benefit types available both for generating the list of
benefit types and validating the incoming data
"""

if (
OrganizationType.resolve_organization_type(company.company_form_code)
== OrganizationType.ASSOCIATION
and not association_has_business_activities
):
benefit_types = [BenefitType.SALARY_BENEFIT] if pay_subsidy_granted else []
benefit_types = [
BenefitType.SALARY_BENEFIT,
]
else:
if apprenticeship_program:
benefit_types = [BenefitType.EMPLOYMENT_BENEFIT]
if pay_subsidy_granted:
benefit_types.append(BenefitType.SALARY_BENEFIT)
benefit_types = [
BenefitType.EMPLOYMENT_BENEFIT,
BenefitType.SALARY_BENEFIT,
]
else:
benefit_types = [
BenefitType.COMMISSION_BENEFIT,
BenefitType.EMPLOYMENT_BENEFIT,
BenefitType.SALARY_BENEFIT,
]
if pay_subsidy_granted:
benefit_types.append(BenefitType.SALARY_BENEFIT)
return benefit_types

def _handle_breaking_changes(self, company, data):
Expand Down Expand Up @@ -1003,6 +1034,11 @@ def validate(self, data):
data.get("apprenticeship_program"),
data.get("pay_subsidy_granted"),
)
self._validate_apprenticeship_program(
data.get("apprenticeship_program"),
data.get("pay_subsidy_granted"),
data.get("status"),
)
self._validate_non_draft_required_fields(data)
return data

Expand Down
9 changes: 0 additions & 9 deletions backend/benefit/applications/api/v1/serializers/employee.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from stdnum.fi import hetu

from applications.models import Employee
from common.utils import PhoneNumberField
from helsinkibenefit.settings import MINIMUM_WORKING_HOURS_PER_WEEK


Expand All @@ -13,21 +12,13 @@ class EmployeeSerializer(serializers.ModelSerializer):
Employee objects are meant to be edited together with their Application object.
"""

phone_number = PhoneNumberField(
allow_blank=True,
help_text=(
"Employee phone number normalized (start with zero, without country code)"
),
)

class Meta:
model = Employee
fields = [
"id",
"first_name",
"last_name",
"social_security_number",
"phone_number",
"email",
"employee_language",
"job_title",
Expand Down
6 changes: 6 additions & 0 deletions backend/benefit/applications/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,9 @@ class AhjoDecision(models.TextChoices):
class ApplicationOrigin(models.TextChoices):
HANDLER = "handler", _("Handler")
APPLICANT = "applicant", _("Applicant")


class PaySubsidyGranted(models.TextChoices):
GRANTED = "granted", _("Pay subsidy granted (default)")
GRANTED_AGED = "granted_aged", _("Pay subsidy granted (aged)")
NOT_GRANTED = "not_granted", _("No granted pay subsidy")
78 changes: 78 additions & 0 deletions backend/benefit/applications/migrations/0040_pay_subsidy_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Generated by Django 3.2.18 on 2023-09-21 10:39

from django.db import migrations, models
from applications.enums import PaySubsidyGranted


def migrate_pay_subsidy_types(apps, _):
def _migrate_pay_subsidy_types(applications):
for app in applications.objects.all():
app.pay_subsidy_granted = (
PaySubsidyGranted.GRANTED
if app.pay_subsidy_granted_old
else PaySubsidyGranted.NOT_GRANTED
)
app.save()

application = apps.get_model("applications", "Application")
hist_application = apps.get_model("applications", "HistoricalApplication")
_migrate_pay_subsidy_types(application)
_migrate_pay_subsidy_types(hist_application)


class Migration(migrations.Migration):
dependencies = [
("applications", "0039_alter_paysubsidy_percentages"),
]

operations = [
migrations.RenameField(
model_name="application",
old_name="pay_subsidy_granted",
new_name="pay_subsidy_granted_old",
),
migrations.RenameField(
model_name="historicalapplication",
old_name="pay_subsidy_granted",
new_name="pay_subsidy_granted_old",
),
migrations.AddField(
model_name="application",
name="pay_subsidy_granted",
field=models.CharField(
blank=True,
choices=[
("granted", "Pay subsidy granted (default)"),
("granted_aged", "Pay subsidy granted (aged)"),
("not_granted", "No granted pay subsidy"),
],
max_length=128,
null=True,
),
),
migrations.AddField(
model_name="historicalapplication",
name="pay_subsidy_granted",
field=models.CharField(
blank=True,
choices=[
("granted", "Pay subsidy granted (default)"),
("granted_aged", "Pay subsidy granted (aged)"),
("not_granted", "No granted pay subsidy"),
],
max_length=128,
null=True,
),
),
migrations.RunPython(
migrate_pay_subsidy_types, reverse_code=migrations.RunPython.noop
),
migrations.RemoveField(
model_name="application",
name="pay_subsidy_granted_old",
),
migrations.RemoveField(
model_name="historicalapplication",
name="pay_subsidy_granted_old",
),
]
12 changes: 10 additions & 2 deletions backend/benefit/applications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
ApplicationStep,
AttachmentType,
BenefitType,
PaySubsidyGranted,
)
from applications.exceptions import (
BatchCompletionDecisionDateError,
Expand Down Expand Up @@ -255,7 +256,12 @@ class Application(UUIDModel, TimeStampedModel, DurationMixin):
blank=True,
)

pay_subsidy_granted = models.BooleanField(null=True)
pay_subsidy_granted = models.CharField(
choices=PaySubsidyGranted.choices,
max_length=128,
null=True,
blank=True,
)

# The PaySubsidy model stores the values entered by handlers for the calculation.
# This field is filled by the applicant.
Expand Down Expand Up @@ -306,7 +312,9 @@ def get_available_benefit_types(self):
self.is_association_application()
and not self.association_has_business_activities
):
return [BenefitType.SALARY_BENEFIT]
return [
BenefitType.SALARY_BENEFIT,
]
else:
return [
BenefitType.SALARY_BENEFIT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def CSV_COLUMNS(self):
),
CsvColumn("YT-neuvottelut?", "co_operation_negotiations", format_bool),
CsvColumn("YT-neuvottelut/tiedot", "co_operation_negotiations_description"),
CsvColumn("Palkkatuki myönnetty?", "pay_subsidy_granted", format_bool),
CsvColumn("Palkkatuki myönnetty?", "pay_subsidy_granted", str),
csv_default_column("Palkkatukiprosentti", "pay_subsidy_percent"),
csv_default_column(
"Toinen palkkatukiprosentti", "additional_pay_subsidy_percent"
Expand Down
11 changes: 8 additions & 3 deletions backend/benefit/applications/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@

import factory

from applications.enums import ApplicationStatus, ApplicationStep, BenefitType
from applications.enums import (
ApplicationStatus,
ApplicationStep,
BenefitType,
PaySubsidyGranted,
)
from applications.models import (
AhjoDecision,
Application,
Expand Down Expand Up @@ -97,12 +102,12 @@ class ApplicationFactory(factory.django.DjangoModelFactory):
co_operation_negotiations_description = factory.Maybe(
"co_operation_negotiations", factory.Faker("paragraph"), ""
)
pay_subsidy_granted = False
pay_subsidy_granted = PaySubsidyGranted.NOT_GRANTED
pay_subsidy_percent = None

additional_pay_subsidy_percent = None

apprenticeship_program = factory.Faker("boolean")
apprenticeship_program = None
archived = False
application_step = ApplicationStep.STEP_1
benefit_type = BenefitType.EMPLOYMENT_BENEFIT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ def test_generate_composed_template_html(mock_pdf_convert):
)


@pytest.mark.skip(reason="flaking because of unique username conflict")
def test_export_application_batch(application_batch):
application_batch.applications.add(
DecidedApplicationFactory.create(
Expand Down
Loading
Loading