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

# GAU & Allocation

> Mapping between WeGive Funds and Salesforce General Accounting Units (GAUs) and Allocations

**Salesforce Object:** `npsp__General_Accounting_Unit__c` (NPSP standard object)<br />**WeGive Model:** Fund

## Overview

This document describes how fund/designation data syncs between WeGive and Salesforce. In Salesforce NPSP, funds are called "General Accounting Units" (GAUs) and represent designations or funds to which donations can be allocated.

**Custom fund objects:** The `fund_api_name` integration setting replaces the GAU object with a custom Salesforce object for fund pulls, pushes and deletion pulls. When it is set, the legacy single-allocation behavior described below is disabled, because `npsp__Allocation__c` can only reference a GAU. This documentation covers the standard NPSP implementation.

***

## How Fund Data Syncs

### Direction

* **Import from Salesforce** - Data imports from Salesforce into WeGive only
* **Export to Salesforce** - Data exports from WeGive to Salesforce only
* **Both Ways** - Data syncs in both directions

### Mapping Types

* **Configurable** - Can be customized via integration settings or mapping rules
* **Hard-coded** - Built into the integration logic and cannot be changed

***

## Sync Configuration

Fund pulls and pushes are controlled by the **Pull funds** and **Push funds** toggles in Sync Configuration. Related settings:

| Setting | Effect |
| :- | :- |
| `fund_api_name` | Salesforce object used instead of `npsp__General_Accounting_Unit__c` |
| `pull_deleted_funds` | Remove WeGive funds whose GAU was deleted in Salesforce |
| `enable_fund_allocations` (organization setting) | Enable per-fund allocation syncing (see GAU Allocation below) |
| `pull_deleted_fund_allocations` | Remove WeGive allocations deleted in Salesforce (requires `enable_fund_allocations`) |

***

## Sync Triggers

### From WeGive to Salesforce (Export)

Fund data is exported when a fund is created or updated in WeGive, and also on demand whenever a transaction, recurring donation, pledge or allocation that references a fund without a Salesforce ID is pushed.

### From Salesforce to WeGive (Import)

Fund data is imported from Salesforce to WeGive based on:

* **Last Modified Date:** WeGive periodically polls Salesforce for GAUs modified since the last sync
* **Modified Field Tracking:** Only GAUs with a `LastModifiedDate` newer than the last successful sync are pulled

### Deleted Funds

When `pull_deleted_funds` is enabled, GAUs with `IsDeleted = true` in the sync window soft-delete the matching WeGive fund.

***

## Sync Process Overview

### Pulling Data from Salesforce

The base query reads `Id` and `CreatedDate`; every other field comes from your Fund mapping rules. The import:

* Matches the WeGive fund by stored `salesforce_id`, creating a new fund if none exists
* Coerces a mapped `active` value to a boolean
* Fills the fund with the mapped values and stores any non-model values as custom field values

### Pushing Data to Salesforce

The fund payload is built entirely from Fund mapping rules; there are no hard-coded default fields on export. The fund's attributes and custom field values are available to rules.

### General Accounting Unit Field Mappings

| Salesforce Field | WeGive Field | WeGive API Field | Direction | Type | Notes |
| :- | :- | :- | :- | :- | :- |
| Id | Salesforce ID | `salesforce_id` | Import from Salesforce | Hard-coded | Salesforce's unique identifier |
| CreatedDate | Created At | `created_at` | Import from Salesforce | Hard-coded | When the GAU was created |
| Name | Fund Name | `name` | Both Ways | Configurable | Via mapping rule |
| npsp\_\_Description\_\_c | Description | `description` | Both Ways | Configurable | Via mapping rule |
| npsp\_\_Active\_\_c | Active Status | `active` | Both Ways | Configurable | Via mapping rule; coerced to boolean on import |
| wegive\_\_WeGive\_Entity\_\_c | WeGive Entity | Organization setting | Export to Salesforce | Hard-coded | Multi-entity orgs only |

### Active Status Handling

On import, a mapped `active` value is converted to a boolean using standard truthiness ("true", "1", "yes" and similar become `true`; everything else `false`).

### Integration with Donations

When a transaction or recurring donation has a fund assigned:

* If `enable_fund_allocations` is **off**, a transaction with a fund gets a single `npsp__Allocation__c` on its Opportunity (unless `fund_api_name` is set). Recurring Donations get no allocation in this mode
* If `enable_fund_allocations` is **on**, each WeGive fund allocation is synced as its own `npsp__Allocation__c` on the Opportunity or Recurring Donation

***

## Fund Matching & Create/Update Logic

### When WeGive Exports a Fund to Salesforce

* If the fund has a `salesforce_id`: **UPDATE** the existing GAU
* If not: acquire a per-fund lock and **CREATE** a new GAU, then store its ID

Funds are not matched by name or any other attribute.

### When Salesforce Exports a Fund to WeGive

* Search for an existing fund by `salesforce_id`; update it, or create a new one
* Import mapped fields, coercing `active` to a boolean, and store unmapped values as custom fields

***

## Integration Rules

Fund field mappings are configured as mapping rules for the `fund` integration on the Salesforce CRM. Import uses rules whose level is not `export`; export uses rules whose level is not `import`. Use them for the standard fields above and for any custom fields on the GAU object.

# GAU Allocation (Fund Allocation) - Field Mapping

**Salesforce Object:** `npsp__Allocation__c` (NPSP standard object)<br />**WeGive Model:** FundAllocation

## Overview

GAU Allocations represent how donations (Opportunities) or recurring donations are allocated to specific funds. A single donation can be split across multiple funds.

**Organization Setting Required:** `enable_fund_allocations` must be enabled for allocation syncing. When disabled, the integration uses the legacy single-fund approach described under Legacy Single Allocation.

***

## How Allocation Data Syncs

### Mapping Types

* **Hard-coded** - All allocation fields are built into the integration logic. There are no mapping rules for allocations.

***

## Sync Triggers

### From WeGive to Salesforce (Export)

Allocations are pushed **as part of their parent record's push**. Whenever a transaction or recurring donation is pushed, its allocations are synchronized to Salesforce. There is no separate allocation push.

### From Salesforce to WeGive (Import)

Allocation data is imported through two paths:

* **With the parent record:** Opportunity and Recurring Donation pulls include the parent's `npsp__Allocation__c` children in the same query. This is not possible when `uses_payments` is enabled, because that pull reads the Payment object
* **Standalone allocation pull:** Polls `npsp__Allocation__c` records (excluding deleted ones) modified since the last sync

### Deleted Allocations

When `pull_deleted_fund_allocations` is enabled (and `enable_fund_allocations` is on), allocations with `IsDeleted = true` in the sync window soft-delete the matching WeGive allocation.

***

## Sync Process Overview

### Pulling Data from Salesforce

For each Salesforce allocation the import:

1. Requires `Id` and `npsp__General_Accounting_Unit__c`
2. Finds the parent: the WeGive transaction matching `npsp__Opportunity__c`, or the recurring plan matching `npsp__Recurring_Donation__c`. Fails if neither is found
3. Finds the WeGive fund matching the GAU. Fails if not found
4. Matches the WeGive allocation by `salesforce_id`, or creates one
5. Sets the amount (dollars x 100), fund, parent and donor

**Reconciliation.** After importing, the integration compares each touched parent's WeGive allocations against Salesforce's complete current set for that parent. WeGive allocations that have a `salesforce_id` no longer present in Salesforce are soft-deleted. Allocations created in WeGive that have not yet been pushed (no `salesforce_id`) are never touched. This handles NPSP designation changes, which delete the old allocation and create a new one under a new ID.

<Note>
  The reconciliation only runs against a set the integration knows is complete. A parent-record pull whose allocation subquery was truncated (Salesforce caps child rows) is treated as "not fetched", and a standalone pull that receives fewer rows than Salesforce reported refuses to reconcile rather than delete against a partial set.
</Note>

### Pushing Data to Salesforce

When a transaction or recurring donation with allocations is pushed:

1. The parent record has already been created, so it has a `salesforce_id`
2. Any allocation whose fund has no `salesforce_id` triggers a fund push first
3. Existing `npsp__Allocation__c` records for the parent are fetched from Salesforce
4. **Sync to match** (one-time gifts and Recurring Donations): each WeGive allocation is updated if it has a `salesforce_id`, otherwise created; Salesforce allocations not in the resulting keep-list are deleted
5. **Adoption** (installment Opportunities of a recurring donation): see Recurring Installments below

### Allocation Field Mappings

| Salesforce Field | WeGive Field | WeGive API Field | Direction | Type | Notes |
| :- | :- | :- | :- | :- | :- |
| Id | Salesforce ID | `salesforce_id` | Import from Salesforce | Hard-coded | Salesforce's unique identifier |
| npsp\_\_Opportunity\_\_c | Transaction Salesforce ID | `allocatable.salesforce_id` | Both Ways | Hard-coded | Create only on export (never sent on update) |
| npsp\_\_Recurring\_Donation\_\_c | Recurring Donation Salesforce ID | `allocatable.salesforce_id` | Both Ways | Hard-coded | Create only on export (never sent on update) |
| npsp\_\_General\_Accounting\_Unit\_\_c | Fund Salesforce ID | `fund.salesforce_id` | Both Ways | Hard-coded | On update, sent only when the fund already has a Salesforce ID |
| npsp\_\_Amount\_\_c | Amount | `amount` | Both Ways | Hard-coded | Dollars in Salesforce, cents in WeGive |

`npsp__Percent__c` is read during pulls but is not stored in WeGive and is not exported. Allocations are amount-based on both sides.

### Recurring Installments

NPSP automatically copies a Recurring Donation's GAU Allocations onto every installment Opportunity it links. Pushing WeGive's own allocations on top would over-allocate the Opportunity and be rejected by Salesforce. For a transaction that belongs to a recurring donation, the integration therefore:

* Matches each WeGive allocation to an NPSP-propagated allocation on the Opportunity by GAU, preferring one with the same amount
* Stores that record's Salesforce ID on the WeGive allocation so later pulls reconcile by ID
* Creates its own allocation only if NPSP did not propagate one for that GAU
* Never deletes allocations on an installment Opportunity

### Legacy Single Allocation

When `enable_fund_allocations` is off, a transaction with a fund (and no `fund_api_name` override) gets one `npsp__Allocation__c` on its Opportunity for the full net amount. Before inserting, the integration checks for an existing allocation on the Opportunity (for example NPSP's default GAU allocation) and updates that instead. The allocation ID is stored on the transaction. If a later update finds the allocation deleted in Salesforce, the stored ID is cleared and the check-then-insert is repeated.

***

## Allocation Matching & Create/Update Logic

### When WeGive Exports Allocations

* Allocations with a `salesforce_id` are **updated** (amount, and GAU when the fund is synced)
* Allocations without one are **created** and their IDs stored
* For one-time gifts and Recurring Donations, Salesforce allocations not in the keep-list are **deleted**
* For recurring installment Opportunities, NPSP's allocations are adopted as described above

### When Salesforce Exports Allocations to WeGive

1. Find the parent transaction or recurring plan by Salesforce ID; fail if not found
2. Find or create the WeGive allocation by `salesforce_id`
3. Find the fund by GAU ID; fail if not found
4. Set amount, fund, parent and donor, then save
5. Reconcile the parent's allocations against Salesforce's complete set

***

## Required Fields

**For WeGive to Salesforce:**

* Parent reference (`npsp__Opportunity__c` or `npsp__Recurring_Donation__c`) on create
* `npsp__General_Accounting_Unit__c`
* `npsp__Amount__c`

**For Salesforce to WeGive:**

* `Id`
* Parent reference matching an existing WeGive transaction or plan
* `npsp__General_Accounting_Unit__c` matching an existing WeGive fund
* `npsp__Amount__c`

## Usage Examples

### Example 1: Single Allocation

A \$100 donation entirely to the "Building Fund":

* **WeGive:** One FundAllocation with amount = 10000 (cents)
* **Salesforce:** One Allocation with `npsp__Amount__c = 100`

### Example 2: Split Allocation

A $100 donation split $60 / \$40 between two funds produces two FundAllocation records (6000 and 4000 cents) and two Salesforce Allocations (60 and 40).

### Example 3: Recurring Donation with Allocations

A \$50/month recurring donation split between two funds has two Allocations on the Recurring Donation. NPSP copies them onto each installment Opportunity, and the integration adopts those copies for each installment transaction.

***

## Troubleshooting

**Allocations not syncing:**

* Verify `enable_fund_allocations` is on
* Check that the parent transaction or recurring plan has a `salesforce_id`
* Ensure funds have `salesforce_id` values (funds are pushed automatically if missing)
* With `uses_payments`, allocations arrive through the standalone allocation pull, not the transaction pull

**Allocation amounts do not match:**

* WeGive stores cents, Salesforce dollars
* Percent-based allocations in Salesforce are imported by their amount only

**Allocations disappearing in WeGive after a pull:**

* Reconciliation soft-deletes WeGive allocations whose Salesforce record no longer exists. Check whether the allocation was deleted or replaced in Salesforce (a designation change replaces the record)

**Installment Opportunity rejected as over-allocated:**

* NPSP has already propagated the Recurring Donation's allocations. Confirm the WeGive allocation GAUs match the Recurring Donation's allocations so they can be adopted

**Fund not found errors:**

* Ensure the GAU referenced by the allocation exists in WeGive with a matching `salesforce_id`

**Parent record not found:**

* Verify the transaction or recurring plan exists in WeGive with a matching `salesforce_id`
* An allocation must reference either an Opportunity or a Recurring Donation

***

## Best Practices

1. Enable fund allocations if your organization tracks donations across multiple funds
2. Create funds before creating transactions with allocations
3. Keep the same fund structure in both systems
4. Monitor sync logs for allocation errors
5. Test allocation changes in a sandbox before production
6. If you use `uses_payments`, make sure the standalone allocation pull is running so allocations stay current

## Related Documentation

* [Data Mapping Overview](./overview) - object index and cross-cutting data conventions
* [Opportunity & Payment](./opportunity) - the parent Opportunity for transaction allocations
* [Recurring Donation](./recurring-donation) - the parent Recurring Donation for plan allocations

*Verified against the integration source, September 2026.*


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.