File: D:/HostingSpaces/TDijk1/erp-apps.eu/wwwroot/App_Code/ERPApps/Ecommerce/ERPOrderInfoProvider.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using CMS.Ecommerce;
using CMS.EventLog;
using CMS.GlobalHelper;
using CMS.SettingsProvider;
using CMS.DataEngine;
using CMS.CMSHelper;
using CMS.TreeEngine;
using CMS.DocumentEngine;
using CMS.Helpers;
using CMS.SiteProvider;
using ERP.Ad;
using ERP.Application;
/// <summary>
/// Order info provider for ERP apps.
/// Handles after-payment logic for orders.
/// </summary>
public class ERPOrderInfoProvider : OrderInfoProvider
{
/// <summary>
/// Flag in Custom data in COM_Order object to determine, whether the order has been processed.
/// </summary>
public const string PROCESSED_FLAG = "ERPIsProcessed";
public const string INVOICE_DATA_FIELD = "ERPInvoiceNumber";
private const string PROVIDER_NAME = "ERPOrderInfoProvider";
#region "Provider methods"
/// <summary>
/// Everytime the order is updated the method checks whether the order was marked as paid.
/// If so, it process custom login on the order
/// </summary>
/// <param name="orderObj"></param>
protected override void SetOrderInfoInternal(OrderInfo orderObj)
{
bool process = false;
OrderItemInfo[] items = null;
if ( orderObj.OrderIsPaid && !HasOrderBeenProcessed(orderObj) )
{
// newly paid order - process it
items = ProcessPaidOrder(orderObj);
process = true;
}
base.SetOrderInfoInternal(orderObj);
if ( process && items != null )
{
if ( orderObj.HasChanged )
{
orderObj.Update();
}
// update order items
foreach ( OrderItemInfo item in items )
{
OrderItemInfoProvider.SetOrderItemInfo(item);
}
// regenerate invoice
//TODO OrderInfoProvider.GetInvoice je zrušené
//orderObj.OrderInvoice = OrderInfoProvider.GetInvoice(orderObj.OrderID);
orderObj.Update();
}
}
#endregion
#region "Custom methods"
/// <summary>
/// Checks whether given order has been processed or not.
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
public bool HasOrderBeenProcessed(OrderInfo info)
{
return ValidationHelper.GetBoolean(info.OrderCustomData[PROCESSED_FLAG], false) == true;
}
/// <summary>
/// Processes new order after it was paid.
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
public OrderItemInfo[] ProcessPaidOrder(OrderInfo info)
{
if (info == null)
{
return null;
}
EventLogProvider elp = new EventLogProvider();
GeneralConnection gc = ConnectionHelper.GetConnection();
LogOrderPaid(info, elp);
// iterate over all order items
OrderItemInfo[] orderItems = OrderItemInfoProvider.GetOrderItems(info.OrderID).ToArray();
foreach (OrderItemInfo item in orderItems)
{
if (ValidationHelper.GetInteger(item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_ID],0) > 0)
{
// ad order item
ProcessAdOrderItem(info, elp, gc, item);
}
else if ( ValidationHelper.GetInteger(item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_ID], 0) > 0 )
{
// application commercial profile
ProcessApplicationOrderItem(info, elp, gc, item);
}
}
if (info.OrderDiscountCouponID > 0)
{
DeactivateDiscountCoupon(info.OrderDiscountCouponID);
}
// mark the order as processed
info.OrderCustomData[PROCESSED_FLAG] = true;
// generate unique invoice number using MSSQL sequence
if (string.IsNullOrEmpty(ValidationHelper.GetString(info.OrderCustomData[INVOICE_DATA_FIELD], string.Empty)))
{
string invoiceNumber = GenerateERPInvoiceNumber();
if (!string.IsNullOrEmpty(invoiceNumber))
info.OrderCustomData[INVOICE_DATA_FIELD] = invoiceNumber;
}
return orderItems;
}
/// <summary>
/// Processes application commercial profile
/// </summary>
/// <param name="info"></param>
/// <param name="elp"></param>
/// <param name="gc"></param>
/// <param name="item"></param>
private void ProcessApplicationOrderItem(OrderInfo info, EventLogProvider elp, GeneralConnection gc, OrderItemInfo item)
{
// application commercial profile item
int appId = ValidationHelper.GetInteger(item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_ID], 0);
if ( appId == 0 )
{
// app ID can not be converted to integer
EventLogProvider.LogEvent(EventType.ERROR, PROVIDER_NAME, "APP NOT FOUND", null, "App ID " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_ID] + " can not be converted to integer! App commercial profile not published. Order ID: " + info.OrderID);
return;
}
// get length of commercial profile from settings module
//int periodLength = SettingsKeyProvider.GetIntValue(CMSContext.CurrentSiteName + "." + ERPConfig.SETTINGS_APP_COMMERCIAL_PROFILE_LENGTH);
//if ( periodLength == 0 )
//{
// // period length can not be converted to integer
// elp.LogEvent(EventType.ERROR, DateTime.Now, PROVIDER_NAME, "APP LENGTH EMPTY", null, "Setting key " + CMSContext.CurrentSiteName + "." + ERPConfig.SETTINGS_APP_COMMERCIAL_PROFILE_LENGTH + " is empty or zero, commercial profile for app " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_ID] + " could not be published! Order ID: " + info.OrderID);
// return;
//}
int periodLength = ValidationHelper.GetInteger(item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_PERIOD], 0);
if (periodLength == 0)
{
// period length can not be converted to integer
EventLogProvider.LogEvent(EventType.ERROR, PROVIDER_NAME, "PERIOD EMPTY", null, "App ID " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_ID] + " has an empty period " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_PERIOD] + " - the period can not be converted to integer! App not published. Order ID: " + info.OrderID);
return;
}
try
{
ActivateAppContact(info, gc, item, appId, periodLength);
LogAppDone(info, elp, item);
}
catch ( Exception ex )
{
LogAppError(info, elp, item, ex);
}
return;
}
private void ActivateAppContact(OrderInfo info, GeneralConnection gc, OrderItemInfo item, int appId, int periodLength)
{
var applicationTreeNode = ApplicationTreeNodeProvider.GetApplications().WhereEquals("AppID", appId).FirstObject;
if (applicationTreeNode == null)
{
throw new Exception(string.Format("Application with appid {0} not found.", appId));
}
DateTime startDate = applicationTreeNode.AppCommercialProfileValidFrom;
DateTime endDate = applicationTreeNode.AppCommercialProfileValidTo;
bool isCommercial = applicationTreeNode.AppShowCommercialProfile;
bool extending = false;
if ((startDate < DateTime.Now.Date && !isCommercial) || startDate == DateTimeHelper.ZERO_TIME)
{
startDate = DateTime.Today;
}
if (endDate > DateTime.Today)
{
endDate = endDate.AddMonths(periodLength);
extending = true;
}
else
{
endDate = startDate.AddMonths(periodLength);
extending = false;
}
applicationTreeNode.AppCommercialProfileValidFrom = startDate;
applicationTreeNode.AppCommercialProfileValidTo = endDate;
applicationTreeNode.AppShowCommercialProfile = true;
applicationTreeNode.AppPaymentLog = (applicationTreeNode.AppPaymentLog ?? "") + string.Format("Commercial profile published on {0} until {1} (extending: {2}) from order {3}<br>", DateTime.Now, endDate, extending, info.OrderID);
applicationTreeNode.Update();
// activate the commercial profile
// add validity date into item dscription
item.OrderItemText = String.Format("{0} ({2} months, valid until {1})", item.OrderItemText, applicationTreeNode.AppCommercialProfileValidTo.ToShortDateString(), periodLength);
// clear cache
CacheHelper.TouchKey("nodeid|" + applicationTreeNode.NodeID);
CacheHelper.TouchKey("appvendorid|" + ValidationHelper.GetInteger(applicationTreeNode.AppVendorID, 0));
}
/// <summary>
/// Processes ad
/// </summary>
/// <param name="info"></param>
/// <param name="elp"></param>
/// <param name="gc"></param>
/// <param name="item"></param>
private void ProcessAdOrderItem(OrderInfo info, EventLogProvider elp, GeneralConnection gc, OrderItemInfo item)
{
int adId = ValidationHelper.GetInteger(item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_ID], 0);
if ( adId == 0 )
{
// ad ID can not be converted to integer
EventLogProvider.LogEvent(EventType.ERROR, PROVIDER_NAME, "AD NOT FOUND", null, "Ad ID " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_ID] + " can not be converted to integer! Ad not published. Order ID: " + info.OrderID);
return;
}
int periodLength = ValidationHelper.GetInteger(item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_PERIOD], 0);
if ( periodLength == 0 )
{
// period length can not be converted to integer
EventLogProvider.LogEvent(EventType.ERROR, PROVIDER_NAME, "PERIOD EMPTY", null, "Ad ID " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_ID] + " has an empty period " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_PERIOD] + " - the period can not be converted to integer! Ad not published. Order ID: " + info.OrderID);
return;
}
try
{
ActivateAd(info, gc, item, adId, periodLength);
LogAdDone(info, elp, item);
}
catch ( Exception ex )
{
// fail
LogAdError(info, elp, item, ex);
}
return;
}
private void ActivateAd(OrderInfo info, GeneralConnection gc, OrderItemInfo item, int adId, int periodLength)
{
var adTreeNode = AdTreeNodeProvider.GetAds().WhereEquals("AdId", adId).FirstObject;
if (adTreeNode == null)
{
throw new Exception(string.Format("Application {0}", adId));
}
var startDate = adTreeNode.AdStartDate;
var endDate = adTreeNode.AdEndDate;
bool extending = false;
if ((startDate < DateTime.Today && !adTreeNode.AdIsPublished) || startDate == DateTimeHelper.ZERO_TIME)
{
startDate = DateTime.Today;
}
if (endDate > DateTime.Today)
{
endDate = endDate.AddMonths(periodLength);
extending = true;
}
else
{
endDate = startDate.AddMonths(periodLength);
extending = false;
}
adTreeNode.AdStartDate = startDate;
adTreeNode.AdEndDate = endDate;
adTreeNode.AdIsPublished = true;
adTreeNode.AdPaymentLog = (adTreeNode.AdPaymentLog ?? "") + string.Format("Published on {0} until {1} (extending: {2}) from order {3}<br>", startDate, endDate, extending, info.OrderID);
adTreeNode.Update();
// add validity date into item dscription
item.OrderItemText = String.Format("{0} (valid until {1})", item.OrderItemText, ValidationHelper.GetDateTime(adTreeNode.AdEndDate, DateTime.Now).ToShortDateString());
// clear cache
CacheHelper.TouchKey("nodeid|" + adTreeNode.NodeID);
CacheHelper.TouchKey("advendorid|" + adTreeNode.AdVendorID);
}
/// <summary>
/// Deactivate vendor specific discount coupon
/// </summary>
/// <param name="couponId"></param>
private void DeactivateDiscountCoupon(int couponId)
{
DiscountCouponInfo coupon = DiscountCouponInfoProvider.GetDiscountCouponInfo(couponId);
if (coupon != null)
{
// deactivate used discount
int couponVendorId = coupon.GetIntegerValue("DiscountCouponVendorID", 0);
if (couponVendorId > 0)
{
coupon.SetValue("DiscountCouponVendorAppliedDate", DateTime.Now);
coupon.DiscountCouponValidTo = DateTime.Now;
coupon.Update();
}
}
}
/// <summary>
/// Generate unique invoice number for new paid order
/// </summary>
/// <param name="gc"></param>
/// <param name="elp"></param>
/// <returns></returns>
public static string GenerateERPInvoiceNumber()
{
var gc = ConnectionHelper.GetConnection();
EventLogProvider elp = new EventLogProvider();
int currentYear = DateTime.Now.Year;
var parameters = new QueryDataParameters();
parameters.Add("@SequenceType", string.Format("invoice_{0}", currentYear));
var queryInfo = QueryInfoProvider.GetQueryInfo(string.Format("{0}.getnumber", ERPConfig.CUSTOM_TABLE_SEQUENCE));
var invoiceNumberDataSet = gc.ExecuteQuery(new QueryParameters(queryInfo, parameters, null));
if ( !DataHelper.DataSourceIsEmpty(invoiceNumberDataSet) )
{
int invoiceNumber = ValidationHelper.GetInteger(invoiceNumberDataSet.Tables[0].Rows[0]["ItemSequenceValue"], 0);
if ( invoiceNumber > 0 )
{
// invoice number as YYYY0000Z
return string.Format("{0}{1:00000}", currentYear, invoiceNumber);
}
else
{
elp = new EventLogProvider();
EventLogProvider.LogEvent(new EventLogInfo() { EventCode = "MISSING_NUMBER", Source = "SEQUENCE", EventDescription = string.Format("Missing invoice number for key {0}", parameters[0].Value), EventType = EventType.ERROR });
}
}
return string.Empty;
}
#endregion
#region "Logging"
private void LogOrderPaid(OrderInfo info, EventLogProvider elp)
{
string code = "ORDERPAID";
string desc = "Order " + info.OrderID + " (transaction ID " + (info.OrderPaymentResult != null ? info.OrderPaymentResult.PaymentTransactionID : "unknown") + "), starting processing...";
LogEvent(elp, EventType.INFORMATION, code, desc);
}
private void LogAppError(OrderInfo info, EventLogProvider elp, OrderItemInfo item, Exception ex)
{
string code = "PUBLISH APP FAIL";
string desc = "Order " + info.OrderID + " (transaction ID " + (info.OrderPaymentResult != null ? info.OrderPaymentResult.PaymentTransactionID : "unknown") + "), publishing application " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_ID] + " failed. " + ex.Message + "\n" + ex.StackTrace;
LogEvent(elp, EventType.ERROR, code, desc);
}
private void LogAppDone(OrderInfo info, EventLogProvider elp, OrderItemInfo item)
{
string code = "PUBLISH APP";
string desc = "Order " + info.OrderID + " mark as paid (transaction ID " + (info.OrderPaymentResult != null ? info.OrderPaymentResult.PaymentTransactionID : "unknown") + "), publishing application " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_APP_CONTACT_FIELD_ID];
LogEvent(elp, EventType.INFORMATION, code, desc);
}
private void LogAdError(OrderInfo info, EventLogProvider elp, OrderItemInfo item, Exception ex)
{
string code = "PUBLISH AD FAIL";
string desc = "Order " + info.OrderID + " (transaction ID " + (info.OrderPaymentResult != null ? info.OrderPaymentResult.PaymentTransactionID : "unknown") + "), publishing ad " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_ID] + " failed. " + ex.Message + "\n" + ex.StackTrace;
LogEvent(elp, EventType.ERROR, code, desc);
}
private void LogAdDone(OrderInfo info, EventLogProvider elp, OrderItemInfo item)
{
string code = "PUBLISH AD";
string desc = "Order " + info.OrderID + " mark as paid (transaction ID " + (info.OrderPaymentResult != null ? info.OrderPaymentResult.PaymentTransactionID : "unknown") + "), publishing ad " + item.OrderItemCustomData[ERPConfig.ORDER_INFO_AD_FIELD_ID];
LogEvent(elp, EventType.INFORMATION, code, desc);
}
private void LogEvent(EventLogProvider elp, string eventType, string eventCode, string eventDescription)
{
EventLogInfo log = new EventLogInfo();
log.EventType = eventType;
log.SiteID = SiteContext.CurrentSiteID;
log.Source = PROVIDER_NAME;
log.EventCode = eventCode;
log.EventDescription = eventDescription;
EventLogProvider.LogEvent(log);
}
#endregion
}