Skip to content

Commit

Permalink
updated participant count code
Browse files Browse the repository at this point in the history
fix for participant count code
  • Loading branch information
MegaphoneJon committed Apr 9, 2024
1 parent 3341be2 commit ec465b4
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 12 deletions.
8 changes: 8 additions & 0 deletions src/AdminHelp.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ protected function participant_fee_amount() {
$this->fee();
}

protected function participant_count() {
return '<p>' .
t('Number of participants (for purposes of max participants) this registration counts for upon submission of the form.') .
'</p><p>' .
t('Note that if a value is not given, the default Participant Count will be 1.') .
'</p>';
}

protected function fee() {
return '<p>' .
t('Once added to the webform, this field can be configured in a number of ways by changing its settings.') .
Expand Down
4 changes: 4 additions & 0 deletions src/Fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,10 @@ protected function wf_crm_get_fields($var = 'fields') {
'name' => t('Participant Fee'),
] + $moneyDefaults;
}
$fields['participant_count'] = [
'name' => t('Participant Count'),
'type' => 'civicrm_number',
];
}
if (isset($sets['membership'])) {
$fields['membership_membership_type_id'] = [
Expand Down
62 changes: 62 additions & 0 deletions src/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,68 @@ function wf_crm_get_events($reg_options, $context) {
return $ret;
}

/**
* Create a hidden Price Set that contains a Price Field Value with a `count` of one so that `qty` accurately reflects
* number of seats registered on submission
*/
function wf_crm_get_participant_price_set() {
// Get the price_set_value id
$qtyPriceFieldValueId = civicrm_api4('PriceFieldValue', 'get', [
'checkPermissions' => FALSE,
'select' => ['id'],
'where' => [['name', '=', 'quantity_count_field_value']],
])[0]['id'] ?? NULL;
// If the Price Set Value exsists, return it.
if ($qtyPriceFieldValueId) {
return $qtyPriceFieldValueId;
}
else {
// If it does not exist, create the price set, price field, and price field value (with a `count` of 1).
$activeFinancialtypeId = civicrm_api4('FinancialType', 'get', [
'checkPermissions' => FALSE,
'select' => ['id'],
'where' => [['is_active', '=', TRUE]],
'limit' => 1,
])[0]['id'];
$qtyPriceSetId = civicrm_api4('PriceSet', 'create', [
'checkPermissions' => FALSE,
'values' => [
'name' => 'quantity_count',
'title' => 'Webform participant quantity count',
'extends:name' => 'CiviEvent',
'is_active' => TRUE,
'is_reserved' => TRUE,
'is_required' => FALSE,
'is_quick_config' => TRUE,
'financial_type_id' => $activeFinancialtypeId,
],
])[0]['id'];
$qtyPriceFieldId = civicrm_api4('PriceField', 'create', [
'checkPermissions' => FALSE,
'values' => [
'price_set_id' => $qtyPriceSetId,
'name' => 'quantity_count_field',
'label' => 'Webform participant quantity count field',
'html_type' => 'Select',
'is_active' => TRUE,
],
])[0]['id'];
$qtyPriceFieldValueId = civicrm_api4('PriceFieldValue', 'create', [
'checkPermissions' => FALSE,
'values' => [
'price_field_id' => $qtyPriceFieldId,
'name' => 'quantity_count_field_value',
'label' => 'Webform participant quantity count field value',
'count' => 1,
'amount' => 1,
'is_active' => TRUE,
'financial_type_id' => $activeFinancialtypeId,
],
])[0]['id'];
return $qtyPriceFieldValueId;
}
}

/**
* @param array $event
* @param string $format
Expand Down
41 changes: 29 additions & 12 deletions src/WebformCivicrmPostProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -478,16 +478,30 @@ private function validateParticipants() {
if (is_numeric($eid)) {
$this->events[$eid]['ended'] = TRUE;
$this->events[$eid]['title'] = t('this event');
$this->events[$eid]['count'] = wf_crm_aval($this->events, "$eid:count", 0) + $count;
$this->line_items[] = [
'qty' => $count,
'entity_table' => 'civicrm_participant',
'event_id' => $eid,
'contact_ids' => $contacts,
'unit_price' => $p['fee_amount'] ?? 0,
'element' => "civicrm_{$c}_participant_{$n}_participant_{$id_and_type}",
'contact_label' => $participantName,
];
$this->events[$eid]['count'] = wf_crm_aval($this->events, "$eid:count", 0) + ($count * ($p['count'] ?? 1));
// Get (or create if needed) a Price Set that has a value field that correctly counts the number of participants registered on submission.
$participantPriceValueID = $this->utils->wf_crm_get_participant_price_set();
// We need a line item for each participant record.
foreach ($contacts as $k => $contact) {
if ($this->data['participant_reg_type'] == 'all') {
$contactIndex = $k;
}
else {
$contactIndex = $c;
}
$this->line_items[] = [
'qty' => $p['count'] ?? 1,
'participant_count' => $p['count'] ?? 1,
'entity_table' => 'civicrm_participant',
'event_id' => $eid,
'contact_ids' => $contact,
'unit_price' => ($p['fee_amount'] ?? 0) / ($p['count'] ?? 1),
'element' => "civicrm_{$contactIndex}_participant_{$n}_participant_{$id_and_type}",
'contact_label' => $participantName,
'price_field_value_id' => $participantPriceValueID,
'line_total' => $p['fee_amount'] ?? 0,
];
}
}
}
}
Expand Down Expand Up @@ -1197,11 +1211,14 @@ private function processParticipants($c, $cid) {

// Update line-item
foreach ($this->line_items as &$item) {
if ($item['element'] == "civicrm_{$n}_participant_{$e}_participant_{$id_and_type}") {
if ($item['element'] == "civicrm_{$c}_participant_{$e}_participant_{$id_and_type}") {
if (empty($item['participant_id'])) {
$item['participant_id'] = $item['entity_id'] = $result['id'];
}
$item['participant_count'] = wf_crm_aval($item, 'participant_count', 0) + 1;
// Free events need line items for correct participant count.
if (!$contribution_enabled) {
$this->utils->wf_civicrm_api('lineItem', 'create', $item);
}
break;
}
}
Expand Down
98 changes: 98 additions & 0 deletions tests/src/FunctionalJavascript/EventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -320,4 +320,102 @@ function testMaxParticipant() {
$this->assertSession()->pageTextContains('Test Event 3');
}

/**
* Verify the participant count is calculated correctly (with multiple participants) - register all for same event.
*/
function testParticipantCountSameReg() {
$this->drupalLogin($this->adminUser);
// Set the max participants on the event.
$maxParticipants = 10;
$this->utils->wf_civicrm_api('Event', 'create', ['id' => $this->_event['id'], 'max_participants' => $maxParticipants]);
$this->drupalGet(Url::fromRoute('entity.webform.civicrm', [
'webform' => $this->webform->id(),
]));
$this->enableCivicrmOnWebform();

$this->getSession()->getPage()->selectFieldOption('number_of_contacts', 2);

$this->getSession()->getPage()->clickLink('Event Registration');

// Configure Event tab.
$this->getSession()->getPage()->selectFieldOption('participant_reg_type', 'same');
$this->assertSession()->assertWaitOnAjaxRequest();
$this->getSession()->getPage()->selectFieldOption('participant_1_number_of_participant', 1);
$this->assertSession()->assertWaitOnAjaxRequest();
$this->getSession()->getPage()->selectFieldOption('civicrm_1_participant_1_participant_event_id[]', 'Test Event');
$this->getSession()->getPage()->checkField('Participant Count');

$this->saveCiviCRMSettings();

// Submit the form.
$this->drupalGet($this->webform->toUrl('canonical'));
$this->assertPageNoErrorMessages();
$edit = [
'civicrm_1_contact_1_contact_first_name' => 'Frederick',
'civicrm_1_contact_1_contact_last_name' => 'Pabst',
'civicrm_2_contact_1_contact_first_name' => 'Mark',
'civicrm_2_contact_1_contact_last_name' => 'Anthony',
'civicrm_1_participant_1_participant_count' => '3',
];
$this->postSubmission($this->webform, $edit);
// Check the number of places available.
$result = civicrm_api3('Event', 'getsingle', [
'return' => ["is_full"],
'id' => $this->_event['id'],
]);
// 10 places, 2 participants, count is 3: 10 - (2 * 3) = 4.
$this->assertEquals(4, $result['available_places']);
}

/**
* Verify the participant count is calculated correctly (with multiple participants) - register for separate events.
*/
function testParticipantCountSeparateReg() {
$this->drupalLogin($this->adminUser);
// Set the max participants on the event.
$maxParticipants = 10;
$this->utils->wf_civicrm_api('Event', 'create', ['id' => $this->_event['id'], 'max_participants' => $maxParticipants]);
$this->drupalGet(Url::fromRoute('entity.webform.civicrm', [
'webform' => $this->webform->id(),
]));
$this->enableCivicrmOnWebform();

$this->getSession()->getPage()->selectFieldOption('number_of_contacts', 2);
$this->getSession()->getPage()->clickLink('Event Registration');

// Configure Event tab.
$this->getSession()->getPage()->selectFieldOption('participant_reg_type', 'separate');
$this->assertSession()->assertWaitOnAjaxRequest();
$this->getSession()->getPage()->selectFieldOption('participant_1_number_of_participant', 1);
$this->assertSession()->assertWaitOnAjaxRequest();
$this->getSession()->getPage()->selectFieldOption('participant_2_number_of_participant', 1);
$this->assertSession()->assertWaitOnAjaxRequest();
$this->getSession()->getPage()->selectFieldOption('civicrm_1_participant_1_participant_event_id[]', 'Test Event');
$this->getSession()->getPage()->selectFieldOption('civicrm_2_participant_1_participant_event_id[]', 'Test Event');
$this->getSession()->getPage()->checkField('civicrm_1_participant_1_participant_count');
$this->getSession()->getPage()->checkField('civicrm_2_participant_1_participant_count');

$this->saveCiviCRMSettings();

// Submit the form.
$this->drupalGet($this->webform->toUrl('canonical'));
$this->assertPageNoErrorMessages();
$edit = [
'civicrm_1_contact_1_contact_first_name' => 'Frederick',
'civicrm_1_contact_1_contact_last_name' => 'Pabst',
'civicrm_2_contact_1_contact_first_name' => 'Mark',
'civicrm_2_contact_1_contact_last_name' => 'Anthony',
'civicrm_1_participant_1_participant_count' => '5',
'civicrm_2_participant_1_participant_count' => '2',
];
$this->postSubmission($this->webform, $edit);
// Check the number of places available.
$result = civicrm_api3('Event', 'getsingle', [
'return' => ["is_full"],
'id' => $this->_event['id'],
]);
// 10 - 5 - 2 = 3.
$this->assertEquals(3, $result['available_places']);
}

}

0 comments on commit ec465b4

Please sign in to comment.