diff --git a/galette/lib/Galette/Repository/Reminders.php b/galette/lib/Galette/Repository/Reminders.php index 17e0fea9d..be1266e96 100644 --- a/galette/lib/Galette/Repository/Reminders.php +++ b/galette/lib/Galette/Repository/Reminders.php @@ -21,11 +21,14 @@ namespace Galette\Repository; +use DateTime; use Galette\Core\Db; use Galette\Entity\Reminder; use Galette\Filters\MembersList; use Analog\Analog; use Laminas\Db\Sql\Expression; +use Laminas\Db\Sql\Select; +use Throwable; /** * Reminders @@ -38,6 +41,8 @@ class Reminders public const TABLE = 'reminders'; public const PK = 'reminder_id'; + private Db $zdb; + /** @var array */ private array $selected; /** @var array */ @@ -57,6 +62,218 @@ public function __construct(array $selected = null) } } + /** + * Load late members + * + * @param boolean $nomail Get reminders for members who do not have email address + * + * @return void + */ + private function loadLate(bool $nomail = false): void + { + $select = $this->getQuery(Reminder::LATE); + + $now = new \DateTime(); + $select->where->LessThan( + 'a.date_echeance', + $now->format('Y-m-d') + ); + + $limit_date = $this->getLimitDate(); + $results = $this->zdb->execute($select); + foreach ($results as $r) { + /*if ($r->last_reminder !== null && $r->last_reminder != '') { + $last_reminder = new \DateTime($r->last_reminder); + if ($limit_date >= $last_reminder) { + //last reminder has been sent too long ago, must be ignored + $r->reminder_type = $type; + $r->last_reminder = ''; + } + }*/ + + /*if ($r->reminder_type < $type) { + //sent impending, but is now late. reset last remind. + $r->reminder_type = $type; + $r->last_reminder = ''; + }*/ + + $date_checked = false; + + $due_date = new \DateTime($r->date_echeance); + + //reminders 30 days and 60 days after + $first = clone $due_date; + $second = clone $due_date; + $first->modify('+30 days'); + $second->modify('+60 days'); + if ($now >= $first || $now >= $second) { + if ($r->last_reminder === null || $r->last_reminder == '') { + $date_checked = true; + } else { + $last_reminder = new \DateTime($r->last_reminder); + if ($now >= $second && $last_reminder >= $limit_date && $second > $last_reminder) { + $date_checked = true; + } + } + } + + if ($date_checked) { + $pk = Members::PK; + $this->toremind[Reminder::LATE][] = $r->$pk; + } + } + } + + /** + * Load late members + * + * @param boolean $nomail Get reminders for members who do not have email address + * + * @return void + */ + private function loadImpendings(bool $nomail = false): void + { + $select = $this->getQuery(Reminder::IMPENDING); + + $now = new \DateTime(); + $due_date = clone $now; + $due_date->modify('+30 days'); + + $select->where->greaterThanOrEqualTo( + 'a.date_echeance', + $now->format('Y-m-d') + )->lessThanOrEqualTo( + 'a.date_echeance', + $due_date->format('Y-m-d') + ); + + $select->where->notIn('a.id_adh', $this->toremind[Reminder::LATE]); + + $limit_date = $this->getLimitDate(); + $results = $this->zdb->execute($select); + foreach ($results as $r) { + /*if ($r->last_reminder !== null && $r->last_reminder != '') { + $last_reminder = new \DateTime($r->last_reminder); + if ($limit_date >= $last_reminder) { + //last reminder has been sent too long ago, must be ignored + $r->reminder_type = $type; + $r->last_reminder = ''; + } + }*/ + + /*if ($r->reminder_type < $type) { + //sent impending, but is now late. reset last remind. + $r->reminder_type = $type; + $r->last_reminder = ''; + }*/ + + $date_checked = false; + + $due_date = new DateTime($r->date_echeance); + + //reminders 30 days and 7 days before + $first = clone $due_date; + $second = clone $due_date; + $first->modify('-30 days'); + $second->modify('-7 days'); + if ($now >= $first || $now >= $second) { + if ($r->last_reminder === null || $r->last_reminder == '') { + $date_checked = true; + } else { + $last_reminder = new DateTime($r->last_reminder); + if ($now >= $second && $last_reminder >= $limit_date && $second > $last_reminder) { + $date_checked = true; + } + } + } + + if ($date_checked) { + $pk = Members::PK; + $this->toremind[Reminder::IMPENDING][] = $r->$pk; + } + } + } + + /** + * Build query + * + * @param integer $type Reminder type + * @param boolean $nomail Get reminders for members who do not have email address + * + * @return Select + */ + private function getQuery(int $type, bool $nomail = false): Select + { + $select = $this->zdb->select(Members::TABLE, 'a'); + $select->columns([Members::PK, 'date_echeance']); + $select->join( + array('r' => PREFIX_DB . self::TABLE), + 'a.' . Members::PK . '=r.reminder_dest', + array( + 'last_reminder' => new Expression('MAX(reminder_date)') + //'reminder_type' => new Expression('MAX(reminder_type)') + ), + $select::JOIN_LEFT + )->join( + array('parent' => PREFIX_DB . Members::TABLE), + 'a.parent_id=parent.' . Members::PK, + array(), + $select::JOIN_LEFT + ); + + $select->where(['reminder_type' => $type]); + + if ($nomail === false) { + //per default, limit to members who have an email address + $select->where( + '(a.email_adh != \'\' OR a.parent_id IS NOT NULL AND parent.email_adh != \'\')' + ); + } else { + $select->where( + '(a.email_adh = \'\' OR a.email_adh IS NULL) AND (parent.email_adh = \'\' OR parent.email_adh IS NULL)' + ); + } + + $select->where('a.activite_adh=true') + ->where('a.bool_exempt_adh=false'); + + $select->group('a.id_adh'); + + return $select; + } + + /** + * Get limit date calculated from preferences + * + * @return DateTime + * @throws Throwable + */ + private function getLimitDate(): DateTime + { + global $preferences; + + $limit_now = new \DateTime(); + $limit_now->setTime(23, 59, 59); + if ($preferences->pref_beg_membership != '') { + //case beginning of membership + list($j, $m) = explode('/', $preferences->pref_beg_membership); + $limit_date = new \DateTime($limit_now->format('Y') . '-' . $m . '-' . $j); + while ($limit_now <= $limit_date) { + $limit_date->sub(new \DateInterval('P1Y')); + } + } elseif ($preferences->pref_membership_ext != '') { + //case membership extension + $limit_date = clone $limit_now; + $limit_date->sub(new \DateInterval('P' . $preferences->pref_membership_ext . 'M')); + } else { + throw new \RuntimeException( + 'Unable to define end date; none of pref_beg_membership nor pref_membership_ext are defined!' + ); + } + + return $limit_date; + } + /** * Load reminders * @@ -225,10 +442,41 @@ private function loadToRemind(Db $zdb, int $type, bool $nomail = false): void */ public function getList(Db $zdb, bool $nomail = false): array { + $this->zdb = $zdb; + $this->toremind = [ + Reminder::IMPENDING => [], + Reminder::LATE => [] + ]; + $types = array(); $reminders = array(); + $m = new Members(); + + $this->loadLate($nomail); + $members = $m->getArrayList( + $this->toremind[Reminder::LATE], + null, + false, + true, + null, + false, + true + ); + $types[Reminder::LATE] = $members; - foreach ($this->selected as $s) { + $this->loadImpendings($nomail); + $members = $m->getArrayList( + $this->toremind[Reminder::IMPENDING], + null, + false, + true, + null, + false, + true + ); + $types[Reminder::IMPENDING] = $members; + + /*foreach ($this->selected as $s) { $this->loadToRemind($zdb, $s, $nomail); if (count($this->toremind) > 0) { @@ -245,7 +493,7 @@ public function getList(Db $zdb, bool $nomail = false): array ); $types[$s] = $members; } - } + }*/ if (is_array($types)) { foreach ($types as $type => $members) { @@ -261,6 +509,7 @@ public function getList(Db $zdb, bool $nomail = false): array } } } + return $reminders; } }