Allow setting the participant status in Order.create api (required by event cart)
authorMatthew Wire <mjw@mjwconsult.co.uk>
Thu, 20 Aug 2020 21:42:13 +0000 (22:42 +0100)
committerMatthew Wire <mjw@mjwconsult.co.uk>
Sat, 5 Dec 2020 15:19:40 +0000 (15:19 +0000)
CRM/Event/BAO/ParticipantStatusType.php
api/v3/Order.php
tests/phpunit/api/v3/OrderTest.php

index 9db56d820b5990a58bad5f385414165271fec124..388e12637d83e86351eda8a7442ee47ee4676c6c 100644 (file)
@@ -99,6 +99,29 @@ class CRM_Event_BAO_ParticipantStatusType extends CRM_Event_DAO_ParticipantStatu
     return CRM_Core_DAO::setFieldValue('CRM_Event_BAO_ParticipantStatusType', $id, 'is_active', $isActive);
   }
 
+  /**
+   * Checks if status_id (id or string (eg. 5 or "Pending from pay later") is allowed for class
+   *
+   * @param int|string $status_id
+   * @param string $class
+   *
+   * @return bool
+   */
+  public static function getIsValidStatusForClass($status_id, $class = 'Pending') {
+    $classParticipantStatuses = civicrm_api3('ParticipantStatusType', 'get', [
+      'class' => $class,
+      'is_active' => 1,
+    ])['values'];
+    $allowedParticipantStatuses = [];
+    foreach ($classParticipantStatuses as $id => $detail) {
+      $allowedParticipantStatuses[$id] = $detail['name'];
+    }
+    if (in_array($status_id, $allowedParticipantStatuses) || array_key_exists($status_id, $allowedParticipantStatuses)) {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
   /**
    * @param array $params
    *
index e99b38542c40afd1e00409f01c51e8a74bf80050..c108b82218923b5f57182a641f0028b1f81105f9 100644 (file)
@@ -93,7 +93,12 @@ function civicrm_api3_order_create($params) {
         $supportedEntity = TRUE;
         switch ($entity) {
           case 'participant':
-            $entityParams['status_id'] = 'Pending from incomplete transaction';
+            if (isset($entityParams['participant_status_id'])
+              && (!CRM_Event_BAO_ParticipantStatusType::getIsValidStatusForClass($entityParams['participant_status_id'], 'Pending'))) {
+              throw new CiviCRM_API3_Exception('Creating a participant via the Order API with a non "pending" status is not supported');
+            }
+            $entityParams['participant_status_id'] = $entityParams['participant_status_id'] ?? 'Pending from incomplete transaction';
+            $entityParams['status_id'] = $entityParams['participant_status_id'];
             break;
 
           case 'membership':
index bf81f4fb6888e01a58e45077e969ebaf4197d62b..55856dd122c0c24c493ecc3fa69caec8e53b9258 100644 (file)
@@ -339,6 +339,16 @@ class api_v3_OrderTest extends CiviUnitTestCase {
       'id' => $order['id'],
     ]);
 
+    // Enable the "Pending from approval" status which is not enabled by default
+    $pendingFromApprovalParticipantStatus = civicrm_api3('ParticipantStatusType', 'getsingle', [
+      'name' => "Pending from approval",
+    ]);
+    civicrm_api3('ParticipantStatusType', 'create', [
+      'id' => $pendingFromApprovalParticipantStatus['id'],
+      'name' => "Pending from approval",
+      'is_active' => 1,
+    ]);
+
     $p['line_items'][] = [
       'line_item' => $lineItems,
       'params' => [
@@ -347,6 +357,7 @@ class api_v3_OrderTest extends CiviUnitTestCase {
         'role_id' => 1,
         'register_date' => '2007-07-21 00:00:00',
         'source' => 'Online Event Registration: API Testing',
+        'participant_status_id' => 'Pending from approval',
       ],
     ];
 
@@ -358,12 +369,15 @@ class api_v3_OrderTest extends CiviUnitTestCase {
         'net_amount' => 600,
       ],
     ];
-    $paymentParticipant = [
+    $orderParams = [
       'contribution_id' => $order['id'],
     ];
-    $order = $this->callAPISuccess('order', 'get', $paymentParticipant);
+    $order = $this->callAPISuccess('order', 'get', $orderParams);
     $this->checkPaymentResult($order, $expectedResult);
-    $this->callAPISuccessGetCount('ParticipantPayment', $paymentParticipant, 2);
+    $paymentParticipant = $this->callAPISuccess('ParticipantPayment', 'get', $orderParams)['values'];
+    $this->assertEquals(2, count($paymentParticipant), 'Expected two participant payments');
+    $participant = $this->callAPISuccessGetSingle('Participant', ['participant_id' => end($paymentParticipant)['participant_id']]);
+    $this->assertEquals('Pending from approval', $participant['participant_status']);
     $this->callAPISuccess('Contribution', 'Delete', [
       'id' => $order['id'],
     ]);