public static OperationResult <Stall> CraeteStall(string userId, string name, string prefix, StallEntities db)
        {
            var result = new OperationResult <Stall>(false);

            if (string.IsNullOrEmpty(userId))
            {
                result.Message = string.Format("UserId不能为空", prefix);
            }
            else if (string.IsNullOrEmpty(name))
            {
                result.Message = string.Format("铺名不能为空", prefix);
            }
            //else if (string.IsNullOrEmpty(prefix))
            //{
            //    result.Message = "Vend前缀不能为空";
            //}
            else if (Stall.FindByName(name, db) != null)
            {
                result.Message = string.Format("铺名 {0} 已占用", name);
            }
            //else if (Stall.FindByVendPrefix(prefix, db) != null)
            //{
            //    result.Message = string.Format("{0}.vendhq.com 已注册", prefix);
            //}
            else
            {
                var stall = new Stall()
                {
                    UserId = userId, StallName = name, Prefix = prefix
                };
                result.Data = db.Stalls.Add(stall);
                try
                {
                    db.SaveChanges();
                }
                catch
                {
                    result.Message = string.Format("无法保存店铺 {0}", name);
                }
            }

            if (result.Data != null)
            {
                result.Succeeded = true;
            }

            return(result);
        }
        public static IList <DeliveryOrPickupOption> GetDeliveryOptions(Models.Stall stall, DateTime dtStart, int nextDays,
                                                                        string area, int?distanceInMeters = null, decimal?orderAmount = null)
        {
            if (nextDays <= 0)
            {
                //stall advanced order days
                nextDays = _instance._setting.MaxAdvancedOrderDays < stall.Setting.MaxAdvancedOrderDays ?
                           _instance._setting.MaxAdvancedOrderDays : stall.Setting.MaxAdvancedOrderDays;
            }

            var options = _instance._setting.Delivery.GetOptions(dtStart, nextDays, null);

            //intersect with stall opening hours

            options = options.Intersect(stall.Setting.OpeningHours.GetDateTimePairs(dtStart, nextDays));

            var result = new List <DeliveryOrPickupOption>();

            foreach (var opt in options)
            {
                if (!Models.Area.IsApplicable(opt.Areas, area))
                {
                    continue;
                }

                var newOpt = DeliveryOrPickupOption.Parse(opt);
                newOpt.IsStoreDelivery = false;
                newOpt.Fee             = opt.Calculator.Calculate(opt.From, area, distanceInMeters, orderAmount);
                if (newOpt.Fee != null)
                {
                    result.Add(newOpt);
                }
            }

            return(result.Where(x => x.ReferenceTimePonit > dtStart).OrderBy(x => x.From).ToList());
        }
        public static async Task <OperationResult> InitMultiStall(int id, StallEntities db)
        {
            var result    = new OperationResult(false);
            var baseStall = Stall.FindById(id, db);

            if (baseStall == null)
            {
                result.Message = $"Stall {id} is not exist";
                return(result);
            }

            //load base info
            var infoResult = await baseStall.LoadInfo();

            if (!infoResult.Succeeded)
            {
                result.Message = infoResult.Message;
                return(result);
            }

            //load product
            var productResult = await baseStall.LoadProduct();

            if (!productResult.Succeeded)
            {
                result.Message = productResult.Message;
                return(result);
            }

            //create webhook
            var webhookResult = await baseStall.CreateWebhook();

            if (!webhookResult.Succeeded)
            {
                result.Message = webhookResult.Message;
                return(result);
            }

            //load suppliers
            var supplierResult = await SDK.Vend.Supplier.GetSuppliersAsync(baseStall.Prefix, await StallApplication.GetAccessTokenAsync(baseStall.Prefix));

            var suppliers = supplierResult.Suppliers;

            if (suppliers == null || suppliers.Count == 0)
            {
                //
                result.Message = "无法获取VEND Supplier信息";
                return(result);
            }

            //seperate by supplier
            var unStalledProduct = new List <Product>();
            var stalls           = new SortedDictionary <string, Stall>();

            foreach (var p in baseStall.Products)
            {
                //loop product
                if (string.IsNullOrEmpty(p.SupplierName))
                {
                    //no supplier product
                    unStalledProduct.Add(p);
                    continue;
                }

                Stall currStall;


                if (stalls.ContainsKey(p.SupplierName))
                {
                    //exist stall
                    currStall = stalls[p.SupplierName];
                }
                else
                {
                    #region new stall
                    var supplier = suppliers.FirstOrDefault(x => x.Name.Equals(p.SupplierName));

                    //new stall
                    currStall = new Stall()
                    {
                        UserId            = baseStall.UserId,
                        Prefix            = baseStall.Prefix,
                        StallName         = p.SupplierName,
                        RetailerId        = baseStall.RetailerId,
                        RegisterId        = baseStall.RegisterId,
                        RegisterName      = baseStall.RegisterName,
                        OutletId          = baseStall.OutletId,
                        PaymentTypeId     = baseStall.PaymentTypeId,
                        DeliveryProductId = baseStall.DeliveryProductId,
                        DiscountProductId = baseStall.DiscountProductId,
                        ContactName       = $"{supplier.Contact.FirstName} {supplier.Contact.LastName}".Trim(),
                        Mobile            = supplier.Contact.Mobile,
                        Phone             = supplier.Contact.Phone,
                        Address1          = supplier.Contact.PhysicalAddress1,
                        Address2          = supplier.Contact.PhysicalAddress2,
                        City          = supplier.Contact.PhysicalCity,
                        CountryId     = supplier.Contact.PhysicalCountryId,
                        Postcode      = supplier.Contact.PhysicalPostcode,
                        StateOrRegion = supplier.Contact.PhysicalState,
                        Suburb        = supplier.Contact.PhysicalSuburb,
                        TimeZone      = baseStall.TimeZone,
                        Status        = StallStatus.Offline
                    };

                    stalls.Add(p.SupplierName, currStall);
                    #endregion
                }

                currStall.Products.Add(p);
            }

            //save to db
            using (var trans = db.Database.BeginTransaction())
            {
                //save base stall
                try
                {
                    //keep unstalled product
                    baseStall.Products = unStalledProduct;
                    db.Set <Stall>().AddOrUpdate(baseStall);
                    db.SaveChanges();
                }
                catch (Exception ex)
                {
                    result.Message = $"failed to save stall {baseStall.StallName}:{ex.ToString()}";
                    trans.Rollback();
                    return(result);
                }

                foreach (var s in stalls.Values)
                {
                    try
                    {
                        db.Set <Stall>().AddOrUpdate(s);
                        db.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        result.Message = $"failed to save stall {s.StallName}:{ex.ToString()}";
                        trans.Rollback();
                        return(result);
                    }
                }

                trans.Commit();
            }

            result.Succeeded = true;
            return(result);
        }