From 01d3dcfda778bee0081171a3415312dc10b4ed82 Mon Sep 17 00:00:00 2001
From: ErikHommel <hommel@ee-atwork.nl>
Date: Thu, 12 Dec 2024 16:29:42 +0100
Subject: [PATCH] fix event for djalali posters

---
 CHANGELOG.md                 |   3 +
 CRM/Corrections/Poster.php   | 221 +++++++++++++++++++++++++++++++++++
 CRM/Corrections/RrnTag.php   |  83 -------------
 CRM/Corrections/Upgrader.php |  53 +++++++++
 api/v3/Posters/Fixevent.php  |  20 ++++
 api/v3/RrnTag/Fixpast.php    |  20 ----
 info.xml                     |  11 +-
 7 files changed, 303 insertions(+), 108 deletions(-)
 create mode 100644 CRM/Corrections/Poster.php
 delete mode 100644 CRM/Corrections/RrnTag.php
 create mode 100644 CRM/Corrections/Upgrader.php
 create mode 100644 api/v3/Posters/Fixevent.php
 delete mode 100644 api/v3/RrnTag/Fixpast.php

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c19cfc3..8ac903f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+## Release 1.10
+* issue 12643 - change posters order Djalali from event to activity with generic fields (see https://issues.civicoop.org/issues/12643)
+
 ## Release 1.9
 * run civix upgrade
 * check PHP8/Civi5.75 compliance
diff --git a/CRM/Corrections/Poster.php b/CRM/Corrections/Poster.php
new file mode 100644
index 0000000..4e35635
--- /dev/null
+++ b/CRM/Corrections/Poster.php
@@ -0,0 +1,221 @@
+<?php
+
+/**
+ * Class for fixing the event poster orders to activity poster orders
+ *
+ * @author Erik Hommel (CiviCooP) <erik.hommel@civicoop.org>
+ * @date 12 Dec 2024
+ * @license AGPL-3.0
+ */
+class CRM_Corrections_Poster {
+  private $_activityType;
+  private $_eventId;
+  private $_campaignId;
+  private $_a2Origin;
+  private $_a2New;
+  private $_a3Origin;
+  private $_a3New;
+  private $_aivlWebsite;
+
+  /**
+   * Constructor
+   */
+  public function __construct() {
+    $this->setActivityType();
+    $this->setEventId();
+    $this->setCampaignId();
+    $this->setAffiches();
+    $this->setAivlWebsite();
+  }
+
+  /**
+   * @return void
+   */
+  public function fixEvent(): void {
+    $participants = $this->getParticipants();
+    foreach ($participants as $participant) {
+      // create activity generic webform
+      $activityId = $this->createActivity($participant);
+      // update generic fields -> move from participant to activity
+      if ($activityId) {
+        $updated = $this->updateGenericFields($activityId, $participant['id']);
+        if ($updated) {
+          // remove participant from event
+          $this->removeParticipant($participant['id']);
+        }
+      }
+    }
+  }
+
+  /**
+   * @param int $participantId
+   * @return void
+   */
+  private function removeParticipant(int $participantId): void {
+    try {
+      \Civi\Api4\Participant::delete(FALSE)
+        ->addWhere('id', '=', $participantId)->execute();
+      // remove event registration activity too if required
+      $activity = \Civi\Api4\Activity::get(FALSE)
+        ->addWhere('source_record_id', '=', $participantId)
+        ->addWhere('activity_type_id:name', '=', 'Event Registration')
+        ->execute()->first();
+      if (isset($activity['id'])) {
+        \Civi\Api4\Activity::delete(FALSE)
+          ->addWhere('id', '=', $activity['id'])
+          ->execute();
+      }
+    }
+    catch (\CRM_Core_Exception $ex) {
+    }
+  }
+
+  /**
+   * @param int $activityId
+   * @param int $participantId
+   * @return bool
+   */
+  private function updateGenericFields(int $activityId, int $participantId): bool {
+    $updated = FALSE;
+    try {
+      \Civi\Api4\GenericFormField::update(FALSE)
+        ->addWhere('participant_id', '=', $participantId)
+        ->addValue('activity_id', $activityId)
+        ->addValue('participant_id', NULL)
+        ->execute();
+      $updated = TRUE;
+      \Civi\Api4\GenericFormField::update(FALSE)
+        ->addWhere('activity_id', '=', $activityId)
+        ->addWhere('field_label', '=', $this->_a2Origin)
+        ->addValue('field_label', $this->_a2New)
+        ->execute(); \Civi\Api4\GenericFormField::update(FALSE)
+        ->addWhere('activity_id', '=', $activityId)
+        ->addWhere('field_label', '=', $this->_a3Origin)
+        ->addValue('field_label', $this->_a3New)
+        ->execute();
+    }
+    catch (\CRM_Core_Exception $ex) {
+    }
+    return $updated;
+  }
+
+  /**
+   * @param array $participant
+   * @return int|null
+   */
+  private function createActivity(array $participant): ?int {
+    $activityId = NULL;
+    if ($this->_activityType) {
+      try {
+        $api = \Civi\Api4\Activity::create(FALSE)
+          ->addValue('activity_type_id:name', $this->_activityType)
+          ->addValue('target_contact_id', [$participant['contact_id']])
+          ->addValue('source_contact_id', $this->_aivlWebsite)
+          ->addValue('subject', 'Bestel affiches Iran Ahmadreza Djalali')
+          ->addValue('status_id:name', 'Completed');
+        if (isset($participant['register_date'])) {
+          $api->addValue('activity_date_time', $participant['register_date']);
+        }
+        if ($this->_campaignId) {
+          $api->addValue('campaign_id', $this->_campaignId);
+        }
+        $activity = $api->execute()->first();
+        if (isset($activity['id'])) {
+          $activityId = $activity['id'];
+        }
+      }
+      catch (\CRM_Core_Exception $ex) {
+      }
+    }
+    return $activityId;
+  }
+
+  /**
+   * @return \Civi\Api4\Generic\Result
+   */
+  private function getParticipants(): Civi\Api4\Generic\Result {
+    $participants = array();
+    if ($this->_eventId) {
+      try {
+        $participants =  \Civi\Api4\Participant::get(FALSE)
+          ->addSelect('id', 'contact_id', 'register_date')
+          ->addWhere('event_id', '=', $this->_eventId)
+          ->execute();
+      }
+      catch (\CRM_Core_Exception $ex) {
+      }
+    }
+    return $participants;
+  }
+
+  /**
+   * @return void
+   */
+  private function setCampaignId(): void {
+    try {
+      $campaign = \Civi\Api4\Campaign::get(FALSE)
+        ->addSelect('id')
+        ->addWhere('title', '=', 'Bestelling affiches Iran Ahmadreza Djalali 2023')
+        ->execute()->first();
+      if ($campaign['id']) {
+        $this->_campaignId = $campaign['id'];
+      }
+    }
+    catch (\CRM_Core_Exception $ex) {
+    }
+  }
+
+  /**
+   * @return void
+   */
+  private function setEventId(): void {
+    try {
+      $event = \Civi\Api4\Event::get(FALSE)
+        ->addSelect('id')
+        ->addWhere('title', '=', 'Bestelling affiches Iran Ahmadreza Djalali 2023')
+        ->execute()->first();
+      if ($event['id']) {
+        $this->_eventId = $event['id'];
+      }
+    }
+    catch (\CRM_Core_Exception $ex) {
+    }
+  }
+
+  /**
+   * @return void
+   */
+  private function setActivityType(): void {
+    $this->_activityType = "generic_website_form";
+  }
+
+  /**
+   * @return void
+   */
+  private function setAffiches(): void {
+    $this->_a2Origin = "Affiche A2 formaat (42cm / 59cm)";
+    $this->_a3Origin = "Affiche A3 formaat (30cm / 42cm)";
+    $this->_a2New = "Affiche A2";
+    $this->_a3New = "Affiche A3";
+  }
+
+  /**
+   * @return void
+   */
+  private function setAivlWebsite(): void {
+    try {
+      $contact = \Civi\Api4\Contact::get(FALSE)
+        ->addSelect('id')
+        ->addWhere('contact_type', '=', 'Organization')
+        ->addWhere('display_name', 'CONTAINS', '%AIVL website%')
+        ->addWhere('api_key', 'IS NOT NULL')
+        ->execute()->first();
+      if (isset($contact['id'])) {
+        $this->_aivlWebsite = $contact['id'];
+      }
+    }
+    catch (\CRM_Core_Exception $ex) {
+    }
+  }
+
+}
diff --git a/CRM/Corrections/RrnTag.php b/CRM/Corrections/RrnTag.php
deleted file mode 100644
index 56efe23..0000000
--- a/CRM/Corrections/RrnTag.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-/**
- * Class for recalculating the RRN tag
- *
- * @author Erik Hommel (CiviCooP) <erik.hommel@civicoop.org>
- * @date 2 Oct 2024
- * @license AGPL-3.0
- */
-class CRM_Corrections_RrnTag {
-  public function fixPast(): void {
-    if (class_exists('CRM_Besensitive_BAO_BeSensitive')) {
-      $service = besensitive_get_service();
-      $this->initializeSetting();
-      $contactIds = $this->getContactIdsToCheck();
-      if (empty($contactIds)) {
-        CRM_Core_DAO::executeQuery("DELETE FROM civicrm_setting WHERE name = %1", [1 => ["aivl_temp_max_contact_id", "String"]]);
-        CRM_Core_Session::setStatus("All contacts checked for Rijksregisternummer", "Complete", "success");
-        return;
-      }
-      $count = 0;
-      foreach ($contactIds as $contactId) {
-        $count++;
-        if ($contactId && $service->isIndividual($contactId) && CRM_Besensitive_BAO_BeSensitive::isEnough($contactId)) {
-          if (!CRM_Besensitive_BAO_BeSensitive::hasRijksregisternummer($contactId)) {
-            CRM_Besensitive_BAO_BeSensitive::addRijksregisternummerTag($contactId);
-          }
-          else {
-            CRM_Besensitive_BAO_BeSensitive::removeGeenRijksregisternummerTag($contactId);
-          }
-        }
-        else {
-          CRM_Besensitive_BAO_BeSensitive::removeGeenRijksregisternummerTag($contactId);
-        }
-      }
-      CRM_Core_Session::setStatus($count . " contacts checked for Rijksregisternummer", "Complete", "success");
-    }
-  }
-
-  /**
-   * Method to get all the contributions in 2024
-   *
-   * @return array
-   */
-  private function getContactIdsToCheck(): array {
-    $contactIds = [];
-    $last = 0;
-    try {
-      $contributions = \Civi\Api4\Contribution::get(TRUE)
-        ->addSelect('contact_id', 'receive_date')
-        ->addWhere('receive_date', '>', '2023-12-31')
-        ->addWhere('contact_id', '>', \Civi::settings()->get('aivl_temp_max_contact_id'))
-        ->addOrderBy('contact_id', 'ASC')
-        ->setLimit(5000)
-        ->execute();
-      foreach ($contributions as $contribution) {
-        $last = $contribution['contact_id'];
-        if (!isset($contactIds[$contribution['contact_id']])) {
-          $contactIds[] = $contribution['contact_id'];
-        }
-      }
-      \Civi::settings()->set('aivl_temp_max_contact_id', $last);
-    }
-    catch (\API_Exception $ex) {
-    }
-    return $contactIds;
-  }
-
-  /**
-   * Method to initialize setting
-   *
-   * @return void
-   * @throws \Civi\Core\Exception\DBQueryException
-   */
-  private function initializeSetting(): void {
-    $query = "SELECT COUNT(*) FROM civicrm_setting WHERE name = %1";
-    $count = CRM_Core_DAO::executeQuery($query, [1 => ["aivl_temp_max_contact_id", "String"]]);
-    if ($count == 0) {
-      \Civi::settings()->set('aivl_temp_max_contact_id', 0);
-    }
-  }
-
-}
diff --git a/CRM/Corrections/Upgrader.php b/CRM/Corrections/Upgrader.php
new file mode 100644
index 0000000..144519b
--- /dev/null
+++ b/CRM/Corrections/Upgrader.php
@@ -0,0 +1,53 @@
+<?php
+
+use CRM_Corrections_ExtensionUtil as E;
+
+/**
+ * Collection of upgrade steps.
+ */
+class CRM_Corrections_Upgrader extends CRM_Extension_Upgrader_Base {
+
+  /**
+   * Create scheduled job to fix event for posters
+   */
+  public function postInstall(): void {
+    $this->addScheduledJob();
+  }
+
+  /**
+   * Method to add the scheduled job for cleanup log
+   *
+   * @return void
+   */
+  private function addScheduledJob(): void {
+    try {
+      $query = 'SELECT COUNT(*) FROM civicrm_job WHERE api_action = %1 AND api_entity = %2';
+      $queryParams = [
+        1 => ['fixevent', "String"],
+        2 => ['Posters', "String"],
+      ];
+      $count = CRM_Core_DAO::singleValueQuery($query, $queryParams);
+      if ($count == 0) {
+        try {
+          $scheduled = \Civi\Api4\Job::create(TRUE)
+            ->addValue('run_frequency','Monthly')
+            ->addValue('name', 'djalali_poster_fix')
+            ->addValue('api_entity', 'Posters')
+            ->addValue('api_action', 'fixevent')
+            ->addValue('is_active', FALSE)
+            ->execute();
+        }
+        catch (\CRM_Core_Exception $ex) {
+        }
+      }
+      else {
+        // make sure job is active
+        $update = "UPDATE civicrm_job SET is_active = TRUE WHERE api_action = %1 AND api_entity = %2";
+        CRM_Core_DAO::executeQuery($update, $queryParams);
+      }
+    }
+    catch (\CRM_Core_Exception $ex) {
+    }
+  }
+
+}
diff --git a/api/v3/Posters/Fixevent.php b/api/v3/Posters/Fixevent.php
new file mode 100644
index 0000000..1ec8c10
--- /dev/null
+++ b/api/v3/Posters/Fixevent.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Posters.Fixevent API
+ *
+ * @param array $params
+ *
+ * @return array
+ *   API result descriptor
+ *
+ * @see civicrm_api3_create_success
+ *
+ * @throws API_Exception
+ */
+function civicrm_api3_posters_Fixevent($params) {
+  $poster = new CRM_Corrections_Poster();
+  $poster->fixEvent();
+
+  return civicrm_api3_create_success([], $params, 'Posters', 'Fixevent');
+}
diff --git a/api/v3/RrnTag/Fixpast.php b/api/v3/RrnTag/Fixpast.php
deleted file mode 100644
index 2d5b8fd..0000000
--- a/api/v3/RrnTag/Fixpast.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-use CRM_Corrections_ExtensionUtil as E;
-
-/**
- * RrnTag.Fixpast API
- *
- * @param array $params
- *
- * @return array
- *   API result descriptor
- *
- * @see civicrm_api3_create_success
- *
- * @throws API_Exception
- */
-function civicrm_api3_rrn_tag_Fixpast($params) {
-  $rrn = new CRM_Corrections_RrnTag();
-  $rrn->fixPast();
-  return civicrm_api3_create_success([], $params, 'RrnTag', 'Fixpast');
-}
diff --git a/info.xml b/info.xml
index 8baff8d..83116ca 100755
--- a/info.xml
+++ b/info.xml
@@ -14,13 +14,13 @@
     <url desc="Support">https://www.civicoop.org</url>
     <url desc="Licensing">http://www.gnu.org/licenses/agpl-3.0.html</url>
   </urls>
-  <releaseDate>2024-10-02</releaseDate>
-  <version>1.9</version>
-  <develStage>beta</develStage>
+  <releaseDate>2024-12-12</releaseDate>
+  <version>1.10</version>
+  <develStage>stable</develStage>
   <compatibility>
-    <ver>5.7</ver>
+    <ver>5.38</ver>
   </compatibility>
-  <comments>To be used by developers only</comments>
+  <comments>To be used by developers only specific for AIVL</comments>
   <civix>
     <namespace>CRM/Corrections</namespace>
     <format>23.02.1</format>
@@ -29,4 +29,5 @@
     <psr0 prefix="CRM_" path="."/>
     <psr4 prefix="Civi\" path="Civi"/>
   </classloader>
+  <upgrader>CRM_Corrections_Upgrader</upgrader>
 </extension>
-- 
GitLab