> ## 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.

# Fund Data Mapping

> Detailed field mapping for funds and GL codes between WeGive and DonorPerfect systems.

# Fund Data Mapping

This document details how WeGive funds map to DonorPerfect GL codes. This is a narrow, one-way, create-only sync — not the full lifecycle management the name suggests.

## DonorPerfect Table Reference

**Primary Table**: `dpcode` (Code Tables)
**WeGive Model**: `Fund`
**Sync Direction**: WeGive → DonorPerfect (Push Only, **create-only**)

<Warning>
  `syncFund()` only runs when the fund has **no** `dp_id` yet. Once a GL code has been created for a fund, later changes to the fund's name or description in WeGive are **never** pushed to DonorPerfect — there is no update path at all.
</Warning>

## Core Fund Fields

### What's Actually Sent (`dp_savecode`)

| Parameter | Value | Notes |
| - | - | - |
| `field_name` | `"GL_CODE"` | Hardcoded |
| `code` | The fund's own WeGive `id` (numeric) | **Not** `dp_gl_code` — see the note below |
| `description` | Fund `name` | |
| `inactive` | `"N"` | Hardcoded — always sent as active, regardless of the fund's real WeGive active status |
| `user_id` | `"WeGive"` | |
| everything else (`original_code`, `mcat_hi`/`mcat_lo`, `reciprocal`, `mailed`, `printing`, `other`, `goal`, `acct_num`, `campaign`, `solicit_code`, `overwrite`, `client_id`, `cashact`, `membership_type`, `leeway_days`, `comments`, `begin_date`, `end_date`, `ty_*` fields) | `null` | Sent as part of the payload but always null — no corresponding WeGive field feeds any of them |

<Warning>
  **The fund's `dp_gl_code` column is not used here at all.** It's a real column on the `funds` table, but `syncFund()` never reads it — the GL code created in DonorPerfect always uses the fund's own numeric WeGive `id`. `dp_gl_code` is used elsewhere: as the `gl_code` **attribution** value on an individual gift push (`syncGift()`'s `@gl_code` parameter) — it labels which GL code a specific gift should be filed under, but doesn't control what code gets created for the fund itself.
</Warning>

### Fields That Don't Sync

* Fund `description` (the extended field, distinct from `name`)
* Fund category
* Fund goal amount
* Fund active/inactive status (always sent as `inactive: "N"`)
* Fund hierarchy/parent-child structure

## GL Code Creation Process

1. A gift push (`syncGift()`) checks whether the transaction's fund has a `dp_id`
2. If not, `syncFund()` is called inline, before the gift itself is sent
3. `syncFund()` acquires a per-fund Redis lock, re-checks `dp_id` under the lock (to prevent duplicate creation under concurrent pushes), then calls `dp_savecode` if still null
4. On success, `dp_id` is set to the fund's own `id` (not a value returned by DonorPerfect — DonorPerfect's `dp_savecode` response isn't parsed for an id at all)
5. That's it — there's no further update, validation, or lifecycle step

<Note>
  Because `dp_id` is set to the fund's own numeric `id` rather than something returned by the API, there's no way to detect from WeGive's side whether the `dp_savecode` call actually succeeded on DonorPerfect's end beyond the HTTP response status — a logical DonorPerfect-side error (returned as an `<error>` XML element under an HTTP 200) would still result in `dp_id` being set locally.
</Note>

## Fund Deactivation

<Warning>
  Deactivating a fund in WeGive has no effect on its DonorPerfect GL code — there's no status sync of any kind. The GL code, once created, exists in DonorPerfect independent of the WeGive fund's active/inactive state going forward.
</Warning>

## API Operations

### `dp_savecode` (Create Only)

See the parameter table above — this is the complete, fixed set every time.

### Pull

<Warning>
  There is no fund pull in this integration at all — `DonorPerfect.php` implements no `pullFund()` method. Funds only ever flow WeGive → DonorPerfect, one direction, once per fund.
</Warning>

## Error Handling

<Warning>
  There is no automatic retry, alternate-code generation, or validation beyond the Redis lock described above. A failed `dp_savecode` call (network error, DonorPerfect logical error) simply leaves the fund without a `dp_id`. Since `syncGift()` calls `syncFund()` directly (not wrapped in a try/catch) before proceeding to the gift itself, **a fund-sync failure blocks the gift push too** — an exception from `syncFund()` propagates up and the gift's own `dp_savegift` call never happens for that attempt. The gift push is retried on the next attempt, which re-triggers the fund sync as well (since `dp_id` is still null).
</Warning>

## Data Quality Considerations

### Before Sync

* There's no need to pre-configure custom GL codes — the fund's own WeGive `id` is what gets used, and `dp_gl_code` isn't read for this purpose
* If you need a specific, human-readable GL code in DonorPerfect rather than WeGive's internal fund id, this integration doesn't support setting it — the code is always the fund's numeric id

### Ongoing Maintenance

* Fund name changes made after the GL code already exists won't propagate — if a name correction is needed in DonorPerfect, it has to be made there directly
* Check Sentry (not the WeGive dashboard) for `dp_savecode` failures

## Troubleshooting

### GL Codes Not Creating

**Possible causes:**

* The integration is disabled
* API authentication failure
* A DonorPerfect logical error was returned (check Sentry for the raw response body)

**Solutions:**

* Confirm the integration's `enabled` flag
* Verify API credentials
* Check Sentry for the specific DonorPerfect error text

### Fund Name Not Updating in DonorPerfect

**Cause:** Not a bug — there's genuinely no update path once a GL code exists for a fund. This is expected behavior, not a sync failure.

**Solution:** Update the GL code's description directly in DonorPerfect.

## Known Limitations

* Create-only — no update, no status sync, no pull
* `dp_gl_code` isn't used to control the created GL code's identifier (it's gift-attribution metadata only)
* No fund hierarchy, category, or goal-amount sync
* No custom GL code numbering — the code is always the fund's own WeGive id

## Related Documentation

<CardGroup>
  <Card title="Transaction Mapping" href="/external/onboarding/donorperfect/data-mapping/transaction">
    How GL codes are used in transaction/gift processing
  </Card>

  <Card title="Configuration Guide" href="/external/onboarding/donorperfect/configuration-options">
    Integration-level configuration (most sync-scope toggles are currently non-functional)
  </Card>

  <Card title="Integration Nuances" href="/external/onboarding/donorperfect/integration-nuances">
    Platform-specific fund handling behaviors
  </Card>

  <Card title="Data Overview" href="/external/onboarding/donorperfect/data-mapping/overview">
    Complete data mapping documentation
  </Card>
</CardGroup>

For additional help with fund data mapping, contact our support team at [support@wegive.com](mailto:support@wegive.com).


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