private Dictionary <string, long> ProfitAllPeriods(Scheme scheme, ProfitDetail profitDetail, Address profitVirtualAddress, Address beneficiary, bool isView = false, string targetSymbol = null) { var profitsMap = new Dictionary <string, long>(); var lastProfitPeriod = profitDetail.LastProfitPeriod; var symbols = targetSymbol == null?scheme.ReceivedTokenSymbols.ToList() : new List <string> { targetSymbol }; foreach (var symbol in symbols) { var totalAmount = 0L; for (var period = profitDetail.LastProfitPeriod; period <= (profitDetail.EndPeriod == long.MaxValue ? Math.Min(scheme.CurrentPeriod - 1, profitDetail.LastProfitPeriod.Add(ProfitContractConstants .MaximumProfitReceivingPeriodCountOfOneTime)) : Math.Min(scheme.CurrentPeriod - 1, profitDetail.EndPeriod)); period++) { var periodToPrint = period; var detailToPrint = profitDetail; var distributedPeriodProfitsVirtualAddress = GetDistributedPeriodProfitsVirtualAddress(profitVirtualAddress, period); var distributedProfitsInformation = State.DistributedProfitsMap[distributedPeriodProfitsVirtualAddress]; if (distributedProfitsInformation == null || distributedProfitsInformation.TotalShares == 0 || !distributedProfitsInformation.AmountsMap.Any() || !distributedProfitsInformation.AmountsMap.ContainsKey(symbol)) { continue; } var amount = SafeCalculateProfits(profitDetail.Shares, distributedProfitsInformation.AmountsMap[symbol], distributedProfitsInformation.TotalShares); if (!isView) { Context.LogDebug(() => $"{beneficiary} is profiting {amount} {symbol} tokens from {scheme.SchemeId.ToHex()} in period {periodToPrint}." + $"Sender's Shares: {detailToPrint.Shares}, total Shares: {distributedProfitsInformation.TotalShares}"); if (distributedProfitsInformation.IsReleased && amount > 0) { if (State.TokenContract.Value == null) { State.TokenContract.Value = Context.GetContractAddressByName(SmartContractConstants.TokenContractSystemName); } State.TokenContract.TransferFrom.Send(new TransferFromInput { From = distributedPeriodProfitsVirtualAddress, To = beneficiary, Symbol = symbol, Amount = amount }); } lastProfitPeriod = period + 1; } totalAmount = totalAmount.Add(amount); } profitsMap.Add(symbol, totalAmount); } profitDetail.LastProfitPeriod = lastProfitPeriod; return(profitsMap); }
public async Task <bool> UpdateProfit(DateTime fromDate, DateTime toDate, string filter, string branchIds, Guid userId) { try { ///Nếu như !=0 tức là trên 1 tháng! var months = (toDate.Year * 12 + toDate.Month) - (fromDate.Year * 12 + fromDate.Month); if (months < 0) { throw new Exception("Should be ToDate than FromDate"); } else { ///Tính thời gian về cuối tháng DateTime ToDate_LastMonth = toDate; DateTime ToDate_ThisMonth = toDate; //loop for (var i = 0; i <= months; i++) { //nếu như khác giá trị ban đầu thì fromDate tăng lên 1 tháng if (i != 0) { fromDate = fromDate.AddMonths(1); ToDate_ThisMonth = new DateTime(fromDate.Year, fromDate.Month, 1); toDate = ToDate_ThisMonth.AddMonths(1).AddSeconds(-1);//ve cuoi thang nay } else { //Khi trường hợp nó bằng 0 tức là đang ở khoảng fromDate, cần phải đưa nó về cuối tháng //vụ đưa về cuối tháng mỗi thèng tự xử rùi không cần quan tâm làm gì? toDate = fromDate; } toDate = toDate.AddMonths(1).AddSeconds(-1);//ve cuoi thang nay var results = this.GetProfitList(fromDate, toDate, filter, branchIds, 0, 0); if (results != null && results.Count() > 0) { var endDate = fromDate.AddMonths(1); var month = endDate.Month; var year = endDate.Year; //get Profit var inv = this.appContext.Profit.FirstOrDefault( p => p.CreatedDate.Month == month && p.CreatedDate.Year == year && p.IsDeleted == false); //Initially ID Guid ProfitId = Guid.NewGuid(); if (inv != null) { ProfitId = inv.ProfitId; } else { inv = new Profit { ProfitId = ProfitId, CreatedBy = userId, CreatedDate = endDate, IsDeleted = false, Note = endDate.ToString(), UpdatedBy = userId, UpdatedDate = DateTime.Now }; await this.appContext.AddAsync(inv); } var invds = this.appContext.ProfitDetail.Where(p => p.ProfitId == inv.ProfitId); foreach (var item in results) { var itemExist = invds.FirstOrDefault(p => p.BranchId == item.BranchId); if (itemExist != null) { itemExist.TotalPrice = item.TotalPriceEnd; itemExist.UpdatedBy = userId; itemExist.UpdatedDate = DateTime.Now; } else { itemExist = new ProfitDetail { ProfitDetailId = Guid.NewGuid(), ProfitId = ProfitId, TotalPrice = item.TotalPriceEnd, CreatedBy = userId, CreatedDate = DateTime.Now, BranchId = item.BranchId, IsDeleted = false, UpdatedBy = userId, UpdatedDate = DateTime.Now }; await this.appContext.AddAsync(itemExist); } } await this.appContext.SaveChangesAsync(); } } } return(true); } catch (Exception ex) { throw ex; } }
public override Empty AddBeneficiary(AddBeneficiaryInput input) { AssertValidInput(input); if (input.EndPeriod == 0) { // Which means this profit Beneficiary will never expired unless removed. input.EndPeriod = long.MaxValue; } var schemeId = input.SchemeId; var scheme = State.SchemeInfos[schemeId]; Assert(scheme != null, "Scheme not found."); // ReSharper disable once PossibleNullReferenceException Assert( Context.Sender == scheme.Manager || Context.Sender == Context.GetContractAddressByName(SmartContractConstants.TokenHolderContractSystemName), "Only manager can add beneficiary."); Context.LogDebug(() => $"{input.SchemeId}.\n End Period: {input.EndPeriod}, Current Period: {scheme.CurrentPeriod}"); Assert(input.EndPeriod >= scheme.CurrentPeriod, $"Invalid end period. End Period: {input.EndPeriod}, Current Period: {scheme.CurrentPeriod}"); scheme.TotalShares = scheme.TotalShares.Add(input.BeneficiaryShare.Shares); State.SchemeInfos[schemeId] = scheme; var profitDetail = new ProfitDetail { StartPeriod = scheme.CurrentPeriod.Add(scheme.DelayDistributePeriodCount), EndPeriod = input.EndPeriod, Shares = input.BeneficiaryShare.Shares, }; var currentProfitDetails = State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary]; if (currentProfitDetails == null) { currentProfitDetails = new ProfitDetails { Details = { profitDetail } }; } else { currentProfitDetails.Details.Add(profitDetail); } // Remove details too old. var oldProfitDetails = currentProfitDetails.Details.Where( d => d.EndPeriod != long.MaxValue && d.LastProfitPeriod >= d.EndPeriod && d.EndPeriod.Add(scheme.ProfitReceivingDuePeriodCount) < scheme.CurrentPeriod).ToList(); foreach (var detail in oldProfitDetails) { currentProfitDetails.Details.Remove(detail); } State.ProfitDetailsMap[schemeId][input.BeneficiaryShare.Beneficiary] = currentProfitDetails; Context.LogDebug(() => $"Added {input.BeneficiaryShare.Shares} weights to scheme {input.SchemeId.ToHex()}: {profitDetail}"); return(new Empty()); }
public override Empty AddWeight(AddWeightInput input) { Assert(input.ProfitId != null, "Invalid profit id."); Assert(input.Receiver != null, "Invalid receiver address."); Assert(input.Weight >= 0, "Invalid weight."); if (input.EndPeriod == 0) { // Which means this profit receiver will never expired. input.EndPeriod = long.MaxValue; } var profitId = input.ProfitId; var profitItem = State.ProfitItemsMap[profitId]; Assert(profitItem != null, "Profit item not found."); if (profitItem == null) { return(new Empty()); } Assert(input.EndPeriod >= profitItem.CurrentPeriod, "Invalid end period."); profitItem.TotalWeight += input.Weight; State.ProfitItemsMap[profitId] = profitItem; var profitDetail = new ProfitDetail { StartPeriod = profitItem.CurrentPeriod, EndPeriod = input.EndPeriod, Weight = input.Weight, }; var currentProfitDetails = State.ProfitDetailsMap[profitId][input.Receiver]; if (currentProfitDetails == null) { // TODO: Reduce Resource token of Profit Contract from DApp Developer because this behaviour will add a new key. currentProfitDetails = new ProfitDetails { Details = { profitDetail } }; } else { currentProfitDetails.Details.Add(profitDetail); } // Remove details too old. foreach (var detail in currentProfitDetails.Details.Where( d => d.EndPeriod != long.MaxValue && d.LastProfitPeriod >= d.EndPeriod && d.EndPeriod.Add(profitItem.ExpiredPeriodNumber) < profitItem.CurrentPeriod)) { currentProfitDetails.Details.Remove(detail); } State.ProfitDetailsMap[profitId][input.Receiver] = currentProfitDetails; return(new Empty()); }