diff --git a/DurnyklyYol.Blazor.Server/API/Security/JwtTokenProviderService.cs b/DurnyklyYol.Blazor.Server/API/Security/JwtTokenProviderService.cs index 4a75de8..39945ac 100644 --- a/DurnyklyYol.Blazor.Server/API/Security/JwtTokenProviderService.cs +++ b/DurnyklyYol.Blazor.Server/API/Security/JwtTokenProviderService.cs @@ -21,8 +21,8 @@ public class JwtTokenProviderService : IAuthenticationTokenProvider { if(result.Succeeded) { var issuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Authentication:Jwt:IssuerSigningKey"])); var token = new JwtSecurityToken( - //issuer: configuration["Authentication:Jwt:Issuer"], - //audience: configuration["Authentication:Jwt:Audience"], + issuer: configuration["Authentication:Jwt:Issuer"], + audience: configuration["Authentication:Jwt:Audience"], claims: result.Principal.Claims, expires: DateTime.Now.AddDays(2), signingCredentials: new SigningCredentials(issuerSigningKey, SecurityAlgorithms.HmacSha256) diff --git a/DurnyklyYol.Blazor.Server/Controllers/CargoController.cs b/DurnyklyYol.Blazor.Server/Controllers/CargoController.cs index f887494..126f549 100644 --- a/DurnyklyYol.Blazor.Server/Controllers/CargoController.cs +++ b/DurnyklyYol.Blazor.Server/Controllers/CargoController.cs @@ -1,10 +1,6 @@ using DevExpress.ExpressApp.Core; -using DevExpress.ExpressApp.Security; -using DevExpress.ExpressApp.WebApi.Services; using DurnyklyYol.Blazor.Server.DTO; using DurnyklyYol.Module.BusinessObjects; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace DurnyklyYol.Blazor.Server.Controllers @@ -34,10 +30,10 @@ namespace DurnyklyYol.Blazor.Server.Controllers .Where(wh => wh.Oid == cargo.Route.Oid) .Select(sl => new { - StartName = sl.StartPoint.Name, - Startpoint = sl.StartPoint.Point, - DestName = sl.DestinationPoint.Name, - Destpoint = sl.DestinationPoint.Point, + //StartName = sl.StartPoint.Name, + //Startpoint = sl.StartPoint.Point, + //DestName = sl.DestinationPoint.Name, + //Destpoint = sl.DestinationPoint.Point, Points = sl.Points.OrderBy(ob => ob.Order).Select(p => p.Point) }) .FirstOrDefault(); @@ -56,24 +52,23 @@ namespace DurnyklyYol.Blazor.Server.Controllers }).ToList(); - points.Insert(0, new PointDto - { - Name = route.StartName, - Lat = route.Startpoint?.Latitude ?? 0, - Long = route.Startpoint?.Longitude ?? 0, - IsCurrent = cargo.CurrentPoint.Oid == route.Startpoint?.Oid, - DateAt = cargo.StartedAt - }); - - points.Add(new PointDto - { - Name = route.DestName, - Lat = route.Destpoint?.Latitude ?? 0, - Long = route.Destpoint?.Longitude ?? 0, - IsCurrent = cargo.CurrentPoint.Oid == route.Destpoint?.Oid, - DateAt = cargo.ArrivedAt - }); + //points.Insert(0, new PointDto + //{ + // //Name = route.StartName, + // //Lat = route.Startpoint?.Latitude ?? 0, + // //Long = route.Startpoint?.Longitude ?? 0, + // //IsCurrent = cargo.CurrentPoint.Oid == route.Startpoint?.Oid, + // DateAt = cargo.StartedAt + //}); + //points.Add(new PointDto + //{ + // //Name = route.DestName, + // //Lat = route.Destpoint?.Latitude ?? 0, + // //Long = route.Destpoint?.Longitude ?? 0, + // //IsCurrent = cargo.CurrentPoint.Oid == route.Destpoint?.Oid, + // DateAt = cargo.ArrivedAt + //}); return Ok(points); } diff --git a/DurnyklyYol.Blazor.Server/Controllers/ClientController.cs b/DurnyklyYol.Blazor.Server/Controllers/ClientController.cs index d66d969..8896297 100644 --- a/DurnyklyYol.Blazor.Server/Controllers/ClientController.cs +++ b/DurnyklyYol.Blazor.Server/Controllers/ClientController.cs @@ -1,36 +1,149 @@ using Microsoft.AspNetCore.Mvc; using DevExpress.ExpressApp.Security; -using DevExpress.Persistent.BaseImpl.PermissionPolicy; -using DevExpress.ExpressApp; -using DevExpress.ExpressApp.SystemModule; -using DevExpress.Persistent.Base; -using DevExpress.ExpressApp.WebApi; -using System.Linq; using DevExpress.ExpressApp.Core; using DurnyklyYol.Module.BusinessObjects; using Microsoft.AspNetCore.Authorization; using DevExpress.ExpressApp.WebApi.Services; +using Swashbuckle.AspNetCore.Annotations; +using DevExpress.Data.Filtering; +using DurnyklyYol.Blazor.Server.DTO; namespace DurnyklyYol.Blazor.Server.Controllers { [ApiController] [Route("api/[controller]")] - [Authorize] public class ClientController : Microsoft.AspNetCore.Mvc.ControllerBase { private readonly IDataService dataService; private readonly ISecurityProvider securityProvider; - - public ClientController(IDataService dataService, ISecurityProvider securityProvider) + private readonly INonSecuredObjectSpaceFactory _nonSecuredObjectSpaceFactory; + public ClientController( + IDataService dataService, + ISecurityProvider securityProvider, + INonSecuredObjectSpaceFactory nonSecuredObjectSpaceFactory + ) { this.dataService = dataService; this.securityProvider = securityProvider; + this._nonSecuredObjectSpaceFactory = nonSecuredObjectSpaceFactory; + } + + [HttpPost(nameof(Register))] + [SwaggerOperation("Register account")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string) )] // Success response + [ProducesResponseType(StatusCodes.Status409Conflict, Type = typeof(string))] // Conflict response + [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(string))] + [ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(string))] + public async Task Register([FromForm] RegisterDto registerDto) + { + // Validate input + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + // Check if dataService is null + if (dataService == null) + { + return StatusCode(500, "Data service is not available"); + } + using var objectSpace = _nonSecuredObjectSpaceFactory.CreateNonSecuredObjectSpace(typeof(ApplicationUser)); + //var objectSpace = dataService.GetObjectSpace(typeof(ApplicationUser)); + // Check if username already exists + + var existingUser = objectSpace.FindObject(CriteriaOperator.Parse("UserName == ?", registerDto.Username)); + if (existingUser != null) + { + return Conflict("Username already exists."); + } + + // Create new user + var result = objectSpace.CreateObject(); + result.UserName = registerDto.Username; + result.FullName = registerDto.Name; + result.Telefon = registerDto.Phone; + result.SetPassword(registerDto.Password); + + objectSpace.CommitChanges(); + + // Create a new UserLoginInfo + ApplicationUserLoginInfo loginInfo = objectSpace.CreateObject(); + loginInfo.User = result; + loginInfo.LoginProviderName = "Password"; // Use "Standard" for standard authentication + loginInfo.ProviderUserKey = result.Oid.ToString(); // Use the username as the provider key + objectSpace.CommitChanges(); + return Ok("User registered successfully."); + } + + [HttpDelete(nameof(DeleteAccount))] + [SwaggerOperation("Delete account")] + [Authorize] + [ProducesResponseType(StatusCodes.Status204NoContent, Type = typeof(string))] // Success response + [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(string))] // Not found response + [ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(string))] + public IActionResult DeleteAccount() + { + try + { + // Check if securityProvider is null + if (securityProvider == null) + { + return StatusCode(500, "Security provider is not available"); + } + + // Check if dataService is null + if (dataService == null) + { + return StatusCode(500, "Data service is not available"); + } + + var objectSpace = dataService.GetObjectSpace(); + var userID = (Guid)securityProvider.GetSecurity().UserId; + var strategy = (SecurityStrategy)securityProvider.GetSecurity(); + if (!strategy.CanWrite(typeof(Client))) + return Forbid("You do not have permissions to update a client!"); + + var user = (Client)strategy.User; + if (user == null) + { + return NotFound("User not found."); + } + + var client = objectSpace.GetObject(user); + if (client == null) + { + return NotFound("Client not found."); + } + + client.Delete(); + objectSpace.CommitChanges(); + return NoContent(); + } + catch (Exception ex) + { + // Log exception details for debugging + return StatusCode(500, $"An error occurred while deleting the account: {ex.Message}"); + } } [HttpGet(nameof(GetClient))] [Authorize] + [SwaggerOperation("Get client information")] + [ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(string))] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))] public IActionResult GetClient() { + // Check if securityProvider is null + if (securityProvider == null) + { + return StatusCode(500, "Security provider is not available"); + } + + // Check if dataService is null + if (dataService == null) + { + return StatusCode(500, "Data service is not available"); + } + var objectSpace = dataService.GetObjectSpace(); var userID = (Guid)securityProvider.GetSecurity().UserId; var clients = objectSpace.GetObjectsQuery() @@ -40,5 +153,46 @@ namespace DurnyklyYol.Blazor.Server.Controllers return Ok(clients); } + + [HttpPost(nameof(FirebaseToken))] + [Authorize] + [SwaggerOperation("Updates clients firebase token")] + [ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(string))] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))] + [ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(string))] + [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(string))] + public IActionResult FirebaseToken([FromQuery] string token) + { + // Check if securityProvider is null + if (securityProvider == null) + { + return StatusCode(500, "Security provider is not available"); + } + + // Check if dataService is null + if (dataService == null) + { + return StatusCode(500, "Data service is not available"); + } + + var strategy = (SecurityStrategy)securityProvider.GetSecurity(); + if(!strategy.CanWrite(typeof(Client))) + return Forbid("You do not have permissions to update a client!"); + + var user = (Client)strategy.User; + if (user == null || string.IsNullOrEmpty(token)) { + return BadRequest(); + } + + var objectSpace = dataService.GetObjectSpace(typeof(Client)); + var client = objectSpace.GetObject(user); + + // Update the token and commit changes + client.FirebaseToken = token; + objectSpace.CommitChanges(); + + return Ok("Firebase token updated successfully."); + } + } } diff --git a/DurnyklyYol.Blazor.Server/Controllers/GoodsController.cs b/DurnyklyYol.Blazor.Server/Controllers/GoodsController.cs index 515ac2d..3bc474d 100644 --- a/DurnyklyYol.Blazor.Server/Controllers/GoodsController.cs +++ b/DurnyklyYol.Blazor.Server/Controllers/GoodsController.cs @@ -5,6 +5,7 @@ using DurnyklyYol.Blazor.Server.DTO; using DurnyklyYol.Module.BusinessObjects; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; namespace DurnyklyYol.Blazor.Server.Controllers { @@ -23,6 +24,7 @@ namespace DurnyklyYol.Blazor.Server.Controllers } [Authorize] + [SwaggerOperation("Get client goods")] [HttpGet] public IActionResult Get([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10, [FromQuery] GoodsState? state = null) { @@ -38,20 +40,19 @@ namespace DurnyklyYol.Blazor.Server.Controllers Volume = sl.Volume, ShopNo = sl.ShopNo, Carrier = sl.Cargo.Carrier.Number, - From = sl.Cargo.StartsFrom, - To = sl.Cargo.DestinationTo, + From = sl.ReceivedPoint.Name, + To = sl.DestinationPoint.Name, ClientId = sl.Client.Oid, DepartedAt = sl.Cargo.StartedAt, - Depth = sl.Depth, - Width = sl.Width, - Height = sl.Height, + //Depth = sl.Depth, + //Width = sl.Width, + //Height = sl.Height, CargoId = sl.Cargo.Oid, CargoState = sl.Cargo.State, State = sl.State, Price = sl.Price, - Image1 = sl.Image1 != null ? string.Format("/FileData/{0}-{1}", sl.Image1.Oid, sl.Image1.FileName) : "", - Image2 = sl.Image2 != null ? string.Format("/FileData/{0}-{1}", sl.Image2.Oid, sl.Image2.FileName) : "", - Image3 = sl.Image3 != null ? string.Format("/FileData/{0}-{1}", sl.Image3.Oid, sl.Image3.FileName) : "", + Invoice = sl.Image1 != null ? string.Format("/FileData/{0}-{1}", sl.Image1.Oid, sl.Image1.FileName) : "", + Image = sl.Image2 != null ? string.Format("/FileData/{0}-{1}", sl.Image2.Oid, sl.Image2.FileName) : "", }); if (state != null) { @@ -75,7 +76,5 @@ namespace DurnyklyYol.Blazor.Server.Controllers return Ok(response); } - - } } diff --git a/DurnyklyYol.Blazor.Server/Controllers/RequestController.cs b/DurnyklyYol.Blazor.Server/Controllers/RequestController.cs new file mode 100644 index 0000000..9f2a854 --- /dev/null +++ b/DurnyklyYol.Blazor.Server/Controllers/RequestController.cs @@ -0,0 +1,95 @@ +using DevExpress.ExpressApp.Security; +using DevExpress.ExpressApp.WebApi.Services; +using DurnyklyYol.Blazor.Server.DTO; +using DurnyklyYol.Module.BusinessObjects; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; + +namespace DurnyklyYol.Blazor.Server.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [Authorize] + public class RequestController : ControllerBase + { + private readonly IDataService dataService; + private readonly ISecurityProvider securityProvider; + + public RequestController(IDataService dataService, ISecurityProvider securityProvider) + { + this.dataService = dataService; + this.securityProvider = securityProvider; + } + + [Authorize] + [HttpGet] + public IActionResult Get([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10) + { + var objectSpace = dataService.GetObjectSpace(); + var userID = (Guid)securityProvider.GetSecurity().UserId; + + var requestQuery = objectSpace.GetObjectsQuery() + .Where(cl => cl.Client.Oid == userID); + + var totalRecords = requestQuery.Count(); + + var requests = requestQuery + .Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .ToList(); + + var response = new + { + TotalRecords = totalRecords, + PageNumber = pageNumber, + PageSize = pageSize, + Data = requests + }; + + return Ok(response); + } + + + [HttpPost] + [SwaggerOperation("Register client cargo request")] + [ProducesResponseType(StatusCodes.Status201Created)] // Success response + [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(string))] + [ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(string))] + public async Task Create([FromForm] RequestDto requstDto) + { + // Validate input + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + // Check if securityProvider is null + if (securityProvider == null || dataService == null) + { + return StatusCode(500, "Data service or Security provider is not available"); + } + + var strategy = (SecurityStrategy)securityProvider.GetSecurity(); + var user = (Client)strategy.User; + + if (user == null || !strategy.CanWrite(typeof(Client))) + return BadRequest("You do not have permissions to update a client!"); + + var objectSpace = dataService.GetObjectSpace(typeof(Client)); + var client = objectSpace.GetObject(user); + + var cargoRequest = objectSpace.CreateObject(); + cargoRequest.Client = client; + cargoRequest.CreatedAt = DateTime.Now; + cargoRequest.Description = requstDto.Description; + cargoRequest.From = requstDto.From; + cargoRequest.To = requstDto.To; + cargoRequest.GoodsType = requstDto.GoodsType; + //cargoRequest.Save(); + objectSpace.CommitChanges(); + + return Created(); + } + } +} diff --git a/DurnyklyYol.Blazor.Server/DTO/GoodsListDto.cs b/DurnyklyYol.Blazor.Server/DTO/GoodsListDto.cs index 1e6624b..92c4112 100644 --- a/DurnyklyYol.Blazor.Server/DTO/GoodsListDto.cs +++ b/DurnyklyYol.Blazor.Server/DTO/GoodsListDto.cs @@ -12,20 +12,20 @@ namespace DurnyklyYol.Blazor.Server.DTO public string No { get; set; } public string Name { get; set; } public string ShopNo { get; set; } - public double Volume { get; set; } + public decimal Volume { get; set; } public uint PlacesCount { get; set; } public string Carrier { get; set; } public string From { get; set; } public string To { get; set; } public DateTime? DepartedAt { get; set; } - public uint Depth { get; set; } - public uint Width { get; set; } - public uint Height { get; set; } + //public uint Depth { get; set; } + //public uint Width { get; set; } + //public uint Height { get; set; } public decimal Price { get; set; } - public string Image1 { get; set; } - public string Image2 { get; set; } - public string Image3 { get; set; } + public string Invoice { get; set; } + public string Image { get; set; } + //public string Image3 { get; set; } } } diff --git a/DurnyklyYol.Blazor.Server/DTO/RegisterDto.cs b/DurnyklyYol.Blazor.Server/DTO/RegisterDto.cs new file mode 100644 index 0000000..4ea90a1 --- /dev/null +++ b/DurnyklyYol.Blazor.Server/DTO/RegisterDto.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; +namespace DurnyklyYol.Blazor.Server.DTO +{ + public class RegisterDto + { + [Required(ErrorMessage = "Username is required")] + public string Username { get; set; } + + [Required(ErrorMessage = "Password is required")] + public string Password { get; set; } + + [Required(ErrorMessage = "Name is required")] + public string Name { get; set; } + + [Required(ErrorMessage = "Phone is required")] + public string Phone { get; set; } + } +} diff --git a/DurnyklyYol.Blazor.Server/DTO/RequestDto.cs b/DurnyklyYol.Blazor.Server/DTO/RequestDto.cs new file mode 100644 index 0000000..1063e54 --- /dev/null +++ b/DurnyklyYol.Blazor.Server/DTO/RequestDto.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; + +namespace DurnyklyYol.Blazor.Server.DTO +{ + public class RequestDto + { + [Required(ErrorMessage = "GoodsType is required")] + public string GoodsType { get; set; } + + [Required(ErrorMessage = "Description is required")] + public string Description { get; set; } + + [Required(ErrorMessage = "From is required")] + public string From { get; set; } + + [Required(ErrorMessage = "To is required")] + public string To { get; set; } + } +} diff --git a/DurnyklyYol.Blazor.Server/DurnyklyYol.Blazor.Server.csproj b/DurnyklyYol.Blazor.Server/DurnyklyYol.Blazor.Server.csproj index 963abc3..7c4d0b7 100644 --- a/DurnyklyYol.Blazor.Server/DurnyklyYol.Blazor.Server.csproj +++ b/DurnyklyYol.Blazor.Server/DurnyklyYol.Blazor.Server.csproj @@ -25,17 +25,20 @@ - - - - - - - - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/DurnyklyYol.Blazor.Server/GoodsImageUpload.razor b/DurnyklyYol.Blazor.Server/GoodsImageUpload.razor index 1dd0bbf..1fa2d75 100644 --- a/DurnyklyYol.Blazor.Server/GoodsImageUpload.razor +++ b/DurnyklyYol.Blazor.Server/GoodsImageUpload.razor @@ -4,7 +4,6 @@ @inject IObjectSpace ObjectSpace @inject IWebHostEnvironment Environment - @code { [Parameter] diff --git a/DurnyklyYol.Blazor.Server/Startup.cs b/DurnyklyYol.Blazor.Server/Startup.cs index f245178..6f760d9 100644 --- a/DurnyklyYol.Blazor.Server/Startup.cs +++ b/DurnyklyYol.Blazor.Server/Startup.cs @@ -17,6 +17,7 @@ using DurnyklyYol.WebApi.JWT; using DevExpress.ExpressApp.Security.Authentication.ClientServer; using DurnyklyYol.Blazor.Server.OData; using Microsoft.AspNetCore.OData.Query.Validator; +using DurnyklyYol.Module.Services; namespace DurnyklyYol.Blazor.Server; @@ -33,6 +34,7 @@ public class Startup { services.AddSingleton(typeof(Microsoft.AspNetCore.SignalR.HubConnectionHandler<>), typeof(ProxyHubConnectionHandler<>)); services.AddRazorPages(); + services.AddSingleton(); services.AddServerSideBlazor(); services.AddHttpContextAccessor(); services.AddScoped(); diff --git a/DurnyklyYol.Blazor.Server/appsettings.json b/DurnyklyYol.Blazor.Server/appsettings.json index 99da02d..e48e645 100644 --- a/DurnyklyYol.Blazor.Server/appsettings.json +++ b/DurnyklyYol.Blazor.Server/appsettings.json @@ -7,11 +7,11 @@ "Authentication": { "Jwt": { // For more information, refer to the following topic: Configure the JWT Authentication for the Web API https://docs.devexpress.com/eXpressAppFramework/403504 - "Issuer": "My", - "Audience": "http://localhost:4200", + "Issuer": "66Kargo", + "Audience": "cargo.tpsadvertising.com", // The debug secret key. You should store sensitive settings in dedicated secret storage. For more information, refer to the following topic: https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-7.0&tabs=windows. "IssuerSigningKey": "3e3d5a02-f807-493c-a590-4250c04f2c94" - }, + } }, "Logging": { "LogLevel": { diff --git a/DurnyklyYol.MiddleTier/DurnyklyYol.MiddleTier.csproj b/DurnyklyYol.MiddleTier/DurnyklyYol.MiddleTier.csproj index a89e7fe..456d0e8 100644 --- a/DurnyklyYol.MiddleTier/DurnyklyYol.MiddleTier.csproj +++ b/DurnyklyYol.MiddleTier/DurnyklyYol.MiddleTier.csproj @@ -9,16 +9,19 @@ enable - - - - - - - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + diff --git a/DurnyklyYol.Module/BusinessObjects/ApplicationUser.cs b/DurnyklyYol.Module/BusinessObjects/ApplicationUser.cs index 136e772..d7cc7e0 100644 --- a/DurnyklyYol.Module/BusinessObjects/ApplicationUser.cs +++ b/DurnyklyYol.Module/BusinessObjects/ApplicationUser.cs @@ -10,36 +10,46 @@ namespace DurnyklyYol.Module.BusinessObjects; [MapInheritance(MapInheritanceType.ParentTable)] [DefaultProperty(nameof(UserName))] public class ApplicationUser : PermissionPolicyUser, ISecurityUserWithLoginInfo, ISecurityUserLockout { + bool suspended; private int accessFailedCount; private DateTime lockoutEnd; public ApplicationUser(Session session) : base(session) { } [Browsable(false)] - public int AccessFailedCount { + public int AccessFailedCount + { get { return accessFailedCount; } set { SetPropertyValue(nameof(AccessFailedCount), ref accessFailedCount, value); } } [Browsable(false)] - public DateTime LockoutEnd { + public DateTime LockoutEnd + { get { return lockoutEnd; } set { SetPropertyValue(nameof(LockoutEnd), ref lockoutEnd, value); } } [Browsable(false)] [Aggregated, Association("User-LoginInfo")] - public XPCollection LoginInfo { + public XPCollection LoginInfo + { get { return GetCollection(nameof(LoginInfo)); } } IEnumerable IOAuthSecurityUser.UserLogins => LoginInfo.OfType(); - ISecurityUserLoginInfo ISecurityUserWithLoginInfo.CreateUserLoginInfo(string loginProviderName, string providerUserKey) { + ISecurityUserLoginInfo ISecurityUserWithLoginInfo.CreateUserLoginInfo(string loginProviderName, string providerUserKey) + { ApplicationUserLoginInfo result = new ApplicationUserLoginInfo(Session); result.LoginProviderName = loginProviderName; result.ProviderUserKey = providerUserKey; result.User = this; return result; } + public bool Suspended + { + get => suspended; + set => SetPropertyValue(nameof(Suspended), ref suspended, value); + } } diff --git a/DurnyklyYol.Module/BusinessObjects/Cargo.cs b/DurnyklyYol.Module/BusinessObjects/Cargo.cs index 2076595..79df91c 100644 --- a/DurnyklyYol.Module/BusinessObjects/Cargo.cs +++ b/DurnyklyYol.Module/BusinessObjects/Cargo.cs @@ -4,6 +4,8 @@ using DevExpress.Persistent.Base; using DevExpress.Persistent.BaseImpl; using DevExpress.Persistent.Validation; using DevExpress.Xpo; +using DurnyklyYol.Module.Services; +using Microsoft.Extensions.DependencyInjection; using System.ComponentModel; namespace DurnyklyYol.Module.BusinessObjects @@ -21,7 +23,12 @@ namespace DurnyklyYol.Module.BusinessObjects : base(session) { } - + private Point originalCurrentPoint; + protected override void OnLoaded() + { + base.OnLoaded(); + originalCurrentPoint = CurrentPoint; + } protected override void OnSaving() { base.OnSaving(); @@ -31,12 +38,31 @@ namespace DurnyklyYol.Module.BusinessObjects && (Session.ObjectLayer is SimpleObjectLayer) //OR //&& !(Session.ObjectLayer is DevExpress.ExpressApp.Security.ClientServer.SecuredSessionObjectLayer) - && string.IsNullOrEmpty(No)) + ) { - int nextSequence = DistributedIdGeneratorHelper.Generate(Session.DataLayer, this.GetType().FullName, "ERPrefix"); - No = string.Format("KA-{0:D6}", nextSequence); + if (string.IsNullOrEmpty(No)) + { + int nextSequence = DistributedIdGeneratorHelper.Generate( + Session.DataLayer, + this.GetType().FullName, + "ERPrefix" + ); + No = string.Format("KA-{0:D6}", nextSequence); + } + } } + protected override void OnSaved() + { + base.OnSaved(); + if (CurrentPoint != null && CurrentPoint != originalCurrentPoint) + { + var notification = Session.ServiceProvider.GetRequiredService(); + System.Threading.Tasks.Task.Run(async () => await notification.NotifyClients(this)); + + } + + } double totalWeight; string no; //CargoState state; @@ -58,18 +84,19 @@ namespace DurnyklyYol.Module.BusinessObjects { get { - if (CurrentPoint == null || CurrentPoint.Oid == Route.StartPoint.Point.Oid) + if (CurrentPoint == null || Route == null || Route.Points.Count == 0) { return CargoState.Warehouse; } - else if (CurrentPoint != null && CurrentPoint.Oid == Route.DestinationPoint.Point.Oid) + + var lastPoint = Route.Points.OrderBy(o => o.Order).Last(); + if (lastPoint != null && CurrentPoint != null && lastPoint.Oid == CurrentPoint.Oid) { return CargoState.Arrived; } - else - { - return CargoState.InTransit; - } + + return CargoState.InTransit; + } //set => SetPropertyValue(nameof(State), ref state, value); } @@ -111,10 +138,6 @@ namespace DurnyklyYol.Module.BusinessObjects [ModelDefault("DisplayFormat", "${0:#,##0.00}")] public decimal CurrentProfit => PayedTotal - TotalExpenseAmount; - [Browsable(false)] - public string StartsFrom => Route?.StartPoint?.Name; - [Browsable(false)] - public string DestinationTo => Route?.DestinationPoint?.Name; [RuleRequiredField(DefaultContexts.Save), ImmediatePostData] public Route Route @@ -142,22 +165,16 @@ namespace DurnyklyYol.Module.BusinessObjects { if (Route is null) return new XPCollection(Session); - var startPoint = Route.StartPoint.Point; - var endPoint = Route.DestinationPoint.Point; - var points = Route.Points .OrderBy(or => or.Order) .Select(sl => sl.Point) .ToList(); - - points.Insert(0, startPoint); - points.Add(endPoint); return new XPCollection(Session, points); } } - [RuleRequiredField(DefaultContexts.Save), ImmediatePostData, DataSourceProperty(nameof(AvailablePoints))] + [ImmediatePostData, DataSourceProperty(nameof(AvailablePoints))] public Point CurrentPoint { get => currentPoint; diff --git a/DurnyklyYol.Module/BusinessObjects/CargoRequest.cs b/DurnyklyYol.Module/BusinessObjects/CargoRequest.cs new file mode 100644 index 0000000..5dd2e50 --- /dev/null +++ b/DurnyklyYol.Module/BusinessObjects/CargoRequest.cs @@ -0,0 +1,96 @@ +using DevExpress.Persistent.Base; +using DevExpress.Persistent.BaseImpl; +using DevExpress.Xpo; + +namespace DurnyklyYol.Module.BusinessObjects +{ + [DefaultClassOptions, NavigationItem("Clients & Goods")] + //[ImageName("BO_Contact")] + //[DefaultProperty("DisplayMemberNameForLookupEditorsOfThisType")] + //[DefaultListViewOptions(MasterDetailMode.ListViewOnly, false, NewItemRowPosition.None)] + //[Persistent("DatabaseTableName")] + // Specify more UI options using a declarative approach (https://documentation.devexpress.com/#eXpressAppFramework/CustomDocument112701). + public class CargoRequest : BaseObject + { // Inherit from a different class to provide a custom primary key, concurrency and deletion behavior, etc. (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument113146.aspx). + // Use CodeRush to create XPO classes and properties with a few keystrokes. + // https://docs.devexpress.com/CodeRushForRoslyn/118557 + public CargoRequest(Session session) + : base(session) + { + } + public override void AfterConstruction() + { + base.AfterConstruction(); + CreatedAt = DateTime.Now; + Status = RequestStatus.New; + } + + + RequestStatus status; + string to; + string from; + string description; + string goodsType; + DateTime createdAt; + Client client; + + [Association("Client-CargoRequests")] + public Client Client + { + get => client; + set => SetPropertyValue(nameof(Client), ref client, value); + } + + public DateTime CreatedAt + { + get => createdAt; + set => SetPropertyValue(nameof(CreatedAt), ref createdAt, value); + } + + + [Size(SizeAttribute.DefaultStringMappingFieldSize)] + public string GoodsType + { + get => goodsType; + set => SetPropertyValue(nameof(GoodsType), ref goodsType, value); + } + + + [Size(SizeAttribute.DefaultStringMappingFieldSize)] + public string Description + { + get => description; + set => SetPropertyValue(nameof(Description), ref description, value); + } + + + [Size(SizeAttribute.DefaultStringMappingFieldSize)] + public string From + { + get => from; + set => SetPropertyValue(nameof(From), ref from, value); + } + + + [Size(SizeAttribute.DefaultStringMappingFieldSize)] + public string To + { + get => to; + set => SetPropertyValue(nameof(To), ref to, value); + } + + + public RequestStatus Status + { + get => status; + set => SetPropertyValue(nameof(Status), ref status, value); + } + } + + public enum RequestStatus + { + New, + Accepted, + Rejected + } +} \ No newline at end of file diff --git a/DurnyklyYol.Module/BusinessObjects/Carrier.cs b/DurnyklyYol.Module/BusinessObjects/Carrier.cs index a859de3..341f24a 100644 --- a/DurnyklyYol.Module/BusinessObjects/Carrier.cs +++ b/DurnyklyYol.Module/BusinessObjects/Carrier.cs @@ -16,7 +16,7 @@ namespace DurnyklyYol.Module.BusinessObjects { [DefaultClassOptions, NavigationItem("Transportation")] [ImageName("Gauges")] - [DefaultProperty(nameof(Name)), FriendlyKeyProperty(nameof(Number))] + [DefaultProperty(nameof(Number)), FriendlyKeyProperty(nameof(Number))] //[DefaultListViewOptions(MasterDetailMode.ListViewOnly, false, NewItemRowPosition.None)] //[Persistent("DatabaseTableName")] // Specify more UI options using a declarative approach (https://documentation.devexpress.com/#eXpressAppFramework/CustomDocument112701). diff --git a/DurnyklyYol.Module/BusinessObjects/Client.cs b/DurnyklyYol.Module/BusinessObjects/Client.cs index 5e3d2e1..6960274 100644 --- a/DurnyklyYol.Module/BusinessObjects/Client.cs +++ b/DurnyklyYol.Module/BusinessObjects/Client.cs @@ -47,6 +47,7 @@ namespace DurnyklyYol.Module.BusinessObjects this.Roles.Add(clientRole); } } + string firebaseToken; string bellik; string telefon; Region region; @@ -85,6 +86,14 @@ namespace DurnyklyYol.Module.BusinessObjects set => SetPropertyValue(nameof(FullName), ref fullName, value); } + + [Size(SizeAttribute.Unlimited)] + public string FirebaseToken + { + get => firebaseToken; + set => SetPropertyValue(nameof(FirebaseToken), ref firebaseToken, value); + } + [IgnoreDataMember] public Region Region { @@ -100,5 +109,14 @@ namespace DurnyklyYol.Module.BusinessObjects return GetCollection(nameof(Goods)); } } + + [Association("Client-CargoRequests")] + public XPCollection CargoRequests + { + get + { + return GetCollection(nameof(CargoRequests)); + } + } } } \ No newline at end of file diff --git a/DurnyklyYol.Module/BusinessObjects/Goods.cs b/DurnyklyYol.Module/BusinessObjects/Goods.cs index 4d271a6..a65e810 100644 --- a/DurnyklyYol.Module/BusinessObjects/Goods.cs +++ b/DurnyklyYol.Module/BusinessObjects/Goods.cs @@ -59,114 +59,111 @@ namespace DurnyklyYol.Module.BusinessObjects get => no; set => SetPropertyValue(nameof(No), ref no, value); } - - [Size(SizeAttribute.DefaultStringMappingFieldSize), RuleRequiredField(DefaultContexts.Save), Index(2), VisibleInLookupListView(true)] + + [Index(1), VisibleInLookupListView(true)] + [Size(SizeAttribute.DefaultStringMappingFieldSize), RuleRequiredField(DefaultContexts.Save)] public string Name { get => name; set => SetPropertyValue(nameof(Name), ref name, value); } - [ModelDefault("DisplayFormat", "{0:g}"), ModelDefault("EditMask", "g"), ReadOnly(true)] + [VisibleInDetailView(false)] + [ModelDefault("DisplayFormat", "{0:g}"), ModelDefault("EditMask", "g")] public DateTime CreatedAt { get => createdAt; set => SetPropertyValue(nameof(CreatedAt), ref createdAt, value); } - [RuleValueComparison(ValueComparisonType.GreaterThan, 0)] - public double Volume - { - get => volume; - set => SetPropertyValue(nameof(Volume), ref volume, value); - } - - [RuleValueComparison(ValueComparisonType.GreaterThan, 0)] + [RuleValueComparison(ValueComparisonType.GreaterThan, 0), Index(2)] public uint PlaceCount { get => placeCount; set => SetPropertyValue(nameof(PlaceCount), ref placeCount, value); } - [RuleValueComparison(ValueComparisonType.GreaterThan, 0)] + [RuleValueComparison(ValueComparisonType.GreaterThan, 0), Index(3)] public uint PackageCount { get => packageCount; set => SetPropertyValue(nameof(PackageCount), ref packageCount, value); } - [Size(SizeAttribute.DefaultStringMappingFieldSize), IgnoreDataMember] - public string PackingType + [ModelDefault("DisplayFormat", "{0:#,##0.00 }"), ModelDefault("EditMask", "############,##0.00")] + [ImmediatePostData, Index(4), RuleValueComparison(ValueComparisonType.GreaterThan, 0)] + public decimal Volume { - get => packingType; - set => SetPropertyValue(nameof(PackingType), ref packingType, value); + get => volume; + set => SetPropertyValue(nameof(Volume), ref volume, value); } - public DateTime ReceivedAt - { - get => receivedAt; - set => SetPropertyValue(nameof(ReceivedAt), ref receivedAt, value); - } - - [ModelDefault("DisplayFormat", "${0:#,##0.00}")] + [ModelDefault("DisplayFormat", "${0:#,##0.00}"), ModelDefault("EditMask", "$############,##0.00"), Index(5)] public decimal Price { get => price; set => SetPropertyValue(nameof(Price), ref price, value); } + [PersistentAlias("Price * Volume"), ModelDefault("DisplayFormat", "${0:#,##0.00 }"), Index(6)] + public decimal TotalPrice => Convert.ToDecimal(EvaluateAlias(nameof(TotalPrice))); - public uint Height - { - get => height; - set => SetPropertyValue(nameof(Height), ref height, value); - } - public uint Width - { - get => width; - set => SetPropertyValue(nameof(Width), ref width, value); - } - - public uint Depth - { - get => depth; - set => SetPropertyValue(nameof(Depth), ref depth, value); - } - - //[RuleRequiredField(DefaultContexts.Save), Index(1)] - //public Shop Shop - //{ - // get => shop; - // set => SetPropertyValue(nameof(Shop), ref shop, value); - //} - - - [Size(SizeAttribute.DefaultStringMappingFieldSize)] - public string ShopNo - { - get => shopNo; - set => SetPropertyValue(nameof(ShopNo), ref shopNo, value); - } - - [Aggregated, ExpandObjectMembers(ExpandObjectMembers.Never), ImmediatePostData] + [Index(7)] + [Aggregated, ExpandObjectMembers(ExpandObjectMembers.Never), ImmediatePostData, VisibleInListView(false)] public FileSystemStoreObject Image1 { get { return GetPropertyValue("Image1"); } set { SetPropertyValue("Image1", value); } } - [Aggregated, ExpandObjectMembers(ExpandObjectMembers.Never), ImmediatePostData] + [Index(9)] + [Aggregated, ExpandObjectMembers(ExpandObjectMembers.Never), ImmediatePostData, VisibleInListView(false)] public FileSystemStoreObject Image2 { get { return GetPropertyValue("Image2"); } set { SetPropertyValue("Image2", value); } } - [Aggregated, ExpandObjectMembers(ExpandObjectMembers.Never), ImmediatePostData] - public FileSystemStoreObject Image3 + [Size(SizeAttribute.DefaultStringMappingFieldSize), Index(10)] + public string ShopNo { - get { return GetPropertyValue("Image3"); } - set { SetPropertyValue("Image3", value); } + get => shopNo; + set => SetPropertyValue(nameof(ShopNo), ref shopNo, value); + } + + [Index(11)] + public Warehouse ReceivedPoint + { + get => receivedPoint; + set => SetPropertyValue(nameof(ReceivedPoint), ref receivedPoint, value); + } + + [Index(12)] + public DateTime? ReceivedAt + { + get => receivedAt; + set => SetPropertyValue(nameof(ReceivedAt), ref receivedAt, value); + } + [Index(13)] + public Warehouse DestinationPoint + { + get => destinationPoint; + set => SetPropertyValue(nameof(DestinationPoint), ref destinationPoint, value); + } + + [Index(14), VisibleInListView(false)] + public DateTime? DeliveredAt + { + get => deliveredAt; + set => SetPropertyValue(nameof(DeliveredAt), ref deliveredAt, value); + } + + [Index(15), VisibleInListView(false)] + [Size(SizeAttribute.DefaultStringMappingFieldSize)] + public string Note + { + get => note; + set => SetPropertyValue(nameof(Note), ref note, value); } [Association("Goods-Payments"), Aggregated] @@ -178,12 +175,6 @@ namespace DurnyklyYol.Module.BusinessObjects } } - [Association("Goods-GoodsImages"), Aggregated] - public XPCollection Images - { - get { return GetCollection(nameof(Images)); } - } - [Index(0), VisibleInLookupListView(true), VisibleInDetailView(true), IgnoreDataMember] [Association("Client-Goods"), RuleRequiredField(DefaultContexts.Save)] public Client Client @@ -197,7 +188,7 @@ namespace DurnyklyYol.Module.BusinessObjects public decimal TotalPayment => Payments.Sum(ps => ps.Amount); [VisibleInDetailView(false)] [ModelDefault("DisplayFormat", "${0:#,##0.00}")] - public decimal Credit => Price - TotalPayment; + public decimal Credit => TotalPrice - TotalPayment; public GoodsState State @@ -206,19 +197,18 @@ namespace DurnyklyYol.Module.BusinessObjects set => SetPropertyValue(nameof(State), ref state, value); } + string note; + DateTime? deliveredAt; + Warehouse destinationPoint; + Warehouse receivedPoint; string shopNo; DateTime createdAt; GoodsState state; - //Shop shop; - uint depth; - uint width; - uint height; uint packageCount; - string packingType; - DateTime receivedAt; + DateTime? receivedAt; decimal price; uint placeCount; - double volume; + decimal volume; string name; string no; Client client; diff --git a/DurnyklyYol.Module/BusinessObjects/GoodsImage.cs b/DurnyklyYol.Module/BusinessObjects/GoodsImage.cs index f68a7aa..640e66c 100644 --- a/DurnyklyYol.Module/BusinessObjects/GoodsImage.cs +++ b/DurnyklyYol.Module/BusinessObjects/GoodsImage.cs @@ -20,13 +20,13 @@ namespace DurnyklyYol.Module.BusinessObjects : base(session) { } - private Goods goods; - [Association("Goods-GoodsImages")] - public Goods Goods - { - get { return goods; } - set { SetPropertyValue(nameof(Goods), ref goods, value); } - } + //private Goods goods; + //[Association("Goods-GoodsImages")] + //public Goods Goods + //{ + // get { return goods; } + // set { SetPropertyValue(nameof(Goods), ref goods, value); } + //} private FileData file; [FileTypeFilter("ImageFiles", 1, "*.png", "*.jpg")] [Aggregated, ExpandObjectMembers(ExpandObjectMembers.Never), ImmediatePostData] diff --git a/DurnyklyYol.Module/BusinessObjects/Route.cs b/DurnyklyYol.Module/BusinessObjects/Route.cs index cbcc464..389ddee 100644 --- a/DurnyklyYol.Module/BusinessObjects/Route.cs +++ b/DurnyklyYol.Module/BusinessObjects/Route.cs @@ -25,9 +25,6 @@ namespace DurnyklyYol.Module.BusinessObjects { } - - Warehouse destinationPoint; - Warehouse startPoint; string title; [Size(SizeAttribute.DefaultStringMappingFieldSize), RuleRequiredField(DefaultContexts.Save)] @@ -36,18 +33,6 @@ namespace DurnyklyYol.Module.BusinessObjects get => title; set => SetPropertyValue(nameof(Title), ref title, value); } - [RuleRequiredField(DefaultContexts.Save)] - public Warehouse StartPoint - { - get => startPoint; - set => SetPropertyValue(nameof(StartPoint), ref startPoint, value); - } - [RuleRequiredField(DefaultContexts.Save)] - public Warehouse DestinationPoint - { - get => destinationPoint; - set => SetPropertyValue(nameof(DestinationPoint), ref destinationPoint, value); - } [Association("Route-RoutePoints"), Aggregated] public XPCollection Points diff --git a/DurnyklyYol.Module/DatabaseUpdate/Updater.cs b/DurnyklyYol.Module/DatabaseUpdate/Updater.cs index 9a7c3a3..8bf4076 100644 --- a/DurnyklyYol.Module/DatabaseUpdate/Updater.cs +++ b/DurnyklyYol.Module/DatabaseUpdate/Updater.cs @@ -86,7 +86,8 @@ public class Updater : ModuleUpdater { clRole.Name = GlobalConstants.ClientRoleName; clRole.AddObjectPermissionFromLambda(SecurityOperations.Read, cm => cm.Oid == (Guid)CurrentUserIdOperator.CurrentUserId(), SecurityPermissionState.Allow); - clRole.AddObjectPermissionFromLambda(SecurityOperations.Read, cm => cm.Oid == (Guid)CurrentUserIdOperator.CurrentUserId(), SecurityPermissionState.Allow); + clRole.AddObjectPermissionFromLambda(SecurityOperations.ReadWriteAccess, cm => cm.Oid == (Guid)CurrentUserIdOperator.CurrentUserId(), SecurityPermissionState.Allow); + clRole.AddObjectPermissionFromLambda(SecurityOperations.Read, cm => cm.Client.Oid == (Guid)CurrentUserIdOperator.CurrentUserId(), SecurityPermissionState.Allow); clRole.AddObjectPermissionFromLambda(SecurityOperations.Read, cm => cm.Client.Oid == (Guid)CurrentUserIdOperator.CurrentUserId(), SecurityPermissionState.Allow); @@ -104,6 +105,7 @@ public class Updater : ModuleUpdater { clRole.AddTypePermission(SecurityOperations.Read, SecurityPermissionState.Allow); clRole.AddTypePermission(SecurityOperations.Read, SecurityPermissionState.Allow); clRole.AddTypePermission(SecurityOperations.Read, SecurityPermissionState.Allow); + clRole.AddTypePermission(SecurityOperations.Create, SecurityPermissionState.Allow); //clRole.AddObjectPermission(SecurityOperations.ReadWriteAccess, "UserId = ToStr(CurrentUserId())", SecurityPermissionState.Deny); diff --git a/DurnyklyYol.Module/DurnyklyYol.Module.csproj b/DurnyklyYol.Module/DurnyklyYol.Module.csproj index fecddeb..a5d4ee1 100644 --- a/DurnyklyYol.Module/DurnyklyYol.Module.csproj +++ b/DurnyklyYol.Module/DurnyklyYol.Module.csproj @@ -21,20 +21,24 @@ - - - - - - - - - - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + @@ -44,6 +48,12 @@ Model.DesignedDiffs.xafml + + Model.DesignedDiffs.xafml + + + Model.DesignedDiffs.xafml + Model.DesignedDiffs.xafml diff --git a/DurnyklyYol.Module/DurnyklyYol.Module.generated.sln b/DurnyklyYol.Module/DurnyklyYol.Module.generated.sln new file mode 100644 index 0000000..dad4340 --- /dev/null +++ b/DurnyklyYol.Module/DurnyklyYol.Module.generated.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DurnyklyYol.Module", "DurnyklyYol.Module.csproj", "{8B75B9DA-F2D1-4BF2-9120-2DF225E1D955}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8B75B9DA-F2D1-4BF2-9120-2DF225E1D955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B75B9DA-F2D1-4BF2-9120-2DF225E1D955}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B75B9DA-F2D1-4BF2-9120-2DF225E1D955}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B75B9DA-F2D1-4BF2-9120-2DF225E1D955}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CC01F604-37EB-4EB6-B1ED-D22E5CDE1F22} + EndGlobalSection +EndGlobal diff --git a/DurnyklyYol.Module/Model.DesignedDiffs.Localization.tk-TM.xafml b/DurnyklyYol.Module/Model.DesignedDiffs.Localization.tk-TM.xafml index 9824d1a..cb669ad 100644 --- a/DurnyklyYol.Module/Model.DesignedDiffs.Localization.tk-TM.xafml +++ b/DurnyklyYol.Module/Model.DesignedDiffs.Localization.tk-TM.xafml @@ -50,35 +50,28 @@ - - + + + - - - + - - - - + + + - + + - - - - - - - + diff --git a/DurnyklyYol.Module/Model.DesignedDiffs.xafml b/DurnyklyYol.Module/Model.DesignedDiffs.xafml index 890344b..f8d364f 100644 --- a/DurnyklyYol.Module/Model.DesignedDiffs.xafml +++ b/DurnyklyYol.Module/Model.DesignedDiffs.xafml @@ -63,16 +63,11 @@ - - - - - @@ -112,12 +107,8 @@ - - - - @@ -128,6 +119,8 @@ + + @@ -154,15 +147,10 @@ - - - - - diff --git a/DurnyklyYol.Module/Services/INotificationService.cs b/DurnyklyYol.Module/Services/INotificationService.cs new file mode 100644 index 0000000..8da67fe --- /dev/null +++ b/DurnyklyYol.Module/Services/INotificationService.cs @@ -0,0 +1,10 @@ + +using DurnyklyYol.Module.BusinessObjects; + +namespace DurnyklyYol.Module.Services +{ + public interface INotificationService + { + Task NotifyClients(Cargo cargo); + } +} diff --git a/DurnyklyYol.Module/Services/NotificationService.cs b/DurnyklyYol.Module/Services/NotificationService.cs new file mode 100644 index 0000000..b003f81 --- /dev/null +++ b/DurnyklyYol.Module/Services/NotificationService.cs @@ -0,0 +1,73 @@ +using Microsoft.Extensions.DependencyInjection; +using FirebaseAdmin; +using FirebaseAdmin.Messaging; +using Google.Apis.Auth.OAuth2; +using System.Threading.Tasks; +using FileSystemData; +using DurnyklyYol.Module.BusinessObjects; +using DevExpress.XtraCharts; +using System.ServiceModel.Channels; +using DevExpress.Persistent.Base; + +namespace DurnyklyYol.Module.Services +{ + public class NotificationService : INotificationService + { + [ActivatorUtilitiesConstructor] + public NotificationService() { + var address = String.Format("{0}cargo-66-firebase-adminsdk.json", PathHelper.GetApplicationFolder()); + Console.WriteLine(address); + if (FirebaseApp.DefaultInstance == null) + FirebaseApp.Create(new AppOptions() + { + Credential = GoogleCredential.FromFile(address) + }); + + } + //private async Task SendNotificationAsync(string title, string body, string token) + //{ + // var message = new Message() + // { + // Notification = new Notification + // { + // Title = title, + // Body = body + // }, + // Token = token + // }; + + // return await FirebaseMessaging.DefaultInstance.SendAsync(message); + //} + + public async Task NotifyClients(Cargo cargo) + { + if (cargo is not null) { + var goodsWithClientTokens = cargo.Goods + .Where(good => !string.IsNullOrEmpty(good.Client.FirebaseToken)) // Filter out clients with empty tokens + .Select(good => new + { + GoodsCode = good.No, // Assuming 'Code' is the property of Goods + ClientToken = good.Client.FirebaseToken + }) + .ToList(); + if (goodsWithClientTokens.Count == 0) + { + return; + } + var messages = goodsWithClientTokens + .Select(item => new FirebaseAdmin.Messaging.Message + { + Notification = new Notification + { + Title = item.GoodsCode, // Customize title for each notification if necessary + Body = item.GoodsCode + " belgili ýüküňiz "+cargo.CurrentPoint.Name + " geldi." // Customize body for each notification if necessary + }, + Token = item.ClientToken + }) + .ToList(); + await FirebaseMessaging.DefaultInstance.SendEachAsync(messages); + + } + } + } +} diff --git a/DurnyklyYol.Module/UnusableNodes1.xml b/DurnyklyYol.Module/UnusableNodes1.xml new file mode 100644 index 0000000..4c12ad9 --- /dev/null +++ b/DurnyklyYol.Module/UnusableNodes1.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DurnyklyYol.Module/UnusableNodes1_tk-TM.xml b/DurnyklyYol.Module/UnusableNodes1_tk-TM.xml new file mode 100644 index 0000000..1cc0275 --- /dev/null +++ b/DurnyklyYol.Module/UnusableNodes1_tk-TM.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DurnyklyYol.Win/DurnyklyYol.Win.csproj b/DurnyklyYol.Win/DurnyklyYol.Win.csproj index 6a76100..7a1fea5 100644 --- a/DurnyklyYol.Win/DurnyklyYol.Win.csproj +++ b/DurnyklyYol.Win/DurnyklyYol.Win.csproj @@ -28,21 +28,24 @@ - - - - - - - - - - - - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + diff --git a/DurnyklyYol.Win/Startup.cs b/DurnyklyYol.Win/Startup.cs index f633d0b..4daf7d1 100644 --- a/DurnyklyYol.Win/Startup.cs +++ b/DurnyklyYol.Win/Startup.cs @@ -27,6 +27,7 @@ public class ApplicationBuilder : IDesignTimeApplicationFactory { // builder.UseServiceProviderFactory(new AutofacServiceProviderFactory()); builder.UseApplication(); + builder.Modules .AddConditionalAppearance() .AddFileAttachments() diff --git a/FileSystemData/FileSystemData.csproj b/FileSystemData/FileSystemData.csproj index 57b8471..3430113 100644 --- a/FileSystemData/FileSystemData.csproj +++ b/FileSystemData/FileSystemData.csproj @@ -24,14 +24,14 @@ - + all runtime; build; native; contentfiles; analyzers - - - + + + \ No newline at end of file