HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
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

}