diff --git a/ServiceApp.sln b/ServiceApp.sln new file mode 100644 index 0000000..9ba1be3 --- /dev/null +++ b/ServiceApp.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35222.181 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceApp", "ServiceApp\ServiceApp.csproj", "{F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2BD7127-5A3B-4AF1-89E4-C60B70EB2E6B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A812EF99-15E4-4DD1-A3AD-370E1AB49A94} + EndGlobalSection +EndGlobal diff --git a/ServiceApp/App.axaml b/ServiceApp/App.axaml new file mode 100644 index 0000000..1d5b7f7 --- /dev/null +++ b/ServiceApp/App.axaml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/ServiceApp/App.axaml.cs b/ServiceApp/App.axaml.cs new file mode 100644 index 0000000..1c6f03f --- /dev/null +++ b/ServiceApp/App.axaml.cs @@ -0,0 +1,24 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; + +namespace ServiceApp +{ + 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(); + } + + base.OnFrameworkInitializationCompleted(); + } + } +} \ No newline at end of file diff --git a/ServiceApp/Assets/diz.jpg b/ServiceApp/Assets/diz.jpg new file mode 100644 index 0000000..bb6d0c6 Binary files /dev/null and b/ServiceApp/Assets/diz.jpg differ diff --git a/ServiceApp/Assets/download.png b/ServiceApp/Assets/download.png new file mode 100644 index 0000000..decc481 Binary files /dev/null and b/ServiceApp/Assets/download.png differ diff --git a/ServiceApp/Assets/rulevoe-upravlenie-avtomobilya.jpg b/ServiceApp/Assets/rulevoe-upravlenie-avtomobilya.jpg new file mode 100644 index 0000000..1f63a94 Binary files /dev/null and b/ServiceApp/Assets/rulevoe-upravlenie-avtomobilya.jpg differ diff --git a/ServiceApp/Assets/transmission.jpg b/ServiceApp/Assets/transmission.jpg new file mode 100644 index 0000000..d6bee7a Binary files /dev/null and b/ServiceApp/Assets/transmission.jpg differ diff --git a/ServiceApp/Assets/АКПП.jpg b/ServiceApp/Assets/АКПП.jpg new file mode 100644 index 0000000..05712af Binary files /dev/null and b/ServiceApp/Assets/АКПП.jpg differ diff --git a/ServiceApp/Assets/Вариатор.jpg b/ServiceApp/Assets/Вариатор.jpg new file mode 100644 index 0000000..dab9ab0 Binary files /dev/null and b/ServiceApp/Assets/Вариатор.jpg differ diff --git a/ServiceApp/Assets/Выхлопная система.jpg b/ServiceApp/Assets/Выхлопная система.jpg new file mode 100644 index 0000000..84a5499 Binary files /dev/null and b/ServiceApp/Assets/Выхлопная система.jpg differ diff --git a/ServiceApp/Assets/ГУР.png b/ServiceApp/Assets/ГУР.png new file mode 100644 index 0000000..f44d643 Binary files /dev/null and b/ServiceApp/Assets/ГУР.png differ diff --git a/ServiceApp/Assets/Двигатель.png b/ServiceApp/Assets/Двигатель.png new file mode 100644 index 0000000..9887cf5 Binary files /dev/null and b/ServiceApp/Assets/Двигатель.png differ diff --git a/ServiceApp/Assets/Дополнительные услуги.png b/ServiceApp/Assets/Дополнительные услуги.png new file mode 100644 index 0000000..fea97ed Binary files /dev/null and b/ServiceApp/Assets/Дополнительные услуги.png differ diff --git a/ServiceApp/Assets/КПП.png b/ServiceApp/Assets/КПП.png new file mode 100644 index 0000000..f480034 Binary files /dev/null and b/ServiceApp/Assets/КПП.png differ diff --git a/ServiceApp/Assets/Кондиционер.jpg b/ServiceApp/Assets/Кондиционер.jpg new file mode 100644 index 0000000..7f18699 Binary files /dev/null and b/ServiceApp/Assets/Кондиционер.jpg differ diff --git a/ServiceApp/Assets/Подвеска.png b/ServiceApp/Assets/Подвеска.png new file mode 100644 index 0000000..0b310b2 Binary files /dev/null and b/ServiceApp/Assets/Подвеска.png differ diff --git a/ServiceApp/Assets/Сцепление.jpg b/ServiceApp/Assets/Сцепление.jpg new file mode 100644 index 0000000..dea13cb Binary files /dev/null and b/ServiceApp/Assets/Сцепление.jpg differ diff --git a/ServiceApp/Assets/Техническое обслуживание.png b/ServiceApp/Assets/Техническое обслуживание.png new file mode 100644 index 0000000..b9c2d04 Binary files /dev/null and b/ServiceApp/Assets/Техническое обслуживание.png differ diff --git a/ServiceApp/Assets/Топливная система.png b/ServiceApp/Assets/Топливная система.png new file mode 100644 index 0000000..7990d1e Binary files /dev/null and b/ServiceApp/Assets/Топливная система.png differ diff --git a/ServiceApp/Assets/Шиномонтаж.jpg b/ServiceApp/Assets/Шиномонтаж.jpg new file mode 100644 index 0000000..b17156e Binary files /dev/null and b/ServiceApp/Assets/Шиномонтаж.jpg differ diff --git a/ServiceApp/Assets/Электрика.png b/ServiceApp/Assets/Электрика.png new file mode 100644 index 0000000..ac0bd50 Binary files /dev/null and b/ServiceApp/Assets/Электрика.png differ diff --git a/ServiceApp/EntityModels/Client.cs b/ServiceApp/EntityModels/Client.cs new file mode 100644 index 0000000..d7ae129 --- /dev/null +++ b/ServiceApp/EntityModels/Client.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Client +{ + public int Id { get; set; } + + public string Firstname { get; set; } = null!; + + public string Lastname { get; set; } = null!; + + public string? Patronymic { get; set; } + + public DateOnly? Birthday { get; set; } + + public DateTime Registrationdate { get; set; } + + public string? Email { get; set; } + + public string Phone { get; set; } = null!; + + public int Gendercode { get; set; } + + public string? Photopath { get; set; } + + public virtual ICollection Clientservices { get; set; } = new List(); + + public virtual Gender GendercodeNavigation { get; set; } = null!; + + public virtual ICollection Tags { get; set; } = new List(); +} diff --git a/ServiceApp/EntityModels/Clientservice.cs b/ServiceApp/EntityModels/Clientservice.cs new file mode 100644 index 0000000..1f1c6c7 --- /dev/null +++ b/ServiceApp/EntityModels/Clientservice.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Clientservice +{ + public int Id { get; set; } + + public int Clientid { get; set; } + + public int Serviceid { get; set; } + + public DateTime Starttime { get; set; } + + public string? Comment { get; set; } + + public virtual Client Client { get; set; } = null!; + + public virtual ICollection Documentbyservices { get; set; } = new List(); + + public virtual ICollection Productsales { get; set; } = new List(); + + public virtual Service Service { get; set; } = null!; +} diff --git a/ServiceApp/EntityModels/Documentbyservice.cs b/ServiceApp/EntityModels/Documentbyservice.cs new file mode 100644 index 0000000..85859d7 --- /dev/null +++ b/ServiceApp/EntityModels/Documentbyservice.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Documentbyservice +{ + public int Id { get; set; } + + public int Clientserviceid { get; set; } + + public string Documentpath { get; set; } = null!; + + public virtual Clientservice Clientservice { get; set; } = null!; +} diff --git a/ServiceApp/EntityModels/Gender.cs b/ServiceApp/EntityModels/Gender.cs new file mode 100644 index 0000000..027d456 --- /dev/null +++ b/ServiceApp/EntityModels/Gender.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Gender +{ + public int Code { get; set; } + + public string? Name { get; set; } + + public virtual ICollection Clients { get; set; } = new List(); +} diff --git a/ServiceApp/EntityModels/IsajkinContext.cs b/ServiceApp/EntityModels/IsajkinContext.cs new file mode 100644 index 0000000..84a51bc --- /dev/null +++ b/ServiceApp/EntityModels/IsajkinContext.cs @@ -0,0 +1,334 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; + +namespace ServiceApp.EnityModels; + +public partial class IsajkinContext : DbContext +{ + public IsajkinContext() + { + } + + public IsajkinContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet Clients { get; set; } + + public virtual DbSet Clientservices { get; set; } + + public virtual DbSet Documentbyservices { get; set; } + + public virtual DbSet Genders { get; set; } + + public virtual DbSet Manufacturers { get; set; } + + public virtual DbSet Products { get; set; } + + public virtual DbSet Productphotos { get; set; } + + public virtual DbSet Productsales { get; set; } + + public virtual DbSet Services { get; set; } + + public virtual DbSet Servicephotos { get; set; } + + public virtual DbSet Tags { 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=45.67.56.214;Port=5454;Username=isajkin;Password=hqD9f9EZ"); + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("client_pkey"); + + entity.ToTable("client"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Birthday).HasColumnName("birthday"); + entity.Property(e => e.Email) + .HasMaxLength(255) + .HasColumnName("email"); + entity.Property(e => e.Firstname) + .HasMaxLength(50) + .HasColumnName("firstname"); + entity.Property(e => e.Gendercode).HasColumnName("gendercode"); + entity.Property(e => e.Lastname) + .HasMaxLength(50) + .HasColumnName("lastname"); + entity.Property(e => e.Patronymic) + .HasMaxLength(50) + .HasColumnName("patronymic"); + entity.Property(e => e.Phone) + .HasMaxLength(20) + .HasColumnName("phone"); + entity.Property(e => e.Photopath) + .HasMaxLength(1000) + .HasColumnName("photopath"); + entity.Property(e => e.Registrationdate) + .HasColumnType("timestamp(6) without time zone") + .HasColumnName("registrationdate"); + + entity.HasOne(d => d.GendercodeNavigation).WithMany(p => p.Clients) + .HasForeignKey(d => d.Gendercode) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_client_gender"); + + entity.HasMany(d => d.Tags).WithMany(p => p.Clients) + .UsingEntity>( + "Tagofclient", + r => r.HasOne().WithMany() + .HasForeignKey("Tagid") + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_tagofclient_tag"), + l => l.HasOne().WithMany() + .HasForeignKey("Clientid") + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_tagofclient_client"), + j => + { + j.HasKey("Clientid", "Tagid").HasName("tagofclient_pkey"); + j.ToTable("tagofclient"); + j.IndexerProperty("Clientid").HasColumnName("clientid"); + j.IndexerProperty("Tagid").HasColumnName("tagid"); + }); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("clientservice_pkey"); + + entity.ToTable("clientservice"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Clientid).HasColumnName("clientid"); + entity.Property(e => e.Comment).HasColumnName("comment"); + entity.Property(e => e.Serviceid).HasColumnName("serviceid"); + entity.Property(e => e.Starttime) + .HasColumnType("timestamp(6) without time zone") + .HasColumnName("starttime"); + + entity.HasOne(d => d.Client).WithMany(p => p.Clientservices) + .HasForeignKey(d => d.Clientid) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_clientservice_client"); + + entity.HasOne(d => d.Service).WithMany(p => p.Clientservices) + .HasForeignKey(d => d.Serviceid) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_clientservice_service"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("documentbyservice_pkey"); + + entity.ToTable("documentbyservice"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Clientserviceid).HasColumnName("clientserviceid"); + entity.Property(e => e.Documentpath) + .HasMaxLength(1000) + .HasColumnName("documentpath"); + + entity.HasOne(d => d.Clientservice).WithMany(p => p.Documentbyservices) + .HasForeignKey(d => d.Clientserviceid) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_documentbyservice_clientservice"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Code).HasName("gender_pkey"); + + entity.ToTable("gender"); + + entity.Property(e => e.Code).HasColumnName("code"); + entity.Property(e => e.Name) + .HasMaxLength(10) + .HasColumnName("name"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("manufacturer_pkey"); + + entity.ToTable("manufacturer"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Name) + .HasMaxLength(100) + .HasColumnName("name"); + entity.Property(e => e.Startdate).HasColumnName("startdate"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("product_pkey"); + + entity.ToTable("product"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Cost) + .HasPrecision(19, 4) + .HasColumnName("cost"); + entity.Property(e => e.Description).HasColumnName("description"); + entity.Property(e => e.Isactive).HasColumnName("isactive"); + entity.Property(e => e.Mainimagepath) + .HasMaxLength(1000) + .HasColumnName("mainimagepath"); + entity.Property(e => e.Manufacturerid).HasColumnName("manufacturerid"); + entity.Property(e => e.Title) + .HasMaxLength(100) + .HasColumnName("title"); + + entity.HasOne(d => d.Manufacturer).WithMany(p => p.Products) + .HasForeignKey(d => d.Manufacturerid) + .HasConstraintName("fk_product_manufacturer"); + + entity.HasMany(d => d.Attachedproducts).WithMany(p => p.Mainproducts) + .UsingEntity>( + "Attachedproduct", + r => r.HasOne().WithMany() + .HasForeignKey("Attachedproductid") + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_attachedproduct_product1"), + l => l.HasOne().WithMany() + .HasForeignKey("Mainproductid") + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_attachedproduct_product"), + j => + { + j.HasKey("Mainproductid", "Attachedproductid").HasName("attachedproduct_pkey"); + j.ToTable("attachedproduct"); + j.IndexerProperty("Mainproductid").HasColumnName("mainproductid"); + j.IndexerProperty("Attachedproductid").HasColumnName("attachedproductid"); + }); + + entity.HasMany(d => d.Mainproducts).WithMany(p => p.Attachedproducts) + .UsingEntity>( + "Attachedproduct", + r => r.HasOne().WithMany() + .HasForeignKey("Mainproductid") + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_attachedproduct_product"), + l => l.HasOne().WithMany() + .HasForeignKey("Attachedproductid") + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_attachedproduct_product1"), + j => + { + j.HasKey("Mainproductid", "Attachedproductid").HasName("attachedproduct_pkey"); + j.ToTable("attachedproduct"); + j.IndexerProperty("Mainproductid").HasColumnName("mainproductid"); + j.IndexerProperty("Attachedproductid").HasColumnName("attachedproductid"); + }); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("productphoto_pkey"); + + entity.ToTable("productphoto"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Photopath) + .HasMaxLength(1000) + .HasColumnName("photopath"); + entity.Property(e => e.Productid).HasColumnName("productid"); + + entity.HasOne(d => d.Product).WithMany(p => p.Productphotos) + .HasForeignKey(d => d.Productid) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_productphoto_product"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("productsale_pkey"); + + entity.ToTable("productsale"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Clientserviceid).HasColumnName("clientserviceid"); + entity.Property(e => e.Productid).HasColumnName("productid"); + entity.Property(e => e.Quantity).HasColumnName("quantity"); + entity.Property(e => e.Saledate) + .HasColumnType("timestamp(6) without time zone") + .HasColumnName("saledate"); + + entity.HasOne(d => d.Clientservice).WithMany(p => p.Productsales) + .HasForeignKey(d => d.Clientserviceid) + .HasConstraintName("fk_productsale_clientservice"); + + entity.HasOne(d => d.Product).WithMany(p => p.Productsales) + .HasForeignKey(d => d.Productid) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_productsale_product"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("service_pkey"); + + entity.ToTable("service"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Cost) + .HasPrecision(19, 4) + .HasColumnName("cost"); + entity.Property(e => e.Description).HasColumnName("description"); + entity.Property(e => e.Discount).HasColumnName("discount"); + entity.Property(e => e.Durationinminutes).HasColumnName("durationinminutes"); + entity.Property(e => e.Mainimagepath) + .HasMaxLength(1000) + .HasColumnName("mainimagepath"); + entity.Property(e => e.Title) + .HasMaxLength(100) + .HasColumnName("title"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("servicephoto_pkey"); + + entity.ToTable("servicephoto"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Photopath) + .HasMaxLength(1000) + .HasColumnName("photopath"); + entity.Property(e => e.Serviceid).HasColumnName("serviceid"); + + entity.HasOne(d => d.Service).WithMany(p => p.Servicephotos) + .HasForeignKey(d => d.Serviceid) + .OnDelete(DeleteBehavior.ClientSetNull) + .HasConstraintName("fk_servicephoto_service"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("tag_pkey"); + + entity.ToTable("tag"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Color) + .HasMaxLength(6) + .IsFixedLength() + .HasColumnName("color"); + entity.Property(e => e.Title) + .HasMaxLength(30) + .HasColumnName("title"); + }); + + OnModelCreatingPartial(modelBuilder); + } + + partial void OnModelCreatingPartial(ModelBuilder modelBuilder); +} diff --git a/ServiceApp/EntityModels/Manufacturer.cs b/ServiceApp/EntityModels/Manufacturer.cs new file mode 100644 index 0000000..1bc90ea --- /dev/null +++ b/ServiceApp/EntityModels/Manufacturer.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Manufacturer +{ + public int Id { get; set; } + + public string Name { get; set; } = null!; + + public DateOnly? Startdate { get; set; } + + public virtual ICollection Products { get; set; } = new List(); +} diff --git a/ServiceApp/EntityModels/Product.cs b/ServiceApp/EntityModels/Product.cs new file mode 100644 index 0000000..ae2f5a7 --- /dev/null +++ b/ServiceApp/EntityModels/Product.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Product +{ + public int Id { get; set; } + + public string Title { get; set; } = null!; + + public decimal Cost { get; set; } + + public string? Description { get; set; } + + public string? Mainimagepath { get; set; } + + public int Isactive { get; set; } + + public int? Manufacturerid { get; set; } + + public virtual Manufacturer? Manufacturer { get; set; } + + public virtual ICollection Productphotos { get; set; } = new List(); + + public virtual ICollection Productsales { get; set; } = new List(); + + public virtual ICollection Attachedproducts { get; set; } = new List(); + + public virtual ICollection Mainproducts { get; set; } = new List(); +} diff --git a/ServiceApp/EntityModels/Productphoto.cs b/ServiceApp/EntityModels/Productphoto.cs new file mode 100644 index 0000000..1ed39c1 --- /dev/null +++ b/ServiceApp/EntityModels/Productphoto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Productphoto +{ + public int Id { get; set; } + + public int Productid { get; set; } + + public string Photopath { get; set; } = null!; + + public virtual Product Product { get; set; } = null!; +} diff --git a/ServiceApp/EntityModels/Productsale.cs b/ServiceApp/EntityModels/Productsale.cs new file mode 100644 index 0000000..6967366 --- /dev/null +++ b/ServiceApp/EntityModels/Productsale.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Productsale +{ + public int Id { get; set; } + + public DateTime Saledate { get; set; } + + public int Productid { get; set; } + + public int Quantity { get; set; } + + public int? Clientserviceid { get; set; } + + public virtual Clientservice? Clientservice { get; set; } + + public virtual Product Product { get; set; } = null!; +} diff --git a/ServiceApp/EntityModels/Service.cs b/ServiceApp/EntityModels/Service.cs new file mode 100644 index 0000000..b4ba8a6 --- /dev/null +++ b/ServiceApp/EntityModels/Service.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Service +{ + public int Id { get; set; } + + public string Title { get; set; } = null!; + + public decimal Cost { get; set; } + + public int Durationinminutes { get; set; } + + public string? Description { get; set; } + + public double? Discount { get; set; } + + public string? Mainimagepath { get; set; } + + public virtual ICollection Clientservices { get; set; } = new List(); + + public virtual ICollection Servicephotos { get; set; } = new List(); +} diff --git a/ServiceApp/EntityModels/Servicephoto.cs b/ServiceApp/EntityModels/Servicephoto.cs new file mode 100644 index 0000000..f893773 --- /dev/null +++ b/ServiceApp/EntityModels/Servicephoto.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Servicephoto +{ + public int Id { get; set; } + + public int Serviceid { get; set; } + + public string Photopath { get; set; } = null!; + + public virtual Service Service { get; set; } = null!; +} diff --git a/ServiceApp/EntityModels/Tag.cs b/ServiceApp/EntityModels/Tag.cs new file mode 100644 index 0000000..a031485 --- /dev/null +++ b/ServiceApp/EntityModels/Tag.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace ServiceApp.EnityModels; + +public partial class Tag +{ + public int Id { get; set; } + + public string Title { get; set; } = null!; + + public string Color { get; set; } = null!; + + public virtual ICollection Clients { get; set; } = new List(); +} diff --git a/ServiceApp/MainWindow.axaml b/ServiceApp/MainWindow.axaml new file mode 100644 index 0000000..ba7249c --- /dev/null +++ b/ServiceApp/MainWindow.axaml @@ -0,0 +1,30 @@ + + + Введите код для перехода в режим авдминистратора + + + + + + + diff --git a/ServiceApp/MainWindow.axaml.cs b/ServiceApp/MainWindow.axaml.cs new file mode 100644 index 0000000..c4d69ee --- /dev/null +++ b/ServiceApp/MainWindow.axaml.cs @@ -0,0 +1,27 @@ +using Avalonia.Controls; + +namespace ServiceApp +{ + public partial class MainWindow : Window + { + private string _secretCode = "0000"; + public MainWindow() + { + InitializeComponent(); + } + + private void LoginClientButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + new ServiceWindow().Show(); + this.Close(); + } + private void LoginAdminButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + if (CodeTextBox.Text == _secretCode) { + new ServiceAdminWindow().Show(); + this.Close(); + } + } + + } +} \ No newline at end of file diff --git a/ServiceApp/Program.cs b/ServiceApp/Program.cs new file mode 100644 index 0000000..39fb0bf --- /dev/null +++ b/ServiceApp/Program.cs @@ -0,0 +1,22 @@ +using Avalonia; +using System; + +namespace ServiceApp +{ + internal class Program + { + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace(); + } +} diff --git a/ServiceApp/ServiceApp.csproj b/ServiceApp/ServiceApp.csproj new file mode 100644 index 0000000..eec6d5e --- /dev/null +++ b/ServiceApp/ServiceApp.csproj @@ -0,0 +1,39 @@ + + + WinExe + net8.0 + enable + true + app.manifest + true + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + ServiceWindowAdmin.axaml + + + diff --git a/ServiceApp/ServiceWindow.axaml b/ServiceApp/ServiceWindow.axaml new file mode 100644 index 0000000..f813513 --- /dev/null +++ b/ServiceApp/ServiceWindow.axaml @@ -0,0 +1,62 @@ + + + + + + + + + + + + Статистика + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ServiceApp/ServiceWindow.axaml.cs b/ServiceApp/ServiceWindow.axaml.cs new file mode 100644 index 0000000..a28ac13 --- /dev/null +++ b/ServiceApp/ServiceWindow.axaml.cs @@ -0,0 +1,132 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using System.Linq; +using ServiceApp.EnityModels; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using SkiaSharp; +using Microsoft.EntityFrameworkCore.Storage.Json; +using System; +using Npgsql.TypeMapping; +using Avalonia.Media.Imaging; +using Avalonia.Platform; + +namespace ServiceApp; + +public partial class ServiceWindow : Window +{ + public List sourceList { get; set; } + public ObservableCollection displayList { get; } + + private string _searchWord = string.Empty; + + private string[] _sortingSource = new string[3] { ".", " .", " ." }; + private Dictionary _dicountFilter = new Dictionary { + {"", (0, 0) }, + { "0-5", (0,5)}, + { "15-30", (5,15)}, + { "30-70", (30,70)}, + { "70-100", (70,100)}, + }; + + public ServiceWindow() + { + InitializeComponent(); + using (var dbContext = new IsajkinContext()) + { + + sourceList = dbContext.Services.Select(service => + new ServicePresenter + { + Title = service.Title, + Discount = service.Discount, + Durationinminutes = service.Durationinminutes, + Id = service.Id, + Cost = service.Cost, + Mainimagepath = service.Mainimagepath, + } + ).ToList(); + } + displayList = new ObservableCollection(sourceList); + SortingComboBox.ItemsSource = _sortingSource; + ServiceListBox.ItemsSource = displayList; + FilteringComboBox.ItemsSource = _dicountFilter.Keys; + StatisticTextBlock.Text = String.Format("{0} {1}", displayList.Count, sourceList.Count); + + } + + private void DisplayService() { + + var displayServiceList = sourceList; + if (FilteringComboBox.SelectedIndex > 0) displayServiceList = displayServiceList.Where(service => + FilterByDiscount(service, FilteringComboBox.SelectionBoxItem.ToString())).ToList(); + if(!String.IsNullOrEmpty(_searchWord)) displayServiceList = displayServiceList.Where(service => SearchByWord(service, _searchWord)).ToList(); + if(SortingComboBox.SelectedIndex > 0) displayServiceList = SortingComboBox.SelectedIndex == 1? + displayServiceList.OrderBy(service => service.Cost).ToList() : + displayServiceList.OrderByDescending(service => service.Cost).ToList(); + displayList.Clear(); + foreach (var service in displayServiceList) { displayList.Add(service); } + StatisticTextBlock.Text = String.Format("{0} {1}", displayServiceList.Count, sourceList.Count); + } + + + private bool SearchByWord(ServicePresenter service, string word) { + if (service.Title.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true; + if (String.IsNullOrEmpty(service.Description)) return false; + if (service.Description.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true; + return false; + } + private bool FilterByDiscount(ServicePresenter servicePresenter, string key) { + (int left, int right) = _dicountFilter[key]; + double discount = servicePresenter.Discount != null? Convert.ToDouble(servicePresenter.Discount) * 100 : 0; + return left <= discount && discount < right; + } + + private void SearchTextBox_TextChanged(object? sender, Avalonia.Controls.TextChangedEventArgs e) + { + _searchWord = SearchTextBox.Text.ToString(); + DisplayService(); + } + + + private void FilteringComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e) + { + DisplayService(); + } + + private void SortingComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e) + { + DisplayService(); + } +} + +public class ServicePresenter() : Service +{ + public int ServiceID { get => this.Id; } + public string ServiceName { get => this.Title; } + public string SeviceCostPerSeconds { get => + (this.Discount != 0 ? + String.Format("{0:0.00} {1} ", this.Cost - this.Cost * Convert.ToDecimal(this.Discount), this.Durationinminutes) + : + String.Format("{0:0.00} {1} ", this.Cost, this.Durationinminutes) + ); + } + public Bitmap ServiceImage { get => GetBitmap(this.Mainimagepath); } + public decimal? OldCost { get => (this.Discount != 0 ? this.Cost : null); } + public string? ServiceDiscount { get => + (this.Discount != 0 ? + String.Format("* {0}%", Discount * 100) + : String.Empty + ); } + + private Bitmap GetBitmap(string fileName) { + try { + return new Bitmap($"Assets\\{fileName}"); + } + catch (Exception ex) { + return new Bitmap("Assets\\download.png"); + + } + } +} \ No newline at end of file diff --git a/ServiceApp/ServiceWindowAdmin.axaml b/ServiceApp/ServiceWindowAdmin.axaml new file mode 100644 index 0000000..2e977a4 --- /dev/null +++ b/ServiceApp/ServiceWindowAdmin.axaml @@ -0,0 +1,66 @@ + + + + + + + + + + + + Статистика + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ServiceApp/ServiceWindowAdmin.axaml.cs b/ServiceApp/ServiceWindowAdmin.axaml.cs new file mode 100644 index 0000000..58d87ea --- /dev/null +++ b/ServiceApp/ServiceWindowAdmin.axaml.cs @@ -0,0 +1,134 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using System.Linq; +using ServiceApp.EnityModels; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using SkiaSharp; +using Microsoft.EntityFrameworkCore.Storage.Json; +using System; +using Npgsql.TypeMapping; +using Avalonia.Media.Imaging; +using Avalonia.Platform; + +namespace ServiceApp; + +public partial class ServiceAdminWindow : Window +{ + public List sourceList { get; set; } + public ObservableCollection displayList { get; } + + private string _searchWord = string.Empty; + + private string[] _sortingSource = new string[3] { ".", " .", " ." }; + private Dictionary _dicountFilter = new Dictionary { + {"", (0, 0) }, + { "0-5", (0,5)}, + { "15-30", (5,15)}, + { "30-70", (30,70)}, + { "70-100", (70,100)}, + }; + + public ServiceAdminWindow() + { + InitializeComponent(); + using (var dbContext = new IsajkinContext()) + { + + sourceList = dbContext.Services.Select(service => + new ServicePresenter + { + Title = service.Title, + Discount = service.Discount, + Durationinminutes = service.Durationinminutes, + Id = service.Id, + Cost = service.Cost, + Mainimagepath = service.Mainimagepath, + } + ).ToList(); + } + displayList = new ObservableCollection(sourceList); + SortingComboBox.ItemsSource = _sortingSource; + ServiceListBox.ItemsSource = displayList; + FilteringComboBox.ItemsSource = _dicountFilter.Keys; + StatisticTextBlock.Text = String.Format("{0} {1}", displayList.Count, sourceList.Count); + + + } + + private void DisplayService() { + + var displayServiceList = sourceList; + if (FilteringComboBox.SelectedIndex > 0) displayServiceList = displayServiceList.Where(service => + FilterByDiscount(service, FilteringComboBox.SelectionBoxItem.ToString())).ToList(); + if(!String.IsNullOrEmpty(_searchWord)) displayServiceList = displayServiceList.Where(service => SearchByWord(service, _searchWord)).ToList(); + if(SortingComboBox.SelectedIndex > 0) displayServiceList = SortingComboBox.SelectedIndex == 1? + displayServiceList.OrderBy(service => service.Cost).ToList() : + displayServiceList.OrderByDescending(service => service.Cost).ToList(); + displayList.Clear(); + foreach (var service in displayServiceList) { displayList.Add(service); } + StatisticTextBlock.Text = String.Format("{0} {1}", displayServiceList.Count, sourceList.Count); + } + + + private bool SearchByWord(ServicePresenter service, string word) { + if (service.Title.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true; + if (String.IsNullOrEmpty(service.Description)) return false; + if (service.Description.Contains(word, StringComparison.CurrentCultureIgnoreCase)) return true; + return false; + } + private bool FilterByDiscount(ServicePresenter servicePresenter, string key) { + (int left, int right) = _dicountFilter[key]; + double discount = servicePresenter.Discount != null? Convert.ToDouble(servicePresenter.Discount) * 100 : 0; + return left <= discount && discount < right; + } + + private void SearchTextBox_TextChanged(object? sender, Avalonia.Controls.TextChangedEventArgs e) + { + _searchWord = SearchTextBox.Text.ToString(); + DisplayService(); + } + + + private void FilteringComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e) + { + DisplayService(); + } + + private void SortingComboBox_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e) + { + DisplayService(); + } + + private void EditButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + + } + + private void RemoveButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + var serviceID = Convert.ToInt32((sender as Button).Tag); + using (var dbContext = new IsajkinContext()) { + var service = dbContext.Services.First(service => service.Id == serviceID); + var serviceLocal = displayList.First(service => service.Id == serviceID); + if (service == null) return; + if (dbContext.Clientservices.Where(item => item.Serviceid == serviceID).Count() > 0) return; + using var transaction = dbContext.Database.BeginTransaction(); + try + { + if (dbContext.Servicephotos.Where(item => item.Serviceid == serviceID).Count() > 0) + { + dbContext.RemoveRange(dbContext.Servicephotos.Where(item => item.Serviceid == serviceID)); + } + dbContext.Services.Remove(service); + displayList.Remove(serviceLocal); + dbContext.SaveChanges(); + transaction.Commit(); + } + catch (Exception ex) { + + } + } ; + } +} diff --git a/ServiceApp/app.manifest b/ServiceApp/app.manifest new file mode 100644 index 0000000..629772a --- /dev/null +++ b/ServiceApp/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + +