/**
* Revenue Settlement and Sharing System GE
* Copyright (C) 2011-2014, Javier Lucio - lucio@tid.es
* Telefonica Investigacion y Desarrollo, S.A.
*
* Copyright (C) 2015, CoNWeT Lab., Universidad Politécnica de Madrid
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package es.upm.fiware.rss.service;
import es.upm.fiware.rss.dao.CurrencyDao;
import es.upm.fiware.rss.dao.DbeAggregatorDao;
import es.upm.fiware.rss.dao.DbeAppProviderDao;
import es.upm.fiware.rss.dao.DbeTransactionDao;
import es.upm.fiware.rss.exception.RSSException;
import es.upm.fiware.rss.exception.UNICAExceptionType;
import es.upm.fiware.rss.model.BmCurrency;
import es.upm.fiware.rss.model.CDR;
import es.upm.fiware.rss.model.DbeAggregator;
import es.upm.fiware.rss.model.DbeAppProvider;
import es.upm.fiware.rss.model.DbeTransaction;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(rollbackFor=Exception.class)
public class CdrsManager {
/***
* Logging system.
*/
private final Logger logger = LoggerFactory.getLogger(CdrsManager.class);
/**
* Properties.
*/
@Autowired
private DbeTransactionDao transactionDao;
@Autowired
private DbeAggregatorDao aggregatorDao;
@Autowired
private DbeAppProviderDao appProviderDao;
@Autowired
private CurrencyDao currencyDao;
@Autowired
private UserManager userManager;
@Autowired
private RSSModelsManager modelsManager;
private List<CDR> getCDRsAPIFormat(List<DbeTransaction> txs) {
List<CDR> result = new ArrayList<>();
for (DbeTransaction tx: txs) {
CDR cdr = new CDR();
cdr.setAppProvider(tx.getAppProvider().getId().getTxAppProviderId());
cdr.setApplication(tx.getTxApplicationId());
cdr.setCdrSource(tx.getCdrSource().getTxEmail());
cdr.setChargedAmount(tx.getFtChargedAmount());
cdr.setChargedTaxAmount(tx.getFtChargedTaxAmount());
cdr.setCorrelationNumber(tx.getTxPbCorrelationId());
cdr.setCurrency(tx.getBmCurrency().getTxIso4217Code());
cdr.setCustomerId(tx.getTxEndUserId());
cdr.setDescription(tx.getTxOperationNature());
cdr.setEvent(tx.getTxEvent());
cdr.setProductClass(tx.getTxProductClass());
cdr.setReferenceCode(tx.getTxReferenceCode());
cdr.setTimestamp(tx.getTsClientDate());
cdr.setTransactionType(tx.getTcTransactionType());
result.add(cdr);
}
return result;
}
/**
* Retrieve existing transactions filtered by aggregator and provider
* @param aggregatorId, id of the aggregator used to filter the list
* @param providerId, id of the provider used to filter the list
* @return, List of CDRs
*/
public List<CDR> getCDRs(String aggregatorId, String providerId) {
List<CDR> result;
// Retrieve all pending transactions
if (aggregatorId == null && providerId == null) {
result = this.getCDRsAPIFormat(this.transactionDao.getTransactions(null, null, null));
} else if (providerId == null) {
result = this.getCDRsAPIFormat(
this.transactionDao.getTransactions(aggregatorId, null, null));
} else {
result = this.getCDRsAPIFormat(
this.transactionDao.getTransactions(aggregatorId, providerId, null));
}
return result;
}
/**
* Saves a list of CDRs in the database as transactionss
* @param cdrs, CDRs containing transaction information
* @throws RSSException, If the CDR information is not valid
*/
public void createCDRs(List<CDR> cdrs) throws RSSException {
// Process CDRs one by one
for (CDR cdr: cdrs) {
// Check if the user has permission to create a new transaction
if (!userManager.isAdmin() &&
!userManager.getCurrentUser().getEmail().equalsIgnoreCase(cdr.getCdrSource())) {
String[] args = {"You are not allowed to register a transaction for the Store owned by " + cdr.getCdrSource()};
throw new RSSException(UNICAExceptionType.NON_ALLOWED_OPERATION, args);
}
// Check that the aggregator (CDR Source) exists
DbeAggregator aggregator = this.aggregatorDao.getById(cdr.getCdrSource());
if (aggregator == null) {
String[] args = {"The Store identified by " + cdr.getCdrSource() + " does not exists"};
throw new RSSException(UNICAExceptionType.NON_EXISTENT_RESOURCE_ID, args);
}
// Validate the provider
this.modelsManager.checkValidAppProvider(cdr.getCdrSource(), cdr.getAppProvider());
DbeAppProvider provider = this.appProviderDao.getProvider(cdr.getCdrSource(), cdr.getAppProvider());
// Validate the currency
BmCurrency currency = this.currencyDao.getByIso4217StringCode(cdr.getCurrency());
if (currency == null) {
String[] args = {"The currency " + cdr.getCurrency() + " is not supported"};
throw new RSSException(UNICAExceptionType.NON_EXISTENT_RESOURCE_ID, args);
}
// Validate correlation number and timestamp
Integer nextCorr = provider.getTxCorrelationNumber();
if (!nextCorr.equals(cdr.getCorrelationNumber())) {
String[] args = {"Invalid correlation number, expected: " + nextCorr};
throw new RSSException(UNICAExceptionType.INVALID_PARAMETER, args);
}
provider.setTxCorrelationNumber(nextCorr + 1);
Date prevTime = provider.getTxTimeStamp();
if (cdr.getTimestamp() == null || prevTime.after(cdr.getTimestamp())) {
String[] args = {"Invalid timestamp: The given time is earlier that the prevoius one"};
throw new RSSException(UNICAExceptionType.INVALID_PARAMETER, args);
}
provider.setTxTimeStamp(cdr.getTimestamp());
// Validate transaction type
if (!cdr.getTransactionType().equalsIgnoreCase("C") &&
!cdr.getTransactionType().equalsIgnoreCase("R")) {
String[] args = {"The transaction type " + cdr.getTransactionType()
+ " is not supported, must be C (charge) or R (refund)"};
throw new RSSException(UNICAExceptionType.INVALID_PARAMETER, args);
}
// Save CDR to the database
DbeTransaction tx = new DbeTransaction();
if (cdr.getProductClass() == null || cdr.getProductClass().isEmpty()) {
String[] args = {"Missing productClass"};
throw new RSSException(UNICAExceptionType.MISSING_MANDATORY_PARAMETER, args);
}
if (cdr.getReferenceCode() == null || cdr.getReferenceCode().isEmpty()) {
String[] args = {"Missing referenceCode"};
throw new RSSException(UNICAExceptionType.MISSING_MANDATORY_PARAMETER, args);
}
tx.setTxProductClass(cdr.getProductClass());
tx.setState("pending");
tx.setCdrSource(aggregator);
tx.setTxPbCorrelationId(cdr.getCorrelationNumber());
tx.setTsClientDate(cdr.getTimestamp());
tx.setTxApplicationId(cdr.getApplication());
tx.setTcTransactionType(cdr.getTransactionType());
tx.setTxEvent(cdr.getEvent());
tx.setTxReferenceCode(cdr.getReferenceCode());
tx.setTxOperationNature(cdr.getDescription());
tx.setFtChargedAmount(cdr.getChargedAmount());
tx.setFtChargedTaxAmount(cdr.getChargedTaxAmount());
tx.setBmCurrency(currency);
tx.setTxEndUserId(cdr.getCustomerId());
tx.setAppProvider(provider);
try {
this.transactionDao.create(tx);
} catch (org.hibernate.NonUniqueObjectException e) {
String msg = "This transaction has been already registered:" +
"For a given transaction the provider, the reference, " +
" and the correlation number must be unique";
String[] args = {msg};
throw new RSSException(UNICAExceptionType.RESOURCE_ALREADY_EXISTS, args);
}
}
}
}