diff --git a/RMuseum/DbContext/RMuseumDbContext.cs b/RMuseum/DbContext/RMuseumDbContext.cs index b7428397..83b8889d 100644 --- a/RMuseum/DbContext/RMuseumDbContext.cs +++ b/RMuseum/DbContext/RMuseumDbContext.cs @@ -13,6 +13,7 @@ using System; using RMuseum.Models.Ganjoor; using RMuseum.Models.MusicCatalogue; using System.IO; +using RMuseum.Models.Accounting; namespace RMuseum.DbContext { @@ -277,6 +278,16 @@ namespace RMuseum.DbContext /// public DbSet GanjoorHealthCheckErrors { get; set; } + /// + /// donations + /// + public DbSet GanjoorDonations { get; set; } + + /// + /// expenses + /// + public DbSet GanjoorExpenses { get; set; } + } } diff --git a/RMuseum/Models/Accounting/DonationExpenditure.cs b/RMuseum/Models/Accounting/DonationExpenditure.cs new file mode 100644 index 00000000..200a795b --- /dev/null +++ b/RMuseum/Models/Accounting/DonationExpenditure.cs @@ -0,0 +1,23 @@ +namespace RMuseum.Models.Accounting +{ + /// + /// donation expenditures + /// + public class DonationExpenditure + { + /// + /// GanjoorDonation Id + /// + public int GanjoorDonationId { get; set; } + + /// + /// GanjoorDonation + /// + public GanjoorDonation GanjoorDonation { get; set; } + + /// + /// amount + /// + public decimal Amount { get; set; } + } +} diff --git a/RMuseum/Models/Accounting/GanjoorDonation.cs b/RMuseum/Models/Accounting/GanjoorDonation.cs index b1bf56e9..1a0e8f25 100644 --- a/RMuseum/Models/Accounting/GanjoorDonation.cs +++ b/RMuseum/Models/Accounting/GanjoorDonation.cs @@ -48,7 +48,7 @@ namespace RMuseum.Models.Accounting public string DonorLink { get; set; } /// - /// remaining + /// remaining (it could be ignored later when our data has been normalized enough and be calculated using related data) /// public decimal Remaining { get; set; } diff --git a/RMuseum/Models/Accounting/GanjoorExpense.cs b/RMuseum/Models/Accounting/GanjoorExpense.cs new file mode 100644 index 00000000..514f778e --- /dev/null +++ b/RMuseum/Models/Accounting/GanjoorExpense.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace RMuseum.Models.Accounting +{ + /// + /// Ganjoor Expenses + /// + public class GanjoorExpense + { + /// + /// Id + /// + public int Id { get; set; } + + /// + /// date + /// + public DateTime ExpenseDate { get; set; } + + /// + /// amount + /// + public decimal Amount { get; set; } + + /// + /// unit + /// + public string Unit { get; set; } + + /// + /// description + /// + public string Description { get; set; } + + /// + /// donation expenitures + /// + public ICollection DonationExpenditures { get; set; } + } +} diff --git a/RMuseum/RMuseum.xml b/RMuseum/RMuseum.xml index 10171119..87f276bc 100644 --- a/RMuseum/RMuseum.xml +++ b/RMuseum/RMuseum.xml @@ -1484,6 +1484,36 @@ Ganjoor Health Check Errors + + + donations + + + + + expenses + + + + + donation expenditures + + + + + GanjoorDonation Id + + + + + GanjoorDonation + + + + + amount + + Ganjoor Donation (based on donation records saved in old html format of https://ganjoor.net/donate/) @@ -1496,7 +1526,7 @@ - date: (donation dates have been collected in different format, so instead of keeping their dates in a DateTime field I ought to use a string field) + date: (donation dates have been collected in different formats, so instead of keeping their dates in a DateTime field I ought to use a string field) @@ -1531,7 +1561,7 @@ - remaining + remaining (it could be ignored later when our data has been normalized enough and be calculated using related data) @@ -1544,6 +1574,41 @@ record is imported from old HTML text of donation page + + + Ganjoor Expenses + + + + + Id + + + + + date + + + + + amount + + + + + unit + + + + + description + + + + + donation expenitures + + Items or pictures status @@ -7721,6 +7786,58 @@ + + + donation service + + + + + donation page row + + + + + date + + + + + amount + + + + + donor + + + + + usage + + + + + remaining + + + + + parse html of https://ganjoor.net/donate/ and fill the records + + + + + + Database Context + + + + + constructor + + + Ganjoor User Service diff --git a/RMuseum/Services/Implementation/DonationService.cs b/RMuseum/Services/Implementation/DonationService.cs new file mode 100644 index 00000000..d8414f43 --- /dev/null +++ b/RMuseum/Services/Implementation/DonationService.cs @@ -0,0 +1,177 @@ +using Microsoft.EntityFrameworkCore; +using RMuseum.DbContext; +using RMuseum.Models.Accounting; +using RSecurityBackend.Models.Generic; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using DNTPersianUtils.Core; + +namespace RMuseum.Services.Implementation +{ + /// + /// donation service + /// + public class DonationService + { + + /// + /// donation page row + /// + private class DonationPageRow + { + /// + /// date + /// + public string Date { get; set; } + + /// + /// amount + /// + public string Amount { get; set; } + + /// + /// donor + /// + public string Donor { get; set; } + + /// + /// usage + /// + public string Usage { get; set; } + + /// + /// remaining + /// + public string Remaining { get; set; } + } + + /// + /// parse html of https://ganjoor.net/donate/ and fill the records + /// + /// + public async Task> InitializeRecords() + { + if (await _context.GanjoorDonations.AnyAsync()) + return new RServiceResult(true); + + string htmlText = await _context.GanjoorPages.Where(p => p.UrlSlug == "donate").Select(p => p.HtmlText).AsNoTracking().SingleAsync(); + + List rows = new List(); + + int nStartIndex = htmlText.IndexOf(""); + int rowNumber = 0; + while(nStartIndex != -1) + { + rowNumber++; + DonationPageRow row = new DonationPageRow(); + + nStartIndex += "".Length; + row.Date = htmlText.Substring(nStartIndex, htmlText.IndexOf("", nStartIndex)); + + nStartIndex = htmlText.IndexOf("", nStartIndex); + if (nStartIndex == -1) + return new RServiceResult(false, $"{rowNumber} : damount"); + nStartIndex += "".Length; + row.Amount = htmlText.Substring(nStartIndex, htmlText.IndexOf("", nStartIndex)); + + nStartIndex = htmlText.IndexOf("", nStartIndex); + if (nStartIndex == -1) + return new RServiceResult(false, $"{rowNumber} : ddonator"); + nStartIndex += "".Length; + row.Donor = htmlText.Substring(nStartIndex, htmlText.IndexOf("", nStartIndex)); + + nStartIndex = htmlText.IndexOf("", nStartIndex); + if (nStartIndex == -1) + return new RServiceResult(false, $"{rowNumber} : dusage"); + nStartIndex += "".Length; + row.Usage = htmlText.Substring(nStartIndex, htmlText.IndexOf("", nStartIndex)); + + nStartIndex = htmlText.IndexOf("", nStartIndex); + if (nStartIndex == -1) + return new RServiceResult(false, $"{rowNumber} : drem"); + nStartIndex += "".Length; + row.Remaining = htmlText.Substring(nStartIndex, htmlText.IndexOf("", nStartIndex)); + + + rows.Add(row); + + nStartIndex = htmlText.IndexOf("", nStartIndex); + } + + DateTime recordDate = DateTime.Now.AddDays(-2); + + for(int i = rows.Count - 1; i>=0; i--) + { + GanjoorDonation donation = new GanjoorDonation() + { + ImportedRecord = true, + DateString = rows[i].Date, + RecordDate = recordDate, + AmountString = rows[i].Amount, + DonorName = rows[i].Donor, //needs to be cleaned from href values + ExpenditureDesc = rows[i].Usage, + Remaining = 0 + }; + + if( + rows[i].Remaining != "۲۰ دلار" //one record + && + rows[i].Remaining.ToEnglishNumbers() != "0" + ) + { + donation.Remaining = decimal.Parse(rows[i].Remaining.Replace("٬", "").Replace("تومان", "").Trim()); + } + + if(donation.DonorName.IndexOf("href") != -1) + { + nStartIndex = donation.DonorName.IndexOf("href") + "href".Length + 1; + donation.DonorLink = donation.DonorName.Substring(nStartIndex, donation.DonorName.IndexOf("") - nStartIndex); + donation.DonorName = donation.DonorName.Substring(0, donation.DonorName.IndexOf("", "").Substring(donation.DonorName.IndexOf(">") + 1); + } + + if(donation.AmountString.Contains("تومان")) + { + donation.Amount = decimal.Parse(donation.AmountString.Replace("٬", "").Replace("تومان", "").Trim()); + donation.Unit = "تومان"; + } + + if (donation.AmountString.Contains("دلار")) + { + donation.Amount = decimal.Parse(donation.AmountString.Replace("٬", "").Replace("دلار", "").Trim()); + donation.Unit = "دلار"; + } + + if(donation.ExpenditureDesc == "هنوز هزینه نشده.") + { + donation.ExpenditureDesc = ""; + } + + _context.GanjoorDonations.Add(donation); + + await _context.SaveChangesAsync(); //in order to make Id columns filled in desired order + + + } + + return new RServiceResult(true); + } + + + /// + /// Database Context + /// + private readonly RMuseumDbContext _context; + + /// + /// constructor + /// + /// + public DonationService(RMuseumDbContext context) + { + _context = context; + + } + } +}