Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"asuntomyynti/react": "1.4.7b",
"asuntomyynti/react": "1.4.9b",
"composer/installers": "^2.0",
"cweagans/composer-patches": "^1.7.3",
"dinbror/blazy": "^1.8",
Expand Down Expand Up @@ -186,9 +186,9 @@
"type": "package",
"package": {
"name": "asuntomyynti/react",
"version": "1.4.7b",
"version": "1.4.9b",
"dist": {
"url": "https://github.com/City-of-Helsinki/asuntomyynti-react/releases/download/v1.4.7b/asuntomyynti-react-1.4.7b.zip",
"url": "https://github.com/City-of-Helsinki/asuntomyynti-react/releases/download/v1.4.9b/asuntomyynti-react-1.4.9b.zip",
"type": "zip"
}
}
Expand Down
4 changes: 2 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions public/modules/custom/asu_api/asu_api.module
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function asu_api_get_apartment_status_request_cron() {
return;
}

$free_states = ['for_sale', 'free_for_reservations'];
$free_states = ['for_sale', 'free_for_reservations', 'reserved', 'reserved_haso'];

foreach ($nids as $nid) {
/** @var \Drupal\node\Entity\Node $node */
Expand Down Expand Up @@ -139,7 +139,7 @@ function asu_api_get_apartment_status_request_cron() {
$dirty = TRUE;
}
}
elseif ($current === 'sold' && in_array($new, $free_states, TRUE)) {
elseif (in_array($new, $free_states, TRUE)) {
if (!$node->isPublished()) {
$node->setPublished(TRUE);
$dirty = TRUE;
Expand Down
20 changes: 18 additions & 2 deletions public/modules/custom/asu_application/src/Form/ApplicationForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,15 @@ public function buildForm(array $form, FormStateInterface $form_state) {
array_push($limit, ['reserved', 'reserved_haso']);
}

// Dont allow users who have a reservation with the state
// 'offered', 'offer_accepted' or 'sold' on the project to apply.
// This shouldn't normally be shown except if the user uses
// the application/add/<type>/<project> link directly.
if ($project->getUserHasReservedOrSoldApartments($this->currentUser->id())) {
$this->messenger()->addError($this->t('You already have an offer or have been sold an apartment in this project and cannot submit a new application.'));
return new RedirectResponse($form['#project_url']->toString());
}

if (!$project_data = $this->getApartments($project, $limit)) {
$this->logger('asu_application')->critical('User tried to access nonexistent project of id ' . $project_id);
$this->messenger()->addMessage($this->t('Unfortunately the project you are trying to apply for is unavailable.'));
Expand Down Expand Up @@ -318,7 +327,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
$form['actions']['draft'] = [
'#type' => 'submit',
'#value' => $this->t('Save as a draft'),
'#attributes' => ['class' => ['hds-button--secondary']],
'#attributes' => ['class' => ['hds-button--secondary application-as-draft-button']],
'#limit_validation_errors' => [],
'#name' => 'submit-draft',
'#submit' => ['::submitDraft'],
Expand Down Expand Up @@ -525,6 +534,8 @@ public function save(array $form, FormStateInterface $form_state) {
/**
* Handle saving the form values.
*
* Deletes old application.
*
* @param array $form
* Form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
Expand All @@ -539,7 +550,12 @@ private function doSave(array $form, FormStateInterface $form_state, $errors = T
$oldBackendId = $this->entity->get('field_backend_id')->value ?? NULL;
$confirmDeletion = $form_state->getValue('confirm_application_deletion') ?? 'NOT SET';

if ($oldBackendId && $confirmDeletion == '1') {
$project_id = $this->entity->get('project_id')->value;
$project = $this->entityTypeManager->getStorage('node')->load($project_id);
$canApplyAfterwards = $project->get('field_can_apply_afterwards')->value;

// Applications made after shouldn't be deleted.
if ($oldBackendId && $confirmDeletion == '1' && !$canApplyAfterwards) {
try {
$user = \Drupal::entityTypeManager()->getStorage('user')->load(\Drupal::currentUser()->id());
\Drupal::service('asu_api.backendapi')->deleteApplication($user, $oldBackendId);
Expand Down
54 changes: 53 additions & 1 deletion public/modules/custom/asu_content/src/Entity/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Drupal\node\Entity\Node;
use Drupal\user\UserInterface;
use Drupal\user\Entity\User;
use Drupal\asu_api\Api\BackendApi\Request\ApplicationLotteryResult;

/**
* Class for node's project bundle.
Expand Down Expand Up @@ -70,7 +72,7 @@ public function getCanApplyAfterwards(): string {
if ($field_can_apply_afterwards->isEmpty()) {
return "";
}
\Drupal::logger('asu_application')->info("field_can_apply_afterwards: " . $field_can_apply_afterwards->value);

return $field_can_apply_afterwards->value;
}

Expand Down Expand Up @@ -163,6 +165,56 @@ public function isArchievable(): bool {
return TRUE;
}

/**
* Get reservations the given user has for the project's apartments.
*
* @param int $userId
* Id of the user to check.
*
* @return array
* reservations
*/
public function getUserReservations($userId): array {
$user = User::load(\Drupal::currentUser()->id());

// Fetch reservations for this project.
$request = new ApplicationLotteryResult($this->uuid());
$request->setSender($user);
$backendApi = \Drupal::service('asu_api.backendapi');

$userReservations = $backendApi
->send($request)
->getContent();

return $userReservations;
}

/**
* Checks if the given user has a reservation with the state 'offered'.
*
* 'offer_accepted' or 'sold' on the project.
*
* @param int $userId
* Id of the user to check.
*
* @return bool
* If user has a reservation with those states.
*/
public function getUserHasReservedOrSoldApartments($userId): bool {
$userHasReservedOrSoldApartment = FALSE;
$userReservations = $this->getUserReservations($userId);
$states = ['offered', 'offer_accepted', 'sold'];

// phpcs:ignore
foreach ($userReservations as $key => $reservation) {

if (in_array($reservation['state'], $states)) {
$userHasReservedOrSoldApartment = TRUE;
}
}
return $userHasReservedOrSoldApartment;
}

/**
* Get project sales person information.
*
Expand Down
3 changes: 3 additions & 0 deletions public/modules/custom/asu_content/translations/fi.po
Original file line number Diff line number Diff line change
Expand Up @@ -43323,3 +43323,6 @@ msgid "Tunnistamo"
msgstr ""
msgid "Helsinki Logo"
msgstr "Helsingin kaupungin logo"

msgid "You already have an offer or have been sold an apartment in this project and cannot submit a new application."
msgstr "Sinulla on jo myyty tai tarjottu asunto tässä kohteessa etkä siksi voi tehdä uutta hakemusta."
36 changes: 35 additions & 1 deletion public/themes/custom/asuntotuotanto/asuntotuotanto.theme
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,12 @@ function asuntotuotanto_preprocess_views_view(&$variables) {
}

/**
* Passes variables to project-apartments-listing.html.twig.
*
* Implements hook_preprocess_HOOK().
*/
function asuntotuotanto_preprocess_views_view_table(&$variables) {

if ($variables['view']->id() === 'project_apartments_listing') {

$results = $variables['result'];
Expand All @@ -251,6 +254,14 @@ function asuntotuotanto_preprocess_views_view_table(&$variables) {
$variables['header']['field_debt_free_sales_price']['content'] = $price_title;
unset($variables['header']['field_release_payment']);

$userHasReservedOrSoldApartment = FALSE;
if (\Drupal::currentUser()->isAuthenticated()) {
// Check if user has offered, offer_accepted or sold reservations.
$userHasReservedOrSoldApartment = $project->getUserHasReservedOrSoldApartments(
\Drupal::currentUser()->id()
);
}

foreach ($results as $key => $row) {
/** @var \Drupal\asu_content\Entity\Apartment $entity */
$apartment = $row->_entity;
Expand Down Expand Up @@ -282,6 +293,7 @@ function asuntotuotanto_preprocess_views_view_table(&$variables) {
$variables['rows'][$key]['application_url_title'] = $apartment->getApplicationUrlTitle();
$variables['rows'][$key]['is_free'] = $apartment->isFree();
$variables['rows'][$key]['can_apply_afterwards'] = $project->getCanApplyAfterwards();
$variables['rows'][$key]['user_has_reserved_or_sold_apartment'] = $userHasReservedOrSoldApartment;
}

usort($variables['rows'], function ($a, $b) {
Expand Down Expand Up @@ -589,6 +601,14 @@ function asuntotuotanto_preprocess_node(&$variables) {
);
}

$userHasReservedOrSoldApartment = FALSE;
if (\Drupal::currentUser()->isAuthenticated()) {
// Check if user has offered, offer_accepted or sold reservations.
$userHasReservedOrSoldApartment = $project->getUserHasReservedOrSoldApartments(
\Drupal::currentUser()->id()
);
}

if (!empty($node->field_street_address->value)) {
$street_address_splitted = split_address_line($node->field_street_address->value);

Expand Down Expand Up @@ -618,6 +638,9 @@ function asuntotuotanto_preprocess_node(&$variables) {
$variables['estimated_completion_date'] = $estimated_completion_date;
$variables['is_application_period_active'] = $is_application_period_active;
$variables['project_type'] = $project_type;
// No idea why, but shows up as null if it has.
// The more sensible name of 'user_has_reserved_or_sold_apartment'.
$variables['current_user_has_reserved_or_sold_apartment'] = $userHasReservedOrSoldApartment;
$variables['apartment_prices'] = $prices_string;
break;

Expand Down Expand Up @@ -768,6 +791,14 @@ function asuntotuotanto_preprocess_node(&$variables) {
}
}

$userHasReservedOrSoldApartment = FALSE;
if (\Drupal::currentUser()->isAuthenticated()) {
// Check if user has offered, offer_accepted or sold reservations.
$userHasReservedOrSoldApartment = $project->getUserHasReservedOrSoldApartments(
\Drupal::currentUser()->id()
);
}

$street_address = $project->get('field_street_address')->value ?? NULL;
$postal_code = $project->get('field_postal_code')->value ?? NULL;
$city = $project->get('field_city')->value ?? NULL;
Expand Down Expand Up @@ -819,6 +850,7 @@ function asuntotuotanto_preprocess_node(&$variables) {
$variables['field_parking_fee'] = $apartment->get('field_parking_fee')->getValue()[0]['value'] ?? NULL;
$variables['field_parking_fee_explanation'] = $apartment->get('field_parking_fee_explanation')->getValue()[0]['value'] ?? NULL;
$variables['field_other_fees'] = $apartment->get('field_other_fees')->getValue()[0]['value'] ?? NULL;
$variables['current_user_has_reserved_or_sold_apartment'] = $userHasReservedOrSoldApartment;
}
break;
}
Expand Down Expand Up @@ -1017,7 +1049,9 @@ function get_project_apartment_teaser_values($project_id) {
$values['project_ownership_type'] = $project->field_ownership_type->entity ? $project->field_ownership_type->entity->name->value : '';
$values['project_district'] = $project->field_district->entity ? $project->field_district->entity->name->value : '';
$values['project_main_image_url'] = isset($project->field_main_image[0]) ? \Drupal::service('file_url_generator')->generateAbsoluteString($project->field_main_image[0]->entity->getFileUri()) : '';
$values['can_apply_afterwards'] = $project->getCanApplyAfterwards();
if ($project) {
$values['can_apply_afterwards'] = $project->get('field_can_apply_afterwards')->value;
}

foreach ($fields as $key => $field) {
if ($project && $project->hasField($field)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,8 @@ line-height: $lineheight-m;
background-color: transparent;
}
}

.application-as-draft-button {
opacity: 0.75;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,24 +189,27 @@
</h2>
{% endif %}
</div>

<div class="apartment__header-section apartment__header-section--actions {{ is_application_period_active or can_apply_afterwards ? 'is-application-period-active' }}">
{% if current_user_has_reserved_or_sold_apartment == FALSE %}
{% if is_application_period_active %}
{% include '@asuntotuotanto/button/button.html.twig' with {
type: 'primary',
disabled: false,
label: 'Create an application'|t,
href: application_url
}
%}
{% elseif can_apply_afterwards == 1 %}
{% include '@asuntotuotanto/button/button.html.twig' with {
type: 'primary',
disabled: false,
label: 'Create an after-application'|t,
href: application_url
}
%}
{% endif %}
%}
{% elseif can_apply_afterwards == 1 %}
{% include '@asuntotuotanto/button/button.html.twig' with {
type: 'primary',
disabled: false,
label: 'Create an after-application'|t,
href: application_url
}
%}
{% endif %}
{% endif %}
<p class="apartment__application-information">
{% if (is_application_period_in_the_past is same as(false)) and (application_start_time != null and application_end_time != null) %}
{% trans %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@
#}

{{ attach_library('asuntotuotanto/sticky-navigation') }}
{% if current_user_has_reserved_or_sold_apartment %}
<section data-drupal-messages="" aria-label="Notification" type="button" class="hds-notification hds-notification--alert">
<div class="hds-notification__content">
<div class="hds-notification__label" role="heading" aria-level="2">
<span class="hds-icon hds-icon--alert-circle-fill" aria-hidden="true"></span>
<span>{% trans %}Varoitusviesti{% endtrans %}</span>
</div>
<div class="hds-notification__body">
{% trans %}Sinulla on jo myyty tai tarjottu asunto tässä kohteessa etkä siksi voi tehdä uutta hakemusta.{% endtrans %}
</div>
</div>
</section>
{% endif %}

{%
set classes = [
Expand All @@ -83,7 +96,6 @@
'project'
]
%}

{% set images = content.field_images %}
{% set district = content.field_district.0 %}
{% set street_address = content.field_street_address.0['#context']['value'] %}
Expand Down Expand Up @@ -254,6 +266,7 @@
Project description
{% endtrans %}
</h2>

<div class="project__project-description">{{ project_description|raw }}</div>
{% if sales_email %}
<div class="project-contact">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
sticky ? 'sticky-enabled',
]
%}

{# === Pre-pass: single calculation for mobile + desktop to avoid duplicating code === #}
{% set _computed = [] %}
{% for row in rows %}
Expand Down Expand Up @@ -279,6 +278,7 @@
{% set application_url_title = row.application_url_title %}
{% set can_apply_afterwards = row.can_apply_afterwards %}
{% set is_free = row.is_free %}
{% set user_has_reserved_or_sold_apartment = row.user_has_reserved_or_sold_apartment %}

{# pre-calculated values #}
{% set comp = _computed[loop.index0] %}
Expand Down Expand Up @@ -322,17 +322,16 @@
}
%}

{# {% if (is_application_period_active or (is_free or can_apply_afterwards)) %}
{% if (is_application_period_active or (is_free or can_apply_afterwards)) and not user_has_reserved_or_sold_apartment %}
{% include '@asuntotuotanto/button/button.html.twig' with {
type: 'primary',
disabled: false,
size: 'small',
label: can_apply_afterwards ? 'Create an after-application'|t : application_url_title|t,
href: application_url,
aria_label: 'Create an application'|t ~ ', ' ~ 'apartment'|t ~ ' ' ~ apartment_number
}
%}
{% endif %} #}
{% endif %}
</td>
</tr>
{% endfor %}
Expand Down