Skip to content

Add CRM CLI seeders for contacts, companies, activities, deals#1548

Merged
iftakharul-islam merged 5 commits intodevelopfrom
CRM-seeder
Feb 2, 2026
Merged

Add CRM CLI seeders for contacts, companies, activities, deals#1548
iftakharul-islam merged 5 commits intodevelopfrom
CRM-seeder

Conversation

@iftakharul-islam
Copy link
Copy Markdown
Member

Introduces CLI seed commands for seeding CRM data: contact groups, companies, contacts, activities, and deals (Pro feature). Adds supporting classes for data generation and seeding logic, and updates command registration to load seeders automatically.

Changes proposed in this Pull Request:

Related issue(s):

Introduces CLI seed commands for seeding CRM data: contact groups, companies, contacts, activities, and deals (Pro feature). Adds supporting classes for data generation and seeding logic, and updates command registration to load seeders automatically.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces CLI seed commands for generating test data in the WP ERP CRM module. It provides commands to seed contact groups, companies, contacts, activities, and deals (Pro feature), along with supporting infrastructure for data generation and storage.

Changes:

  • Adds abstract base class and data provider for CRM seeding operations
  • Implements five new WP-CLI commands for seeding different CRM entities
  • Adds orchestrator command to run all seeders in sequence
  • Updates command registration to auto-load seeder classes

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
AbstractCrmSeeder.php Base class providing common seeding utilities (ID storage, random data generation, progress bars)
CrmDataProvider.php Static data provider with realistic sample data for contacts, companies, deals, and activities
SeedContactGroups.php Creates contact groups/segments with duplicate checking
SeedCompanies.php Seeds company records with address and metadata
SeedContacts.php Generates individual contacts with associations to companies and groups
SeedActivities.php Creates various activity types (notes, calls, meetings, tasks, emails)
SeedDeals.php Generates deals with pipelines, stages, and lost reasons (Pro feature)
SeedCommand.php Orchestrates running all seed commands in proper sequence
Commands.php Loads and registers all seeder commands automatically

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

'country' => $city_data['country'],
'life_stage' => CrmDataProvider::weighted_life_stage(),
'source' => $this->random_element( CrmDataProvider::sources() ),
'contact_owner' => 1,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded user ID 1 on line 62 assumes this user exists. This will cause foreign key constraint violations if user 1 doesn't exist in the WordPress installation.

Copilot uses AI. Check for mistakes.
'street_1' => $this->random_element( $streets ),
'city' => $city_data['city'],
'state' => $city_data['state'],
'postal_code'=> $city_data['postal'],
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after 'postal_code' key on line 58. While PHP will parse this correctly, it's inconsistent with the formatting on other lines where keys have consistent spacing.

Suggested change
'postal_code'=> $city_data['postal'],
'postal_code' => $city_data['postal'],

Copilot uses AI. Check for mistakes.
Comment on lines +247 to +258
if ( $is_won ) {
$deal_data['won_at'] = date( 'Y-m-d H:i:s', strtotime( $created_at . ' +' . mt_rand( 7, 60 ) . ' days' ) );
} elseif ( $is_lost && ! empty( $lost_reason_ids ) ) {
$deal_data['lost_at'] = date( 'Y-m-d H:i:s', strtotime( $created_at . ' +' . mt_rand( 7, 45 ) . ' days' ) );
$deal_data['lost_reason_id'] = $this->random_element( $lost_reason_ids );
}

$result = $wpdb->insert(
$wpdb->prefix . 'erp_crm_deals',
$deal_data,
[ '%s', '%d', '%d', '%d', '%d', '%d', '%f', '%s', '%s', '%s', '%s', '%s', '%s', '%d' ]
);
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional checks for won_at and lost_at fields but doesn't handle the case where neither is set. When a deal is neither won nor lost, the base deal_data has 12 fields, but the format string specifies 14 placeholders. The wpdb->insert will fail due to this mismatch. The format array should be dynamically constructed to match the actual data array being inserted.

Copilot uses AI. Check for mistakes.
* @param array $ids
*/
protected function store_ids( $key, $ids ) {
set_transient( '_erp_crm_seed_' . $key, $ids, HOUR_IN_SECONDS );
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using HOUR_IN_SECONDS (1 hour) as the transient expiration is too short for seeding operations. If someone runs seed:contacts, waits more than an hour, and then runs seed:activities, the contact IDs will be lost. Consider using a longer expiration like DAY_IN_SECONDS or adding a note in documentation about running all seed commands in sequence.

Suggested change
set_transient( '_erp_crm_seed_' . $key, $ids, HOUR_IN_SECONDS );
set_transient( '_erp_crm_seed_' . $key, $ids, DAY_IN_SECONDS );

Copilot uses AI. Check for mistakes.
Comment on lines +118 to +123
$random_groups = array_rand( array_flip( $group_ids ), $subscribe_count );

if ( ! is_array( $random_groups ) ) {
$random_groups = [ $random_groups ];
}

Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array_rand and array_flip combination on line 118 is used to select random group IDs, but this creates an unnecessary intermediate array. When array_rand returns a single value (not an array), line 120-122 wraps it in an array. However, when $subscribe_count is 1, array_rand already returns a single integer, not an array. Consider using a simpler approach like shuffle() and array_slice() for clarity.

Suggested change
$random_groups = array_rand( array_flip( $group_ids ), $subscribe_count );
if ( ! is_array( $random_groups ) ) {
$random_groups = [ $random_groups ];
}
$shuffled_groups = $group_ids;
shuffle( $shuffled_groups );
$random_groups = array_slice( $shuffled_groups, 0, $subscribe_count );

Copilot uses AI. Check for mistakes.
'country' => $city_data['country'],
'life_stage' => $life_stage,
'source' => $this->random_element( $sources ),
'contact_owner' => 1,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All hardcoded user IDs (lines 80, 96) assume user 1 exists and is valid. This will cause foreign key constraint violations if user 1 doesn't exist in the WordPress installation.

Copilot uses AI. Check for mistakes.
iftakharul-islam and others added 4 commits February 2, 2026 10:57
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@iftakharul-islam iftakharul-islam merged commit 19dcff2 into develop Feb 2, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants