/// <summary>
        /// Get the collection of pricing variables required to create a package.
        /// When only loading variables to create the form, packageID can be 0 (providerID too),
        /// but for when using it to get the posted values and saved in database, all ID fields
        /// need to be accuracy.
        /// Variables values will be empty, but the list and definitions will be complete.
        /// </summary>
        /// <param name="providerID"></param>
        /// <param name="packageID"></param>
        /// <param name="positionID"></param>
        /// <param name="pricingTypeID"></param>
        /// <returns></returns>
        public static PricingVariables ForNewProviderPackage(int providerID, int packageID, int positionID, int pricingTypeID)
        {
            var ret = new PricingVariables(providerID, packageID);

            LoadNew(ret, positionID, pricingTypeID);
            return(ret);
        }
Beispiel #2
0
        public void CalculateCustomerData(int customerID, PackageBaseData package, FeeRate fee, PricingModelData modelData, System.Web.WebPages.Html.ModelStateDictionary ModelState)
        {
            /* IMPORTANT: we calculate here the service duration for one session based on some custom variables for housekeeper pricing,
             * final price and fees are calculated in the standard code using the package Duration field, because of that
             * we only update package.Duration here for later complete price calculation */

            // Get customer input
            var nbeds  = Request[String.Format("bedrooms-number[{0}]", package.ID)].AsInt();
            var nbaths = Request[String.Format("bathrooms-number[{0}]", package.ID)].AsInt();
            // get provider rate
            var providerRate = GetProviderCleaningRate(package);
            // Apply formula, changed by the providerRate (variation from the average)
            var duration = ApplyFormula(nbeds, nbaths) * providerRate;
            // Create time object from duration, rounded to quarter-hours (15 minutes blocks)
            var timeDuration = ASP.LcHelpers.RoundTimeToQuarterHour(TimeSpan.FromMinutes(duration), ASP.LcHelpers.RoundingType.Up);

            // Create variables object with the specific data used in this calculation (will be saved later by the normal packages process)
            // Provider values get included in the object, something that is wanted for historic purposes on database.
            PricingVariables pricingvars = PricingVariables.FromPackageBaseData(package);

            pricingvars["BathsNumber"].Value = nbaths;
            pricingvars["BedsNumber"].Value  = nbeds;
            // Change package with the information:
            package.Duration        = timeDuration;
            modelData.ProviderInput = providerRate;
            modelData.CustomerInput = pricingvars;
        }
        /// <summary>
        /// Get the collection of pricing variables with its values that were persisted
        /// for a given package and pricing estimate.
        /// </summary>
        /// <param name="packageID"></param>
        /// <param name="pricingEstimateID"></param>
        /// <param name="pricingEstimateRevision"></param>
        /// <returns></returns>
        public static PricingVariables FromPricingEstimatePackage(int packageID, int pricingEstimateID, int pricingEstimateRevision)
        {
            var ret = new PricingVariables(-1, packageID);

            Load(ret, -1, packageID, pricingEstimateID, pricingEstimateRevision);
            return(ret);
        }
Beispiel #4
0
        /// <summary>
        /// It shows the customer variables values
        /// </summary>
        /// <param name="package"></param>
        /// <returns></returns>
        public string GetPackagePricingDetails(int packageID, int pricingEstimateID, int pricingEstimateRevision)
        {
            var pv = PricingVariables.FromPricingEstimatePackage(packageID, pricingEstimateID, pricingEstimateRevision);

            return(pv == null ? ""
                : String.Format("bedrooms: {0}, bathrooms: {1}", pv.GetValue <int>("BedsNumber", 0), pv.GetValue <int>("BathsNumber", 0)));
        }
Beispiel #5
0
        public List <string> Post([FromBody] PricingVariables variables)
        {
            var bedrooms      = Int32.Parse(variables.Bedrooms);
            var bathrooms     = Int32.Parse(variables.Bathrooms);
            var residenceType = variables.ResidenceType;
            var serviceType   = variables.ServiceType;

            var duration = GetDuration(bedrooms, bathrooms, residenceType, serviceType);

            var price = CalculatePrice(bedrooms, bathrooms, residenceType, serviceType);

            //double approxDuration = duration / 2;
            double finalDuration = Math.Round(duration, 1);

            string serviceDuration = finalDuration.ToString();

            string finalPrice = price.ToString();

            var list = new List <string>();

            list.Add(serviceDuration);
            list.Add(finalPrice);

            return(list);
        }
Beispiel #6
0
        private double GetProviderCleaningRate(PackageBaseData package)
        {
            // return .8; // 140.34 / formulaAverageT
            PricingVariables pricingvars = PricingVariables.FromPackageBaseData(package);

            return(pricingvars.GetValue <double>("CleaningRate", 1.0));
        }
        /// <summary>
        /// Get the collection of variables with its values for an existent provider package.
        /// </summary>
        /// <param name="providerID"></param>
        /// <param name="packageID"></param>
        /// <returns></returns>
        public static PricingVariables FromProviderPackage(int providerID, int packageID)
        {
            var ret = new PricingVariables(providerID, packageID);

            Load(ret, providerID, packageID, 0, 0);
            return(ret);
        }
Beispiel #8
0
        public void SaveProviderData(PackageBaseData package, Database db)
        {
            var provTime = Request["provider-average-time"].AsFloat();
            var provRate = provTime / ApplyFormula();
            // Save rate on DB
            PricingVariables provars = PricingVariables.FromPackageBaseData(package);

            provars["CleaningRate"].Value = provRate;
            provars.Save();
        }
        public void CalculateCustomerData(int customerID, PackageBaseData package, FeeRate fee, PricingModelData modelData, System.Web.WebPages.Html.ModelStateDictionary ModelState)
        {
            /* IMPORTANT: we set here the service duration for one session based on the customer value (from the form),
             * update the hourly-price from provider variable value
             * and the hourly-surcharge based on the variables.
             * Final price and fees are calculated in the standard code using the package Duration field and HourlySurcharge field, because of that
             * the final price is not calculated here. */

            // TOREVIEW: Needs input data validation with ModelState and check ModelState.IsValid at LcPricingModel?

            // Getting variables
            PricingVariables pricingvars     = PricingVariables.FromPackageBaseData(package);
            TimeSpan         timeDuration    = TimeSpan.Zero;
            decimal          hourlySurcharge = 0;

            // Iterating customer variables:
            foreach (var pvar in pricingvars)
            {
                if (pvar.Value.Def.IsCustomerVariable)
                {
                    // Setting value from the form
                    pvar.Value.Value = LcUtils.GetTypedValue(Request[String.Format("{0}[{1}]", pvar.Key, package.ID)], null, pvar.Value.Def.DataType);
                    // For the 'Hours:2' customer variable, we get it form the form and set the duration with it.
                    if (pvar.Key == "Hours")
                    {
                        // Create time object from duration, rounded to quarter-hours (15 minutes blocks)
                        var duration = pvar.Value.GetValue <double>(0);
                        timeDuration = ASP.LcHelpers.RoundTimeToQuarterHour(TimeSpan.FromHours(duration), ASP.LcHelpers.RoundingType.Up);
                    }
                    else
                    {
                        // For other variables, we calculate it using the general formula and its added to the hourly surcharge
                        // Get the provider var, we need its values.
                        var provar = pricingvars.GetCalculateWithVariableFor(pvar.Value);
                        // General formula for 1 hour: (CustomerValueInputVariable - ProviderNumberIncludedVariable) * ProviderPriceVariable
                        // EXCEPT when CustomerValueInputVariable is equal or less than ProviderNumberIncludedVariable, then is 0
                        decimal amount = 0;
                        if (pvar.Value.GetValue <decimal>(0) > (provar.ProviderNumberIncluded ?? 0))
                        {
                            amount = (pvar.Value.GetValue <decimal>(0) - (provar.ProviderNumberIncluded ?? 0)) * provar.GetValue <decimal>(0);
                        }
                        // Add to the hourly surcharge
                        hourlySurcharge += amount;
                    }
                }
            }

            // Update package data:
            package.Duration        = timeDuration;
            package.HourlySurcharge = hourlySurcharge;
            modelData.CustomerInput = pricingvars;
        }
        public bool ValidateProviderData(PackageBaseData package, System.Web.WebPages.Html.ModelStateDictionary modelState)
        {
            var valid = true;
            PricingVariables provars = PricingVariables.FromPackageBaseData(package);

            foreach (var provar in provars)
            {
                if (provar.Value.Def.IsProviderVariable)
                {
                    // Validation: Emit error if there is not a value or is not of the desired type
                    if (String.IsNullOrWhiteSpace(Request[provar.Key + "-value"]))
                    {
                        modelState.AddError(provar.Key + "-value", LcRessources.RequiredField(provar.Value.Def.VariableLabel));
                        valid = false;
                    }
                    else if (!LcUtils.ValidateType(Request[provar.Key + "-value"], provar.Value.Def.DataType))
                    {
                        modelState.AddError(provar.Key + "-value", LcRessources.InvalidFieldValue(provar.Value.Def.VariableLabel));
                        valid = false;
                    }
                    // NO Validation: Detect pricing variable 'hourly rate' to copy the value to the standard field on package
                    // PricingVariableID:1 'hourly rate' for all positions and pricings.
                    // We need to do this data change on validation because the 'save' part happen after the package being saved (for good reasons)
                    if (provar.Value.PricingVariableID == 1)
                    {
                        package.PriceRate     = Request[provar.Key + "-value"].AsDecimal();
                        package.PriceRateUnit = "hour";
                    }
                    // Validation: Check the optional variable value properties (number, min, max)
                    if (!String.IsNullOrWhiteSpace(Request[provar.Key + "-numberincluded"]) &&
                        !Request[provar.Key + "-numberincluded"].IsDecimal())
                    {
                        modelState.AddError(provar.Key + "-numberincluded", String.Format("Invalid number for included '{0}'", provar.Value.Def.VariableNameSingular));
                        valid = false;
                    }
                    if (!String.IsNullOrWhiteSpace(Request[provar.Key + "-minnumberallowed"]) &&
                        !Request[provar.Key + "-minnumberallowed"].IsDecimal())
                    {
                        modelState.AddError(provar.Key + "-minnumberallowed", String.Format("Invalid number for '{0}'", provar.Value.Def.MinNumberAllowedLabel));
                        valid = false;
                    }
                    if (!String.IsNullOrWhiteSpace(Request[provar.Key + "-maxnumberallowed"]) &&
                        !Request[provar.Key + "-maxnumberallowed"].IsDecimal())
                    {
                        modelState.AddError(provar.Key + "-maxnumberallowed", String.Format("Invalid number for '{0}'", provar.Value.Def.MaxNumberAllowedLabel));
                        valid = false;
                    }
                }
            }
            return(valid);
        }
        /// <summary>
        /// Get variables given a package object that enables this to automatically get variables
        /// for a new package (when ID is 0) or the values for the existing package on other case.
        /// </summary>
        /// <param name="package">The package information used to discover what variables and values retrieve.</param>
        /// <returns></returns>
        public static PricingVariables FromPackageBaseData(PackageBaseData package)
        {
            PricingVariables provars;

            if (package.ID == 0)
            {
                provars = PricingVariables.ForNewProviderPackage(package.ProviderUserID, 0, package.PositionID, package.PricingTypeID);
            }
            else
            {
                provars = PricingVariables.FromUpdatedProviderPackage(package.ProviderUserID, package.ID, package.PositionID, package.PricingTypeID);
            }
            return(provars);
        }
 private static void Load(PricingVariables data, int userID, int packageID, int pricingEstimateID = 0, int pricingEstimateRevision = 0)
 {
     using (var db = Database.Open("sqlloco"))
     {
         var vars = db.Query(sqlGetVariablesActualValues, userID, packageID, pricingEstimateID, pricingEstimateRevision,
                             LcData.GetCurrentLanguageID(), LcData.GetCurrentCountryID());
         foreach (var r in vars)
         {
             var varValue = PricingVariableValue.CreateFromDbRecord(r);
             data[r.InternalName] = varValue;
             // Update index
             data.idIndex[varValue.PricingVariableID] = varValue;
         }
     }
 }
        /// <summary>
        /// It updates the values for customer variables in the passed @vars with
        /// the values used by the @customerID in its last booking/estimate.
        /// This allows the 'memory effect' on bookings, helping customers with repeated bookings.
        /// </summary>
        /// <param name="vars"></param>
        /// <param name="customerID"></param>
        public static void UpdateWithLastCustomerValues(PricingVariables vars, int customerID)
        {
            dynamic data = null;

            // Get customer values from last booking/estimate
            using (var db = Database.Open("sqlloco"))
            {
                var sql = @"
                    DECLARE @UserID int

                    SET @UserID = @0

                    DECLARE @PricingEstimateID int
                    DECLARE @PricingEstimateRevision int

                    SELECT	TOP 1
		                    @PricingEstimateID = PricingEstimateID,
                            @PricingEstimateRevision = PricingEstimateRevision
                    FROM	PricingVariableValue
                    WHERE	Active = 1
		                    AND UserID = @UserID
                    ORDER BY PricingEstimateID DESC, PricingEstimateRevision DESC

                    SELECT	V.PricingVariableID, V.Value
                    FROM	PricingVariableValue As V
                    WHERE	V.Active = 1
		                    AND V.UserID = @UserID
		                    AND V.PricingEstimateID = @PricingEstimateID
		                    AND V.PricingEstimateRevision = @PricingEstimateRevision
                ";

                data = db.Query(sql, customerID);
            }
            // Update vars with that values
            foreach (var r in data)
            {
                var v = vars[(int)r.PricingVariableID];
                if (v != null && v.Def.IsCustomerVariable)
                {
                    v.Value = r.Value;
                }
            }
        }
        public void SaveProviderData(PackageBaseData package, Database db)
        {
            PricingVariables provars = PricingVariables.FromPackageBaseData(package);

            // Get values from for per variable
            foreach (var provar in provars)
            {
                if (provar.Value.Def.IsProviderVariable)
                {
                    // Value
                    provar.Value.Value = LcUtils.GetTypedValue(Request[provar.Key + "-value"], null, provar.Value.Def.DataType);
                    // Number Included
                    provar.Value.ProviderNumberIncluded = LcUtils.GetTypedValue <decimal>(Request[provar.Key + "-numberincluded"], 0);
                    // Min/Max allowed
                    provar.Value.ProviderMinNumberAllowed = LcUtils.GetTypedValue <decimal>(Request[provar.Key + "-minnumberallowed"], 0);
                    provar.Value.ProviderMaxNumberAllowed = LcUtils.GetTypedValue <decimal>(Request[provar.Key + "-maxnumberallowed"], 0);
                }
            }
            provars.Save();
        }
 /// <summary>
 /// Load the set of pricingVariables with the saved values for the given provider package
 /// updated with current set of variables assigned to the position and pricingType,
 /// suitable to fill the 'edit package' form.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="userID"></param>
 /// <param name="packageID"></param>
 /// <param name="positionID"></param>
 /// <param name="pricingTypeID"></param>
 private static void LoadUpdated(PricingVariables data, int userID, int packageID, int positionID, int pricingTypeID)
 {
     using (var db = Database.Open("sqlloco"))
     {
         var vars = db.Query(sqlGetVariablesForEdit,
                             userID,
                             packageID,
                             positionID,
                             pricingTypeID,
                             LcData.GetCurrentLanguageID(),
                             LcData.GetCurrentCountryID());
         foreach (var r in vars)
         {
             var varValue = PricingVariableValue.CreateFromDbRecord(r);
             data[r.InternalName] = varValue;
             // Update index
             data.idIndex[varValue.PricingVariableID] = varValue;
         }
     }
 }
Beispiel #16
0
        public async Task <List <string> > GeneratePriceAndDuration(string bedrooms, string bathrooms, string residence, string serviceType)
        {
            PricingVariables variables = new PricingVariables()
            {
                Bedrooms      = bedrooms,
                Bathrooms     = bathrooms,
                ResidenceType = residence,
                ServiceType   = serviceType
            };

            HttpClient          client = new HttpClient();
            HttpResponseMessage response;

            // Use the PostAsync method against the base URL to add the book.
            // Create the HttpContent from the JSON string by creating a new StringContent object,
            // use the constructor which also takes an encoding and media type.
            response = await client.PostAsync(Url, new StringContent(JsonConvert.SerializeObject(variables),
                                                                     Encoding.UTF8, "application/json"));

            return(JsonConvert.DeserializeObject <List <string> >(await response.Content.ReadAsStringAsync()));
        }
        /// <summary>
        /// It shows the customer variables values
        /// </summary>
        /// <param name="package"></param>
        /// <returns></returns>
        public string GetPackagePricingDetails(int packageID, int pricingEstimateID, int pricingEstimateRevision)
        {
            var pv            = PricingVariables.FromPricingEstimatePackage(packageID, pricingEstimateID, pricingEstimateRevision);
            var res           = new List <string>();
            var summaryFormat = "{0}: {1}";

            foreach (var v in pv)
            {
                // On pricing summary only customer values are showed,
                // and the special var 'Hours' is avoided since the package already shows its 'total duration'
                // as part of the generic information
                if (v.Value.Def.IsProviderVariable ||
                    v.Key == "Hours")
                {
                    continue;
                }

                // If value is a number
                var val = v.Value.GetValue <double?>(null);
                if (val.HasValue)
                {
                    // Show singular or plural depending on the value
                    if (val.Value == 1)
                    {
                        res.Add(String.Format(summaryFormat, v.Value.Def.VariableNameSingular, 1));
                    }
                    else
                    {
                        res.Add(String.Format(summaryFormat, v.Value.Def.VariableNamePlural, val.Value));
                    }
                }
                else
                {
                    // Is another kind of value (string, datetime, ...) use singular variable name
                    res.Add(String.Format(summaryFormat, v.Value.Def.VariableNameSingular, v.Value.Value));
                }
            }
            return(ASP.LcHelpers.JoinNotEmptyStrings(", ", res));
        }
 /// <summary>
 /// Save all the values for the variables in the database.
 /// If there is no pricingEstimate (@pricingEstimateID is 0 or less)
 /// then only the provider variables will be saved.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="userID"></param>
 /// <param name="packageID"></param>
 /// <param name="pricingEstimateID"></param>
 /// <param name="pricingEstimateRevision"></param>
 private static void Save(PricingVariables data, int userID, int packageID, int pricingEstimateID = 0, int pricingEstimateRevision = 0)
 {
     using (var db = Database.Open("sqlloco"))
     {
         foreach (var v in data)
         {
             // Only save provider values when there is no pricingEstimate
             // (avoid save customer variables that are null, unneed and will fail)
             if (pricingEstimateID > 0 || v.Value.Def.IsProviderVariable)
             {
                 db.Execute(sqlSetVariables,
                            userID, packageID, pricingEstimateID, pricingEstimateRevision,
                            v.Value.PricingVariableID,
                            v.Value.Value,
                            v.Value.ProviderNumberIncluded,
                            v.Value.ProviderMinNumberAllowed,
                            v.Value.ProviderMaxNumberAllowed
                            );
             }
         }
     }
 }
 private static void LoadNew(PricingVariables data, int positionID, int pricingTypeID)
 {
     using (var db = Database.Open("sqlloco"))
     {
         var vars = db.Query(sqlGetVariablesForNewPackage, positionID, pricingTypeID,
                             LcData.GetCurrentLanguageID(), LcData.GetCurrentCountryID());
         foreach (var r in vars)
         {
             var varValue = new PricingVariableValue {
                 PricingVariableID          = r.PricingVariableID
                 , Value                    = null
                 , ProviderNumberIncluded   = null
                 , ProviderMinNumberAllowed = null
                 , ProviderMaxNumberAllowed = null
                 , Def = PricingVariableDefinition.CreateFromDbRecord(r)
             };
             data[r.InternalName] = varValue;
             // Update index
             data.idIndex[varValue.PricingVariableID] = varValue;
         }
     }
 }
        public string GetPackageViewHtml(PackageBaseData package, Dictionary <string, LcPricingModel.FeeRate> feesSet, bool forEmail = false)
        {
            // NOTE: It follows the same base code than GetProviderHtml but replacing form elements by div/span and appling fees when customer

            // Get variables
            PricingVariables provars = PricingVariables.FromPackageBaseData(package);

            // Create html for form elements, variables values organized per sections
            var hValues       = new StringBuilder();
            var hSurcharges   = new StringBuilder();
            var hIncludes     = new StringBuilder();
            var hRestrictions = new StringBuilder();

            // Iterating provider variables:
            foreach (var provar in provars)
            {
                // A listing view of *the package* only shows provider variables for any user, since there is no customer values!
                if (provar.Value.Def.IsProviderVariable)
                {
                    // Showing the variable value.
                    // Avoid the 'hourly-rate' variable value, thats is showed already in a special way
                    // by the standard package code (using the copy at pak.PriceRate)
                    if (provar.Key != "HourlyRate")
                    {
                        // Provider variables *value*s are ever a price: if we have a feesSet, then
                        // we must apply fees because the view require show prices with fees (mostly when is
                        // the user who see the package, as in booking and public profile).
                        // To variables, we apply ever the standard fees, there is no chance for the flat ones.
                        // We follow the convention for hourly prices (since this are too per hour): 1 decimal position
                        var valuePrice = feesSet == null
                                         // Without fees, we apply a fee-rate of 0, and rounding to 1 decimal
                            ? new Price(provar.Value.GetValue <decimal>(0), 0, 1)
                                         // With fees, we apply that, rounding ever to 1 decimal
                            : new Price(provar.Value.GetValue <decimal>(0), feesSet["standard:customer"], 1);

                        if (!String.IsNullOrEmpty(provar.Value.Def.HourlySurchargeLabel))
                        {
                            hSurcharges.AppendFormat("<li>{1:c} {0}</li>",
                                                     EncodeForHtml(provar.Value.Def.HourlySurchargeLabel),
                                                     valuePrice.TotalPrice);
                        }
                        else
                        {
                            // Is not a surcharge, is a value
                            hValues.AppendFormat("<li>{0}: {1:c}</li>",
                                                 EncodeForHtml(provar.Value.Def.VariableLabel),
                                                 valuePrice.TotalPrice);
                        }
                    }
                    // Number Included
                    if (!String.IsNullOrEmpty(provar.Value.Def.NumberIncludedLabel) &&
                        provar.Value.ProviderNumberIncluded.HasValue &&
                        provar.Value.ProviderNumberIncluded.Value > 0)
                    {
                        hIncludes.AppendFormat("<li>{0} {1:#,##0.##} {2}</li>",
                                               EncodeForHtml(provar.Value.Def.NumberIncludedLabel),
                                               provar.Value.ProviderNumberIncluded.Value,
                                               provar.Value.ProviderNumberIncluded.Value != 1
                            ? EncodeForHtml(provar.Value.Def.VariableNamePlural)
                            : EncodeForHtml(provar.Value.Def.VariableNameSingular));
                    }
                    // Minimum number
                    if (!String.IsNullOrEmpty(provar.Value.Def.MinNumberAllowedLabel) &&
                        provar.Value.ProviderMinNumberAllowed.HasValue)
                    {
                        hRestrictions.AppendFormat("<li>{0} {1:#,##0.##} {2}</li>",
                                                   EncodeForHtml(provar.Value.Def.MinNumberAllowedLabel),
                                                   provar.Value.ProviderMinNumberAllowed,
                                                   provar.Value.ProviderMinNumberAllowed.Value != 1
                            ? EncodeForHtml(provar.Value.Def.VariableNamePlural)
                            : EncodeForHtml(provar.Value.Def.VariableNameSingular));
                    }
                    // Maximum number
                    if (!String.IsNullOrEmpty(provar.Value.Def.MaxNumberAllowedLabel) &&
                        provar.Value.ProviderMaxNumberAllowed.HasValue)
                    {
                        hRestrictions.AppendFormat("<li>{0} {1:#,##0.##} {2}</li>",
                                                   EncodeForHtml(provar.Value.Def.MaxNumberAllowedLabel),
                                                   provar.Value.ProviderMaxNumberAllowed,
                                                   provar.Value.ProviderMaxNumberAllowed.Value != 1
                            ? EncodeForHtml(provar.Value.Def.VariableNamePlural)
                            : EncodeForHtml(provar.Value.Def.VariableNameSingular));
                    }
                }
            }

            // Creating HTML
            var s = new StringBuilder();

            s.Append("<div class='hourly-pricing'>");
            if (hValues.Length > 0)
            {
                s.AppendFormat("<ul class='var-values' style='{0}'>", forEmail ? ASP.LcEmailTemplateHelper.ClassUlOl(false) : "");
                s.Append(hValues);
                s.Append("</ul>");
            }
            if (hIncludes.Length > 0)
            {
                s.AppendFormat("<h5 class='w-ProviderPackage-sectionTitle' style='{0}'>Includes:</h5>", forEmail ? ASP.LcEmailTemplateHelper.ClassH5() : "");
                s.AppendFormat("<ul class='var-includes' style='{0}'>", forEmail ? ASP.LcEmailTemplateHelper.ClassUlOl(false) : "");
                s.Append(hIncludes);
                s.Append("</ul>");
            }
            if (hSurcharges.Length > 0)
            {
                s.AppendFormat("<h5 class='w-ProviderPackage-sectionTitle' style='{0}'>Hourly surcharge(s):</h5>", forEmail ? ASP.LcEmailTemplateHelper.ClassH5() : "");
                s.AppendFormat("<ul class='var-surcharges' style='{0}'>", forEmail ? ASP.LcEmailTemplateHelper.ClassUlOl(false) : "");
                s.Append(hSurcharges);
                s.Append("</ul>");
            }
            if (hRestrictions.Length > 0)
            {
                s.AppendFormat("<h5 class='w-ProviderPackage-sectionTitle' style='{0}'>Booking restrictions:</h5>", forEmail ? ASP.LcEmailTemplateHelper.ClassH5() : "");
                s.AppendFormat("<ul class='var-restrictions' style='{0}'>", forEmail ? ASP.LcEmailTemplateHelper.ClassUlOl(false) : "");
                s.Append(hRestrictions);
                s.Append("</ul>");
            }
            s.Append("</div>");

            return(s.ToString());
        }
        public string GetCustomerHtml(int customerID, PackageBaseData package, FeeRate fee)
        {
            // Get variables
            PricingVariables provars = PricingVariables.FromPackageBaseData(package);

            // Update vars with customers values from its last estimate/booking?
            PricingVariables.UpdateWithLastCustomerValues(provars, customerID);

            var sv = new StringBuilder();

            // Iterating customer variables:
            foreach (var custvar in provars)
            {
                if (custvar.Value.Def.IsCustomerVariable)
                {
                    var    calculateWithVar = provars.GetCalculateWithVariableFor(custvar.Value);
                    var    provPrice        = new Price(calculateWithVar.GetValue <decimal>(0), fee, 1);
                    string footNoteFormat   = calculateWithVar.PricingVariableID == 1 ? "Base rate is {0:C} per hour" : "Add {0:C} per hour is for each additional {2}";
                    // If package already include an amount, notify it
                    if ((calculateWithVar.ProviderNumberIncluded ?? 0) > 0)
                    {
                        footNoteFormat = "Includes {1:#,##0.##} {3}--add {0:C}/hr for each add'l {2}";
                    }
                    string sliderFootnote = String.Format(footNoteFormat, provPrice.TotalPrice,
                                                          calculateWithVar.ProviderNumberIncluded, calculateWithVar.Def.VariableNameSingular,
                                                          calculateWithVar.Def.VariableNamePlural);

                    // We set the customer value as
                    // - the posted-form value,
                    // - else the db saved value (it works when variables get updated with its last estimate/booking values)
                    // - else the ProviderNumberIncluded for the var
                    // - else defaulted to zero:
                    var custValue = Request[String.Format("{1}[{0}]", package.ID, EncodeForHtml(custvar.Key))]
                                    .AsDecimal(custvar.Value.GetValue <decimal>(calculateWithVar.ProviderNumberIncluded ?? 0));

                    if (custvar.Key == "Hours")
                    {
                        sv.AppendFormat("<div class='customer-list' data-prov-value='{2}' data-slider-stype='hourly' data-slider-footnote='{3}'><label><span class='has-tooltip' title='{1}'>{0}</span>: {4}</div>",
                                        EncodeForHtml(custvar.Value.Def.VariableLabel),
                                        EncodeForHtml(custvar.Value.Def.VariableLabelPopUp),
                                        provPrice.BasePrice, // Gives to html the price without fees, that are calculated client-side
                                        EncodeForHtml(sliderFootnote),
                                        LcUtils.BuildHtmlSelect(
                                            String.Format("{1}[{0}]", package.ID, EncodeForHtml(custvar.Key)),
                                            custValue,
                                            LcUtils.GenerateKeyValueRange <string, object>(
                                                calculateWithVar.ProviderMinNumberAllowed ?? 0,
                                                (calculateWithVar.ProviderMaxNumberAllowed ?? 100) + .5M,
                                                .5M,
                                                custvar.Value.Def.VariableNameSingular,
                                                custvar.Value.Def.VariableNamePlural
                                                )
                                            )
                                        );
                    }
                    else
                    {
                        sv.AppendFormat(@"
                        <div class='customer-slider' data-prov-value='{2}'
                            data-slider-value='{5}' data-slider-step='{6}' data-slider-footnote='{7}' data-slider-stype='hourly'
                            data-slider-min='{8}' data-slider-max='{9}' data-slider-number-included='{10}' data-slider-labels-layout='{11}' data-slider-autosize='true'>
                        <label><span class='has-tooltip' title='{4}'>{3}</span>: <input name='{1}[{0}]' type='text' value='{5}' /></label></div>"
                                        , package.ID
                                        , EncodeForHtml(custvar.Key)
                                        , provPrice.BasePrice // Gives to html the price without fees, that are calculated client-side
                                        , EncodeForHtml(custvar.Value.Def.VariableLabel)
                                        , EncodeForHtml(custvar.Value.Def.VariableLabelPopUp)
                                        , custValue
                                        // slider step fixed to 1 for most cases, or .5 for Hours
                                        , custvar.Value.PricingVariableID == 2 ? .5 : 1
                                        , EncodeForHtml(sliderFootnote)
                                        , calculateWithVar.ProviderMinNumberAllowed
                                        , calculateWithVar.ProviderMaxNumberAllowed
                                        , calculateWithVar.ProviderNumberIncluded
                                        // special labels for Hours
                                        , custvar.Key == "Hours" ? "hours" : "standard");
                    }
                }
            }

            // Create html
            var h = new StringBuilder();

            h.AppendFormat("<div class='hourly-pricing' data-fee-rate='{0}' data-fixed-fee-amount='{1}'>", fee.Percentage, fee.Currency);
            h.Append(sv);
            h.Append("</div>");

            return(h.ToString());
        }
        public string GetProviderHtml(PackageBaseData package)
        {
            // Get variables
            PricingVariables provars = PricingVariables.FromPackageBaseData(package);

            // Create html for form elements, variables values organized per sections
            var hValues       = new StringBuilder();
            var hSurcharges   = new StringBuilder();
            var hIncludes     = new StringBuilder();
            var hRestrictions = new StringBuilder();

            // Iterating provider variables:
            foreach (var provar in provars)
            {
                if (provar.Value.Def.IsProviderVariable)
                {
                    if (!String.IsNullOrEmpty(provar.Value.Def.HourlySurchargeLabel))
                    {
                        hSurcharges.AppendFormat("<li><label>$ <input type='text' name='{1}-value' value='{3}' /> <span class='has-tooltip' title='{2}'>{0}</span></label></li>",
                                                 EncodeForHtml(provar.Value.Def.HourlySurchargeLabel),
                                                 EncodeForHtml(provar.Value.Def.InternalName), //==Key
                                                 EncodeForHtml(provar.Value.Def.VariableLabelPopUp),
                                                 Request[provar.Key + "-value"] ?? provar.Value.Value);
                    }
                    else
                    {
                        // Is not a surcharge, is a value
                        hValues.AppendFormat("<li><label><span class='has-tooltip' title='{2}'>{0}</span>: $ <input type='text' name='{1}-value' value='{3}' /></label></li>",
                                             EncodeForHtml(provar.Value.Def.VariableLabel),
                                             EncodeForHtml(provar.Value.Def.InternalName), //==Key
                                             EncodeForHtml(provar.Value.Def.VariableLabelPopUp),
                                             Request[provar.Key + "-value"] ?? provar.Value.Value);
                    }
                    if (!String.IsNullOrEmpty(provar.Value.Def.NumberIncludedLabel))
                    {
                        hIncludes.AppendFormat("<li><label>{0} <input type='text' name='{1}-numberincluded' value='{3}' /> <span class='has-tooltip' title='{2}'>{4}/{5}</span></label></li>",
                                               EncodeForHtml(provar.Value.Def.NumberIncludedLabel),
                                               EncodeForHtml(provar.Value.Def.InternalName), //==Key
                                               EncodeForHtml(provar.Value.Def.NumberIncludedLabelPopUp),
                                               (object)(Request[provar.Key + "-numberincluded"]) ?? provar.Value.ProviderNumberIncluded,
                                               EncodeForHtml(provar.Value.Def.VariableNameSingular),
                                               EncodeForHtml(provar.Value.Def.VariableNamePlural));
                    }
                    // Get min-max values list if available
                    var minMaxValuesList = String.IsNullOrWhiteSpace(provar.Value.Def.MinMaxValuesList)
                        ? null
                        : provar.Value.Def.GenerateMinMaxValuesCollection();
                    if (!String.IsNullOrEmpty(provar.Value.Def.MinNumberAllowedLabel))
                    {
                        string formControlHtml = "",
                               name            = provar.Key + "-minnumberallowed"; //==Value.Def.InternalName
                        var selectedValue      = (object)(Request[provar.Key + "-minnumberallowed"]) ?? provar.Value.ProviderMinNumberAllowed;

                        if (minMaxValuesList != null)
                        {
                            formControlHtml = LcUtils.BuildHtmlSelect(
                                name,
                                selectedValue,
                                minMaxValuesList);
                        }
                        else
                        {
                            formControlHtml = LcUtils.BuildHtmlInput(
                                name,
                                selectedValue);
                        }

                        hRestrictions.AppendFormat("<li><label><span class='has-tooltip' title='{2}'>{0}</span> {1}</label></li>",
                                                   EncodeForHtml(provar.Value.Def.MinNumberAllowedLabel),
                                                   formControlHtml,
                                                   EncodeForHtml(provar.Value.Def.MinNumberAllowedLabelPopUp));
                    }
                    if (!String.IsNullOrEmpty(provar.Value.Def.MaxNumberAllowedLabel))
                    {
                        string formControlHtml = "",
                               name            = provar.Key + "-maxnumberallowed"; //==Value.Def.InternalName
                        var selectedValue      = (object)(Request[provar.Key + "-maxnumberallowed"])
                                                 ?? provar.Value.ProviderMaxNumberAllowed
                                                 // Special default value for Max Hours #425
                                                 ?? (provar.Key == "HourlyRate" ? 8 : 0);
                        if (minMaxValuesList != null)
                        {
                            formControlHtml = LcUtils.BuildHtmlSelect(
                                name,
                                selectedValue,
                                minMaxValuesList);
                        }
                        else
                        {
                            formControlHtml = LcUtils.BuildHtmlInput(
                                name,
                                selectedValue);
                        }

                        hRestrictions.AppendFormat("<li><label><span class='has-tooltip' title='{2}'>{0}</span> {1}</label></li>",
                                                   EncodeForHtml(provar.Value.Def.MaxNumberAllowedLabel),
                                                   formControlHtml,
                                                   EncodeForHtml(provar.Value.Def.MaxNumberAllowedLabelPopUp));
                    }
                }
            }

            // Creating HTML
            var s = new StringBuilder();

            s.Append("<div class='hourly-pricing'>");
            if (hValues.Length > 0)
            {
                s.Append("<ul class='var-values'>");
                s.Append(hValues);
                s.Append("</ul>");
            }
            if (hIncludes.Length > 0)
            {
                s.Append("<h5>Includes:</h5>");
                s.Append("<ul class='var-includes'>");
                s.Append(hIncludes);
                s.Append("</ul>");
            }
            if (hSurcharges.Length > 0)
            {
                s.Append("<h5>Hourly surcharge(s):</h5>");
                s.Append("<ul class='var-surcharges'>");
                s.Append(hSurcharges);
                s.Append("</ul>");
            }
            if (hRestrictions.Length > 0)
            {
                s.Append("<h5>Booking restrictions:</h5>");
                s.Append("<ul class='var-restrictions'>");
                s.Append(hRestrictions);
                s.Append("</ul>");
            }
            s.Append("</div>");

            return(s.ToString());
        }