[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/schemas/order.schema.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Account, AccountDoc } from 'src/app/accounts/schemas/account.schema';
import {
  Model,
  Document,
  Schema,
  ModelDefinition,
} from 'src/shared/utils/dynamoose-module';

interface OrderAttrs {
  country: string;
  currency: string;
  status: string;
  salesChannel: string;
  channel?: string;
  oms?: string;
  account: AccountDoc;
  accountName: string;
  creationDate: string;
  createdAt: number;
  log: string;
  shipping: {
    address: {
      id: string;
      country: string;
      state: string;
      city: string;
      street: string;
      number: string;
      postalCode: string;
      reference?: string;
      neighborhood: string;
      receiverName?: string;
      geoCoordinates: {
        latitude: string;
        longitude: string;
      };
    };
    logisticsInfo: {
      itemIndex: number;
      selectedSla: string;
      selectedDeliveryChannel: string;
    }[];
  };
  user: {
    name: string;
    lastname: string;
    documentType: string;
    document: string;
    phoneCode: string;
    phoneNumber: string;
    email: string;
  };
  items: {
    id: string;
    quantity: number;
    seller: string;
  }[];
  customData?: {
    customApps: [
      {
        id: string;
        major: number;
        fields: {
          key: string;
          value: string;
        }[];
      },
    ];
  };
}

export interface OrderDoc extends Document {
  total: number;
  totalShipping: number;
  country: string;
  currency: string;
  status: string;
  salesChannel: string;
  orderId: string;
  channel: string;
  oms: string;
  account: AccountDoc;
  accountName: string;
  creationDate: string;
  createdAt: number;
  log?: string;
  shipping: {
    address: {
      id: string;
      country: string;
      state: string;
      city: string;
      street: string;
      number: string;
      postalCode: string;
      reference: string;
      neighborhood: string;
      receiverName: string;
      geoCoordinates: {
        latitude: string;
        longitude: string;
      };
    };
    logisticsInfo: [
      {
        itemIndex: number;
        selectedSla: string;
        selectedDeliveryChannel: string;
      },
    ];
  };
  user: {
    name: string;
    lastname: string;
    documentType: string;
    document: string;
    phoneCode: string;
    phoneNumber: string;
    email: string;
  };
  items: {
    id: string;
    quantity: number;
    seller: string;
  };
  payment: {
    number: string;
    franchise: string;
    transactionId: string;
    gateway: string;
    paymentMethod: string;
    paymentSystem?: string;
    cardId: string;
  };
  customData?: {
    customApps: [
      {
        id: string;
        major: number;
        fields: {
          key: string;
          value: string;
        }[];
      },
    ];
  };
}

export type OrderModel = Model<OrderDoc, OrderAttrs>;

const OrderSchema = Schema.build({
  total: { type: Number },
  totalShipping: { type: Number },
  country: { type: String, required: true },
  currency: { type: String },
  status: {
    type: String,
    default: 'incomplete',
    index: { global: true, name: 'statusIndex' },
  },
  salesChannel: { type: String },
  orderId: { type: String, index: { global: true, name: 'orderIdIndex' } },
  channel: { type: String },
  oms: { type: String },
  creationDate: { type: String },
  createdAt: { type: Number },
  log: { type: String },
  accountName: { type: String },
  shipping: {
    type: Object,
    schema: {
      address: {
        type: Object,
        schema: {
          id: { type: String, required: true },
          country: { type: String, required: true },
          state: { type: String, required: true },
          city: { type: String, required: true },
          street: { type: String, required: true },
          number: { type: String, required: true },
          postalCode: { type: String, required: true },
          neighborhood: { type: String, required: false },
          reference: { type: String },
          receiverName: { type: String },
          geoCoordinates: {
            type: Object,
            schema: {
              latitude: { type: String, required: true },
              longitude: { type: String, required: true },
            },
          },
        },
      },
      logisticsInfo: {
        type: Array,
        schema: [
          {
            type: Object,
            schema: {
              itemIndex: { type: Number, required: true },
              selectedSla: { type: String, required: true },
              selectedDeliveryChannel: { type: String, required: true },
            },
          },
        ],
      },
    },
  },
  user: {
    type: Object,
    schema: {
      name: { type: String, required: true },
      lastname: { type: String, required: true },
      documentType: { type: String, required: true },
      document: { type: String, required: true },
      phoneCode: { type: String, required: false, default: '' },
      phoneNumber: { type: String, required: true },
      email: { type: String, required: true },
    },
  },
  items: {
    type: Array,
    schema: [
      {
        type: Object,
        schema: {
          id: { type: String, required: true },
          quantity: { type: Number, required: true },
          seller: { type: String, required: true },
        },
      },
    ],
  },
  payment: {
    type: Object,
    schema: {
      number: { type: String },
      franchise: { type: String },
      transactionId: { type: String },
      gateway: { type: String },
      paymentMethod: { type: String },
      paymentSystem: { type: String },
      cardId: { type: String },
    },
  },
  customData: {
    type: Object,
    schema: {
      customApps: {
        type: Array,
        schema: [
          {
            type: Object,
            schema: {
              id: { type: String },
              major: { type: Number },
              fields: {
                type: Array,
                schema: [
                  {
                    type: Object,
                    schema: {
                      key: { type: String },
                      value: { type: String },
                    },
                  },
                ],
              },
            },
          },
        ],
      },
    },
  },
});

export const Order: ModelDefinition = {
  name: 'orders',
  schema: OrderSchema,
  population: function (populate) {
    this.schema.schemaObject.account = {
      type: populate(Account),
      index: { global: true, name: 'accountIndex' },
    };
  },
};

```


[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/dtos/storePreferences.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

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

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

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  salesChannel: 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/orders/dtos/customDataApps.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses';
import { Type } from 'class-transformer';
import {
  IsNotEmpty,
  IsNumber,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { CustomDataFieldsDto } from './customDataFields.dto';

export class CustomDataAppsDto {
  @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),
  })
  @IsNumber(
    {},
    {
      message: (args: ValidationArguments) =>
        ApiError.parse('validations.invalid_number', args),
    },
  )
  major: number;

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

```


[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/dtos/externalAddress.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses';
import {
  IsOptional,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { GeoCoordinateDto } from 'src/app/users/addresses/dtos/geoCoordinates.dto';

export class ExternalAddressDto {
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  addressId: string;

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

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

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

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

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

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

  @ValidateNested()
  geoCoordinates: GeoCoordinateDto;

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

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

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  reference: 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/orders/dtos/logisticInfo.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses';
import { Type } from 'class-transformer';
import {
  IsNotEmpty,
  IsNumber,
  IsOptional,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { DeliveryWindowDto } from './deliveryWindow.dto';

export class LogisticInfoDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsNumber(
    {},
    {
      message: (args: ValidationArguments) =>
        ApiError.parse('validations.invalid_string', args),
    },
  )
  itemIndex: number;

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

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

  @IsOptional()
  @ValidateNested()
  @Type(() => DeliveryWindowDto)
  deliveryWindow?: DeliveryWindowDto;
}

```


[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/dtos/deliveryWindow.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

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

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  endDateUtc: 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/orders/dtos/createOrder.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses/api-error';
import {
  IsNotEmpty,
  IsOptional,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { Type } from 'class-transformer';
import { ItemDto } from './item.dto';
import { PaymentDataDto } from './paymentData.dto';
import { ProfileDto } from './profile.dto';
import { AccountDto } from './account.dto';
import { ShippingDto } from './shipping.dto';
import { OfferingDto } from './Offering.dto';
import { CustomDataDto } from './customData.dto';
import { MarketingDataDto } from './marketingData.dto';

export class CreateOrderDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => ProfileDto)
  profile: ProfileDto;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => ShippingDto)
  shipping: ShippingDto;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => AccountDto)
  account: AccountDto;

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

  @IsOptional()
  @ValidateNested()
  @Type(() => ItemDto)
  gifts?: ItemDto[];

  @IsOptional()
  @ValidateNested()
  @Type(() => OfferingDto)
  offerings?: OfferingDto[];

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => PaymentDataDto)
  payment: PaymentDataDto;

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

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

  @IsOptional()
  @ValidateNested()
  @Type(() => CustomDataDto)
  customData?: CustomDataDto;

  @IsOptional()
  @ValidateNested()
  @Type(() => MarketingDataDto)
  marketingData?: MarketingDataDto;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  authToken?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  ip: 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/orders/dtos/customData.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses';
import { Type } from 'class-transformer';
import {
  IsNotEmpty,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { CustomDataAppsDto } from './customDataApps.dto';

export class CustomDataDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => CustomDataAppsDto)
  customApps: [CustomDataAppsDto];
}

```


[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/dtos/item.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

export class ItemDto {
  @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),
  })
  @IsNumber(
    {},
    {
      message: (args: ValidationArguments) =>
        ApiError.parse('validations.invalid_string', args),
    },
  )
  quantity: number;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  seller: 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/orders/dtos/customDataFields.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

export class CustomDataFieldsDto {
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  key: string;

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  value: 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/orders/dtos/shipping.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Type } from 'class-transformer';
import {
  IsNotEmpty,
  IsOptional,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { ApiError } from '../../../shared/responses';
import { ExternalAddressDto } from './externalAddress.dto';
import { LogisticInfoDto } from './logisticInfo.dto';

export class ShippingDto {
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  addressId?: string;

  @ValidateNested()
  @IsOptional()
  @Type(() => ExternalAddressDto)
  externalAddress?: ExternalAddressDto;

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

```


[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/dtos/Offering.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

export class OfferingDto {
  @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),
  })
  parentItemId: 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/orders/dtos/profile.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

export class ProfileDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsEmail(
    {},
    {
      message: (args: ValidationArguments) =>
        ApiError.parse('validations.invalid_email', args),
    },
  )
  email: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  profileId?: string;

  @IsOptional()
  @IsBoolean({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  habeasData?: boolean;
}

```


[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/dtos/account.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

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

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

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => StorePreferencesDto)
  storePreferences: StorePreferencesDto;
}

```


[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/dtos/totalizers.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

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

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

  @IsInt({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.field_integer', args),
  })
  @Type(() => Number)
  subTotal: 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/orders/dtos/marketingData.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

export class MarketingDataDto {
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  coupon?: 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/orders/dtos/processTransaction.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../shared/responses/api-error';
import {
  IsNotEmpty,
  IsOptional,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { Type } from 'class-transformer';
import { PaymentDataDto } from './paymentData.dto';
import { CreateAccountDto } from '../../accounts/dtos/createAccount.dto';
import { ShippingDto } from './shipping.dto';
import { ProfileDto } from './profile.dto';
import { TotalizersDto } from './totalizers.dto';

export class ProcessTransactionDto {
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => ProfileDto)
  profile: ProfileDto;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => ShippingDto)
  shipping: ShippingDto;

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

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => CreateAccountDto)
  account: CreateAccountDto;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => PaymentDataDto)
  payment: PaymentDataDto;

  @IsOptional()
  omsExtraData: any;

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  version?: string;

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

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

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

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  reference?: string;

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @ValidateNested()
  @Type(() => TotalizersDto)
  totalizers: TotalizersDto;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  authToken?: 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/orders/dtos/paymentData.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

export class PaymentDataDto {
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  token?: string;

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  franchise?: string;

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  number?: string;

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

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

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  cardId?: string;

  @IsOptional()
  additionalData?: any;

  @IsOptional()
  cardContent?: any;

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  payment_method_id?: string;

  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  @IsOptional()
  issuer_id?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  cvv?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  bin?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  holderName?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  paymentSystem?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  holderDocument?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  expirationDate?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  cardNumber?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  aliasCC?: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  aliasCVV?: 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/payment-providers/types/payment-providers.type.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 { CreditPayService } from '../credit-pay/credit-pay.service';

export type PaymentProviderServices = {
  httpService: HttpService;
  configService: ConfigService;
  creditPayService: CreditPayService;
};

export enum PaymentProviderName {
  MercadoPago = 'mercadopago',
  Paymentez = 'paymentez',
  Noop = 'noop',
  CashOnDelivery = 'promissory',
  CreditPay = 'creditpay',
  Custom = 'custom',
}

export enum PaymentMethodName {
  Promissory = 'promissory',
  CreditCard = 'tc',
  BNPL = 'BNPL',
}

```


[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/credit-pay/credit-pay.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 { CreateUserCreditDto } from './dto/createUserCredit.dto';
import { ValidateCreditDto } from './dto/validateCredit.dto';
import { Credit, CreditDoc, CreditModel } from './schema/credit.schema';

@Injectable()
export class CreditPayService {
  constructor(@InjectModel(Credit.name) private creditModel: CreditModel) {}

  async createUserCredit(createUserCreditDto: CreateUserCreditDto) {
    let userCredit: CreditDoc = await this.creditModel
      .findOne({
        email: createUserCreditDto.email,
      })
      .exec();

    if (!userCredit) {
      userCredit = this.creditModel.build({
        email: createUserCreditDto.email,
        creditLimit: createUserCreditDto.creditLimit,
      });
    } else {
      userCredit.set({
        creditLimit: createUserCreditDto.creditLimit,
      });
    }

    return userCredit.save();
  }

  async chargeCredit(validateCreditDto: ValidateCreditDto) {
    const userCredit: CreditDoc = await this.creditModel
      .findOne({
        email: validateCreditDto.email,
      })
      .exec();

    userCredit.set({
      creditLimit: userCredit.creditLimit - validateCreditDto.totals,
    });

    return userCredit.save();
  }

  private calculateInstallments(total: number) {
    if (total <= 100000) {
      return 3;
    } else if (total > 100000 && total < 1000000) {
      return 12;
    } else {
      return 24;
    }
  }

  async validateCredit(validateCreditDto: ValidateCreditDto) {
    const userCredit = await this.creditModel
      .findOne({
        email: validateCreditDto.email,
      })
      .exec();

    if (!userCredit) {
      return {
        approvedCredit: 0,
        maxInstallments: 0,
      };
    }

    if (userCredit.creditLimit - validateCreditDto.totals > 0) {
      return {
        approvedCredit: validateCreditDto.totals,
        maxInstallments: this.calculateInstallments(validateCreditDto.totals),
      };
    }

    return {
      approvedCredit: 0,
      maxInstallments: 0,
    };
  }
}

```


[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/credit-pay/credit-pay.controller.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Body, Controller, Post } from '@nestjs/common';
import { CreditPayService } from './credit-pay.service';
import { CreateUserCreditDto } from './dto/createUserCredit.dto';
import { ValidateCreditDto } from './dto/validateCredit.dto';

@Controller('credit-pay')
export class CreditPayController {
  constructor(private creditPayService: CreditPayService) {}

  @Post('/user')
  createUserCredit(@Body() createUserDto: CreateUserCreditDto) {
    return this.creditPayService.createUserCredit(createUserDto);
  }

  @Post('/validate-credit')
  validateCredit(@Body() validateCreditDto: ValidateCreditDto) {
    return this.creditPayService.validateCredit(validateCreditDto);
  }
}

```


[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/credit-pay/credit-pay.controller.spec.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Test, TestingModule } from '@nestjs/testing';
import { CreditPayController } from './credit-pay.controller';
import { CreditPayService } from './credit-pay.service';

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

  beforeEach(async () => {
    const ApiServiceProvider = {
      provide: CreditPayService,
      useFactory: () => ({}),
    };

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

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

  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/payment-providers/credit-pay/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { HttpException, HttpStatus } from '@nestjs/common';
import { PaymentProvider } from '../payment-provider';
import { ValidateCreditDto } from './dto/validateCredit.dto';

export class CreditPayProvider extends PaymentProvider {
  async authorizePayment(): Promise<void> {
    const {
      profile: { email },
      totalizers: { totals },
    } = this.ctx.processTransactionDto;

    const validateCreditDto = new ValidateCreditDto();
    validateCreditDto.email = email;
    validateCreditDto.totals = totals;

    const approvedCredit = await this.services.creditPayService.validateCredit(
      validateCreditDto,
    );

    if (approvedCredit.approvedCredit === 0) {
      throw new HttpException('Credit Limit Exceeded', HttpStatus.BAD_REQUEST);
    }

    await this.services.creditPayService.chargeCredit(validateCreditDto);

    this.ctx.transaction = {
      transactionId: 'credit',
    };
  }
  capturePayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  refundPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  cancelPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  rollbackPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
}

```


[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/credit-pay/credit-pay.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 { CreditPayService } from './credit-pay.service';
import { Credit } from './schema/credit.schema';

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

  beforeEach(async () => {
    const CreditModel = {
      provide: getModelToken(Credit.name),
      useFactory: () => ({}),
    };
    const module: TestingModule = await Test.createTestingModule({
      providers: [CreditPayService, CreditModel],
    }).compile();

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

  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/payment-providers/mercadopago/mercadopago.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as mercadopago from 'mercadopago';
import { IBaseAll } from '../base/base-all.interface';
import { CardsService } from './services/cards.service';
import { PreferencesService } from './services/preferences.service';
import { TransactionService } from './services/transaction.service';

@Injectable()
export class MercadopagoService implements IBaseAll {
  cards: CardsService;
  transactions: TransactionService;
  preferences: PreferencesService;

  constructor(private readonly configService: ConfigService) {
    mercadopago.configure({
      access_token: this.configService.get('MERCADOPAGO_ACCESS_TOKEN'),
    });

    this.cards = new CardsService(mercadopago);
    this.transactions = new TransactionService(mercadopago);
    this.preferences = new PreferencesService(mercadopago);
  }
}

```


[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/mercadopago/types.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface AdditionalData {
  issuerId: string;
  installments: number;
}

export interface customerData {
  email: string;
  document: string;
  documentType: 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/payment-providers/mercadopago/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderContext } from '../../../typings/OrderContext';
import * as mercadopago from 'mercadopago';
import { CreateCardPayload } from 'mercadopago/models/cards/create-payload';
import { CreateCustomerPayload } from 'mercadopago/models/customers/create-payload.model';
import { CreatePaymentPayload } from 'mercadopago/models/payment/create-payload.model';
import { PaymentProvider } from '../payment-provider';
import { PaymentProviderServices } from '../types/payment-providers.type';
import { CardsService } from './services/cards.service';
import { TransactionService } from './services/transaction.service';
import { AdditionalData } from './types';

export class MercadoPagoProvider extends PaymentProvider {
  cards: CardsService;
  transactions: TransactionService;

  constructor(
    public services: PaymentProviderServices,
    public ctx: OrderContext,
  ) {
    super(services, ctx);

    mercadopago.configure({
      access_token: this.services.configService.get('MERCADOPAGO_ACCESS_TOKEN'),
    });

    this.cards = new CardsService(mercadopago);
    this.transactions = new TransactionService(mercadopago);
  }

  private formattedEmail(profileId: string, email: string) {
    const splittedEmail = email.split('@');
    return `${splittedEmail[0]}+${profileId}@${splittedEmail[1]}`;
  }

  private createCustomer(profileId: string, email: string) {
    const customer: CreateCustomerPayload = {
      email: this.formattedEmail(profileId, email),
    };
    return mercadopago.customers.create(customer);
  }

  private createCard(customerId: string, token: string) {
    const card: CreateCardPayload = {
      customer_id: customerId,
      token,
    };

    return mercadopago.card.create(card);
  }

  private getCustomer(profileId: string, email: string) {
    return mercadopago.customers.search({
      qs: { email: this.formattedEmail(profileId, email) },
    });
  }

  async authorizePayment(): Promise<void> {
    const {
      processTransactionDto: {
        totalizers: { totals },
        payment: { additionalData: ad, ...payment },
        reference,
        orderId,
        profile: { email },
      },
      profile: { document, documentType, id },
    } = this.ctx;

    const additionalData = ad as AdditionalData;

    const paymentData: CreatePaymentPayload = {
      transaction_amount: totals,
      token: payment.token,
      description: reference || orderId,
      installments: Number(additionalData.installments),
      payment_method_id: payment.franchise,
      issuer_id: additionalData.issuerId,
      payer: {
        email: email,
        identification: {
          number: document,
          type: documentType,
        },
      },
    };

    if (payment.cardId) {
      paymentData.payer = {
        ...paymentData.payer,
        type: 'customer',
        id: (payment as any).internalCardContent.customerId,
      };
    }

    const transaction = await mercadopago.payment.create(paymentData);

    this.ctx.transaction = {
      transactionId: transaction.body.id,
    };

    if (!payment.cardId) {
      let customerId: string;

      const customerQuery = await this.getCustomer(id, email);

      if (
        customerQuery &&
        customerQuery.body &&
        customerQuery.body.results.length === 0
      ) {
        const customerCreated = await this.createCustomer(id, email);
        customerId = customerCreated.body.id;
      } else {
        customerId = customerQuery.body.results[0].id;
      }

      const card = await this.createCard(customerId, payment.token);

      this.ctx.transaction = {
        ...this.ctx.transaction,
        cardContent: {
          cardId: card.body.id,
        },
        internalCardContent: {
          customerId,
        },
      };
    }
  }
  capturePayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  refundPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  cancelPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  rollbackPayment(): 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/payment-providers/mercadopago/mercadopago.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 { MercadopagoService } from './mercadopago.service';

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

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

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

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

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

  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/payment-providers/cashOnDelivery/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { PaymentProvider } from '../payment-provider';

export class CashOnDelivery extends PaymentProvider {
  authorizePayment(): Promise<void> {
    this.ctx.transaction = {
      transactionId: 'promissory',
    };
    return;
  }
  capturePayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  refundPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  cancelPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  rollbackPayment(): 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/payment-providers/custom/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

export class Custom extends PaymentProvider {
  constructor(
    protected services: PaymentProviderServices,
    protected ctx: OrderContext,
    protected paymentMethod: string,
  ) {
    super(services, ctx);
  }
  authorizePayment(): Promise<void> {
    this.ctx.transaction = {
      transactionId: this.paymentMethod,
    };
    return;
  }
  capturePayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  refundPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  cancelPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  rollbackPayment(): 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/payment-providers/kuikpay/kuikpay.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { CreateAccountDto } from '../../accounts/dtos/createAccount.dto';
import { PaymentDataDto } from '../../orders/dtos/paymentData.dto';
import { OrderVtexDto } from '../../vtex/dtos/orderVtex.dto';
import { PaymentVtexDto } from '../../vtex/dtos/paymentVtex.dto';
import { TransactionVtexDto } from '../../vtex/dtos/transactionVtex.dto';
import { Injectable } from '@nestjs/common';
import { PaymentProviderServices } from '../types/payment-providers.type';
import { OrderContext } from 'src/typings/OrderContext';

@Injectable()
export class KuikpayService {
  private readonly api;
  constructor(public services: PaymentProviderServices) {
    this.api = this.services.configService.get('KUIKPAY_API_PAYMENTS');
  }

  sendPayment(
    payment: PaymentVtexDto,
    orderVtex: OrderVtexDto,
    transaction: TransactionVtexDto,
    accountData: CreateAccountDto,
    checkoutCookie: any,
    hostname: string,
    paymentData?: PaymentDataDto,
    ctx?: OrderContext,
  ) {
    const installments = paymentData.additionalData?.installments
      ? paymentData.additionalData?.installments
      : 1;
    const proxy: any = {};
    //TODO: revisar accountId al eliminar PCI proxy
    const accountId = paymentData.additionalData?.accountId;
    proxy.transactionId = paymentData.additionalData?.transactionId;
    proxy.token = paymentData.token;
    proxy.aliasCC = paymentData.aliasCC;
    proxy.aliasCVV = paymentData.aliasCVV;

    const payments = {
      proxy: proxy,
      gateway: proxy.token ? 'paymentez' : 'pci',
      vtex: {
        user: {
          email: ctx.processTransactionDto.profile.email,
          document: ctx.profile.document,
        },
        payment: {
          paymentSystem: Number.parseInt(payment.paymentSystem),
          installments: Number.parseInt(installments),
          installmentsInterestRate: 0,
          installmentsValue: 0,
          value: payment.value,
          franchise: paymentData.franchise,
          referenceValue: payment.referenceValue,
          fields: {
            validationCode: paymentData.cvv,
            holderName: paymentData.holderName,
            dueDate: paymentData.expirationDate,
            addressId: orderVtex.addressId,
            number: paymentData.number,
            bin: paymentData.bin,
          },
          transaction: {
            id: transaction.transactionId,
            merchantName: transaction.merchantName,
          },
          currencyCode: orderVtex.currencyCode,
        },
        order: {
          accountName: accountData.account,
          hostname,
          VtexChkoAuth: checkoutCookie,
          orderGroup: orderVtex.orderGroup,
        },
      },
    };

    if (accountId) {
      payments.vtex.payment.fields['cardNumber'] = null;
      payments.vtex.payment.fields['accountId'] = accountId;
      payments.vtex.payment.fields.dueDate = null;
      delete payments.vtex.payment.fields.holderName;
    }

    return this.services.httpService
      .post(this.api, payments, {
        headers: {
          ...ctx?.headers,
        },
      })
      .toPromise()
      .then((r: any) => {
        if (r?.data) {
          (ctx as any).transaction = {
            aliasCC: r.data.aliasCC,
            aliasCVV: r.data.aliasCVV,
            gatewayCallbackResponse: r.data.gatewayCallbackResponse,
            token: r.data.token,
          };
        }
      });
  }
}

```


[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/kuikpay/types.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface AdditionalData {
  transactionId: string;
  installments: 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/payment-providers/kuikpay/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { GatewayException } from '../../../shared/exceptions/gateway-exception';
import { OrderContext } from '../../../typings/OrderContext';
import { PaymentProvider } from '../payment-provider';
import { PaymentProviderServices } from '../types/payment-providers.type';
import { KuikpayService } from './kuikpay.service';
import { AdditionalData } from './types';

export class KuikpayProvider extends PaymentProvider {
  constructor(
    public services: PaymentProviderServices,
    public ctx: OrderContext,
  ) {
    super(services, ctx);
  }

  async authorizePayment(): Promise<void> {
    const {
      processTransactionDto: {
        payment: { additionalData: ad, ...paymentData },
        omsExtraData: { order: orderVtex, transactions, checkoutCookie },
        account,
        hostname,
      },
    } = this.ctx;

    const additionalData = ad as AdditionalData;
    const kuikpayService = new KuikpayService(this.services);
    const transactionPromises = [];

    try {
      transactions.forEach((transaction) =>
        transaction.payments.forEach((payment) =>
          transactionPromises.push(
            kuikpayService.sendPayment(
              payment,
              orderVtex,
              transaction,
              account,
              checkoutCookie,
              hostname,
              { additionalData, ...paymentData },
              this.ctx,
            ),
          ),
        ),
      );
      await Promise.all(transactionPromises);
    } catch (err) {
      if (err.code && err.code === 'ECONNREFUSED') {
        throw new GatewayException(
          'Payments service is not online',
          err.response,
        );
      }
      throw new GatewayException(
        'Error in payment service',
        err.response?.data,
      );
    }

    this.ctx.transaction = {
      ...this.ctx.transaction,
      transactionId: additionalData?.transactionId,
    };
  }

  capturePayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  refundPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  cancelPayment(): Promise<void> {
    throw new Error('Method not implemented.');
  }
  rollbackPayment(): 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/payment-providers/base/base-all.interface.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { CardsService as MercadopagoCard } from '../mercadopago/services/cards.service';
import { TransactionService as MercadopagoTransaction } from '../mercadopago/services/transaction.service';

export interface IBaseAll {
  cards: MercadopagoCard;
  transactions: MercadopagoTransaction;
}

```


[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/base/base-transaction.interface.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ChargesDto } from './dtos/charges.dto';
import { CustomerDto } from './dtos/customer.dto';

export interface ITransactionService {
  createCharge(data: ChargesDto, customer: CustomerDto): Promise<any>;
}

```


[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/base/base-cards.interface.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { CustomerDto } from './dtos/customer.dto';

export interface ICardsService {
  listOfUserCards(customer: CustomerDto): Promise<any>;
  deleteUserCards(token: string, customer: CustomerDto): Promise<any>;
  createCard(customer: CustomerDto, data: any);
}

```


[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/credit-pay/dto/validateCredit.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

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

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsEmail(
    {},
    {
      message: (args: ValidationArguments) =>
        ApiError.parse('validations.invalid_email', args),
    },
  )
  email: 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/payment-providers/credit-pay/dto/createUserCredit.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

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

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

  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsEmail(
    {},
    {
      message: (args: ValidationArguments) =>
        ApiError.parse('validations.invalid_email', args),
    },
  )
  email: 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/payment-providers/credit-pay/schema/credit.schema.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  Model,
  Document,
  Schema,
  ModelDefinition,
} from 'src/shared/utils/dynamoose-module';

interface CreditAttrs {
  email: string;
  creditLimit: number;
}

export interface CreditDoc extends Document {
  email: string;
  creditLimit: number;
}

export type CreditModel = Model<CreditDoc, CreditAttrs>;

const CreditSchema = Schema.build({
  email: {
    type: String,
    required: true,
    index: { global: true, name: 'emailIndex' },
  },
  creditLimit: { type: Number, required: true },
});

export const Credit: ModelDefinition = {
  name: 'credits',
  schema: CreditSchema,
};

```


[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/mercadopago/config/constants.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
const DOMAIN = '';

export const MERCADOPAGO = {
  BUSINESS_NAME: 'Checkoutless',
  NOTIFICATION_URL: `https://`,
  SUCCESS_URL: `${DOMAIN}/ecommerce/success`,
  FAILURE_URL: `${DOMAIN}/ecommerce/failure`,
  PENDING_URL: `${DOMAIN}/ecommerce/pending`,
};

```


[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/mercadopago/config/preference.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { MERCADOPAGO } from './constants';
import { OrderDoc } from '../../../orders/schemas/order.schema';

//Available types in https://github.com/mercadopago/devsite-docs/issues/1173

export const preference = (order: OrderDoc) => {
  const user = order.user;
  const address = order.shipping.address;
  return {
    binary_mode: false,
    expires: true,
    expiration_date_from: new Date(Date.now()).toISOString(),
    expiration_date_to: new Date(Date.now() + 3).toISOString(),
    payer: {
      name: user.name,
      surname: user.lastname,
      email: user.email,
      phone: {
        area_code: user.phoneCode,
        number: Number(user.phoneNumber) as any,
      },
      identification: {
        type: user.documentType,
        number: user.document,
      },
      address: {
        street_name: address.neighborhood,
        zip_code: address.postalCode,
        street_number: address.street as any,
      },
    },
    shipments: {
      receiver_address: {
        zip_code: address.postalCode,
        street_number: address.street as any,
        city_name: address.city,
        state_name: address.state,
      },
    },
    external_reference: order.orderId,
    items: [
      {
        currency_id: order.currency,
        unit_price: order.total,
        category_id: `others`, // Available categories at https://api.mercadopago.com/item_categories
      },
    ],
    auto_return: 'approved',
    notification_url: MERCADOPAGO.NOTIFICATION_URL,
    back_urls: {
      success: MERCADOPAGO.SUCCESS_URL,
      failure: MERCADOPAGO.FAILURE_URL,
      pending: MERCADOPAGO.PENDING_URL,
    },
    payment_methods: {
      excluded_payment_methods: [{ id: 'amex' }],
      excluded_payment_types: [{ id: 'atm' }],
      installments: 6,
      default_installments: 6,
    },
  };
};

```


[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/mercadopago/services/transaction.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiResponse } from '../../../../shared/responses';
import { ITransactionService } from '../../base/base-transaction.interface';
import { ChargesDto } from '../../base/dtos/charges.dto';
import { CustomerDto } from '../../base/dtos/customer.dto';

export class TransactionService implements ITransactionService {
  constructor(private readonly mercadopago) {}

  createCharge(data: ChargesDto, customer: CustomerDto): Promise<any> {
    // details in https://www.mercadopago.com.mx/developers/es/guides/online-payments/checkout-api/receiving-payment-by-card
    let transaction;
    if (data.order.issuer_id)
      transaction = this.mercadopago.payment.save({
        transaction_amount: data.order.amount,
        token: data.ccToken,
        description: data.order.description,
        installments: data.order.installments,
        payment_method_id: data.order.payment_method_id,
        issuer_id: data.order.issuer_id,
        payer: {
          email: customer.email,
          identification: {
            type: customer.documentType,
            number: customer.documentNumber,
          },
        },
      });
    else
      transaction = this.mercadopago.payment.create({
        transaction_amount: data.order.amount,
        token: data.ccToken,
        description: data.order.description,
        installments: data.order.installments,
        payer: {
          type: 'customer',
          id: customer.id,
        },
      });

    return transaction
      .then((response) => {
        this.paymentCapture(response.body.id);
        return {
          transaction_id: response.body.id,
          authorization_code: response.body.status_detail,
          status: response.body.status,
        };
      })
      .catch((error) => {
        console.log(error);
        throw ApiResponse.errorWithObject(
          'errors.mercadopago_create_transaction',
          { error: error },
        );
      });
  }

  private paymentCapture(paymentId: number) {
    // acretited payment after being authorized
    return this.mercadopago.payment.capture(
      paymentId,
      this.mercadopago,
      (error, response) => {
        if (error) {
          console.log(error);
        } else {
          console.log(response);
        }
      },
    );
  }
  /*createOtherPayment(payment: PaymentDto, order: OrderDoc) {
    // details in https://www.mercadopago.com.mx/developers/es/guides/online-payments/checkout-api/other-payment-ways
    const user = order.user;
    return this.mercadopago.payment
      .create({
        ...payment,
        payer: {
          email: user.email,
        },
      })
      .then((response) => {
        this.paymentCapture(response.body.id);
        return {
          status: response.body.status,
          status_detail: response.body.status_detail,
          id: response.body.id,
          transaction_details: response.body.transaction_details,
        };
      })
      .catch((error) => {
        console.log(error);
        throw ApiResponse.errorWithObject(
          'errors.mercadopago_create_transaction',
          { error: error },
        );
      });
  }*/

  getPaymentMethods() {
    return this.mercadopago
      .get('/v1/payment_methods')
      .then((response) => response.response)
      .catch((error) => error);
  }
}

```


[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/mercadopago/services/cards.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ICardsService } from '../../base/base-cards.interface';
import { CustomerDto } from '../../base/dtos/customer.dto';

export class CardsService implements ICardsService {
  constructor(private readonly mercadopago) {}

  createCard(customer, data): Promise<any> {
    const saveCard = (customerData) => {
      const card_data = {
        token: data.token,
        customer: customerData.id,
        issuer_id: data.issuer_id,
        payment_method_id: data.payment_method_id,
      };

      return this.mercadopago.cards.create(card_data).then(function (card) {
        return card;
      });
    };

    if (!customer.id) {
      const customer_data = { email: customer.email };

      return this.mercadopago.customers
        .create(customer_data)
        .then((customerData) => {
          return saveCard(customerData);
        });
    } else {
      const filters = {
        id: customer.id,
      };

      this.mercadopago.customers
        .search({
          qs: filters,
        })
        .then((customerData) => {
          return saveCard(customerData);
        });
    }
  }

  listOfUserCards(customer: CustomerDto): Promise<any> {
    const filters = {
      id: customer.id,
    };
    return this.mercadopago.customers
      .search({
        qs: filters,
      })
      .then((customerData) => {
        return customerData;
      });
  }

  deleteUserCards(token: string, customer: CustomerDto): Promise<any> {
    throw new Error('Method not implemented.');
  }
}

```


[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/mercadopago/services/preferences.service.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { OrderDoc } from '../../../orders/schemas/order.schema';
import { preference } from '../config/preference';

export class PreferencesService {
  constructor(private readonly mercadopago) {}

  createPreference(order: OrderDoc) {
    return this.mercadopago.preferences
      .create(preference(order))
      .then((res) => res.body)
      .catch((error) => error);
  }
}

```


[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/base/dtos/orders.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
export class OrdersDto {
  amount: number;
  description: string;
  dev_reference?: string;
  vat?: number;
  installments?: number;
  payment_method_id?: any;
  issuer_id?: any;
}

```


[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/base/dtos/customer.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
export class CustomerDto {
  constructor(o: CustomerDto) {
    Object.assign(this, o);
  }

  email: string;
  id: any;
  documentType?: string;
  documentNumber?: 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/payment-providers/base/dtos/charges.dto.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ApiError } from '../../../../shared/responses';
import { Type } from 'class-transformer';
import {
  IsEmail,
  IsNotEmpty,
  IsOptional,
  IsString,
  ValidateNested,
  ValidationArguments,
} from 'class-validator';
import { OrdersDto } from './orders.dto';

export class ChargesDto {
  /*cardToken arg*/
  //validations
  @IsNotEmpty({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.not_empty', args),
  })
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  //field
  ccToken: string;

  @IsOptional()
  @IsString({
    message: (args: ValidationArguments) =>
      ApiError.parse('validations.invalid_string', args),
  })
  cvv?: string;

  /*order field*/
  @ValidateNested()
  @Type(() => OrdersDto)
  order: OrdersDto;
}

```


[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/types/services.type.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
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';

export type ChannelServices = {
  profilesService: ProfilesService;
  addressesService: AddressesService;
  accountsServices: AccountsService;
  cardsServices: CardsService;
};

export enum ChannelName {
  Kuikpay = 'kuikpay',
  Checkout = 'checkout',
  Whatsapp = 'whatsapp',
}

```


[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/standard/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AccountDoc } from '../../accounts/schemas/account.schema';
import { OrderDoc, OrderModel } from '../../orders/schemas/order.schema';
import { PaymentMethodName } from '../../payment-providers/types/payment-providers.type';
import { AddressDoc } from '../../users/addresses/schemas/address.schema';
import { ProfileDoc } from '../../users/profiles/schemas/profile.schema';
import { NotFoundException } from '../../../shared/exceptions/not-found-exception';
import { Channel } from '../channel';
import { decrypt } from 'src/shared/utils/encription';

export class StandardChannel extends Channel {
  async prepare(): Promise<void> {
    const {
      dataDto: {
        profile: { email },
        account: { accountName },
        shipping: { addressId, logisticsInfo },
      },
      headers,
    } = this.ctx;

    const promises: [
      Promise<ProfileDoc>,
      Promise<AddressDoc> | AddressDoc,
      Promise<AccountDoc>,
      Promise<void>,
    ] = [
      this.findProfile(email, accountName, headers),
      this.findAddress(addressId),
      this.findAccount(accountName),
      Promise.resolve(),
    ];

    const card = {
      token: this.ctx.dataDto.payment.token,
      franchise: this.ctx.dataDto.payment.franchise,
      number: this.ctx.dataDto.payment.number,
      gateway: this.ctx.dataDto.payment.gateway,
      paymentMethod: this.ctx.dataDto.payment.paymentMethod,
      paymentSystem: this.ctx.dataDto.payment.additionalData?.['paymentSystem'],
      cardId: this.ctx.dataDto.payment.cardId,
      bin: this.ctx.dataDto.payment.bin,
      holderName: this.ctx.dataDto.payment.holderName,
      holderDocument: this.ctx.dataDto.payment.holderDocument,
      expirationDate: this.ctx.dataDto.payment.expirationDate,
      cardNumber: this.ctx.dataDto.payment.cardNumber,
      additionalData: this.ctx.dataDto.payment.additionalData,
      cardContent: null,
      aliasCC: null,
      aliasCVV: null,
      internalCardContent: null,
      cvv: this.ctx.dataDto.payment.cvv,
    };

    if (this.ctx.dataDto.payment.cardId) {
      promises[3] = new Promise<any>(async (resolve) => {
        const cardData = await this.findCard();
        if (cardData) {
          card.token = decrypt(cardData.token);
          card.franchise = cardData.franchise;
          card.number = cardData.number;
          card.cardContent = cardData.cardContent;
          card.internalCardContent = cardData.internalCardContent;
          card.bin = cardData.bin || card.bin;
          card.holderName = cardData.holderName;
          card.aliasCC = cardData.aliasCC;
          card.expirationDate = cardData.expirationDate;
          card.cardNumber = cardData.cardNumber;
          card.holderDocument = cardData.holderDocument;
        }
        resolve(null);
      });
    }

    const [profile, address, account] = await Promise.all(promises);

    if (!profile) {
      throw new NotFoundException('errors.user_doesnt_exist');
    }

    if (
      !(address && address.geoCoordinates) &&
      logisticsInfo.find((lgi) => lgi.selectedDeliveryChannel === 'delivery')
    ) {
      throw new NotFoundException('errors.address_doesnt_exist');
    }
    const additionalData: any = card.additionalData;
    if (
      !card ||
      (card.paymentMethod === PaymentMethodName.CreditCard &&
        card &&
        !(
          card.token ||
          card.cardNumber ||
          additionalData?.transactionId ||
          card.aliasCVV ||
          additionalData?.accountId
        ))
    ) {
      throw new NotFoundException('errors.card_doesnt_exist');
    }

    if (!account) {
      throw new NotFoundException('errors.card_doesnt_exist');
    }

    this.ctx.profile = profile;
    this.ctx.addresses = [address];
    this.ctx.account = account;
    this.ctx.payment = card;

    this.ctx.queueMessage.profile.profileId = profile.id;
    this.ctx.queueMessage.payment = card;
    this.ctx.queueMessage.account = {
      account: account.account,
      additionalData: account.additionalData?.reduce<Record<string, string>>(
        (
          prev: Record<string, string>,
          item: { key: string; value: string },
        ) => {
          return {
            ...prev,
            [item.key]: item.value,
          };
        },
        {},
      ),
    };
  }

  async createOrder(orderModel: OrderModel): Promise<void> {
    const {
      profile,
      addresses,
      account,
      dataDto: {
        channel,
        oms,
        shipping: { logisticsInfo },
        items,
        account: {
          storePreferences: { salesChannel, currencyCode, countryCode },
        },
        customData,
      },
    } = this.ctx;

    const dataAdress = addresses[0] || addresses[1];
    const order = orderModel.build({
      channel,
      oms,
      account,
      accountName: account.account,
      creationDate: new Date().toISOString(),
      createdAt: Date.now(),
      log: '',
      user: {
        document: profile.document,
        documentType: profile.documentType,
        lastname: profile.lastname,
        name: profile.name,
        phoneNumber: profile.phoneNumber,
        phoneCode: profile.phoneCode,
        email: profile.email,
      },
      shipping: {
        address: {
          id: dataAdress.id,
          street: dataAdress.street,
          number: dataAdress.number,
          city: dataAdress.city,
          state: dataAdress.state,
          country: dataAdress.country,
          geoCoordinates: dataAdress.geoCoordinates,
          postalCode: dataAdress.postalCode,
          reference: dataAdress.reference,
          receiverName: dataAdress.receiverName,
          neighborhood: dataAdress.neighborhood,
        },
        logisticsInfo: logisticsInfo.map((logisticInfo) => ({
          itemIndex: logisticInfo.itemIndex,
          selectedDeliveryChannel: logisticInfo.selectedDeliveryChannel,
          selectedSla: logisticInfo.selectedSla,
        })),
      },
      country: countryCode,
      currency: currencyCode,
      salesChannel,
      status: 'pending',
      items: items.map((item) => ({
        id: item.id,
        quantity: item.quantity,
        seller: item.seller,
      })),
      customData: customData,
    });

    this.ctx.order = await order.save();
    this.ctx.queueMessage.orderId = this.ctx.order.id;
  }

  async prepareProcessTransaction(orderModel: OrderModel): Promise<void> {
    const {
      orderId,
      profile: { profileId },
    } = this.ctx.processTransactionDto;

    const promises: [Promise<ProfileDoc>, Promise<OrderDoc>] = [
      this.findProfileById(profileId),
      orderModel.get(orderId),
    ];

    const [profile, order] = await Promise.all(promises);

    this.ctx.profile = profile;
    this.ctx.order = order;
  }

  async onProcessTransaction(): Promise<void> {
    const {
      order,
      profile,
      processTransactionDto: {
        account,
        payment,
        omsExtraData: { order: orderVtex },
        totalizers,
        profile: { habeasData },
        shipping: { addressId },
      },
      transaction: { transactionId, token },
    } = this.ctx;

    const accountId = payment.additionalData?.accountId;
    if (!accountId) {
      if (
        !payment.cardId &&
        payment.paymentMethod === PaymentMethodName.CreditCard
      ) {
        const cardData = await this.createCard();

        payment.cardId = cardData.id;
      } else if (payment.cardId) {
        if (payment.bin) await this.updateCardData({ bin: payment.bin });
        if (payment.paymentSystem)
          await this.updateCardData({ paymentSystem: payment.paymentSystem });
        if (token && account.additionalData?.paymentez == 'true')
          await this.updateCardData({ token });
      }

      profile.set({
        selectedPayment: {
          paymentMethod: payment.paymentMethod,
          card: payment.cardId,
        },
      });
    }

    order.set({
      orderId: orderVtex.orderGroup,
      total: totalizers.totals,
      totalShipping: totalizers.shippingTotal,
      status: 'approved',
      payment: {
        number: payment.number,
        franchise: payment.franchise,
        transactionId: transactionId,
        gateway: payment.gateway,
        cardId: accountId || (payment.cardId && payment.cardId.toString()),
        paymentMethod: payment.paymentMethod,
        paymentSystem: payment.paymentSystem,
      },
    });

    await order.save();

    profile.set({
      habeasData: !habeasData ? profile.habeasData : habeasData,
    });

    if (addressId)
      profile.set({
        selectedAddress: addressId,
      });

    await profile.save();

    this.ctx.order = order;
  }

  async cancelOrder(orderModel: OrderModel, log = ''): Promise<void> {
    const {
      profile,
      addresses,
      account,
      payment,
      vtex: { order: orderVtex = {} },
      queueMessage: { totalizers },
      dataDto: {
        channel,
        oms,
        shipping: { logisticsInfo },
        items,
        account: {
          storePreferences: { salesChannel, currencyCode, countryCode },
        },
        customData,
      },
    } = this.ctx;

    const dataAdress = addresses[0] || addresses[1];
    const order = orderModel.build({
      channel,
      oms,
      account,
      accountName: account.account,
      creationDate: new Date().toISOString(),
      createdAt: Date.now(),
      log,
      orderId: orderVtex.orderGroup || 'null',
      user: {
        document: profile.document,
        documentType: profile.documentType,
        lastname: profile.lastname,
        name: profile.name,
        phoneNumber: profile.phoneNumber,
        phoneCode: profile.phoneCode,
        email: profile.email,
      },
      shipping: {
        address: {
          id: dataAdress.id,
          street: dataAdress.street,
          number: dataAdress.number,
          city: dataAdress.city,
          state: dataAdress.state,
          country: dataAdress.country,
          geoCoordinates: dataAdress.geoCoordinates,
          postalCode: dataAdress.postalCode,
          reference: dataAdress.reference,
          receiverName: dataAdress.receiverName,
          neighborhood: dataAdress.neighborhood,
        },
        logisticsInfo: logisticsInfo.map((logisticInfo) => ({
          itemIndex: logisticInfo.itemIndex,
          selectedDeliveryChannel: logisticInfo.selectedDeliveryChannel,
          selectedSla: logisticInfo.selectedSla,
        })),
      },
      country: countryCode,
      currency: currencyCode,
      salesChannel,
      status: 'cancelled',
      items: items.map((item) => ({
        id: item.id,
        quantity: item.quantity,
        seller: item.seller,
      })),
      customData: customData,
      total: totalizers.totals,
      totalShipping: totalizers.shippingTotal,
      payment: {
        number: payment.number,
        franchise: payment.franchise,
        transactionId: '',
        gateway: payment.gateway,
        cardId: '',
        paymentMethod: payment.paymentMethod,
        paymentSystem: payment.paymentSystem,
      },
    });

    this.ctx.order = await order.save();
    this.ctx.queueMessage.orderId = this.ctx.order.id;
  }

  async cancelOrderProcessTransaction(log = ''): Promise<void> {
    const {
      order,
      processTransactionDto: {
        payment,
        omsExtraData: { order: orderVtex },
        totalizers,
      },
    } = this.ctx;

    order.set({
      orderId: orderVtex.orderGroup,
      total: totalizers.totals,
      totalShipping: totalizers.shippingTotal,
      status: 'cancelled',
      log,
      payment: {
        number: payment.number,
        franchise: payment.franchise,
        transactionId: '',
        gateway: payment.gateway,
        cardId: '',
        paymentMethod: payment.paymentMethod,
        paymentSystem: payment.paymentSystem,
      },
    });

    await order.save();

    this.ctx.order = 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/channels/kuikpay/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { StandardChannel } from '../standard';

export class KuikpayChannel extends StandardChannel {}

```


[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/whatsapp/index.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { StandardChannel } from '../standard';

export class WhatsappChannel extends StandardChannel {}

```


[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/typings/vtex/checkout.d.ts from the mycheckout-checkout-service VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface CheckoutOrderForm {
  orderFormId: string;
  salesChannel: string;
  country: string;
  loggedIn: boolean;
  isCheckedIn: boolean;
  storeId: string | null;
  checkedInPickupPointId: string | null;
  allowManualPrice: boolean;
  canEditData: boolean;
  userProfileId: string | null;
  userType: string | null;
  ignoreProfileData: boolean;
  value: number;
  messages: any[];
  items: OrderFormItem[];
  selectableGifts: any[];
  totals: Array<{
    id: string;
    name: string;
    value: number;
  }>;
  logisticsInfo: LogisticsInfo[] | null;
  clientProfileData: ClientProfileData | null;
  paymentData: PaymentData;
  marketingData: OrderFormMarketingData | null;
  sellers: Array<{
    id: string;
    name: string;
    logo: string;
  }>;
  clientPreferencesData: {
    locale: string;
    optinNewsLetter: any | null;
  };
  commercialConditionData: any | null;
  storePreferencesData: {
    countryCode: string;
    currencyCode: string;
    currencyFormatInfo: {
      currencyDecimalDigits: number;
      currencyDecimalSeparator: string;
      currencyGroupSeparator: string;
      currencyGroupSize: number;
      startsWithCurrencySymbol: boolean;
    };
    currencyLocale: string;
    currencySymbol: string;
    saveUserData: boolean;
    timeZone: string;
  };
  giftRegistryData: any | null;
  openTextField: any | null;
  invoiceData: any | null;
  customData: any | null;
  itemMetadata: {
    items: MetadataItem[];
  };
  hooksData: any | null;
  ratesAndBenefitsData: {
    rateAndBenefitsIdentifiers: any[];
    teaser: any[];
  };
  subscriptionData: SubscriptionData | null;
  itemsOrdination: any | null;
}

interface OrderFormItem {
  id: string;
  name: string;
  detailUrl: string;
  imageUrl: string;
  skuName: string;
  quantity: number;
  uniqueId: string;
  productId: string;
  refId: string;
  ean: string;
  priceValidUntil: string;
  price: number;
  tax: number;
  listPrice: number;
  sellingPrice: number;
  rewardValue: number;
  isGift: boolean;
  parentItemIndex: number | null;
  parentAssemblyBinding: string | null;
  productCategoryIds: string;
  priceTags: string[];
  manualPrice: number;
  measurementUnit: string;
  additionalInfo: {
    brandName: string;
    brandId: string;
    offeringInfo: any | null;
    offeringType: any | null;
    offeringTypeId: any | null;
  };
  offerings: any;
  productCategories: Record<string, string>;
  productRefId: string;
  seller: string;
  sellerChain: string[];
  availability: string;
  unitMultiplier: number;
  skuSpecifications: SKUSpecification[];
}

interface SKUSpecification {
  fieldName: string;
  fieldValues: string[];
}

interface MetadataItem {
  id: string;
  name: string;
  imageUrl: string;
  detailUrl: string;
  seller: string;
  assemblyOptions: AssemblyOption[];
  skuName: string;
  productId: string;
  refId: string;
  ean: string | null;
}

interface CompositionItem {
  id: string;
  minQuantity: number;
  maxQuantity: number;
  initialQuantity: number;
  priceTable: string;
  seller: string;
}

interface Composition {
  minQuantity: number;
  maxQuantity: number;
  items: CompositionItem[];
}

interface AssemblyOption {
  id: string;
  name: string;
  composition: Composition | null;
}

interface SubscriptionDataEntry {
  executionCount: number;
  itemIndex: number;
  plan: {
    frequency: {
      interval: number;
      periodicity: 'YEAR' | 'MONTH' | 'WEEK' | 'DAY';
    };
    type: string;
    // validity: {};
  };
}

interface SubscriptionData {
  subscriptions: SubscriptionDataEntry[];
}

interface ShippingData {
  address: CheckoutAddress | null;
  logisticsInfo: LogisticsInfo[];
  selectedAddresses: CheckoutAddress[];
  availableAddresses: CheckoutAddress[];
  pickupPoints: PickupPoint[];
}

interface PickupPoint {
  friendlyName: string;
  address: CheckoutAddress;
  additionalInfo: string;
  id: string;
  businessHours: BusinessHour[];
}

interface LogisticsInfo {
  addressId: string | null;
  deliveryChannels: DeliveryChannel[];
  itemId: string;
  itemIndex: number;
  shipsTo: string[];
  slas: SLA[];
  selectedDeliveryChannel: string | null;
  selectedSla: string | null;
}

interface DeliveryChannel {
  id: string;
}

interface SLA {
  id: string;
  deliveryChannel: string;
  name: string;
  deliveryIds: DeliveryId[];
  shippingEstimate: string;
  shippingEstimateDate: string | null;
  lockTTL: string | null;
  availableDeliveryWindows: any[];
  deliveryWindow: string | null;
  price: number;
  listPrice: number;
  tax: number;
  pickupStoreInfo: {
    isPickupStore: boolean;
    friendlyName: string | null;
    address: CheckoutAddress | null;
    additionalInfo: any | null;
    dockId: string | null;
  };
  pickupPointId: string | null;
  pickupDistance: number | null;
  polygonName: string | null;
  transitTime: string | null;
}

interface DeliveryId {
  courierId: string;
  warehouseId: string;
  dockId: string;
  courierName: string;
  quantity: number;
}

interface CheckoutAddress {
  addressId: string;
  addressType: string;
  city: string | null;
  complement: string | null;
  country: string;
  geoCoordinates: number[];
  neighborhood: string | null;
  number: string | null;
  postalCode: string | null;
  receiverName: string | null;
  reference: string | null;
  state: string | null;
  street: string | null;
  isDisposable: boolean;
}

interface BusinessHour {
  DayOfWeek: number;
  ClosingTime: string;
  OpeningTime: string;
}

interface ClientProfileData {
  email: string;
  firstName: string;
  lastName: string;
  document: string;
  documentType: string;
  phone: string;
  corporateName: string;
  tradeName: string;
  corporateDocument: string;
  stateInscription: string;
  corporatePhone: string;
  isCorporate: boolean;
  profileCompleteOnLoading: boolean;
  profileErrorOnLoading: boolean;
  customerClass: string;
}

interface PaymentData {
  installmentOptions: Array<{
    paymentSystem: string;
    bin: string | null;
    paymentName: string | null;
    paymentGroupName: string | null;
    value: number;
    installments: Array<{
      count: number;
      hasInterestRate: false;
      interestRate: number;
      value: number;
      total: number;
      sellerMerchantInstallments: Array<{
        count: number;
        hasInterestRate: false;
        interestRate: number;
        value: number;
        total: number;
      }>;
    }>;
  }>;
  paymentSystems: Array<{
    id: string;
    name: string;
    groupName: string;
    validator: {
      regex: string;
      mask: string;
      cardCodeRegex: string;
      cardCodeMask: string;
      weights: number[];
      useCvv: boolean;
      useExpirationDate: boolean;
      useCardHolderName: boolean;
      useBillingAddress: boolean;
    };
    stringId: string;
    template: string;
    requiresDocument: boolean;
    isCustom: boolean;
    description: string | null;
    requiresAuthentication: boolean;
    dueDate: string;
    availablePayments: any | null;
  }>;
  payments: any[];
  giftCards: any[];
  giftCardMessages: any[];
  availableAccounts: any[];
  availableTokens: any[];
}

interface OrderFormMarketingData {
  utmCampaign?: string;
  utmMedium?: string;
  utmSource?: string;
  utmiCampaign?: string;
  utmiPart?: string;
  utmipage?: string;
  marketingTags?: string;
  coupon?: string;
}

interface ItemInput {
  id: string;
  quantity: number;
  seller: string;
}

interface LogisticInfoInput {
  itemIndex: number;
  selectedSla: string;
  selectedDeliveryChannel: string;
  deliveryWindow?: { startDateUtc: string; endDateUtc: string };
}

```