/// <summary>
        /// Creates an incoming payment.
        /// </summary>
        /// <param name="cardCode">The BP's CardCode.</param>
        /// <param name="salesOrderNo">The salesOrder's DocNum</param>
        /// <param name="order">The Amazon order object</param>
        /// <returns>Payment DocNum on success, -1 on error.</returns>
        public string CreatePayment(string cardCode, string salesOrderNo, AmazonOrder order)
        {
            Recordset rs;
            string    DocEntry = null, DocNum = null, q;

            try
            {
                // If incoming payment exists with AmzOrderId, log and return
                q  = "usp_MarketplaceGetIncomingPaymentByAmazonOrderID '" + order.AmazonOrderId + "'";
                rs = (Recordset)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                rs.DoQuery(q);
                if (!(rs.EoF)) // Invoice exists
                {
                    _amazonOrderLogRepository.LogEvent(
                        order.AmazonOrderId,
                        "Incoming Payment #" + rs.Fields.Item(0).Value.ToString() + " already exists in SAP.",
                        nameof(LogEventLevel.Information),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");

                    return(rs.Fields.Item(0).Value.ToString());
                }
                rs = null;

                DIAPI_Objects.Payment                  = (Payments)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.oIncomingPayments);
                DIAPI_Objects.Payment.Series           = 12;
                DIAPI_Objects.Payment.CardCode         = cardCode; // Mandatory
                DIAPI_Objects.Payment.CashSum          = 0;        // Mandatory (DocTotal Invoice)
                DIAPI_Objects.Payment.DocDate          = DateTime.Now;
                DIAPI_Objects.Payment.Remarks          = order.AmazonOrderId;
                DIAPI_Objects.Payment.CounterReference = salesOrderNo;

                // Bank Transfer
                DIAPI_Objects.Payment.TransferAccount   = "_SYS00000001076";
                DIAPI_Objects.Payment.TransferDate      = DateTime.Now;
                DIAPI_Objects.Payment.TransferReference = order.AmazonOrderId;

                // if shipping state is CA, use OrderTotal (includes tax and freight).
                if (string.Equals(order.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) || string.Equals(order.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase))
                {
                    DIAPI_Objects.Payment.TransferSum = Decimal.ToDouble(order.OrderTotal);
                }
                else // Non-CA, so omit tax. Generate order total from the sum of totalItemPrice + totalShipCost
                {
                    double totalItemPrice = 0, totalShipCost = 0;
                    foreach (var l in order.OrderItems)
                    {
                        totalItemPrice += Decimal.ToDouble(l.ItemPrice);
                        totalShipCost  += Decimal.ToDouble(l.ShippingPrice);
                    }
                    DIAPI_Objects.Payment.TransferSum = totalItemPrice + totalShipCost;
                }

                RetCode = DIAPI_Objects.Payment.Add();

                if (RetCode != 0)
                {
                    DIAPI_Objects.Company.GetLastError(out errCode, out errMsg);

                    _amazonOrderLogRepository.LogEvent(
                        order.AmazonOrderId,
                        errCode + " - " + errMsg + " - Incoming payment was not created.",
                        nameof(LogEventLevel.Critical),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");

                    DocNum = RetCode.ToString(); // return err num
                }
                else
                {
                    // return DocEntry of new payment
                    DIAPI_Objects.Company.GetNewObjectCode(out DocEntry);

                    // NOTE: pass DocEntry to proc to get payment DocNum for log
                    q  = "usp_MarketplaceGetDocNum " + DocEntry + ", 'Pmt'";
                    rs = (Recordset)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                    rs.DoQuery(q);
                    if (!(rs.EoF))
                    {
                        DocNum = rs.Fields.Item(0).Value.ToString();
                    }

                    _amazonOrderLogRepository.LogEvent(
                        order.AmazonOrderId,
                        String.Format("Incoming Payment {0} was created.", DocNum),
                        nameof(LogEventLevel.Information),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");

                    rs = null;
                }

                _unitOfWorkMarketplace.Commit();

                return(DocNum);
            }
            catch (Exception ex)
            {
                _amazonOrderLogRepository.LogEvent(
                    order.AmazonOrderId,
                    ex.GetType().Name + " - " + ex.Message + " - Incoming payment was not created.",
                    nameof(LogEventLevel.Critical),
                    "Bast",
                    "DIAPI_Services",
                    StackExtensions.GetCurrentMethod(),
                    "HAL 9000");

                return("-1"); // error
            }
        }
        /// <summary>
        /// Create SAP Sales Order
        /// </summary>
        /// <param name="cardCode">The CardCode for the BP.</param>
        /// <param name="o">The Amazon order object</param>
        /// <returns>Dictionary with DocEntry and DocNum of the sales order.</returns>
        public Dictionary <string, string> CreateSalesOrder(string cardCode, AmazonOrder o)
        {
            double totalItemPrice = 0, totalItemTax = 0, totalShipCost = 0, totalShipTax = 0;
            string DocEntry = null, q;
            int    DocNum = 0;
            Dictionary <string, string> SalesOrderNums = new Dictionary <string, string>();
            Recordset rs;

            try
            {
                // If sales order exists with AmzOrderId, log and return
                q  = "usp_MarketplaceGetOrderDocNumByAmazonOrderID '" + o.AmazonOrderId + "'";
                rs = (Recordset)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                rs.DoQuery(q);
                if (!(rs.EoF)) // sales order exists
                {
                    _amazonOrderLogRepository.LogEvent(
                        o.AmazonOrderId,
                        "Invoice #" + rs.Fields.Item(0).Value.ToString() + " already exists in SAP.",
                        nameof(LogEventLevel.Warning),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");

                    SalesOrderNums.Add("DocNum", rs.Fields.Item(0).Value.ToString());
                    SalesOrderNums.Add("DocEntry", rs.Fields.Item(1).Value.ToString());

                    // Check if sales order total matches Amazon order total
                    var validInvTotal = Decimal.TryParse(rs.Fields.Item(2).Value.ToString(), out decimal invTotal);
                    if (Decimal.Compare(invTotal, o.OrderTotal) != 0)
                    {
                        bool shipToWA = false;
                        if (o.StateOrRegion == "WA" || o.StateOrRegion == "Washington")
                        {
                            shipToWA = true;
                        }

                        _amazonOrderLogRepository.LogEvent(
                            o.AmazonOrderId,
                            (shipToWA ? "Shipped to WA: " : "") + "Sales order total $" + invTotal.ToString() + " doesn't equal Amazon-order total of $" + o.OrderTotal.ToString() + ". Please verify that this isn't an error.",
                            nameof(LogEventLevel.Warning),
                            "Bast",
                            "DIAPI_Services",
                            StackExtensions.GetCurrentMethod(),
                            "HAL 9000");
                    }

                    _unitOfWorkMarketplace.Commit();

                    return(SalesOrderNums);
                }
                rs = null;

                DIAPI_Objects.Order                 = (Documents)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.oOrders);
                DIAPI_Objects.Order.CardCode        = cardCode;
                DIAPI_Objects.Order.NumAtCard       = o.AmazonOrderId.Trim();
                DIAPI_Objects.Order.HandWritten     = BoYesNoEnum.tNO;
                DIAPI_Objects.Order.DocDate         = DateTime.Now;
                DIAPI_Objects.Order.DocDueDate      = DateTime.Now;
                DIAPI_Objects.Order.DocCurrency     = "$";
                DIAPI_Objects.Order.SalesPersonCode = 68; // Amazon slpcode
                DIAPI_Objects.Order.UserFields.Fields.Item("U_LeadSource").Value = "29";

                // Calculate shipping
                foreach (var l in o.OrderItems)
                {
                    totalShipCost += Decimal.ToDouble(l.ShippingPrice);
                    //totalShipTax += Decimal.ToDouble(l.ShippingTax);
                }

                DIAPI_Objects.Order.Expenses.ExpenseCode = 1;
                DIAPI_Objects.Order.Expenses.LineTotal   = totalShipCost;
                DIAPI_Objects.Order.Expenses.Add();

                bool partFound = false;
                foreach (var line in o.OrderItems)
                {
                    q  = "usp_findPartBySKU '" + line.VendorSKU + "'";
                    rs = (Recordset)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                    rs.DoQuery(q);
                    if (!(rs.EoF))
                    {
                        DIAPI_Objects.Order.Lines.ItemCode      = rs.Fields.Item(0).Value.ToString();
                        DIAPI_Objects.Order.Lines.Quantity      = Decimal.ToDouble(line.QuantityOrdered);
                        DIAPI_Objects.Order.Lines.WarehouseCode = "DS1";

                        // Set tax
                        // flag "Shipping to CA, but no sales tax charged"
                        if ((string.Equals(o.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) || string.Equals(o.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase)) && line.ItemTax == 0)
                        {
                            DIAPI_Objects.Order.Lines.TaxCode  = "Exempt";
                            DIAPI_Objects.Order.Lines.TaxTotal = 0;

                            _amazonOrderLogRepository.LogEvent(
                                o.AmazonOrderId,
                                "Adding " + line.VendorSKU + " - Shipping address is CA, but no sales tax was charged.",
                                nameof(LogEventLevel.Information),
                                "Bast",
                                "DIAPI_Services",
                                StackExtensions.GetCurrentMethod(),
                                "HAL 9000");
                        }
                        else if (!string.Equals(o.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) && !string.Equals(o.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase))
                        {
                            // no tax outside of california
                            DIAPI_Objects.Order.Lines.TaxCode  = "Exempt";
                            DIAPI_Objects.Order.Lines.TaxTotal = 0;
                        }
                        else // California
                        {
                            // Set tax
                            DIAPI_Objects.Order.Lines.TaxCode  = "CA";
                            DIAPI_Objects.Order.Lines.TaxTotal = Decimal.ToDouble(line.ItemTax);
                        }

                        totalItemPrice += Decimal.ToDouble(line.ItemPrice); // add ItemPrice to total

                        // Amazon ItemPrice = Quantity * ItemPrice
                        DIAPI_Objects.Order.Lines.LineTotal = Decimal.ToDouble(line.ItemPrice);
                        DIAPI_Objects.Order.Lines.Add();

                        partFound = true;

                        _amazonOrderLogRepository.LogEvent(
                            o.AmazonOrderId,
                            String.Format("{0} was added to sales order", line.VendorSKU),
                            nameof(LogEventLevel.Information),
                            "Bast",
                            "DIAPI_Services",
                            StackExtensions.GetCurrentMethod(),
                            "HAL 9000");
                    }
                    else // SKU not found
                    {
                        // update return Dictionary with 'ActionRequired' flag
                        if (!SalesOrderNums.ContainsKey("ActionRequired"))
                        {
                            SalesOrderNums.Add("ActionRequired", "true");
                        }
                        else
                        {
                            SalesOrderNums["ActionRequired"] = "true";
                        }

                        _amazonOrderLogRepository.LogEvent(
                            o.AmazonOrderId,
                            String.Format("{0} was not found. Please add manually", line.VendorSKU),
                            nameof(LogEventLevel.Error),
                            "Bast",
                            "DIAPI_Services",
                            StackExtensions.GetCurrentMethod(),
                            "HAL 9000");
                    }
                }
                rs = null;

                if (!partFound)
                {
                    DIAPI_Objects.Order.Lines.ItemCode        = "PLCHLDR";
                    DIAPI_Objects.Order.Lines.ItemDescription = "Placeholder";
                    DIAPI_Objects.Order.Lines.Quantity        = 1;
                    DIAPI_Objects.Order.Lines.UnitPrice       = 0;
                    DIAPI_Objects.Order.Lines.Add();

                    _amazonOrderLogRepository.LogEvent(
                        o.AmazonOrderId,
                        "Unable to find SKUs for sales order, so a placeholder was added.",
                        nameof(LogEventLevel.Error),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");
                }

                // Override OrderTotal
                // if shipping state is not CA, ignore tax and generate order total from the sum of all totalItemPrice + totalShipCost
                if (string.Equals(o.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) || string.Equals(o.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase))
                {
                    DIAPI_Objects.Order.DocTotal = Decimal.ToDouble(o.OrderTotal);
                }
                else
                {
                    DIAPI_Objects.Order.DocTotal = totalItemPrice + totalShipCost;
                }

                RetCode = DIAPI_Objects.Order.Add();

                if (RetCode != 0)
                {
                    DIAPI_Objects.Company.GetLastError(out errCode, out errMsg);

                    _amazonOrderLogRepository.LogEvent(
                        o.AmazonOrderId,
                        errCode + " - " + errMsg + " - Sales order was not created.",
                        nameof(LogEventLevel.Critical),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");

                    if (!SalesOrderNums.ContainsKey("ActionRequired"))
                    {
                        SalesOrderNums.Add("ActionRequired", "true");
                    }
                    else
                    {
                        SalesOrderNums["ActionRequired"] = "true";
                    }

                    DocEntry = RetCode.ToString(); // return err num
                }
                else
                {
                    // return DocEntry of new Invoice
                    DIAPI_Objects.Company.GetNewObjectCode(out DocEntry);

                    // NOTE: pass DocEntry to proc to get sales-order DocNum for log, but return DocEntry
                    q  = "usp_MarketplaceGetDocNum " + DocEntry + ", 'SO'";
                    rs = (Recordset)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                    rs.DoQuery(q);
                    if (!(rs.EoF))
                    {
                        DocNum = Convert.ToInt32(rs.Fields.Item(0).Value);
                    }

                    SalesOrderNums.Add("DocEntry", DocEntry);
                    SalesOrderNums.Add("DocNum", DocNum.ToString());

                    _amazonOrderLogRepository.LogEvent(
                        o.AmazonOrderId,
                        String.Format("Sales order {0} was created. Please verify addresses, pricing, warehouses and shipping.", DocNum),
                        nameof(LogEventLevel.Information),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");

                    rs = null;
                }

                _unitOfWorkMarketplace.Commit();

                // return Dictionary with sales-order DocNum and DocEntry
                return(SalesOrderNums);
            }
            catch (Exception ex)
            {
                _amazonOrderLogRepository.LogEvent(
                    o.AmazonOrderId,
                    String.Format("{0} - Sales order was not created.", ex.GetType().Name + " - " + ex.Message),
                    nameof(LogEventLevel.Critical),
                    "Bast",
                    "DIAPI_Services",
                    StackExtensions.GetCurrentMethod(),
                    "HAL 9000");

                if (!SalesOrderNums.ContainsKey("ActionRequired"))
                {
                    SalesOrderNums.Add("ActionRequired", "true");
                }
                else
                {
                    SalesOrderNums["ActionRequired"] = "true";
                }

                rs = null;

                return(SalesOrderNums);
            }
        }
        /// <summary>
        /// Connect to SAP Company and Db
        /// </summary>
        /// <returns>Log object.</returns>
        public static AmazonOrderLog Connect()
        {
            if (Company != null)
            {
                if (Company.Connected)
                {
                    var l = new AmazonOrderLog
                    {
                        EventDescription = "success"
                    };
                    return(l);
                }
            }

            try
            {
                Company = new Company
                {
                    DbServerType  = BoDataServerTypes.dst_MSSQL2012,
                    language      = BoSuppLangs.ln_English,
                    UseTrusted    = false,
                    Server        = Constants.SapDiapiSettings.B1_SERVER,
                    LicenseServer = Constants.SapDiapiSettings.B1_LICENSE_SERVER,
                    DbUserName    = Constants.SapDiapiSettings.B1_DB_USER_NAME,
                    DbPassword    = Constants.SapDiapiSettings.B1_DB_PASSWORD,
                    CompanyDB     = Constants.SapDiapiSettings.B1_COMPANY_DB, // change to COMPANY_DB when go live
                    UserName      = Constants.SapDiapiSettings.B1_USER_NAME,
                    Password      = Constants.SapDiapiSettings.B1_PASSWORD
                };

                long RetCode = Company.Connect();

                if (RetCode != 0)
                {
                    Company.GetLastError(out int errCode, out string errMsg);

                    var l = new AmazonOrderLog
                    {
                        EventDate        = DateTime.Now,
                        EventDescription = errCode + " - " + errMsg,
                        EventType        = nameof(LogEventLevel.Error),
                        ContentRootName  = "Bast",
                        Source           = "DIAPI_Objects",
                        Action           = StackExtensions.GetCurrentMethod(),
                        UserName         = "******"
                    };

                    return(l);
                }

                if (Company.Connected)
                {
                    var l = new AmazonOrderLog
                    {
                        EventDescription = "success"
                    };

                    return(l);
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception ex)
            {
                var l = new AmazonOrderLog
                {
                    EventDate        = DateTime.Now,
                    EventDescription = ex.GetType().Name + " - " + ex.Message,
                    EventType        = nameof(LogEventLevel.Critical),
                    ContentRootName  = "Bast",
                    Source           = "DIAPI_Objects",
                    Action           = StackExtensions.GetCurrentMethod(),
                    UserName         = "******"
                };

                return(l);
            }
        }
        /// <summary>
        /// Creates a BP.
        /// </summary>
        /// <param name="o">The Amazon order object.</param>
        /// <returns>The BP's CardCode or null on error.</returns>
        public string CreateBusinessPartner(AmazonOrder o)
        {
            try
            {
                // If state is longer than two characters, find abbreviation and update Amazon order.
                // If unable to resolve state, throw exception.
                string stateCode = null;
                if (o.StateOrRegion?.Length > 2) // potentially full name of state
                {
                    var s = _sapDataService.GetStateCode(o.StateOrRegion);
                    stateCode = s.StateCode;
                    if (!s.StateCode.IsNullOrWhitespace()) // abbreviation found: Set Amazon-order stateCode to abbreviation
                    {
                        o.StateOrRegion = stateCode;
                    }
                    else // unable to find stateCode. Allow BP creation to continue (allowing for correction), even though invoice creation will fail.
                    {
                        o.StateOrRegion = null;

                        _amazonOrderLogRepository.LogEvent(
                            o.AmazonOrderId,
                            "Shipping state could not be resolved. Please update manually, as invoice creation will fail.",
                            nameof(LogEventLevel.Error),
                            "Bast",
                            "DIAPI_Services",
                            StackExtensions.GetCurrentMethod(),
                            "HAL 9000");
                    }
                }

                // Get Matching BPs from SAP for user's email.
                var bp = _sapDataService.GetCardCodeForEmail(o.BuyerEmail?.Trim());

                if (bp.Count > 0)     // Matching BP found. Grab first CardCode in list (most recent Sales Order date) and return.
                {
                    if (bp.Count > 1) // At least one dupe BP. Deactivate.
                    {
                        int i = _sapDataService.DeactivateRedundantBPs(o.BuyerEmail?.Trim(), bp[0].CardCode);
                    }

                    // Add both shipping and billing addresses using the Amazon order's Shipping address
                    var addr = new BPAddress
                    {
                        AddressName = o.AddressName,
                        Street      = o.AddressLine1,
                        Block       = o.AddressLine2,
                        City        = o.City,
                        StateCode   = o.StateOrRegion,
                        ZipCode     = o.PostalCode,
                        CountryCode = o.CountryCode,
                        PhoneNumber = o.Phone
                    };

                    _sapDataService.AddAddress(bp[0].CardCode, 1, addr); // shipping
                    _sapDataService.AddAddress(bp[0].CardCode, 2, addr); // billing

                    _amazonOrderLogRepository.LogEvent(
                        o.AmazonOrderId,
                        "BP " + bp[0].CardCode + " already exists. Billing and shipping addresses updated.",
                        nameof(LogEventLevel.Information),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");

                    _unitOfWorkMarketplace.Commit();

                    return(bp[0].CardCode);
                }

                // create  new Business Partner
                DIAPI_Objects.BusinessPartner                 = (BusinessPartners)DIAPI_Objects.Company.GetBusinessObject(BoObjectTypes.oBusinessPartners);
                DIAPI_Objects.BusinessPartner.CardName        = o.BuyerName;
                DIAPI_Objects.BusinessPartner.CardType        = BoCardTypes.cCustomer;
                DIAPI_Objects.BusinessPartner.Phone1          = o.Phone;
                DIAPI_Objects.BusinessPartner.EmailAddress    = !o.BuyerEmail.IsNullOrWhitespace() ? o.BuyerEmail : "*****@*****.**";
                DIAPI_Objects.BusinessPartner.ContactPerson   = o.BuyerName;
                DIAPI_Objects.BusinessPartner.Notes           = "Auto-created by Marketplace App";
                DIAPI_Objects.BusinessPartner.PayTermsGrpCode = 5; // Credit Card
                DIAPI_Objects.BusinessPartner.Valid           = BoYesNoEnum.tYES;

                DIAPI_Objects.BusinessPartner.Addresses.Add();

                // Shipping
                DIAPI_Objects.BusinessPartner.Addresses.SetCurrentLine(0);
                DIAPI_Objects.BusinessPartner.Addresses.AddressType = BoAddressType.bo_ShipTo;
                DIAPI_Objects.BusinessPartner.Addresses.AddressName = o.AddressName;
                DIAPI_Objects.BusinessPartner.Addresses.Street      = o.AddressLine1;
                DIAPI_Objects.BusinessPartner.Addresses.Block       = o.AddressLine2;
                DIAPI_Objects.BusinessPartner.Addresses.City        = o.City;
                DIAPI_Objects.BusinessPartner.Addresses.State       = o.StateOrRegion;
                DIAPI_Objects.BusinessPartner.Addresses.ZipCode     = o.PostalCode;
                DIAPI_Objects.BusinessPartner.Addresses.Country     = o.CountryCode;
                DIAPI_Objects.BusinessPartner.Addresses.UserFields.Fields.Item("U_MarketingOptOut").Value = 0;

                // Billing
                DIAPI_Objects.BusinessPartner.Addresses.SetCurrentLine(1);
                DIAPI_Objects.BusinessPartner.Addresses.AddressType = BoAddressType.bo_BillTo;
                DIAPI_Objects.BusinessPartner.Addresses.AddressName = o.AddressName;
                DIAPI_Objects.BusinessPartner.Addresses.Street      = o.AddressLine1;
                DIAPI_Objects.BusinessPartner.Addresses.Block       = o.AddressLine2;
                DIAPI_Objects.BusinessPartner.Addresses.City        = o.City;
                DIAPI_Objects.BusinessPartner.Addresses.State       = o.StateOrRegion;
                DIAPI_Objects.BusinessPartner.Addresses.ZipCode     = o.PostalCode;
                DIAPI_Objects.BusinessPartner.Addresses.Country     = o.CountryCode;
                DIAPI_Objects.BusinessPartner.Addresses.UserFields.Fields.Item("U_MarketingOptOut").Value = 0;

                DIAPI_Objects.BusinessPartner.CardCode = GetNextID("BusinessPartner");;

                // contact info
                DIAPI_Objects.BusinessPartner.ContactEmployees.Add();
                DIAPI_Objects.BusinessPartner.ContactEmployees.SetCurrentLine(0);
                DIAPI_Objects.BusinessPartner.ContactEmployees.Name    = o.BuyerName;
                DIAPI_Objects.BusinessPartner.ContactEmployees.Address = o.AddressLine1 + ", " + o.City + ", " + o.StateOrRegion + " " + o.PostalCode + " " + o.CountryCode;
                DIAPI_Objects.BusinessPartner.ContactEmployees.E_Mail  = o.BuyerEmail;
                DIAPI_Objects.BusinessPartner.ContactEmployees.Phone1  = o.Phone;

                RetCode = DIAPI_Objects.BusinessPartner.Add();

                // Save CardCode to log and update OrderHeader and UserAccount
                string CardCode = DIAPI_Objects.BusinessPartner.CardCode;

                if (RetCode != 0)
                {
                    DIAPI_Objects.Company.GetLastError(out errCode, out errMsg);

                    _amazonOrderLogRepository.LogEvent(
                        o.AmazonOrderId,
                        errCode + " - " + errMsg + " - BP was not created.",
                        nameof(LogEventLevel.Critical),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");
                }
                else
                {
                    _amazonOrderLogRepository.LogEvent(
                        o.AmazonOrderId,
                        "BP " + CardCode + " was created.",
                        nameof(LogEventLevel.Information),
                        "Bast",
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "HAL 9000");
                }

                _unitOfWorkMarketplace.Commit();
                return(CardCode);
            }
            catch (Exception ex)
            {
                _amazonOrderLogRepository.LogEvent(
                    o.AmazonOrderId,
                    ex.GetType().Name + " - " + ex.Message,
                    nameof(LogEventLevel.Critical),
                    "Bast",
                    "DIAPI_Services",
                    StackExtensions.GetCurrentMethod(),
                    "HAL 9000");

                _unitOfWorkMarketplace.Commit();

                return(null);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Creates an incoming payment.
        /// </summary>
        /// <param name="cardCode">The BP's CardCode.</param>
        /// <param name="invDocEntry">The Invoice's DocEntry</param>
        /// <param name="order">The Amazon order object</param>
        /// <returns>Payment DocNum on success, -1 on error.</returns>
        public string CreatePayment(string cardCode, string invDocEntry, MWSOrder order)
        {
            Recordset rs;
            string    DocEntry = null, DocNum = null, q;

            try
            {
                // If incoming payment exists with AmzOrderId, log and return
                q  = "usp_MarketplaceGetIncomingPaymentByAmazonOrderID '" + order.Order.AmazonOrderId + "'";
                rs = (Recordset)DIAPI_Objects_FBA.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                rs.DoQuery(q);
                if (!(rs.EoF)) // Invoice exists
                {
                    _orderLogRepository.LogEvent(
                        order.Order.AmazonOrderId,
                        "Incoming Payment #" + rs.Fields.Item(0).Value.ToString() + " already exists in SAP.",
                        nameof(LogEventLevel.Information),
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "Bast",
                        "HAL 9000");

                    return(rs.Fields.Item(0).Value.ToString());
                }
                rs = null;

                DIAPI_Objects_FBA.Payment          = (Payments)DIAPI_Objects_FBA.Company.GetBusinessObject(BoObjectTypes.oIncomingPayments);
                DIAPI_Objects_FBA.Payment.Series   = 12;
                DIAPI_Objects_FBA.Payment.CardCode = cardCode; // Mandatory
                DIAPI_Objects_FBA.Payment.CashSum  = 0;        // Mandatory (DocTotal Invoice)
                DIAPI_Objects_FBA.Payment.DocDate  = DateTime.Now;

                // convert docEntry to an integer
                if (int.TryParse(invDocEntry, out int docEntry))
                {
                    // Link incoming payment to created invoice
                    DIAPI_Objects_FBA.Payment.Invoices.DocEntry = docEntry;
                }
                else
                {
                    throw new InvalidOperationException("Invoice DocEntry for Amz order " + order.Order.AmazonOrderId + " is not in a valid format.");
                }

                // Bank Transfer
                DIAPI_Objects_FBA.Payment.TransferAccount   = "_SYS00000001076";
                DIAPI_Objects_FBA.Payment.TransferDate      = DateTime.Now;
                DIAPI_Objects_FBA.Payment.TransferReference = order.Order.AmazonOrderId;

                // if shipping state is CA, use OrderTotal (includes tax and freight).
                if (string.Equals(order.Order.ShippingAddress.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) || string.Equals(order.Order.ShippingAddress.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase))
                {
                    if (Double.TryParse(order.Order.OrderTotal.Amount, out double orderTotal))
                    {
                        DIAPI_Objects_FBA.Payment.TransferSum = orderTotal;
                    }
                    else
                    {
                        throw new InvalidOperationException("Amazon Order " + order.Order.AmazonOrderId + " total has invalid value. Payment not created.");
                    }
                }
                else // Non-CA, so omit tax. Generate order total from the sum of totalItemPrice + totalShipCost
                {
                    double totalItemPrice = 0, totalShipCost = 0;
                    foreach (var l in order.OrderItems)
                    {
                        var s = l.ShippingPrice == null ? "0" : l.ShippingPrice?.Amount;
                        //var t = l.ShippingTax == null ? "0" : l.ShippingTax?.Amount;

                        if (Double.TryParse(s, out double shipCost))
                        {
                            totalShipCost += shipCost;
                            //if (Double.TryParse(t, out double shipTax))
                            //{
                            //    totalShipTax += shipTax;
                            //}
                        }

                        if (!Double.TryParse(l.ItemPrice.Amount, out double itemPrice))
                        {
                            throw new InvalidOperationException("Invalid ItemPrice value for " + l.SellerSKU + " - " + l.Title);
                        }
                        else
                        {
                            totalItemPrice += itemPrice;
                        }
                    }
                    DIAPI_Objects_FBA.Payment.TransferSum = totalItemPrice + totalShipCost;
                }

                RetCode = DIAPI_Objects_FBA.Payment.Add();

                if (RetCode != 0)
                {
                    DIAPI_Objects_FBA.Company.GetLastError(out errCode, out errMsg);

                    _orderLogRepository.LogEvent(
                        order.Order.AmazonOrderId,
                        errCode + " - " + errMsg + " - Incoming payment was not created.",
                        nameof(LogEventLevel.Critical),
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "Bast",
                        "HAL 9000");

                    DocNum = RetCode.ToString(); // return err num
                }
                else
                {
                    // return DocEntry of new payment
                    DIAPI_Objects_FBA.Company.GetNewObjectCode(out DocEntry);

                    // NOTE: pass DocEntry to proc to get payment DocNum for log
                    q  = "usp_MarketplaceGetDocNum " + DocEntry + ", 'Pmt'";
                    rs = (Recordset)DIAPI_Objects_FBA.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                    rs.DoQuery(q);
                    if (!(rs.EoF))
                    {
                        DocNum = rs.Fields.Item(0).Value.ToString();
                    }

                    _orderLogRepository.LogEvent(
                        order.Order.AmazonOrderId,
                        String.Format("Incoming Payment {0} was created.", DocNum),
                        nameof(LogEventLevel.Information),
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "Bast",
                        "HAL 9000");

                    rs = null;
                }

                _unitOfWork.Commit();

                return(DocNum);
            }
            catch (Exception ex)
            {
                _orderLogRepository.LogEvent(
                    order.Order.AmazonOrderId,
                    ex.GetType().Name + " - " + ex.Message + " - Incoming payment was not created.",
                    nameof(LogEventLevel.Critical),
                    "DIAPI_Services",
                    StackExtensions.GetCurrentMethod(),
                    "Bast",
                    "HAL 9000");

                return("-1"); // error
            }
        }
Beispiel #6
0
        /// <summary>
        /// Create SAP Invoice
        /// </summary>
        /// <param name="cardCode">The CardCode for the BP.</param>
        /// <param name="o">The Amazon order object</param>
        /// <returns>Dictionary with DocEntry and DocNum of the invoice.</returns>
        public Dictionary <string, string> CreateInvoice(string cardCode, MWSOrder o)
        {
            double totalItemPrice = 0, totalItemTax = 0, totalShipCost = 0, totalShipTax = 0;
            string DocEntry = null, q;
            int    DocNum = 0;
            Dictionary <string, string> InvoiceNums = new Dictionary <string, string>();
            Recordset rs;

            try
            {
                // If invoice exists with AmzOrderId, log and return
                q  = "usp_MarketplaceGetDocNumByAmazonOrderID '" + o.Order.AmazonOrderId + "'";
                rs = (Recordset)DIAPI_Objects_FBA.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                rs.DoQuery(q);
                if (!(rs.EoF)) // Invoice exists
                {
                    _orderLogRepository.LogEvent(
                        o.Order.AmazonOrderId,
                        "Invoice #" + rs.Fields.Item(0).Value.ToString() + " already exists in SAP.",
                        nameof(LogEventLevel.Warning),
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "Bast",
                        "HAL 9000");

                    InvoiceNums.Add("DocNum", rs.Fields.Item(0).Value.ToString());
                    InvoiceNums.Add("DocEntry", rs.Fields.Item(1).Value.ToString());

                    // Check if invoice total matches Amazon order total
                    var validInvTotal = Decimal.TryParse(rs.Fields.Item(2).Value.ToString(), out decimal invTotal);
                    var validAmzTotal = Decimal.TryParse(o.Order.OrderTotal.Amount, out decimal amzTotal);

                    if (validInvTotal && validAmzTotal)
                    {
                        if (Decimal.Compare(invTotal, amzTotal) != 0)
                        {
                            bool shipToWA = false;
                            if (o.Order.ShippingAddress.StateOrRegion == "WA" || o.Order.ShippingAddress.StateOrRegion == "Washington")
                            {
                                shipToWA = true;
                            }

                            _orderLogRepository.LogEvent(
                                o.Order.AmazonOrderId,
                                (shipToWA ? "Shipped to WA: " : "") + "Invoice total $" + invTotal.ToString() + " doesn't equal Amazon-order total of $" + amzTotal.ToString() + ". Please verify that this isn't an error.",
                                nameof(LogEventLevel.Warning),
                                "DIAPI_Services",
                                StackExtensions.GetCurrentMethod(),
                                "Bast",
                                "HAL 9000");
                        }
                    }

                    _unitOfWork.Commit();

                    return(InvoiceNums);
                }
                rs = null;

                DIAPI_Objects_FBA.Invoice                    = (Documents)DIAPI_Objects_FBA.Company.GetBusinessObject(BoObjectTypes.oInvoices);
                DIAPI_Objects_FBA.Invoice.CardCode           = cardCode;
                DIAPI_Objects_FBA.Invoice.NumAtCard          = o.Order.AmazonOrderId.Trim();
                DIAPI_Objects_FBA.Invoice.HandWritten        = BoYesNoEnum.tNO;
                DIAPI_Objects_FBA.Invoice.DocDate            = DateTime.Now;
                DIAPI_Objects_FBA.Invoice.DocDueDate         = DateTime.Now;
                DIAPI_Objects_FBA.Invoice.DocCurrency        = "$";
                DIAPI_Objects_FBA.Invoice.SalesPersonCode    = 68; // Amazon slpcode
                DIAPI_Objects_FBA.Invoice.TransportationCode = 13; // Ground

                // Calculate shipping
                foreach (var l in o.OrderItems)
                {
                    var s = l.ShippingPrice == null ? "0" : l.ShippingPrice?.Amount;
                    //var t = l.ShippingTax == null ? "0" : l.ShippingTax?.Amount;
                    if (Double.TryParse(s, out double shipCost))
                    {
                        totalShipCost += shipCost;
                        //if (Double.TryParse(t, out double shipTax))
                        //{
                        //    totalShipTax += shipTax;
                        //}
                    }
                    else
                    {
                        throw new InvalidOperationException("Invalid shipping cost for " + l.SellerSKU + " - " + l.Title);
                    }
                }

                DIAPI_Objects_FBA.Invoice.Expenses.ExpenseCode = 1;
                DIAPI_Objects_FBA.Invoice.Expenses.LineTotal   = totalShipCost;
                DIAPI_Objects_FBA.Invoice.Expenses.Add();

                bool partFound = false;
                foreach (var line in o.OrderItems)
                {
                    //if quantity shipped is zero, continue
                    if (line.QuantityShipped == 0)
                    {
                        continue;
                    }

                    // Amazon: get mfr SKU by substring to left of underscore.
                    int    index = line.SellerSKU.IndexOf("_");
                    string sku   = (index > 0 ? line.SellerSKU.Substring(0, index) : line.SellerSKU);

                    q  = "usp_findPartBySKU '" + sku + "'";
                    rs = (Recordset)DIAPI_Objects_FBA.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                    rs.DoQuery(q);
                    if (!(rs.EoF))
                    {
                        DIAPI_Objects_FBA.Invoice.Lines.ItemCode      = rs.Fields.Item(0).Value.ToString();
                        DIAPI_Objects_FBA.Invoice.Lines.Quantity      = Convert.ToDouble(line.QuantityShipped);
                        DIAPI_Objects_FBA.Invoice.Lines.WarehouseCode = "AM1"; // FBA orders ship from Amazon's warehouse.

                        // Add serial numbers
                        var sn = _sapDataService.GetSerialNumbers(sku, Convert.ToInt32(line.QuantityShipped));

                        // ensure that available serial numbers/license keys exist for SKU, in the required quantity
                        if (sn != null && sn.Count >= line.QuantityShipped)
                        {
                            for (int k = 0; k < Convert.ToInt32(line.QuantityShipped); k++)
                            {
                                DIAPI_Objects_FBA.Invoice.Lines.SerialNumbers.SetCurrentLine(k);
                                DIAPI_Objects_FBA.Invoice.Lines.SerialNumbers.ManufacturerSerialNumber = sn[k].SuppSerial;
                                DIAPI_Objects_FBA.Invoice.Lines.SerialNumbers.Quantity = 1;
                                DIAPI_Objects_FBA.Invoice.Lines.SerialNumbers.Add();
                            }
                        }
                        else // throw exception.
                        {
                            throw new SerialNumberNotFoundException(sku + ": Available serial#/license key was either not found or not enough to match quantity.");
                        }

                        // Set tax
                        if (Double.TryParse(line.ItemTax?.Amount, out double itemTax))
                        {
                            DIAPI_Objects_FBA.Invoice.Lines.TaxTotal = itemTax;

                            if ((string.Equals(o.Order.ShippingAddress.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) || string.Equals(o.Order.ShippingAddress.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase)) && itemTax == 0)
                            {
                                DIAPI_Objects_FBA.Invoice.Lines.TaxCode = "Exempt";

                                _orderLogRepository.LogEvent(
                                    o.Order.AmazonOrderId,
                                    "Adding " + sku + " - Shipping address is CA, but no sales tax was charged.",
                                    nameof(LogEventLevel.Warning),
                                    "DIAPI_Services",
                                    StackExtensions.GetCurrentMethod(),
                                    "Bast",
                                    "HAL 9000");
                            }
                            else if (!string.Equals(o.Order.ShippingAddress.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) && !string.Equals(o.Order.ShippingAddress.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase))
                            {
                                // no tax outside of california
                                DIAPI_Objects_FBA.Invoice.Lines.TaxCode  = "Exempt";
                                DIAPI_Objects_FBA.Invoice.Lines.TaxTotal = 0;
                            }
                            else // California
                            {
                                // Set tax
                                DIAPI_Objects_FBA.Invoice.Lines.TaxCode  = "CA";
                                DIAPI_Objects_FBA.Invoice.Lines.TaxTotal = itemTax;
                                //totalItemTax += itemTax;
                            }
                        }
                        else // invalid number, set tax to zero
                        {
                            DIAPI_Objects_FBA.Invoice.Lines.TaxTotal = 0;

                            _orderLogRepository.LogEvent(
                                o.Order.AmazonOrderId,
                                "Adding " + sku + ": Tax format invalid. Unable to set sales tax. Please validate tax manually.",
                                nameof(LogEventLevel.Error),
                                "DIAPI_Services",
                                StackExtensions.GetCurrentMethod(),
                                "Bast",
                                "HAL 9000");
                        }

                        if (!Double.TryParse(line.ItemPrice.Amount, out double itemPrice))
                        {
                            throw new InvalidOperationException("Invalid ItemPrice value for " + line.SellerSKU + " - " + line.Title);
                        }
                        else
                        {
                            totalItemPrice += itemPrice;
                        }

                        // Amazon ItemPrice = Quantity * ItemPrice
                        DIAPI_Objects_FBA.Invoice.Lines.LineTotal = itemPrice;
                        DIAPI_Objects_FBA.Invoice.Lines.Add();

                        partFound = true;

                        _orderLogRepository.LogEvent(
                            o.Order.AmazonOrderId,
                            String.Format("{0} was added to Invoice", sku),
                            nameof(LogEventLevel.Information),
                            "DIAPI_Services",
                            StackExtensions.GetCurrentMethod(),
                            "Bast",
                            "HAL 9000");
                    }
                    else // SKU not found
                    {
                        // update return Dictionary with missingSKU flag
                        if (!InvoiceNums.ContainsKey("ActionRequired"))
                        {
                            InvoiceNums.Add("ActionRequired", "true");
                        }
                        else
                        {
                            InvoiceNums["ActionRequired"] = "true";
                        }

                        _orderLogRepository.LogEvent(
                            o.Order.AmazonOrderId,
                            String.Format("{0} was not found. Please add manually", sku),
                            nameof(LogEventLevel.Error),
                            "DIAPI_Services",
                            StackExtensions.GetCurrentMethod(),
                            "Bast",
                            "HAL 9000");
                    }
                }
                rs = null;

                if (!partFound)
                {
                    DIAPI_Objects_FBA.Invoice.Lines.ItemCode        = "PLCHLDR";
                    DIAPI_Objects_FBA.Invoice.Lines.ItemDescription = "Placeholder";
                    DIAPI_Objects_FBA.Invoice.Lines.Quantity        = 1;
                    DIAPI_Objects_FBA.Invoice.Lines.UnitPrice       = 0;
                    DIAPI_Objects_FBA.Invoice.Lines.Add();

                    _orderLogRepository.LogEvent(
                        o.Order.AmazonOrderId,
                        "Unable to find SKUs for invoice, so a placeholder was added.",
                        nameof(LogEventLevel.Error),
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "Bast",
                        "HAL 9000");
                }

                if (!Double.TryParse(o.Order.OrderTotal.Amount, out double total))
                {
                    throw new InvalidOrderTotalException("The OrderTotal for Amazon order " + o.Order.AmazonOrderId + " is invalid.");
                }

                // Override OrderTotal
                // if shipping state is not CA, ignore tax and generate order total from the sum of all totalItemPrice + totalShipCost
                if (string.Equals(o.Order.ShippingAddress.StateOrRegion, "ca", StringComparison.OrdinalIgnoreCase) || string.Equals(o.Order.ShippingAddress.StateOrRegion, "california", StringComparison.OrdinalIgnoreCase))
                {
                    DIAPI_Objects_FBA.Invoice.DocTotal = total;
                }
                else
                {
                    DIAPI_Objects_FBA.Invoice.DocTotal = totalItemPrice + totalShipCost;
                }

                RetCode = DIAPI_Objects_FBA.Invoice.Add();

                if (RetCode != 0)
                {
                    DIAPI_Objects_FBA.Company.GetLastError(out errCode, out errMsg);

                    _orderLogRepository.LogEvent(
                        o.Order.AmazonOrderId,
                        errCode + " - " + errMsg + " - Invoice was not created.",
                        nameof(LogEventLevel.Critical),
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "Bast",
                        "HAL 9000");

                    if (!InvoiceNums.ContainsKey("ActionRequired"))
                    {
                        InvoiceNums.Add("ActionRequired", "true");
                    }
                    else
                    {
                        InvoiceNums["ActionRequired"] = "true";
                    }

                    DocEntry = RetCode.ToString(); // return err num
                }
                else
                {
                    // return DocEntry of new Invoice
                    DIAPI_Objects_FBA.Company.GetNewObjectCode(out DocEntry);

                    // NOTE: pass DocEntry to proc to get invoice DocNum for log, but return DocEntry
                    q  = "usp_MarketplaceGetDocNum " + DocEntry + ", 'Inv'";
                    rs = (Recordset)DIAPI_Objects_FBA.Company.GetBusinessObject(BoObjectTypes.BoRecordset);
                    rs.DoQuery(q);
                    if (!(rs.EoF))
                    {
                        DocNum = Convert.ToInt32(rs.Fields.Item(0).Value);
                    }

                    InvoiceNums.Add("DocEntry", DocEntry);
                    InvoiceNums.Add("DocNum", DocNum.ToString());

                    _orderLogRepository.LogEvent(
                        o.Order.AmazonOrderId,
                        String.Format("Invoice {0} was created. Please verify addresses, pricing, warehouses and shipping.", DocNum),
                        nameof(LogEventLevel.Information),
                        "DIAPI_Services",
                        StackExtensions.GetCurrentMethod(),
                        "Bast",
                        "HAL 9000");

                    rs = null;
                }

                _unitOfWork.Commit();

                // return Dictionary with DocNum and DocEntry
                return(InvoiceNums);
            }
            catch (Exception ex)
            {
                _orderLogRepository.LogEvent(
                    o.Order.AmazonOrderId,
                    String.Format("{0} - Invoice was not created.", ex.GetType().Name + " - " + ex.Message),
                    nameof(LogEventLevel.Critical),
                    "DIAPI_Services",
                    StackExtensions.GetCurrentMethod(),
                    "Bast",
                    "HAL 9000");

                if (!InvoiceNums.ContainsKey("ActionRequired"))
                {
                    InvoiceNums.Add("ActionRequired", "true");
                }
                else
                {
                    InvoiceNums["ActionRequired"] = "true";
                }

                rs = null;

                return(InvoiceNums);
            }
        }