From 0e01bbaa1e197a2d6ccc8fb4f437e79c9f8180e9 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Thu, 22 Sep 2022 16:51:29 +0530
Subject: [PATCH 01/16] Support Tier Membership payment

---
 tieredpricingformembership.php | 126 ++++++++++++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 2 deletions(-)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 4e3a395..28d5703 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -139,7 +139,7 @@ function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
               'sequential': 1,
               'return': [\"custom_{$cfID}\"],
               'id': $(this).val()
-            }).then(function(result) {              
+            }).then(function(result) {
 	      var c = 0,
                count = parseInt(result['values'][0]['custom_2']);
               $('[id^=\'custom_3\'] > option').each(function(){
@@ -151,7 +151,7 @@ function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
                   $('#minimum_fee').val(this.value);
                   return false;
 		}
-	      });    
+	      });
             });
          });
   });
@@ -160,6 +160,128 @@ function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
   }
 }
 
+function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
+  if ($formName == 'CRM_Contribute_Form_Contribution_Confirm' && !empty($form->_submitValues['custom_23'])) {
+     $mappingRecord = mappedEntries();
+     $lineItems = $tierPrices = [];
+     $totalAmount = 0;
+     $employeeCount = \Civi\Api4\Contact::get(FALSE)
+        ->addSelect('Employee_count.Employee_count_including_subsidiaries')
+        ->addWhere('id', '=', $form->_submitValues['custom_23'])
+        ->execute()->first()['Employee_count.Employee_count_including_subsidiaries'] ?? 0;
+     foreach ($form->_lineItem[$form->_priceSetId] as $item) {
+       if (empty($tierPrices[$item['membership_type_id']])) {
+           $tierPrices[$item['membership_type_id']] = \Civi\Api4\TierPrice::get(FALSE)
+            ->addSelect('tier_level', 'unit_price')
+            ->addWhere('membership_type_id', '=', $item['membership_type_id']])
+            ->execute()->getArrayCopy();
+       }
+       $key = 'price_' . $item['price_field_id'] . '_' . $item['price_field_value_id'];
+       $item['qty'] = $form->_submitValues[$mappingRecord[$key]['qty']];
+       foreach ($tierPrices[$item['membership_type_id']] as $tierPrice) {
+         if ($employeeCount >= $tierPrice['tier_level']) {
+           $item['unit_price'] = $tierPrice['unit_price'];
+         }
+       }
+       $item['line_total'] = $item['qty'] * $item['unit_price'];
+       $lid = \Civi\Api4\LineItem::get(FALSE)
+            ->addSelect('id')
+            ->addWhere('contribution_id', '=', $form->_contributionID)
+            ->addWhere('price_field_value_id', '=', $item['price_field_value_id'])
+            ->execute()->first()['id'];
+       $item['id'] = $lid;
+       $lineItems[$lid] = $item;
+     }
+
+     civicrm_api3('Contribution', 'create', [
+       'id' => $form->_contributionID,
+       'total_amount' => $totalAmount,
+       'contact_id' => $form->_submitValues['custom_23'],
+       'line_item' => [$form->_priceSetId => $lineItems],
+     ]);
+  }
+}
+
+function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
+  if ($formName == 'CRM_Contribute_Form_Contribution_Main') {
+    $mappingRecord = mappedEntries();
+    $mappingRecord = json_encode($mappingRecord);
+      $bednos = json_encode($bednos);
+        Civi::resources()->addScript("
+         CRM.$(function($) {
+          var mapping =  {$mappingRecord},
+             bednos = {$bednos};
+          $('#priceset').hide();
+          $('input[type=\"text\"]').on('change', function(e) {
+            var name = $(this).attr('id'), orgType = [];
+            if ($.inArray($(this).attr('id'), bednos) !== -1) {
+               $('input[name*=\"custom_6\"]').filter(':checked').each(function() {
+                 orgType.push($(this).attr('id'));
+               });
+               if (orgType.length > 0) {
+                 $.each(mapping, function(k, v) {
+                   if ($.trim($('#' + name).val()) != '' && $.inArray(v.org_type, orgType) !== -1 && v.qty == name) {
+                     if (!$('#' + k).is(':checked')) {
+                       $('#' + k).trigger('click');
+                     }
+                   }
+                   else if ($.trim($('#' + name).val()) == '' && $('#' + k).is(':checked')) {
+                     $('#' + k).trigger('click');
+                   }
+                 });
+               }
+            }
+          });
+          $('input[name*=\"custom_6\"]').on('click', function(e) {
+              var name = $(this).attr('id');
+                $.each(mapping, function(k, v) {
+                  if (v.org_type == name && $.trim($('#' + v.qty).val()) != '') {
+                    $('#' + k).trigger('click');
+                  }
+                });
+          });
+      });
+    ");
+  }
+}
+
+// return [membership_type - price_field_value_id => [number of beds, organization type] mapping fieldsname selector
+function mappedEntries() {
+  $bednos = CRM_Utils_Array::collect('fieldName',
+    \Civi\Api4\CustomField::get(FALSE)
+      ->addSelect("CONCAT('custom_', id) AS fieldName")
+      ->addWhere('custom_group_id:name', '=', 'Number_of_Beds')
+      ->execute()
+      ->getArrayCopy()
+  );
+  $id = \Civi\Api4\CustomField::get(FALSE)
+    ->addWhere('custom_group_id:name', '=', 'Organization_Type')
+    ->execute()->first()['id'];
+
+  $mappingRecord = [];
+  $i = $k = 0;
+  end($bednos);
+  $flag = false;
+  foreach(\Civi\Api4\PriceFieldValue::get(FALSE)
+  ->addSelect("CONCAT('price_', price_field_id, '_', id) AS fieldName")
+  ->addWhere('price_field_id.name', '=', 'tiered_membership_prices')
+  ->execute()
+  ->getArrayCopy() as $key => $value) {
+    if ($k == 9 && !$flag) {$k = key($bednos);}
+    $mappingRecord[$value['fieldName']] = [
+     'org_type' => 'custom_' . $id . '_' . ($i + 1),
+      'qty' => $bednos[$k],
+    ];
+    $i++;
+    if ($i == 7) {
+     if ($k == key($bednos)) {$k = 8; $flag = true;}
+      $i = 0;
+      $k++;
+    }
+  }
+  return $mappingRecord;
+}
+
 // --- Functions below this ship commented out. Uncomment as required. ---
 
 /**
-- 
GitLab


From 5a9cc34778c559cee1fed6adcec15231194c9d19 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Tue, 27 Sep 2022 21:08:08 +0530
Subject: [PATCH 02/16] Remove tier page as it will be built from afform

---
 .../Page/TierPrice.php                        | 109 ------------------
 .../Page/TierPrice.tpl                        |  36 ------
 xml/Menu/tieredpricingformembership.xml       |   9 --
 3 files changed, 154 deletions(-)
 delete mode 100644 CRM/Tieredpricingformembership/Page/TierPrice.php
 delete mode 100644 templates/CRM/Tieredpricingformembership/Page/TierPrice.tpl
 delete mode 100644 xml/Menu/tieredpricingformembership.xml

diff --git a/CRM/Tieredpricingformembership/Page/TierPrice.php b/CRM/Tieredpricingformembership/Page/TierPrice.php
deleted file mode 100644
index e871b42..0000000
--- a/CRM/Tieredpricingformembership/Page/TierPrice.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-use CRM_Tieredpricingformembership_ExtensionUtil as E;
-use Civi\Api4\TierPrice;
-
-class CRM_Tieredpricingformembership_Page_TierPrice extends CRM_Core_Page_Basic {
-
-  /**
-   * The action links that we need to display for the browse screen.
-   *
-   * @var array
-   */
-  public static $_links = [];
-
-  /**
-   * Get name of edit form.
-   *
-   * @return string
-   *   Classname of edit form.
-   */
-  public function editForm() {
-    return 'CRM_Tieredpricingformembership_Form_TierPrice';
-  }
-
-  /**
-   * Get edit form name.
-   *
-   * @return string
-   *   name of this page.
-   */
-  public function editName() {
-    return 'Tiered Membership Prices';
-  }
-
-  /**
-   * Get action Links.
-   *
-   * @return array
-   *   (reference) of action links
-   */
-  public function &links() {
-    if (empty(self::$_links)) {
-      self::$_links = [
-        CRM_Core_Action::UPDATE => [
-          'name' => ts('Edit'),
-          'url' => 'civicrm/admin/tierprice',
-          'qs' => 'action=update&id=%%id%%&reset=1',
-          'title' => ts('Edit Payment Processor'),
-        ],
-        CRM_Core_Action::DELETE => [
-          'name' => ts('Delete'),
-          'url' => 'civicrm/admin/tierprice',
-          'qs' => 'action=delete&id=%%id%%',
-          'title' => ts('Delete Payment Processor'),
-        ],
-      ];
-    }
-    return self::$_links;
-  }
-
-  public function run() {
-    // Example: Set the page-title dynamically; alternatively, declare a static title in xml/Menu/*.xml
-    CRM_Utils_System::setTitle(E::ts('Tier Prices'));
-    parent::run();
-  }
-
-  public function browse() {
-    $tierPrices = TierPrice::get()->addSelect('*', 'membership_type_id.name')->execute();
-    var_dump($tierPrices);
-    foreach ($tierPrices as $tierPriceID => $tierPrice) {
-      // Annoyingly Smarty can't handle the colon syntax (or a .)
-      $tierPrices[$tierPriceID]['membership_type_id'] = $tierPrice['membership_type_id.name'];
-
-      // form all action links
-      $action = array_sum(array_keys($this->links()));
-      $tierPrices[$tierPriceID]['action'] = CRM_Core_Action::formLink($this->links(), $action,
-        ['id' => $tierPrice['id']],
-        ts('more'),
-        FALSE,
-        'tierPrice.manage.action',
-        'tierPrice',
-        $tierPrice['id']
-      );
-    }
-
-    $this->assign('tierPrices', $tierPrices);
-  }
-
-  /**
-   * UserContext to pop back to.
-   *
-   * @param int $mode
-   *   Mode that we are in.
-   *
-   * @return string
-   */
-  public function userContext($mode = NULL) {
-    return 'civicrm/admin/tierprice';
-  }
-
-  /**
-   * Name of the BAO to perform various DB manipulations.
-   *
-   * @return string
-   */
-  public function getBAOName() {
-    return 'CRM_Tieredpricingformembership_BAO_TierPrice';
-  }
-
-}
diff --git a/templates/CRM/Tieredpricingformembership/Page/TierPrice.tpl b/templates/CRM/Tieredpricingformembership/Page/TierPrice.tpl
deleted file mode 100644
index f037aff..0000000
--- a/templates/CRM/Tieredpricingformembership/Page/TierPrice.tpl
+++ /dev/null
@@ -1,36 +0,0 @@
-{if $action eq 1 or $action eq 2 or $action eq 8}
-   {include file="CRM/Tieredpricingformembership/Form/TierPrice.tpl"}
-{else}
-<div class="crm-content-block crm-block">
-  {if $tierPrices}
-    <div id="tierprices">
-      <table class="selector row-highlight">
-        <tr class="columnheader">
-          <th>{ts}Membership Type Id{/ts}</th>
-          <th>{ts}Tier Level Minimum Staff{/ts}</th>
-          <th>{ts}Tier Level Maximum Staff{/ts}</th>
-          <th>{ts}Unit Price{/ts}</th>
-          <th></th>
-        </tr>
-        {foreach from=$tierPrices item=tierPrice}
-          <tr id="tier-price-{$row.id}" class="crm-entity {cycle values="odd-row,even-row"}">
-            <td>{$tierPrice.membership_type_id}</td>
-            <td>{$tierPrice.min_staff_tier_level}</td>
-            <td>{$tierPrice.max_staff_tier_level}</td>
-            <td>{$tierPrice.unit_price}</td>
-            <td>{$tierPrice.action|smarty:nodefaults|replace:'xx':$row.id}</td>
-          </tr>
-        {/foreach}
-      </table>
-    </div>
-  {elseif $action ne 1}
-    <div class="messages status no-popup">
-      {icon icon="fa-info-circle"}{/icon}
-        {ts}There are no Tier Prices entered.{/ts}
-     </div>
-     <div class="action-link">
-       {crmButton p='civicrm/admin/tierprice' q="action=add&reset=1" id="newTierPrice"  icon="plus-circle"}{ts}Add Tier Price{/ts}{/crmButton}
-     </div>
-  {/if}
-</div>
-{/if}
diff --git a/xml/Menu/tieredpricingformembership.xml b/xml/Menu/tieredpricingformembership.xml
deleted file mode 100644
index 37fc697..0000000
--- a/xml/Menu/tieredpricingformembership.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0"?>
-<menu>
-  <item>
-    <path>civicrm/admin/tierprice</path>
-    <page_callback>CRM_Tieredpricingformembership_Page_TierPrice</page_callback>
-    <title>Tier Prices</title>
-    <access_arguments>administer CiviMember</access_arguments>
-  </item>
-</menu>
-- 
GitLab


From 2a9e3e742e2485a942914bc06903daac6deaacaf Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Tue, 27 Sep 2022 21:25:41 +0530
Subject: [PATCH 03/16] cleanup

---
 tieredpricingformembership.php | 153 +++++++++++----------------------
 1 file changed, 49 insertions(+), 104 deletions(-)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 28d5703..6f426a5 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -92,11 +92,7 @@ function tieredpricingformembership_civicrm_post($op, $objectName, $objectId, &$
         $subcount += \Civi\Api4\Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $org['contact_id_b'])->execute()->first()['Employee_count.Employee_count'] ?? 0;
       }
       $subcount += $count;
-/*
-      \Civi\Api4\Contact::update(FALSE)
-        ->addValue('id', $objectId)
-        ->addValue('Employee_count.Employee_count_including_subsidiaries', $count);
-*/
+  
       $cfID = \Civi\Api4\CustomField::get(FALSE)
         ->addSelect('id')
         ->addWhere('custom_group_id:name', '=', 'Employee_count')
@@ -128,40 +124,8 @@ function _get_custom_field_id_by_name($fieldName, $cgName) {
     ->execute()->first()['id'];
 }
 
-function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
-  if ($formName == 'CRM_Member_Form_MembershipType') {
-    $cfID = _get_custom_field_id_by_name('Employee_count_including_subsidiaries', 'Employee_count');
-    Civi::resources()->addScript("
-     CRM.$(function($) {
-       $( document ).ajaxComplete(function() {
-         $('#member_of_contact_id').on('change', function(e) {
-           CRM.api3('Contact', 'get', {
-              'sequential': 1,
-              'return': [\"custom_{$cfID}\"],
-              'id': $(this).val()
-            }).then(function(result) {
-	      var c = 0,
-               count = parseInt(result['values'][0]['custom_2']);
-              $('[id^=\'custom_3\'] > option').each(function(){
-                if (count < parseInt(this.text) || count == parseInt(this.text)) {
-                  c++;
-                }
-                if (c == 1) {
-                  $('[id^=\'custom_3\']').val(this.value).trigger('change');
-                  $('#minimum_fee').val(this.value);
-                  return false;
-		}
-	      });
-            });
-         });
-  });
-});
-    ", -100, 'html-header');
-  }
-}
-
 function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
-  if ($formName == 'CRM_Contribute_Form_Contribution_Confirm' && !empty($form->_submitValues['custom_23'])) {
+  if ($formName == 'CRM_Contribute_Form_Contribution_Confirm') {
      $mappingRecord = mappedEntries();
      $lineItems = $tierPrices = [];
      $totalAmount = 0;
@@ -172,18 +136,19 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
      foreach ($form->_lineItem[$form->_priceSetId] as $item) {
        if (empty($tierPrices[$item['membership_type_id']])) {
            $tierPrices[$item['membership_type_id']] = \Civi\Api4\TierPrice::get(FALSE)
-            ->addSelect('tier_level', 'unit_price')
-            ->addWhere('membership_type_id', '=', $item['membership_type_id']])
+            ->addSelect('min_staff_tier_level', 'min_staff_tier_level', 'unit_price')
+            ->addWhere('membership_type_id', '=', $item['membership_type_id'])
             ->execute()->getArrayCopy();
        }
        $key = 'price_' . $item['price_field_id'] . '_' . $item['price_field_value_id'];
        $item['qty'] = $form->_submitValues[$mappingRecord[$key]['qty']];
-       foreach ($tierPrices[$item['membership_type_id']] as $tierPrice) {
-         if ($employeeCount >= $tierPrice['tier_level']) {
+       foreach ($tierPrices[$item['membership_type_id']] as $k1 => $tierPrice) {
+         if ($employeeCount <= $tierPrice['max_staff_tier_level'] && $employeeCount >= $tierPrice['min_staff_tier_level']) {
            $item['unit_price'] = $tierPrice['unit_price'];
          }
        }
        $item['line_total'] = $item['qty'] * $item['unit_price'];
+       $totalAmount += $item['line_total'];
        $lid = \Civi\Api4\LineItem::get(FALSE)
             ->addSelect('id')
             ->addWhere('contribution_id', '=', $form->_contributionID)
@@ -192,6 +157,12 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
        $item['id'] = $lid;
        $lineItems[$lid] = $item;
      }
+     
+     $params = [
+       'id' => $form->_contributionID,
+       'contact_id' => $form->_submitValues['custom_23'],
+       'line_item' => [$form->_priceSetId => $lineItems],
+     ];
 
      civicrm_api3('Contribution', 'create', [
        'id' => $form->_contributionID,
@@ -202,6 +173,7 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
   }
 }
 
+
 function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
   if ($formName == 'CRM_Contribute_Form_Contribution_Main') {
     $mappingRecord = mappedEntries();
@@ -245,67 +217,40 @@ function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
   }
 }
 
-// return [membership_type - price_field_value_id => [number of beds, organization type] mapping fieldsname selector
-function mappedEntries() {
-  $bednos = CRM_Utils_Array::collect('fieldName',
-    \Civi\Api4\CustomField::get(FALSE)
-      ->addSelect("CONCAT('custom_', id) AS fieldName")
-      ->addWhere('custom_group_id:name', '=', 'Number_of_Beds')
-      ->execute()
-      ->getArrayCopy()
-  );
-  $id = \Civi\Api4\CustomField::get(FALSE)
-    ->addWhere('custom_group_id:name', '=', 'Organization_Type')
-    ->execute()->first()['id'];
-
-  $mappingRecord = [];
-  $i = $k = 0;
-  end($bednos);
-  $flag = false;
-  foreach(\Civi\Api4\PriceFieldValue::get(FALSE)
-  ->addSelect("CONCAT('price_', price_field_id, '_', id) AS fieldName")
-  ->addWhere('price_field_id.name', '=', 'tiered_membership_prices')
-  ->execute()
-  ->getArrayCopy() as $key => $value) {
-    if ($k == 9 && !$flag) {$k = key($bednos);}
-    $mappingRecord[$value['fieldName']] = [
-     'org_type' => 'custom_' . $id . '_' . ($i + 1),
-      'qty' => $bednos[$k],
-    ];
-    $i++;
-    if ($i == 7) {
-     if ($k == key($bednos)) {$k = 8; $flag = true;}
-      $i = 0;
-      $k++;
-    }
-  }
-  return $mappingRecord;
-}
-
-// --- Functions below this ship commented out. Uncomment as required. ---
-
-/**
- * Implements hook_civicrm_preProcess().
- *
- * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_preProcess
+/*
+ * return [membership_type - price_field_value_id => [number of beds, organization type] mapping fieldsname selector
  */
-//function tieredpricingformembership_civicrm_preProcess($formName, &$form) {
-//
-//}
+ function mappedEntries() {
+   $bednos = CRM_Utils_Array::collect('fieldName', \Civi\Api4\CustomField::get(FALSE)
+    ->addSelect("CONCAT('custom_', id) AS fieldName")
+    ->addWhere('custom_group_id:name', '=', 'Number_of_Beds')
+    ->execute()
+    ->getArrayCopy());
+   $id = \Civi\Api4\CustomField::get(FALSE)
+     ->addWhere('custom_group_id:name', '=', 'Organization_Type')
+     ->execute()->first()['id'];
 
-/**
- * Implements hook_civicrm_navigationMenu().
- *
- * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_navigationMenu
- */
-function tieredpricingformembership_civicrm_navigationMenu(&$menu) {
-  _tieredpricingformembership_civix_insert_navigation_menu($menu, 'Administer/CiviMember', array(
-    'label' => E::ts('Tier Prices'),
-    'name' => 'civimember_tier_prices',
-    'url' => 'civicrm/admin/tierprice',
-    'permission' => 'access CiviMember',
-    'operator' => 'OR',
-    'separator' => 0,
-  ));
-  _tieredpricingformembership_civix_navigationMenu($menu);
-}
+   $mappingRecord = [];
+   $i = $k = 0;
+   end($bednos);
+   $flag = false;
+   foreach(\Civi\Api4\PriceFieldValue::get(FALSE)
+   ->addSelect("CONCAT('price_', price_field_id, '_', id) AS fieldName")
+   ->addWhere('price_field_id.name', '=', 'tiered_membership_prices')
+   ->execute()
+   ->getArrayCopy() as $key => $value) {
+     if ($k == 9 && !$flag) {$k = key($bednos);}
+     $mappingRecord[$value['fieldName']] = [
+      'org_type' => 'custom_' . $id . '_' . ($i + 1),
+       'qty' => $bednos[$k],
+     ];
+     $i++;
+     if ($i == 7) {
+      if ($k == key($bednos)) {$k = 8; $flag = true;}
+       $i = 0;
+       $k++;
+     }
+   }
+
+   return $mappingRecord;
+ }
-- 
GitLab


From d56b95d68169569e70c157a28d9afad71929530b Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmacosnulting.biz>
Date: Tue, 27 Sep 2022 12:28:39 -0400
Subject: [PATCH 04/16] Made correction in upgrade script and add tier price
 form

---
 CRM/Tieredpricingformembership/Form/TierPrice.php | 3 ++-
 CRM/Tieredpricingformembership/Upgrader.php       | 4 +++-
 xml/Menu/tieredpricingformembership.xml           | 9 +++++++++
 3 files changed, 14 insertions(+), 2 deletions(-)
 create mode 100644 xml/Menu/tieredpricingformembership.xml

diff --git a/CRM/Tieredpricingformembership/Form/TierPrice.php b/CRM/Tieredpricingformembership/Form/TierPrice.php
index 5ce8500..4b90da4 100644
--- a/CRM/Tieredpricingformembership/Form/TierPrice.php
+++ b/CRM/Tieredpricingformembership/Form/TierPrice.php
@@ -19,7 +19,8 @@ class CRM_Tieredpricingformembership_Form_TierPrice extends CRM_Core_Form {
    * Basic setup.
    */
   public function preProcess() {
-    $this->_id = $this->get('id');
+    parent::preProcess();
+    $this->_id = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE);
     $this->_BAOName = $this->get('BAOName');
   }
 
diff --git a/CRM/Tieredpricingformembership/Upgrader.php b/CRM/Tieredpricingformembership/Upgrader.php
index 348ecbf..e6a9a3a 100644
--- a/CRM/Tieredpricingformembership/Upgrader.php
+++ b/CRM/Tieredpricingformembership/Upgrader.php
@@ -63,10 +63,12 @@ class CRM_Tieredpricingformembership_Upgrader extends CRM_Tieredpricingformember
    */
   public function upgrade_1100(): bool {
     $this->ctx->log->info('Applying update 1100 Adding in Max field and renaming tier_level to be minimum');
+    CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 0");
     CRM_Core_BAO_SchemaHandler::dropIndexIfExists('civicrm_tier_price', 'UI_membership_type_id_tier_level');
-    CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_tier_price CHANGE tier_price min_staff_tier_level INT NOT NULL DEFAULT 0 COMMENT \'min number of staff that this tier applies to\'');
+    CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_tier_price CHANGE tier_level min_staff_tier_level INT NOT NULL DEFAULT 0 COMMENT \'min number of staff that this tier applies to\'');
     CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_tier_price ADD COLUMN max_staff_tier_level INT DEFAULT NULL COMMENT \'min number of staff that this tier applies to\'');
     CRM_Core_DAO::executeQuery('ALTER TABLE civicrm_tier_price ADD UNIQUE INDEX UI_membership_type_id_tier_level(`membership_type_id`,`min_staff_tier_level`)');
+    CRM_Core_DAO::executeQuery("SET FOREIGN_KEY_CHECKS = 1");
     return TRUE;
   }
 
diff --git a/xml/Menu/tieredpricingformembership.xml b/xml/Menu/tieredpricingformembership.xml
new file mode 100644
index 0000000..bf31348
--- /dev/null
+++ b/xml/Menu/tieredpricingformembership.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<menu>
+  <item>
+    <path>civicrm/admin/tierprice</path>
+    <page_callback>CRM_Tieredpricingformembership_Form_TierPrice</page_callback>
+    <title>Tier Prices</title>
+    <access_arguments>administer CiviMember</access_arguments>
+  </item>
+</menu>
-- 
GitLab


From 7dff4e78080fbf08bc36f39ecc5320165d54ccf0 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Thu, 29 Sep 2022 04:22:59 -0400
Subject: [PATCH 05/16] Add angular files for tier price searchkit display

---
 ang/afsearchTieredMembershipPrices.aff.html | 15 +++++++++++++++
 ang/afsearchTieredMembershipPrices.aff.json |  6 ++++++
 2 files changed, 21 insertions(+)
 create mode 100644 ang/afsearchTieredMembershipPrices.aff.html
 create mode 100644 ang/afsearchTieredMembershipPrices.aff.json

diff --git a/ang/afsearchTieredMembershipPrices.aff.html b/ang/afsearchTieredMembershipPrices.aff.html
new file mode 100644
index 0000000..2cd32db
--- /dev/null
+++ b/ang/afsearchTieredMembershipPrices.aff.html
@@ -0,0 +1,15 @@
+<div class="btn-group">
+  
+  
+  
+        <a class="btn btn-primary crm-popup" ng-href="{{ crmUrl('civicrm/admin/tierprice', {reset: 1, action: 'add', context: 'create'}) }}">
+          <i class="crm-i fa-plus-circle"/>
+          {{:: ts('Add') }}
+        </a>
+
+
+
+</div>
+<div af-fieldset="">
+  <crm-search-display-table search-name="Tiered_membership_prices" display-name="Tiered_membership_prices_Table_1"></crm-search-display-table>
+</div>
diff --git a/ang/afsearchTieredMembershipPrices.aff.json b/ang/afsearchTieredMembershipPrices.aff.json
new file mode 100644
index 0000000..7e00089
--- /dev/null
+++ b/ang/afsearchTieredMembershipPrices.aff.json
@@ -0,0 +1,6 @@
+{
+    "type": "search",
+    "title": "Tiered Membership Prices",
+    "server_route": "civicrm/tiered-membership-prices",
+    "permission": "access CiviCRM"
+}
\ No newline at end of file
-- 
GitLab


From 1f77feb6e751cd917ecf7dc8c0308481d4ffdb0f Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Fri, 30 Sep 2022 12:49:04 -0400
Subject: [PATCH 06/16] staging site changes

---
 .../Form/TierPrice.php                        | 29 +++++++---
 .../Form/TierPrice.tpl                        |  7 +--
 tieredpricingformembership.php                | 55 +++++++++----------
 3 files changed, 51 insertions(+), 40 deletions(-)

diff --git a/CRM/Tieredpricingformembership/Form/TierPrice.php b/CRM/Tieredpricingformembership/Form/TierPrice.php
index 4b90da4..a2cbe32 100644
--- a/CRM/Tieredpricingformembership/Form/TierPrice.php
+++ b/CRM/Tieredpricingformembership/Form/TierPrice.php
@@ -26,7 +26,9 @@ class CRM_Tieredpricingformembership_Form_TierPrice extends CRM_Core_Form {
 
   public function buildQuickForm() {
     $this->buildQuickEntityForm();
-    $this->addEntityRef('membership_type_id', E::ts('Membership Type'), ['entity' => 'Membership Type', 'placeholder' => E::ts('- Select Membership Type -')], TRUE);
+    if ($this->_action != CRM_Core_Action::DELETE) {
+      $this->addEntityRef('membership_type_id', E::ts('Membership Type'), ['entity' => 'Membership Type', 'placeholder' => E::ts('- Select Membership Type -')], TRUE);
+    }
   }
 
   public function setEntityFields() {
@@ -49,29 +51,40 @@ class CRM_Tieredpricingformembership_Form_TierPrice extends CRM_Core_Form {
 
   public static function formRule($fields) {
     $errors = [];
+    if (!empty($fields['min_staff_tier_level']) && !empty($fields['max_staff_tier_level']) && $fields['min_staff_tier_level'] >= $fields['max_staff_tier_level']) {
+      $errors['min_staff_tier_level'] = E::ts('The minimum staff tier level should be greater then max tier level.');
+    }
     $tierPrices = TierPrice::get()
       ->addWhere('membership_type_id', '=', $fields['membership_type_id'])
       ->addWhere('min_staff_tier_level', '=', $fields['min_staff_tier_level'])
       ->execute();
+
     if (count($tierPrices) > 0) {
       $errors['min_staff_tier_level'] = E::ts('There is already a tier price for this level');
     }
+
     $tierPrices = TierPrice::get()
       ->addWhere('membership_type_id', '=', $fields['membership_type_id'])
-      ->addWhere('min_staff_tier_level', '>', $fields['min_staff_tier_level'])
-      ->addWhere('max_staff_tier_level', '<', $fields['min_staff_tier_level'])
-      ->execute();
-    if (count($tierPrices) > 0) {
+      ->addWhere('min_staff_tier_level', '>=', $fields['min_staff_tier_level'])
+      ->execute()->count();
+    if ($tierPrices > 0) {
       $errors['min_staff_tier_level'] = E::ts('There is already a tier price that exists that covers this minimum staff level');
     }
+    $tierPrices = TierPrice::get()
+      ->addWhere('membership_type_id', '=', $fields['membership_type_id'])
+      ->addWhere('max_staff_tier_level', '=', $fields['min_staff_tier_level'])
+      ->execute()->count();
+    if ($tierPrices > 0) {
+      $errors['min_staff_tier_level'] = E::ts('There is already a tier price that exists that exists as maximum staff level.');
+    }
+
     if (!empty($fields['max_staff_tier_level'])) {
       $tierPrices = TierPrice::get()
         ->addWhere('membership_type_id', '=', $fields['membership_type_id'])
-        ->addWhere('min_staff_tier_level', '>', $fields['max_staff_tier_level'])
-        ->addClause('OR', ['max_staff_tier_level', 'IS NULL', ''], ['max_staff_tier_level', '<', $fields['max_staff_tier_level']])
+        ->addWhere('max_staff_tier_level', '>=', $fields['max_staff_tier_level'])
         ->execute();
       if (count($tierPrices) > 0) {
-        $errors['max_staff_tier_level'] = E::ts('There is already a tier price that exists that covrers this maximum staff level');
+        $errors['max_staff_tier_level'] = E::ts('There is already a tier price that exists that covers this maximum staff level');
       }
     }
     else {
diff --git a/templates/CRM/Tieredpricingformembership/Form/TierPrice.tpl b/templates/CRM/Tieredpricingformembership/Form/TierPrice.tpl
index 695a484..ea060bf 100644
--- a/templates/CRM/Tieredpricingformembership/Form/TierPrice.tpl
+++ b/templates/CRM/Tieredpricingformembership/Form/TierPrice.tpl
@@ -1,11 +1,10 @@
 {* HEADER *}
 
-<div class="crm-submit-buttons">
-{include file="CRM/common/formButtons.tpl" location="top"}
-</div>
-
 {* FIELD EXAMPLE: OPTION 1 (AUTOMATIC LAYOUT) *}
 
+{if $action eq 8}
+  Do you want to delete this entry?
+{/if}
 <table class="form-layout-compressed">
   <tr class="crm-tierprice-form-block-membership_type_id">
     <td class="label">
diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 6f426a5..f2380e1 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -1,3 +1,4 @@
+
 <?php
 
 require_once 'tieredpricingformembership.civix.php';
@@ -81,39 +82,34 @@ function tieredpricingformembership_civicrm_entityTypes(&$entityTypes) {
 
 function tieredpricingformembership_civicrm_post($op, $objectName, $objectId, &$objectRef) {
   if ($objectName == 'Organization' && in_array($op, ['edit', 'create'])) {
+    _updateEmployeeCount($objectId);
+  }
+  if ($objectName == 'Relationship' && in_array($op, ['edit', 'create'])) {
+    if ($objectRef->relationship_type_id == \Civi\Api4\RelationshipType::get(FALSE)->addWhere('name_a_b', '=', 'Has Subsidiary')->execute()->first()['id']) {
+      _updateEmployeeCount($objectRef->contact_id_a);
+    }
+  }
+}
+
+function _updateEmployeeCount($cid, $count = NULL) {
     $subsdiaryOrgs = \Civi\Api4\Relationship::get(FALSE)
       ->addWhere('relationship_type_id:name', '=', 'Has Subsidiary')
-      ->addWhere('contact_id_a', '=', $objectId)
+      ->addWhere('contact_id_a', '=', $cid)
       ->execute();
     if (!empty($subsdiaryOrgs)) {
       $subcount = 0;
-      $count = \Civi\Api4\Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $objectId)->execute()->first()['Employee_count.Employee_count'] ?? 0;
+      $count = $count ?: \Civi\Api4\Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $cid)->execute()->first()['Employee_count.Employee_count'] ?? 0;
       foreach ($subsdiaryOrgs as $org) {
         $subcount += \Civi\Api4\Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $org['contact_id_b'])->execute()->first()['Employee_count.Employee_count'] ?? 0;
       }
       $subcount += $count;
-  
-      $cfID = \Civi\Api4\CustomField::get(FALSE)
-        ->addSelect('id')
-        ->addWhere('custom_group_id:name', '=', 'Employee_count')
-        ->addWhere('name', '=', 'Employee_count_including_subsidiaries')
-        ->execute()->first()['id'];
+
+      $cfID = _get_custom_field_id_by_name('Employee_count_including_subsidiaries', 'Employee_count');
       civicrm_api3('CustomValue', 'create', [
-        'entity_id' => $objectId,
+        'entity_id' => $cid,
         'custom_' . $cfID => $subcount,
       ]);
-
-      $cfID = _get_custom_field_id_by_name('Tier_prices', 'Option_group_containing_price_tiers_based_on_employee_count_inc');
-      $membershipTypes = \Civi\Api4\MembershipType::get(FALSE)->addWhere('member_of_contact_id', $objectId)->execute();
-      $price = _get_tier_price_by_count($subcount);
-      foreach ($membershipTypes as $membershipType) {
-        civicrm_api3('CustomValue', 'create', [
-          'entity_id' => $membershipType['id'],
-          'custom_' . $cfID => $price,
-        ]);
-      }
     }
-  }
 }
 
 function _get_custom_field_id_by_name($fieldName, $cgName) {
@@ -125,6 +121,14 @@ function _get_custom_field_id_by_name($fieldName, $cgName) {
 }
 
 function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
+  if ('CRM_Contact_Form_Inline_CustomData' == $formName) {
+    if ($form->_contactType == 'Organization' && !empty($form->_contactId)) {
+      $cgID = \Civi\Api4\CustomGroup::get(FALSE)->addWhere('name', '=', 'Employee_count')->execute()->first()['id'];
+      if (!empty($form->_submitValues['custom_' . $cgID . '_' . $form->_submitValues['customRecId']])) {
+        _updateEmployeeCount($form->_contactId, $form->_submitValues['custom_' . $cgID . '_' . $form->_submitValues['customRecId']]);
+      }
+    }
+  }
   if ($formName == 'CRM_Contribute_Form_Contribution_Confirm') {
      $mappingRecord = mappedEntries();
      $lineItems = $tierPrices = [];
@@ -136,14 +140,14 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
      foreach ($form->_lineItem[$form->_priceSetId] as $item) {
        if (empty($tierPrices[$item['membership_type_id']])) {
            $tierPrices[$item['membership_type_id']] = \Civi\Api4\TierPrice::get(FALSE)
-            ->addSelect('min_staff_tier_level', 'min_staff_tier_level', 'unit_price')
+            ->addSelect('max_staff_tier_level', 'min_staff_tier_level', 'unit_price')
             ->addWhere('membership_type_id', '=', $item['membership_type_id'])
             ->execute()->getArrayCopy();
        }
        $key = 'price_' . $item['price_field_id'] . '_' . $item['price_field_value_id'];
        $item['qty'] = $form->_submitValues[$mappingRecord[$key]['qty']];
        foreach ($tierPrices[$item['membership_type_id']] as $k1 => $tierPrice) {
-         if ($employeeCount <= $tierPrice['max_staff_tier_level'] && $employeeCount >= $tierPrice['min_staff_tier_level']) {
+         if (($employeeCount <= $tierPrice['max_staff_tier_level'] || empty($tierPrice['max_staff_tier_level'])) && $employeeCount >= $tierPrice['min_staff_tier_level']) {
            $item['unit_price'] = $tierPrice['unit_price'];
          }
        }
@@ -157,16 +161,11 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
        $item['id'] = $lid;
        $lineItems[$lid] = $item;
      }
-     
-     $params = [
-       'id' => $form->_contributionID,
-       'contact_id' => $form->_submitValues['custom_23'],
-       'line_item' => [$form->_priceSetId => $lineItems],
-     ];
 
      civicrm_api3('Contribution', 'create', [
        'id' => $form->_contributionID,
        'total_amount' => $totalAmount,
+       'skipLineItem' => 1,
        'contact_id' => $form->_submitValues['custom_23'],
        'line_item' => [$form->_priceSetId => $lineItems],
      ]);
-- 
GitLab


From df8fbe3a63ee2136c47a45128dba61ac937f9ece Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Fri, 30 Sep 2022 23:42:55 +0530
Subject: [PATCH 07/16] various improment, added comments

---
 ang/afsearchTieredMembershipPrices.aff.html |  10 +-
 tieredpricingformembership.php              | 162 +++++++-------------
 2 files changed, 60 insertions(+), 112 deletions(-)

diff --git a/ang/afsearchTieredMembershipPrices.aff.html b/ang/afsearchTieredMembershipPrices.aff.html
index 2cd32db..02dec8e 100644
--- a/ang/afsearchTieredMembershipPrices.aff.html
+++ b/ang/afsearchTieredMembershipPrices.aff.html
@@ -1,15 +1,17 @@
 <div class="btn-group">
   
-  
-  
         <a class="btn btn-primary crm-popup" ng-href="{{ crmUrl('civicrm/admin/tierprice', {reset: 1, action: 'add', context: 'create'}) }}">
           <i class="crm-i fa-plus-circle"/>
           {{:: ts('Add') }}
         </a>
 
-
-
 </div>
 <div af-fieldset="">
+  <af-field name="membership_type_id.name" />
+  <af-field name="membership_type_id" />
+  <af-field name="min_staff_tier_level" />
+  <af-field name="max_staff_tier_level" />
+  <af-field name="unit_price" />
+  <br />
   <crm-search-display-table search-name="Tiered_membership_prices" display-name="Tiered_membership_prices_Table_1"></crm-search-display-table>
 </div>
diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index f2380e1..11dd71c 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -3,7 +3,7 @@
 
 require_once 'tieredpricingformembership.civix.php';
 // phpcs:disable
-use CRM_Tieredpricingformembership_ExtensionUtil as E;
+use CRM_Tieredpricingformembership_Utils as E;
 // phpcs:enable
 
 /**
@@ -81,72 +81,53 @@ function tieredpricingformembership_civicrm_entityTypes(&$entityTypes) {
 }
 
 function tieredpricingformembership_civicrm_post($op, $objectName, $objectId, &$objectRef) {
+  // when a new or existing organization is updated, recalculate and save the employee count
   if ($objectName == 'Organization' && in_array($op, ['edit', 'create'])) {
-    _updateEmployeeCount($objectId);
+    E::updateEmployeeCount($objectId);
   }
+  // when a new or existing subsidiary relationship is updated, recalculate and save the employee count
   if ($objectName == 'Relationship' && in_array($op, ['edit', 'create'])) {
     if ($objectRef->relationship_type_id == \Civi\Api4\RelationshipType::get(FALSE)->addWhere('name_a_b', '=', 'Has Subsidiary')->execute()->first()['id']) {
-      _updateEmployeeCount($objectRef->contact_id_a);
+      E::updateEmployeeCount($objectRef->contact_id_a);
     }
   }
 }
 
-function _updateEmployeeCount($cid, $count = NULL) {
-    $subsdiaryOrgs = \Civi\Api4\Relationship::get(FALSE)
-      ->addWhere('relationship_type_id:name', '=', 'Has Subsidiary')
-      ->addWhere('contact_id_a', '=', $cid)
-      ->execute();
-    if (!empty($subsdiaryOrgs)) {
-      $subcount = 0;
-      $count = $count ?: \Civi\Api4\Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $cid)->execute()->first()['Employee_count.Employee_count'] ?? 0;
-      foreach ($subsdiaryOrgs as $org) {
-        $subcount += \Civi\Api4\Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $org['contact_id_b'])->execute()->first()['Employee_count.Employee_count'] ?? 0;
-      }
-      $subcount += $count;
-
-      $cfID = _get_custom_field_id_by_name('Employee_count_including_subsidiaries', 'Employee_count');
-      civicrm_api3('CustomValue', 'create', [
-        'entity_id' => $cid,
-        'custom_' . $cfID => $subcount,
-      ]);
-    }
-}
-
-function _get_custom_field_id_by_name($fieldName, $cgName) {
-  return \Civi\Api4\CustomField::get(FALSE)
-    ->addSelect('id')
-    ->addWhere('custom_group_id:name', '=', $cgName)
-    ->addWhere('name', '=', $fieldName)
-    ->execute()->first()['id'];
-}
-
 function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
+  // when a employee count of a organization is updated from inline edit in contact summary page, recalculate and save the employee count
   if ('CRM_Contact_Form_Inline_CustomData' == $formName) {
     if ($form->_contactType == 'Organization' && !empty($form->_contactId)) {
       $cgID = \Civi\Api4\CustomGroup::get(FALSE)->addWhere('name', '=', 'Employee_count')->execute()->first()['id'];
       if (!empty($form->_submitValues['custom_' . $cgID . '_' . $form->_submitValues['customRecId']])) {
-        _updateEmployeeCount($form->_contactId, $form->_submitValues['custom_' . $cgID . '_' . $form->_submitValues['customRecId']]);
+        E::updateEmployeeCount($form->_contactId, $form->_submitValues['custom_' . $cgID . '_' . $form->_submitValues['customRecId']]);
       }
     }
   }
+  // update existing contribution with updated line-item
   if ($formName == 'CRM_Contribute_Form_Contribution_Confirm') {
-     $mappingRecord = mappedEntries();
+     // get all mapping record between membership type and organization type and number of beds fields
+     $mappingRecord = E::mappedEntries();
      $lineItems = $tierPrices = [];
      $totalAmount = 0;
+     // get the employee count of donor organization
      $employeeCount = \Civi\Api4\Contact::get(FALSE)
         ->addSelect('Employee_count.Employee_count_including_subsidiaries')
         ->addWhere('id', '=', $form->_submitValues['custom_23'])
         ->execute()->first()['Employee_count.Employee_count_including_subsidiaries'] ?? 0;
+     // update the line-item unit price based tier level price, which is decided by tier range the employee count falls
      foreach ($form->_lineItem[$form->_priceSetId] as $item) {
        if (empty($tierPrices[$item['membership_type_id']])) {
+           // fetch the tier price of selected membership type
            $tierPrices[$item['membership_type_id']] = \Civi\Api4\TierPrice::get(FALSE)
             ->addSelect('max_staff_tier_level', 'min_staff_tier_level', 'unit_price')
             ->addWhere('membership_type_id', '=', $item['membership_type_id'])
             ->execute()->getArrayCopy();
        }
        $key = 'price_' . $item['price_field_id'] . '_' . $item['price_field_value_id'];
+       // qty is going to be number of beds selected in the donation form
        $item['qty'] = $form->_submitValues[$mappingRecord[$key]['qty']];
        foreach ($tierPrices[$item['membership_type_id']] as $k1 => $tierPrice) {
+         // if the employee count of the organization falls in the tier range the get the unit-price
          if (($employeeCount <= $tierPrice['max_staff_tier_level'] || empty($tierPrice['max_staff_tier_level'])) && $employeeCount >= $tierPrice['min_staff_tier_level']) {
            $item['unit_price'] = $tierPrice['unit_price'];
          }
@@ -162,11 +143,13 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
        $lineItems[$lid] = $item;
      }
 
+     $cfID = E::getCustomFieldIDByName('Organization', 'Primary_Donor');
+     // update the existing contribution with updated line-item, total amount and organization contact ID
      civicrm_api3('Contribution', 'create', [
        'id' => $form->_contributionID,
        'total_amount' => $totalAmount,
        'skipLineItem' => 1,
-       'contact_id' => $form->_submitValues['custom_23'],
+       'contact_id' => $form->_submitValues['custom_' . $cfID],
        'line_item' => [$form->_priceSetId => $lineItems],
      ]);
   }
@@ -175,81 +158,44 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
 
 function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
   if ($formName == 'CRM_Contribute_Form_Contribution_Main') {
-    $mappingRecord = mappedEntries();
+    $mappingRecord = E::mappedEntries();
     $mappingRecord = json_encode($mappingRecord);
-      $bednos = json_encode($bednos);
-        Civi::resources()->addScript("
-         CRM.$(function($) {
-          var mapping =  {$mappingRecord},
-             bednos = {$bednos};
-          $('#priceset').hide();
-          $('input[type=\"text\"]').on('change', function(e) {
-            var name = $(this).attr('id'), orgType = [];
-            if ($.inArray($(this).attr('id'), bednos) !== -1) {
-               $('input[name*=\"custom_6\"]').filter(':checked').each(function() {
-                 orgType.push($(this).attr('id'));
-               });
-               if (orgType.length > 0) {
-                 $.each(mapping, function(k, v) {
-                   if ($.trim($('#' + name).val()) != '' && $.inArray(v.org_type, orgType) !== -1 && v.qty == name) {
-                     if (!$('#' + k).is(':checked')) {
-                       $('#' + k).trigger('click');
-                     }
-                   }
-                   else if ($.trim($('#' + name).val()) == '' && $('#' + k).is(':checked')) {
+    $bednos = json_encode($bednos);
+    $customKey = 'custom_' . E::getCustomFieldIDByName('Type_of_Organization', 'Organization_Type');
+    Civi::resources()->addScript("
+       CRM.$(function($) {
+        var mapping = {$mappingRecord},
+           bednos = {$bednos};
+        $('#priceset').hide();
+        $('input[type=\"text\"]').on('change', function(e) {
+          var name = $(this).attr('id'), orgType = [];
+          if ($.inArray($(this).attr('id'), bednos) !== -1) {
+             $('input[name*=\"{$customKey}\"]').filter(':checked').each(function() {
+               orgType.push($(this).attr('id'));
+             });
+             if (orgType.length > 0) {
+               $.each(mapping, function(k, v) {
+                 if ($.trim($('#' + name).val()) != '' && $.inArray(v.org_type, orgType) !== -1 && v.qty == name) {
+                   if (!$('#' + k).is(':checked')) {
                      $('#' + k).trigger('click');
                    }
-                 });
-               }
-            }
-          });
-          $('input[name*=\"custom_6\"]').on('click', function(e) {
-              var name = $(this).attr('id');
-                $.each(mapping, function(k, v) {
-                  if (v.org_type == name && $.trim($('#' + v.qty).val()) != '') {
-                    $('#' + k).trigger('click');
-                  }
-                });
-          });
-      });
-    ");
+                 }
+                 else if ($.trim($('#' + name).val()) == '' && $('#' + k).is(':checked')) {
+                   $('#' + k).trigger('click');
+                 }
+               });
+             }
+          }
+        });
+        $('input[name*=\"{$customKey}\"]').on('click', function(e) {
+            var name = $(this).attr('id');
+              $.each(mapping, function(k, v) {
+                if (v.org_type == name && $.trim($('#' + v.qty).val()) != '') {
+                  $('#' + k).trigger('click');
+                }
+              });
+        });
+    });");
   }
 }
-
-/*
- * return [membership_type - price_field_value_id => [number of beds, organization type] mapping fieldsname selector
- */
- function mappedEntries() {
-   $bednos = CRM_Utils_Array::collect('fieldName', \Civi\Api4\CustomField::get(FALSE)
-    ->addSelect("CONCAT('custom_', id) AS fieldName")
-    ->addWhere('custom_group_id:name', '=', 'Number_of_Beds')
-    ->execute()
-    ->getArrayCopy());
-   $id = \Civi\Api4\CustomField::get(FALSE)
-     ->addWhere('custom_group_id:name', '=', 'Organization_Type')
-     ->execute()->first()['id'];
-
-   $mappingRecord = [];
-   $i = $k = 0;
-   end($bednos);
-   $flag = false;
-   foreach(\Civi\Api4\PriceFieldValue::get(FALSE)
-   ->addSelect("CONCAT('price_', price_field_id, '_', id) AS fieldName")
-   ->addWhere('price_field_id.name', '=', 'tiered_membership_prices')
-   ->execute()
-   ->getArrayCopy() as $key => $value) {
-     if ($k == 9 && !$flag) {$k = key($bednos);}
-     $mappingRecord[$value['fieldName']] = [
-      'org_type' => 'custom_' . $id . '_' . ($i + 1),
-       'qty' => $bednos[$k],
-     ];
-     $i++;
-     if ($i == 7) {
-      if ($k == key($bednos)) {$k = 8; $flag = true;}
-       $i = 0;
-       $k++;
-     }
-   }
-
-   return $mappingRecord;
- }
+ 
-- 
GitLab


From 824caec2ed624accfeec295ee7ab5a596cd6b3cc Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Fri, 30 Sep 2022 23:44:52 +0530
Subject: [PATCH 08/16] git add Utils file

---
 CRM/Tieredpricingformembership/Utils.php | 104 +++++++++++++++++++++++
 1 file changed, 104 insertions(+)
 create mode 100644 CRM/Tieredpricingformembership/Utils.php

diff --git a/CRM/Tieredpricingformembership/Utils.php b/CRM/Tieredpricingformembership/Utils.php
new file mode 100644
index 0000000..1e92bd4
--- /dev/null
+++ b/CRM/Tieredpricingformembership/Utils.php
@@ -0,0 +1,104 @@
+<?php 
+
+use \Civi\Api4\CustomField;
+use \Civi\Api4\Relationship;
+use \Civi\Api4\Contact;
+use \Civi\Api4\PriceFieldValue;
+
+class CRM_Tieredpricingformembership_Utils {
+
+  /**
+   * Get custom field ID by name
+   * @param string $fieldName Custom field name
+   * @param string $cgName Custom group name
+   *
+   * @return int custom field ID
+   */
+  public static function getCustomFieldIDByName($fieldName, $cgName) {
+    return CustomField::get(FALSE)
+      ->addSelect('id')
+      ->addWhere('custom_group_id:name', '=', $cgName)
+      ->addWhere('name', '=', $fieldName)
+      ->execute()->first()['id'];
+  }
+  
+  /**
+   * Update organization employee count
+   *
+   * @param int $cid contact ID
+   * @param int|void $count Custom group name
+   *
+   * @return void
+   */
+  public static function updateEmployeeCount($cid, $count = NULL) {
+    // Check if the contact ID $cid has a relalionship of type 'Has Subsidiary'
+    $subsdiaryOrgs = Relationship::get(FALSE)
+      ->addWhere('relationship_type_id:name', '=', 'Has Subsidiary')
+      ->addWhere('contact_id_a', '=', $cid)
+      ->execute();
+    // get the employee count of each related subsidiary organization 
+    if (!empty($subsdiaryOrgs)) {
+      $subcount = 0;
+      // Get the employee count of given contact ID $cid
+      $count = $count ?: Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $cid)->execute()->first()['Employee_count.Employee_count'] ?? 0;
+      foreach ($subsdiaryOrgs as $org) {
+        $subcount += Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $org['contact_id_b'])->execute()->first()['Employee_count.Employee_count'] ?? 0;
+      }
+      // the final count of the contact ID $cid will be sum of employee count of all related subsidiary organizations and itself
+      $subcount += $count;
+
+      $cfID = self::getCustomFieldIDByName('Employee_count_including_subsidiaries', 'Employee_count');
+      // Update the 'Employee count including subsidiary'
+      civicrm_api3('CustomValue', 'create', [
+        'entity_id' => $cid,
+        'custom_' . $cfID => $subcount,
+      ]);
+    }
+  }
+  
+  /**
+  * Return mapped entries between price_field_value_id (represent each kind of membership type) and organiation type and number of bed fields
+  *
+  * @return array
+  */
+  public static function mappedEntries() {
+    $bednos = CRM_Utils_Array::collect('fieldName', CustomField::get(FALSE)
+     ->addSelect("CONCAT('custom_', id) AS fieldName")
+     ->addWhere('custom_group_id:name', '=', 'Number_of_Beds')
+     ->execute()
+     ->getArrayCopy());
+    $id = CustomField::get(FALSE)
+      ->addWhere('custom_group_id:name', '=', 'Organization_Type')
+      ->execute()->first()['id'];
+
+    $mappingRecord = [];
+    $i = $k = 0;
+    end($bednos);
+    $flag = false;
+    foreach(PriceFieldValue::get(FALSE)
+      ->addSelect("CONCAT('price_', price_field_id, '_', id) AS fieldName")
+      ->addWhere('price_field_id.name', '=', 'tiered_membership_prices')
+      ->execute()
+      ->getArrayCopy() as $key => $value) {
+        if ($k == 9 && !$flag) {
+          $k = key($bednos);
+        }
+        $mappingRecord[$value['fieldName']] = [
+         'org_type' => 'custom_' . $id . '_' . ($i + 1),
+          'qty' => $bednos[$k],
+        ];
+      $i++;
+      if ($i == 7) {
+        if ($k == key($bednos)) {
+          $k = 8;
+          $flag = true;
+        }
+        $i = 0;
+        $k++;
+      }
+    }
+
+    return $mappingRecord;
+  }
+
+}
\ No newline at end of file
-- 
GitLab


From 595434b34b4ce821b672c9d568f52fe3647f3554 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Fri, 30 Sep 2022 14:24:45 -0400
Subject: [PATCH 09/16] Add 'Tier Price' navigation url

---
 tieredpricingformembership.php | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 11dd71c..145efcc 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -4,6 +4,7 @@
 require_once 'tieredpricingformembership.civix.php';
 // phpcs:disable
 use CRM_Tieredpricingformembership_Utils as E;
+use CRM_Tieredpricingformembership_ExtensionUtil as F;
 // phpcs:enable
 
 /**
@@ -148,7 +149,6 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
      civicrm_api3('Contribution', 'create', [
        'id' => $form->_contributionID,
        'total_amount' => $totalAmount,
-       'skipLineItem' => 1,
        'contact_id' => $form->_submitValues['custom_' . $cfID],
        'line_item' => [$form->_priceSetId => $lineItems],
      ]);
@@ -198,4 +198,15 @@ function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
     });");
   }
 }
- 
+
+function tieredpricingformembership_civicrm_navigationMenu(&$menu) {
+  _tieredpricingformembership_civix_insert_navigation_menu($menu, 'Administer/CiviMember', array(
+    'label' => F::ts('Tier Prices'),
+    'name' => 'civimember_tier_prices',
+    'url' => 'civicrm/tiered-membership-prices',
+    'permission' => 'access CiviMember',
+    'operator' => 'OR',
+    'separator' => 0,
+  ));
+  _tieredpricingformembership_civix_navigationMenu($menu);
+}
-- 
GitLab


From 814c531918e07d31aa7c097688952000c9556557 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Tue, 4 Oct 2022 11:20:15 +0530
Subject: [PATCH 10/16] Calculate employee count for contact_id_b

---
 CRM/Tieredpricingformembership/Utils.php | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/CRM/Tieredpricingformembership/Utils.php b/CRM/Tieredpricingformembership/Utils.php
index 1e92bd4..899476e 100644
--- a/CRM/Tieredpricingformembership/Utils.php
+++ b/CRM/Tieredpricingformembership/Utils.php
@@ -31,12 +31,13 @@ class CRM_Tieredpricingformembership_Utils {
    * @return void
    */
   public static function updateEmployeeCount($cid, $count = NULL) {
+    $cfID = self::getCustomFieldIDByName('Employee_count_including_subsidiaries', 'Employee_count');
     // Check if the contact ID $cid has a relalionship of type 'Has Subsidiary'
     $subsdiaryOrgs = Relationship::get(FALSE)
       ->addWhere('relationship_type_id:name', '=', 'Has Subsidiary')
       ->addWhere('contact_id_a', '=', $cid)
       ->execute();
-    // get the employee count of each related subsidiary organization 
+    // get the employee count of each related subsidiary organization
     if (!empty($subsdiaryOrgs)) {
       $subcount = 0;
       // Get the employee count of given contact ID $cid
@@ -47,13 +48,31 @@ class CRM_Tieredpricingformembership_Utils {
       // the final count of the contact ID $cid will be sum of employee count of all related subsidiary organizations and itself
       $subcount += $count;
 
-      $cfID = self::getCustomFieldIDByName('Employee_count_including_subsidiaries', 'Employee_count');
       // Update the 'Employee count including subsidiary'
       civicrm_api3('CustomValue', 'create', [
         'entity_id' => $cid,
         'custom_' . $cfID => $subcount,
       ]);
     }
+    // if the $cid is a child subsidiary organization
+    else {
+      $subsdiaryOrgs = Relationship::get(FALSE)
+        ->addWhere('relationship_type_id:name', '=', 'Has Subsidiary')
+        ->addWhere('contact_id_b', '=', $cid)
+        ->execute();
+
+      if (!empty($subsdiaryOrgs)) {
+        foreach ($subsdiaryOrgs as $org) {
+          $count = Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $org['contact_id_a'])->execute()->first()['Employee_count.Employee_count'] ?? 0;
+          $count += Contact::get(FALSE)->addSelect('Employee_count.Employee_count')->addWhere('id', '=', $org['contact_id_b'])->execute()->first()['Employee_count.Employee_count'] ?? 0;
+          // Update the 'Employee count including subsidiary'
+          civicrm_api3('CustomValue', 'create', [
+            'entity_id' => $org['contact_id_a'],
+            'custom_' . $cfID => $count,
+          ]);
+        }
+      }
+    }
   }
   
   /**
-- 
GitLab


From b3c2cb1f6d51d3ae6fedf97e5d9bcbddceaa7956 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Tue, 4 Oct 2022 16:23:23 +0530
Subject: [PATCH 11/16] bug fixes: transfer membership to primary contact

---
 tieredpricingformembership.php | 67 +++++++++++++++++++++-------------
 1 file changed, 42 insertions(+), 25 deletions(-)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 145efcc..5bd5638 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -110,10 +110,11 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
      $mappingRecord = E::mappedEntries();
      $lineItems = $tierPrices = [];
      $totalAmount = 0;
+     $cfID = E::getCustomFieldIDByName('Organization', 'Primary_Donor');
      // get the employee count of donor organization
      $employeeCount = \Civi\Api4\Contact::get(FALSE)
         ->addSelect('Employee_count.Employee_count_including_subsidiaries')
-        ->addWhere('id', '=', $form->_submitValues['custom_23'])
+        ->addWhere('id', '=', $form->_submitValues['custom_' . $cfID])
         ->execute()->first()['Employee_count.Employee_count_including_subsidiaries'] ?? 0;
      // update the line-item unit price based tier level price, which is decided by tier range the employee count falls
      foreach ($form->_lineItem[$form->_priceSetId] as $item) {
@@ -144,7 +145,6 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
        $lineItems[$lid] = $item;
      }
 
-     $cfID = E::getCustomFieldIDByName('Organization', 'Primary_Donor');
      // update the existing contribution with updated line-item, total amount and organization contact ID
      civicrm_api3('Contribution', 'create', [
        'id' => $form->_contributionID,
@@ -152,6 +152,11 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
        'contact_id' => $form->_submitValues['custom_' . $cfID],
        'line_item' => [$form->_priceSetId => $lineItems],
      ]);
+     
+     // update the primary membership to selected primary organization
+     foreach (civicrm_api3('MembershipPayment', 'get', ['contribution_id' => $form->_contributionID])['values'] as $membershipPayment) {
+       \Civi\Api4\Membership::update(FALSE)->addValue('contact_id', $form->_submitValues['custom_' . $cfID])->addWhere('id', '=', $membershipPayment['membership_id'])->execute();
+     }
   }
 }
 
@@ -165,36 +170,48 @@ function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
     Civi::resources()->addScript("
        CRM.$(function($) {
         var mapping = {$mappingRecord},
-           bednos = {$bednos};
+           bednos = {$bednos},
+           clickTriggred = false;
         $('#priceset').hide();
         $('input[type=\"text\"]').on('change', function(e) {
-          var name = $(this).attr('id'), orgType = [];
           if ($.inArray($(this).attr('id'), bednos) !== -1) {
-             $('input[name*=\"{$customKey}\"]').filter(':checked').each(function() {
-               orgType.push($(this).attr('id'));
-             });
-             if (orgType.length > 0) {
-               $.each(mapping, function(k, v) {
-                 if ($.trim($('#' + name).val()) != '' && $.inArray(v.org_type, orgType) !== -1 && v.qty == name) {
-                   if (!$('#' + k).is(':checked')) {
-                     $('#' + k).trigger('click');
-                   }
-                 }
-                 else if ($.trim($('#' + name).val()) == '' && $('#' + k).is(':checked')) {
-                   $('#' + k).trigger('click');
-                 }
-               });
-             }
+            selectPriceField();
+          }
+        });
+        $('#_qf_Main_upload').on('click', function(e) {
+          if (!clickTriggred) {
+            e.preventDefault();
+            selectPriceField();
+            $(this).trigger('click');
+            clickTriggred = true;
+          }
+          else {
+            clickTriggred = false;
           }
         });
         $('input[name*=\"{$customKey}\"]').on('click', function(e) {
-            var name = $(this).attr('id');
-              $.each(mapping, function(k, v) {
-                if (v.org_type == name && $.trim($('#' + v.qty).val()) != '') {
-                  $('#' + k).trigger('click');
-                }
-              });
+          $.each(mapping, function(k, v) {
+            if (v.org_type == $(this).attr('id') && $.trim($('#' + v.qty).val()) != '') {
+              $('#' + k).trigger('click');
+            }
+          });
         });
+        function selectPriceField() {
+          var orgType = [];
+          $('input[name*=\"{$customKey}\"]').filter(':checked').each(function() {
+            orgType.push($(this).attr('id'));
+          });
+          $.each(mapping, function(k, v) {
+            if ($.trim($('#' + v.qty).val()) != '' && $.inArray(v.org_type, orgType) !== -1) {
+              if (!$('#' + k).is(':checked')) {
+                $('#' + k).trigger('click');
+              }
+            }
+            else if ($.trim($('#' + v.qty).val()) == '' && $('#' + k).is(':checked')) {
+              $('#' + k).trigger('click');
+            }
+          });
+        }
     });");
   }
 }
-- 
GitLab


From 43f221dfc0a98089986db9f1a54310a7df5bee74 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Tue, 4 Oct 2022 16:39:22 +0530
Subject: [PATCH 12/16] js fix

---
 tieredpricingformembership.php | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 5bd5638..3fd96ef 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -170,24 +170,15 @@ function tieredpricingformembership_civicrm_buildForm($formName, &$form) {
     Civi::resources()->addScript("
        CRM.$(function($) {
         var mapping = {$mappingRecord},
-           bednos = {$bednos},
-           clickTriggred = false;
+           bednos = {$bednos};
         $('#priceset').hide();
         $('input[type=\"text\"]').on('change', function(e) {
           if ($.inArray($(this).attr('id'), bednos) !== -1) {
             selectPriceField();
           }
         });
-        $('#_qf_Main_upload').on('click', function(e) {
-          if (!clickTriggred) {
-            e.preventDefault();
-            selectPriceField();
-            $(this).trigger('click');
-            clickTriggred = true;
-          }
-          else {
-            clickTriggred = false;
-          }
+        $('#_qf_Main_upload-bottom').on('click', function(e) {
+          selectPriceField();
         });
         $('input[name*=\"{$customKey}\"]').on('click', function(e) {
           $.each(mapping, function(k, v) {
-- 
GitLab


From d3ba23f35a8a7411e836b0e71ae39892172b5faf Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Tue, 4 Oct 2022 16:47:37 +0530
Subject: [PATCH 13/16] Add managed files

---
 managed/CustomGroup_Employee_count.mgd.php    | 112 ++++
 managed/CustomGroup_Number_of_Beds.mgd.php    | 619 ++++++++++++++++++
 managed/CustomGroup_Organization_Type.mgd.php | 285 ++++++++
 managed/CustomGroup_Primary_Donor.mgd.php     |  73 +++
 managed/Entities.mgd.php                      | 263 +-------
 5 files changed, 1091 insertions(+), 261 deletions(-)
 create mode 100644 managed/CustomGroup_Employee_count.mgd.php
 create mode 100644 managed/CustomGroup_Number_of_Beds.mgd.php
 create mode 100644 managed/CustomGroup_Organization_Type.mgd.php
 create mode 100644 managed/CustomGroup_Primary_Donor.mgd.php

diff --git a/managed/CustomGroup_Employee_count.mgd.php b/managed/CustomGroup_Employee_count.mgd.php
new file mode 100644
index 0000000..e5981f2
--- /dev/null
+++ b/managed/CustomGroup_Employee_count.mgd.php
@@ -0,0 +1,112 @@
+<?php
+
+return [
+  [
+    'name' => 'CustomGroup_Employee_count', 
+    'entity' => 'CustomGroup', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'name' => 'Employee_count', 
+        'title' => 'Employee count', 
+        'extends' => 'Organization', 
+        'extends_entity_column_value' => NULL, 
+        'style' => 'Inline', 
+        'collapse_display' => FALSE, 
+        'help_pre' => '', 
+        'help_post' => '', 
+        'weight' => 2, 
+        'is_active' => TRUE, 
+        'is_multiple' => FALSE, 
+        'min_multiple' => NULL, 
+        'max_multiple' => NULL, 
+        'collapse_adv_display' => TRUE, 
+        'created_date' => '2022-07-21 14:04:47', 
+        'is_reserved' => FALSE, 
+        'is_public' => TRUE, 
+        'icon' => '', 
+        'extends_entity_column_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Employee_count_CustomField_Employee_count', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Employee_count', 
+        'name' => 'Employee_count', 
+        'label' => 'Employee count', 
+        'data_type' => 'String', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => TRUE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'employee_count_1', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Employee_count_CustomField_Employee_count_including_subsidiaries', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Employee_count', 
+        'name' => 'Employee_count_including_subsidiaries', 
+        'label' => 'Employee count including subsidiaries', 
+        'data_type' => 'String', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => TRUE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => TRUE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'employee_count_including_subsidi_2', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ],
+];
\ No newline at end of file
diff --git a/managed/CustomGroup_Number_of_Beds.mgd.php b/managed/CustomGroup_Number_of_Beds.mgd.php
new file mode 100644
index 0000000..2750cdc
--- /dev/null
+++ b/managed/CustomGroup_Number_of_Beds.mgd.php
@@ -0,0 +1,619 @@
+<?php
+
+return [
+  [
+    'name' => 'CustomGroup_Number_of_Beds', 
+    'entity' => 'CustomGroup', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'name' => 'Number_of_Beds', 
+        'title' => 'Qtes', 
+        'extends' => 'Membership', 
+        'extends_entity_column_value' => NULL, 
+        'style' => 'Inline', 
+        'collapse_display' => FALSE, 
+        'help_pre' => '', 
+        'help_post' => '', 
+        'weight' => 5, 
+        'is_active' => TRUE, 
+        'is_multiple' => FALSE, 
+        'min_multiple' => NULL, 
+        'max_multiple' => NULL, 
+        'collapse_adv_display' => TRUE, 
+        'created_date' => '2022-09-13 08:16:42', 
+        'is_reserved' => FALSE, 
+        'is_public' => TRUE, 
+        'icon' => '', 
+        'extends_entity_column_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_M_dicine', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'M_dicine', 
+        'label' => 'Médicine', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'm_dicine_8', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Chirurgie', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Chirurgie', 
+        'label' => 'Chirurgie', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'chirurgie_9', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Obst_trique', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Obst_trique', 
+        'label' => 'Obstétrique', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'obst_trique_10', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Ambulatoire', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Ambulatoire', 
+        'label' => 'Ambulatoire', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'ambulatoire_11', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_HTP', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'HTP', 
+        'label' => 'HTP', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'htp_12', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Poste_dialyse', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Poste_dialyse', 
+        'label' => 'Poste dialyse', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'poste_dialyse_13', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Forfait_dialyse', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Forfait_dialyse', 
+        'label' => 'Forfait dialyse', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'forfait_dialyse_14', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_PSY', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'PSY', 
+        'label' => 'PSY', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'psy_15', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_MECS_therme', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'MECS_therme', 
+        'label' => 'MECS therme', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'mecs_therme_16', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_MECS', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'MECS', 
+        'label' => 'MECS', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'mecs_22', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_RF', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'RF', 
+        'label' => 'RF', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'rf_17', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Soins_de_suite', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Soins_de_suite', 
+        'label' => 'Soins de suite', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'soins_de_suite_18', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_HAD', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'HAD', 
+        'label' => 'HAD', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'had_19', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Cot_forfaitaire_1', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Cot_forfaitaire_1', 
+        'label' => 'Cot. forfaitaire 1', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'cot_forfaitaire_1_20', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Number_of_Beds_CustomField_Cot_forfaitaire_2', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Number_of_Beds', 
+        'name' => 'Cot_forfaitaire_2', 
+        'label' => 'Cot. forfaitaire 2', 
+        'data_type' => 'Int', 
+        'html_type' => 'Text', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'cot_forfaitaire_2_21', 
+        'serialize' => 0, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ],
+];
\ No newline at end of file
diff --git a/managed/CustomGroup_Organization_Type.mgd.php b/managed/CustomGroup_Organization_Type.mgd.php
new file mode 100644
index 0000000..f6c65d3
--- /dev/null
+++ b/managed/CustomGroup_Organization_Type.mgd.php
@@ -0,0 +1,285 @@
+<?php
+return [
+  [
+    'name' => 'CustomGroup_Organization_Type', 
+    'entity' => 'CustomGroup', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'name' => 'Organization_Type', 
+        'title' => 'Organization Type', 
+        'extends' => 'Membership', 
+        'extends_entity_column_value' => NULL, 
+        'style' => 'Inline', 
+        'collapse_display' => FALSE, 
+        'help_pre' => '', 
+        'help_post' => '', 
+        'weight' => 1, 
+        'is_active' => TRUE, 
+        'is_multiple' => FALSE, 
+        'min_multiple' => NULL, 
+        'max_multiple' => NULL, 
+        'collapse_adv_display' => TRUE, 
+        'created_date' => '2022-09-13 08:11:58', 
+        'is_reserved' => FALSE, 
+        'is_public' => TRUE, 
+        'icon' => '', 
+        'extends_entity_column_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization', 
+    'entity' => 'OptionGroup', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'name' => 'Organization_Type_Type_of_Organization', 
+        'title' => 'Organization Type :: Type of Organization', 
+        'description' => NULL, 
+        'data_type' => 'String', 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'is_locked' => FALSE, 
+        'option_value_fields' => [
+          'name', 
+          'label', 
+          'description',
+        ],
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization_OptionValue_FHP', 
+    'entity' => 'OptionValue', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'label' => 'FHP', 
+        'value' => '1', 
+        'name' => 'FHP', 
+        'grouping' => NULL, 
+        'filter' => 0, 
+        'is_default' => FALSE, 
+        'description' => NULL, 
+        'is_optgroup' => FALSE, 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'icon' => NULL, 
+        'color' => NULL, 
+        'component_id' => NULL, 
+        'domain_id' => NULL, 
+        'visibility_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization_OptionValue_R_gional', 
+    'entity' => 'OptionValue', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'label' => 'Régional', 
+        'value' => '2', 
+        'name' => 'R_gional', 
+        'grouping' => NULL, 
+        'filter' => 0, 
+        'is_default' => FALSE, 
+        'description' => NULL, 
+        'is_optgroup' => FALSE, 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'icon' => NULL, 
+        'color' => NULL, 
+        'component_id' => NULL, 
+        'domain_id' => NULL, 
+        'visibility_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization_OptionValue_FHP_MCO', 
+    'entity' => 'OptionValue', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'label' => 'FHP-MCO', 
+        'value' => '3', 
+        'name' => 'FHP_MCO', 
+        'grouping' => NULL, 
+        'filter' => 0, 
+        'is_default' => FALSE, 
+        'description' => NULL, 
+        'is_optgroup' => FALSE, 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'icon' => NULL, 
+        'color' => NULL, 
+        'component_id' => NULL, 
+        'domain_id' => NULL, 
+        'visibility_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization_OptionValue_FHP_DIALYSE', 
+    'entity' => 'OptionValue', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'label' => 'FHP-DIALYSE', 
+        'value' => '4', 
+        'name' => 'FHP_DIALYSE', 
+        'grouping' => NULL, 
+        'filter' => 0, 
+        'is_default' => FALSE, 
+        'description' => NULL, 
+        'is_optgroup' => FALSE, 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'icon' => NULL, 
+        'color' => NULL, 
+        'component_id' => NULL, 
+        'domain_id' => NULL, 
+        'visibility_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization_OptionValue_UNCPSY', 
+    'entity' => 'OptionValue', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'label' => 'UNCPSY', 
+        'value' => '5', 
+        'name' => 'UNCPSY', 
+        'grouping' => NULL, 
+        'filter' => 0, 
+        'is_default' => FALSE, 
+        'description' => NULL, 
+        'is_optgroup' => FALSE, 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'icon' => NULL, 
+        'color' => NULL, 
+        'component_id' => NULL, 
+        'domain_id' => NULL, 
+        'visibility_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization_OptionValue_CSSR_FHP', 
+    'entity' => 'OptionValue', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'label' => 'CSSR-FHP', 
+        'value' => '6', 
+        'name' => 'CSSR_FHP', 
+        'grouping' => NULL, 
+        'filter' => 0, 
+        'is_default' => FALSE, 
+        'description' => NULL, 
+        'is_optgroup' => FALSE, 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'icon' => NULL, 
+        'color' => NULL, 
+        'component_id' => NULL, 
+        'domain_id' => NULL, 
+        'visibility_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'OptionGroup_Organization_Type_Type_of_Organization_OptionValue_UNHPC', 
+    'entity' => 'OptionValue', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'label' => 'UNHPC', 
+        'value' => '7', 
+        'name' => 'UNHPC', 
+        'grouping' => NULL, 
+        'filter' => 0, 
+        'is_default' => FALSE, 
+        'description' => NULL, 
+        'is_optgroup' => FALSE, 
+        'is_reserved' => FALSE, 
+        'is_active' => TRUE, 
+        'icon' => NULL, 
+        'color' => NULL, 
+        'component_id' => NULL, 
+        'domain_id' => NULL, 
+        'visibility_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Organization_Type_CustomField_Type_of_Organization', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Organization_Type', 
+        'name' => 'Type_of_Organization', 
+        'label' => 'Type of Organization', 
+        'data_type' => 'String', 
+        'html_type' => 'CheckBox', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => 1, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'type_of_organization_6', 
+        'option_group_id.name' => 'Organization_Type_Type_of_Organization', 
+        'serialize' => 1, 
+        'filter' => NULL, 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ],
+];
\ No newline at end of file
diff --git a/managed/CustomGroup_Primary_Donor.mgd.php b/managed/CustomGroup_Primary_Donor.mgd.php
new file mode 100644
index 0000000..5a69fee
--- /dev/null
+++ b/managed/CustomGroup_Primary_Donor.mgd.php
@@ -0,0 +1,73 @@
+<?php
+
+return [
+  [
+    'name' => 'CustomGroup_Primary_Donor', 
+    'entity' => 'CustomGroup', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'name' => 'Primary_Donor', 
+        'title' => 'Primary Donor', 
+        'extends' => 'Membership', 
+        'extends_entity_column_value' => NULL, 
+        'style' => 'Inline', 
+        'collapse_display' => FALSE, 
+        'help_pre' => '', 
+        'help_post' => '', 
+        'weight' => 6, 
+        'is_active' => TRUE, 
+        'is_multiple' => FALSE, 
+        'min_multiple' => NULL, 
+        'max_multiple' => NULL, 
+        'collapse_adv_display' => TRUE, 
+        'created_date' => '2022-09-22 09:21:58', 
+        'is_reserved' => FALSE, 
+        'is_public' => TRUE, 
+        'icon' => '', 
+        'extends_entity_column_id' => NULL,
+      ],
+    ],
+  ], 
+  [
+    'name' => 'CustomGroup_Primary_Donor_CustomField_Organization', 
+    'entity' => 'CustomField', 
+    'cleanup' => 'unused', 
+    'update' => 'unmodified', 
+    'params' => [
+      'version' => 4, 
+      'values' => [
+        'custom_group_id.name' => 'Primary_Donor', 
+        'name' => 'Organization', 
+        'label' => 'Organization', 
+        'data_type' => 'ContactReference', 
+        'html_type' => 'Autocomplete-Select', 
+        'default_value' => NULL, 
+        'is_required' => FALSE, 
+        'is_searchable' => FALSE, 
+        'is_search_range' => FALSE, 
+        'help_pre' => NULL, 
+        'help_post' => NULL, 
+        'mask' => NULL, 
+        'attributes' => NULL, 
+        'javascript' => NULL, 
+        'is_active' => TRUE, 
+        'is_view' => FALSE, 
+        'options_per_line' => NULL, 
+        'text_length' => 255, 
+        'start_date_years' => NULL, 
+        'end_date_years' => NULL, 
+        'date_format' => NULL, 
+        'time_format' => NULL, 
+        'note_columns' => 60, 
+        'note_rows' => 4, 
+        'column_name' => 'organization_23', 
+        'serialize' => 0, 
+        'filter' => 'action=lookup&group=2', 
+        'in_selector' => FALSE,
+      ],
+    ],
+  ],
+];
\ No newline at end of file
diff --git a/managed/Entities.mgd.php b/managed/Entities.mgd.php
index f825a58..6835743 100644
--- a/managed/Entities.mgd.php
+++ b/managed/Entities.mgd.php
@@ -1,264 +1,5 @@
 <?php
-return [];
-/*return [
-  [
-    'name' => 'OptionValue_membership_type_custom_data_type',
-    'entity' => 'OptionValue',
-    'cleanup' => 'always',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'option_group_id.name' => 'cg_extend_objects',
-        'label' => 'Membership Type',
-        'name' => 'civicrm_membership_type',
-        'value' => 'MembershipType',
-        'description' => NULL,
-        'is_active' => TRUE,
-        'grouping' => NULL,
-      ],
-      'match' => ['label'],
-    ],
-  ],
-  [
-    'name' => 'OptionGroup_tier_membership_prices',
-    'entity' => 'OptionGroup',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'name' => 'tiered_membership_prices',
-        'title' => 'Tiered Membership prices',
-        'description' => NULL,
-        'data_type' => 'String',
-        'is_reserved' => TRUE,
-        'is_active' => TRUE,
-        'is_locked' => FALSE,
-        'option_value_fields' => [
-          'name',
-          'label',
-          'description',
-        ],
-      ],
-    ],
-  ],
-  [
-    'name' => 'OptionGroup_tier_membership_prices_OptionValue_4',
-    'entity' => 'OptionValue',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'option_group_id.name' => 'tier_membership_prices',
-        'label' => '4',
-        'value' => '10',
-        'name' => '4',
-        'grouping' => NULL,
-        'filter' => 0,
-        'is_default' => FALSE,
-        'description' => '0-4',
-        'is_optgroup' => FALSE,
-        'is_reserved' => TRUE,
-        'is_active' => TRUE,
-        'icon' => NULL,
-        'color' => NULL,
-        'component_id' => NULL,
-        'domain_id' => NULL,
-        'visibility_id' => NULL,
-      ],
-    ],
-  ],
-  [
-    'name' => 'OptionGroup_tier_membership_prices_OptionValue_14',
-    'entity' => 'OptionValue',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'option_group_id.name' => 'tier_membership_prices',
-        'label' => '14',
-        'value' => '20',
-        'name' => '14',
-        'grouping' => NULL,
-        'filter' => 0,
-        'is_default' => FALSE,
-        'description' => '5-14',
-        'is_optgroup' => FALSE,
-        'is_reserved' => TRUE,
-        'is_active' => TRUE,
-        'icon' => NULL,
-        'color' => NULL,
-        'component_id' => NULL,
-        'domain_id' => NULL,
-        'visibility_id' => NULL,
-      ],
-    ],
-  ],
-  [
-    'name' => 'OptionGroup_tier_membership_prices_OptionValue_49',
-    'entity' => 'OptionValue',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'option_group_id.name' => 'tier_membership_prices',
-        'label' => '49',
-        'value' => '30',
-        'name' => '49',
-        'grouping' => NULL,
-        'filter' => 0,
-        'is_default' => FALSE,
-        'description' => '15-49',
-        'is_optgroup' => FALSE,
-        'is_reserved' => TRUE,
-        'is_active' => TRUE,
-        'icon' => NULL,
-        'color' => NULL,
-        'component_id' => NULL,
-        'domain_id' => NULL,
-        'visibility_id' => NULL,
-      ],
-    ],
-  ],
-  [
-    'name' => 'OptionGroup_tier_membership_prices_OptionValue_9999999',
-    'entity' => 'OptionValue',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'option_group_id.name' => 'tier_membership_prices',
-        'label' => '9999999',
-        'value' => '40',
-        'name' => '9999999',
-        'grouping' => NULL,
-        'filter' => 0,
-        'is_default' => FALSE,
-        'description' => '50+',
-        'is_optgroup' => FALSE,
-        'is_reserved' => TRUE,
-        'is_active' => TRUE,
-        'icon' => NULL,
-        'color' => NULL,
-        'component_id' => NULL,
-        'domain_id' => NULL,
-        'visibility_id' => NULL,
-      ],
-    ],
-  ],
-  [
-    'name' => 'CustomGroup_Employee_count',
-    'entity' => 'CustomGroup',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'name' => 'Employee_count',
-        'title' => 'Employee count',
-        'extends' => 'Organization',
-        'extends_entity_column_value' => NULL,
-        'style' => 'Inline',
-        'collapse_display' => FALSE,
-        'help_pre' => '',
-        'help_post' => '',
-        'weight' => 1,
-        'is_active' => TRUE,
-        'is_multiple' => FALSE,
-        'min_multiple' => NULL,
-        'max_multiple' => NULL,
-        'collapse_adv_display' => TRUE,
-        'created_date' => '2022-07-21 14:04:47',
-        'is_reserved' => FALSE,
-        'is_public' => TRUE,
-        'icon' => '',
-        'extends_entity_column_id' => NULL,
-      ],
-    ],
-  ],
-  [
-    'name' => 'CustomGroup_Employee_count_CustomField_Employee_count',
-    'entity' => 'CustomField',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'custom_group_id.name' => 'Employee_count',
-        'name' => 'Employee_count',
-        'label' => 'Employee count',
-        'data_type' => 'String',
-        'html_type' => 'Text',
-        'default_value' => NULL,
-        'is_required' => FALSE,
-        'is_searchable' => FALSE,
-        'is_search_range' => FALSE,
-        'help_pre' => NULL,
-        'help_post' => NULL,
-        'mask' => NULL,
-        'attributes' => NULL,
-        'javascript' => NULL,
-        'is_active' => TRUE,
-        'is_view' => FALSE,
-        'options_per_line' => NULL,
-        'text_length' => 255,
-        'start_date_years' => NULL,
-        'end_date_years' => NULL,
-        'date_format' => NULL,
-        'time_format' => NULL,
-        'note_columns' => 60,
-        'note_rows' => 4,
-        'column_name' => 'employee_count_1',
-        'serialize' => 0,
-        'filter' => NULL,
-        'in_selector' => FALSE,
-      ],
-    ],
-  ],
-  [
-    'name' => 'CustomGroup_Employee_count_CustomField_Employee_count_including_subsidiaries',
-    'entity' => 'CustomField',
-    'cleanup' => 'unused',
-    'update' => 'unmodified',
-    'params' => [
-      'version' => 4,
-      'values' => [
-        'custom_group_id.name' => 'Employee_count',
-        'name' => 'Employee_count_including_subsidiaries',
-        'label' => 'Employee count including subsidiaries',
-        'data_type' => 'String',
-        'html_type' => 'Text',
-        'default_value' => NULL,
-        'is_required' => FALSE,
-        'is_searchable' => FALSE,
-        'is_search_range' => FALSE,
-        'help_pre' => NULL,
-        'help_post' => NULL,
-        'mask' => NULL,
-        'attributes' => NULL,
-        'javascript' => NULL,
-        'is_active' => TRUE,
-        'is_view' => TRUE,
-        'options_per_line' => NULL,
-        'text_length' => 255,
-        'start_date_years' => NULL,
-        'end_date_years' => NULL,
-        'date_format' => NULL,
-        'time_format' => NULL,
-        'note_columns' => 60,
-        'note_rows' => 4,
-        'column_name' => 'employee_count_including_subsidi_2',
-        'serialize' => 0,
-        'filter' => NULL,
-        'in_selector' => FALSE,
-      ],
-    ],
-  ],
+return [
   [
     'name' => 'RelationshipType_1',
     'entity' => 'RelationshipType',
@@ -281,4 +22,4 @@ return [];
       ],
     ],
   ],
-];*/
+];
-- 
GitLab


From 2edcef45081078af2ca69c5e3f924e532269dc61 Mon Sep 17 00:00:00 2001
From: Seamus Lee <seamus.lee@jmaconsulting.biz>
Date: Fri, 7 Oct 2022 02:04:04 -0400
Subject: [PATCH 14/16] Fix updating line items prior to contribution creation

---
 tieredpricingformembership.php | 39 +++++++++++++++++-----------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 3fd96ef..e7f9522 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -105,7 +105,7 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
     }
   }
   // update existing contribution with updated line-item
-  if ($formName == 'CRM_Contribute_Form_Contribution_Confirm') {
+  if ($formName == 'CRM_Contribute_Form_Contribution_Main') {
      // get all mapping record between membership type and organization type and number of beds fields
      $mappingRecord = E::mappedEntries();
      $lineItems = $tierPrices = [];
@@ -117,7 +117,8 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
         ->addWhere('id', '=', $form->_submitValues['custom_' . $cfID])
         ->execute()->first()['Employee_count.Employee_count_including_subsidiaries'] ?? 0;
      // update the line-item unit price based tier level price, which is decided by tier range the employee count falls
-     foreach ($form->_lineItem[$form->_priceSetId] as $item) {
+     $formLineItems = $form->get('lineItem'); 
+     foreach ($formLineItems[$form->_priceSetId] as &$item) {
        if (empty($tierPrices[$item['membership_type_id']])) {
            // fetch the tier price of selected membership type
            $tierPrices[$item['membership_type_id']] = \Civi\Api4\TierPrice::get(FALSE)
@@ -136,27 +137,25 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
        }
        $item['line_total'] = $item['qty'] * $item['unit_price'];
        $totalAmount += $item['line_total'];
-       $lid = \Civi\Api4\LineItem::get(FALSE)
-            ->addSelect('id')
-            ->addWhere('contribution_id', '=', $form->_contributionID)
-            ->addWhere('price_field_value_id', '=', $item['price_field_value_id'])
-            ->execute()->first()['id'];
-       $item['id'] = $lid;
-       $lineItems[$lid] = $item;
      }
+     $form->set('lineItem', $formLineItems);
+     $form->set('amount', $totalAmount);
+     $form->_params['amount'] = $totalAmount;
+     $form->_values['amount'] = $totalAmount;
+  }
 
-     // update the existing contribution with updated line-item, total amount and organization contact ID
-     civicrm_api3('Contribution', 'create', [
-       'id' => $form->_contributionID,
-       'total_amount' => $totalAmount,
-       'contact_id' => $form->_submitValues['custom_' . $cfID],
-       'line_item' => [$form->_priceSetId => $lineItems],
-     ]);
+  if ($formName == 'CRM_Contribute_Form_Contribution_Confirm') {
+    $cfID = E::getCustomFieldIDByName('Organization', 'Primary_Donor');
+    // update the existing contribution with updated line-item, total amount and organization contact ID
+    civicrm_api3('Contribution', 'create', [
+      'id' => $form->_contributionID,
+      'contact_id' => $form->_submitValues['custom_' . $cfID],
+    ]);
      
-     // update the primary membership to selected primary organization
-     foreach (civicrm_api3('MembershipPayment', 'get', ['contribution_id' => $form->_contributionID])['values'] as $membershipPayment) {
-       \Civi\Api4\Membership::update(FALSE)->addValue('contact_id', $form->_submitValues['custom_' . $cfID])->addWhere('id', '=', $membershipPayment['membership_id'])->execute();
-     }
+    // update the primary membership to selected primary organization
+    foreach (civicrm_api3('MembershipPayment', 'get', ['contribution_id' => $form->_contributionID])['values'] as $membershipPayment) {
+      \Civi\Api4\Membership::update(FALSE)->addValue('contact_id', $form->_submitValues['custom_' . $cfID])->addWhere('id', '=', $membershipPayment['membership_id'])->execute();
+    }
   }
 }
 
-- 
GitLab


From a8c958e97b4ae7b06425b2bc027f8cf7225f38e5 Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Wed, 12 Oct 2022 10:57:12 -0400
Subject: [PATCH 15/16] Use update SQL query instead of APIv4 update action for
 membership as it is not possible to ignore date calculation

---
 tieredpricingformembership.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index e7f9522..911f9be 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -151,10 +151,10 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
       'id' => $form->_contributionID,
       'contact_id' => $form->_submitValues['custom_' . $cfID],
     ]);
-     
+
     // update the primary membership to selected primary organization
     foreach (civicrm_api3('MembershipPayment', 'get', ['contribution_id' => $form->_contributionID])['values'] as $membershipPayment) {
-      \Civi\Api4\Membership::update(FALSE)->addValue('contact_id', $form->_submitValues['custom_' . $cfID])->addWhere('id', '=', $membershipPayment['membership_id'])->execute();
+      CRM_Core_DAO::executeQuery("UPDATE civicrm_membership SET contact_id = %1 WHERE id = %2", [1 => [$form->_submitValues['custom_' . $cfID], 'Integer'], 2 => [$membershipPayment['membership_id'], 'Integer']]);
     }
   }
 }
-- 
GitLab


From 07cfe54b8ec05df766a84e8234e1cb4565e0557f Mon Sep 17 00:00:00 2001
From: Monish Deb <monish.deb@jmaconsulting.biz>
Date: Wed, 12 Oct 2022 11:10:42 -0400
Subject: [PATCH 16/16] Complete the created contribution

---
 tieredpricingformembership.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tieredpricingformembership.php b/tieredpricingformembership.php
index 911f9be..90b93f0 100644
--- a/tieredpricingformembership.php
+++ b/tieredpricingformembership.php
@@ -150,6 +150,7 @@ function tieredpricingformembership_civicrm_postProcess($formName, &$form) {
     civicrm_api3('Contribution', 'create', [
       'id' => $form->_contributionID,
       'contact_id' => $form->_submitValues['custom_' . $cfID],
+      'contribution_status_id' => 'Completed',
     ]);
 
     // update the primary membership to selected primary organization
-- 
GitLab