We're moving the community! Starting July 7, the current community will be read-only for approx. 2 weeks. You can browse content, but posting will be temporarily unavailable. Learn more

Re: "Field 'customers' doesn't exist on type 'QueryRoot'

Solved

"Field 'customers' doesn't exist on type 'QueryRoot'

FutureAndAHope
Shopify Partner
51 3 19

I have a checkout extension, and I need to fetch all orders from customers that are associated with a particular company. I need to do this so I can find out if a company has unpaid orders. This is used in a credit app, to determine how much credit a customer has available.  But I get the error "Field 'customers' doesn't exist on type 'QueryRoot'

 

 

import {useEffect, useState} from 'react';
import {
  Banner,
  reactExtension,
  useBuyerJourneyIntercept,
  usePurchasingCompany,
  useApi,
  useTranslate,
    useSettings,
    useTotalAmount
} from "@shopify/ui-extensions-react/checkout";

// 1. Choose an extension target
export default reactExtension("purchase.checkout.block.render", () => (
  <Extension />
));

function Extension() {
    const translate = useTranslate();
    //const customer = useCustomer();
    const {extension, query} = useApi();
    const [balance, setBalance] = useState(-1);
    const [done, setDone] = useState(false);
    const {credit_allowed} = useSettings();
    const {amount, currencyCode} = useTotalAmount();
    const [error, setError] = useState('');
    const companyData = usePurchasingCompany();
    const [otherErrors, setOtherErrors]= useState([]);
    const [customers, setCustomers] = useState([]);


    const fetchCustomers = () => {
        query(`
    {
        customers(first: 250, query:"companyContactProfiles.company.id:`+companyData.company.id +`"){
        edges {
            node {
                id
                companyContactProfiles{
                    edges{
                        node {
                           company{
                              id
                           }
                        }
                    }
                }
            }
        } 
      }
    }`).then(({data, errors}) => {
        setOtherErrors(errors)
        const len = data.edges.length;
        let out = [];
        for(let i= 0; i < len; i++){
            out.push(data.edges[i]['node']['id']);
        }
        setCustomers(out);
    }).catch((ex)=>{
        setError(ex);
        setDone(true);
        });
    }

    const fetchOrders = (customer_id, cursor) => {

        return new Promise((resolve, reject) => {


            if (cursor === null) {
                resolve([])
                return;
            }

            query(`
    query{
    
        customer(id: `+customer_id+`)
     
        orders(first: 250 ` + (cursor !== '' ? ', after: ' + cursor : '') + `, query: "company.id:`+companyData.company.id +`") {
          edges {
            node {
            company{
                id
            }
              totalPriceSet {
                shopMoney {
                  amount
                }
              }
              cancelledAt
              displayFinancialStatus
              refunds {
                totalRefunded {
                  amount
                }
              }

            }
            cursor
          }
          pageInfo {
            hasNextPage
          }
        }
        
        }
    }`,

            ).then(({data, errors}) => {
                setOtherErrors(errors)
                let curs = null;
                if (data.customer.orders.pageInfo.hasNextPage) {
                    curs = data.customer.orders.edges[data.customer.orders.edges.length - 1].cursor;
                }
                fetchOrders(customer_id, curs).then((ord) => {


                    let out = [];
                    if (data.customer.orders.edges.length > 0) {
                        out = data.customer.orders.edges;
                    }
                    resolve(out.concat(ord));
                })
            }).catch((err) => {
                reject(err);
            });
        });
    }

    const fetchCustomerOrders = () =>{
        return new Promise((res, rej) =>{
            let bal = 0;
            let action_counter = 0;

            const len = customers.length;
            for(let j = 0; j < len; j++) {

                fetchOrders(customers[j], '').then((ord) => {

                    let totalAmount = 0;
                    let outstandingBalance = 0;
                    let totalRefunded = 0;
                    let totalCanceled = 0;
                    let orderCount = ord.length;

                    for (let i = 0; i < orderCount; i++) {

                        let order = ord[i];

                        totalAmount += order['node']['totalPriceSet']['shopMoney']['amount'];

                        if (order['node']['displayFinancialStatus'] !== 'PAID') {
                            outstandingBalance += order['node']['totalPriceSet']['shopMoney']['amount'];
                        }
                        if (order['node']['displayFinancialStatus'] !== 'PAID') {

                            if (order['node']['cancelledAt']) {

                                totalCanceled += order['node']['totalPriceSet']['shopMoney']['amount'];

                            } else {
                                let refundCount = order['node']['refunds'].length;
                                for (let i = 0; i < refundCount; i++) {
                                    let refund = order['node']['refunds'][i];
                                    totalRefunded += refund['totalRefunded']['amount'];
                                }
                            }

                        }
                    }

                    bal += (outstandingBalance - totalRefunded - totalCanceled);
                    action_counter++
                    if(len === action_counter){
                        res(bal);
                    }
                }).catch((err) => {
                    rej(err)

                });
            }
        })
    }

    useEffect(()=>{
        fetchCustomers();
    },[])

    useEffect(() => {
        if(customers.length === 0){
            return;
        }
        fetchCustomerOrders().then((bal) => {
            setBalance(bal);
            setDone(true)
        }).catch((err)=>{
            setError(err);
            setDone();
        })
    }, [customers]);


    let ok = false;
    let message = '';
    if (balance !== -1 && done) {

        if ((credit_allowed - balance) >= amount) {
            ok = true;
        } else {
            message = 'You only have ' + (credit_allowed - balance).toFixed(2) + ' available to spend. You can not checkout.';
        }
    }

    const blockResponse = (canBlockProgress) => {
        if (!companyData) {
            return {
                behavior: 'allow',
            }
        } else if (ok) {
            return {
                behavior: 'allow',
            }
        } else if (balance !== -1 && done && message.length > 0) {
            return {
                behavior: 'block',
                reason: 'Not enough credit.',
                errors: [
                    {

                        message:
                        message,
                    },
                ],
            };
        } else if (!done && canBlockProgress) {
            return {
                behavior: 'block',
                reason: 'Still calculating ...',
                errors: [
                    {
                        message:
                            'Checking if you have any outstanding bills.',
                    },
                ],
            };
        } else {
            return {
                behavior: 'allow',
            }
        }
    }

    const getData = () => {
        return 'Balance: ' + balance + ' done: ' + (done ? 'true' : 'false') + 'credit: ' + credit_allowed + ' amount: ' + amount + ' error: ' + error + ' Company: ' + JSON.stringify(companyData) + ' Other: ' + JSON.stringify(otherErrors);
    }

    const block = blockResponse(true);

    let banner = <Banner status="success" title={"You" + getData()} />

    if(block['behavior'] === 'block'){
        banner = <Banner status="error" title={block['errors'][0]} />
    }

    useBuyerJourneyIntercept(
        ({canBlockProgress}) => {
            return blockResponse(canBlockProgress)
        },
    );



    return banner;

}

 

Accepted Solution (1)
FutureAndAHope
Shopify Partner
51 3 19

This is an accepted solution.

The problem turns out to be that the storefront API (that is used by checkout UI) only has a subset of the Admin API commands. So it is not accessible via the functions above.

View solution in original post

Replies 2 (2)

FutureAndAHope
Shopify Partner
51 3 19

I looked in the documentation and apparently "company" exists on query root. So I tried to use it, but it too gives the same typeof error. "Field 'company' doesn't exist on type 'QueryRoot'"

 

I have the following scopes defined, and have allowed protected customer data.

 

scopes = "read_customers, read_orders, read_companies"

 

 

 

const fetchCustomers = () => {
        query(`query{
        company(id: "`+companyData.company.id +`"){
           contacts(first: 250){
              edges{
                  node{
                     customer {
                        id
                     }
                  }
              }
           }
        }
    }`).then(({data, errors}) => {
        setOtherErrors(errors)
        const len = data.contacts.edges.length;
        let out = [];
        for(let i= 0; i < len; i++){
            out.push(data.contacts.edges[i]['node']['id']);
        }
        setCustomers(out);
    }).catch((ex)=>{
        setError(ex);
        setDone(true);
        });
    }

 

 

 

 

 

FutureAndAHope
Shopify Partner
51 3 19

This is an accepted solution.

The problem turns out to be that the storefront API (that is used by checkout UI) only has a subset of the Admin API commands. So it is not accessible via the functions above.