/*
* Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.billing.core.handlers;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.billing.core.BillingConstants;
import org.wso2.carbon.billing.core.BillingEngineContext;
import org.wso2.carbon.billing.core.BillingException;
import org.wso2.carbon.billing.core.BillingHandler;
import org.wso2.carbon.billing.core.dataobjects.*;
import org.wso2.carbon.billing.core.internal.Util;
import org.wso2.carbon.common.util.ClaimsMgtUtil;
import org.wso2.carbon.common.util.CommonUtil;
import org.wso2.carbon.email.sender.api.EmailSender;
import org.wso2.carbon.email.sender.api.EmailSenderConfiguration;
import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.utils.CarbonUtils;
import java.text.SimpleDateFormat;
import java.util.*;
public class EmailSendingHandler implements BillingHandler {
private static Log log = LogFactory.getLog(EmailSendingHandler.class);
private static String DEFAULT_CONF_FILENAME = "email-billing-notification.xml";
private static String DEFAULT_REPORT_MAIL_FILENAME = "email-bill-generated.xml";
private static String EMAIL_SENDING_CONF_KEY = "file";
private static String NOTIFICATION_EMAIL ="cloudservice@wso2.com";
EmailSender sender;
EmailSender reportMailSender;
public void init(Map<String, String> handlerConfig) throws BillingException {
if(CommonUtil.getStratosConfig()!=null){
NOTIFICATION_EMAIL = CommonUtil.getStratosConfig().getNotificationEmail();
}
String confFileName = handlerConfig.get(EMAIL_SENDING_CONF_KEY);
if (confFileName == null) {
confFileName = DEFAULT_CONF_FILENAME;
}
confFileName = CarbonUtils.getCarbonConfigDirPath() + "/" + confFileName;
EmailSenderConfiguration emailSenderConfig =
EmailSenderConfiguration.loadEmailSenderConfiguration(confFileName);
sender = new EmailSender(emailSenderConfig);
String reportMailFileName = DEFAULT_REPORT_MAIL_FILENAME;
reportMailFileName = CarbonUtils.getCarbonConfigDirPath() + "/" + reportMailFileName;
EmailSenderConfiguration reportEmailSenderConfig =
EmailSenderConfiguration.loadEmailSenderConfiguration(reportMailFileName);
reportMailSender = new EmailSender(reportEmailSenderConfig);
}
public void execute(BillingEngineContext handlerContext) throws BillingException {
List<Subscription> subscriptions = handlerContext.getSubscriptions();
Map<Integer, Invoice> invoiceMap = new HashMap<Integer, Invoice>();
Map<Integer, Invoice> creditLimitExceededMap = new HashMap<Integer, Invoice>(); //<customerId, Invoice>
List<Integer> creditLimitExceededCustomers = new ArrayList<Integer>();
for (Subscription subscription : subscriptions) {
Customer customer = subscription.getCustomer();
Invoice invoice = customer.getActiveInvoice();
if (invoiceMap.get(customer.getId()) == null) {
invoiceMap.put(customer.getId(), invoice);
}
}
for (Invoice invoice : invoiceMap.values()) {
Map<String, String> mailParameters = deriveInvoiceMailParameters(invoice);
Customer customer = invoice.getCustomer();
String emailAddress = customer.getEmail();
if(isExceedsCreditLimit(invoice)){
log.debug("Customer " + invoice.getCustomer().getName() + " needs to be reported");
//creditLimitExceededMap.put(invoice.getCustomer().getName(), invoice.getCarriedForward().toString());
creditLimitExceededCustomers.add(invoice.getCustomer().getId());
}
try {
sender.sendEmail(emailAddress, mailParameters);
} catch (Exception e) {
String msg = "Error in sending the bill for the customer. " + "customer: " +
customer.getName() + ", invoice id:" + invoice.getId();
log.error(msg, e);
}
}
//now sending the email with customers who have exceeded the credit limit
Map<String, String> reportEmailParameters = deriveReportEmailParameters(creditLimitExceededCustomers, invoiceMap);
try {
reportMailSender.sendEmail(NOTIFICATION_EMAIL, reportEmailParameters);
} catch (Exception e) {
String msg = "Error in sending the bill generation completed email";
log.error(msg, e);
}
}
public static Map<String, String> deriveInvoiceMailParameters(Invoice invoice) {
Map<String, String> mailParameters = new HashMap<String, String>();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
mailParameters.put("start-date", dateFormat.format(invoice.getStartDate()));
mailParameters.put("end-date", dateFormat.format(invoice.getEndDate()));
Customer customer = invoice.getCustomer();
try{
TenantManager tenantManager = Util.getRealmService().getTenantManager();
Tenant tenant = (Tenant) tenantManager.getTenant(customer.getId());
String customerName =
ClaimsMgtUtil.getFirstName(Util.getRealmService(), tenant, customer.getId());
if(customerName!=null){
mailParameters.put("customer-name", customerName);
}else{
mailParameters.put("customer-name", "");
}
}catch(Exception e){
log.error("Could not get tenant information for tenant: " +
customer.getName() + "\n" + e.getMessage());
mailParameters.put("customer-name", "");
}
List<Subscription> subscriptions = invoice.getSubscriptions();
if (subscriptions != null) {
StringBuffer subscriptionText = new StringBuffer();
for (Subscription subscription : subscriptions) {
Item item = subscription.getItem();
String itemName = item.getName();
Cash itemCost = item.getCost();
String subscriptionPlan = getModifiedSubscriptionPlanName(itemName);
if(itemCost!=null){
subscriptionText.append(subscriptionPlan).append("\t\t\t").append(itemCost.toString()).append("\n");
}else{
subscriptionText.append(subscriptionPlan).append("\n");
}
List<? extends Item> children = item.getChildren();
if (children != null) {
for (Item childItem : children) {
String childItemName = childItem.getName();
Cash childItemCost = childItem.getCost();
String childItemCostStr;
if(childItemCost!=null){
childItemCostStr = childItemCost.toString();
}else{
childItemCostStr = "$0.00";
}
subscriptionText.append("\t").append(childItemName).append("\t\t")
.append(childItemCostStr).append("\n");
}
}
subscriptionText.append("-------------------------------------------").append("\n");
}
mailParameters.put("subscription-charges", subscriptionText.toString());
}
StringBuffer paymentText = new StringBuffer();
if (invoice.getPayments() != null && invoice.getPayments().size()>0) {
for (Payment payment : invoice.getPayments()) {
Date paymentDate = payment.getDate();
Cash paymentAmount = payment.getAmount();
paymentText.append(dateFormat.format(paymentDate)).append("\t\t")
.append(paymentAmount.toString()).append("\n");
}
}else{
paymentText.append("No payment details during this period");
}
mailParameters.put("payment-details", paymentText.toString());
if (invoice.getBoughtForward() != null) {
mailParameters.put("bought-forward", invoice.getBoughtForward().toString());
} else {
mailParameters.put("bought-forward", "$0");
}
if (invoice.getTotalCost() != null) {
mailParameters.put("total-cost", invoice.getTotalCost().toString());
} else {
mailParameters.put("total-cost", "$0");
}
if (invoice.getTotalPayment() != null) {
mailParameters.put("total-payments", invoice.getTotalPayment().toString());
} else {
mailParameters.put("total-payments", "$0");
}
if (invoice.getCarriedForward() != null) {
mailParameters.put("carried-forward", invoice.getCarriedForward().toString());
} else {
mailParameters.put("carried-forward", "$0");
}
return mailParameters;
}
private boolean isExceedsCreditLimit(Invoice invoice) throws BillingException{
boolean exceedsCreditLimit = false;
Cash creditLimit = new Cash("$0");
List<Subscription> subscriptions = invoice.getSubscriptions();
for(Subscription subscription : subscriptions){
if(subscription.isActive()){
List<? extends Item> subItems = subscription.getItem().getChildren();
for (Item item : subItems){
if(BillingConstants.SUBSCRIPTION_SUBITEM.equals(item.getName())){
if(item.getCreditLimit()!=null){
creditLimit = Cash.add(creditLimit, item.getCreditLimit());
}else{
creditLimit = Cash.add(creditLimit, new Cash("$0"));
}
break;
}
}
break;
}
}
Cash difference = Cash.subtract(invoice.getCarriedForward(), creditLimit);
if(Cash.Sign.POSITIVE == difference.getSign() && difference.getWholeNumber()>0){
exceedsCreditLimit = true;
}
return exceedsCreditLimit;
}
public Map<String, String> deriveReportEmailParameters(List<Integer> creditExceededCustomers, Map<Integer, Invoice> invoiceMap){
Map<String, String> mailParameters = new HashMap<String, String>();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
//note that I havent considered the timezone here
mailParameters.put("date", dateFormat.format(new Date()));
StringBuffer reportedCustomers = new StringBuffer();
if(creditExceededCustomers.isEmpty()){
reportedCustomers.append("No customers to be reported");
}else{
for(Integer customerId : creditExceededCustomers){
Invoice invoice = invoiceMap.get(customerId);
List<Subscription> subscriptions = invoice.getSubscriptions();
String activeSubscriptionName = "";
for(Subscription subscription : subscriptions){
if(subscription.isActive()){
activeSubscriptionName = subscription.getSubscriptionPlan();
break;
}
}
reportedCustomers.append(invoice.getCustomer().getName()).append("\t\t").
append(activeSubscriptionName).append("\t\t").append(invoice.getCarriedForward().toString()).
append("\n");
}
}
mailParameters.put("reported-customers", reportedCustomers.toString());
return mailParameters;
}
private static String getModifiedSubscriptionPlanName(String plan){
String subscriptionPlan = "Subscription Type: ";
if("multitenancy-free".equals(plan)){
return subscriptionPlan + "Free";
}else if("multitenancy-small".equals(plan)){
return subscriptionPlan + "Small";
}else if("multitenancy-medium".equals(plan)){
return subscriptionPlan + "Medium";
}else if("multitenancy-large".equals(plan)){
return subscriptionPlan + "Large";
}else{
return subscriptionPlan + "Undefined";
}
}
}