From 64752b5db6a64664d4c66ad4a01790601f504c24 Mon Sep 17 00:00:00 2001 From: daniilda Date: Wed, 18 May 2022 01:26:34 +0300 Subject: [PATCH 01/11] kafka grpc --- ToxiCode.BuyIt.Logistics.Api.sln | 7 + .../ToxiCode.BuyIt.Logistics.Api.Grpc.csproj | 24 ++ .../google/api/annotations.proto | 32 ++ .../google/api/http.proto | 376 ++++++++++++++++++ .../protos/CommonBuyItLogisticsService.proto | 33 ++ .../ItemsServiceNotificationDecorator.cs | 53 +++ .../GrpcServices/CommonGrpcService.cs | 8 + .../HttpControllers/ItemController.cs | 4 +- .../Extensions/KafkaExtensions.cs | 19 + .../Kafka/IKafkaProducer.cs | 6 + .../Kafka/KafkaProducer.cs | 54 +++ .../Kafka/KafkaProducerOptions.cs | 13 + src/ToxiCode.BuyIt.Logistics.Api/Program.cs | 13 +- .../ToxiCode.BuyIt.Logistics.Api.csproj | 4 + .../appsettings.json | 9 +- 15 files changed, 651 insertions(+), 4 deletions(-) create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/annotations.proto create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/http.proto create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Items/ItemsServiceNotificationDecorator.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/Kafka/IKafkaProducer.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducer.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducerOptions.cs diff --git a/ToxiCode.BuyIt.Logistics.Api.sln b/ToxiCode.BuyIt.Logistics.Api.sln index 384f244..82a50a8 100644 --- a/ToxiCode.BuyIt.Logistics.Api.sln +++ b/ToxiCode.BuyIt.Logistics.Api.sln @@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ToxiCode.BuyIt.Logistics.Ap EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ToxiCode.BuyIt.Logistics.Api.Dtos", "src\ToxiCode.BuyIt.Logistics.Api.Dtos\ToxiCode.BuyIt.Logistics.Api.Dtos.csproj", "{DAD80286-F78A-40EE-99B4-E5B66DE2600B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ToxiCode.BuyIt.Logistics.Api.Grpc", "src\ToxiCode.BuyIt.Logistics.Api.Grpc\ToxiCode.BuyIt.Logistics.Api.Grpc.csproj", "{907821A0-FF80-4782-AF78-6A5D2C2930D5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -36,10 +38,15 @@ Global {DAD80286-F78A-40EE-99B4-E5B66DE2600B}.Debug|Any CPU.Build.0 = Debug|Any CPU {DAD80286-F78A-40EE-99B4-E5B66DE2600B}.Release|Any CPU.ActiveCfg = Release|Any CPU {DAD80286-F78A-40EE-99B4-E5B66DE2600B}.Release|Any CPU.Build.0 = Release|Any CPU + {907821A0-FF80-4782-AF78-6A5D2C2930D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {907821A0-FF80-4782-AF78-6A5D2C2930D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {907821A0-FF80-4782-AF78-6A5D2C2930D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {907821A0-FF80-4782-AF78-6A5D2C2930D5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {F5B0C8B1-81AD-4BA5-B8AB-21A1C9C74FD6} = {A9176EE0-8CC8-409D-8581-3F9FC81B1414} {734C9075-AF0E-44CB-A9C5-1FDB104D4027} = {F1F7FC49-302C-48A2-9F89-3F0DCC9A945A} {DAD80286-F78A-40EE-99B4-E5B66DE2600B} = {A9176EE0-8CC8-409D-8581-3F9FC81B1414} + {907821A0-FF80-4782-AF78-6A5D2C2930D5} = {A9176EE0-8CC8-409D-8581-3F9FC81B1414} EndGlobalSection EndGlobal diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj new file mode 100644 index 0000000..6b121cf --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + enable + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/annotations.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/annotations.proto new file mode 100644 index 0000000..4c08a7d --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/annotations.proto @@ -0,0 +1,32 @@ + +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/http.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/http.proto new file mode 100644 index 0000000..d5614b8 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/google/api/http.proto @@ -0,0 +1,376 @@ +// Copyright 2019 Google LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +package google.api; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; +option objc_class_prefix = "GAPI"; + +// Defines the HTTP configuration for an API service. It contains a list of +// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +// to one or more HTTP REST API methods. +message Http { + // A list of HTTP configuration rules that apply to individual API methods. + // + // **NOTE:** All service configuration rules follow "last one wins" order. + repeated HttpRule rules = 1; + + // When set to true, URL path parameters will be fully URI-decoded except in + // cases of single segment matches in reserved expansion, where "%2F" will be + // left encoded. + // + // The default behavior is to not decode RFC 6570 reserved characters in multi + // segment matches. + bool fully_decode_reserved_expansion = 2; +} + +// # gRPC Transcoding +// +// gRPC Transcoding is a feature for mapping between a gRPC method and one or +// more HTTP REST endpoints. It allows developers to build a single API service +// that supports both gRPC APIs and REST APIs. Many systems, including [Google +// APIs](https://github.com/googleapis/googleapis), +// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +// and use it for large scale production services. +// +// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +// how different portions of the gRPC request message are mapped to the URL +// path, URL query parameters, and HTTP request body. It also controls how the +// gRPC response message is mapped to the HTTP response body. `HttpRule` is +// typically specified as an `google.api.http` annotation on the gRPC method. +// +// Each mapping specifies a URL path template and an HTTP method. The path +// template may refer to one or more fields in the gRPC request message, as long +// as each field is a non-repeated field with a primitive (non-message) type. +// The path template controls how fields of the request message are mapped to +// the URL path. +// +// Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/{name=messages/*}" +// }; +// } +// } +// message GetMessageRequest { +// string name = 1; // Mapped to URL path. +// } +// message Message { +// string text = 1; // The resource content. +// } +// +// This enables an HTTP REST to gRPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// +// Any fields in the request message which are not bound by the path template +// automatically become HTTP query parameters if there is no HTTP request body. +// For example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get:"/v1/messages/{message_id}" +// }; +// } +// } +// message GetMessageRequest { +// message SubMessage { +// string subfield = 1; +// } +// string message_id = 1; // Mapped to URL path. +// int64 revision = 2; // Mapped to URL query parameter `revision`. +// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +// } +// +// This enables a HTTP JSON to RPC mapping as below: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +// "foo"))` +// +// Note that fields which are mapped to URL query parameters must have a +// primitive type or a repeated primitive type or a non-repeated message type. +// In the case of a repeated type, the parameter can be repeated in the URL +// as `...?param=A¶m=B`. In the case of a message type, each field of the +// message is mapped to a separate parameter, such as +// `...?foo.a=A&foo.b=B&foo.c=C`. +// +// For HTTP methods that allow a request body, the `body` field +// specifies the mapping. Consider a REST update method on the +// message resource collection: +// +// service Messaging { +// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "message" +// }; +// } +// } +// message UpdateMessageRequest { +// string message_id = 1; // mapped to the URL +// Message message = 2; // mapped to the body +// } +// +// The following HTTP JSON to RPC mapping is enabled, where the +// representation of the JSON in the request body is determined by +// protos JSON encoding: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" message { text: "Hi!" })` +// +// The special name `*` can be used in the body mapping to define that +// every field not bound by the path template should be mapped to the +// request body. This enables the following alternative definition of +// the update method: +// +// service Messaging { +// rpc UpdateMessage(Message) returns (Message) { +// option (google.api.http) = { +// patch: "/v1/messages/{message_id}" +// body: "*" +// }; +// } +// } +// message Message { +// string message_id = 1; +// string text = 2; +// } +// +// +// The following HTTP JSON to RPC mapping is enabled: +// +// HTTP | gRPC +// -----|----- +// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +// "123456" text: "Hi!")` +// +// Note that when using `*` in the body mapping, it is not possible to +// have HTTP parameters, as all fields not bound by the path end in +// the body. This makes this option more rarely used in practice when +// defining REST APIs. The common usage of `*` is in custom methods +// which don't use the URL at all for transferring data. +// +// It is possible to define multiple HTTP methods for one RPC by using +// the `additional_bindings` option. Example: +// +// service Messaging { +// rpc GetMessage(GetMessageRequest) returns (Message) { +// option (google.api.http) = { +// get: "/v1/messages/{message_id}" +// additional_bindings { +// get: "/v1/users/{user_id}/messages/{message_id}" +// } +// }; +// } +// } +// message GetMessageRequest { +// string message_id = 1; +// string user_id = 2; +// } +// +// This enables the following two alternative HTTP JSON to RPC mappings: +// +// HTTP | gRPC +// -----|----- +// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +// "123456")` +// +// ## Rules for HTTP mapping +// +// 1. Leaf request fields (recursive expansion nested messages in the request +// message) are classified into three categories: +// - Fields referred by the path template. They are passed via the URL path. +// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP +// request body. +// - All other fields are passed via the URL query parameters, and the +// parameter name is the field path in the request message. A repeated +// field can be represented as multiple query parameters under the same +// name. +// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields +// are passed via URL path and HTTP request body. +// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all +// fields are passed via URL path and URL query parameters. +// +// ### Path template syntax +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// The syntax `*` matches a single URL path segment. The syntax `**` matches +// zero or more URL path segments, which must be the last part of the URL path +// except the `Verb`. +// +// The syntax `Variable` matches part of the URL path as specified by its +// template. A variable template must not contain other variables. If a variable +// matches a single path segment, its template may be omitted, e.g. `{var}` +// is equivalent to `{var=*}`. +// +// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +// contains any reserved character, such characters should be percent-encoded +// before the matching. +// +// If a variable contains exactly one path segment, such as `"{var}"` or +// `"{var=*}"`, when such a variable is expanded into a URL path on the client +// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +// server side does the reverse decoding. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{var}`. +// +// If a variable contains multiple path segments, such as `"{var=foo/*}"` +// or `"{var=**}"`, when such a variable is expanded into a URL path on the +// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +// The server side does the reverse decoding, except "%2F" and "%2f" are left +// unchanged. Such variables show up in the +// [Discovery +// Document](https://developers.google.com/discovery/v1/reference/apis) as +// `{+var}`. +// +// ## Using gRPC API Service Configuration +// +// gRPC API Service Configuration (service config) is a configuration language +// for configuring a gRPC service to become a user-facing product. The +// service config is simply the YAML representation of the `google.api.Service` +// proto message. +// +// As an alternative to annotating your proto file, you can configure gRPC +// transcoding in your service config YAML files. You do this by specifying a +// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +// effect as the proto annotation. This can be particularly useful if you +// have a proto that is reused in multiple services. Note that any transcoding +// specified in the service config will override any matching transcoding +// configuration in the proto. +// +// Example: +// +// http: +// rules: +// # Selects a gRPC method and applies HttpRule to it. +// - selector: example.v1.Messaging.GetMessage +// get: /v1/messages/{message_id}/{sub.subfield} +// +// ## Special notes +// +// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +// proto to JSON conversion must follow the [proto3 +// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +// +// While the single segment variable follows the semantics of +// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +// Expansion, the multi segment variable **does not** follow RFC 6570 Section +// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +// does not expand special characters like `?` and `#`, which would lead +// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +// for multi segment variables. +// +// The path variables **must not** refer to any repeated or mapped field, +// because client libraries are not capable of handling such variable expansion. +// +// The path variables **must not** capture the leading "/" character. The reason +// is that the most common use case "{var}" does not capture the leading "/" +// character. For consistency, all path variables must share the same behavior. +// +// Repeated message fields must not be mapped to URL query parameters, because +// no client library can support such complicated mapping. +// +// If an API needs to use a JSON array for request or response body, it can map +// the request or response body to a repeated field. However, some gRPC +// Transcoding implementations may not support this feature. +message HttpRule { + // Selects a method to which this rule applies. + // + // Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + string selector = 1; + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Maps to HTTP GET. Used for listing and getting information about + // resources. + string get = 2; + + // Maps to HTTP PUT. Used for replacing a resource. + string put = 3; + + // Maps to HTTP POST. Used for creating a resource or performing an action. + string post = 4; + + // Maps to HTTP DELETE. Used for deleting a resource. + string delete = 5; + + // Maps to HTTP PATCH. Used for updating a resource. + string patch = 6; + + // The custom pattern is used for specifying an HTTP method that is not + // included in the `pattern` field, such as HEAD, or "*" to leave the + // HTTP method unspecified for this rule. The wild-card rule is useful + // for services that provide content to Web (HTML) clients. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP request + // body, or `*` for mapping all request fields not captured by the path + // pattern to the HTTP body, or omitted for not having any HTTP request body. + // + // NOTE: the referred field must be present at the top-level of the request + // message type. + string body = 7; + + // Optional. The name of the response field whose value is mapped to the HTTP + // response body. When omitted, the entire response message will be used + // as the HTTP response body. + // + // NOTE: The referred field must be present at the top-level of the response + // message type. + string response_body = 12; + + // Additional HTTP bindings for the selector. Nested bindings must + // not contain an `additional_bindings` field themselves (that is, + // the nesting may only be one level deep). + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto new file mode 100644 index 0000000..c1f775c --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto @@ -0,0 +1,33 @@ +syntax = "proto3"; + +option csharp_namespace = "ToxiCode.BuyIt.Logistics.Api.Grpc"; + +import "google/api/annotations.proto"; + +package BuyIt.Logistics; + +message AddItem{ + string name = 1; +} + +message ItemModel{ + int64 id = 1; + string name = 2; +} + +message AddItemsRequest{ + repeated AddItem add_items = 1; +} + +message AddItemsResponse{ + repeated ItemModel items = 1; +} + +service CommonBuyItLogisticsService{ + rpc AddItems(AddItemsRequest) returns (AddItemsResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Items/ItemsServiceNotificationDecorator.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Items/ItemsServiceNotificationDecorator.cs new file mode 100644 index 0000000..423d831 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Items/ItemsServiceNotificationDecorator.cs @@ -0,0 +1,53 @@ +using System.Text.Json; +using Confluent.Kafka; +using ToxiCode.BuyIt.Api.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Items.Commands; +using ToxiCode.BuyIt.Logistics.Api.Kafka; +using Action = ToxiCode.BuyIt.Api.Contracts.Action; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Items; + +public class ItemsServiceNotificationDecorator : IItemService +{ + private readonly IItemService _target; + private readonly IKafkaProducer _producer; + + public ItemsServiceNotificationDecorator(IItemService target, IKafkaProducer producer) + { + _target = target; + _producer = producer; + } + + public async Task CreateItem(CreateItemRequest request, CancellationToken cancellationToken) + { + var result = await _target.CreateItem(request, cancellationToken); + var notification = new CreatedItemNotification() + { + Price = request.Price, + Name = request.Name, + Description = "Not provided", + Id = result, + OwnerId = Guid.NewGuid() + }; + var wrapper = new KafkaMessage + { + CreatedItemNotification = notification, + Action = Action.Created + }; + var json = JsonSerializer.Serialize(wrapper); + await _producer.SendMessageAsync(result.ToString(), json, cancellationToken); + return result; + } + + public Task DeleteItem(long request, CancellationToken cancellationToken) + => _target.DeleteItem(request, cancellationToken); + + public Task ChangeItem(ChangeItemRequest request, CancellationToken cancellationToken) + => _target.ChangeItem(request, cancellationToken); + + public Task GetItem(long id) + => _target.GetItem(id); + + public Task GetItems() + => _target.GetItems(); +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs b/src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs new file mode 100644 index 0000000..570f6d5 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs @@ -0,0 +1,8 @@ +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace ToxiCode.BuyIt.Logistics.Api.GrpcServices; + +public class CommonGrpcService : CommonBuyItLogisticsService.CommonBuyItLogisticsServiceBase +{ + +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs index 7e0b495..d7f58c4 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs @@ -9,10 +9,10 @@ namespace ToxiCode.BuyIt.Logistics.Api.HttpControllers; [ApiController] public class ItemController : ControllerBase { - private readonly ItemServiceResolver _resolver; + private readonly IItemService _resolver; private readonly HttpCancellationTokenAccessor _cancellationToken; - public ItemController(ItemsRepository repository, HttpCancellationTokenAccessor cancellationToken, ItemServiceResolver resolver) + public ItemController(HttpCancellationTokenAccessor cancellationToken, IItemService resolver) { _cancellationToken = cancellationToken; _resolver = resolver; diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs b/src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs new file mode 100644 index 0000000..8173cdc --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs @@ -0,0 +1,19 @@ +using ToxiCode.BuyIt.Logistics.Api.Kafka; + +namespace ToxiCode.BuyIt.Logistics.Api.Infrustructure.Extensions; + +public static class KafkaExtensions +{ + public static IServiceCollection AddKafka(this IServiceCollection services, + IConfiguration configuration) + { + services + .AddOptions() + .Configure(options => configuration.GetSection(nameof(KafkaProducerOptions)).Bind(options)) + .ValidateDataAnnotations(); + + return services + .AddSingleton(); + } + +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Kafka/IKafkaProducer.cs b/src/ToxiCode.BuyIt.Logistics.Api/Kafka/IKafkaProducer.cs new file mode 100644 index 0000000..f308482 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/Kafka/IKafkaProducer.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.Kafka; + +public interface IKafkaProducer +{ + public Task SendMessageAsync(string key, string message, CancellationToken cancellationToken); +} diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducer.cs b/src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducer.cs new file mode 100644 index 0000000..0ce20af --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducer.cs @@ -0,0 +1,54 @@ +using Confluent.Kafka; +using Microsoft.Extensions.Options; + +namespace ToxiCode.BuyIt.Logistics.Api.Kafka; + +public class KafkaProducer : IKafkaProducer, IDisposable +{ + private readonly IProducer _kafkaProducer; + private readonly ILogger _logger; + private readonly string _topicName; + + public KafkaProducer( + IOptions config, + ILogger logger + ) + { + if (config == null) + throw new ArgumentNullException( + $"Producer creation exception. {nameof(KafkaProducerOptions)} has no value"); + + _logger = logger; + _topicName = config.Value.TopicName; + _kafkaProducer = CreateProducer(config.Value?.ProducerConfig!); + } + + public void Dispose() + => _kafkaProducer.Dispose(); + + public async Task SendMessageAsync(string key, string message, CancellationToken cancellationToken) + { + await _kafkaProducer.ProduceAsync(_topicName, + new Message + { + Key = key, + Value = message + }, cancellationToken); + } + + private IProducer CreateProducer(ProducerConfig config) + { + var builder = new ProducerBuilder(config) + .SetLogHandler((_, message) => + _logger.LogError("Librdkafka message: {Name}:{Message}", message.Name, message.Message)) + .SetErrorHandler((_, error) => DefaultErrorHandler(error)); + + return builder.Build(); + } + + private void DefaultErrorHandler(Error error) + => _logger.LogError("{IsFatalError} error {ErrorCode} occured in confluent kafka: {ErrorReason}", + error.IsFatal ? "Fatal" : "Non-fatal", + error.Code, + error.Reason); +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducerOptions.cs b/src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducerOptions.cs new file mode 100644 index 0000000..14abfd9 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/Kafka/KafkaProducerOptions.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; +using Confluent.Kafka; + +namespace ToxiCode.BuyIt.Logistics.Api.Kafka; + +public class KafkaProducerOptions +{ + [Required] + public string TopicName { get; init; } = null!; + + [Required] + public ProducerConfig ProducerConfig { get; init; } = null!; +} diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs index 873b467..11e6ec8 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs @@ -3,7 +3,11 @@ using System.Net; using Microsoft.AspNetCore.Server.Kestrel.Core; using ToxiCode.BuyIt.Logistics.Api; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Items; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Extensions; +using ToxiCode.BuyIt.Logistics.Api.Grpc; +using ToxiCode.BuyIt.Logistics.Api.GrpcServices; +using ToxiCode.BuyIt.Logistics.Api.Infrustructure.Extensions; var builder = WebApplication.CreateBuilder(args); @@ -39,7 +43,13 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro services.AddGrpcSwagger(); services .AddHttpContextAccessor() - .AddSingleton(); + .AddSingleton() + .AddSingleton() + .AddKafka(builder.Configuration); + +services + .AddSingleton() + .Decorate(); #endregion @@ -51,6 +61,7 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro app.UseSwaggerUI(); app.UseAuthorization(); app.MapControllers(); +app.MapGrpcService(); app.Migrate(); app.Run(); diff --git a/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj b/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj index 7f644d0..1c1faa9 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj +++ b/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj @@ -9,6 +9,7 @@ + @@ -16,9 +17,12 @@ + + + diff --git a/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json b/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json index 9ce6aec..e9d1eb0 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json +++ b/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json @@ -1,5 +1,12 @@ { "ConnectionStrings": { - "Postgre" : "UserID=root;Password=root;Host=localhost;Port=5432;Database=database;Pooling=true;MinPoolSize=0;MaxPoolSize=100;ConnectionLifetime=0" + "Postgre" : "UserID=root;Password=root;Host=localhost;Port=5432;Database=buyit-logistics-api-dev;Pooling=true;MinPoolSize=0;MaxPoolSize=100;ConnectionLifetime=0" + }, + "KafkaProducerOptions": { + "TopicName": "toxicode_buyit_api_items", + "ProducerConfig": { + "BootstrapServers": "broker1.kafka.txcd.xyz:29092" + } } + } From 99cd029726d23632dc7ca55c61a07b56b83dfb3d Mon Sep 17 00:00:00 2001 From: daniilkuznetsov Date: Sat, 21 May 2022 15:12:18 +0300 Subject: [PATCH 02/11] [TXC-5] Add grpc (feature) --- src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs | 3 + .../Order.cs | 5 +- .../ToxiCode.BuyIt.Logistics.Api.Dtos.csproj | 4 + .../ToxiCode.BuyIt.Logistics.Api.Grpc.csproj | 6 +- .../protos/CommonBuyItLogisticsService.proto | 33 ------- .../protos/ItemsService.proto | 91 ++++++++++++++++++ .../protos/OrdersService.proto | 92 +++++++++++++++++++ .../ItemsServiceNotificationDecorator.cs | 13 +-- .../DataLayer/Repository/ItemsRepository.cs | 7 +- .../GrpcControllers/ItemsGrpcController.cs | 14 +++ .../GrpcControllers/OrdersGrpcController.cs | 10 ++ .../GrpcServices/CommonGrpcService.cs | 8 -- src/ToxiCode.BuyIt.Logistics.Api/Program.cs | 15 ++- .../ToxiCode.BuyIt.Logistics.Api.csproj | 1 + 14 files changed, 243 insertions(+), 59 deletions(-) delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs index df886d5..90895eb 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs @@ -6,4 +6,7 @@ public class Item public string Name { get; set; } = null!; public decimal Price { get; set; } public decimal Weight { get; set; } + public decimal Height { get; set; } + public decimal Lenght { get; set; } + public decimal Width { get; set; } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs index b3f452f..4643db3 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs @@ -1,4 +1,6 @@ -namespace Dtos; +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace Dtos; public class Order { @@ -7,4 +9,5 @@ public class Order public Place From { get; set; } = null!; public Place To { get; set; } = null!; public long[]? Articles { get; set; } + public OrderStatus Status { get; set; } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj index b061f14..3ecd91f 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj index 6b121cf..47dd13c 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/ToxiCode.BuyIt.Logistics.Api.Grpc.csproj @@ -1,9 +1,13 @@ - net6.0 + https://github.com/mToxicCode/buyit-logistics-api enable enable + true + true + content + true diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto deleted file mode 100644 index c1f775c..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/CommonBuyItLogisticsService.proto +++ /dev/null @@ -1,33 +0,0 @@ -syntax = "proto3"; - -option csharp_namespace = "ToxiCode.BuyIt.Logistics.Api.Grpc"; - -import "google/api/annotations.proto"; - -package BuyIt.Logistics; - -message AddItem{ - string name = 1; -} - -message ItemModel{ - int64 id = 1; - string name = 2; -} - -message AddItemsRequest{ - repeated AddItem add_items = 1; -} - -message AddItemsResponse{ - repeated ItemModel items = 1; -} - -service CommonBuyItLogisticsService{ - rpc AddItems(AddItemsRequest) returns (AddItemsResponse){ - option(google.api.http) = { - post: "/v1/common/items/add" - body: "*" - }; - } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto new file mode 100644 index 0000000..ddc2dcc --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto @@ -0,0 +1,91 @@ +syntax = "proto3"; +option csharp_namespace = "ToxiCode.BuyIt.Logistics.Api.Grpc"; +import "google/protobuf/timestamp.proto"; +import "google/api/annotations.proto"; +package BuyIt.Logistics; + +service ItemsService{ + rpc AddItems(AddItemsRequest) returns (AddItemsResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } + rpc GetItems(GetItemsRequest) returns (GetItemsResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } + rpc ChangeItems(ChangeItemsRequest) returns (ChangeItemsResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } +} + +message AddItemsRequest{ + repeated AddItem add_items = 1; +} + +message AddItem{ + string item_name = 1; + string seller_id = 2; + int32 weight = 3; + int32 height = 4; + int32 length = 5; + int32 width = 6; + int32 count = 7; + string request_item_id = 8; + repeated string img_urls = 9; +} + +message AddItemsResponse{ + repeated ItemResult items = 1; +} + +message ItemResult{ + int64 item_id = 1; + string request_item_id = 2; + string result_message = 3; +} + +message GetItemsRequest{ + repeated int64 items_ids = 1; +} + +message GetItemsResponse{ + repeated Item items = 1; +} + +message Item{ + int64 item_id = 1; + int32 weight = 2; + int32 height = 3; + int32 length = 4; + int32 width = 5; + int32 available_count = 6; + google.protobuf.Timestamp creation_date = 7; + google.protobuf.Timestamp change_at = 8; +} + +message ChangeItemsRequest{ + int64 item_id = 1; + string item_name = 2; + int32 height = 3; + int32 weight = 4; + int32 length = 5; + int32 width = 6; + repeated string img_urls = 7; +} + +message ChangeItemsResponse{ + repeated ItemChangeResult items = 1; +} + +message ItemChangeResult{ + int64 item_id = 1; + bool item_changed = 2; + string result_message = 3; +} diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto new file mode 100644 index 0000000..cb4a7f6 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto @@ -0,0 +1,92 @@ +syntax = "proto3"; +option csharp_namespace = "ToxiCode.BuyIt.Logistics.Api.Grpc"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; +import "protos/ItemsService.proto"; +import "google/api/annotations.proto"; +package BuyIt.Logistics; + + +service OrdersService{ + rpc AddOrder(AddOrderRequest) returns (AddOrderResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } + rpc GetOrders(GetOrdersRequest) returns (GetOrdersResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } + rpc OrderPaid(OrderPaidRequest) returns (OrderPaidResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } + rpc CancelOrder(CancelOrderRequest) returns (CancelOrderResponse){ + option(google.api.http) = { + post: "/v1/common/items/add" + body: "*" + }; + } +} + +message AddOrderRequest{ + repeated ItemAmountPair items = 1; +} + +message ItemAmountPair{ + int64 item_id = 1; + int64 count = 2; +} + +message AddOrderResponse{ + google.protobuf.Int64Value order_id = 1; + string result_message = 2; +} + +message GetOrdersRequest{ + string buyer_id = 1; +} + +message GetOrdersResponse{ + repeated Order orders = 1; +} + +message Order{ + int64 order_id = 1; + OrderStatus order_status = 2; + repeated BuyIt.Logistics.Item items = 3; +} + +enum OrderStatus{ + Default = 0; + Created = 1; + Processing = 2; + Forming = 3; + Formed = 4; + Delivering = 5; + Delivered = 6; + Cancelled = 7; +} + +message OrderPaidRequest{ + int64 order_id = 1; +} + + +message OrderPaidResponse{ + string result_message = 1; +} + +message CancelOrderRequest{ + int64 order_id = 1; +} + + +message CancelOrderResponse{ + string result_message = 1; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs index 423d831..9af2bf8 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs @@ -1,11 +1,12 @@ using System.Text.Json; -using Confluent.Kafka; -using ToxiCode.BuyIt.Api.Contracts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Items.Commands; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; using ToxiCode.BuyIt.Logistics.Api.Kafka; +using ToxiCode.BuyIt.Api.Contracts; using Action = ToxiCode.BuyIt.Api.Contracts.Action; -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Items; +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; public class ItemsServiceNotificationDecorator : IItemService { @@ -23,8 +24,8 @@ public async Task CreateItem(CreateItemRequest request, CancellationToken var result = await _target.CreateItem(request, cancellationToken); var notification = new CreatedItemNotification() { - Price = request.Price, - Name = request.Name, + Price = request.Item.Price, + Name = request.Item.Name, Description = "Not provided", Id = result, OwnerId = Guid.NewGuid() diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs index 1ad536c..8fd903a 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs @@ -38,7 +38,7 @@ public async Task CreateItem(CreateItemRequest request, Canc const string insertItemQuery = $@"INSERT INTO {SqlConstants.Items} (name, price, weight) - VALUES (@Name, @Price, @Weight) returning id"; + VALUES (@Name, @Price, @Weight, @Height, @Lenght, @Width) returning id"; await using var db = _connectionFactory.CreateDatabase(cancellationToken); @@ -46,7 +46,10 @@ public async Task CreateItem(CreateItemRequest request, Canc { request.Item.Name, request.Item.Price, - request.Item.Weight + request.Item.Weight, + request.Item.Height, + request.Item.Lenght, + request.Item.Width }); return new CreateItemResponse() { diff --git a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs new file mode 100644 index 0000000..5829977 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs @@ -0,0 +1,14 @@ +using Grpc.Core; +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace ToxiCode.BuyIt.Logistics.Api.GrpcControllers; + +public class ItemsGrpcController : ItemsService.ItemsServiceBase +{ + public override Task AddItems(AddItemsRequest request, ServerCallContext context) + => base.AddItems(request, context); + + public override Task GetItems(GetItemsRequest request, ServerCallContext context) => base.GetItems(request, context); + + public override Task ChangeItems(ChangeItemsRequest request, ServerCallContext context) => base.ChangeItems(request, context); +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs new file mode 100644 index 0000000..9f65176 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs @@ -0,0 +1,10 @@ +using Grpc.Core; +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace ToxiCode.BuyIt.Logistics.Api.GrpcControllers; + +public class OrdersGrpcController : OrdersService.OrdersServiceBase +{ + public override Task AddOrder(AddOrderRequest request, ServerCallContext context) => base.AddOrder(request, context); + public override Task GetOrders(GetOrdersRequest request, ServerCallContext context) => base.GetOrders(request, context); +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs b/src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs deleted file mode 100644 index 570f6d5..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/GrpcServices/CommonGrpcService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using ToxiCode.BuyIt.Logistics.Api.Grpc; - -namespace ToxiCode.BuyIt.Logistics.Api.GrpcServices; - -public class CommonGrpcService : CommonBuyItLogisticsService.CommonBuyItLogisticsServiceBase -{ - -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs index 38c8ac9..716f810 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs @@ -4,10 +4,9 @@ using MediatR; using Microsoft.AspNetCore.Server.Kestrel.Core; using ToxiCode.BuyIt.Logistics.Api; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Items; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Extensions; -using ToxiCode.BuyIt.Logistics.Api.Grpc; -using ToxiCode.BuyIt.Logistics.Api.GrpcServices; +using ToxiCode.BuyIt.Logistics.Api.GrpcControllers; using ToxiCode.BuyIt.Logistics.Api.Infrustructure.Extensions; var builder = WebApplication.CreateBuilder(args); @@ -46,12 +45,11 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro services .AddHttpContextAccessor() .AddSingleton() - .AddSingleton() + .AddSingleton() + .AddSingleton() .AddKafka(builder.Configuration); -services - .AddSingleton() - .Decorate(); +services.AddSingleton(); #endregion @@ -63,7 +61,8 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro app.UseSwaggerUI(); app.UseAuthorization(); app.MapControllers(); -app.MapGrpcService(); +app.MapGrpcService(); +app.MapGrpcService(); app.Migrate(); app.Run(); diff --git a/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj b/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj index c398694..984649c 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj +++ b/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj @@ -3,6 +3,7 @@ enable enable + false Linux From 9335e20b4d7fdc8afc4d47b7ccee88576cce34e8 Mon Sep 17 00:00:00 2001 From: daniilkuznetsov Date: Sat, 21 May 2022 15:15:55 +0300 Subject: [PATCH 03/11] 0 --- .../ToxiCode.BuyIt.Logistics.Api.Dtos.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj index 3ecd91f..73f44b0 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ToxiCode.BuyIt.Logistics.Api.Dtos.csproj @@ -3,6 +3,7 @@ enable enable + false Dtos From d5d149b975d658afc278a98de5079c53cfda4d71 Mon Sep 17 00:00:00 2001 From: daniilkuznetsov Date: Sun, 22 May 2022 00:27:44 +0300 Subject: [PATCH 04/11] [TXC-5] added proto and more new things --- .../AddItemGrpcDto.cs | 13 ++ src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs | 12 -- .../ItemDto.cs | 15 +++ .../DecimalValue.cs | 31 +++++ .../protos/Decimal.proto | 9 ++ .../protos/ItemsService.proto | 75 ++++++----- .../protos/OrdersService.proto | 7 +- .../AddArticlesByItemHandler.cs | 19 --- .../Contracts/CreateArticleRequest.cs | 9 -- .../Contracts/CreateArticleRespone.cs | 6 - .../ChangeItemById/ChangeItemByIdHandler.cs | 17 ++- .../Contracnts/ChangeItemCommand.cs | 13 ++ .../Contracnts/ChangeItemRequest.cs | 11 -- .../Contracts/CreateArticleByItemIdCommand.cs | 9 ++ .../CreateArticleByItemIdHandler.cs | 24 ++++ ...ateItemRequest.cs => CreateItemCommand.cs} | 4 +- .../Commands/CreateItem/CreateItemHandler.cs | 36 +++++- .../BusinessLayer/Commands/GetItemResponse.cs | 8 -- .../GetItems/Contracts/GetItemResponse.cs | 8 ++ .../Contracts/GetItemsByIdsCommand.cs | 8 ++ .../Commands/GetItems/GetItemsByIdsHandler.cs | 23 ++++ .../BusinessLayer/Commands/GetItemsRequest.cs | 1 + .../Commands/GetItemsResponse.cs | 2 +- .../BusinessLayer/Services/IItemService.cs | 4 +- .../ItemsServiceNotificationDecorator.cs | 27 +--- .../DatabaseInfrastructureExtension.cs | 2 + .../DataLayer/Migrations/initMigration.cs | 18 ++- .../Repository/Articles/ArticlesRepository.cs | 40 ++++++ .../Queries/CreateArticleByItemIdQuery.cs | 7 + .../Repository/ArticlesRepository.cs | 40 ------ .../Repository/Items/ItemsRepository.cs | 99 ++++++++++++++ .../Items/Queries/ChangeItemQuery.cs | 11 ++ .../Items/Queries/CreateItemQuery.cs | 8 ++ .../DataLayer/Repository/ItemsRepository.cs | 87 ------------- .../GrpcControllers/ItemsGrpcController.cs | 122 +++++++++++++++++- .../HttpControllers/ItemController.cs | 19 +-- src/ToxiCode.BuyIt.Logistics.Api/Program.cs | 2 +- .../appsettings.json | 2 +- 38 files changed, 558 insertions(+), 290 deletions(-) create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Dtos/AddItemGrpcDto.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Dtos/ItemDto.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/DecimalValue.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/Decimal.proto delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/AddArticlesByItemHandler.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRequest.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRespone.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemCommand.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemRequest.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/Contracts/CreateArticleByItemIdCommand.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs rename src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/Contracts/{CreateItemRequest.cs => CreateItemCommand.cs} (50%) delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsByIdsCommand.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ArticlesRepository.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/ChangeItemQuery.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/CreateItemQuery.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/AddItemGrpcDto.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/AddItemGrpcDto.cs new file mode 100644 index 0000000..b744617 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/AddItemGrpcDto.cs @@ -0,0 +1,13 @@ +namespace Dtos; + +public class AddItemGrpcDto +{ + public Guid SellerId { get; set; } + public string ItemName { get; set; } = null!; + public decimal Weight { get; set; } + public decimal Height { get; set; } + public decimal Length { get; set; } + public decimal Width { get; set; } + public int Count { get; set; } + public string ImgUrl { get; set; } = null!; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs deleted file mode 100644 index 90895eb..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Item.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Dtos; - -public class Item -{ - public long Id { get; set; } - public string Name { get; set; } = null!; - public decimal Price { get; set; } - public decimal Weight { get; set; } - public decimal Height { get; set; } - public decimal Lenght { get; set; } - public decimal Width { get; set; } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ItemDto.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ItemDto.cs new file mode 100644 index 0000000..ec73662 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/ItemDto.cs @@ -0,0 +1,15 @@ +namespace Dtos; + +public class ItemDto +{ + public long Id { get; set; } + public Guid SellerId { get; set; } + public string ItemName { get; set; } = null!; + public decimal Weight { get; set; } + public decimal Height { get; set; } + public decimal Length { get; set; } + public decimal Width { get; set; } + public int AvailableCount { get; set; } + public DateTime CreationDate { get; set; } + public DateTime ChangedAt { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/DecimalValue.cs b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/DecimalValue.cs new file mode 100644 index 0000000..39f3a5a --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/DecimalValue.cs @@ -0,0 +1,31 @@ +namespace ToxiCode.BuyIt.Logistics.Api.Grpc; + +public partial class DecimalValue +{ + private const decimal NanoFactor = 1_000_000_000; + + public DecimalValue(long units, int nanos) + { + Units = units; + Nanos = nanos; + } + + public static implicit operator decimal(DecimalValue grpcDecimal) + => grpcDecimal == null! + ? throw new ArgumentNullException(nameof(grpcDecimal)) + : grpcDecimal.Units + grpcDecimal.Nanos / NanoFactor; + + public static implicit operator DecimalValue(decimal value) + { + var units = decimal.ToInt64(value); + var nanos = decimal.ToInt32((value - units) * NanoFactor); + return new DecimalValue(units, nanos); + } + + public static implicit operator decimal?(DecimalValue? grpcDecimal) + => grpcDecimal is null ? null : (decimal)grpcDecimal; + + public static implicit operator DecimalValue?(decimal? value) + => value is null ? null : value.Value; +} + diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/Decimal.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/Decimal.proto new file mode 100644 index 0000000..0dfc7c0 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/Decimal.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +option csharp_namespace = "ToxiCode.BuyIt.Logistics.Api.Grpc"; +package BuyIt.Logistics; + + +message DecimalValue { + int64 units = 1; + sfixed32 nanos = 2; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto index ddc2dcc..4abedc9 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/ItemsService.proto @@ -2,86 +2,92 @@ syntax = "proto3"; option csharp_namespace = "ToxiCode.BuyIt.Logistics.Api.Grpc"; import "google/protobuf/timestamp.proto"; import "google/api/annotations.proto"; +import "protos/Decimal.proto"; package BuyIt.Logistics; service ItemsService{ - rpc AddItems(AddItemsRequest) returns (AddItemsResponse){ + rpc AddItem(AddItemRequest) returns (AddItemResponse){ option(google.api.http) = { - post: "/v1/common/items/add" + post: "/v1/items/add" body: "*" }; } - rpc GetItems(GetItemsRequest) returns (GetItemsResponse){ + rpc GetItemsByIds(GetItemsByIdsRequest) returns (GetItemsByIdsResponse){ option(google.api.http) = { - post: "/v1/common/items/add" + patch: "/v1/items/get" body: "*" }; } - rpc ChangeItems(ChangeItemsRequest) returns (ChangeItemsResponse){ + rpc ChangeItem(ChangeItemRequest) returns (ChangeItemResponse){ option(google.api.http) = { - post: "/v1/common/items/add" + put: "/v1/items/change" + body: "*" + }; + } + rpc AddArticles(AddArticlesRequest) returns (AddArticlesResponse){ + option(google.api.http) = { + put: "/v1/articles/add" body: "*" }; } } -message AddItemsRequest{ - repeated AddItem add_items = 1; +message AddItemRequest{ + AddItem add_item = 1; } message AddItem{ string item_name = 1; string seller_id = 2; - int32 weight = 3; - int32 height = 4; - int32 length = 5; - int32 width = 6; + BuyIt.Logistics.DecimalValue weight = 3; + BuyIt.Logistics.DecimalValue height = 4; + BuyIt.Logistics.DecimalValue length = 5; + BuyIt.Logistics.DecimalValue width = 6; int32 count = 7; - string request_item_id = 8; - repeated string img_urls = 9; + string img_url = 9; } -message AddItemsResponse{ - repeated ItemResult items = 1; +message AddItemResponse{ + ItemResult add_item_result = 1; } message ItemResult{ int64 item_id = 1; - string request_item_id = 2; string result_message = 3; } -message GetItemsRequest{ +message GetItemsByIdsRequest{ repeated int64 items_ids = 1; } -message GetItemsResponse{ +message GetItemsByIdsResponse{ repeated Item items = 1; } message Item{ int64 item_id = 1; - int32 weight = 2; - int32 height = 3; - int32 length = 4; - int32 width = 5; - int32 available_count = 6; - google.protobuf.Timestamp creation_date = 7; - google.protobuf.Timestamp change_at = 8; + string item_name = 2; + string seller_id = 3; + BuyIt.Logistics.DecimalValue weight = 4; + BuyIt.Logistics.DecimalValue height = 5; + BuyIt.Logistics.DecimalValue length = 6; + BuyIt.Logistics.DecimalValue width = 7; + int32 available_count = 8; + google.protobuf.Timestamp creation_date = 9; + google.protobuf.Timestamp changed_at = 10; } -message ChangeItemsRequest{ +message ChangeItemRequest{ int64 item_id = 1; string item_name = 2; int32 height = 3; int32 weight = 4; int32 length = 5; int32 width = 6; - repeated string img_urls = 7; } -message ChangeItemsResponse{ - repeated ItemChangeResult items = 1; +message ChangeItemResponse{ + ItemChangeResult ItemResult = 1; } message ItemChangeResult{ @@ -89,3 +95,12 @@ message ItemChangeResult{ bool item_changed = 2; string result_message = 3; } + +message AddArticlesRequest{ + int64 item_id = 1; + int32 count = 2; +} + +message AddArticlesResponse{ + string result_message = 1; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto index cb4a7f6..97ff333 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto @@ -10,19 +10,19 @@ package BuyIt.Logistics; service OrdersService{ rpc AddOrder(AddOrderRequest) returns (AddOrderResponse){ option(google.api.http) = { - post: "/v1/common/items/add" + post: "/v1/orders/add" body: "*" }; } rpc GetOrders(GetOrdersRequest) returns (GetOrdersResponse){ option(google.api.http) = { - post: "/v1/common/items/add" + patch: "/v1/orders/get" body: "*" }; } rpc OrderPaid(OrderPaidRequest) returns (OrderPaidResponse){ option(google.api.http) = { - post: "/v1/common/items/add" + put: "/v1/orders/change" body: "*" }; } @@ -36,6 +36,7 @@ service OrdersService{ message AddOrderRequest{ repeated ItemAmountPair items = 1; + int64 place_id = 2; } message ItemAmountPair{ diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/AddArticlesByItemHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/AddArticlesByItemHandler.cs deleted file mode 100644 index 937eaf5..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/AddArticlesByItemHandler.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediatR; -using MediatR.Wrappers; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.AddArticlesByItem.Contracts; -using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.AddArticlesByItem; - -public class AddArticlesByItemHandler : IRequestHandler -{ - private readonly ArticlesRepository _articlesRepository; - - public AddArticlesByItemHandler(ArticlesRepository articlesRepository) - => _articlesRepository = articlesRepository; - - public async Task Handle(CreateArticleRequest request, CancellationToken cancellationToken) - { - return await _articlesRepository.CreateArticles(request, cancellationToken); - } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRequest.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRequest.cs deleted file mode 100644 index 1cc0e0f..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRequest.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MediatR; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.AddArticlesByItem.Contracts; - -public class CreateArticleRequest : IRequest -{ - public int Count; - public long ItemId; -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRespone.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRespone.cs deleted file mode 100644 index 199b6f1..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/AddArticlesByItem/Contracts/CreateArticleRespone.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.AddArticlesByItem.Contracts; - -public class CreateArticleRespone -{ - public long[] Articles { get; set; } = null!; -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/ChangeItemByIdHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/ChangeItemByIdHandler.cs index 004dec6..118d575 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/ChangeItemByIdHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/ChangeItemByIdHandler.cs @@ -1,18 +1,29 @@ using MediatR; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById; -public class ChangeItemByIdHandler : AsyncRequestHandler +public class ChangeItemByIdHandler : AsyncRequestHandler { private readonly ItemsRepository _itemsRepository; public ChangeItemByIdHandler(ItemsRepository itemsRepository) => _itemsRepository = itemsRepository; - protected override async Task Handle(ChangeItemRequest request, CancellationToken cancellationToken) + protected override async Task Handle(ChangeItemCommand command, CancellationToken cancellationToken) { - await _itemsRepository.ChangeItem(request, cancellationToken); + var query = new ChangeItemQuery + { + Id = command.Id, + ItemName = command.ItemName, + Weight = command.Weight, + Height = command.Height, + Length = command.Length, + Width = command.Width, + }; + await _itemsRepository.ChangeItem(query, cancellationToken); } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemCommand.cs new file mode 100644 index 0000000..010a495 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemCommand.cs @@ -0,0 +1,13 @@ +using MediatR; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; + +public class ChangeItemCommand : IRequest +{ + public long Id { get; set; } + public string ItemName { get; set; } = null!; + public decimal Weight { get; set; } + public decimal Height { get; set; } + public decimal Length { get; set; } + public decimal Width { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemRequest.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemRequest.cs deleted file mode 100644 index e550dcd..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/ChangeItemById/Contracnts/ChangeItemRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediatR; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; - -public class ChangeItemRequest : IRequest -{ - public long Id { get; set; } - public string Name { get; set; } = null!; - public decimal Price { get; set; } - public decimal Weight { get; set; } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/Contracts/CreateArticleByItemIdCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/Contracts/CreateArticleByItemIdCommand.cs new file mode 100644 index 0000000..510c1c8 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/Contracts/CreateArticleByItemIdCommand.cs @@ -0,0 +1,9 @@ +using MediatR; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateArticleByItemId.Contracts; + +public class CreateArticleByItemIdCommand : IRequest +{ + public int Count; + public long ItemId; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs new file mode 100644 index 0000000..4d64916 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs @@ -0,0 +1,24 @@ +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateArticleByItemId.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateArticleByItemId; + +public class CreateArticleByItemIdHandler : AsyncRequestHandler +{ + private readonly ArticlesRepository _articlesRepository; + + public CreateArticleByItemIdHandler(ArticlesRepository articlesRepository) + => _articlesRepository = articlesRepository; + + protected override async Task Handle(CreateArticleByItemIdCommand request, CancellationToken cancellationToken) + { + var query = new CreateArticleByItemIdQuery() + { + ItemId = request.ItemId, + Count = request.Count + }; + await _articlesRepository.CreateArticleByItemId(query, cancellationToken); + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/Contracts/CreateItemRequest.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/Contracts/CreateItemCommand.cs similarity index 50% rename from src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/Contracts/CreateItemRequest.cs rename to src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/Contracts/CreateItemCommand.cs index d0203a5..e4576fd 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/Contracts/CreateItemRequest.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/Contracts/CreateItemCommand.cs @@ -3,7 +3,7 @@ namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; -public class CreateItemRequest : IRequest +public class CreateItemCommand : IRequest { - public Item Item { get; set; } = null!; + public AddItemGrpcDto Item { get; set; } = null!; } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/CreateItemHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/CreateItemHandler.cs index 27d6d80..9997032 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/CreateItemHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateItem/CreateItemHandler.cs @@ -1,18 +1,44 @@ using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateArticleByItemId.Contracts; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem; -public class CreateItemsHandler : IRequestHandler +public class CreateItemHandler : IRequestHandler { private readonly ItemsRepository _itemsRepository; + private readonly ArticlesRepository _articlesRepository; - public CreateItemsHandler(ItemsRepository itemsRepository) - => _itemsRepository = itemsRepository; + public CreateItemHandler(ItemsRepository itemsRepository, ArticlesRepository articlesRepository) + { + _itemsRepository = itemsRepository; + _articlesRepository = articlesRepository; + } - public async Task Handle(CreateItemRequest request, CancellationToken cancellationToken) + public async Task Handle(CreateItemCommand request, CancellationToken cancellationToken) { - return await _itemsRepository.CreateItem(request, cancellationToken); + var query = new CreateItemQuery + { + Item = request.Item + }; + var id = await _itemsRepository.CreateItem(query, cancellationToken); + + var articleQuery = new CreateArticleByItemIdQuery + { + ItemId = id, + Count = request.Item.Count + }; + + await _articlesRepository.CreateArticleByItemId(articleQuery, cancellationToken); + + return new CreateItemResponse() + { + Id = id + }; } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemResponse.cs deleted file mode 100644 index 3537712..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Dtos; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; - -public class GetItemResponse -{ - public Item? Item { get; set; } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemResponse.cs new file mode 100644 index 0000000..5f2fe84 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemResponse.cs @@ -0,0 +1,8 @@ +using Dtos; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; + +public class GetItemResponse +{ + public ItemDto? Item { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsByIdsCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsByIdsCommand.cs new file mode 100644 index 0000000..0c89f06 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsByIdsCommand.cs @@ -0,0 +1,8 @@ +using MediatR; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; + +public class GetItemsByIdsCommand : IRequest +{ + public IEnumerable ItemIds { get; set; } = null!; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs new file mode 100644 index 0000000..ba1c1ab --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs @@ -0,0 +1,23 @@ +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems; + +public class GetItemsByIdsHandler : IRequestHandler +{ + private readonly ItemsRepository _itemsRepository; + + public GetItemsByIdsHandler(ItemsRepository itemsRepository) + { + _itemsRepository = itemsRepository; + } + public async Task Handle(GetItemsByIdsCommand request, CancellationToken cancellationToken) + { + return new GetItemsResponse + { + Items = await _itemsRepository.GetItemsByIds(request.ItemIds.ToArray()) + }; + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs index 8c4d1c5..426204b 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs @@ -2,4 +2,5 @@ namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; public class GetItemsRequest { + public long ItemsIds { get; set; } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs index 2061576..ce62f3d 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs @@ -4,5 +4,5 @@ namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; public class GetItemsResponse { - public IEnumerable? Items { get; set; } + public IEnumerable Items { get; set; } = Array.Empty(); } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs index 9f504ad..998b1d7 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs @@ -2,14 +2,14 @@ using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; public interface IItemService { - public Task CreateItem(CreateItemRequest request, CancellationToken cancellationToken); public Task DeleteItem(long request, CancellationToken cancellationToken); - public Task ChangeItem(ChangeItemRequest request, CancellationToken cancellationToken); + public Task ChangeItem(ChangeItemCommand command, CancellationToken cancellationToken); public Task GetItem(long id); public Task GetItems(); } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs index 9af2bf8..7ce2585 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs @@ -4,6 +4,7 @@ using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; using ToxiCode.BuyIt.Logistics.Api.Kafka; using ToxiCode.BuyIt.Api.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; using Action = ToxiCode.BuyIt.Api.Contracts.Action; namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; @@ -18,33 +19,13 @@ public ItemsServiceNotificationDecorator(IItemService target, IKafkaProducer pro _target = target; _producer = producer; } - - public async Task CreateItem(CreateItemRequest request, CancellationToken cancellationToken) - { - var result = await _target.CreateItem(request, cancellationToken); - var notification = new CreatedItemNotification() - { - Price = request.Item.Price, - Name = request.Item.Name, - Description = "Not provided", - Id = result, - OwnerId = Guid.NewGuid() - }; - var wrapper = new KafkaMessage - { - CreatedItemNotification = notification, - Action = Action.Created - }; - var json = JsonSerializer.Serialize(wrapper); - await _producer.SendMessageAsync(result.ToString(), json, cancellationToken); - return result; - } + public Task DeleteItem(long request, CancellationToken cancellationToken) => _target.DeleteItem(request, cancellationToken); - public Task ChangeItem(ChangeItemRequest request, CancellationToken cancellationToken) - => _target.ChangeItem(request, cancellationToken); + public Task ChangeItem(ChangeItemCommand command, CancellationToken cancellationToken) + => _target.ChangeItem(command, cancellationToken); public Task GetItem(long id) => _target.GetItem(id); diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs index d06adb7..84ba592 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs @@ -2,6 +2,8 @@ using FluentMigrator.Runner; using Microsoft.AspNetCore.Mvc; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Extensions; diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs index 1eee1c7..bc48d5a 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs @@ -10,11 +10,18 @@ public class InitMigration : ForwardOnlyMigration { public override void Up() { + Execute.Sql($"CREATE TYPE State AS ENUM ('Default', 'Created', 'Processing', 'Forming', 'Formed', 'Delivering', 'Delivered', 'Cancelled');"); Create.Table(SqlConstants.Items) .WithColumn("id").AsInt64().PrimaryKey().Identity() - .WithColumn("name").AsString(1000).NotNullable().Unique() - .WithColumn("price").AsDecimal() - .WithColumn("weight").AsDecimal(); + .WithColumn("seller_id").AsGuid() + .WithColumn("item_name").AsString(1000).NotNullable() + .WithColumn("weight").AsDecimal() + .WithColumn("height").AsDecimal() + .WithColumn("length").AsDecimal() + .WithColumn("width").AsDecimal() + .WithColumn("creation_date").AsDateTime().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("changed_at").AsDateTime().WithDefault(SystemMethods.CurrentUTCDateTime) + .WithColumn("img_url").AsString().WithDefaultValue("https://www.ceph.txcd.xyz/toxicode-buyit-api/7f2c3f68-af2f-47b6-9628-40fa98906d30.png"); Create.Table(SqlConstants.Places) .WithColumn("id").AsInt64().PrimaryKey().Identity() @@ -26,9 +33,10 @@ public override void Up() Create.Table(SqlConstants.Orders) .WithColumn("id").AsInt64().PrimaryKey().Identity() - .WithColumn("date_time").AsDateTime() + .WithColumn("creation_date").AsDateTime().WithDefault(SystemMethods.CurrentUTCDateTime) .WithColumn("from").AsInt64().ForeignKey(SqlConstants.Places, "id").NotNullable() - .WithColumn("to").AsInt64().ForeignKey(SqlConstants.Places, "id").NotNullable(); + .WithColumn("to").AsInt64().ForeignKey(SqlConstants.Places, "id").NotNullable() + .WithColumn("state").AsCustom("State"); Create.Table(SqlConstants.ArticlesInOrder) .WithColumn("id").AsInt64().PrimaryKey().Identity() diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs new file mode 100644 index 0000000..5ad3b89 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs @@ -0,0 +1,40 @@ +using Dapper; +using Dtos; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; + +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; + +public class ArticlesRepository +{ + private readonly IDbConnectionFactory _connectionFactory; + + public ArticlesRepository(IDbConnectionFactory connectionFactory) => _connectionFactory = connectionFactory; + + public async Task> GetArticles() + { + const string getArticleQuery = $@"SELECT id, item_id FROM {SqlConstants.Articles}"; + await using var db = _connectionFactory.CreateDatabase(); + return await db.Connection.QueryAsync
(db.CreateCommand(getArticleQuery)); + } + + public async Task CreateArticleByItemId(CreateArticleByItemIdQuery request, CancellationToken cancellationToken) + { + const string insertArticlesQuery = + $@"INSERT INTO {SqlConstants.Articles} + (item_id) + VALUES (@ItemId)"; + + await using var db = _connectionFactory.CreateDatabase(cancellationToken); + await db.Connection.OpenAsync(cancellationToken); + var transaction = await db.Connection.BeginTransactionAsync(cancellationToken); + + for(var i = 0; i < request.Count; i++) + await db.Connection.ExecuteAsync(insertArticlesQuery, new + { + request.ItemId + }, + transaction); + await transaction.CommitAsync(cancellationToken); + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs new file mode 100644 index 0000000..2a32470 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs @@ -0,0 +1,7 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; + +public class CreateArticleByItemIdQuery +{ + public int Count; + public long ItemId; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ArticlesRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ArticlesRepository.cs deleted file mode 100644 index d2cef71..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ArticlesRepository.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Dapper; -using Dtos; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.AddArticlesByItem.Contracts; -using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; - -namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; - -public class ArticlesRepository -{ - private readonly IDbConnectionFactory _connectionFactory; - - public ArticlesRepository(IDbConnectionFactory connectionFactory) => _connectionFactory = connectionFactory; - - public async Task> GetItems() - { - const string getArticleQuery = $@"SELECT id, item_id FROM {SqlConstants.Articles}"; - await using var db = _connectionFactory.CreateDatabase(); - return await db.Connection.QueryAsync
(db.CreateCommand(getArticleQuery)); - } - - public async Task CreateArticles(CreateArticleRequest request, CancellationToken cancellationToken) - { - const string insertArticlesQuery = - $@"INSERT INTO {SqlConstants.Articles} - (item_id) - VALUES (@ItemId) returning id"; - - await using var db = _connectionFactory.CreateDatabase(cancellationToken); - - var articlesId = await db.Connection.QueryFirstOrDefaultAsync(insertArticlesQuery, new - { - request.ItemId - }); - return new CreateArticleRespone() - { - Articles = articlesId - }; - } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs new file mode 100644 index 0000000..c63ba24 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs @@ -0,0 +1,99 @@ +using Dapper; +using Dtos; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; + +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; + +public class ItemsRepository +{ + private readonly IDbConnectionFactory _connectionFactory; + + public ItemsRepository(IDbConnectionFactory connectionFactory) => _connectionFactory = connectionFactory; + + public async Task> GetItemsByIds(long[] Ids) + { + const string getItemsQuery = $@" SELECT + it.id, + seller_id SellerId, + item_name Name, + weight, + height, + length, + width, + it.creation_date CreationDate, + changed_at ChangedAt, + (SELECT count(a.id) + FROM public.articles a + LEFT JOIN public.articles_in_order aio ON aio.article_id = a.id + LEFT JOIN public.orders o ON aio.order_id = o.id + WHERE a.item_id = it.id AND o.id IS NULL OR o.state = 'Cancelled'::State) + FROM items it + WHERE it.id = any(@Ids)"; + await using var db = _connectionFactory.CreateDatabase(); + return await db.Connection.QueryAsync(db.CreateCommand(getItemsQuery, new {Ids})); + } + + public async Task CreateItem(CreateItemQuery request, CancellationToken cancellationToken) + { + var insertItemQuery = $@"INSERT INTO {SqlConstants.Items} + (item_name, seller_id, weight, height, length, width"; + + if (!string.IsNullOrEmpty(request.Item.ImgUrl)) + insertItemQuery += ", img_url) VALUES (@ItemName, @SellerId, @Weight, @Height, @Length, @Width, @ImgUrl) returning id"; + else + insertItemQuery += ") VALUES (@ItemName, @SellerId, @Weight, @Height, @Length, @Width) returning id"; + + await using var db = _connectionFactory.CreateDatabase(cancellationToken); + + var id = await db.Connection.QueryFirstOrDefaultAsync(insertItemQuery, new + { + request.Item.ItemName, + request.Item.SellerId, + request.Item.Weight, + request.Item.Height, + request.Item.Length, + request.Item.Width, + request.Item.ImgUrl + }); + return id; + } + + public async Task DeleteItemById(long itemId, CancellationToken cancellationToken) + { + const string DeleteItemQuery = $@"DELETE FROM {SqlConstants.Items} WHERE id = @Id "; + + await using var db = _connectionFactory.CreateDatabase(cancellationToken); + + await db.Connection.ExecuteAsync(DeleteItemQuery, new + { + Id = itemId + }); + } + + public async Task ChangeItem(ChangeItemQuery command, CancellationToken cancellationToken) + { + const string ChangeItemQuery = $@"UPDATE {SqlConstants.Items} + SET + item_name = @ItemName, + weight = @Weight, + height = @Height, + length = @Length, + width = @Width + WHERE id = @Id "; + + await using var db = _connectionFactory.CreateDatabase(cancellationToken); + + await db.Connection.ExecuteAsync(ChangeItemQuery, new + { + command.Id, + command.ItemName, + command.Weight, + command.Height, + command.Length, + command.Width + }); + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/ChangeItemQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/ChangeItemQuery.cs new file mode 100644 index 0000000..63e8df7 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/ChangeItemQuery.cs @@ -0,0 +1,11 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; + +public class ChangeItemQuery +{ + public long Id { get; set; } + public string ItemName { get; set; } = null!; + public decimal Weight { get; set; } + public decimal Height { get; set; } + public decimal Length { get; set; } + public decimal Width { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/CreateItemQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/CreateItemQuery.cs new file mode 100644 index 0000000..8a54e28 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/CreateItemQuery.cs @@ -0,0 +1,8 @@ +using Dtos; + +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; + +public class CreateItemQuery +{ + public AddItemGrpcDto Item { get; set; } = null!; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs deleted file mode 100644 index 8fd903a..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/ItemsRepository.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Dapper; -using Dtos; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; -using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; - - -namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; - -public class ItemsRepository -{ - private readonly IDbConnectionFactory _connectionFactory; - - public ItemsRepository(IDbConnectionFactory connectionFactory) => _connectionFactory = connectionFactory; - - public async Task> GetItems() - { - const string getItemsQuery = $@"SELECT id, name, price, weight FROM {SqlConstants.Items}"; - await using var db = _connectionFactory.CreateDatabase(); - return await db.Connection.QueryAsync(db.CreateCommand(getItemsQuery)); - } - - public async Task GetItemById(long itemId) - { - const string getItemByIdQuery = $@"SELECT id, name, price, weight FROM {SqlConstants.Items} WHERE id = @Id"; - await using var db = _connectionFactory.CreateDatabase(); - var requestItem = await db.Connection.QueryFirstOrDefaultAsync(db.CreateCommand(getItemByIdQuery, new - { - Id = itemId - })); - return requestItem; - } - - public async Task CreateItem(CreateItemRequest request, CancellationToken cancellationToken) - { - const string insertItemQuery = - $@"INSERT INTO {SqlConstants.Items} - (name, price, weight) - VALUES (@Name, @Price, @Weight, @Height, @Lenght, @Width) returning id"; - - await using var db = _connectionFactory.CreateDatabase(cancellationToken); - - var id = await db.Connection.QueryFirstOrDefaultAsync(insertItemQuery, new - { - request.Item.Name, - request.Item.Price, - request.Item.Weight, - request.Item.Height, - request.Item.Lenght, - request.Item.Width - }); - return new CreateItemResponse() - { - Id = id - }; - } - - public async Task DeleteItemById(long itemId, CancellationToken cancellationToken) - { - const string DeleteItemQuery = $@"DELETE FROM {SqlConstants.Items} WHERE id = @Id "; - - await using var db = _connectionFactory.CreateDatabase(cancellationToken); - - await db.Connection.ExecuteAsync(DeleteItemQuery, new - { - Id = itemId - }); - } - - public async Task ChangeItem(ChangeItemRequest request, CancellationToken cancellationToken) - { - const string ChangeItemQuery = $@"UPDATE {SqlConstants.Items} - SET name = @Name, price = @Price, weight = @Weight WHERE id = @Id "; - - await using var db = _connectionFactory.CreateDatabase(cancellationToken); - - await db.Connection.ExecuteAsync(ChangeItemQuery, new - { - request.Id, - request.Name, - request.Price, - request.Weight - }); - } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs index 5829977..a6317cb 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs @@ -1,14 +1,124 @@ +using Dtos; +using Google.Protobuf.WellKnownTypes; using Grpc.Core; -using ToxiCode.BuyIt.Logistics.Api.Grpc; +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateArticleByItemId.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; +using GRPC = ToxiCode.BuyIt.Logistics.Api.Grpc; namespace ToxiCode.BuyIt.Logistics.Api.GrpcControllers; -public class ItemsGrpcController : ItemsService.ItemsServiceBase +public class ItemsGrpcController : GRPC.ItemsService.ItemsServiceBase { - public override Task AddItems(AddItemsRequest request, ServerCallContext context) - => base.AddItems(request, context); + private readonly IMediator _mediator; - public override Task GetItems(GetItemsRequest request, ServerCallContext context) => base.GetItems(request, context); + public ItemsGrpcController(IMediator mediator) + { + _mediator = mediator; + } - public override Task ChangeItems(ChangeItemsRequest request, ServerCallContext context) => base.ChangeItems(request, context); + public override async Task AddItem(GRPC.AddItemRequest request, ServerCallContext context) + { + CreateItemCommand command = new() + { + Item = new AddItemGrpcDto + { + ItemName = request.AddItem.ItemName, + SellerId = Guid.Parse(request.AddItem.SellerId), + Weight = request.AddItem.Weight, + Height = request.AddItem.Height, + Length = request.AddItem.Length, + Width = request.AddItem.Width, + Count = request.AddItem.Count, + ImgUrl = request.AddItem.ImgUrl + } + }; + + var response = await _mediator.Send(command); + + var result = new GRPC.AddItemResponse + { + AddItemResult = new GRPC.ItemResult + { + ItemId = response.Id, + ResultMessage = "Success" + } + }; + return result; + } + + public override async Task GetItemsByIds(GRPC.GetItemsByIdsRequest request, ServerCallContext context) + { + GetItemsByIdsCommand command = new() + { + ItemIds = request.ItemsIds + }; + var response = await _mediator.Send(command); + + var result = new GRPC.GetItemsByIdsResponse + { + Items = + { + response.Items.Select(x => + new GRPC.Item + { + ItemId = x.Id, + ItemName = x.ItemName, + SellerId = x.SellerId.ToString(), + Weight = x.Weight, + Height = x.Height, + Length = x.Length, + Width = x.Width, + AvailableCount = x.AvailableCount, + CreationDate = DateTime.SpecifyKind(x.CreationDate, DateTimeKind.Utc).ToTimestamp(), + ChangedAt = DateTime.SpecifyKind(x.ChangedAt, DateTimeKind.Utc).ToTimestamp() + } + ) + } + }; + return result; + } + + public override async Task ChangeItem(GRPC.ChangeItemRequest request, ServerCallContext context) + { + var command = new ChangeItemCommand + { + Id = request.ItemId, + ItemName = request.ItemName, + Weight = request.Weight, + Height = request.Height, + Length = request.Length, + Width = request.Width + }; + + await _mediator.Send(command, context.CancellationToken); + + return new GRPC.ChangeItemResponse + { + ItemResult = new GRPC.ItemChangeResult + { + ItemId = request.ItemId, + ItemChanged = true, + ResultMessage = "Success", + } + }; + } + + public override async Task AddArticles(GRPC.AddArticlesRequest request, ServerCallContext context) + { + var command = new CreateArticleByItemIdCommand + { + ItemId = request.ItemId, + Count = request.Count + }; + + await _mediator.Send(command, context.CancellationToken); + + return new GRPC.AddArticlesResponse + { + ResultMessage = "Success" + }; + } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs index 6967064..839d224 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs @@ -17,26 +17,13 @@ public ItemController(HttpCancellationTokenAccessor cancellationToken, IMediator _cancellationToken = cancellationToken; _mediator = mediator; } - - [HttpGet("api/item/all")] - public async Task GetItems(GetItemsRequest request) - { - return Ok(await _mediator.Send(request)); - } - - + [HttpGet("api/item/{itemId:long}")] public async Task GetItemById(long itemId) { return Ok(await _mediator.Send(itemId)); } - [HttpPost("api/item")] - public async Task> CreateItem([FromBody] CreateItemRequest request) - { - return Ok(await _mediator.Send(request, _cancellationToken.Token)); - } - [HttpDelete("api/item/{itemId:long}")] public async Task DeleteItem(long itemId) { @@ -45,9 +32,9 @@ public async Task DeleteItem(long itemId) } [HttpPut("api/item/")] - public async Task ChangeItem([FromBody] ChangeItemRequest request) + public async Task ChangeItem([FromBody] ChangeItemCommand command) { - await _mediator.Send(request, _cancellationToken.Token); + await _mediator.Send(command, _cancellationToken.Token); return Ok(); } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs index 716f810..5578e3d 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs @@ -49,7 +49,7 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro .AddSingleton() .AddKafka(builder.Configuration); -services.AddSingleton(); +// services.AddSingleton(); #endregion diff --git a/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json b/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json index 79d90e6..1e96c21 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json +++ b/src/ToxiCode.BuyIt.Logistics.Api/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "Postgre" : "UserID=root;Password=root;Host=localhost;Port=5432;Database=buyit-logistics-api-dev;Pooling=true;MinPoolSize=0;MaxPoolSize=100;ConnectionLifetime=0" + "Postgre" : "UserID=postgres;Password=postgres;Host=localhost;Port=5432;Database=postgres;Pooling=true;MinPoolSize=0;MaxPoolSize=100;ConnectionLifetime=0" }, "KafkaProducerOptions": { "TopicName": "toxicode_buyit_api_items", From 59feff04260196cc658a66a227b88552ed9eae65 Mon Sep 17 00:00:00 2001 From: daniilkuznetsov Date: Wed, 25 May 2022 21:36:48 +0300 Subject: [PATCH 05/11] [TXC-5] change OrdersService.proto --- .../protos/OrdersService.proto | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto index 97ff333..873b746 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto @@ -36,7 +36,9 @@ service OrdersService{ message AddOrderRequest{ repeated ItemAmountPair items = 1; - int64 place_id = 2; + int64 from_address_id = 4; + int64 to_address_id = 5; + string user_id = 2; } message ItemAmountPair{ @@ -59,8 +61,11 @@ message GetOrdersResponse{ message Order{ int64 order_id = 1; - OrderStatus order_status = 2; - repeated BuyIt.Logistics.Item items = 3; + google.protobuf.Timestamp created_date = 2; + OrderStatus order_status = 3; + int64 from_address_id = 4; + int64 to_address_id = 5; + repeated int64 articles = 6; } enum OrderStatus{ From 95a4797682604b37a029a161169de9821828d637 Mon Sep 17 00:00:00 2001 From: "daniilkuznetsov@ozon.ru" Date: Fri, 27 May 2022 04:29:27 +0300 Subject: [PATCH 06/11] [TXC-5] ADD ALL @here @channel --- .../Order.cs | 13 -- .../OrderDto.cs | 21 +++ .../OrderStatusChangedNotificationMessage.cs | 9 ++ .../protos/OrdersService.proto | 12 +- .../CreateArticleByItemIdHandler.cs | 2 +- .../Contracts/CreateOrderCommand.cs | 17 +++ .../Contracts/CreateOrderResponse.cs | 6 + .../CreateOrder/CreateOrderHandler.cs | 56 ++++++++ .../Commands/CreateOrderRequest.cs | 11 -- ...{GetItemResponse.cs => GetItemsCommand.cs} | 6 +- .../GetItems/Contracts/GetItemsResponse.cs | 8 ++ .../Commands/GetItems/GetItemsHandler.cs | 20 +++ .../BusinessLayer/Commands/GetItemsRequest.cs | 6 - .../Commands/GetItemsResponse.cs | 8 -- .../Commands/GetOrderResponse.cs | 8 -- .../Contracts/GetOrdersByBuyerIdCommand.cs | 8 ++ .../Contracts/GetOrdersByBuyerIdResponse.cs | 8 ++ .../GetOrders/Contracts/GetOrdersCommand.cs | 5 + .../GetOrders/Contracts/GetOrdersResponse.cs | 8 ++ .../GetOrders/GetOrdersByBuyerIdHandler.cs | 50 +++++++ .../Commands/GetOrders/GetOrdersHandler.cs | 46 +++++++ .../Commands/GetOrdersResponse.cs | 8 -- .../Contracts/SetOrderStatusCommand.cs | 10 ++ .../Contracts/SetOrderStatusResponse.cs | 6 + .../SetOrderStatus/SetStatusHandler.cs | 30 +++++ .../BusinessLayer/Services/IItemService.cs | 15 --- .../BusinessLayer/Services/IOrderService.cs | 13 -- .../ItemsServiceNotificationDecorator.cs | 35 ----- .../Services/OrdersServiceNotificator.cs | 33 +++++ .../DatabaseInfrastructureExtension.cs | 1 + .../DataLayer/Migrations/initMigration.cs | 5 +- .../Repository/Articles/ArticlesRepository.cs | 39 +++++- .../Queries/CreateArticleByItemIdQuery.cs | 2 +- .../Queries/GetArticleByItemIdQuery.cs | 7 + .../Queries/GetArticlesByOrderIdQuery.cs | 6 + .../Queries/GetItemIdByArticleQuery.cs | 6 + .../Repository/Items/ItemsRepository.cs | 59 ++++++-- .../Repository/Orders/OrdersRepository.cs | 127 ++++++++++++++++++ .../Orders/Queries/CreateOrderQuery.cs | 10 ++ .../Orders/Queries/GetOrdersByBuyerIdQuery.cs | 6 + .../Orders/Queries/SetOrderStatusQuery.cs | 9 ++ .../DataLayer/Repository/OrdersRepository.cs | 93 ------------- .../GrpcControllers/ItemsGrpcController.cs | 2 +- .../GrpcControllers/OrdersGrpcController.cs | 97 ++++++++++++- .../HttpControllers/ItemController.cs | 36 ++++- .../HttpControllers/OrderController.cs | 33 +++-- .../Extensions/KafkaExtensions.cs | 4 +- src/ToxiCode.BuyIt.Logistics.Api/Program.cs | 17 ++- .../ToxiCode.BuyIt.Logistics.Api.csproj | 2 +- 49 files changed, 778 insertions(+), 261 deletions(-) delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderStatusChangedNotificationMessage.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderCommand.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrderRequest.cs rename src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/{GetItemResponse.cs => GetItemsCommand.cs} (51%) create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsHandler.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrderResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdCommand.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersCommand.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrdersResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusCommand.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/SetStatusHandler.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IOrderService.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/OrdersServiceNotificator.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticleByItemIdQuery.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticlesByOrderIdQuery.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetItemIdByArticleQuery.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/CreateOrderQuery.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrdersByBuyerIdQuery.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/SetOrderStatusQuery.cs delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/OrdersRepository.cs diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs deleted file mode 100644 index 4643db3..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Order.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ToxiCode.BuyIt.Logistics.Api.Grpc; - -namespace Dtos; - -public class Order -{ - public long Id { get; set; } - public DateTime CreatedDate { get; set; } - public Place From { get; set; } = null!; - public Place To { get; set; } = null!; - public long[]? Articles { get; set; } - public OrderStatus Status { get; set; } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs new file mode 100644 index 0000000..efe70a1 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs @@ -0,0 +1,21 @@ +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace Dtos; + +public class OrderDto +{ + public long Id { get; set; } + public DateTime CreationDate { get; set; } + public long From { get; set; } + public long To { get; set; } + public IEnumerable Items { get; set; } = null!; + public OrderStatus Status { get; set; } + public string BuyerId { get; set; } = null!; +} + +public class ItemInOrder +{ + public long ItemId { get; set; } + public int Count { get; set; } +} + diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderStatusChangedNotificationMessage.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderStatusChangedNotificationMessage.cs new file mode 100644 index 0000000..c48df34 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderStatusChangedNotificationMessage.cs @@ -0,0 +1,9 @@ +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace Dtos; + +public class OrderStatusChangedNotificationMessage +{ + public long OrderId { get; set; } + public OrderStatus OrderStatus { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto index 873b746..ba2720c 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto @@ -14,7 +14,7 @@ service OrdersService{ body: "*" }; } - rpc GetOrders(GetOrdersRequest) returns (GetOrdersResponse){ + rpc GetOrdersByBuyerId(GetOrdersByBuyerIdRequest) returns (GetOrdersByBuyerIdResponse){ option(google.api.http) = { patch: "/v1/orders/get" body: "*" @@ -43,7 +43,7 @@ message AddOrderRequest{ message ItemAmountPair{ int64 item_id = 1; - int64 count = 2; + int32 count = 2; } message AddOrderResponse{ @@ -51,11 +51,11 @@ message AddOrderResponse{ string result_message = 2; } -message GetOrdersRequest{ +message GetOrdersByBuyerIdRequest{ string buyer_id = 1; } -message GetOrdersResponse{ +message GetOrdersByBuyerIdResponse{ repeated Order orders = 1; } @@ -65,9 +65,11 @@ message Order{ OrderStatus order_status = 3; int64 from_address_id = 4; int64 to_address_id = 5; - repeated int64 articles = 6; + repeated ItemAmountPair items = 6; + string BuyerId = 7; } + enum OrderStatus{ Default = 0; Created = 1; diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs index 4d64916..16dff22 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateArticleByItemId/CreateArticleByItemIdHandler.cs @@ -14,7 +14,7 @@ public CreateArticleByItemIdHandler(ArticlesRepository articlesRepository) protected override async Task Handle(CreateArticleByItemIdCommand request, CancellationToken cancellationToken) { - var query = new CreateArticleByItemIdQuery() + var query = new CreateArticleByItemIdQuery { ItemId = request.ItemId, Count = request.Count diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderCommand.cs new file mode 100644 index 0000000..03610b6 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderCommand.cs @@ -0,0 +1,17 @@ +using MediatR; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateOrder.Contracts; + +public class CreateOrderCommand : IRequest +{ + + public IEnumerable Items { get; set; } = null!; + public long From { get; set; } + public long To { get; set; } + public string UserId { get; set; } = null!; +} + +public class ItemPair{ + public long ItemId { get; set; } + public int Count { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderResponse.cs new file mode 100644 index 0000000..89e215a --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/Contracts/CreateOrderResponse.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateOrder.Contracts; + +public class CreateOrderResponse +{ + public long OrderId { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs new file mode 100644 index 0000000..3779d9e --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs @@ -0,0 +1,56 @@ +using Dtos; +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateOrder.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateOrder; + +public class CreateOrderHandler : IRequestHandler +{ + private readonly OrdersRepository _ordersRepository; + private readonly ArticlesRepository _articlesRepository; + private readonly OrdersServiceNotificator _notificator; + + public CreateOrderHandler(OrdersRepository ordersRepository, ArticlesRepository articlesRepository, OrdersServiceNotificator notificator) + { + _ordersRepository = ordersRepository; + _articlesRepository = articlesRepository; + _notificator = notificator; + } + + public async Task Handle(CreateOrderCommand request, CancellationToken cancellationToken) + { + var articles = new List(); + foreach (var item in request.Items) + { + var articlesQuery = new CreateArticleByItemIdQuery + { + Count = item.Count, + ItemId = item.ItemId + }; + var itemArticles = await _articlesRepository.GetArticlesByItemId(articlesQuery); + articles.AddRange(itemArticles.Select(article => article.Id)); + } + + var query = new CreateOrderQuery + { + CreationDate = DateTime.Now, + From = request.From, + To = request.To, + Articles = articles.ToArray(), + BuyerId = request.UserId + }; + var orderId = await _ordersRepository.CreateOrder(query, cancellationToken); + var result = new CreateOrderResponse + { + OrderId = orderId + }; + await _notificator.NotifyStatusChanged(orderId, OrderStatus.Created, cancellationToken); + return result; + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrderRequest.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrderRequest.cs deleted file mode 100644 index cc21c5e..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrderRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Dtos; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; - -public class CreateOrderRequest -{ - public DateTime CreatedDate { get; set; } - public Place From { get; set; } = null!; - public Place To { get; set; } = null!; - public long[] Articles { get; set; } = null!; -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsCommand.cs similarity index 51% rename from src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemResponse.cs rename to src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsCommand.cs index 5f2fe84..13b5ddb 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemResponse.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsCommand.cs @@ -1,8 +1,8 @@ -using Dtos; +using MediatR; namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; -public class GetItemResponse +public class GetItemsCommand : IRequest { - public ItemDto? Item { get; set; } + } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsResponse.cs new file mode 100644 index 0000000..1b273b1 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/Contracts/GetItemsResponse.cs @@ -0,0 +1,8 @@ +using Dtos; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; + +public class GetItemsResponse +{ + public IEnumerable? Items { get; set; } = Array.Empty(); +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsHandler.cs new file mode 100644 index 0000000..9f4d3e3 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsHandler.cs @@ -0,0 +1,20 @@ + using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems; + +public class GetItemsHandler : IRequestHandler +{ + private readonly ItemsRepository _itemsRepository; + + public GetItemsHandler(ItemsRepository itemsRepository) => _itemsRepository = itemsRepository; + + public async Task Handle(GetItemsCommand request, CancellationToken cancellationToken) + { + return new GetItemsResponse + { + Items = await _itemsRepository.GetItems() + }; + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs deleted file mode 100644 index 426204b..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsRequest.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; - -public class GetItemsRequest -{ - public long ItemsIds { get; set; } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs deleted file mode 100644 index ce62f3d..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItemsResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Dtos; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; - -public class GetItemsResponse -{ - public IEnumerable Items { get; set; } = Array.Empty(); -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrderResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrderResponse.cs deleted file mode 100644 index a50083a..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrderResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Dtos; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; - -public class GetOrderResponse -{ - public Order? Order { get; set; } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdCommand.cs new file mode 100644 index 0000000..081a783 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdCommand.cs @@ -0,0 +1,8 @@ +using MediatR; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; + +public class GetOrdersByBuyerIdCommand : IRequest +{ + public string BuyerId { get; set; } = null!; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdResponse.cs new file mode 100644 index 0000000..b0e059d --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersByBuyerIdResponse.cs @@ -0,0 +1,8 @@ +using Dtos; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; + +public class GetOrdersByBuyerIdResponse +{ + public IEnumerable? Orders { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersCommand.cs new file mode 100644 index 0000000..031b516 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersCommand.cs @@ -0,0 +1,5 @@ +using MediatR; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; + +public record class GetOrdersCommand : IRequest; \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs new file mode 100644 index 0000000..276b0aa --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs @@ -0,0 +1,8 @@ +using Dtos; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; + +public class GetOrdersResponse +{ + public IEnumerable? Orders { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs new file mode 100644 index 0000000..2e47cd3 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs @@ -0,0 +1,50 @@ +using System.Linq; +using System.Runtime.InteropServices.ComTypes; +using Dtos; +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; +using ToxiCode.BuyIt.Logistics.Api.Grpc; +using GetOrdersByBuyerIdResponse = ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts.GetOrdersByBuyerIdResponse; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders; + +public class GetOrdersByBuyerIdHandler : IRequestHandler +{ + private readonly OrdersRepository _ordersRepository; + private readonly ArticlesRepository _articlesRepository; + private readonly ItemsRepository _itemsRepository; + + public GetOrdersByBuyerIdHandler(OrdersRepository ordersRepository, ArticlesRepository articlesRepository, ItemsRepository itemsRepository) + { + _ordersRepository = ordersRepository; + _articlesRepository = articlesRepository; + _itemsRepository = itemsRepository; + } + + public async Task Handle(GetOrdersByBuyerIdCommand request, CancellationToken cancellationToken) + { + var query = new GetOrdersByBuyerIdQuery + { + BuyerId = request.BuyerId + }; + var orders = await _ordersRepository.GetOrdersByBuyerId(query); + foreach (var order in orders) + { + var articlesQuery = new GetArticlesByOrderIdQuery + { + OrderId = order.Id + }; + order.Items = await _itemsRepository.GetItemsByOrderId(order.Id, cancellationToken); + } + + return new GetOrdersByBuyerIdResponse + { + Orders = orders + }; + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs new file mode 100644 index 0000000..4d31e87 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs @@ -0,0 +1,46 @@ +using Dtos; +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders; + +public class GetOrdersHandler : IRequestHandler +{ + private readonly OrdersRepository _ordersRepository; + private ArticlesRepository _articlesRepository; + + public GetOrdersHandler(OrdersRepository ordersRepository, ArticlesRepository articlesRepository) + { + _ordersRepository = ordersRepository; + _articlesRepository = articlesRepository; + } + + public async Task Handle(GetOrdersCommand request, CancellationToken cancellationToken) + { + var orders = await _ordersRepository.GetOrders(); + foreach (var order in orders) + { + var articlesQuery = new GetArticlesByOrderIdQuery + { + OrderId = order.Id + }; + IEnumerable articlesInOrder = await _articlesRepository.GetArticlesByOrderId(articlesQuery); + foreach (var article in articlesInOrder) + { + var articleQuery = new GetItemIdByArticleQuery + { + ArticleId = article + }; + var itemId = await _articlesRepository.GetItemIdByArticle(articleQuery); + } + } + + return new GetOrdersResponse + { + Orders = orders + }; + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrdersResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrdersResponse.cs deleted file mode 100644 index 66d730f..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrdersResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Dtos; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; - -public class GetOrdersResponse -{ - public IEnumerable? Orders { get; set; } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusCommand.cs new file mode 100644 index 0000000..82ac7a6 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusCommand.cs @@ -0,0 +1,10 @@ +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.SetOrderStatus.Contracts; + +public class SetOrderStatusCommand : IRequest +{ + public long OrderId { get; set; } + public OrderStatus Status { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusResponse.cs new file mode 100644 index 0000000..b25cd1b --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/Contracts/SetOrderStatusResponse.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.SetOrderStatus.Contracts; + +public class SetOrderStatusResponse +{ + +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/SetStatusHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/SetStatusHandler.cs new file mode 100644 index 0000000..47924e8 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/SetOrderStatus/SetStatusHandler.cs @@ -0,0 +1,30 @@ +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.SetOrderStatus.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.SetOrderStatus; + +public class SetStatusHandler : AsyncRequestHandler +{ + private OrdersRepository _ordersRepository; + private readonly OrdersServiceNotificator _notificator; + + public SetStatusHandler(OrdersRepository ordersRepository, OrdersServiceNotificator notificator) + { + _ordersRepository = ordersRepository; + _notificator = notificator; + } + + protected override async Task Handle(SetOrderStatusCommand request, CancellationToken cancellationToken) + { + var query = new SetOrderStatusQuery + { + Status = request.Status, + OrderId = request.OrderId + }; + await _ordersRepository.SetOrderStatus(query); + await _notificator.NotifyStatusChanged(query.OrderId, query.Status, cancellationToken); + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs deleted file mode 100644 index 998b1d7..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IItemService.cs +++ /dev/null @@ -1,15 +0,0 @@ -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; - -public interface IItemService -{ - public Task DeleteItem(long request, CancellationToken cancellationToken); - public Task ChangeItem(ChangeItemCommand command, CancellationToken cancellationToken); - public Task GetItem(long id); - public Task GetItems(); -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IOrderService.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IOrderService.cs deleted file mode 100644 index 53e62ed..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/IOrderService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeOrderById.Contracts; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; - -public interface IOrderService -{ - public Task CreateOrder(CreateOrderRequest request, CancellationToken cancellationToken); - public Task DeleteOrder(long request, CancellationToken cancellationToken); - public Task ChangeOrder(ChangeOrderRequest request, CancellationToken cancellationToken); - public Task GetOrder(long id); - public Task GetOrders(); -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs deleted file mode 100644 index 7ce2585..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/ItemsServiceNotificationDecorator.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Text.Json; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; -using ToxiCode.BuyIt.Logistics.Api.Kafka; -using ToxiCode.BuyIt.Api.Contracts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; -using Action = ToxiCode.BuyIt.Api.Contracts.Action; - -namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; - -public class ItemsServiceNotificationDecorator : IItemService -{ - private readonly IItemService _target; - private readonly IKafkaProducer _producer; - - public ItemsServiceNotificationDecorator(IItemService target, IKafkaProducer producer) - { - _target = target; - _producer = producer; - } - - - public Task DeleteItem(long request, CancellationToken cancellationToken) - => _target.DeleteItem(request, cancellationToken); - - public Task ChangeItem(ChangeItemCommand command, CancellationToken cancellationToken) - => _target.ChangeItem(command, cancellationToken); - - public Task GetItem(long id) - => _target.GetItem(id); - - public Task GetItems() - => _target.GetItems(); -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/OrdersServiceNotificator.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/OrdersServiceNotificator.cs new file mode 100644 index 0000000..4fef8b0 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Services/OrdersServiceNotificator.cs @@ -0,0 +1,33 @@ +using System.Text.Json; +using Confluent.Kafka; +using Dtos; +using Newtonsoft.Json; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; +using ToxiCode.BuyIt.Logistics.Api.Kafka; +using ToxiCode.BuyIt.Api.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; +using ToxiCode.BuyIt.Logistics.Api.Grpc; +using Action = ToxiCode.BuyIt.Api.Contracts.Action; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; + +public class OrdersServiceNotificator +{ + private readonly IKafkaProducer _producer; + + public OrdersServiceNotificator(IKafkaProducer producer) + => _producer = producer; + + public Task NotifyStatusChanged(long orderId, OrderStatus status, CancellationToken cancellationToken) + { + var request = new OrderStatusChangedNotificationMessage + { + OrderId = orderId, + OrderStatus = status + }; + var json = JsonConvert.SerializeObject(request); + return _producer.SendMessageAsync(orderId.ToString(), json, cancellationToken); + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs index 84ba592..1870d51 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Extensions/DatabaseInfrastructureExtension.cs @@ -4,6 +4,7 @@ using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Extensions; diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs index bc48d5a..f6b1dbb 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Migrations/initMigration.cs @@ -29,14 +29,15 @@ public override void Up() Create.Table(SqlConstants.Articles) .WithColumn("id").AsInt64().PrimaryKey().Identity() - .WithColumn("item_id").AsInt64(); + .WithColumn("item_id").AsInt64().ForeignKey(SqlConstants.Items, "id"); Create.Table(SqlConstants.Orders) .WithColumn("id").AsInt64().PrimaryKey().Identity() .WithColumn("creation_date").AsDateTime().WithDefault(SystemMethods.CurrentUTCDateTime) .WithColumn("from").AsInt64().ForeignKey(SqlConstants.Places, "id").NotNullable() .WithColumn("to").AsInt64().ForeignKey(SqlConstants.Places, "id").NotNullable() - .WithColumn("state").AsCustom("State"); + .WithColumn("state").AsCustom("State") + .WithColumn("buyer_id").AsString(5000).NotNullable(); Create.Table(SqlConstants.ArticlesInOrder) .WithColumn("id").AsInt64().PrimaryKey().Identity() diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs index 5ad3b89..3969ab4 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/ArticlesRepository.cs @@ -17,6 +17,43 @@ public async Task> GetArticles() await using var db = _connectionFactory.CreateDatabase(); return await db.Connection.QueryAsync
(db.CreateCommand(getArticleQuery)); } + + public async Task GetItemIdByArticle(GetItemIdByArticleQuery request) + { + const string getArticleQuery = $@"SELECT item_id FROM {SqlConstants.Articles} + WHERE id = @ArticleId"; + await using var db = _connectionFactory.CreateDatabase(); + return db.Connection.QueryFirstOrDefault(db.CreateCommand(getArticleQuery, new + { + request.ArticleId + })); + } + + public async Task> GetArticlesByOrderId(GetArticlesByOrderIdQuery request) + { + const string getArticleQuery = $@"SELECT article_id FROM {SqlConstants.ArticlesInOrder} + WHERE order_id = @OrderId"; + await using var db = _connectionFactory.CreateDatabase(); + var articles = await db.Connection.QueryAsync(db.CreateCommand(getArticleQuery, new + { + request.OrderId + })); + return articles; + } + + public async Task> GetArticlesByItemId(CreateArticleByItemIdQuery request) + { + const string getArticleQuery = $@"SELECT id, item_id FROM {SqlConstants.Articles} + WHERE item_id = @ItemId + LIMIT @Count"; + await using var db = _connectionFactory.CreateDatabase(); + var articles = await db.Connection.QueryAsync
(db.CreateCommand(getArticleQuery, new + { + request.Count, + request.ItemId + })); + return articles; + } public async Task CreateArticleByItemId(CreateArticleByItemIdQuery request, CancellationToken cancellationToken) { @@ -29,7 +66,7 @@ public async Task CreateArticleByItemId(CreateArticleByItemIdQuery request, Canc await db.Connection.OpenAsync(cancellationToken); var transaction = await db.Connection.BeginTransactionAsync(cancellationToken); - for(var i = 0; i < request.Count; i++) + for (var i = 0; i < request.Count; i++) await db.Connection.ExecuteAsync(insertArticlesQuery, new { request.ItemId diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs index 2a32470..b4d254a 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/CreateArticleByItemIdQuery.cs @@ -4,4 +4,4 @@ public class CreateArticleByItemIdQuery { public int Count; public long ItemId; -} \ No newline at end of file +} diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticleByItemIdQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticleByItemIdQuery.cs new file mode 100644 index 0000000..c4715d0 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticleByItemIdQuery.cs @@ -0,0 +1,7 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; + +public class GetArticleByItemIdQuery +{ + public int Count; + public long ItemId; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticlesByOrderIdQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticlesByOrderIdQuery.cs new file mode 100644 index 0000000..1d5c73c --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetArticlesByOrderIdQuery.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; + +public class GetArticlesByOrderIdQuery +{ + public long OrderId { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetItemIdByArticleQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetItemIdByArticleQuery.cs new file mode 100644 index 0000000..4a7df0f --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Articles/Queries/GetItemIdByArticleQuery.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; + +public class GetItemIdByArticleQuery +{ + public long ArticleId { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs index c63ba24..1466d2e 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs @@ -1,7 +1,5 @@ using Dapper; using Dtos; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; @@ -18,14 +16,14 @@ public async Task> GetItemsByIds(long[] Ids) const string getItemsQuery = $@" SELECT it.id, seller_id SellerId, - item_name Name, + item_name ItemName, weight, height, length, width, it.creation_date CreationDate, changed_at ChangedAt, - (SELECT count(a.id) + (SELECT count(a.id) AvailableCount FROM public.articles a LEFT JOIN public.articles_in_order aio ON aio.article_id = a.id LEFT JOIN public.orders o ON aio.order_id = o.id @@ -36,6 +34,28 @@ FROM items it return await db.Connection.QueryAsync(db.CreateCommand(getItemsQuery, new {Ids})); } + public async Task> GetItems() + { + const string getItemsQuery = $@" SELECT + it.id, + seller_id SellerId, + item_name ItemName, + weight, + height, + length, + width, + it.creation_date CreationDate, + changed_at ChangedAt, + (SELECT count(a.id) AvailableCount + FROM public.articles a + LEFT JOIN public.articles_in_order aio ON aio.article_id = a.id + LEFT JOIN public.orders o ON aio.order_id = o.id + WHERE a.item_id = it.id AND o.id IS NULL OR o.state = 'Cancelled'::State) + FROM items it"; + await using var db = _connectionFactory.CreateDatabase(); + return await db.Connection.QueryAsync(db.CreateCommand(getItemsQuery)); + } + public async Task CreateItem(CreateItemQuery request, CancellationToken cancellationToken) { var insertItemQuery = $@"INSERT INTO {SqlConstants.Items} @@ -61,13 +81,34 @@ public async Task CreateItem(CreateItemQuery request, CancellationToken ca return id; } + public async Task> GetItemsByOrderId(long orderId, CancellationToken cancellationToken) + { + const string query = @"select i.id item_id from articles a + inner join articles_in_order aio on aio.article_id = a.id + inner join orders o on aio.order_id = o.id + inner join items i on a.item_id = i.id + where o.id = @OrderId"; + + await using var db = _connectionFactory.CreateDatabase(cancellationToken); + + var result = (await db.Connection.QueryAsync(query, new + { + OrderId = orderId + })).ToArray(); + + var intersected = result.Distinct(); + + return intersected + .Select(item => new ItemInOrder {ItemId = item, Count = result.Count(x => x == item)}).ToList(); + } + public async Task DeleteItemById(long itemId, CancellationToken cancellationToken) { - const string DeleteItemQuery = $@"DELETE FROM {SqlConstants.Items} WHERE id = @Id "; + const string deleteItemQuery = $@"DELETE FROM {SqlConstants.Items} WHERE id = @Id "; await using var db = _connectionFactory.CreateDatabase(cancellationToken); - await db.Connection.ExecuteAsync(DeleteItemQuery, new + await db.Connection.ExecuteAsync(deleteItemQuery, new { Id = itemId }); @@ -81,7 +122,8 @@ public async Task ChangeItem(ChangeItemQuery command, CancellationToken cancella weight = @Weight, height = @Height, length = @Length, - width = @Width + width = @Width, + changed_at = @ChangedAt WHERE id = @Id "; await using var db = _connectionFactory.CreateDatabase(cancellationToken); @@ -93,7 +135,8 @@ public async Task ChangeItem(ChangeItemQuery command, CancellationToken cancella command.Weight, command.Height, command.Length, - command.Width + command.Width, + ChangedAt = DateTime.Now }); } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs new file mode 100644 index 0000000..aa2b28b --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs @@ -0,0 +1,127 @@ +using Dapper; +using Dtos; +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeOrderById.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; + +public class OrdersRepository + +{ + private readonly IDbConnectionFactory _connectionFactory; + + public OrdersRepository(IDbConnectionFactory connectionFactory) => _connectionFactory = connectionFactory; + + public async Task> GetOrders() + { + const string getOrdersQuery = $@"SELECT id AS Id, + creation_date AS CreationDate, + ""from"", + ""to"", + ""state"" AS Status, + buyer_id AS BuyerId + FROM {SqlConstants.Orders}"; + await using var db = _connectionFactory.CreateDatabase(); + return await db.Connection.QueryAsync(db.CreateCommand(getOrdersQuery)); + } + + public async Task> GetOrdersByBuyerId(GetOrdersByBuyerIdQuery request) + { + const string getOrdersQuery = $@"SELECT id AS Id, + creation_date AS CreationDate, + ""from"", + ""to"", + ""state"" AS Status, + buyer_id AS BuyerId + FROM {SqlConstants.Orders} + WHERE buyer_id = @BuyerId"; + await using var db = _connectionFactory.CreateDatabase(); + var orders = await db.Connection.QueryAsync(db.CreateCommand(getOrdersQuery, new + { + request.BuyerId + })); + return orders; + } + + public async Task GetOrderById(long OrderId) + { + const string getOrderByIdQuery = $@"SELECT id, name, price, weight FROM {SqlConstants.Orders} WHERE id = @Id"; + await using var db = _connectionFactory.CreateDatabase(); + OrderDto requestOrder = await db.Connection.QueryFirstOrDefaultAsync(db.CreateCommand(getOrderByIdQuery, new + { + Id = OrderId + })); + return requestOrder; + } + + public async Task CreateOrder(CreateOrderQuery request, CancellationToken cancellationToken) + { + // Создание заказа + + const string insertOrderQuery = + $@"INSERT INTO {SqlConstants.Orders} + (creation_date, ""from"", ""to"", state, buyer_id) + VALUES (@CreationDate, @From, @To, @Status::State, @BuyerId) returning id"; + + await using var db = _connectionFactory.CreateDatabase(cancellationToken); + + var orderId = await db.Connection.QueryFirstOrDefaultAsync(insertOrderQuery, new + { + request.CreationDate, + request.From, + request.To, + Status = OrderStatus.Created.ToString(), + request.BuyerId + }); + + // Привязка артиклов к заказу + + const string insertItemsInOrderQuery = + $@"INSERT INTO {SqlConstants.ArticlesInOrder} + (article_id, order_id) + VALUES (@ArticleId, @OrderId) returning id"; + + foreach (var article in request.Articles) + { + await db.Connection.ExecuteAsync(insertItemsInOrderQuery, new + { + ArticleId = article, + OrderId = orderId + }); + } + + return orderId; + } + + public async Task SetOrderStatus(SetOrderStatusQuery request) + { + const string moveOrderStatusQuery = $@"UPDATE {SqlConstants.Orders} + SET state = @Status::state + WHERE id = @OrderId "; + await using var db = _connectionFactory.CreateDatabase(); + await db.Connection.ExecuteAsync(moveOrderStatusQuery, new + { + request.OrderId, + Status = request.Status.ToString() + }); + } + + public async Task ChangeOrder(ChangeOrderRequest request, CancellationToken cancellationToken) + { + const string ChangeOrderQuery = $@"UPDATE {SqlConstants.Orders} + SET name = @Name, price = @Price, weight = @Weight WHERE id = @Id "; + + await using var db = _connectionFactory.CreateDatabase(cancellationToken); + + await db.Connection.ExecuteAsync(ChangeOrderQuery, new + { + request.Id, + request.Name, + request.Price, + request.Weight + }); + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/CreateOrderQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/CreateOrderQuery.cs new file mode 100644 index 0000000..9543eaf --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/CreateOrderQuery.cs @@ -0,0 +1,10 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; + +public class CreateOrderQuery +{ + public DateTime CreationDate { get; set; } + public long From { get; set; } + public long To { get; set; } + public long[] Articles { get; set; } = null!; + public string BuyerId { get; set; } = null!; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrdersByBuyerIdQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrdersByBuyerIdQuery.cs new file mode 100644 index 0000000..eeed8d0 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrdersByBuyerIdQuery.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; + +public class GetOrdersByBuyerIdQuery +{ + public string BuyerId { get; set; } = null!; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/SetOrderStatusQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/SetOrderStatusQuery.cs new file mode 100644 index 0000000..1d4b941 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/SetOrderStatusQuery.cs @@ -0,0 +1,9 @@ +using ToxiCode.BuyIt.Logistics.Api.Grpc; + +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; + +public class SetOrderStatusQuery +{ + public long OrderId { get; set; } + public OrderStatus Status { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/OrdersRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/OrdersRepository.cs deleted file mode 100644 index ccd50ac..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/OrdersRepository.cs +++ /dev/null @@ -1,93 +0,0 @@ -using Dapper; -using Dtos; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeOrderById.Contracts; -using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; - -namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; - -public class OrdersRepository - -{ - private readonly IDbConnectionFactory _connectionFactory; - - public OrdersRepository(IDbConnectionFactory connectionFactory) => _connectionFactory = connectionFactory; - - public async Task> GetOrders() - { - const string getOrdersQuery = $@"SELECT id, name, price, weight FROM {SqlConstants.Orders}"; - await using var db = _connectionFactory.CreateDatabase(); - return await db.Connection.QueryAsync(db.CreateCommand(getOrdersQuery)); - } - - public async Task GetOrderById(long OrderId) - { - const string getOrderByIdQuery = $@"SELECT id, name, price, weight FROM {SqlConstants.Orders} WHERE id = @Id"; - await using var db = _connectionFactory.CreateDatabase(); - Order requestOrder = await db.Connection.QueryFirstOrDefaultAsync(db.CreateCommand(getOrderByIdQuery, new - { - Id = OrderId - })); - return requestOrder ; - } - - public async Task CreateOrder(CreateOrderRequest request, CancellationToken cancellationToken) - { - // Создание заказа - - const string insertOrderQuery = - $@"INSERT INTO {SqlConstants.Orders} - (date_time, from, to) - VALUES (@DateTime, @From, @To) returning id"; - - await using var db = _connectionFactory.CreateDatabase(cancellationToken); - - var orderId = await db.Connection.QueryFirstOrDefaultAsync(insertOrderQuery, new - { - request.From, - request.To, - }); - - // Привязка артиклов к заказу - - const string insertItemsInOrderQuery = - $@"INSERT INTO {SqlConstants.ArticlesInOrder} - (article_id, item_id) - VALUES (@ArticleId, @ItemId) returning id"; - - await db.Connection.ExecuteAsync(insertItemsInOrderQuery, request.Articles.Select(x => new - { - - })); - - return orderId; - } - - public async Task DeleteOrderById(long OrderId, CancellationToken cancellationToken) - { - const string DeleteOrderQuery = $@"DELETE FROM {SqlConstants.Orders} WHERE id = @Id "; - - await using var db = _connectionFactory.CreateDatabase(cancellationToken); - - await db.Connection.ExecuteAsync(DeleteOrderQuery, new - { - Id = OrderId - }); - } - - public async Task ChangeOrder(ChangeOrderRequest request, CancellationToken cancellationToken) - { - const string ChangeOrderQuery = $@"UPDATE {SqlConstants.Orders} - SET name = @Name, price = @Price, weight = @Weight WHERE id = @Id "; - - await using var db = _connectionFactory.CreateDatabase(cancellationToken); - - await db.Connection.ExecuteAsync(ChangeOrderQuery, new - { - request.Id, - request.Name, - request.Price, - request.Weight - }); - } -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs index a6317cb..1e7cc8e 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/ItemsGrpcController.cs @@ -61,7 +61,7 @@ public ItemsGrpcController(IMediator mediator) { Items = { - response.Items.Select(x => + response.Items!.Select(x => new GRPC.Item { ItemId = x.Id, diff --git a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs index 9f65176..4480452 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/GrpcControllers/OrdersGrpcController.cs @@ -1,10 +1,103 @@ +using Google.Protobuf.WellKnownTypes; using Grpc.Core; +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateOrder.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.SetOrderStatus.Contracts; using ToxiCode.BuyIt.Logistics.Api.Grpc; +using GetOrdersByBuyerIdResponse = ToxiCode.BuyIt.Logistics.Api.Grpc.GetOrdersByBuyerIdResponse; namespace ToxiCode.BuyIt.Logistics.Api.GrpcControllers; public class OrdersGrpcController : OrdersService.OrdersServiceBase { - public override Task AddOrder(AddOrderRequest request, ServerCallContext context) => base.AddOrder(request, context); - public override Task GetOrders(GetOrdersRequest request, ServerCallContext context) => base.GetOrders(request, context); + private readonly IMediator _mediator; + + public OrdersGrpcController(IMediator mediator) + { + _mediator = mediator; + } + + public override async Task AddOrder(AddOrderRequest request, ServerCallContext context) + { + var command = new CreateOrderCommand + { + From = request.FromAddressId, + To = request.ToAddressId, + UserId = request.UserId, + Items = request.Items.Select(x => new ItemPair + { + Count = x.Count, + ItemId = x.ItemId + }) + }; + var response = await _mediator.Send(command); + return new AddOrderResponse + { + OrderId = response.OrderId, + ResultMessage = "Success" + }; + } + + public override async Task OrderPaid(OrderPaidRequest request, ServerCallContext context) + { + var command = new SetOrderStatusCommand + { + Status = OrderStatus.Processing, + OrderId = request.OrderId + }; + await _mediator.Send(command); + return new OrderPaidResponse + { + ResultMessage = "Success" + }; + } + + public override async Task CancelOrder(CancelOrderRequest request, ServerCallContext context) + { + var command = new SetOrderStatusCommand + { + Status = OrderStatus.Cancelled, + OrderId = request.OrderId + }; + await _mediator.Send(command); + return new CancelOrderResponse + { + ResultMessage = "Success" + }; + } + + public override async Task GetOrdersByBuyerId(GetOrdersByBuyerIdRequest request, ServerCallContext context) + { + var command = new GetOrdersByBuyerIdCommand + { + BuyerId = request.BuyerId + }; + var orders = await _mediator.Send(command); + if (orders.Orders != null) + return new GetOrdersByBuyerIdResponse + { + Orders = + { + orders.Orders.Select(x => new Order + { + OrderId = x.Id, + CreatedDate = DateTime.SpecifyKind(x.CreationDate, DateTimeKind.Utc).ToTimestamp(), + OrderStatus = x.Status, + FromAddressId = x.From, + ToAddressId = x.To, + Items = + { + x.Items.Select(y => new ItemAmountPair + { + ItemId = y.ItemId, + Count = y.Count, + }) + }, + BuyerId = x.BuyerId + }) + } + }; + return new GetOrdersByBuyerIdResponse(); + } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs index 839d224..c4a2411 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs @@ -1,8 +1,8 @@ -using MediatR; +using Dtos; +using MediatR; using Microsoft.AspNetCore.Mvc; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeItemById.Contracnts; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateItem.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; namespace ToxiCode.BuyIt.Logistics.Api.HttpControllers; @@ -18,12 +18,36 @@ public ItemController(HttpCancellationTokenAccessor cancellationToken, IMediator _mediator = mediator; } + [HttpPost("api/itemsByIds/")] + public async Task> GetItemByIds(long[] itemsIds) + { + var command = new GetItemsByIdsCommand + { + ItemIds = itemsIds + }; + var result = await _mediator.Send(command); + return Ok(result.Items); + } + [HttpGet("api/item/{itemId:long}")] - public async Task GetItemById(long itemId) + public async Task> GetItemById(long itemId) { - return Ok(await _mediator.Send(itemId)); + var command = new GetItemsByIdsCommand() + { + ItemIds = new[] {itemId} + }; + var result = await _mediator.Send(command); + return Ok(result.Items!.FirstOrDefault()); } - + + [HttpGet("api/items")] + public async Task>> GetItems() + { + var command = new GetItemsCommand(); + var result = await _mediator.Send(command); + return Ok(result.Items); + } + [HttpDelete("api/item/{itemId:long}")] public async Task DeleteItem(long itemId) { diff --git a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs index 1511ca7..0e0807d 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs @@ -1,28 +1,41 @@ -using Microsoft.AspNetCore.Mvc; +using Dtos; +using JetBrains.Annotations; +using MediatR; +using Microsoft.AspNetCore.Mvc; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeOrderById.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateOrder.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; namespace ToxiCode.BuyIt.Logistics.Api.HttpControllers; [ApiController] +[Route("api")] public class OrderController : ControllerBase { private readonly HttpCancellationTokenAccessor _cancellationToken; + private readonly IMediator _mediator; - public OrderController(HttpCancellationTokenAccessor cancellationToken) + public OrderController(HttpCancellationTokenAccessor cancellationToken, IMediator mediator) { _cancellationToken = cancellationToken; + _mediator = mediator; + } + + [HttpGet("Orders")] + public async Task>> GetOrders() + { + var request = new GetOrdersCommand(); + var result = await _mediator.Send(request, _cancellationToken.Token); + return Ok(result); } - // [HttpGet("api/Order/all")] - // public async Task GetOrders() => Ok(await _resolver.GetOrders()); - // // [HttpGet("api/Order/{orderId:long}")] - // public async Task GetOrderById(long orderId) => Ok(await _resolver.GetOrder(orderId)); - // - // [HttpPost("api/Order")] - // public async Task> CreateOrder([FromBody] CreateOrderRequest request) - // => Ok(await _resolver.CreateOrder(request, _cancellationToken.Token)); + // public async Task GetOrderByBuyerId(long orderId) => Ok(await _resolver.GetOrder(orderId)); + + [HttpPost("Order/Create")] + public async Task> CreateOrder([FromBody] CreateOrderCommand request) + => Ok(await _mediator.Send(request, _cancellationToken.Token)); // // [HttpDelete("api/Order/{orderId:long}")] // public async Task DeleteOrder(long orderId) diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs b/src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs index 8173cdc..d70fb8a 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/Infrustructure/Extensions/KafkaExtensions.cs @@ -1,3 +1,4 @@ +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Services; using ToxiCode.BuyIt.Logistics.Api.Kafka; namespace ToxiCode.BuyIt.Logistics.Api.Infrustructure.Extensions; @@ -13,7 +14,8 @@ public static IServiceCollection AddKafka(this IServiceCollection services, .ValidateDataAnnotations(); return services - .AddSingleton(); + .AddSingleton(). + AddSingleton(); } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs index 5578e3d..23abefd 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/Program.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/Program.cs @@ -12,13 +12,12 @@ var builder = WebApplication.CreateBuilder(args); - builder.WebHost.ConfigureKestrel( options => { Listen(options, 5000, HttpProtocols.Http1); Listen(options, 5002, HttpProtocols.Http2); - }); + }); static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpProtocols protocols) { @@ -27,18 +26,16 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro var address = IPAddress.Loopback; - - + kestrelServerOptions.Listen(address, port.Value, listenOptions => { listenOptions.Protocols = protocols; }); } - - var services = builder.Services; -services.AddControllers(); services.AddEndpointsApiExplorer(); services.AddDatabaseInfrastructure(builder.Configuration); +services.AddControllers(); +services.AddAuthorization(); services.AddSwaggerGen(); services.AddGrpcSwagger(); services.AddMediatR(typeof(Program)); @@ -49,8 +46,6 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro .AddSingleton() .AddKafka(builder.Configuration); -// services.AddSingleton(); - #endregion #region App @@ -61,6 +56,10 @@ static void Listen(KestrelServerOptions kestrelServerOptions, int? port, HttpPro app.UseSwaggerUI(); app.UseAuthorization(); app.MapControllers(); +app.UseCors(x => x + .AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader()); app.MapGrpcService(); app.MapGrpcService(); app.Migrate(); diff --git a/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj b/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj index 984649c..ab1f6b7 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj +++ b/src/ToxiCode.BuyIt.Logistics.Api/ToxiCode.BuyIt.Logistics.Api.csproj @@ -18,6 +18,7 @@ + @@ -43,7 +44,6 @@ - From 54273c43f0cdeb577a425b0a39c12244b16187bd Mon Sep 17 00:00:00 2001 From: daniilkuznetsov Date: Fri, 27 May 2022 10:44:17 +0300 Subject: [PATCH 07/11] [TXC-5] just trying my best --- .../OrderDto.cs | 1 + .../protos/OrdersService.proto | 1 - .../Commands/GetItems/GetItemsByIdsHandler.cs | 11 +++- .../Contracts/GetOrderByIdResponse.cs | 8 +++ .../GetOrders/Contracts/GetOrdersResponse.cs | 2 +- .../Commands/GetOrders/GetOrderByIdHandler.cs | 51 +++++++++++++++++++ .../GetOrders/GetOrdersByBuyerIdHandler.cs | 6 +-- .../Commands/GetOrders/GetOrdersHandler.cs | 24 +++------ .../Repository/Items/ItemsRepository.cs | 32 ++++++++---- .../Repository/Orders/OrdersRepository.cs | 14 +++-- .../Orders/Queries/GetOrderByIdQuery.cs | 6 +++ .../HttpControllers/ItemController.cs | 11 ++-- .../HttpControllers/OrderController.cs | 32 +++++++++--- 13 files changed, 148 insertions(+), 51 deletions(-) create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdResponse.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrderByIdQuery.cs diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs index efe70a1..e652e94 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs @@ -15,6 +15,7 @@ public class OrderDto public class ItemInOrder { + public string ItemName { get; set; } = null!; public long ItemId { get; set; } public int Count { get; set; } } diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto index ba2720c..ab1ab9b 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto +++ b/src/ToxiCode.BuyIt.Logistics.Api.Grpc/protos/OrdersService.proto @@ -69,7 +69,6 @@ message Order{ string BuyerId = 7; } - enum OrderStatus{ Default = 0; Created = 1; diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs index ba1c1ab..ac9acd3 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetItems/GetItemsByIdsHandler.cs @@ -2,6 +2,7 @@ using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems; @@ -13,11 +14,17 @@ public GetItemsByIdsHandler(ItemsRepository itemsRepository) { _itemsRepository = itemsRepository; } + public async Task Handle(GetItemsByIdsCommand request, CancellationToken cancellationToken) { - return new GetItemsResponse + var response = new GetItemsResponse() { - Items = await _itemsRepository.GetItemsByIds(request.ItemIds.ToArray()) + Items = await _itemsRepository.GetItemsByIds(new GetItemsByIdsQuery + { + Ids = request.ItemIds.ToArray() + }) }; + return response; } + } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdResponse.cs new file mode 100644 index 0000000..0eff02d --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdResponse.cs @@ -0,0 +1,8 @@ +using Dtos; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; + +public class GetOrderByIdResponse +{ + public OrderDto Orders { get; set; } = null!; +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs index 276b0aa..fe7bf08 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrdersResponse.cs @@ -4,5 +4,5 @@ namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contract public class GetOrdersResponse { - public IEnumerable? Orders { get; set; } + public OrderDto[] Orders { get; set; } = null!; } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs new file mode 100644 index 0000000..a250d4a --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs @@ -0,0 +1,51 @@ +using Dtos; +using MediatR; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetItems.Contracts; +using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders; + +public class GetOrderByIdHandler : IRequestHandler +{ + private readonly OrdersRepository _ordersRepository; + private readonly ItemsRepository _itemsRepository; + + public GetOrderByIdHandler(OrdersRepository ordersRepository, ItemsRepository itemsRepository) + { + _ordersRepository = ordersRepository; + _itemsRepository = itemsRepository; + } + + public async Task Handle(GetOrderByIdCommand request, CancellationToken cancellationToken) + { + var query = new GetOrderByIdQuery + { + OrderId = request.OrderId + }; + var order = await _ordersRepository.GetOrderById(query); + + if (order == null) + return new GetOrderByIdResponse(); + + order.Items = await _itemsRepository.GetItemsByOrderId(order.Id); + + + return new GetOrderByIdResponse + { + Orders = new OrderDto + { + From = order!.From, + To = order.To, + Items = order.Items, + Id = order.Id, + Status = order.Status, + BuyerId = order.BuyerId, + CreationDate = order.CreationDate, + } + }; + } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs index 2e47cd3..cd97311 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersByBuyerIdHandler.cs @@ -35,11 +35,7 @@ public async Task Handle(GetOrdersByBuyerIdCommand r var orders = await _ordersRepository.GetOrdersByBuyerId(query); foreach (var order in orders) { - var articlesQuery = new GetArticlesByOrderIdQuery - { - OrderId = order.Id - }; - order.Items = await _itemsRepository.GetItemsByOrderId(order.Id, cancellationToken); + // order.Items = await _itemsRepository.GetItemsByOrderId(order.Id); } return new GetOrdersByBuyerIdResponse diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs index 4d31e87..fcbae79 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrdersHandler.cs @@ -3,6 +3,7 @@ using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Articles.Queries; +using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders; namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders; @@ -10,12 +11,12 @@ namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders; public class GetOrdersHandler : IRequestHandler { private readonly OrdersRepository _ordersRepository; - private ArticlesRepository _articlesRepository; + private ItemsRepository _itemsRepository; - public GetOrdersHandler(OrdersRepository ordersRepository, ArticlesRepository articlesRepository) + public GetOrdersHandler(OrdersRepository ordersRepository, ArticlesRepository articlesRepository, ItemsRepository itemsRepository) { _ordersRepository = ordersRepository; - _articlesRepository = articlesRepository; + _itemsRepository = itemsRepository; } public async Task Handle(GetOrdersCommand request, CancellationToken cancellationToken) @@ -23,24 +24,11 @@ public async Task Handle(GetOrdersCommand request, Cancellati var orders = await _ordersRepository.GetOrders(); foreach (var order in orders) { - var articlesQuery = new GetArticlesByOrderIdQuery - { - OrderId = order.Id - }; - IEnumerable articlesInOrder = await _articlesRepository.GetArticlesByOrderId(articlesQuery); - foreach (var article in articlesInOrder) - { - var articleQuery = new GetItemIdByArticleQuery - { - ArticleId = article - }; - var itemId = await _articlesRepository.GetItemIdByArticle(articleQuery); - } + order.Items = await _itemsRepository.GetItemsByOrderId(order.Id); } - return new GetOrdersResponse { - Orders = orders + Orders = orders.ToArray() }; } } \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs index 1466d2e..a8e3e65 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/ItemsRepository.cs @@ -9,9 +9,12 @@ public class ItemsRepository { private readonly IDbConnectionFactory _connectionFactory; - public ItemsRepository(IDbConnectionFactory connectionFactory) => _connectionFactory = connectionFactory; + public ItemsRepository(IDbConnectionFactory connectionFactory) + { + _connectionFactory = connectionFactory; + } - public async Task> GetItemsByIds(long[] Ids) + public async Task> GetItemsByIds(GetItemsByIdsQuery ids) { const string getItemsQuery = $@" SELECT it.id, @@ -31,7 +34,10 @@ FROM public.articles a FROM items it WHERE it.id = any(@Ids)"; await using var db = _connectionFactory.CreateDatabase(); - return await db.Connection.QueryAsync(db.CreateCommand(getItemsQuery, new {Ids})); + return await db.Connection.QueryAsync(db.CreateCommand(getItemsQuery, new + { + Ids = ids + })); } public async Task> GetItems() @@ -81,25 +87,33 @@ public async Task CreateItem(CreateItemQuery request, CancellationToken ca return id; } - public async Task> GetItemsByOrderId(long orderId, CancellationToken cancellationToken) + public async Task> GetItemsByOrderId(long orderId) { - const string query = @"select i.id item_id from articles a + const string query = @"select i.id item_id, i.item_name ItemName from articles a inner join articles_in_order aio on aio.article_id = a.id inner join orders o on aio.order_id = o.id inner join items i on a.item_id = i.id where o.id = @OrderId"; - await using var db = _connectionFactory.CreateDatabase(cancellationToken); + await using var db = _connectionFactory.CreateDatabase(); - var result = (await db.Connection.QueryAsync(query, new + var result = (await db.Connection.QueryAsync<(long, string)>(query, new { OrderId = orderId })).ToArray(); var intersected = result.Distinct(); - return intersected - .Select(item => new ItemInOrder {ItemId = item, Count = result.Count(x => x == item)}).ToList(); + var items = intersected + .Select(item => + new ItemInOrder + { + ItemId = item.Item1, + ItemName = item.Item2, + Count = result.Count(x => x == item) + }).ToList(); + + return items; } public async Task DeleteItemById(long itemId, CancellationToken cancellationToken) diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs index aa2b28b..f08c348 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/OrdersRepository.cs @@ -1,6 +1,5 @@ using Dapper; using Dtos; -using MediatR; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeOrderById.Contracts; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; using ToxiCode.BuyIt.Logistics.Api.DataLayer.Utils; @@ -46,13 +45,20 @@ buyer_id AS BuyerId return orders; } - public async Task GetOrderById(long OrderId) + public async Task GetOrderById(GetOrderByIdQuery request) { - const string getOrderByIdQuery = $@"SELECT id, name, price, weight FROM {SqlConstants.Orders} WHERE id = @Id"; + const string getOrderByIdQuery = $@"SELECT id AS Id, + creation_date AS CreationDate, + ""from"", + ""to"", + ""state"" AS Status, + buyer_id AS BuyerId + FROM {SqlConstants.Orders} + WHERE id = @OrderId"; await using var db = _connectionFactory.CreateDatabase(); OrderDto requestOrder = await db.Connection.QueryFirstOrDefaultAsync(db.CreateCommand(getOrderByIdQuery, new { - Id = OrderId + request.OrderId })); return requestOrder; } diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrderByIdQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrderByIdQuery.cs new file mode 100644 index 0000000..dca3966 --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Orders/Queries/GetOrderByIdQuery.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Orders.Queries; + +public class GetOrderByIdQuery +{ + public long OrderId { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs index c4a2411..c752838 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/ItemController.cs @@ -7,6 +7,7 @@ namespace ToxiCode.BuyIt.Logistics.Api.HttpControllers; [ApiController] +[Route("api")] public class ItemController : ControllerBase { private readonly HttpCancellationTokenAccessor _cancellationToken; @@ -18,7 +19,7 @@ public ItemController(HttpCancellationTokenAccessor cancellationToken, IMediator _mediator = mediator; } - [HttpPost("api/itemsByIds/")] + [HttpPost("itemsByIds/")] public async Task> GetItemByIds(long[] itemsIds) { var command = new GetItemsByIdsCommand @@ -29,7 +30,7 @@ public ItemController(HttpCancellationTokenAccessor cancellationToken, IMediator return Ok(result.Items); } - [HttpGet("api/item/{itemId:long}")] + [HttpGet("item/{itemId:long}")] public async Task> GetItemById(long itemId) { var command = new GetItemsByIdsCommand() @@ -40,7 +41,7 @@ public ItemController(HttpCancellationTokenAccessor cancellationToken, IMediator return Ok(result.Items!.FirstOrDefault()); } - [HttpGet("api/items")] + [HttpGet("items")] public async Task>> GetItems() { var command = new GetItemsCommand(); @@ -48,14 +49,14 @@ public ItemController(HttpCancellationTokenAccessor cancellationToken, IMediator return Ok(result.Items); } - [HttpDelete("api/item/{itemId:long}")] + [HttpDelete("item/{itemId:long}")] public async Task DeleteItem(long itemId) { await _mediator.Send(itemId, _cancellationToken.Token); return Ok(); } - [HttpPut("api/item/")] + [HttpPut("item/")] public async Task ChangeItem([FromBody] ChangeItemCommand command) { await _mediator.Send(command, _cancellationToken.Token); diff --git a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs index 0e0807d..cbf1461 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs @@ -22,18 +22,38 @@ public OrderController(HttpCancellationTokenAccessor cancellationToken, IMediato _mediator = mediator; } - [HttpGet("Orders")] + [HttpGet("orders")] public async Task>> GetOrders() { var request = new GetOrdersCommand(); - var result = await _mediator.Send(request, _cancellationToken.Token); - return Ok(result); + var result = await _mediator.Send(request); + return Ok(result.Orders); + } + + [HttpGet("orderById/{orderId:long}")] + public async Task> GetOrderById(long orderId) + { + var command = new GetOrderByIdCommand + { + OrderId = orderId + }; + var result = await _mediator.Send(command); + return Ok(result.Orders); } - // [HttpGet("api/Order/{orderId:long}")] - // public async Task GetOrderByBuyerId(long orderId) => Ok(await _resolver.GetOrder(orderId)); + [HttpGet("order/{buyerId}")] + public async Task>> GetOrderByBuyerId(string buyerId) + { + var command = new GetOrdersByBuyerIdCommand + { + BuyerId = buyerId, + }; + + var response = await _mediator.Send(command); + return Ok(response.Orders); + } - [HttpPost("Order/Create")] + [HttpPost("order/create")] public async Task> CreateOrder([FromBody] CreateOrderCommand request) => Ok(await _mediator.Send(request, _cancellationToken.Token)); // From d5f23278d86ec7d4df499c34b43984b97d1f7781 Mon Sep 17 00:00:00 2001 From: daniilkuznetsov Date: Fri, 27 May 2022 10:44:54 +0300 Subject: [PATCH 08/11] [TXC-5] fix --- .../Commands/GetOrders/Contracts/GetOrderByIdCommand.cs | 8 ++++++++ .../Repository/Items/Queries/GetItemsByIdsQuery.cs | 6 ++++++ 2 files changed, 14 insertions(+) create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdCommand.cs create mode 100644 src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/GetItemsByIdsQuery.cs diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdCommand.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdCommand.cs new file mode 100644 index 0000000..6ad9d2f --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/Contracts/GetOrderByIdCommand.cs @@ -0,0 +1,8 @@ +using MediatR; + +namespace ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; + +public class GetOrderByIdCommand : IRequest +{ + public long OrderId { get; set; } +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/GetItemsByIdsQuery.cs b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/GetItemsByIdsQuery.cs new file mode 100644 index 0000000..d903c8a --- /dev/null +++ b/src/ToxiCode.BuyIt.Logistics.Api/DataLayer/Repository/Items/Queries/GetItemsByIdsQuery.cs @@ -0,0 +1,6 @@ +namespace ToxiCode.BuyIt.Logistics.Api.DataLayer.Repository.Items.Queries; + +public class GetItemsByIdsQuery +{ + public IEnumerable Ids { get; set; } = null!; +} \ No newline at end of file From 4a96929f5cb97eb8c14c51c54d714ec195fbd5f7 Mon Sep 17 00:00:00 2001 From: daniilda Date: Fri, 27 May 2022 10:53:00 +0300 Subject: [PATCH 09/11] fix --- .../BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs index a250d4a..f184589 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/GetOrders/GetOrderByIdHandler.cs @@ -26,12 +26,12 @@ public async Task Handle(GetOrderByIdCommand request, Canc { OrderId = request.OrderId }; - var order = await _ordersRepository.GetOrderById(query); + var order = await _ordersRepository.GetOrderById(query.OrderId); if (order == null) return new GetOrderByIdResponse(); - order.Items = await _itemsRepository.GetItemsByOrderId(order.Id); + order.Items = await _itemsRepository.GetItemsByOrderId(order.Id, cancellationToken); return new GetOrderByIdResponse From 91b1c2d513beaa108c969ce42b9b839151b8935a Mon Sep 17 00:00:00 2001 From: "daniilkuznetsov@ozon.ru" Date: Wed, 1 Jun 2022 02:10:26 +0300 Subject: [PATCH 10/11] [TXC-5] hotfix --- src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs | 3 +-- src/ToxiCode.BuyIt.Logistics.Api.Dtos/Place.cs | 7 ------- .../HttpControllers/OrderController.cs | 3 --- 3 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 src/ToxiCode.BuyIt.Logistics.Api.Dtos/Place.cs diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs index efe70a1..b077eb1 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/OrderDto.cs @@ -17,5 +17,4 @@ public class ItemInOrder { public long ItemId { get; set; } public int Count { get; set; } -} - +} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Place.cs b/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Place.cs deleted file mode 100644 index aacb1b5..0000000 --- a/src/ToxiCode.BuyIt.Logistics.Api.Dtos/Place.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Dtos; - -public class Place -{ - public long Id { get; set; } - public string Address { get; set; } = null!; -} \ No newline at end of file diff --git a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs index 0e0807d..b99d42c 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/HttpControllers/OrderController.cs @@ -1,9 +1,6 @@ using Dtos; -using JetBrains.Annotations; using MediatR; using Microsoft.AspNetCore.Mvc; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands; -using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.ChangeOrderById.Contracts; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.CreateOrder.Contracts; using ToxiCode.BuyIt.Logistics.Api.BusinessLayer.Commands.GetOrders.Contracts; From 13aa788bfe8005c279e47484622e848b9030732b Mon Sep 17 00:00:00 2001 From: daniilkuznetsov Date: Wed, 15 Jun 2022 09:39:00 +0300 Subject: [PATCH 11/11] [TXC-6] Lets go --- .../BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs index 3779d9e..c0fda3a 100644 --- a/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs +++ b/src/ToxiCode.BuyIt.Logistics.Api/BusinessLayer/Commands/CreateOrder/CreateOrderHandler.cs @@ -50,7 +50,7 @@ public async Task Handle(CreateOrderCommand request, Cancel { OrderId = orderId }; - await _notificator.NotifyStatusChanged(orderId, OrderStatus.Created, cancellationToken); + // await _notificator.NotifyStatusChanged(orderId, OrderStatus.Created, cancellationToken); return result; } } \ No newline at end of file