Browse Source

Merge pull request #110 from abpframework/11426-Dashboard

#11426 dashboard
pull/111/head
Muhammed Altuğ 4 years ago
committed by GitHub
parent
commit
133350bc95
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      apps/angular/angular.json
  2. 6
      apps/angular/projects/catalog/src/pages/product/product.component.ts
  3. 4
      apps/angular/projects/ordering/config/src/enums/route-names.ts
  4. 14
      apps/angular/projects/ordering/config/src/providers/route.provider.ts
  5. 330
      apps/angular/projects/ordering/src/lib/proxy/generate-proxy.json
  6. 3
      apps/angular/projects/ordering/src/lib/proxy/index.ts
  7. 1
      apps/angular/projects/ordering/src/lib/proxy/order-items/index.ts
  8. 7
      apps/angular/projects/ordering/src/lib/proxy/order-items/models.ts
  9. 22
      apps/angular/projects/ordering/src/lib/proxy/orders/models.ts
  10. 20
      apps/angular/projects/ordering/src/lib/proxy/orders/order-status.enum.ts
  11. 10
      apps/angular/projects/ordering/src/lib/proxy/orders/order.service.ts
  12. 11
      apps/angular/projects/ordering/src/ordering-routing.module.ts
  13. 19
      apps/angular/projects/ordering/src/pages/dashboard/components/order-status-chart/order-status-chart.component.html
  14. 25
      apps/angular/projects/ordering/src/pages/dashboard/components/order-status-chart/order-status-chart.component.spec.ts
  15. 38
      apps/angular/projects/ordering/src/pages/dashboard/components/order-status-chart/order-status-chart.component.ts
  16. 19
      apps/angular/projects/ordering/src/pages/dashboard/components/payments-chart/payments-chart.component.html
  17. 25
      apps/angular/projects/ordering/src/pages/dashboard/components/payments-chart/payments-chart.component.spec.ts
  18. 35
      apps/angular/projects/ordering/src/pages/dashboard/components/payments-chart/payments-chart.component.ts
  19. 24
      apps/angular/projects/ordering/src/pages/dashboard/components/top-selling/top-selling.component.html
  20. 25
      apps/angular/projects/ordering/src/pages/dashboard/components/top-selling/top-selling.component.spec.ts
  21. 12
      apps/angular/projects/ordering/src/pages/dashboard/components/top-selling/top-selling.component.ts
  22. 20
      apps/angular/projects/ordering/src/pages/dashboard/dashboard-routing.module.ts
  23. 0
      apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.css
  24. 19
      apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.html
  25. 25
      apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.spec.ts
  26. 13
      apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.ts
  27. 25
      apps/angular/projects/ordering/src/pages/dashboard/dashboard.module.ts
  28. 2
      apps/angular/projects/ordering/src/pages/orders/order-detail/order-detail-item/order-detail-item.component.ts
  29. 28
      apps/angular/projects/ordering/src/pages/orders/order-detail/order-detail.component.html
  30. 2
      apps/angular/projects/ordering/src/pages/orders/order-detail/order-detail.component.ts
  31. 4
      apps/angular/projects/ordering/src/pages/orders/orders.component.html
  32. 2
      apps/angular/projects/ordering/src/pages/orders/orders.component.ts
  33. 2
      gateways/web-public/src/EShopOnAbp.WebPublicGateway/yarp.json
  34. 11
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/OrderItems/TopSellingDto.cs
  35. 2
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/OrderingServiceRemoteServiceConsts.cs
  36. 13
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/DashboardDto.cs
  37. 7
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/DashboardInput.cs
  38. 1
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/IOrderAppService.cs
  39. 10
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/OrderStatusDto.cs
  40. 9
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/PaymentDto.cs
  41. 2
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Permissions/OrderingServicePermissionDefinitionProvider.cs
  42. 1
      services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Permissions/OrderingServicePermissions.cs
  43. 6
      services/ordering/src/EShopOnAbp.OrderingService.Application/OrderingServiceApplicationAutoMapperProfile.cs
  44. 66
      services/ordering/src/EShopOnAbp.OrderingService.Application/Orders/OrderAppService.cs
  45. 14
      services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Localization/OrderingService/en.json
  46. 4
      services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Localization/OrderingService/tr.json
  47. 3
      services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Localization/OrderingService/zh-Hans.json
  48. 2
      services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Orders/OrderConstants.cs
  49. 14
      services/ordering/src/EShopOnAbp.OrderingService.Domain/Orders/IOrderRepository.cs
  50. 38
      services/ordering/src/EShopOnAbp.OrderingService.EntityFrameworkCore/Orders/EfCoreOrderRepository.cs
  51. 8
      services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Client/ClientProxies/OrderClientProxy.Generated.cs
  52. 37
      services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Client/ClientProxies/ordering-generate-proxy.json
  53. 2
      services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/appsettings.json

4
apps/angular/angular.json

@ -161,7 +161,7 @@
"projectType": "library",
"root": "projects/catalog",
"sourceRoot": "projects/catalog/src",
"prefix": "lib",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
@ -192,7 +192,7 @@
"projectType": "library",
"root": "projects/ordering",
"sourceRoot": "projects/ordering/src",
"prefix": "lib",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",

6
apps/angular/projects/catalog/src/pages/product/product.component.ts

@ -8,7 +8,7 @@ import { ProductDto } from '../../lib/proxy/products/models';
import { ProductService } from '../../lib/proxy/products/product.service';
@Component({
selector: 'lib-product',
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css'],
providers: [ListService],
@ -86,7 +86,9 @@ export class ProductComponent implements OnInit {
}
save() {
if (!this.form.valid || this.modalBusy) return;
if (!this.form.valid || this.modalBusy) {
return;
}
this.modalBusy = true;
const { id } = this.selected;

4
apps/angular/projects/ordering/config/src/enums/route-names.ts

@ -1,3 +1,5 @@
export const enum eOrderingRouteNames {
ordering = 'OrderingService::Menu:OrderManagement'
ordering = 'OrderingService::Menu:OrderManagement',
dashboard = 'OrderingService::Menu:Dashboard',
orders = 'OrderingService::Menu:Orders',
}

14
apps/angular/projects/ordering/config/src/providers/route.provider.ts

@ -18,6 +18,20 @@ export function configureRoutes(routesService: RoutesService) {
parentName: null,
iconClass: 'bi bi-collection-fill',
},
{
path: '/ordering',
name: eOrderingRouteNames.dashboard,
parentName: eOrderingRouteNames.ordering,
order: 1,
requiredPolicy: eOrderingPolicyNames.ordering,
},
{
path: '/ordering/orders',
name: eOrderingRouteNames.orders,
parentName: eOrderingRouteNames.ordering,
order: 2,
requiredPolicy: eOrderingPolicyNames.ordering,
},
]);
};
}

330
apps/angular/projects/ordering/src/lib/proxy/generate-proxy.json

@ -3,6 +3,84 @@
"ordering"
],
"modules": {
"abp": {
"rootPath": "abp",
"remoteServiceName": "abp",
"controllers": {
"Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController": {
"controllerName": "AbpApplicationConfiguration",
"controllerGroupName": "AbpApplicationConfiguration",
"type": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController",
"interfaces": [
{
"type": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.IAbpApplicationConfigurationAppService"
}
],
"actions": {
"GetAsync": {
"uniqueName": "GetAsync",
"name": "GetAsync",
"httpMethod": "GET",
"url": "api/abp/application-configuration",
"supportedVersions": [],
"parametersOnMethod": [],
"parameters": [],
"returnValue": {
"type": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto",
"typeSimple": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto"
},
"allowAnonymous": null,
"implementFrom": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.IAbpApplicationConfigurationAppService"
}
}
},
"Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController": {
"controllerName": "AbpApiDefinition",
"controllerGroupName": "AbpApiDefinition",
"type": "Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController",
"interfaces": [],
"actions": {
"GetByModel": {
"uniqueName": "GetByModel",
"name": "Get",
"httpMethod": "GET",
"url": "api/abp/api-definition",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "model",
"typeAsString": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModelRequestDto, Volo.Abp.Http",
"type": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModelRequestDto",
"typeSimple": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModelRequestDto",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "model",
"name": "IncludeTypes",
"jsonName": null,
"type": "System.Boolean",
"typeSimple": "boolean",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "ModelBinding",
"descriptorName": "model"
}
],
"returnValue": {
"type": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel",
"typeSimple": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel"
},
"allowAnonymous": null,
"implementFrom": "Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController"
}
}
}
}
},
"ordering": {
"rootPath": "ordering",
"remoteServiceName": "Ordering",
@ -60,7 +138,7 @@
"type": "EShopOnAbp.OrderingService.Orders.OrderDto",
"typeSimple": "EShopOnAbp.OrderingService.Orders.OrderDto"
},
"allowAnonymous": null,
"allowAnonymous": false,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
},
"GetMyOrdersAsyncByInput": {
@ -97,7 +175,7 @@
"type": "System.Collections.Generic.List<EShopOnAbp.OrderingService.Orders.OrderDto>",
"typeSimple": "[EShopOnAbp.OrderingService.Orders.OrderDto]"
},
"allowAnonymous": null,
"allowAnonymous": true,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
},
"GetOrdersAsyncByInput": {
@ -198,6 +276,43 @@
"allowAnonymous": false,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
},
"GetDashboardAsyncByInput": {
"uniqueName": "GetDashboardAsyncByInput",
"name": "GetDashboardAsync",
"httpMethod": "GET",
"url": "api/ordering/order/dashboard",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "EShopOnAbp.OrderingService.Orders.DashboardInput, EShopOnAbp.OrderingService.Application.Contracts",
"type": "EShopOnAbp.OrderingService.Orders.DashboardInput",
"typeSimple": "EShopOnAbp.OrderingService.Orders.DashboardInput",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "input",
"name": "Filter",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "ModelBinding",
"descriptorName": "input"
}
],
"returnValue": {
"type": "EShopOnAbp.OrderingService.Orders.DashboardDto",
"typeSimple": "EShopOnAbp.OrderingService.Orders.DashboardDto"
},
"allowAnonymous": false,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
},
"GetByOrderNoAsyncByOrderNo": {
"uniqueName": "GetByOrderNoAsyncByOrderNo",
"name": "GetByOrderNoAsync",
@ -232,7 +347,7 @@
"type": "EShopOnAbp.OrderingService.Orders.OrderDto",
"typeSimple": "EShopOnAbp.OrderingService.Orders.OrderDto"
},
"allowAnonymous": null,
"allowAnonymous": false,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
},
"SetAsCancelledAsyncById": {
@ -343,90 +458,12 @@
"type": "EShopOnAbp.OrderingService.Orders.OrderDto",
"typeSimple": "EShopOnAbp.OrderingService.Orders.OrderDto"
},
"allowAnonymous": null,
"allowAnonymous": true,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
}
}
}
}
},
"abp": {
"rootPath": "abp",
"remoteServiceName": "abp",
"controllers": {
"Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController": {
"controllerName": "AbpApplicationConfiguration",
"controllerGroupName": "AbpApplicationConfiguration",
"type": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController",
"interfaces": [
{
"type": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.IAbpApplicationConfigurationAppService"
}
],
"actions": {
"GetAsync": {
"uniqueName": "GetAsync",
"name": "GetAsync",
"httpMethod": "GET",
"url": "api/abp/application-configuration",
"supportedVersions": [],
"parametersOnMethod": [],
"parameters": [],
"returnValue": {
"type": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto",
"typeSimple": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto"
},
"allowAnonymous": null,
"implementFrom": "Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.IAbpApplicationConfigurationAppService"
}
}
},
"Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController": {
"controllerName": "AbpApiDefinition",
"controllerGroupName": "AbpApiDefinition",
"type": "Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController",
"interfaces": [],
"actions": {
"GetByModel": {
"uniqueName": "GetByModel",
"name": "Get",
"httpMethod": "GET",
"url": "api/abp/api-definition",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "model",
"typeAsString": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModelRequestDto, Volo.Abp.Http",
"type": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModelRequestDto",
"typeSimple": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModelRequestDto",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "model",
"name": "IncludeTypes",
"jsonName": null,
"type": "System.Boolean",
"typeSimple": "boolean",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "ModelBinding",
"descriptorName": "model"
}
],
"returnValue": {
"type": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel",
"typeSimple": "Volo.Abp.Http.Modeling.ApplicationApiDescriptionModel"
},
"allowAnonymous": null,
"implementFrom": "Volo.Abp.AspNetCore.Mvc.ApiExploring.AbpApiDefinitionController"
}
}
}
}
}
},
"types": {
@ -2285,6 +2322,135 @@
}
]
},
"EShopOnAbp.OrderingService.Orders.DashboardInput": {
"baseType": null,
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": [
{
"name": "Filter",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isRequired": false
}
]
},
"EShopOnAbp.OrderingService.Orders.DashboardDto": {
"baseType": "Volo.Abp.Application.Dtos.EntityDto",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": [
{
"name": "TopSellings",
"jsonName": null,
"type": "[EShopOnAbp.OrderingService.OrderItems.TopSellingDto]",
"typeSimple": "[EShopOnAbp.OrderingService.OrderItems.TopSellingDto]",
"isRequired": false
},
{
"name": "Payments",
"jsonName": null,
"type": "[EShopOnAbp.OrderingService.Orders.PaymentDto]",
"typeSimple": "[EShopOnAbp.OrderingService.Orders.PaymentDto]",
"isRequired": false
},
{
"name": "OrderStatusDto",
"jsonName": null,
"type": "[EShopOnAbp.OrderingService.Orders.OrderStatusDto]",
"typeSimple": "[EShopOnAbp.OrderingService.Orders.OrderStatusDto]",
"isRequired": false
}
]
},
"EShopOnAbp.OrderingService.OrderItems.TopSellingDto": {
"baseType": "Volo.Abp.Application.Dtos.EntityDto",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": [
{
"name": "ProductName",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isRequired": false
},
{
"name": "PictureUrl",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isRequired": false
},
{
"name": "Units",
"jsonName": null,
"type": "System.Int32",
"typeSimple": "number",
"isRequired": false
}
]
},
"EShopOnAbp.OrderingService.Orders.PaymentDto": {
"baseType": "Volo.Abp.Application.Dtos.EntityDto",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": [
{
"name": "RateOfPaymentMethod",
"jsonName": null,
"type": "System.Decimal",
"typeSimple": "number",
"isRequired": false
},
{
"name": "PaymentMethod",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isRequired": false
}
]
},
"EShopOnAbp.OrderingService.Orders.OrderStatusDto": {
"baseType": "Volo.Abp.Application.Dtos.EntityDto",
"isEnum": false,
"enumNames": null,
"enumValues": null,
"genericArguments": null,
"properties": [
{
"name": "CountOfStatusOrder",
"jsonName": null,
"type": "System.Int32",
"typeSimple": "number",
"isRequired": false
},
{
"name": "OrderStatus",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isRequired": false
},
{
"name": "TotalIncome",
"jsonName": null,
"type": "System.Decimal",
"typeSimple": "number",
"isRequired": false
}
]
},
"EShopOnAbp.OrderingService.Orders.OrderCreateDto": {
"baseType": null,
"isEnum": false,

3
apps/angular/projects/ordering/src/lib/proxy/index.ts

@ -1,2 +1,3 @@
import * as OrderItems from './order-items';
import * as Orders from './orders';
export { Orders };
export { OrderItems, Orders };

1
apps/angular/projects/ordering/src/lib/proxy/order-items/index.ts

@ -0,0 +1 @@
export * from './models';

7
apps/angular/projects/ordering/src/lib/proxy/order-items/models.ts

@ -0,0 +1,7 @@
import type { EntityDto } from '@abp/ng.core';
export interface TopSellingDto extends EntityDto {
productName?: string;
pictureUrl?: string;
units: number;
}

22
apps/angular/projects/ordering/src/lib/proxy/orders/models.ts

@ -1,4 +1,5 @@
import type { EntityDto } from '@abp/ng.core';
import type { TopSellingDto } from '../order-items/models';
import type { OrderStatus } from './order-status.enum';
export interface BuyerDto extends EntityDto<string> {
@ -6,6 +7,16 @@ export interface BuyerDto extends EntityDto<string> {
email?: string;
}
export interface DashboardDto extends EntityDto {
topSellings: TopSellingDto[];
payments: PaymentDto[];
orderStatusDto: OrderStatusDto[];
}
export interface DashboardInput {
filter?: string;
}
export interface GetMyOrdersInput {
filter?: string;
}
@ -56,3 +67,14 @@ export interface OrderItemDto extends EntityDto<string> {
discount: number;
units: number;
}
export interface OrderStatusDto extends EntityDto {
countOfStatusOrder: number;
orderStatus?: string;
totalIncome: number;
}
export interface PaymentDto extends EntityDto {
rateOfPaymentMethod: number;
paymentMethod?: string;
}

20
apps/angular/projects/ordering/src/lib/proxy/orders/order-status.enum.ts

@ -1,10 +1,10 @@
import { mapEnumToOptions } from '@abp/ng.core';
export enum OrderStatus {
Placed = 0,
Paid = 1,
Shipped = 2,
Cancelled = 3,
}
export const orderStatusOptions = mapEnumToOptions(OrderStatus);
import { mapEnumToOptions } from '@abp/ng.core';
export enum OrderStatus {
Placed = 0,
Paid = 1,
Shipped = 2,
Cancelled = 3,
}
export const orderStatusOptions = mapEnumToOptions(OrderStatus);

10
apps/angular/projects/ordering/src/lib/proxy/orders/order.service.ts

@ -1,4 +1,4 @@
import type { GetMyOrdersInput, GetOrdersInput, OrderCreateDto, OrderDto } from './models';
import type { DashboardDto, DashboardInput, GetMyOrdersInput, GetOrdersInput, OrderCreateDto, OrderDto } from './models';
import { RestService } from '@abp/ng.core';
import type { PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
import { Injectable } from '@angular/core';
@ -32,6 +32,14 @@ export class OrderService {
},
{ apiName: this.apiName });
getDashboard = (input: DashboardInput) =>
this.restService.request<any, DashboardDto>({
method: 'GET',
url: '/api/ordering/order/dashboard',
params: { filter: input.filter },
},
{ apiName: this.apiName });
getListPaged = (input: PagedAndSortedResultRequestDto) =>
this.restService.request<any, PagedResultDto<OrderDto>>({
method: 'GET',

11
apps/angular/projects/ordering/src/ordering-routing.module.ts

@ -2,8 +2,15 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', redirectTo: 'orders', pathMatch: 'full' },
{ path: 'orders', loadChildren: () => import('./pages/orders/orders.module').then(m => m.OrdersModule) },
{
path: '',
loadChildren: () => import('./pages/dashboard/dashboard.module').then(m => m.DashboardModule),
pathMatch: 'full',
},
{
path: 'orders',
loadChildren: () => import('./pages/orders/orders.module').then(m => m.OrdersModule),
},
];
@NgModule({

19
apps/angular/projects/ordering/src/pages/dashboard/components/order-status-chart/order-status-chart.component.html

@ -0,0 +1,19 @@
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-md-12">
<h5 class="card-title">{{ 'OrderingService::Dashboard:OrderStatusChartTitle' | abpLocalization }}</h5>
</div>
</div>
</div>
<div class="card-body" >
<abp-chart
type="pie"
[data]="chartData"
[options]="options"
[responsive]="true"
></abp-chart>
</div>
</div>

25
apps/angular/projects/ordering/src/pages/dashboard/components/order-status-chart/order-status-chart.component.spec.ts

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { OrderStatusChartComponent } from './order-status-chart.component';
describe('OrderStatusChartComponent', () => {
let component: OrderStatusChartComponent;
let fixture: ComponentFixture<OrderStatusChartComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ OrderStatusChartComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(OrderStatusChartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

38
apps/angular/projects/ordering/src/pages/dashboard/components/order-status-chart/order-status-chart.component.ts

@ -0,0 +1,38 @@
import { Component, Input } from '@angular/core';
import { OrderStatusDto } from '../../../../lib/proxy/orders';
@Component({
selector: 'app-order-status-chart',
templateUrl: './order-status-chart.component.html',
})
export class OrderStatusChartComponent {
@Input()
set data(value: OrderStatusDto[]) {
const filtered = value.filter(x => x.countOfStatusOrder > 0);
this.chartData.datasets = [
{
data: [...filtered.map(x => x.countOfStatusOrder)],
backgroundColor: ['#fdcb6e', '#0984e3', '#ff7675'],
},
];
this.chartData.labels = [...filtered.map(x => x.orderStatus)];
}
chartData = {
labels: [],
datasets: [],
};
options = {
plugins: {
title: {
display: false,
text: '',
fontSize: 16,
},
legend: {
position: 'bottom',
},
},
};
}

19
apps/angular/projects/ordering/src/pages/dashboard/components/payments-chart/payments-chart.component.html

@ -0,0 +1,19 @@
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-md-12">
<h5 class="card-title">{{ 'OrderingService::Dashboard:PaymentChartTitle' | abpLocalization }}</h5>
</div>
</div>
</div>
<div class="card-body" >
<abp-chart
type="doughnut"
[data]="chartData"
[options]="options"
[responsive]="true"
></abp-chart>
</div>
</div>

25
apps/angular/projects/ordering/src/pages/dashboard/components/payments-chart/payments-chart.component.spec.ts

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PaymentsChartComponent } from './payments-chart.component';
describe('PaymentsChartComponent', () => {
let component: PaymentsChartComponent;
let fixture: ComponentFixture<PaymentsChartComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PaymentsChartComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(PaymentsChartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

35
apps/angular/projects/ordering/src/pages/dashboard/components/payments-chart/payments-chart.component.ts

@ -0,0 +1,35 @@
import { Component, Input } from '@angular/core';
import { PaymentDto } from '../../../../lib/proxy/orders';
@Component({
selector: 'app-payments-chart',
templateUrl: './payments-chart.component.html',
})
export class PaymentsChartComponent {
@Input()
set data(value: PaymentDto[]) {
this.chartData.datasets = [
{
data: [...value.map(x => x.rateOfPaymentMethod)],
backgroundColor: ['#fdcb6e', '#0984e3', '#ff7675'],
},
];
this.chartData.labels = [...value.map(x => x.paymentMethod)];
}
chartData = {
labels: [],
datasets: [],
};
options = {
plugins: {
title: {
display: false,
},
legend: {
position: 'bottom',
},
},
};
}

24
apps/angular/projects/ordering/src/pages/dashboard/components/top-selling/top-selling.component.html

@ -0,0 +1,24 @@
<div class="card">
<div class="card-header">
<div class="row">
<div class="col col-md-12">
<h5 class="card-title">{{ 'OrderingService::Dashboard:TopSellingCardTitle' | abpLocalization }}</h5>
</div>
</div>
</div>
<div class="card-body" *ngIf="topSellingProducts">
<ngx-datatable [rows]="topSellingProducts" [count]="topSellingProducts.length" default>
<ngx-datatable-column
[name]="'OrderingService::DisplayName:ProductName' | abpLocalization"
prop="productName"
></ngx-datatable-column>
<ngx-datatable-column
[name]="'OrderingService::DisplayName:Units' | abpLocalization"
prop="units"
></ngx-datatable-column>
</ngx-datatable>
</div>
</div>

25
apps/angular/projects/ordering/src/pages/dashboard/components/top-selling/top-selling.component.spec.ts

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TopSellingComponent } from './top-selling.component';
describe('TopSellingComponent', () => {
let component: TopSellingComponent;
let fixture: ComponentFixture<TopSellingComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ TopSellingComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(TopSellingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

12
apps/angular/projects/ordering/src/pages/dashboard/components/top-selling/top-selling.component.ts

@ -0,0 +1,12 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { TopSellingDto } from '../../../../lib/proxy/order-items';
@Component({
selector: 'app-top-selling',
templateUrl: './top-selling.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TopSellingComponent {
@Input()
topSellingProducts: Array<TopSellingDto> | undefined;
}

20
apps/angular/projects/ordering/src/pages/dashboard/dashboard-routing.module.ts

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DashboardComponent } from './dashboard.component';
const routes: Routes = [
{
path: '',
component: DashboardComponent,
// canActivate: [AuthGuard, PermissionGuard],
// data: {
// requiredPolicy: eCatalogPolicyNames.ProductManagement,
// },
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class DashboardRoutingModule {}

0
apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.css

19
apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.html

@ -0,0 +1,19 @@
<h1> {{"OrderingService::Dashboard:Title" | abpLocalization}}</h1>
<br>
<div *ngIf="dashboard$ | async as dashboard">
<div class="row">
<div class="col col-md-3">
<app-order-status-chart [data]="dashboard.orderStatusDto">
</app-order-status-chart>
</div>
<div class="col col-md-6">
<app-top-selling [topSellingProducts]="dashboard.topSellings">
</app-top-selling>
</div>
<div class="col col-md-3">
<app-payments-chart [data]="dashboard.payments">
</app-payments-chart>
</div>
</div>
</div>

25
apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.spec.ts

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DashboardComponent } from './dashboard.component';
describe('DashboardComponent', () => {
let component: DashboardComponent;
let fixture: ComponentFixture<DashboardComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DashboardComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DashboardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

13
apps/angular/projects/ordering/src/pages/dashboard/dashboard.component.ts

@ -0,0 +1,13 @@
import { Component } from '@angular/core';
import { OrderService } from '../../lib/proxy/orders';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css'],
})
export class DashboardComponent {
constructor(private service: OrderService) {}
dashboard$ = this.service.getDashboard({});
}

25
apps/angular/projects/ordering/src/pages/dashboard/dashboard.module.ts

@ -0,0 +1,25 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProductRoutingModule } from '@eshoponabp/catalog';
import { ThemeSharedModule } from '@abp/ng.theme.shared';
import { CoreModule } from '@abp/ng.core';
import { DashboardRoutingModule } from './dashboard-routing.module';
import { DashboardComponent } from './dashboard.component';
import { TopSellingComponent } from './components/top-selling/top-selling.component';
import { OrderStatusChartComponent } from './components/order-status-chart/order-status-chart.component';
import { ChartModule } from '@abp/ng.components/chart.js';
import { PaymentsChartComponent } from './components/payments-chart/payments-chart.component';
@NgModule({
declarations: [DashboardComponent, TopSellingComponent, OrderStatusChartComponent, PaymentsChartComponent],
imports: [
DashboardRoutingModule,
CommonModule,
ProductRoutingModule,
CommonModule,
ThemeSharedModule,
CoreModule,
ChartModule,
],
})
export class DashboardModule {}

2
apps/angular/projects/ordering/src/pages/orders/order-detail/order-detail-item/order-detail-item.component.ts

@ -1,7 +1,7 @@
import { Component, Input } from '@angular/core';
@Component({
selector: 'lib-order-detail-item',
selector: 'app-order-detail-item',
template: `
<div class="row">
<div class="col-3">

28
apps/angular/projects/ordering/src/pages/orders/order-detail/order-detail.component.html

@ -7,33 +7,33 @@
<ng-template #abpBody>
<div *ngIf="order">
<div class="container">
<lib-order-detail-item label="OrderingService::DisplayName:OrderNo"
>#{{ order.orderNo }}</lib-order-detail-item
<app-order-detail-item label="OrderingService::DisplayName:OrderNo"
>#{{ order.orderNo }}</app-order-detail-item
>
<lib-order-detail-item label="OrderingService::DisplayName:OrderStatus">{{
<app-order-detail-item label="OrderingService::DisplayName:OrderStatus">{{
order.orderStatus
}}</lib-order-detail-item>
<lib-order-detail-item label="OrderingService::DisplayName:BuyerName">{{
}}</app-order-detail-item>
<app-order-detail-item label="OrderingService::DisplayName:BuyerName">{{
order.buyer.name
}}</lib-order-detail-item>
<lib-order-detail-item label="OrderingService::DisplayName:BuyerEmail">{{
}}</app-order-detail-item>
<app-order-detail-item label="OrderingService::DisplayName:BuyerEmail">{{
order.buyer.email
}}</lib-order-detail-item>
}}</app-order-detail-item>
<lib-order-detail-item label="OrderingService::DisplayName:Address">
<app-order-detail-item label="OrderingService::DisplayName:Address">
<span *ngIf="order.address as address">
{{ address.description }} <br />
{{ address.street }} <br />
{{ address.zipCode }} <br />
{{ address.city }} / {{ address.country }} <br />
</span>
</lib-order-detail-item>
<lib-order-detail-item label="OrderingService::DisplayName:PaymentMethod">{{
</app-order-detail-item>
<app-order-detail-item label="OrderingService::DisplayName:PaymentMethod">{{
order.paymentMethod
}}</lib-order-detail-item>
<lib-order-detail-item label="OrderingService::DisplayName:Total">{{
}}</app-order-detail-item>
<app-order-detail-item label="OrderingService::DisplayName:Total">{{
order.orderTotal | currency
}}</lib-order-detail-item>
}}</app-order-detail-item>
</div>
<br /><br /><br />

2
apps/angular/projects/ordering/src/pages/orders/order-detail/order-detail.component.ts

@ -3,7 +3,7 @@ import { OrderViewModel } from '../../../lib/order-view-model';
import { environment } from '../../../../../../src/environments/environment';
@Component({
selector: 'lib-order-detail',
selector: 'app-order-detail',
templateUrl: './order-detail.component.html',
})
export class OrderDetailComponent {

4
apps/angular/projects/ordering/src/pages/orders/orders.component.html

@ -79,9 +79,9 @@
</div>
</div>
<lib-order-detail
<app-order-detail
[visible]="isModalVisible"
(visibleChange)="closeModal($event)"
[order]="selectedOrder"
>
</lib-order-detail>
</app-order-detail>

2
apps/angular/projects/ordering/src/pages/orders/orders.component.ts

@ -6,7 +6,7 @@ import { ListService } from '@abp/ng.core';
import { eOrderingPolicyNames } from '@eshoponabp/ordering/config';
@Component({
selector: 'lib-orders',
selector: 'app-orders',
templateUrl: './orders.component.html',
providers: [ListService],
})

2
gateways/web-public/src/EShopOnAbp.WebPublicGateway/yarp.json

@ -56,7 +56,7 @@
"administrationCluster": {
"Destinations": {
"destination1": {
"Address": "http://localhost:44353"
"Address": "https://localhost:44353"
}
}
},

11
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/OrderItems/TopSellingDto.cs

@ -0,0 +1,11 @@
using Volo.Abp.Application.Dtos;
namespace EShopOnAbp.OrderingService.OrderItems
{
public class TopSellingDto : EntityDto
{
public string ProductName { get; set; }
public string PictureUrl { get; set; }
public int Units { get; set; }
}
}

2
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/OrderingServiceRemoteServiceConsts.cs

@ -1,6 +1,6 @@
namespace EShopOnAbp.OrderingService
{
public class OrderingServiceRemoteServiceConsts
public static class OrderingServiceRemoteServiceConsts
{
public const string RemoteServiceName = "Ordering";
}

13
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/DashboardDto.cs

@ -0,0 +1,13 @@
using EShopOnAbp.OrderingService.OrderItems;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
namespace EShopOnAbp.OrderingService.Orders
{
public class DashboardDto: EntityDto
{
public List<TopSellingDto> TopSellings { get; set; }
public List<PaymentDto> Payments { get; set; }
public List<OrderStatusDto> OrderStatusDto { get; set; }
}
}

7
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/DashboardInput.cs

@ -0,0 +1,7 @@
namespace EShopOnAbp.OrderingService.Orders
{
public class DashboardInput
{
public string Filter { get; set; }
}
}

1
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/IOrderAppService.cs

@ -16,5 +16,6 @@ public interface IOrderAppService : IApplicationService
Task SetAsCancelledAsync(Guid id);
Task SetAsShippedAsync(Guid id);
Task<PagedResultDto<OrderDto>> GetListPagedAsync(PagedAndSortedResultRequestDto input);
Task<DashboardDto> GetDashboardAsync(DashboardInput input);
}

10
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/OrderStatusDto.cs

@ -0,0 +1,10 @@
using Volo.Abp.Application.Dtos;
namespace EShopOnAbp.OrderingService.Orders;
public class OrderStatusDto : EntityDto
{
public int CountOfStatusOrder { get; set; }
public string OrderStatus { get; set; }
public decimal TotalIncome { get; set; }
}

9
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Orders/PaymentDto.cs

@ -0,0 +1,9 @@
using Volo.Abp.Application.Dtos;
namespace EShopOnAbp.OrderingService.Orders;
public class PaymentDto : EntityDto
{
public decimal RateOfPaymentMethod { get; set; }
public string PaymentMethod { get; set; }
}

2
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Permissions/OrderingServicePermissionDefinitionProvider.cs

@ -9,10 +9,12 @@ namespace EShopOnAbp.OrderingService.Permissions
public override void Define(IPermissionDefinitionContext context)
{
var orderManagmentGroup = context.AddGroup(OrderingServicePermissions.GroupName, L("Permission:OrderingService"));
var oders = orderManagmentGroup.AddPermission(OrderingServicePermissions.Orders.Default, L("Permission:Orders"));
oders.AddChild(OrderingServicePermissions.Orders.SetAsCancelled, L("Permission:Orders.SetAsCancelled"));
oders.AddChild(OrderingServicePermissions.Orders.SetAsShipped, L("Permission:Orders.SetAsShipped"));
orderManagmentGroup.AddPermission(OrderingServicePermissions.Orders.Dashboard, L("Permission:Dashboard"));
}
private static LocalizableString L(string name)

1
services/ordering/src/EShopOnAbp.OrderingService.Application.Contracts/Permissions/OrderingServicePermissions.cs

@ -11,6 +11,7 @@ namespace EShopOnAbp.OrderingService.Permissions
public const string Default = GroupName + ".Orders";
public const string SetAsCancelled = GroupName + ".SetAsCancelled";
public const string SetAsShipped = GroupName + ".SetAsShipped";
public const string Dashboard = GroupName + ".Dashboard";
}
public static string[] GetAll()

6
services/ordering/src/EShopOnAbp.OrderingService.Application/OrderingServiceApplicationAutoMapperProfile.cs

@ -1,4 +1,5 @@
using AutoMapper;
using EShopOnAbp.OrderingService.OrderItems;
using EShopOnAbp.OrderingService.Orders;
using Volo.Abp.AutoMapper;
@ -10,9 +11,10 @@ namespace EShopOnAbp.OrderingService
{
CreateMap<Address, OrderAddressDto>();
CreateMap<Buyer, BuyerDto>();
CreateMap<OrderItem, OrderItemDto>();
CreateMap<OrderItem, TopSellingDto>();
CreateMap<Order, OrderDto>()
.Ignore(q => q.Address)
.Ignore(q => q.Items)

66
services/ordering/src/EShopOnAbp.OrderingService.Application/Orders/OrderAppService.cs

@ -1,10 +1,12 @@
using EShopOnAbp.OrderingService.Localization;
using EShopOnAbp.OrderingService.OrderItems;
using EShopOnAbp.OrderingService.Orders.Specifications;
using EShopOnAbp.OrderingService.Permissions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
@ -61,7 +63,37 @@ public class OrderAppService : ApplicationService, IOrderAppService
);
}
[AllowAnonymous]
[Authorize(OrderingServicePermissions.Orders.Dashboard)]
public async Task<DashboardDto> GetDashboardAsync(DashboardInput input)
{
return new DashboardDto()
{
TopSellings = await GetTopSellingAsync(input.Filter),
OrderStatusDto = await GetCountOfTotalOrderStatusAsync(input.Filter),
Payments = await GetPercentOfTotalPaymentAsync(input.Filter)
};
}
private async Task<List<TopSellingDto>> GetTopSellingAsync(string filter)
{
ISpecification<Order> specification = SpecificationFactory.Create(filter);
var orderItems = await _orderRepository.GetTopSelling(specification, true);
return ObjectMapper.Map<List<OrderItem>, List<TopSellingDto>>(orderItems);
}
private async Task<List<PaymentDto>> GetPercentOfTotalPaymentAsync(string filter)
{
ISpecification<Order> specification = SpecificationFactory.Create(filter);
var orders = await _orderRepository.GetPercentOfTotalPayment(specification);
return CreatePaymentDtoMapping(orders);
}
private async Task<List<OrderStatusDto>> GetCountOfTotalOrderStatusAsync(string filter)
{
ISpecification<Order> specification = SpecificationFactory.Create(filter);
var orders = await _orderRepository.GetCountOfTotalOrderStatus(specification, true);
return CreateOrderStatusDtoMapping(orders);
}
public async Task<OrderDto> GetByOrderNoAsync(int orderNo)
{
var order = await _orderRepository.GetByOrderNoAsync(orderNo);
@ -149,4 +181,36 @@ public class OrderAppService : ApplicationService, IOrderAppService
PaymentMethod = order.PaymentMethod
};
}
private List<PaymentDto> CreatePaymentDtoMapping(List<Order> orders)
{
var payments = orders
.GroupBy(p => p.PaymentMethod)
.Select(p => new PaymentDto { RateOfPaymentMethod = p.Count(), PaymentMethod = p.Key })
.OrderBy(p => p.RateOfPaymentMethod)
.ToList();
var denominator = payments.Sum(p => p.RateOfPaymentMethod);
if (denominator != 0)
{
decimal rate = 100 / payments.Sum(p => p.RateOfPaymentMethod);
payments.ForEach(p => p.RateOfPaymentMethod *= rate);
}
return payments;
}
private List<OrderStatusDto> CreateOrderStatusDtoMapping(List<Order> orders)
{
var orderStatus = orders
.GroupBy(p => p.OrderStatus)
.Select(p => new OrderStatusDto { CountOfStatusOrder = p.Count(), OrderStatus = p.Key.ToString(), })
.OrderBy(p => p.CountOfStatusOrder)
.ToList();
decimal totalIncome = orders.Sum(p => p.OrderItems.Sum(p => p.Units * p.UnitPrice));
orderStatus.Add(new OrderStatusDto() { OrderStatus = "Total Income", TotalIncome = totalIncome });
return orderStatus;
}
}

14
services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Localization/OrderingService/en.json

@ -12,9 +12,8 @@
"Permission:OrderingService": "Ordering Service",
"Menu:Orders": "Orders",
"Menu:OrderManagement": "Order Management",
"Menu:Dashboard": "Dashboard",
"ModalTitle":"Order Detail",
"DisplayName:OrderNo": "Order No",
"DisplayName:OrderDate": "Order Date",
"DisplayName:OrderTotal": "Order Total",
@ -30,14 +29,17 @@
"DisplayName:BuyerEmail": "Buyer E-mail",
"DisplayName:Address": "Address",
"DisplayName:PaymentMethod": "Payment Method",
"DisplayName:Total": "Total",
"DisplayName:Total": "Total",
"Permission:Orders.SetAsCancelled": "Set As Cancelled",
"Permission:Orders.SetAsShipped": "Set As Shipped",
"Enum:OrderStatus:0":"Placed",
"Enum:OrderStatus:1":"Paid",
"Enum:OrderStatus:2":"Shipped",
"Enum:OrderStatus:3":"Cancelled"
"Enum:OrderStatus:3":"Cancelled",
"Permission:Dashboard": "Dashboard",
"Dashboard:Title": "Dashboard",
"Dashboard:OrderStatusChartTitle": "Order Status Chart",
"Dashboard:PaymentChartTitle": "Payments Chart",
"Dashboard:TopSellingCardTitle": "Top Selling"
}
}

4
services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Localization/OrderingService/tr.json

@ -38,6 +38,8 @@
"Enum:OrderStatus:0": "Oluşturuldu",
"Enum:OrderStatus:1": "Ödendi",
"Enum:OrderStatus:2": "Sevk Edildi",
"Enum:OrderStatus:3": "İptal Edildi"
"Enum:OrderStatus:3": "İptal Edildi",
"Permission:Dashboard": "Gösterge Paneli"
}
}

3
services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Localization/OrderingService/zh-Hans.json

@ -14,6 +14,7 @@
"Menu:Orders": "命令",
"Menu:OrderManagement": "订单管理",
"Permission:Orders.SetAsCancelled": "设置为取消",
"Permission:Orders.SetAsShipped": "设置为发货"
"Permission:Orders.SetAsShipped": "设置为发货",
"Permission:Dashboard": "仪表板"
}
}

2
services/ordering/src/EShopOnAbp.OrderingService.Domain.Shared/Orders/OrderConstants.cs

@ -5,5 +5,5 @@ public static class OrderConstants
public const int OrderPaymentMethodNameMaxLength = 128;
public const int OrderStatusNameMaxLength = 256;
public const int PaymentStatusMaxLength = 256;
public const int Top10 = 10;
}

14
services/ordering/src/EShopOnAbp.OrderingService.Domain/Orders/IOrderRepository.cs

@ -20,6 +20,20 @@ public interface IOrderRepository : IRepository<Order, Guid>
bool includeDetails = true,
CancellationToken cancellationToken = default);
Task<List<OrderItem>> GetTopSelling(
ISpecification<Order> spec,
bool includeDetails = true,
CancellationToken cancellationToken = default);
Task<List<Order>> GetPercentOfTotalPayment(
ISpecification<Order> spec,
CancellationToken cancellationToken = default);
Task<List<Order>> GetCountOfTotalOrderStatus(
ISpecification<Order> spec,
bool includeDetails = true,
CancellationToken cancellationToken = default);
Task<Order> GetByOrderNoAsync(int orderNo,
bool includeDetails = true,
CancellationToken cancellationToken = default);

38
services/ordering/src/EShopOnAbp.OrderingService.EntityFrameworkCore/Orders/EfCoreOrderRepository.cs

@ -46,6 +46,44 @@ public class EfCoreOrderRepository : EfCoreRepository<OrderingServiceDbContext,
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<OrderItem>> GetTopSelling(
ISpecification<Order> spec,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return (await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.Where(spec.ToExpression())
.SelectMany(oi => oi.OrderItems)
.GroupBy(p => p.ProductCode)
.OrderByDescending(o => o.Sum(p => p.Units))
.Select(o => o.ToList())
.ToListAsync())
.SelectMany(t => t)
.Take(OrderConstants.Top10)
.ToList();
}
public async Task<List<Order>> GetPercentOfTotalPayment(
ISpecification<Order> spec,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(spec.ToExpression())
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<List<Order>> GetCountOfTotalOrderStatus(
ISpecification<Order> spec,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.IncludeDetails(includeDetails)
.Where(spec.ToExpression())
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task<Order> GetByOrderNoAsync(
int orderNo,
bool includeDetails = true,

8
services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Client/ClientProxies/OrderClientProxy.Generated.cs

@ -48,6 +48,14 @@ public partial class OrderClientProxy : ClientProxyBase<IOrderAppService>, IOrde
});
}
public virtual async Task<DashboardDto> GetDashboardAsync(DashboardInput input)
{
return await RequestAsync<DashboardDto>(nameof(GetDashboardAsync), new ClientProxyRequestTypeValue
{
{ typeof(DashboardInput), input }
});
}
public virtual async Task<OrderDto> GetByOrderNoAsync(int orderNo)
{
return await RequestAsync<OrderDto>(nameof(GetByOrderNoAsync), new ClientProxyRequestTypeValue

37
services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Client/ClientProxies/ordering-generate-proxy.json

@ -195,6 +195,43 @@
"allowAnonymous": false,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
},
"GetDashboardAsyncByInput": {
"uniqueName": "GetDashboardAsyncByInput",
"name": "GetDashboardAsync",
"httpMethod": "GET",
"url": "api/ordering/order/dashboard",
"supportedVersions": [],
"parametersOnMethod": [
{
"name": "input",
"typeAsString": "EShopOnAbp.OrderingService.Orders.DashboardInput, EShopOnAbp.OrderingService.Application.Contracts",
"type": "EShopOnAbp.OrderingService.Orders.DashboardInput",
"typeSimple": "EShopOnAbp.OrderingService.Orders.DashboardInput",
"isOptional": false,
"defaultValue": null
}
],
"parameters": [
{
"nameOnMethod": "input",
"name": "Filter",
"jsonName": null,
"type": "System.String",
"typeSimple": "string",
"isOptional": false,
"defaultValue": null,
"constraintTypes": null,
"bindingSourceId": "ModelBinding",
"descriptorName": "input"
}
],
"returnValue": {
"type": "EShopOnAbp.OrderingService.Orders.DashboardDto",
"typeSimple": "EShopOnAbp.OrderingService.Orders.DashboardDto"
},
"allowAnonymous": null,
"implementFrom": "EShopOnAbp.OrderingService.Orders.IOrderAppService"
},
"GetByOrderNoAsyncByOrderNo": {
"uniqueName": "GetByOrderNoAsyncByOrderNo",
"name": "GetByOrderNoAsync",

2
services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/appsettings.json

@ -1,7 +1,7 @@
{
"App": {
"SelfUrl": "https://localhost:44356",
"CorsOrigins": "https://localhost:44372,https://localhost:44373,https://localhost:4200"
"CorsOrigins": "https://localhost:44372,https://localhost:44373,http://localhost:4200"
},
"AuthServer": {
"Authority": "https://localhost:44330",

Loading…
Cancel
Save