[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/base/base.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Repository } from 'typeorm';
import { HttpStatus } from '@nestjs/common';
import { IBaseService } from './base-service.interface';
import { BaseEntity } from './base.entity';
import { PaginationDto } from './paginator/dto/pagination.dto';
import { PaginationService } from './paginator';
import { ApiResponse } from '../shared/responses';

export class BaseService<T extends BaseEntity> implements IBaseService<T> {
  private readonly paginationService: PaginationService<T>;

  constructor(private readonly genericRepository: Repository<T>) {
    this.paginationService = new PaginationService<T>();
  }

  get(query: string): Promise<T> {
    try {
      return this.genericRepository.findOne(query);
    } catch {
      throw ApiResponse.error('errors.bad_gateway');
    }
  }

  getAll(paginationDto?: PaginationDto): Promise<any> {
    try {
      return this.paginate(paginationDto?.limit, paginationDto?.page);
    } catch {
      throw ApiResponse.error('errors.bad_gateway');
    }
  }

  create(data: any): Promise<any> {
    try {
      return new Promise<any>((resolve, reject) => {
        delete data.id;
        delete data._id;
        this.genericRepository
          .save(data)
          .then((created) => resolve(created))
          .catch(() => reject(ApiResponse.error('errors.internal_error')));
      });
    } catch {
      throw ApiResponse.error('errors.bad_gateway');
    }
  }

  update(query: string, data: any, user?: any): Promise<any> {
    try {
      return new Promise<any>((resolve, reject) => {
        this.genericRepository
          .findOneOrFail(query)
          .then((responseGet: any) => {
            try {
              if (user && user.email !== responseGet.email)
                reject(ApiResponse.error('errors.forbidden'));
              else {
                this.genericRepository
                  .update(responseGet.id, data)
                  .then(() => {
                    Object.assign(responseGet, data);
                    resolve(
                      ApiResponse.send(
                        'responses.resource_updated',
                        responseGet,
                      ),
                    );
                  })
                  .catch((e) => {
                    console.log(e);
                    reject(ApiResponse.error('errors.internal_error'));
                  });
              }
            } catch {
              reject(ApiResponse.error('errors.internal_error'));
            }
          })
          .catch(() =>
            reject(
              ApiResponse.error('errors.not_found', {}, HttpStatus.NOT_FOUND),
            ),
          );
      });
    } catch {
      throw ApiResponse.error('errors.bad_gateway');
    }
  }

  delete(query: string, user?: any): Promise<any> {
    try {
      return new Promise<any>((resolve, reject) => {
        this.genericRepository
          .findOneOrFail(query)
          .then((responseGet: any) => {
            try {
              if (user && user.email !== responseGet.email)
                reject(ApiResponse.error('errors.forbidden'));
              else {
                this.genericRepository
                  .delete(responseGet.id)
                  .then(() => {
                    resolve(
                      ApiResponse.send(
                        'responses.resource_deleted',
                        responseGet,
                      ),
                    );
                  })
                  .catch(() =>
                    reject(ApiResponse.error('errors.internal_error')),
                  );
              }
            } catch {
              reject(reject(ApiResponse.error('errors.internal_error')));
            }
          })
          .catch(() =>
            reject(
              ApiResponse.error('errors.not_found', {}, HttpStatus.NOT_FOUND),
            ),
          );
      });
    } catch {
      throw ApiResponse.error('errors.bad_gateway');
    }
  }

  createOrUpdate(query: string, data: any): Promise<any> {
    try {
      return this.update(query, data).catch(() => {
        return this.create(data).then((response) => {
          return ApiResponse.send(
            'responses.resource_created_updated',
            response,
          );
        });
      });
    } catch {
      throw ApiResponse.error('errors.bad_gateway');
    }
  }

  getAllByQuery(query: unknown): Promise<any> {
    try {
      return this.genericRepository.find(query);
    } catch {
      throw ApiResponse.error('errors.bad_gateway');
    }
  }

  paginate(limit = 10, page = 1, query?: unknown): Promise<any> {
    return this.paginationService.paginate(
      limit,
      page,
      query,
      this.genericRepository,
    );
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/base/base.entity.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Entity, ObjectIdColumn } from 'typeorm';

@Entity()
export class BaseEntity {
  /*id field*/
  //validations
  //entity assignations
  @ObjectIdColumn()
  //field
  id: string;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/base/base.controller.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  Get,
  Post,
  Delete,
  Put,
  Body,
  Query,
  Controller,
  Param,
  Inject,
} from '@nestjs/common';
import { Type } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { IBaseService } from './base-service.interface';
import { BaseEntity } from './base.entity';
import { PaginationDto } from './paginator/dto/pagination.dto';
import { PaginationResponse } from './paginator';
import { GeneralResponse } from '../shared/responses/general-response';
import { ExtendTypes } from './base-inheritance/extends-types.enum';
import { DecoratorExtendTypeSelector } from './base-inheritance/decorators-extends';
import { ExtendTypeSelector } from './base-inheritance/extend-type-selector';
import { BaseOptionsA, BaseOptionsB } from './base-options.interface';
import { DecoratorAssing } from './base-inheritance/decorators-assing';
import { IBaseController } from './base-controller.interface';

export function BaseController<
  T extends BaseEntity,
  K extends keyof IBaseService<T>,
>(
  Entity: Type<T>,
  _options?: BaseOptionsA<K, Type<T>> | BaseOptionsB<K, Type<T>>,
) {
  const options: any = _options;
  const type = options?.omit
    ? ExtendTypes.omit
    : options?.pick
    ? ExtendTypes.pick
    : null;
  const methods = options?.omit ? options.omit : options?.pick;
  const decorators = options?.decorators;
  const ValidateDecorator = DecoratorExtendTypeSelector(type);
  const ExtendType = ExtendTypeSelector(type);
  const PartialEntity = options?.partialEntity ? options.partialEntity : Entity;

  @Controller()
  abstract class BaseController implements IBaseController<T> {
    constructor(
      @Inject(REQUEST) protected readonly request: any,
      private readonly IBaseService: IBaseService<T>,
    ) {}
    update(query: any, data: Partial<T>): Promise<GeneralResponse> {
      throw new Error('Method not implemented.');
    }

    @ValidateDecorator(Get(`/:id`), methods, 'get')
    @DecoratorAssing(decorators, 'get')
    async get(@Param('id') id: string): Promise<T> {
      return this.IBaseService.get(id);
    }

    @ValidateDecorator(Get(), methods, 'getAll')
    @DecoratorAssing(decorators, 'getAll')
    async getAll(
      @Query() paginationDto: PaginationDto,
    ): Promise<PaginationResponse<T>> {
      return this.IBaseService.getAll(paginationDto);
    }

    @ValidateDecorator(Post(), methods, 'create')
    @DecoratorAssing(decorators, 'create')
    //@ts-ignore
    async create(@Body() entity: Entity): Promise<T> {
      // TODO: Remove it, when it is implemented in the front
      const data = entity;
      if (data.email) {
        data.email = data.email.toLowerCase();
      }

      return this.IBaseService.create(data);
    }

    @ValidateDecorator(Delete(`/:id`), methods, 'delete')
    @DecoratorAssing(decorators, 'delete')
    async delete(@Param('id') id: string): Promise<GeneralResponse> {
      return this.IBaseService.delete(id, this.request.user);
    }

    /*@ValidateDecorator(Put(), methods, 'update')
    @DecoratorAssing(decorators, 'update')
    async update(
      @Body() entity: PartialEntity,
      @Body('id') id: string,
    ): Promise<GeneralResponse> {
      return this.IBaseService.update(id, entity, this.request.user);
    }*/
  }
  const controller = ExtendType(BaseController, methods);
  return <Type<typeof controller>>controller;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/oms.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpService } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { OrdersVTEXService } from '../vtex/orders/orders.service';
import { OmsService } from './oms.service';

const HttpServiceProvider = {
  provide: HttpService,
  useFactory: () => ({}),
};

const OrdersVTEXServiceProvider = {
  provide: OrdersVTEXService,
  useFactory: () => ({}),
};

describe('OmsService', () => {
  let service: OmsService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [OmsService, HttpServiceProvider, OrdersVTEXServiceProvider],
    }).compile();

    service = module.get<OmsService>(OmsService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/oms.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderContext } from '../../typings/OrderContext';
import { OmsServices } from './types/oms.types';

export abstract class Oms {
  constructor(protected ctx: OrderContext, protected services: OmsServices) {}
  abstract prepare(): Promise<void>;

  abstract createOrder(): Promise<void>;

  abstract onProcessTransaction(): Promise<void>;

  async run() {
    await this.prepare();
    await this.createOrder();
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/oms.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Module } from '@nestjs/common';
import { VtexModule } from '../vtex/vtex.module';
import { OmsService } from './oms.service';

@Module({
  imports: [VtexModule],
  providers: [OmsService],
  exports: [OmsService],
})
export class OmsModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/oms.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderContext } from '../../typings/OrderContext';
import { Injectable } from '@nestjs/common';
import { OrdersVTEXService } from '../vtex/orders/orders.service';
import { NoopOms } from './noop';
import { Oms } from './oms';
import { OmsName, OmsServices } from './types/oms.types';
import { VtexOms } from './vtex';

@Injectable()
export class OmsService {
  private services: OmsServices;
  constructor(vtexService: OrdersVTEXService) {
    this.services = {
      vtexService,
    };
  }
  createOms(oms: string, ctx: OrderContext): Oms {
    switch (oms) {
      case OmsName.VTEX:
        return new VtexOms(ctx, this.services);
      case OmsName.NOOP:
        return new NoopOms(ctx, this.services);
      default:
        break;
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/health/health.controller.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Test, TestingModule } from '@nestjs/testing';
import { HealthController } from './health.controller';

describe('HealthController', () => {
  let controller: HealthController;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [HealthController],
    }).compile();

    controller = module.get<HealthController>(HealthController);
  });

  it('should be defined', () => {
    expect(controller).toBeDefined();
  });

  it('should return ok', () => {
    expect(controller.health()).toBe('ok');
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/health/health.controller.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Controller, Get } from '@nestjs/common';

@Controller('health')
export class HealthController {
  @Get(`/`)
  health(): string {
    return 'ok ci/cd';
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/vtex.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpModule, Module } from '@nestjs/common';
import { OrdersVTEXService } from './orders/orders.service';
import { ProfileSystemVTEXService } from './profile-system/profile-system.service';
import { AccountsModule } from '../accounts/accounts.module';
import { CheckoutVTEXService } from './orders/checkout/checkout.service';
import { CartVTEXService } from './orders/cart/cart.service';
import { PaymentVTEXService } from './orders/payment/payment.service';

@Module({
  imports: [HttpModule, AccountsModule],
  providers: [
    OrdersVTEXService,
    ProfileSystemVTEXService,
    CheckoutVTEXService,
    CartVTEXService,
    PaymentVTEXService,
  ],
  exports: [OrdersVTEXService, ProfileSystemVTEXService],
})
export class VtexModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/common/common.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Global, HttpModule, Module } from '@nestjs/common';
import { AwsService } from './aws/aws.service';
import { MailerService } from './mailer/mailer.service';
import { SMSService } from './sms/sms.service';
import { CommunicationModule } from './communication/communication.module';

@Global()
@Module({
  imports: [HttpModule, CommunicationModule],
  providers: [AwsService, MailerService, SMSService],
  exports: [AwsService, SMSService, MailerService],
})
export class CommonModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/accounts/accounts.controller.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
import { AccountsService } from './accounts.service';
import { CreateAccountDto } from './dtos/createAccount.dto';

@Controller('accounts')
export class AccountsController {
  constructor(private accountsService: AccountsService) {}

  @Post()
  save(@Body() createAccountDto: CreateAccountDto) {
    return this.accountsService.save(createAccountDto);
  }

  @Get()
  findByAccount(@Query('an') an: string) {
    return this.accountsService.get({ account: an });
  }

  @Post('toggleGoogleAnalytics')
  toggleGoogleAnalytics(@Query('an') an: string) {
    return this.accountsService.toggleGoogleAnalytics(an);
  }

  @Get('storefront')
  getStoreFrontSettings(@Query('an') account: string) {
    return this.accountsService.getStoreFrontSettings(account);
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/accounts/accounts.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { InjectModel } from 'nestjs-dynamoose';
import { CreateAccountDto } from './dtos/createAccount.dto';
import { NotFoundException } from '../../shared/exceptions/not-found-exception';
import { PaymentMethodsService } from './payment-methods/payment-methods.service';
import { Account, AccountDoc, AccountModel } from './schemas/account.schema';
import { StylesSchema, TextButton } from './styles/utils/stylesBase';
import { UploadCSS } from './styles/uploadCssToS3';
import { HabeasData } from './habeasData/schemas/habeasdata.schema';
import { HabeasDataService } from './habeasData/habeasData.service';

@Injectable()
export class AccountsService {
  constructor(
    @InjectModel(Account.name)
    @Inject(forwardRef(() => PaymentMethodsService))
    @Inject(HabeasData.name)
    private accountModel: AccountModel,
    private habeasDataService: HabeasDataService,
    private paymentMethods: PaymentMethodsService,
    private uploadCSS: UploadCSS,
  ) {}
  async save(accountDto: CreateAccountDto) {
    const existAccount = await this.accountModel
      .findOne({ account: accountDto.account })
      .exec();

    if (existAccount) {
      existAccount.set({
        paymentMethodId: accountDto.paymentMethodId,
        cvcRequired:
          accountDto.cvcRequired === true || accountDto.cvcRequired === false
            ? accountDto.cvcRequired
            : existAccount.cvcRequired,
        buttonMessage:
          accountDto.buttonMessage || accountDto.buttonMessage === ''
            ? accountDto.buttonMessage
            : existAccount.buttonMessage,
        visualization: accountDto.visualization || existAccount.visualization,
      });
      return existAccount.save();
    } else {
      const account = this.accountModel.build({
        account: accountDto.account,
        cvcRequired: accountDto.cvcRequired,
        paymentMethodId: accountDto.paymentMethodId,
        visualization: accountDto.visualization,
        buttonMessage: accountDto.buttonMessage,
        buttonText: TextButton,
        styles: JSON.stringify(StylesSchema),
        createdAt: Date.now(),
      });

      await this.uploadCSS.uploadFile(accountDto.account, StylesSchema);
      return await account.save();
    }
  }

  async toggleGoogleAnalytics(an: string) {
    const account = await this.accountModel.findOne({ account: an }).exec();

    if (!account) {
      throw new NotFoundException();
    }

    account.set({
      hasGoogleAnalytics: !account.hasGoogleAnalytics,
    });

    return account.save();
  }

  async get(query: Partial<AccountDoc>) {
    const account = await this.accountModel.findOne(query).exec();

    if (!account) {
      throw new NotFoundException();
    }

    let isConfigured = true;
    const pms = await this.paymentMethods.findByAccount(query.account);
    if (pms.count > 0 && isConfigured) {
      const resultado = pms.find((pm) => pm.isActive === true);
      if (!resultado) isConfigured = false;
    } else {
      isConfigured = false;
    }

    return {
      ...account,
      isConfigured,
    } as AccountDoc;
  }

  async getMany(query) {
    return this.accountModel.scan(query).exec();
  }

  async getStoreFrontSettings(an: string) {
    const account = await this.accountModel.findOne({ account: an }).exec();

    const { url, version } = await this.habeasDataService.getByActiveState();

    if (!account) {
      throw new NotFoundException();
    }

    let isConfigured = true;
    const pms = await this.paymentMethods.findByAccount(an);
    if (pms.count > 0 && isConfigured) {
      const resultado = pms.find((pm) => pm.isActive === true);
      if (!resultado) isConfigured = false;
    } else {
      isConfigured = false;
    }

    return {
      cvcRequired: account.cvcRequired,
      paymentSystem: account.paymentMethodId,
      visualization: account.visualization,
      buttonMessage: account.buttonMessage,
      hasGoogleAnalytics: account.hasGoogleAnalytics || false,
      isTracking: account.isTracking || false,
      trackingKey: account.trackingKey || null,
      isConfigured: isConfigured,
      PaymentMethod: pms,
      styles: account.styles ? account.styles : JSON.stringify(StylesSchema),
      text: account.buttonText,
      habeasDataInformation: {
        url,
        version,
      },
      additionalData: account.additionalData,
    };
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/accounts/accounts.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Module } from '@nestjs/common';

import { AcceptanceHabeasData } from './habeasData/schemas/acceptanceHabeasData.schema';
import { AcceptanceHabeasDataController } from './habeasData/acceptanceHabeasData/acceptanceHabeasData.controller';
import { AcceptanceHabeasDataService } from './habeasData/acceptanceHabeasData/acceptanceHabeasData.service';
import { Account } from './schemas/account.schema';
import { AccountLink } from './accounts-links/schemas/account-link.schema';
import { AccountsController } from './accounts.controller';
import { AccountsLinksController } from './accounts-links/accounts-links.controller';
import { AccountsLinksService } from './accounts-links/accounts-links.service';
import { AccountsService } from './accounts.service';
import { CustomDynamooseModule } from 'src/shared/utils/dynamoose-module';
import { HabeasData } from './habeasData/schemas/habeasdata.schema';
import { HabeasDataController } from './habeasData/habeasData.controller';
import { HabeasDataService } from './habeasData/habeasData.service';
import { PaymentMethod } from './payment-methods/schemas/payment-method.schema';
import { PaymentMethodsController } from './payment-methods/payment-methods.controller';
import { PaymentMethodsService } from './payment-methods/payment-methods.service';
import { StylesController } from './styles/styles.controller';
import { StylesService } from './styles/styles.service';
import { UploadCSS } from './styles/uploadCssToS3';

@Module({
  imports: [
    CustomDynamooseModule.forFeature([
      AcceptanceHabeasData,
      Account,
      AccountLink,
      HabeasData,
      PaymentMethod,
    ]),
  ],
  controllers: [
    AcceptanceHabeasDataController,
    AccountsController,
    AccountsLinksController,
    HabeasDataController,
    PaymentMethodsController,
    StylesController,
  ],
  providers: [
    AcceptanceHabeasDataService,
    AccountsLinksService,
    AccountsService,
    HabeasDataService,
    PaymentMethodsService,
    StylesService,
    UploadCSS,
  ],
  exports: [
    AcceptanceHabeasDataService,
    AccountsLinksService,
    AccountsService,
    HabeasDataService,
    StylesService,
  ],
})
export class AccountsModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/accounts/accounts.controller.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Provider } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { validate } from 'class-validator';
import { AccountsController } from './accounts.controller';
import { AccountsService } from './accounts.service';
import { CreateAccountDto } from './dtos/createAccount.dto';
import { createMock } from '@golevelup/ts-jest';
import { Account } from './schemas/account.schema';

describe('AccountsController', () => {
  let controller: AccountsController;
  let service: AccountsService;

  beforeEach(async () => {
    const ApiServiceProvider: Provider = {
      provide: AccountsService,
      useValue: {
        save: jest
          .fn()
          .mockImplementation((createAccountDto: CreateAccountDto) =>
            Promise.resolve({ _id: 'a uuid', ...createAccountDto }),
          ),
        get: jest
          .fn()
          .mockImplementation(({ account }: { account: string }) => {
            return Promise.resolve({
              _id: 'a uuid',
              account,
              cvcRequired: false,
              paymentMethodId: '201',
              visualization: [],
            });
          }),
        getStoreFrontSettings: jest.fn().mockImplementation(() =>
          Promise.resolve({
            cvcRequired: false,
            paymentMethodId: '201',
            visualization: [],
          }),
        ),
      },
    };

    const module: TestingModule = await Test.createTestingModule({
      controllers: [AccountsController],
      providers: [ApiServiceProvider],
    }).compile();

    controller = module.get<AccountsController>(AccountsController);
    service = module.get<AccountsService>(AccountsService);
  });

  it('should be defined', () => {
    expect(controller).toBeDefined();
  });

  describe('save', () => {
    it('should call the service', () => {
      const createAccountDto = new CreateAccountDto();

      controller.save(createAccountDto);

      expect(service.save).toHaveBeenCalled();
    });

    it('should receive a valid body', async () => {
      const createAccountDto = new CreateAccountDto();
      createAccountDto.account = 'test';
      createAccountDto.cvcRequired = true;
      createAccountDto.paymentMethodId = '201';
      createAccountDto.visualization = [];

      const validationResult = await validate(createAccountDto).then(
        (errors: unknown[]) => errors,
      );

      expect(validationResult.length).toEqual(0);
    });

    it('should return a non-empty result', async () => {
      const createAccountDto = new CreateAccountDto();
      createAccountDto.account = 'test';
      createAccountDto.cvcRequired = true;
      createAccountDto.paymentMethodId = '201';
      createAccountDto.visualization = [];

      expect(controller.save(createAccountDto)).resolves.toEqual({
        _id: 'a uuid',
        ...createAccountDto,
      });
    });
  });

  describe('get', () => {
    it('should call the service', () => {
      const account = 'test';

      controller.findByAccount(account);

      expect(service.get).toHaveBeenCalled();
    });

    it('should return a non-empty result', async () => {
      const account = 'test';

      await expect(controller.findByAccount(account)).resolves.toEqual({
        _id: 'a uuid',
        account,
        cvcRequired: false,
        paymentMethodId: '201',
        visualization: [],
      });

      const accountMock = createMock<Account>({
        account: 'test2',
        cvcRequired: false,
        paymentMethodId: '201',
        visualization: [],
      });

      const getSpy = jest
        .spyOn(service, 'get')
        .mockResolvedValueOnce(accountMock as any);

      const getResponse = await controller.findByAccount('test2');

      expect(getResponse).toEqual(accountMock);
      expect(getSpy).toBeCalledWith({ account: 'test2' });
    });
  });

  describe('storeFront settings', () => {
    it('should call the service', () => {
      const account = 'test';

      controller.getStoreFrontSettings(account);

      expect(service.getStoreFrontSettings).toHaveBeenCalled();
    });

    it('should return a non-empty result', async () => {
      const account = 'test';

      expect(controller.getStoreFrontSettings(account)).resolves.toBe({
        cvcRequired: false,
        paymentMethodId: '201',
        visualization: [],
      });
    });
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/accounts/accounts.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Provider } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from 'nestjs-dynamoose';
import { NotFoundException } from '../../shared/exceptions/not-found-exception';
import { AccountsService } from './accounts.service';
import { CreateAccountDto } from './dtos/createAccount.dto';
import { PaymentMethodsService } from './payment-methods/payment-methods.service';
import { PaymentMethod } from './payment-methods/schemas/payment-method.schema';
import { Account, AccountDoc, AccountModel } from './schemas/account.schema';

const mockAccountDoc = (mock?: Partial<AccountDoc>): Partial<AccountDoc> => ({
  account: mock?.account || 'test',
  id: 'a uuid',
  cvcRequired: mock?.cvcRequired || false,
  paymentMethodId: mock?.paymentMethodId || '201',
  visualization: mock?.visualization || [
    { type: 'category', key: '123', secondaryKey: 'vestidos' },
  ],
  set(updateMock: any) {
    for (const key in updateMock) {
      if (this[key] !== undefined) {
        this[key] = updateMock[key];
      }
    }

    return this;
  },
  save() {
    return this;
  },
});

describe('AccountsService', () => {
  let service: AccountsService;
  let paymentMethodsService: PaymentMethodsService;
  let accountModel: AccountModel;

  beforeEach(async () => {
    const AccountModel: Provider = {
      provide: getModelToken(Account.name),
      useValue: {
        findOne: jest.fn(),
        build: jest.fn(),
      },
    };

    const PaymentMethodsModel: Provider = {
      provide: getModelToken(PaymentMethod.name),
      useValue: {},
    };

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        AccountsService,
        PaymentMethodsService,
        AccountModel,
        PaymentMethodsModel,
      ],
    }).compile();

    service = module.get<AccountsService>(AccountsService);
    paymentMethodsService = module.get<PaymentMethodsService>(
      PaymentMethodsService,
    );
    accountModel = module.get<AccountModel>(getModelToken(Account.name));
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('save', () => {
    it('save a new account', async () => {
      const createAccountDto = new CreateAccountDto();
      createAccountDto.account = 'NotTest';
      createAccountDto.cvcRequired = true;
      createAccountDto.paymentMethodId = '201';
      createAccountDto.visualization = [];

      jest.spyOn(accountModel, 'findOne').mockReturnValue({
        exec: jest.fn().mockResolvedValueOnce(null),
      } as any);

      const spiedBuild = jest
        .spyOn(accountModel, 'build')
        .mockImplementationOnce(
          () => mockAccountDoc({ ...createAccountDto }) as any,
        );

      await expect(service.save(createAccountDto)).resolves.toMatchObject({
        ...createAccountDto,
      });

      expect(spiedBuild).toHaveBeenCalled();
    });

    it('update existent account', async () => {
      const createAccountDto = new CreateAccountDto();
      createAccountDto.cvcRequired = true;

      jest.spyOn(accountModel, 'findOne').mockReturnValue({
        exec: jest.fn().mockResolvedValueOnce(mockAccountDoc()),
      } as any);

      const response = await service.save(createAccountDto);

      expect(response).toMatchObject({
        ...createAccountDto,
      });
    });
  });

  describe('get', () => {
    it('should return NotFoundException if the account does not exist', async () => {
      const account = 'test';

      jest.spyOn(accountModel, 'findOne').mockReturnValue({
        exec: jest.fn().mockResolvedValueOnce(null),
      } as any);

      await expect(service.get({ account })).rejects.toBeInstanceOf(
        NotFoundException,
      );
    });

    it('should return an existing account', () => {
      const account = 'test';

      jest.spyOn(accountModel, 'findOne').mockReturnValue({
        exec: jest.fn().mockResolvedValueOnce(mockAccountDoc()),
      } as any);

      expect(service.get({ account })).resolves.toMatchObject({
        account: 'test',
        id: 'a uuid',
        cvcRequired: false,
        paymentMethodId: '201',
        visualization: [
          { type: 'category', key: '123', secondaryKey: 'vestidos' },
        ],
      });
    });
  });

  describe('storeFront', () => {
    it('should return NotFoundException if the account does not exist', async () => {
      const account = 'test';

      jest.spyOn(accountModel, 'findOne').mockReturnValue({
        exec: jest.fn().mockResolvedValueOnce(null),
      } as any);

      await expect(
        service.getStoreFrontSettings(account),
      ).rejects.toBeInstanceOf(NotFoundException);
    });

    it('should return an existing account storeFront setting', () => {
      const account = 'test';

      jest.spyOn(accountModel, 'findOne').mockReturnValue({
        exec: jest.fn().mockResolvedValueOnce(mockAccountDoc()),
      } as any);

      jest
        .spyOn(paymentMethodsService, 'findByAccount')
        .mockReturnValueOnce([] as any);

      expect(service.getStoreFrontSettings(account)).resolves.toMatchObject({
        cvcRequired: false,
        paymentMethodId: '201',
        visualization: [
          { type: 'category', key: '123', secondaryKey: 'vestidos' },
        ],
        PaymentMethod: [],
      });
    });
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/users/users.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Injectable } from '@nestjs/common';
import { InjectModel } from 'nestjs-dynamoose';
import { User, UserModel } from './schemas/user.schema';

@Injectable()
export class UsersService {
  constructor(@InjectModel(User.name) private userModel: UserModel) {}

  async create({ email, account }: { email: string; account: string }) {
    const user = this.userModel.build({
      email,
      creationDate: new Date().toISOString(),
      createdAt: Date.now(),
      createdAccount: account,
    });
    try {
      return await user.save();
    } catch (e) {
      console.log(e);
    }
  }

  getUserByEmail(email: string) {
    return this.userModel.findOne({ email }).exec();
  }

  getUserById(id: string) {
    return this.userModel.get(id);
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/users/users.controller.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Controller } from '@nestjs/common';

@Controller('users')
export class UsersController {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/users/users.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { ProfilesController } from './profiles/profiles.controller';
import { ProfilesService } from './profiles/profiles.service';
import { AddressesController } from './addresses/addresses.controller';
import { AddressesService } from './addresses/addresses.service';
import { CardsController } from './cards/cards.controller';
import { CardsService } from './cards/cards.service';
import { User } from './schemas/user.schema';
import { Profile } from './profiles/schemas/profile.schema';
import { Address } from './addresses/schemas/address.schema';
import { Card } from './cards/schemas/cards.schema';
import { AccountsModule } from '../accounts/accounts.module';
import { AuthController } from './auth/auth.controller';
import { AuthService } from './auth/auth.service';
import { Auth } from './auth/schemas/auth.schema';
import { JwtModule } from '@nestjs/jwt';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { VtexModule } from '../vtex/vtex.module';
import { CustomDynamooseModule } from 'src/shared/utils/dynamoose-module';

@Module({
  imports: [
    JwtModule.registerAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        secret: configService.get('JWT_TOKEN'),
      }),
      inject: [ConfigService],
    }),
    CustomDynamooseModule.forFeature([User, Auth, Profile, Card, Address]),
    AccountsModule,
    VtexModule,
  ],
  providers: [
    UsersService,
    ProfilesService,
    AddressesService,
    CardsService,
    AuthService,
  ],
  controllers: [
    UsersController,
    ProfilesController,
    AddressesController,
    CardsController,
    AuthController,
  ],
  exports: [ProfilesService, AddressesService, CardsService],
})
export class UsersModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/users/users.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { User } from './schemas/user.schema';
import { UsersService } from './users.service';

describe('UsersService', () => {
  let service: UsersService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UsersService,
        {
          provide: getModelToken(User.name),
          useFactory: () => ({
            findOne: jest.fn(({ email }: { email: string }) => {
              let result: Record<string, string>;

              if (email === 'test@vtex.com.br') {
                result = {
                  email,
                };
              }

              return {
                exec: () => result,
              };
            }),
          }),
        },
      ],
    }).compile();

    service = module.get<UsersService>(UsersService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  describe('save', () => {
    it('should not save existent email', () => {});
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/users/users.controller.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';

describe('UsersController', () => {
  let controller: UsersController;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [UsersController],
    }).compile();

    controller = module.get<UsersController>(UsersController);
  });

  it('should be defined', () => {
    expect(controller).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/masters/masters.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Module } from '@nestjs/common';
import { DocumentTypesController } from './document-types/document-types.controller';
import { DocumentTypesService } from './document-types/document-types.service';
import { CitiesController } from './cities/cities.controller';
import { CitiesService } from './cities/cities.service';
import { CountriesController } from './countries/countries.controller';
import { CountriesService } from './countries/countries.service';
import { City } from './cities/schemas/city.schema';
import { Country } from './countries/schemas/country.schema';
import { DocumentType } from './document-types/schemas/document-type.schema';
import { CustomDynamooseModule } from 'src/shared/utils/dynamoose-module';

@Module({
  imports: [CustomDynamooseModule.forFeature([City, Country, DocumentType])],
  controllers: [DocumentTypesController, CitiesController, CountriesController],
  providers: [DocumentTypesService, CitiesService, CountriesService],
})
export class MastersModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/orders/orders.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Test, TestingModule } from '@nestjs/testing';
import { getModelToken } from 'nestjs-dynamoose';
import { ChannelsService } from '../channels/channels.service';
import { AwsService } from '../common/aws/aws.service';
import { OmsService } from '../oms/oms.service';
import { PaymentProvidersService } from '../payment-providers/payment-providers.service';
import { OrdersService } from './orders.service';
import { Order } from './schemas/order.schema';

const AwsServiceProvider = {
  provide: AwsService,
  useFactory: () => ({}),
};

const OrderModel = {
  provide: getModelToken(Order.name),
  useFactory: () => ({}),
};

const ChannelsServiceProvider = {
  provide: ChannelsService,
  useFactory: () => ({}),
};
const OmsServiceProvider = {
  provide: OmsService,
  useFactory: () => ({}),
};

const PaymentProviderServiceProvider = {
  provide: PaymentProvidersService,
  useFactory: () => ({}),
};

describe('OrdersService', () => {
  let service: OrdersService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        OrdersService,
        AwsServiceProvider,
        OrderModel,
        ChannelsServiceProvider,
        OmsServiceProvider,
        PaymentProviderServiceProvider,
      ],
    }).compile();

    service = module.get<OrdersService>(OrdersService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/orders/orders.controller.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Test, TestingModule } from '@nestjs/testing';
import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';

const OrdersServiceProvider = {
  provide: OrdersService,
  useFactory: () => ({}),
};

describe('OrdersController', () => {
  let controller: OrdersController;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [OrdersController],
      providers: [OrdersServiceProvider],
    }).compile();

    controller = module.get<OrdersController>(OrdersController);
  });

  it('should be defined', () => {
    expect(controller).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/orders/orders.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Module } from '@nestjs/common';
import { AccountsModule } from '../accounts/accounts.module';
import { PaymentProvidersModule } from '../payment-providers/payment-providers.module';
import { UsersModule } from '../users/users.module';
import { VtexModule } from '../vtex/vtex.module';
import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';
import { Order } from './schemas/order.schema';
import { ChannelsModule } from '../channels/channels.module';
import { OmsModule } from '../oms/oms.module';
import { CustomDynamooseModule } from 'src/shared/utils/dynamoose-module';

@Module({
  imports: [
    CustomDynamooseModule.forFeature([Order]),
    VtexModule,
    UsersModule,
    AccountsModule,
    PaymentProvidersModule,
    ChannelsModule,
    OmsModule,
  ],
  controllers: [OrdersController],
  providers: [OrdersService, OrdersService],
})
export class OrdersModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/orders/orders.controller.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Body, Controller, Get, Post, Query, Headers } from '@nestjs/common';
import { CreateOrderDto } from './dtos/createOrder.dto';
import { ProcessTransactionDto } from './dtos/processTransaction.dto';
import { OrdersService } from './orders.service';

@Controller('orders')
export class OrdersController {
  constructor(private ordersService: OrdersService) {}

  @Post('/v2')
  create(@Body() createOrderDto: CreateOrderDto, @Headers() headers) {
    return this.ordersService.create({
      ...createOrderDto,
      authToken: headers?.vtexidclientautcookie,
    });
  }

  @Post('v2/process-transaction')
  processTransaction(@Body() processTransactionDto: ProcessTransactionDto) {
    return this.ordersService.processTransaction(processTransactionDto);
  }

  @Get('/payment-process')
  async paymentProcess(
    @Query('orderId') id: number,
    @Query('an') an: string,
    @Headers() headers,
  ) {
    return this.ordersService.paymentProcess(
      an,
      String(id),
      headers?.vtexidclientautcookie,
    );
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/orders/orders.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Injectable } from '@nestjs/common';
import { OrderContext } from '../../typings/OrderContext';
import { ChannelsService } from '../channels/channels.service';
import { OmsService } from '../oms/oms.service';
import { PaymentProvidersService } from '../payment-providers/payment-providers.service';
import { AwsService } from '../common/aws/aws.service';
import { CreateOrderDto } from './dtos/createOrder.dto';
import { ProcessTransactionDto } from './dtos/processTransaction.dto';
import { Order, OrderModel } from './schemas/order.schema';
import { InjectModel } from 'nestjs-dynamoose';
import { OrdersVTEXService } from '../vtex/orders/orders.service';
import { AccountsService } from '../accounts/accounts.service';
import { OrderVtexDto } from '../vtex/dtos/orderVtex.dto';
// import { AcceptanceHabeasDataService } from '../accounts/habeasData/acceptanceHabeasData/acceptanceHabeasData.service';
// import { HabeasDataService } from '../accounts/habeasData/habeasData.service';
import { ProfilesService } from '../users/profiles/profiles.service';
import { AddressesService } from '../users/addresses/addresses.service';

@Injectable()
export class OrdersService {
  constructor(
    @InjectModel(Order.name) private orderModel: OrderModel,
    // private acceptanceHabeasDataService: AcceptanceHabeasDataService,
    private accountServices: AccountsService,
    private awsService: AwsService,
    private channelsService: ChannelsService,
    // private habeasDataService: HabeasDataService,
    private omsService: OmsService,
    private paymentProviderService: PaymentProvidersService,
    private profilesService: ProfilesService,
    private vtexOrderService: OrdersVTEXService,
    private addressService: AddressesService,
  ) {}

  async create(createOrderDto: CreateOrderDto) {
    const orderAddress = createOrderDto.shipping.addressId;
    const externalAddress = createOrderDto.shipping.externalAddress;
    const email = createOrderDto.profile.email;

    const address = await this.addressService.findByEmail(
      email,
      createOrderDto.account.accountName,
    );

    const profile = (await this.profilesService.getByEmail(email)).toJSON();

    if (
      externalAddress &&
      !address.find((address) => {
        return address.id === orderAddress;
      }) &&
      externalAddress.addressId === orderAddress
    ) {
      const newAddress = {
        receiverName: externalAddress.receiverName,
        profileId: profile[0].id,
        geoCoordinates: externalAddress.geoCoordinates,
        user: profile[0].user,
        country: externalAddress.country,
        state: externalAddress.state,
        city: externalAddress.city,
        number: externalAddress.number,
        neighborhood: externalAddress.neighborhood,
        id: externalAddress.addressId,
        postalCode: externalAddress.postalCode,
        street: externalAddress.street,
      };
      // save the direction
      await this.addressService.create(newAddress, true);
    }

    const ctx: OrderContext = {
      dataDto: createOrderDto,
      queueMessage: {
        profile: createOrderDto.profile,
        shipping: createOrderDto.shipping,
        channel: createOrderDto.channel,
        oms: createOrderDto.oms,
        hostname: createOrderDto.account.hostname,
        version: '2',
      },
      headers: {
        VtexIdclientAutCookie: createOrderDto.authToken,
      },
    };
    const channel = this.channelsService.createChannel(
      createOrderDto.channel,
      ctx,
    );
    const oms = this.omsService.createOms(createOrderDto.oms, ctx);
    const paymentProvider = this.paymentProviderService.createPaymentProvider(
      createOrderDto.payment.paymentMethod,
      createOrderDto.payment.gateway,
      createOrderDto.payment.additionalData?.accountId,
      ctx,
    );
    try {
      await channel.prepare();
      await oms.prepare();

      await oms.createOrder();
      await channel.createOrder(this.orderModel);
      if (ctx.account.paymentRedirect) {
        return this.processTransaction({
          ...ctx.queueMessage,
          authToken: createOrderDto.authToken,
        } as ProcessTransactionDto);
      } else {
        await this.awsService.sendTransactionProcessorQueue({
          ...ctx.queueMessage,
          authToken: createOrderDto.authToken,
        });

        return ctx.order;
      }
    } catch (err) {
      if (ctx.dataDto.payment.token && !ctx.dataDto.payment.cardId) {
        paymentProvider.rollbackPayment();
      }

      if (ctx.account && ctx.account.paymentRedirect && !ctx.order) {
        await channel.cancelOrder(this.orderModel, err.toString());
      }
      throw err;
    }
  }

  async processTransaction(processTransactionDto: ProcessTransactionDto) {
    const ctx: OrderContext = {
      processTransactionDto,
      headers: {
        VtexIdclientAutCookie: processTransactionDto.authToken,
      },
    };

    const channel = this.channelsService.createChannel(
      processTransactionDto.channel,
      ctx,
    );
    const oms = this.omsService.createOms(processTransactionDto.oms, ctx);
    const paymentProvider = this.paymentProviderService.createPaymentProvider(
      processTransactionDto.payment.paymentMethod,
      processTransactionDto.payment.gateway,
      processTransactionDto.payment.additionalData?.accountId,
      ctx,
    );

    try {
      await channel.prepareProcessTransaction(this.orderModel);

      await oms.onProcessTransaction();

      await paymentProvider.authorizePayment();

      await channel.onProcessTransaction();

      return {
        ...ctx.order.toJSON(),
        transaction: {
          ...(ctx.transaction.gatewayCallbackResponse &&
            (ctx.transaction.gatewayCallbackResponse as Record<
              string,
              unknown
            >)),
        },
      };
    } catch (err) {
      if (
        ctx.processTransactionDto.payment.token &&
        !ctx.processTransactionDto.payment.cardId
      ) {
        paymentProvider.rollbackPayment();
      }

      await channel.cancelOrderProcessTransaction(err.toString());
      throw err;
    }
  }

  async paymentProcess(an: string, order: string, authToken: string) {
    const account = await this.accountServices.get({
      account: an,
    });
    const headers = {
      VtexIdclientAutCookie: authToken,
    };

    try {
      return await this.vtexOrderService.payment.requestPaymentProcess(
        account,
        '',
        {
          orderGroup: order,
        } as OrderVtexDto,
        headers,
      );
    } catch (err) {
      return { status: false, message: err.response.data?.error.message };
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/payment-providers/payment-provider.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderContext } from '../../typings/OrderContext';
import { PaymentProviderServices } from './types/payment-providers.type';

export abstract class PaymentProvider {
  constructor(
    protected services: PaymentProviderServices,
    protected ctx: OrderContext,
  ) {}

  abstract authorizePayment(): Promise<void>;
  abstract capturePayment(): Promise<void>;
  abstract refundPayment(): Promise<void>;
  abstract cancelPayment(): Promise<void>;
  abstract rollbackPayment(): Promise<void>;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/payment-providers/payment-providers.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpModule, Module } from '@nestjs/common';
import { MercadopagoService } from './mercadopago/mercadopago.service';
import { PaymentProvidersService } from './payment-providers.service';
import { CreditPayController } from './credit-pay/credit-pay.controller';
import { CreditPayService } from './credit-pay/credit-pay.service';
import { Credit } from './credit-pay/schema/credit.schema';
import { CustomDynamooseModule } from 'src/shared/utils/dynamoose-module';

@Module({
  imports: [HttpModule, CustomDynamooseModule.forFeature([Credit])],
  providers: [MercadopagoService, PaymentProvidersService, CreditPayService],
  exports: [PaymentProvidersService],
  controllers: [CreditPayController],
})
export class PaymentProvidersModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/payment-providers/payment-providers.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderContext } from '../../typings/OrderContext';
import { HttpService, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { CashOnDelivery } from './cashOnDelivery';
import { CreditPayProvider } from './credit-pay';
import { CreditPayService } from './credit-pay/credit-pay.service';
import { KuikpayProvider } from './kuikpay';
import { MercadoPagoProvider } from './mercadopago';
import { MercadopagoService } from './mercadopago/mercadopago.service';
import { PaymentProvider } from './payment-provider';
import {
  PaymentMethodName,
  PaymentProviderName,
  PaymentProviderServices,
} from './types/payment-providers.type';
import { Custom } from './custom';

@Injectable()
export class PaymentProvidersService {
  public readonly payments: {
    Mercadopago: MercadopagoService;
  } = {
    Mercadopago: undefined,
  };
  private services: PaymentProviderServices;

  constructor(
    private readonly mercadoPagoService: MercadopagoService,
    private readonly httpService: HttpService,
    private readonly configService: ConfigService,
    private readonly creditPayService: CreditPayService,
  ) {
    this.services = {
      configService,
      httpService,
      creditPayService,
    };

    this.payments['Mercadopago'] = this.mercadoPagoService;
  }

  createPaymentProvider(
    paymentMethod: string,
    paymentProviderName: string,
    accountId: string,
    ctx: OrderContext,
  ): PaymentProvider {
    //TODO: Revisar al eliminar PCI proxy
    //if (accountId) return new Custom(this.services, ctx, paymentMethod);
    switch (paymentMethod) {
      case PaymentMethodName.CreditCard:
        switch (paymentProviderName) {
          case PaymentProviderName.MercadoPago:
            return new MercadoPagoProvider(this.services, ctx);

          case PaymentProviderName.Noop:
            return new KuikpayProvider(this.services, ctx);

          default:
            throw new Error('Gateway Does Not Exist');
        }
      case PaymentMethodName.Promissory:
        switch (paymentProviderName) {
          case PaymentProviderName.CashOnDelivery:
            return new CashOnDelivery(this.services, ctx);

          default:
            throw new Error('Gateway Does Not Exist');
        }
      case PaymentMethodName.BNPL:
        switch (paymentProviderName) {
          case PaymentProviderName.CreditPay:
            return new CreditPayProvider(this.services, ctx);

          default:
            throw new Error('Gateway Does Not Exist');
        }
      default:
        if (paymentProviderName == PaymentProviderName.Custom)
          return new Custom(this.services, ctx, paymentMethod);
        else throw new Error('Payment Method Does Not Exist');
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/payment-providers/payment-providers.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpService } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { CreditPayService } from './credit-pay/credit-pay.service';
import { MercadopagoService } from './mercadopago/mercadopago.service';
import { PaymentProvidersService } from './payment-providers.service';

const MercadoPagoServiceProvider = {
  provide: MercadopagoService,
  useFactory: () => ({}),
};

const HttpServiceProvider = {
  provide: HttpService,
  useFactory: () => ({}),
};

const ConfigServiceProvider = {
  provide: ConfigService,
  useFactory: () => ({}),
};

const CreditPayServiceProvider = {
  provide: CreditPayService,
  useFactory: () => ({}),
};

describe('PaymentProvidersService', () => {
  let service: PaymentProvidersService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        PaymentProvidersService,
        MercadoPagoServiceProvider,
        HttpServiceProvider,
        ConfigServiceProvider,
        CreditPayServiceProvider,
      ],
    }).compile();

    service = module.get<PaymentProvidersService>(PaymentProvidersService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/channels/channels.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Injectable } from '@nestjs/common';
import { OrderContext } from '../../typings/OrderContext';
import { AccountsService } from '../accounts/accounts.service';
import { AddressesService } from '../users/addresses/addresses.service';
import { CardsService } from '../users/cards/cards.service';
import { ProfilesService } from '../users/profiles/profiles.service';
import { Channel } from './channel';
import { KuikpayChannel } from './kuikpay';
import { ChannelName, ChannelServices } from './types/services.type';
import { WhatsappChannel } from './whatsapp';

@Injectable()
export class ChannelsService {
  private services: ChannelServices;
  constructor(
    profilesService: ProfilesService,
    addressesService: AddressesService,
    accountsServices: AccountsService,
    cardsServices: CardsService,
  ) {
    this.services = {
      profilesService,
      addressesService,
      accountsServices,
      cardsServices,
    };
  }

  createChannel(channel: string, ctx: OrderContext): Channel {
    switch (channel) {
      case ChannelName.Kuikpay:
        return new KuikpayChannel(ctx, this.services);
      case ChannelName.Whatsapp:
        return new WhatsappChannel(ctx, this.services);
      case ChannelName.Checkout:
        break;
      default:
        break;
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/channels/channels.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Test, TestingModule } from '@nestjs/testing';
import { AccountsService } from '../accounts/accounts.service';
import { AddressesService } from '../users/addresses/addresses.service';
import { CardsService } from '../users/cards/cards.service';
import { ProfilesService } from '../users/profiles/profiles.service';
import { ChannelsService } from './channels.service';

const AddressServiceProvider = {
  provide: AddressesService,
  useFactory: () => ({}),
};
const ProfilesServiceProvider = {
  provide: ProfilesService,
  useFactory: () => ({}),
};

const CardsServiceProvider = {
  provide: CardsService,
  useFactory: () => ({}),
};

const AccountServiceProvider = {
  provide: AccountsService,
  useFactory: () => ({}),
};

describe('ChannelsService', () => {
  let service: ChannelsService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        ChannelsService,
        AddressServiceProvider,
        ProfilesServiceProvider,
        CardsServiceProvider,
        AccountServiceProvider,
      ],
    }).compile();

    service = module.get<ChannelsService>(ChannelsService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/channels/channel.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderContext } from '../../typings/OrderContext';
import { OrderModel } from '../orders/schemas/order.schema';
import { CardDto } from '../users/cards/dtos/card.dto';
import { ChannelServices } from './types/services.type';

export abstract class Channel {
  constructor(
    protected ctx: OrderContext,
    protected services: ChannelServices,
  ) {}

  protected findAccount(accountName: string) {
    const { accountsServices } = this.services;

    return accountsServices.get({
      account: accountName,
    });
  }

  protected findProfile(email: string, accountName: string, headers: string) {
    const { profilesService } = this.services;

    return profilesService.getProfileInfo(email, accountName, headers);
  }

  protected findProfileById(id: string) {
    const { profilesService } = this.services;
    return profilesService.getById(id);
  }

  protected findAddress(addressId: string) {
    const { addressesService } = this.services;

    return addressesService.get(addressId);
  }

  protected findCard() {
    const { cardsServices } = this.services;
    return cardsServices.get(this.ctx.dataDto.payment.cardId);
  }

  protected createCard() {
    const { cardsServices } = this.services;
    const {
      processTransactionDto: { payment },
      transaction: { cardContent, internalCardContent, aliasCC, aliasCVV },
      profile,
    } = this.ctx;
    return cardsServices.create(
      {
        number: payment.number,
        franchise: payment.franchise,
        token: payment.token,
        gateway: payment.gateway,
        bin: payment.bin,
        paymentSystem: payment.paymentSystem,
        holderName: payment.holderName,
        expirationDate: payment.expirationDate,
        cardNumber: payment.cardNumber,
        aliasCC: aliasCC,
        aliasCVV: aliasCVV,
        holderDocument: payment.holderDocument,
        cardContent,
        internalCardContent,
      },
      profile,
    );
  }

  protected updateCardData(data: Partial<CardDto>) {
    const { cardsServices } = this.services;
    const {
      processTransactionDto: { payment },
    } = this.ctx;

    return cardsServices.update(data, payment.cardId);
  }

  abstract prepare(): Promise<void>;
  abstract createOrder(orderModel: OrderModel): Promise<void>;
  abstract prepareProcessTransaction(orderModel: OrderModel): Promise<void>;
  abstract onProcessTransaction(): Promise<void>;
  abstract cancelOrderProcessTransaction(log?: string): Promise<void>;
  abstract cancelOrder(orderModel: OrderModel, log?: string): Promise<void>;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/channels/channels.module.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Module } from '@nestjs/common';
import { AccountsModule } from '../accounts/accounts.module';
import { UsersModule } from '../users/users.module';
import { ChannelsService } from './channels.service';

@Module({
  providers: [ChannelsService],
  imports: [UsersModule, AccountsModule],
  exports: [ChannelsService],
})
export class ChannelsModule {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/noop/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Oms } from '../oms';

export class NoopOms extends Oms {
  prepare(): Promise<void> {
    return;
  }
  createOrder(): Promise<void> {
    return;
  }
  onProcessTransaction(): Promise<void> {
    return;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/types/oms.types.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrdersVTEXService } from '../../vtex/orders/orders.service';

export type OmsServices = {
  vtexService: OrdersVTEXService;
};

export enum OmsName {
  VTEX = 'vtex',
  NOOP = 'noop',
}

export enum paymentSystem {
  amex = 1,
  Amex = 1,
  'American Express' = 1,
  visa = 2,
  Visa = 2,
  diners = 3,
  Diners = 3,
  master = 4,
  Master = 4,
  Mastercard = 4,
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/vtex/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import * as cookie from 'cookie';
import { Oms } from '../oms';
import { GatewayException } from '../../../shared/exceptions/gateway-exception';
import { paymentSystem as paymentSystemData } from '../types/oms.types';
import { ManageItemsService } from './items/manageItems.service';
import { AddressDoc } from 'src/app/users/addresses/schemas/address.schema';

export class VtexOms extends Oms {
  private getCheckoutCookies = (headers: Record<string, any>) => {
    const responseSetCookies: string[] = headers?.['set-cookie'] || [];
    const checkoutCookie = responseSetCookies.find((item) =>
      item.includes('Vtex_CHKO_Auth'),
    );
    if (checkoutCookie) return cookie.parse(checkoutCookie)['Vtex_CHKO_Auth'];
    return null;
  };

  async prepare(): Promise<void> {
    const {
      dataDto: {
        account,
        items,
        shipping: { logisticsInfo, externalAddress },
        marketingData,
        payment,
      },
      payment: { franchise, paymentSystem },
    } = this.ctx;

    const manageItemsService = new ManageItemsService();
    const { addresses } = this.ctx;
    const { vtexService } = this.services;

    if (payment.gateway == 'noop')
      this.ctx.account.paymentMethodId =
        paymentSystem || paymentSystemData[franchise];
    else if (payment.gateway == 'custom')
      this.ctx.account.paymentMethodId = payment.paymentMethod;

    const promises = [];

    promises[0] = vtexService.cart.cartSimulation(
      account.accountName,
      items,
      externalAddress || addresses[0],
      logisticsInfo,
      marketingData,
      payment,
      this.ctx.account.paymentMethodId,
    );

    //TODO: revisar si es verdaderamente necesario las dos simulaciones
    if (externalAddress)
      promises.push(
        manageItemsService.individualSimulation(
          logisticsInfo,
          items,
          account,
          externalAddress as AddressDoc,
          'pickup-in-point',
          marketingData,
          payment,
          vtexService,
          this.ctx,
        ),
      );
    if (addresses[0])
      promises.push(
        manageItemsService.individualSimulation(
          logisticsInfo,
          items,
          account,
          addresses[0],
          'delivery',
          marketingData,
          payment,
          vtexService,
          this.ctx,
        ),
      );

    const simulations = (await Promise.all(promises)).filter((e) => {
      return e !== undefined;
    });

    //manageItemsService.validateAvailability(simulations[0]);

    let shippingTotal = 0;
    const totals: number = simulations[0].totals.reduce((acumm, total) => {
      if (total.id === 'Shipping') {
        shippingTotal = shippingTotal;
      }

      return acumm + total.value;
    }, 0);

    const {
      items: formattedItems,
      gifts,
      offersTotal,
    } = manageItemsService.manageItems(simulations[0], this.ctx);

    this.ctx.vtex = {
      simulation: simulations[0],
      items: formattedItems,
      gifts,
      totals: totals + offersTotal,
      shippingTotal,
    };

    this.ctx.queueMessage.totalizers = {
      totals: (totals + offersTotal) / 100,
      shippingTotal: shippingTotal / 100,
      subTotal: (totals + offersTotal - shippingTotal) / 100,
    };
  }

  async createOrder(): Promise<void> {
    const {
      account,
      profile,
      addresses,
      vtex: { totals, simulation, items, gifts },
      dataDto: {
        account: {
          storePreferences: { currencyCode },
        },
        customData,
        marketingData,
        payment,
      },
      headers,
    } = this.ctx;

    const { vtexService } = this.services;

    let vtexOrderResp: any;

    try {
      vtexOrderResp = await vtexService.checkout.createOrder(
        account,
        simulation,
        profile,
        addresses,
        totals,
        items,
        gifts,
        customData,
        marketingData,
        payment,
        headers,
      );
    } catch (err) {
      throw new GatewayException(
        'VTEX: Error creating order',
        err.response?.data,
      );
    }

    const checkoutCookie = this.getCheckoutCookies(vtexOrderResp.headers);

    this.ctx.vtex = {
      ...this.ctx.vtex,
      order: vtexOrderResp.data,
      checkoutCookie,
    };

    this.ctx.queueMessage.reference = vtexOrderResp.data.orders[0].orderGroup;
    this.ctx.queueMessage.omsExtraData = {
      transactions: vtexOrderResp.data.transactionData.merchantTransactions.map(
        (transaction) => ({
          transactionId: transaction.transactionId,
          merchantName: transaction.merchantName,
          payments: transaction.payments.map((payment) => ({
            value: payment.value,
            referenceValue: payment.referenceValue,
            paymentSystem: payment.paymentSystem,
          })),
        }),
      ),
      order: {
        addressId: vtexOrderResp.data.orders[0].shippingData.address.addressId,
        currencyCode: currencyCode,
        orderGroup: vtexOrderResp.data.orders[0].orderGroup,
        id: vtexOrderResp.data.orders[0].orderId,
      },
      checkoutCookie,
    };
  }

  async onProcessTransaction(): Promise<void> {
    const {
      processTransactionDto: {
        omsExtraData: { order: orderVtex, transactions, checkoutCookie },
        account,
        payment,
      },
      headers,
    } = this.ctx;

    //TODO: Realizar pago de targetas de comercio aqui, al eliminar PCI proxy
    if (payment.gateway !== 'noop' /*|| payment.additionalData?.accountId*/) {
      const { vtexService } = this.services;

      const transactionPromises = [];
      transactions.forEach((transaction) =>
        transactionPromises.push(
          vtexService.payment.sendPaymentData(
            account,
            transaction,
            orderVtex,
            headers,
            payment,
          ),
        ),
      );

      await Promise.all(transactionPromises);

      await vtexService.payment.requestPaymentProcess(
        account,
        checkoutCookie,
        orderVtex,
        headers,
      );
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/oms/vtex/items/manageItems.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { GatewayException } from 'src/shared/exceptions/gateway-exception';
import {
  DataDTO,
  Item,
  Offering,
  Vtex,
} from '../../../../typings/OrderContext';
import * as R from 'ramda';
import { LogisticInfoDto } from 'src/app/orders/dtos/logisticInfo.dto';
import { ItemDto } from 'src/app/orders/dtos/item.dto';
import { AddressDoc } from 'src/app/users/addresses/schemas/address.schema';
import { MarketingDataDto } from 'src/app/orders/dtos/marketingData.dto';
import { OrdersVTEXService } from 'src/app/vtex/orders/orders.service';
import { OrderContext } from '../../../../typings/OrderContext';

export class ManageItemsService {
  async individualSimulation(
    logisticsInfo: LogisticInfoDto[],
    items: ItemDto[],
    account: DataDTO['account'],
    address: AddressDoc,
    deliveryType: string,
    marketingData: MarketingDataDto,
    payment: DataDTO['payment'],
    vtexService: OrdersVTEXService,
    ctx: OrderContext,
  ) {
    const logistics = logisticsInfo.filter(
      (item) => item.selectedDeliveryChannel == deliveryType,
    );
    const itemsArr = [];
    logistics.map((item, id) => {
      itemsArr.push(items[item.itemIndex]);
      item.itemIndex = id;
      return item;
    });

    if (itemsArr.length > 0) {
      const simulation = await vtexService.cart.cartSimulation(
        account.accountName,
        itemsArr,
        address,
        logistics,
        marketingData,
        payment,
        ctx.account.paymentMethodId,
      );

      this.validateAvailability(simulation);

      return simulation;
    }
  }

  validateAvailability(simulation: Vtex['simulation']) {
    const itemNotAvailable = simulation.items.some(
      (item: any) => item.availability !== 'available',
    );

    if (itemNotAvailable) {
      throw new GatewayException(
        "Some items can't be deliverable in this location",
        simulation.items,
      );
    }
  }

  manageItems(simulation: Vtex['simulation'], ctx: OrderContext) {
    const {
      dataDto: { offerings },
    } = ctx;
    const { gifts, items } = this.splitItemsAndGifts(
      ctx,
      simulation.items,
      simulation.selectableGifts,
    );

    if (offerings && offerings.length > 0) {
      const { itemsWithBundle, offersTotal } = this.AddOfferings(
        items,
        offerings,
      );

      return { items: itemsWithBundle, gifts, offersTotal };
    }

    return { items, gifts, offersTotal: 0 };
  }

  AddOfferings(items: Item[], offerings: Offering[]) {
    let offersTotal = 0;
    const itemsWithBundle = items.map((item) => {
      const currentOffers = offerings.filter(
        (offer) => item.id === offer.parentItemId,
      );

      const offers = item.offerings.filter((offer) =>
        R.includes({ id: offer.id, parentItemId: item.id }, currentOffers),
      );

      return {
        ...item,
        bundleItems: offers.map((offer) => {
          offersTotal += offer.price;
          return {
            id: offer.id,
            quantity: 1,
            seller: null,
            price: offer.price,
            sellingPrice: offer.price,
          };
        }),
      };
    });

    return { itemsWithBundle, offersTotal };
  }

  splitItemsAndGifts(
    ctx: OrderContext,
    simulationItems: CheckoutOrderForm['items'],
    selectableGifts: CheckoutOrderForm['selectableGifts'],
  ): {
    items: Item[];
    gifts: Item[];
  } {
    const {
      dataDto: { gifts },
    } = ctx;
    const isGift = (priceTags: any) => {
      return priceTags.some((tags: { name: string }) =>
        tags.name.toLocaleLowerCase().includes('gift'),
      );
    };

    const itemsAndGifts: {
      items: Item[];
      gifts: Item[];
    } = simulationItems.reduce(
      (prevValue, currValue) => {
        if (currValue.priceTags && isGift(currValue.priceTags)) {
          prevValue.gifts.push({
            id: currValue.id,
            quantity: currValue.quantity,
            seller: currValue.seller,
            priceTags: currValue.priceTags,
            offerings: currValue.offerings,
            price: currValue.price,
            measurementUnit: currValue.measurementUnit,
            unitMultiplier: currValue.unitMultiplier,
            isGift: true,
          });
        } else {
          prevValue.items.push({
            id: currValue.id,
            quantity: currValue.quantity,
            seller: currValue.seller,
            priceTags: currValue.priceTags,
            offerings: currValue.offerings,
            price: currValue.price,
            measurementUnit: currValue.measurementUnit,
            unitMultiplier: currValue.unitMultiplier,
            isGift: false,
          });
        }
        return prevValue;
      },
      {
        items: [],
        gifts: [],
      },
    );

    itemsAndGifts.gifts = itemsAndGifts.gifts.filter(
      (gift: any) =>
        gifts.some((g) => g.id === gift.id) && // Validate if selected in dto
        selectableGifts.some((sg: any) =>
          // Validate if it is a selectableGift in the simulation
          sg.availableGifts.some((g: any) => g.id === gift.id),
        ),
    );

    return itemsAndGifts;
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/profile-system/profile-system.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpService } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { ProfileSystemVTEXService } from './profile-system.service';

const HttpServiceProvider = {
  provide: HttpService,
  useFactory: () => ({}),
};

describe('ProfileSystemService', () => {
  let service: ProfileSystemVTEXService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [ProfileSystemVTEXService, HttpServiceProvider],
    }).compile();

    service = module.get<ProfileSystemVTEXService>(ProfileSystemVTEXService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/profile-system/profile-system.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Injectable, HttpService } from '@nestjs/common';
import { map } from 'rxjs/operators';
import { AccountDoc } from '../../accounts/schemas/account.schema';
import { ProfileDoc } from '../../users/profiles/schemas/profile.schema';

@Injectable()
export class ProfileSystemVTEXService {
  private readonly headers;
  constructor(private httpService: HttpService) {}

  getUserInfo(account: AccountDoc, email: string, headers: any) {
    try {
      return this.httpService
        .get(
          `https://${account.account}.vtexcommercestable.com.br/api/dataentities/CL/search`,
          {
            params: {
              email: email,
              _fields:
                'id,email,firstName,lastName,phone,homePhone,businessPhone,documentType,document',
            },
            headers: {
              ...headers,
            },
          },
        )
        .pipe(
          map((response) => {
            const phone = response.data[0].phone
              ? response.data[0].phone
              : response.data[0].homePhone
              ? response.data[0].homePhone
              : response.data[0].businessPhone
              ? response.data[0].businessPhone
              : '';
            return {
              name: response.data[0].firstName,
              lastname: response.data[0].lastName,
              email: response.data[0].email,
              phoneCode: '',
              phoneNumber: phone,
              documentType: response.data[0].documentType,
              document: response.data[0].document,
              id: response.data[0].id,
            };
          }),
        )
        .toPromise()
        .catch((error) => {
          console.log('ProfileSystemVTEXService.getUserInfo', error);
          return null;
        });
    } catch {
      return null;
    }
  }

  getUserAddress(
    account: AccountDoc,
    profile: ProfileDoc,
    params: any,
    headers: any,
  ) {
    try {
      return this.httpService
        .get(
          `https://${account.account}.vtexcommercestable.com.br/api/dataentities/AD/search`,
          {
            params: {
              ...params,
              _fields: '_all',
            },
            headers: {
              ...headers,
            },
          },
        )
        .pipe(
          map((response) => {
            const addresses = [];
            response.data.forEach((data) => {
              addresses.push({
                addressName: data.addressName,
                profile: profile,
                user: profile.user,
                country: data.country,
                state: data.state,
                city: data.city,
                neighborhood: data.neighborhood,
                street: data.street,
                number: data.number || '0',
                postalCode: data.postalCode,
                reference: data.reference,
                receiverName:
                  data.receiverName ?? `${profile.name} ${profile.lastname}`,
                addressType: data.addressType,
                geoCoordinates: data.geoCoordinate
                  ? {
                      latitude: data.geoCoordinate[1]?.toString() ?? '0',
                      longitude: data.geoCoordinate[0]?.toString() ?? '0',
                    }
                  : {
                      latitude: '0',
                      longitude: '0',
                    },
              });
            });
            return addresses;
          }),
        )
        .toPromise()
        .catch((error) => {
          console.log('ProfileSystemVTEXService.getUserAddress', error);
          return null;
        });
    } catch {
      return null;
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/dtos/transactionVtex.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses/api-error';
import {
  IsNotEmpty,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { Type } from 'class-transformer';
import { PaymentVtexDto } from './paymentVtex.dto';

export class TransactionVtexDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  transactionId: string;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  merchantName: string;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => PaymentVtexDto)
  payments: PaymentVtexDto[];
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/dtos/paymentVtex.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses/api-error';
import {
  IsInt,
  IsNotEmpty,
  IsString,
  ValidationArguments,
} from 'class-validator';
import { Type } from 'class-transformer';

export class PaymentVtexDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  paymentSystem: string;

  @IsInt({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.field_integer', args),
  })
  @Type(() => Number)
  referenceValue: number;

  @IsInt({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.field_integer', args),
  })
  @Type(() => Number)
  value: number;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/dtos/orderVtex.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses/api-error';
import { IsNotEmpty, IsString, ValidationArguments } from 'class-validator';

export class OrderVtexDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  id: string;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  orderGroup: string;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  addressId: string;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  currencyCode: string;
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/orders/orders.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpService } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { OrdersVTEXService } from './orders.service';

const HttpServiceProvider = {
  provide: HttpService,
  useFactory: () => ({}),
};

describe('OrdersService', () => {
  let service: OrdersVTEXService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [OrdersVTEXService, HttpServiceProvider],
    }).compile();

    service = module.get<OrdersVTEXService>(OrdersVTEXService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/orders/orders.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Injectable } from '@nestjs/common';
import { CheckoutVTEXService } from './checkout/checkout.service';
import { CartVTEXService } from './cart/cart.service';
import { PaymentVTEXService } from './payment/payment.service';

@Injectable()
export class OrdersVTEXService {
  constructor(
    public checkout: CheckoutVTEXService,
    public cart: CartVTEXService,
    public payment: PaymentVTEXService,
  ) {}
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/orders/payment/payment.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpService, Injectable } from '@nestjs/common';
import { map } from 'rxjs/operators';
import { CreateAccountDto } from 'src/app/accounts/dtos/createAccount.dto';
import { OrderVtexDto } from '../../dtos/orderVtex.dto';
import { TransactionVtexDto } from '../../dtos/transactionVtex.dto';
import { PaymentData } from '../../../../typings/OrderContext';
import { GatewayException } from 'src/shared/exceptions/gateway-exception';

@Injectable()
export class PaymentVTEXService {
  constructor(private httpService: HttpService) {}

  async sendPaymentData(
    accountData: CreateAccountDto,
    transaction: TransactionVtexDto,
    order: OrderVtexDto,
    headers: any,
    paymentData?: PaymentData,
  ) {
    const payments = [];
    transaction.payments.forEach((payment) => {
      payments.push({
        paymentSystem: payment.paymentSystem,
        installments: 1,
        installmentsInterestRate: 0,
        installmentsValue: 0,
        Value: payment.value,
        referenceValue: payment.referenceValue,
        bin: paymentData?.bin,
        fields: {
          holderName: paymentData?.holderName,
          cardNumber: paymentData?.cardNumber,
          validationCode: paymentData?.cvv,
          accountId: (paymentData.additionalData as any)?.accountId,
          dueDate: paymentData?.expirationDate,
          addressId: order.addressId,
          bin: paymentData?.bin,
        },
        transaction: {
          id: transaction.transactionId,
          merchantName: transaction.merchantName,
        },
        currencyCode: order.currencyCode,
      });
    });

    try {
      return this.httpService
        .post(
          `https://${accountData.account}.vtexpayments.com.br/api/pub/transactions/${transaction.transactionId}/payments`,
          payments,
          {
            headers: {
              ...headers,
            },
          },
        )
        .pipe(map((response: any) => response.status))
        .toPromise();
    } catch (err) {
      throw new GatewayException(
        'VTEX: Error send payment data',
        err.response?.data,
        order,
      );
    }
  }

  async requestPaymentProcess(
    accountData: CreateAccountDto,
    checkoutCookie: string,
    order: OrderVtexDto,
    headers: any,
  ) {
    try {
      return this.httpService
        .post(
          `http://${accountData.account}.vtexcommercestable.com.br/api/checkout/pub/gatewayCallback/${order.orderGroup}`,
          null,
          {
            headers: {
              Vtex_CHKO_Auth: checkoutCookie,
              ...headers,
            },
          },
        )
        .pipe(
          map((response: any) => {
            return {
              status: response.status === 200 || response.status === 204,
              message: 'ok',
            };
          }),
        )
        .toPromise();
    } catch (err) {
      throw new GatewayException(
        'VTEX: Error send payment data',
        err.response?.data,
        order,
      );
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-checkout-service/src/app/vtex/orders/payment/payment.service.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpService } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { PaymentVTEXService } from './payment.service';

const HttpServiceProvider = {
  provide: HttpService,
  useFactory: () => ({}),
};

describe('CartVTEXService', () => {
  let service: PaymentVTEXService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [PaymentVTEXService, HttpServiceProvider],
    }).compile();

    service = module.get<PaymentVTEXService>(PaymentVTEXService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
});

```