账单计费率

时间:2016-01-20 19:38:01

标签: azure azure-billing-api

Azure Rate Card API返回MeterRates字段(请参阅documentation)。 Azure UsageAggregate提供数量(请参阅documentation)。

根据天蓝色的支持page。这是提问的论坛。

那么,如何应用电表费率?

示例计费率:

{"0":20, "100":15, "200":10}

如果我的数量为175,则金额为100*20 + 75*15175*15

为什么要指定包含数量?

示例:包含quantitiy 10的rates:{"0":23}可以表示为费率:

{"0":0, "10":23}

3 个答案:

答案 0 :(得分:5)

  

示例电表费率:{“0”:20,“100”:15,“200”:10}

     

如果我的数量为175,则数量为100 * 20 + 75 * 15或175 * 15?

定价是分层定价。因此,当您获得费率时,它基本上告诉您:

  • 来自0 - 99个单位,单位费率为20
  • 来自100 - 199个单位,单位费率为15
  • 来自200个单位及以上,单位费率为10

根据这个逻辑,你的计算应该是:

  

99 * 20 + 75 * 15 = 3105

令我困惑的一件事是上限。以上计算基于我从Azure Billing团队收到的信息。令我感到困惑的是,如果消费是99.5个单位,会发生什么?对于第一个99单位,它很好,但我不确定如何计算其他0.5单位。

答案 1 :(得分:2)

Guarav处理问题的核心,这也是我将其标记为答案的原因。基于此,我设计了以下代码来实现逻辑。它分为两部分:

  1. 根据计费率创建清单列表
  2. 使用清单列表处理数量以确定金额
  3. 以下函数创建存储桶列表(每个存储桶对象都是具有Min,Max和Rate属性的简单POCO)。该列表附加到仪表对象,该对象具有价目表api中的其他属性。

            private Dictionary<int, RateBucket> ParseRateBuckets(string rates)
        {
            dynamic dRates = JsonConvert.DeserializeObject(rates);
            var rateContainer = (JContainer)dRates;
    
            var buckets = new Dictionary<int, RateBucket>();
            var bucketNumber = 0;
            foreach (var jToken in rateContainer.Children())
            {
                var jProperty = jToken as JProperty;
                if (jProperty != null)
                {
                    var bucket = new RateBucket
                    {
                        Min = Convert.ToDouble(jProperty.Name),
                        Rate = Convert.ToDouble(jProperty.Value.ToString())
                    };
    
                    if (bucketNumber > 0)
                        buckets[bucketNumber - 1].Max = bucket.Min;
    
                    buckets.Add(bucketNumber, bucket);
                }
    
                bucketNumber++;
            }
    
            return buckets;
        }
    

    第二个函数使用具有两个有用属性的仪表对象:桶列表和包含的数量。根据价目表文件(正如我所读),您不会开始计算可结算数量,直到您超过所包含的数量。我确定可以在这里完成一些重构,但是对桶的有序处理是关键点。

    我认为我已经通过认识到它是一个双重而不是整数来解决数量问题。因此,与任何单个桶相关联的数量是桶最大值和桶最小值之间的差值(除非我们仅填充了部分桶)。

            private double CalculateUsageCost(RateCardMeter meter, double quantity)
        {
            var amount = 0.0;
    
            quantity -= meter.IncludedQuantity;
    
            if (quantity > 0)
            {
                for (var i = 0; i < meter.RateBuckets.Count; i++)
                {
                    var bucket = meter.RateBuckets[i];
                    if (quantity > bucket.Min)
                    {
                        if (bucket.Max.HasValue && quantity > bucket.Max)
                            amount += (bucket.Max.Value - bucket.Min)*bucket.Rate;
                        else
                            amount += (quantity - bucket.Min)*bucket.Rate;
                    }
                }
            }
            return amount;
        }
    

    最后,文档不清楚层的时间范围。如果我根据数量得到折扣价,我会在什么时间范围内汇总数量?用法api允许我每天或每小时提取数据。我想每小时提取一次数据,以便我可以按时间关联我的费用。但什么时候实际计算账单是否合适?似乎每小时都是错的,每天都可以工作,但它可能只适用于整个月。

答案 2 :(得分:0)

最近我刚做了类似的任务。以下是我的例子(我认为你可以使用正则表达式删除那些字符而不是像我一样使用替换)。第一个函数解析rate信息字符串以生成键值对集合,第二个函数用于计算总价格。

private Dictionary<float, double> GetRatesDetail(string r)
{
    Dictionary<float, double> pairs = null;
    if(string.IsNullOrEmpty(r) || r.Length <=2)
    {
        pairs = new Dictionary<float, double>();
        pairs.Add(0, 0);
    }
    else
    {
        pairs = r.Replace("{", "").Replace("}", "").Split(',')
        .Select(value => value.Split(':'))
        .ToDictionary(pair => float.Parse(pair[0].Replace("\"", "")), pair => double.Parse(pair[1]));
    }

    return pairs;
}

public decimal Process(Dictionary<float, double> rates, decimal quantity)
{
    double ret = 0;

    foreach (int key in rates.Keys.OrderByDescending(k => k))
    {
        if (quantity >= key)
        {
            ret += ((double)quantity - key) * rates[key];
            quantity = key;
        }
    }

    return (decimal)ret;
}