-
Notifications
You must be signed in to change notification settings - Fork 0
[EDIFIKANA] #424 Common Area API contracts and backend services #462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
gaaliciA1990
wants to merge
8
commits into
main
Choose a base branch
from
alg/424_CommonArea_API_BE_Services
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
6329c70
[EDIFIKANA] #424 Updating existing network resposes with CommonAreaTy…
gaaliciA1990 04d45a7
[EDIFIKANA] #424 Adding CommonArea API, DS and Service
gaaliciA1990 bc687e0
[EDIFIKANA] #424 Adding CommonArea RBAC checks and new controller. Up…
gaaliciA1990 7480b48
[EDIFIKANA] #424 Adding CommonArea tests
gaaliciA1990 d820a6a
[EDIFIKANA] #424 Updating and fixing after running tests
gaaliciA1990 26812f7
[EDIFIKANA] Addressing PR feedback
gaaliciA1990 ef5a84c
[EDIFIKANA] Removing orgId as a param for CommonArea
gaaliciA1990 86f8322
[EDIFIKANA] Removing orgId as a param for CommonArea
gaaliciA1990 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
61 changes: 61 additions & 0 deletions
61
edifikana/api/src/commonMain/kotlin/com/cramsan/edifikana/api/CommonAreaApi.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package com.cramsan.edifikana.api | ||
|
|
||
| import com.cramsan.edifikana.lib.model.CommonAreaId | ||
| import com.cramsan.edifikana.lib.model.PropertyId | ||
| import com.cramsan.edifikana.lib.model.network.CommonAreaListNetworkResponse | ||
| import com.cramsan.edifikana.lib.model.network.CommonAreaNetworkResponse | ||
| import com.cramsan.edifikana.lib.model.network.CreateCommonAreaNetworkRequest | ||
| import com.cramsan.edifikana.lib.model.network.UpdateCommonAreaNetworkRequest | ||
| import com.cramsan.framework.annotations.NetworkModel | ||
| import com.cramsan.framework.annotations.api.NoPathParam | ||
| import com.cramsan.framework.annotations.api.NoQueryParam | ||
| import com.cramsan.framework.annotations.api.NoRequestBody | ||
| import com.cramsan.framework.annotations.api.NoResponseBody | ||
| import com.cramsan.framework.networkapi.Api | ||
| import io.ktor.http.HttpMethod | ||
|
|
||
| /** | ||
| * API definition for common area operations within a property. | ||
| * | ||
| * Common areas are shared spaces (e.g. Lobby, Pool, Gym) that belong to a single property. | ||
| * All operations require MANAGER role or higher in the property's organization, depending on | ||
| * the operation. In some cases it will be ADMIN+, in others it will be MANAGER+ | ||
| */ | ||
| @OptIn(NetworkModel::class) | ||
| object CommonAreaApi : Api("common-area") { | ||
|
|
||
| val createCommonArea = operation< | ||
| CreateCommonAreaNetworkRequest, | ||
| NoQueryParam, | ||
| NoPathParam, | ||
| CommonAreaNetworkResponse | ||
| >(HttpMethod.Post) | ||
|
|
||
| val getCommonArea = operation< | ||
| NoRequestBody, | ||
| NoQueryParam, | ||
| CommonAreaId, | ||
| CommonAreaNetworkResponse | ||
| >(HttpMethod.Get) | ||
|
|
||
| val getCommonAreasForProperty = operation< | ||
| NoRequestBody, | ||
| NoQueryParam, | ||
| PropertyId, | ||
| CommonAreaListNetworkResponse | ||
| >(HttpMethod.Get, "by-property") | ||
|
|
||
| val updateCommonArea = operation< | ||
| UpdateCommonAreaNetworkRequest, | ||
| NoQueryParam, | ||
| CommonAreaId, | ||
| CommonAreaNetworkResponse | ||
| >(HttpMethod.Put) | ||
|
|
||
| val deleteCommonArea = operation< | ||
| NoRequestBody, | ||
| NoQueryParam, | ||
| CommonAreaId, | ||
| NoResponseBody | ||
| >(HttpMethod.Delete) | ||
| } | ||
217 changes: 217 additions & 0 deletions
217
...cramsan/edifikana/server/datastore/supabase/SupabaseCommonAreaDatastoreIntegrationTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| package com.cramsan.edifikana.server.datastore.supabase | ||
|
|
||
| import com.cramsan.edifikana.lib.model.CommonAreaId | ||
| import com.cramsan.edifikana.lib.model.CommonAreaType | ||
| import com.cramsan.edifikana.lib.model.OrganizationId | ||
| import com.cramsan.edifikana.lib.model.PropertyId | ||
| import com.cramsan.edifikana.lib.model.UserId | ||
| import com.cramsan.framework.utils.uuid.UUID | ||
| import kotlinx.coroutines.runBlocking | ||
| import kotlin.test.BeforeTest | ||
| import kotlin.test.Test | ||
| import kotlin.test.assertEquals | ||
| import kotlin.test.assertNotNull | ||
| import kotlin.test.assertNull | ||
| import kotlin.test.assertTrue | ||
|
|
||
| class SupabaseCommonAreaDatastoreIntegrationTest : SupabaseIntegrationTest() { | ||
|
|
||
| private lateinit var testPrefix: String | ||
| private var propertyId: PropertyId? = null | ||
| private var testUserId: UserId? = null | ||
| private var orgId: OrganizationId? = null | ||
|
|
||
| @BeforeTest | ||
| fun setup() { | ||
| testPrefix = UUID.random() | ||
| runBlocking { | ||
| testUserId = createTestUser("user-${testPrefix}@test.com") | ||
| orgId = createTestOrganization("org_$testPrefix", "") | ||
| propertyId = createTestProperty("${testPrefix}_Property", testUserId!!, orgId!!) | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| fun `createCommonArea should return created common area`() = runCoroutineTest { | ||
| // Arrange | ||
|
|
||
| // Act | ||
| val result = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_Lobby", | ||
| type = CommonAreaType.LOBBY, | ||
| description = "Main entrance", | ||
| ).registerCommonAreaForDeletion() | ||
|
|
||
| // Assert | ||
| assertTrue(result.isSuccess) | ||
| val area = result.getOrNull() | ||
| assertNotNull(area) | ||
| assertEquals("${testPrefix}_Lobby", area.name) | ||
| assertEquals(CommonAreaType.LOBBY, area.type) | ||
| assertEquals("Main entrance", area.description) | ||
| assertEquals(propertyId, area.propertyId) | ||
| } | ||
|
|
||
| @Test | ||
| fun `getCommonArea should return created common area`() = runCoroutineTest { | ||
| // Arrange | ||
| val createResult = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_GetLobby", | ||
| type = CommonAreaType.LOBBY, | ||
| description = null, | ||
| ).registerCommonAreaForDeletion() | ||
| assertTrue(createResult.isSuccess) | ||
| val created = createResult.getOrNull()!! | ||
|
|
||
| // Act | ||
| val getResult = commonAreaDatastore.getCommonArea(created.id) | ||
|
|
||
| // Assert | ||
| assertTrue(getResult.isSuccess) | ||
| val fetched = getResult.getOrNull() | ||
| assertNotNull(fetched) | ||
| assertEquals("${testPrefix}_GetLobby", fetched.name) | ||
| assertEquals(created.id, fetched.id) | ||
| } | ||
|
|
||
| @Test | ||
| fun `getCommonArea should return null when not found`() = runCoroutineTest { | ||
| // Arrange | ||
| val fakeId = CommonAreaId(UUID.random()) | ||
|
|
||
| // Act | ||
| val result = commonAreaDatastore.getCommonArea(fakeId) | ||
|
|
||
| // Assert | ||
| assertTrue(result.isSuccess) | ||
| assertNull(result.getOrNull()) | ||
| } | ||
|
|
||
| @Test | ||
| fun `getCommonAreasForProperty should return all areas for property`() = runCoroutineTest { | ||
| // Arrange | ||
|
|
||
| // Act | ||
| val result1 = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_Pool", | ||
| type = CommonAreaType.POOL, | ||
| description = null, | ||
| ).registerCommonAreaForDeletion() | ||
| val result2 = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_Gym", | ||
| type = CommonAreaType.GYM, | ||
| description = null, | ||
| ).registerCommonAreaForDeletion() | ||
| assertTrue(result1.isSuccess) | ||
| assertTrue(result2.isSuccess) | ||
| val listResult = commonAreaDatastore.getCommonAreasForProperty(propertyId!!) | ||
|
|
||
| // Assert | ||
| assertTrue(listResult.isSuccess) | ||
| val areas = listResult.getOrNull() | ||
| assertNotNull(areas) | ||
| val names = areas.map { it.name } | ||
| assertTrue(names.contains("${testPrefix}_Pool")) | ||
| assertTrue(names.contains("${testPrefix}_Gym")) | ||
| } | ||
|
|
||
| @Test | ||
| fun `getCommonAreasForProperty should not return deleted areas`() = runCoroutineTest { | ||
| // Arrange | ||
| val createResult = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_Rooftop", | ||
| type = CommonAreaType.ROOFTOP, | ||
| description = null, | ||
| ).registerCommonAreaForDeletion() | ||
| assertTrue(createResult.isSuccess) | ||
| val area = createResult.getOrNull()!! | ||
| val deleteResult = commonAreaDatastore.deleteCommonArea(area.id) | ||
| assertTrue(deleteResult.isSuccess) | ||
|
|
||
| // Act | ||
| val listResult = commonAreaDatastore.getCommonAreasForProperty(propertyId!!) | ||
|
|
||
| // Assert | ||
| assertTrue(listResult.isSuccess) | ||
| val names = listResult.getOrNull()!!.map { it.name } | ||
| assertTrue(!names.contains("${testPrefix}_Rooftop")) | ||
| } | ||
|
|
||
| @Test | ||
| fun `updateCommonArea should update name and type`() = runCoroutineTest { | ||
| // Arrange | ||
| val createResult = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_OldName", | ||
| type = CommonAreaType.LOBBY, | ||
| description = "Original description", | ||
| ).registerCommonAreaForDeletion() | ||
| assertTrue(createResult.isSuccess) | ||
| val area = createResult.getOrNull()!! | ||
|
|
||
| // Act | ||
| val updateResult = commonAreaDatastore.updateCommonArea( | ||
| commonAreaId = area.id, | ||
| name = "${testPrefix}_NewName", | ||
| type = CommonAreaType.GYM, | ||
| description = null, | ||
| ) | ||
|
|
||
| // Assert | ||
| assertTrue(updateResult.isSuccess) | ||
| val updated = updateResult.getOrNull() | ||
| assertNotNull(updated) | ||
| assertEquals("${testPrefix}_NewName", updated.name) | ||
| assertEquals(CommonAreaType.GYM, updated.type) | ||
| } | ||
|
|
||
| @Test | ||
| fun `deleteCommonArea should soft delete and make area invisible`() = runCoroutineTest { | ||
| // Arrange | ||
| val createResult = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_ToDelete", | ||
| type = CommonAreaType.PARKING, | ||
| description = null, | ||
| ).registerCommonAreaForDeletion() | ||
| assertTrue(createResult.isSuccess) | ||
| val area = createResult.getOrNull()!! | ||
|
|
||
| // Act | ||
| val deleteResult = commonAreaDatastore.deleteCommonArea(area.id) | ||
|
|
||
| // Assert | ||
| assertTrue(deleteResult.isSuccess) | ||
| assertTrue(deleteResult.getOrNull() == true) | ||
| val getResult = commonAreaDatastore.getCommonArea(area.id) | ||
| assertTrue(getResult.isSuccess) | ||
| assertNull(getResult.getOrNull()) | ||
| } | ||
|
|
||
| @Test | ||
| fun `purgeCommonArea should hard delete the area`() = runCoroutineTest { | ||
| // Arrange | ||
| val createResult = commonAreaDatastore.createCommonArea( | ||
| propertyId = propertyId!!, | ||
| name = "${testPrefix}_ToPurge", | ||
| type = CommonAreaType.LAUNDRY, | ||
| description = null, | ||
| ) | ||
| assertTrue(createResult.isSuccess) | ||
| val area = createResult.getOrNull()!! | ||
|
|
||
| // Act | ||
| val purgeResult = commonAreaDatastore.purgeCommonArea(area.id) | ||
|
|
||
| // Assert | ||
| assertTrue(purgeResult.isSuccess) | ||
| val getResult = commonAreaDatastore.getCommonArea(area.id) | ||
| assertTrue(getResult.isSuccess) | ||
| assertNull(getResult.getOrNull()) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.