Skip to content

Commit

Permalink
Merge branch 'develop' into helsinkilisa_review_environment
Browse files Browse the repository at this point in the history
  • Loading branch information
terovirtanen committed Jul 25, 2023
2 parents 1a7deab + b012ab4 commit 94f44c5
Show file tree
Hide file tree
Showing 170 changed files with 10,933 additions and 1,717 deletions.
12 changes: 8 additions & 4 deletions .env.benefit-backend.example
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,18 @@ MEDIA_ROOT=/app/var/media
CSRF_COOKIE_NAME=yjdhcsrftoken
CSRF_TRUSTED_ORIGINS="localhost:3000,localhost:3100"

YRTTI_TIMEOUT=30
YRTTI_BASIC_INFO_PATH=https://yrtti-integration-test.agw.arodevtest.hel.fi/api/BasicInfo
SERVICE_BUS_INFO_PATH=https://ytj-integration-test.agw.arodevtest.hel.fi/api/GetCompany
YRTTI_BASE_URL=https://yrtti-integration-test.agw.arodevtest.hel.fi/api
YRTTI_AUTH_PASSWORD=
YRTTI_AUTH_USERNAME=helsinkilisatest
YRTTI_TIMEOUT=30
YRTTI_SEARCH_LIMIT=10
YRTTI_DISABLE=0

SERVICE_BUS_BASE_URL=https://ytj-integration-test.agw.arodevtest.hel.fi/api
SERVICE_BUS_AUTH_PASSWORD=
SERVICE_BUS_AUTH_USERNAME=helsinkilisatest
SERVICE_BUS_TIMEOUT=30
SERVICE_BUS_SEARCH_LIMIT=10

SEND_AUDIT_LOG=0

Expand Down Expand Up @@ -104,4 +108,4 @@ USE_S3=1
S3_ENDPOINT_URL="http://minio:9000"
S3_ACCESS_KEY_ID=minio-root
S3_SECRET_ACCESS_KEY=minio-pass
S3_STORAGE_BUCKET_NAME=local-s3-bucket
S3_STORAGE_BUCKET_NAME=local-s3-bucket
58 changes: 39 additions & 19 deletions backend/benefit/applications/api/v1/application_batch_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def assign_applications(self, request):
def create_application_batch_by_ids(app_status, apps):
if apps:
batch = ApplicationBatch.objects.create(
proposal_for_decision=app_status
proposal_for_decision=app_status, handler=request.user
)
return batch

Expand All @@ -209,16 +209,23 @@ def create_application_batch_by_ids(app_status, apps):
)

# Try finding an existing batch
batch = (
ApplicationBatch.objects.filter(
status=ApplicationBatchStatus.DRAFT, proposal_for_decision=app_status
).first()
) or create_application_batch_by_ids(
app_status,
apps,
)
try:
batch = (
ApplicationBatch.objects.filter(
status=ApplicationBatchStatus.DRAFT,
proposal_for_decision=app_status,
).first()
) or create_application_batch_by_ids(
app_status,
apps,
)
except BatchTooManyDraftsError:
return Response(
{"errorKey": "batchInvalidDraftAlreadyExists"},
status=status.HTTP_400_BAD_REQUEST,
)

if batch:
if batch and batch.status == ApplicationBatchStatus.DRAFT:
apps.update(batch=batch)
batch = ApplicationBatchSerializer(batch)
return Response(batch.data, status=status.HTTP_200_OK)
Expand All @@ -239,16 +246,22 @@ def deassign_applications(self, request, pk=None):
application_ids = request.data.get("application_ids")
batch = self.get_batch(pk)

apps = Application.objects.filter(
deassign_apps = Application.objects.filter(
batch=batch,
pk__in=application_ids,
status__in=[ApplicationStatus.ACCEPTED, ApplicationStatus.REJECTED],
batch=batch,
)
if apps:
for app in apps:
if deassign_apps:
for app in deassign_apps:
app.batch = None
app.save()
return Response(status=status.HTTP_200_OK)
remaining_apps = Application.objects.filter(batch=batch)
if len(remaining_apps) == 0:
batch.delete()
return Response(
{"remainingApps": len(remaining_apps)}, status=status.HTTP_200_OK
)

return Response(
{"detail": "Applications were not applicable to be detached."},
status=status.HTTP_404_NOT_FOUND,
Expand All @@ -264,23 +277,29 @@ def status(self, request, pk=None):
batch = self.get_batch(pk)
if new_status not in [
ApplicationBatchStatus.DRAFT,
ApplicationBatchStatus.AHJO_REPORT_CREATED,
ApplicationBatchStatus.AWAITING_AHJO_DECISION,
ApplicationBatchStatus.DECIDED_ACCEPTED,
ApplicationBatchStatus.DECIDED_REJECTED,
ApplicationBatchStatus.SENT_TO_TALPA,
]:
return Response(status=status.HTTP_400_BAD_REQUEST)

if new_status in [
ApplicationBatchStatus.DECIDED_ACCEPTED,
ApplicationBatchStatus.DECIDED_REJECTED,
]:
# Archive all applications if this batch will be completed
Application.objects.filter(batch=batch).update(archived=True)

# Patch all required fields for batch completion
# Patch all required fields after batch inspection
for key in request.data:
setattr(batch, key, request.data.get(key))

if new_status in [
ApplicationBatchStatus.SENT_TO_TALPA,
]:
# Archive all applications if this batch will be completed
Application.objects.filter(batch=batch).update(archived=True)

previous_status = batch.status
batch.status = new_status

try:
Expand Down Expand Up @@ -309,6 +328,7 @@ def status(self, request, pk=None):
{
"id": batch.id,
"status": batch.status,
"previousStatus": previous_status,
"decision": batch.proposal_for_decision,
},
status=status.HTTP_200_OK,
Expand Down
107 changes: 74 additions & 33 deletions backend/benefit/applications/api/v1/serializers/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
)
from applications.benefit_aggregation import get_former_benefit_info
from applications.enums import (
ApplicationOrigin,
ApplicationStatus,
AttachmentRequirement,
AttachmentType,
Expand Down Expand Up @@ -424,7 +425,14 @@ def get_applicant_terms_approval_needed(self, obj):

@extend_schema_field(TermsSerializer())
def get_applicant_terms_in_effect(self, obj):
terms = Terms.objects.get_terms_in_effect(TermsType.APPLICANT_TERMS)
terms_map = {
ApplicationOrigin.APPLICANT: TermsType.APPLICANT_TERMS,
ApplicationOrigin.HANDLER: TermsType.HANDLER_TERMS,
}
terms_type = terms_map.get(
ApplicationOrigin(obj.application_origin), ApplicationOrigin.APPLICANT
)
terms = Terms.objects.get_terms_in_effect(terms_type)
if terms:
# If given the request in context, DRF will output the URL for FileFields
context = {"request": self.context.get("request")}
Expand Down Expand Up @@ -532,6 +540,9 @@ def get_modified_at(self, obj):
return None
return obj.modified_at

def get_company_for_new_application(self, _):
raise NotImplementedError()

def _get_pay_subsidy_attachment_requirements(self, application):
req = []
if application.pay_subsidy_percent:
Expand All @@ -540,35 +551,58 @@ def _get_pay_subsidy_attachment_requirements(self, application):
)
return req

@staticmethod
def _get_handler_attachment_requirements(application):
if application.application_origin == ApplicationOrigin.HANDLER:
return [
(AttachmentType.FULL_APPLICATION, AttachmentRequirement.REQUIRED),
(AttachmentType.OTHER_ATTACHMENT, AttachmentRequirement.OPTIONAL),
]
return []

def get_attachment_requirements(self, obj):
if obj.apprenticeship_program:
return [
(AttachmentType.EMPLOYMENT_CONTRACT, AttachmentRequirement.REQUIRED),
(AttachmentType.EDUCATION_CONTRACT, AttachmentRequirement.REQUIRED),
(
AttachmentType.HELSINKI_BENEFIT_VOUCHER,
AttachmentRequirement.OPTIONAL,
),
] + self._get_pay_subsidy_attachment_requirements(obj)
return (
[
(
AttachmentType.EMPLOYMENT_CONTRACT,
AttachmentRequirement.REQUIRED,
),
(AttachmentType.EDUCATION_CONTRACT, AttachmentRequirement.REQUIRED),
(
AttachmentType.HELSINKI_BENEFIT_VOUCHER,
AttachmentRequirement.OPTIONAL,
),
]
+ self._get_pay_subsidy_attachment_requirements(obj)
+ self._get_handler_attachment_requirements(obj)
)
elif obj.benefit_type in [
BenefitType.EMPLOYMENT_BENEFIT,
BenefitType.SALARY_BENEFIT,
]:
return [
(AttachmentType.EMPLOYMENT_CONTRACT, AttachmentRequirement.REQUIRED),
(
AttachmentType.HELSINKI_BENEFIT_VOUCHER,
AttachmentRequirement.OPTIONAL,
),
] + self._get_pay_subsidy_attachment_requirements(obj)
return (
[
(
AttachmentType.EMPLOYMENT_CONTRACT,
AttachmentRequirement.REQUIRED,
),
(
AttachmentType.HELSINKI_BENEFIT_VOUCHER,
AttachmentRequirement.OPTIONAL,
),
]
+ self._get_pay_subsidy_attachment_requirements(obj)
+ self._get_handler_attachment_requirements(obj)
)
elif obj.benefit_type == BenefitType.COMMISSION_BENEFIT:
return [
(AttachmentType.COMMISSION_CONTRACT, AttachmentRequirement.REQUIRED),
(
AttachmentType.HELSINKI_BENEFIT_VOUCHER,
AttachmentRequirement.OPTIONAL,
),
]
] + self._get_handler_attachment_requirements(obj)
elif not obj.benefit_type:
# applicant has not selected the value yet
return []
Expand Down Expand Up @@ -1026,14 +1060,17 @@ def _validate_employee_consent(self, instance):
consent_count = instance.attachments.filter(
attachment_type=AttachmentType.EMPLOYEE_CONSENT
).count()
if consent_count == 0:
raise serializers.ValidationError(
_("Application does not have the employee consent attachment")
)
if consent_count > 1:
raise serializers.ValidationError(
_("Application cannot have more than one employee consent attachment")
)
if instance.application_origin == ApplicationOrigin.APPLICANT:
if consent_count == 0:
raise serializers.ValidationError(
_("Application does not have the employee consent attachment")
)
if consent_count > 1:
raise serializers.ValidationError(
_(
"Application cannot have more than one employee consent attachment"
)
)

def _update_applicant_terms_approval(self, instance, approve_terms):
if ApplicantTermsApproval.terms_approval_needed(instance):
Expand Down Expand Up @@ -1140,7 +1177,7 @@ def create(self, validated_data):
return application

def _update_or_create_employee(self, application, employee_data):
employee, created = Employee.objects.update_or_create(
employee, _ = Employee.objects.update_or_create(
application=application, defaults=employee_data
)
return employee
Expand Down Expand Up @@ -1225,7 +1262,7 @@ class ApplicantApplicationSerializer(BaseApplicationSerializer):
),
)

def get_company_for_new_application(self, validated_data):
def get_company_for_new_application(self, _):
"""
Company field is read_only. When creating a new application, assign company.
"""
Expand Down Expand Up @@ -1280,26 +1317,29 @@ class HandlerApplicationSerializer(BaseApplicationSerializer):
read_only=True, help_text="Application batch of this application, if any"
)

create_application_for_company = serializers.PrimaryKeyRelatedField(
write_only=True,
create_application_for_company = serializers.UUIDField(
read_only=True,
required=False,
queryset=Company.objects.all(),
help_text=(
"To be used when a logged-in application handler creates a new application"
" based on a paper applicationreceived via mail. Ordinary applicants can"
" only create applications for their own company."
),
)

def get_company_for_new_application(self, validated_data):
def get_company_for_new_application(self, _):
"""
Company field is read_only. When creating a new application, assign company.
"""
if not validated_data["create_application_for_company"]:
company_id = self.initial_data.get("create_application_for_company")
if not company_id:
raise BenefitAPIException(
_("create_application_for_company missing from request")
)
return Company.objects.get(validated_data["create_application_for_company"])
company = Company.objects.get(id=company_id)
if not company:
raise BenefitAPIException(_(f"company with id {company_id} not found"))
return company

handled_at = serializers.SerializerMethodField(
"get_handled_at",
Expand All @@ -1320,6 +1360,7 @@ class Meta(BaseApplicationSerializer.Meta):
"create_application_for_company",
"latest_decision_comment",
"handled_at",
"application_origin",
]
read_only_fields = BaseApplicationSerializer.Meta.read_only_fields + [
"latest_decision_comment",
Expand Down
15 changes: 15 additions & 0 deletions backend/benefit/applications/api/v1/serializers/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
)
from applications.enums import ApplicationBatchStatus, ApplicationStatus
from applications.models import Application, ApplicationBatch, Company, Employee
from users.api.v1.serializers import UserSerializer


class ApplicationBatchSerializer(serializers.ModelSerializer):
Expand All @@ -34,6 +35,14 @@ class ApplicationBatchSerializer(serializers.ModelSerializer):
help_text="Proposed decision for Ahjo",
)

handler = UserSerializer(
help_text=(
"The handler object, with fields, currently assigned to this calculation"
" and application (read-only)"
),
read_only=True,
)

class Meta:
model = ApplicationBatch
fields = [
Expand All @@ -47,7 +56,12 @@ class Meta:
"decision_date",
"expert_inspector_name",
"expert_inspector_email",
"expert_inspector_title",
"p2p_inspector_name",
"p2p_inspector_email",
"p2p_checker_name",
"created_at",
"handler",
]
read_only_fields = [
"created_at",
Expand Down Expand Up @@ -165,6 +179,7 @@ class Meta:
class BatchApplicationSerializer(ReadOnlySerializer):
company = BatchCompanySerializer(read_only=True)
employee = BatchEmployeeSerializer(read_only=True)

handled_at = serializers.SerializerMethodField(
"get_handled_at",
help_text=(
Expand Down
Loading

0 comments on commit 94f44c5

Please sign in to comment.