@merkaly/api 0.2.4-6 → 0.2.4-7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.DS_Store +0 -0
- package/.bin/deploy.sh +9 -0
- package/.bin/package.sh +7 -0
- package/.docker/Dockerfile +21 -0
- package/.dockerignore +12 -0
- package/.env +21 -0
- package/.eslintignore +8 -0
- package/.eslintrc.js +35 -0
- package/.github/dependabot.yml +17 -0
- package/.github/semantic.yml +5 -0
- package/.github/workflows/pull_request.yml +35 -0
- package/.gitignore +42 -0
- package/.husky/.gitignore +1 -0
- package/.husky/commit-msg +5 -0
- package/.husky/common.sh +8 -0
- package/.husky/pre-commit +5 -0
- package/.husky/pre-push +4 -0
- package/.idea/.gitignore +5 -0
- package/.idea/api.iml +13 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/inspectionProfiles/Project_Default.xml +11 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +12 -0
- package/.idea/workspace.xml +2320 -0
- package/.output/modules/sales/orders/order.entity.d.ts +1 -1
- package/.output/modules/sales/orders/order.validator.js +2 -3
- package/authCertificate.pem +19 -0
- package/cloudbuild.yaml +20 -0
- package/commitlint.config.js +3 -0
- package/jest.config.js +14 -0
- package/merkaly-api-0.2.4-6.tgz +0 -0
- package/nest-cli.json +9 -0
- package/package.json +8 -7
- package/serviceAccount.json +7 -0
- package/src/abstract/absctract.listener.ts +2 -0
- package/src/abstract/abstract.controller.ts +27 -0
- package/src/abstract/abstract.entity.ts +19 -0
- package/src/abstract/abstract.exception.ts +56 -0
- package/src/abstract/abstract.fixture.ts +7 -0
- package/src/abstract/abstract.migration.ts +13 -0
- package/src/abstract/abstract.repository.ts +79 -0
- package/src/abstract/abstract.router.ts +7 -0
- package/src/abstract/abstract.validator.ts +62 -0
- package/src/app.config.ts +57 -0
- package/src/app.console.ts +30 -0
- package/src/app.controller.ts +48 -0
- package/src/app.migration.ts +7 -0
- package/src/app.module.ts +92 -0
- package/src/app.strategy.ts +25 -0
- package/src/commands/assets.command.ts +38 -0
- package/src/commands/deploy.command.ts +6 -0
- package/src/commands/fixture.command.ts +11 -0
- package/src/commands/generate.command.ts +286 -0
- package/src/decorators/public.decorator.ts +5 -0
- package/src/decorators/user.decorator.ts +21 -0
- package/src/exceptions/missing-identity.exception.ts +11 -0
- package/src/exceptions/store-not-implemented.exception.ts +13 -0
- package/src/exceptions/store-not-recognized.exception.ts +11 -0
- package/src/guards/auth.guard.ts +43 -0
- package/src/guards/organization.guard.ts +39 -0
- package/src/interceptors/mongo.interceptor.ts +16 -0
- package/src/main.ts +37 -0
- package/src/middlewares/logger.middleware.ts +15 -0
- package/src/middlewares/organization.middleware.ts +76 -0
- package/src/migrations/1667226478717-product_price_enhance.ts +29 -0
- package/src/migrations/1667329249561-product_add_seo_code_dimension.ts +37 -0
- package/src/migrations/1667601099139-product_activve_and_hashtag.ts +35 -0
- package/src/migrations/1668136428972-content_banners-use-as-image.ts +56 -0
- package/src/migrations/1680483744321-order-billing-shipping-status.ts +32 -0
- package/src/modules/assets/asset.controller.ts +33 -0
- package/src/modules/assets/asset.entity.ts +26 -0
- package/src/modules/assets/asset.module.ts +21 -0
- package/src/modules/assets/asset.repository.ts +51 -0
- package/src/modules/assets/asset.schema.ts +4 -0
- package/src/modules/assets/asset.service.ts +41 -0
- package/src/modules/auth/auth.controller.ts +42 -0
- package/src/modules/auth/auth.module.ts +18 -0
- package/src/modules/auth/logout.ts +0 -0
- package/src/modules/command.module.ts +19 -0
- package/src/modules/content/banners/banner.controller.ts +56 -0
- package/src/modules/content/banners/banner.entity.ts +17 -0
- package/src/modules/content/banners/banner.fixture.ts +19 -0
- package/src/modules/content/banners/banner.listener.ts +6 -0
- package/src/modules/content/banners/banner.module.ts +21 -0
- package/src/modules/content/banners/banner.repository.ts +38 -0
- package/src/modules/content/banners/banner.schema.ts +4 -0
- package/src/modules/content/banners/banner.types.ts +7 -0
- package/src/modules/content/banners/banner.validator.ts +19 -0
- package/src/modules/content/content.module.ts +20 -0
- package/src/modules/content/pages/page.controller.ts +53 -0
- package/src/modules/content/pages/page.entity.ts +27 -0
- package/src/modules/content/pages/page.fixture.ts +19 -0
- package/src/modules/content/pages/page.listener.ts +6 -0
- package/src/modules/content/pages/page.module.ts +21 -0
- package/src/modules/content/pages/page.repository.ts +44 -0
- package/src/modules/content/pages/page.schema.ts +4 -0
- package/src/modules/content/pages/page.types.ts +9 -0
- package/src/modules/content/pages/page.validator.ts +29 -0
- package/src/modules/global.module.ts +70 -0
- package/src/modules/insight/controllers/address.controller.ts +29 -0
- package/src/modules/insight/controllers/order.controller.ts +70 -0
- package/src/modules/insight/controllers/products.controller.ts +18 -0
- package/src/modules/insight/insight.module.ts +24 -0
- package/src/modules/insight/validators/order.validator.ts +10 -0
- package/src/modules/inventory/brands/brand.controller.ts +59 -0
- package/src/modules/inventory/brands/brand.entity.ts +14 -0
- package/src/modules/inventory/brands/brand.exception.ts +9 -0
- package/src/modules/inventory/brands/brand.listener.ts +18 -0
- package/src/modules/inventory/brands/brand.module.ts +19 -0
- package/src/modules/inventory/brands/brand.repository.ts +39 -0
- package/src/modules/inventory/brands/brand.schema.ts +4 -0
- package/src/modules/inventory/brands/brand.validator.ts +23 -0
- package/src/modules/inventory/categories/category.controller.ts +59 -0
- package/src/modules/inventory/categories/category.entity.ts +21 -0
- package/src/modules/inventory/categories/category.exception.ts +9 -0
- package/src/modules/inventory/categories/category.fixture.ts +18 -0
- package/src/modules/inventory/categories/category.listener.ts +17 -0
- package/src/modules/inventory/categories/category.module.ts +19 -0
- package/src/modules/inventory/categories/category.repository.ts +40 -0
- package/src/modules/inventory/categories/category.schema.ts +4 -0
- package/src/modules/inventory/categories/category.validator.ts +30 -0
- package/src/modules/inventory/inventory.module.ts +22 -0
- package/src/modules/inventory/products/entities/code.entity.ts +15 -0
- package/src/modules/inventory/products/entities/dimension.entity.ts +18 -0
- package/src/modules/inventory/products/entities/price.entity.ts +12 -0
- package/src/modules/inventory/products/entities/seo.entity.ts +15 -0
- package/src/modules/inventory/products/product.controller.ts +59 -0
- package/src/modules/inventory/products/product.entity.ts +53 -0
- package/src/modules/inventory/products/product.exception.ts +9 -0
- package/src/modules/inventory/products/product.fixture.ts +19 -0
- package/src/modules/inventory/products/product.listener.ts +27 -0
- package/src/modules/inventory/products/product.module.ts +20 -0
- package/src/modules/inventory/products/product.repository.ts +108 -0
- package/src/modules/inventory/products/product.schema.ts +15 -0
- package/src/modules/inventory/products/product.validator.ts +71 -0
- package/src/modules/inventory/products/validators/code.validator.ts +15 -0
- package/src/modules/inventory/products/validators/dimension.validator.ts +19 -0
- package/src/modules/inventory/products/validators/price.validator.ts +10 -0
- package/src/modules/inventory/products/validators/seo.validator.ts +15 -0
- package/src/modules/inventory/properties/property.controller.ts +56 -0
- package/src/modules/inventory/properties/property.entity.ts +18 -0
- package/src/modules/inventory/properties/property.exception.ts +9 -0
- package/src/modules/inventory/properties/property.listener.ts +20 -0
- package/src/modules/inventory/properties/property.module.ts +21 -0
- package/src/modules/inventory/properties/property.repository.ts +23 -0
- package/src/modules/inventory/properties/property.schema.ts +4 -0
- package/src/modules/inventory/properties/property.validator.ts +27 -0
- package/src/modules/sales/clients/client.controller.ts +60 -0
- package/src/modules/sales/clients/client.entity.ts +25 -0
- package/src/modules/sales/clients/client.exception.ts +9 -0
- package/src/modules/sales/clients/client.listener.ts +20 -0
- package/src/modules/sales/clients/client.module.ts +19 -0
- package/src/modules/sales/clients/client.repository.ts +37 -0
- package/src/modules/sales/clients/client.schema.ts +4 -0
- package/src/modules/sales/clients/client.validator.ts +43 -0
- package/src/modules/sales/orders/billing/billing.entity.ts +22 -0
- package/src/modules/sales/orders/billing/billing.types.ts +10 -0
- package/src/modules/sales/orders/billing/billing.validator.ts +21 -0
- package/src/modules/sales/orders/billing/entities/address.entity.ts +27 -0
- package/src/modules/sales/orders/billing/entities/customer.entity.ts +14 -0
- package/src/modules/sales/orders/billing/entities/status.entity.ts +16 -0
- package/src/modules/sales/orders/billing/validators/address.validator.ts +28 -0
- package/src/modules/sales/orders/billing/validators/customer.validator.ts +14 -0
- package/src/modules/sales/orders/customer/customer.entity.ts +14 -0
- package/src/modules/sales/orders/customer/customer.validator.ts +14 -0
- package/src/modules/sales/orders/item/item.entity.ts +21 -0
- package/src/modules/sales/orders/item/item.schema.ts +8 -0
- package/src/modules/sales/orders/item/item.validator.ts +10 -0
- package/src/modules/sales/orders/order.controller.ts +93 -0
- package/src/modules/sales/orders/order.entity.ts +47 -0
- package/src/modules/sales/orders/order.listener.ts +20 -0
- package/src/modules/sales/orders/order.module.ts +19 -0
- package/src/modules/sales/orders/order.repository.ts +189 -0
- package/src/modules/sales/orders/order.schema.ts +35 -0
- package/src/modules/sales/orders/order.validator.ts +72 -0
- package/src/modules/sales/orders/shipping/entities/address.entity.ts +27 -0
- package/src/modules/sales/orders/shipping/entities/customer.entity.ts +14 -0
- package/src/modules/sales/orders/shipping/entities/status.entity.ts +16 -0
- package/src/modules/sales/orders/shipping/shipping.entity.ts +25 -0
- package/src/modules/sales/orders/shipping/shipping.types.ts +12 -0
- package/src/modules/sales/orders/shipping/shipping.validator.ts +25 -0
- package/src/modules/sales/orders/shipping/validators/address.validator.ts +28 -0
- package/src/modules/sales/orders/shipping/validators/customer.validator.ts +14 -0
- package/src/modules/sales/orders/status/status.entity.ts +16 -0
- package/src/modules/sales/orders/status/status.validator.ts +8 -0
- package/src/modules/sales/sales.module.ts +20 -0
- package/src/modules/setting/connections/connection.controller.ts +27 -0
- package/src/modules/setting/connections/connection.module.ts +17 -0
- package/src/modules/setting/connections/connection.validator.ts +15 -0
- package/src/modules/setting/layout/layout.controller.ts +34 -0
- package/src/modules/setting/layout/layout.entity.ts +13 -0
- package/src/modules/setting/layout/layout.listener.ts +7 -0
- package/src/modules/setting/layout/layout.module.ts +21 -0
- package/src/modules/setting/layout/layout.repository.ts +29 -0
- package/src/modules/setting/layout/layout.schema.ts +4 -0
- package/src/modules/setting/members/member.controller.ts +22 -0
- package/src/modules/setting/members/member.module.ts +17 -0
- package/src/modules/setting/members/member.validator.ts +3 -0
- package/src/modules/setting/organization/organization.controller.ts +33 -0
- package/src/modules/setting/organization/organization.entity.ts +27 -0
- package/src/modules/setting/organization/organization.listener.ts +46 -0
- package/src/modules/setting/organization/organization.module.ts +21 -0
- package/src/modules/setting/organization/organization.repository.ts +55 -0
- package/src/modules/setting/organization/organization.types.ts +65 -0
- package/src/modules/setting/organization/organization.validator.ts +56 -0
- package/src/modules/setting/setting.module.ts +23 -0
- package/src/modules/setting/theme/theme.controller.ts +34 -0
- package/src/modules/setting/theme/theme.entity.ts +13 -0
- package/src/modules/setting/theme/theme.listener.ts +6 -0
- package/src/modules/setting/theme/theme.module.ts +21 -0
- package/src/modules/setting/theme/theme.repository.ts +23 -0
- package/src/modules/setting/theme/theme.schema.ts +4 -0
- package/src/modules/users/user.controller.ts +75 -0
- package/src/modules/users/user.module.ts +20 -0
- package/src/modules/users/user.validator.ts +28 -0
- package/src/providers/auth0.provider.ts +36 -0
- package/src/providers/storage.provider.ts +22 -0
- package/src/services/auth0.service.ts +7 -0
- package/src/services/logger.service.ts +33 -0
- package/src/services/mongo.service.ts +44 -0
- package/src/services/storage.service.ts +39 -0
- package/src/types.ts +19 -0
- package/tsconfig.json +40 -0
- package/tsconfig.package.json +20 -0
- package/yarn.lock +8782 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Prop } from '@nestjs/mongoose';
|
|
2
|
+
import { Schema as Collection } from '@nestjs/mongoose/dist/decorators/schema.decorator';
|
|
3
|
+
import { Schema } from 'mongoose';
|
|
4
|
+
import { BillingMethod } from "./billing.types";
|
|
5
|
+
import { BillingStatusEntity } from "./entities/status.entity";
|
|
6
|
+
import { BillingAddressEntity } from "./entities/address.entity";
|
|
7
|
+
import { BillingCustomerEntity } from "./entities/customer.entity";
|
|
8
|
+
|
|
9
|
+
@Collection({})
|
|
10
|
+
export class BillingEntity extends Map {
|
|
11
|
+
@Prop({ type: Schema.Types.Map, ref: () => BillingAddressEntity, default: new BillingAddressEntity() })
|
|
12
|
+
public address = new BillingAddressEntity();
|
|
13
|
+
|
|
14
|
+
@Prop({ type: Schema.Types.Map, ref: () => BillingCustomerEntity, default: new BillingCustomerEntity() })
|
|
15
|
+
public customer = new BillingCustomerEntity();
|
|
16
|
+
|
|
17
|
+
@Prop({ type: Schema.Types.String, enum: BillingMethod, required: true })
|
|
18
|
+
public method: BillingMethod;
|
|
19
|
+
|
|
20
|
+
@Prop({ type: Schema.Types.Array, default: [] })
|
|
21
|
+
public status: BillingStatusEntity[] = [];
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Type } from 'class-transformer';
|
|
2
|
+
import { IsEnum, IsNotEmptyObject, ValidateNested } from 'class-validator';
|
|
3
|
+
import 'reflect-metadata';
|
|
4
|
+
import { BillingMethod } from "./billing.types";
|
|
5
|
+
import { BillingCustomerValidator } from "./validators/customer.validator";
|
|
6
|
+
import { BillingAddressValidator } from "./validators/address.validator";
|
|
7
|
+
|
|
8
|
+
export class CreateBillingValidator {
|
|
9
|
+
@ValidateNested()
|
|
10
|
+
@Type(() => BillingCustomerValidator)
|
|
11
|
+
@IsNotEmptyObject()
|
|
12
|
+
public customer = new BillingCustomerValidator();
|
|
13
|
+
|
|
14
|
+
@ValidateNested()
|
|
15
|
+
@Type(() => BillingAddressValidator)
|
|
16
|
+
@IsNotEmptyObject()
|
|
17
|
+
public address = new BillingAddressValidator();
|
|
18
|
+
|
|
19
|
+
@IsEnum(BillingMethod)
|
|
20
|
+
public method: BillingMethod;
|
|
21
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Prop, Schema as Collection } from '@nestjs/mongoose';
|
|
2
|
+
import { Schema } from 'mongoose';
|
|
3
|
+
import { MetaAddress } from "../../../../../types";
|
|
4
|
+
|
|
5
|
+
@Collection()
|
|
6
|
+
export class BillingAddressEntity extends Map implements MetaAddress {
|
|
7
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
8
|
+
public country: string;
|
|
9
|
+
|
|
10
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
11
|
+
public code: string;
|
|
12
|
+
|
|
13
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
14
|
+
public street: string;
|
|
15
|
+
|
|
16
|
+
@Prop({ type: Schema.Types.String })
|
|
17
|
+
public number: string;
|
|
18
|
+
|
|
19
|
+
@Prop({ type: Schema.Types.String })
|
|
20
|
+
public complement: string;
|
|
21
|
+
|
|
22
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
23
|
+
public city: string;
|
|
24
|
+
|
|
25
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
26
|
+
public state: string;
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Prop, Schema as Collection } from '@nestjs/mongoose';
|
|
2
|
+
import { Schema } from 'mongoose';
|
|
3
|
+
|
|
4
|
+
@Collection({})
|
|
5
|
+
export class BillingCustomerEntity extends Map {
|
|
6
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
7
|
+
public name: string;
|
|
8
|
+
|
|
9
|
+
@Prop({ type: Schema.Types.String })
|
|
10
|
+
public email: string;
|
|
11
|
+
|
|
12
|
+
@Prop({ type: Schema.Types.String })
|
|
13
|
+
public phone: string;
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Prop } from '@nestjs/mongoose';
|
|
2
|
+
import { Schema as Collection } from '@nestjs/mongoose/dist/decorators/schema.decorator';
|
|
3
|
+
import { Schema } from 'mongoose';
|
|
4
|
+
import { BillingStatus } from "../billing.types";
|
|
5
|
+
|
|
6
|
+
@Collection({ timestamps: true })
|
|
7
|
+
export class BillingStatusEntity {
|
|
8
|
+
@Prop({ type: Schema.Types.String, enum: BillingStatus, required: true })
|
|
9
|
+
public name: BillingStatus;
|
|
10
|
+
|
|
11
|
+
@Prop({ type: Schema.Types.String })
|
|
12
|
+
public user: string;
|
|
13
|
+
|
|
14
|
+
@Prop({ type: Schema.Types.Date })
|
|
15
|
+
public date;
|
|
16
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { IsISO31661Alpha2, IsOptional, IsString } from 'class-validator';
|
|
2
|
+
import { MetaAddress } from "../../../../../types";
|
|
3
|
+
|
|
4
|
+
export class BillingAddressValidator implements MetaAddress {
|
|
5
|
+
@IsISO31661Alpha2()
|
|
6
|
+
public country = String();
|
|
7
|
+
|
|
8
|
+
@IsString()
|
|
9
|
+
public code = String();
|
|
10
|
+
|
|
11
|
+
@IsString()
|
|
12
|
+
public street = String();
|
|
13
|
+
|
|
14
|
+
@IsString()
|
|
15
|
+
@IsOptional()
|
|
16
|
+
public number = String();
|
|
17
|
+
|
|
18
|
+
@IsString()
|
|
19
|
+
@IsOptional()
|
|
20
|
+
public complement?: string = undefined;
|
|
21
|
+
|
|
22
|
+
@IsString()
|
|
23
|
+
public city = String();
|
|
24
|
+
|
|
25
|
+
@IsString()
|
|
26
|
+
public state = String();
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
|
2
|
+
|
|
3
|
+
export class BillingCustomerValidator {
|
|
4
|
+
@IsString()
|
|
5
|
+
@IsNotEmpty()
|
|
6
|
+
public name = String();
|
|
7
|
+
|
|
8
|
+
@IsEmail()
|
|
9
|
+
public email = String();
|
|
10
|
+
|
|
11
|
+
@IsString()
|
|
12
|
+
@IsOptional()
|
|
13
|
+
public phone?: string = undefined;
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Prop, Schema as Collection } from '@nestjs/mongoose';
|
|
2
|
+
import { Schema } from 'mongoose';
|
|
3
|
+
|
|
4
|
+
@Collection()
|
|
5
|
+
export class CustomerEntity extends Map {
|
|
6
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
7
|
+
public name: string;
|
|
8
|
+
|
|
9
|
+
@Prop({ type: Schema.Types.String })
|
|
10
|
+
public email: string;
|
|
11
|
+
|
|
12
|
+
@Prop({ type: Schema.Types.String })
|
|
13
|
+
public phone: string;
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
|
2
|
+
|
|
3
|
+
export class CustomerValidator {
|
|
4
|
+
@IsString()
|
|
5
|
+
@IsNotEmpty()
|
|
6
|
+
public name = String();
|
|
7
|
+
|
|
8
|
+
@IsEmail()
|
|
9
|
+
public email = String();
|
|
10
|
+
|
|
11
|
+
@IsString()
|
|
12
|
+
@IsOptional()
|
|
13
|
+
public phone?: string = undefined;
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Prop, Schema as Collection } from '@nestjs/mongoose';
|
|
2
|
+
import { Schema, Types } from 'mongoose';
|
|
3
|
+
import { AbstractEntity } from '../../../../abstract/abstract.entity';
|
|
4
|
+
import { ProductEntity } from '../../../inventory/products/product.entity';
|
|
5
|
+
|
|
6
|
+
@Collection({ timestamps: true, toJSON: { virtuals: true } })
|
|
7
|
+
export class ItemEntity extends AbstractEntity {
|
|
8
|
+
@Prop({ type: Schema.Types.Number, default: 1 })
|
|
9
|
+
public quantity: number;
|
|
10
|
+
|
|
11
|
+
@Prop({ type: Schema.Types.Number, default: 0 })
|
|
12
|
+
public price: number;
|
|
13
|
+
|
|
14
|
+
@Prop({ type: Schema.Types.Number, default: 0 })
|
|
15
|
+
public refund: number;
|
|
16
|
+
|
|
17
|
+
@Prop({ type: Types.ObjectId, ref: ProductEntity.$index, required: true })
|
|
18
|
+
public product: ProductEntity;
|
|
19
|
+
|
|
20
|
+
public readonly total: number
|
|
21
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SchemaFactory } from '@nestjs/mongoose';
|
|
2
|
+
import { ItemEntity } from './item.entity';
|
|
3
|
+
|
|
4
|
+
export const ItemSchema = SchemaFactory.createForClass(ItemEntity);
|
|
5
|
+
|
|
6
|
+
ItemSchema.virtual('total').get<ItemEntity>(function () {
|
|
7
|
+
return this.price * this.quantity
|
|
8
|
+
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Controller,
|
|
4
|
+
Delete,
|
|
5
|
+
Get,
|
|
6
|
+
HttpCode,
|
|
7
|
+
HttpStatus,
|
|
8
|
+
Inject,
|
|
9
|
+
Param,
|
|
10
|
+
ParseArrayPipe,
|
|
11
|
+
Patch,
|
|
12
|
+
Post,
|
|
13
|
+
Query,
|
|
14
|
+
} from '@nestjs/common';
|
|
15
|
+
import { ApiTags } from '@nestjs/swagger';
|
|
16
|
+
import { AbstractController } from '../../../abstract/abstract.controller';
|
|
17
|
+
import { FindValidator } from '../../../abstract/abstract.validator';
|
|
18
|
+
import { GetUser } from '../../../decorators/user.decorator';
|
|
19
|
+
import { OrderEntity } from './order.entity';
|
|
20
|
+
import { OrderRepository } from './order.repository';
|
|
21
|
+
import {
|
|
22
|
+
ChangeOrderStatusValidator,
|
|
23
|
+
CreateOrderValidator,
|
|
24
|
+
GetByStatus,
|
|
25
|
+
RefundOrderItemsValidator,
|
|
26
|
+
UpdateOrderValidator
|
|
27
|
+
} from './order.validator';
|
|
28
|
+
import { PopulateOptions } from "mongoose";
|
|
29
|
+
|
|
30
|
+
@Controller()
|
|
31
|
+
@ApiTags('orders')
|
|
32
|
+
export class OrderController extends AbstractController<OrderEntity> {
|
|
33
|
+
@Inject()
|
|
34
|
+
protected readonly $repository: OrderRepository;
|
|
35
|
+
|
|
36
|
+
@Get('/')
|
|
37
|
+
public async find(@Query() validator: FindValidator<OrderEntity>) {
|
|
38
|
+
return this.$repository.find(validator);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Get('/mine')
|
|
42
|
+
public async myOrders(@GetUser('sub') user: string, @Query() validator: FindValidator<OrderEntity>) {
|
|
43
|
+
return this.$repository.findByUser(user, validator);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Get('/:id')
|
|
47
|
+
public async read(@Param('id') id: string, @Query() validator: FindValidator<OrderEntity>) {
|
|
48
|
+
return this.$repository.read(id, validator.join);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Post('/')
|
|
52
|
+
@HttpCode(HttpStatus.CREATED)
|
|
53
|
+
public async create(@Body() validator: CreateOrderValidator) {
|
|
54
|
+
return this.$repository.create(validator);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@Patch('/:id')
|
|
58
|
+
public async update(@Param('id') id: string, @Body() validator: UpdateOrderValidator) {
|
|
59
|
+
return this.$repository.update(id, validator);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@Post('/:id/status')
|
|
63
|
+
public async changeStatus(@Param('id') id: string, @Body() validator: ChangeOrderStatusValidator) {
|
|
64
|
+
return this.$repository.changeStatus(id, validator);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Delete('/:id')
|
|
68
|
+
@HttpCode(HttpStatus.NO_CONTENT)
|
|
69
|
+
public async delete(@Param('id') id: string) {
|
|
70
|
+
return this.$repository.delete(id);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Post('/:id/refund')
|
|
74
|
+
public async refund(
|
|
75
|
+
@Param('id') id: string,
|
|
76
|
+
@Body(new ParseArrayPipe({ items: RefundOrderItemsValidator })) validator: RefundOrderItemsValidator[]) {
|
|
77
|
+
|
|
78
|
+
return this.$repository.refundItems(id, validator);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@Get('/status/:status')
|
|
82
|
+
public async status(
|
|
83
|
+
@Param() { status }: GetByStatus,
|
|
84
|
+
@Query() validator: FindValidator<OrderEntity>): Promise<OrderEntity[]> {
|
|
85
|
+
|
|
86
|
+
const query = this.$repository.$model
|
|
87
|
+
.find({ $expr: { $eq: [{ "$arrayElemAt": ["$status.name", -1] }, status] } })
|
|
88
|
+
|
|
89
|
+
validator.join && query.populate(validator.join as (PopulateOptions | string)[]);
|
|
90
|
+
|
|
91
|
+
return query.exec()
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Prop, Schema as Collection } from '@nestjs/mongoose';
|
|
2
|
+
import { Schema } from 'mongoose';
|
|
3
|
+
import { AbstractEntity } from '../../../abstract/abstract.entity';
|
|
4
|
+
import { BillingEntity } from './billing/billing.entity';
|
|
5
|
+
import { ItemEntity } from './item/item.entity';
|
|
6
|
+
import { ItemSchema } from './item/item.schema';
|
|
7
|
+
import { ShippingEntity } from './shipping/shipping.entity';
|
|
8
|
+
import { StatusEntity } from './status/status.entity';
|
|
9
|
+
import { ClientEntity } from "../clients/client.entity";
|
|
10
|
+
import { CustomerEntity } from "./customer/customer.entity";
|
|
11
|
+
|
|
12
|
+
@Collection({ timestamps: true, toJSON: { virtuals: true } })
|
|
13
|
+
export class OrderEntity extends AbstractEntity {
|
|
14
|
+
public static readonly $index = 'store_orders';
|
|
15
|
+
|
|
16
|
+
@Prop({ type: Schema.Types.Number, required: true, unique: true })
|
|
17
|
+
public number: number;
|
|
18
|
+
|
|
19
|
+
@Prop({ type: Schema.Types.Array, default: [] })
|
|
20
|
+
public status: StatusEntity[] = [];
|
|
21
|
+
|
|
22
|
+
@Prop({ type: [ItemSchema], default: [] })
|
|
23
|
+
public items: ItemEntity[] = [];
|
|
24
|
+
|
|
25
|
+
@Prop({ type: Schema.Types.ObjectId, ref: ClientEntity.$index })
|
|
26
|
+
public client?: ClientEntity;
|
|
27
|
+
|
|
28
|
+
@Prop({ type: Schema.Types.Map, ref: () => BillingEntity, default: new BillingEntity() })
|
|
29
|
+
public billing = new BillingEntity()
|
|
30
|
+
|
|
31
|
+
@Prop({ type: Schema.Types.Map, ref: () => ShippingEntity, default: new ShippingEntity() })
|
|
32
|
+
public shipping = new ShippingEntity();
|
|
33
|
+
|
|
34
|
+
@Prop({ type: Schema.Types.Map, ref: () => CustomerEntity, default: new CustomerEntity() })
|
|
35
|
+
public customer = new CustomerEntity();
|
|
36
|
+
|
|
37
|
+
@Prop({ type: Schema.Types.String, default: null })
|
|
38
|
+
public notes: string;
|
|
39
|
+
|
|
40
|
+
@Prop({ type: Schema.Types.String, required: true })
|
|
41
|
+
public createdBy: string;
|
|
42
|
+
|
|
43
|
+
public readonly fullNumber: string
|
|
44
|
+
public readonly total: number
|
|
45
|
+
public readonly subtotal: number
|
|
46
|
+
public readonly currentStatus: StatusEntity
|
|
47
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { AbsctractListener } from '../../../abstract/absctract.listener';
|
|
3
|
+
|
|
4
|
+
export enum OrderEvent {
|
|
5
|
+
PRE_CREATE = 'database.store.order.create.pre',
|
|
6
|
+
POST_CREATE = 'database.store.order.create.post',
|
|
7
|
+
|
|
8
|
+
PRE_UPDATE = 'database.store.order.update.pre',
|
|
9
|
+
POST_UPDATE = 'database.store.order.update.post',
|
|
10
|
+
|
|
11
|
+
PRE_STATUS_CHANGE = 'database.store.order.status_change.pre',
|
|
12
|
+
POST_STATUS_CHANGE = 'database.store.order.status_change.post',
|
|
13
|
+
|
|
14
|
+
PRE_DELETE = 'database.store.order.delete.pre',
|
|
15
|
+
POST_DELETE = 'database.store.order.delete.post',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Injectable()
|
|
19
|
+
export class OrderListener extends AbsctractListener {
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Module, ModuleMetadata } from '@nestjs/common';
|
|
2
|
+
import { AbstractRouter } from '../../../abstract/abstract.router';
|
|
3
|
+
import { OrderController } from './order.controller';
|
|
4
|
+
import { OrderListener } from './order.listener';
|
|
5
|
+
import { OrderRepository } from './order.repository';
|
|
6
|
+
|
|
7
|
+
export const metadata: ModuleMetadata = {
|
|
8
|
+
imports: [],
|
|
9
|
+
controllers: [OrderController],
|
|
10
|
+
providers: [OrderRepository, OrderListener],
|
|
11
|
+
exports: [OrderRepository],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
@Module(metadata)
|
|
15
|
+
export class OrderModule extends AbstractRouter {
|
|
16
|
+
public static readonly path = '/orders';
|
|
17
|
+
|
|
18
|
+
public static readonly module = OrderModule;
|
|
19
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { InjectModel } from '@nestjs/mongoose';
|
|
3
|
+
import { Model, Types } from 'mongoose';
|
|
4
|
+
import { AbstractRepository } from '../../../abstract/abstract.repository';
|
|
5
|
+
import { FindValidator } from '../../../abstract/abstract.validator';
|
|
6
|
+
import { AssetEntity } from '../../assets/asset.entity';
|
|
7
|
+
import { ProductEntity } from '../../inventory/products/product.entity';
|
|
8
|
+
import { ItemEntity } from './item/item.entity';
|
|
9
|
+
import { OrderEntity } from './order.entity';
|
|
10
|
+
import {
|
|
11
|
+
ChangeOrderStatusValidator,
|
|
12
|
+
CreateOrderValidator,
|
|
13
|
+
RefundOrderItemsValidator,
|
|
14
|
+
UpdateOrderValidator
|
|
15
|
+
} from './order.validator';
|
|
16
|
+
import { StatusType } from './status/status.validator';
|
|
17
|
+
import { ClientEntity } from "../clients/client.entity";
|
|
18
|
+
import { instanceToPlain } from "class-transformer";
|
|
19
|
+
import { BillingStatus } from "./billing/billing.types";
|
|
20
|
+
import { ShippingStatus } from "./shipping/shipping.types";
|
|
21
|
+
|
|
22
|
+
@Injectable()
|
|
23
|
+
export class OrderRepository extends AbstractRepository<OrderEntity> {
|
|
24
|
+
@InjectModel(OrderEntity.$index)
|
|
25
|
+
public readonly $model: Model<OrderEntity>;
|
|
26
|
+
|
|
27
|
+
@InjectModel(ProductEntity.$index)
|
|
28
|
+
public readonly $products: Model<ProductEntity>;
|
|
29
|
+
|
|
30
|
+
@InjectModel(AssetEntity.$index)
|
|
31
|
+
public readonly $assets: Model<AssetEntity>;
|
|
32
|
+
|
|
33
|
+
@InjectModel(ClientEntity.$index)
|
|
34
|
+
public readonly $clients: Model<ClientEntity>;
|
|
35
|
+
|
|
36
|
+
public async create(validator: CreateOrderValidator) {
|
|
37
|
+
const order = new this.$model();
|
|
38
|
+
|
|
39
|
+
const lastOrder = (await this.$model.find().sort({ _id: -1 }).limit(1).exec()).pop()
|
|
40
|
+
|
|
41
|
+
order.createdBy = super.$user?.sub
|
|
42
|
+
order.number = (lastOrder?.number || 0) + 1;
|
|
43
|
+
|
|
44
|
+
order.items = validator.items.map<any>((value) => ({ ...value, product: new Types.ObjectId(value.product) }));
|
|
45
|
+
order.notes = validator.notes;
|
|
46
|
+
|
|
47
|
+
// Client business
|
|
48
|
+
if (validator.client) {
|
|
49
|
+
order.client = new Types.ObjectId(validator.client) as any
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Customer business
|
|
53
|
+
if (validator.customer) {
|
|
54
|
+
order.customer.set('name', validator.customer.name)
|
|
55
|
+
order.customer.set('email', validator.customer.email)
|
|
56
|
+
order.customer.set('phone', validator.customer.phone)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Billing business
|
|
60
|
+
order.billing.set('customer', {
|
|
61
|
+
name: validator.billing.customer.name,
|
|
62
|
+
email: validator.billing.customer.email,
|
|
63
|
+
phone: validator.billing.customer.phone,
|
|
64
|
+
})
|
|
65
|
+
order.billing.set('method', validator.billing.method)
|
|
66
|
+
order.billing.set('status', [{
|
|
67
|
+
user: super.$user?.sub,
|
|
68
|
+
name: BillingStatus.UNPAID,
|
|
69
|
+
date: new Date(),
|
|
70
|
+
}])
|
|
71
|
+
|
|
72
|
+
order.billing.set('address', {
|
|
73
|
+
city: validator.billing.address.city,
|
|
74
|
+
code: validator.billing.address.code,
|
|
75
|
+
complement: validator.billing.address.complement,
|
|
76
|
+
country: validator.billing.address.country,
|
|
77
|
+
number: validator.billing.address.number,
|
|
78
|
+
state: validator.billing.address.state,
|
|
79
|
+
street: validator.billing.address.street,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Shipping business
|
|
83
|
+
order.shipping.set('method', validator.shipping.method)
|
|
84
|
+
order.shipping.set('price', validator.shipping.price)
|
|
85
|
+
order.shipping.set('status', [{
|
|
86
|
+
user: super.$user?.sub,
|
|
87
|
+
name: ShippingStatus.ORDERED,
|
|
88
|
+
date: new Date(),
|
|
89
|
+
}])
|
|
90
|
+
order.shipping.set('customer', {
|
|
91
|
+
name: validator.shipping.customer.name,
|
|
92
|
+
email: validator.shipping.customer.email,
|
|
93
|
+
phone: validator.shipping.customer.phone,
|
|
94
|
+
})
|
|
95
|
+
order.shipping.set('address', {
|
|
96
|
+
city: validator.shipping.address.city,
|
|
97
|
+
code: validator.shipping.address.code,
|
|
98
|
+
complement: validator.shipping.address.complement,
|
|
99
|
+
country: validator.shipping.address.country,
|
|
100
|
+
number: validator.shipping.address.number,
|
|
101
|
+
state: validator.shipping.address.state,
|
|
102
|
+
street: validator.shipping.address.street,
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
order.status = [{
|
|
106
|
+
user: super.$user?.sub,
|
|
107
|
+
name: StatusType.CREATED,
|
|
108
|
+
date: new Date(),
|
|
109
|
+
}];
|
|
110
|
+
|
|
111
|
+
await order.populate(['items.product']);
|
|
112
|
+
|
|
113
|
+
order.items = order.items.map(item => ({
|
|
114
|
+
...item,
|
|
115
|
+
price: item.product.price.get('sale')
|
|
116
|
+
})) as ItemEntity[];
|
|
117
|
+
|
|
118
|
+
await order.depopulate(['items.product']);
|
|
119
|
+
|
|
120
|
+
return super.$create(order);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public async read(id: string, poulate: FindValidator<OrderEntity>['join'] = []) {
|
|
124
|
+
return this.$model.findById(id).populate(poulate);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public delete(id: string): Promise<void> {
|
|
128
|
+
return super.$delete(id);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public update(id: string, validator: UpdateOrderValidator): Promise<OrderEntity> {
|
|
132
|
+
return super.$update(id, {
|
|
133
|
+
$set: instanceToPlain(validator)
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public changeStatus(id: string, validator: ChangeOrderStatusValidator) {
|
|
138
|
+
const query = {
|
|
139
|
+
$push: {
|
|
140
|
+
status: {
|
|
141
|
+
user: super.$user?.sub,
|
|
142
|
+
name: validator.status,
|
|
143
|
+
date: new Date(),
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return super.$update(id, query);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public async findByUser(userId: string, validator: FindValidator<OrderEntity>) {
|
|
152
|
+
validator.filters = { ...validator.filters, createdBy: userId };
|
|
153
|
+
|
|
154
|
+
return this.$find(validator);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public async findOneByUser(fullNumber: string, user: string) {
|
|
158
|
+
const [orderNumber] = fullNumber.split('-').reverse()
|
|
159
|
+
const number = Number(orderNumber)
|
|
160
|
+
|
|
161
|
+
return this.$find({
|
|
162
|
+
filters: {
|
|
163
|
+
user: { $eq: user },
|
|
164
|
+
number: { $eq: number }
|
|
165
|
+
},
|
|
166
|
+
join: [{ 'path': 'items', populate: [{ path: 'product', populate: ['files'] }] }],
|
|
167
|
+
limit: 1
|
|
168
|
+
})
|
|
169
|
+
.then(res => res.items.pop());
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public async refundItems(id: string, validators: RefundOrderItemsValidator[]) {
|
|
173
|
+
const order: OrderEntity = await this.read(id)
|
|
174
|
+
|
|
175
|
+
validators.map((refund) => {
|
|
176
|
+
const item = order.items.find(({ _id }) => _id.toString() === refund.item)
|
|
177
|
+
|
|
178
|
+
if (!item) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
item.refund = refund.quantity || 0
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
await order.save()
|
|
186
|
+
|
|
187
|
+
return order
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SchemaFactory } from '@nestjs/mongoose';
|
|
2
|
+
import { OrderEntity } from './order.entity';
|
|
3
|
+
|
|
4
|
+
export const OrderSchema = SchemaFactory.createForClass(OrderEntity);
|
|
5
|
+
|
|
6
|
+
OrderSchema.virtual('fullNumber').get<OrderEntity>(function () {
|
|
7
|
+
const createdAt = new Date(this.createdAt);
|
|
8
|
+
|
|
9
|
+
const year = `Y${createdAt.getFullYear().toString().slice(2)}`;
|
|
10
|
+
const month = `M${(createdAt.getMonth() + 1).toString().padStart(2, '0')}`;
|
|
11
|
+
const day = `D${createdAt.getDate().toString().padStart(2, '0')}`;
|
|
12
|
+
|
|
13
|
+
const date = `${year}${month}${day}`;
|
|
14
|
+
const number = this.number.toString().padStart(4, '0');
|
|
15
|
+
|
|
16
|
+
return `${date}-${number}`.toUpperCase();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
OrderSchema.virtual('total').get<OrderEntity>(function () {
|
|
20
|
+
const subtotal = this.items
|
|
21
|
+
.reduce((previous, current) => (previous + (current.price * current.quantity)), 0)
|
|
22
|
+
|
|
23
|
+
return subtotal + this.shipping.get('price')
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
OrderSchema.virtual('subtotal').get<OrderEntity>(function () {
|
|
27
|
+
return this.items
|
|
28
|
+
.reduce((previous, current) => (previous + (current.price * current.quantity)), 0)
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
OrderSchema.virtual('currentStatus').get<OrderEntity>(function () {
|
|
32
|
+
const [first] = this.status.reverse()
|
|
33
|
+
|
|
34
|
+
return first
|
|
35
|
+
})
|