From 65fa55c852f86835b34864ea7a2b38210d995797 Mon Sep 17 00:00:00 2001 From: Mathieu Date: Sat, 25 May 2024 20:54:19 +0200 Subject: [PATCH] feat: Allow setting GK as parked --- .php-cs-fixer.php | 30 +-- .pre-commit-config.yaml | 2 +- .../040_Collectible/020_Moves.robot | 4 +- .../050_Parked/010_ManageFlag.robot | 92 ++++++++ .../030_Geokrety/050_Parked/020_Moves.robot | 71 +++++++ .../030_Geokrety/050_Parked/030_export.robot | 69 ++++++ .../030_Geokrety/050_Parked/040_export2.robot | 112 ++++++++++ .../030_Geokrety/050_Parked/050_ruchy.robot | 125 +++++++++++ .../030_Geokrety/050_Parked/__init__.robot | 2 + .../ressources/ComponentsLocator.robot | 2 + .../smarty/blocks/geokret/details.tpl | 4 +- .../extension/SmartyGeokretyExtension.php | 5 + .../app-templates/smarty/forms/geokret.tpl | 17 ++ .../js/moves/geokret_move.validation.tpl.js | 6 +- .../smarty/pages/geokret_create.tpl | 9 + .../app-templates/smarty/pages/help_api.tpl | 25 +++ .../Controller/Pages/BaseExportXML.php | 5 + .../GeoKrety/Controller/Pages/GeokretEdit.php | 17 +- .../Pages/GeokretSelectFromInventory.php | 2 +- .../GeoKrety/Controller/Pages/HallOfFame.php | 5 + .../Controller/Pages/LegacyRoutes.php | 1 + website/app/GeoKrety/Model/Geokret.php | 15 ++ .../app/GeoKrety/Model/GeokretWithDetails.php | 10 + .../GeoKrety/Service/Xml/GeokretyExport.php | 2 + .../GeoKrety/Service/Xml/GeokretyExport2.php | 4 + .../Service/Xml/GeokretyExport2Details.php | 3 + website/app/validators.php | 5 +- .../migrations/20240524085913_collectible.php | 200 ++++++++++++++++-- .../tests/test-30-moves-moved-on-datetime.sql | 19 +- website/db/tests/test-54-collectible.sql | 104 ++++----- website/db/tests/test-55-parked.sql | 57 +++++ 31 files changed, 918 insertions(+), 106 deletions(-) create mode 100644 tests-qa/acceptance/030_Geokrety/050_Parked/010_ManageFlag.robot create mode 100644 tests-qa/acceptance/030_Geokrety/050_Parked/020_Moves.robot create mode 100644 tests-qa/acceptance/030_Geokrety/050_Parked/030_export.robot create mode 100644 tests-qa/acceptance/030_Geokrety/050_Parked/040_export2.robot create mode 100644 tests-qa/acceptance/030_Geokrety/050_Parked/050_ruchy.robot create mode 100644 tests-qa/acceptance/030_Geokrety/050_Parked/__init__.robot create mode 100644 website/db/tests/test-55-parked.sql diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 74e2833f48..d05fac0a5f 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -12,21 +12,21 @@ // doc position_after_functions_and_oop_constructs: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/4e91f495a7ece1f2566feba2f07cc5824d68ec0b/README.rst $config = new PhpCsFixer\Config(); $config->setRules([ - '@Symfony' => true, - 'no_closing_tag' => true, - 'yoda_style' => false, - 'curly_braces_position' => [ - 'allow_single_line_anonymous_functions' => true, - 'functions_opening_brace' => 'same_line', - 'anonymous_functions_opening_brace' => 'same_line', - 'classes_opening_brace' => 'same_line', - 'anonymous_classes_opening_brace' => 'same_line', - ], - // 'statement_indentation' => false, - 'nullable_type_declaration_for_default_null_value' => [ - 'use_nullable_type_declaration' => true, - ], - ]) + '@Symfony' => true, + 'no_closing_tag' => true, + 'yoda_style' => false, + 'curly_braces_position' => [ + 'allow_single_line_anonymous_functions' => true, + 'functions_opening_brace' => 'same_line', + 'anonymous_functions_opening_brace' => 'same_line', + 'classes_opening_brace' => 'same_line', + 'anonymous_classes_opening_brace' => 'same_line', + ], + // 'statement_indentation' => false, + 'nullable_type_declaration_for_default_null_value' => [ + 'use_nullable_type_declaration' => true, + ], + ]) ->setFinder($finder); return $config; diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b540b215ed..52d6e53822 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - id: php-lint-all - id: php-cs-fixer files: \.(php)$ - args: [ "--config=.php-cs-fixer.php", "-q" ] + args: [ "--config=.php-cs-fixer.php", "-q", "--diff" ] - repo: https://github.com/IamTheFij/docker-pre-commit.git rev: v2.0.0 diff --git a/tests-qa/acceptance/030_Geokrety/040_Collectible/020_Moves.robot b/tests-qa/acceptance/030_Geokrety/040_Collectible/020_Moves.robot index 4397e494e5..ac2a18d51d 100644 --- a/tests-qa/acceptance/030_Geokrety/040_Collectible/020_Moves.robot +++ b/tests-qa/acceptance/030_Geokrety/040_Collectible/020_Moves.robot @@ -26,7 +26,7 @@ Ensure initial state: everything is shown Element Should Not Be Visible ${MOVE_LOG_TYPE_NOT_COLLECTIBLE_INFO} -Some logtype should be hidden for non-admin and non-holder +Some logtype should be hidden for non-owner and non-holder Sign In ${USER_1.name} Fast # Change collectible flag @@ -87,7 +87,7 @@ Some logtype should be hidden for owner Go To Move Input Text ${MOVE_TRACKING_CODE_INPUT} ${GEOKRETY_1.tc} Click Button And Check Panel Validation Has Success ${MOVE_TRACKING_CODE_NEXT_BUTTON} ${MOVE_TRACKING_CODE_PANEL} ${MOVE_LOG_TYPE_PANEL} - Element Should Be Enabled ${MOVE_LOG_TYPE_DROPPED_RADIO} + Element Should Be Disabled ${MOVE_LOG_TYPE_DROPPED_RADIO} Element Should Be Disabled ${MOVE_LOG_TYPE_GRABBED_RADIO} Element Should Be Disabled ${MOVE_LOG_TYPE_MEET_RADIO} Element Should Be Enabled ${MOVE_LOG_TYPE_DIPPED_RADIO} diff --git a/tests-qa/acceptance/030_Geokrety/050_Parked/010_ManageFlag.robot b/tests-qa/acceptance/030_Geokrety/050_Parked/010_ManageFlag.robot new file mode 100644 index 0000000000..c315f9f692 --- /dev/null +++ b/tests-qa/acceptance/030_Geokrety/050_Parked/010_ManageFlag.robot @@ -0,0 +1,92 @@ +*** Settings *** +Library RequestsLibrary +Resource ../../ressources/Authentication.robot +Resource ../../ressources/vars/Urls.robot +Resource ../../ressources/Moves.robot +Variables ../../ressources/vars/users.yml +Variables ../../ressources/vars/geokrety.yml +Variables ../../ressources/vars/moves.yml +Test Setup Test Setup + +*** Variables *** + +*** Test Cases *** + +Parked Happy Path + Sign In ${USER_1.name} Fast + + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Element Attribute Should Be ${GEOKRET_CREATE_COLLECTIBLE_CHECKBOX} disabled true + Element Attribute Should Be ${GEOKRET_CREATE_COLLECTIBLE_CHECKBOX} checked None + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + Element Should Contain ${GEOKRET_DETAILS_PARKED} Parked + Page Should Not Contain Element ${GEOKRET_DETAILS_COLLECTIBLE} + ${date1} = Browser.Get Element Attribute ${GEOKRET_DETAILS_PARKED} title + + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Unselect Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Element Attribute Should Be ${GEOKRET_CREATE_COLLECTIBLE_CHECKBOX} disabled None + Element Attribute Should Be ${GEOKRET_CREATE_COLLECTIBLE_CHECKBOX} checked true + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + Page Should Not Contain Element ${GEOKRET_DETAILS_COLLECTIBLE} + Page Should Not Contain Element ${GEOKRET_DETAILS_PARKED} + Page Should Not Contain Element ${GEOKRET_DETAILS_COLLECTIBLE} + + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + Element Should Contain ${GEOKRET_DETAILS_PARKED} Parked + Page Should Not Contain Element ${GEOKRET_DETAILS_COLLECTIBLE} + ${date2} = Browser.Get Element Attribute ${GEOKRET_DETAILS_PARKED} title + + Should Not Be Equal As Strings ${date1} ${date2} + +Changing other value should not change the parked date + Sign In ${USER_1.name} Fast + + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Input Text ${GEOKRET_CREATE_NAME_INPUT} GKNewName + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Input Text ${GEOKRET_CREATE_NAME_INPUT} GKNewName2 + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + + +Can be enabled only if owner is the holder + Sign In ${USER_1.name} Fast + + Post Move Fast &{MOVE_22} + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Page Should Not Contain Element ${GEOKRET_CREATE_PARKED_CHECKBOX} + + Post Move Fast &{MOVE_2} + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Page Should Contain Element ${GEOKRET_CREATE_PARKED_CHECKBOX} + + +*** Keywords *** + +Test Setup + Clear Database And Seed ${2} users + Seed ${1} geokrety owned by ${1} diff --git a/tests-qa/acceptance/030_Geokrety/050_Parked/020_Moves.robot b/tests-qa/acceptance/030_Geokrety/050_Parked/020_Moves.robot new file mode 100644 index 0000000000..6a7e437297 --- /dev/null +++ b/tests-qa/acceptance/030_Geokrety/050_Parked/020_Moves.robot @@ -0,0 +1,71 @@ +*** Settings *** +Library RequestsLibrary +Resource ../../ressources/Authentication.robot +Resource ../../ressources/vars/Urls.robot +Resource ../../ressources/Moves.robot +Variables ../../ressources/vars/users.yml +Variables ../../ressources/vars/geokrety.yml +Variables ../../ressources/vars/moves.yml +Test Setup Test Setup + +*** Variables *** + +*** Test Cases *** + +Some logtype should be hidden for non-owner + Sign In ${USER_1.name} Fast + + # Change collectible flag + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + Element Should Contain ${GEOKRET_DETAILS_PARKED} Parked + + # Only a limited number of move type are shown + Sign In ${USER_2.name} Fast + Go To Move + Input Text ${MOVE_TRACKING_CODE_INPUT} ${GEOKRETY_1.tc} + Click Button And Check Panel Validation Has Success ${MOVE_TRACKING_CODE_NEXT_BUTTON} ${MOVE_TRACKING_CODE_PANEL} ${MOVE_LOG_TYPE_PANEL} + Element Should Be Disabled ${MOVE_LOG_TYPE_DROPPED_RADIO} + Element Should Be Disabled ${MOVE_LOG_TYPE_GRABBED_RADIO} + Element Should Be Enabled ${MOVE_LOG_TYPE_MEET_RADIO} + Element Should Be Disabled ${MOVE_LOG_TYPE_DIPPED_RADIO} + Element Should Be Enabled ${MOVE_LOG_TYPE_COMMENT_RADIO} + Element Should Be Visible ${MOVE_LOG_TYPE_NOT_COLLECTIBLE_INFO} + +Some logtype should be hidden for owner + Sign In ${USER_1.name} Fast + + # Change parked flag + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + Element Should Contain ${GEOKRET_DETAILS_PARKED} Parked + + # Only a limited number of move type are shown + Sign In ${USER_1.name} Fast + Go To Move + Input Text ${MOVE_TRACKING_CODE_INPUT} ${GEOKRETY_1.tc} + Click Button And Check Panel Validation Has Success ${MOVE_TRACKING_CODE_NEXT_BUTTON} ${MOVE_TRACKING_CODE_PANEL} ${MOVE_LOG_TYPE_PANEL} + Element Should Be Disabled ${MOVE_LOG_TYPE_DROPPED_RADIO} + Element Should Be Disabled ${MOVE_LOG_TYPE_GRABBED_RADIO} + Element Should Be Disabled ${MOVE_LOG_TYPE_MEET_RADIO} + Element Should Be Enabled ${MOVE_LOG_TYPE_DIPPED_RADIO} + Element Should Be Enabled ${MOVE_LOG_TYPE_COMMENT_RADIO} + Element Should Be Visible ${MOVE_LOG_TYPE_NOT_COLLECTIBLE_INFO} + + +*** Keywords *** + +Test Setup + Clear Database And Seed ${3} users + Seed ${1} geokrety owned by ${1} + +Click Button And Check Panel Validation Has Success + [Arguments] ${button} ${current_panel} ${next_panel} + Panel validation has success ${current_panel} + Click Button ${button} + Panel Is Collapsed ${current_panel} + Panel Is Open ${next_panel} diff --git a/tests-qa/acceptance/030_Geokrety/050_Parked/030_export.robot b/tests-qa/acceptance/030_Geokrety/050_Parked/030_export.robot new file mode 100644 index 0000000000..af4489d3da --- /dev/null +++ b/tests-qa/acceptance/030_Geokrety/050_Parked/030_export.robot @@ -0,0 +1,69 @@ +*** Settings *** +Library RequestsLibrary +Library XML +Library DateTime +Resource ../../ressources/Authentication.robot +Resource ../../ressources/vars/Urls.robot +Variables ../../ressources/vars/users.yml +Variables ../../ressources/vars/geokrety.yml +Variables ../../ressources/vars/moves.yml +Test Setup Test Setup + +*** Variables *** + +*** Test Cases *** + +Validate XML - structure + # Check first GK + ${date_2_days_old} = Get Current Date increment=-2d result_format=%Y%m%d%H%M%d + + Create Session geokrety ${GK_URL} + ${xml} = GET On Session geokrety url=/export.php?modifiedsince=${date_2_days_old} + Status Should Be 200 ${xml} + + ${root} = Parse XML ${xml.content} + Should Be Equal ${root.tag} gkxml + + ${first_gk} = Get Element ${root} geokret + Should Be Equal ${first_gk.attrib['id']} 1 + XML.Element Attribute Should Be ${first_gk} id 1 + + ${name} = Get Element ${first_gk} name + XML.Element Text Should Be ${name} geokrety01 + ${collectible} = Get Element ${first_gk} collectible + XML.Element Text Should Be ${collectible} true + ${parked} = Get Element ${first_gk} parked + XML.Element Text Should Be ${parked} false + + # Park GK 1 + Sign In ${USER_1.name} Fast + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Input Text ${GEOKRET_CREATE_NAME_INPUT} GKNewName + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + + + ${xml} = GET On Session geokrety url=/export.php?modifiedsince=${date_2_days_old} + Status Should Be 200 ${xml} + + ${root} = Parse XML ${xml.content} + Should Be Equal ${root.tag} gkxml + + ${first_gk} = Get Element ${root} geokret + Should Be Equal ${first_gk.attrib['id']} 1 + XML.Element Attribute Should Be ${first_gk} id 1 + + ${name} = Get Element ${first_gk} name + XML.Element Text Should Be ${name} GKNewName + ${collectible} = Get Element ${first_gk} collectible + XML.Element Text Should Be ${collectible} false + ${parked} = Get Element ${first_gk} parked + XML.Element Text Should Be ${parked} true + +*** Keywords *** + +Test Setup + Clear Database And Seed ${3} users + Seed ${1} geokrety owned by ${1} diff --git a/tests-qa/acceptance/030_Geokrety/050_Parked/040_export2.robot b/tests-qa/acceptance/030_Geokrety/050_Parked/040_export2.robot new file mode 100644 index 0000000000..1615286894 --- /dev/null +++ b/tests-qa/acceptance/030_Geokrety/050_Parked/040_export2.robot @@ -0,0 +1,112 @@ +*** Settings *** +Library RequestsLibrary +Library XML +Resource ../../ressources/Authentication.robot +Resource ../../ressources/vars/Urls.robot +Variables ../../ressources/vars/users.yml +Variables ../../ressources/vars/geokrety.yml +Variables ../../ressources/vars/moves.yml +Test Setup Test Setup + +*** Variables *** + +*** Test Cases *** + +Validate XML - structure + Create Session geokrety ${GK_URL} + + ${xml} = GET On Session geokrety url=/export2.php?gkid=${GEOKRETY_1.id} + Status Should Be 200 ${xml} + + ${root} = Parse Xml ${xml.content} + Should Be Equal ${root.tag} gkxml + + ${first_gk} = Get Element ${root} geokrety/geokret + ${gkid} = Convert To String ${GEOKRETY_1.id} + XML.Element Attribute Should Be ${first_gk} id ${gkid} + XML.Element Attribute Should Be ${first_gk} owner_id 1 + XML.Element Attribute Should Be ${first_gk} ownername ${USER_1.name} + XML.Element Text Should Be ${first_gk} ${GEOKRETY_1.name} + # New fields + XML.Element Attribute Should Be ${first_gk} collectible true + XML.Element Should Not Have Attribute ${first_gk} parked + + + # Park GK 1 + Sign In ${USER_1.name} Fast + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Input Text ${GEOKRET_CREATE_NAME_INPUT} GKNewName + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + + + ${xml} = GET On Session geokrety url=/export2.php?gkid=${GEOKRETY_1.id} + Status Should Be 200 ${xml} + + ${root} = Parse Xml ${xml.content} + Should Be Equal ${root.tag} gkxml + + ${first_gk} = Get Element ${root} geokrety/geokret + ${gkid} = Convert To String ${GEOKRETY_1.id} + XML.Element Attribute Should Be ${first_gk} id ${gkid} + XML.Element Attribute Should Be ${first_gk} owner_id 1 + XML.Element Attribute Should Be ${first_gk} ownername ${USER_1.name} + XML.Element Text Should Be ${first_gk} GKNewName + # New fields + XML.Element Attribute Should Be ${first_gk} collectible false + XML.Element Attribute Should Be ${first_gk} parked true + + + ${xml} = GET On Session geokrety url=/export2.php?gkid=${GEOKRETY_1.id}&details=1 + Status Should Be 200 ${xml} + + ${root} = Parse Xml ${xml.content} + Should Be Equal ${root.tag} gkxml + + ${first_gk} = Get Element ${root} geokrety/geokret + Should Be Equal ${first_gk.attrib['id']} 1 + XML.Element Attribute Should Be ${first_gk} id 1 + + ${name} = Get Element ${first_gk} name + XML.Element Text Should Be ${name} GKNewName + + ${collectible} = Get Element ${first_gk} collectible + XML.Element Text Should Be ${collectible} false + + ${parked} = Get Element ${first_gk} parked + XML.Element Text Should Be ${parked} true + +Search By UserId And Inventory + Count GeoKrety Element /export2.php?userid=${USER_1.id}&inventory=1 1 + + # Park GK 1 + Sign In ${USER_1.name} Fast + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Input Text ${GEOKRET_CREATE_NAME_INPUT} GKNewName + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + + Count GeoKrety Element /export2.php?userid=${USER_1.id}&inventory=1 0 + +*** Keywords *** + +Test Setup + Clear Database And Seed ${3} users + Seed ${1} geokrety owned by ${1} + + +Count GeoKrety Element + [Arguments] ${url} ${compare} + Create Session geokrety ${GK_URL} + ${xml} = GET On Session geokrety ${url} + Status Should Be 200 ${xml} + + ${root} = Parse XML ${xml.content} + Should Be Equal ${root.tag} gkxml + + ${count} = XML.Get Element Count ${root} geokrety/geokret + Should Be Equal As Numbers ${count} ${compare} diff --git a/tests-qa/acceptance/030_Geokrety/050_Parked/050_ruchy.robot b/tests-qa/acceptance/030_Geokrety/050_Parked/050_ruchy.robot new file mode 100644 index 0000000000..eb5b23a01c --- /dev/null +++ b/tests-qa/acceptance/030_Geokrety/050_Parked/050_ruchy.robot @@ -0,0 +1,125 @@ +*** Settings *** +Library RequestsLibrary +Library XML +Library DateTime +Resource ../../ressources/Authentication.robot +Resource ../../ressources/vars/Urls.robot +Variables ../../ressources/vars/users.yml +Variables ../../ressources/vars/geokrety.yml +Variables ../../ressources/vars/moves.yml +Variables ../../ressources/vars/waypoints.yml +# Test Setup Test Setup + +*** Variables *** +# Logtypes +&{move_21} secid=${USER_1.secid} nr=${GEOKRETY_1.tc} logtype=0 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} +&{move_22} secid=${USER_1.secid} nr=${GEOKRETY_1.tc} logtype=1 +&{move_23} secid=${USER_1.secid} nr=${GEOKRETY_1.tc} logtype=2 +&{move_24} secid=${USER_1.secid} nr=${GEOKRETY_1.tc} logtype=3 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} +&{move_25} secid=${USER_1.secid} nr=${GEOKRETY_1.tc} logtype=4 +&{move_26} secid=${USER_1.secid} nr=${GEOKRETY_1.tc} logtype=5 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} +&{move_27} secid=${USER_1.secid} nr=${GEOKRETY_1.tc} logtype=6 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} +# Logtypes +&{move_31} secid=${USER_2.secid} nr=${GEOKRETY_1.tc} logtype=0 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} +&{move_32} secid=${USER_2.secid} nr=${GEOKRETY_1.tc} logtype=1 +&{move_33} secid=${USER_2.secid} nr=${GEOKRETY_1.tc} logtype=2 +&{move_34} secid=${USER_2.secid} nr=${GEOKRETY_1.tc} logtype=3 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} +&{move_35} secid=${USER_2.secid} nr=${GEOKRETY_1.tc} logtype=4 +&{move_36} secid=${USER_2.secid} nr=${GEOKRETY_1.tc} logtype=5 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} +&{move_37} secid=${USER_2.secid} nr=${GEOKRETY_1.tc} logtype=6 wpt=${WPT_GC_1.id} latlon=${WPT_GC_1.coords} + + +*** Test Cases *** +Test Valid Cases + [Template] Post Move Valid + ${move_23} ${GEOKRETY_1} + ${move_26} ${GEOKRETY_1} + ${move_34} ${GEOKRETY_1} + +Test Invalid Cases + [Template] Post Return Error + ${move_22} Holder of non collectible GeoKret cannot log DROPPED/GRABBED/SEEN + ${move_31} Non collectible GeoKret cannot be DROPPED/GRABBED/DIPPED + +*** Keywords *** + +Test Setup + Clear Database And Seed ${3} users + Seed ${1} geokrety owned by ${1} + + # Park GK 1 + Sign In ${USER_1.name} Fast + Go To Url ${PAGE_GEOKRETY_EDIT_URL} + Checkbox Should Not Be Selected ${GEOKRET_CREATE_PARKED_CHECKBOX} + Select Checkbox ${GEOKRET_CREATE_PARKED_CHECKBOX} + Input Text ${GEOKRET_CREATE_NAME_INPUT} GKNewName + Click Button ${GEOKRET_CREATE_CREATE_BUTTON} + Location Should Be ${PAGE_GEOKRETY_1_DETAILS_URL} + + +Post Move Valid + [Arguments] ${move} @{geokrety} + Test Setup + Create Session geokrety ${GK_URL} + ${auth} = GET On Session geokrety url=/ + + ${resp} = POST On Session geokrety url=/ruchy.php data=&{move} + Should Not Be Empty ${resp.content} + + ${root} = Parse XML ${resp.content} + Should Be Equal ${root.tag} gkxml + Response Should be XML Valid ${root} @{geokrety} + Delete All Sessions + +Check Error In XML List + [Arguments] ${root} ${error} + ${value} = Get Elements ${root} xpath=.//error[.='${error}'] + Length Should Be ${value} 1 msg=Error not found: ${error} + + +Response Should be XML Error + [Arguments] ${root} @{errors} + Should Be Equal ${root.tag} gkxml + + ${errors_count} = Get Length ${errors} + ${count} = XML.Get Element Count ${root} errors/error + Should Be Equal As Numbers ${errors_count} ${count} + + FOR ${error} IN @{errors} + Check Error In XML List ${root} ${error} + END + + +Post Return Error + [Arguments] ${move} @{errors} + Test Setup + Create Session geokrety ${GK_URL} + ${auth} = GET On Session geokrety url=/ + + ${resp} = POST On Session geokrety url=/ruchy.php data=&{move} + Should Not Be Empty ${resp.content} + + ${root} = Parse XML ${resp.content} + Should Be Equal ${root.tag} gkxml + Response Should be XML Error ${root} @{errors} + + Delete All Sessions + + +Check GeoKret In XML List + [Arguments] ${root} ${geokret} + ${value} = Get Elements ${root} xpath=.//geokret[@id='${geokret.id}'] + Length Should Be ${value} 1 + + +Response Should be XML Valid + [Arguments] ${root} @{geokrety} + Should Be Equal ${root.tag} gkxml + + ${geokrety_count} = Get Length ${geokrety} + ${count} = XML.Get Element Count ${root} geokrety/geokret + Should Be Equal As Numbers ${geokrety_count} ${count} + + FOR ${geokret} IN @{geokrety} + Check GeoKret In XML List ${root} ${geokret} + END diff --git a/tests-qa/acceptance/030_Geokrety/050_Parked/__init__.robot b/tests-qa/acceptance/030_Geokrety/050_Parked/__init__.robot new file mode 100644 index 0000000000..bdc095b56a --- /dev/null +++ b/tests-qa/acceptance/030_Geokrety/050_Parked/__init__.robot @@ -0,0 +1,2 @@ +*** Settings *** +Force Tags GeoKrety Details Collectible diff --git a/tests-qa/acceptance/ressources/ComponentsLocator.robot b/tests-qa/acceptance/ressources/ComponentsLocator.robot index bad88bd623..66f937199a 100644 --- a/tests-qa/acceptance/ressources/ComponentsLocator.robot +++ b/tests-qa/acceptance/ressources/ComponentsLocator.robot @@ -31,6 +31,7 @@ ${NAVBAR_ACTIONS_PHOTO_GALLERY_LINK} //*[@id="navbar-actions-gallery"] ${GEOKRET_CREATE_CREATE_BUTTON} //*[@id="createOrUpdateSubmitButton"] ${GEOKRET_CREATE_NAME_INPUT} //*[@id="inputName"] ${GEOKRET_CREATE_COLLECTIBLE_CHECKBOX} //*[@id="checkboxCollectible"] +${GEOKRET_CREATE_PARKED_CHECKBOX} //*[@id="checkboxParked"] ${GEOKRET_CREATE_BORN_ON_DATETIME_INPUT} //*[@id="born_on_datetime_localized"] ${GEOKRET_CREATE_BORN_ON_DATETIME_HIDDEN_INPUT} //*[@id="born_on_datetime"] ${GEOKRET_CREATE_TYPE_SELECT} //*[@id="inputGeokretType"] @@ -52,6 +53,7 @@ ${GEOKRET_DETAILS_TYPE} ${GEOKRET_DETAILS_DETAILS_PANEL} ${GEOKRET_DETAILS_TYPE_IMG} ${GEOKRET_DETAILS_DETAILS_PANEL}/div[@class="panel-heading"]/img ${GEOKRET_DETAILS_OWNER} ${GEOKRET_DETAILS_DETAILS_PANEL}/div[@class="panel-heading"]/a[@data-gk-link="user"] ${GEOKRET_DETAILS_COLLECTIBLE} //span[@id="non-collectible"] +${GEOKRET_DETAILS_PARKED} //span[@id="parked"] ${GEOKRET_DETAILS_TRACKING_CODE} ${GEOKRET_DETAILS_DETAILS_PANEL_BODY}//dd[@class="geokret-tracking-code"] ${GEOKRET_DETAILS_TRACKING_CODE_LABEL} ${GEOKRET_DETAILS_DETAILS_PANEL_BODY}//dt[text()="Tracking Code"] diff --git a/website/app-templates/smarty/blocks/geokret/details.tpl b/website/app-templates/smarty/blocks/geokret/details.tpl index 4d1919781b..8a89d019fb 100644 --- a/website/app-templates/smarty/blocks/geokret/details.tpl +++ b/website/app-templates/smarty/blocks/geokret/details.tpl @@ -22,7 +22,9 @@ - {t}archived{/t} {/if} - {if !$geokret->isCollectible()} + {if $geokret->isParked()} + ({t}Parked{/t}) + {elseif !$geokret->isCollectible()} ({t}Non-Collectible{/t}) {/if} diff --git a/website/app-templates/smarty/extension/SmartyGeokretyExtension.php b/website/app-templates/smarty/extension/SmartyGeokretyExtension.php index f696e56dff..4510b58259 100644 --- a/website/app-templates/smarty/extension/SmartyGeokretyExtension.php +++ b/website/app-templates/smarty/extension/SmartyGeokretyExtension.php @@ -40,6 +40,8 @@ function getPosIcon($id): string { return _('Probably lost'); case 5: return _('Visiting'); + case 7: + return _('Parked'); case 8: return _('In the owner hands'); case 9: @@ -50,6 +52,9 @@ function getPosIcon($id): string { } function computeLogType(Geokret $geokret, ?int $locationType, ?int $lastUserId): int { + if ($geokret->isParked()) { + return 7; + } if (is_null($locationType)) { return 9; } diff --git a/website/app-templates/smarty/forms/geokret.tpl b/website/app-templates/smarty/forms/geokret.tpl index 8c46b02bdf..8a2a8ab428 100644 --- a/website/app-templates/smarty/forms/geokret.tpl +++ b/website/app-templates/smarty/forms/geokret.tpl @@ -57,6 +57,23 @@ {/if} + {if isset($geokret) and $geokret->gkid() and $geokret->isHolder() and $geokret->isOwner()} +
+ +
+
+ +
+

+ {t}Parked GeoKrety will automatically imply non-collectible.{/t} + {t}They will not appear in your inventory.{/t} +

+
+
+ {/if} +
+ +
+
Collectible and Parked
+
+

Collectible

+

+ Collectible GeoKrety is the default status. When a Geokret is set to non-collectible, then only + a restricted number of move types are allowed. For every users, they can log: + meet and comments. While current holder will be allowed to: dip + and comment. +

+ +

Parked

+

+ Parked GeoKrety automatically imply Collectible status. When a Geokret is set to parked, + in addition to Collectible restrictions, such GeoKrety will not appear in user inventory. +

+
+
+

Database synchronizing

@@ -236,6 +257,10 @@ var_dump($gk); userid - list GeoKrety owned by userid

{'api_v1_export2'|alias}?userid=1
+
  • + parked - Include parked GeoKrety (works only with userid) +
    {'api_v1_export2'|alias}?userid=1&parked=1
    +
  • gkid - list only one GeoKret
    {'api_v1_export2'|alias}?gkid=141
  • diff --git a/website/app/GeoKrety/Controller/Pages/BaseExportXML.php b/website/app/GeoKrety/Controller/Pages/BaseExportXML.php index 8b00efcf2b..c1c00ac81a 100644 --- a/website/app/GeoKrety/Controller/Pages/BaseExportXML.php +++ b/website/app/GeoKrety/Controller/Pages/BaseExportXML.php @@ -64,6 +64,11 @@ public function _check_userid() { } else { $this->setFilter('owner = ?', $userid); } + + // Filter by parked + if (!filter_var($this->f3->get('GET.parked'), FILTER_VALIDATE_BOOLEAN)) { + $this->setFilter('parked = ?', null); + } } protected function setFilter(string $query, ...$params) { diff --git a/website/app/GeoKrety/Controller/Pages/GeokretEdit.php b/website/app/GeoKrety/Controller/Pages/GeokretEdit.php index 3b4f60428f..4f0c3ccc48 100644 --- a/website/app/GeoKrety/Controller/Pages/GeokretEdit.php +++ b/website/app/GeoKrety/Controller/Pages/GeokretEdit.php @@ -17,8 +17,9 @@ public function _beforeRoute(\Base $f3) { public function post($f3) { $this->checkCsrf(); $geokret = $this->geokret; - $geokret->copyFrom('POST'); + $geokret->copyFrom('POST', ['name', 'born_on_datetime', 'type', 'mission']); $this->manageCollectible($f3, $geokret); + $this->manageParked($f3, $geokret); $this->loadSelectedTemplate($f3); if ($geokret->validate()) { @@ -50,4 +51,18 @@ private function manageCollectible($f3, \GeoKrety\Model\Geokret $geokret): void $geokret->non_collectible = null; } } + + private function manageParked($f3, \GeoKrety\Model\Geokret $geokret): void { + if (filter_var($f3->get('POST.parked'), FILTER_VALIDATE_BOOLEAN)) { + if (is_null($geokret->parked)) { + $geokret->touch('parked'); + } + + return; + } + + if (!is_null($geokret->parked)) { + $geokret->parked = null; + } + } } diff --git a/website/app/GeoKrety/Controller/Pages/GeokretSelectFromInventory.php b/website/app/GeoKrety/Controller/Pages/GeokretSelectFromInventory.php index 899d8ff7c6..88d8792181 100644 --- a/website/app/GeoKrety/Controller/Pages/GeokretSelectFromInventory.php +++ b/website/app/GeoKrety/Controller/Pages/GeokretSelectFromInventory.php @@ -9,7 +9,7 @@ class GeokretSelectFromInventory extends Base { public function get($f3) { // Load owned GeoKrety $geokret = new Geokret(); - $filter = ['holder = ?', $f3->get('SESSION.CURRENT_USER')]; + $filter = ['holder = ? AND parked = ?', $f3->get('SESSION.CURRENT_USER'), null]; $option = ['order' => 'name ASC']; $geokrety = $geokret->find($filter, $option); Smarty::assign('geokrety', $geokrety); diff --git a/website/app/GeoKrety/Controller/Pages/HallOfFame.php b/website/app/GeoKrety/Controller/Pages/HallOfFame.php index bb2c8ddc50..5632363f44 100644 --- a/website/app/GeoKrety/Controller/Pages/HallOfFame.php +++ b/website/app/GeoKrety/Controller/Pages/HallOfFame.php @@ -158,6 +158,11 @@ public function get() { 'link' => 'https://fatfreeframework.com', 'desc' => 'PHP micro-framework', ]; + $credits[] = [ + 'name' => 'Google Noto Color Emoji', + 'link' => 'https://github.com/googlefonts/noto-emoji', + 'desc' => 'Noto Emoji fonts', + ]; Smarty::assign('app_credits', $credits); Smarty::render('pages/hall_of_fame.tpl'); diff --git a/website/app/GeoKrety/Controller/Pages/LegacyRoutes.php b/website/app/GeoKrety/Controller/Pages/LegacyRoutes.php index 540ea4dd6b..cf5cecd31c 100644 --- a/website/app/GeoKrety/Controller/Pages/LegacyRoutes.php +++ b/website/app/GeoKrety/Controller/Pages/LegacyRoutes.php @@ -113,6 +113,7 @@ public function export2(\Base $f3) { 'inventory' => $f3->get('GET.inventory'), 'details' => $f3->get('GET.details'), 'tracking_code' => $f3->get('GET.tracking_code'), + 'parked' => $f3->get('GET.parked'), ]; if ($f3->exists('GET.rate_limits_bypass')) { $others['rate_limits_bypass'] = $f3->get('GET.rate_limits_bypass'); diff --git a/website/app/GeoKrety/Model/Geokret.php b/website/app/GeoKrety/Model/Geokret.php index e729f132e3..ce6f16d8e2 100644 --- a/website/app/GeoKrety/Model/Geokret.php +++ b/website/app/GeoKrety/Model/Geokret.php @@ -29,6 +29,7 @@ * @property \DateTime created_on_datetime * @property \DateTime born_on_datetime * @property \DateTime|null non_collectible + * @property \DateTime|null parked * @property Picture[]|null avatars * @property \DateTime updated_on_datetime * @property bool missing @@ -151,6 +152,11 @@ class Geokret extends Base { 'nullable' => true, 'validate' => 'is_date', ], + 'parked' => [ + 'type' => Schema::DT_DATETIME, + 'nullable' => true, + 'validate' => 'is_date', + ], ]; public function __construct() { @@ -249,6 +255,10 @@ public function get_non_collectible($value): ?\DateTime { return self::get_date_object($value); } + public function get_parked($value): ?\DateTime { + return self::get_date_object($value); + } + public function get_url(): string { return \Base::instance()->alias('geokret_details', '@gkid='.$this->gkid); } @@ -311,6 +321,10 @@ public function isCollectible(): bool { return is_null($this->non_collectible); } + public function isParked(): bool { + return !is_null($this->parked); + } + public function countryTrack(): array { $sql = <<<'SQL' SELECT geokret, @@ -342,6 +356,7 @@ public function jsonSerialize(): mixed { 'id' => $this->id, 'gkid' => $this->gkid, 'collectible' => $this->isCollectible(), + 'parked' => $this->isParked(), // 'tracking_code' => $this->tracking_code, // 'name' => $this->name, // 'mission' => $this->mission, diff --git a/website/app/GeoKrety/Model/GeokretWithDetails.php b/website/app/GeoKrety/Model/GeokretWithDetails.php index 74635a1baf..e0e1909a89 100644 --- a/website/app/GeoKrety/Model/GeokretWithDetails.php +++ b/website/app/GeoKrety/Model/GeokretWithDetails.php @@ -100,6 +100,16 @@ class GeokretWithDetails extends Geokret { 'nullable' => true, 'validate' => 'is_date', ], + 'non_collectible' => [ + 'type' => Schema::DT_DATETIME, + 'nullable' => true, + 'validate' => 'is_date', + ], + 'parked' => [ + 'type' => Schema::DT_DATETIME, + 'nullable' => true, + 'validate' => 'is_date', + ], ]; public function get_moved_on_datetime($value): ?\DateTime { diff --git a/website/app/GeoKrety/Service/Xml/GeokretyExport.php b/website/app/GeoKrety/Service/Xml/GeokretyExport.php index d15229a8e7..c92cd764b4 100644 --- a/website/app/GeoKrety/Service/Xml/GeokretyExport.php +++ b/website/app/GeoKrety/Service/Xml/GeokretyExport.php @@ -53,6 +53,8 @@ public function addGeokret(Geokret &$geokret) { $xml->writeElement('state', $geokret->move_type->getLogTypeId()); } $xml->writeElement('missing', (int) $geokret->isMissing()); + $xml->writeElement('collectible', (int) $geokret->isCollectible() ? 'true' : 'false'); + $xml->writeElement('parked', (int) $geokret->isParked() ? 'true' : 'false'); $xml->startElement('position'); if (!is_null($geokret->last_position)) { diff --git a/website/app/GeoKrety/Service/Xml/GeokretyExport2.php b/website/app/GeoKrety/Service/Xml/GeokretyExport2.php index 058ed0fb2e..de22a05f44 100644 --- a/website/app/GeoKrety/Service/Xml/GeokretyExport2.php +++ b/website/app/GeoKrety/Service/Xml/GeokretyExport2.php @@ -26,6 +26,10 @@ public function addGeokret(\GeoKrety\Model\Geokret &$geokret) { if ($geokret->isMissing()) { $xml->writeAttribute('missing', $geokret->isMissing()); } + $xml->writeAttribute('collectible', $geokret->isCollectible() ? 'true' : 'false'); + if ($geokret->isParked()) { + $xml->writeAttribute('parked', $geokret->isParked() ? 'true' : 'false'); + } if ($geokret->owner) { $xml->writeAttribute('owner_id', $geokret->owner); diff --git a/website/app/GeoKrety/Service/Xml/GeokretyExport2Details.php b/website/app/GeoKrety/Service/Xml/GeokretyExport2Details.php index 79892476b0..30e5bb0440 100644 --- a/website/app/GeoKrety/Service/Xml/GeokretyExport2Details.php +++ b/website/app/GeoKrety/Service/Xml/GeokretyExport2Details.php @@ -76,6 +76,9 @@ public function addGeokret(Geokret &$geokret) { $xml->writeCData((int) $geokret->isMissing()); $xml->endElement(); // missing + $xml->writeElement('collectible', (int) $geokret->isCollectible() ? 'true' : 'false'); + $xml->writeElement('parked', (int) $geokret->isParked() ? 'true' : 'false'); + if (!is_null($geokret->waypoint)) { $xml->startElement('position'); $xml->writeAttribute('latitude', $geokret->lat ?? ''); diff --git a/website/app/validators.php b/website/app/validators.php index a2be62a908..8f38d84b9e 100644 --- a/website/app/validators.php +++ b/website/app/validators.php @@ -81,9 +81,12 @@ if (!$input[$field] or is_null($input['geokret'])) { return true; } + if ($input['move_type']->isType(GeoKrety\LogType::LOG_TYPE_COMMENT)) { + return true; + } $move = new GeoKrety\Model\Move(); - $move->load([$field.' = ? AND geokret = ? AND id != ?', $input[$field]->format(GK_DB_DATETIME_FORMAT), $input['geokret']->id, $input['_id']]); + $move->load([$field.' = ? AND geokret = ? AND id != ? AND move_type NOT IN (2)', $input[$field]->format(GK_DB_DATETIME_FORMAT), $input['geokret']->id, $input['_id']]); return $move->dry(); }, _('Something already exists at the same datetime "{0}"')); diff --git a/website/db/migrations/20240524085913_collectible.php b/website/db/migrations/20240524085913_collectible.php index 844464a971..33da3852b5 100644 --- a/website/db/migrations/20240524085913_collectible.php +++ b/website/db/migrations/20240524085913_collectible.php @@ -7,8 +7,13 @@ final class Collectible extends AbstractMigration { public function up(): void { $table_gk = $this->table('geokrety.gk_geokrety'); - $table_gk->addColumn('non_collectible', 'timestamp', ['default' => null, 'null' => true, 'timezone' => true]) - ->save(); + if (is_null($table_gk->getColumn('non_collectible'))) { + $table_gk->addColumn('non_collectible', 'timestamp', ['default' => null, 'null' => true, 'timezone' => true]); + } + if (is_null($table_gk->getColumn('parked'))) { + $table_gk->addColumn('parked', 'timestamp', ['default' => null, 'null' => true, 'timezone' => true]); + } + $table_gk->save(); $this->execute(<<<'EOL' CREATE FUNCTION geokrety.moves_check_non_collectible() @@ -34,21 +39,13 @@ public function up(): void { END IF; -- prevent dropped grabbed dipped form non-holder+non-owner -IF (gk.holder != NEW.author AND gk.owner != NEW.author) AND NEW.move_type IN (0::smallint, 1::smallint, 5::smallint) THEN - RAISE 'Author(%) ; Holder(%) of non collectible(%) GeoKret(%) cannot do log of type DROP/GRAB/DIPPED (%)', NEW.author, gk.holder, gk.non_collectible, gk.id, NEW.move_type; +IF gk.holder != NEW.author AND NEW.move_type IN (0::smallint, 1::smallint, 5::smallint) THEN + RAISE 'Non collectible GeoKret cannot be DROPPED/GRABBED/DIPPED'; END IF; -- prevent grabbed from holder -IF gk.holder = NEW.author AND gk.owner != NEW.author AND NEW.move_type = 1::smallint THEN - RAISE 'Holder of non collectible GeoKret cannot do log of type GRAB'; -END IF; - --- disable non_collectible flag on drop -IF 0::smallint = NEW.move_type THEN - UPDATE "gk_geokrety" - SET non_collectible=NULL - WHERE id = NEW.geokret - AND non_collectible IS NOT NULL; +IF gk.holder = NEW.author AND NEW.move_type IN (0::smallint, 1::smallint, 3::smallint) THEN + RAISE 'Holder of non collectible GeoKret cannot log DROPPED/GRABBED/SEEN'; END IF; RETURN NEW; @@ -57,17 +54,57 @@ public function up(): void { EOL); $this->execute(<<<'EOL' -CREATE FUNCTION geokrety.grokret_check_non_collectible() +CREATE FUNCTION geokrety.geokret_check_non_collectible() RETURNS trigger LANGUAGE 'plpgsql' AS $BODY$ BEGIN +IF NEW.parked IS NOT NULL AND NEW.non_collectible IS NULL THEN + IF OLD.non_collectible IS NOT NULL THEN + NEW.non_collectible := OLD.non_collectible; + ELSE + NEW.non_collectible := NEW.parked; + END IF; +ELSIF OLD.parked IS NOT NULL AND NEW.parked IS NULL THEN + NEW.non_collectible := NULL; +END IF; + -- Set collectible require an holder IF NEW.non_collectible IS NOT NULL AND NEW.holder IS NULL AND OLD.holder IS NULL THEN RAISE 'Cannot set non collectible without an holder'; END IF; +RETURN NEW; +END; +$BODY$; +EOL); + + $this->execute(<<<'EOL' +CREATE FUNCTION geokrety.geokret_parked_non_collectible() + RETURNS trigger + LANGUAGE 'plpgsql' +AS $BODY$ +BEGIN + +IF OLD.parked != NEW.parked OR (OLD.parked IS NULL) != (NEW.parked IS NULL) THEN + IF NEW.parked IS NULL THEN + INSERT INTO geokrety.gk_moves ("geokret", "username", "moved_on_datetime", "move_type", "comment") + VALUES (NEW.id, 'GeoKrety Bot', NEW.parked, 2, '📦 GeoKrety removed from parked state'); + ELSE + INSERT INTO geokrety.gk_moves ("geokret", "username", "moved_on_datetime", "move_type", "comment") + VALUES (NEW.id, 'GeoKrety Bot', NEW.parked, 2, '📦 GeoKrety set as parked'); + END IF; +ELSIF OLD.non_collectible != NEW.non_collectible OR (OLD.non_collectible IS NULL) != (NEW.non_collectible IS NULL) THEN + IF NEW.non_collectible IS NULL THEN + INSERT INTO geokrety.gk_moves ("geokret", "username", "moved_on_datetime", "move_type", "comment") + VALUES (NEW.id, 'GeoKrety Bot', NEW.non_collectible, 2, '🪤 GeoKrety set as collectible'); + ELSE + INSERT INTO geokrety.gk_moves ("geokret", "username", "moved_on_datetime", "move_type", "comment") + VALUES (NEW.id, 'GeoKrety Bot', NEW.non_collectible, 2, '🪤 GeoKrety set as non-collectible'); + END IF; +END IF; + RETURN NEW; END; $BODY$; @@ -83,24 +120,141 @@ public function up(): void { $this->execute(<<<'EOL' CREATE OR REPLACE TRIGGER before_50_check_non_collectible - BEFORE INSERT OR UPDATE + BEFORE INSERT OR UPDATE OF non_collectible, parked + ON geokrety.gk_geokrety + FOR EACH ROW + EXECUTE FUNCTION geokrety.geokret_check_non_collectible(); +EOL); + + $this->execute(<<<'EOL' +CREATE OR REPLACE TRIGGER after_20_parked_non_collectible + AFTER INSERT OR UPDATE OF non_collectible, parked ON geokrety.gk_geokrety FOR EACH ROW - EXECUTE FUNCTION geokrety.grokret_check_non_collectible(); + EXECUTE FUNCTION geokrety.geokret_parked_non_collectible(); +EOL); + + $this->execute(<<<'EOL' +CREATE OR REPLACE FUNCTION geokrety.moves_moved_on_datetime_checker() + RETURNS trigger + LANGUAGE 'plpgsql' + VOLATILE + COST 100 +AS $BODY$ +DECLARE +_geokret gk_geokrety; +BEGIN + +SELECT * +FROM gk_geokrety +WHERE id = NEW.geokret +INTO _geokret; + +-- move before GK birth +IF DATE_TRUNC('MINUTE', NEW.moved_on_datetime) < DATE_TRUNC('MINUTE', _geokret.born_on_datetime) THEN + RAISE 'Move date (%) time can not be before GeoKret birth (%)', DATE_TRUNC('MINUTE', NEW.moved_on_datetime), DATE_TRUNC('MINUTE', _geokret.born_on_datetime); +-- move after NOW() +ELSIF NEW.moved_on_datetime > NOW()::timestamp(0) THEN + RAISE 'The date is in the future (if you are an inventor of a time travelling machine, contact us please!)'; +-- same move on this GK at this datetime +ELSIF COUNT(*) > 0 FROM gk_moves WHERE moved_on_datetime = NEW.moved_on_datetime AND "geokret" = NEW.geokret AND id != NEW.id AND move_type NOT IN (2::smallint) AND NEW.move_type NOT IN (2::smallint) THEN + RAISE 'A move at the exact same date already exists for this GeoKret'; +END IF; + +RETURN NEW; +END; +$BODY$; +EOL); + + $this->execute(<<<'EOL' +CREATE OR REPLACE VIEW geokrety.gk_geokrety_with_details + AS + SELECT gk_geokrety.id, + gk_geokrety.gkid, + gk_geokrety.tracking_code, + gk_geokrety.name, + gk_geokrety.mission, + gk_geokrety.owner, + gk_geokrety.distance, + gk_geokrety.caches_count, + gk_geokrety.pictures_count, + gk_geokrety.last_position, + gk_geokrety.last_log, + gk_geokrety.holder, + gk_geokrety.avatar, + gk_geokrety.created_on_datetime, + gk_geokrety.updated_on_datetime, + gk_geokrety.missing, + gk_geokrety.type, + gk_moves."position", + gk_moves.lat, + gk_moves.lon, + gk_moves.waypoint, + gk_moves.elevation, + gk_moves.country, + gk_moves.move_type, + gk_moves.author, + gk_moves.moved_on_datetime, + COALESCE(gk_moves.username, m_author.username) AS author_username, + COALESCE(g_owner.username, 'Abandoned'::character varying) AS owner_username, + g_avatar.key AS avatar_key, + gk_geokrety.born_on_datetime, + gk_geokrety.non_collectible, + gk_geokrety.parked + FROM gk_geokrety + LEFT JOIN gk_moves ON gk_geokrety.last_position = gk_moves.id + LEFT JOIN gk_users m_author ON gk_moves.author = m_author.id + LEFT JOIN gk_users g_owner ON gk_geokrety.owner = g_owner.id + LEFT JOIN gk_pictures g_avatar ON gk_geokrety.avatar = g_avatar.id; EOL); } + /** + * Note: it's not possible to remove column from a view, so the column will be left untouched on downgrade :(. + */ public function down(): void { - $this->execute('DROP TRIGGER before_60_check_non_collectible ON geokrety.gk_moves'); - $this->execute('DROP TRIGGER before_50_check_non_collectible ON geokrety.gk_geokrety'); + $this->execute('DROP TRIGGER IF EXISTS before_60_check_non_collectible ON geokrety.gk_moves'); + $this->execute('DROP TRIGGER IF EXISTS before_50_check_non_collectible ON geokrety.gk_geokrety'); + $this->execute('DROP TRIGGER IF EXISTS after_80_check_non_collectible ON geokrety.gk_moves'); + $this->execute('DROP TRIGGER IF EXISTS after_20_parked_non_collectible ON geokrety.gk_geokrety'); $this->execute(<<<'EOL' DROP FUNCTION IF EXISTS geokrety.moves_check_non_collectible(); -DROP FUNCTION IF EXISTS geokrety.grokret_check_non_collectible(); +DROP FUNCTION IF EXISTS geokrety.moves_check_non_collectible_after(); +DROP FUNCTION IF EXISTS geokrety.geokret_check_non_collectible(); +DROP FUNCTION IF EXISTS geokrety.geokret_parked_non_collectible(); EOL); - $table_gk = $this->table('geokrety.gk_geokrety'); - $table_gk->removeColumn('non_collectible') - ->save(); + $this->execute(<<<'EOL' +CREATE OR REPLACE FUNCTION geokrety.moves_moved_on_datetime_checker() + RETURNS trigger + LANGUAGE 'plpgsql' + VOLATILE + COST 100 +AS $BODY$ +DECLARE +_geokret gk_geokrety; +BEGIN + +SELECT * +FROM gk_geokrety +WHERE id = NEW.geokret +INTO _geokret; + +-- move before GK birth +IF DATE_TRUNC('MINUTE', NEW.moved_on_datetime) < DATE_TRUNC('MINUTE', _geokret.born_on_datetime) THEN + RAISE 'Move date (%) time can not be before GeoKret birth (%)', DATE_TRUNC('MINUTE', NEW.moved_on_datetime), DATE_TRUNC('MINUTE', _geokret.born_on_datetime); +-- move after NOW() +ELSIF NEW.moved_on_datetime > NOW()::timestamp(0) THEN + RAISE 'The date is in the future (if you are an inventor of a time travelling machine, contact us please!)'; +-- same move on this GK at this datetime +ELSIF COUNT(*) > 0 FROM gk_moves WHERE moved_on_datetime = NEW.moved_on_datetime AND "geokret" = NEW.geokret AND id != NEW.id THEN + RAISE 'A move at the exact same date already exists for this GeoKret'; +END IF; + +RETURN NEW; +END; +$BODY$; +EOL); } } diff --git a/website/db/tests/test-30-moves-moved-on-datetime.sql b/website/db/tests/test-30-moves-moved-on-datetime.sql index 6c80b56779..7ce1bb5c41 100644 --- a/website/db/tests/test-30-moves-moved-on-datetime.sql +++ b/website/db/tests/test-30-moves-moved-on-datetime.sql @@ -3,7 +3,7 @@ BEGIN; -- SELECT * FROM no_plan(); -SELECT plan(19); +SELECT plan(23); \set nice '\'0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540\'' \set move_type_comment 2 @@ -30,9 +30,9 @@ SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_ -- same move on this GK at this datetime INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime") VALUES (5, 'test', 0, '2020-04-07 00:00:00+00'); INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime") VALUES (6, 'test', 0, '2020-04-07 00:00:00+00'); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (3, 5, 1, '2020-04-08 00:00:00+00', 2)$$); -SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (4, 5, 1, '2020-04-08 00:00:00+00', 2)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (5, 6, 1, '2020-04-08 00:00:00+00', 2)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (3, 5, 1, '2020-04-08 00:00:00+00', 1)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (4, 5, 1, '2020-04-08 00:00:00+00', 1)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (5, 6, 1, '2020-04-08 00:00:00+00', 1)$$); -- move in the right range INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime") VALUES (7, 'test', 0, '2020-04-07 00:00:00+00'); @@ -42,8 +42,8 @@ SELECT is(COUNT(*) > 0, TRUE, 'move in the right range') from gk_geokrety WHERE -- update can reuse same date INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime") VALUES (8, 'test', 0, '2020-04-07 00:00:00+00'); INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime") VALUES (9, 'test', 0, '2020-04-07 00:00:00+00'); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (7, 8, 1, '2020-04-08 00:00:00+00', 2); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (8, 9, 1, '2020-04-08 00:00:00+00', 2); +INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (7, 8, 1, '2020-04-08 00:00:00+00', 1); +INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (8, 9, 1, '2020-04-08 00:00:00+00', 1); SELECT lives_ok($$UPDATE "gk_moves" set moved_on_datetime = '2020-04-08 00:00:00+00'::timestamptz WHERE id = 7::bigint$$); SELECT throws_ok($$UPDATE "gk_moves" set geokret=9, moved_on_datetime = '2020-04-08 00:00:00+00'::timestamptz WHERE id = 7::bigint$$); @@ -64,6 +64,13 @@ SELECT lives_ok($$UPDATE "gk_geokrety" set born_on_datetime = '2024-05-10 00:00: SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (12, 12, 1, '2024-05-10 00:00:00+00', 2)$$); SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (13, 12, 1, '2024-05-09 00:00:00+00', 2)$$); +-- Multiple comments can exists at this datetime +INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime") VALUES (13, 'test', 0, '2020-04-07 00:00:00+00'); +SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (14, 13, 1, '2020-04-08 00:00:00+00', 2)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (15, 13, 1, '2020-04-08 00:00:00+00', 1)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (16, 13, 1, '2020-04-08 00:00:00+00', 1)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (17, 13, 1, '2020-04-08 00:00:00+00', 2)$$); + -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; diff --git a/website/db/tests/test-54-collectible.sql b/website/db/tests/test-54-collectible.sql index d8d6173be0..9413cd074d 100644 --- a/website/db/tests/test-54-collectible.sql +++ b/website/db/tests/test-54-collectible.sql @@ -1,8 +1,8 @@ -- Start transaction and plan the tests. BEGIN; -SELECT * FROM no_plan(); --- SELECT plan(21); +-- SELECT * FROM no_plan(); +SELECT plan(130); \set nice '\'0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540\'' \set paris '\'0101000020E610000066666666666602406666666666664840\'' @@ -29,182 +29,182 @@ SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 1::bigint; -- When non_collectible is NULL, all log types are allowed by everyone SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (2, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (1, 2, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 0)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (2, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 0)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (3, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (2, 3, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 3)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (3, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 3)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (4, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (3, 4, 2, '2024-05-24 00:00:03+00', 1)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (4, 2, '2024-05-24 00:00:03+00', 1)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (5, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (4, 5, 2, '2024-05-24 00:00:04+00', 2)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (5, 2, '2024-05-24 00:00:04+00', 2)$$); -- Archive is only for owner --- SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (5, 2, 2, '2024-05-24 00:00:05+00', 4)$$); +-- SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (2, 2, '2024-05-24 00:00:05+00', 4)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (6, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (6, 6, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 5)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (6, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 5)$$); -- When non_collectible is NULL, all log types are allowed by owner SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (7, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (11, 7, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 0)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (7, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 0)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (8, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (12, 8, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 3)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (8, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 3)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (9, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (13, 9, 1, '2024-05-24 00:00:03+00', 1)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (9, 1, '2024-05-24 00:00:03+00', 1)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (10, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (14, 10, 1, '2024-05-24 00:00:04+00', 2)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (10, 1, '2024-05-24 00:00:04+00', 2)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (11, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (15, 11, 1, '2024-05-24 00:00:05+00', 4)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (11, 1, '2024-05-24 00:00:05+00', 4)$$); SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (12, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (16, 12, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 5)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (12, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:00+00', 5)$$); -- When non_collectible is set to a date, only discovered types are allowed by everyone SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "non_collectible") VALUES (14, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:02+00')$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 14::bigint; -SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (21, 14, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 0)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (14, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 0)$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 14::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "non_collectible") VALUES (15, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:02+00')$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 15::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (22, 15, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 3)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (15, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 3)$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 15::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "non_collectible") VALUES (16, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:02+00')$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 16::bigint; -SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (23, 16, 2, '2024-05-24 00:00:03+00', 1)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (16, 2, '2024-05-24 00:00:03+00', 1)$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 16::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "non_collectible") VALUES (17, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:02+00')$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 17::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (24, 17, 2, '2024-05-24 00:00:03+00', 2)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (17, 2, '2024-05-24 00:00:03+00', 2)$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 17::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "non_collectible") VALUES (18, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:02+00')$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 18::bigint; -SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (26, 18, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 5)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (18, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 5)$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 18::bigint; -- When non_collectible is set to a date, holder can .... SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (30, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (30, 30, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (30, 3, '2024-05-24 00:00:01+00', 1); UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 30::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 30::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 30::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (31, 30, 3, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 0)$$); --- logtype 0 should disable non_collectible flag -SELECT is(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 30::bigint; -SELECT is(holder, NULL) FROM "gk_geokrety" WHERE id = 30::bigint; +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (30, 3, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 0)$$); +SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 30::bigint; +SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 30::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (31, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (32, 31, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (31, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 31::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 31::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (33, 31, 3, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 3)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (31, 3, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 3)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 31::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 31::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (32, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (34, 32, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (32, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 32::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 32::bigint; -SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (35, 32, 3, '2024-05-24 00:00:03+00', 1)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (32, 3, '2024-05-24 00:00:03+00', 1)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 32::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 32::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (33, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (36, 33, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (33, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 33::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 33::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 33::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (37, 12, 3, '2024-05-24 00:00:03+00', 2)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (12, 3, '2024-05-24 00:00:03+00', 2)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 33::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 33::bigint; -- Only GeoKret owner can archive it s GeoKrety SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (34, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (38, 34, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (34, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 34::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 34::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 34::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (39, 34, 3, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 5)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (34, 3, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 5)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 34::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 34::bigint; -- -- When non_collectible is set to a date and holder is someone else, owner can .... +-- TODO only seen SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (35, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (40, 35, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (35, 3, '2024-05-24 00:00:01+00', 1); SELECT is(owner, 1::bigint) FROM "gk_geokrety" WHERE id = 35::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 35::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 35::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 35::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (41, 35, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 0)$$); -SELECT is(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 35::bigint; -SELECT is(holder, NULL) FROM "gk_geokrety" WHERE id = 35::bigint; +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (35, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 0)$$); +SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 35::bigint; +SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 35::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (36, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (42, 36, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (36, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 36::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 36::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 36::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (43, 36, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 3)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (36, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 3)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 36::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 36::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (37, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (44, 37, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (37, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 37::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 37::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 37::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (45, 37, 1, '2024-05-24 00:01:03+00', 1)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (37, 1, '2024-05-24 00:01:03+00', 1)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 37::bigint; -SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 37::bigint; +SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 37::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (38, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (46, 38, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (38, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 38::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 38::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 38::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (47, 38, 1, '2024-05-24 00:00:03+00', 2)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (38, 1, '2024-05-24 00:00:03+00', 2)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 38::bigint; SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 38::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (39, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (48, 39, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (39, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 39::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 39::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 39::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (49, 39, 1, '2024-05-24 00:00:03+00', 4)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (39, 1, '2024-05-24 00:00:03+00', 4)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 39::bigint; SELECT is(holder, NULL) FROM "gk_geokrety" WHERE id = 39::bigint; SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (40, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (50, 40, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (40, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 40::bigint; UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 40::bigint; SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 40::bigint; -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (51, 40, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 5)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (40, 1, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:03+00', 5)$$); SELECT isnt(non_collectible, NULL) FROM "gk_geokrety" WHERE id = 40::bigint; -SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 40::bigint; +SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 40::bigint; -- Not effective if move is before non_collectible activation SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "non_collectible") VALUES (41, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:02+00')$$); SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 41::bigint; -- 121 -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (53, 41, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:01+00', 0)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (41, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:01+00', 0)$$); SELECT is(holder, NULL) FROM "gk_geokrety" WHERE id = 41::bigint; -- Effective as soon as non_collectible is enabled SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "non_collectible") VALUES (42, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:02+00')$$); -INSERT INTO "gk_moves" ("id", "geokret", "author", "moved_on_datetime", "move_type") VALUES (54, 42, 3, '2024-05-24 00:00:01+00', 1); +INSERT INTO "gk_moves" ("geokret", "author", "moved_on_datetime", "move_type") VALUES (42, 3, '2024-05-24 00:00:01+00', 1); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 42::bigint; -SELECT throws_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (55, 42, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:02+00', 0)$$); +SELECT throws_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (42, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:02+00', 0)$$); SELECT is(holder, 3::bigint) FROM "gk_geokrety" WHERE id = 42::bigint; -- Can be enabled only if it has an holder SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (43, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); -SELECT lives_ok($$INSERT INTO "gk_moves" ("id", "geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (56, 43, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:02+00', 0)$$); +SELECT lives_ok($$INSERT INTO "gk_moves" ("geokret", "author", "position", "moved_on_datetime", "move_type") VALUES (43, 2, '0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540', '2024-05-24 00:00:02+00', 0)$$); SELECT is(holder, NULL) FROM "gk_geokrety" WHERE id = 43::bigint; SELECT throws_ok($$UPDATE "gk_geokrety" SET non_collectible='2024-05-24 00:00:02+00' WHERE id = 43::bigint$$); diff --git a/website/db/tests/test-55-parked.sql b/website/db/tests/test-55-parked.sql new file mode 100644 index 0000000000..adc103dba6 --- /dev/null +++ b/website/db/tests/test-55-parked.sql @@ -0,0 +1,57 @@ +-- Start transaction and plan the tests. + +BEGIN; +SELECT * FROM no_plan(); +-- SELECT plan(16); + +\set nice '\'0101000020E6100000F6285C8FC2F51C405C8FC2F528DC4540\'' +\set paris '\'0101000020E610000066666666666602406666666666664840\'' +\set move_type_dropped 0 +\set move_type_grabbed 1 +\set move_type_comment 2 +\set move_type_seen 3 +\set move_type_archived 4 +\set move_type_dipped 5 + +SELECT lives_ok($$INSERT INTO "gk_users" ("id", "username", "registration_ip") VALUES (1, 'test 1', '127.0.0.1')$$); +SELECT lives_ok($$INSERT INTO "gk_users" ("id", "username", "registration_ip") VALUES (2, 'test 2', '127.0.0.1')$$); +SELECT lives_ok($$INSERT INTO "gk_users" ("id", "username", "registration_ip") VALUES (3, 'test 3', '127.0.0.1')$$); + +-- parked can be set +SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner") VALUES (1, 'test', 0, '2024-05-24 00:00:00+00', 1)$$); +SELECT is(owner, 1::bigint) FROM "gk_geokrety" WHERE id = 1::bigint; +SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 1::bigint; +SELECT is(parked, NULL, 'Is null by default') FROM gk_geokrety WHERE id = 1::bigint; +SELECT is(COUNT(*), 0::bigint) FROM gk_moves WHERE geokret = 1::bigint; +SELECT lives_ok($$UPDATE gk_geokrety SET parked='2024-05-24 00:00:01+00' WHERE id = 1::bigint$$); +SELECT is(parked, '2024-05-24 00:00:01+00') FROM gk_geokrety WHERE id = 1::bigint; +-- non_collectible flag is automatically set +SELECT is(non_collectible, '2024-05-24 00:00:01+00') FROM gk_geokrety WHERE id = 1::bigint; +SELECT is(owner, 1::bigint) FROM "gk_geokrety" WHERE id = 1::bigint; +SELECT is(holder, 1::bigint) FROM "gk_geokrety" WHERE id = 1::bigint; +SELECT is(COUNT(*), 1::bigint) FROM gk_moves WHERE geokret = 1::bigint; + +-- parked can be removed +SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "parked") VALUES (2, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:01+00')$$); +SELECT is(parked, '2024-05-24 00:00:01+00') FROM gk_geokrety WHERE id = 2::bigint; +SELECT is(non_collectible, '2024-05-24 00:00:01+00') FROM gk_geokrety WHERE id = 2::bigint; +SELECT is(COUNT(*), 1::bigint) FROM gk_moves WHERE geokret = 2::bigint; +UPDATE gk_geokrety SET parked=NULL WHERE id = 2::bigint; +SELECT is(parked, NULL) FROM gk_geokrety WHERE id = 2::bigint; +-- Non collectible is automatically removed +SELECT is(non_collectible, NULL) FROM gk_geokrety WHERE id = 2::bigint; +SELECT is(COUNT(*), 2::bigint) FROM gk_moves WHERE geokret = 2::bigint; + +-- non_collectible cannot be removed alone +SELECT lives_ok($$INSERT INTO "gk_geokrety" ("id", "name", "type", "created_on_datetime", "owner", "parked") VALUES (3, 'test', 0, '2024-05-24 00:00:00+00', 1, '2024-05-24 00:00:01+00')$$); +SELECT is(parked, '2024-05-24 00:00:01+00') FROM gk_geokrety WHERE id = 3::bigint; +SELECT is(COUNT(*), 1::bigint) FROM gk_moves WHERE geokret = 3::bigint; +UPDATE gk_geokrety SET non_collectible=NULL WHERE id = 3::bigint; +SELECT is(parked, '2024-05-24 00:00:01+00') FROM gk_geokrety WHERE id = 3::bigint; +-- Non collectible is automatically reverted +SELECT is(non_collectible, '2024-05-24 00:00:01+00') FROM gk_geokrety WHERE id = 3::bigint; +SELECT is(COUNT(*), 1::bigint) FROM gk_moves WHERE geokret = 3::bigint; + +-- Finish the tests and clean up. +SELECT * FROM finish(); +ROLLBACK;