Compare commits

..

No commits in common. "6365d344abdcd9f1837b0d1dfaf311a867682887" and "48f4cf8ed67aca95263992472057683765b3b2ea" have entirely different histories.

11 changed files with 42 additions and 233 deletions

View File

@ -2,7 +2,8 @@ package net.hostsharing.hsadminng.hs.office.coopassets;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeCoopAssetsApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeCoopAssetsApi;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionInsertResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionResource;
import net.hostsharing.hsadminng.mapper.Mapper; import net.hostsharing.hsadminng.mapper.Mapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
@ -12,13 +13,11 @@ 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 jakarta.validation.ValidationException; import jakarta.validation.ValidationException;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer;
import static java.lang.String.join; import static java.lang.String.join;
import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.*; import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.*;
@ -64,11 +63,8 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
context.define(currentUser, assumedRoles); context.define(currentUser, assumedRoles);
validate(requestBody); validate(requestBody);
final var entityToSave = mapper.map(requestBody, HsOfficeCoopAssetsTransactionEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); final var entityToSave = mapper.map(requestBody, HsOfficeCoopAssetsTransactionEntity.class);
if (entityToSave.getReverseEntry() != null) {
entityToSave.getReverseEntry().setReverseEntry(entityToSave);
}
final var saved = coopAssetsTransactionRepo.save(entityToSave); final var saved = coopAssetsTransactionRepo.save(entityToSave);
final var uri = final var uri =
@ -135,10 +131,4 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
} }
} }
final BiConsumer<HsOfficeCoopAssetsTransactionInsertResource, HsOfficeCoopAssetsTransactionEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { }
if ( resource.getReverseEntryUuid() != null ) {
entity.setReverseEntry(coopAssetsTransactionRepo.findByUuid(resource.getReverseEntryUuid())
.orElseThrow(() -> new EntityNotFoundException("ERROR: [400] reverseEntityUuid %s not found".formatted(resource.getReverseEntryUuid()))));
}
};
};

View File

@ -50,7 +50,6 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, RbacO
.withProp(HsOfficeCoopAssetsTransactionEntity::getAssetValue) .withProp(HsOfficeCoopAssetsTransactionEntity::getAssetValue)
.withProp(HsOfficeCoopAssetsTransactionEntity::getReference) .withProp(HsOfficeCoopAssetsTransactionEntity::getReference)
.withProp(HsOfficeCoopAssetsTransactionEntity::getComment) .withProp(HsOfficeCoopAssetsTransactionEntity::getComment)
.withProp(at -> ofNullable(at.getReverseEntry()).map(HsOfficeCoopAssetsTransactionEntity::toShortString).orElse(null))
.quotedValues(false); .quotedValues(false);
@Id @Id
@ -94,13 +93,6 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, RbacO
@Column(name = "comment") @Column(name = "comment")
private String comment; private String comment;
/**
* Optionally, the UUID of the corresponding transaction for an adjustment transaction,
* linked in both directions.
*/
@OneToOne
@JoinColumn(name = "reverseentryuuid")
private HsOfficeCoopAssetsTransactionEntity reverseEntry;
public String getTaggedMemberNumber() { public String getTaggedMemberNumber() {
return ofNullable(membership).map(HsOfficeMembershipEntity::toShortString).orElse("M-?????"); return ofNullable(membership).map(HsOfficeMembershipEntity::toShortString).orElse("M-?????");

View File

@ -19,13 +19,7 @@ import org.hibernate.annotations.JoinFormula;
import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction; import org.hibernate.annotations.NotFoundAction;
import jakarta.persistence.Column; import jakarta.persistence.*;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.Version; import jakarta.persistence.Version;
import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Pattern;
import java.io.IOException; import java.io.IOException;

View File

@ -32,30 +32,6 @@ components:
type: string type: string
comment: comment:
type: string type: string
reverseEntry:
$ref: '#/components/schemas/HsOfficeCoopAssetsTransactionReverse'
HsOfficeCoopAssetsTransactionReverse:
description:
Similar to `HsOfficeCoopAssetsTransaction` but without the `reverseEntry`,
otherwise the JSON would be recursive.
type: object
properties:
uuid:
type: string
format: uuid
transactionType:
$ref: '#/components/schemas/HsOfficeCoopAssetsTransactionType'
assetValue:
type: number
format: currency
valueDate:
type: string
format: date
reference:
type: string
comment:
type: string
HsOfficeCoopAssetsTransactionInsert: HsOfficeCoopAssetsTransactionInsert:
type: object type: object
@ -78,9 +54,6 @@ components:
maxLength: 48 maxLength: 48
comment: comment:
type: string type: string
reverseEntryUuid:
type: string
format: uuid
required: required:
- membershipUuid - membershipUuid
- transactionType - transactionType

View File

@ -17,41 +17,15 @@ CREATE CAST (character varying as HsOfficeCoopAssetsTransactionType) WITH INOUT
create table if not exists hs_office_coopassetstransaction create table if not exists hs_office_coopassetstransaction
( (
uuid uuid unique references RbacObject (uuid) initially deferred, uuid uuid unique references RbacObject (uuid) initially deferred,
version int not null default 0, version int not null default 0,
membershipUuid uuid not null references hs_office_membership(uuid), membershipUuid uuid not null references hs_office_membership(uuid),
transactionType HsOfficeCoopAssetsTransactionType not null, transactionType HsOfficeCoopAssetsTransactionType not null,
valueDate date not null, valueDate date not null,
assetValue money not null, assetValue money,
reference varchar(48) not null, reference varchar(48),
reverseEntryUuid uuid references hs_office_coopassetstransaction (uuid) deferrable , comment varchar(512)
comment varchar(512)
); );
alter table hs_office_coopassetstransaction
add constraint hs_office_coopassetstransaction_reverse_entry_missing
check ( transactionType != 'ADJUSTMENT' or reverseEntryUuid is not null);
CREATE OR REPLACE FUNCTION hs_office_coopassetstransaction_reverse_entry_is_reciprocal_tf()
RETURNS TRIGGER
LANGUAGE plpgsql AS $$
BEGIN
IF NEW.reverseEntryUuid IS NULL
OR NEW.uuid IN (SELECT other.reverseEntryUuid
FROM hs_office_coopassetstransaction other
WHERE other.uuid = NEW.reverseEntryUuid
AND NEW.membershipUuid = other.membershipUuid)
THEN
RETURN NEW;
END IF;
RAISE EXCEPTION 'reverseEntryUuid must refer to a row that has a reference back to this row and belongs to the same membership';
END; $$;
-- FIXME: why does this not work?
-- CREATE TRIGGER hs_office_coopassetstransaction_reverse_entry_is_reciprocal_tg
-- AFTER INSERT OR UPDATE ON hs_office_coopassetstransaction
-- FOR EACH ROW EXECUTE FUNCTION hs_office_coopassetstransaction_reverse_entry_is_reciprocal_tf();
--// --//
-- ============================================================================ -- ============================================================================

View File

@ -14,14 +14,11 @@ create or replace procedure createHsOfficeCoopAssetsTransactionTestData(
) )
language plpgsql as $$ language plpgsql as $$
declare declare
currentTask varchar; currentTask varchar;
membership hs_office_membership; membership hs_office_membership;
lossEntryUuid uuid;
adjustmentEntryUuid uuid;
begin begin
currentTask = 'creating coopAssetsTransaction test-data ' || givenPartnerNumber || givenMemberNumberSuffix; currentTask = 'creating coopAssetsTransaction test-data ' || givenPartnerNumber || givenMemberNumberSuffix;
execute format('set local hsadminng.currentTask to %L', currentTask); execute format('set local hsadminng.currentTask to %L', currentTask);
SET CONSTRAINTS ALL DEFERRED;
call defineContext(currentTask); call defineContext(currentTask);
select m.uuid select m.uuid
@ -32,15 +29,12 @@ begin
into membership; into membership;
raise notice 'creating test coopAssetsTransaction: %', givenPartnerNumber || givenMemberNumberSuffix; raise notice 'creating test coopAssetsTransaction: %', givenPartnerNumber || givenMemberNumberSuffix;
lossEntryUuid := uuid_generate_v4();
adjustmentEntryUuid := uuid_generate_v4();
insert insert
into hs_office_coopassetstransaction(uuid, membershipuuid, transactiontype, valuedate, assetvalue, reference, comment, reverseEntryUuid) into hs_office_coopassetstransaction(uuid, membershipuuid, transactiontype, valuedate, assetvalue, reference, comment)
values values
(uuid_generate_v4(), membership.uuid, 'DEPOSIT', '2010-03-15', 320.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-1', 'initial deposit', null), (uuid_generate_v4(), membership.uuid, 'DEPOSIT', '2010-03-15', 320.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-1', 'initial deposit'),
(uuid_generate_v4(), membership.uuid, 'DISBURSAL', '2021-09-01', -128.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-2', 'partial disbursal', null), (uuid_generate_v4(), membership.uuid, 'DISBURSAL', '2021-09-01', -128.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-2', 'partial disbursal'),
(lossEntryUuid, membership.uuid, 'LOSS', '2022-10-20', -128.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-3', 'some loss', adjustmentEntryUuid), (uuid_generate_v4(), membership.uuid, 'ADJUSTMENT', '2022-10-20', 128.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-3', 'some adjustment');
(adjustmentEntryUuid, membership.uuid, 'ADJUSTMENT', '2022-10-21', 128.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-3', 'some adjustment', lossEntryUuid);
end; $$; end; $$;
--// --//

View File

@ -22,7 +22,6 @@ import jakarta.persistence.PersistenceContext;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.UUID; import java.util.UUID;
import static net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionType.LOSS;
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid; import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
import static net.hostsharing.test.JsonMatcher.lenientlyEquals; import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -70,7 +69,7 @@ class HsOfficeCoopAssetsTransactionControllerAcceptanceTest extends ContextBased
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
.body("", hasSize(12)); // @formatter:on .body("", hasSize(9)); // @formatter:on
} }
@Test @Test
@ -104,17 +103,10 @@ class HsOfficeCoopAssetsTransactionControllerAcceptanceTest extends ContextBased
"reference": "ref 1000202-2", "reference": "ref 1000202-2",
"comment": "partial disbursal" "comment": "partial disbursal"
}, },
{
"transactionType": "LOSS",
"assetValue": -128.00,
"valueDate": "2022-10-20",
"reference": "ref 1000202-3",
"comment": "some loss"
},
{ {
"transactionType": "ADJUSTMENT", "transactionType": "ADJUSTMENT",
"assetValue": 128.00, "assetValue": 128.00,
"valueDate": "2022-10-21", "valueDate": "2022-10-20",
"reference": "ref 1000202-3", "reference": "ref 1000202-3",
"comment": "some adjustment" "comment": "some adjustment"
} }
@ -201,66 +193,6 @@ class HsOfficeCoopAssetsTransactionControllerAcceptanceTest extends ContextBased
assertThat(newUserUuid).isNotNull(); assertThat(newUserUuid).isNotNull();
} }
@Test
void globalAdmin_canAddCoopAssetsAdjustmentTransaction() {
context.define("superuser-alex@hostsharing.net");
final var givenMembership = membershipRepo.findMembershipByMemberNumber(1000101);
final var givenTransaction = coopAssetsTransactionRepo.findCoopAssetsTransactionByOptionalMembershipUuidAndDateRange(givenMembership.getUuid(), null, null)
.stream().filter(at -> at.getTransactionType() == LOSS)
.findFirst()
.orElseThrow();
final var location = RestAssured // @formatter:off
.given()
.header("current-user", "superuser-alex@hostsharing.net")
.contentType(ContentType.JSON)
.body("""
{
"membershipUuid": "%s",
"transactionType": "ADJUSTMENT",
"assetValue": %s,
"valueDate": "2022-10-30",
"reference": "temp ref A",
"comment": "some coop assets adjustment transaction",
"reverseEntryUuid": "%s"
}
""".formatted(
givenMembership.getUuid(),
givenTransaction.getAssetValue().negate().toString(),
givenTransaction.getUuid()))
.port(port)
.when()
.post("http://localhost/api/hs/office/coopassetstransactions")
.then().log().all().assertThat()
.statusCode(201)
.contentType(ContentType.JSON)
.body("uuid", isUuidValid())
.body("", lenientlyEquals("""
{
"transactionType": "ADJUSTMENT",
"assetValue": 128.00,
"valueDate": "2022-10-30",
"reference": "temp ref A",
"comment": "some coop assets adjustment transaction",
"reverseEntry": {
"transactionType": "LOSS",
"assetValue": -128.00,
"valueDate": "2022-10-20",
"reference": "ref 1000101-3",
"comment": "some loss"
}
}
""".formatted(givenTransaction.getUuid())))
.header("Location", startsWith("http://localhost"))
.extract().header("Location"); // @formatter:on
// finally, the new coopAssetsTransaction can be accessed under the generated UUID
final var newUserUuid = UUID.fromString(
location.substring(location.lastIndexOf('/') + 1));
assertThat(newUserUuid).isNotNull();
}
@Test @Test
void globalAdmin_canNotCancelMoreAssetsThanCurrentlySubscribed() { void globalAdmin_canNotCancelMoreAssetsThanCurrentlySubscribed() {

View File

@ -16,36 +16,14 @@ class HsOfficeCoopAssetsTransactionEntityUnitTest {
.valueDate(LocalDate.parse("2020-01-01")) .valueDate(LocalDate.parse("2020-01-01"))
.transactionType(HsOfficeCoopAssetsTransactionType.DEPOSIT) .transactionType(HsOfficeCoopAssetsTransactionType.DEPOSIT)
.assetValue(new BigDecimal("128.00")) .assetValue(new BigDecimal("128.00"))
.comment("some comment")
.build(); .build();
final HsOfficeCoopAssetsTransactionEntity givenCoopAssetAdjustmentTransaction = HsOfficeCoopAssetsTransactionEntity.builder()
.membership(TEST_MEMBERSHIP)
.reference("some-ref")
.valueDate(LocalDate.parse("2020-01-15"))
.transactionType(HsOfficeCoopAssetsTransactionType.ADJUSTMENT)
.assetValue(new BigDecimal("-128.00"))
.comment("some comment")
.reverseEntry(givenCoopAssetTransaction)
.build();
final HsOfficeCoopAssetsTransactionEntity givenEmptyCoopAssetsTransaction = HsOfficeCoopAssetsTransactionEntity.builder().build(); final HsOfficeCoopAssetsTransactionEntity givenEmptyCoopAssetsTransaction = HsOfficeCoopAssetsTransactionEntity.builder().build();
@Test @Test
void toStringContainsAllNonNullProperties() { void toStringContainsAlmostAllPropertiesAccount() {
final var result = givenCoopAssetTransaction.toString(); final var result = givenCoopAssetTransaction.toString();
assertThat(result).isEqualTo("CoopAssetsTransaction(M-1000101: 2020-01-01, DEPOSIT, 128.00, some-ref, some comment)"); assertThat(result).isEqualTo("CoopAssetsTransaction(M-1000101: 2020-01-01, DEPOSIT, 128.00, some-ref)");
}
@Test
void toStringWithReverseEntryContainsReverseEntry() {
givenCoopAssetTransaction.setReverseEntry(givenCoopAssetAdjustmentTransaction);
final var result = givenCoopAssetTransaction.toString();
assertThat(result).isEqualTo("CoopAssetsTransaction(M-1000101: 2020-01-01, DEPOSIT, 128.00, some-ref, some comment, M-1000101:-128.00)");
} }
@Test @Test

View File

@ -127,7 +127,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
class FindAllCoopAssetsTransactions { class FindAllCoopAssetsTransactions {
@Test @Test
public void globalAdmin_canViewAllCoopAssetsTransactions() { public void globalAdmin_anViewAllCoopAssetsTransactions() {
// given // given
context("superuser-alex@hostsharing.net"); context("superuser-alex@hostsharing.net");
@ -138,22 +138,19 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
null); null);
// then // then
exactlyTheseCoopAssetsTransactionsAreReturned( allTheseCoopAssetsTransactionsAreReturned(
result, result,
"CoopAssetsTransaction(M-1000101: 2010-03-15, DEPOSIT, 320.00, ref 1000101-1, initial deposit)", "CoopAssetsTransaction(M-1000101: 2010-03-15, DEPOSIT, 320.00, ref 1000101-1, initial deposit)",
"CoopAssetsTransaction(M-1000101: 2021-09-01, DISBURSAL, -128.00, ref 1000101-2, partial disbursal)", "CoopAssetsTransaction(M-1000101: 2021-09-01, DISBURSAL, -128.00, ref 1000101-2, partial disbursal)",
"CoopAssetsTransaction(M-1000101: 2022-10-20, LOSS, -128.00, ref 1000101-3, some loss, M-1000101:+128.00)", "CoopAssetsTransaction(M-1000101: 2022-10-20, ADJUSTMENT, 128.00, ref 1000101-3, some adjustment)",
"CoopAssetsTransaction(M-1000101: 2022-10-21, ADJUSTMENT, 128.00, ref 1000101-3, some adjustment, M-1000101:-128.00)",
"CoopAssetsTransaction(M-1000202: 2010-03-15, DEPOSIT, 320.00, ref 1000202-1, initial deposit)", "CoopAssetsTransaction(M-1000202: 2010-03-15, DEPOSIT, 320.00, ref 1000202-1, initial deposit)",
"CoopAssetsTransaction(M-1000202: 2021-09-01, DISBURSAL, -128.00, ref 1000202-2, partial disbursal)", "CoopAssetsTransaction(M-1000202: 2021-09-01, DISBURSAL, -128.00, ref 1000202-2, partial disbursal)",
"CoopAssetsTransaction(M-1000202: 2022-10-20, LOSS, -128.00, ref 1000202-3, some loss, M-1000202:+128.00)", "CoopAssetsTransaction(M-1000202: 2022-10-20, ADJUSTMENT, 128.00, ref 1000202-3, some adjustment)",
"CoopAssetsTransaction(M-1000202: 2022-10-21, ADJUSTMENT, 128.00, ref 1000202-3, some adjustment, M-1000202:-128.00)",
"CoopAssetsTransaction(M-1000303: 2010-03-15, DEPOSIT, 320.00, ref 1000303-1, initial deposit)", "CoopAssetsTransaction(M-1000303: 2010-03-15, DEPOSIT, 320.00, ref 1000303-1, initial deposit)",
"CoopAssetsTransaction(M-1000303: 2021-09-01, DISBURSAL, -128.00, ref 1000303-2, partial disbursal)", "CoopAssetsTransaction(M-1000303: 2021-09-01, DISBURSAL, -128.00, ref 1000303-2, partial disbursal)",
"CoopAssetsTransaction(M-1000303: 2022-10-20, LOSS, -128.00, ref 1000303-3, some loss, M-1000303:+128.00)", "CoopAssetsTransaction(M-1000303: 2022-10-20, ADJUSTMENT, 128.00, ref 1000303-3, some adjustment)");
"CoopAssetsTransaction(M-1000303: 2022-10-21, ADJUSTMENT, 128.00, ref 1000303-3, some adjustment, M-1000303:-128.00)");
} }
@Test @Test
@ -169,12 +166,11 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
null); null);
// then // then
exactlyTheseCoopAssetsTransactionsAreReturned( allTheseCoopAssetsTransactionsAreReturned(
result, result,
"CoopAssetsTransaction(M-1000202: 2010-03-15, DEPOSIT, 320.00, ref 1000202-1, initial deposit)", "CoopAssetsTransaction(M-1000202: 2010-03-15, DEPOSIT, 320.00, ref 1000202-1, initial deposit)",
"CoopAssetsTransaction(M-1000202: 2021-09-01, DISBURSAL, -128.00, ref 1000202-2, partial disbursal)", "CoopAssetsTransaction(M-1000202: 2021-09-01, DISBURSAL, -128.00, ref 1000202-2, partial disbursal)",
"CoopAssetsTransaction(M-1000202: 2022-10-20, LOSS, -128.00, ref 1000202-3, some loss, M-1000202:+128.00)", "CoopAssetsTransaction(M-1000202: 2022-10-20, ADJUSTMENT, 128.00, ref 1000202-3, some adjustment)");
"CoopAssetsTransaction(M-1000202: 2022-10-21, ADJUSTMENT, 128.00, ref 1000202-3, some adjustment, M-1000202:-128.00)");
} }
@Test @Test
@ -211,8 +207,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
result, result,
"CoopAssetsTransaction(M-1000101: 2010-03-15, DEPOSIT, 320.00, ref 1000101-1, initial deposit)", "CoopAssetsTransaction(M-1000101: 2010-03-15, DEPOSIT, 320.00, ref 1000101-1, initial deposit)",
"CoopAssetsTransaction(M-1000101: 2021-09-01, DISBURSAL, -128.00, ref 1000101-2, partial disbursal)", "CoopAssetsTransaction(M-1000101: 2021-09-01, DISBURSAL, -128.00, ref 1000101-2, partial disbursal)",
"CoopAssetsTransaction(M-1000101: 2022-10-20, LOSS, -128.00, ref 1000101-3, some loss, M-1000101:+128.00)", "CoopAssetsTransaction(M-1000101: 2022-10-20, ADJUSTMENT, 128.00, ref 1000101-3, some adjustment)");
"CoopAssetsTransaction(M-1000101: 2022-10-21, ADJUSTMENT, 128.00, ref 1000101-3, some adjustment, M-1000101:-128.00)");
} }
} }

View File

@ -387,16 +387,16 @@ public class ImportOfficeData extends ContextBasedTest {
assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace("""
{ {
30000=CoopAssetsTransaction(M-1001700: 2000-12-06, DEPOSIT, 1280.00, legacy data import, for subscription A), 30000=CoopAssetsTransaction(M-1001700: 2000-12-06, DEPOSIT, 1280.00, for subscription A),
31000=CoopAssetsTransaction(M-1002000: 2000-12-06, DEPOSIT, 128.00, legacy data import, for subscription B), 31000=CoopAssetsTransaction(M-1002000: 2000-12-06, DEPOSIT, 128.00, for subscription B),
32000=CoopAssetsTransaction(M-1001700: 2005-01-10, DEPOSIT, 2560.00, legacy data import, for subscription C), 32000=CoopAssetsTransaction(M-1001700: 2005-01-10, DEPOSIT, 2560.00, for subscription C),
33001=CoopAssetsTransaction(M-1001700: 2005-01-10, TRANSFER, -512.00, legacy data import, for transfer to 10), 33001=CoopAssetsTransaction(M-1001700: 2005-01-10, TRANSFER, -512.00, for transfer to 10),
33002=CoopAssetsTransaction(M-1002000: 2005-01-10, ADOPTION, 512.00, legacy data import, for transfer from 7), 33002=CoopAssetsTransaction(M-1002000: 2005-01-10, ADOPTION, 512.00, for transfer from 7),
34001=CoopAssetsTransaction(M-1002000: 2016-12-31, CLEARING, -8.00, legacy data import, for cancellation D), 34001=CoopAssetsTransaction(M-1002000: 2016-12-31, CLEARING, -8.00, for cancellation D),
34002=CoopAssetsTransaction(M-1002000: 2016-12-31, DISBURSAL, -100.00, legacy data import, for cancellation D), 34002=CoopAssetsTransaction(M-1002000: 2016-12-31, DISBURSAL, -100.00, for cancellation D),
34003=CoopAssetsTransaction(M-1002000: 2016-12-31, LOSS, -20.00, legacy data import, for cancellation D), 34003=CoopAssetsTransaction(M-1002000: 2016-12-31, LOSS, -20.00, for cancellation D),
35001=CoopAssetsTransaction(M-1909000: 2024-01-15, DEPOSIT, 128.00, legacy data import, for subscription E, M-1909000:-128.00), 35001=CoopAssetsTransaction(M-1909000: 2024-01-15, DEPOSIT, 128.00, for subscription E),
35002=CoopAssetsTransaction(M-1909000: 2024-01-20, ADJUSTMENT, -128.00, legacy data import, chargeback for subscription E, M-1909000:+128.00) 35002=CoopAssetsTransaction(M-1909000: 2024-01-20, ADJUSTMENT, -128.00, chargeback for subscription E)
} }
"""); """);
} }
@ -849,21 +849,8 @@ public class ImportOfficeData extends ContextBasedTest {
.transactionType(assetTypeMapping.get(rec.getString("action"))) .transactionType(assetTypeMapping.get(rec.getString("action")))
.assetValue(rec.getBigDecimal("amount")) .assetValue(rec.getBigDecimal("amount"))
.comment(rec.getString("comment")) .comment(rec.getString("comment"))
.reference("legacy data import") // TODO.spec: or use value from comment column?
.build(); .build();
if (assetTransaction.getTransactionType() == HsOfficeCoopAssetsTransactionType.ADJUSTMENT) {
final var negativeValue = assetTransaction.getAssetValue().negate();
final var reverseEntry = coopAssets.values().stream().filter(a ->
a.getTransactionType() != HsOfficeCoopAssetsTransactionType.ADJUSTMENT &&
a.getMembership() == assetTransaction.getMembership() &&
a.getAssetValue().equals(negativeValue))
.findAny()
.orElseThrow(() -> new IllegalStateException("cannot determine asset reverse entry for adjustment " + assetTransaction));
reverseEntry.setReverseEntry(assetTransaction);
assetTransaction.setReverseEntry(reverseEntry);
}
coopAssets.put(rec.getInteger("member_asset_id"), assetTransaction); coopAssets.put(rec.getInteger("member_asset_id"), assetTransaction);
}); });
} }

View File

@ -6,7 +6,7 @@ spring:
datasource: datasource:
url-tc: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers url-tc: jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers
url-local: jdbc:postgresql://localhost:5432/postgres url-local: jdbc:postgresql://localhost:5432/postgres
url: ${spring.datasource.url-local} url: ${spring.datasource.url-tc}
username: postgres username: postgres
password: password password: password