Bläddra i källkod

Gewerke fast abgeschlossen!

Arne Diekmann 5 år sedan
förälder
incheckning
3b44c4255e
43 ändrade filer med 4591 tillägg och 173 borttagningar
  1. 5 0
      GreenTree.Strohrmann.ERP.Core/Domain/Business/Craft.cs
  2. 10 0
      GreenTree.Strohrmann.ERP.Core/Domain/Business/CraftEmployee.cs
  3. 5 0
      GreenTree.Strohrmann.ERP.Core/Domain/Business/CraftMaterial.cs
  4. 36 0
      GreenTree.Strohrmann.ERP.Core/Extension/DecimalExtension.cs
  5. 25 0
      GreenTree.Strohrmann.ERP.Core/Extension/StringExtension.cs
  6. 44 0
      GreenTree.Strohrmann.ERP.Domain/Extension/DbSetExtension.cs
  7. 14 4
      GreenTree.Strohrmann.ERP.Domain/GreenTree.Strohrmann.ERP.Domain.csproj
  8. 727 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200726163658_CraftMaterial_Hotfix.Designer.cs
  9. 23 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200726163658_CraftMaterial_Hotfix.cs
  10. 736 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200727154942_CraftEmployee_Hotfix.Designer.cs
  11. 61 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200727154942_CraftEmployee_Hotfix.cs
  12. 736 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200727160055_CraftEmployee_Hotfix_2.Designer.cs
  13. 25 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200727160055_CraftEmployee_Hotfix_2.cs
  14. 739 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200731124621_Craft_Comment.Designer.cs
  15. 22 0
      GreenTree.Strohrmann.ERP.Domain/Migrations/20200731124621_Craft_Comment.cs
  16. 19 4
      GreenTree.Strohrmann.ERP.Domain/Migrations/ERPDbContextModelSnapshot.cs
  17. 13 2
      GreenTree.Strohrmann.ERP.Domain/Model/Business/CraftEmployeeMapping.cs
  18. 3 0
      GreenTree.Strohrmann.ERP.Domain/Model/Business/CraftMapping.cs
  19. 6 0
      GreenTree.Strohrmann.ERP.Domain/Model/Business/CraftMaterialMapping.cs
  20. 191 26
      GreenTree.Strohrmann.ERP.Web/Controllers/CraftController.cs
  21. 10 3
      GreenTree.Strohrmann.ERP.Web/Controllers/CustomerController.cs
  22. 28 0
      GreenTree.Strohrmann.ERP.Web/Extension/HtmlContentExtension.cs
  23. 20 1
      GreenTree.Strohrmann.ERP.Web/Models/Business/CraftEmployeeModel.cs
  24. 17 3
      GreenTree.Strohrmann.ERP.Web/Models/Business/CraftMaterialModel.cs
  25. 49 4
      GreenTree.Strohrmann.ERP.Web/Models/Business/CraftModel.cs
  26. 8 0
      GreenTree.Strohrmann.ERP.Web/Models/Search/ICustomerSearchable.cs
  27. 49 0
      GreenTree.Strohrmann.ERP.Web/Validators/CraftEmployeeValidator.cs
  28. 53 0
      GreenTree.Strohrmann.ERP.Web/Validators/CraftMaterialValidator.cs
  29. 63 0
      GreenTree.Strohrmann.ERP.Web/Validators/CraftValidator.cs
  30. 223 41
      GreenTree.Strohrmann.ERP.Web/Views/Craft/Create.cshtml
  31. 274 0
      GreenTree.Strohrmann.ERP.Web/Views/Craft/Edit.cshtml
  32. 20 2
      GreenTree.Strohrmann.ERP.Web/Views/Craft/Index.cshtml
  33. 89 14
      GreenTree.Strohrmann.ERP.Web/Views/Craft/_CraftEmployeePartial.cshtml
  34. 125 0
      GreenTree.Strohrmann.ERP.Web/Views/Craft/_CraftMaterialPartial.cshtml
  35. 72 61
      GreenTree.Strohrmann.ERP.Web/Views/Customer/_SearchCustomerPartial.cshtml
  36. 0 6
      GreenTree.Strohrmann.ERP.Web/Views/Home/Privacy.cshtml
  37. 3 0
      GreenTree.Strohrmann.ERP.Web/Views/Shared/_Layout.cshtml
  38. 1 1
      GreenTree.Strohrmann.ERP.Web/Views/Supplier/Edit.cshtml
  39. 3 1
      GreenTree.Strohrmann.ERP.Web/Views/_ViewImports.cshtml
  40. 5 0
      GreenTree.Strohrmann.ERP.Web/wwwroot/css/site.css
  41. BIN
      GreenTree.Strohrmann.ERP.Web/wwwroot/img/icon-average-48.png
  42. BIN
      GreenTree.Strohrmann.ERP.Web/wwwroot/img/icon-sigma-48.png
  43. 39 0
      GreenTree.Strohrmann.ERP.Web/wwwroot/js/extension.js

+ 5 - 0
GreenTree.Strohrmann.ERP.Core/Domain/Business/Craft.cs

@@ -27,6 +27,11 @@ namespace GreenTree.Strohrmann.ERP.Core.Domain.Business
         /// </summary>
         public virtual Customer Customer { get; set; }
 
+        /// <summary>
+        /// Craft comment
+        /// </summary>
+        public string Comment { get; set; }
+
         /// <summary>
         /// Craft employees
         /// </summary>

+ 10 - 0
GreenTree.Strohrmann.ERP.Core/Domain/Business/CraftEmployee.cs

@@ -6,6 +6,11 @@ namespace GreenTree.Strohrmann.ERP.Core.Domain.Business
 {
     public class CraftEmployee
     {
+        /// <summary>
+        /// Employee id
+        /// </summary>
+        public int Id { get; set; }
+
         /// <summary>
         /// Craft id
         /// </summary>
@@ -35,5 +40,10 @@ namespace GreenTree.Strohrmann.ERP.Core.Domain.Business
         /// The value of the employee working hours
         /// </summary>
         public decimal Value { get; set; }
+
+        /// <summary>
+        /// Employee comment
+        /// </summary>
+        public string Comment { get; set; }
     }
 }

+ 5 - 0
GreenTree.Strohrmann.ERP.Core/Domain/Business/CraftMaterial.cs

@@ -35,5 +35,10 @@ namespace GreenTree.Strohrmann.ERP.Core.Domain.Business
         /// The material calculation factor
         /// </summary>
         public decimal CalculationFactor { get; set; }
+
+        /// <summary>
+        /// The craft material value
+        /// </summary>
+        public decimal Value { get; set; }
     }
 }

+ 36 - 0
GreenTree.Strohrmann.ERP.Core/Extension/DecimalExtension.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+namespace GreenTree.Strohrmann.ERP.Core.Extension
+{
+    public static class DecimalExtension
+    {
+        /// <summary>
+        /// Trims trailing zeros of decimal
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The same number without trailing zero decimal places.</returns>
+        public static decimal TrimEnd(this decimal value)
+        {
+            var decimalSplit = value.ToString(CultureInfo.InvariantCulture.NumberFormat).Split('.');
+
+            if (decimalSplit.Length == 1)
+                return value;
+
+            var onlyZero = true;
+
+            for (int i = 0; i < decimalSplit[1].Length; i++)
+            {
+                if (decimalSplit[1][i] != '0')
+                {
+                    onlyZero = false;
+                    break;
+                }
+            }
+
+            return onlyZero ? Convert.ToDecimal(decimalSplit[0]) : value;
+        }
+    }
+}

+ 25 - 0
GreenTree.Strohrmann.ERP.Core/Extension/StringExtension.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace GreenTree.Strohrmann.ERP.Core.Extension
+{
+    public static class StringExtension
+    {
+        /// <summary>
+        /// Évaluates a string between a starting and an endling string part
+        /// </summary>
+        /// <param name="str">Base string.</param>
+        /// <param name="start">Beginning string part.</param>
+        /// <param name="end">Ending string part.</param>
+        public static string Between(this string str, string start, string end)
+        {
+            var startIndex = str.IndexOf(start) + start.Length;
+            var endIndex = str.IndexOf(end, startIndex);
+
+            return end == String.Empty 
+                ? str.Substring(startIndex) 
+                : str[startIndex..endIndex];
+        }
+    }
+}

+ 44 - 0
GreenTree.Strohrmann.ERP.Domain/Extension/DbSetExtension.cs

@@ -0,0 +1,44 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Extension
+{
+    public static class DbSetExtension
+    {
+        /// <summary>
+        /// Removes a sequence of entities from a specific DbSet filtered by a predicate
+        /// </summary>
+        /// <typeparam name="TEntity">Entity type.</typeparam>
+        /// <param name="dbSet">Database DbSet.</param>
+        /// <param name="expression">Filter expression.</param>
+        public static void RemoveWhere<TEntity>(this DbSet<TEntity> dbSet, Expression<Func<TEntity, bool>> expression)
+            where TEntity : class
+        {
+            var entities = dbSet
+                .Where(expression);
+
+            dbSet.RemoveRange(entities);
+        }
+
+        /// <summary>
+        /// Removes a sequence of entities from a specific DbSet filtered by a predicate and inserts a set of new entities for them
+        /// </summary>
+        /// <typeparam name="TEntity">Entity type.</typeparam>
+        /// <param name="dbSet">Database DbSet.</param>
+        /// <param name="expression">Filter expression.</param>
+        /// <param name="newEntities">New entities.</param>
+        public static void ReplaceWhere<TEntity>(this DbSet<TEntity> dbSet, Expression<Func<TEntity, bool>> expression,
+            IEnumerable<TEntity> newEntities)
+            where TEntity : class
+        {
+            RemoveWhere(dbSet, expression);
+
+            dbSet.AddRange(newEntities);
+        }
+    }
+}

+ 14 - 4
GreenTree.Strohrmann.ERP.Domain/GreenTree.Strohrmann.ERP.Domain.csproj

@@ -21,6 +21,20 @@
     <Compile Remove="Migrations\20200721130913_Titles.Designer.cs" />
     <Compile Remove="Migrations\20200721131229_Titles.cs" />
     <Compile Remove="Migrations\20200721131229_Titles.Designer.cs" />
+    <Compile Remove="Migrations\20200726163539_CraftMaterial_Hotfix.cs" />
+    <Compile Remove="Migrations\20200726163539_CraftMaterial_Hotfix.Designer.cs" />
+    <Compile Remove="Migrations\20200727144454_CraftEmployee_Hotfix.cs" />
+    <Compile Remove="Migrations\20200727144454_CraftEmployee_Hotfix.Designer.cs" />
+    <Compile Remove="Migrations\20200727144849_CraftEmployee_Hotfix.cs" />
+    <Compile Remove="Migrations\20200727144849_CraftEmployee_Hotfix.Designer.cs" />
+    <Compile Remove="Migrations\20200727153610_CraftEmployee_Hotfix.cs" />
+    <Compile Remove="Migrations\20200727153610_CraftEmployee_Hotfix.Designer.cs" />
+    <Compile Remove="Migrations\20200727154230_CraftEmployee_Hotfix.cs" />
+    <Compile Remove="Migrations\20200727154230_CraftEmployee_Hotfix.Designer.cs" />
+    <Compile Remove="Migrations\20200727155915_CraftEmployee_Hotfix_2.cs" />
+    <Compile Remove="Migrations\20200727155915_CraftEmployee_Hotfix_2.Designer.cs" />
+    <Compile Remove="Migrations\20200728100718_CraftMaterials_Hotfix.cs" />
+    <Compile Remove="Migrations\20200728100718_CraftMaterials_Hotfix.Designer.cs" />
   </ItemGroup>
 
   <ItemGroup>
@@ -40,8 +54,4 @@
     <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Extension\" />
-  </ItemGroup>
-
 </Project>

+ 727 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200726163658_CraftMaterial_Hotfix.Designer.cs

@@ -0,0 +1,727 @@
+// <auto-generated />
+using System;
+using GreenTree.Strohrmann.ERP.Domain.Model;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    [DbContext(typeof(ERPDbContext))]
+    [Migration("20200726163658_CraftMaterial_Hotfix")]
+    partial class CraftMaterial_Hotfix
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "3.1.5")
+                .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("CustomerId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CustomerId");
+
+                    b.ToTable("Crafts");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("EmployeeId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("CraftId", "EmployeeId");
+
+                    b.HasIndex("EmployeeId");
+
+                    b.ToTable("CraftEmployees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("MaterialId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("CalculationFactor")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("CraftId", "MaterialId");
+
+                    b.HasIndex("MaterialId");
+
+                    b.ToTable("CraftMaterials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CompanyName")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool>("IsBusiness")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(false);
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int?>("TaxId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("TitleId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("TaxId");
+
+                    b.HasIndex("TitleId");
+
+                    b.ToTable("Customers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("EmployeeDegreeId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("EmployeeDegreeId");
+
+                    b.ToTable("Employees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("EmployeeDegrees");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Meister",
+                            Order = 3,
+                            Value = 60m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Geselle",
+                            Order = 2,
+                            Value = 30m
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Aushilfe",
+                            Order = 1,
+                            Value = 15m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("DefaultUnitId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Depth")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Description")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Height")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("ItemNumber")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("NetValue")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("PackageSize")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("decimal(65,30)")
+                        .HasDefaultValue(1m);
+
+                    b.Property<int>("SupplierId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Width")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("DefaultUnitId");
+
+                    b.HasIndex("SupplierId");
+
+                    b.ToTable("Materials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Suppliers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Taxes");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Deutschland Umsatzsteuer",
+                            ShortName = "Umst. (19%)",
+                            Value = 0.19m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Deutschland Umsatzsteuer 2020",
+                            ShortName = "Umst. (16%) 2020",
+                            Value = 0.16m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Titles");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Keiner"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Herr"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Frau"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Name = "Firma"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Name = "Familie"
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Name = "Eheleute"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Name = "Herr und Frau"
+                        },
+                        new
+                        {
+                            Id = 8,
+                            Name = "Prof."
+                        },
+                        new
+                        {
+                            Id = 9,
+                            Name = "Dr."
+                        },
+                        new
+                        {
+                            Id = 10,
+                            Name = "Dr. med."
+                        },
+                        new
+                        {
+                            Id = 11,
+                            Name = "Prof. Dr."
+                        },
+                        new
+                        {
+                            Id = 12,
+                            Name = "Prof. Dr. med."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Units");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 8,
+                            Description = "Angabe in Einheit Milimeter",
+                            Name = "Milimeter",
+                            ShortName = "mm"
+                        },
+                        new
+                        {
+                            Id = 1,
+                            Description = "Angabe in Einheit Meter",
+                            Name = "Meter",
+                            ShortName = "m"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Description = "Angabe in Einheit Quadratmeter",
+                            Name = "Quadratmeter",
+                            ShortName = "m²"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Description = "Angabe in Einheit Kubikmeter",
+                            Name = "Kubikmeter",
+                            ShortName = "m³"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Description = "Angabe in Einheit Liter",
+                            Name = "Liter",
+                            ShortName = "l"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Stück",
+                            ShortName = "Stck."
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Kilogramm",
+                            ShortName = "Kg"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Description = "Angabe in Zeitstunden",
+                            Name = "Stunden",
+                            ShortName = "Std."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.Policy", b =>
+                {
+                    b.Property<string>("Name")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("Name");
+
+                    b.ToTable("Policies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Accountname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool?>("Activated")
+                        .IsRequired()
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(true);
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Forename")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.Property<int>("UserId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("PolicyName")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("UserId", "PolicyName");
+
+                    b.ToTable("UserPolicies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", "Customer")
+                        .WithMany("Crafts")
+                        .HasForeignKey("CustomerId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftEmployees")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", "Employee")
+                        .WithMany()
+                        .HasForeignKey("EmployeeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftMaterials")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", "Material")
+                        .WithMany()
+                        .HasForeignKey("MaterialId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", "Tax")
+                        .WithMany("Customers")
+                        .HasForeignKey("TaxId")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", "Title")
+                        .WithMany("Customers")
+                        .HasForeignKey("TitleId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", "EmployeeDegree")
+                        .WithMany("Employees")
+                        .HasForeignKey("EmployeeDegreeId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", "DefaultUnit")
+                        .WithMany("Materials")
+                        .HasForeignKey("DefaultUnitId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", "Supplier")
+                        .WithMany("Materials")
+                        .HasForeignKey("SupplierId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", "User")
+                        .WithMany("Policies")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 23 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200726163658_CraftMaterial_Hotfix.cs

@@ -0,0 +1,23 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    public partial class CraftMaterial_Hotfix : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<decimal>(
+                name: "Value",
+                table: "CraftMaterials",
+                nullable: false,
+                defaultValue: 0m);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "Value",
+                table: "CraftMaterials");
+        }
+    }
+}

+ 736 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200727154942_CraftEmployee_Hotfix.Designer.cs

@@ -0,0 +1,736 @@
+// <auto-generated />
+using System;
+using GreenTree.Strohrmann.ERP.Domain.Model;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    [DbContext(typeof(ERPDbContext))]
+    [Migration("20200727154942_CraftEmployee_Hotfix")]
+    partial class CraftEmployee_Hotfix
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "3.1.5")
+                .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("CustomerId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CustomerId");
+
+                    b.ToTable("Crafts");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("EmployeeId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CraftId");
+
+                    b.HasIndex("EmployeeId");
+
+                    b.ToTable("CraftEmployees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("MaterialId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("CalculationFactor")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("CraftId", "MaterialId");
+
+                    b.HasIndex("MaterialId");
+
+                    b.ToTable("CraftMaterials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CompanyName")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool>("IsBusiness")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(false);
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int?>("TaxId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("TitleId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("TaxId");
+
+                    b.HasIndex("TitleId");
+
+                    b.ToTable("Customers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("EmployeeDegreeId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("EmployeeDegreeId");
+
+                    b.ToTable("Employees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("EmployeeDegrees");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Meister",
+                            Order = 3,
+                            Value = 60m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Geselle",
+                            Order = 2,
+                            Value = 30m
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Aushilfe",
+                            Order = 1,
+                            Value = 15m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("DefaultUnitId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Depth")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Description")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Height")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("ItemNumber")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("NetValue")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("PackageSize")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("decimal(65,30)")
+                        .HasDefaultValue(1m);
+
+                    b.Property<int>("SupplierId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Width")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("DefaultUnitId");
+
+                    b.HasIndex("SupplierId");
+
+                    b.ToTable("Materials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Suppliers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Taxes");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Deutschland Umsatzsteuer",
+                            ShortName = "Umst. (19%)",
+                            Value = 0.19m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Deutschland Umsatzsteuer 2020",
+                            ShortName = "Umst. (16%) 2020",
+                            Value = 0.16m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Titles");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Keiner"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Herr"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Frau"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Name = "Firma"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Name = "Familie"
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Name = "Eheleute"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Name = "Herr und Frau"
+                        },
+                        new
+                        {
+                            Id = 8,
+                            Name = "Prof."
+                        },
+                        new
+                        {
+                            Id = 9,
+                            Name = "Dr."
+                        },
+                        new
+                        {
+                            Id = 10,
+                            Name = "Dr. med."
+                        },
+                        new
+                        {
+                            Id = 11,
+                            Name = "Prof. Dr."
+                        },
+                        new
+                        {
+                            Id = 12,
+                            Name = "Prof. Dr. med."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Units");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 8,
+                            Description = "Angabe in Einheit Milimeter",
+                            Name = "Milimeter",
+                            ShortName = "mm"
+                        },
+                        new
+                        {
+                            Id = 1,
+                            Description = "Angabe in Einheit Meter",
+                            Name = "Meter",
+                            ShortName = "m"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Description = "Angabe in Einheit Quadratmeter",
+                            Name = "Quadratmeter",
+                            ShortName = "m²"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Description = "Angabe in Einheit Kubikmeter",
+                            Name = "Kubikmeter",
+                            ShortName = "m³"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Description = "Angabe in Einheit Liter",
+                            Name = "Liter",
+                            ShortName = "l"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Stück",
+                            ShortName = "Stck."
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Kilogramm",
+                            ShortName = "Kg"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Description = "Angabe in Zeitstunden",
+                            Name = "Stunden",
+                            ShortName = "Std."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.Policy", b =>
+                {
+                    b.Property<string>("Name")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("Name");
+
+                    b.ToTable("Policies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Accountname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool?>("Activated")
+                        .IsRequired()
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(true);
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Forename")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.Property<int>("UserId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("PolicyName")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("UserId", "PolicyName");
+
+                    b.ToTable("UserPolicies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", "Customer")
+                        .WithMany("Crafts")
+                        .HasForeignKey("CustomerId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftEmployees")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", "Employee")
+                        .WithMany()
+                        .HasForeignKey("EmployeeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftMaterials")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", "Material")
+                        .WithMany()
+                        .HasForeignKey("MaterialId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", "Tax")
+                        .WithMany("Customers")
+                        .HasForeignKey("TaxId")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", "Title")
+                        .WithMany("Customers")
+                        .HasForeignKey("TitleId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", "EmployeeDegree")
+                        .WithMany("Employees")
+                        .HasForeignKey("EmployeeDegreeId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", "DefaultUnit")
+                        .WithMany("Materials")
+                        .HasForeignKey("DefaultUnitId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", "Supplier")
+                        .WithMany("Materials")
+                        .HasForeignKey("SupplierId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", "User")
+                        .WithMany("Policies")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 61 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200727154942_CraftEmployee_Hotfix.cs

@@ -0,0 +1,61 @@
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    public partial class CraftEmployee_Hotfix : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropPrimaryKey(
+                name: "PK_CraftEmployees",
+                table: "CraftEmployees");
+
+            migrationBuilder.AddColumn<int>(
+                name: "Id",
+                table: "CraftEmployees",
+                nullable: false,
+                defaultValue: 0)
+                .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+            migrationBuilder.AddColumn<string>(
+                name: "Comment",
+                table: "CraftEmployees",
+                nullable: true);
+
+            migrationBuilder.AddPrimaryKey(
+                name: "PK_CraftEmployees",
+                table: "CraftEmployees",
+                column: "Id");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CraftEmployees_CraftId",
+                table: "CraftEmployees",
+                column: "CraftId");
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropPrimaryKey(
+                name: "PK_CraftEmployees",
+                table: "CraftEmployees");
+
+            migrationBuilder.DropIndex(
+                name: "IX_CraftEmployees_CraftId",
+                table: "CraftEmployees");
+
+            migrationBuilder.DropColumn(
+                name: "Id",
+                table: "CraftEmployees");
+
+            migrationBuilder.DropColumn(
+                name: "Comment",
+                table: "CraftEmployees");
+
+            migrationBuilder.AddPrimaryKey(
+                name: "PK_CraftEmployees",
+                table: "CraftEmployees",
+                columns: new[] { "CraftId", "EmployeeId" });
+        }
+    }
+}

+ 736 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200727160055_CraftEmployee_Hotfix_2.Designer.cs

@@ -0,0 +1,736 @@
+// <auto-generated />
+using System;
+using GreenTree.Strohrmann.ERP.Domain.Model;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    [DbContext(typeof(ERPDbContext))]
+    [Migration("20200727160055_CraftEmployee_Hotfix_2")]
+    partial class CraftEmployee_Hotfix_2
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "3.1.5")
+                .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("CustomerId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CustomerId");
+
+                    b.ToTable("Crafts");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("EmployeeId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CraftId");
+
+                    b.HasIndex("EmployeeId");
+
+                    b.ToTable("CraftEmployees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("MaterialId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("CalculationFactor")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("CraftId", "MaterialId");
+
+                    b.HasIndex("MaterialId");
+
+                    b.ToTable("CraftMaterials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CompanyName")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool>("IsBusiness")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(false);
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int?>("TaxId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("TitleId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("TaxId");
+
+                    b.HasIndex("TitleId");
+
+                    b.ToTable("Customers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("EmployeeDegreeId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("EmployeeDegreeId");
+
+                    b.ToTable("Employees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("EmployeeDegrees");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Meister",
+                            Order = 3,
+                            Value = 60m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Geselle",
+                            Order = 2,
+                            Value = 30m
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Aushilfe",
+                            Order = 1,
+                            Value = 15m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("DefaultUnitId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Depth")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Description")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Height")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("ItemNumber")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("NetValue")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("PackageSize")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("decimal(65,30)")
+                        .HasDefaultValue(1m);
+
+                    b.Property<int>("SupplierId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Width")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("DefaultUnitId");
+
+                    b.HasIndex("SupplierId");
+
+                    b.ToTable("Materials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Suppliers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Taxes");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Deutschland Umsatzsteuer",
+                            ShortName = "Umst. (19%)",
+                            Value = 0.19m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Deutschland Umsatzsteuer 2020",
+                            ShortName = "Umst. (16%) 2020",
+                            Value = 0.16m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Titles");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Keiner"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Herr"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Frau"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Name = "Firma"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Name = "Familie"
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Name = "Eheleute"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Name = "Herr und Frau"
+                        },
+                        new
+                        {
+                            Id = 8,
+                            Name = "Prof."
+                        },
+                        new
+                        {
+                            Id = 9,
+                            Name = "Dr."
+                        },
+                        new
+                        {
+                            Id = 10,
+                            Name = "Dr. med."
+                        },
+                        new
+                        {
+                            Id = 11,
+                            Name = "Prof. Dr."
+                        },
+                        new
+                        {
+                            Id = 12,
+                            Name = "Prof. Dr. med."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Units");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 8,
+                            Description = "Angabe in Einheit Milimeter",
+                            Name = "Milimeter",
+                            ShortName = "mm"
+                        },
+                        new
+                        {
+                            Id = 1,
+                            Description = "Angabe in Einheit Meter",
+                            Name = "Meter",
+                            ShortName = "m"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Description = "Angabe in Einheit Quadratmeter",
+                            Name = "Quadratmeter",
+                            ShortName = "m²"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Description = "Angabe in Einheit Kubikmeter",
+                            Name = "Kubikmeter",
+                            ShortName = "m³"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Description = "Angabe in Einheit Liter",
+                            Name = "Liter",
+                            ShortName = "l"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Stück",
+                            ShortName = "Stck."
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Kilogramm",
+                            ShortName = "Kg"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Description = "Angabe in Zeitstunden",
+                            Name = "Stunden",
+                            ShortName = "Std."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.Policy", b =>
+                {
+                    b.Property<string>("Name")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("Name");
+
+                    b.ToTable("Policies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Accountname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool?>("Activated")
+                        .IsRequired()
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(true);
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Forename")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.Property<int>("UserId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("PolicyName")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("UserId", "PolicyName");
+
+                    b.ToTable("UserPolicies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", "Customer")
+                        .WithMany("Crafts")
+                        .HasForeignKey("CustomerId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftEmployees")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", "Employee")
+                        .WithMany()
+                        .HasForeignKey("EmployeeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftMaterials")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", "Material")
+                        .WithMany()
+                        .HasForeignKey("MaterialId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", "Tax")
+                        .WithMany("Customers")
+                        .HasForeignKey("TaxId")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", "Title")
+                        .WithMany("Customers")
+                        .HasForeignKey("TitleId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", "EmployeeDegree")
+                        .WithMany("Employees")
+                        .HasForeignKey("EmployeeDegreeId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", "DefaultUnit")
+                        .WithMany("Materials")
+                        .HasForeignKey("DefaultUnitId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", "Supplier")
+                        .WithMany("Materials")
+                        .HasForeignKey("SupplierId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", "User")
+                        .WithMany("Policies")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 25 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200727160055_CraftEmployee_Hotfix_2.cs

@@ -0,0 +1,25 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    public partial class CraftEmployee_Hotfix_2 : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddForeignKey(
+                table: "CraftEmployees",
+                name: "FK_CraftEmployees_Crafts_CraftId",
+                column: "CraftId",
+                principalTable: "Crafts",
+                principalColumn: "Id",
+                onDelete: ReferentialAction.Cascade);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropForeignKey(
+                table: "CraftEmployees",
+                name: "FK_CraftEmployees_Crafts_CraftId");
+        }
+    }
+}

+ 739 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200731124621_Craft_Comment.Designer.cs

@@ -0,0 +1,739 @@
+// <auto-generated />
+using System;
+using GreenTree.Strohrmann.ERP.Domain.Model;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    [DbContext(typeof(ERPDbContext))]
+    [Migration("20200731124621_Craft_Comment")]
+    partial class Craft_Comment
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "3.1.5")
+                .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("CustomerId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CustomerId");
+
+                    b.ToTable("Crafts");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("EmployeeId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CraftId");
+
+                    b.HasIndex("EmployeeId");
+
+                    b.ToTable("CraftEmployees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.Property<int>("CraftId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("MaterialId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("CalculationFactor")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("CraftId", "MaterialId");
+
+                    b.HasIndex("MaterialId");
+
+                    b.ToTable("CraftMaterials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CompanyName")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool>("IsBusiness")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(false);
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int?>("TaxId")
+                        .HasColumnType("int");
+
+                    b.Property<int>("TitleId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("TaxId");
+
+                    b.HasIndex("TitleId");
+
+                    b.ToTable("Customers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("EmployeeDegreeId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Firstname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("EmployeeDegreeId");
+
+                    b.ToTable("Employees");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<int>("Order")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("EmployeeDegrees");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Meister",
+                            Order = 3,
+                            Value = 60m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Geselle",
+                            Order = 2,
+                            Value = 30m
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Aushilfe",
+                            Order = 1,
+                            Value = 15m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int>("DefaultUnitId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Depth")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Description")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Height")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("ItemNumber")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("NetValue")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<decimal>("PackageSize")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("decimal(65,30)")
+                        .HasDefaultValue(1m);
+
+                    b.Property<int>("SupplierId")
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Width")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("DefaultUnitId");
+
+                    b.HasIndex("SupplierId");
+
+                    b.ToTable("Materials");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Address")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ChangedBy")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime?>("ChangedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Country")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("CreatedBy")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<DateTime>("CreatedOn")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneFirst")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("PhoneSecond")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Town")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ZipCode")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Suppliers");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Taxes");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Deutschland Umsatzsteuer",
+                            ShortName = "Umst. (19%)",
+                            Value = 0.19m
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Deutschland Umsatzsteuer 2020",
+                            ShortName = "Umst. (16%) 2020",
+                            Value = 0.16m
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Titles");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 1,
+                            Name = "Keiner"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Name = "Herr"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Name = "Frau"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Name = "Firma"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Name = "Familie"
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Name = "Eheleute"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Name = "Herr und Frau"
+                        },
+                        new
+                        {
+                            Id = 8,
+                            Name = "Prof."
+                        },
+                        new
+                        {
+                            Id = 9,
+                            Name = "Dr."
+                        },
+                        new
+                        {
+                            Id = 10,
+                            Name = "Dr. med."
+                        },
+                        new
+                        {
+                            Id = 11,
+                            Name = "Prof. Dr."
+                        },
+                        new
+                        {
+                            Id = 12,
+                            Name = "Prof. Dr. med."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Description")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("ShortName")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Units");
+
+                    b.HasData(
+                        new
+                        {
+                            Id = 8,
+                            Description = "Angabe in Einheit Milimeter",
+                            Name = "Milimeter",
+                            ShortName = "mm"
+                        },
+                        new
+                        {
+                            Id = 1,
+                            Description = "Angabe in Einheit Meter",
+                            Name = "Meter",
+                            ShortName = "m"
+                        },
+                        new
+                        {
+                            Id = 2,
+                            Description = "Angabe in Einheit Quadratmeter",
+                            Name = "Quadratmeter",
+                            ShortName = "m²"
+                        },
+                        new
+                        {
+                            Id = 3,
+                            Description = "Angabe in Einheit Kubikmeter",
+                            Name = "Kubikmeter",
+                            ShortName = "m³"
+                        },
+                        new
+                        {
+                            Id = 4,
+                            Description = "Angabe in Einheit Liter",
+                            Name = "Liter",
+                            ShortName = "l"
+                        },
+                        new
+                        {
+                            Id = 5,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Stück",
+                            ShortName = "Stck."
+                        },
+                        new
+                        {
+                            Id = 6,
+                            Description = "Angabe in Stückzahl",
+                            Name = "Kilogramm",
+                            ShortName = "Kg"
+                        },
+                        new
+                        {
+                            Id = 7,
+                            Description = "Angabe in Zeitstunden",
+                            Name = "Stunden",
+                            ShortName = "Std."
+                        });
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.Policy", b =>
+                {
+                    b.Property<string>("Name")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("Name");
+
+                    b.ToTable("Policies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("Accountname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<bool?>("Activated")
+                        .IsRequired()
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("tinyint(1)")
+                        .HasDefaultValue(true);
+
+                    b.Property<DateTime?>("Birthdate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Forename")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Lastname")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("MailAddress")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.Property<int>("UserId")
+                        .HasColumnType("int");
+
+                    b.Property<string>("PolicyName")
+                        .HasColumnType("varchar(255) CHARACTER SET utf8mb4");
+
+                    b.HasKey("UserId", "PolicyName");
+
+                    b.ToTable("UserPolicies");
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", "Customer")
+                        .WithMany("Crafts")
+                        .HasForeignKey("CustomerId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftEmployees")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", "Employee")
+                        .WithMany()
+                        .HasForeignKey("EmployeeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftMaterial", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Craft", "Craft")
+                        .WithMany("CraftMaterials")
+                        .HasForeignKey("CraftId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", "Material")
+                        .WithMany()
+                        .HasForeignKey("MaterialId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Customer", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Tax", "Tax")
+                        .WithMany("Customers")
+                        .HasForeignKey("TaxId")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Title", "Title")
+                        .WithMany("Customers")
+                        .HasForeignKey("TitleId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Employee", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.EmployeeDegree", "EmployeeDegree")
+                        .WithMany("Employees")
+                        .HasForeignKey("EmployeeDegreeId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.Material", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Unit", "DefaultUnit")
+                        .WithMany("Materials")
+                        .HasForeignKey("DefaultUnitId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Business.Supplier", "Supplier")
+                        .WithMany("Materials")
+                        .HasForeignKey("SupplierId")
+                        .OnDelete(DeleteBehavior.Restrict)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Rights.UserPolicy", b =>
+                {
+                    b.HasOne("GreenTree.Strohrmann.ERP.Core.Domain.Rights.User", "User")
+                        .WithMany("Policies")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}

+ 22 - 0
GreenTree.Strohrmann.ERP.Domain/Migrations/20200731124621_Craft_Comment.cs

@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace GreenTree.Strohrmann.ERP.Domain.Migrations
+{
+    public partial class Craft_Comment : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AddColumn<string>(
+                name: "Comment",
+                table: "Crafts",
+                nullable: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropColumn(
+                name: "Comment",
+                table: "Crafts");
+        }
+    }
+}

+ 19 - 4
GreenTree.Strohrmann.ERP.Domain/Migrations/ERPDbContextModelSnapshot.cs

@@ -29,6 +29,9 @@ namespace GreenTree.Strohrmann.ERP.Domain.Migrations
                     b.Property<DateTime?>("ChangedOn")
                         .HasColumnType("datetime(6)");
 
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
                     b.Property<string>("CreatedBy")
                         .IsRequired()
                         .HasColumnType("longtext CHARACTER SET utf8mb4");
@@ -55,19 +58,28 @@ namespace GreenTree.Strohrmann.ERP.Domain.Migrations
 
             modelBuilder.Entity("GreenTree.Strohrmann.ERP.Core.Domain.Business.CraftEmployee", b =>
                 {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("Comment")
+                        .HasColumnType("longtext CHARACTER SET utf8mb4");
+
                     b.Property<int>("CraftId")
                         .HasColumnType("int");
 
                     b.Property<int>("EmployeeId")
                         .HasColumnType("int");
 
-                    b.Property<decimal>("Amount")
-                        .HasColumnType("decimal(65,30)");
-
                     b.Property<decimal>("Value")
                         .HasColumnType("decimal(65,30)");
 
-                    b.HasKey("CraftId", "EmployeeId");
+                    b.HasKey("Id");
+
+                    b.HasIndex("CraftId");
 
                     b.HasIndex("EmployeeId");
 
@@ -88,6 +100,9 @@ namespace GreenTree.Strohrmann.ERP.Domain.Migrations
                     b.Property<decimal>("CalculationFactor")
                         .HasColumnType("decimal(65,30)");
 
+                    b.Property<decimal>("Value")
+                        .HasColumnType("decimal(65,30)");
+
                     b.HasKey("CraftId", "MaterialId");
 
                     b.HasIndex("MaterialId");

+ 13 - 2
GreenTree.Strohrmann.ERP.Domain/Model/Business/CraftEmployeeMapping.cs

@@ -14,13 +14,24 @@ namespace GreenTree.Strohrmann.ERP.Domain.Model.Business
         {
             builder.ToTable("CraftEmployees");
 
-            builder.HasKey(ce => new { ce.CraftId, ce.EmployeeId });
+            builder.HasKey(ce => ce.Id);
+
+            builder.Property(ce => ce.Id)
+                .ValueGeneratedOnAdd();
+
+            builder.Property(ce => ce.Amount)
+                .IsRequired();
 
             builder.Property(ce => ce.Value)
                 .IsRequired();
 
+            builder.Property(ce => ce.Comment)
+                .IsRequired(false);
+
             builder.HasOne(rp => rp.Craft)
-                .WithMany(r => r.CraftEmployees);
+                .WithMany(r => r.CraftEmployees)
+                .HasForeignKey(rp => rp.CraftId)
+                .IsRequired();
         }
     }
 }

+ 3 - 0
GreenTree.Strohrmann.ERP.Domain/Model/Business/CraftMapping.cs

@@ -27,6 +27,9 @@ namespace GreenTree.Strohrmann.ERP.Domain.Model.Business
             builder.Property(u => u.CreationDate)
                 .IsRequired();
 
+            builder.Property(u => u.Comment)
+                .IsRequired(false);
+
             builder.HasOne(u => u.Customer)
                 .WithMany(d => d.Crafts)
                 .IsRequired()

+ 6 - 0
GreenTree.Strohrmann.ERP.Domain/Model/Business/CraftMaterialMapping.cs

@@ -16,9 +16,15 @@ namespace GreenTree.Strohrmann.ERP.Domain.Model.Business
 
             builder.HasKey(cm => new { cm.CraftId, cm.MaterialId });
 
+            builder.Property(cm => cm.Amount)
+                .IsRequired();  
+
             builder.Property(cm => cm.CalculationFactor)
                 .IsRequired();
 
+            builder.Property(cm => cm.Value)
+                .IsRequired();
+
             builder.HasOne(rp => rp.Craft)
                 .WithMany(r => r.CraftMaterials);
         }

+ 191 - 26
GreenTree.Strohrmann.ERP.Web/Controllers/CraftController.cs

@@ -4,12 +4,15 @@ using System.Linq;
 using System.Net.Http;
 using System.Threading.Tasks;
 using GreenTree.Strohrmann.ERP.Core.Domain.Business;
+using GreenTree.Strohrmann.ERP.Core.Extension;
 using GreenTree.Strohrmann.ERP.Core.Helper;
+using GreenTree.Strohrmann.ERP.Domain.Extension;
 using GreenTree.Strohrmann.ERP.Domain.Model;
 using GreenTree.Strohrmann.ERP.Services.Geolocator;
 using GreenTree.Strohrmann.ERP.Web.Extension;
 using GreenTree.Strohrmann.ERP.Web.Models.Business;
 using GreenTree.Strohrmann.ERP.Web.Models.Rights.User;
+using GreenTree.Strohrmann.ERP.Web.Validators;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 
@@ -63,9 +66,8 @@ namespace GreenTree.Strohrmann.ERP.Web.Controllers
         // GET: CraftController/Create
         public ActionResult Create()
         {
-            ViewData.AddSelectList("AvailableEmployees",
-                _eRPDbContext.Employees,
-                e => e.Id, e => String.Format("{0} {1}", e.Firstname, e.Lastname));
+            AddEmployeeListForSelection();
+            AddMaterialListForSelection();
 
             return View();
         }
@@ -77,37 +79,63 @@ namespace GreenTree.Strohrmann.ERP.Web.Controllers
         {
             if (!ModelState.IsValid)
             {
-                ViewData.AddSelectList("AvailableEmployees",
-                    _eRPDbContext.Employees,
-                    e => e.Id, e => String.Format("{0} {1}", e.Firstname, e.Lastname));
+                AddEmployeeListForSelection();
+                AddMaterialListForSelection();
+
+                foreach (var item in model.CraftMaterials)
+                {
+                    if (item.Value.Amount % 1 != 0)
+                        item.Value.Amount /= 10;
+
+                    item.Value.CalculationFactor = item.Value.CalculationFactor / 100;
+                }
 
                 return View(model);
             }
 
-            //var craft = new Craft
-            //{
-            //    CreatedBy = User.Identity.Name,
-            //    CreatedOn = DateTime.Now
-            //};
-
-            //_eRPDbContext.Crafts.Add(craft);
-            //_eRPDbContext.SaveChanges();
+            var craft = new Craft
+            {
+                Name = model.Name,
+                CreationDate = model.CreationDate,
+                Customer = _eRPDbContext.Customers.Find(model.CustomerId),
+                CreatedBy = User.Identity.Name,
+                CreatedOn = DateTime.Now
+            };
+
+            craft.CraftEmployees = new List<CraftEmployee>(
+                model.CraftEmployees
+                    .Select(ce => new CraftEmployee
+                    {
+                        Craft = craft,
+                        Employee = _eRPDbContext.Employees.Find(ce.Value.EmployeeId),
+                        Amount = ce.Value.Amount,
+                        Value = Convert.ToDecimal(ce.Value.Value),
+                        Comment = ce.Value.Comment
+                    }));
+
+            craft.CraftMaterials = new List<CraftMaterial>(
+                model.CraftMaterials
+                    .GroupBy(cm => cm.Value.MaterialId)
+                    .Select(cm => new CraftMaterial
+                    {
+                        Craft = craft,
+                        Material = _eRPDbContext.Materials.Find(cm.Key),
+                        Amount = cm.Sum(v => v.Value.Amount),
+                        CalculationFactor = cm.Average(v => v.Value.CalculationFactor / 100),
+                        Value = cm.Sum(v => Convert.ToDecimal(v.Value.Value))
+                    }));
+
+            _eRPDbContext.Crafts.Add(craft);
+            _eRPDbContext.SaveChanges();
 
             return RedirectToAction(nameof(Index));
         }
 
-        // GET: CraftController/AddCraftEmployeePartial
-        public ActionResult AddCraftEmployeePartial(CraftEmployeeModel craftEmployeeModel)
-        {
-            return PartialView("~/Views/Craft/_CraftEmployeePartial.cshtml", craftEmployeeModel);
-        }
-
         // GET: CraftController/Edit/5
         public ActionResult Edit(int id)
         {
-            ViewData.AddSelectList("AvailableEmployees",
-                _eRPDbContext.Employees,
-                e => e.Id, e => String.Format("{0} {1}", e.Firstname, e.Lastname));
+            AddEmployeeListForSelection();
+            AddMaterialListForSelection();
 
             var craft = _eRPDbContext.Crafts
                 .FirstOrDefault(c => c.Id == id);
@@ -124,9 +152,16 @@ namespace GreenTree.Strohrmann.ERP.Web.Controllers
         {
             if (!ModelState.IsValid)
             {
-                ViewData.AddSelectList("AvailableEmployees",
-                    _eRPDbContext.Employees,
-                    e => e.Id, e => String.Format("{0} {1}", e.Firstname, e.Lastname));
+                AddEmployeeListForSelection();
+                AddMaterialListForSelection();
+
+                foreach (var item in model.CraftMaterials)
+                {
+                    if (item.Value.Amount % 1 != 0)
+                        item.Value.Amount /= 10;
+
+                    item.Value.CalculationFactor = item.Value.CalculationFactor / 100;
+                }
 
                 return View(model);
             }
@@ -134,8 +169,35 @@ namespace GreenTree.Strohrmann.ERP.Web.Controllers
             var craft = _eRPDbContext.Crafts
                 .FirstOrDefault(u => u.Id == id);
 
+            craft.Name = model.Name;
+            craft.CreationDate = model.CreationDate;
+            craft.Customer = _eRPDbContext.Customers.Find(model.CustomerId);
             craft.ChangedBy = User.Identity.Name;
             craft.ChangedOn = DateTime.Now;
+            craft.CraftEmployees.Clear();
+            craft.CraftMaterials.Clear();
+            craft.CraftEmployees = new List<CraftEmployee>(
+                model.CraftEmployees
+                    .Select(ce => new CraftEmployee
+                    {
+                        Craft = craft,
+                        Employee = _eRPDbContext.Employees.Find(ce.Value.EmployeeId),
+                        Amount = ce.Value.Amount,
+                        Value = Convert.ToDecimal(ce.Value.Value),
+                        Comment = ce.Value.Comment
+                    }));
+
+            craft.CraftMaterials = new List<CraftMaterial>(
+                model.CraftMaterials
+                    .GroupBy(cm => cm.Value.MaterialId)
+                    .Select(cm => new CraftMaterial
+                    {
+                        Craft = craft,
+                        Material = _eRPDbContext.Materials.Find(cm.Key),
+                        Amount = cm.Sum(v => v.Value.Amount),
+                        CalculationFactor = cm.Average(v => v.Value.CalculationFactor / 100),
+                        Value = cm.Sum(v => Convert.ToDecimal(v.Value.Value))
+                    }));
 
             _eRPDbContext.SaveChanges();
 
@@ -157,5 +219,108 @@ namespace GreenTree.Strohrmann.ERP.Web.Controllers
         }
 
         #endregion
+
+        #region Partials
+
+        // GET: CraftController/AddCraftEmployeePartial
+        public ActionResult AddCraftEmployeePartial(CraftEmployeeModel craftEmployeeModel)
+        {
+            AddEmployeeListForSelection();
+
+            ModelState.Clear();
+
+            return PartialView("~/Views/Craft/_CraftEmployeePartial.cshtml", craftEmployeeModel);
+        }
+
+        // GET: CraftController/AddCraftMaterialPartial
+        public ActionResult AddCraftMaterialPartial(CraftMaterialModel craftMaterialModel)
+        {
+            AddMaterialListForSelection();
+
+            craftMaterialModel.CalculationFactor = 1.2m;
+
+            return PartialView("~/Views/Craft/_CraftMaterialPartial.cshtml", craftMaterialModel);
+        }
+
+        #endregion
+
+        #region Values
+
+        // POST: CraftController/CalculateEmployeeValue
+        [HttpPost]
+        public ActionResult CalculateEmployeeValue(CraftEmployeeModel craftEmployeeModel)
+        {
+            if (craftEmployeeModel == null)
+                return Ok(0);
+
+            if (craftEmployeeModel.EmployeeId == default)
+                return Ok(0);
+
+            var employee = _eRPDbContext.Employees.Find(craftEmployeeModel.EmployeeId);
+            var result = employee.EmployeeDegree.Value * craftEmployeeModel.Amount;
+
+            return Ok(result);
+        }
+
+        // POST: CraftController/CalculateMaterialValue
+        [HttpPost]
+        public ActionResult CalculateMaterialValue(CraftMaterialModel craftMaterialModel)
+        {
+            if (craftMaterialModel == null)
+                return Ok(0);
+
+            if (craftMaterialModel.MaterialId == default)
+                return Ok(0);
+
+            var material = _eRPDbContext.Materials.Find(craftMaterialModel.MaterialId);
+            var result = material.NetValue * craftMaterialModel.Amount * (craftMaterialModel.CalculationFactor / 100);
+
+            return Ok(result);
+        }
+
+        // POST: CraftController/CalculateMaterialCalculationFactor
+        [HttpPost]
+        public ActionResult CalculateMaterialCalculationFactor(CraftMaterialModel craftMaterialModel)
+        {
+            if (craftMaterialModel == null)
+                return Ok(0);
+
+            if (craftMaterialModel.MaterialId == default)
+                return Ok(0);
+
+            var material = _eRPDbContext.Materials.Find(craftMaterialModel.MaterialId);
+            var result = Convert.ToDecimal(craftMaterialModel.Value) / (material.NetValue * craftMaterialModel.Amount) * 100;
+
+            return Ok(result);
+        }
+
+        #endregion
+
+        #region Helper
+
+        /// <summary>
+        /// Adds the employee SelectListItem collection to the current ViewData dictionary
+        /// </summary>
+        private void AddEmployeeListForSelection()
+        {
+            ViewData.AddSelectList("AvailableEmployees",
+                _eRPDbContext.Employees
+                    .ToList()
+                    .Select(e => new EmployeeModel(e)),
+                e => e.Id, e => String.Format("{0} {1} ({2} - {3:n0}€ / Std.)",
+                    e.Firstname, e.Lastname, e.EmployeeDegree.Name, e.EmployeeDegree.Value));
+        }
+
+        /// <summary>
+        /// Adds the material SelectListItem collection to the current ViewData dictionary
+        /// </summary>
+        private void AddMaterialListForSelection()
+        {
+            ViewData.AddSelectList("AvailableMaterials",
+                _eRPDbContext.Materials,
+                m => m.Id, e => String.Format("{0} ({1})", e.Name, e.ItemNumber));
+        }
+
+        #endregion
     }
 }

+ 10 - 3
GreenTree.Strohrmann.ERP.Web/Controllers/CustomerController.cs

@@ -161,6 +161,11 @@ namespace GreenTree.Strohrmann.ERP.Web.Controllers
             return RedirectToAction(nameof(Index));
         }
 
+        #endregion
+
+        #region Partials
+
+
         // POST: CustomerController/Search/*term*
         [HttpPost]
         public ActionResult Search(SearchModel search)
@@ -168,10 +173,12 @@ namespace GreenTree.Strohrmann.ERP.Web.Controllers
             if (search == null)
                 return new JsonResult(null);
 
+            var words = search.SearchTerm.Split(' ');
+
             var result = _eRPDbContext.Customers
-                .Where(c => c.Firstname.Contains(search.SearchTerm, StringComparison.OrdinalIgnoreCase) ||
-                            c.Lastname.Contains(search.SearchTerm, StringComparison.OrdinalIgnoreCase) ||
-                            c.CompanyName.Contains(search.SearchTerm, StringComparison.OrdinalIgnoreCase))
+                .Where(c => words.Contains(c.Firstname) ||
+                            words.Contains(c.Lastname) ||
+                            words.Contains(c.CompanyName))
                 .ToArray()
                 .Select(c => new CustomerModel(c));
 

+ 28 - 0
GreenTree.Strohrmann.ERP.Web/Extension/HtmlContentExtension.cs

@@ -226,6 +226,26 @@ namespace GreenTree.Strohrmann.ERP.Web.Extension
             return new HtmlString(selectBuilder.ToString());
         }
 
+        /// <summary>
+        /// Generates a Span HTML element
+        /// </summary>
+        /// <param name="htmlHelper">HtmlHelper context.</param>
+        /// <param name="content">The span content text.</param>
+        /// <param name="htmlAttributes">Additional HTML attributes.</param>
+        /// <returns></returns>
+        public static IHtmlContent Span(this IHtmlHelper htmlHelper, string content, object htmlAttributes = null)
+        {
+            var attributes = htmlAttributes == null
+                ? new string[0]
+                : htmlAttributes.GetType().GetProperties()
+                    .Select(p => String.Format("{0}='{1}'", p.Name.Replace("_", "-"), p.GetValue(htmlAttributes)))
+                    .ToArray();
+
+            var htmlString = String.Format("<span {0}>{1}</span>", String.Join(" ", attributes), content);
+
+            return new HtmlString(htmlString);
+        }
+
         #endregion
 
         #region Helper
@@ -239,6 +259,14 @@ namespace GreenTree.Strohrmann.ERP.Web.Extension
             return Guid.NewGuid().ToShortString();
         }
 
+        /// <summary>
+        /// Generates a random short ID string
+        /// </summary>
+        public static string RandomId()
+        {
+            return Guid.NewGuid().ToShortString();
+        }
+
         /// <summary>
         /// Converts an object in a JS literal object format
         /// </summary>

+ 20 - 1
GreenTree.Strohrmann.ERP.Web/Models/Business/CraftEmployeeModel.cs

@@ -15,7 +15,17 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         /// <summary>
         /// Craft employee model index
         /// </summary>
-        public int Index { get; set; }
+        public int? Index { get; set; }
+
+        /// <summary>
+        /// Craft employee Dictionary identifier
+        /// </summary>
+        public string DictIdentifier { get; set; }
+
+        /// <summary>
+        /// Craft employee id
+        /// </summary>
+        public int Id { get; set; }
 
         /// <summary>
         /// Craft id
@@ -51,8 +61,15 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         /// The value of the employee working hours
         /// </summary>
         [Display(Name = "Wert")]
+        [DisplayFormat(ApplyFormatInEditMode = false, DataFormatString = "{0:C}")]
         public float Value { get; set; }
 
+        /// <summary>
+        /// Craft employee comment
+        /// </summary>
+        [Display(Name = "Kommentar")]
+        public string Comment { get; set; }
+
         #endregion
 
         #region Ctor
@@ -70,10 +87,12 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         {
             if (craftEmployee == null) return;
 
+            Id = craftEmployee.Id;
             CraftId = craftEmployee.CraftId;
             EmployeeId = craftEmployee.EmployeeId;
             Amount = craftEmployee.Amount;
             Value = Convert.ToSingle(craftEmployee.Value);
+            Comment = craftEmployee.Comment;
         }
 
         #endregion

+ 17 - 3
GreenTree.Strohrmann.ERP.Web/Models/Business/CraftMaterialModel.cs

@@ -13,9 +13,14 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         #region Properties
 
         /// <summary>
-        /// Craft employee model index
+        /// Craft material model index
         /// </summary>
-        public int Index { get; set; }
+        public int? Index { get; set; }
+
+        /// <summary>
+        /// Craft material Dictionary identifier
+        /// </summary>
+        public string DictIdentifier { get; set; }
 
         /// <summary>
         /// Craft id
@@ -32,7 +37,7 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         /// <summary>
         /// Material id
         /// </summary>
-        [Display(Name = "Material ID")]
+        [Display(Name = "Material")]
         public int MaterialId { get; set; }
 
         /// <summary>
@@ -51,8 +56,16 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         /// The material calculation factor
         /// </summary>
         [Display(Name = "Kalkulationsfaktor")]
+        [DisplayFormat(DataFormatString = "{0:P0}")]
         public decimal CalculationFactor { get; set; }
 
+        /// <summary>
+        /// The value of the employee working hours
+        /// </summary>
+        [Display(Name = "Wert")]
+        [DisplayFormat(ApplyFormatInEditMode = false, DataFormatString = "{0:C}")]
+        public float Value { get; set; }
+
         #endregion
 
         #region Ctor
@@ -74,6 +87,7 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
             MaterialId = craftMaterial.MaterialId;
             Amount = craftMaterial.Amount;
             CalculationFactor = craftMaterial.CalculationFactor;
+            Value = Convert.ToSingle(craftMaterial.Value);
         }
 
         #endregion

+ 49 - 4
GreenTree.Strohrmann.ERP.Web/Models/Business/CraftModel.cs

@@ -1,5 +1,8 @@
 using GreenTree.Strohrmann.ERP.Core.Domain.Business;
+using GreenTree.Strohrmann.ERP.Web.Extension;
 using GreenTree.Strohrmann.ERP.Web.Models.Search;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ViewFeatures;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
@@ -28,6 +31,7 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         /// Craft creation date
         /// </summary>
         [Display(Name = "Gestartet am")]
+        [DisplayFormat(ApplyFormatInEditMode = false, DataFormatString = "{0:dd.MM.yyyy}")]
         public DateTime CreationDate { get; set; }
 
         /// <summary>
@@ -39,19 +43,58 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
         /// <summary>
         /// Craft customer id
         /// </summary>
+        [Display(Name = "Kunde")]
         public int CustomerId { get; set; }
 
+        /// <summary>
+        /// Craft customer text
+        /// </summary>
+        [Display(Name = "Kundenname")]
+        public string CustomerText { get; set; }
+
+        /// <summary>
+        /// Craft comment
+        /// </summary>
+        [Display(Name = "Kommentar")]
+        public string Comment { get; set; }
+
         /// <summary>
         /// Craft employees
         /// </summary>
         [Display(Name = "Stunden")]
-        public List<CraftEmployeeModel> CraftEmployees { get; set; }
+        public Dictionary<string, CraftEmployeeModel> CraftEmployees { get; set; }
+
+        /// <summary>
+        /// Craft employee value sum
+        /// </summary>
+        [Display(Name = "Wert (Stunden)")]
+        [DisplayFormat(DataFormatString = "{0:c2}")]
+        public float CraftEmployeeValue 
+        { 
+            get
+            {
+                return CraftEmployees.Sum(ce => ce.Value.Value);
+            }
+        }
 
         /// <summary>
         /// Craft materials
         /// </summary>
         [Display(Name = "Material")]
-        public List<CraftMaterialModel> CraftMaterials { get; set; }
+        public Dictionary<string, CraftMaterialModel> CraftMaterials { get; set; }
+
+        /// <summary>
+        /// Craft material value sum
+        /// </summary>
+        [Display(Name = "Wert (Material)")]
+        [DisplayFormat(DataFormatString = "{0:c2}")]
+        public float CraftMaterialValue
+        {
+            get
+            {
+                return CraftMaterials.Sum(ce => ce.Value.Value);
+            }
+        }
 
         #endregion
 
@@ -74,13 +117,15 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Business
             Name = craft.Name;
             CreationDate = craft.CreationDate;
             Customer = new CustomerModel(craft.Customer);
+            CustomerText = Customer.Fullname;
             CustomerId = craft.Customer.Id;
+            Comment = craft.Comment;
             CraftEmployees = craft.CraftEmployees
                 .Select(ce => new CraftEmployeeModel(ce))
-                .ToList();
+                .ToDictionary(ce => HtmlContentExtension.RandomId(), ce => ce);
             CraftMaterials = craft.CraftMaterials
                 .Select(cm => new CraftMaterialModel(cm))
-                .ToList();
+                .ToDictionary(cm => HtmlContentExtension.RandomId(), cm => cm);
         }
 
         #endregion

+ 8 - 0
GreenTree.Strohrmann.ERP.Web/Models/Search/ICustomerSearchable.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
 using System.Linq;
 using System.Threading.Tasks;
 
@@ -10,6 +11,13 @@ namespace GreenTree.Strohrmann.ERP.Web.Models.Search
         /// <summary>
         /// Model class searchable for customer id
         /// </summary>
+        [Display(Name = "Kunde")]
         public int CustomerId { get; set; }
+
+        /// <summary>
+        /// Model class searchable for customer text
+        /// </summary>
+        [Display(Name = "Kundenname")]
+        public string CustomerText { get; set; }
     }
 }

+ 49 - 0
GreenTree.Strohrmann.ERP.Web/Validators/CraftEmployeeValidator.cs

@@ -0,0 +1,49 @@
+using FluentValidation;
+using GreenTree.Strohrmann.ERP.Domain.Model;
+using GreenTree.Strohrmann.ERP.Web.Models.Business;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace GreenTree.Strohrmann.ERP.Web.Validators
+{
+	public class CraftEmployeeValidator : AbstractValidator<KeyValuePair<string, CraftEmployeeModel>>
+	{
+		#region DI fields
+
+		// The global DbContext
+		private readonly ERPDbContext _eRPDbContext;
+
+		#endregion
+
+		#region Ctor
+
+		/// <summary>
+		/// Initializes a new instance of the CraftEmployeeValidator class
+		/// </summary>
+		/// <param name="eRPDbContext">Global DbContext.</param>
+		public CraftEmployeeValidator(
+			ERPDbContext eRPDbContext)
+		{
+			_eRPDbContext = eRPDbContext;
+
+			RuleFor(m => m.Value)
+				.Custom((val, ctx) =>
+				{
+					if (val.EmployeeId == 0)
+						ctx.AddFailure("EmployeeId", "Ein Mitarbeiter muss gewählt werden.");
+
+					if (val.Amount <= 0)
+						ctx.AddFailure(
+							String.Format("CraftEmployees[{0}].Amount", val.DictIdentifier), "'Dauer' muss größer als 0 sein.");
+
+					if (val.Value <= 0)
+						ctx.AddFailure(
+							String.Format("CraftEmployees[{0}].Value", val.DictIdentifier), "'Wert' muss größer als 0 sein.");
+				});
+		}
+
+        #endregion
+    }
+}

+ 53 - 0
GreenTree.Strohrmann.ERP.Web/Validators/CraftMaterialValidator.cs

@@ -0,0 +1,53 @@
+using FluentValidation;
+using GreenTree.Strohrmann.ERP.Domain.Model;
+using GreenTree.Strohrmann.ERP.Web.Models.Business;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace GreenTree.Strohrmann.ERP.Web.Validators
+{
+	public class CraftMaterialValidator : AbstractValidator<KeyValuePair<string, CraftMaterialModel>>
+	{
+		#region DI fields
+
+		// The global DbContext
+		private readonly ERPDbContext _eRPDbContext;
+
+		#endregion
+
+		#region Ctor
+
+		/// <summary>
+		/// Initializes a new instance of the CraftMaterialValidator class
+		/// </summary>
+		/// <param name="eRPDbContext">Global DbContext.</param>
+		public CraftMaterialValidator(
+			ERPDbContext eRPDbContext)
+		{
+			_eRPDbContext = eRPDbContext;
+
+			RuleFor(m => m.Value)
+				.Custom((val, ctx) =>
+				{
+					if (val.MaterialId == 0)
+						ctx.AddFailure("MaterialId", "Ein Material muss gewählt werden.");
+
+					if (val.Amount <= 0)
+						ctx.AddFailure(
+							String.Format("CraftMaterials[{0}].Amount", val.DictIdentifier), "'Menge' muss größer als 0 sein.");
+
+					if (val.CalculationFactor <= 0)
+						ctx.AddFailure(
+							String.Format("CraftMaterials[{0}].CalculationFactor", val.DictIdentifier), "'Kalkulationsfaktor' muss größer als 0 sein.");
+
+					if (val.Value <= 0)
+						ctx.AddFailure(
+							String.Format("CraftMaterials[{0}].Value", val.DictIdentifier), "'Wert' muss größer als 0 sein.");
+				});
+		}
+
+        #endregion
+    }
+}

+ 63 - 0
GreenTree.Strohrmann.ERP.Web/Validators/CraftValidator.cs

@@ -0,0 +1,63 @@
+using FluentValidation;
+using GreenTree.Strohrmann.ERP.Domain.Model;
+using GreenTree.Strohrmann.ERP.Web.Models.Business;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace GreenTree.Strohrmann.ERP.Web.Validators
+{
+	public class CraftValidator : AbstractValidator<CraftModel>
+	{
+		#region DI fields
+
+		// The global DbContext
+		private readonly ERPDbContext _eRPDbContext;
+
+		#endregion
+
+		#region Ctor
+
+		/// <summary>
+		/// Initializes a new instance of the EmployeeValidator class
+		/// </summary>
+		/// <param name="eRPDbContext">Global DbContext.</param>
+		public CraftValidator(
+			ERPDbContext eRPDbContext)
+		{
+			_eRPDbContext = eRPDbContext;
+
+			RuleFor(m => m.Name)
+				.NotEmpty();
+
+			RuleFor(m => m.CustomerId)
+				.NotEmpty();
+
+			RuleFor(m => m.CreationDate)
+				.NotEmpty();
+
+			RuleForEach(m => m.CraftEmployees)
+				.SetValidator(new CraftEmployeeValidator(_eRPDbContext));
+
+			RuleForEach(m => m.CraftMaterials)
+				.SetValidator(new CraftMaterialValidator(_eRPDbContext));
+
+			//RuleForEach(m => m.CraftEmployees)
+			//	.ChildRules(subModel =>
+			//	{
+			//		subModel
+			//			.RuleFor(x => x.Value.EmployeeId)
+			//				.GreaterThan(0);
+			//		subModel
+			//			.RuleFor(x => x.Value.Amount)
+			//				.GreaterThan(0);
+			//		subModel
+			//			.RuleFor(x => x.Value.Value)
+			//				.GreaterThan(0);
+			//	});
+		}
+
+        #endregion
+    }
+}

+ 223 - 41
GreenTree.Strohrmann.ERP.Web/Views/Craft/Create.cshtml

@@ -6,6 +6,38 @@
 
 <script type="text/javascript">
 
+    function calculateEmployeeAggregation() {
+        var count = $("input[data-aggregation='employeeAmount']").length;
+
+        var avgAmount = $("input[data-aggregation='employeeAmount']").map(function () {
+            return parseFloat($(this).val());
+        }).get().avg();
+
+        var sumValues = $("input[data-aggregation='employeeValue']").map(function () {
+            return parseFloat($(this).val());
+        }).get().sum();
+
+        $("#aggEmployeeCount").text(count);
+        $("#aggEmployeeAmountAvg").text(isNaN(avgAmount) ? " -" : avgAmount + " Std.");
+        $("#aggEmployeeValueSum").text(isNaN(sumValues) ? " -" : sumValues + " €");
+    }
+
+    function calculateMaterialAggregation() {
+        var count = $("input[data-aggregation='materialCalculationFactor']").length;
+
+        var avgCalculationFactor = $("input[data-aggregation='materialCalculationFactor']").map(function () {
+            return parseFloat($(this).val());
+        }).get().avg();
+
+        var sumValues = $("input[data-aggregation='materialValue']").map(function () {
+            return parseFloat($(this).val());
+        }).get().sum();
+
+        $("#aggMaterialCount").text(count);
+        $("#aggMaterialCalculationFactorAvg").text(isNaN(avgCalculationFactor) ? " -" : avgCalculationFactor + " %");
+        $("#aggMaterialValueSum").text(isNaN(sumValues) ? " -" : sumValues + " €");
+	}
+
     function addCraftEmployeePartial() {
         $.ajax({
             type: "GET",
@@ -15,6 +47,21 @@
 			},
             success: function (data) { 
                 $("#craftemployeelist").append(data);
+                calculateEmployeeAggregation();
+            },
+            error: function (errorData) { console.error(errorData); }
+        });
+    }
+
+    function addCraftMaterialPartial() {
+        $.ajax({
+            type: "GET",
+            url: '@Url.Action("AddCraftMaterialPartial")',
+            data: {
+                Index: $("#craftmateriallist").children(".row").length
+			},
+            success: function (data) { 
+                $("#craftmateriallist").append(data);
             },
             error: function (errorData) { console.error(errorData); }
         });
@@ -29,55 +76,190 @@
 
 <form asp-action="Create">
     <div asp-validation-summary="ModelOnly" class="text-danger"></div>
-    <div class="card-deck">
-        <div class="card card-maxw bg-light">
-            <div class="card-header pb-1">
-                <h6>Allgemein</h6>
-            </div>
-            <div class="card-body">
-                <div class="form-group">
-                    <label asp-for="Name" class="control-label"></label>
-                    <input asp-for="Name" class="form-control" />
-                    <span asp-validation-for="Name" class="text-danger"></span>
+    <div class="row">
+        <div class="col-3 pr-1">
+            <div class="card h-100 bg-light">
+                <div class="card-header pb-1">
+                    <h6>Allgemein</h6>
                 </div>
-                <div class="form-group">
-                    <label asp-for="CreationDate" class="control-label"></label>
-                    <input asp-for="CreationDate" class="form-control" />
-                    <span asp-validation-for="CreationDate" class="text-danger"></span>
-                </div>
-                <div class="form-group">
-                    <label asp-for="Customer" class="control-label"></label>
-                    @await Html.PartialAsync("~/Views/Customer/_SearchCustomerPartial.cshtml")
-                    <span asp-validation-for="Customer" class="text-danger"></span>
+                <div class="card-body">
+                    <div class="form-group">
+                        <label asp-for="Name" class="control-label"></label>
+                        <input asp-for="Name" class="form-control" />
+                        <span asp-validation-for="Name" class="text-danger"></span>
+                    </div>
+                    <div class="form-group">
+                        <label asp-for="CreationDate" class="control-label"></label>
+                        <input asp-for="CreationDate" type="date" class="form-control" />
+                        <span asp-validation-for="CreationDate" class="text-danger"></span>
+                    </div>
+                    <div class="form-group">
+                        <label asp-for="CustomerId" class="control-label"></label>
+                        @await Html.PartialAsync("~/Views/Customer/_SearchCustomerPartial.cshtml")
+                        <span asp-validation-for="CustomerId" class="text-danger"></span>
+                    </div>
+                    <div class="form-group">
+                        <label asp-for="Comment" class="control-label"></label>
+                        <textarea asp-for="Comment" class="form-control"></textarea>
+                        <span asp-validation-for="Comment" class="text-danger"></span>
+                    </div>
                 </div>
             </div>
         </div>
-        <div class="card bg-light">
-            <div class="card-header pb-1">
-                <h6 class="float-left">Arbeitsstunden</h6>
-                <a class="float-right" href="#" onclick="addCraftEmployeePartial()">Hinzufügen</a>
-            </div>
-            <div id="craftemployeelist" class="card-body">
-                @if (Model != null && Model.CraftEmployees != null)
-				{
-                    @for (int i = 0; i < Model.CraftEmployees.Count; i++)
+        <div class="col-9">
+            <div class="card bg-light">
+                <div class="card-header pb-1">
+                    <h6 class="float-left">Arbeitsstunden</h6>
+                    <a class="float-right" href="#" onclick="addCraftEmployeePartial()">Hinzufügen</a>
+                </div>
+                <div id="craftemployeelist" class="card-body">
+                    @if (Model != null && Model.CraftEmployees != null)
 				    {
-                        @await Html.PartialAsync("_CraftEmployeePartial", Model.CraftEmployees[i])
+                        @foreach (var item in Model.CraftEmployees)
+						{
+                            @await Html.PartialAsync("_CraftEmployeePartial", item.Value)
+						}
 				    }
-				}
-				else
-				{
-                    @await Html.PartialAsync("_CraftEmployeePartial", new GreenTree.Strohrmann.ERP.Web.Models.Business.CraftEmployeeModel())
-				}
-            </div>
-        </div>
-        @*<div class="card card-maxw bg-light">
-            <div class="card-header pb-1">
-                <h6>Materialien</h6>
+				    else
+				    {
+                        @await Html.PartialAsync("_CraftEmployeePartial")
+				    }
+                </div>
+                <div class="card-footer">
+                    <div class="row">
+                        <div class="col-4">
+                            <h5 class="mb-0">
+                                <span class="badge badge-info">
+                                    <span class="fa fa-hashtag" aria-label="Anzahl"> </span>
+                                    @if (Model != null && Model.CraftEmployees != null)
+				                    {
+                                        <span id="aggEmployeeCount">
+                                            @Model.CraftEmployees.Values.Count
+                                        </span>
+				                    }
+				                    else
+				                    {
+                                        <span id="aggEmployeeCount">1</span>
+				                    }
+                                </span>
+                            </h5>
+                        </div>
+                        <div class="col-2">
+                            <h5 class="mb-0">
+                                <span class="badge badge-info">
+                                    <img height="14" src="~/img/icon-average-48.png" alt="Durchschnitt" title="Durchschnitt" />
+                                    @if (Model != null && Model.CraftEmployees != null)
+				                    {
+                                        <span id="aggEmployeeAmountAvg">
+                                            @String.Format("{0} Std.", Model.CraftEmployees.Values.Average(m => m.Amount))
+                                        </span>
+				                    }
+				                    else
+				                    {
+                                        <span id="aggEmployeeAmountAvg"> -</span>
+				                    }
+                                </span>
+                            </h5>
+                        </div>
+                        <div class="col-6">
+                            <h5 class="mb-0">
+                                <span class="badge badge-info">
+                                    <img height="14" src="~/img/icon-sigma-48.png" alt="Summe" title="Summe" />
+                                    @if (Model != null && Model.CraftEmployees != null)
+				                    {
+                                        <span id="aggEmployeeValueSum">
+                                            @String.Format("{0} €", Model.CraftEmployees.Values.Sum(m => m.Value))
+                                        </span>
+				                    }
+				                    else
+				                    {
+                                        <span id="aggEmployeeValueSum"> -</span>
+				                    }
+                                </span>
+                            </h5>
+                        </div>
+                    </div>
+                </div>
             </div>
-            <div class="card-body">
+            <div class="card bg-light mt-3">
+                <div class="card bg-light">
+                    <div class="card-header pb-1">
+                        <h6 class="float-left">Materialien</h6>
+                        <a class="float-right" href="#" onclick="addCraftMaterialPartial()">Hinzufügen</a>
+                    </div>
+                    <div id="craftmateriallist" class="card-body">
+                        @if (Model != null && Model.CraftMaterials != null)
+				        {
+                            @foreach (var item in Model.CraftMaterials)
+					        {
+                                @await Html.PartialAsync("_CraftMaterialPartial", item.Value)
+					        }
+				        }
+				        else
+				        {
+                            @await Html.PartialAsync("_CraftMaterialPartial")
+				        }
+                    </div>
+                    <div class="card-footer">
+                        <div class="row">
+                            <div class="col-3">
+                                <h5 class="mb-0">
+                                    <span class="badge badge-info">
+                                        <span class="fa fa-hashtag" aria-label="Anzahl"> </span>
+                                        @if (Model != null && Model.CraftMaterials != null)
+				                        {
+                                            <span id="aggMaterialCount">
+                                                @Model.CraftMaterials.Values.Count
+                                            </span>
+				                        }
+				                        else
+				                        {
+                                            <span id="aggMaterialCount">1</span>
+				                        }
+                                    </span>
+                                </h5>
+                            </div>
+                            <div class="col-2">
+                            </div>
+                            <div class="col-3">
+                                <h5 class="mb-0">
+                                    <span class="badge badge-info">
+                                        <img height="14" src="~/img/icon-average-48.png" alt="Durchschnitt" title="Durchschnitt" />
+                                        @if (Model != null && Model.CraftMaterials != null)
+				                        {
+                                            <span id="aggMaterialCalculationFactorAvg">
+                                                @String.Format("{0} %", Model.CraftMaterials.Values.Average(m => m.CalculationFactor))
+                                            </span>
+				                        }
+				                        else
+				                        {
+                                            <span id="aggMaterialCalculationFactorAvg"> -</span>
+				                        }
+                                    </span>
+                                </h5>
+                            </div>
+                            <div class="col-4">
+                                <h5 class="mb-0">
+                                    <span class="badge badge-info">
+                                        <img height="14" src="~/img/icon-sigma-48.png" alt="Summe" title="Summe" />
+                                        @if (Model != null && Model.CraftMaterials != null)
+				                        {
+                                            <span id="aggMaterialValueSum">
+                                                @String.Format("{0} €", Model.CraftMaterials.Values.Sum(m => m.Value))
+                                            </span>
+				                        }
+				                        else
+				                        {
+                                            <span id="aggMaterialValueSum"> -</span>
+				                        }
+                                    </span>
+                                </h5>
+                            </div>
+                        </div>
+                    </div>
+                </div>
             </div>
-        </div>*@
+        </div>
     </div>
 
     <hr />

+ 274 - 0
GreenTree.Strohrmann.ERP.Web/Views/Craft/Edit.cshtml

@@ -0,0 +1,274 @@
+@model GreenTree.Strohrmann.ERP.Web.Models.Business.CraftModel
+
+@{
+    ViewData["Title"] = "Gewerk bearbeiten";
+}
+
+<script type="text/javascript">
+
+    function calculateEmployeeAggregation() {
+        var count = $("input[data-aggregation='employeeAmount']").length;
+
+        var avgAmount = $("input[data-aggregation='employeeAmount']").map(function () {
+            return parseFloat($(this).val());
+        }).get().avg();
+
+        var sumValues = $("input[data-aggregation='employeeValue']").map(function () {
+            return parseFloat($(this).val());
+        }).get().sum();
+
+        $("#aggEmployeeCount").text(count);
+        $("#aggEmployeeAmountAvg").text(isNaN(avgAmount) ? " -" : avgAmount + " Std.");
+        $("#aggEmployeeValueSum").text(isNaN(sumValues) ? " -" : sumValues + " €");
+    }
+
+    function calculateMaterialAggregation() {
+        var count = $("input[data-aggregation='materialCalculationFactor']").length;
+
+        var avgCalculationFactor = $("input[data-aggregation='materialCalculationFactor']").map(function () {
+            return parseFloat($(this).val());
+        }).get().avg();
+
+        var sumValues = $("input[data-aggregation='materialValue']").map(function () {
+            return parseFloat($(this).val());
+        }).get().sum();
+
+        $("#aggMaterialCount").text(count);
+        $("#aggMaterialCalculationFactorAvg").text(isNaN(avgCalculationFactor) ? " -" : avgCalculationFactor + " %");
+        $("#aggMaterialValueSum").text(isNaN(sumValues) ? " -" : sumValues + " €");
+	}
+
+    function addCraftEmployeePartial() {
+        $.ajax({
+            type: "GET",
+            url: '@Url.Action("AddCraftEmployeePartial")',
+            data: {
+                Index: $("#craftemployeelist").children(".row").length
+			},
+            success: function (data) { 
+                $("#craftemployeelist").append(data);
+                calculateEmployeeAggregation();
+            },
+            error: function (errorData) { console.error(errorData); }
+        });
+    }
+
+    function addCraftMaterialPartial() {
+        $.ajax({
+            type: "GET",
+            url: '@Url.Action("AddCraftMaterialPartial")',
+            data: {
+                Index: $("#craftmateriallist").children(".row").length
+			},
+            success: function (data) { 
+                $("#craftmateriallist").append(data);
+            },
+            error: function (errorData) { console.error(errorData); }
+        });
+	}
+
+</script>
+
+<h1>Gewerk bearbeiten</h1>
+
+<h4>@Model.Name</h4>
+
+<hr />
+
+<form asp-action="Edit">
+    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
+    <div class="row">
+        <div class="col-3 pr-1">
+            <div class="card h-100 bg-light">
+                <div class="card-header pb-1">
+                    <h6>Allgemein</h6>
+                </div>
+                <div class="card-body">
+                    <div class="form-group">
+                        <label asp-for="Name" class="control-label"></label>
+                        <input asp-for="Name" class="form-control" />
+                        <span asp-validation-for="Name" class="text-danger"></span>
+                    </div>
+                    <div class="form-group">
+                        <label asp-for="CreationDate" class="control-label"></label>
+                        <input asp-for="CreationDate" type="date" class="form-control" />
+                        <span asp-validation-for="CreationDate" class="text-danger"></span>
+                    </div>
+                    <div class="form-group">
+                        <label asp-for="CustomerId" class="control-label"></label>
+                        @await Html.PartialAsync("~/Views/Customer/_SearchCustomerPartial.cshtml")
+                        <span asp-validation-for="CustomerId" class="text-danger"></span>
+                    </div>
+                    <div class="form-group">
+                        <label asp-for="Comment" class="control-label"></label>
+                        <textarea asp-for="Comment" class="form-control"></textarea>
+                        <span asp-validation-for="Comment" class="text-danger"></span>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="col-9">
+            <div class="card bg-light">
+                <div class="card-header pb-1">
+                    <h6 class="float-left">Arbeitsstunden</h6>
+                    <a class="float-right" href="#" onclick="addCraftEmployeePartial()">Hinzufügen</a>
+                </div>
+                <div id="craftemployeelist" class="card-body">
+                    @if (Model != null && Model.CraftEmployees != null)
+				    {
+                        @foreach (var item in Model.CraftEmployees)
+						{
+                            @await Html.PartialAsync("_CraftEmployeePartial", item.Value)
+						}
+				    }
+				    else
+				    {
+                        @await Html.PartialAsync("_CraftEmployeePartial")
+				    }
+                </div>
+                <div class="card-footer">
+                    <div class="row">
+                        <div class="col-4">
+                            <h5 class="mb-0">
+                                <span class="badge badge-info">
+                                    <span class="fa fa-hashtag" aria-label="Anzahl"> </span>
+                                    @if (Model != null && Model.CraftEmployees != null)
+				                    {
+                                        <span id="aggEmployeeCount">
+                                            @Model.CraftEmployees.Values.Count
+                                        </span>
+				                    }
+				                    else
+				                    {
+                                        <span id="aggEmployeeCount">1</span>
+				                    }
+                                </span>
+                            </h5>
+                        </div>
+                        <div class="col-2">
+                            <h5 class="mb-0">
+                                <span class="badge badge-info">
+                                    <img height="14" src="~/img/icon-average-48.png" alt="Durchschnitt" title="Durchschnitt" />
+                                    @if (Model != null && Model.CraftEmployees != null)
+				                    {
+                                        <span id="aggEmployeeAmountAvg">
+                                            @String.Format("{0:G29} Std.", Model.CraftEmployees.Values.Average(m => m.Amount))
+                                        </span>
+				                    }
+				                    else
+				                    {
+                                        <span id="aggEmployeeAmountAvg"> -</span>
+				                    }
+                                </span>
+                            </h5>
+                        </div>
+                        <div class="col-6">
+                            <h5 class="mb-0">
+                                <span class="badge badge-info">
+                                    <img height="14" src="~/img/icon-sigma-48.png" alt="Summe" title="Summe" />
+                                    @if (Model != null && Model.CraftEmployees != null)
+				                    {
+                                        <span id="aggEmployeeValueSum">
+                                            @String.Format("{0} €", Model.CraftEmployees.Values.Sum(m => m.Value))
+                                        </span>
+				                    }
+				                    else
+				                    {
+                                        <span id="aggEmployeeValueSum"> -</span>
+				                    }
+                                </span>
+                            </h5>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="card bg-light mt-3">
+                <div class="card bg-light">
+                    <div class="card-header pb-1">
+                        <h6 class="float-left">Materialien</h6>
+                        <a class="float-right" href="#" onclick="addCraftMaterialPartial()">Hinzufügen</a>
+                    </div>
+                    <div id="craftmateriallist" class="card-body">
+                        @if (Model != null && Model.CraftMaterials != null)
+				        {
+                            @foreach (var item in Model.CraftMaterials)
+					        {
+                                @await Html.PartialAsync("_CraftMaterialPartial", item.Value)
+					        }
+				        }
+				        else
+				        {
+                            @await Html.PartialAsync("_CraftMaterialPartial")
+				        }
+                    </div>
+                    <div class="card-footer">
+                        <div class="row">
+                            <div class="col-3">
+                                <h5 class="mb-0">
+                                    <span class="badge badge-info">
+                                        <span class="fa fa-hashtag" aria-label="Anzahl"> </span>
+                                        @if (Model != null && Model.CraftMaterials != null)
+				                        {
+                                            <span id="aggMaterialCount">
+                                                @Model.CraftMaterials.Values.Count
+                                            </span>
+				                        }
+				                        else
+				                        {
+                                            <span id="aggMaterialCount">1</span>
+				                        }
+                                    </span>
+                                </h5>
+                            </div>
+                            <div class="col-2">
+                            </div>
+                            <div class="col-3">
+                                <h5 class="mb-0">
+                                    <span class="badge badge-info">
+                                        <img height="14" src="~/img/icon-average-48.png" alt="Durchschnitt" title="Durchschnitt" />
+                                        @if (Model != null && Model.CraftMaterials != null)
+				                        {
+                                            <span id="aggMaterialCalculationFactorAvg">
+                                                @String.Format("{0:G29} %", Model.CraftMaterials.Values.Average(m => m.CalculationFactor) * 100)
+                                            </span>
+				                        }
+				                        else
+				                        {
+                                            <span id="aggMaterialCalculationFactorAvg"> -</span>
+				                        }
+                                    </span>
+                                </h5>
+                            </div>
+                            <div class="col-4">
+                                <h5 class="mb-0">
+                                    <span class="badge badge-info">
+                                        <img height="14" src="~/img/icon-sigma-48.png" alt="Summe" title="Summe" />
+                                        @if (Model != null && Model.CraftMaterials != null)
+				                        {
+                                            <span id="aggMaterialValueSum">
+                                                @String.Format("{0} €", Model.CraftMaterials.Values.Sum(m => m.Value))
+                                            </span>
+				                        }
+				                        else
+				                        {
+                                            <span id="aggMaterialValueSum"> -</span>
+				                        }
+                                    </span>
+                                </h5>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <hr />
+
+    <div class="form-group d-flex mt-3">
+        <input type="submit" value="Speichern" class="btn btn-primary" />
+        <div class="align-self-center ml-3">
+            <a asp-action="Index">Zurück zur Liste</a>
+        </div>
+    </div>
+</form>

+ 20 - 2
GreenTree.Strohrmann.ERP.Web/Views/Craft/Index.cshtml

@@ -79,13 +79,22 @@
             <th data-priority="4">
                 @Html.DisplayNameFor(model => model.Customer)
             </th>
+            <th data-priority="5">
+                @Html.DisplayNameFor(model => model.Comment)
+            </th>
+            <th class="text-right">
+                @Html.DisplayNameFor(model => model.CraftEmployeeValue)
+            </th>
+            <th class="text-right">
+                @Html.DisplayNameFor(model => model.CraftMaterialValue)
+            </th>
             <th data-priority="1">
                 Aktionen
             </th>
         </tr>
     </thead>
     <tbody>
-@foreach (var item in Model) {
+    @foreach (var item in Model) {
         <tr>
             <td>
                 @Html.DisplayFor(modelItem => item.Id)
@@ -99,13 +108,22 @@
             <td>
                 @Html.DisplayFor(modelItem => item.Customer.Fullname)
             </td>
+            <td>
+                @Html.DisplayFor(modelItem => item.Comment)
+            </td>
+            <td class="text-right">
+                @Html.DisplayFor(modelItem => item.CraftEmployeeValue)
+            </td>
+            <td class="text-right">
+                @Html.DisplayFor(modelItem => item.CraftMaterialValue)
+            </td>
             <td>
                 @Html.ActionLink("Bearbeiten", "Edit", new { id = item.Id }) |
                 @Html.ActionLink("Anzeigen", "Details", new { id = item.Id }) |
                 <a href="#" onclick="showDeleteModal(@item.Id)">Löschen</a>
             </td>
         </tr>
-}
+    }
     </tbody>
 </table>
 

+ 89 - 14
GreenTree.Strohrmann.ERP.Web/Views/Craft/_CraftEmployeePartial.cshtml

@@ -1,21 +1,96 @@
 @model GreenTree.Strohrmann.ERP.Web.Models.Business.CraftEmployeeModel
 
-<div class="row">
+@{ 
+	var id = Model != null && !String.IsNullOrEmpty(Model.DictIdentifier) ? Model.DictIdentifier : Html.RandomId();
+}
+
+<script type="text/javascript">
+    @{ 
+        <text>
+
+        function recalculateEmployeeValue_@id () {
+            $.ajax({
+                method: "POST",
+                url: "@Url.Action("CalculateEmployeeValue", "Craft")",
+                data: {
+                    EmployeeId: $("select[name='CraftEmployees[@id].EmployeeId']").val(),
+                    Amount: $("input[name='CraftEmployees[@id].Amount']").val().replace('.', ',')
+                },
+                success: function (data) {
+                    $("input[name='CraftEmployees[@id].Value']").val(data);
+                    calculateEmployeeAggregation();
+                },
+                error: function (msg) {
+
+                }
+            });
+	    }
+
+        </text>
+	}
+</script>
+
+<div class="row align-items-start">
+    <input type="hidden" asp-for="Index" name="CraftEmployees[@id].Index" />
+    <input type="hidden" asp-for="DictIdentifier" name="CraftEmployees[@id].DictIdentifier" value="@id" />
+
     <div class="form-group col-md-4">
-        <label asp-for="EmployeeId" class="control-label"></label>
-        @Html.DropDownListFor(e => e.Employee.Id, 
-            (IEnumerable<SelectListItem>)ViewData["AvailableEmployees"], 
-            new { @class = "form-control" })
-        <span asp-validation-for="EmployeeId" class="text-danger"></span>
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="EmployeeId" class="control-label"></label>
+		}
+        <select asp-items='(IEnumerable<SelectListItem>)ViewData["AvailableEmployees"]' 
+                name="CraftEmployees[@id].EmployeeId" class="form-control" 
+                onchange="calculateEmployeeAggregation(); recalculateEmployeeValue_@id ();">
+        </select>
+        @Html.ValidationMessage(String.Format("CraftEmployees[{0}].EmployeeId", id), new { @class = "text-danger" })
     </div>
-    <div class="form-group col-md-4">
-        <label asp-for="Amount" class="control-label"></label>
-        <input asp-for="Amount" name="CraftEmployees[@Model.Index].Amount" class="form-control" />
-        <span asp-validation-for="Amount" class="text-danger"></span>
+    <div class="form-group col-md-2">
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="Amount" class="control-label"></label>
+		}
+        <div class="input-group">
+            <div class="input-group-prepend">
+                <span class="input-group-text">Std.</span>
+            </div>
+            <input name="CraftEmployees[@id].Amount" type="number" min="0.00" step="0.50" class="form-control"
+                   id="CraftEmployees[@id].Amount" data-aggregation="employeeAmount"
+                   value="@Model.Amount.ToString("G29")"
+                   onchange="calculateEmployeeAggregation(); recalculateEmployeeValue_@id ();" />
+        </div>
+        @Html.ValidationMessage(String.Format("CraftEmployees[{0}].Amount", id), new { @class = "text-danger" })
     </div>
-    <div class="form-group col-md-4">
-        <label asp-for="Value" class="control-label"></label>
-        <input asp-for="Value" name="CraftEmployees[@Model.Index].Value" class="form-control" />
-        <span asp-validation-for="Value" class="text-danger"></span>
+    <div class="form-group col-md-2">
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="Value" class="control-label"></label>
+		}
+        <div class="input-group">
+            <div class="input-group-prepend">
+                <span class="input-group-text">€</span>
+            </div>
+            <input asp-for="Value" name="CraftEmployees[@id].Value" type="number" min="0.00" class="form-control"
+                   data-aggregation="employeeValue"
+                   onchange="calculateEmployeeAggregation();" />
+        </div>
+        @Html.ValidationMessage(String.Format("CraftEmployees[{0}].Value", id), new { @class = "text-danger" })
+    </div>
+    <div class="form-group col-md-3">
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="Comment" class="control-label"></label>
+		}
+        <input asp-for="Comment" name="CraftEmployees[@id].Comment" class="form-control" />
+        @Html.ValidationMessage(String.Format("CraftEmployees[{0}].Comment", id), new { @class = "text-danger" })
+    </div>
+    <div class="form-group col-md-1 pl-1">
+        @if (Model != null && Model.Index > 0)
+		{
+            <button type="button" class="btn btn-danger" aria-label="Entfernen"
+                    onclick="$(this).closest('.row').remove(); calculateEmployeeAggregation();">
+                <span class="fas fa-trash"></span>
+            </button>
+		}
     </div>
 </div>

+ 125 - 0
GreenTree.Strohrmann.ERP.Web/Views/Craft/_CraftMaterialPartial.cshtml

@@ -0,0 +1,125 @@
+@model GreenTree.Strohrmann.ERP.Web.Models.Business.CraftMaterialModel
+
+@{ 
+	var id = Model != null && !String.IsNullOrEmpty(Model.DictIdentifier) ? Model.DictIdentifier : Html.RandomId();
+}
+
+<script type="text/javascript">
+@{ 
+    <text>
+
+    function recalculateMaterialValue_@id (input) {
+        if (input != null && input.name == "CraftMaterials[@id].Value") {
+            $.ajax({
+                method: "POST",
+                url: "@Url.Action("CalculateMaterialCalculationFactor", "Craft")",
+                data: {
+                    MaterialId: $("select[name='CraftMaterials[@id].MaterialId']").val(),
+                    Amount: $("input[name='CraftMaterials[@id].Amount']").val().replace('.', ','),
+                    Value: $("input[name='CraftMaterials[@id].Value']").val()
+                },
+                success: function (data) {
+                    $("input[name='CraftMaterials[@id].CalculationFactor']").val(data);
+                    calculateMaterialAggregation();
+                },
+                error: function (msg) {
+
+                }
+            });
+        } else {
+            $.ajax({
+                method: "POST",
+                url: "@Url.Action("CalculateMaterialValue", "Craft")",
+                data: {
+                    MaterialId: $("select[name='CraftMaterials[@id].MaterialId']").val(),
+                    Amount: $("input[name='CraftMaterials[@id].Amount']").val().replace('.', ','),
+                    CalculationFactor: $("input[name='CraftMaterials[@id].CalculationFactor']").val()
+                },
+                success: function (data) {
+                    $("input[name='CraftMaterials[@id].Value']").val(data);
+                    calculateMaterialAggregation();
+                },
+                error: function (msg) {
+
+                }
+            });
+		}
+	}
+
+    </text>
+}
+</script>
+
+<div class="row align-items-start">
+    <input type="hidden" asp-for="Index" name="CraftMaterials[@id].Index" />
+    <input type="hidden" asp-for="DictIdentifier" name="CraftMaterials[@id].DictIdentifier" value="@id" />
+
+    <div class="form-group col-md-3">
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="MaterialId" class="control-label"></label>
+		}
+        <select asp-items='(IEnumerable<SelectListItem>)ViewData["AvailableMaterials"]' 
+                name="CraftMaterials[@id].MaterialId" class="form-control" 
+                onchange="calculateMaterialAggregation(); recalculateMaterialValue_@id (this);">
+        </select>
+        @Html.ValidationMessage(String.Format("CraftMaterials[{0}].MaterialId", id), new { @class = "text-danger" })
+    </div>
+    <div class="form-group col-md-2">
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="Amount" class="control-label"></label>
+		}
+        <div class="input-group">
+            <div class="input-group-prepend">
+                <span class="input-group-text">Stk.</span>
+            </div>
+            <input name="CraftMaterials[@id].Amount" type="number" min="0.00" step="0.50" class="form-control"
+                   id="CraftMaterials[@id].Amount"
+                   value="@Model.Amount.ToString("G29")"
+                   onchange="calculateMaterialAggregation(); recalculateMaterialValue_@id (this);" />
+        </div>
+        @Html.ValidationMessage(String.Format("CraftMaterials[{0}].Amount", id), new { @class = "text-danger" })
+    </div>
+    <div class="form-group col-md-3">
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="CalculationFactor" class="control-label"></label>
+		}
+        <div class="input-group">
+            <div class="input-group-prepend">
+                <span class="input-group-text">%</span>
+            </div>
+            <input asp-for="CalculationFactor" name="CraftMaterials[@id].CalculationFactor" 
+                   type="number" min="0" step="5"
+                   value="@((Model == null ? 120m : Model.CalculationFactor * 100m).TrimEnd().ToString().Replace(',','.'))" 
+                   class="form-control" data-aggregation="materialCalculationFactor"
+                   onchange="calculateMaterialAggregation(); recalculateMaterialValue_@id (this);" />
+        </div>
+        @Html.ValidationMessage(String.Format("CraftMaterials[{0}].CalculationFactor", id), new { @class = "text-danger" })
+    </div>
+    <div class="form-group col-md-3">
+        @if (Model == null || (Model != null && (!Model.Index.HasValue || Model.Index == 0)))
+		{
+            <label asp-for="Value" class="control-label"></label>
+		}
+        <div class="input-group">
+            <div class="input-group-prepend">
+                <span class="input-group-text">€</span>
+            </div>
+            <input asp-for="Value" name="CraftMaterials[@id].Value" type="number" min="0.00" step="1" class="form-control" 
+                   data-aggregation="materialValue"
+                   onchange="calculateMaterialAggregation(); recalculateMaterialValue_@id (this);"/>
+        </div>
+        @Html.ValidationMessage(String.Format("CraftMaterials[{0}].Value", id), new { @class = "text-danger" })
+    </div>
+    <div class="form-group col-md-1 pl-1">
+        @if (Model != null && Model.Index > 0)
+		{
+            <button type="button" class="btn btn-danger" aria-label="Entfernen" 
+                    onclick="$(this).closest('.row').remove(); calculateMaterialAggregation();">
+                <span class="fas fa-trash"></span>
+            </button>
+		}
+    </div>
+</div>

+ 72 - 61
GreenTree.Strohrmann.ERP.Web/Views/Customer/_SearchCustomerPartial.cshtml

@@ -6,78 +6,89 @@
 
 <script type="text/javascript">
 
-    @{ 
-        <text>
-        $(document).ready(function () {
-            $("#text_@partialId").on('keypress', function (e) {
-                if (e.keyCode == 13) {
-                    search_@partialId ();
-                    e.preventDefault();
-                };
-            });
-            $("#text_@partialId").on('keydown', function (e) {
-                if (e.keyCode == 8 && $("#value_@partialId").val() != "") {
-                    $("#text_@partialId").val("");
-                    $("#value_@partialId").val("");
-                    e.preventDefault();
-                };
-            });
+@{ 
+    <text>
+    $(document).ready(function () {
+        $("#text_@partialId").on('keypress', function (e) {
+            if (e.keyCode == 13) {
+                search_@partialId ();
+                e.preventDefault();
+            };
+        });
+        $("#text_@partialId").on('keydown', function (e) {
+            if (e.keyCode == 8 && $("#value_@partialId").val() != "") {
+                $("#text_@partialId").val("");
+                $("#value_@partialId").val("");
+                $("#text_@partialId").next().children(".fa-check-circle").fadeOut("fast", function () {
+                    $("#text_@partialId").next().children(".fa-ellipsis-h").fadeIn("fast");
+                });
+                e.preventDefault();
+            };
         });
+    });
 
-        function search_@partialId () {
-            $.ajax({
-                method: "POST",
-                url: "@Url.Action("Search", "Customer")",
-                data: {
-                    SearchTerm: $("#text_@partialId").val()
-                },
-                success: function (data) {
-                    $("#searchCustomerModal_@partialId").find(".list-group").empty();
-                    if (data.length > 0) {
-                        $(data).each(function (index, elem) {
-                            $("#searchCustomerModal_@partialId").find(".list-group").append(
-                                '<a href="#" class="list-group-item list-group-item-info list-group-item-action" ' +
-                                'data-toggle="list" data-val="{0}" data-text="{1}">{1} ({2})</a>'
-                                    .format(elem.id, elem.fullname, elem.localAddress));
-                            $("#searchCustomerModal_@partialId").find(".list-group").append(
-                                '<a href="#" class="list-group-item list-group-item-info list-group-item-action" ' +
-                                'data-toggle="list" data-val="{0}" data-text="{1}">{1} ({2})</a>'
-                                    .format(elem.id, elem.fullname, elem.localAddress));
-                            $("#searchCustomerModal_@partialId").find(".list-group").append(
-                                '<a href="#" class="list-group-item list-group-item-info list-group-item-action" ' +
-                                'data-toggle="list" data-val="{0}" data-text="{1}">{1} ({2})</a>'
-                                    .format(elem.id, elem.fullname, elem.localAddress));
-                        });
-                    } else {
+    function search_@partialId () {
+        $.ajax({
+            method: "POST",
+            url: "@Url.Action("Search", "Customer")",
+            data: {
+                SearchTerm: $("#text_@partialId").val()
+            },
+            success: function (data) {
+                $("#searchCustomerModal_@partialId").find(".list-group").empty();
+                if (data.length > 0) {
+                    $(data).each(function (index, elem) {
                         $("#searchCustomerModal_@partialId").find(".list-group").append(
-                            '<button type="button" class="list-group-item">Keine Treffer</button>');
-					}
-                    $("#searchCustomerModal_@partialId").modal("show");
-                },
-                error: function (msg) {
+                            '<a href="#" class="list-group-item list-group-item-info list-group-item-action" ' +
+                            'data-toggle="list" data-val="{0}" data-text="{1}" ondblclick="select_@partialId ()">{1} ({2})</a>'
+                                .format(elem.id, elem.fullname, elem.localAddress));
+                    });
+                } else {
+                    $("#searchCustomerModal_@partialId").find(".list-group").append(
+                        '<button type="button" class="list-group-item">Keine Treffer</button>');
+				}
+                $("#searchCustomerModal_@partialId").modal("show");
+            },
+            error: function (msg) {
 
-                }
-            });
-        }
+            }
+        });
+    }
 
-        function select_@partialId () {
-            $("#searchCustomerModal_@partialId").modal("hide");
-            var val = $("#searchCustomerModal_@partialId").find("a.active").attr("data-val");
-            var text = $("#searchCustomerModal_@partialId").find("a.active").attr("data-text");
-            $("#value_@partialId").val(val);
-            $("#text_@partialId").val(text);
-	    }
+    function select_@partialId () {
+        $("#searchCustomerModal_@partialId").modal("hide");
+        var val = $("#searchCustomerModal_@partialId").find("a.active").attr("data-val");
+        var text = $("#searchCustomerModal_@partialId").find("a.active").attr("data-text");
+        $("#value_@partialId").val(val);
+        $("#text_@partialId").val(text);
+        $("#text_@partialId").next().children(".fa-ellipsis-h").fadeOut("fast", function () {
+            $("#text_@partialId").next().children(".fa-check-circle").fadeIn("fast");
+        });
+	}
             
-        </text>
-    }
+    </text>
+}
 
 </script>
 
-<div class="input-group mb-3">
+<div class="input-group">
     <div class="input-group-prepend">
         <button class="btn btn-info fas fa-search" type="button" onclick="search_@partialId ()"></button>
     </div>
-    <input id="text_@partialId" type="text" class="form-control" placeholder="Suchbegriff" aria-label="Suchbegriff" aria-describedby="basic-addon1">
+    <input id="text_@partialId" type="text" asp-for="CustomerText" class="form-control" placeholder="Suchbegriff" 
+           aria-label="Suchbegriff" aria-describedby="basic-addon1">
+    <div class="input-group-append">
+        @if (Model.CustomerId > 0)
+		{
+            @Html.Span("", new { @class = "input-group-text bg-success text-white rounded-right fas fa-cust-lh fa-check-circle" })
+            @Html.Span("", new { @class = "input-group-text rounded-right fas fa-cust-lh fa-ellipsis-h", style = "display: none" })
+		}
+		else
+		{
+            @Html.Span("", new { @class = "input-group-text bg-success text-white rounded-right fas fa-cust-lh fa-check-circle", style = "display: none" })
+            @Html.Span("", new { @class = "input-group-text rounded-right fas fa-cust-lh fa-ellipsis-h" })
+		}
+    </div>
 </div>
 
 <input id="value_@partialId" type="hidden" asp-for="CustomerId" />
@@ -88,7 +99,7 @@
             <div class="modal-header">
                 <h4 class="modal-title">Suchergebnisse</h4>
             </div>
-            <div class="modal-body">
+            <div class="modal-body overflow-auto" style="max-height: 400px">
                 <div class="list-group">
                 </div>
             </div>

+ 0 - 6
GreenTree.Strohrmann.ERP.Web/Views/Home/Privacy.cshtml

@@ -1,6 +0,0 @@
-@{
-    ViewData["Title"] = "Privacy Policy";
-}
-<h1>@ViewData["Title"]</h1>
-
-<p>Use this page to detail your site's privacy policy.</p>

+ 3 - 0
GreenTree.Strohrmann.ERP.Web/Views/Shared/_Layout.cshtml

@@ -73,6 +73,9 @@
     <!-- application core JavaScript -->
     <script src="~/js/site.js" asp-append-version="true"></script>
 
+    <!-- application extension JavaScript -->
+    <script src="~/js/extension.js" asp-append-version="true"></script>
+
     @RenderSection("Scripts", required: false)
 
     <div class="d-flex" id="wrapper">

+ 1 - 1
GreenTree.Strohrmann.ERP.Web/Views/Supplier/Edit.cshtml

@@ -31,7 +31,7 @@
                 </div>
                 <div class="form-group">
                     <label asp-for="Comment" class="control-label"></label>
-                    <textarea asp-for="Comment" rows="5" class="form-control"  />
+                    <textarea asp-for="Comment" rows="5" class="form-control"></textarea>
                     <span asp-validation-for="Comment" class="text-danger"></span>
                 </div>
             </div>

+ 3 - 1
GreenTree.Strohrmann.ERP.Web/Views/_ViewImports.cshtml

@@ -1,4 +1,6 @@
 @using GreenTree.Strohrmann.ERP.Web
 @using GreenTree.Strohrmann.ERP.Web.Models
 @using GreenTree.Strohrmann.ERP.Web.Extension
-@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
+@using GreenTree.Strohrmann.ERP.Web.Models.Business
+@using GreenTree.Strohrmann.ERP.Core.Extension
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

+ 5 - 0
GreenTree.Strohrmann.ERP.Web/wwwroot/css/site.css

@@ -175,4 +175,9 @@ body {
 .selectpicker-form {
     background-color: white;
     border: 1px solid #ced4da;
+}
+
+/* FontAwesome extension */
+.fa-cust-lh {
+    line-height: inherit;
 }

BIN
GreenTree.Strohrmann.ERP.Web/wwwroot/img/icon-average-48.png


BIN
GreenTree.Strohrmann.ERP.Web/wwwroot/img/icon-sigma-48.png


+ 39 - 0
GreenTree.Strohrmann.ERP.Web/wwwroot/js/extension.js

@@ -0,0 +1,39 @@
+//************** JQuery extension **************//
+
+(function ($) {
+    var jqAppend = $.fn.append;
+    $.fn.append = function () {
+        // Make a list of arguments that are jQuery objects
+        var appendages = $.makeArray(arguments).filter(function (arg) {
+            return arg instanceof $;
+        });
+
+        // Call the actual function
+        var returnValue = jqAppend.apply(this, arguments);
+
+        // Trigger "append" event on all jQuery objects that were appended
+        for (var i = 0; i < appendages.length; ++i) {
+            appendages[i].trigger('append');
+        }
+
+        return returnValue;
+    };
+})(jQuery)
+
+//************** Array extension **************//
+
+Array.prototype.sum = function () {
+    var r = 0;
+    for (var i = 0; i < this.length; i++) {
+        r += this[i];
+    }
+    return r;
+};
+
+Array.prototype.avg = function () {
+    var r = 0;
+    for (var i = 0; i < this.length; i++) {
+        r += this[i];
+    }
+    return r / this.length;
+};