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);
        }