class BankAccountController {
public void changeBaProduct(BaProduct baProduct, EJBContext context) {
try {
final BaProductData oldBaProduct = new BaProductController().findBaProductCompleteWithBaProductTypeAndAdmin(data.getPrimKey(), context);
oldBaProduct.setBaProductGeneralTermsData(new BaProductGeneralTermsTableManager().
findBaProductGeneralTerms(oldBaProduct.getBaProductGeneralTermsData().getPrimKey(), context));
if (oldBaProduct.getBaProductTypeData().isHasOverdraftTerms()) {
oldBaProduct.setBaProductOverdraftTermsData(new BaProductOverdraftTermsTableManager().
findBaProductOverdraftTerms(oldBaProduct.getBaProductOverdraftTermsData().getPrimKey(), context));
}
if (data.isLoanAccount()) {
oldBaProduct.setBaProductLoanTermsData(new BaProductLoanTermsTableManager().
findBaProductLoanTerms(oldBaProduct.getBaProductLoanTermsData().getPrimKey(), context));
}
if (data.isParticipationAccount()) {
oldBaProduct.setBaProductParticipationTermsData(new BaProductParticipationTermsTableManager().
findBaProductParticipationTerms(oldBaProduct.getBaProductParticipationTermsData().getPrimKey(), context));
}
if (data.isGuaranteeAccount()) {
oldBaProduct.setBaProductGuaranteeTermsData(new BaProductGuaranteeTermsTableManager().
findBaProductGuaranteeTerms(oldBaProduct.getBaProductGuaranteeTermsData().getPrimKey(), context));
}
// in BaProductChangeEventTableManager we need the _original_ ProductData from
// the database, so we need retrieve and fill it here
oldBaProduct.setProductData(new ProductTableManager().findProductCompleteWithProductTypeAndAdmin(oldBaProduct.getPrimKey(), context));
// Now change the 'ancestor' product
ProductData product = data.getProductData();
// Prepare for validation (set validationAdministrationId and/or validationCountryId), also related objects
data.prepareForValidation();
if (product != null) {
product = new ProductTableManager().changeProduct(product, context);
} else {
throw new ApplicationException("The BaProductData needs a ProductData to exist.");
}
final String administrationID = data.getBaProductTypeData().getBaAdministrationData().getAdministrationID();
// Change BaProduct
data.determineTotalBlockForNoIdentityCheck();
data.suppressStatementCreationIfApplicable();
data.determineSignatureCardStatusForAccount();
final BaProductData newData = changeRecord(data, context);
//copy values of original object
newData.setProposals(data.getProposals());
newData.setProductTypeChange(data.isProductTypeChange());
// Some values on 'data' are used later to generate changeevents according to newData.
// These values are temporary and not persisted to the database, so we
// should hand them over manually
newData.setInterestValueDateForChangeEvent(data.getInterestValueDateForChangeEvent());
newData.setConfigurationRemarkForChangeEvent(data.getConfigurationRemarkForChangeEvent());
// Apply changes of the product object to the new BaProduct object
newData.setProductData(product);
// Make sure that BaProductType is passed on to the new data
newData.setBaProductTypeData(data.getBaProductTypeData());
// Change BaProductGeneralTermsData
if (data.getBaProductGeneralTermsData() != null) {
if (data.getBaProductGeneralTermsData().isNewRecord()) {
newData.setBaProductGeneralTermsDataWithBackReference(new BaProductGeneralTermsTableManager().
createBaProductGeneralTerms(data.getBaProductGeneralTermsData(), context));
} else {
newData.setBaProductGeneralTermsDataWithBackReference(new BaProductGeneralTermsTableManager().
changeBaProductGeneralTerms(data.getBaProductGeneralTermsData(), context));
}
} // generalterms are never removed, so no remove call required
// Change BaProductOverdraftTerms object
if (data.getBaProductOverdraftTermsData() != null) {
if (data.getBaProductOverdraftTermsData().isNewRecord()) {
if (data.isProductTypeChange()) {
newData.setBaProductOverdraftTermsDataWithBackReference(new BaProductOverdraftTermsTableManager().
createBaProductOverdraftTermsForProductTypeChange(data.getBaProductOverdraftTermsData(), context));
} else {
newData.setBaProductOverdraftTermsDataWithBackReference(new BaProductOverdraftTermsTableManager().
createBaProductOverdraftTerms(data.getBaProductOverdraftTermsData(), context));
}
} else {
newData.setBaProductOverdraftTermsDataWithBackReference(new BaProductOverdraftTermsTableManager().
changeBaProductOverdraftTerms(data.getBaProductOverdraftTermsData(), context));
}
} else if (oldBaProduct.getBaProductOverdraftTermsData() != null) {
new BaProductOverdraftTermsTableManager().removeBaProductOverdraftTerms(
oldBaProduct.getBaProductOverdraftTermsData().getPrimKey(), context);
}
// Change BaProductCharges object
final BaProductChargesData userCharges = data.getBaProductChargesData();
if (userCharges != null) {
if (userCharges.isNewRecord()) {
// If the old productType does not allow charges and the new productType does, but for some reason the product
// already has charges, we need to update these charges instead of create a new charges object (which would fail).
BaProductChargesData newCharges = null;
try {
BaProductChargesData oldCharges = new BaProductChargesTableManager().findBaProductCharges(data.getPrimKey(), ServerContext.getDummyContext());
// Since no exception was thrown, the product itself *does* have charges, so we update these instead of
// creating new charges. First we should copy some properties from the original charges object to the new
// charges object.
userCharges.setCreateDate(oldCharges.getCreateDate());
userCharges.setCreateUser(oldCharges.getCreateUser());
userCharges.setChangeDate(oldCharges.getChangeDate());
userCharges.setChangeUser(oldCharges.getChangeUser());
userCharges.setRowVersion(oldCharges.getRowVersion());
newCharges = new BaProductChargesTableManager().changeBaProductCharges(userCharges, context);
} catch (TritonFinderException ignored) {
// The product itself has no charges either, so we can create a new Charges object.
newCharges = new BaProductChargesTableManager().createBaProductCharges(userCharges, context);
} finally {
newData.setBaProductChargesDataWithBackReference(newCharges);
}
} else {
newData.setBaProductChargesDataWithBackReference(new BaProductChargesTableManager().changeBaProductCharges(userCharges, context));
}
} else if (oldBaProduct.getBaProductChargesData() != null) {
// First, remove all BaProductBatchCharges records for the account.
new BaProductBatchChargesTableManager().removeBaProductBatchChargesForProduct(product.getProductID(), context);
new BaProductChargesTableManager().removeBaProductCharges(
oldBaProduct.getBaProductChargesData().getPrimKey(), context);
}
if (data.isBaProductTypeHasCharges() &&
data.getBaProductTypeData().getBaProductTypeChargesData() != null &&
data.getBaProductTypeData().getBaProductTypeChargesData().isHasChargesUK()) {
BaProductChargesUKData newChargesUKData = data.getBaProductChargesUKData();
if (newChargesUKData != null) {
final BaProductChargesUKData chargesUKData = new BaProductChargesUKTableManager().find(data.getPrimKey(), context);
chargesUKData.setSuppressChargeUDD(newChargesUKData.isSuppressChargeUDD());
chargesUKData.setSuppressChargeMonthlyFee(newChargesUKData.isSuppressChargeMonthlyFee());
chargesUKData.setSuppressChargeUnpaidCheques(newChargesUKData.isSuppressChargeUnpaidCheques());
chargesUKData.setSuppressChargeStatementCopy(newChargesUKData.isSuppressChargeStatementCopy());
chargesUKData.setSuppressChargeCopyOfRecords(newChargesUKData.isSuppressChargeCopyOfRecords());
chargesUKData.setSuppressChargeStoppedCheque(newChargesUKData.isSuppressChargeStoppedCheque());
chargesUKData.setSuppressChargeCHAPS(newChargesUKData.isSuppressChargeCHAPS());
chargesUKData.setSuppressChargeForeign(newChargesUKData.isSuppressChargeForeign());
new BaProductChargesUKTableManager().save(chargesUKData, context);
}
}
// Change BaProductDirectDebit object
if (data.getBaProductDirectDebitData() != null) {
if (data.getBaProductDirectDebitData().isNewRecord()) {
newData.setBaProductDirectDebitDataWithBackReference(new BaProductDirectDebitTableManager().
create(data.getBaProductDirectDebitData(), context));
} else {
newData.setBaProductDirectDebitDataWithBackReference(new BaProductDirectDebitTableManager().
change(data.getBaProductDirectDebitData(), context));
}
} else if (oldBaProduct.getBaProductDirectDebitData() != null) {
new BaProductDirectDebitTableManager().remove(
oldBaProduct.getBaProductDirectDebitData().getPrimKey(), context);
}
// Change BaProductCreditRisk object
if (data.getBaProductCreditRiskData() != null) {
if (data.getBaProductCreditRiskData().isNewRecord()) {
newData.setBaProductCreditRiskDataWithBackReference(new BaProductCreditRiskTableManager().
create(data.getBaProductCreditRiskData(), context));
} else {
newData.setBaProductCreditRiskData(new BaProductCreditRiskTableManager().
change(data.getBaProductCreditRiskData(), context));
}
} else if (oldBaProduct.getBaProductCreditRiskData() != null) {
// TODO -- Do we need a remove for Credit Risk objects??!?!
// new BaProductCreditRiskTableManager().remove(oldBaProduct.getBaProductCreditRiskData().getPrimKey(), context);
}
// Change BaProductChequeBook object
if (data.getBaProductChequeBookData() != null) {
if (data.getBaProductChequeBookData().isNewRecord()) {
newData.setBaProductChequeBookDataWithBackReference(new BaProductChequeBookTableManager().
createBaProductChequeBook(data.getBaProductChequeBookData(), context));
} else {
newData.setBaProductChequeBookDataWithBackReference(new BaProductChequeBookTableManager().
changeBaProductChequeBook(data.getBaProductChequeBookData(), administrationID, context));
}
}
// Change BaProductCreditBook object
if (data.getBaProductCreditBookData() != null) {
if (data.getBaProductCreditBookData().isNewRecord()) {
newData.setBaProductCreditBookDataWithBackReference(new BaProductCreditBookTableManager().
createBaProductCreditBook(data.getBaProductCreditBookData(), administrationID, context));
} else {
newData.setBaProductCreditBookDataWithBackReference(new BaProductCreditBookTableManager().
changeBaProductCreditBook(data.getBaProductCreditBookData(), administrationID, context));
}
}
final boolean isNL = AdministrationConstants.isBankNL(newData.getProductData().getProductTypeData().getAdministrationID());
final boolean totalBlockForNoIdentityCheckChanged = oldBaProduct.isHasTotalBlockForNoIdentityChk() != newData.isHasTotalBlockForNoIdentityChk();
// Change BaProductStatementTermsData
final BaProductStatementTermsData baProductStatementTermsData = data.getBaProductStatementTermsData();
if (baProductStatementTermsData != null) {
if (isNL && totalBlockForNoIdentityCheckChanged && !newData.isHasTotalBlockForNoIdentityChk()) {
baProductStatementTermsData.setSuppressCreate(false);
}
if (baProductStatementTermsData.isNewRecord()) {
// Creating a baProductStatementTerms record also results in creation of a new 'Reserved' statement
// If the administration uses periodical statements the periodBeginDate of the statment has to be
// filled with the date of product type change
LocalDate periodBeginDate = null;
if (newData.getBaProductTypeData().getBaAdministrationData().isHasPeriodOnStatement()) {
periodBeginDate = newData.getProductData().getLastProductTypeChangeDate();
}
newData.setBaProductStatementTermsDataWithBackReference(new BaProductStatementTermsTableManager().
createBaProductStatementTerms(baProductStatementTermsData, periodBeginDate, context));
} else {
// update BaProductStatementTerms
if (newData.getBaProductTypeData().getBaAdministrationData().isHasPeriodOnStatement() &&
!baProductStatementTermsData.isSuppressCreate() &&
oldBaProduct.getBaProductStatementTermsData().isSuppressCreate()) {
// The admin uses fixed periods on statements and SuppressCreate is switched off:
// --------------------------------------------------------------------------------
// The upcoming statement will contain only change events belonging to the period for which the
// periodEndDate is calculated as nextCreateDueDate - 1 day.
// When the statement was suppressed for a long time the nextCreateDueDate is way in the past.
// We need to set the nextCreateDueDate to the begin date of the current period to prevent
// the change events created while suppression was active will be split-up over 2 statements (see OBI-1085).
LocalDate newNextCreateDueDate =
StatementUtil.calculateBeginDateOfCurrentPeriod(administrationID,
TDate.today(),
baProductStatementTermsData.getCreateFrequency(),
baProductStatementTermsData.getCreateDayOfWeek1(),
baProductStatementTermsData.getCreateDateOfMonth1());
// Safety check: only update nextCreateDueDate when new calculated day is after the 'original' nextCreateDueDate
if (newNextCreateDueDate != null &&
newNextCreateDueDate.isAfter(oldBaProduct.getBaProductStatementTermsData().getNextCreateDueDate())) {
baProductStatementTermsData.setNextCreateDueDate(newNextCreateDueDate);
}
}
newData.setBaProductStatementTermsDataWithBackReference(new BaProductStatementTermsTableManager().
changeBaProductStatementTerms(baProductStatementTermsData, context));
}
// Also set changed BaProductStatementTerms on the old data object, because later on a reference
// to BaProductStatementTerms may be retrieved and changed through the old data again, which else
// causes an update conflict.
data.setBaProductStatementTermsDataWithBackReference(newData.getBaProductStatementTermsData());
} else if (oldBaProduct.getBaProductStatementTermsData() != null) {
new BaProductStatementTermsTableManager().
removeBaProductStatementTerms(oldBaProduct.getBaProductStatementTermsData().getPrimKey(), context);
}
// Change BaProductCodaboxStatementTermsData
if (data.getBaProductCodaboxStatementTerms() != null) {
BaProductCodaboxStatementTermsData codaboxTerms = data.getBaProductCodaboxStatementTerms();
new BaProductCodaboxStatementTermsTableManager().changeCodaboxStatementTerms(codaboxTerms, context);
}
// Change BaProductTelFaxEmail
if (data.getBaProductTelFaxEmailData() != null) {
if (data.getBaProductTelFaxEmailData().isNewRecord()) {
newData.setBaProductTelFaxEmailData(new BaProductTelFaxEmailTableManager().
createBaProductTelFaxEmail(data.getBaProductTelFaxEmailData(), context));
} else {
newData.setBaProductTelFaxEmailData(new BaProductTelFaxEmailTableManager().
changeBaProductTelFaxEmail(data.getBaProductTelFaxEmailData(), context));
}
} else if (oldBaProduct.getBaProductTelFaxEmailData() != null) {
new BaProductTelFaxEmailTableManager().removeBaProductTelFaxEmail(
oldBaProduct.getBaProductTelFaxEmailData().getPrimKey(), context);
}
// Change BaProductTxExportTerms
if (data.getBaProductTxExportTermsData() != null) {
if (data.getBaProductTxExportTermsData().isNewRecord()) {
newData.setBaProductTxExportTermsData(new BaProductTxExportTermsTableManager().
createBaProductTxExportTerms(data.getBaProductTxExportTermsData(), context));
} else {
newData.setBaProductTxExportTermsData(new BaProductTxExportTermsTableManager().
changeBaProductTxExportTerms(data.getBaProductTxExportTermsData(), context));
}
} else if (oldBaProduct.getBaProductTxExportTermsData() != null) {
new BaProductTxExportTermsTableManager().removeBaProductTxExportTerms(
oldBaProduct.getBaProductTxExportTermsData().getPrimKey(), context);
}
// Change BaProductLoanTerms object
if (data.getBaProductLoanTermsData() != null) {
Validate.isTrue(!data.getBaProductLoanTermsData().isNewRecord(), "you can't add loan terms to an existing account");
newData.setBaProductLoanTermsDataWithBackReference(new BaProductLoanTermsTableManager().changeBaProductLoanTerms(data.getBaProductLoanTermsData(), context));
} else {
Validate.isTrue(oldBaProduct.getBaProductLoanTermsData() == null, "you can't remove the loan terms of an account");
}
// Change BaProductParticipationTerms object
if (data.getBaProductParticipationTermsData() != null) {
if (data.getBaProductParticipationTermsData().isNewRecord()) {
newData.setBaProductParticipationTermsDataWithBackReference(new BaProductParticipationTermsTableManager().
createBaProductParticipationTerms(data.getBaProductParticipationTermsData(), context));
} else {
newData.setBaProductParticipationTermsDataWithBackReference(new BaProductParticipationTermsTableManager().
changeBaProductParticipationTerms(data.getBaProductParticipationTermsData(), context));
}
} else if (oldBaProduct.getBaProductParticipationTermsData() != null) {
new BaProductParticipationTermsTableManager().removeBaProductParticipationTerms(
oldBaProduct.getBaProductParticipationTermsData().getPrimKey(), context);
}
// Change BaProductGuaranteeTerms object
if (data.getBaProductGuaranteeTermsData() != null) {
if (data.getBaProductGuaranteeTermsData().isNewRecord()) {
newData.setBaProductGuaranteeTermsDataWithBackReference(new BaProductGuaranteeTermsTableManager().
createBaProductGuaranteeTerms(data.getBaProductGuaranteeTermsData(), context));
} else {
newData.setBaProductGuaranteeTermsDataWithBackReference(new BaProductGuaranteeTermsTableManager().
changeBaProductGuaranteeTerms(data.getBaProductGuaranteeTermsData(), context));
}
} else if (oldBaProduct.getBaProductGuaranteeTermsData() != null) {
new BaProductGuaranteeTermsTableManager().removeBaProductGuaranteeTerms(
oldBaProduct.getBaProductGuaranteeTermsData().getPrimKey(), context);
}
// Change BaProductISA object
if (data.getBaProductISAData() != null) {
if (data.getBaProductISAData().isNewRecord()) {
newData.setBaProductISADataWithBackReference(new BaProductISATableManager().
createBaProductISA(data.getBaProductISAData(), context));
} else {
if (isaDeclarationStateChangedToComplete(data, oldBaProduct)) {
data.getBaProductISAData().setDeclarationChannel(BaProductISATableManager.determineDeclarationChannel(context));
data.getBaProductISAData().setDeclaredBy(ServerContext.getLoginName(context));
}
newData.setBaProductISADataWithBackReference(new BaProductISATableManager().
changeBaProductISA(data.getBaProductISAData(), context));
}
new BankAccountController().closeIsaRedeclarationRemoteUserMessagesIfApplicable(data.getProductData(), context);
} else if (oldBaProduct.getBaProductISAData() != null) {
new BaProductISATableManager().removeBaProductISA(
oldBaProduct.getBaProductISAData().getPrimKey(), context);
}
// Create InternetAccountData object.
// Cannot be changed, must always be changed with a change proposal.
// Cannot be removed, the end date must be set when it isn't an internet account anymore.
// This is done with a change proposal.
if (data.getInternetAccountData() != null) {
data.getInternetAccountData().setProductID(newData.getProductID());
if (data.getInternetAccountData().isNewRecord()) {
newData.setInternetAccountDataWithBackReference(new InternetAccountTableManager().
createInternetAccountWithCounterAccounts(data.getInternetAccountData(), context));
} else {
// Though the InternetAccountData will not be changed, the counteraccount list should be.
new InternetAccountTableManager().updateInternetAccountCounterAccountList(data.getInternetAccountData(),
data.getInternetAccountData().getInternetAccountCounterAccountList(),
context);
// And the rejected add proposals.
new InternetAccountTableManager().updateInternetAccountCounterAccountChangeProposalList(data.getInternetAccountData(),
data.getInternetAccountData().getInternetAccountCounterAccountChangeProposalList(),
context);
// Set the old InternetAccountData is the newData.
newData.setInternetAccountData(data.getInternetAccountData());
}
}
if (isNL && data.getProductData().getInternetProductData() != null) {
newData.getProductData().setInternetProductData(new InternetProductTableManager().changeInternetProduct(data.getProductData().getInternetProductData(), context));
}
// Change BaProductClearingNL object
if (data.getBaProductClearingNLData() != null) {
if (data.getBaProductClearingNLData().isNewRecord()) {
newData.setBaProductClearingNLDataWithBackReference(new BaProductClearingNLTableManager().
create(data.getBaProductClearingNLData(), context));
} else {
newData.setBaProductClearingNLDataWithBackReference(new BaProductClearingNLTableManager().
change(data.getBaProductClearingNLData(), context));
}
} else if (oldBaProduct.getBaProductClearingNLData() != null) {
new BaProductClearingNLTableManager().remove(
oldBaProduct.getBaProductClearingNLData().getPrimKey(), context);
}
// Note: updating BaProductCardTerms list (is never done via the normal wizard).
// Copy the list from the original object, since we need it below.
newData.setBaProductCardTermsList(data.getBaProductCardTermsList());
// Note: updating BaProductCard list (is never done via the normal wizard).
// Copy the list from the original object, since we need it below.
newData.setBaProductCardList(data.getBaProductCardList());
// Signature card is received? Call PA143 (other blockparams are checked in BA036 Execute proposal Change Block)
if (new SignatureCardService(administrationID).hasSignatureStatusOnProductLevel() &&
oldBaProduct.getSignatureCard().isBlocking() && !newData.getSignatureCard().isBlocking()) {
// signatureCard changed into received or not required
// reset transaction state to entry approved
new PaymentsController().resetTransactionStateToEntryApproved(
newData.getProductData().getProductTypeData().getAdministrationID(), newData.getProductID(), false, context);
}
if (isNL && newData.isCurrentAccount()) {
updateCardTerms(oldBaProduct, newData, context);
}
final boolean isUK = AdministrationConstants.isBankUK(newData.getProductData().getProductTypeData().getAdministrationID());
if (isUK && newData.isCurrentAccount()) {
removeRedundantCardHolderRoles(oldBaProduct, newData, context);
updateCardsUK(oldBaProduct, newData, context);
}
// Automatically add counter accounts to savings accounts if hasTotalBlockForIdentityCheck has changed to not blocking
if (isNL && totalBlockForNoIdentityCheckChanged && !newData.isHasTotalBlockForNoIdentityChk()) {
CounterAccountLinker.link(data, context);
}
// Create BaProductFixedTermContract list
if (data.getBaProductFixedTermContractList() != null) {
newData.setBaProductFixedTermContractList(new BaProductFixedTermContractTableManager().
updateBaFixedTermContractListForBaProduct(data, context));
} // BA459 is not for FTA, so only updates required, no add/remove
// Update BaProductOloBookletOrder list
if (data.getBaProductOloBookletOrderList() != null) {
newData.setBaProductOloBookletOrderList(new BaProductOloBookletOrderTableManager().
updateBaProductOloBookletOrderListForBaProduct(data, context));
}
//check for bank NL if there is the totalBlockForIdentiyCheck is removed
if (isNL && newData.getProposals() != null && totalBlockForNoIdentityCheckChanged && !newData.isHasTotalBlockForNoIdentityChk()) {
//make system-created debit limit change proposal visible
BaProductDtLimitChangeProposalData cp = newData.getProposals().getDebitLimitChangeProposal();
if (cp != null && cp.isInitiated()) {
cp.setIcStatus(ChangeProposalICStatus.SUBMITTED);
new ChangeProposalTableManager().changeChangeProposal(cp.getChangeProposalData(), context);
}
}
final SDDBlockByDebtorService sddBlockByDebtorService = new SDDBlockByDebtorService();
if (sddBlockByDebtorService.isBlockByDebtorTypeChangedToBlacklist(oldBaProduct, newData)) {
sddBlockByDebtorService.deactivateWhitelist(newData, context);
}
// Add change events
new BaProductConfigEventTableManager().addBaProductConfigEvents(oldBaProduct, newData, context);
//if step-in service former account number or start date is changed, make a contact event for printing an step in service letter
if (StringUtil.isStringDefined(data.getStepInServiceFormerIBAN()) &&
(!data.getStepInServiceFormerIBAN().equals(oldBaProduct.getStepInServiceFormerIBAN()) ||
!DateUtil.equalDates(data.getStepInServiceBeginDate(), oldBaProduct.getStepInServiceBeginDate()))) {
// Flush CE tags cache
TemplateDataCache.flushBaProductCache(data.getProductID());
addStepInServiceContactEvent(data, context);
}
updateOptimisticLockValue(newData, context);
return newData;
} catch (TritonCreateException | TritonRemoveException | TritonSaveException e) {
context.setRollbackOnly();
throw new RelationshipException(e.getTritonMessages(), e);
}
}
}