Untitled

 avatar
unknown
plain_text
2 years ago
16 kB
4
Indexable
/*
 * ---------------------------------------------
 * Author: Geraldine
 * Date:   Tuesday May 3rd 2022
 * Last Modified by: Geraldine - <gsamen@konsulta.md>
 * Last Modified time: November 10th 2023, 10:48:28 am
 * ---------------------------------------------
 */

import { composeWithMongoose } from 'graphql-compose-mongoose'

import { withFilter } from 'graphql-subscriptions'
import {
  IDeliveryStatusTimeline,
  IFulfillment,
  IStore,
} from 'healthnow-pharmacy-schemas'
import { isObject } from 'lodash'
import {
  AccountPermissionScopesEnum,
  ResourcesEnum,
} from '../lib/authorizations'
import constants from '../lib/constants'
import flatten from '../lib/flatten'
import checkAuthMiddleware from '../lib/middleware'
import pharmacyApi from '../lib/pharmacyAPI'
import pubsub from '../lib/pubsub'
import DeliveryStatusTimeline from '../models/DeliveryStatusTimeline'
import Fulfillment from '../models/Fulfillment'
import Order from '../models/Order'
import OrderDocument from '../models/OrderDocument'
import PartnerTC from './PartnerTC'
import StoreTC from './StoreTC'
import bulkAcceptOrder from './handlers/orders/bulkAcceptOrder'
import cancelOrders from './handlers/orders/cancel'
import complete from './handlers/orders/complete'
import cancel from './handlers/orders/delivery/cancel'
import manualBook from './handlers/orders/delivery/manualBook'
import manuallyCompleteDelivery from './handlers/orders/delivery/manualComplete'
import rebook from './handlers/orders/delivery/rebook'
import findOne from './handlers/orders/findOneByAccounType'
import listOrders from './handlers/orders/list'
import listOrdersv2, { IOrderListParam } from './handlers/orders/list-v2'
import manuallybookingfailed from './handlers/orders/manuallyBookingFailed'
import getHeatmapOrders, { IOrderListParams } from './handlers/orders/getHeatmapCoordinates'
import orderReport, {
  IOrderListStatusParam,
} from './handlers/orders/orderReport'
import statusReasonList, {
  IStatusReasonListParams,
} from './handlers/orders/statusReason'
import paginatedResultTC from './paginatedResultTC'
import schemaComposer from './schemaComposer'

schemaComposer.delete('Order')
const OrderTC = composeWithMongoose(Order, { schemaComposer })

schemaComposer.delete('Fulfillment')
const FulfillmentTC = composeWithMongoose(Fulfillment, {
  schemaComposer,
  removeFields: ['order'],
})

schemaComposer.delete('OrderDocument')
const OrderDocumentTC = composeWithMongoose(OrderDocument, {
  schemaComposer,
  removeFields: ['orderId', 'createdAt', 'updatedAt', '_id'],
})

schemaComposer.delete('DeliveryStatusTimeline')
const DeliveryTC = composeWithMongoose(DeliveryStatusTimeline, {
  schemaComposer,
  inputType: {
    fields: {
      remove: ['_id', 'createdAt', 'updatedAt'],
    },
  },
  removeFields: ['createdAt', 'updatedAt'],
})

export const getOrderGraphqlSchema = () => {
  const OrderTCPaginatedType = paginatedResultTC(
    'OrderTCPaginatedType',
    OrderTC
  )
  const OrderStatusReasonType = paginatedResultTC(
    'OrderStatusReasonType',
    'String'
  )

  FulfillmentTC.addNestedFields({
    'documents.document': OrderDocumentTC,
    'documents.document.signedUrl': {
      type: 'String',
      resolve: async (source: any) => {
        const result = await pharmacyApi.imageLink(source.key, source.mimeType)
        const imageLink = result.success
          ? result?.link
          : `${constants.BASE_URL}/images/not-found.png`
        return imageLink
      },
    },
  })
  OrderTC.addFields({
    fulfillments: {
      type: [FulfillmentTC],
      resolve: async (source: any) => {
        if (source?.fulfillments?.length) return source.fulfillments

        if (isObject(source.fulfillments)) {
          const result = await Fulfillment.find({ order: source._id })
            .populate('store')
            .populate({
              path: 'store',
              populate: 'partner',
            })
            .lean()
          return result
        }
      },
    },
    delivery: {
      type: DeliveryTC,
      resolve: async (source: any) => {
        const order = await Order.findById({ _id: source._id })
          .populate('delivery')
          .lean()
        return order?.delivery
      },
    },
    subStatus: 'String',
    refundSummary: {
      type: 'TRefundSummary',
      resolve: (source: any) => {
        return source.refundSummary
      },
    },
  })

  OrderTC.addNestedFields({
    'fulfillments.documents': {
      type: [FulfillmentTC.get('documents').getType()],
      resolve: async (source: any) => {
        const docIds = source.documents.map((item: { _id: string }) => item._id)
        const result = await Fulfillment.findOne(
          {
            'documents._id': { $in: docIds },
          },
          { documents: 1 }
        ).populate('documents.document')

        return result?.documents
      },
    },
    'fulfillments.store': {
      type: StoreTC,
      resolve: async (source: IFulfillment) => {
        return source.store
      },
    },
    'fulfillments.store.partner': {
      type: PartnerTC,
      resolve: async (source: IStore) => {
        return source.partner
      },
    },
    'fulfillments.receipt.signedUrl': {
      type: 'String',
      resolve: async (source: any) => {
        const result = await pharmacyApi.imageLink(source.key, source.mimeType)
        const imageLink = result.success
          ? result?.link
          : `${constants.BASE_URL}/images/not-found.png`
        return imageLink
      },
    },
  })

  OrderTC.addResolver({
    name: 'getOrder',
    kind: 'query',
    type: OrderTC.getType(),
    args: {
      _id: 'String!',
    },
    resolve: async ({
      projection,
      args,
      context,
    }: {
      projection: any
      args: { _id: string }
      context: IContext
    }) => {
      const order = await findOne(args._id, context, flatten(projection))
      return order
    },
  })

  OrderTC.addResolver({
    name: 'orderReport',
    kind: 'query',
    type: OrderTCPaginatedType,
    args: {
      options: 'Options',
      type: 'String!',
      minutes: 'Int!',
      statuses: '[EOrderStatus]',
    },
    resolve: async ({
      projection,
      args,
      context,
    }: {
      projection: any
      args: IOrderListStatusParam
      context: IContext
    }) => {
      const orders = await orderReport(args, flatten(projection.docs), context)
      return orders
    },
  })

  OrderTC.addResolver({
    name: 'listOrders',
    kind: 'query',
    type: OrderTCPaginatedType,
    args: {
      searchString: 'String',
      start: 'Date',
      end: 'Date',
      options: 'Options',
      status: '[EOrderStatus]',
      schedule: 'String',
      clientId: 'String',
      partnerId: 'String',
      storeId: 'String',
      sortingBy: 'String',
      sortingOrder: 'Int',
      shippingOption: 'String',
      isReport: 'Boolean',
      isScheduled: 'Boolean',
      amountPaid: 'IAmountPaidFilter',
      isArchived: 'Boolean',
      reasons: '[String]',
      isForAudit: 'Boolean',
    },
    resolve: async ({
      projection,
      args,
      context,
    }: {
      projection: any
      args: IOrderListParam
      context: IContext
    }) => {
      if (constants.APP_ENV === 'prod') {
        return await listOrdersv2(args, context, flatten(projection.docs))
      } else {
        return await listOrders(args, context, flatten(projection.docs))
      }
    },
  })

  OrderTC.addResolver({
    name: 'listOrderStatusReasons',
    type: OrderStatusReasonType,
    kind: 'query',
    args: {
      orderStatus: '[String!]!',
      options: 'Options',
      searchString: 'String',
    },
    resolve: async ({ args }: { args: IStatusReasonListParams }) => {
      return await statusReasonList(args)
    },
  })

  //mutations
  OrderTC.addResolver({
    name: 'cancelOrders',
    type: 'BulkCancelOrderResult',
    args: {
      orderIds: '[String!]!',
      reason: 'String!',
    },
    resolve: async ({ args, context }: { args: any; context: any }) => {
      const result = await cancelOrders(args.orderIds, args.reason, context)
      return result
    },
  })

  OrderTC.addResolver({
    name: 'bulkCancelOrdersDelivery',
    type: 'BulkCancelDeliveryResult',
    args: {
      orderIds: '[String!]!',
      reason: 'String!',
    },
    resolve: async ({ args, context }: { args: any; context: any }) => {
      const result = await cancel(args.orderIds, args.reason, context)
      return result
    },
  })

  OrderTC.addResolver({
    name: 'bulkRebookDriver',
    type: 'BulkRebookDriverResult',
    args: {
      orderIds: '[String!]!',
    },
    resolve: async ({ args, context }: { args: any; context: any }) => {
      const result = await rebook(args.orderIds, context)
      return result
    },
  })

  OrderTC.addResolver({
    name: 'bulkAcceptOrder',
    type: 'BulkAcceptOrderResult',
    args: {
      orderIds: '[String!]!',
    },
    resolve: async ({ args, context }: { args: any; context: any }) => {
      const result = await bulkAcceptOrder(args.orderIds, context)
      return result
    },
  })

  OrderTC.addResolver({
    name: 'manualBook',
    kind: 'mutation',
    type: DeliveryTC.getType(),
    args: {
      delivery: DeliveryTC.getITC(),
    },
    resolve: async ({
      args,
      context,
    }: {
      args: { delivery: IDeliveryStatusTimeline }
      context: IContext
    }) => {
      const deliveryDetails = await manualBook(args.delivery, context)
      return deliveryDetails
    },
  })

  OrderTC.addResolver({
    name: 'manualCompleteDelivery',
    kind: 'mutation',
    type: DeliveryTC.getType(),
    args: {
      deliveryId: 'String!',
    },
    resolve: async ({
      args,
      context,
    }: {
      args: { deliveryId: string }
      context: IContext
    }) => {
      const deliveryDetails = await manuallyCompleteDelivery({
        ...args,
        context,
      })
      return deliveryDetails
    },
  })

  OrderTC.addResolver({
    name: 'completeOrder',
    type: OrderTC.getType(),
    args: {
      orderId: 'String!',
    },
    resolve: async ({ args, context }: { args: any; context: any }) => {
      const result = await complete(args.orderId, context)
      return result
    },
  })

  OrderTC.addResolver({
    name: 'manuallyBookingFailedOrder',
    type: OrderTC.getType(),
    args: {
      orderId: 'String!',
    },
    resolve: async ({ args, context }: { args: any; context: any }) => {
      const result = await manuallybookingfailed(args.orderId, context)
      return result
    },
  })

  OrderTC.addResolver({
    name: 'getHeatmapOrders',
    kind: 'query',
    type: OrderTCPaginatedType,
    args: {
      status: '[String]'
    },
    resolve: async ({
      projection,
      args,
      context,
    }: {
      projection: any
      args: IOrderListParams
      context: IContext
    }) => {
      return await getHeatmapOrders(args, context, flatten(projection.docs))
    },
  })

  const onOrderUpdated = {
    type: 'JSON',
    args: {
      storeId: 'String',
    },
    subscribe: withFilter(
      () => pubsub.asyncIterator(['ON_ORDER_UPDATED']),
      () => {
        return true
      }
    ),
    resolve: (payload: any) => {
      return { ...payload }
    },
  }

  const onOrderChanged = {
    type: 'JSON',
    args: {
      orderId: 'String',
    },
    subscribe: withFilter(
      () => pubsub.asyncIterator(['ON_ORDER_CHANGED']),
      (payload, { orderId }) => {
        return payload._id === orderId
      }
    ),
    resolve: (payload: any) => {
      return { ...payload }
    },
  }

  return {
    query: {
      getOrder: checkAuthMiddleware({
        resolver: OrderTC.getResolver('getOrder'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      listOrders: checkAuthMiddleware({
        resolver: OrderTC.getResolver('listOrders'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      listOrderStatusReasons: checkAuthMiddleware({
        resolver: OrderTC.getResolver('listOrderStatusReasons'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      orderReports: checkAuthMiddleware({
        resolver: OrderTC.getResolver('orderReport'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      getHeatmapOrders: checkAuthMiddleware({
        resolver: OrderTC.getResolver('getHeatmapOrders'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
    },
    mutation: {
      cancelOrders: checkAuthMiddleware({
        resolver: OrderTC.getResolver('cancelOrders'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      bulkCancelOrdersDelivery: checkAuthMiddleware({
        resolver: OrderTC.getResolver('bulkCancelOrdersDelivery'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      manualBook: checkAuthMiddleware({
        resolver: OrderTC.getResolver('manualBook'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      manualCompleteDelivery: checkAuthMiddleware({
        resolver: OrderTC.getResolver('manualCompleteDelivery'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      manuallyBookingFailedOrder: checkAuthMiddleware({
        resolver: OrderTC.getResolver('manuallyBookingFailedOrder'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      bulkRebookDriver: checkAuthMiddleware({
        resolver: OrderTC.getResolver('bulkRebookDriver'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      bulkAcceptOrder: checkAuthMiddleware({
        resolver: OrderTC.getResolver('bulkAcceptOrder'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
      completeOrder: checkAuthMiddleware({
        resolver: OrderTC.getResolver('completeOrder'),
        resource: ResourcesEnum.ORDER,
        scope: [
          AccountPermissionScopesEnum.READ_WRITE_SCOPE,
          AccountPermissionScopesEnum.READ_ONLY_SCOPE,
        ],
      }),
    },

    subscription: {
      onOrderUpdated: onOrderUpdated,
      onOrderChanged: onOrderChanged,
    },
  }
}

export default OrderTC
Editor is loading...
Leave a Comment