|
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc;
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
using Kitty_Fall.Cms.Helpers;
|
|
using Kitty_Fall.Cms.Helpers;
|
|
|
using Kitty_Fall.Cms.Models;
|
|
using Kitty_Fall.Cms.Models;
|
|
|
|
|
+using System.Globalization;
|
|
|
|
|
|
|
|
namespace Kitty_Fall.Cms.Controllers;
|
|
namespace Kitty_Fall.Cms.Controllers;
|
|
|
|
|
|
|
@@ -20,16 +21,21 @@ public class SubscriptionChargeReportController : CmsAuthorizedController
|
|
|
[HttpGet("/SubscriptionChargeReport")]
|
|
[HttpGet("/SubscriptionChargeReport")]
|
|
|
[HttpGet("/SubscriptionChargeReport/Index")]
|
|
[HttpGet("/SubscriptionChargeReport/Index")]
|
|
|
[HttpGet("/Admin/SubscriptionChargeReport")]
|
|
[HttpGet("/Admin/SubscriptionChargeReport")]
|
|
|
- public async Task<IActionResult> Index(string? msisdn = null, int regPage = 1, int chargePage = 1)
|
|
|
|
|
|
|
+ public async Task<IActionResult> Index(string? msisdn = null, string? selectedDate = null, int regPage = 1, int chargePage = 1)
|
|
|
{
|
|
{
|
|
|
if (!CheckLogin()) return RedirectToLogin();
|
|
if (!CheckLogin()) return RedirectToLogin();
|
|
|
if (!HasMenuPermission(CmsSecurityHelper.SubscriptionChargeReportsMenuKey)) return RedirectNoPermission();
|
|
if (!HasMenuPermission(CmsSecurityHelper.SubscriptionChargeReportsMenuKey)) return RedirectNoPermission();
|
|
|
|
|
|
|
|
- var submittedSearch = Request.Query.ContainsKey("msisdn");
|
|
|
|
|
var searchMsisdn = NormalizeRawMsisdn(msisdn);
|
|
var searchMsisdn = NormalizeRawMsisdn(msisdn);
|
|
|
- var normalizedMsisdn = CommonLogic.ValidateMsisdn(CommonConstants.CountryCode, msisdn);
|
|
|
|
|
var hasSearch = !string.IsNullOrWhiteSpace(searchMsisdn);
|
|
var hasSearch = !string.IsNullOrWhiteSpace(searchMsisdn);
|
|
|
- var isInvalidMsisdn = submittedSearch && (!hasSearch || string.IsNullOrWhiteSpace(normalizedMsisdn));
|
|
|
|
|
|
|
+ var normalizedMsisdn = hasSearch
|
|
|
|
|
+ ? CommonLogic.ValidateMsisdn(CommonConstants.CountryCode, msisdn)
|
|
|
|
|
+ : null;
|
|
|
|
|
+ var isInvalidMsisdn = hasSearch && string.IsNullOrWhiteSpace(normalizedMsisdn);
|
|
|
|
|
+ var hasDateValue = !string.IsNullOrWhiteSpace(selectedDate);
|
|
|
|
|
+ var reportDate = DateTime.Today;
|
|
|
|
|
+ var isInvalidDate = hasDateValue && !DateTime.TryParseExact(
|
|
|
|
|
+ selectedDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out reportDate);
|
|
|
|
|
|
|
|
var model = new SubscriptionChargeReportViewModel
|
|
var model = new SubscriptionChargeReportViewModel
|
|
|
{
|
|
{
|
|
@@ -38,19 +44,25 @@ public class SubscriptionChargeReportController : CmsAuthorizedController
|
|
|
HasSearch = hasSearch,
|
|
HasSearch = hasSearch,
|
|
|
IsInvalidMsisdn = isInvalidMsisdn,
|
|
IsInvalidMsisdn = isInvalidMsisdn,
|
|
|
MsisdnErrorMessage = isInvalidMsisdn
|
|
MsisdnErrorMessage = isInvalidMsisdn
|
|
|
- ? (!hasSearch ? "Please enter a phone number." : "Invalid MSISDN. Please enter digits only, with or without country code.")
|
|
|
|
|
|
|
+ ? "Invalid MSISDN. Please enter digits only, with or without country code."
|
|
|
: null,
|
|
: null,
|
|
|
|
|
+ SelectedDate = isInvalidDate
|
|
|
|
|
+ ? (selectedDate ?? string.Empty).Trim()
|
|
|
|
|
+ : reportDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture),
|
|
|
|
|
+ IsInvalidDate = isInvalidDate,
|
|
|
|
|
+ DateErrorMessage = isInvalidDate ? "Invalid date. Please select one valid date." : null,
|
|
|
PageSize = PageSize,
|
|
PageSize = PageSize,
|
|
|
RegPage = Math.Max(1, regPage),
|
|
RegPage = Math.Max(1, regPage),
|
|
|
ChargePage = Math.Max(1, chargePage)
|
|
ChargePage = Math.Max(1, chargePage)
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- if (!hasSearch || isInvalidMsisdn)
|
|
|
|
|
|
|
+ if (isInvalidMsisdn || isInvalidDate)
|
|
|
{
|
|
{
|
|
|
return View("~/Views/Reports/SubscriptionCharge.cshtml", model);
|
|
return View("~/Views/Reports/SubscriptionCharge.cshtml", model);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- var regQuery = BuildRegInfoQuery(searchMsisdn, normalizedMsisdn);
|
|
|
|
|
|
|
+ var selectedDay = reportDate.Date;
|
|
|
|
|
+ var regQuery = BuildRegInfoQuery(searchMsisdn, normalizedMsisdn, selectedDay);
|
|
|
model.RegTotalRows = await regQuery.CountAsync();
|
|
model.RegTotalRows = await regQuery.CountAsync();
|
|
|
model.RegTotalPages = CalculateTotalPages(model.RegTotalRows);
|
|
model.RegTotalPages = CalculateTotalPages(model.RegTotalRows);
|
|
|
model.RegPage = Math.Min(model.RegPage, model.RegTotalPages);
|
|
model.RegPage = Math.Min(model.RegPage, model.RegTotalPages);
|
|
@@ -80,7 +92,7 @@ public class SubscriptionChargeReportController : CmsAuthorizedController
|
|
|
})
|
|
})
|
|
|
.ToListAsync();
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
- var chargeQuery = BuildChargeLogQuery(searchMsisdn, normalizedMsisdn);
|
|
|
|
|
|
|
+ var chargeQuery = BuildChargeLogQuery(searchMsisdn, normalizedMsisdn, selectedDay);
|
|
|
model.ChargeTotalRows = await chargeQuery.CountAsync();
|
|
model.ChargeTotalRows = await chargeQuery.CountAsync();
|
|
|
model.ChargeTotalPages = CalculateTotalPages(model.ChargeTotalRows);
|
|
model.ChargeTotalPages = CalculateTotalPages(model.ChargeTotalRows);
|
|
|
model.ChargePage = Math.Min(model.ChargePage, model.ChargeTotalPages);
|
|
model.ChargePage = Math.Min(model.ChargePage, model.ChargeTotalPages);
|
|
@@ -102,23 +114,69 @@ public class SubscriptionChargeReportController : CmsAuthorizedController
|
|
|
})
|
|
})
|
|
|
.ToListAsync();
|
|
.ToListAsync();
|
|
|
|
|
|
|
|
|
|
+ var packageLookup = await _db.Packgs
|
|
|
|
|
+ .AsNoTracking()
|
|
|
|
|
+ .Where(x => x.Fee.HasValue && x.ProductName != null)
|
|
|
|
|
+ .OrderBy(x => x.ProductId)
|
|
|
|
|
+ .Select(x => new { x.Fee, x.ProductName, x.NumberSpin })
|
|
|
|
|
+ .ToListAsync();
|
|
|
|
|
+
|
|
|
|
|
+ foreach (var chargeLog in model.ChargeLogs)
|
|
|
|
|
+ {
|
|
|
|
|
+ var productName = ExtractProductName(chargeLog.Description);
|
|
|
|
|
+ if (string.IsNullOrWhiteSpace(productName)) continue;
|
|
|
|
|
+
|
|
|
|
|
+ chargeLog.Turn = packageLookup.FirstOrDefault(x =>
|
|
|
|
|
+ x.Fee == chargeLog.Fee &&
|
|
|
|
|
+ string.Equals(x.ProductName?.Trim(), productName, StringComparison.OrdinalIgnoreCase))?.NumberSpin;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return View("~/Views/Reports/SubscriptionCharge.cshtml", model);
|
|
return View("~/Views/Reports/SubscriptionCharge.cshtml", model);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private IQueryable<RegInfo> BuildRegInfoQuery(string searchMsisdn, string? normalizedMsisdn)
|
|
|
|
|
|
|
+ private IQueryable<RegInfo> BuildRegInfoQuery(string searchMsisdn, string? normalizedMsisdn, DateTime selectedDay)
|
|
|
{
|
|
{
|
|
|
var query = _db.RegInfos.AsNoTracking();
|
|
var query = _db.RegInfos.AsNoTracking();
|
|
|
- return HasDistinctNormalizedMsisdn(searchMsisdn, normalizedMsisdn)
|
|
|
|
|
- ? query.Where(x => x.Msisdn == searchMsisdn || x.Msisdn == normalizedMsisdn)
|
|
|
|
|
- : query.Where(x => x.Msisdn == searchMsisdn);
|
|
|
|
|
|
|
+ if (!string.IsNullOrWhiteSpace(searchMsisdn))
|
|
|
|
|
+ {
|
|
|
|
|
+ query = HasDistinctNormalizedMsisdn(searchMsisdn, normalizedMsisdn)
|
|
|
|
|
+ ? query.Where(x => x.Msisdn == searchMsisdn || x.Msisdn == normalizedMsisdn)
|
|
|
|
|
+ : query.Where(x => x.Msisdn == searchMsisdn);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var end = selectedDay.AddDays(1);
|
|
|
|
|
+ query = query.Where(x => x.RegisterTime.HasValue && x.RegisterTime.Value >= selectedDay && x.RegisterTime.Value < end);
|
|
|
|
|
+
|
|
|
|
|
+ return query;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private IQueryable<ChargeLog> BuildChargeLogQuery(string searchMsisdn, string? normalizedMsisdn)
|
|
|
|
|
|
|
+ private IQueryable<ChargeLog> BuildChargeLogQuery(string searchMsisdn, string? normalizedMsisdn, DateTime selectedDay)
|
|
|
{
|
|
{
|
|
|
var query = _db.ChargeLogs.AsNoTracking();
|
|
var query = _db.ChargeLogs.AsNoTracking();
|
|
|
- return HasDistinctNormalizedMsisdn(searchMsisdn, normalizedMsisdn)
|
|
|
|
|
- ? query.Where(x => x.Msisdn == searchMsisdn || x.Msisdn == normalizedMsisdn)
|
|
|
|
|
- : query.Where(x => x.Msisdn == searchMsisdn);
|
|
|
|
|
|
|
+ if (!string.IsNullOrWhiteSpace(searchMsisdn))
|
|
|
|
|
+ {
|
|
|
|
|
+ query = HasDistinctNormalizedMsisdn(searchMsisdn, normalizedMsisdn)
|
|
|
|
|
+ ? query.Where(x => x.Msisdn == searchMsisdn || x.Msisdn == normalizedMsisdn)
|
|
|
|
|
+ : query.Where(x => x.Msisdn == searchMsisdn);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var end = selectedDay.AddDays(1);
|
|
|
|
|
+ query = query.Where(x =>
|
|
|
|
|
+ (x.ChargeTime.HasValue && x.ChargeTime.Value >= selectedDay && x.ChargeTime.Value < end) ||
|
|
|
|
|
+ (!x.ChargeTime.HasValue && x.InsertTime.HasValue && x.InsertTime.Value >= selectedDay && x.InsertTime.Value < end));
|
|
|
|
|
+
|
|
|
|
|
+ return query;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static string? ExtractProductName(string? description)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (string.IsNullOrWhiteSpace(description)) return null;
|
|
|
|
|
+
|
|
|
|
|
+ var value = description.Trim();
|
|
|
|
|
+ var separatorIndex = value.IndexOf(' ');
|
|
|
|
|
+ return separatorIndex >= 0 && separatorIndex < value.Length - 1
|
|
|
|
|
+ ? value[(separatorIndex + 1)..].Trim()
|
|
|
|
|
+ : null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static bool HasDistinctNormalizedMsisdn(string searchMsisdn, string? normalizedMsisdn)
|
|
private static bool HasDistinctNormalizedMsisdn(string searchMsisdn, string? normalizedMsisdn)
|