[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 marketplace-financial-commission/node/services/searchOrdersService.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { orderDetailCommission } from '../middlewares/orders/orderDetailCommission'
import { orderListSeller } from '../middlewares/orders/orderListSeller'

export const searchOrdersService = async (
  searchOrdersParams: SearchOrdersServiceRequest,
  ctx: Context
) => {
  const { dateStart, dateEnd, sellerName, page, perpage } = searchOrdersParams

  const status = searchOrdersParams.status as string

  const listOrders = await orderListSeller(
    ctx,
    sellerName,
    dateStart,
    dateEnd,
    page,
    perpage,
    status
  )

  const ordersDetailCommission = await orderDetailCommission(ctx, listOrders)

  const resultDetail: OrdersResponse = {
    data: ordersDetailCommission,
    paging: listOrders.paging,
  }

  return { status: 200, resultDetail }
}

```


[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 marketplace-financial-commission/node/services/getTokenService.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { NotFoundError } from '@vtex/api'

import { config } from '../constants'

export const getTokenService = async (seller: Seller, ctx: Context) => {
  const {
    clients: { vbase },
  } = ctx

  let vbaseData: TokenConfiguration | undefined
  const accountMarketplace = ctx.vtex.account

  const { name, account } = seller as Seller
  const keyBucket = `${accountMarketplace}-${name}-${account}`

  try {
    vbaseData = await vbase.getJSON<TokenConfiguration>(
      config.BUCKET_VBASE_TOKEN,
      keyBucket
    )
  } catch (err) {
    throw new NotFoundError('Seller not configured')
  }

  return {
    status: 200,
    resultGetToken: vbaseData,
  }
}

```


[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 marketplace-financial-commission/node/services/createTokenMarketplaceService.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { config } from '../constants'
import { createKeyToken } from '../utils'

export const createTokenMarketplaceService = async (
  accountMarketplace: string,
  ctx: Context
) => {
  const {
    clients: { vbase },
  } = ctx

  const date = new Date()
  const creationDate = date.toISOString()

  const autheticationToken = createKeyToken()

  const keyBucket = `${accountMarketplace}`

  let vbaseData: TokenConfiguration | undefined
  let lastModificationDate

  try {
    vbaseData = await vbase.getJSON<TokenConfiguration>(
      config.BUCKET_VBASE_TOKEN,
      keyBucket
    )
  } catch (err) {
    console.info('Token new')
  }

  if (vbaseData) {
    lastModificationDate = creationDate
  }

  const vbaseBody: TokenConfiguration = {
    account: accountMarketplace,
    autheticationToken,
    creationDate: vbaseData?.creationDate as string,
    enabled: true,
    name: accountMarketplace,
    id: accountMarketplace,
    lastModificationDate,
  }

  const resultVBase = await vbase.saveJSON(
    config.BUCKET_VBASE_TOKEN,
    keyBucket,
    vbaseBody
  )

  return {
    status: 200,
    resultCreateToken: {
      message: 'Successful token creation',
      accountId: accountMarketplace,
      autheticationToken,
      creationDate,
      resultVBase,
    },
  }
}

```


[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 marketplace-financial-commission/node/services/getTokenMarketplaceService.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { NotFoundError } from '@vtex/api'

import { config } from '../constants'

export const getTokenMarketplaceService = async (
  accountMarketplace: string,
  ctx: Context
) => {
  const {
    clients: { vbase },
  } = ctx

  let vbaseData: TokenConfiguration | undefined

  const keyBucket = `${accountMarketplace}`

  try {
    vbaseData = await vbase.getJSON<TokenConfiguration>(
      config.BUCKET_VBASE_TOKEN,
      keyBucket
    )

    console.info({ vbaseData })
  } catch (err) {
    throw new NotFoundError('Marketplace not configured')
  }

  return {
    status: 200,
    resultGetToken: vbaseData,
  }
}

```


[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 marketplace-financial-commission/node/services/invoicingProcess.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { config, JOB_STATUS } from '../constants'
import { draftInvoice } from '../utils/draftInvoice'

interface JobHistory {
  referenceId: string | null
  sellerId: string
  status: JobStatus
  message: string | null
}

type JobStatus = 'ONGOING' | 'COMPLETE' | 'ERROR' | 'OMITTED'

/**
 * @description
 * Attempts to save a Commission Invoice document in MasterData.
 * @param sellerData
 * Data required to submit a document to the data entity
 * - id (Seller id)
 * - name (Seller name)
 * - email (Seller email)
 * - startDate (Orders lookup start)
 * - endDate (Orders lookup end)
 * @param automated
 * Used to either state the invoice was made manually or automatically
 * @returns
 * - If no orders are available, returns an 'omitted' message
 * - If the process completed, returns the masterdata document ID
 */
export const invoicingProcess = async (
  ctx: Context,
  sellerData: SellerInvoice,
  automated?: boolean
): Promise<string> => {
  const {
    clients: { vbase, commissionInvoices, mail },
  } = ctx

  const [today] = new Date().toISOString().split('T')

  const { id: sellerId, name: SELLER_NAME, email } = sellerData

  const BUCKET = automated ? config.AUTO_JOB_BUCKET : config.MANUAL_JOB_BUCKET

  const HISTORY = {
    referenceId: null,
    sellerId,
    status: JOB_STATUS.ONGOING,
    message: null,
  }

  await vbase.saveJSON<JobHistory>(BUCKET, SELLER_NAME, HISTORY)

  let invoice = await draftInvoice(ctx, sellerData)

  if (!invoice) {
    await vbase.saveJSON<JobHistory>(BUCKET, SELLER_NAME, {
      ...HISTORY,
      status: JOB_STATUS.OMITTED,
      message: `No eligible orders to invoice between ${sellerData.startDate} and ${sellerData.endDate}`,
    })

    return JOB_STATUS.OMITTED
  }

  if (automated) {
    invoice = { ...invoice, comment: `Invoice manually created on ${today}` }
  }

  const document = await commissionInvoices.save(invoice)

  await mail.sendMail({
    templateName: config.INVOICE_MAIL_TEMPLATE,
    jsonData: {
      message: {
        to: email,
      },
      ...invoice,
    },
  })

  await vbase.saveJSON<JobHistory>(BUCKET, SELLER_NAME, {
    ...HISTORY,
    referenceId: document.DocumentId,
    status: JOB_STATUS.COMPLETE,
  })

  /**
   * @todo save new dates for seller settings
   */

  return document.DocumentId
}

```


[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 marketplace-financial-commission/node/services/updateTokenService.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { NotFoundError, UserInputError } from '@vtex/api'

import { config } from '../constants'

export const updateTokenService = async (
  seller: Seller,
  body: RequestUpdateToken,
  ctx: Context
) => {
  const {
    clients: { vbase },
  } = ctx

  const { enabled } = body

  if (enabled === undefined) {
    throw new UserInputError('field enabled is required')
  }

  const date = new Date()
  const lastModificationDate = date.toISOString()

  const accountMarketplace = ctx.vtex.account

  const { id, name, account } = seller as Seller
  const sellerId = id as string

  const keyBucket = `${accountMarketplace}-${name}-${account}`

  let vbaseData: TokenConfiguration | undefined

  try {
    vbaseData = await vbase.getJSON<TokenConfiguration>(
      config.BUCKET_VBASE_TOKEN,
      keyBucket
    )
  } catch (err) {
    throw new NotFoundError('Seller not configured')
  }

  const vbaseBody: TokenConfiguration = enabled
    ? {
        ...vbaseData,
        enabled,
        lastModificationDate,
      }
    : {
        ...vbaseData,
        enabled,
        lastModificationDate,
        autheticationToken: '',
      }

  const resultVBase = await vbase.saveJSON(
    config.BUCKET_VBASE_TOKEN,
    keyBucket,
    vbaseBody
  )

  return {
    status: 200,
    resultUpdateToken: {
      message: 'Successful token update',
      accountId: sellerId,
      lastModificationDate,
      resultVBase,
    },
  }
}

```


[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 marketplace-financial-commission/node/services/searchStatisticsService.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable no-await-in-loop */
/* eslint-disable @typescript-eslint/restrict-plus-operands */
import type { StatisticsDashboard } from 'vtex.marketplace-financial-commission'

export const searchStatisticsService = async (
  ctx: Context,
  searchStatsDashboardParams: SearchStatsServiceRequest
) => {
  const {
    clients: { statisticsDashboardClientMD },
  } = ctx

  const { dateStart, dateEnd } = searchStatsDashboardParams
  const statisticsArray: StatisticsDashboard[] = []

  let pagination = {
    page: 1,
    pageSize: 100,
  }

  const where = `dateCut between ${dateStart} AND ${dateEnd}`

  let responseSearchMD = await statisticsDashboardClientMD.searchRaw(
    pagination,
    ['dateCut,statistics'],
    'createdIn',
    where
  )

  let statisticsArrayTemp = responseSearchMD.data as StatisticsDashboard[]

  statisticsArrayTemp.forEach((statistics) => {
    statisticsArray.push(statistics)
  })

  const totalRecords = responseSearchMD.pagination.total
  let currentRecords = responseSearchMD.pagination.pageSize

  if (totalRecords > currentRecords) {
    while (totalRecords > currentRecords) {
      const page = pagination.page + 1

      pagination = {
        page,
        pageSize: 100,
      }

      responseSearchMD = await statisticsDashboardClientMD.searchRaw(
        pagination,
        ['dateCut,statistics'],
        'createdIn',
        where
      )

      statisticsArrayTemp = responseSearchMD.data as StatisticsDashboard[]

      statisticsArrayTemp.forEach((statistics) => {
        statisticsArray.push(statistics)
      })

      currentRecords += responseSearchMD.pagination.pageSize

      if (currentRecords >= totalRecords) {
        break
      }
    }
  }

  const ordersCount = Number(
    statisticsArray
      .reduce((total, count) => (total += count.statistics.ordersCount), 0)
      .toFixed(2)
  ) as number

  const totalComission = Number(
    statisticsArray
      .reduce((total, comis) => (total += comis.statistics.totalComission), 0)
      .toFixed(2)
  )

  const totalOrderValue = Number(
    statisticsArray
      .reduce((total, value) => (total += value.statistics.totalOrderValue), 0)
      .toFixed(2)
  )

  const statistics: StatsSeller = {
    ordersCount,
    totalComission,
    totalOrderValue,
  }

  const statisticsDashboard: StatisticsGeneralDashboard = {
    dateStart,
    dateEnd,
    statistics,
  }

  return { status: 200, statisticsDashboard }
}

```


[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 marketplace-financial-commission/node/services/searchSellersService.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable no-await-in-loop */
/* eslint-disable @typescript-eslint/restrict-plus-operands */
import { config } from '../constants'
import { calculateSellersSearch } from '../middlewares/dashboard/search/calculateSellersSearch'
import { findSeller } from '../middlewares/dashboard/search/findSeller'
import { unificationSellers } from '../middlewares/dashboard/search/unificationSellers'
import { sortGeneric } from '../middlewares/dashboard/search/sortGeneric'

export const searchSellersService = async (
  searchDashboardParams: SearchSellersServiceRequest,
  ctx: Context
) => {
  const {
    clients: { sellersDashboardClientMD, vbase },
  } = ctx

  let pagination = {
    page: 1,
    pageSize: 100,
  }

  const { dateStart, dateEnd, sellersId, page, pageSize, reIndex, sort } =
    searchDashboardParams

  const vbaseId = `${dateStart.replace('-', '').replace('-', '')}-${dateEnd
    .replace('-', '')
    .replace('-', '')}`

  let result: any = ''
  let vbaseResponse: any | null = null
  let vbaseSellers: SellersDashboard[] | null = null

  try {
    vbaseResponse = await vbase.getRawJSON<Dashboards>(
      config.BUCKET_VBASE,
      vbaseId
    )

    const sellerDashboardVbase: Dashboards = vbaseResponse.data

    vbaseSellers = sellerDashboardVbase.sellers
  } catch (error) {
    console.info('No exist data')
  }

  if (
    vbaseResponse === null ||
    vbaseSellers?.length === 0 ||
    reIndex === true
  ) {
    const dashboardResponse: any[] = []
    let dashboardResponseTemp = await sellersDashboardClientMD.searchRaw(
      pagination,
      ['_all'],
      'createdIn',
      `dateCut between ${dateStart} AND ${dateEnd}`
    )

    dashboardResponseTemp.data.forEach((item) => {
      dashboardResponse.push(item)
    })

    const totalRecords = dashboardResponseTemp.pagination.total
    let currentRecords = dashboardResponseTemp.pagination.pageSize

    if (totalRecords > currentRecords) {
      while (totalRecords > currentRecords) {
        const pageMD = pagination.page + 1

        pagination = {
          page: pageMD,
          pageSize: 100,
        }

        dashboardResponseTemp = await sellersDashboardClientMD.searchRaw(
          pagination,
          ['_all'],
          'createdIn',
          `dateCut between ${dateStart} AND ${dateEnd}`
        )

        dashboardResponseTemp.data.forEach((item) => {
          dashboardResponse.push(item)
        })

        currentRecords += dashboardResponseTemp.pagination.pageSize

        if (currentRecords >= totalRecords) {
          break
        }
      }
    }

    const unificationResponse = await unificationSellers(dashboardResponse)

    const calculateSellers = await calculateSellersSearch(unificationResponse)

    const dashboard: Dashboards = {
      dateStart,
      dateEnd,
      sellers: calculateSellers,
    }

    if (calculateSellers.length > 0) {
      const responseSaveVbase = await vbase.saveJSON<Dashboards>(
        config.BUCKET_VBASE,
        vbaseId,
        dashboard
      )

      result = {
        message: 'Save to VBase',
        responseSaveVbase,
      }
    }

    if (sellersId) {
      const searchSellerId = findSeller(dashboard, sellersId)

      const sortSellers = sortGeneric(
        searchSellerId,
        sort as string
      ) as SellersDashboard[]

      const ordersCount = sortSellers.reduce(
        (total, comis) => (total += Number(comis.statistics?.ordersCount)),
        0
      )

      const totalComission = sortSellers.reduce(
        (total, comis) => (total += Number(comis.statistics?.totalComission)),
        0
      )

      const totalOrderValue = sortSellers.reduce(
        (total, value) => (total += Number(value.statistics?.totalOrderValue)),
        0
      )

      const searchResult = {
        dateStart,
        dateEnd,
        sellers: sortSellers,
        statistics: {
          ordersCount,
          totalComission,
          totalOrderValue,
        },
        pagination: {
          currentPage: 1,
          pageSize: 1,
          totalPage: 1,
        },
      }

      result = searchResult
    } else {
      const initialOffset = (page - 1) * pageSize

      const sortSellers = sortGeneric(dashboard.sellers, sort as string)

      const sellersDashboardOffset = sortSellers.slice(
        initialOffset,
        page * pageSize
      )

      const totalPage = Math.ceil(dashboard.sellers.length / pageSize)

      const searchResult: ResultSearch = {
        dateStart,
        dateEnd,
        sellers: sellersDashboardOffset,
        pagination: {
          currentPage: page,
          pageSize,
          totalPage,
        },
      }

      result = searchResult
    }
  } else {
    const sellerDashboardVbase: Dashboards = vbaseResponse.data

    if (sellersId) {
      const searchSellerId = findSeller(sellerDashboardVbase, sellersId)

      const sortSellers = sortGeneric(
        searchSellerId,
        sort as string
      ) as SellersDashboard[]

      const ordersCount = sortSellers.reduce(
        (total, comis) => (total += Number(comis.statistics?.ordersCount)),
        0
      )

      const totalComission = sortSellers.reduce(
        (total, comis) => (total += Number(comis.statistics?.totalComission)),
        0
      )

      const totalOrderValue = sortSellers.reduce(
        (total, value) => (total += Number(value.statistics?.totalOrderValue)),
        0
      )

      result = {
        dateStart,
        dateEnd,
        sellers: sortSellers,
        statistics: {
          ordersCount,
          totalComission,
          totalOrderValue,
        },
        pagination: {
          currentPage: 1,
          pageSize: 1,
          totalPage: 1,
        },
      }
    } else {
      const initialOffset = (page - 1) * pageSize

      const sortSellers = sortGeneric(
        sellerDashboardVbase.sellers,
        sort as string
      )

      const sellersDashboardOffset = sortSellers.slice(
        initialOffset,
        page * pageSize
      )

      const totalPage = Math.ceil(
        sellerDashboardVbase.sellers.length / pageSize
      )

      result = {
        dateStart,
        dateEnd,
        sellers: sellersDashboardOffset,
        pagination: {
          currentPage: page,
          pageSize,
          totalPage,
        },
      }
    }
  }

  return { status: 200, result }
}

```


[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 marketplace-financial-commission/node/clients/mail/index.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { JanusClient } from '@vtex/api'
import { pipe } from 'ramda'

interface MailParameters {
  templateName: string
  jsonData: JsonData
}

interface JsonData {
  message: {
    to: string
  }
}

const withCookieAsHeader =
  (context: IOContext) =>
  (options: InstanceOptions): InstanceOptions => ({
    ...options,
    headers: {
      VtexIdclientAutCookie: context.authToken,
      ...(options?.headers ?? {}),
    },
  })

export default class Mail extends JanusClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super(context, options && pipe(withCookieAsHeader(context))(options))
  }

  public async sendMail(mailData: MailParameters): Promise<string> {
    const data = {
      ...mailData,
    }

    return this.http.post(`/api/mail-service/pvt/sendmail`, data)
  }
}

```


[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 marketplace-financial-commission/node/clients/vtexLogin/index.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { AuthenticationError, JanusClient } from '@vtex/api'

interface Data {
  appkey: string
  apptoken: string
}

interface AuthenticatedUser {
  userId: string
  user: string
  userType: string
}

export default class AppTokenClient extends JanusClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super(context, {
      ...options,
      headers: {
        'X-Vtex-Use-Https': 'true',
        'Content-Type': 'application/json',
      },
    })
  }

  public async validateAppKeyAndToken(data: Data): Promise<any> {
    try {
      const result = await this.http.post(`/api/vtexid/apptoken/login`, data)

      return result
    } catch (error) {
      throw new AuthenticationError('Unauthorized')
    }
  }

  public getAuthenticatedUser(
    authToken: string
  ): Promise<AuthenticatedUser | null> {
    return this.http.get('/api/vtexid/pub/authenticated/user/', {
      params: {
        authToken,
      },
    })
  }
}

```


[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 marketplace-financial-commission/node/clients/template/index.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { JanusClient } from '@vtex/api'

const TEMPLATE_RENDER_PATH = '/api/template-render/pvt/templates'

export default class Template extends JanusClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super(context, {
      ...options,
      headers: {
        VtexIdClientAutCookie: context.authToken,
      },
    })
  }

  public getTemplate() {
    return this.http.get(`${TEMPLATE_RENDER_PATH}/invoice-detail`, {
      metric: 'mail-get-template',
    })
  }

  public publishTemplate(template: TemplateType) {
    return this.http.post(TEMPLATE_RENDER_PATH, template, {
      metric: 'mail-post-template',
    })
  }
}

interface TemplateType {
  AccountId?: string
  AccountName?: string
  ApplicationId?: string
  Description?: string
  FriendlyName: string
  IsDefaultTemplate: boolean
  IsPersisted: boolean
  IsRemoved: boolean
  Name: string
  Type: string
  Templates: {
    email: {
      To: string
      CC?: string
      BCC?: string
      Subject: string
      Message: string
      Type: string
      ProviderId: string
      ProviderName?: string
      IsActive: boolean
      withError: boolean
    }
    sms: {
      Type: string
      ProviderId?: string
      ProviderName?: string
      IsActive: boolean
      withError: boolean
      Parameters: 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 marketplace-financial-commission/node/clients/orders/index.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { JanusClient } from '@vtex/api'
import Polly from 'polly-js'
import fetch from 'node-fetch'

const routes = {
  getOrder: (account: string, orderId: string) =>
    `${routes.baseUrl(account)}/${orderId}`,
  listOrders: (account: string, params: ParamsListOrders) => {
    const {
      fStatus,
      fieldDate,
      fieldDateStart,
      fieldDateEnd,
      sellerName,
      orderBy,
      page,
      perpage,
    } = params

    return `${routes.baseUrl(
      account
    )}?f_status=${fStatus}&f_${fieldDate}=${fieldDate}:[${fieldDateStart} TO ${fieldDateEnd}]&f_sellerNames=${sellerName}&orderBy=${orderBy},desc&page=${page}&per_page=${
      perpage ?? 100
    }`
  },
  baseUrl: (account: string) =>
    `http://${account}.vtexcommercestable.com.br/api/oms/pvt/orders`,
}

export class OrdersClient extends JanusClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super(context, {
      ...options,
      headers: {
        'X-Vtex-Use-Https': 'true',
        'Content-Type': 'application/json',
        vtexIdClientAutCookie: context.authToken,
      },
    })
  }

  public async getOrder(orderId: string): Promise<VtexOrder> {
    const { logger } = this.context

    try {
      const loadData = () => {
        return Polly()
          .waitAndRetry([1000, 2000, 3000, 4000, 5000, 6000, 7000])
          .executeForPromise(async () => {
            const rsp = await fetch(
              routes.getOrder(this.context.account, orderId),
              {
                method: 'get',
                headers: this.options?.headers,
              }
            )

            if (rsp.ok) {
              return rsp.json()
            }

            return Promise.reject(rsp)
          })
      }
      // const order = await this.http.get(routes.getOrder(orderId))

      const order = await loadData()

      return order
    } catch (err) {
      logger.error({
        workflowInstance: 'GetOrder',
        message: 'Error Getting VTEX order',
        exception: err,
      } as LoggerMessage)

      throw err
    }
  }

  /* eslint max-params: ["error", 4] */
  public async listOrders(params: ParamsListOrders): Promise<VtexListOrder> {
    const { logger } = this.context

    try {
      const characterReplace = '%26'
      let sellersNameReplace

      if (params.sellerName.includes('&', 0)) {
        const splitSellerName = params.sellerName.split(' ')
        const arrayResult: string[] = []

        splitSellerName.forEach((element) => {
          const salida = element.replace('&', characterReplace)

          arrayResult.push(salida)
        })
        sellersNameReplace = arrayResult.join(' ')
      }

      params.sellerName = sellersNameReplace ?? params.sellerName

      const loadData = () => {
        return Polly()
          .waitAndRetry([3000, 5000, 7000, 9000, 10000])
          .executeForPromise(async () => {
            const rsp = await fetch(
              routes.listOrders(this.context.account, params),
              {
                method: 'get',
                headers: this.options?.headers,
              }
            )

            if (rsp.ok) {
              return rsp.json()
            }

            return Promise.reject(rsp)
          })
      }

      const listOrders = await loadData()

      // const order = await this.http.get<VtexListOrder>(
      //   routes.listOrders(params)
      // )

      return listOrders
    } catch (err) {
      logger.error({
        workflowInstance: 'GetListOrders',
        message: 'Error Getting VTEX List Order',
        exception: err,
      } as LoggerMessage)

      throw err
    }
  }
}

```


[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 marketplace-financial-commission/node/clients/sellers/queries.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const GET_SELLERS = `
query GetSellers($sellersParams: SellersParams) {
  sellers(parameters: $sellersParams){
      items {
        id
        name
        account
        productCommissionPercentage
        freightCommissionPercentage
        isActive
      },
      paging {
        from
        to
        total
      }
    }
  }
`

export const GET_SELLER = `
query getSeller($sellerId: ID!) {
  seller(id: $sellerId) {
    id,
    name,
    account,
    isActive
  }
}
`

```


[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 marketplace-financial-commission/node/clients/sellers/index.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type {
  IOContext,
  InstanceOptions,
  Serializable,
  GraphQLResponse,
} from '@vtex/api'
import { AppGraphQLClient } from '@vtex/api'

import { GET_SELLER, GET_SELLERS } from './queries'

// interface SellersParams {
//   pagination: Pagination
// }

// interface Pagination {
//   from: number
//   to: number
// }

class CustomGraphQLError extends Error {
  public graphQLErrors: any

  constructor(message: string, graphQLErrors: any[]) {
    super(message)
    this.graphQLErrors = JSON.stringify(graphQLErrors)
  }
}

function throwOnGraphQLErrors<T extends Serializable>(message: string) {
  return function maybeGraphQLResponse(response: GraphQLResponse<T>) {
    if (response?.errors && response.errors.length > 0) {
      throw new CustomGraphQLError(message, response.errors)
    }

    return response
  }
}

export default class SellersIO extends AppGraphQLClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super('vtex.sellers-graphql@8.x', context, {
      ...options,
      headers: {
        ...options?.headers,
        cookie: `VtexIdclientAutCookie=${context.authToken}`,
      },
    })
  }

  public async getSellers(sellersParams?: SellerListParams): Promise<Sellers> {
    const sellers = await this.graphql
      .query<Data, Record<string, unknown>>(
        {
          query: GET_SELLERS,
          variables: { sellersParams },
        },
        {
          metric: 'get-sellers',
        }
      )
      .then(
        throwOnGraphQLErrors(
          'Error getting items data from vtex.sellers-graphql'
        )
      )
      .then((query) => {
        return query.data?.sellers as Sellers
      })

    return sellers
  }

  public async seller(sellerId: string): Promise<Seller> {
    const sellers = await this.graphql
      .query<Data, Record<string, unknown>>(
        {
          query: GET_SELLER,
          variables: { sellerId },
        },
        {
          metric: 'get-seller',
        }
      )
      .then(
        throwOnGraphQLErrors(
          'Error getting items data from vtex.sellers-graphql'
        )
      )
      .then((query) => {
        return query.data?.seller as Seller
      })

    return sellers
  }
}

```


[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 marketplace-financial-commission/node/middlewares/invoiceExternal/createInvoiceExternal.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { processInvoiceExternal } from './processInvoiceExternal'
import { sendEmailInvoiceExternal } from './sendEmailInvoiceExternal'

export async function createInvoiceExternal(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    state: {
      body: { requestData },
    },
  } = ctx

  let status
  let body

  const documentMD = await processInvoiceExternal(ctx, requestData)
  const { DocumentId } = documentMD
  const documentId = DocumentId

  if (documentId) {
    try {
      await sendEmailInvoiceExternal(ctx, documentId, requestData)
    } catch (error) {
      console.error(error)
    }

    status = 200
    body = {
      message: `Invoice Created, Shortly you will receive an email with the invoice created to your email address. ${requestData.seller.contact.email}`,
      id: documentId,
    }
  } else {
    status = 400
    body = {
      message: `It was not possible to create the invoice`,
      exception: documentMD,
    }
  }

  ctx.status = status
  ctx.body = body
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/invoiceExternal/processInvoiceExternal.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { DocumentResponse } from '@vtex/clients/build/clients/masterData'
import type { ExternalInvoice } from 'vtex.marketplace-financial-commission'

import { config, JOB_STATUS } from '../../constants'
import type { InvoiceExternal } from '../../typings/externalInvoice'
import { randomId } from '../../utils/randomId'

interface JobHistory {
  referenceId: string | null
  sellerId: string
  status: JobStatus
  message: string | null
}

type JobStatus = 'ONGOING' | 'COMPLETE' | 'ERROR' | 'OMITTED'

export const processInvoiceExternal = async (
  ctx: Context,
  dataInvoice: InvoiceExternal
): Promise<DocumentResponse> => {
  const {
    clients: { vbase, externalInvoices },
  } = ctx

  const [today] = new Date().toISOString().split('T')

  const BUCKET = config.APIREST_JOB_BUCKET

  const HISTORY = {
    referenceId: null,
    sellerId: dataInvoice.seller.id,
    status: JOB_STATUS.ONGOING,
    message: null,
  }

  await vbase.saveJSON<JobHistory>(BUCKET, dataInvoice.seller.id, HISTORY)

  const bodyExternalInvoice: ExternalInvoice = {
    seller: {
      id: dataInvoice.seller.id,
      name: dataInvoice.seller.name,
      contact: {
        email: dataInvoice.seller.contact.email,
        phone: dataInvoice.seller.contact.phone,
      },
    },
    invoiceCreatedDate: dataInvoice.invoiceCreatedDate,
    status: dataInvoice.status,
    jsonData: dataInvoice.jsonData,
    comment: `Invoice created by external API REST integration on ${today}`,
  }

  const idInvoice = randomId(dataInvoice.seller.id)

  const bodyExternalInvoiceWithId = {
    id: idInvoice,
    ...bodyExternalInvoice,
  }

  const document = await externalInvoices.save(bodyExternalInvoiceWithId)

  await vbase.saveJSON<JobHistory>(BUCKET, dataInvoice.seller.id, {
    ...HISTORY,
    referenceId: document.DocumentId,
    status: JOB_STATUS.COMPLETE,
  })

  return document
}

```


[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 marketplace-financial-commission/node/middlewares/invoiceExternal/deleteInvoiceExternal.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export async function deleteInvoiceExternal(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    vtex: {
      route: {
        params: { id },
      },
    },
    clients: { externalInvoices },
  } = ctx

  let message
  let status

  const getInvoice = await externalInvoices.get(id as string, ['_all'])

  if (getInvoice) {
    await externalInvoices.delete(id as string)
    message = {
      invoiceId: id,
      message: 'The invoice has been successfully deleted ',
    }
    status = 200
  } else {
    message = {
      invoiceId: id,
      message: 'The invoice no found, please verify ',
    }
    status = 404
  }

  ctx.status = status
  ctx.body = message
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/invoiceExternal/validateParamsExternal.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable no-useless-escape */
import type { ErrorLike } from '@vtex/api'
import { AuthenticationError, UserInputError } from '@vtex/api'
import { json } from 'co-body'

import { INVOICE_STATUS, validationMessage } from '../../constants'
import { typeIntegration } from '../../utils/typeIntegration'
// import type { InvoiceExternal } from '../../typings/externalInvoice'

export async function validateParamsExternal(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    req,
    method,
    vtex: {
      route: { params },
    },
  } = ctx

  const requestData = await json(req) // as InvoiceExternal

  switch (method) {
    case 'PATCH': {
      const integration = await typeIntegration(ctx)

      if (TypeIntegration.external !== integration) {
        throw new AuthenticationError('Invalid type integration')
      }

      if (!requestData || JSON.stringify(requestData) === '{}') {
        const error: ErrorLike = {
          message: 'Body is requerid',
          name: '',
          stack: '',
        }

        throw new UserInputError(error)
      }

      if (!params.id || params.id === '' || params.id === null) {
        const error: ErrorLike = {
          message: `The param id is requerid`,
          name: 'id',
          stack: '',
        }

        throw new UserInputError(error)
      }

      const { status, seller, invoiceCreatedDate, jsonData } = requestData

      if (
        status === undefined &&
        seller === undefined &&
        invoiceCreatedDate === undefined &&
        jsonData === undefined
      ) {
        const error: ErrorLike = {
          message: `Error model no valid`,
          name: 'email',
          stack: '',
        }

        throw new UserInputError(error)
      }

      isNullorEmpty(seller, 'seller')
      isNullorEmpty(invoiceCreatedDate, 'invoiceCreatedDate')
      isNullorEmpty(jsonData, 'jsonData')

      if (status || status === '') {
        validateStatus(status)
      }

      if (seller) {
        const { contact, id, name } = seller

        if (contact === undefined && id === undefined && name === undefined) {
          const error: ErrorLike = {
            message: `Error model object seller no valid`,
          }

          throw new UserInputError(error)
        }

        isNullorEmpty(id, 'id')
        isNullorEmpty(name, 'name')

        if (contact === '' || contact === null || contact === {}) {
          const error: ErrorLike = {
            message: `Error model, is requerid object contact`,
          }

          throw new UserInputError(error)
        }

        if (contact) {
          const { email } = contact

          isNullorEmpty(email, 'email')
          isRequerid(email, 'email')

          if (email) {
            validateEmail(email)
          }
        }
      }

      if (jsonData) {
        isJsonString(jsonData)
      }

      ctx.state.body = { requestData }

      break
    }

    case 'POST': {
      const integration = await typeIntegration(ctx)

      if (TypeIntegration.external !== integration) {
        throw new AuthenticationError('Invalid type integration')
      }

      if (!requestData || JSON.stringify(requestData) === '{}') {
        const error: ErrorLike = {
          message: 'Body is requerid',
          name: '',
          stack: '',
        }

        throw new UserInputError(error)
      }

      const { invoiceCreatedDate, status, seller, jsonData } = requestData

      if (!invoiceCreatedDate) {
        isRequerid(invoiceCreatedDate, 'invoiceCreatedDate')
      }

      if (!status) {
        isRequerid(status, 'status')
      } else {
        validateStatus(status)
      }

      if (!seller) {
        isRequerid(seller, 'seller')
      }

      const { id, name, contact } = seller

      if (!id) {
        isRequerid(id, 'seller.id')
      }

      if (!name) {
        isRequerid(name, 'seller.name')
      }

      if (!contact) {
        isRequerid(contact, 'seller.contact')
      }

      const { email } = contact

      if (!email) {
        isRequerid(email, 'seller.contact.email')
      } else {
        validateEmail(email)
      }

      if (!jsonData) {
        isRequerid(jsonData, 'jsonData')
      } else {
        isJsonString(jsonData)
      }

      ctx.state.body = { requestData }
      ctx.vtex.route.params.id = params.id

      break
    }

    case 'DELETE': {
      const integration = await typeIntegration(ctx)

      if (TypeIntegration.external !== integration) {
        throw new AuthenticationError('Invalid type integration')
      }

      if (!params.id || params.id === '' || params.id === null) {
        const error: ErrorLike = {
          message: `The param id is requerid`,
          name: 'id',
          stack: '',
        }

        throw new UserInputError(error)
      }

      ctx.vtex.route.params.id = params.id

      break
    }

    case 'GET':
      break

    default:
      break
  }

  await next()
}

function isRequerid(value: string | number, name: string) {
  if (!value || value === '' || value === null) {
    const error: ErrorLike = {
      message: `The field ${name} is requerid`,
      name,
      stack: '',
    }

    throw new UserInputError(error)
  }
}

function isNullorEmpty(value: string, name: string) {
  if (value === '' || value === null) {
    const errorString: ErrorLike = {
      message:
        name === 'seller'
          ? 'Object seller is requerid'
          : `Field "${name}" cannot be empty or null`,
      name,
    }

    throw new UserInputError(errorString)
  }
}

function validateEmail(email: string) {
  const regexp = new RegExp(
    /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
  )

  const emailTest = regexp.test(String(email).toLowerCase())

  if (emailTest !== true) {
    const error: ErrorLike = {
      message: validationMessage.ERROR_EMAIL,
      name: email,
    }

    throw new UserInputError(error)
  }
}

function validateStatus(value: string) {
  try {
    if (
      !Object.values(INVOICE_STATUS).includes(
        value as 'unpaid' | 'partial' | 'paid'
      )
    ) {
      throw new UserInputError(
        `Invalid status '${value}'. The valid values are 'unpaid' | 'partial' | 'paid'`
      )
    }
  } catch (error) {
    throw new UserInputError(
      `Invalid status '${value}'. The valid values are 'unpaid' | 'partial' | 'paid'`
    )
  }
}

function isJsonString(str: string) {
  if (typeof str !== 'string') {
    const errorString: ErrorLike = {
      message: validationMessage.ERROR_JSONDATA,
      name: 'jsonData',
    }

    throw new UserInputError(errorString)
  }

  try {
    const jsonData = JSON.parse(str)

    return typeof jsonData === 'object'
  } catch (err) {
    const errorJson: ErrorLike = {
      message: validationMessage.ERROR_JSONDATA,
      name: 'jsonData',
    }

    throw new UserInputError(errorJson)
  }
}

```


[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 marketplace-financial-commission/node/middlewares/invoiceExternal/sendEmailInvoiceExternal.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { config } from '../../constants'
import type {
  EmailInvoiceData,
  InvoiceExternal,
} from '../../typings/externalInvoice'

export const sendEmailInvoiceExternal = async (
  ctx: Context,
  documentId: string,
  dataInvoice: InvoiceExternal
): Promise<any> => {
  try {
    const {
      clients: { mail },
    } = ctx

    const emailData: EmailInvoiceData = {
      id: documentId,
      invoiceCreatedDate: dataInvoice.invoiceCreatedDate,
      seller: dataInvoice.seller,
      status: dataInvoice.status,
      jsonData: JSON.parse(dataInvoice.jsonData),
    }

    await mail.sendMail({
      templateName: config.INVOICE_MAIL_TEMPLATE,
      jsonData: {
        message: {
          to: dataInvoice.seller.contact.email,
        },
        ...emailData,
      },
    })
  } catch (error) {
    console.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 marketplace-financial-commission/node/middlewares/invoiceExternal/updateInvoiceExternal.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ExternalInvoice } from 'vtex.marketplace-financial-commission'

export async function updateInvoiceExternal(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    state: {
      body: { requestData },
    },
    vtex: {
      route: {
        params: { id },
      },
    },
    clients: { externalInvoices },
  } = ctx

  let message
  let statusResponse

  const getInvoice = (await externalInvoices.get(id as string, [
    '_all',
  ])) as ExternalInvoice

  const generateBody = () => {
    const { status, invoiceCreatedDate, seller, jsonData } = requestData
    let sellerData

    if (seller) {
      sellerData = {
        name: seller.name === undefined ? getInvoice.seller.name : seller.name,
        id: seller.id === undefined ? getInvoice.seller.id : seller.id,
        contact: {
          email:
            seller.contact === undefined
              ? getInvoice.seller.contact?.email
              : seller.contact.email,
        },
      }
    }

    return {
      status: status === undefined ? getInvoice.status : status,
      invoiceCreatedDate:
        invoiceCreatedDate === undefined
          ? getInvoice.invoiceCreatedDate
          : invoiceCreatedDate,
      jsonData: jsonData === undefined ? getInvoice.jsonData : jsonData,
      seller: seller === undefined ? getInvoice.seller : sellerData,
    }
  }

  const bodyUpdate = generateBody()

  if (getInvoice) {
    await externalInvoices.update(id as string, bodyUpdate)
    message = {
      invoiceId: id,
      message: 'The invoice has been successfully update ',
    }
    statusResponse = 200
  } else {
    message = {
      invoiceId: id,
      message: 'The invoice no found, please verify ',
    }
    statusResponse = 404
  }

  ctx.status = statusResponse
  ctx.body = message
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/invoiceExternal/index.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export * from './createInvoiceExternal'
export * from './getInvoiceExternal'

```


[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 marketplace-financial-commission/node/middlewares/invoiceExternal/getInvoiceExternal.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
const assembleWhere = async (query: any): Promise<string> => {
  const sellerName = (query.sellerName ?? '') as string
  const sellerId = (query.sellerId ?? '') as string
  const status = (query.status ?? '') as string
  const createdDateInitial = (query.createdDateInitial ?? '') as string
  const createdDateEnd = (query.createdDateEnd ?? '') as string

  let where = ''

  if (sellerName !== '') {
    where += `seller.name="${sellerName}"`
  }

  if (sellerId !== '') {
    if (sellerName !== '') {
      where += ` AND seller.id="${sellerId}"`
    } else {
      where += `seller.id="${sellerId}"`
    }
  }

  if (status !== '') {
    if (sellerName !== '' || sellerId !== '') {
      where += ` AND status="${status}"`
    } else {
      where += `status="${status}"`
    }
  }

  if (createdDateInitial !== '' && createdDateEnd !== '') {
    if (sellerName !== '' || sellerId !== '' || status !== '') {
      where += ` AND (invoiceCreatedDate between ${createdDateInitial} AND ${createdDateEnd})`
    } else {
      where += `(invoiceCreatedDate between ${createdDateInitial} AND ${createdDateEnd})`
    }
  }

  return where
}

export async function getInvoiceExternal(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    vtex: {
      route: {
        params: { id },
      },
    },
    query,
    clients: { externalInvoices },
  } = ctx

  let sellerInvoices

  if (id !== '' && id !== undefined) {
    const pagination = {
      page: 1,
      pageSize: 100,
    }

    sellerInvoices = await externalInvoices.searchRaw(
      pagination,
      ['id,status,accountName,seller,invoiceCreatedDate,jsonData,comment'],
      'createdIn',
      `id=${id}`
    )
  } else {
    const page = Number(
      (ctx.query.page === '' || ctx.query.page === undefined
        ? '1'
        : ctx.query.page) as string
    )

    const pageSize = Number(
      (ctx.query.pageSize === '' || ctx.query.pageSize === undefined
        ? '100'
        : ctx.query.pageSize) as string
    )

    const where = await assembleWhere(query)

    const pagination = {
      page,
      pageSize,
    }

    if (where !== '') {
      sellerInvoices = await externalInvoices.searchRaw(
        pagination,
        ['id,status,accountName,seller,invoiceCreatedDate,jsonData,comment'],
        'createdIn',
        where
      )
    } else {
      sellerInvoices = await externalInvoices.searchRaw(
        pagination,
        ['id,status,accountName,seller,invoiceCreatedDate,jsonData,comment'],
        'createdIn'
      )
    }
  }

  ctx.status = 200
  ctx.body = sellerInvoices
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/mail/mail.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { json } from 'co-body'

export async function sendMail(ctx: Context, next: () => Promise<any>) {
  const {
    clients: { mail },
  } = ctx

  const body = await json(ctx.req)

  const { email } = body

  if (!email) {
    ctx.status = 400
    ctx.body = 'Specify an email address'

    return
  }

  let data = {}

  if (!body.jsonData) {
    ctx.status = 400
    ctx.body = 'Specify a jsonData attribute for invoice payload'

    return
  }

  data = { ...body.jsonData }

  const sendEmailResponse = await mail.sendMail({
    templateName: 'invoice-detail',
    jsonData: {
      message: {
        to: email,
      },
      ...data,
    },
  })

  if (sendEmailResponse) {
    ctx.status = 200
    ctx.body = 'ok'
  }

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/template/template.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import GetBody from '../../templates'

export async function templateMethod(ctx: Context, next: () => Promise<any>) {
  const {
    clients: { template },
  } = ctx

  const templateResponse = await template.getTemplate()

  if (templateResponse) {
    ctx.body = { template: templateResponse }
  } else {
    const templateBody = await GetBody(ctx)
    const templateCreated = await template.publishTemplate(templateBody)

    ctx.body = { template: templateCreated }
  }

  ctx.set('Cache-Control', 'no-cache')
  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/typeIntegration/getTypeIntegration.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { typeIntegration } from '../../utils/typeIntegration'

export async function getTypeIntegration(
  ctx: Context,
  next: () => Promise<any>
) {
  const integration = await typeIntegration(ctx)

  ctx.status = 200
  ctx.body = { integration }
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/orders/orderListSeller.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
// eslint-disable-next-line max-params
export async function orderListSeller(
  ctx: Context,
  sellerName: string,
  dateStart: string,
  dateEnd: string,
  page: number,
  perpage: number,
  status?: string
): Promise<VtexListOrder> {
  const {
    clients: { ordersClient },
  } = ctx

  if (status === 'invoiced') {
    const orderList = await ordersClient.listOrders({
      fStatus: status,
      fieldDate: 'invoicedDate',
      fieldDateStart: `${dateStart}T00:00:00.000Z`,
      fieldDateEnd: `${dateEnd}T23:59:59.999Z`,
      sellerName,
      orderBy: 'invoicedDate',
      page,
      perpage,
    })

    return orderList
  }

  const orderList = await ordersClient.listOrders({
    fStatus: status ?? '',
    fieldDate: 'creationDate',
    fieldDateStart: `${dateStart}T00:00:00.000Z`,
    fieldDateEnd: `${dateEnd}T23:59:59.999Z`,
    sellerName,
    orderBy: 'creationDate',
    page,
    perpage,
  })

  return orderList
}

```


[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 marketplace-financial-commission/node/middlewares/orders/orders.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { searchOrdersService } from '../../services/searchOrdersService'
import { validationParams } from '../validationParams'

export async function orders(ctx: Context, next: () => Promise<Sellers>) {
  const dateStart = ctx.query.dateStart as string
  const dateEnd = ctx.query.dateEnd as string
  const sellerName = ctx.query.sellerName as string
  const page = Number(ctx.query.page)
  const perpage = Number(ctx.query.perpage)
  const statusVtex = ctx.query.status as string

  await validationParams('Orders', ctx.query)

  const searchOrdersParams = {
    dateStart,
    dateEnd,
    sellerName,
    page,
    perpage,
    status: statusVtex,
  }

  const { status, resultDetail } = await searchOrdersService(
    searchOrdersParams,
    ctx
  )

  ctx.status = status
  ctx.body = resultDetail
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/orders/orderDetailCommission.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export async function orderDetailCommission(
  ctx: Context,
  orderListBySeller: VtexListOrder
): Promise<Order[]> {
  const {
    clients: { ordersClient },
  } = ctx

  const formatVtexNumber = (v: number) => v / 100

  const orderSeller: Order[] = await Promise.all(
    orderListBySeller.list.map(async (order) => {
      const orderData = await ordersClient.getOrder(order.orderId)

      const totalComission = Number(
        orderData.items
          .reduce(
            (total, x) =>
              total +
              x.quantity *
                (formatVtexNumber(x.price) *
                  formatVtexNumber(formatVtexNumber(x.commission)) +
                  formatVtexNumber(x.shippingPrice ?? 0) *
                    formatVtexNumber(
                      formatVtexNumber(x.freightCommission ?? 0)
                    )),
            0
          )
          .toFixed(2)
      )

      const totalOrderValue = Number(
        formatVtexNumber(orderData.value).toFixed(2)
      )

      const itemsRate: ItemsRate[] = orderData.items.map((item) => {
        return {
          itemId: item.id,
          nameItem: item.name,
          rate: {
            freightCommissionPercentage: Number(
              formatVtexNumber(item.freightCommission).toFixed(2)
            ),
            productCommissionPercentage: Number(
              formatVtexNumber(item.commission).toFixed(2)
            ),
          },
        }
      })

      const item: Order = {
        orderId: orderData.orderId,
        sellerOrderId: orderData.sellerOrderId,
        totalOrderValue,
        totalComission,
        status: orderData.status,
        statusDescription: orderData.statusDescription,
        creationDate: orderData.creationDate,
        rate: itemsRate,
      }

      return item
    })
  )

  return orderSeller
}

```


[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 marketplace-financial-commission/node/middlewares/authentication/authenticationValidationVtex.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ErrorLike } from '@vtex/api'
import { AuthenticationError, UserInputError } from '@vtex/api'

export async function authenticationValidationVtex(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    clients: { appTokenClient },
    request: { header },
    vtex: {
      route: { params },
    },
  } = ctx

  const appkey = header['x-vtex-api-appkey'] as string | undefined
  const apptoken = header['x-vtex-api-apptoken'] as string | undefined
  const authCookie = header.vtexidclientautcookie as string | undefined

  try {
    if (authCookie) {
      const authenticatedUser = await appTokenClient.getAuthenticatedUser(
        authCookie
      )

      if (authenticatedUser === null) {
        throw new AuthenticationError('Unauthorized')
      }
    } else {
      if (!appkey) {
        const error: ErrorLike = {
          message: 'Header "X-VTEX-API-AppKey" is requerid.',
          name: 'X-VTEX-API-AppKey',
          stack: '',
        }

        throw new UserInputError(error)
      }

      if (!apptoken) {
        const error: ErrorLike = {
          message: 'Header "X-VTEX-API-AppToken" is requerid.',
          name: 'X-VTEX-API-AppToken',
          stack: '',
        }

        throw new UserInputError(error)
      }

      const dataAppToken = {
        appkey,
        apptoken,
      }

      const resultToken = await appTokenClient.validateAppKeyAndToken(
        dataAppToken
      )

      const { authStatus } = resultToken

      if (authStatus !== 'Success') {
        throw new AuthenticationError('Unauthorized')
      }
    }

    ctx.request.header = header
    ctx.vtex.route.params = params

    ctx.set('Cache-Control', 'no-cache ')
    await next()
  } catch (err) {
    const error: any = err

    throw new 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 marketplace-financial-commission/node/middlewares/authentication/authentication.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AuthenticationError } from '@vtex/api'

import { config } from '../../constants'

/**
 * @description
 * Performs a custom authentication. Uses the seller to retrieve
 * their token. Can be skipped by being called through the seller app.
 * Writes a new query.
 * @query {sellerName}
 * Name of the seller; different from the id
 */
export async function authentication(ctx: Context, next: () => Promise<any>) {
  const {
    clients: { vbase },
    request: { header },
    vtex: { logger },
    state: {
      body: { seller },
    },
  } = ctx

  const accountMarketplace = ctx.vtex.account

  const { name, account } = seller as Seller

  const keyBucket = `${accountMarketplace}-${name}-${account}`

  let autheticationToken = ''
  let enabledToken = true

  try {
    const resultVBase = await vbase.getJSON<TokenConfiguration>(
      config.BUCKET_VBASE_TOKEN,
      keyBucket
    )

    autheticationToken = resultVBase.autheticationToken
    enabledToken = resultVBase.enabled
  } catch (err) {
    throw new AuthenticationError('Unauthorized')
  }

  const verifyToken = async (): Promise<void> => {
    const bearerHeader = header.authorization

    if (bearerHeader) {
      const bearer = bearerHeader.split(' ')

      if (autheticationToken !== bearer[1]) {
        logger.warn({
          message: 'incoming-wrongApiKey',
        })
        throw new AuthenticationError('Unauthorized')
      }

      if (!enabledToken) {
        logger.warn({
          message: 'incoming-disabledApiKey',
        })
        throw new AuthenticationError('Unauthorized')
      }
    } else {
      logger.warn({
        message: 'incoming-missingApiKey',
      })
      throw new AuthenticationError('Unauthorized')
    }
  }

  await verifyToken()

  ctx.query.sellerName = name

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/authentication/switchUser.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { NotFoundError, UserInputError } from '@vtex/api'

export async function switchUser(ctx: Context, next: () => Promise<any>) {
  const {
    clients: { sellersIO },
    request: { header },
    vtex: {
      route: { params },
    },
  } = ctx

  const originToken = header.origintoken?.toString().toUpperCase()

  switch (originToken) {
    case 'SELLER': {
      const sellerId = params.sellerId as string

      if (!sellerId) {
        throw new UserInputError('field "sellerId" is required')
      }

      const responseSeller = await sellersIO.seller(sellerId)

      if (!responseSeller) throw new NotFoundError('Seller no found')

      ctx.state.body = {
        originToken,
        seller: responseSeller,
      }

      break
    }

    case 'MARKETPLACE': {
      ctx.state.body = {
        originToken,
      }

      break
    }

    default:
      throw new UserInputError('Header originToken no valid o not Found')
  }

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/authentication/authenticationMarketplace.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AuthenticationError } from '@vtex/api'

import { config } from '../../constants'

/**
 * @description
 * Performs a custom authentication. Uses the seller to retrieve
 * their token. Can be skipped by being called through the seller app.
 * Writes a new query.
 * @query {sellerName}
 * Name of the seller; different from the id
 */
export async function authenticationMarketplace(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    clients: { vbase },
    request: { header },
    vtex: { logger },
  } = ctx

  const accountMarketplace = ctx.vtex.account

  const keyBucket = `${accountMarketplace}`

  let autheticationToken = ''
  let enabledToken = true

  try {
    const resultVBase = await vbase.getJSON<TokenConfiguration>(
      config.BUCKET_VBASE_TOKEN,
      keyBucket
    )

    autheticationToken = resultVBase.autheticationToken
    enabledToken = resultVBase.enabled
  } catch (err) {
    throw new AuthenticationError('Unauthorized')
  }

  const verifyToken = async (): Promise<void> => {
    const bearerHeader = header.authorization

    if (bearerHeader) {
      const bearer = bearerHeader.split(' ')

      if (autheticationToken !== bearer[1]) {
        logger.warn({
          message: 'incoming-wrongApiKey',
        })
        throw new AuthenticationError('Unauthorized')
      }

      if (!enabledToken) {
        logger.warn({
          message: 'incoming-disabledApiKey',
        })
        throw new AuthenticationError('Unauthorized')
      }
    } else {
      logger.warn({
        message: 'incoming-missingApiKey',
      })
      throw new AuthenticationError('Unauthorized')
    }
  }

  await verifyToken()

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/authentication/getToken.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { UserInputError } from '@vtex/api'

import { getTokenMarketplaceService } from '../../services/getTokenMarketplaceService'
import { getTokenService } from '../../services/getTokenService'

export async function getToken(ctx: Context, next: () => Promise<any>) {
  const {
    state: {
      body: { seller, originToken },
    },
  } = ctx

  switch (originToken) {
    case 'SELLER': {
      const { status, resultGetToken } = await getTokenService(seller, ctx)

      ctx.status = status
      ctx.body = resultGetToken
      break
    }

    case 'MARKETPLACE': {
      const { status, resultGetToken } = await getTokenMarketplaceService(
        ctx.vtex.account,
        ctx
      )

      ctx.status = status
      ctx.body = resultGetToken
      break
    }

    default:
      throw new UserInputError('Header originToken no valid o not Found')
  }

  ctx.set('Cache-Control', 'no-cache ')
  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/authentication/createTokenAuth.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { UserInputError } from '@vtex/api'

import { createTokenMarketplaceService } from '../../services/createTokenMarketplaceService'
import { createTokenService } from '../../services/createTokenService'

export async function createTokenAuth(ctx: Context, next: () => Promise<any>) {
  const {
    state: {
      body: { seller, originToken },
    },
  } = ctx

  switch (originToken) {
    case 'SELLER': {
      const { status, resultCreateToken } = await createTokenService(
        seller,
        ctx
      )

      ctx.status = status
      ctx.body = resultCreateToken
      break
    }

    case 'MARKETPLACE': {
      const { status, resultCreateToken } = await createTokenMarketplaceService(
        ctx.vtex.account,
        ctx
      )

      ctx.status = status
      ctx.body = resultCreateToken
      break
    }

    default:
      throw new UserInputError('Header originToken no valid o not Found')
  }

  ctx.set('Cache-Control', 'no-cache ')
  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/authentication/updateToken.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { UserInputError } from '@vtex/api'
import { json } from 'co-body'

import { updateTokenMarketplaceService } from '../../services/updateTokenMarketplaceService'
import { updateTokenService } from '../../services/updateTokenService'

export async function updateToken(ctx: Context, next: () => Promise<any>) {
  const {
    state: {
      body: { seller, originToken },
    },
  } = ctx

  const bodyReq = await json(ctx.req)

  switch (originToken) {
    case 'SELLER': {
      const { status, resultUpdateToken } = await updateTokenService(
        seller,
        bodyReq,
        ctx
      )

      ctx.status = status
      ctx.body = resultUpdateToken
      break
    }

    case 'MARKETPLACE': {
      const { status, resultUpdateToken } = await updateTokenMarketplaceService(
        ctx.vtex.account,
        bodyReq,
        ctx
      )

      ctx.status = status
      ctx.body = resultUpdateToken
      break
    }

    default:
      throw new UserInputError('Header originToken no valid o not Found')
  }

  ctx.set('Cache-Control', 'no-cache ')
  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/sellers/seller.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { NotFoundError, UserInputError } from '@vtex/api'

/**
 * @description
 * Takes the sellerId from the query or route to retrieve
 * the Seller data, and then write it in the state body.
 * @state {Seller}
 * - id
 * - name
 * - account
 * - isActive
 */
export async function seller(ctx: Context, next: () => Promise<Seller>) {
  const {
    clients: { sellersIO },
    vtex: {
      route: { params },
    },
    query,
  } = ctx

  const sellerId = (query.sellerId as string) ?? (params.sellerId as string)

  if (!sellerId) {
    throw new UserInputError('field "sellerId" is required')
  }

  const responseSeller = await sellersIO.seller(sellerId)

  if (!responseSeller) throw new NotFoundError('Seller no found')

  ctx.state.body = {
    seller: responseSeller,
  }

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/sellers/eligibleSellers.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ResolverError } from '@vtex/api'

import { config } from '../../constants'
import { listSellers } from './listSellers'

/**
 * @middleware
 * Filter sellers that are eligible for Invoice creation.
 * Intended to be automatically run by a scheduler in a Marketplace.
 */
export async function eligibleSellers(
  ctx: Context,
  next: () => Promise<Sellers>
) {
  const {
    clients: { vbase },
    vtex: { account: marketplace },
  } = ctx

  const [today] = new Date().toISOString().split('T')

  const retrySellers = await vbase.getJSON<any>(
    config.RETRY_SELLERS_BUCKET,
    marketplace,
    true
  )

  if (retrySellers) {
    ctx.state.body = { sellers: JSON.parse(retrySellers) }

    await next()
  }

  const DEFAULT_SETTINGS = await vbase.getJSON<Settings>(
    config.SETTINGS_BUCKET,
    marketplace,
    true
  )

  if (!DEFAULT_SETTINGS) {
    throw new ResolverError(
      "No default Marketplace's settings found, please configure them in the Admin panel",
      500
    )
  }

  const allSellers = await listSellers(ctx)

  const activeSellers = allSellers.items.filter(({ isActive }) => isActive)

  if (!activeSellers) {
    throw new ResolverError(
      "There're no active sellers for this Marketplace",
      204
    )
  }

  const sellersToInvoice = await Promise.all(
    activeSellers.map(async (seller) => {
      const sellerSettings =
        (await vbase.getJSON<SellerSettings>(
          config.SETTINGS_BUCKET,
          seller.name,
          true
        )) || DEFAULT_SETTINGS

      if (sellerSettings.endDate <= today) {
        return { ...seller, ...sellerSettings }
      }

      return null
    })
  )

  // Filter sellers that fall outside this cycle
  const sellers = sellersToInvoice.filter(Boolean) as SellerInvoice[]

  ctx.state.body = { sellers }

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/sellers/findSellerList.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const findSellerList = (sellers: Sellers, sellersId: string) => {
  const sellersIds = sellersId.split(',')
  const searchSeller = sellers.items.filter((v) =>
    sellersIds.includes(v.id)
  ) as ItemSeller[]

  return searchSeller
}

```


[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 marketplace-financial-commission/node/middlewares/sellers/sellers.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { listSellers } from './listSellers'

export async function sellers(ctx: Context, next: () => Promise<Sellers>) {
  const respsellers = await listSellers(ctx)

  ctx.state.body = { sellers: respsellers }

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/sellers/response.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export async function response(ctx: Context, next: () => Promise<Sellers>) {
  const {
    state: {
      body: { sellers },
    },
  } = ctx

  ctx.status = 200
  ctx.body = sellers
  ctx.set('Cache-Control', 'no-cache')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/sellers/listSellers.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable no-await-in-loop */
export async function listSellers(ctx: Context): Promise<Sellers> {
  const {
    clients: { sellersIO },
  } = ctx

  const ArraySellers: ItemSeller[] = []
  let from = 0
  let to = 100
  let total = 0

  while (total !== to) {
    let sellersParams: SellerListParams = {
      pagination: {
        from,
        to,
      },
    }

    const respsellers = await sellersIO.getSellers(sellersParams)

    respsellers.items.forEach((seller) => {
      ArraySellers.push(seller)
    })

    total = respsellers.paging.total ?? 0

    if (total <= to) {
      break
    }

    const totalProcessPending = total - to

    from = to
    to = total > totalProcessPending ? from + 100 : totalProcessPending

    sellersParams = {
      pagination: {
        from,
        to,
      },
    }
  }

  const sellers: Sellers = {
    items: ArraySellers,
    paging: {
      total,
    },
  }

  return sellers
}

```


[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 marketplace-financial-commission/node/middlewares/invoice/resolveInvoice.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable padding-line-between-statements */

import {
  getInvoice,
  createInvoice,
  deleteInvoice,
  updateInvoice,
} from './index'

export async function resolveInvoice(ctx: Context): Promise<void> {
  const {
    method,
    query: { id },
  } = ctx

  let body: any

  switch (method) {
    case 'PATCH':
      body = await updateInvoice(ctx)
      break

    case 'POST':
      body = await createInvoice(ctx)
      break

    case 'DELETE':
      body = await deleteInvoice(ctx)
      break

    default:
    case 'GET':
      body = await getInvoice(ctx)
      break
  }

  if (!body) {
    ctx.status = 404
    ctx.body = `Invoice '${id}' not found`
  }

  ctx.status = 200
  ctx.body = body
  ctx.set('Cache-Control', 'no-cache ')
}

```


[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 marketplace-financial-commission/node/middlewares/invoice/getInvoice.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AuthenticationError } from '@vtex/api'
import type { CommissionInvoice } from 'vtex.marketplace-financial-commission'

import { PAGE_DEFAULT, PAGE_SIZE_DEFAULT } from '../../constants'
import { typeIntegration } from '../../utils/typeIntegration'

/**
 * @description Retrieves a specific Invoice by ID.
 */
export async function getInvoice(ctx: Context) {
  const {
    query: { sellerName },
    vtex: {
      route: {
        params: { id },
      },
    },
    // params: { id },
    clients: { commissionInvoices, externalInvoices },
    state: {
      body: { seller },
    },
  } = ctx

  /* This means the seller wants to access other seller's invoices */
  if (sellerName !== seller.name) {
    throw new AuthenticationError(`Cannot access invoices for ${seller}`)
  }

  const where = `id=${id} AND seller.name="${sellerName}"`

  let invoice

  const integration = await typeIntegration(ctx)

  if (TypeIntegration.external === integration) {
    const externalInvoice = await externalInvoices.search(
      { page: PAGE_DEFAULT, pageSize: PAGE_SIZE_DEFAULT },
      ['id,status,invoiceCreatedDate,seller,jsonData,comment'],
      '',
      where
    )

    if (externalInvoice.length === 0) {
      invoice = externalInvoice
    } else {
      invoice = [
        {
          id: externalInvoice[0].id,
          status: externalInvoice[0].status,
          invoiceCreatedDate: externalInvoice[0].invoiceCreatedDate,
          seller: externalInvoice[0].seller,
          jsonData: JSON.parse(externalInvoice[0].jsonData as string),
          comment: externalInvoice[0].comment,
        },
      ]
    }
  } else {
    const internalInvoice = (await commissionInvoices.search(
      { page: PAGE_DEFAULT, pageSize: PAGE_SIZE_DEFAULT },
      ['id,status,invoiceCreatedDate,seller,orders,totalizers,comment'],
      '',
      where
    )) as unknown as CommissionInvoice[]

    const orders: any[] = internalInvoice[0].orders.map((order) => {
      return {
        orderId: order.orderId as string,
        sellerOrderId: order.sellerOrderId as string,
        totalComission: order.totalComission?.toFixed(2),
        totalOrderValue: order.totalOrderValue?.toFixed(2),
        totalOrderRate: order.totalOrderRate?.toFixed(2),
      }
    })

    invoice = [
      {
        id: internalInvoice[0].id as string,
        status: internalInvoice[0].status as string,
        invoiceCreatedDate: internalInvoice[0].invoiceCreatedDate as string,
        seller: internalInvoice[0].seller,
        orders,
        totalizers: {
          subTotal: internalInvoice[0].totalizers.subTotal?.toFixed(2),
          fee: internalInvoice[0].totalizers.fee?.toFixed(2),
          total: internalInvoice[0].totalizers.total?.toFixed(2),
        },
        comment: internalInvoice[0].comment,
      },
    ]
  }

  if (invoice.length > 1) {
    console.warn('Invoice duplication, seek resolution')
  }

  if (invoice.length > 0) {
    return invoice[0]
  }

  return null
}

```


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

[User] Show me the implementation of marketplace-financial-commission/node/middlewares/invoice/createInvoice.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AuthenticationError, UserInputError } from '@vtex/api'
import { json } from 'co-body'

import { JOB_STATUS } from '../../constants'
import { invoicingProcess } from '../../services/invoicingProcess'

/**
 * @description Attempts to create an Invoice.
 */
export async function createInvoice(ctx: Context) {
  const {
    query: { sellerName },
    state: {
      body: { seller },
    },
    req,
  } = ctx

  /* This means the seller wants to access other seller's invoices */
  if (sellerName !== seller.name) {
    throw new AuthenticationError(`Cannot access invoices for ${seller}`)
  }

  const requestData = await json(req)

  if (!requestData.startDate || !requestData.endDate) {
    throw new UserInputError(
      'startDate and/or endDate not provided in the request'
    )
  }

  const sellerData = { ...requestData, id: seller.id, name: seller.name }

  const invoice = await invoicingProcess(ctx, sellerData)

  if (invoice === JOB_STATUS.OMITTED) {
    return 'No eligible orders to invoice for given date range'
  }

  return `Invoice ${invoice} created`
}

```


[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 marketplace-financial-commission/node/middlewares/invoice/updateInvoice.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { json } from 'co-body'

/**
 * @description
 * Attempts to update an Invoice.
 * @returns
 * Message confirming the update
 */
export async function updateInvoice(ctx: Context): Promise<string> {
  const {
    clients: { commissionInvoices },
    vtex: {
      route: {
        params: { id },
      },
    },
    req,
  } = ctx

  const requestBody = await json(req)

  const invoice = {
    id: id[0],
    ...requestBody,
  }

  await commissionInvoices.update(id.toString(), invoice)

  return `Invoice ${id.toString()} updated`
}

```


[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 marketplace-financial-commission/node/middlewares/invoice/invoicesBySeller.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { AuthenticationError, UserInputError } from '@vtex/api'
import { json } from 'co-body'

import { PAGE_DEFAULT, PAGE_SIZE_DEFAULT } from '../../constants'
import { typeIntegration } from '../../utils/typeIntegration'

/**
 * @description Retrieves a REFERENCE list of invoices for a given seller.
 */
export async function invoicesBySeller(ctx: Context, next: () => Promise<any>) {
  const {
    clients: { commissionInvoices, externalInvoices },
    state: {
      body: { seller },
    },
    vtex: {
      route: { params },
    },
    req,
  } = ctx

  /* This means the seller wants to access other seller's invoices */
  if (params.sellerId !== seller.id) {
    throw new AuthenticationError(
      `${seller.id} cannot access invoices for ${params.sellerId}`
    )
  }

  const {
    page = PAGE_DEFAULT,
    pageSize = PAGE_SIZE_DEFAULT,
    startDate,
    endDate,
  } = await json(req)

  if (!startDate || !endDate) {
    throw new UserInputError(
      'startDate and/or endDate not provided in the request'
    )
  }

  const where = `seller.name="${seller.name}" AND (invoiceCreatedDate between ${startDate} AND ${endDate})`

  const fields = ['id', 'status', 'invoiceCreatedDate', 'totalizers']

  let sellerInvoices

  const integration = await typeIntegration(ctx)

  if (TypeIntegration.external === integration) {
    sellerInvoices = await externalInvoices.searchRaw(
      { page, pageSize },
      fields,
      'invoiceCreatedDate',
      where
    )
  } else {
    sellerInvoices = await commissionInvoices.searchRaw(
      { page, pageSize },
      fields,
      'invoiceCreatedDate',
      where
    )
  }

  ctx.status = 200
  ctx.body = sellerInvoices
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/invoice/generateInvoices.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ResolverError } from '@vtex/api'

import { config } from '../../constants'
import { invoicingProcess } from '../../services/invoicingProcess'

/**
 * @description
 * Starts the process which will create
 * an invoice for each seller.
 * @throws {409 - Conflict}
 * If any fails we will store them and error out.
 * This will cause the scheduler to retry, which will
 * make the sellers to be those that failed.
 */
export async function generateInvoices(ctx: Context) {
  const {
    state,
    clients: { vbase },
    vtex: { account: marketplace },
  } = ctx

  // Sellers that have their billing cycle today
  const sellers = state.body.sellers as SellerInvoice[]

  const unresolvedInvoices = sellers.map((seller) =>
    invoicingProcess(ctx, seller, true)
  )

  const results = (await Promise.allSettled(
    unresolvedInvoices
  )) as PromiseResult[]

  const rejectedSellers = results.reduce((rejected, promise, i) => {
    if (promise.status === 'rejected') {
      rejected.push(sellers[i])
    }

    return rejected
  }, [] as SellerInvoice[])

  const anyRejected = rejectedSellers.some(Boolean)

  // If any invoicing promise fails, we will retry them
  if (anyRejected) {
    await vbase.saveJSON(
      config.RETRY_SELLERS_BUCKET,
      marketplace,
      JSON.stringify(rejectedSellers)
    )

    throw new ResolverError(
      "Couldn't complete the invoicing process for some sellers",
      409
    )
  }

  // The retry bucket is purged if all succeeded
  await vbase.saveJSON(config.RETRY_SELLERS_BUCKET, marketplace, null)

  return (ctx.status = 200)
}

```


[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 marketplace-financial-commission/node/middlewares/invoice/index.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export * from './generateInvoices'
export * from './getInvoice'
export * from './createInvoice'
export * from './updateInvoice'
export * from './deleteInvoice'
export * from './invoicesBySeller'
export * from './resolveInvoice'

```


[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 marketplace-financial-commission/node/middlewares/invoice/deleteInvoice.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { getInvoice } from './getInvoice'

/**
 * @description Attempts to delete a specific Invoice by ID.
 * Only the Marketplace account has access to this resource
 */
export async function deleteInvoice(ctx: Context) {
  const {
    vtex: {
      route: {
        params: { id },
      },
    },
    clients: { commissionInvoices },
  } = ctx

  const invoiceToDelete = await getInvoice(ctx)

  if (!invoiceToDelete) {
    return null
  }

  await commissionInvoices.delete(id.toString())

  return `Invoice ${id} deleted`
}

```


[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 marketplace-financial-commission/node/middlewares/dashboard/search/sortGeneric.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const sortGeneric = (arr: any[], fieldsArray = 'totalComission DSC') => {
  let result = 0

  const fields = fieldsArray.split(',')

  fields.forEach((element) => {
    arr.sort((a, b) => {
      const [field, order] = element.split(' ')

      if (field.includes('id') || field.includes('name')) {
        if (order === 'DSC') {
          result = String(b[field]).localeCompare(a[field])

          return result
        }

        if (order === 'ASC') {
          result = String(a[field]).localeCompare(b[field])

          return result
        }

        return 0
      }

      if (order === 'DSC') {
        const field2 = 'ordersCount'

        result =
          b.statistics[field] - a.statistics[field] ||
          b.statistics[field2] - a.statistics[field2]

        return result
      }

      if (order === 'ASC') {
        const field2 = 'ordersCount'

        result =
          a.statistics[field] - b.statistics[field] ||
          a.statistics[field2] - b.statistics[field2]

        return result
      }

      return 0
    })

    return result
  })

  return arr
}

```


[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 marketplace-financial-commission/node/middlewares/dashboard/search/unificationSellers.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export async function unificationSellers(
  dashboardResponse: any[]
): Promise<any[]> {
  const sellersArray = dashboardResponse.reduce((arr, p) => {
    const sell = p?.sellers as SellersDashboard[]

    return [...arr, ...sell]
  }, [] as SellersDashboard[])

  const unificationSellersDashboard: UnificationSellersDashboard[] = []
  let arrayTemp = []

  for (let i = 0; i < sellersArray.length; i++) {
    arrayTemp = unificationSellersDashboard.filter(
      (resp) => resp.id === sellersArray[i].id
    )
    if (arrayTemp.length > 0) {
      unificationSellersDashboard[
        unificationSellersDashboard.indexOf(arrayTemp[0])
      ].statistics.push(sellersArray[i].statistics)
    } else {
      unificationSellersDashboard.push({
        id: sellersArray[i].id,
        account: sellersArray[i].account,
        name: sellersArray[i].name,
        statistics: [sellersArray[i].statistics],
      })
    }
  }

  return unificationSellersDashboard
}

```


[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 marketplace-financial-commission/node/middlewares/dashboard/search/findSeller.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const findSeller = (dashboard: Dashboards, sellersId: string) => {
  const sellersIds = sellersId.split(',')
  const searchSeller = dashboard.sellers.filter((v) =>
    sellersIds.includes(v.id)
  ) as SellersDashboard[]

  return searchSeller
}

```


[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 marketplace-financial-commission/node/middlewares/dashboard/search/searchSellers.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { searchSellersService } from '../../../services/searchSellersService'
import { validationParams } from '../../validationParams'

export async function searchSellers(ctx: Context, next: () => Promise<any>) {
  const dateStart = ctx.query.dateStart as string
  const dateEnd = ctx.query.dateEnd as string
  const sellersId = ctx.query.sellersId as string
  const page = Number(ctx.query.page)
  const pageSize = Number(ctx.query.pageSize)
  const reIndex = JSON.parse(
    (ctx.query.reIndex as string) ?? 'false'
  ) as boolean

  const sort = ctx.query.sort as string

  await validationParams('Sellers', ctx.query)

  const searchSellersParams = {
    dateStart,
    dateEnd,
    sellersId,
    page,
    pageSize,
    reIndex,
    sort,
  }

  const { status, result } = await searchSellersService(
    searchSellersParams,
    ctx
  )

  ctx.status = status
  ctx.body = result
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/dashboard/search/calculateSellersSearch.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/restrict-plus-operands */
export async function calculateSellersSearch(
  unificationSellers: UnificationSellersDashboard[]
): Promise<SellersDashboard[]> {
  const calculateSellers: SellersDashboard[] = []

  unificationSellers.forEach((item) => {
    const ordersCount = Number(
      item.statistics
        .reduce((total, x) => (total += x.ordersCount), 0)
        .toFixed(2)
    )

    const totalComission = Number(
      item.statistics
        .reduce((total, x) => (total += x.totalComission), 0)
        .toFixed(2)
    )

    const totalOrderValue = Number(
      item.statistics
        .reduce((total, x) => (total += x.totalOrderValue), 0)
        .toFixed(2)
    )

    const outstandingBalance = 0

    const seller: SellersDashboard = {
      id: item.id,
      account: item.account,
      name: item.name,
      statistics: {
        ordersCount,
        totalComission,
        totalOrderValue,
        outstandingBalance,
      },
    }

    calculateSellers.push(seller)
  })

  return calculateSellers
}

```


[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 marketplace-financial-commission/node/middlewares/dashboard/search/searchStatistics.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { searchStatisticsService } from '../../../services/searchStatisticsService'
import { validationParams } from '../../validationParams'

/* eslint-disable @typescript-eslint/restrict-plus-operands */
export async function searchStatistics(ctx: Context, next: () => Promise<any>) {
  const dateStart = ctx.query.dateStart as string
  const dateEnd = ctx.query.dateEnd as string

  await validationParams('Statistics', ctx.query)

  const searchStatsParms = { dateStart, dateEnd }

  const { status, statisticsDashboard } = await searchStatisticsService(
    ctx,
    searchStatsParms
  )

  ctx.status = status
  ctx.body = statisticsDashboard
  ctx.set('Cache-Control', 'no-cache ')

  await next()
}

```


[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 marketplace-financial-commission/node/middlewares/dashboard/generate/calculateCommissionByOrder.ts from the marketplace-financial-commission VTEX app.

[Assistant]
Here's the implementation:

```typescript
export async function calculateCommissionByOrder(
  ctx: Context,
  orderListBySeller: VtexListOrder[]
): Promise<OrderComission[]> {
  const {
    clients: { ordersClient },
  } = ctx

  const formatVtexNumber = (v: number) => v / 100

  const commissionByOrder: OrderComission[] = await Promise.all(
    orderListBySeller[0].list.map(async (order) => {
      const orderData = await ordersClient.getOrder(order.orderId)

      const totalComission = orderData.items.reduce(
        (total, x) =>
          total +
          x.quantity *
            (formatVtexNumber(x.price) *
              formatVtexNumber(formatVtexNumber(x.commission)) +
              formatVtexNumber(x.shippingPrice ?? 0) *
                formatVtexNumber(formatVtexNumber(x.freightCommission ?? 0))),
        0
      )

      const totalOrderValue = formatVtexNumber(orderData.value)
      const totalDiscounts = orderData.totals
        .filter((x) => x.id === 'Discounts')
        .reduce((total, x) => (total += formatVtexNumber(x.value)), 0)

      const totalOrdersItems = orderData.totals
        .filter((x) => x.id === 'Items')
        .reduce((total, x) => (total += formatVtexNumber(x.value)), 0)

      const totalShipping = orderData.totals
        .filter((x) => x.id === 'Shipping')
        .reduce((total, x) => (total += formatVtexNumber(x.value)), 0)

      const totalTax = orderData.totals
        .filter((x) => x.id === 'Tax')
        .reduce((total, x) => (total += formatVtexNumber(x.value)), 0)

      const lines: OrderComission = {
        orderId: order.orderId,
        sellerOrderId: orderData.sellerOrderId,
        totalComission,
        totalOrderValue,
        totalDiscounts,
        totalOrdersItems,
        totalShipping,
        totalTax,
        // TODO: Calculete correctly
        totalOrderRate: null,
      }

      return lines
    })
  )

  return commissionByOrder
}

```