Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
39de6fd5 | 4 | | CiviCRM version 4.6 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
06b69b18 | 6 | | Copyright CiviCRM LLC (c) 2004-2014 | |
6a488035 TO |
7 | +--------------------------------------------------------------------+ |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
d25dd0ee | 26 | */ |
6a488035 TO |
27 | |
28 | /** | |
29 | * | |
30 | * @package CRM | |
06b69b18 | 31 | * @copyright CiviCRM LLC (c) 2004-2014 |
6a488035 TO |
32 | * $Id$ |
33 | * | |
34 | */ | |
35 | class CRM_Member_BAO_MembershipType extends CRM_Member_DAO_MembershipType { | |
36 | ||
37 | /** | |
4c429c82 | 38 | * Static holder for the default Membership Type. |
6a488035 TO |
39 | */ |
40 | static $_defaultMembershipType = NULL; | |
41 | ||
42 | static $_membershipTypeInfo = array(); | |
43 | ||
44 | /** | |
4c429c82 | 45 | * Class constructor. |
6a488035 | 46 | */ |
00be9182 | 47 | public function __construct() { |
6a488035 TO |
48 | parent::__construct(); |
49 | } | |
50 | ||
51 | /** | |
4c429c82 | 52 | * Fetch object based on array of properties. |
6a488035 | 53 | * |
b2363ea8 TO |
54 | * @param array $params |
55 | * (reference ) an assoc array of name/value pairs. | |
56 | * @param array $defaults | |
57 | * (reference ) an assoc array to hold the flattened values. | |
6a488035 | 58 | * |
16b10e64 | 59 | * @return CRM_Member_BAO_MembershipType |
6a488035 | 60 | */ |
00be9182 | 61 | public static function retrieve(&$params, &$defaults) { |
6a488035 TO |
62 | $membershipType = new CRM_Member_DAO_MembershipType(); |
63 | $membershipType->copyValues($params); | |
64 | if ($membershipType->find(TRUE)) { | |
65 | CRM_Core_DAO::storeValues($membershipType, $defaults); | |
66 | return $membershipType; | |
67 | } | |
68 | return NULL; | |
69 | } | |
70 | ||
71 | /** | |
4c429c82 | 72 | * Update the is_active flag in the db. |
6a488035 | 73 | * |
b2363ea8 TO |
74 | * @param int $id |
75 | * Id of the database record. | |
76 | * @param bool $is_active | |
77 | * Value we want to set the is_active field. | |
6a488035 | 78 | * |
a6c01b45 | 79 | * @return Object |
87ad884a | 80 | * DAO object on success, null otherwise |
6a488035 | 81 | */ |
00be9182 | 82 | public static function setIsActive($id, $is_active) { |
6a488035 TO |
83 | return CRM_Core_DAO::setFieldValue('CRM_Member_DAO_MembershipType', $id, 'is_active', $is_active); |
84 | } | |
85 | ||
86 | /** | |
4c429c82 | 87 | * Add the membership types. |
6a488035 | 88 | * |
b2363ea8 TO |
89 | * @param array $params |
90 | * Reference array contains the values submitted by the form. | |
91 | * @param array $ids | |
92 | * Array contains the id (deprecated). | |
6a488035 | 93 | * |
6a488035 TO |
94 | * |
95 | * @return object | |
96 | */ | |
00be9182 | 97 | public static function add(&$params, $ids = array()) { |
36e3b794 EM |
98 | $id = CRM_Utils_Array::value('id', $params, CRM_Utils_Array::value('membershipType', $ids)); |
99 | if (!$id) { | |
100 | if (!isset($params['is_active'])) { | |
101 | // do we need this? | |
102 | $params['is_active'] = FALSE; | |
103 | } | |
104 | if (!isset($params['domain_id'])) { | |
105 | $params['domain_id'] = CRM_Core_Config::domainID(); | |
106 | } | |
107 | } | |
6a488035 TO |
108 | |
109 | // action is taken depending upon the mode | |
110 | $membershipType = new CRM_Member_DAO_MembershipType(); | |
6a488035 | 111 | $membershipType->copyValues($params); |
36e3b794 | 112 | $membershipType->id = $id; |
6a488035 | 113 | |
301db4f8 | 114 | // $previousID is the old organization id for membership type i.e 'member_of_contact_id'. This is used when an organization is changed. |
6a488035 | 115 | $previousID = NULL; |
806e9b71 EM |
116 | if ($id) { |
117 | $previousID = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $id, 'member_of_contact_id'); | |
6a488035 TO |
118 | } |
119 | ||
120 | $membershipType->save(); | |
806e9b71 EM |
121 | if ($id) { |
122 | // on update we may need to retrieve some details for the price field function - otherwise we get e-notices on attempts to retrieve | |
123 | // name etc - the presence of previous id tells us this is an update | |
124 | $params = array_merge(civicrm_api3('membership_type', 'getsingle', array('id' => $membershipType->id)), $params); | |
125 | } | |
301db4f8 | 126 | self::createMembershipPriceField($params, $previousID, $membershipType->id); |
6a488035 | 127 | // update all price field value for quick config when membership type is set CRM-11718 |
36e3b794 EM |
128 | if ($id) { |
129 | self::updateAllPriceFieldValue($id, $params); | |
6a488035 | 130 | } |
452b9e04 | 131 | self::flush(); |
6a488035 TO |
132 | return $membershipType; |
133 | } | |
134 | ||
452b9e04 | 135 | /** |
4c429c82 EM |
136 | * Flush anywhere that membership types might be cached. |
137 | * | |
452b9e04 EM |
138 | * @throws \CiviCRM_API3_Exception |
139 | */ | |
c8881afb | 140 | public static function flush() { |
452b9e04 EM |
141 | CRM_Member_PseudoConstant::membershipType(NULL, TRUE); |
142 | civicrm_api3('membership', 'getfields', array('cache_clear' => 1, 'fieldname' => 'membership_type_id')); | |
143 | civicrm_api3('profile', 'getfields', array('action' => 'submit', 'cache_clear' => 1)); | |
144 | } | |
145 | ||
6a488035 | 146 | /** |
4c429c82 | 147 | * Delete membership Types. |
6a488035 TO |
148 | * |
149 | * @param int $membershipTypeId | |
77b97be7 EM |
150 | * |
151 | * @throws CRM_Core_Exception | |
152 | * @return bool|mixed | |
6a488035 | 153 | */ |
00be9182 | 154 | public static function del($membershipTypeId) { |
4c429c82 | 155 | // Check dependencies. |
353ffa53 TO |
156 | $check = FALSE; |
157 | $status = array(); | |
edc9b94e | 158 | $dependency = array( |
6a488035 TO |
159 | 'Membership' => 'membership_type_id', |
160 | 'MembershipBlock' => 'membership_type_default', | |
161 | ); | |
162 | ||
edc9b94e | 163 | foreach ($dependency as $name => $field) { |
4d5c2eb5 | 164 | $baoString = 'CRM_Member_BAO_' . $name; |
165 | $dao = new $baoString(); | |
6a488035 | 166 | $dao->$field = $membershipTypeId; |
b204fd50 | 167 | /** @noinspection PhpUndefinedMethodInspection */ |
6a488035 TO |
168 | if ($dao->find(TRUE)) { |
169 | $check = TRUE; | |
170 | $status[] = $name; | |
171 | } | |
172 | } | |
173 | if ($check) { | |
6a488035 TO |
174 | $cnt = 1; |
175 | $message = ts('This membership type cannot be deleted due to following reason(s):'); | |
176 | if (in_array('Membership', $status)) { | |
d6d6bc96 DG |
177 | $findMembersURL = CRM_Utils_System::url('civicrm/member/search', 'reset=1'); |
178 | $deleteURL = CRM_Utils_System::url('civicrm/contact/search/advanced', 'reset=1'); | |
353ffa53 TO |
179 | $message .= '<br/>' . ts('%3. There are some contacts who have this membership type assigned to them. Search for contacts with this membership type from <a href=\'%1\'>Find Members</a>. If you are still getting this message after deleting these memberships, there may be contacts in the Trash (deleted) with this membership type. Try using <a href="%2">Advanced Search</a> and checking "Search in Trash".', array( |
180 | 1 => $findMembersURL, | |
181 | 2 => $deleteURL, | |
5396af74 | 182 | 3 => $cnt, |
353ffa53 | 183 | )); |
6a488035 TO |
184 | $cnt++; |
185 | } | |
186 | ||
187 | if (in_array('MembershipBlock', $status)) { | |
188 | $deleteURL = CRM_Utils_System::url('civicrm/admin/contribute', 'reset=1'); | |
353ffa53 TO |
189 | $message .= ts('%2. This Membership Type is used in an <a href=\'%1\'>Online Contribution page</a>. Uncheck this membership type in the Memberships tab.', array( |
190 | 1 => $deleteURL, | |
5396af74 | 191 | 2 => $cnt, |
353ffa53 | 192 | )); |
dcc4f6a7 | 193 | throw new CRM_Core_Exception($message); |
6a488035 TO |
194 | } |
195 | } | |
dcc4f6a7 | 196 | CRM_Utils_Weight::delWeight('CRM_Member_DAO_MembershipType', $membershipTypeId); |
6a488035 TO |
197 | //delete from membership Type table |
198 | $membershipType = new CRM_Member_DAO_MembershipType(); | |
199 | $membershipType->id = $membershipTypeId; | |
200 | ||
201 | //fix for membership type delete api | |
202 | $result = FALSE; | |
203 | if ($membershipType->find(TRUE)) { | |
8c33a68c | 204 | return $membershipType->delete(); |
6a488035 TO |
205 | } |
206 | ||
207 | return $result; | |
208 | } | |
209 | ||
210 | /** | |
4c429c82 | 211 | * Convert membership type's 'start day' & 'rollover day' to human readable formats. |
6a488035 | 212 | * |
b2363ea8 TO |
213 | * @param array $membershipType |
214 | * An array of membershipType-details. | |
6a488035 | 215 | */ |
00be9182 | 216 | public static function convertDayFormat(&$membershipType) { |
6a488035 TO |
217 | $periodDays = array( |
218 | 'fixed_period_start_day', | |
219 | 'fixed_period_rollover_day', | |
220 | ); | |
221 | foreach ($membershipType as $id => $details) { | |
222 | foreach ($periodDays as $pDay) { | |
a7488080 | 223 | if (!empty($details[$pDay])) { |
6a488035 | 224 | if ($details[$pDay] > 31) { |
353ffa53 TO |
225 | $month = substr($details[$pDay], 0, strlen($details[$pDay]) - 2); |
226 | $day = substr($details[$pDay], -2); | |
6a488035 TO |
227 | $monthMap = array( |
228 | '1' => 'Jan', | |
229 | '2' => 'Feb', | |
230 | '3' => 'Mar', | |
231 | '4' => 'Apr', | |
232 | '5' => 'May', | |
233 | '6' => 'Jun', | |
234 | '7' => 'Jul', | |
235 | '8' => 'Aug', | |
236 | '9' => 'Sep', | |
237 | '10' => 'Oct', | |
238 | '11' => 'Nov', | |
239 | '12' => 'Dec', | |
240 | ); | |
241 | $membershipType[$id][$pDay] = $monthMap[$month] . ' ' . $day; | |
242 | } | |
243 | else { | |
244 | $membershipType[$id][$pDay] = $details[$pDay]; | |
245 | } | |
246 | } | |
247 | } | |
248 | } | |
249 | } | |
250 | ||
251 | /** | |
4c429c82 | 252 | * Get membership Types. |
6a488035 | 253 | * |
77b97be7 EM |
254 | * @param bool $public |
255 | * | |
256 | * @return array | |
6a488035 | 257 | */ |
00be9182 | 258 | public static function getMembershipTypes($public = TRUE) { |
6a488035 TO |
259 | $membershipTypes = array(); |
260 | $membershipType = new CRM_Member_DAO_MembershipType(); | |
261 | $membershipType->is_active = 1; | |
262 | if ($public) { | |
263 | $membershipType->visibility = 'Public'; | |
264 | } | |
265 | $membershipType->orderBy(' weight'); | |
266 | $membershipType->find(); | |
267 | while ($membershipType->fetch()) { | |
268 | $membershipTypes[$membershipType->id] = $membershipType->name; | |
269 | } | |
270 | $membershipType->free(); | |
271 | return $membershipTypes; | |
272 | } | |
273 | ||
274 | /** | |
4c429c82 | 275 | * Get membership Type Details. |
6a488035 TO |
276 | * |
277 | * @param int $membershipTypeId | |
77b97be7 EM |
278 | * |
279 | * @return array|null | |
6a488035 | 280 | */ |
00be9182 | 281 | public static function getMembershipTypeDetails($membershipTypeId) { |
6a488035 TO |
282 | $membershipTypeDetails = array(); |
283 | ||
284 | $membershipType = new CRM_Member_DAO_MembershipType(); | |
285 | $membershipType->is_active = 1; | |
286 | $membershipType->id = $membershipTypeId; | |
287 | if ($membershipType->find(TRUE)) { | |
288 | CRM_Core_DAO::storeValues($membershipType, $membershipTypeDetails); | |
289 | $membershipType->free(); | |
290 | return $membershipTypeDetails; | |
291 | } | |
292 | else { | |
293 | return NULL; | |
294 | } | |
295 | } | |
296 | ||
297 | /** | |
4c429c82 | 298 | * Calculate start date and end date for new membership. |
6a488035 | 299 | * |
b2363ea8 TO |
300 | * @param int $membershipTypeId |
301 | * Membership type id. | |
87ad884a | 302 | * @param string $joinDate |
b2363ea8 | 303 | * Member since ( in mysql date format ). |
87ad884a | 304 | * @param string $startDate |
b2363ea8 | 305 | * Start date ( in mysql date format ). |
da6b46f4 | 306 | * @param null $endDate |
b2363ea8 TO |
307 | * @param int $numRenewTerms |
308 | * How many membership terms are being added to end date (default is 1). | |
6a488035 | 309 | * |
a6c01b45 CW |
310 | * @return array |
311 | * associated array with start date, end date and join date for the membership | |
6a488035 TO |
312 | */ |
313 | public static function getDatesForMembershipType($membershipTypeId, $joinDate = NULL, $startDate = NULL, $endDate = NULL, $numRenewTerms = 1) { | |
314 | $membershipTypeDetails = self::getMembershipTypeDetails($membershipTypeId); | |
315 | ||
4c429c82 | 316 | // Convert all dates to 'Y-m-d' format. |
6a488035 | 317 | foreach (array( |
353ffa53 TO |
318 | 'joinDate', |
319 | 'startDate', | |
5396af74 | 320 | 'endDate', |
353ffa53 | 321 | ) as $dateParam) { |
6a488035 TO |
322 | if (!empty($$dateParam)) { |
323 | $$dateParam = CRM_Utils_Date::processDate($$dateParam, NULL, FALSE, 'Y-m-d'); | |
324 | } | |
325 | } | |
326 | if (!$joinDate) { | |
327 | $joinDate = date('Y-m-d'); | |
328 | } | |
329 | $actualStartDate = $joinDate; | |
330 | if ($startDate) { | |
331 | $actualStartDate = $startDate; | |
332 | } | |
333 | ||
334 | $fixed_period_rollover = FALSE; | |
335 | if (CRM_Utils_Array::value('period_type', $membershipTypeDetails) == 'rolling') { | |
336 | if (!$startDate) { | |
337 | $startDate = $joinDate; | |
338 | } | |
339 | $actualStartDate = $startDate; | |
340 | } | |
341 | elseif (CRM_Utils_Array::value('period_type', $membershipTypeDetails) == 'fixed') { | |
5ae96933 DG |
342 | // calculate start date |
343 | // if !$startDate then use $joinDate | |
344 | $toDay = explode('-', (empty($startDate) ? $joinDate : $startDate)); | |
6a488035 TO |
345 | $year = $toDay[0]; |
346 | $month = $toDay[1]; | |
f7660a39 | 347 | $day = $toDay[2]; |
6a488035 TO |
348 | |
349 | if ($membershipTypeDetails['duration_unit'] == 'year') { | |
350 | ||
351 | //get start fixed day | |
352 | $startMonth = substr($membershipTypeDetails['fixed_period_start_day'], 0, | |
353 | strlen($membershipTypeDetails['fixed_period_start_day']) - 2 | |
354 | ); | |
355 | $startDay = substr($membershipTypeDetails['fixed_period_start_day'], -2); | |
356 | ||
f7660a39 | 357 | if (date('Y-m-d', mktime(0, 0, 0, $startMonth, $startDay, $year)) <= date('Y-m-d', mktime(0, 0, 0, $month, $day, $year))) { |
4c429c82 | 358 | $actualStartDate = date('Y-m-d', mktime(0, 0, 0, $startMonth, $startDay, $year)); |
f7660a39 DG |
359 | } |
360 | else { | |
4c429c82 | 361 | $actualStartDate = date('Y-m-d', mktime(0, 0, 0, $startMonth, $startDay, $year - 1)); |
f7660a39 | 362 | } |
82d11b3f | 363 | |
4c429c82 | 364 | $fixed_period_rollover = self::isDuringFixedAnnualRolloverPeriod($joinDate, $membershipTypeDetails, $year, $actualStartDate); |
6a488035 TO |
365 | |
366 | if (!$startDate) { | |
367 | $startDate = $actualStartDate; | |
368 | } | |
369 | } | |
370 | elseif ($membershipTypeDetails['duration_unit'] == 'month') { | |
371 | // Check if we are on or after rollover day of the month - CRM-10585 | |
372 | // If so, set fixed_period_rollover TRUE so we increment end_date month below. | |
373 | $dateParts = explode('-', $actualStartDate); | |
9b873358 | 374 | if ($dateParts[2] >= $membershipTypeDetails['fixed_period_rollover_day']) { |
b09fe5ed | 375 | $fixed_period_rollover = TRUE; |
6a488035 | 376 | } |
03e04002 | 377 | |
6a488035 TO |
378 | // Start date is always first day of actualStartDate month |
379 | if (!$startDate) { | |
380 | $actualStartDate = $startDate = $year . '-' . $month . '-01'; | |
381 | } | |
382 | } | |
383 | } | |
384 | ||
4c429c82 | 385 | // Calculate end date if it is not passed by user. |
6a488035 TO |
386 | if (!$endDate) { |
387 | //end date calculation | |
353ffa53 TO |
388 | $date = explode('-', $actualStartDate); |
389 | $year = $date[0]; | |
6a488035 | 390 | $month = $date[1]; |
353ffa53 | 391 | $day = $date[2]; |
6a488035 TO |
392 | |
393 | switch ($membershipTypeDetails['duration_unit']) { | |
394 | case 'year': | |
395 | $year = $year + ($numRenewTerms * $membershipTypeDetails['duration_interval']); | |
396 | //extend membership date by duration interval. | |
397 | if ($fixed_period_rollover) { | |
398 | $year += 1; | |
399 | } | |
400 | break; | |
401 | ||
402 | case 'month': | |
403 | $month = $month + ($numRenewTerms * $membershipTypeDetails['duration_interval']); | |
404 | //duration interval is month | |
405 | if ($fixed_period_rollover) { | |
406 | //CRM-10585 | |
407 | $month += 1; | |
408 | } | |
409 | break; | |
410 | ||
411 | case 'day': | |
412 | $day = $day + ($numRenewTerms * $membershipTypeDetails['duration_interval']); | |
413 | ||
414 | if ($fixed_period_rollover) { | |
415 | //Fix Me: Currently we don't allow rollover if | |
416 | //duration interval is day | |
417 | } | |
418 | break; | |
419 | } | |
420 | ||
421 | if ($membershipTypeDetails['duration_unit'] == 'lifetime') { | |
422 | $endDate = NULL; | |
423 | } | |
424 | else { | |
425 | $endDate = date('Y-m-d', mktime(0, 0, 0, $month, $day - 1, $year)); | |
426 | } | |
427 | } | |
428 | ||
edc9b94e | 429 | $membershipDates = array( |
c8881afb | 430 | 'start_date' => CRM_Utils_Date::customFormat($startDate, '%Y%m%d'), |
edc9b94e EM |
431 | 'end_date' => CRM_Utils_Date::customFormat($endDate, '%Y%m%d'), |
432 | 'join_date' => CRM_Utils_Date::customFormat($joinDate, '%Y%m%d'), | |
6a488035 | 433 | ); |
6a488035 TO |
434 | |
435 | return $membershipDates; | |
436 | } | |
437 | ||
87ad884a | 438 | /** |
fe482240 | 439 | * Does this membership start between the rollover date and the start of the next period. |
87ad884a EM |
440 | * (in which case they will get an extra membership period) |
441 | * ie if annual memberships run June - May & the rollover is in May memberships between | |
442 | * May and June will return TRUE and between June and May will return FALSE | |
443 | * | |
444 | * @param string $startDate start date of current membership period | |
87ad884a | 445 | * @param array $membershipTypeDetails |
81d97e72 | 446 | * @param int $year |
e9ac29eb | 447 | * @param string $actualStartDate |
87ad884a EM |
448 | * @return bool is this in the window where the membership gets an extra part-period added |
449 | */ | |
e9ac29eb | 450 | protected static function isDuringFixedAnnualRolloverPeriod($startDate, $membershipTypeDetails, $year, $actualStartDate) { |
87ad884a EM |
451 | |
452 | $rolloverMonth = substr($membershipTypeDetails['fixed_period_rollover_day'], 0, | |
453 | strlen($membershipTypeDetails['fixed_period_rollover_day']) - 2 | |
454 | ); | |
455 | $rolloverDay = substr($membershipTypeDetails['fixed_period_rollover_day'], -2); | |
456 | ||
8454b618 | 457 | $calculatedRolloverDate = date('Y-m-d', mktime(0, 0, 0, $rolloverMonth, $rolloverDay, $year)); |
87ad884a EM |
458 | |
459 | //CRM-7825 -membership date rules are : | |
460 | //1. Membership should not be start in future. | |
461 | //2. rollover window should be subset of membership window. | |
462 | ||
87ad884a EM |
463 | //get the fixed end date here. |
464 | $dateParts = explode('-', $actualStartDate); | |
8454b618 | 465 | $endDateOfFirstYearMembershipPeriod = date('Y-m-d', mktime(0, 0, 0, |
87ad884a EM |
466 | $dateParts[1], |
467 | $dateParts[2] - 1, | |
6f1c82f5 | 468 | $dateParts[0] + 1 |
87ad884a EM |
469 | )); |
470 | ||
8454b618 EM |
471 | //we know the month and day of the rollover date but not the year (we're just |
472 | //using the start date year at the moment. So if it's after the end | |
473 | // of the first year of membership then it's the next period & we'll adjust back a year. If it's | |
474 | // before the start_date then it's too early & we'll adjust forward. | |
475 | if ($endDateOfFirstYearMembershipPeriod < $calculatedRolloverDate) { | |
476 | $calculatedRolloverDate = date('Y-m-d', mktime(0, 0, 0, $rolloverMonth, $rolloverDay, $year - 1)); | |
87ad884a | 477 | } |
8454b618 EM |
478 | if ($calculatedRolloverDate < $actualStartDate) { |
479 | $calculatedRolloverDate = date('Y-m-d', mktime(0, 0, 0, $rolloverMonth, $rolloverDay, $year + 1)); | |
87ad884a EM |
480 | } |
481 | ||
8454b618 | 482 | if ($calculatedRolloverDate <= $startDate) { |
87ad884a EM |
483 | return TRUE; |
484 | } | |
485 | return FALSE; | |
486 | } | |
487 | ||
6a488035 | 488 | /** |
fe482240 | 489 | * Calculate start date and end date for renewal membership. |
6a488035 TO |
490 | * |
491 | * @param int $membershipId | |
492 | * @param $changeToday | |
b2363ea8 TO |
493 | * @param int $membershipTypeID |
494 | * If provided, overrides the membership type of the $membershipID membership. | |
495 | * @param int $numRenewTerms | |
496 | * How many membership terms are being added to end date (default is 1). | |
6a488035 TO |
497 | * |
498 | * CRM-7297 Membership Upsell - Added $membershipTypeID param to facilitate calculations of dates when membership type changes | |
499 | * | |
5396af74 | 500 | * @return array |
a6c01b45 | 501 | * array fo the start date, end date and join date of the membership |
6a488035 TO |
502 | */ |
503 | public static function getRenewalDatesForMembershipType($membershipId, $changeToday = NULL, $membershipTypeID = NULL, $numRenewTerms = 1) { | |
353ffa53 | 504 | $params = array('id' => $membershipId); |
6a488035 | 505 | $membershipDetails = CRM_Member_BAO_Membership::getValues($params, $values); |
353ffa53 | 506 | $statusID = $membershipDetails[$membershipId]->status_id; |
01f6b47e CW |
507 | $membershipDates = array( |
508 | 'join_date' => CRM_Utils_Date::customFormat($membershipDetails[$membershipId]->join_date, '%Y%m%d'), | |
509 | ); | |
6a488035 TO |
510 | |
511 | $oldPeriodType = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', | |
353ffa53 | 512 | CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $membershipId, 'membership_type_id'), 'period_type'); |
6a488035 TO |
513 | |
514 | // CRM-7297 Membership Upsell | |
515 | if (is_null($membershipTypeID)) { | |
516 | $membershipTypeDetails = self::getMembershipTypeDetails($membershipDetails[$membershipId]->membership_type_id); | |
517 | } | |
518 | else { | |
519 | $membershipTypeDetails = self::getMembershipTypeDetails($membershipTypeID); | |
520 | } | |
521 | $statusDetails = CRM_Member_BAO_MembershipStatus::getMembershipStatus($statusID); | |
522 | ||
523 | if ($statusDetails['is_current_member'] == 1) { | |
524 | $startDate = $membershipDetails[$membershipId]->start_date; | |
525 | // CRM=7297 Membership Upsell: we need to handle null end_date in case we are switching | |
526 | // from a lifetime to a different membership type | |
527 | if (is_null($membershipDetails[$membershipId]->end_date)) { | |
528 | $date = date('Y-m-d'); | |
529 | } | |
530 | else { | |
531 | $date = $membershipDetails[$membershipId]->end_date; | |
532 | } | |
353ffa53 | 533 | $date = explode('-', $date); |
6a488035 | 534 | $logStartDate = date('Y-m-d', mktime(0, 0, 0, |
353ffa53 TO |
535 | (double) $date[1], |
536 | (double) ($date[2] + 1), | |
537 | (double) $date[0] | |
538 | )); | |
6a488035 | 539 | |
353ffa53 TO |
540 | $date = explode('-', $logStartDate); |
541 | $year = $date[0]; | |
6a488035 | 542 | $month = $date[1]; |
353ffa53 | 543 | $day = $date[2]; |
6a488035 TO |
544 | |
545 | switch ($membershipTypeDetails['duration_unit']) { | |
546 | case 'year': | |
547 | //need to check if the upsell is from rolling to fixed and adjust accordingly | |
481a74f4 | 548 | if ($membershipTypeDetails['period_type'] == 'fixed' && $oldPeriodType == 'rolling') { |
6a488035 TO |
549 | $month = substr($membershipTypeDetails['fixed_period_start_day'], 0, strlen($membershipTypeDetails['fixed_period_start_day']) - 2); |
550 | $day = substr($membershipTypeDetails['fixed_period_start_day'], -2); | |
551 | $year += 1; | |
0db6c3e1 TO |
552 | } |
553 | else { | |
b09fe5ed | 554 | $year = $year + ($numRenewTerms * $membershipTypeDetails['duration_interval']); |
6a488035 TO |
555 | } |
556 | break; | |
557 | ||
558 | case 'month': | |
559 | $month = $month + ($numRenewTerms * $membershipTypeDetails['duration_interval']); | |
560 | break; | |
561 | ||
562 | case 'day': | |
563 | $day = $day + ($numRenewTerms * $membershipTypeDetails['duration_interval']); | |
564 | break; | |
565 | } | |
566 | if ($membershipTypeDetails['duration_unit'] == 'lifetime') { | |
567 | $endDate = NULL; | |
568 | } | |
569 | else { | |
570 | $endDate = date('Y-m-d', mktime(0, 0, 0, | |
353ffa53 TO |
571 | $month, |
572 | $day - 1, | |
573 | $year | |
574 | )); | |
6a488035 TO |
575 | } |
576 | $today = date('Y-m-d'); | |
6a488035 TO |
577 | $membershipDates['today'] = CRM_Utils_Date::customFormat($today, '%Y%m%d'); |
578 | $membershipDates['start_date'] = CRM_Utils_Date::customFormat($startDate, '%Y%m%d'); | |
579 | $membershipDates['end_date'] = CRM_Utils_Date::customFormat($endDate, '%Y%m%d'); | |
580 | $membershipDates['log_start_date'] = CRM_Utils_Date::customFormat($logStartDate, '%Y%m%d'); | |
581 | } | |
582 | else { | |
583 | $today = date('Y-m-d'); | |
584 | if ($changeToday) { | |
585 | $today = CRM_Utils_Date::processDate($changeToday, NULL, FALSE, 'Y-m-d'); | |
586 | } | |
587 | // Calculate new start/end dates when join date is today | |
588 | $renewalDates = self::getDatesForMembershipType($membershipTypeDetails['id'], | |
589 | $today, NULL, NULL, $numRenewTerms | |
590 | ); | |
6a488035 TO |
591 | $membershipDates['today'] = CRM_Utils_Date::customFormat($today, '%Y%m%d'); |
592 | $membershipDates['start_date'] = $renewalDates['start_date']; | |
593 | $membershipDates['end_date'] = $renewalDates['end_date']; | |
594 | $membershipDates['log_start_date'] = $renewalDates['start_date']; | |
595 | } | |
596 | ||
597 | return $membershipDates; | |
598 | } | |
599 | ||
600 | /** | |
fe482240 | 601 | * Retrieve all Membership Types associated. |
6a488035 TO |
602 | * with an Organization |
603 | * | |
b2363ea8 TO |
604 | * @param int $orgID |
605 | * Id of Organization. | |
6a488035 | 606 | * |
5396af74 | 607 | * @return array |
a6c01b45 | 608 | * array of the details of membership types |
6a488035 | 609 | */ |
00be9182 | 610 | public static function getMembershipTypesByOrg($orgID) { |
6a488035 TO |
611 | $membershipTypes = array(); |
612 | $dao = new CRM_Member_DAO_MembershipType(); | |
613 | $dao->member_of_contact_id = $orgID; | |
614 | $dao->find(); | |
615 | while ($dao->fetch()) { | |
616 | $membershipTypes[$dao->id] = array(); | |
617 | CRM_Core_DAO::storeValues($dao, $membershipTypes[$dao->id]); | |
618 | } | |
619 | return $membershipTypes; | |
620 | } | |
621 | ||
622 | /** | |
fe482240 | 623 | * Retrieve all Membership Types with Member of Contact id. |
6a488035 | 624 | * |
5396af74 | 625 | * @param array $membershipTypes |
626 | * array of membership type ids | |
627 | * @return array | |
a6c01b45 | 628 | * array of the details of membership types with Member of Contact id |
6a488035 | 629 | */ |
00be9182 | 630 | public static function getMemberOfContactByMemTypes($membershipTypes) { |
b204fd50 | 631 | $memTypeOrganizations = array(); |
6a488035 | 632 | if (empty($membershipTypes)) { |
b204fd50 | 633 | return $memTypeOrganizations; |
6a488035 TO |
634 | } |
635 | ||
636 | $result = CRM_Core_DAO::executeQuery("SELECT id, member_of_contact_id FROM civicrm_membership_type WHERE id IN (" . implode(',', $membershipTypes) . ")"); | |
637 | while ($result->fetch()) { | |
b204fd50 | 638 | $memTypeOrganizations[$result->id] = $result->member_of_contact_id; |
6a488035 TO |
639 | } |
640 | ||
b204fd50 | 641 | return $memTypeOrganizations; |
6a488035 TO |
642 | } |
643 | ||
77b97be7 | 644 | /** |
87ad884a | 645 | * The function returns all the Organization for all membershipTypes . |
6a488035 | 646 | * |
c490a46a | 647 | * @param int $membershipTypeId |
77b97be7 EM |
648 | * |
649 | * @return array | |
6a488035 | 650 | */ |
00be9182 | 651 | public static function getMembershipTypeOrganization($membershipTypeId = NULL) { |
b204fd50 | 652 | $allMembershipTypes = array(); |
6a488035 TO |
653 | |
654 | $membershipType = new CRM_Member_DAO_MembershipType(); | |
655 | ||
656 | if (isset($membershipTypeId)) { | |
657 | $membershipType->id = $membershipTypeId; | |
658 | } | |
659 | $membershipType->find(); | |
660 | ||
661 | while ($membershipType->fetch()) { | |
b204fd50 | 662 | $allMembershipTypes[$membershipType->id] = $membershipType->member_of_contact_id; |
6a488035 | 663 | } |
b204fd50 | 664 | return $allMembershipTypes; |
6a488035 TO |
665 | } |
666 | ||
667 | /** | |
87ad884a | 668 | * Function to retrieve organization and associated membership |
6a488035 TO |
669 | * types |
670 | * | |
a6c01b45 CW |
671 | * @return array |
672 | * arrays of organization and membership types | |
6a488035 | 673 | * |
6a488035 | 674 | */ |
00be9182 | 675 | public static function getMembershipTypeInfo() { |
6a488035 TO |
676 | if (!self::$_membershipTypeInfo) { |
677 | $orgs = $types = array(); | |
678 | ||
679 | $query = 'SELECT memType.id, memType.name, memType.member_of_contact_id, c.sort_name | |
680 | FROM civicrm_membership_type memType INNER JOIN civicrm_contact c ON c.id = memType.member_of_contact_id | |
681 | WHERE memType.is_active = 1 '; | |
481a74f4 | 682 | $dao = CRM_Core_DAO::executeQuery($query); |
6a488035 TO |
683 | while ($dao->fetch()) { |
684 | $orgs[$dao->member_of_contact_id] = $dao->sort_name; | |
685 | $types[$dao->member_of_contact_id][$dao->id] = $dao->name; | |
686 | } | |
687 | ||
688 | self::$_membershipTypeInfo = array($orgs, $types); | |
689 | } | |
690 | return self::$_membershipTypeInfo; | |
691 | } | |
692 | ||
693 | ||
bb3a214a | 694 | /** |
c490a46a | 695 | * @param array $params |
100fef9d CW |
696 | * @param int $previousID |
697 | * @param int $membershipTypeId | |
bb3a214a | 698 | */ |
301db4f8 | 699 | public static function createMembershipPriceField($params, $previousID, $membershipTypeId) { |
6a488035 | 700 | |
9da8dc8c | 701 | $priceSetId = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', 'default_membership_type_amount', 'id', 'name'); |
6a488035 | 702 | |
a7488080 | 703 | if (!empty($params['member_of_contact_id'])) { |
6a488035 TO |
704 | $fieldName = $params['member_of_contact_id']; |
705 | } | |
706 | else { | |
707 | $fieldName = $previousID; | |
708 | } | |
353ffa53 TO |
709 | $fieldLabel = 'Membership Amount'; |
710 | $optionsIds = NULL; | |
6a488035 TO |
711 | $fieldParams = array( |
712 | 'price_set_id ' => $priceSetId, | |
713 | 'name' => $fieldName, | |
714 | ); | |
715 | $results = array(); | |
9da8dc8c | 716 | CRM_Price_BAO_PriceField::retrieve($fieldParams, $results); |
6a488035 TO |
717 | if (empty($results)) { |
718 | $fieldParams = array(); | |
719 | $fieldParams['label'] = $fieldLabel; | |
720 | $fieldParams['name'] = $fieldName; | |
721 | $fieldParams['price_set_id'] = $priceSetId; | |
722 | $fieldParams['html_type'] = 'Radio'; | |
723 | $fieldParams['is_display_amounts'] = $fieldParams['is_required'] = 0; | |
724 | $fieldParams['weight'] = $fieldParams['option_weight'][1] = 1; | |
725 | $fieldParams['option_label'][1] = $params['name']; | |
0e09eaf5 | 726 | $fieldParams['option_description'][1] = CRM_Utils_Array::value('description', $params); |
03e04002 | 727 | |
6a488035 TO |
728 | $fieldParams['membership_type_id'][1] = $membershipTypeId; |
729 | $fieldParams['option_amount'][1] = empty($params['minimum_fee']) ? 0 : $params['minimum_fee']; | |
730 | $fieldParams['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $params); | |
731 | ||
732 | if ($previousID) { | |
733 | CRM_Member_Form_MembershipType::checkPreviousPriceField($previousID, $priceSetId, $membershipTypeId, $optionsIds); | |
734 | $fieldParams['option_id'] = CRM_Utils_Array::value('option_id', $optionsIds); | |
735 | } | |
806e9b71 | 736 | CRM_Price_BAO_PriceField::create($fieldParams); |
03e04002 | 737 | } |
6a488035 TO |
738 | else { |
739 | $fieldID = $results['id']; | |
740 | $fieldValueParams = array( | |
741 | 'price_field_id' => $fieldID, | |
742 | 'membership_type_id' => $membershipTypeId, | |
743 | ); | |
744 | $results = array(); | |
9da8dc8c | 745 | CRM_Price_BAO_PriceFieldValue::retrieve($fieldValueParams, $results); |
6a488035 | 746 | if (!empty($results)) { |
353ffa53 | 747 | $results['label'] = $results['name'] = $params['name']; |
6a488035 | 748 | $results['amount'] = empty($params['minimum_fee']) ? 0 : $params['minimum_fee']; |
353ffa53 | 749 | $optionsIds['id'] = $results['id']; |
03e04002 | 750 | } |
6a488035 TO |
751 | else { |
752 | $results = array( | |
753 | 'price_field_id' => $fieldID, | |
754 | 'name' => $params['name'], | |
755 | 'label' => $params['name'], | |
756 | 'amount' => empty($params['minimum_fee']) ? 0 : $params['minimum_fee'], | |
757 | 'membership_type_id' => $membershipTypeId, | |
758 | 'is_active' => 1, | |
759 | ); | |
760 | } | |
761 | ||
762 | if ($previousID) { | |
763 | CRM_Member_Form_MembershipType::checkPreviousPriceField($previousID, $priceSetId, $membershipTypeId, $optionsIds); | |
a7488080 | 764 | if (!empty($optionsIds['option_id'])) { |
6a488035 TO |
765 | $optionsIds['id'] = current(CRM_Utils_Array::value('option_id', $optionsIds)); |
766 | } | |
767 | } | |
768 | $results['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $params); | |
0e09eaf5 | 769 | $results['description'] = CRM_Utils_Array::value('description', $params); |
9da8dc8c | 770 | CRM_Price_BAO_PriceFieldValue::add($results, $optionsIds); |
6a488035 TO |
771 | } |
772 | } | |
773 | ||
be2e0c6a TO |
774 | /** |
775 | * This function updates all price field value for quick config | |
6a488035 TO |
776 | * price set which has membership type |
777 | * | |
87ad884a | 778 | * @param int $membershipTypeId membership type id |
6a488035 | 779 | * |
87ad884a | 780 | * @param array $params |
6a488035 | 781 | */ |
00be9182 | 782 | public static function updateAllPriceFieldValue($membershipTypeId, $params) { |
b204fd50 | 783 | $updateFields = array(); |
9b873358 | 784 | if (!empty($params['minimum_fee'])) { |
5a9c4d4a PN |
785 | $amount = $params['minimum_fee']; |
786 | } | |
787 | else { | |
788 | $amount = 0; | |
789 | } | |
0e09eaf5 PN |
790 | |
791 | $updateValues = array( | |
792 | 2 => array('financial_type_id', 'financial_type_id', 'Integer'), | |
793 | 3 => array('label', 'name', 'String'), | |
794 | 4 => array('amount', 'minimum_fee', 'Float'), | |
795 | 5 => array('description', 'description', 'String'), | |
796 | ); | |
797 | ||
798 | $queryParams = array(1 => array($membershipTypeId, 'Integer')); | |
03e04002 | 799 | foreach ($updateValues as $key => $value) { |
0e09eaf5 PN |
800 | if (array_key_exists($value[1], $params)) { |
801 | $updateFields[] = "cpfv." . $value[0] . " = %$key"; | |
802 | if ($value[1] == 'minimum_fee') { | |
803 | $fieldValue = $amount; | |
804 | } | |
805 | else { | |
806 | $fieldValue = $params[$value[1]]; | |
807 | } | |
808 | $queryParams[$key] = array($fieldValue, $value[2]); | |
809 | } | |
810 | } | |
811 | ||
6a488035 | 812 | $query = "UPDATE `civicrm_price_field_value` cpfv |
03e04002 | 813 | INNER JOIN civicrm_price_field cpf on cpf.id = cpfv.price_field_id |
6a488035 | 814 | INNER JOIN civicrm_price_set cps on cps.id = cpf.price_set_id |
03e04002 | 815 | SET " . implode(' , ', $updateFields) . " WHERE cpfv.membership_type_id = %1 |
0e09eaf5 PN |
816 | AND cps.is_quick_config = 1 AND cps.name != 'default_membership_type_amount'"; |
817 | CRM_Core_DAO::executeQuery($query, $queryParams); | |
03e04002 | 818 | } |
96025800 | 819 | |
6a488035 | 820 | } |