commit 1bcaac832afaf655aed15c7156fa595e2369d0ef Author: student Date: Fri Oct 4 15:41:04 2024 +0300 init diff --git a/App.axaml b/App.axaml new file mode 100644 index 0000000..d8f2401 --- /dev/null +++ b/App.axaml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/App.axaml.cs b/App.axaml.cs new file mode 100644 index 0000000..df3c544 --- /dev/null +++ b/App.axaml.cs @@ -0,0 +1,32 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Data.Core; +using Avalonia.Data.Core.Plugins; +using Avalonia.Markup.Xaml; +using demo_trade.ViewModels; +using demo_trade.Views; + +namespace demo_trade +{ + public partial class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + + desktop.MainWindow = new MainWindow + { + DataContext = new MainWindowViewModel(), + }; + } + + base.OnFrameworkInitializationCompleted(); + } + } +} \ No newline at end of file diff --git a/Assets/avalonia-logo.ico b/Assets/avalonia-logo.ico new file mode 100644 index 0000000..da8d49f Binary files /dev/null and b/Assets/avalonia-logo.ico differ diff --git a/Data/RemoteData/Entity/Category.cs b/Data/RemoteData/Entity/Category.cs new file mode 100644 index 0000000..413698d --- /dev/null +++ b/Data/RemoteData/Entity/Category.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class Category +{ + public int CategoryId { get; set; } + + public string? CategoryName { get; set; } + + public virtual ICollection Products { get; set; } = new List(); +} diff --git a/Data/RemoteData/Entity/Manufacturer.cs b/Data/RemoteData/Entity/Manufacturer.cs new file mode 100644 index 0000000..abbb916 --- /dev/null +++ b/Data/RemoteData/Entity/Manufacturer.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class Manufacturer +{ + public int ManufacturerId { get; set; } + + public string? ManufacturerName { get; set; } + + public virtual ICollection Products { get; set; } = new List(); +} diff --git a/Data/RemoteData/Entity/Order.cs b/Data/RemoteData/Entity/Order.cs new file mode 100644 index 0000000..fb88d2e --- /dev/null +++ b/Data/RemoteData/Entity/Order.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class Order +{ + public int Orderid { get; set; } + + public string Orderstatus { get; set; } = null!; + + public DateOnly Orderdeliverydate { get; set; } + + public int Orderpickuppoint { get; set; } + public decimal? OrderSumCost { get; set; } + + public string? ClientName { get; set; } + + public virtual PickupPoint OrderpickuppointNavigation { get; set; } = null!; + + public virtual ICollection Orderproducts { get; set; } = new List(); +} diff --git a/Data/RemoteData/Entity/Orderproduct.cs b/Data/RemoteData/Entity/Orderproduct.cs new file mode 100644 index 0000000..3aefeb6 --- /dev/null +++ b/Data/RemoteData/Entity/Orderproduct.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class Orderproduct +{ + public int Orderid { get; set; } + + public string Productarticlenumber { get; set; } = null!; + + public int? ProductCount { get; set; } + + public virtual Order Order { get; set; } = null!; + + public virtual Product ProductarticlenumberNavigation { get; set; } = null!; +} diff --git a/Data/RemoteData/Entity/PickupPoint.cs b/Data/RemoteData/Entity/PickupPoint.cs new file mode 100644 index 0000000..1c0469a --- /dev/null +++ b/Data/RemoteData/Entity/PickupPoint.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class PickupPoint +{ + public int PickupPointId { get; set; } + + public string? PickupPointName { get; set; } + + public virtual ICollection Orders { get; set; } = new List(); +} diff --git a/Data/RemoteData/Entity/Porductprovider.cs b/Data/RemoteData/Entity/Porductprovider.cs new file mode 100644 index 0000000..cb99036 --- /dev/null +++ b/Data/RemoteData/Entity/Porductprovider.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + + +public partial class Porductprovider +{ + public int PorductproviderId { get; set; } + + public string? PorductproviderName { get; set; } + + public virtual ICollection Products { get; set; } = new List(); +} diff --git a/Data/RemoteData/Entity/Product.cs b/Data/RemoteData/Entity/Product.cs new file mode 100644 index 0000000..3281096 --- /dev/null +++ b/Data/RemoteData/Entity/Product.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class Product +{ + public string Productarticlenumber { get; set; } = null!; + + public string? Productname { get; set; } + + public string? Productdescription { get; set; } + + public byte[]? Productphoto { get; set; } + + public decimal? Productcost { get; set; } + + public short? Productdiscountamount { get; set; } + + public int? Productquantityinstock { get; set; } + + public string? Imagename { get; set; } + + public int? UnitId { get; set; } + + public int? Productmaxdiscount { get; set; } + + public int? CategoryId { get; set; } + + public int? ManufacturerId { get; set; } + + public int? PorductproviderId { get; set; } + + public virtual Category? Category { get; set; } + + public virtual Manufacturer? Manufacturer { get; set; } + + public virtual ICollection Orderproducts { get; set; } = new List(); + + public virtual Porductprovider? Porductprovider { get; set; } + + public virtual Productunit? Unit { get; set; } +} diff --git a/Data/RemoteData/Entity/Productunit.cs b/Data/RemoteData/Entity/Productunit.cs new file mode 100644 index 0000000..2175a96 --- /dev/null +++ b/Data/RemoteData/Entity/Productunit.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class Productunit +{ + public int UnitId { get; set; } + + public string UnitName { get; set; } = null!; + + public virtual ICollection Products { get; set; } = new List(); +} diff --git a/Data/RemoteData/Entity/Role.cs b/Data/RemoteData/Entity/Role.cs new file mode 100644 index 0000000..a421c13 --- /dev/null +++ b/Data/RemoteData/Entity/Role.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class Role +{ + public int Roleid { get; set; } + + public string Rolename { get; set; } = null!; + + public virtual ICollection Users { get; set; } = new List(); +} diff --git a/Data/RemoteData/Entity/TradeContext.cs b/Data/RemoteData/Entity/TradeContext.cs new file mode 100644 index 0000000..ab4b5b3 --- /dev/null +++ b/Data/RemoteData/Entity/TradeContext.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class TradeContext : DbContext +{ + public TradeContext() + { + } + + public TradeContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet Categories { get; set; } + + public virtual DbSet Manufacturers { get; set; } + + public virtual DbSet Orders { get; set; } + + public virtual DbSet Orderproducts { get; set; } + + public virtual DbSet PickupPoints { get; set; } + + public virtual DbSet Porductproviders { get; set; } + + public virtual DbSet Products { get; set; } + + public virtual DbSet Productunits { get; set; } + + public virtual DbSet Roles { get; set; } + + public virtual DbSet Users { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) +#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263. + => optionsBuilder.UseNpgsql("Host=localhost;Username=postgres;Database=trade;Password=Student"); + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.CategoryId).HasName("category_pkey"); + + entity.ToTable("category"); + + entity.Property(e => e.CategoryId) + .UseIdentityAlwaysColumn() + .HasColumnName("category_id"); + entity.Property(e => e.CategoryName).HasColumnName("category_name"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.ManufacturerId).HasName("manufacturer_pkey"); + + entity.ToTable("manufacturer"); + + entity.Property(e => e.ManufacturerId) + .UseIdentityAlwaysColumn() + .HasColumnName("manufacturer_id"); + entity.Property(e => e.ManufacturerName).HasColumnName("manufacturer_name"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Orderid).HasName("Order_pkey"); + + entity.ToTable("Order"); + + entity.Property(e => e.Orderid) + .UseIdentityAlwaysColumn() + .HasColumnName("orderid"); + entity.Property(e => e.Orderdeliverydate).HasColumnName("orderdeliverydate"); + entity.Property(e => e.Orderpickuppoint).HasColumnName("orderpickuppoint"); + entity.Property(e => e.Orderstatus).HasColumnName("orderstatus"); + entity.Property(e => e.ClientName).HasColumnName("client_name"); + entity.Property(e => e.OrderSumCost).HasColumnName("order_sum_cost"); + + entity.HasOne(d => d.OrderpickuppointNavigation).WithMany(p => p.Orders) + .HasForeignKey(d => d.Orderpickuppoint) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("Order_orderpickuppoint_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => new { e.Orderid, e.Productarticlenumber }).HasName("orderproduct_pkey"); + + entity.ToTable("orderproduct"); + + entity.Property(e => e.Orderid).HasColumnName("orderid"); + entity.Property(e => e.Productarticlenumber).HasColumnName("productarticlenumber"); + entity.Property(e => e.ProductCount).HasColumnName("product_count"); + + entity.HasOne(d => d.Order).WithMany(p => p.Orderproducts) + .HasForeignKey(d => d.Orderid) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("orderproduct_orderid_fkey"); + + entity.HasOne(d => d.ProductarticlenumberNavigation).WithMany(p => p.Orderproducts) + .HasForeignKey(d => d.Productarticlenumber) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("orderproduct_productarticlenumber_fkey"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.PickupPointId).HasName("pickup_point_pkey"); + + entity.ToTable("pickup_point"); + + entity.Property(e => e.PickupPointId) + .UseIdentityAlwaysColumn() + .HasColumnName("pickup_point_id"); + entity.Property(e => e.PickupPointName).HasColumnName("pickup_point_name"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.PorductproviderId).HasName("porductprovider_pkey"); + + entity.ToTable("porductprovider"); + + entity.Property(e => e.PorductproviderId) + .UseIdentityAlwaysColumn() + .HasColumnName("porductprovider_id"); + entity.Property(e => e.PorductproviderName).HasColumnName("porductprovider_name"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Productarticlenumber).HasName("product_pkey1"); + + entity.ToTable("product"); + + entity.Property(e => e.Productarticlenumber).HasColumnName("productarticlenumber"); + entity.Property(e => e.CategoryId).HasColumnName("category_id"); + entity.Property(e => e.Imagename) + .HasMaxLength(50) + .HasColumnName("imagename"); + entity.Property(e => e.ManufacturerId).HasColumnName("manufacturer_id"); + entity.Property(e => e.PorductproviderId).HasColumnName("porductprovider_id"); + entity.Property(e => e.Productcost) + .HasPrecision(19, 4) + .HasColumnName("productcost"); + entity.Property(e => e.Productdescription).HasColumnName("productdescription"); + entity.Property(e => e.Productdiscountamount).HasColumnName("productdiscountamount"); + entity.Property(e => e.Productmaxdiscount).HasColumnName("productmaxdiscount"); + entity.Property(e => e.Productname).HasColumnName("productname"); + entity.Property(e => e.Productphoto).HasColumnName("productphoto"); + entity.Property(e => e.Productquantityinstock).HasColumnName("productquantityinstock"); + entity.Property(e => e.UnitId).HasColumnName("unit_id"); + + entity.HasOne(d => d.Category).WithMany(p => p.Products) + .HasForeignKey(d => d.CategoryId) + .HasConstraintName("product_category_id_fkey"); + + entity.HasOne(d => d.Manufacturer).WithMany(p => p.Products) + .HasForeignKey(d => d.ManufacturerId) + .HasConstraintName("product_manufacturer_id_fkey"); + + entity.HasOne(d => d.Porductprovider).WithMany(p => p.Products) + .HasForeignKey(d => d.PorductproviderId) + .HasConstraintName("product_porductprovider_id_fkey"); + + entity.HasOne(d => d.Unit).WithMany(p => p.Products) + .HasForeignKey(d => d.UnitId) + .HasConstraintName("product_unit_id_fkey1"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.UnitId).HasName("productunit_pkey"); + + entity.ToTable("productunit"); + + entity.Property(e => e.UnitId) + .UseIdentityAlwaysColumn() + .HasColumnName("unit_id"); + entity.Property(e => e.UnitName).HasColumnName("unit_name"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Roleid).HasName("Role_pkey"); + + entity.ToTable("Role"); + + entity.Property(e => e.Roleid) + .UseIdentityAlwaysColumn() + .HasColumnName("roleid"); + entity.Property(e => e.Rolename).HasColumnName("rolename"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Userid).HasName("User_pkey"); + + entity.ToTable("User"); + + entity.Property(e => e.Userid) + .UseIdentityAlwaysColumn() + .HasColumnName("userid"); + entity.Property(e => e.Userlogin).HasColumnName("userlogin"); + entity.Property(e => e.Username).HasColumnName("username"); + entity.Property(e => e.Userpassword).HasColumnName("userpassword"); + entity.Property(e => e.Userpatronymic).HasColumnName("userpatronymic"); + entity.Property(e => e.Userrole).HasColumnName("userrole"); + entity.Property(e => e.Usersurname).HasColumnName("usersurname"); + + entity.HasOne(d => d.UserroleNavigation).WithMany(p => p.Users) + .HasForeignKey(d => d.Userrole) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("User_userrole_fkey"); + }); + + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); +} diff --git a/Data/RemoteData/Entity/User.cs b/Data/RemoteData/Entity/User.cs new file mode 100644 index 0000000..3b2f12a --- /dev/null +++ b/Data/RemoteData/Entity/User.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; + +namespace demo_trade.Data.RemoteData.Entity; + +public partial class User +{ + public int Userid { get; set; } + + public string Usersurname { get; set; } = null!; + + public string Username { get; set; } = null!; + + public string Userpatronymic { get; set; } = null!; + + public string Userlogin { get; set; } = null!; + + public string Userpassword { get; set; } = null!; + + public int Userrole { get; set; } + + public virtual Role UserroleNavigation { get; set; } = null!; +} diff --git a/Data/Repository/ILoginRepository.cs b/Data/Repository/ILoginRepository.cs new file mode 100644 index 0000000..d77c700 --- /dev/null +++ b/Data/Repository/ILoginRepository.cs @@ -0,0 +1,14 @@ +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public interface ILoginRepository: IDisposable + { + User? GetUserByLogin(string login); + } +} diff --git a/Data/Repository/IOrderManagerRepository.cs b/Data/Repository/IOrderManagerRepository.cs new file mode 100644 index 0000000..2ba482c --- /dev/null +++ b/Data/Repository/IOrderManagerRepository.cs @@ -0,0 +1,18 @@ +using demo_trade.Data.RemoteData.Entity; +using demo_trade.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Order = demo_trade.Data.RemoteData.Entity.Order; + +namespace demo_trade.Data.Repository +{ + public interface IOrderManagerRepository: IDisposable + { + List GetAllOrders(); + bool EditRangeOrders(List orders); + + } +} diff --git a/Data/Repository/IOrderRepository.cs b/Data/Repository/IOrderRepository.cs new file mode 100644 index 0000000..fb051e0 --- /dev/null +++ b/Data/Repository/IOrderRepository.cs @@ -0,0 +1,16 @@ +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public interface IOrderRepository + { + List GetAllOrders(); + int GetNumberForNewOrder(); + Order CreateOrder(Order order, List orderproducts); + } +} diff --git a/Data/Repository/IPickupRepositorycs.cs b/Data/Repository/IPickupRepositorycs.cs new file mode 100644 index 0000000..33ce453 --- /dev/null +++ b/Data/Repository/IPickupRepositorycs.cs @@ -0,0 +1,15 @@ +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public interface IPickupRepository + { + List GetAllPickupPoints(); + } +} diff --git a/Data/Repository/IProductRepository.cs b/Data/Repository/IProductRepository.cs new file mode 100644 index 0000000..bf60eca --- /dev/null +++ b/Data/Repository/IProductRepository.cs @@ -0,0 +1,18 @@ +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public interface IProductRepository : IDisposable + { + List GetProducts(); + Boolean RemoveProductByArticleNumber(string articleNumber); + Product? UpdateProductByArticleNumber(Product product); + Product? GetProductByArticleNumber(string articleNumber); + void Save(); + } +} diff --git a/Data/Repository/SQLLoginRepository.cs b/Data/Repository/SQLLoginRepository.cs new file mode 100644 index 0000000..7289479 --- /dev/null +++ b/Data/Repository/SQLLoginRepository.cs @@ -0,0 +1,27 @@ +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public class SQLLoginRepository : ILoginRepository + { + private TradeContext _tradeContext; + public SQLLoginRepository() { + _tradeContext = new TradeContext(); + } + public void Dispose() + { + Dispose(); + GC.SuppressFinalize(this); + } + + public User? GetUserByLogin(string login) + { + return _tradeContext.Users.Where(user => user.Userlogin == login).FirstOrDefault(); + } + } +} diff --git a/Data/Repository/SQLOrderClientRepository.cs b/Data/Repository/SQLOrderClientRepository.cs new file mode 100644 index 0000000..b53832f --- /dev/null +++ b/Data/Repository/SQLOrderClientRepository.cs @@ -0,0 +1,51 @@ +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public class SQLOrderClientRepository : IOrderRepository, IDisposable + { + private TradeContext _tradeContext; + public SQLOrderClientRepository() { + + _tradeContext = new TradeContext(); + } + public Order CreateOrder(Order order, List orderproducts) + { + using var transaction = _tradeContext.Database.BeginTransaction(); + try { + var createdOrder = _tradeContext.Add(order); + _tradeContext.SaveChanges(); + foreach (var product in orderproducts) { + _tradeContext.Add(new Orderproduct { Orderid = order.Orderid, Productarticlenumber = product.Productarticlenumber, ProductCount = product.ProductCount }); + } + _tradeContext.SaveChanges(); + transaction.Commit(); + } + catch (Exception ex) { + + } + + return order; + } + + public void Dispose() + { + GC.SuppressFinalize(this); + } + + public List GetAllOrders() + { + throw new NotImplementedException(); + } + + public int GetNumberForNewOrder() + { + return _tradeContext.Orders.Max(it => it.Orderid) + 1; + } + } +} diff --git a/Data/Repository/SQLOrderManagerRepository.cs b/Data/Repository/SQLOrderManagerRepository.cs new file mode 100644 index 0000000..3f84cee --- /dev/null +++ b/Data/Repository/SQLOrderManagerRepository.cs @@ -0,0 +1,52 @@ +using demo_trade.Data.RemoteData.Entity; +using demo_trade.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Order = demo_trade.Data.RemoteData.Entity.Order; + +namespace demo_trade.Data.Repository +{ + public class SQLOrderManagerRepository : IOrderManagerRepository + { + private TradeContext _tradeContext; + + public void Dispose() + { + GC.SuppressFinalize(this); + } + + public SQLOrderManagerRepository() { + _tradeContext = new TradeContext(); + } + public bool EditRangeOrders(List orders) + { + using var transaction = _tradeContext.Database.BeginTransaction(); + try + { + foreach (var item in orders) + { + var order = _tradeContext.Orders.Find(item.OrderId); + if (item.OrderStatus == null) continue; + if (order.Orderstatus != item.OrderStatus) order.Orderstatus = item.OrderStatus; + if (item.OrderDeliveryDate == null) continue; + if (order.Orderdeliverydate != item.OrderDeliveryDate) order.Orderdeliverydate = item.OrderDeliveryDate.Value; + _tradeContext.SaveChanges(); + } + transaction.Commit(); + return true; + } + catch (Exception ex) { + return false; + } + } + + public List GetAllOrders() + { + return _tradeContext.Orders.Include(it => it.Orderproducts).ThenInclude(it => it.ProductarticlenumberNavigation).Include(it => it.OrderpickuppointNavigation).ToList(); + } + } +} diff --git a/Data/Repository/SQLPickupRepository.cs b/Data/Repository/SQLPickupRepository.cs new file mode 100644 index 0000000..c45d7e0 --- /dev/null +++ b/Data/Repository/SQLPickupRepository.cs @@ -0,0 +1,22 @@ +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public class SQLPickupRepository : IPickupRepository + { + private TradeContext _tradeContext; + public SQLPickupRepository() { + + _tradeContext = new TradeContext(); + } + public List GetAllPickupPoints() + { + return _tradeContext.PickupPoints.ToList(); + } + } +} diff --git a/Data/Repository/SQLProductRepository.cs b/Data/Repository/SQLProductRepository.cs new file mode 100644 index 0000000..064631a --- /dev/null +++ b/Data/Repository/SQLProductRepository.cs @@ -0,0 +1,56 @@ +using demo_trade.Data.RemoteData.Entity; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Data.Repository +{ + public class SQLProductRepository : IProductRepository + { + private TradeContext _tradeContext; + + public SQLProductRepository() { + _tradeContext = new TradeContext(); + } + public void Dispose() + { + GC.SuppressFinalize(this); + } + + public Product? GetProductByArticleNumber(string articleNumber) + { + return _tradeContext.Products.Where(it => articleNumber == it.Productarticlenumber).FirstOrDefault(); + } + + public List GetProducts() + { + + return _tradeContext.Products.Include(manfucture => manfucture.Manufacturer).Select(it => it).ToList(); + } + + public bool RemoveProductByArticleNumber(string articleNumber) + { + Product? product = GetProductByArticleNumber(articleNumber); + if (product != null) + { + _tradeContext.Products.Remove(product); + return true; + } + return false; + } + + public void Save() + { + _tradeContext.SaveChanges(); + } + + public Product? UpdateProductByArticleNumber(Product product) + { + _tradeContext.Entry(product).State = EntityState.Modified; + return product; + } + } +} diff --git a/Domain/GuestProductUseCase.cs b/Domain/GuestProductUseCase.cs new file mode 100644 index 0000000..123afa2 --- /dev/null +++ b/Domain/GuestProductUseCase.cs @@ -0,0 +1,41 @@ +using demo_trade.Data.Repository; +using demo_trade.Models; +using demo_trade.UI.Presenters; +using demo_trade.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Domain +{ + public class GuestProductUseCase + { + private IProductRepository _productRepository; + + public GuestProductUseCase(IProductRepository productRepository) { + + _productRepository = productRepository; + } + + public List GetProducts() => _productRepository + .GetProducts() + .Select(it => new ProductPresenter + { + ArticleNumber = it.Productarticlenumber, + Description = it.Productdescription, + Name = it.Productname, + DiscountAmount = it.Productdiscountamount, + Cost = it.Productcost == null ? 0 : Convert.ToDecimal(it.Productcost), + ProductMaxDiscount = it.Productmaxdiscount, + QuantityInStock = it.Productquantityinstock, + Manufacturer = new Manufacturer { Id = it.Manufacturer.ManufacturerId, Name = it.Manufacturer.ManufacturerName }, + Image = !String.IsNullOrEmpty(it.Imagename) ? + ImageHelper.BASE_URL + "/" + it.Imagename + : ImageHelper.BASE_URL + "/" + "default.png" + , + }).ToList(); + + } +} diff --git a/Domain/LoginUseCase.cs b/Domain/LoginUseCase.cs new file mode 100644 index 0000000..6851822 --- /dev/null +++ b/Domain/LoginUseCase.cs @@ -0,0 +1,29 @@ +using demo_trade.Data.RemoteData.Entity; +using demo_trade.Data.Repository; +using demo_trade.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Authentication; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Domain +{ + public class LoginUseCase + { + private ILoginRepository _loginRepository; + public LoginUseCase(ILoginRepository loginRepository) { + _loginRepository = loginRepository; + } + + public User AutorizationByLoginAndPassword(UserLogin userLogin) + { + User? user = _loginRepository.GetUserByLogin(userLogin.Login); + if (user == null) throw new AuthenticationException("Пользователь не найден"); + if (user.Userpassword != userLogin.Password) throw new AuthenticationException("Пароли не совпадают"); + return user; + + } + } +} diff --git a/Domain/OrderClientUseCase.cs b/Domain/OrderClientUseCase.cs new file mode 100644 index 0000000..821d930 --- /dev/null +++ b/Domain/OrderClientUseCase.cs @@ -0,0 +1,40 @@ +using demo_trade.Data.RemoteData.Entity; +using demo_trade.Data.Repository; +using demo_trade.UI.Presenters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Domain +{ + public class OrderClientUseCase + { + private IOrderRepository _orderRepository; + private IPickupRepository _pickupRepository; + public OrderClientUseCase(IOrderRepository orderRepository, IPickupRepository pickupRepository) { + _orderRepository = orderRepository; + _pickupRepository = pickupRepository; + } + + public List GetPickupPoints() => _pickupRepository.GetAllPickupPoints(); + public int GetNewOrderNumber() => _orderRepository.GetNumberForNewOrder(); + + public Models.Order? GenerateNewOrder(PickupPoint orderPickupPoint, List products,decimal orderSumCost, string? clientName = null) { + int daysOrderCount = CheckProductsQuntity(products) ? 3 : 6; + Order order = new Order { Orderdeliverydate = DateOnly.FromDateTime(DateTime.Now.AddDays(daysOrderCount)), Orderpickuppoint = orderPickupPoint.PickupPointId, Orderstatus = "Новый", ClientName= clientName, OrderSumCost=orderSumCost}; + List orderproducts = products.Select(it => new Orderproduct { Productarticlenumber = it.ArticleNumber, ProductCount = it.ProductCount }).ToList(); + var resultOrder = _orderRepository.CreateOrder(order, orderproducts); + if (resultOrder != null) return new demo_trade.Models.Order { Orderid = resultOrder.Orderid, Orderdeliverydate = resultOrder.Orderdeliverydate, PickupPointName = orderPickupPoint.PickupPointName, Orderstatus = resultOrder.Orderstatus, ProductList =products, OrderClient=clientName, OrderSumCost=orderSumCost }; + return null; + } + private bool CheckProductsQuntity(List orderProducts) { + + foreach (var product in orderProducts) { + if (product.QuantityInStock <= 3) return false; + } + return true; + } + } +} diff --git a/Domain/OrderManagerUseCase.cs b/Domain/OrderManagerUseCase.cs new file mode 100644 index 0000000..d8b5b61 --- /dev/null +++ b/Domain/OrderManagerUseCase.cs @@ -0,0 +1,44 @@ +using demo_trade.Data.Repository; +using demo_trade.Models; +using demo_trade.UI.Presenters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Domain +{ + public class OrderManagerUseCase + { + private IOrderManagerRepository _orderRepository; + + public OrderManagerUseCase(IOrderManagerRepository orderRepository) { + _orderRepository = orderRepository; + } + + public void ChangeOrders(List orderChangeds) { + _orderRepository.EditRangeOrders(orderChangeds); + } + + public List GetOrders() + { + return _orderRepository.GetAllOrders().Select(it => new OrderManager { + OrderClient = it.ClientName, + Orderdeliverydate = it.Orderdeliverydate, + Orderid = it.Orderid, + Orderstatus = it.Orderstatus, + PickupPointName = it.OrderpickuppointNavigation.PickupPointName, + ProductList = String.Join("\n", it.Orderproducts.Select(product => String.Format("Article: {0} Count: {1} Stock: {2}", + product.Productarticlenumber, + product.ProductCount, + product.ProductarticlenumberNavigation.Productquantityinstock + )).ToList()), + OrderSumCost = it.OrderSumCost, + ProductStock = it.Orderproducts.Select(it => it.ProductarticlenumberNavigation).ToList() + }).ToList(); + + } + + } +} diff --git a/Exceptions/AutorizeException.cs b/Exceptions/AutorizeException.cs new file mode 100644 index 0000000..4b67387 --- /dev/null +++ b/Exceptions/AutorizeException.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Exceptions +{ + class AutorizeException : Exception + { + public AutorizeException(string message) : base(message) { } + } +} diff --git a/Models/Manufacturer.cs b/Models/Manufacturer.cs new file mode 100644 index 0000000..179a47c --- /dev/null +++ b/Models/Manufacturer.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Models +{ + public class Manufacturer + { + public int Id { get; set; } + + public string Name { get; set; } + } +} diff --git a/Models/Order.cs b/Models/Order.cs new file mode 100644 index 0000000..3574107 --- /dev/null +++ b/Models/Order.cs @@ -0,0 +1,25 @@ +using demo_trade.UI.Presenters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Models +{ + public class Order + { + public int Orderid { get; set; } + + public string Orderstatus { get; set; } + + public string? OrderClient { get; set; } = null; + + public DateOnly Orderdeliverydate { get; set; } + + public string PickupPointName { get; set; } + public decimal OrderSumCost { get; set; } + + public List ProductList{ get; set; } + } +} diff --git a/Models/OrderChanged.cs b/Models/OrderChanged.cs new file mode 100644 index 0000000..75a376f --- /dev/null +++ b/Models/OrderChanged.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Models +{ + public class OrderChanged + { + public int OrderId { get; set; } + public string? OrderStatus { get; set; } + public DateOnly? OrderDeliveryDate { get; set; } + } +} diff --git a/Models/OrderManager.cs b/Models/OrderManager.cs new file mode 100644 index 0000000..25013a7 --- /dev/null +++ b/Models/OrderManager.cs @@ -0,0 +1,26 @@ +using demo_trade.UI.Presenters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Models +{ + public class OrderManager + { + public int Orderid { get; set; } + + public string Orderstatus { get; set; } + + public string? OrderClient { get; set; } = null; + + public DateOnly Orderdeliverydate { get; set; } + + public string PickupPointName { get; set; } + public decimal? OrderSumCost { get; set; } + + public string ProductList { get; set; } + public List ProductStock { get; set; } + } +} diff --git a/Models/Product.cs b/Models/Product.cs new file mode 100644 index 0000000..5bac7b0 --- /dev/null +++ b/Models/Product.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Models +{ + public class Product + { + public string ArticleNumber { get; set; } + public string Name { get; set; } + + public string Description { get; set; } + public decimal Cost { get; set; } + + public short? DiscountAmount { get; set; } + + public int? QuantityInStock { get; set; } + + public int? ProductMaxDiscount { get; set; } + + public Manufacturer Manufacturer { get; set; } + } +} diff --git a/Models/Ticket.cs b/Models/Ticket.cs new file mode 100644 index 0000000..3b39c39 --- /dev/null +++ b/Models/Ticket.cs @@ -0,0 +1,54 @@ +using demo_trade.UI.Presenters; +using iText.IO.Font.Constants; +using iText.Kernel.Font; +using iTextSharp.text; +using iTextSharp.text.pdf; +using Microsoft.EntityFrameworkCore.Metadata.Internal; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using PdfFont = iText.Kernel.Font.PdfFont; + +namespace demo_trade.Models +{ + public class Ticket + { + public int OrderID { get; set; } + public string PickupPointName{ get; set; } + public decimal OrderSumCost{ get; set; } + public string? ClientName { get; set; } = null; + public DateOnly OrderDate { get; set; } + public DateOnly OrderDelivery { get; set; } + + public List Products { get; set; } + + public int OrderCode { get; set; } + + public void GeneratePDF(string path) { + using var document = new Document(); + PdfWriter.GetInstance(document, new FileStream(path, FileMode.OpenOrCreate)); + document.Open(); + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + BaseFont baseFont = BaseFont.CreateFont("C:\\Windows\\Fonts\\arial.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); + + Font font = new Font(baseFont, iTextSharp.text.Font.DEFAULTSIZE, iTextSharp.text.Font.NORMAL); + Font fontCode = new Font(baseFont, iTextSharp.text.Font.DEFAULTSIZE, iTextSharp.text.Font.BOLD); + + Paragraph paragraph = new Paragraph(String.Format("Order №{0} Create {1} Data delivery {2}\nПункт выдачи: {3}\nСумма заказа: {4}", OrderID, OrderDate, OrderDelivery, PickupPointName, OrderSumCost), font); + if (ClientName != null) paragraph.Add(String.Format("\nClient name: {0}", ClientName)); + document.Add(paragraph); + foreach (OrderProductPresenter presenter in Products) { + + document.Add(new Phrase(String.Format("Article: {0}, Name: {2}, Count: {1}\n", presenter.ArticleNumber, presenter.ProductCount, presenter.Name), font)); + } + GenerateCode(); + document.Add(new Paragraph(String.Format("Code: {0}", OrderCode), fontCode)); + document.Close(); + } + + private void GenerateCode() { + OrderCode = new Random().Next(100, 999); + } + } +} diff --git a/Models/UserLogin.cs b/Models/UserLogin.cs new file mode 100644 index 0000000..bcef779 --- /dev/null +++ b/Models/UserLogin.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Models +{ + public class UserLogin + { + public string Login { get; set; } + public string Password { get; set; } + + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..05f9099 --- /dev/null +++ b/Program.cs @@ -0,0 +1,21 @@ +using Avalonia; +using Avalonia.ReactiveUI; +using System; + +namespace demo_trade +{ + internal sealed class Program + { + + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UseReactiveUI() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace(); + } +} diff --git a/UI/Converters/ItemColorConverter.cs b/UI/Converters/ItemColorConverter.cs new file mode 100644 index 0000000..d48f463 --- /dev/null +++ b/UI/Converters/ItemColorConverter.cs @@ -0,0 +1,27 @@ +using Avalonia.Data.Converters; +using Avalonia.Media; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.UI.Converters +{ + + public class ItemEnableConverterByDate : IValueConverter + { + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + + DateOnly date = (DateOnly)value; + return date >= DateOnly.FromDateTime(DateTime.Now); + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } + } +} diff --git a/UI/Converters/ItemColorOrderConverter.cs b/UI/Converters/ItemColorOrderConverter.cs new file mode 100644 index 0000000..5398694 --- /dev/null +++ b/UI/Converters/ItemColorOrderConverter.cs @@ -0,0 +1,28 @@ +using Avalonia.Data.Converters; +using Avalonia.Media; +using demo_trade.Data.RemoteData.Entity; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.UI.Converters +{ + + public class ItemColorOrderConverter : IValueConverter + { + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + + var products = (List)value; + return products.Where(it => it.Productquantityinstock < 3).ToList().Count > 0 ? new SolidColorBrush(Colors.Yellow) : new SolidColorBrush(Colors.White); + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } + } +} diff --git a/UI/Converters/ItemComboboxConverter.cs b/UI/Converters/ItemComboboxConverter.cs new file mode 100644 index 0000000..a5b3a79 --- /dev/null +++ b/UI/Converters/ItemComboboxConverter.cs @@ -0,0 +1,30 @@ +using Avalonia.Data.Converters; +using Avalonia.Media; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.UI.Converters +{ + + public class ItemComboboxConverter : IValueConverter + { + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + + string status = (string)value; + + return status == "Новый" ? 0: 1; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + int status = (int)value; + + return status != 0 ? "Завершен" : "Новый"; + } + } +} diff --git a/UI/Converters/ItemDateConverter.cs b/UI/Converters/ItemDateConverter.cs new file mode 100644 index 0000000..80bf459 --- /dev/null +++ b/UI/Converters/ItemDateConverter.cs @@ -0,0 +1,30 @@ +using Avalonia.Data.Converters; +using Avalonia.Media; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tmds.DBus.Protocol; + +namespace demo_trade.UI.Converters +{ + + public class ItemDateConverter : IValueConverter + { + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + + var date = (DateOnly)value; + return new DateTimeOffset(new DateTime(date.Year, date.Month, date.Day)); + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + var date = (DateTimeOffset)value; + + return new DateOnly(date.Year, date.Month, date.Day); + } + } +} diff --git a/UI/Converters/ItemEnableConverterByDate.cs b/UI/Converters/ItemEnableConverterByDate.cs new file mode 100644 index 0000000..19fb90e --- /dev/null +++ b/UI/Converters/ItemEnableConverterByDate.cs @@ -0,0 +1,26 @@ +using Avalonia.Data.Converters; +using Avalonia.Media; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.UI.Converters +{ + + public class ItemColorConverter : IValueConverter + { + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + + return (short?)value > 15? new SolidColorBrush(Colors.Yellow) : new SolidColorBrush(Colors.White); + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotSupportedException(); + } + } +} diff --git a/UI/Presenters/OrderProductPresenter.cs b/UI/Presenters/OrderProductPresenter.cs new file mode 100644 index 0000000..a1a2cdf --- /dev/null +++ b/UI/Presenters/OrderProductPresenter.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.UI.Presenters +{ + public class OrderProductPresenter: ProductPresenter + { + public int ProductCount { get; set; } + + public OrderProductPresenter(ProductPresenter productPresenter, int count) { + this.ArticleNumber = productPresenter.ArticleNumber; + this.ProductCount = count; + this.ProductMaxDiscount = productPresenter.ProductMaxDiscount; + this.QuantityInStock = productPresenter.QuantityInStock; + this.Manufacturer = productPresenter.Manufacturer; + this.Description = productPresenter.Description; + this.Name = productPresenter.Name; + this.Cost = productPresenter.Cost; + this.DiscountAmount = productPresenter.DiscountAmount; + this.Image = productPresenter.Image; + + } + } +} diff --git a/UI/Presenters/ProductPresenter.cs b/UI/Presenters/ProductPresenter.cs new file mode 100644 index 0000000..14b8374 --- /dev/null +++ b/UI/Presenters/ProductPresenter.cs @@ -0,0 +1,36 @@ +using Avalonia.Media; +using Avalonia.Media.Imaging; +using demo_trade.Models; +using System.Threading.Tasks; + + +namespace demo_trade.UI.Presenters +{ + public class ProductPresenter + { + public string ArticleNumber { get; set; } + public string Name { get; set; } + + public string Description { get; set; } + public decimal Cost { get; set; } + + public short? DiscountAmount { get; set; } + + public int? QuantityInStock { get; set; } + + public string Image { get; set; } + public int? ProductMaxDiscount { get; set; } + + + public decimal? CostWithDiscount { get => Cost - (Cost * DiscountAmount / 100); } + + public Manufacturer Manufacturer { get; set; } + + public SolidColorBrush ColorBackgroundItem { get => DiscountAmount < 15 ? + new SolidColorBrush(Color.FromRgb(255, 255, 255)) + : + new SolidColorBrush(Color.FromRgb(255, 245, 0)); + } + + } +} diff --git a/UI/Themes/Colors.cs b/UI/Themes/Colors.cs new file mode 100644 index 0000000..7e25e0f --- /dev/null +++ b/UI/Themes/Colors.cs @@ -0,0 +1,15 @@ +using Avalonia.Media; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.UI.Themes +{ + public static class Colors + { + public static Color White = new Color(255, 255, 255, 255); + public static Color Green = new Color(255, 255, 245, 0); + } +} diff --git a/Utils/ImageHelper.cs b/Utils/ImageHelper.cs new file mode 100644 index 0000000..594181b --- /dev/null +++ b/Utils/ImageHelper.cs @@ -0,0 +1,37 @@ +using Avalonia.Media.Imaging; +using SkiaSharp; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.Utils +{ + public static class ImageHelper + { + public static string BASE_URL = "http://localhost:5025/images"; + public static async Task LoadFromRemoteByName(string imageName) + { + if (String.IsNullOrWhiteSpace(imageName)) imageName = "default.png"; + using var httpClient = new HttpClient(); + try + { + + var response = await httpClient.GetAsync(BASE_URL + "/" + imageName); + var data = await response.Content.ReadAsByteArrayAsync(); + var bimap = new Bitmap(new MemoryStream(data)); + bimap.Save(imageName); + return new Bitmap(new MemoryStream(data)); + } + catch (Exception ex) + { + return null; + } + } + + } +} diff --git a/ViewLocator.cs b/ViewLocator.cs new file mode 100644 index 0000000..05a96c9 --- /dev/null +++ b/ViewLocator.cs @@ -0,0 +1,23 @@ +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using demo_trade.ViewModels; +using ReactiveUI; +using System; + +namespace demo_trade +{ + public class ViewLocator : ReactiveUI.IViewLocator + { + public IViewFor? ResolveView(T? viewModel, string? contract = null) => viewModel switch + { + LoginViewModel context => new LoginControl { DataContext = context }, + GuestProductViewModel context => new GuestProductControl { DataContext = context }, + ClientProductViewModel context => new ClientProductControl{ DataContext = context }, + OrderShowDialogViewModel context => new OrderShowDialog{ DataContext = context}, + OrderManagerViewModel context => new OrderManagerControl { DataContext = context }, + _ => throw new ArgumentOutOfRangeException(nameof(viewModel)) + + }; + + } +} diff --git a/ViewModels/ClientProductViewModel.cs b/ViewModels/ClientProductViewModel.cs new file mode 100644 index 0000000..7a6d050 --- /dev/null +++ b/ViewModels/ClientProductViewModel.cs @@ -0,0 +1,179 @@ +using Avalonia.Markup.Xaml.Templates; +using demo_trade.Data.RemoteData.Entity; +using demo_trade.Data.Repository; +using demo_trade.Domain; +using demo_trade.Models; +using demo_trade.UI.Presenters; +using ReactiveUI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; +using System.Text; +using System.Threading.Tasks; +using Tmds.DBus.Protocol; + +namespace demo_trade.ViewModels +{ + public class ClientProductViewModel : ViewModelBase, IRoutableViewModel + { + private GuestProductUseCase _guestProductUseCase; + public string? UrlPathSegment => Guid.NewGuid().ToString(); + + private User _user = new(); + + private bool _isManager = false; + public bool IsManager { get => _isManager; set => this.RaiseAndSetIfChanged(ref _isManager, value); } + + private Dictionary _productOrder = new(); + public Dictionary ProductOrder + { + get => _productOrder; + set => this.RaiseAndSetIfChanged(ref _productOrder, value); + } + public User AutorizedUser { + get => _user; + set => this.RaiseAndSetIfChanged(ref _user, value); + } + + private List _productOrderList = new(); + public List ProductOrderList + { + get => _productOrderList; + set => this.RaiseAndSetIfChanged(ref _productOrderList, value); + } + + private bool _thereItemsInOrder = false; + public bool ThereItemsInOrder + { + get => _thereItemsInOrder; + set => this.RaiseAndSetIfChanged(ref _thereItemsInOrder, value); + } + + private Dictionary _filterValues = new Dictionary() { + {0, (0, null)}, + {1, (0, 10)}, + {2, (10, 15)}, + {3, (15, null)} + }; + public ReactiveCommand AddToOrderCommand { get; } + public ReactiveCommand AttachToOrderCommand { get; } + public ReactiveCommand AttachToOrderManagerCommand { get; } + + + private int _selectedFilterValue = 0; + private int _selectedSortValue = 0; + public int SelectedFilterValue + { + get => _selectedFilterValue; + set => this.RaiseAndSetIfChanged(ref _selectedFilterValue, value); + } + public int SelectedSortValue + { + get => _selectedSortValue; + set => this.RaiseAndSetIfChanged(ref _selectedSortValue, value); + } + + private string _searchWord = string.Empty; + public string SearchWord + { + + get => _searchWord; + set => this.RaiseAndSetIfChanged(ref _searchWord, value); + } + + private string _statisticText = string.Empty; + public string StatisticText + { + + get => _statisticText; + set => this.RaiseAndSetIfChanged(ref _statisticText, value); + } + + private List _dataSource = new(); + private List _products = new(); + public List Products + { + get => _products; + set => this.RaiseAndSetIfChanged(ref _products, value); + } + + public IScreen HostScreen { get; } + + + + public ClientProductViewModel(IScreen home, IProductRepository productRepository, User user) + { + AutorizedUser = user; + HostScreen = home; + if (AutorizedUser.Userrole == 1 || AutorizedUser.Userrole == 3) IsManager = true; + _guestProductUseCase = new GuestProductUseCase(productRepository); + _dataSource = _guestProductUseCase.GetProducts(); + this.WhenAnyValue(search => search.SearchWord).Subscribe(_ => { DisplayList(); }); + this.WhenAnyValue(selectedFilter => selectedFilter.SelectedFilterValue).Subscribe(_ => { DisplayList(); }); + this.WhenAnyValue(selectedSort => selectedSort.SelectedSortValue).Subscribe(_ => { DisplayList(); }); + DisplayList(); + AddToOrderCommand = ReactiveCommand.Create(product => { + if (ProductOrder.ContainsKey(product.ArticleNumber)) + { + var values = ProductOrder[product.ArticleNumber]; + ProductOrder[product.ArticleNumber] = (product, values.Item2 + 1); + } + else + { + ProductOrder.Add(product.ArticleNumber, (product, 1)); + } + ThereItemsInOrder = ProductOrder.Keys.Count > 0; + }); + + AttachToOrderManagerCommand = ReactiveCommand.Create( + () => + { + var orderManagerUseCase = new OrderManagerUseCase(new SQLOrderManagerRepository()); + HostScreen.Router.Navigate.Execute(new OrderManagerViewModel(HostScreen, orderManagerUseCase)); + } + ); + ShowDialog = new Interaction(); + AttachToOrderCommand = ReactiveCommand.CreateFromTask(async () => + { + var userOrderCase = new OrderClientUseCase(new SQLOrderClientRepository(), new SQLPickupRepository()); + var order = new OrderShowDialogViewModel(ProductOrder, userOrderCase, user); + var result = await ShowDialog.Handle(order); + } + ); + + } + public Interaction ShowDialog { get; } + + private bool FilterByDiscount(short? discount) + { + if (discount == null) return false; + (int leftBound, int? rightBound) = _filterValues[SelectedFilterValue]; + if (rightBound == null) return leftBound <= discount; + return leftBound <= discount && discount < rightBound; + } + private void DisplayList() + { + var temp = _dataSource; + if (SelectedFilterValue > 0) + { + temp = temp.Where(it => FilterByDiscount(it.DiscountAmount)).ToList(); + } + if (!String.IsNullOrEmpty(SearchWord)) + { + temp = temp.Where(it => it.Name.Contains(SearchWord, StringComparison.CurrentCultureIgnoreCase)).ToList(); + } + if (SelectedSortValue == 1) + { + temp = temp.OrderByDescending(it => it.Cost).ToList(); + } + else if (SelectedSortValue == 2) + { + temp = temp.OrderBy(it => it.Cost).ToList(); + } + this.Products = temp; + StatisticText = String.Format("{0} из {1}", temp.Count, _dataSource.Count); + } + } +} diff --git a/ViewModels/GuestProductViewModel.cs b/ViewModels/GuestProductViewModel.cs new file mode 100644 index 0000000..b71db2b --- /dev/null +++ b/ViewModels/GuestProductViewModel.cs @@ -0,0 +1,142 @@ +using Avalonia.Markup.Xaml.Templates; +using demo_trade.Data.Repository; +using demo_trade.Domain; +using demo_trade.Models; +using demo_trade.UI.Presenters; +using ReactiveUI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.ViewModels +{ + public class GuestProductViewModel : ViewModelBase, IRoutableViewModel + { + private GuestProductUseCase _guestProductUseCase; + + private Dictionary _productOrder = new(); + public Dictionary ProductOrder + { + get => _productOrder; + set => this.RaiseAndSetIfChanged(ref _productOrder, value); + } + + private bool _thereItemsInOrder = false; + public bool ThereItemsInOrder { + get => _thereItemsInOrder; + set => this.RaiseAndSetIfChanged(ref _thereItemsInOrder, value); + } + + public string? UrlPathSegment => Guid.NewGuid().ToString(); + + private Dictionary _filterValues = new Dictionary() { + {0, (0, null)}, + {1, (0, 10)}, + {2, (10, 15)}, + {3, (15, null)} + }; + public ReactiveCommand AddToOrderCommand { get; } + public ReactiveCommand AttachToOrderCommand { get; } + + + private int _selectedFilterValue = 0; + private int _selectedSortValue = 0; + public int SelectedFilterValue { + get => _selectedFilterValue; + set => this.RaiseAndSetIfChanged(ref _selectedFilterValue, value); + } + public int SelectedSortValue + { + get => _selectedSortValue; + set => this.RaiseAndSetIfChanged(ref _selectedSortValue, value); + } + + private string _searchWord = string.Empty; + public string SearchWord { + + get => _searchWord; + set => this.RaiseAndSetIfChanged(ref _searchWord, value); + } + + private string _statisticText = string.Empty; + public string StatisticText + { + + get => _statisticText; + set => this.RaiseAndSetIfChanged(ref _statisticText, value); + } + + private List _dataSource = new(); + private List _products = new(); + public List Products { + get => _products; + set => this.RaiseAndSetIfChanged(ref _products, value); + } + + public IScreen HostScreen { get; } + + + + public GuestProductViewModel(IScreen home, IProductRepository productRepository) { + HostScreen = home; + _guestProductUseCase = new GuestProductUseCase(productRepository); + _dataSource = _guestProductUseCase.GetProducts(); + this.WhenAnyValue(search => search.SearchWord).Subscribe(_ => { DisplayList(); }); + this.WhenAnyValue(selectedFilter => selectedFilter.SelectedFilterValue).Subscribe(_ => { DisplayList(); }); + this.WhenAnyValue(selectedSort => selectedSort.SelectedSortValue).Subscribe(_ => { DisplayList(); }); + DisplayList(); + AddToOrderCommand = ReactiveCommand.Create(product => { + if (ProductOrder.ContainsKey(product.ArticleNumber)) + { + var values = ProductOrder[product.ArticleNumber]; + ProductOrder[product.ArticleNumber] = (product, values.Item2 + 1); + } + else { + ProductOrder.Add(product.ArticleNumber, (product, 1)); + } + ThereItemsInOrder = ProductOrder.Keys.Count > 0; + + }); + ShowDialog = new Interaction(); + AttachToOrderCommand = ReactiveCommand.CreateFromTask(async() => + { + var userOrderCase = new OrderClientUseCase(new SQLOrderClientRepository(), new SQLPickupRepository()); + var order = new OrderShowDialogViewModel(ProductOrder, userOrderCase); + var result = await ShowDialog.Handle(order); + } + ); + + } + private bool FilterByDiscount(short? discount) { + if (discount == null) return false; + (int leftBound, int? rightBound) = _filterValues[SelectedFilterValue]; + if (rightBound == null) return leftBound <= discount; + return leftBound <= discount && discount < rightBound; + } + private void DisplayList() { + var temp = _dataSource; + if (SelectedFilterValue > 0) { + temp = temp.Where(it => FilterByDiscount(it.DiscountAmount)).ToList(); + } + if (!String.IsNullOrEmpty(SearchWord)) { + temp = temp.Where(it => it.Name.Contains(SearchWord, StringComparison.CurrentCultureIgnoreCase)).ToList(); + } + if (SelectedSortValue == 1) + { + temp = temp.OrderByDescending(it => it.Cost).ToList(); + } + else if (SelectedSortValue == 2) { + temp = temp.OrderBy(it => it.Cost).ToList(); + } + this.Products = temp; + StatisticText = String.Format("{0} из {1}", temp.Count, _dataSource.Count); + } + + public Interaction ShowDialog { get; } + + } +} diff --git a/ViewModels/LoginViewModel.cs b/ViewModels/LoginViewModel.cs new file mode 100644 index 0000000..a9c2164 --- /dev/null +++ b/ViewModels/LoginViewModel.cs @@ -0,0 +1,63 @@ +using demo_trade.Data.Repository; +using demo_trade.Domain; +using demo_trade.Models; +using ReactiveUI; +using System; +using System.Reactive; +using System.Reactive.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.ViewModels +{ + public class LoginViewModel: ViewModelBase, IRoutableViewModel + { + + + private LoginUseCase _loginUseCase; + + private string _errorMessage = string.Empty; + public string ErrorMessage { get => _errorMessage; set => this.RaiseAndSetIfChanged(ref _errorMessage, value); } + private UserLogin _userLogin = new(); + + public UserLogin UserLogin { + get => _userLogin; + set => this.RaiseAndSetIfChanged(ref _userLogin, value); + } + + public ReactiveCommand LoginCommand { get;} + public ReactiveCommand GuestCommand { get; } + + public string? UrlPathSegment { get; } = Guid.NewGuid().ToString(); + + public IScreen HostScreen { get; } + + public LoginViewModel(IScreen screen, ILoginRepository loginRepository) { + _loginUseCase = new LoginUseCase(loginRepository); + HostScreen = screen; + + LoginCommand = ReactiveCommand.Create(() => + { + try + { + var userLogin = _loginUseCase.AutorizationByLoginAndPassword(_userLogin); + SQLProductRepository sqlProductRepository = new SQLProductRepository(); + HostScreen.Router.Navigate.Execute(new ClientProductViewModel(HostScreen, sqlProductRepository, userLogin)); + } + catch (Exception ex) { + ErrorMessage = ex.Message; + + } + + } + ); + + GuestCommand = ReactiveCommand.Create(() => { + SQLProductRepository sqlProductRepository = new SQLProductRepository(); + HostScreen.Router.Navigate.Execute(new GuestProductViewModel(HostScreen, sqlProductRepository)); + }); + } + + + } +} diff --git a/ViewModels/MainWindowViewModel.cs b/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000..fd78bec --- /dev/null +++ b/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,19 @@ +using demo_trade.Data.Repository; +using ReactiveUI; +using System.Reactive; + +namespace demo_trade.ViewModels +{ + public partial class MainWindowViewModel : ReactiveObject, IScreen + { + public RoutingState Router { get; } = new RoutingState(); + + + public MainWindowViewModel() { + SQLLoginRepository loginRepository = new SQLLoginRepository(); + Router.Navigate.Execute(new LoginViewModel(this, loginRepository)); + + + } + } +} diff --git a/ViewModels/OrderManagerViewModel.cs b/ViewModels/OrderManagerViewModel.cs new file mode 100644 index 0000000..e7ebc7b --- /dev/null +++ b/ViewModels/OrderManagerViewModel.cs @@ -0,0 +1,81 @@ +using demo_trade.Domain; +using demo_trade.Models; +using DynamicData; +using ReactiveUI; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.ViewModels +{ + public class OrderManagerViewModel : ViewModelBase, IRoutableViewModel + { + OrderManagerUseCase _orderManagerUseCase; + public string? UrlPathSegment { get; } = Guid.NewGuid().ToString(); + + private ObservableCollection _orders = new(); + + private Dictionary _changedOrdes = new(); + + private List _dateSource = new(); + public ObservableCollection Orders { get => _orders; set => this.RaiseAndSetIfChanged(ref _orders, value); } + + + private int _selectedSortNumber = 0; + public int SelectedSortNumber { get => _selectedSortNumber; set => this.RaiseAndSetIfChanged(ref _selectedSortNumber, value); } + + public IScreen HostScreen { get; } + public ReactiveCommand ConfirmChangeCommand { get; } + + public OrderManagerViewModel(IScreen screen, OrderManagerUseCase orderManagerUseCase) + { + _orderManagerUseCase = orderManagerUseCase; + _dateSource = _orderManagerUseCase.GetOrders(); + this.WhenAnyValue(sort => sort.SelectedSortNumber).Subscribe(_ => DisplayList()); + ConfirmChangeCommand = ReactiveCommand.Create(() => { + if (_changedOrdes.Values.Count == 0) return; + _orderManagerUseCase.ChangeOrders(_changedOrdes.Values.ToList()); + }); + HostScreen = screen; + } + + private void DisplayList() { + var temp = _dateSource; + if (SelectedSortNumber == 1) + { + temp = temp.OrderByDescending(it => it.OrderSumCost).ToList(); + } + else if (SelectedSortNumber == 2) temp = temp.OrderBy(it => it.OrderSumCost).ToList(); + _orders.Clear(); + foreach (var order in temp) + { + _orders.Add(order); + } + + } + + public void OrderDateChanged(int id, DateTimeOffset dateDelivery) { + if (dateDelivery.DateTime <= DateTime.Now) return; + if (_changedOrdes.ContainsKey(id)) { + _changedOrdes[id].OrderDeliveryDate = DateOnly.FromDateTime(dateDelivery.DateTime); + return; + } + _changedOrdes.Add(id, new OrderChanged { OrderDeliveryDate = DateOnly.FromDateTime(dateDelivery.DateTime), OrderId= id }); + } + public void OrderStatusChanged(int id, int status) + { + if (status != 1) return; + if (_changedOrdes.ContainsKey(id)) + { + _changedOrdes[id].OrderStatus = "Завершен"; + return; + } + _changedOrdes.Add(id, new OrderChanged { OrderStatus = "Завершен", OrderId = id }); + } + + } +} diff --git a/ViewModels/OrderShowDialogViewModel.cs b/ViewModels/OrderShowDialogViewModel.cs new file mode 100644 index 0000000..69617a8 --- /dev/null +++ b/ViewModels/OrderShowDialogViewModel.cs @@ -0,0 +1,119 @@ +using Avalonia.Controls; +using demo_trade.Data.RemoteData.Entity; +using demo_trade.Domain; +using demo_trade.Models; +using demo_trade.UI.Presenters; +using DynamicData; +using ReactiveUI; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive; +using System.Reflection.Emit; +using System.Text; +using System.Threading.Tasks; + +namespace demo_trade.ViewModels +{ + public class OrderShowDialogViewModel : ViewModelBase + { + + private OrderClientUseCase _orderClientUseCase; + + private PickupPoint _pickupPointSelected = new(); + public PickupPoint PickupPointSelected { get => _pickupPointSelected; set => this.RaiseAndSetIfChanged(ref _pickupPointSelected, value); } + + private Models.Order? orderComplete { get; set; } = null; + + private string _userName = String.Empty; + public string UserName{ get => _userName; set => this.RaiseAndSetIfChanged(ref _userName, value); } + + private int _numberOrder = 0; + public int NumberOrder { get => _numberOrder; set => this.RaiseAndSetIfChanged(ref _numberOrder, value); } + + private int _selectedPointId = 0; + public int SelectedPointId { get => _selectedPointId; set => this.RaiseAndSetIfChanged(ref _selectedPointId, value); } + + private List _pickupPoints = new(); + public List PickupPoints { get => _pickupPoints; set => this.RaiseAndSetIfChanged(ref _pickupPoints, value); } + + private Decimal _orderSumValue = 0; + public Decimal OrderSumValue { get => _orderSumValue; set => this.RaiseAndSetIfChanged(ref _orderSumValue, value); } + + public ReactiveCommand GenerateOrderCommand { get; } + + + private ObservableCollection _productOrderList = new(); + public ObservableCollection ProductOrderList + { + get => _productOrderList; + set => this.RaiseAndSetIfChanged(ref _productOrderList, value); + } + + public OrderShowDialogViewModel( Dictionary orderProducts, OrderClientUseCase orderClientUseCase, User? user = null) { + + _orderClientUseCase = orderClientUseCase; + _numberOrder = _orderClientUseCase.GetNewOrderNumber(); + _pickupPoints = _orderClientUseCase.GetPickupPoints(); + if (user != null) + { + UserName = String.Format("{0} {1} {2}", user.Usersurname, user.Username, user.Userpatronymic); + } + GenerateOrderCommand = ReactiveCommand.Create(() => { + string? clientName = null; + if(!String.IsNullOrEmpty(UserName)) clientName = UserName; + var resultOrder = _orderClientUseCase.GenerateNewOrder(PickupPointSelected, ProductOrderList.ToList(),OrderSumValue, clientName); + if (resultOrder != null) { + NumberOrder = resultOrder.Orderid + 1; + orderComplete = resultOrder; + } + }); + + foreach (var item in orderProducts.Values) + { + ProductOrderList.Add(new OrderProductPresenter(item.Item1, item.Item2)); + } + + this.WhenAnyValue(it => it.ProductOrderList).Subscribe(it => CalculateOrderSum()); + + } + + public void NumericChange(string ArticleProduct, int value) { + ProductOrderList.First(it => it.ArticleNumber == ArticleProduct).ProductCount = value; + CalculateOrderSum(); + if (value == 0) + { + ProductOrderList.Remove(ProductOrderList.First(it => it.ArticleNumber == ArticleProduct)); + return; + } + + } + + public void SaveFile(string path) { + if (orderComplete == null) return; + Ticket ticket = new Ticket() + { + ClientName = orderComplete.OrderClient, + OrderID = orderComplete.Orderid, + OrderDate = DateOnly.FromDateTime(DateTime.Now), + OrderDelivery = orderComplete.Orderdeliverydate, + Products = orderComplete.ProductList, + PickupPointName = orderComplete.PickupPointName, + OrderSumCost = orderComplete.OrderSumCost + } + ; + ticket.GeneratePDF(path); + + } + private void CalculateOrderSum() { + var orderSum = ProductOrderList.Sum(product => { + if (product.CostWithDiscount != null) return product.CostWithDiscount * product.ProductCount; + return product.ProductCount * product.Cost; + }); + if (orderSum != null) OrderSumValue = orderSum.Value; + + } + } + +} diff --git a/ViewModels/ViewModelBase.cs b/ViewModels/ViewModelBase.cs new file mode 100644 index 0000000..badc705 --- /dev/null +++ b/ViewModels/ViewModelBase.cs @@ -0,0 +1,9 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using ReactiveUI; + +namespace demo_trade.ViewModels +{ + public class ViewModelBase : ReactiveObject + { + } +} diff --git a/Views/ClientProductControl.axaml b/Views/ClientProductControl.axaml new file mode 100644 index 0000000..be62582 --- /dev/null +++ b/Views/ClientProductControl.axaml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + Все диапазоны + 0-9.99% + 10-14.99% + 15% и болле + + + отсут. + по убыв. + по возраст. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +