@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.
Files changed (225) hide show
  1. package/.DS_Store +0 -0
  2. package/.bin/deploy.sh +9 -0
  3. package/.bin/package.sh +7 -0
  4. package/.docker/Dockerfile +21 -0
  5. package/.dockerignore +12 -0
  6. package/.env +21 -0
  7. package/.eslintignore +8 -0
  8. package/.eslintrc.js +35 -0
  9. package/.github/dependabot.yml +17 -0
  10. package/.github/semantic.yml +5 -0
  11. package/.github/workflows/pull_request.yml +35 -0
  12. package/.gitignore +42 -0
  13. package/.husky/.gitignore +1 -0
  14. package/.husky/commit-msg +5 -0
  15. package/.husky/common.sh +8 -0
  16. package/.husky/pre-commit +5 -0
  17. package/.husky/pre-push +4 -0
  18. package/.idea/.gitignore +5 -0
  19. package/.idea/api.iml +13 -0
  20. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  21. package/.idea/inspectionProfiles/Project_Default.xml +11 -0
  22. package/.idea/modules.xml +8 -0
  23. package/.idea/vcs.xml +12 -0
  24. package/.idea/workspace.xml +2320 -0
  25. package/.output/modules/sales/orders/order.entity.d.ts +1 -1
  26. package/.output/modules/sales/orders/order.validator.js +2 -3
  27. package/authCertificate.pem +19 -0
  28. package/cloudbuild.yaml +20 -0
  29. package/commitlint.config.js +3 -0
  30. package/jest.config.js +14 -0
  31. package/merkaly-api-0.2.4-6.tgz +0 -0
  32. package/nest-cli.json +9 -0
  33. package/package.json +8 -7
  34. package/serviceAccount.json +7 -0
  35. package/src/abstract/absctract.listener.ts +2 -0
  36. package/src/abstract/abstract.controller.ts +27 -0
  37. package/src/abstract/abstract.entity.ts +19 -0
  38. package/src/abstract/abstract.exception.ts +56 -0
  39. package/src/abstract/abstract.fixture.ts +7 -0
  40. package/src/abstract/abstract.migration.ts +13 -0
  41. package/src/abstract/abstract.repository.ts +79 -0
  42. package/src/abstract/abstract.router.ts +7 -0
  43. package/src/abstract/abstract.validator.ts +62 -0
  44. package/src/app.config.ts +57 -0
  45. package/src/app.console.ts +30 -0
  46. package/src/app.controller.ts +48 -0
  47. package/src/app.migration.ts +7 -0
  48. package/src/app.module.ts +92 -0
  49. package/src/app.strategy.ts +25 -0
  50. package/src/commands/assets.command.ts +38 -0
  51. package/src/commands/deploy.command.ts +6 -0
  52. package/src/commands/fixture.command.ts +11 -0
  53. package/src/commands/generate.command.ts +286 -0
  54. package/src/decorators/public.decorator.ts +5 -0
  55. package/src/decorators/user.decorator.ts +21 -0
  56. package/src/exceptions/missing-identity.exception.ts +11 -0
  57. package/src/exceptions/store-not-implemented.exception.ts +13 -0
  58. package/src/exceptions/store-not-recognized.exception.ts +11 -0
  59. package/src/guards/auth.guard.ts +43 -0
  60. package/src/guards/organization.guard.ts +39 -0
  61. package/src/interceptors/mongo.interceptor.ts +16 -0
  62. package/src/main.ts +37 -0
  63. package/src/middlewares/logger.middleware.ts +15 -0
  64. package/src/middlewares/organization.middleware.ts +76 -0
  65. package/src/migrations/1667226478717-product_price_enhance.ts +29 -0
  66. package/src/migrations/1667329249561-product_add_seo_code_dimension.ts +37 -0
  67. package/src/migrations/1667601099139-product_activve_and_hashtag.ts +35 -0
  68. package/src/migrations/1668136428972-content_banners-use-as-image.ts +56 -0
  69. package/src/migrations/1680483744321-order-billing-shipping-status.ts +32 -0
  70. package/src/modules/assets/asset.controller.ts +33 -0
  71. package/src/modules/assets/asset.entity.ts +26 -0
  72. package/src/modules/assets/asset.module.ts +21 -0
  73. package/src/modules/assets/asset.repository.ts +51 -0
  74. package/src/modules/assets/asset.schema.ts +4 -0
  75. package/src/modules/assets/asset.service.ts +41 -0
  76. package/src/modules/auth/auth.controller.ts +42 -0
  77. package/src/modules/auth/auth.module.ts +18 -0
  78. package/src/modules/auth/logout.ts +0 -0
  79. package/src/modules/command.module.ts +19 -0
  80. package/src/modules/content/banners/banner.controller.ts +56 -0
  81. package/src/modules/content/banners/banner.entity.ts +17 -0
  82. package/src/modules/content/banners/banner.fixture.ts +19 -0
  83. package/src/modules/content/banners/banner.listener.ts +6 -0
  84. package/src/modules/content/banners/banner.module.ts +21 -0
  85. package/src/modules/content/banners/banner.repository.ts +38 -0
  86. package/src/modules/content/banners/banner.schema.ts +4 -0
  87. package/src/modules/content/banners/banner.types.ts +7 -0
  88. package/src/modules/content/banners/banner.validator.ts +19 -0
  89. package/src/modules/content/content.module.ts +20 -0
  90. package/src/modules/content/pages/page.controller.ts +53 -0
  91. package/src/modules/content/pages/page.entity.ts +27 -0
  92. package/src/modules/content/pages/page.fixture.ts +19 -0
  93. package/src/modules/content/pages/page.listener.ts +6 -0
  94. package/src/modules/content/pages/page.module.ts +21 -0
  95. package/src/modules/content/pages/page.repository.ts +44 -0
  96. package/src/modules/content/pages/page.schema.ts +4 -0
  97. package/src/modules/content/pages/page.types.ts +9 -0
  98. package/src/modules/content/pages/page.validator.ts +29 -0
  99. package/src/modules/global.module.ts +70 -0
  100. package/src/modules/insight/controllers/address.controller.ts +29 -0
  101. package/src/modules/insight/controllers/order.controller.ts +70 -0
  102. package/src/modules/insight/controllers/products.controller.ts +18 -0
  103. package/src/modules/insight/insight.module.ts +24 -0
  104. package/src/modules/insight/validators/order.validator.ts +10 -0
  105. package/src/modules/inventory/brands/brand.controller.ts +59 -0
  106. package/src/modules/inventory/brands/brand.entity.ts +14 -0
  107. package/src/modules/inventory/brands/brand.exception.ts +9 -0
  108. package/src/modules/inventory/brands/brand.listener.ts +18 -0
  109. package/src/modules/inventory/brands/brand.module.ts +19 -0
  110. package/src/modules/inventory/brands/brand.repository.ts +39 -0
  111. package/src/modules/inventory/brands/brand.schema.ts +4 -0
  112. package/src/modules/inventory/brands/brand.validator.ts +23 -0
  113. package/src/modules/inventory/categories/category.controller.ts +59 -0
  114. package/src/modules/inventory/categories/category.entity.ts +21 -0
  115. package/src/modules/inventory/categories/category.exception.ts +9 -0
  116. package/src/modules/inventory/categories/category.fixture.ts +18 -0
  117. package/src/modules/inventory/categories/category.listener.ts +17 -0
  118. package/src/modules/inventory/categories/category.module.ts +19 -0
  119. package/src/modules/inventory/categories/category.repository.ts +40 -0
  120. package/src/modules/inventory/categories/category.schema.ts +4 -0
  121. package/src/modules/inventory/categories/category.validator.ts +30 -0
  122. package/src/modules/inventory/inventory.module.ts +22 -0
  123. package/src/modules/inventory/products/entities/code.entity.ts +15 -0
  124. package/src/modules/inventory/products/entities/dimension.entity.ts +18 -0
  125. package/src/modules/inventory/products/entities/price.entity.ts +12 -0
  126. package/src/modules/inventory/products/entities/seo.entity.ts +15 -0
  127. package/src/modules/inventory/products/product.controller.ts +59 -0
  128. package/src/modules/inventory/products/product.entity.ts +53 -0
  129. package/src/modules/inventory/products/product.exception.ts +9 -0
  130. package/src/modules/inventory/products/product.fixture.ts +19 -0
  131. package/src/modules/inventory/products/product.listener.ts +27 -0
  132. package/src/modules/inventory/products/product.module.ts +20 -0
  133. package/src/modules/inventory/products/product.repository.ts +108 -0
  134. package/src/modules/inventory/products/product.schema.ts +15 -0
  135. package/src/modules/inventory/products/product.validator.ts +71 -0
  136. package/src/modules/inventory/products/validators/code.validator.ts +15 -0
  137. package/src/modules/inventory/products/validators/dimension.validator.ts +19 -0
  138. package/src/modules/inventory/products/validators/price.validator.ts +10 -0
  139. package/src/modules/inventory/products/validators/seo.validator.ts +15 -0
  140. package/src/modules/inventory/properties/property.controller.ts +56 -0
  141. package/src/modules/inventory/properties/property.entity.ts +18 -0
  142. package/src/modules/inventory/properties/property.exception.ts +9 -0
  143. package/src/modules/inventory/properties/property.listener.ts +20 -0
  144. package/src/modules/inventory/properties/property.module.ts +21 -0
  145. package/src/modules/inventory/properties/property.repository.ts +23 -0
  146. package/src/modules/inventory/properties/property.schema.ts +4 -0
  147. package/src/modules/inventory/properties/property.validator.ts +27 -0
  148. package/src/modules/sales/clients/client.controller.ts +60 -0
  149. package/src/modules/sales/clients/client.entity.ts +25 -0
  150. package/src/modules/sales/clients/client.exception.ts +9 -0
  151. package/src/modules/sales/clients/client.listener.ts +20 -0
  152. package/src/modules/sales/clients/client.module.ts +19 -0
  153. package/src/modules/sales/clients/client.repository.ts +37 -0
  154. package/src/modules/sales/clients/client.schema.ts +4 -0
  155. package/src/modules/sales/clients/client.validator.ts +43 -0
  156. package/src/modules/sales/orders/billing/billing.entity.ts +22 -0
  157. package/src/modules/sales/orders/billing/billing.types.ts +10 -0
  158. package/src/modules/sales/orders/billing/billing.validator.ts +21 -0
  159. package/src/modules/sales/orders/billing/entities/address.entity.ts +27 -0
  160. package/src/modules/sales/orders/billing/entities/customer.entity.ts +14 -0
  161. package/src/modules/sales/orders/billing/entities/status.entity.ts +16 -0
  162. package/src/modules/sales/orders/billing/validators/address.validator.ts +28 -0
  163. package/src/modules/sales/orders/billing/validators/customer.validator.ts +14 -0
  164. package/src/modules/sales/orders/customer/customer.entity.ts +14 -0
  165. package/src/modules/sales/orders/customer/customer.validator.ts +14 -0
  166. package/src/modules/sales/orders/item/item.entity.ts +21 -0
  167. package/src/modules/sales/orders/item/item.schema.ts +8 -0
  168. package/src/modules/sales/orders/item/item.validator.ts +10 -0
  169. package/src/modules/sales/orders/order.controller.ts +93 -0
  170. package/src/modules/sales/orders/order.entity.ts +47 -0
  171. package/src/modules/sales/orders/order.listener.ts +20 -0
  172. package/src/modules/sales/orders/order.module.ts +19 -0
  173. package/src/modules/sales/orders/order.repository.ts +189 -0
  174. package/src/modules/sales/orders/order.schema.ts +35 -0
  175. package/src/modules/sales/orders/order.validator.ts +72 -0
  176. package/src/modules/sales/orders/shipping/entities/address.entity.ts +27 -0
  177. package/src/modules/sales/orders/shipping/entities/customer.entity.ts +14 -0
  178. package/src/modules/sales/orders/shipping/entities/status.entity.ts +16 -0
  179. package/src/modules/sales/orders/shipping/shipping.entity.ts +25 -0
  180. package/src/modules/sales/orders/shipping/shipping.types.ts +12 -0
  181. package/src/modules/sales/orders/shipping/shipping.validator.ts +25 -0
  182. package/src/modules/sales/orders/shipping/validators/address.validator.ts +28 -0
  183. package/src/modules/sales/orders/shipping/validators/customer.validator.ts +14 -0
  184. package/src/modules/sales/orders/status/status.entity.ts +16 -0
  185. package/src/modules/sales/orders/status/status.validator.ts +8 -0
  186. package/src/modules/sales/sales.module.ts +20 -0
  187. package/src/modules/setting/connections/connection.controller.ts +27 -0
  188. package/src/modules/setting/connections/connection.module.ts +17 -0
  189. package/src/modules/setting/connections/connection.validator.ts +15 -0
  190. package/src/modules/setting/layout/layout.controller.ts +34 -0
  191. package/src/modules/setting/layout/layout.entity.ts +13 -0
  192. package/src/modules/setting/layout/layout.listener.ts +7 -0
  193. package/src/modules/setting/layout/layout.module.ts +21 -0
  194. package/src/modules/setting/layout/layout.repository.ts +29 -0
  195. package/src/modules/setting/layout/layout.schema.ts +4 -0
  196. package/src/modules/setting/members/member.controller.ts +22 -0
  197. package/src/modules/setting/members/member.module.ts +17 -0
  198. package/src/modules/setting/members/member.validator.ts +3 -0
  199. package/src/modules/setting/organization/organization.controller.ts +33 -0
  200. package/src/modules/setting/organization/organization.entity.ts +27 -0
  201. package/src/modules/setting/organization/organization.listener.ts +46 -0
  202. package/src/modules/setting/organization/organization.module.ts +21 -0
  203. package/src/modules/setting/organization/organization.repository.ts +55 -0
  204. package/src/modules/setting/organization/organization.types.ts +65 -0
  205. package/src/modules/setting/organization/organization.validator.ts +56 -0
  206. package/src/modules/setting/setting.module.ts +23 -0
  207. package/src/modules/setting/theme/theme.controller.ts +34 -0
  208. package/src/modules/setting/theme/theme.entity.ts +13 -0
  209. package/src/modules/setting/theme/theme.listener.ts +6 -0
  210. package/src/modules/setting/theme/theme.module.ts +21 -0
  211. package/src/modules/setting/theme/theme.repository.ts +23 -0
  212. package/src/modules/setting/theme/theme.schema.ts +4 -0
  213. package/src/modules/users/user.controller.ts +75 -0
  214. package/src/modules/users/user.module.ts +20 -0
  215. package/src/modules/users/user.validator.ts +28 -0
  216. package/src/providers/auth0.provider.ts +36 -0
  217. package/src/providers/storage.provider.ts +22 -0
  218. package/src/services/auth0.service.ts +7 -0
  219. package/src/services/logger.service.ts +33 -0
  220. package/src/services/mongo.service.ts +44 -0
  221. package/src/services/storage.service.ts +39 -0
  222. package/src/types.ts +19 -0
  223. package/tsconfig.json +40 -0
  224. package/tsconfig.package.json +20 -0
  225. 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,10 @@
1
+ export enum BillingMethod {
2
+ CASH = 'CASH',
3
+ CARD = 'CARD',
4
+ TRANSFER = 'TRANSFER',
5
+ }
6
+
7
+ export enum BillingStatus {
8
+ UNPAID = 'UNPAID',
9
+ PAID = 'PAID',
10
+ }
@@ -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,10 @@
1
+ import { IsMongoId, IsNotEmpty, IsNumber } from 'class-validator';
2
+
3
+ export class CreateItemValidator {
4
+ @IsNumber()
5
+ @IsNotEmpty()
6
+ public quantity = 1;
7
+
8
+ @IsMongoId()
9
+ public product: string;
10
+ }
@@ -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
+ })