add assigned-asset, add more hosting-asset test-data and introduce HsBookingDebitor+hs_booking_debitor_rv #58
@ -18,7 +18,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
|||||||
|
|
||||||
// a partial HsOfficeDebitorEntity to reduce the number of SQL queries to load the entity
|
// a partial HsOfficeDebitorEntity to reduce the number of SQL queries to load the entity
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "hs_office_debitor_rv") // TODO.impl: create a readonly view for this, which also joins the partner-number?
|
@Table(name = "hs_booking_debitor_rv")
|
||||||
@Getter
|
@Getter
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@ -37,8 +37,8 @@ public class HsBookingDebitorEntity implements Stringifyable {
|
|||||||
@Id
|
@Id
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
|
|
||||||
@Column(name = "debitornumbersuffix", length = 2)
|
@Column(name = "debitornumber")
|
||||||
private String debitorNumberSuffix;
|
private Integer debitorNumber;
|
||||||
|
|
||||||
@Column(name = "defaultprefix", columnDefinition = "char(3) not null")
|
@Column(name = "defaultprefix", columnDefinition = "char(3) not null")
|
||||||
private String defaultPrefix;
|
private String defaultPrefix;
|
||||||
@ -50,6 +50,6 @@ public class HsBookingDebitorEntity implements Stringifyable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toShortString() {
|
public String toShortString() {
|
||||||
return DEBITOR_NUMBER_TAG + defaultPrefix;
|
return DEBITOR_NUMBER_TAG + debitorNumber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,5 @@ public interface HsBookingDebitorRepository extends Repository<HsBookingDebitorE
|
|||||||
|
|
||||||
Optional<HsBookingDebitorEntity> findByUuid(UUID id);
|
Optional<HsBookingDebitorEntity> findByUuid(UUID id);
|
||||||
|
|
||||||
List<HsBookingDebitorEntity> findByDefaultPrefix(String defaultPrefix);
|
List<HsBookingDebitorEntity> findByDefaultPrefix(String defaultPrefix); // FIXME: change to findByDebitorNumber
|
||||||
|
|
||||||
long count();
|
|
||||||
}
|
}
|
@ -202,6 +202,6 @@ public class HsBookingItemEntity implements Stringifyable, RbacObject, Validatab
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
rbac().generateWithBaseFileName("6-hs-booking/620-booking-item/6203-hs-booking-item-rbac");
|
rbac().generateWithBaseFileName("6-hs-booking/630-booking-item/6303-hs-booking-item-rbac");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.hs.booking.project;
|
package net.hostsharing.hsadminng.hs.booking.project;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.debitor.HsBookingDebitorRepository;
|
||||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.api.HsBookingProjectsApi;
|
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.api.HsBookingProjectsApi;
|
||||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectInsertResource;
|
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectInsertResource;
|
||||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectPatchResource;
|
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsBookingProjectPatchResource;
|
||||||
@ -12,8 +13,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class HsBookingProjectController implements HsBookingProjectsApi {
|
public class HsBookingProjectController implements HsBookingProjectsApi {
|
||||||
@ -27,6 +30,9 @@ public class HsBookingProjectController implements HsBookingProjectsApi {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private HsBookingProjectRepository bookingProjectRepo;
|
private HsBookingProjectRepository bookingProjectRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HsBookingDebitorRepository debitorRepo;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseEntity<List<HsBookingProjectResource>> listBookingProjectsByDebitorUuid(
|
public ResponseEntity<List<HsBookingProjectResource>> listBookingProjectsByDebitorUuid(
|
||||||
@ -50,7 +56,7 @@ public class HsBookingProjectController implements HsBookingProjectsApi {
|
|||||||
|
|
||||||
context.define(currentUser, assumedRoles);
|
context.define(currentUser, assumedRoles);
|
||||||
|
|
||||||
final var entityToSave = mapper.map(body, HsBookingProjectEntity.class);
|
final var entityToSave = mapper.map(body, HsBookingProjectEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
|
||||||
|
|
||||||
final var saved = bookingProjectRepo.save(entityToSave);
|
final var saved = bookingProjectRepo.save(entityToSave);
|
||||||
|
|
||||||
@ -111,4 +117,12 @@ public class HsBookingProjectController implements HsBookingProjectsApi {
|
|||||||
final var mapped = mapper.map(saved, HsBookingProjectResource.class);
|
final var mapped = mapper.map(saved, HsBookingProjectResource.class);
|
||||||
return ResponseEntity.ok(mapped);
|
return ResponseEntity.ok(mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final BiConsumer<HsBookingProjectInsertResource, HsBookingProjectEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
||||||
|
if (resource.getDebitorUuid() != null) {
|
||||||
|
entity.setDebitor(debitorRepo.findByUuid(resource.getDebitorUuid())
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException("ERROR: [400] debitorUuid %s not found".formatted(
|
||||||
|
resource.getDebitorUuid()))));
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,6 @@ public class HsBookingProjectEntity implements Stringifyable, RbacObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
rbac().generateWithBaseFileName("6-hs-booking/610-booking-project/6103-hs-booking-project-rbac");
|
rbac().generateWithBaseFileName("6-hs-booking/620-booking-project/6203-hs-booking-project-rbac");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
--liquibase formatted sql
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hs-booking-debitor-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
create view hs_booking_debitor_rv as
|
||||||
|
select debitor.uuid,
|
||||||
|
debitor.version,
|
||||||
|
(partner.partnerNumber::varchar || debitor.debitorNumberSuffix)::numeric as debitorNumber,
|
||||||
|
debitor.defaultPrefix
|
||||||
|
from hs_office_debitor_rv debitor
|
||||||
|
-- RBAC for debitor is sufficient, for faster access we are bypassing RBAC for the join tables
|
||||||
|
join hs_office_relation debitorRel on debitor.debitorReluUid=debitorRel.uuid
|
||||||
|
join hs_office_relation partnerRel on partnerRel.holderUuid=debitorRel.anchorUuid
|
||||||
|
join hs_office_partner partner on partner.partnerReluUid=partnerRel.uuid;
|
||||||
|
--//
|
@ -130,17 +130,19 @@ databaseChangeLog:
|
|||||||
- include:
|
- include:
|
||||||
file: db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql
|
file: db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/6-hs-booking/610-booking-project/6100-hs-booking-project.sql
|
file: db/changelog/6-hs-booking/610-booking-debitor/6100-hs-booking-debitor.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/6-hs-booking/610-booking-project/6103-hs-booking-project-rbac.sql
|
file: db/changelog/6-hs-booking/620-booking-project/6200-hs-booking-project.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/6-hs-booking/610-booking-project/6108-hs-booking-project-test-data.sql
|
file: db/changelog/6-hs-booking/620-booking-project/6203-hs-booking-project-rbac.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/6-hs-booking/620-booking-item/6200-hs-booking-item.sql
|
file: db/changelog/6-hs-booking/620-booking-project/6208-hs-booking-project-test-data.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/6-hs-booking/620-booking-item/6203-hs-booking-item-rbac.sql
|
file: db/changelog/6-hs-booking/630-booking-item/6200-hs-booking-item.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/6-hs-booking/620-booking-item/6208-hs-booking-item-test-data.sql
|
file: db/changelog/6-hs-booking/630-booking-item/6203-hs-booking-item-rbac.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/6-hs-booking/630-booking-item/6208-hs-booking-item-test-data.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql
|
file: db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql
|
||||||
- include:
|
- include:
|
||||||
|
@ -9,25 +9,25 @@ class HsBookingDebitorEntityTest {
|
|||||||
@Test
|
@Test
|
||||||
void toStringContainsDebitorNumberAndDefaultPrefix() {
|
void toStringContainsDebitorNumberAndDefaultPrefix() {
|
||||||
final var given = HsBookingDebitorEntity.builder()
|
final var given = HsBookingDebitorEntity.builder()
|
||||||
.debitorNumberSuffix("67")
|
.debitorNumber(1234567)
|
||||||
.defaultPrefix("som")
|
.defaultPrefix("som")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
final var result = given.toString();
|
final var result = given.toString();
|
||||||
|
|
||||||
assertThat(result).isEqualTo("booking-debitor(D-som: som)"); // FIXME: I want "booking-debitor(D-1000167: som)"
|
assertThat(result).isEqualTo("booking-debitor(D-1234567: som)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void toShortStringContainsDefaultPrefix() {
|
void toShortStringContainsDefaultPrefix() {
|
||||||
final var given = HsBookingDebitorEntity.builder()
|
final var given = HsBookingDebitorEntity.builder()
|
||||||
.debitorNumberSuffix("67")
|
.debitorNumber(1234567)
|
||||||
.defaultPrefix("som")
|
.defaultPrefix("som")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
final var result = given.toShortString();
|
final var result = given.toShortString();
|
||||||
|
|
||||||
assertThat(result).isEqualTo("D-som"); // FIXME: I want "booking-debitor(D-1000167: som)"
|
assertThat(result).isEqualTo("D-1234567");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,8 @@ import lombok.experimental.UtilityClass;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class TestHsBookingDebitor {
|
public class TestHsBookingDebitor {
|
||||||
|
|
||||||
public String DEFAULT_DEBITOR_SUFFIX = "00";
|
|
||||||
|
|
||||||
public static final HsBookingDebitorEntity TEST_BOOKING_DEBITOR = HsBookingDebitorEntity.builder()
|
public static final HsBookingDebitorEntity TEST_BOOKING_DEBITOR = HsBookingDebitorEntity.builder()
|
||||||
.debitorNumberSuffix(DEFAULT_DEBITOR_SUFFIX)
|
.debitorNumber(1234500)
|
||||||
.defaultPrefix("abc")
|
.defaultPrefix("abc")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -311,7 +311,7 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
assertThat(bookingItemRepo.findByUuid(givenBookingItem.getUuid())).isPresent().get()
|
assertThat(bookingItemRepo.findByUuid(givenBookingItem.getUuid())).isPresent().get()
|
||||||
.matches(mandate -> {
|
.matches(mandate -> {
|
||||||
assertThat(mandate.getProject().getDebitor().toString()).isEqualTo("booking-debitor(D-fir: fir)");
|
assertThat(mandate.getProject().getDebitor().toString()).isEqualTo("booking-debitor(D-1000111: fir)");
|
||||||
assertThat(mandate.getValidFrom()).isEqualTo("2022-11-01");
|
assertThat(mandate.getValidFrom()).isEqualTo("2022-11-01");
|
||||||
assertThat(mandate.getValidTo()).isEqualTo("2022-12-31");
|
assertThat(mandate.getValidTo()).isEqualTo("2022-12-31");
|
||||||
return true;
|
return true;
|
||||||
|
@ -29,14 +29,14 @@ class HsBookingItemEntityUnitTest {
|
|||||||
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
||||||
final var result = givenBookingItem.toString();
|
final var result = givenBookingItem.toString();
|
||||||
|
|
||||||
assertThat(result).isEqualTo("HsBookingItemEntity(D-abc:test project, CLOUD_SERVER, [2020-01-01,2031-01-01), some caption, { CPUs: 2, HDD-storage: 2048, SSD-storage: 512 })");
|
assertThat(result).isEqualTo("HsBookingItemEntity(D-1234500:test project, CLOUD_SERVER, [2020-01-01,2031-01-01), some caption, { CPUs: 2, HDD-storage: 2048, SSD-storage: 512 })");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void toShortStringContainsOnlyMemberNumberAndCaption() {
|
void toShortStringContainsOnlyMemberNumberAndCaption() {
|
||||||
final var result = givenBookingItem.toShortString();
|
final var result = givenBookingItem.toShortString();
|
||||||
|
|
||||||
assertThat(result).isEqualTo("D-abc:test project:some caption");
|
assertThat(result).isEqualTo("D-1234500:test project:some caption");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -174,9 +174,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
// then
|
// then
|
||||||
allTheseBookingItemsAreReturned(
|
allTheseBookingItemsAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsBookingItemEntity(D-sec:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SDD: 512, Traffic: 12 })",
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SDD: 512, Traffic: 12 })",
|
||||||
"HsBookingItemEntity(D-sec:D-1000212 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })",
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })",
|
||||||
"HsBookingItemEntity(D-sec:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })");
|
"HsBookingItemEntity(D-1000212:D-1000212 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -194,9 +194,9 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
// then:
|
// then:
|
||||||
exactlyTheseBookingItemsAreReturned(
|
exactlyTheseBookingItemsAreReturned(
|
||||||
result,
|
result,
|
||||||
"HsBookingItemEntity(D-fir:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })",
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_SERVER, [2022-10-01,), separate ManagedServer, { CPUs: 2, RAM: 8, SDD: 512, Traffic: 42 })",
|
||||||
"HsBookingItemEntity(D-fir:D-1000111 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SDD: 512, Traffic: 12 })",
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, MANAGED_WEBSPACE, [2022-10-01,), some ManagedWebspace, { Daemons: 2, Multi: 4, SDD: 512, Traffic: 12 })",
|
||||||
"HsBookingItemEntity(D-fir:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })");
|
"HsBookingItemEntity(D-1000111:D-1000111 default project, PRIVATE_CLOUD, [2024-04-01,), some PrivateCloud, { CPUs: 10, HDD: 10240, SDD: 10240, Traffic: 42 })");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ class HsBookingProjectControllerAcceptanceTest extends ContextBasedTestWithClean
|
|||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
assertThat(bookingProjectRepo.findByUuid(givenBookingProject.getUuid())).isPresent().get()
|
assertThat(bookingProjectRepo.findByUuid(givenBookingProject.getUuid())).isPresent().get()
|
||||||
.matches(mandate -> {
|
.matches(mandate -> {
|
||||||
assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(D-1000111: rel(anchor='LP First GmbH', type='DEBITOR', holder='LP First GmbH'), fir)");
|
assertThat(mandate.getDebitor().toString()).isEqualTo("booking-debitor(D-1000111: fir)");
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ class HsBookingProjectEntityUnitTest {
|
|||||||
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
void toStringContainsAllPropertiesAndResourcesSortedByKey() {
|
||||||
final var result = givenBookingProject.toString();
|
final var result = givenBookingProject.toString();
|
||||||
|
|
||||||
assertThat(result).isEqualTo("HsBookingProjectEntity(D-1000100, some caption)");
|
assertThat(result).isEqualTo("HsBookingProjectEntity(D-1234500, some caption)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void toShortStringContainsOnlyMemberNumberAndCaption() {
|
void toShortStringContainsOnlyMemberNumberAndCaption() {
|
||||||
final var result = givenBookingProject.toShortString();
|
final var result = givenBookingProject.toShortString();
|
||||||
|
|
||||||
assertThat(result).isEqualTo("D-1000100:some caption");
|
assertThat(result).isEqualTo("D-1234500:some caption");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user