Merge pull request #20681 from eileenmcnaughton/order_easy
[civicrm-core.git] / CRM / Financial / BAO / Order.php
index ed96a7a22ef47aa6d179e673c0a487456fb3a2df..5e7e4417f4441364b746459c2065c8f0f218f095 100644 (file)
@@ -58,6 +58,29 @@ class CRM_Financial_BAO_Order {
    */
   protected $overrideFinancialTypeID;
 
+  /**
+   * Financial type id to use for any lines where is is not provided.
+   *
+   * @var int
+   */
+  protected $defaultFinancialTypeID;
+
+  /**
+   * @return int
+   */
+  public function getDefaultFinancialTypeID(): int {
+    return $this->defaultFinancialTypeID;
+  }
+
+  /**
+   * Set the default financial type id to be used when the line has none.
+   *
+   * @param int|null $defaultFinancialTypeID
+   */
+  public function setDefaultFinancialTypeID(?int $defaultFinancialTypeID): void {
+    $this->defaultFinancialTypeID = $defaultFinancialTypeID;
+  }
+
   /**
    * Override for the total amount of the order.
    *
@@ -634,4 +657,107 @@ class CRM_Financial_BAO_Order {
     }
   }
 
+  /**
+   * Set the line item.
+   *
+   * This function augments the line item where possible. The calling code
+   * should not attempt to set taxes. This function allows minimal values
+   * to be passed for the default price sets - ie if only membership_type_id is
+   * specified the price_field_id and price_value_id will be determined.
+   *
+   * @param array $lineItem
+   * @param int|string $index
+   *
+   * @throws \API_Exception
+   * @internal tested core code usage only.
+   * @internal use in tested core code only.
+   *
+   */
+  public function setLineItem(array $lineItem, $index): void {
+    if (!empty($lineItem['price_field_id']) && !isset($this->priceSetID)) {
+      $this->setPriceSetIDFromSelectedField($lineItem['price_field_id']);
+    }
+    if (!isset($lineItem['financial_type_id'])) {
+      $lineItem['financial_type_id'] = $this->getDefaultFinancialTypeID();
+    }
+    if (!is_numeric($lineItem['financial_type_id'])) {
+      $lineItem['financial_type_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', $lineItem['financial_type_id']);
+    }
+    $lineItem['tax_amount'] = ($this->getTaxRate($lineItem['financial_type_id']) / 100) * $lineItem['line_total'];
+    if (!empty($lineItem['membership_type_id'])) {
+      $lineItem['entity_table'] = 'civicrm_membership';
+      if (empty($lineItem['price_field_id']) && empty($lineItem['price_field_value_id'])) {
+        // If only the membership type is passed in we use the default price field.
+        if (!isset($this->priceSetID)) {
+          $this->setPriceSetToDefault('membership');
+        }
+        $lineItem = $this->fillMembershipLine($lineItem);
+      }
+    }
+    $this->lineItems[$index] = $lineItem;
+  }
+
+  /**
+   * Set a value on a line item.
+   *
+   * @internal only use in core tested code.
+   *
+   * @param string $name
+   * @param mixed $value
+   * @param string|int $index
+   */
+  public function setLineItemValue(string $name, $value, $index): void {
+    $this->lineItems[$index][$name] = $value;
+  }
+
+  /**
+   * @param int|string $index
+   *
+   * @return string
+   */
+  public function getLineItemEntity($index):string {
+    // @todo - ensure entity_table is set in setLineItem, go back to enotices here.
+    return str_replace('civicrm_', '', ($this->lineItems[$index]['entity_table'] ?? 'contribution'));
+  }
+
+  /**
+   * Get the ordered line item.
+   *
+   * @param string|int $index
+   *
+   * @return array
+   */
+  public function getLineItem($index): array {
+    return $this->lineItems[$index];
+  }
+
+  /**
+   * Fills in additional data for the membership line.
+   *
+   * The minimum requirement is the membership_type_id and that priceSetID is set.
+   *
+   * @param array $lineItem
+   *
+   * @return array
+   */
+  protected function fillMembershipLine(array $lineItem): array {
+    $fields = $this->getPriceFieldsMetadata();
+    $field = reset($fields);
+    if (!isset($lineItem['price_field_value_id'])) {
+      foreach ($field['options'] as $option) {
+        if ((int) $option['membership_type_id'] === (int) $lineItem['membership_type_id']) {
+          $lineItem['price_field_id'] = $field['id'];
+          $lineItem['price_field_value_id'] = $option['id'];
+          $lineItem['qty'] = 1;
+        }
+      }
+    }
+    $option = $field['options'][$lineItem['price_field_value_id']];
+    $lineItem['unit_price'] = $lineItem['line_total'] ?? $option['amount'];
+    $lineItem['label'] = $lineItem['label'] ?? $option['label'];
+    $lineItem['field_title'] = $lineItem['field_title'] ?? $option['label'];
+    $lineItem['financial_type_id'] = $lineItem['financial_type_id'] ?: ($this->getDefaultFinancialTypeID() ?? $option['financial_type_id']);
+    return $lineItem;
+  }
+
 }