Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
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
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,10 +322,9 @@
}
%}

{# {% 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,
Expand Down