> ## Documentation Index
> Fetch the complete documentation index at: https://docs.on-it.no/llms.txt
> Use this file to discover all available pages before exploring further.

# Project Trigger

> A trigger that updates the actualStartDate when it's created, actualEndDate when it's completed, and orgUnit1 and orgUnit2 when it's responsible employee is changed.

A common issue inherited from Business NXT is that users forget to set the actualStartDate when they create a project, and when the project is concluded, they forget to set the actualEndDate.
This trigger will automatically set the actualStartDate to the current date when the project is created and the actualEndDate to the current date when the project is concluded. In addition it will set the project department to the department of the user who created the project.

**[TLDR](/nxt-triggers/examples/projects-trigger#the-complete-trigger)**

Let's create the trigger part by part.

## Setup an ISV user

First we have to create an ISV user, so that we can use GraphQL to query the Business NXT API.

1. Start by following Vismas guide on how to create an ISV user [here](https://docs.business.visma.net/docs/authentication/service/setup_service). Make sure that the name of the user starts with **nbt** or **nt** in order to not acrue any extra costs for ignored events. The user name will be **isv\_nt\_yourclientname**.
2. Add the ISV user to Business NXT by following the guide [here](https://docs.business.visma.net/docs/authentication/service/vbnxt_service).
3. Take the credentials created for the ISV user and add them to the settings in NXT Triggers. It must be stored under `VISMA_CLIENT_ID` and `VISMA_CLIENT_SECRET`.

## Starting with an empty trigger

Start by creating a new trigger in NXT Triggers and select the `orgUnit2`-table and `ALL` events. This will give you some sample code, but we'll just remove all of that.

```typescript theme={null}
import { HandlerFunctionArgs, gql, invariant } from "businessnxt-dev";

export default async function ({
  event,
  db,
}: HandlerFunctionArgs<"orgUnit2", Env>) {
  if (event.event !== "DELETE") {
    // this is where we'll add our code
  }
}
```

## Getting the data we need

First we need to get the data we need to update the project. We need the `orgUnit1`, `orgUnit2`, `orgUnitProcessing`, `actualEndDate`, `actualStartDate`, `changedDate`, and the `official`-field from the project.

To simplify creating the query, we can use the [playground in Business NXT](https://docs.business.visma.net/graphiql/) to create the query. The query will look like this:

```graphql theme={null}
query REndDTandR1onR2($companyNo: Int, $orgUnit2No: Int) {
  useCompany(no: $companyNo) {
    orgUnit2(filter: { orgUnit2No: { _eq: $orgUnit2No } }) {
      items {
        orgUnit1
        orgUnit2No
        orgUnitProcessing ##Susp
        actualEndDate
        actualStartDate
        changedDate
        official: joinup_Associate_via_Official {
          orgUnit1
        }
      }
    }
  }
```

## The complete trigger

```typescript theme={null}
import { HandlerFunctionArgs, gql, invariant } from "businessnxt-dev";

const QUERY_REndDTandR1onR2 = gql`
  query REndDTandR1onR2($companyNo: Int, $orgUnit2No: Int) {
    useCompany(no: $companyNo) {
      orgUnit2(filter: { orgUnit2No: { _eq: $orgUnit2No } }) {
        items {
          orgUnit1
          orgUnit2No
          orgUnitProcessing ##Susp
          actualEndDate
          actualStartDate
          changedDate
          official: joinup_Associate_via_Official {
            orgUnit1
          }
        }
      }
    }
  }
`;

const MUTATION_UpdateOrgUnit2 = gql`
  mutation UpdateOrgUnit2(
    $companyNo: Int
    $orgUnit2No: Int
    $update: OrgUnit2_Input!
  ) {
    useCompany(no: $companyNo) {
      orgUnit2_update(
        filter: { orgUnit2No: { _eq: $orgUnit2No } }
        value: $update
      ) {
        affectedRows
      }
    }
  }
`;

export default async function ({
  event,
  createGraphQLClient,
  db,
}: HandlerFunctionArgs<"orgUnit2", Env>) {
  if (event.event !== "DELETE") {
    const client = await createGraphQLClient();
    const rsp = await client.request<any>(QUERY_REndDTandR1onR2, {
      companyNo: event.companyNo,
      orgUnit2No: event.primaryKeys.orgUnit2No,
    });

    const orgUnit2 = rsp.useCompany.orgUnit2.items?.[0];

    const update = {
      actualEndDate:
        orgUnit2.actualEndDate === 0 &&
        orgUnit2.orgUnitProcessing === (orgUnit2.orgUnitProcessing | 1)
          ? orgUnit2.changedDate
          : undefined,
      actualStartDate:
        orgUnit2.actualStartDate === 0 ? orgUnit2.changedDate : undefined,
      orgUnit1:
        orgUnit2.orgUnit1 !== orgUnit2.official?.orgUnit1 &&
        orgUnit2.official?.orgUnit1
          ? orgUnit2.official?.orgUnit1
          : undefined,
    };

    const hasUpdates = Object.values(update).filter((x) => x).length > 0;
    if (hasUpdates) {
      const rsp = await client.request<any>(MUTATION_UpdateOrgUnit2, {
        companyNo: event.companyNo,
        orgUnit2No: event.primaryKeys.orgUnit2No,
        update,
      });
      console.log("response", rsp);
    }
  }
}
```
