Merge branch 'refs/heads/Feature/roll-call/apk-versioning' into Feature/roll-call/camera-api

This commit is contained in:
2025-11-16 22:00:19 +03:30
24 changed files with 23066 additions and 45 deletions

View File

@@ -0,0 +1,61 @@
using CompanyManagment.App.Contracts.AndroidApkVersion;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ServiceHost.BaseControllers;
namespace ServiceHost.Areas.Admin.Controllers;
[AllowAnonymous]
[ApiController]
[Route("api/android-apk")]
public class AndroidApkController:AdminBaseController
{
private readonly IAndroidApkVersionApplication _apkApp;
public AndroidApkController(IAndroidApkVersionApplication apkApp)
{
_apkApp = apkApp;
}
[HttpGet("check-update")]
public async Task<IActionResult> CheckUpdate([FromQuery] ApkType type, [FromQuery] int currentVersionCode = 0)
{
var info = await _apkApp.GetLatestActiveInfo(type, currentVersionCode);
return Ok(new
{
latestVersionCode = info.LatestVersionCode,
latestVersionName = info.LatestVersionName,
shouldUpdate = info.ShouldUpdate,
isForceUpdate = info.IsForceUpdate,
downloadUrl = info.DownloadUrl,
releaseNotes = info.ReleaseNotes
});
}
[HttpGet("download")]
public async Task<IActionResult> Download([FromQuery] ApkType type)
{
// Check if APK exists
if (!_apkApp.HasAndroidApkToDownload(type))
{
return NotFound(new { message = $"هیچ فایل APK فعالی برای {type} یافت نشد" });
}
// Get the path to the latest active APK
var path = await _apkApp.GetLatestActiveVersionPath(type);
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path))
{
return NotFound(new { message = "فایل APK یافت نشد" });
}
// Set appropriate file name for download
var fileName = type == ApkType.WebView
? "Gozareshgir.apk"
: "Gozareshgir-FaceDetection.apk";
// Return the file for download
return PhysicalFile(path, "application/vnd.android.package-archive", fileName);
}
}

View File

@@ -10,7 +10,17 @@
<label asp-for="File">Choose a file:</label>
<input asp-for="File" type="file" required>
</div>
<button type="submit">Upload</button>
<div style="margin-top:12px;">
<label asp-for="SelectedApkType">نوع اپلیکیشن:</label>
<select asp-for="SelectedApkType" asp-items="Html.GetEnumSelectList<CompanyManagment.App.Contracts.AndroidApkVersion.ApkType>()"></select>
</div>
<div style="margin-top:12px;">
<label asp-for="IsForce">
<input asp-for="IsForce" type="checkbox">
آپدیت اجباری (Force Update)
</label>
</div>
<button type="submit" style="margin-top:12px;">Upload</button>
</form>
<form asp-page-handler="ShiftDate" id="8" method="post">

View File

@@ -2,6 +2,7 @@
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
using AccountManagement.Domain.AccountLeftWorkAgg;
using AccountMangement.Infrastructure.EFCore;
using Company.Domain.AndroidApkVersionAgg;
using Company.Domain.CustomizeCheckoutAgg.ValueObjects;
using Company.Domain.CustomizeCheckoutTempAgg.ValueObjects;
using Company.Domain.RewardAgg;
@@ -45,6 +46,8 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
[BindProperty] public IFormFile File { get; set; }
[BindProperty] public ApkType SelectedApkType { get; set; }
[BindProperty] public bool IsForce { get; set; }
public IndexModel(IAndroidApkVersionApplication application, IRollCallDomainService rollCallDomainService,
CompanyContext context, AccountContext accountContext, IHttpClientFactory httpClientFactory,
@@ -67,7 +70,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
public async Task<IActionResult> OnPostUpload()
{
var result = await _application.CreateAndActive(File);
var result = await _application.CreateAndActive(File, SelectedApkType, IsForce);
ViewData["message"] = result.Message;
return Page();
}

View File

@@ -9,6 +9,7 @@ using _0_Framework.Exceptions;
using AccountManagement.Application.Contracts.Account;
using AccountManagement.Application.Contracts.CameraAccount;
using AccountManagement.Domain.TaskAgg;
using CompanyManagment.App.Contracts.AndroidApkVersion;
using CompanyManagment.App.Contracts.PersonnleCode;
using CompanyManagment.App.Contracts.RollCall;
using CompanyManagment.App.Contracts.RollCallEmployee;
@@ -36,6 +37,7 @@ public class CameraController : CameraBaseController
private long _workshopId;
private readonly IHttpClientFactory _httpClientFactory;
private readonly HttpClient _faceEmbeddingHttpClient;
private readonly IAndroidApkVersionApplication _androidApkVersionApplication;
public CameraController(IWebHostEnvironment webHostEnvironment,
IConfiguration configuration,
@@ -48,7 +50,7 @@ public class CameraController : CameraBaseController
IAccountApplication accountApplication,
IPasswordHasher passwordHasher,
ICameraAccountApplication cameraAccountApplication,
IEmployeeFaceEmbeddingApplication employeeFaceEmbeddingApplication, IHttpClientFactory httpClientFactory)
IEmployeeFaceEmbeddingApplication employeeFaceEmbeddingApplication, IHttpClientFactory httpClientFactory, IAndroidApkVersionApplication androidApkVersionApplication)
{
_webHostEnvironment = webHostEnvironment;
_configuration = configuration;
@@ -63,6 +65,7 @@ public class CameraController : CameraBaseController
_cameraAccountApplication = cameraAccountApplication;
_employeeFaceEmbeddingApplication = employeeFaceEmbeddingApplication;
_httpClientFactory = httpClientFactory;
_androidApkVersionApplication = androidApkVersionApplication;
_faceEmbeddingHttpClient = httpClientFactory.CreateClient();
_faceEmbeddingHttpClient.BaseAddress = new Uri("http://localhost:8000/");
_workshopId= authHelper.GetWorkshopId();
@@ -217,6 +220,50 @@ public class CameraController : CameraBaseController
}
}
[AllowAnonymous]
[HttpGet("check-update")]
public async Task<IActionResult> CheckUpdate([FromQuery] ApkType type, [FromQuery] int currentVersionCode = 0)
{
var info = await _androidApkVersionApplication.GetLatestActiveInfo(type, currentVersionCode);
return Ok(new
{
latestVersionCode = 6000,
latestVersionName = "2.0.0",
shouldUpdate = info.ShouldUpdate,
isForceUpdate = info.IsForceUpdate,
downloadUrl = info.DownloadUrl,
releaseNotes = info.ReleaseNotes
});
}
[AllowAnonymous]
[HttpGet("download")]
public async Task<IActionResult> Download([FromQuery] ApkType type)
{
// Check if APK exists
if (!_androidApkVersionApplication.HasAndroidApkToDownload(type))
{
return NotFound(new { message = $"هیچ فایل APK فعالی برای {type} یافت نشد" });
}
// Get the path to the latest active APK
var path = await _androidApkVersionApplication.GetLatestActiveVersionPath(type);
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path))
{
return NotFound(new { message = "فایل APK یافت نشد" });
}
// Set appropriate file name for download
var fileName = type == ApkType.WebView
? "Gozareshgir.apk"
: "Gozareshgir-FaceDetection.apk";
// Return the file for download
return PhysicalFile(path, "application/vnd.android.package-archive", fileName);
}
[HttpGet("SendPersonelCodeToGetEmployeeId")]
public IActionResult SendPersonelCodeToGetEmployeeId(long personelCode, long workshopId)

View File

@@ -65,6 +65,7 @@ namespace ServiceHost.Areas.Client.Pages
#region Mahan
public bool HasInsuranceToConfirm { get; set; }
public bool HasApkToDownload { get; set; }
public bool HasFaceDetectionApkToDownload { get; set; }
#endregion
public IndexModel(IAuthHelper authHelper, IPasswordHasher passwordHasher, IWorkshopApplication workshopApplication, ILeaveApplication leaveApplication, IEmployeeApplication employeeApplication, IPaymentToEmployeeItemApplication paymentToEmployeeItemApplication, IPaymentToEmployeeApplication paymentToEmployeeApplication, IHolidayItemApplication holidayItemApplication, IInsuranceListApplication insuranceListApplication, IAndroidApkVersionApplication androidApkVersionApplication, IRollCallServiceApplication rollCallServiceApplication, IPersonnelCodeApplication personnelCodeApplication, ICustomizeWorkshopSettingsApplication customizeWorkshopSettingsApplication, IBankApplication bankApplication, ILeftWorkTempApplication leftWorkTempApplication, IJobApplication jobApplication, ICustomizeWorkshopSettingsApplication customizeWorkshopEmployee, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, ICameraAccountApplication cameraAccountApplication)
@@ -100,7 +101,8 @@ namespace ServiceHost.Areas.Client.Pages
profilePicture = account.ProfilePhoto;
AccountFullName = account.Fullname;
var todayGr = DateTime.Now;
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload();
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.WebView);
HasFaceDetectionApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.FaceDetection);
#region Mahan

View File

@@ -13,9 +13,11 @@ public class AndroidApk : Controller
}
[Route("Apk/Android")]
public async Task<IActionResult> Index()
public async Task<IActionResult> Index([FromQuery] string type = "WebView")
{
var path = await _androidApkVersionApplication.GetLatestActiveVersionPath();
return PhysicalFile(path,"application/vnd.android.package-archive","Gozareshgir.apk");
ApkType apkType = type.ToLower() == "facedetection" ? ApkType.FaceDetection : ApkType.WebView;
var path = await _androidApkVersionApplication.GetLatestActiveVersionPath(apkType);
var fileName = apkType == ApkType.WebView ? "Gozareshgir.apk" : "Gozareshgir-FaceDetection.apk";
return PhysicalFile(path,"application/vnd.android.package-archive", fileName);
}
}

View File

@@ -43,6 +43,7 @@ public class IndexModel : PageModel
[BindProperty] public string Password { get; set; }
[BindProperty] public string CaptchaResponse { get; set; }
public bool HasApkToDownload { get; set; }
public bool HasFaceDetectionApkToDownload { get; set; }
private static Timer aTimer;
public Login login;
public AccountViewModel Search;
@@ -76,7 +77,8 @@ public class IndexModel : PageModel
//_context.SaveChanges();
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload();
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.WebView);
HasFaceDetectionApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.FaceDetection);
if (User.Identity is { IsAuthenticated: true })
{
if (User.FindFirstValue("IsCamera") == "true")

View File

@@ -19,7 +19,7 @@
"sqlDebugging": true,
"dotnetRunMessages": "true",
"nativeDebugging": true,
"applicationUrl": "https://localhost:5004;http://localhost:5003;",
"applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5005;http://192.168.0.117:5006;",
"jsWebView2Debugging": false,
"hotReloadEnabled": true
},