Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for participant count #944

Open
wants to merge 1 commit into
base: 6.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be moved to an upgrade hook?

/**
* @param array $event
* @param string $format
Expand Down
42 changes: 30 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 @@ -1130,6 +1144,7 @@ private function processRelationship($params, $cid1, $cid2) {
private function processParticipants($c, $cid) {
static $registered_by_id = [];
$n = $this->data['participant_reg_type'] == 'separate' ? $c : 1;
$contribution_enabled = wf_crm_aval($this->data, 'contribution:1:contribution:1:enable_contribution');
if ($p = wf_crm_aval($this->data, "participant:$n:participant")) {
// Fetch existing participant records
$existing = $this->utils->wf_crm_apivalues('Participant', 'get', [
Expand Down Expand Up @@ -1197,11 +1212,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']);
}

}