Skip to content

Commit

Permalink
5755-app - Create endpoint to directly insert invoice candidates
Browse files Browse the repository at this point in the history
* starting to work on lookup/retrieval-code for masterdata (BPartner) and ICs
#5755
  • Loading branch information
metas-ts committed Nov 5, 2019
1 parent fa94098 commit ddc1094
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 56 deletions.
Expand Up @@ -4,7 +4,6 @@

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;

Expand All @@ -14,8 +13,6 @@
import org.adempiere.ad.table.RecordChangeLogEntry;
import org.adempiere.ad.table.RecordChangeLogRepository;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.util.Env;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
Expand All @@ -24,7 +21,6 @@
import de.metas.bpartner.BPGroupId;
import de.metas.bpartner.BPGroupRepository;
import de.metas.bpartner.BPartnerContactId;
import de.metas.bpartner.BPartnerId;
import de.metas.bpartner.GLN;
import de.metas.bpartner.composite.BPartner;
import de.metas.bpartner.composite.BPartnerComposite;
Expand All @@ -44,8 +40,6 @@
import de.metas.greeting.Greeting;
import de.metas.greeting.GreetingRepository;
import de.metas.i18n.Language;
import de.metas.organization.OrgId;
import de.metas.rest_api.JsonExternalId;
import de.metas.rest_api.MetasfreshId;
import de.metas.rest_api.bpartner.response.JsonResponseBPartner;
import de.metas.rest_api.bpartner.response.JsonResponseComposite;
Expand All @@ -56,6 +50,7 @@
import de.metas.rest_api.changelog.JsonChangeInfo.JsonChangeInfoBuilder;
import de.metas.rest_api.changelog.JsonChangeLogItem;
import de.metas.rest_api.changelog.JsonChangeLogItem.JsonChangeLogItemBuilder;
import de.metas.rest_api.utils.BPartnerQueryService;
import de.metas.rest_api.utils.IdentifierString;
import de.metas.rest_api.utils.JsonConverters;
import de.metas.user.UserId;
Expand Down Expand Up @@ -164,6 +159,7 @@ public class JsonRetrieverService
.put(BPartnerLocationType.SHIP_TO_DEFAULT, JsonResponseLocation.SHIP_TO_DEFAULT)
.build();

private final transient BPartnerQueryService bPartnerQueryService;
private final transient BPartnerCompositeRepository bpartnerCompositeRepository;
private final transient BPGroupRepository bpGroupRepository;

Expand All @@ -176,12 +172,14 @@ public class JsonRetrieverService
private final String identifier;

public JsonRetrieverService(
@NonNull final BPartnerQueryService bPartnerQueryService,
@NonNull final BPartnerCompositeRepository bpartnerCompositeRepository,
@NonNull final BPGroupRepository bpGroupRepository,
@NonNull final GreetingRepository greetingRepository,
@NonNull final RecordChangeLogRepository recordChangeLogRepository,
@NonNull final String identifier)
{
this.bPartnerQueryService = bPartnerQueryService;
this.bpartnerCompositeRepository = bpartnerCompositeRepository;
this.bpGroupRepository = bpGroupRepository;
this.greetingRepository = greetingRepository;
Expand Down Expand Up @@ -418,22 +416,24 @@ Optional<BPartnerComposite> getBPartnerCompositeAssertCacheHit(@NonNull final Im

private ImmutableMap<BPartnerCompositeLookupKey, BPartnerComposite> retrieveBPartnerComposites(@NonNull final Collection<BPartnerCompositeLookupKey> queryLookupKeys)
{
final OrgId onlyOrgId = Env.getOrgId(); // FIXME avoid using Env.getOrgId();
final BPartnerQuery query = createBPartnerQuery(queryLookupKeys, onlyOrgId);

final List<BPartnerComposite> byQuery = bpartnerCompositeRepository.getByQuery(query);
if (byQuery.size() > 1)
final BPartnerQuery query = bPartnerQueryService.createQuery(queryLookupKeys);
final Optional<BPartnerComposite> byQuery;
try
{
byQuery = bpartnerCompositeRepository.getSingleByQuery(query);
}
catch (AdempiereException e)
{
throw new AdempiereException("The given lookup keys needs to yield max one BPartnerComposite; items yielded instead: " + byQuery.size())
throw new AdempiereException("The given lookup keys needs to yield max one BPartnerComposite; multiple items yielded instead", e)
.appendParametersToMessage()
.setParameter("BPartnerIdLookupKeys", queryLookupKeys);
}
if (byQuery.isEmpty())
if (!byQuery.isPresent())
{
return ImmutableMap.of();
}

final BPartnerComposite singleElement = CollectionUtils.singleElement(byQuery);
final BPartnerComposite singleElement = byQuery.get();

final HashSet<BPartnerCompositeLookupKey> allLookupKeys = new HashSet<>(queryLookupKeys);
allLookupKeys.addAll(extractBPartnerLookupKeys(singleElement));
Expand All @@ -446,43 +446,6 @@ private ImmutableMap<BPartnerCompositeLookupKey, BPartnerComposite> retrieveBPar
return result.build();
}

private static BPartnerQuery createBPartnerQuery(
@NonNull final Collection<BPartnerCompositeLookupKey> bpartnerLookupKeys,
@NonNull final OrgId onlyOrgId)
{
final BPartnerQuery.BPartnerQueryBuilder query = BPartnerQuery.builder()
.onlyOrgId(onlyOrgId);

for (final BPartnerCompositeLookupKey bpartnerLookupKey : bpartnerLookupKeys)
{
final JsonExternalId jsonExternalId = bpartnerLookupKey.getJsonExternalId();
if (jsonExternalId != null)
{
query.externalId(JsonConverters.fromJsonOrNull(jsonExternalId));
}

final String value = bpartnerLookupKey.getCode();
if (!isEmpty(value, true))
{
query.bpartnerValue(value);
}

final GLN gln = bpartnerLookupKey.getGln();
if (gln != null)
{
query.gln(gln);
}

final MetasfreshId metasfreshId = bpartnerLookupKey.getMetasfreshId();
if (metasfreshId != null)
{
query.bPartnerId(BPartnerId.ofRepoId(metasfreshId.getValue()));
}
}

return query.build();
}

private static final Collection<BPartnerCompositeLookupKey> extractBPartnerLookupKeys(@NonNull final BPartnerComposite bPartnerComposite)
{
final ImmutableList.Builder<BPartnerCompositeLookupKey> result = ImmutableList.builder();
Expand Down
@@ -1,9 +1,23 @@
package de.metas.rest_api.invoicecandidates.impl;

import java.util.Optional;

import org.adempiere.exceptions.AdempiereException;
import org.springframework.stereotype.Service;

import de.metas.bpartner.composite.BPartnerComposite;
import de.metas.bpartner.composite.repository.BPartnerCompositeRepository;
import de.metas.bpartner.service.BPartnerQuery;
import de.metas.rest_api.bpartner.impl.bpartnercomposite.BPartnerCompositeLookupKey;
import de.metas.rest_api.invoicecandidates.request.JsonRequestInvoiceCandidateUpsert;
import de.metas.rest_api.invoicecandidates.request.JsonRequestInvoiceCandidateUpsertItem;
import de.metas.rest_api.invoicecandidates.response.JsonResponseInvoiceCandidateUpsert;
import de.metas.rest_api.invoicecandidates.response.JsonResponseInvoiceCandidateUpsert.JsonResponseInvoiceCandidateUpsertBuilder;
import de.metas.rest_api.invoicecandidates.response.JsonResponseInvoiceCandidateUpsertItem;
import de.metas.rest_api.invoicecandidates.response.JsonResponseInvoiceCandidateUpsertItem.JsonResponseInvoiceCandidateUpsertItemBuilder;
import de.metas.rest_api.utils.BPartnerQueryService;
import de.metas.rest_api.utils.IdentifierString;
import lombok.NonNull;

/*
* #%L
Expand All @@ -18,11 +32,11 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
Expand All @@ -31,10 +45,53 @@
public class JsonInvoiceCandidateUpsertService
{

public JsonResponseInvoiceCandidateUpsert createOrUpdateInvoiceCandidates(JsonRequestInvoiceCandidateUpsert request)
// private final transient IBPartnerDAO bpartnerDAO = Services.get(IBPartnerDAO.class);
private final transient BPartnerQueryService bPartnerQueryService;
private BPartnerCompositeRepository bpartnerCompositeRepository;

private JsonInvoiceCandidateUpsertService(
@NonNull final BPartnerQueryService bPartnerQueryService,
@NonNull final BPartnerCompositeRepository bpartnerCompositeRepository)
{
this.bPartnerQueryService = bPartnerQueryService;
this.bpartnerCompositeRepository = bpartnerCompositeRepository;
}

public JsonResponseInvoiceCandidateUpsert createOrUpdateInvoiceCandidates(@NonNull final JsonRequestInvoiceCandidateUpsert request)
{
// TODO Auto-generated method stub
return null;
final JsonResponseInvoiceCandidateUpsertBuilder result = JsonResponseInvoiceCandidateUpsert.builder();
for (final JsonRequestInvoiceCandidateUpsertItem item : request.getRequestItems())
{

final IdentifierString bpartnerIdentifier = IdentifierString.of(item.getBillPartnerIdentifier());
final BPartnerCompositeLookupKey bpartnerIdLookupKey = BPartnerCompositeLookupKey.ofIdentifierString(bpartnerIdentifier);
final BPartnerQuery query = bPartnerQueryService.createQueryFailIfNotExists(bpartnerIdLookupKey);

final JsonResponseInvoiceCandidateUpsertItemBuilder responseItem = JsonResponseInvoiceCandidateUpsertItem.builder();

final Optional<BPartnerComposite> bpartnerComposite;
try
{
bpartnerComposite = bpartnerCompositeRepository.getSingleByQuery(query);
}
catch (AdempiereException e)
{
throw new AdempiereException("The given lookup keys needs to yield max one BPartnerComposite; multiple items yielded instead", e)
.appendParametersToMessage()
.setParameter("BillPartnerIdentifier", item.getBillPartnerIdentifier());
}

if(!bpartnerComposite.isPresent())
{
// TODO we can still update existing ICs, but not create new ones
// TODO if we were able to look up an existing IC and item.getBillLocationIdentifier() and/or item.getBillContactIdentifier() are set

}

result.responseItem(responseItem.build());
}

return result.build();
}

}
@@ -0,0 +1,104 @@
package de.metas.rest_api.utils;

import static de.metas.util.Check.isEmpty;

import java.util.Collection;

import org.compiere.util.Env;
import org.springframework.stereotype.Service;

import de.metas.bpartner.BPartnerId;
import de.metas.bpartner.GLN;
import de.metas.bpartner.service.BPartnerQuery;
import de.metas.organization.OrgId;
import de.metas.rest_api.JsonExternalId;
import de.metas.rest_api.MetasfreshId;
import de.metas.rest_api.bpartner.impl.bpartnercomposite.BPartnerCompositeLookupKey;
import lombok.NonNull;

/*
* #%L
* de.metas.business.rest-api-impl
* %%
* Copyright (C) 2019 metas GmbH
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/

@Service
public class BPartnerQueryService
{
public BPartnerQuery createQuery(@NonNull final Collection<BPartnerCompositeLookupKey> queryLookupKeys)
{
final OrgId onlyOrgId = Env.getOrgId(); // FIXME avoid using Env.getOrgId();
return createBPartnerQuery(queryLookupKeys, onlyOrgId);
}

public BPartnerQuery createQueryFailIfNotExists(@NonNull final BPartnerCompositeLookupKey queryLookupKey)
{
final OrgId onlyOrgId = Env.getOrgId(); // FIXME avoid using Env.getOrgId();

final BPartnerQuery.BPartnerQueryBuilder queryBuilder = BPartnerQuery.builder()
.onlyOrgId(onlyOrgId)
.failIfNotExists(true);
addKeyToQueryBuilder(queryLookupKey, queryBuilder);

return queryBuilder.build();
}

private static BPartnerQuery createBPartnerQuery(
@NonNull final Collection<BPartnerCompositeLookupKey> bpartnerLookupKeys,
@NonNull final OrgId onlyOrgId)
{
final BPartnerQuery.BPartnerQueryBuilder query = BPartnerQuery.builder()
.onlyOrgId(onlyOrgId);

for (final BPartnerCompositeLookupKey bpartnerLookupKey : bpartnerLookupKeys)
{
addKeyToQueryBuilder(bpartnerLookupKey, query);
}

return query.build();
}

private static void addKeyToQueryBuilder(final BPartnerCompositeLookupKey bpartnerLookupKey, final BPartnerQuery.BPartnerQueryBuilder queryBuilder)
{
final JsonExternalId jsonExternalId = bpartnerLookupKey.getJsonExternalId();
if (jsonExternalId != null)
{
queryBuilder.externalId(JsonConverters.fromJsonOrNull(jsonExternalId));
}

final String value = bpartnerLookupKey.getCode();
if (!isEmpty(value, true))
{
queryBuilder.bpartnerValue(value);
}

final GLN gln = bpartnerLookupKey.getGln();
if (gln != null)
{
queryBuilder.gln(gln);
}

final MetasfreshId metasfreshId = bpartnerLookupKey.getMetasfreshId();
if (metasfreshId != null)
{
queryBuilder.bPartnerId(BPartnerId.ofRepoId(metasfreshId.getValue()));
}
}

}
Expand Up @@ -215,6 +215,18 @@ public ImmutableList<BPartnerComposite> getByQuery(@NonNull final BPartnerQuery
return getByIds(bpartnerIds);
}

public Optional<BPartnerComposite> getSingleByQuery(@NonNull final BPartnerQuery query)
{
final ImmutableList<BPartnerComposite> byQuery = getByQuery(query);
if (byQuery.size() > 1)
{
throw new AdempiereException("The given query needs to yield max one BPartnerComposite; items yielded instead: " + byQuery.size())
.appendParametersToMessage()
.setParameter("BPartnerQuery", query);
}
return Optional.ofNullable(CollectionUtils.singleElementOrNull(byQuery));
}

private ImmutableSet<BPartnerId> getIdsByQuery(@NonNull final BPartnerQuery query)
{
return bpartnersRepo.retrieveBPartnerIdsBy(query);
Expand Down

0 comments on commit ddc1094

Please sign in to comment.