9. ABPZero series of tutorials on multi-vendor tool assembly reminder class library encapsulation

Posted by Mobile on Sat, 18 May 2019 21:10:05 +0200

This article began to formally do the function, before I developed the reminder of puzzle puzzle, the function of reminding sellers that puzzle puzzle is too many and the number of puzzle puzzle is not enough.

This idea comes mainly from the complaints of friends. I think it should be the voice of most sellers.

After analysis, I got several api s. Don't ask me how I got them. This is not the content of this series.

Interface 1: http://apiv4.yangkeduo.com/mall/{0}/info?pdduid=0

Interface 2: http://apiv4.yangkeduo.com/v2/mall/{0}/goods? Page=1&size=500&sort_type=PRIORITY&pdduid=0 (pass in store number, you can get store information, and limit access to up to 500 items)

Interface 3: http://apiv2.yangkeduo.com/v2/goods/{0}/local_group

With these api s, the jigsaw reminder function is out of the question. Next, we will explain the implementation process.

 

Establishment of new projects

Build a PddTool project under the solution, aiming at putting together many related business logic in a special class library.

 

Right-click on the solution to select the "NuGet package for managing the solution", search for and install the following NuGet package, pay attention to the version number.

 

 

To create a directory, first create several directories, as shown in the following figure:

 

Create a new MallEntity class in the Response directory with the following code:

public class MallEntity
    {
        /// <summary>
        /// 
        /// </summary>
        public int mall_id { get; set; }
        /// <summary>
        /// Muzi edge
        /// </summary>
        public string mall_name { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string logo { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int goods_num { get; set; }
        /// <summary>
        /// The shop mainly manages fashion fashion women's clothes, quality women's clothes, quality assurance!
        /// </summary>
        public string mall_desc { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string company_phone { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string offline_note { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int chat_enable { get; set; }
        /// <summary>
        /// Tianhe District, Guangzhou, Guangdong
        /// </summary>
        public string refund_address { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int score_avg { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int staple_id { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int mall_sales { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int region_emergent { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int is_open { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int status { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int wms_id { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public List<string> mall_coupons { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int server_time { get; set; }
    }

 

 

This is the class generated by returning json data after requesting the api.

http://www.bejson.com/convert/json2csharp/(through this tool, you can transfer JSON to C entity class)

New ProductEntity class under the same directory, code as follows:

/// <summary>
    /// Assemble
    /// </summary>
    public class Group
    {
        /// <summary>
        /// Group number
        /// </summary>
        public int customer_num { get; set; }
        /// <summary>
        /// Group price÷100
        /// </summary>
        public int price { get; set; }
    }

    public class Goods_listItem
    {
        /// <summary>
        /// Single purchase price÷100
        /// </summary>
        public int normal_price { get; set; }
        /// <summary>
        /// Quantity already assembled
        /// </summary>
        public int cnt { get; set; }
        /// <summary>
        /// Small graph connection
        /// </summary>
        public string thumb_url { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int event_type { get; set; }
        /// <summary>
        /// Market value÷100
        /// </summary>
        public int market_price { get; set; }
        /// <summary>
        /// [Wooden jacket long and medium-length Korean version 2017 new relaxed and self-cultivating students put on large and thick jackets bf Knee-length woolen overcoat
        /// </summary>
        public string goods_name { get; set; }
        /// <summary>
        /// commodity id
        /// </summary>
        public int goods_id { get; set; }
        /// <summary>
        /// [Wooden jacket long and medium-length Korean version 2017 new relaxed and self-cultivating students put on large and thick jackets bf Knee-length woolen overcoat
        /// </summary>
        public string short_name { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public Group group { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string country { get; set; }
        /// <summary>
        /// Commodity master plan
        /// </summary>
        public string image_url { get; set; }
        /// <summary>
        /// HD map
        /// </summary>
        public string hd_thumb_url { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int is_app { get; set; }
    }

    public class ProductEntity
    {
        /// <summary>
        /// 
        /// </summary>
        public List<string> recommend_subject { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int server_time { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public List<Goods_listItem> goods_list { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public List<string> subject_list { get; set; }
    }

 

 

Create the KaiTuanEntity class under the same directory. The code is as follows:

public class Local_groupItem
    {
        /// <summary>
        /// Group order id
        /// </summary>
        public string group_order_id { get; set; }
        /// <summary>
        /// commodity id
        /// </summary>
        public string goods_id { get; set; }
        /// <summary>
        /// City name
        /// </summary>
        public string city_name { get; set; }
        /// <summary>
        /// Nickname?
        /// </summary>
        public string nickname { get; set; }
        /// <summary>
        /// Head portrait
        /// </summary>
        public string avatar { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string expire_time { get; set; }
        /// <summary>
        /// user id
        /// </summary>
        public string uid { get; set; }
    }

    public class KaiTuanEntity
    {
        /// <summary>
        /// Collage List in progress
        /// </summary>
        public List<Local_groupItem> local_group { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int server_time { get; set; }
        /// <summary>
        /// Number of group members in progress
        /// </summary>
        public int total { get; set; }
    }

 

 

Then in the Entities directory, create the KaiTuan class, code as follows:

public class KaiTuan
    {
        /// <summary>
        /// commodity id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// Nickname?
        /// </summary>
        public string NickName { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string SKU { get; set; }

        /// <summary>
        /// Order number
        /// </summary>
        public string OrderNum { get; set; }

        /// <summary>
        /// Remaining time
        /// </summary>
        public double TimeLeft { get; set; }

        /// <summary>
        /// Group number
        /// </summary>
        public string KaiTuanOrderNum { get; set; }
    }

 

 

Continue to create the KaiTuanProduct class under the Entities directory with the following code:

/// <summary>
    /// Group merchandise
    /// </summary>
   public  class KaiTuanProduct
    {
        /// <summary>
        /// commodity id
        /// </summary>
        public int GoodId { get; set; }
        /// <summary>
        /// Trade name
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Commodity pictures
        /// </summary>
        public string Img { get; set; }
        /// <summary>
        /// Number of persons opening
        /// </summary>
        public int KaiTuanCount { get; set; }
    }

 

 

Create the DateTimeHelper class under the class library. The code is as follows:

public class DateTimeHelper
    {
        /// <summary>
        /// afferent unix Timestamp, calculating the number of hours between the current time
        /// </summary>
        /// <param name="unixTimeStamp"></param>
        /// <returns></returns>
        public static double GetHours(long unixTimeStamp)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // Local time zone
            DateTime dt = startTime.AddSeconds(unixTimeStamp);
            var a = dt - DateTime.Now;
            
            return Math.Round(a.TotalHours, 1);
        }
    }

 

 

The MallTool class is created under the class library and several methods are implemented. The code is as follows:

public class MallTool
    {
        /// <summary>
        /// By store id Access to store information
        /// </summary>
        /// <param name="mallId"></param>
        public static MallEntity GetInfo(string mallId)
        {
            string url = string.Format("http://apiv4.yangkeduo.com/mall/{0}/info?pdduid=0", mallId);
            var client = new RestClient(url);
            var request = new RestRequest(Method.GET);
            request.AddHeader("cache-control", "no-cache");
            request.AddHeader("referer", url);
            IRestResponse response = client.Execute(request);
            if (string.IsNullOrWhiteSpace(response.Content) || response.Content.Contains("mall not exists"))
            {
                throw new Exception("The shop number is wrong!");
            }
            var mall = JsonConvert.DeserializeObject<MallEntity>(response.Content);
            return mall;
        }

        /// <summary>
        /// Up to 500 items
        /// </summary>
        /// <param name="mallId"></param>
        /// <returns></returns>
        public static ProductEntity GetGoods(string mallId)
        {
            string url =
                string.Format(
                    "http://apiv4.yangkeduo.com/v2/mall/{0}/goods?page=1&size=500&sort_type=PRIORITY&pdduid=0", mallId);
            var client = new RestClient(url);
            var request = new RestRequest(Method.GET);
            request.AddHeader("cache-control", "no-cache");
            request.AddHeader("referer", url);
            IRestResponse response = client.Execute(request);
            var product = JsonConvert.DeserializeObject<ProductEntity>(response.Content);
            return product;
        }

        /// <summary>
        /// According to commodity id ,Obtain information about the opening of the group
        /// </summary>
        /// <param name="goodId"></param>
        /// <returns></returns>
        public static KaiTuanEntity GetKaiTuanInfo(int goodId)
        {
            string url = string.Format("http://apiv2.yangkeduo.com/v2/goods/{0}/local_group", goodId);
            var client = new RestClient(url);
            var request = new RestRequest(Method.GET);
            request.AddHeader("cache-control", "no-cache");
            request.AddHeader("referer", url);
            IRestResponse response = client.Execute(request);
            var content = response.Content.Replace("\\\"", "\"");
            content = content.Replace("\\\\", "\\").Replace("\"{", "{").Replace("}\"", "}");
            var kaiTuan = JsonConvert.DeserializeObject<KaiTuanEntity>(content);
            return kaiTuan;
        }

        /// <summary>
        /// According to commodity id,Get all information about the opening of this product
        /// </summary>
        /// <param name="goodId"></param>
        /// <returns></returns>
        public static List<KaiTuan> GetAllKaiTuanByGoodId(int mallId, int goodId)
        {
            int total = 0;// Total Opening Quantity
            var kaituan = GetKaiTuanInfo(goodId);
            total = kaituan.total;
            List<KaiTuan> groups = new List<KaiTuan>();
            int maxNoKaituan = 20;//Get together
            int noKaituan = 0;//Get the jigsaw. There is no new jigsaw rule in the returned data.+1
            //Get the opening information and store it in the collection
            AddRange(groups, kaituan, mallId, goodId, ref noKaituan);

            //Paging cycle when the number of groups is more than 5
            if (kaituan.total > 5)
            {
                while (true)
                {
                    //Retry maxNoKaituan Second, exit without new data
                    if (noKaituan >= maxNoKaituan)
                    {
                        break;
                    }
                    kaituan = GetKaiTuanInfo(goodId);
                    //Number of Openings Obtained>=Get back the number of openings and quit
                    if (groups.Count >= kaituan.total)
                    {
                        break;
                    }
                    AddRange(groups, kaituan, mallId, goodId, ref noKaituan);
                }
            }
            return groups;
        }

        /// <summary>
        /// According to the shop id,Number of group members who have access to all commodities
        /// </summary>
        /// <param name="mallId"></param>
        /// <returns></returns>
        public static List<KaiTuanProduct> GetKaiTuanList(string mallId)
        {
            var goods = GetGoods(mallId);
            if (goods.goods_list.Count == 0)
            {
                throw new UserFriendlyException("This shop has a merchandise of 0.");
            }
            List<KaiTuanProduct> kaiTuanProducts = new List<KaiTuanProduct>();
            foreach (var goodsListItem in goods.goods_list)
            {
                var kaituanProduct = GetKaiTuanCountByGoodId(goodsListItem.goods_id);
                if (kaituanProduct == null)
                {
                    continue;
                }
                kaituanProduct.Name = goodsListItem.goods_name;
                kaituanProduct.GoodId = goodsListItem.goods_id;
                kaituanProduct.Img = goodsListItem.thumb_url;
                kaiTuanProducts.Add(kaituanProduct);
            }
            return kaiTuanProducts;
        }

        /// <summary>
        ///According to commodity id, Obtain the number of the group members
        /// </summary>
        /// <param name="goodId"></param>
        public static KaiTuanProduct GetKaiTuanCountByGoodId(int goodId)
        {
            var kaituanInfo = GetKaiTuanInfo(goodId);
            if (kaituanInfo.total == 0)
            {
                return null;
            }
            return new KaiTuanProduct()
            {
                KaiTuanCount = kaituanInfo.total
            };
        }

        public static void AddRange(List<KaiTuan> groups, KaiTuanEntity kaiTuan, int mallId, int goodId, ref int noKaituan)
        {
            bool isExist = true;
            int count = 0;
            foreach (var localGroupItem in kaiTuan.local_group)
            {
                //Filter existing puzzles
                if (groups.Any(a => a.KaiTuanOrderNum == localGroupItem.group_order_id))
                {
                    count++;
                    isExist = false;
                    continue;
                }
                //Collage with filter time less than 0
                var t = DateTimeHelper.GetHours(Convert.ToInt64(localGroupItem.expire_time));
                if (t <= 0)
                {
                    count++;
                    isExist = false;
                    continue;
                }

                var item = new KaiTuan()
                {
                    Id = Convert.ToInt32(localGroupItem.goods_id),
                    KaiTuanOrderNum = localGroupItem.group_order_id,
                    NickName = localGroupItem.nickname,
                    TimeLeft = DateTimeHelper.GetHours(Convert.ToInt64(localGroupItem.expire_time)),
                };
                groups.Add(item);
                isExist = true;
            }
            if (isExist == false && count == kaiTuan.local_group.Count)
            {
                noKaituan++;
            }
        }
    }

 

 

You can see that UserFriendlyException reports exceptions, which are ABP exception classes. Then the solution opens the NuGet package of the management solution and searches for "abp" installation.

Finally, the structure of the project is as follows. The reminder function is encapsulated.

 

 

Create unit tests

Create a new unit test project under the Solution Tests directory, as shown in the following figure:

 

Create a new MallTool_Test class to test several methods just encapsulated. The code is as follows:

[TestClass]
    public class MallTool_Test
    {
        public string mallId { get; set; } = "1277675";
        [TestMethod]
        public void TestGetInfo()
        {
            MallEntity result=MallTool.GetInfo(mallId);
            Console.WriteLine(result.mall_name);
        }
    }

 

 

The following figure shows the output of debugging:

 

The above code is passed into the store number to obtain the store information.

Where does the store number come from?

http://mobile.yangkeduo.com/search_result.html?search_key=%E6%89%93%E5%BA%95%E8%A1%AB%E5%A5%B3&search_src=history&search_met=history_sort&search_met_track=history&refer_page_name=search&refer_page_id=&page_id=&sp=0&item_index=1&is_back=1

Through the above links, you can inquire about the information of more than one item. Then you can click on a random item and click "Shop in", as shown in the following figure:

 

When you come in, you can see the number of the store in the address bar, as shown in the following figure:

 

Several other methods are similar, so they are not explained one by one.

 

 Return to the General Directory

Topics: ASP.NET JSON Unix less Mobile