@W-22335628 add generating-eval-seed-data skill (#237)

* feat: add generating-eval-seed-data skill

New skill that generates minimal seed-data stubs (custom fields, objects,
Apex class stubs) for evaluation datasets in the afv-library. Adapted from
the adk-eval-seed-data-generator with afv-library conventions and all
PR #194 review feedback addressed (scoped allowed-tools, no hardcoded
paths, progressive disclosure, skills referenced by name).

* fix: replace stub eval data with real adk-core datasets

Replace fabricated eval stubs with actual gold files and seed-data from
adk-core: payment_overdue (formula field), AssetFedexValidationRule
(validation rule with lookup deps), QueueableWithCalloutRecipes (Apex
with class dependencies).

* fix: remove related-skills from generating-eval-seed-data frontmatter

* fix: use detailed allowed-tools command signatures

* fix: scope allowed-tools to sf project deploy start only

* fix: change stage from Draft to Pilot
This commit is contained in:
ysachdeva-sfdc 2026-05-05 13:13:46 +05:30 committed by GitHub
parent 4d37555dd8
commit 808127c03a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 635 additions and 0 deletions

View File

@ -0,0 +1,162 @@
---
name: generating-eval-seed-data
description: "Generate minimal seed-data stubs for Salesforce metadata evaluation datasets in the afv-library. Use this skill to create seed-data directories containing lightweight dependency declarations (custom fields, objects, Apex class stubs) that a dataset's gold file references. TRIGGER when: user says generate seed data, create seed-data stubs, populate seed-data, dataset dependencies, gold file dependencies, add supporting metadata for eval, or wants to set up prerequisite objects/fields for a test dataset. Also use when the user mentions seed-data, eval fixtures, stub generation, or asks to fill in the seed-data directory for any skill's tests/evals/ dataset. SKIP when: user wants to generate the gold file itself (use the domain-specific generating skill), wants to run evals (use eval runner tooling), or wants to create a new skill from scratch (use creating-sf-skill)."
license: LICENSE.txt has complete terms
metadata:
version: "1.0"
stage: Pilot
allowed-tools: Bash(sf project deploy start) Read Write
---
# Generating Eval Seed Data
Generate seed-data **stubs** — minimal supporting metadata dependencies — for evaluation datasets in the afv-library. Stubs declare the bare-minimum custom objects, fields, relationships, and Apex classes that a dataset's gold file references, just enough so the gold file can be validated in isolation.
## Scope
- **In scope**: Analyzing gold files to identify custom dependencies, generating minimal stub XML/Apex for those dependencies, validating stubs deploy successfully via dry-run, and populating the `seed-data/` directory.
- **Out of scope**: Generating the gold file itself (delegate to the domain-specific skill), creating new eval datasets or prompt.md files (delegate to `creating-sf-skill`), deploying metadata to production orgs.
---
## Required Inputs
Gather before proceeding:
- **Dataset path**: Path to a single dataset (`skills/<name>/tests/evals/<dataset>/`) or a domain path containing multiple datasets. Always ask if not provided.
- **Target org alias**: The Salesforce org alias for dry-run validation (e.g., `myDevOrg`). Ask if not provided.
Defaults unless specified:
- API version: `62.0`
- Stub style: absolute minimum elements per metadata type (see `references/stub-rules.md`)
---
## Workflow
All steps are sequential. Do not skip or reorder.
### Phase 1 — Identify and Read
1. **Identify the dataset(s)**
- If the path contains `tests/evals/<datasetName>` (or has `prompt.md` / `gold/` directly inside), treat as a single dataset.
- Otherwise, look for `tests/evals/` subdirectory. If it exists, list all subdirectories — each is a dataset. Process them all.
- If neither pattern matches, ask the user to clarify.
2. **Read the gold file(s)**
- Look for gold files in `{dataset_path}/gold/`. These are Salesforce metadata XML or Apex files.
- If gold files exist, proceed to step 3.
- If gold files do NOT exist, ask: "This dataset has no gold file. Would you like me to generate one from `prompt.md`?" If yes, read `prompt.md` and generate a plausible gold file, then proceed.
3. **Read stub generation rules** — load `references/stub-rules.md` before analyzing.
### Phase 2 — Analyze and Generate
4. **Analyze dependencies**
- Read all gold files and identify every custom dependency. Look for:
- **Custom fields** (`__c`): referenced in formulas, conditions, assignments, or relationship traversals (`__r.Name` implies a lookup `__c`)
- **Custom objects** (`__c`): any custom object the gold metadata lives on or references via lookups
- **Apex classes**: parent classes, interfaces, or utility classes referenced by gold code
- For each dependency, determine: metadata type, correct API name, minimum required attributes.
- Standard Salesforce objects (Account, Contact, Case, etc.) and their standard fields do NOT need stubs.
5. **Generate stubs**
- Create the `seed-data/` directory structure following the rules in `references/stub-rules.md`.
- Include ONLY the minimum elements per metadata type — no optional attributes.
- For picklists: only include values explicitly referenced in the gold file.
6. **Compare against example** — verify output matches patterns in `examples/stub-examples.md`.
### Phase 3 — Validate
7. **Validate with dry-run deployment**
- Create a temporary SFDX project:
```bash
cd /tmp && sf project generate --name seed-data-validation-$(date +%s) --template empty
```
- Read the temp project's `sfdx-project.json` to resolve the deploy path — do not hardcode `force-app/main/default/`. Extract `packageDirectories[].path` (use the entry with `"default": true`; if none, use the first entry).
- Copy seed-data and gold files into the resolved deploy path:
```bash
cp -r {dataset_path}/seed-data/* {temp_project}/{resolved_path}/
cp -r {dataset_path}/gold/* {temp_project}/{resolved_path}/
```
- Run dry-run:
```bash
sf project deploy start --dry-run -d "{resolved_path}" --target-org {target_org} --test-level NoTestRun --wait 10 --json
```
8. **Auto-fix on failure**
- Parse JSON error output and fix issues (missing fields, invalid types, missing relationships).
- Re-run dry-run after each fix. Max 3 retries.
- If still failing after 3 retries, report remaining errors and ask for guidance.
9. **Copy validated stubs back**
- Replace `{dataset_path}/seed-data/` with the validated versions.
- Only copy back stub files you generated — do NOT copy gold file content into seed-data.
10. **Clean up and report**
- Delete the temporary SFDX project.
- Report: files generated, validation status, any fixes applied.
- For multiple datasets, print a summary table:
| # | Dataset | Stubs Generated | Validation | Notes |
|---|---------|----------------|------------|-------|
| 1 | … | … | … | … |
---
## Rules / Constraints
| Constraint | Rationale |
|-----------|-----------|
| Stubs include ONLY minimum required elements | Optional attributes add noise and can cause unexpected deployment errors |
| Never invent picklist values beyond what gold references | Extra values create false dependencies and mislead evaluators |
| Standard objects/fields never get stubs | They exist in every org; stubs would be redundant and can conflict |
| Always validate via dry-run before finalizing | Catches missing dependencies and malformed XML before the contributor sees them |
| API version defaults to 62.0 | Matches current afv-library convention; override only if gold file specifies otherwise |
| Copy back only stub files, not gold files | Mixing gold content into seed-data corrupts the dataset structure |
| Never hardcode `force-app/main/default/` — always read `sfdx-project.json` | Customers customize the package directory path; hardcoding breaks non-default projects |
| Reference cross-skills by name, never by filesystem path | Skill catalog layout varies across AFV installations; hardcoded paths break portability |
---
## Gotchas
| Issue | Resolution |
|-------|------------|
| Relationship traversal (`__r.Name`) implies a lookup field | Generate a Lookup stub for the corresponding `__c` field |
| Gold file references a field on a standard object | Only generate the custom field stub, not the standard object definition |
| Multiple gold files reference the same custom object | Generate the object stub once; place field stubs under the same object directory |
| Picklist referenced in formula via `ISPICKVAL` | Extract only the specific value string from the formula; do not add other values |
| Gold file has no custom dependencies | Skip stub generation; report "no seed-data needed" |
| Dry-run fails with `DUPLICATE_DEVELOPER_NAME` | A stub conflicts with an existing org object — rename or skip |
---
## Output Expectations
Deliverables:
- Stub metadata files: `{dataset_path}/seed-data/objects/{ObjectName}/fields/{FieldName}.field-meta.xml`
- Stub object definitions: `{dataset_path}/seed-data/objects/{ObjectName}/{ObjectName}.object-meta.xml`
- Stub Apex classes: `{dataset_path}/seed-data/classes/{ClassName}.cls` + `.cls-meta.xml`
- Console report: list of generated files, validation status, fixes applied
---
## Cross-Skill Integration
| Need | Delegate to |
|------|-------------|
| Generate the gold file for a dataset | Domain-specific skill (`generating-validation-rule`, `generating-apex`, etc.) |
| Create a new skill with eval datasets | `creating-sf-skill` |
| Generate a complete custom field (not a stub) | `generating-custom-field` |
| Generate a complete custom object (not a stub) | `generating-custom-object` |
---
## Reference File Index
| File | When to read |
|------|-------------|
| `references/stub-rules.md` | Phase 2, step 3 — before generating any stubs |
| `examples/stub-examples.md` | Phase 2, step 6 — to verify generated output matches expected patterns |

View File

@ -0,0 +1,132 @@
# Seed-Data Stub Examples
Input/output examples showing gold file analysis and the resulting seed-data stubs.
---
## Example 1: Formula Field with Date and Picklist Dependencies
**Gold file**: `gold/objects/Contract/fields/Payment_Overdue__c.field-meta.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Payment_Overdue__c</fullName>
<label>Payment Overdue</label>
<type>Text</type>
<formula>IF(AND(Payment_Due_Date__c &lt; TODAY(), ISPICKVAL(Payment_Status__c, "UNPAID")), "PAYMENT OVERDUE", null)</formula>
<formulaTreatBlanksAs>BlankAsZero</formulaTreatBlanksAs>
<length>20</length>
</CustomField>
```
**Analysis**: Formula references `Payment_Due_Date__c` (Date) and `Payment_Status__c`
(Picklist with value `UNPAID`).
**Generated stubs**:
`seed-data/objects/Contract/fields/Payment_Due_Date__c.field-meta.xml`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Payment_Due_Date__c</fullName>
<label>Payment Due Date</label>
<type>Date</type>
</CustomField>
```
`seed-data/objects/Contract/fields/Payment_Status__c.field-meta.xml`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Payment_Status__c</fullName>
<label>Payment Status</label>
<type>Picklist</type>
<valueSet>
<valueSetDefinition>
<value>
<fullName>UNPAID</fullName>
<label>UNPAID</label>
</value>
</valueSetDefinition>
</valueSet>
</CustomField>
```
Only `UNPAID` is included — no other values.
---
## Example 2: Flow Referencing Custom Objects
**Gold file**: A Flow XML that triggers on `Adoption__c` record creation and references
a Lookup to `Animal__c`.
**Generated stubs**:
`seed-data/objects/Adoption__c/Adoption__c.object-meta.xml`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<deploymentStatus>Deployed</deploymentStatus>
<label>Adoption</label>
<nameField>
<label>Adoption Name</label>
<type>Text</type>
</nameField>
<pluralLabel>Adoptions</pluralLabel>
<sharingModel>ReadWrite</sharingModel>
</CustomObject>
```
`seed-data/objects/Animal__c/Animal__c.object-meta.xml`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<deploymentStatus>Deployed</deploymentStatus>
<label>Animal</label>
<nameField>
<label>Animal Name</label>
<type>Text</type>
</nameField>
<pluralLabel>Animals</pluralLabel>
<sharingModel>ReadWrite</sharingModel>
</CustomObject>
```
`seed-data/objects/Adoption__c/fields/Animal__c.field-meta.xml`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Animal__c</fullName>
<label>Animal</label>
<type>Lookup</type>
<referenceTo>Animal__c</referenceTo>
<relationshipName>Adoptions</relationshipName>
</CustomField>
```
---
## Example 3: Apex Class with Parent Class Dependency
**Gold file**: `gold/classes/OrderProcessor.cls` extends `BaseProcessor`.
**Generated stubs**:
`seed-data/classes/BaseProcessor.cls`:
```java
public abstract class BaseProcessor {
}
```
`seed-data/classes/BaseProcessor.cls-meta.xml`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<status>Active</status>
</ApexClass>
```
Empty stub — no method bodies or implementations.

View File

@ -0,0 +1,147 @@
# Stub Generation Rules
Rules for generating minimal seed-data stubs. Stubs declare what exists and what type
it is — nothing more.
---
## General Principles
- **Stubs, not full metadata**: generate the absolute minimum XML to declare a field,
object, or class. No optional attributes, no invented values.
- **Only what gold references**: for picklists, include ONLY values explicitly named in
the gold file. For objects, do not add fields beyond what gold uses.
- **No optional attributes**: omit `description`, `trackHistory`, `trackTrending`,
`required`, `externalId`, `inlineHelpText`, `restricted`, `sorted`, `default`,
`relationshipLabel`, and any other non-essential element.
- **Standard objects don't need definitions**: Account, Contact, Opportunity, Case, Lead,
User, and other standard objects already exist. Only stub their custom fields (`__c`).
- **API version**: use `62.0` unless gold specifies otherwise.
---
## Custom Field Stubs
**Path**: `seed-data/objects/{ObjectName}/fields/{FieldApiName}.field-meta.xml`
Include ONLY these elements per field type:
| Field Type | Required Elements |
|-----------|------------------|
| Lookup | `fullName`, `label`, `type`, `referenceTo`, `relationshipName` |
| Master-Detail | `fullName`, `label`, `type`, `referenceTo`, `relationshipName` |
| Picklist | `fullName`, `label`, `type`, `valueSet` (only referenced values) |
| Text | `fullName`, `label`, `type`, `length` |
| Number | `fullName`, `label`, `type`, `precision`, `scale` |
| Currency | `fullName`, `label`, `type`, `precision`, `scale` |
| Percent | `fullName`, `label`, `type`, `precision`, `scale` |
| Date | `fullName`, `label`, `type` |
| DateTime | `fullName`, `label`, `type` |
| Checkbox | `fullName`, `label`, `type`, `defaultValue` |
| Email | `fullName`, `label`, `type` |
| Phone | `fullName`, `label`, `type` |
| Url | `fullName`, `label`, `type` |
| TextArea | `fullName`, `label`, `type` |
| LongTextArea | `fullName`, `label`, `type`, `length`, `visibleLines` |
### Picklist Value Rules
Only include picklist values that appear explicitly in the gold file. Common patterns:
| Gold Pattern | Extract |
|-------------|---------|
| `ISPICKVAL(Status__c, "UNPAID")` | `UNPAID` only |
| `IF(Stage__c = "Closed Won", ...)` | `Closed Won` only |
| `<value><fullName>Active</fullName>...</value>` | `Active` only |
Do NOT add values "for completeness." If the gold formula checks for `"UNPAID"`, do not
add `PAID`, `PARTIALLY_PAID`, or any other values.
---
## Custom Object Stubs
**Path**: `seed-data/objects/{ObjectApiName}/{ObjectApiName}.object-meta.xml`
Include ONLY these elements:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<deploymentStatus>Deployed</deploymentStatus>
<label>{Object Label}</label>
<nameField>
<label>{Object Label} Name</label>
<type>Text</type>
</nameField>
<pluralLabel>{Object Plural Label}</pluralLabel>
<sharingModel>ReadWrite</sharingModel>
</CustomObject>
```
Do NOT add `description`, `enableActivities`, `enableBulkApi`, `enableHistory`,
`enableReports`, `enableSearch`, or any other optional element.
---
## Apex Class Stubs
**Path**: `seed-data/classes/{ClassName}.cls` + `seed-data/classes/{ClassName}.cls-meta.xml`
The `.cls` file is an empty stub — class signature only:
```java
public class MyUtilClass {
}
```
For interfaces:
```java
public interface MyInterface {
}
```
For abstract classes:
```java
public abstract class MyBaseClass {
}
```
The `.cls-meta.xml`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<status>Active</status>
</ApexClass>
```
Do NOT generate method bodies, business logic, or implementations.
---
## Dependency Detection Patterns
| Gold Pattern | Dependency Type | Stub Needed |
|-------------|----------------|-------------|
| `Payment_Due_Date__c` in formula | Custom field | Date field stub |
| `AssetProvided__r.Name` in formula | Lookup relationship | Lookup field stub for `AssetProvided__c` |
| `ISPICKVAL(Status__c, "X")` | Picklist field | Picklist stub with value `X` |
| `<referenceTo>Animal__c</referenceTo>` | Custom object | Object stub for `Animal__c` |
| `extends BaseHandler` | Apex parent class | Class stub for `BaseHandler` |
| `implements Queueable` | Standard interface | No stub needed (standard) |
| `Account.Name` | Standard object + field | No stub needed |
| `CustomObj__c.Custom_Field__c` | Custom field on custom object | Both object and field stubs |
---
## Common Validation Errors and Fixes
| Error Pattern | Fix |
|--------------|-----|
| `Field does not exist: FieldName__c` | Add the missing field stub |
| `Invalid type: ObjectName__c` | Add the custom object stub |
| `Missing required field: X` | Add the required XML element |
| `Invalid picklist value` | Add the missing value to the picklist stub |
| `Relationship not found` | Add the lookup field that defines the relationship |
| `apiVersion is required` | Add `<apiVersion>62.0</apiVersion>` |

View File

@ -0,0 +1,20 @@
public with sharing class RestClient {
public enum HttpVerb {
GET,
POST,
PUT,
PATCH,
DEL
}
public static HttpResponse makeApiCall(
String namedCredential,
HttpVerb method,
String path
) {
HttpRequest request = new HttpRequest();
request.setEndpoint('callout:' + namedCredential + '/' + path);
request.setMethod(method.name());
return new Http().send(request);
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<status>Active</status>
</ApexClass>

View File

@ -0,0 +1,6 @@
@isTest
public class TestFactory {
public static List<SObject> invalidateSObjectList(List<SObject> records) {
return records;
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<status>Active</status>
</ApexClass>

View File

@ -0,0 +1 @@
Generate seed-data for an Apex dataset. The gold file is a QueueableWithCalloutRecipes class that implements Queueable and Database.AllowsCallouts. It references RestClient.makeApiCall() and TestFactory.invalidateSObjectList(). The dataset path is domains/apex/datasets/QueueableWithCalloutRecipes/. My target org is myDevOrg.

View File

@ -0,0 +1,70 @@
/**
* @description Demmonstrates the use of the Queueable interface to make
* callouts. The methods in this class are called by the system at run time.
* To enqueue this job and see it's results, use `System.enqueueJob(new QueueableWithCalloutRecipes());`
*
* More on the Queable interface:
* https://sfdc.co/queueable-apex
*
* @group Async Apex Recipes
* @see RestClient
*/
public with sharing class QueueableWithCalloutRecipes implements Queueable, Database.AllowsCallouts {
// This allows us to cause a DML failure in execute batch, enabling testing.
@testVisible
private static Boolean throwError = false;
@testVisible
private static Boolean circuitBreakerThrown = false;
/**
* @description Internal custom exception class
*/
public class QueueableWithCalloutRecipesException extends Exception {
}
/**
* @description This is the only required method to implement Queueable.
* Queueable classes that also implement Database.allowsCallouts can make
* HTTP requests to external services. In this recipe we make a GET request
* to developer.salesforce.com
* @param qc dependency injected by the system
* @example
* ```
* System.enqueueJob(new QueueableWithCalloutRecipes());
* ```
*/
public static void execute(QueueableContext qc) {
HttpResponse response = RestClient.makeApiCall(
'GoogleBooksAPI',
RestClient.HttpVerb.GET,
'volumes?q=salesforce'
);
List<Account> accounts = [
SELECT Id
FROM Account
ORDER BY Id
LIMIT 1000
];
for (Account acct : accounts) {
acct.Description = String.valueOf(response.getStatusCode());
}
if (Test.isRunningTest() && throwError) {
accounts = (List<Account>) TestFactory.invalidateSObjectList(
accounts
);
}
try {
update accounts;
} catch (DmlException dmle) {
System.debug(
LoggingLevel.INFO,
'real life use cases should do something more than just logging the error: ' +
dmle.getMessage()
);
if (Test.isRunningTest()) {
QueueableWithCalloutRecipes.circuitBreakerThrown = true;
}
}
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Payment_Due_Date__c</fullName>
<label>Payment Due Date</label>
<type>Date</type>
</CustomField>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Payment_Status__c</fullName>
<label>Payment Status</label>
<type>Picklist</type>
<valueSet>
<restricted>false</restricted>
<valueSetDefinition>
<sorted>false</sorted>
<value>
<fullName>UNPAID</fullName>
<default>false</default>
<label>UNPAID</label>
</value>
<value>
<fullName>PAID</fullName>
<default>false</default>
<label>PAID</label>
</value>
</valueSetDefinition>
</valueSet>
</CustomField>

View File

@ -0,0 +1 @@
Generate seed-data for a CustomFormulaField dataset. The gold file is a formula field on Contract that checks if a payment is overdue — it references Payment_Due_Date__c and ISPICKVAL(Payment_Status__c, "UNPAID"). The dataset path is domains/CustomFormulaField/datasets/payment_overdue/. My target org is myDevOrg.

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Payment_Overdue__c</fullName>
<label>Payment Overdue</label>
<type>Text</type>
<formula><![CDATA[IF(
AND(
Payment_Due_Date__c < TODAY(),
ISPICKVAL(Payment_Status__c, "UNPAID")
),
"PAYMENT OVERDUE",
null
)]]></formula>
<formulaTreatBlanksAs>BlankAsZero</formulaTreatBlanksAs>
<description>Returns 'PAYMENT OVERDUE' when Payment_Due_Date__c is before today and Payment_Status__c is UNPAID; otherwise null.</description>
<trackHistory>false</trackHistory>
<trackTrending>false</trackTrending>
<required>false</required>
<externalId>false</externalId>
<unique>false</unique>
</CustomField>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>AssetProvided__c</fullName>
<label>Asset Provided</label>
<referenceTo>Account</referenceTo>
<relationshipName>AssetProvided</relationshipName>
<type>Lookup</type>
</CustomField>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>AssetServicedBy__c</fullName>
<label>Asset Serviced By</label>
<referenceTo>Account</referenceTo>
<relationshipName>AssetServicedBy</relationshipName>
<type>Lookup</type>
</CustomField>

View File

@ -0,0 +1 @@
Generate seed-data for a ValidationRule dataset. The gold file is a validation rule on Asset that blocks insert/update when AssetProvided Name contains FedEx, AssetServicedBy Owner CompanyName contains FedEx, and Asset was modified within last 3 months. The dataset path is domains/ValidationRule/datasets/AssetFedexValidationRule/. My target org is myDevOrg.

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<ValidationRule xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>AssetFedExValidation</fullName>
<active>true</active>
<description>Block insert/update if AssetProvided Name contains 'FedEx', AssetServicedBy Owner CompanyName contains 'FedEx', and Asset LastModified is not more than last 3 months</description>
<errorConditionFormula>
<![CDATA[AND(
/* Ensure lookups exist */
NOT(ISBLANK(AssetProvided__c)),
NOT(ISBLANK(AssetServicedBy__c)),
/* Name of AssetProvided contains FedEx (case-insensitive) */
CONTAINS( UPPER( AssetProvided__r.Name ), "FEDEX" ),
/* Owner CompanyName of AssetServicedBy contains FedEx (case-insensitive) */
CONTAINS( UPPER( AssetServicedBy__r.Owner.CompanyName ), "FEDEX" ),
/* Asset LastModified is within last 3 months (inclusive) */
DATEVALUE(LastModifiedDate) >= ADDMONTHS(TODAY(), -3)
)]]>
</errorConditionFormula>
<errorMessage>Cannot insert/update: Asset conditions not met.</errorMessage>
</ValidationRule>