Skip to content

Commit

Permalink
feat: #841/generate product variants
Browse files Browse the repository at this point in the history
  • Loading branch information
tsvetelina-e-y committed Apr 23, 2020
1 parent 711519c commit b30fb04
Show file tree
Hide file tree
Showing 41 changed files with 588 additions and 56 deletions.
14 changes: 13 additions & 1 deletion apps/api/src/app/app.module.ts
Expand Up @@ -54,6 +54,8 @@ import { ProductModule } from './product/product.module';
import { IntegrationSettingModule } from './integration-setting/integration-setting.module';
import { IntegrationModule } from './integration/integration.module';
import { IntegrationMapModule } from './integration-map/integration-map.module';
import { ProductVariantPriceModule } from './product-variant-price/product-variant-price-module';
import { ProductVariantModule } from './product-variant/product-variant.module';

@Module({
imports: [
Expand Down Expand Up @@ -197,6 +199,14 @@ import { IntegrationMapModule } from './integration-map/integration-map.module';
{
path: '/product-types',
module: ProductTypesModule
},
{
path: '/product-variant-prices',
module: ProductVariantPriceModule
},
{
path: '/product-variants',
module: ProductVariantModule
}
]
}
Expand Down Expand Up @@ -261,7 +271,9 @@ import { IntegrationMapModule } from './integration-map/integration-map.module';
ProductModule,
IntegrationSettingModule,
IntegrationModule,
IntegrationMapModule
IntegrationMapModule,
ProductVariantPriceModule,
ProductVariantModule
],
controllers: [AppController],
providers: [AppService, SeedDataService],
Expand Down
13 changes: 13 additions & 0 deletions apps/api/src/app/product-option/product-option-module.ts
@@ -0,0 +1,13 @@
import { TypeOrmModule } from '@nestjs/typeorm';
import { Module } from '@nestjs/common';
import { ProductOption } from './product-option.entity';
import { ProductOptionService } from './product-option.service';
import { ProductOptionController } from './product-option.controller';

@Module({
imports: [TypeOrmModule.forFeature([ProductOption])],
controllers: [ProductOptionController],
providers: [ProductOptionService],
exports: [ProductOptionService]
})
export class ProductOptionModule {}
14 changes: 14 additions & 0 deletions apps/api/src/app/product-option/product-option.controller.ts
@@ -0,0 +1,14 @@
import { ApiTags } from '@nestjs/swagger';
import { CrudController } from '../core';
import { Controller } from '@nestjs/common';
import { ProductOption } from './product-option.entity';
import { ProductOptionService } from './product-option.service';

@ApiTags('Product-Options')
// @UseGuards(AuthGuard('jwt'))
@Controller()
export class ProductOptionController extends CrudController<ProductOption> {
constructor(private readonly productOptionService: ProductOptionService) {
super(productOptionService);
}
}
8 changes: 6 additions & 2 deletions apps/api/src/app/product-option/product-option.entity.ts
@@ -1,4 +1,4 @@
import { Entity, Column } from 'typeorm';
import { Entity, Column, ManyToOne, JoinColumn } from 'typeorm';
import { Base } from '../core/entities/base';
import { ProductOption as IProductOption } from '@gauzy/models';
import { ApiProperty } from '@nestjs/swagger';
Expand All @@ -17,6 +17,10 @@ export class ProductOption extends Base implements IProductOption {
@Column()
code: string;

// @ManyToOne(()=> Product, product => product.options)
@ManyToOne(
() => Product,
(product) => product.options
)
@JoinColumn()
product: Product;
}
Empty file.
21 changes: 21 additions & 0 deletions apps/api/src/app/product-option/product-option.service.ts
@@ -0,0 +1,21 @@
import { Injectable } from '@nestjs/common';
import { CrudService } from '../core';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ProductOption } from './product-option.entity';

@Injectable()
export class ProductOptionService extends CrudService<ProductOption> {
constructor(
@InjectRepository(ProductOption)
private readonly productOptionRepository: Repository<ProductOption>
) {
super(productOptionRepository);
}

async createBulk(
productOptionsInput: ProductOption[]
): Promise<ProductOption[]> {
return this.productOptionRepository.create(productOptionsInput);
}
}
18 changes: 18 additions & 0 deletions apps/api/src/app/product-settings/product-settings.controller.ts
@@ -0,0 +1,18 @@
import { ApiTags } from '@nestjs/swagger';
import { CrudController } from '../core';
import { Controller } from '@nestjs/common';
import { ProductVariantSettings } from './product-settings.entity';
import { ProductVariantSettingService } from './product-settings.service';

@ApiTags('Product-Variant-Price')
// @UseGuards(AuthGuard('jwt'))
@Controller()
export class ProductVariantSettingsController extends CrudController<
ProductVariantSettings
> {
constructor(
private readonly productVariantSettingService: ProductVariantSettingService
) {
super(productVariantSettingService);
}
}
6 changes: 5 additions & 1 deletion apps/api/src/app/product-settings/product-settings.entity.ts
@@ -1,7 +1,8 @@
import { Entity, Column } from 'typeorm';
import { Entity, Column, OneToOne } from 'typeorm';
import { Base } from '../core/entities/base';
import { ProductVariantSettings as IProductVariantSettings } from '@gauzy/models';
import { ApiPropertyOptional } from '@nestjs/swagger';
import { ProductVariant } from '../product-variant/product-variant.entity';

@Entity('product_variant_settings')
export class ProductVariantSettings extends Base
Expand Down Expand Up @@ -37,4 +38,7 @@ export class ProductVariantSettings extends Base
@ApiPropertyOptional({ type: Boolean })
@Column({ default: false })
trackInventory: boolean;

@OneToOne(() => ProductVariant)
productVariant: ProductVariant;
}
13 changes: 13 additions & 0 deletions apps/api/src/app/product-settings/product-settings.module.ts
@@ -0,0 +1,13 @@
import { TypeOrmModule } from '@nestjs/typeorm';
import { Module } from '@nestjs/common';
import { ProductVariantSettings } from './product-settings.entity';
import { ProductVariantSettingService } from './product-settings.service';
import { ProductVariantSettingsController } from './product-settings.controller';

@Module({
imports: [TypeOrmModule.forFeature([ProductVariantSettings])],
controllers: [ProductVariantSettingsController],
providers: [ProductVariantSettingService],
exports: [ProductVariantSettingService]
})
export class ProductVariantSettingsModule {}
Empty file.
26 changes: 26 additions & 0 deletions apps/api/src/app/product-settings/product-settings.service.ts
@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CrudService } from '../core';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ProductVariantSettings } from './product-settings.entity';

@Injectable()
export class ProductVariantSettingService extends CrudService<
ProductVariantSettings
> {
constructor(
@InjectRepository(ProductVariantSettings)
private readonly productVariantSettingsRepository: Repository<
ProductVariantSettings
>
) {
super(productVariantSettingsRepository);
}

async createDefaultVariantSettings(): Promise<ProductVariantSettings> {
const newProductVariantSettings = new ProductVariantSettings();
return this.productVariantSettingsRepository.save(
newProductVariantSettings
);
}
}
@@ -0,0 +1,13 @@
import { TypeOrmModule } from '@nestjs/typeorm';
import { Module } from '@nestjs/common';
import { ProductVariantPrice } from './product-variant-price.entity';
import { ProductVariantPriceController } from './product-variant-price.controller';
import { ProductVariantPriceService } from './product-variant-price.service';

@Module({
imports: [TypeOrmModule.forFeature([ProductVariantPrice])],
controllers: [ProductVariantPriceController],
providers: [ProductVariantPriceService],
exports: [ProductVariantPriceService]
})
export class ProductVariantPriceModule {}
@@ -0,0 +1,18 @@
import { ApiTags } from '@nestjs/swagger';
import { CrudController } from '../core';
import { Controller } from '@nestjs/common';
import { ProductVariantPrice } from './product-variant-price.entity';
import { ProductVariantPriceService } from './product-variant-price.service';

@ApiTags('Product-Variant-Price')
// @UseGuards(AuthGuard('jwt'))
@Controller()
export class ProductVariantPriceController extends CrudController<
ProductVariantPrice
> {
constructor(
private readonly productVariantPriceService: ProductVariantPriceService
) {
super(productVariantPriceService);
}
}
Expand Up @@ -12,7 +12,7 @@ import { ProductVariant } from '../product-variant/product-variant.entity';
export class ProductVariantPrice extends Base implements IProductVariantPrice {
@ApiProperty({ type: Number })
@IsNumber()
@Column()
@Column({ default: 0 })
unitCost: number;

@ApiProperty({ type: String, enum: CurrenciesEnum })
Expand All @@ -22,7 +22,7 @@ export class ProductVariantPrice extends Base implements IProductVariantPrice {

@ApiProperty({ type: Number })
@IsNumber()
@Column()
@Column({ default: 0 })
retailPrice: number;

@ApiProperty({ type: String, enum: CurrenciesEnum })
Expand Down
Empty file.
@@ -0,0 +1,29 @@
import { Injectable } from '@nestjs/common';
import { CrudService } from '../core';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ProductVariantPrice } from './product-variant-price.entity';
import { CurrenciesEnum } from '@gauzy/models';

@Injectable()
export class ProductVariantPriceService extends CrudService<
ProductVariantPrice
> {
constructor(
@InjectRepository(ProductVariantPrice)
private readonly productVariantPriceRepository: Repository<
ProductVariantPrice
>
) {
super(productVariantPriceRepository);
}

async createDefaultProductVariantPrice(): Promise<ProductVariantPrice> {
const newProductVariantPrice = new ProductVariantPrice();

newProductVariantPrice.retailPriceCurrency = CurrenciesEnum.BGN;
newProductVariantPrice.unitCostCurrency = CurrenciesEnum.BGN;

return this.productVariantPriceRepository.save(newProductVariantPrice);
}
}
3 changes: 3 additions & 0 deletions apps/api/src/app/product-variant/commands/handlers/index.ts
@@ -0,0 +1,3 @@
import { ProductVariantCreateHandler } from './product-variant.create.handler';

export const CommandHandlers = [ProductVariantCreateHandler];
@@ -0,0 +1,45 @@
import { ICommandHandler, CommandHandler } from '@nestjs/cqrs';
import { ProductVariant } from '../../product-variant.entity';
import { ProductVariantCreateCommand } from '../product-variant.create.command';
import { ProductVariantService } from '../../product-variant.service';
import { ProductVariantPriceService } from '../../../product-variant-price/product-variant-price.service';
import { ProductVariantSettingService } from '../../../product-settings/product-settings.service';

@CommandHandler(ProductVariantCreateCommand)
export class ProductVariantCreateHandler
implements ICommandHandler<ProductVariantCreateCommand> {
constructor(
private productVariantService: ProductVariantService,
private productVariantPriceService: ProductVariantPriceService,
private productVariantSettingsService: ProductVariantSettingService
) {}

public async execute(
command?: ProductVariantCreateCommand
): Promise<ProductVariant[]> {
const { productInput } = command;

const arrVariants = [];

for await (const productOption of productInput.options) {
const newProductVariant = new ProductVariant();

//tstodo
newProductVariant.billingInvoicingPolicy = 'policy';
newProductVariant.internalReference =
productOption.name + productOption.code;

newProductVariant.settings = await this.productVariantSettingsService.createDefaultVariantSettings();
newProductVariant.price = await this.productVariantPriceService.createDefaultProductVariantPrice();
newProductVariant.product = productInput;

arrVariants.push(
await this.productVariantService.createVariant(
newProductVariant
)
);
}

return arrVariants;
}
}
1 change: 1 addition & 0 deletions apps/api/src/app/product-variant/commands/index.ts
@@ -0,0 +1 @@
export { ProductVariantCreateCommand } from './product-variant.create.command';
@@ -0,0 +1,8 @@
import { ICommand } from '@nestjs/cqrs';
import { Product } from '../../product/product.entity';

export class ProductVariantCreateCommand implements ICommand {
static readonly type = '[ProductVariant] Register';

constructor(public readonly productInput: Product) {}
}
32 changes: 29 additions & 3 deletions apps/api/src/app/product-variant/product-variant.controller.ts
@@ -1,13 +1,39 @@
import { Controller } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { Controller, HttpStatus, Post, Body } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { CrudController } from '../core';
import { ProductVariant } from './product-variant.entity';
import { ProductVariantService } from './product-variant.service';
import { ProductVariantCreateCommand } from './commands';
import { CommandBus } from '@nestjs/cqrs';
import { Product } from '../product/product.entity';

@ApiTags('ProductVariant')
@Controller()
export class ProductVariantController extends CrudController<ProductVariant> {
constructor(private readonly productVariantService: ProductVariantService) {
constructor(
private readonly productVariantService: ProductVariantService,
private readonly commandBus: CommandBus
) {
super(productVariantService);
}

@ApiOperation({ summary: 'Create product variants' })
@ApiResponse({
status: HttpStatus.CREATED,
description:
'These records have been successfully created.' /*, type: T*/
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description:
'Invalid input, The response body may contain clues as to what went wrong'
})
// @UseGuards(PermissionGuard)
@Post('/create-variants')
async createProductVariants(
@Body() entity: Product,
...options: any[]
): Promise<ProductVariant[]> {
return this.commandBus.execute(new ProductVariantCreateCommand(entity));
}
}

0 comments on commit b30fb04

Please sign in to comment.