123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717 |
- using Azure.Storage.Blobs.Models;
- using HTEXLib.COMM.Helpers;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Cors;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.Options;
- using System;
- using System.Collections.Generic;
- using System.IdentityModel.Tokens.Jwt;
- using System.Linq;
- using System.Net.Http;
- using System.Text.Json;
- using System.Threading.Tasks;
- using TEAMModelOS.Models;
- using TEAMModelOS.SDK;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.Extension;
- namespace TEAMModelOS.Controllers
- {
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status400BadRequest)]
- [Route("bill")]
- [ApiController]
- public class BillController : ControllerBase
- {
- private readonly DingDing _dingDing;
- private readonly IHttpClientFactory _httpClient;
- private readonly IConfiguration _configuration;
- private readonly AzureStorageFactory _azureStorage;
- private readonly AzureRedisFactory _azureRedis;
- private readonly IPSearcher _ipSearcher;
- private readonly Option _option;
- private readonly Region2LongitudeLatitudeTranslator _longitudeLatitudeTranslator;
- public BillController(AzureRedisFactory azureRedis, Region2LongitudeLatitudeTranslator longitudeLatitudeTranslator, IHttpClientFactory httpClient, IConfiguration configuration, AzureStorageFactory azureStorage, IPSearcher searcher, DingDing dingDing, IOptionsSnapshot<Option> option)
- {
- _httpClient = httpClient;
- _configuration = configuration;
- _azureStorage = azureStorage;
- _ipSearcher = searcher;
- _dingDing = dingDing;
- _option = option.Value;
- _azureRedis=azureRedis;
- _longitudeLatitudeTranslator = longitudeLatitudeTranslator;
- }
-
- [HttpPost("report")]
- [EnableCors("AllowSpecificOrigin")]
- [AllowAnonymous]
- [RequestSizeLimit(102_400_000_00)] //最大10000m左右
- public async Task<IActionResult> Report(JsonElement json)
- {
- try
- {
- List<KeyBillDetail> monthData = new List<KeyBillDetail>();
- List<DayBillDetail> dayData = new List<DayBillDetail>();
- List<DayBillDetail> resourceGroupDataGroup = new List<DayBillDetail>();
- List<DayBillDetail> cloudServiceDataGroup = new List<DayBillDetail>();
- List<DayBillDetail> meterCategoryDataGroup = new List<DayBillDetail>();
- List<DayBillDetail> consumedServiceDataGroup = new List<DayBillDetail>();
- string BillToken = _configuration.GetValue<string>("Azure:Bill:Token");
- List<string> times = json.GetProperty("times").ToObject<List<string>>();
- List<string> ResourceGroup = new List<string>();
- List<string> CloudService = new List<string>();
- List<string> Product = new List<string>();
- List<string> MeterCategory = new List<string>();
- List<string> MeterSubCategory = new List<string>();
- List<string> MeterName = new List<string>();
- List<string> ConsumedService = new List<string>();
- if (json.TryGetProperty("CloudService", out JsonElement _CloudService))
- {
- CloudService = _CloudService.ToObject<List<string>>();
- }
- if (json.TryGetProperty("ResourceGroup", out JsonElement _ResourceGroup))
- {
- ResourceGroup = _ResourceGroup.ToObject<List<string>>();
- }
- if (json.TryGetProperty("Product", out JsonElement _Product))
- {
- Product = _Product.ToObject<List<string>>();
- }
- if (json.TryGetProperty("MeterCategory", out JsonElement _MeterCategory))
- {
- MeterCategory = _MeterCategory.ToObject<List<string>>();
- }
- if (json.TryGetProperty("MeterSubCategory", out JsonElement _MeterSubCategory))
- {
- MeterSubCategory = _MeterSubCategory.ToObject<List<string>>();
- }
- if (json.TryGetProperty("MeterName", out JsonElement _MeterName))
- {
- MeterName = _MeterName.ToObject<List<string>>();
- }
- if (json.TryGetProperty("ConsumedService", out JsonElement _ConsumedService))
- {
- ConsumedService = _ConsumedService.ToObject<List<string>>();
- }
- var httpClient = _httpClient.CreateClient();
- httpClient.DefaultRequestHeaders.Remove("Authorization");
- httpClient.DefaultRequestHeaders.Remove("api-version");
- httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {BillToken}");
- httpClient.DefaultRequestHeaders.Add("api-version", "2014-09-02");
- var jwt = new JwtSecurityToken(BillToken);
- jwt.Payload.TryGetValue("EnrollmentNumber", out object EnrollmentNumber);
- int? exp = jwt.Payload.Exp;
- long now = DateTimeOffset.Now.ToUnixTimeSeconds();
- if (exp.HasValue && now >= exp.Value)
- {
- return Ok(new { code = 401 });
- }
- Dictionary<string, HashSet<string>> dict = new Dictionary<string, HashSet<string>>();
- Dictionary<string, HashSet<string>> dictCond = new Dictionary<string, HashSet<string>>();
- var BlobClientDict = _azureStorage.GetBlobContainerClient("teammodelos").GetBlobClient($"bill/dict.json");
- if (BlobClientDict.Exists())
- {
- BlobDownloadResult resultDict = await _azureStorage.GetBlobContainerClient("teammodelos").GetBlobClient($"bill/dict.json").DownloadContentAsync();
- var dictBlob = resultDict.Content.ToObjectFromJson<Dictionary<string, HashSet<string>>>();
- if (dictBlob != null && dictBlob.Count > 0)
- {
- dict = dictBlob;
- }
- }
- bool change = false;
- foreach (var time in times)
- {
- IEnumerable<BillDetail> billDetails = new List<BillDetail>();
- string force = json.GetProperty("force").GetString();
- var BlobClient = _azureStorage.GetBlobContainerClient("teammodelos").GetBlobClient($"bill/{time}.json");
- string nowMonth = DateTimeOffset.Now.ToString("yyyy-MM");
- //获取已经存在的月账单,且如果force!=1 并且不是当月的 ,如果force=1或者 是当月的账单,当月账单每天还在不断累加。 则是强制去刷新Azure远程账单
- if (BlobClient.Exists() && !force.Equals("1") && !nowMonth.Equals(time))
- {
- //不是当月的历史账单以现成的数据结构存储,直接获取。
- BlobDownloadResult result = await _azureStorage.GetBlobContainerClient("teammodelos").GetBlobClient($"bill/{time}.json").DownloadContentAsync();
- var bill = result.Content.ToObjectFromJson<List<BillDetail>>();
- billDetails = bill;
- }
- else
- {
- string url = $"https://ea.azure.cn/rest/{EnrollmentNumber}/usage-report/paginated?month={time}&fmt=JSON&pageindex=0";
- var response = await httpClient.GetAsync(url);
- if (response.IsSuccessStatusCode)
- {
- var content = await response.Content.ReadAsStringAsync();
- var bill = content.ToObject<List<BillDetail>>();
- //移除金额0的项目
- bill = bill.FindAll(x => x.ExtendedCost > 0);
- bill.ForEach(x =>
- {
- x.ResourceGroup = x.ResourceGroup.ToLower();
- x.MeterCategory = x.MeterCategory.ToLower();
- x.ConsumedService = x.ConsumedService.ToLower();
- if (string.IsNullOrWhiteSpace(x.ConsumedService))
- {
- x.ConsumedService = "default";
- }
- if (string.IsNullOrWhiteSpace(x.ResourceGroup))
- {
- x.ResourceGroup = "default";
- }
- if (string.IsNullOrWhiteSpace(x.MeterCategory))
- {
- x.MeterCategory = "default";
- }
- if (x.ResourceGroup.Equals("teammodelchengdu"))
- {
- x.CloudService = "ies5";
- }
- else if (x.ResourceGroup.Equals("coreservicerg"))
- {
- x.CloudService = "core";
- }
- else if (x.ResourceGroup.Equals("mc_iesresourcegroup_sokcluster_chinaeast2") || x.ResourceGroup.Equals("iesresourcegroup"))
- {
- x.CloudService = "sokrates";
- }
- else if (x.ResourceGroup.Equals("coreserviceresourcegroupcn"))
- {
- x.CloudService = "ies3";
- }
- else
- {
- x.CloudService = "other";
- }
- });
- var group = bill.GroupBy(x => $"{x.Date}{x.ResourceGroup}{x.CloudService}{x.Product}{x.MeterCategory}{x.MeterSubCategory}{x.MeterName}{x.ConsumedService}").Select(x => new { x.Key, list = x.ToList() });
- List<BillDetail> details = new List<BillDetail>();
- foreach (var item in group)
- {
- BillDetail billDetail = item.list.First();
- billDetail.ExtendedCost = item.list.Sum(x => x.ExtendedCost);
- details.Add(billDetail);
- }
- if (!nowMonth.Equals(time))
- {
- await _azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(details.ToJsonString(), "bill", $"{time}.json", true);
- }
- billDetails = details;
- //MeterCategory 服务
- {
- var newKey = billDetails.Select(x => x.MeterCategory).ToHashSet();
- if (dict.ContainsKey("MeterCategory"))
- {
- var moreKey = newKey.Except(dict["MeterCategory"]);
- foreach (var key in moreKey)
- {
- change = true;
- dict["MeterCategory"].Add(key);
- }
- }
- else
- {
- change = true;
- dict.Add("MeterCategory", newKey);
- }
- }
- //MeterSubCategory 服务类型
- {
- var newKey = billDetails.Select(x => x.MeterSubCategory).ToHashSet();
- if (dict.ContainsKey("MeterSubCategory"))
- {
- var moreKey = newKey.Except(dict["MeterSubCategory"]);
- foreach (var key in moreKey)
- {
- change = true;
- dict["MeterSubCategory"].Add(key);
- }
- }
- else
- {
- change = true;
- dict.Add("MeterSubCategory", newKey);
- }
- }
- //ConsumedService 服务信息
- {
- var newKey = billDetails.Select(x => x.ConsumedService).ToHashSet();
- if (dict.ContainsKey("ConsumedService"))
- {
- var moreKey = newKey.Except(dict["ConsumedService"]);
- foreach (var key in moreKey)
- {
- change = true;
- dict["ConsumedService"].Add(key);
- }
- }
- else
- {
- change = true;
- dict.Add("ConsumedService", newKey);
- }
- }
- //CloudService 资源组
- {
- var newKey = billDetails.Select(x => x.CloudService.ToLower()).ToHashSet();
- if (dict.ContainsKey("CloudService"))
- {
- var moreKey = newKey.Except(dict["CloudService"]);
- foreach (var key in moreKey)
- {
- change = true;
- dict["CloudService"].Add(key);
- }
- }
- else
- {
- change = true;
- dict.Add("CloudService", newKey);
- }
- }
- //ResourceGroup 资源组
- {
- var newKey = billDetails.Select(x => x.ResourceGroup.ToLower()).ToHashSet();
- if (dict.ContainsKey("ResourceGroup"))
- {
- var moreKey = newKey.Except(dict["ResourceGroup"]);
- foreach (var key in moreKey)
- {
- change = true;
- dict["ResourceGroup"].Add(key);
- }
- }
- else
- {
- change = true;
- dict.Add("ResourceGroup", newKey);
- }
- }
- //MeterName 服务资源
- {
- var newKey = billDetails.Select(x => x.MeterName).ToHashSet();
- if (dict.ContainsKey("MeterName"))
- {
- var moreKey = newKey.Except(dict["MeterName"]);
- foreach (var key in moreKey)
- {
- change = true;
- dict["MeterName"].Add(key);
- }
- }
- else
- {
- change = true;
- dict.Add("MeterName", newKey);
- }
- }
- //Product 产品
- {
- var newKey = billDetails.Select(x => x.Product).ToHashSet();
- if (dict.ContainsKey("Product"))
- {
- var moreKey = newKey.Except(dict["Product"]);
- foreach (var key in moreKey)
- {
- change = true;
- dict["Product"].Add(key);
- }
- }
- else
- {
- change = true;
- dict.Add("Product", newKey);
- }
- }
- }
- }
- if (CloudService.IsNotEmpty())
- {
- billDetails = billDetails.Where(x => CloudService.Contains(x.CloudService));
- }
- if (ResourceGroup.IsNotEmpty())
- {
- billDetails = billDetails.Where(x => ResourceGroup.Contains(x.ResourceGroup));
- }
- if (Product.IsNotEmpty())
- {
- billDetails = billDetails.Where(x => Product.Contains(x.Product));
- }
- if (MeterCategory.IsNotEmpty())
- {
- billDetails = billDetails.Where(x => MeterCategory.Contains(x.MeterCategory));
- }
- if (MeterSubCategory.IsNotEmpty())
- {
- billDetails = billDetails.Where(x => MeterSubCategory.Contains(x.MeterSubCategory));
- }
- if (MeterName.IsNotEmpty())
- {
- billDetails = billDetails.Where(x => MeterName.Contains(x.MeterName));
- }
- if (ConsumedService.IsNotEmpty())
- {
- billDetails = billDetails.Where(x => ConsumedService.Contains(x.ConsumedService));
- }
- {
- //MeterCategory 服务
- {
- var newKey = billDetails.Select(x => x.MeterCategory).ToHashSet();
- if (dictCond.ContainsKey("MeterCategory"))
- {
- var moreKey = newKey.Except(dictCond["MeterCategory"]);
- foreach (var key in moreKey)
- {
- change = true;
- dictCond["MeterCategory"].Add(key);
- }
- }
- else
- {
- change = true;
- dictCond.Add("MeterCategory", newKey);
- }
- }
- //MeterSubCategory 服务类型
- {
- var newKey = billDetails.Select(x => x.MeterSubCategory).ToHashSet();
- if (dictCond.ContainsKey("MeterSubCategory"))
- {
- var moreKey = newKey.Except(dictCond["MeterSubCategory"]);
- foreach (var key in moreKey)
- {
- change = true;
- dictCond["MeterSubCategory"].Add(key);
- }
- }
- else
- {
- change = true;
- dictCond.Add("MeterSubCategory", newKey);
- }
- }
- //ConsumedService 服务信息
- {
- var newKey = billDetails.Select(x => x.ConsumedService).ToHashSet();
- if (dictCond.ContainsKey("ConsumedService"))
- {
- var moreKey = newKey.Except(dictCond["ConsumedService"]);
- foreach (var key in moreKey)
- {
- change = true;
- dictCond["ConsumedService"].Add(key);
- }
- }
- else
- {
- change = true;
- dictCond.Add("ConsumedService", newKey);
- }
- }
- //CloudService 资源组
- {
- var newKey = billDetails.Select(x => x.CloudService.ToLower()).ToHashSet();
- if (dictCond.ContainsKey("CloudService"))
- {
- var moreKey = newKey.Except(dictCond["CloudService"]);
- foreach (var key in moreKey)
- {
- change = true;
- dictCond["CloudService"].Add(key);
- }
- }
- else
- {
- change = true;
- dictCond.Add("CloudService", newKey);
- }
- }
- //ResourceGroup 资源组
- {
- var newKey = billDetails.Select(x => x.ResourceGroup.ToLower()).ToHashSet();
- if (dictCond.ContainsKey("ResourceGroup"))
- {
- var moreKey = newKey.Except(dictCond["ResourceGroup"]);
- foreach (var key in moreKey)
- {
- change = true;
- dictCond["ResourceGroup"].Add(key);
- }
- }
- else
- {
- change = true;
- dictCond.Add("ResourceGroup", newKey);
- }
- }
- //MeterName 服务资源
- {
- var newKey = billDetails.Select(x => x.MeterName).ToHashSet();
- if (dictCond.ContainsKey("MeterName"))
- {
- var moreKey = newKey.Except(dictCond["MeterName"]);
- foreach (var key in moreKey)
- {
- change = true;
- dictCond["MeterName"].Add(key);
- }
- }
- else
- {
- change = true;
- dictCond.Add("MeterName", newKey);
- }
- }
- //Product 产品
- {
- var newKey = billDetails.Select(x => x.Product).ToHashSet();
- if (dictCond.ContainsKey("Product"))
- {
- var moreKey = newKey.Except(dictCond["Product"]);
- foreach (var key in moreKey)
- {
- change = true;
- dictCond["Product"].Add(key);
- }
- }
- else
- {
- change = true;
- dictCond.Add("Product", newKey);
- }
- }
- }
- monthData.Add(new KeyBillDetail
- {
- key = time,
- cost = billDetails.Sum(x => x.ExtendedCost)
- });
- var ResourceGroupData = billDetails.GroupBy(x => x.ResourceGroup);
- DayBillDetail ResourceGroupDataBillDetail = new DayBillDetail() { month = time };
- foreach (var group in ResourceGroupData)
- {
- ResourceGroupDataBillDetail.bills.Add(new KeyBillDetail() { key = group.Key, cost = group.Select(x => x.ExtendedCost).Sum() });
- }
- ResourceGroupDataBillDetail.bills = ResourceGroupDataBillDetail.bills.OrderByDescending(x => x.cost).ToList();
- resourceGroupDataGroup.Add(ResourceGroupDataBillDetail);
- var CloudServiceData = billDetails.GroupBy(x => x.CloudService);
- DayBillDetail CloudServiceDataBillDetail = new DayBillDetail() { month = time };
- foreach (var group in CloudServiceData)
- {
- CloudServiceDataBillDetail.bills.Add(new KeyBillDetail() { key = group.Key, cost = group.Select(x => x.ExtendedCost).Sum() });
- }
- CloudServiceDataBillDetail.bills = CloudServiceDataBillDetail.bills.OrderByDescending(x => x.cost).ToList();
- cloudServiceDataGroup.Add(CloudServiceDataBillDetail);
- var MeterCategoryData = billDetails.GroupBy(x => x.MeterCategory);
- DayBillDetail MeterCategoryDataBillDetail = new DayBillDetail() { month = time };
- foreach (var group in MeterCategoryData)
- {
- MeterCategoryDataBillDetail.bills.Add(new KeyBillDetail() { key = group.Key, cost = group.Select(x => x.ExtendedCost).Sum() });
- }
- MeterCategoryDataBillDetail.bills = MeterCategoryDataBillDetail.bills.OrderByDescending(x => x.cost).ToList();
- meterCategoryDataGroup.Add(MeterCategoryDataBillDetail);
- DayBillDetail ConsumedServiceDataBillDetail = new DayBillDetail() { month = time };
- var ConsumedServiceData = billDetails.GroupBy(x => x.ConsumedService);
- foreach (var group in ConsumedServiceData)
- {
- ConsumedServiceDataBillDetail.bills.Add(new KeyBillDetail() { key = group.Key, cost = group.Select(x => x.ExtendedCost).Sum() });
- }
- ConsumedServiceDataBillDetail.bills = ConsumedServiceDataBillDetail.bills.OrderByDescending(x => x.cost).ToList();
- consumedServiceDataGroup.Add(ConsumedServiceDataBillDetail);
- DayBillDetail dayBillDetail = new DayBillDetail() { month = time };
- for (int i = 1; i <= 31; i++)
- {
- var day = billDetails.Where(x => x.Day == i);
- if (day != null && day.Count() > 0)
- {
- dayBillDetail.bills.Add(new KeyBillDetail
- {
- key = $"{i}",
- cost = day.Sum(x => x.ExtendedCost)
- });
- }
- else
- {
- dayBillDetail.bills.Add(new KeyBillDetail { key = $"{i}", cost = 0 });
- }
- }
- dayData.Add(dayBillDetail);
- }
- if (change)
- {
- await _azureStorage.GetBlobContainerClient("teammodelos").UploadFileByContainer(dict.ToJsonString(), "bill", $"dict.json", true);
- }
- return Ok(new { monthData, dayData, dict, dictCond, code = 200, consumedServiceDataGroup, meterCategoryDataGroup, cloudServiceDataGroup, resourceGroupDataGroup });
- }
- catch (Exception ex)
- {
- return Ok(new { code = 500, msg = $"{ex.Message}{ex.StackTrace}" });
- }
- }
- public class KeyBillDetail
- {
- public string key { get; set; }
- public double cost { get; set; }
- }
- public class DayBillDetail
- {
- public string month { get; set; }
- /// <summary>
- /// 每天的数据
- /// </summary>
- public List<KeyBillDetail> bills { get; set; } = new List<KeyBillDetail>();
- }
- public class BillDetail
- {
- /// <summary>
- ///
- /// </summary>
- // public string AccountOwnerId { get; set; }
- /// <summary>
- /// 云米
- /// </summary>
- //public string AccountName { get; set; }
- /// <summary>
- ///
- /// </summary>
- //public string ServiceAdministratorId { get; set; }
- /// <summary>
- ///
- /// </summary>
- //public long SubscriptionId { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string SubscriptionGuid { get; set; }
- /// <summary>
- /// 标准预付费服务(Converted to EA)
- /// </summary>
- //public string SubscriptionName { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string Date { get; set; }
- /// <summary>
- ///
- /// </summary>
- public int Month { get; set; }
- /// <summary>
- ///
- /// </summary>
- public int Day { get; set; }
- /// <summary>
- ///
- /// </summary>
- public int Year { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string Product { get; set; }
- /// <summary>
- ///
- /// </summary>
- //public string MeterId { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string MeterCategory { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string MeterSubCategory { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string MeterRegion { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string MeterName { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public double ConsumedQuantity { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public double ResourceRate { get; set; }
- /// <summary>
- ///
- /// </summary>
- public double ExtendedCost { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string ResourceLocation { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string ConsumedService { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string InstanceId { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string ServiceInfo1 { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string ServiceInfo2 { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string AdditionalInfo { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string Tags { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string StoreServiceIdentifier { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string DepartmentName { get; set; }
- /// <summary>
- ///
- /// </summary>
- // public string CostCenter { get; set; }
- /// <summary>
- ///
- /// </summary>
- //public string UnitOfMeasure { get; set; }
- /// <summary>
- ///
- /// </summary>
- public string ResourceGroup { get; set; }
- public string CloudService { get; set; }
- public string CloudServiceName { get; set; }
- }
- }
- }
|