From 9f138a90b11807a9e1844e5ba9f88322f8494b96 Mon Sep 17 00:00:00 2001 From: Aleksandr Vishniakov Date: Tue, 12 Nov 2024 18:11:11 +0200 Subject: [PATCH] Allow to create line items (with & without products) (#121) Co-authored-by: Kutasina Elena <62027488+ekuvirto@users.noreply.github.com> Co-authored-by: Artem Dudarev --- .editorconfig | 2 +- .gitattributes | 1 + VirtoCommerce.QuoteModule.sln | 13 + VirtoCommerce.QuoteModule.sln.DotSettings | 2 + ...226_RelaxQuoteItemRestrictions.Designer.cs | 544 ++++++++++++++++++ ...240830073226_RelaxQuoteItemRestrictions.cs | 114 ++++ .../Migrations/QuoteDbContextModelSnapshot.cs | 3 - ...235_RelaxQuoteItemRestrictions.Designer.cs | 539 +++++++++++++++++ ...240830073235_RelaxQuoteItemRestrictions.cs | 84 +++ .../Migrations/QuoteDbContextModelSnapshot.cs | 3 - ...244_RelaxQuoteItemRestrictions.Designer.cs | 539 +++++++++++++++++ ...240830073244_RelaxQuoteItemRestrictions.cs | 84 +++ .../Migrations/QuoteDbContextModelSnapshot.cs | 3 - .../Model/QuoteItemEntity.cs | 6 +- .../Commands/AddQuoteItemsCommand.cs | 18 + .../Commands/AddQuoteItemsCommandBuilder.cs | 13 + .../Commands/AddQuoteItemsCommandHandler.cs | 90 +++ .../Commands/QuoteCommandHandler.cs | 6 +- .../Models/NewQuoteItem.cs | 19 + .../Schemas/InputNewQuoteItemType.cs | 19 + .../Schemas/QuoteItemType.cs | 15 +- 21 files changed, 2096 insertions(+), 21 deletions(-) create mode 100644 .gitattributes create mode 100644 src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.Designer.cs create mode 100644 src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.cs create mode 100644 src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.Designer.cs create mode 100644 src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.cs create mode 100644 src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.Designer.cs create mode 100644 src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.cs create mode 100644 src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommand.cs create mode 100644 src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandBuilder.cs create mode 100644 src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandHandler.cs create mode 100644 src/VirtoCommerce.QuoteModule.ExperienceApi/Models/NewQuoteItem.cs create mode 100644 src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/InputNewQuoteItemType.cs diff --git a/.editorconfig b/.editorconfig index 52a5b14d..d467f1b2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -102,7 +102,7 @@ csharp_preserve_single_line_statements = false csharp_preserve_single_line_blocks = true csharp_using_directive_placement = outside_namespace:silent csharp_prefer_simple_using_statement = true:suggestion -csharp_style_namespace_declarations = block_scoped:silent +csharp_style_namespace_declarations = file_scoped:silent csharp_style_prefer_method_group_conversion = true:silent csharp_style_prefer_top_level_statements = true:silent csharp_style_expression_bodied_lambdas = true:silent diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/VirtoCommerce.QuoteModule.sln b/VirtoCommerce.QuoteModule.sln index e92c089e..38e6760f 100644 --- a/VirtoCommerce.QuoteModule.sln +++ b/VirtoCommerce.QuoteModule.sln @@ -27,6 +27,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.QuoteModule.D EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.QuoteModule.Data.PostgreSql", "src\VirtoCommerce.QuoteModule.Data.PostgreSql\VirtoCommerce.QuoteModule.Data.PostgreSql.csproj", "{AF5FE400-6C31-47F9-9E90-A553887FED9E}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AE6605AE-C77E-4C09-B824-68ABDE5657B7}" + ProjectSection(SolutionItems) = preProject + VirtoCommerce.QuoteModule.sln.DotSettings = VirtoCommerce.QuoteModule.sln.DotSettings + README.md = README.md + module.ignore = module.ignore + mkdocs.yml = mkdocs.yml + MkDocs.md = MkDocs.md + Directory.Build.props = Directory.Build.props + .gitignore = .gitignore + .editorconfig = .editorconfig + .gitattributes = .gitattributes + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/VirtoCommerce.QuoteModule.sln.DotSettings b/VirtoCommerce.QuoteModule.sln.DotSettings index 605f80fc..7083860f 100644 --- a/VirtoCommerce.QuoteModule.sln.DotSettings +++ b/VirtoCommerce.QuoteModule.sln.DotSettings @@ -1,5 +1,7 @@  <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy> + True True True True diff --git a/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.Designer.cs b/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.Designer.cs new file mode 100644 index 00000000..29276052 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.Designer.cs @@ -0,0 +1,544 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using VirtoCommerce.QuoteModule.Data.Repositories; + +#nullable disable + +namespace VirtoCommerce.QuoteModule.Data.MySql.Migrations +{ + [DbContext(typeof(QuoteDbContext))] + [Migration("20240830073226_RelaxQuoteItemRestrictions")] + partial class RelaxQuoteItemRestrictions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AddressEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("AddressType") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CountryCode") + .HasMaxLength(3) + .HasColumnType("varchar(3)"); + + b.Property("CountryName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Line1") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Line2") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Organization") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("OuterId") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Phone") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("PostalCode") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.Property("RegionId") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("RegionName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteAddress", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AttachmentEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("MimeType") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(2083) + .HasColumnType("varchar(2083)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteAttachment", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteDynamicPropertyObjectValueEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("BooleanValue") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("DateTimeValue") + .HasColumnType("datetime(6)"); + + b.Property("DecimalValue") + .HasColumnType("decimal(18,5)"); + + b.Property("DictionaryItemId") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IntegerValue") + .HasColumnType("int"); + + b.Property("Locale") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("LongTextValue") + .HasColumnType("longtext"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("ObjectId") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ObjectType") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PropertyId") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("PropertyName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ShortTextValue") + .HasMaxLength(512) + .HasColumnType("varchar(512)"); + + b.Property("ValueType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("ObjectId"); + + b.HasIndex("ObjectType", "ObjectId") + .HasDatabaseName("IX_QuoteDynamicPropertyObjectValue_ObjectType_ObjectId"); + + b.ToTable("QuoteDynamicPropertyObjectValue", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CatalogId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CategoryId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Comment") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("varchar(3)"); + + b.Property("ImageUrl") + .HasMaxLength(1028) + .HasColumnType("varchar(1028)"); + + b.Property("ListPrice") + .HasPrecision(18, 4) + .HasColumnType("decimal"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("ProductId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.Property("SalePrice") + .HasPrecision(18, 4) + .HasColumnType("decimal"); + + b.Property("Sku") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TaxType") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteItem", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CancelReason") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("CancelledDate") + .HasColumnType("datetime(6)"); + + b.Property("ChannelId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Coupon") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("varchar(3)"); + + b.Property("CustomerId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CustomerName") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("EmployeeId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("EmployeeName") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("EnableNotification") + .HasColumnType("tinyint(1)"); + + b.Property("ExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("InnerComment") + .HasColumnType("longtext"); + + b.Property("IsAnonymous") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("IsLocked") + .HasColumnType("tinyint(1)"); + + b.Property("IsSubmitted") + .HasColumnType("tinyint(1)"); + + b.Property("LanguageCode") + .HasMaxLength(5) + .HasColumnType("varchar(5)"); + + b.Property("ManualRelDiscountAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ManualShippingTotal") + .HasPrecision(18, 4) + .HasColumnType("decimal"); + + b.Property("ManualSubTotal") + .HasPrecision(18, 4) + .HasColumnType("decimal"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("Number") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("OrganizationId") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("OrganizationName") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("ReminderDate") + .HasColumnType("datetime(6)"); + + b.Property("ShipmentMethodCode") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ShipmentMethodOption") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Status") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("StoreId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("StoreName") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("Tag") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.ToTable("QuoteRequest", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.TierPriceEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Price") + .HasPrecision(18, 4) + .HasColumnType("decimal"); + + b.Property("Quantity") + .HasColumnType("bigint"); + + b.Property("QuoteItemId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteItemId"); + + b.ToTable("QuoteTierPrice", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AddressEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Addresses") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AttachmentEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Attachments") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteDynamicPropertyObjectValueEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("DynamicPropertyObjectValues") + .HasForeignKey("ObjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Items") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.TierPriceEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", "QuoteItem") + .WithMany("ProposalPrices") + .HasForeignKey("QuoteItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteItem"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.Navigation("ProposalPrices"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", b => + { + b.Navigation("Addresses"); + + b.Navigation("Attachments"); + + b.Navigation("DynamicPropertyObjectValues"); + + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.cs b/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.cs new file mode 100644 index 00000000..b7ea11e8 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/20240830073226_RelaxQuoteItemRestrictions.cs @@ -0,0 +1,114 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace VirtoCommerce.QuoteModule.Data.MySql.Migrations +{ + /// + public partial class RelaxQuoteItemRestrictions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Sku", + table: "QuoteItem", + type: "varchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "ProductId", + table: "QuoteItem", + type: "varchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "CatalogId", + table: "QuoteItem", + type: "varchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.UpdateData( + table: "QuoteItem", + keyColumn: "Sku", + keyValue: null, + column: "Sku", + value: ""); + + migrationBuilder.AlterColumn( + name: "Sku", + table: "QuoteItem", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64, + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "QuoteItem", + keyColumn: "ProductId", + keyValue: null, + column: "ProductId", + value: ""); + + migrationBuilder.AlterColumn( + name: "ProductId", + table: "QuoteItem", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64, + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "QuoteItem", + keyColumn: "CatalogId", + keyValue: null, + column: "CatalogId", + value: ""); + + migrationBuilder.AlterColumn( + name: "CatalogId", + table: "QuoteItem", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64, + oldNullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/QuoteDbContextModelSnapshot.cs b/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/QuoteDbContextModelSnapshot.cs index 472051eb..908d86b6 100644 --- a/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/QuoteDbContextModelSnapshot.cs +++ b/src/VirtoCommerce.QuoteModule.Data.MySql/Migrations/QuoteDbContextModelSnapshot.cs @@ -239,7 +239,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("varchar(128)"); b.Property("CatalogId") - .IsRequired() .HasMaxLength(64) .HasColumnType("varchar(64)"); @@ -270,7 +269,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("varchar(1024)"); b.Property("ProductId") - .IsRequired() .HasMaxLength(64) .HasColumnType("varchar(64)"); @@ -286,7 +284,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("decimal"); b.Property("Sku") - .IsRequired() .HasMaxLength(64) .HasColumnType("varchar(64)"); diff --git a/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.Designer.cs b/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.Designer.cs new file mode 100644 index 00000000..b0d72379 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.Designer.cs @@ -0,0 +1,539 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using VirtoCommerce.QuoteModule.Data.Repositories; + +#nullable disable + +namespace VirtoCommerce.QuoteModule.Data.PostgreSql.Migrations +{ + [DbContext(typeof(QuoteDbContext))] + [Migration("20240830073235_RelaxQuoteItemRestrictions")] + partial class RelaxQuoteItemRestrictions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AddressEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("AddressType") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CountryCode") + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("CountryName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Line1") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Line2") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Organization") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("OuterId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Phone") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("PostalCode") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.Property("RegionId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("RegionName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteAddress", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AttachmentEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("MimeType") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ModifiedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(2083) + .HasColumnType("character varying(2083)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteAttachment", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteDynamicPropertyObjectValueEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("BooleanValue") + .HasColumnType("boolean"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DateTimeValue") + .HasColumnType("timestamp with time zone"); + + b.Property("DecimalValue") + .HasColumnType("decimal(18,5)"); + + b.Property("DictionaryItemId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("IntegerValue") + .HasColumnType("integer"); + + b.Property("Locale") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LongTextValue") + .HasColumnType("text"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ModifiedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ObjectId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ObjectType") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PropertyId") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("PropertyName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ShortTextValue") + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ValueType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("ObjectId"); + + b.HasIndex("ObjectType", "ObjectId") + .HasDatabaseName("IX_QuoteDynamicPropertyObjectValue_ObjectType_ObjectId"); + + b.ToTable("QuoteDynamicPropertyObjectValue", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CatalogId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CategoryId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Comment") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("ImageUrl") + .HasMaxLength(1028) + .HasColumnType("character varying(1028)"); + + b.Property("ListPrice") + .HasColumnType("Money"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("ProductId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.Property("SalePrice") + .HasColumnType("Money"); + + b.Property("Sku") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("TaxType") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteItem", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CancelReason") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("CancelledDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ChannelId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Comment") + .HasColumnType("text"); + + b.Property("Coupon") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("character varying(3)"); + + b.Property("CustomerId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CustomerName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("EmployeeId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("EmployeeName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("EnableNotification") + .HasColumnType("boolean"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("InnerComment") + .HasColumnType("text"); + + b.Property("IsAnonymous") + .HasColumnType("boolean"); + + b.Property("IsCancelled") + .HasColumnType("boolean"); + + b.Property("IsLocked") + .HasColumnType("boolean"); + + b.Property("IsSubmitted") + .HasColumnType("boolean"); + + b.Property("LanguageCode") + .HasMaxLength(5) + .HasColumnType("character varying(5)"); + + b.Property("ManualRelDiscountAmount") + .HasPrecision(18, 2) + .HasColumnType("numeric(18,2)"); + + b.Property("ManualShippingTotal") + .HasColumnType("Money"); + + b.Property("ManualSubTotal") + .HasColumnType("Money"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ModifiedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Number") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("OrganizationId") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("OrganizationName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("ReminderDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ShipmentMethodCode") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("ShipmentMethodOption") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Status") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("StoreId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("StoreName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("Tag") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.ToTable("QuoteRequest", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.TierPriceEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Price") + .HasColumnType("Money"); + + b.Property("Quantity") + .HasColumnType("bigint"); + + b.Property("QuoteItemId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteItemId"); + + b.ToTable("QuoteTierPrice", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AddressEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Addresses") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AttachmentEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Attachments") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteDynamicPropertyObjectValueEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("DynamicPropertyObjectValues") + .HasForeignKey("ObjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Items") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.TierPriceEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", "QuoteItem") + .WithMany("ProposalPrices") + .HasForeignKey("QuoteItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteItem"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.Navigation("ProposalPrices"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", b => + { + b.Navigation("Addresses"); + + b.Navigation("Attachments"); + + b.Navigation("DynamicPropertyObjectValues"); + + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.cs b/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.cs new file mode 100644 index 00000000..ee9b0f65 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/20240830073235_RelaxQuoteItemRestrictions.cs @@ -0,0 +1,84 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace VirtoCommerce.QuoteModule.Data.PostgreSql.Migrations +{ + /// + public partial class RelaxQuoteItemRestrictions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Sku", + table: "QuoteItem", + type: "character varying(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(64)", + oldMaxLength: 64); + + migrationBuilder.AlterColumn( + name: "ProductId", + table: "QuoteItem", + type: "character varying(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(64)", + oldMaxLength: 64); + + migrationBuilder.AlterColumn( + name: "CatalogId", + table: "QuoteItem", + type: "character varying(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(64)", + oldMaxLength: 64); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Sku", + table: "QuoteItem", + type: "character varying(64)", + maxLength: 64, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(64)", + oldMaxLength: 64, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProductId", + table: "QuoteItem", + type: "character varying(64)", + maxLength: 64, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(64)", + oldMaxLength: 64, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CatalogId", + table: "QuoteItem", + type: "character varying(64)", + maxLength: 64, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(64)", + oldMaxLength: 64, + oldNullable: true); + } + } +} diff --git a/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/QuoteDbContextModelSnapshot.cs b/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/QuoteDbContextModelSnapshot.cs index f0deb0d5..75d2d981 100644 --- a/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/QuoteDbContextModelSnapshot.cs +++ b/src/VirtoCommerce.QuoteModule.Data.PostgreSql/Migrations/QuoteDbContextModelSnapshot.cs @@ -239,7 +239,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(128)"); b.Property("CatalogId") - .IsRequired() .HasMaxLength(64) .HasColumnType("character varying(64)"); @@ -269,7 +268,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("character varying(1024)"); b.Property("ProductId") - .IsRequired() .HasMaxLength(64) .HasColumnType("character varying(64)"); @@ -284,7 +282,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("Money"); b.Property("Sku") - .IsRequired() .HasMaxLength(64) .HasColumnType("character varying(64)"); diff --git a/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.Designer.cs b/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.Designer.cs new file mode 100644 index 00000000..f2acbaa3 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.Designer.cs @@ -0,0 +1,539 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using VirtoCommerce.QuoteModule.Data.Repositories; + +#nullable disable + +namespace VirtoCommerce.QuoteModule.Data.SqlServer.Migrations +{ + [DbContext(typeof(QuoteDbContext))] + [Migration("20240830073244_RelaxQuoteItemRestrictions")] + partial class RelaxQuoteItemRestrictions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AddressEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("AddressType") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CountryCode") + .HasMaxLength(3) + .HasColumnType("nvarchar(3)"); + + b.Property("CountryName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Line1") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Line2") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Organization") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("OuterId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Phone") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("PostalCode") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.Property("RegionId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("RegionName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteAddress", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AttachmentEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("MimeType") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ModifiedDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(2083) + .HasColumnType("nvarchar(2083)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteAttachment", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteDynamicPropertyObjectValueEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("BooleanValue") + .HasColumnType("bit"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("DateTimeValue") + .HasColumnType("datetime2"); + + b.Property("DecimalValue") + .HasColumnType("decimal(18,5)"); + + b.Property("DictionaryItemId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IntegerValue") + .HasColumnType("int"); + + b.Property("Locale") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("LongTextValue") + .HasColumnType("nvarchar(max)"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ModifiedDate") + .HasColumnType("datetime2"); + + b.Property("ObjectId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ObjectType") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PropertyId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("PropertyName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ShortTextValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ValueType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("ObjectId"); + + b.HasIndex("ObjectType", "ObjectId") + .HasDatabaseName("IX_QuoteDynamicPropertyObjectValue_ObjectType_ObjectId"); + + b.ToTable("QuoteDynamicPropertyObjectValue", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CatalogId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CategoryId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Comment") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("nvarchar(3)"); + + b.Property("ImageUrl") + .HasMaxLength(1028) + .HasColumnType("nvarchar(1028)"); + + b.Property("ListPrice") + .HasColumnType("Money"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("ProductId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuoteRequestId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.Property("SalePrice") + .HasColumnType("Money"); + + b.Property("Sku") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TaxType") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteRequestId"); + + b.ToTable("QuoteItem", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CancelReason") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("CancelledDate") + .HasColumnType("datetime2"); + + b.Property("ChannelId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Comment") + .HasColumnType("nvarchar(max)"); + + b.Property("Coupon") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreatedBy") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreatedDate") + .HasColumnType("datetime2"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("nvarchar(3)"); + + b.Property("CustomerId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CustomerName") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("EmployeeId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("EmployeeName") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("EnableNotification") + .HasColumnType("bit"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("InnerComment") + .HasColumnType("nvarchar(max)"); + + b.Property("IsAnonymous") + .HasColumnType("bit"); + + b.Property("IsCancelled") + .HasColumnType("bit"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("IsSubmitted") + .HasColumnType("bit"); + + b.Property("LanguageCode") + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("ManualRelDiscountAmount") + .HasPrecision(18, 2) + .HasColumnType("decimal(18,2)"); + + b.Property("ManualShippingTotal") + .HasColumnType("Money"); + + b.Property("ManualSubTotal") + .HasColumnType("Money"); + + b.Property("ModifiedBy") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ModifiedDate") + .HasColumnType("datetime2"); + + b.Property("Number") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("OrganizationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("OrganizationName") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("ReminderDate") + .HasColumnType("datetime2"); + + b.Property("ShipmentMethodCode") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ShipmentMethodOption") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Status") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("StoreId") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("StoreName") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("Tag") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("QuoteRequest", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.TierPriceEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Price") + .HasColumnType("Money"); + + b.Property("Quantity") + .HasColumnType("bigint"); + + b.Property("QuoteItemId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("QuoteItemId"); + + b.ToTable("QuoteTierPrice", (string)null); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AddressEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Addresses") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.AttachmentEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Attachments") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteDynamicPropertyObjectValueEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("DynamicPropertyObjectValues") + .HasForeignKey("ObjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", "QuoteRequest") + .WithMany("Items") + .HasForeignKey("QuoteRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteRequest"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.TierPriceEntity", b => + { + b.HasOne("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", "QuoteItem") + .WithMany("ProposalPrices") + .HasForeignKey("QuoteItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QuoteItem"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteItemEntity", b => + { + b.Navigation("ProposalPrices"); + }); + + modelBuilder.Entity("VirtoCommerce.QuoteModule.Data.Model.QuoteRequestEntity", b => + { + b.Navigation("Addresses"); + + b.Navigation("Attachments"); + + b.Navigation("DynamicPropertyObjectValues"); + + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.cs b/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.cs new file mode 100644 index 00000000..9755abc7 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/20240830073244_RelaxQuoteItemRestrictions.cs @@ -0,0 +1,84 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace VirtoCommerce.QuoteModule.Data.SqlServer.Migrations +{ + /// + public partial class RelaxQuoteItemRestrictions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Sku", + table: "QuoteItem", + type: "nvarchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64); + + migrationBuilder.AlterColumn( + name: "ProductId", + table: "QuoteItem", + type: "nvarchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64); + + migrationBuilder.AlterColumn( + name: "CatalogId", + table: "QuoteItem", + type: "nvarchar(64)", + maxLength: 64, + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Sku", + table: "QuoteItem", + type: "nvarchar(64)", + maxLength: 64, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProductId", + table: "QuoteItem", + type: "nvarchar(64)", + maxLength: 64, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CatalogId", + table: "QuoteItem", + type: "nvarchar(64)", + maxLength: 64, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(64)", + oldMaxLength: 64, + oldNullable: true); + } + } +} diff --git a/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/QuoteDbContextModelSnapshot.cs b/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/QuoteDbContextModelSnapshot.cs index 6ac17f0b..be3a1071 100644 --- a/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/QuoteDbContextModelSnapshot.cs +++ b/src/VirtoCommerce.QuoteModule.Data.SqlServer/Migrations/QuoteDbContextModelSnapshot.cs @@ -239,7 +239,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(128)"); b.Property("CatalogId") - .IsRequired() .HasMaxLength(64) .HasColumnType("nvarchar(64)"); @@ -269,7 +268,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(1024)"); b.Property("ProductId") - .IsRequired() .HasMaxLength(64) .HasColumnType("nvarchar(64)"); @@ -284,7 +282,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("Money"); b.Property("Sku") - .IsRequired() .HasMaxLength(64) .HasColumnType("nvarchar(64)"); diff --git a/src/VirtoCommerce.QuoteModule.Data/Model/QuoteItemEntity.cs b/src/VirtoCommerce.QuoteModule.Data/Model/QuoteItemEntity.cs index 1076afab..8cac331e 100644 --- a/src/VirtoCommerce.QuoteModule.Data/Model/QuoteItemEntity.cs +++ b/src/VirtoCommerce.QuoteModule.Data/Model/QuoteItemEntity.cs @@ -21,22 +21,22 @@ public QuoteItemEntity() [Column(TypeName = "Money")] public decimal ListPrice { get; set; } + [Column(TypeName = "Money")] public decimal SalePrice { get; set; } - [Required] [StringLength(64)] public string ProductId { get; set; } - [Required] + [StringLength(64)] public string Sku { get; set; } - [Required] [StringLength(64)] public string CatalogId { get; set; } [StringLength(64)] public string CategoryId { get; set; } + [Required] [StringLength(1024)] public string Name { get; set; } diff --git a/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommand.cs b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommand.cs new file mode 100644 index 00000000..63e02be2 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommand.cs @@ -0,0 +1,18 @@ +using GraphQL.Types; +using VirtoCommerce.QuoteModule.ExperienceApi.Models; +using VirtoCommerce.QuoteModule.ExperienceApi.Schemas; + +namespace VirtoCommerce.QuoteModule.ExperienceApi.Commands; + +public class AddQuoteItemsCommand : QuoteCommand +{ + public NewQuoteItem[] NewQuoteItems { get; set; } +} + +public class AddQuoteItemsCommandType : QuoteCommandType +{ + public AddQuoteItemsCommandType() + { + Field>>(nameof(AddQuoteItemsCommand.NewQuoteItems)); + } +} diff --git a/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandBuilder.cs b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandBuilder.cs new file mode 100644 index 00000000..1eac0bea --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandBuilder.cs @@ -0,0 +1,13 @@ +using MediatR; +using Microsoft.AspNetCore.Authorization; + +namespace VirtoCommerce.QuoteModule.ExperienceApi.Commands; + +public class AddQuoteItemsCommandBuilder : QuoteCommandBuilder +{ + protected override string Name => "addQuoteItems"; + + public AddQuoteItemsCommandBuilder(IMediator mediator, IAuthorizationService authorizationService) : base(mediator, authorizationService) + { + } +} diff --git a/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandHandler.cs b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandHandler.cs new file mode 100644 index 00000000..82cfd435 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/AddQuoteItemsCommandHandler.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using MediatR; +using VirtoCommerce.Platform.Core.Common; +using VirtoCommerce.Platform.Core.Settings; +using VirtoCommerce.QuoteModule.Core.Models; +using VirtoCommerce.QuoteModule.Core.Services; +using VirtoCommerce.QuoteModule.ExperienceApi.Aggregates; +using VirtoCommerce.XCatalog.Core.Models; +using VirtoCommerce.XCatalog.Core.Queries; + +namespace VirtoCommerce.QuoteModule.ExperienceApi.Commands; + +public class AddQuoteItemsCommandHandler( + IQuoteRequestService quoteRequestService, + IQuoteAggregateRepository quoteAggregateRepository, + ISettingsManager settingsManager, + IMediator mediator +) + : QuoteCommandHandler(quoteRequestService, quoteAggregateRepository, settingsManager) +{ + protected override async Task UpdateQuoteAsync(QuoteRequest quote, AddQuoteItemsCommand request) + { + var productIds = request.NewQuoteItems.Where(x => !string.IsNullOrEmpty(x.ProductId)).Select(x => x.ProductId).ToArray(); + + var productsQuery = new LoadProductsQuery + { + UserId = quote.CustomerId, + StoreId = quote.StoreId, + CurrencyCode = quote.Currency, + ObjectIds = productIds, + IncludeFields = + [ + "__object", + "price", + "images", + "properties", + "description", + "slug", + "outlines" + ], + EvaluatePromotions = false, + }; + + var productsResponse = await mediator.Send(productsQuery); + + AddQuoteItems(quote, request, productsResponse.Products); + } + + // This method should be a part of QuoteAggregate, but it requires QuoteCommand to be refactored with breaking changes + protected virtual void AddQuoteItems(QuoteRequest quote, AddQuoteItemsCommand request, ICollection products) + { + var productsByIds = products.ToDictionary(x => x.Id, x => x); + + foreach (var newQuoteItem in request.NewQuoteItems) + { + var quoteItem = AbstractTypeFactory.TryCreateInstance(); + + quoteItem.ProductId = newQuoteItem.ProductId; + quoteItem.Name = newQuoteItem.Name; + quoteItem.Comment = newQuoteItem.Comment; + quoteItem.Quantity = newQuoteItem.Quantity; + quoteItem.Currency = quote.Currency; + + var product = productsByIds.GetValueSafe(newQuoteItem.ProductId); + if (product != null) + { + quoteItem.Name = product.IndexedProduct.Name; + quoteItem.Sku = product.IndexedProduct.Code; + quoteItem.CatalogId = product.IndexedProduct.CatalogId; + quoteItem.CategoryId = product.IndexedProduct.CategoryId; + quoteItem.ImageUrl = product.IndexedProduct.ImgSrc; + quoteItem.TaxType = product.IndexedProduct.TaxType; + } + + var price = product?.AllPrices.FirstOrDefault(); + quoteItem.ListPrice = price?.ListPrice.InternalAmount ?? 0; + quoteItem.SalePrice = price?.SalePrice.InternalAmount ?? 0; + + var tierPrice = AbstractTypeFactory.TryCreateInstance(); + tierPrice.Price = newQuoteItem.Price ?? quoteItem.SalePrice; + tierPrice.Quantity = newQuoteItem.Quantity; + + quoteItem.ProposalPrices = [tierPrice]; + + quote.Items.Add(quoteItem); + } + } +} diff --git a/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/QuoteCommandHandler.cs b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/QuoteCommandHandler.cs index c4815af8..3d76bc33 100644 --- a/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/QuoteCommandHandler.cs +++ b/src/VirtoCommerce.QuoteModule.ExperienceApi/Commands/QuoteCommandHandler.cs @@ -3,12 +3,12 @@ using System.Threading.Tasks; using GraphQL; using MediatR; -using VirtoCommerce.Xapi.Core.Helpers; using VirtoCommerce.Platform.Core.Settings; using VirtoCommerce.QuoteModule.Core.Extensions; using VirtoCommerce.QuoteModule.Core.Models; using VirtoCommerce.QuoteModule.Core.Services; using VirtoCommerce.QuoteModule.ExperienceApi.Aggregates; +using VirtoCommerce.Xapi.Core.Helpers; namespace VirtoCommerce.QuoteModule.ExperienceApi.Commands; @@ -57,5 +57,7 @@ protected virtual Task UpdateQuoteAsync(QuoteRequest quote, TCommand request) return Task.CompletedTask; } - protected abstract void UpdateQuote(QuoteRequest quote, TCommand request); + protected virtual void UpdateQuote(QuoteRequest quote, TCommand request) + { + } } diff --git a/src/VirtoCommerce.QuoteModule.ExperienceApi/Models/NewQuoteItem.cs b/src/VirtoCommerce.QuoteModule.ExperienceApi/Models/NewQuoteItem.cs new file mode 100644 index 00000000..5b625143 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.ExperienceApi/Models/NewQuoteItem.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using VirtoCommerce.Xapi.Core.Models; + +namespace VirtoCommerce.QuoteModule.ExperienceApi.Models; + +public class NewQuoteItem +{ + public string ProductId { get; set; } + + public string Name { get; set; } + + public int Quantity { get; set; } + + public decimal? Price { get; set; } + + public string Comment { get; set; } + + public IList DynamicProperties { get; set; } +} diff --git a/src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/InputNewQuoteItemType.cs b/src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/InputNewQuoteItemType.cs new file mode 100644 index 00000000..b2a29d85 --- /dev/null +++ b/src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/InputNewQuoteItemType.cs @@ -0,0 +1,19 @@ +using GraphQL.Types; +using VirtoCommerce.QuoteModule.ExperienceApi.Models; +using VirtoCommerce.Xapi.Core.Schemas; + +namespace VirtoCommerce.QuoteModule.ExperienceApi.Schemas; + +public class InputNewQuoteItemType : InputObjectGraphType +{ + public InputNewQuoteItemType() + { + Field(x => x.ProductId, nullable: true); + Field(x => x.Name, nullable: true); + Field(x => x.Quantity, nullable: false); + Field(x => x.Price, nullable: true); + Field(x => x.Comment, nullable: true); + + Field>("dynamicProperties"); + } +} diff --git a/src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/QuoteItemType.cs b/src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/QuoteItemType.cs index cc5a1036..ff167632 100644 --- a/src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/QuoteItemType.cs +++ b/src/VirtoCommerce.QuoteModule.ExperienceApi/Schemas/QuoteItemType.cs @@ -1,13 +1,14 @@ using System.Linq; +using System.Threading.Tasks; using GraphQL.DataLoader; using GraphQL.Resolvers; using GraphQL.Types; using MediatR; +using VirtoCommerce.QuoteModule.Core.Models; +using VirtoCommerce.QuoteModule.ExperienceApi.Aggregates; using VirtoCommerce.Xapi.Core.Extensions; using VirtoCommerce.Xapi.Core.Helpers; using VirtoCommerce.Xapi.Core.Schemas; -using VirtoCommerce.QuoteModule.Core.Models; -using VirtoCommerce.QuoteModule.ExperienceApi.Aggregates; using VirtoCommerce.XCatalog.Core.Models; using VirtoCommerce.XCatalog.Core.Queries; using VirtoCommerce.XCatalog.Core.Schemas; @@ -19,9 +20,9 @@ public class QuoteItemType : ExtendableGraphType public QuoteItemType(IMediator mediator, IDataLoaderContextAccessor dataLoader) { Field(x => x.Model.Id, nullable: false); - Field(x => x.Model.Sku, nullable: false); - Field(x => x.Model.ProductId, nullable: false); - Field(x => x.Model.CatalogId, nullable: false); + Field(x => x.Model.Sku, nullable: true); + Field(x => x.Model.ProductId, nullable: true); + Field(x => x.Model.CatalogId, nullable: true); Field(x => x.Model.CategoryId, nullable: true); Field(x => x.Model.Name, nullable: false); Field(x => x.Model.Comment, nullable: true); @@ -58,7 +59,9 @@ public QuoteItemType(IMediator mediator, IDataLoaderContextAccessor dataLoader) return response.Products.ToDictionary(x => x.Id); }); - return loader.LoadAsync(context.Source.Model.ProductId); + return context.Source.Model.ProductId != null + ? loader.LoadAsync(context.Source.Model.ProductId) + : new DataLoaderResult(Task.FromResult(null)); }) };