4 +--------------------------------------------------------------------+
5 | CiviCRM version 4.3 |
6 +--------------------------------------------------------------------+
7 | Copyright CiviCRM LLC (c) 2004-2013 |
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007. |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
20 | You should have received a copy of the GNU Affero General Public |
21 | License along 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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2013
35 class CRM_Upgrade_Incremental_php_FourThree
{
36 const BATCH_SIZE
= 5000;
38 function verifyPreDBstate(&$errors) {
43 * Compute any messages which should be displayed after upgrade
45 * @param $postUpgradeMessage string, alterable
46 * @param $rev string, an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs
49 function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
50 if ($rev == '4.3.alpha1') {
51 // check if CiviMember component is enabled
52 $config = CRM_Core_Config
::singleton();
53 if (in_array('CiviMember', $config->enableComponents
)) {
54 $postUpgradeMessage .= '<br />' . ts('Membership renewal reminders must now be configured using the Schedule Reminders feature, which supports multiple renewal reminders (Administer > Communications > Schedule Reminders). The Update Membership Statuses scheduled job will no longer send membershp renewal reminders. You can use your existing renewal reminder message template(s) with the Schedule Reminders feature.');
55 $postUpgradeMessage .= '<br />' . ts('The Set Membership Reminder Dates scheduled job has been deleted since membership reminder dates stored in the membership table are no longer in use.');
59 //here we do the financial type check and migration
60 $isDefaultsModified = self
::_checkAndMigrateDefaultFinancialTypes();
61 if($isDefaultsModified) {
62 $postUpgradeMessage .= '<br />' . ts('Please review all price set financial type assignments.');
64 list($context, $orgName) = self
::createDomainContacts();
65 if ($context == 'added') {
66 $postUpgradeMessage .= '<br />' . ts("A new organization contact has been added as the default domain contact using the information from your Organization Address and Contact Info settings: '{$orgName}'.");
68 elseif ($context == 'merged') {
69 $postUpgradeMessage .= '<br />' . ts("The existing organization contact record for '{$orgName}' has marked as the default domain contact, and has been updated with information from your Organization Address and Contact Info settings.");
72 $providerExists = CRM_Core_DAO
::singleValueQuery("SELECT id FROM civicrm_sms_provider LIMIT 1");
73 if ($providerExists) {
74 $postUpgradeMessage .= '<br />' . ts('SMS providers were found to setup. Please note Clickatell / Twilio are now shipped as extensions and will require installing them to continue working. Extension could be downloaded and installed from <a href="%1">github</a>.', array(1 => 'https://github.com/civicrm/civicrm-core/tree/master/tools/extensions'));
78 if ($rev == '4.3.alpha2') {
81 FROM civicrm_action_schedule
82 WHERE entity_value = '' OR entity_value IS NULL
85 $dao = CRM_Core_DAO
::executeQuery($sql);
88 while ($dao->fetch()) {
89 $reminder[$dao->id
] = $dao->title
;
90 $list .= "<li>{$dao->title}</li>";
92 if (!empty($reminder)) {
93 $list = "<br /><ul>" . $list . "</ul>";
94 $postUpgradeMessage .= '<br />' .ts("Scheduled Reminders must be linked to one or more 'entities' (Events, Event Templates, Activity Types, Membership Types). The following reminders are not configured properly and will not be run. Please review them and update or delete them: %1", array(1 => $list));
98 if ($rev == '4.3.beta1') {
99 $postUpgradeMessage .= '<br />' . ts('Default versions of the following System Workflow Message Templates have been modified to handle new functionality: <ul><li>Events - Registration Confirmation and Receipt (on-line)</li><li>Events - Registration Confirmation and Receipt (off-line)</li><li>Pledges - Acknowledgement</li><li>Pledges - Payment Reminder</li><li>Contributions - Receipt (off-line)</li><li>Contributions - Receipt (on-line)</li><li>Memberships - Signup and Renewal Receipts (off-line)</li><li>Memberships - Receipt (on-line)</li><li>Personal Campaign Pages - Admin Notification</li></ul> If you have modified these templates, please review the new default versions and implement updates as needed to your copies (Administer > Communications > Message Templates > System Workflow Messages).');
104 function upgrade_4_3_alpha1($rev) {
105 self
::task_4_3_alpha1_checkDBConstraints();
107 // task to process sql
108 $this->addTask(ts('Upgrade DB to 4.3.alpha1: SQL'), 'task_4_3_x_runSql', $rev);
111 $this->addTask(ts('Populate financial type values for price records'), 'assignFinancialTypeToPriceRecords');
112 //CRM-11514 create financial records for contributions
113 $this->addTask(ts('Create financial records for contributions'), 'createFinancialRecords');
115 $minId = CRM_Core_DAO
::singleValueQuery('SELECT coalesce(min(id),0) FROM civicrm_contact');
116 $maxId = CRM_Core_DAO
::singleValueQuery('SELECT coalesce(max(id),0) FROM civicrm_contact');
117 for ($startId = $minId; $startId <= $maxId; $startId +
= self
::BATCH_SIZE
) {
118 $endId = $startId + self
::BATCH_SIZE
- 1;
119 $title = ts('Upgrade timestamps (%1 => %2)', array(
123 $this->addTask($title, 'convertTimestamps', $startId, $endId);
127 // fix WP access control
128 $config = CRM_Core_Config
::singleton( );
129 if ($config->userFramework
== 'WordPress') {
130 civicrm_wp_set_capabilities( );
133 // Update phones CRM-11292.
134 $this->addTask(ts('Upgrade Phone Numbers'), 'phoneNumeric');
139 function upgrade_4_3_alpha2($rev) {
141 $isColumnPresent = CRM_Core_DAO
::checkFieldExists('civicrm_dedupe_rule_group', 'is_default');
142 if ($isColumnPresent) {
143 CRM_Core_DAO
::executeQuery('ALTER TABLE civicrm_dedupe_rule_group DROP COLUMN is_default');
145 $this->addTask(ts('Upgrade DB to 4.3.alpha2: SQL'), 'task_4_3_x_runSql', $rev);
148 function upgrade_4_3_alpha3($rev) {
149 $this->addTask(ts('Upgrade DB to 4.3.alpha3: SQL'), 'task_4_3_x_runSql', $rev);
152 function upgrade_4_3_beta2($rev2) {
155 CRM_Core_DAO
::checkTableExists('log_civicrm_line_item') &&
156 CRM_Core_DAO
::checkFieldExists('log_civicrm_line_item', 'label')
158 CRM_Core_DAO
::executeQuery('ALTER TABLE `log_civicrm_line_item` CHANGE `label` `label` VARCHAR(255) NULL DEFAULT NULL');
163 function assignFinancialTypeToPriceRecords() {
164 $upgrade = new CRM_Upgrade_Form();
165 //here we update price set entries
166 $sqlFinancialIds = "SELECT id, name FROM civicrm_financial_type
167 WHERE name IN ('Donation', 'Event Fee', 'Member Dues');";
168 $daoFinancialIds = CRM_Core_DAO
::executeQuery($sqlFinancialIds);
169 while($daoFinancialIds->fetch()) {
170 $financialIds[$daoFinancialIds->name
] = $daoFinancialIds->id
;
172 $sqlPriceSetUpdate = "UPDATE civicrm_price_set ps
173 SET ps.financial_type_id = CASE
174 WHEN ps.extends LIKE '%1%' THEN {$financialIds['Event Fee']}
175 WHEN ps.extends LIKE '2' THEN {$financialIds['Donation']}
176 WHEN ps.extends LIKE '3' THEN {$financialIds['Member Dues']}
178 WHERE financial_type_id IS NULL";
179 CRM_Core_DAO
::executeQuery($sqlPriceSetUpdate);
181 //here we update price field value rows
182 $sqlPriceFieldValueUpdate = "UPDATE civicrm_price_field_value pfv
183 LEFT JOIN civicrm_membership_type mt ON (pfv.membership_type_id = mt.id)
184 INNER JOIN civicrm_price_field pf ON (pfv.price_field_id = pf.id)
185 INNER JOIN civicrm_price_set ps ON (pf.price_set_id = ps.id)
186 SET pfv.financial_type_id = CASE
187 WHEN pfv.membership_type_id IS NOT NULL THEN mt.financial_type_id
188 WHEN pfv.membership_type_id IS NULL THEN ps.financial_type_id
190 CRM_Core_DAO
::executeQuery($sqlPriceFieldValueUpdate);
195 static function _checkAndMigrateDefaultFinancialTypes() {
196 $modifiedDefaults = FALSE;
197 //insert types if not exists
198 $sqlFetchTypes = "SELECT id, name FROM civicrm_contribution_type
199 WHERE name IN ('Donation', 'Event Fee', 'Member Dues') AND is_active =1;";
200 $daoFetchTypes = CRM_Core_DAO
::executeQuery($sqlFetchTypes);
202 if ($daoFetchTypes->N
< 3) {
203 $modifiedDefaults = TRUE;
204 $insertStatments = array (
205 'Donation' => "('Donation', 0, 1, 1)",
206 'Member' => "('Member Dues', 0, 1, 1)",
207 'Event Fee' => "('Event Fee', 0, 1, 0)",
209 foreach ($insertStatments as $values) {
210 $query = "INSERT INTO civicrm_contribution_type (name, is_reserved, is_active, is_deductible)
212 ON DUPLICATE KEY UPDATE is_active = 1;";
213 CRM_Core_DAO
::executeQuery($query);
216 return $modifiedDefaults;
219 function createFinancialRecords() {
220 $upgrade = new CRM_Upgrade_Form();
222 // update civicrm_entity_financial_trxn.amount = civicrm_financial_trxn.total_amount
223 $query = "UPDATE civicrm_entity_financial_trxn ceft
224 LEFT JOIN civicrm_financial_trxn cft ON cft.id = ceft.financial_trxn_id
225 SET ceft.amount = total_amount
226 WHERE cft.net_amount IS NOT NULL AND ceft.entity_table = 'civicrm_contribution';";
227 CRM_Core_DAO
::executeQuery($query);
229 $contributionStatus = CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
230 $completedStatus = array_search('Completed', $contributionStatus);
231 $pendingStatus = array_search('Pending', $contributionStatus);
232 $cancelledStatus = array_search('Cancelled', $contributionStatus);
233 $queryParams = array(
234 1 => array($completedStatus, 'Integer'),
235 2 => array($pendingStatus, 'Integer'),
236 3 => array($cancelledStatus, 'Integer')
239 $accountType = key(CRM_Core_PseudoConstant
::accountOptionValues('financial_account_type', NULL, " AND v.name = 'Asset' "));
240 $financialAccountId =
241 CRM_Core_DAO
::singleValueQuery("SELECT id FROM civicrm_financial_account WHERE is_default = 1 AND financial_account_type_id = {$accountType}");
243 $accountRelationsips = CRM_Core_PseudoConstant
::accountOptionValues('account_relationship', NULL);
245 $accountsReceivableAccount = array_search('Accounts Receivable Account is', $accountRelationsips);
246 $incomeAccountIs = array_search('Income Account is', $accountRelationsips);
247 $assetAccountIs = array_search('Asset Account is', $accountRelationsips);
248 $expenseAccountIs = array_search('Expense Account is', $accountRelationsips);
250 $financialItemStatus = CRM_Core_PseudoConstant
::accountOptionValues('financial_item_status');
251 $unpaidStatus = array_search('Unpaid', $financialItemStatus);
252 $paidStatus = array_search('Paid', $financialItemStatus);
254 $validCurrencyCodes = CRM_Core_PseudoConstant
::currencyCode();
255 $validCurrencyCodes = implode("','", $validCurrencyCodes);
256 $config = CRM_Core_Config
::singleton();
257 $defaultCurrency = $config->defaultCurrency
;
258 $now = date( 'YmdHis' );
260 //adding financial_trxn records and entity_financial_trxn records related to contribution
261 //Add temp column for easy entry in entity_financial_trxn
262 $sql = "ALTER TABLE civicrm_financial_trxn ADD COLUMN contribution_id INT DEFAULT NULL";
263 CRM_Core_DAO
::executeQuery($sql);
265 //pending pay later status handling
267 INSERT INTO civicrm_financial_trxn
268 (contribution_id, payment_instrument_id, currency, total_amount, net_amount, fee_amount, trxn_id, status_id,
269 check_number, to_financial_account_id, from_financial_account_id, trxn_date)
271 SELECT con.id as contribution_id, con.payment_instrument_id, IF(con.currency IN ('{$validCurrencyCodes}'), con.currency, '{$defaultCurrency}')
272 as currency, con.total_amount, con.net_amount, con.fee_amount, con.trxn_id, con.contribution_status_id,
273 con.check_number, efa.financial_account_id as to_financial_account_id, NULL as from_financial_account_id,
274 REPLACE(REPLACE(REPLACE(
276 WHEN con.receive_date IS NOT NULL THEN
278 WHEN con.receipt_date IS NOT NULL THEN
283 , '-', ''), ':', ''), ' ', '') as trxn_date
284 FROM civicrm_contribution con
285 LEFT JOIN civicrm_entity_financial_account efa
286 ON (con.financial_type_id = efa.entity_id AND efa.entity_table = 'civicrm_financial_type'
287 AND efa.account_relationship = {$accountsReceivableAccount})
288 WHERE con.is_pay_later = 1 AND con.contribution_status_id = {$pendingStatus}";
289 CRM_Core_DAO
::executeQuery($sql);
291 //create a temp table to hold financial account id related to payment instruments
292 $tempTableName1 = CRM_Core_DAO
::createTempTableName();
294 $sql = "CREATE TEMPORARY TABLE {$tempTableName1}
296 SELECT ceft.financial_account_id financial_account_id, cov.value as instrument_id
297 FROM civicrm_entity_financial_account ceft
298 INNER JOIN civicrm_option_value cov ON cov.id = ceft.entity_id AND ceft.entity_table = 'civicrm_option_value'
299 INNER JOIN civicrm_option_group cog ON cog.id = cov.option_group_id
300 WHERE cog.name = 'payment_instrument'";
301 CRM_Core_DAO
::executeQuery($sql);
303 //create temp table to process completed / cancelled contribution
304 $tempTableName2 = CRM_Core_DAO
::createTempTableName();
305 $sql = "CREATE TEMPORARY TABLE {$tempTableName2}
307 SELECT con.id as contribution_id, con.payment_instrument_id, IF(con.currency IN ('{$validCurrencyCodes}'), con.currency, '{$defaultCurrency}') as currency,
308 con.total_amount, con.net_amount, con.fee_amount, con.trxn_id, con.contribution_status_id, con.check_number, NULL as from_financial_account_id,
309 REPLACE(REPLACE(REPLACE(
311 WHEN con.receive_date IS NOT NULL THEN
313 WHEN con.receipt_date IS NOT NULL THEN
318 , '-', ''), ':', ''), ' ', '') as trxn_date,
320 WHEN con.payment_instrument_id IS NULL THEN
321 {$financialAccountId}
322 WHEN con.payment_instrument_id IS NOT NULL THEN
323 tpi.financial_account_id
324 END as to_financial_account_id,
325 IF(eft.financial_trxn_id IS NULL, 'insert', eft.financial_trxn_id) as action
326 FROM civicrm_contribution con
327 LEFT JOIN civicrm_entity_financial_trxn eft
328 ON (eft.entity_table = 'civicrm_contribution' AND eft.entity_id = con.id)
329 LEFT JOIN {$tempTableName1} tpi
330 ON con.payment_instrument_id = tpi.instrument_id
331 WHERE con.contribution_status_id IN ({$completedStatus}, {$cancelledStatus})";
332 CRM_Core_DAO
::executeQuery($sql);
334 //handling for completed contribution and cancelled contribution
335 //insertion of new records
337 INSERT INTO civicrm_financial_trxn
338 (contribution_id, payment_instrument_id, currency, total_amount, net_amount, fee_amount, trxn_id, status_id, check_number,
339 to_financial_account_id, from_financial_account_id, trxn_date)
340 SELECT tempI.contribution_id, tempI.payment_instrument_id, tempI.currency, tempI.total_amount, tempI.net_amount,
341 tempI.fee_amount, tempI.trxn_id, tempI.contribution_status_id, tempI.check_number,
342 tempI.to_financial_account_id, tempI.from_financial_account_id, tempI.trxn_date
343 FROM {$tempTableName2} tempI
344 WHERE tempI.action = 'insert';";
345 CRM_Core_DAO
::executeQuery($sql);
347 //update of existing records
349 UPDATE civicrm_financial_trxn ft
350 INNER JOIN {$tempTableName2} tempU
351 ON (tempU.action != 'insert' AND ft.id = tempU.action)
352 SET ft.from_financial_account_id = NULL,
353 ft.to_financial_account_id = tempU.to_financial_account_id,
354 ft.status_id = tempU.contribution_status_id,
355 ft.payment_instrument_id = tempU.payment_instrument_id,
356 ft.check_number = tempU.check_number,
357 ft.contribution_id = tempU.contribution_id;";
358 CRM_Core_DAO
::executeQuery($sql);
360 //insert the -ve transaction rows for cancelled contributions
362 INSERT INTO civicrm_financial_trxn
363 (contribution_id, payment_instrument_id, currency, total_amount, net_amount, fee_amount, trxn_id, status_id,
364 check_number, to_financial_account_id, from_financial_account_id, trxn_date)
365 SELECT ft.contribution_id, ft.payment_instrument_id, ft.currency, -ft.total_amount, ft.net_amount, ft.fee_amount, ft.trxn_id,
366 ft.status_id, ft.check_number, ft.to_financial_account_id, ft.from_financial_account_id, ft.trxn_date
367 FROM civicrm_financial_trxn ft
368 WHERE ft.status_id = {$cancelledStatus};";
369 CRM_Core_DAO
::executeQuery($sql);
371 //inserting entity financial trxn entries if its not present in entity_financial_trxn for completed and pending contribution statuses
372 //this also handles +ve and -ve both transaction entries for a cancelled contribution
374 INSERT INTO civicrm_entity_financial_trxn (entity_table, entity_id, financial_trxn_id, amount)
375 SELECT 'civicrm_contribution', ft.contribution_id, ft.id, ft.total_amount as amount
376 FROM civicrm_financial_trxn ft
377 WHERE contribution_id IS NOT NULL AND
378 ft.id NOT IN (SELECT financial_trxn_id
379 FROM civicrm_entity_financial_trxn
380 WHERE entity_table = 'civicrm_contribution'
381 AND entity_id = ft.contribution_id)";
382 CRM_Core_DAO
::executeQuery($sql);
383 //end of adding financial_trxn records and entity_financial_trxn records related to contribution
385 //update all linked line_item rows
386 // set line_item.financial_type_id = contribution.financial_type_id if contribution page id is null and not participant line item
387 // set line_item.financial_type_id = price_field_value.financial_type_id if contribution page id is set and not participant line item
388 // set line_item.financial_type_id = event.financial_type_id if its participant line item and line_item.price_field_value_id is null
389 // set line_item.financial_type_id = price_field_value.financial_type_id if its participant line item and line_item.price_field_value_id is set
390 $updateLineItemSql = "
391 UPDATE civicrm_line_item li
392 LEFT JOIN civicrm_contribution con
393 ON (li.entity_id = con.id AND li.entity_table = 'civicrm_contribution')
394 LEFT JOIN civicrm_price_field_value cpfv
395 ON li.price_field_value_id = cpfv.id
396 LEFT JOIN civicrm_participant cp
397 ON (li.entity_id = cp.id AND li.entity_table = 'civicrm_participant')
398 LEFT JOIN civicrm_event ce
399 ON ce.id = cp.event_id
400 SET li.financial_type_id = CASE
401 WHEN (con.contribution_page_id IS NULL || li.price_field_value_id IS NULL) AND cp.id IS NULL THEN
402 con.financial_type_id
403 WHEN (con.contribution_page_id IS NOT NULL AND cp.id IS NULL) || (cp.id IS NOT NULL AND li.price_field_value_id IS NOT NULL) THEN
404 cpfv.financial_type_id
405 WHEN cp.id IS NOT NULL AND li.price_field_value_id IS NULL THEN
408 CRM_Core_DAO
::executeQuery($updateLineItemSql, $queryParams);
410 //add the financial_item entries
411 //add a temp column so that inserting entity_financial_trxn entries gets easy
412 $sql = "ALTER TABLE civicrm_financial_item ADD COLUMN f_trxn_id INT DEFAULT NULL";
413 CRM_Core_DAO
::executeQuery($sql);
415 //add financial_item entries for contribution completed / pending pay later / cancelled
416 $contributionlineItemSql = "
417 INSERT INTO civicrm_financial_item
418 (transaction_date, contact_id, amount, currency, entity_table, entity_id, description, status_id, financial_account_id, f_trxn_id)
420 SELECT REPLACE(REPLACE(REPLACE(ft.trxn_date, '-', ''), ':', ''), ' ', ''), con.contact_id,
421 IF(ft.total_amount < 0 AND con.contribution_status_id = %3, -li.line_total, li.line_total) as line_total, con.currency, 'civicrm_line_item',
422 li.id as line_item_id, li.label as line_item_label,
423 IF(con.contribution_status_id = {$pendingStatus}, {$unpaidStatus}, {$paidStatus}) as status_id, efa.financial_account_id as financial_account_id,
425 FROM civicrm_line_item li
426 INNER JOIN civicrm_contribution con
427 ON (li.entity_id = con.id AND li.entity_table = 'civicrm_contribution')
428 INNER JOIN civicrm_financial_trxn ft
429 ON (con.id = ft.contribution_id)
430 LEFT JOIN civicrm_entity_financial_account efa
431 ON (li.financial_type_id = efa.entity_id AND efa.entity_table = 'civicrm_financial_type'
432 AND efa.account_relationship = {$incomeAccountIs})
433 WHERE con.contribution_status_id IN (%1, %3) OR (con.is_pay_later = 1 AND con.contribution_status_id = %2)";
434 CRM_Core_DAO
::executeQuery($contributionlineItemSql, $queryParams);
436 //add financial_item entries for event
437 $participantLineItemSql = "
438 INSERT INTO civicrm_financial_item
439 (transaction_date, contact_id, amount, currency, entity_table, entity_id, description, status_id, financial_account_id, f_trxn_id)
441 SELECT REPLACE(REPLACE(REPLACE(ft.trxn_date, '-', ''), ':', ''), ' ', ''), con.contact_id,
442 IF(ft.total_amount < 0 AND con.contribution_status_id = %3, -li.line_total, li.line_total) as line_total,
443 con.currency, 'civicrm_line_item', li.id as line_item_id, li.label as line_item_label,
444 IF(con.contribution_status_id = {$pendingStatus}, {$unpaidStatus}, {$paidStatus}) as status_id,
445 efa.financial_account_id as financial_account_id, ft.id as f_trxn_id
446 FROM civicrm_line_item li
447 INNER JOIN civicrm_participant par
448 ON (li.entity_id = par.id AND li.entity_table = 'civicrm_participant')
449 INNER JOIN civicrm_participant_payment pp
450 ON (pp.participant_id = par.id)
451 INNER JOIN civicrm_contribution con
452 ON (pp.contribution_id = con.id)
453 INNER JOIN civicrm_financial_trxn ft
454 ON (con.id = ft.contribution_id)
455 LEFT JOIN civicrm_entity_financial_account efa
456 ON (li.financial_type_id = efa.entity_id AND
457 efa.entity_table = 'civicrm_financial_type' AND efa.account_relationship = {$incomeAccountIs})
458 WHERE con.contribution_status_id IN (%1, %3) OR (con.is_pay_later = 1 AND con.contribution_status_id = %2)";
459 CRM_Core_DAO
::executeQuery($participantLineItemSql, $queryParams);
461 //fee handling for contributions
462 //insert fee entries in financial_trxn for contributions
463 $sql = "ALTER TABLE civicrm_financial_trxn ADD COLUMN is_fee TINYINT DEFAULT NULL";
464 CRM_Core_DAO
::executeQuery($sql);
467 INSERT INTO civicrm_financial_trxn
468 (contribution_id, payment_instrument_id, currency, total_amount, net_amount, fee_amount, trxn_id, status_id, check_number,
469 to_financial_account_id, from_financial_account_id, trxn_date, payment_processor_id, is_fee)
471 SELECT con.id, ft.payment_instrument_id, ft.currency, ft.fee_amount, NULL, NULL, ft.trxn_id, %1 as status_id,
472 ft.check_number, efaFT.financial_account_id as to_financial_account_id, CASE
473 WHEN efaPP.financial_account_id IS NOT NULL THEN
474 efaPP.financial_account_id
475 WHEN tpi.financial_account_id IS NOT NULL THEN
476 tpi.financial_account_id
478 {$financialAccountId}
479 END as from_financial_account_id, ft.trxn_date, ft.payment_processor_id, 1 as is_fee
480 FROM civicrm_contribution con
481 INNER JOIN civicrm_financial_trxn ft
482 ON (ft.contribution_id = con.id)
483 LEFT JOIN civicrm_entity_financial_account efaFT
484 ON (con.financial_type_id = efaFT.entity_id AND efaFT.entity_table = 'civicrm_financial_type'
485 AND efaFT.account_relationship = {$expenseAccountIs})
486 LEFT JOIN civicrm_entity_financial_account efaPP
487 ON (ft.payment_processor_id = efaPP.entity_id AND efaPP.entity_table = 'civicrm_payment_processor'
488 AND efaPP.account_relationship = {$assetAccountIs})
489 LEFT JOIN {$tempTableName1} tpi
490 ON ft.payment_instrument_id = tpi.instrument_id
491 WHERE con.fee_amount IS NOT NULL AND (con.contribution_status_id IN (%1, %3) OR (con.contribution_status_id =%2 AND con.is_pay_later = 1))
493 CRM_Core_DAO
::executeQuery($sql, $queryParams);
495 //link financial_trxn to contribution
497 INSERT INTO civicrm_entity_financial_trxn
498 (entity_table, entity_id, financial_trxn_id, amount)
499 SELECT 'civicrm_contribution', ft.contribution_id, ft.id, ft.total_amount
500 FROM civicrm_financial_trxn ft
501 WHERE ft.is_fee = 1";
502 CRM_Core_DAO
::executeQuery($sql);
504 //add fee related entries to financial item table
505 $domainId = CRM_Core_Config
::domainID();
506 $domainContactId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_Domain', $domainId, 'contact_id');
508 INSERT INTO civicrm_financial_item
509 (transaction_date, contact_id, amount, currency, entity_table, entity_id, description, status_id, financial_account_id, f_trxn_id)
510 SELECT ft.trxn_date, {$domainContactId} as contact_id, ft.total_amount, ft.currency, 'civicrm_financial_trxn', ft.id,
511 'Fee', {$paidStatus} as status_id, ft.to_financial_account_id as financial_account_id, ft.id as f_trxn_id
512 FROM civicrm_financial_trxn ft
513 WHERE ft.is_fee = 1;";
514 CRM_Core_DAO
::executeQuery($sql);
516 //add entries to entity_financial_trxn table
518 INSERT INTO civicrm_entity_financial_trxn (entity_table, entity_id, financial_trxn_id, amount)
519 SELECT 'civicrm_financial_item' as entity_table, fi.id as entity_id, fi.f_trxn_id as financial_trxn_id, fi.amount
520 FROM civicrm_financial_item fi";
521 CRM_Core_DAO
::executeQuery($sql);
523 //drop the temparory columns
524 $sql = "ALTER TABLE civicrm_financial_trxn
525 DROP COLUMN contribution_id,
526 DROP COLUMN is_fee;";
527 CRM_Core_DAO
::executeQuery($sql);
529 $sql = "ALTER TABLE civicrm_financial_item DROP f_trxn_id";
530 CRM_Core_DAO
::executeQuery($sql);
535 function createDomainContacts() {
536 $domainParams = $context = array();
538 ALTER TABLE `civicrm_domain` ADD `contact_id` INT( 10 ) UNSIGNED NULL DEFAULT NULL COMMENT 'FK to Contact ID. This is specifically not an FK to avoid circular constraints',
539 ADD CONSTRAINT `FK_civicrm_domain_contact_id` FOREIGN KEY (`contact_id`) REFERENCES `civicrm_contact` (`id`);";
540 CRM_Core_DAO
::executeQuery($query, CRM_Core_DAO
::$_nullArray, TRUE, NULL, FALSE, FALSE);
542 $query = 'SELECT cd.id, cd.name, ce.email FROM `civicrm_domain` cd
543 LEFT JOIN civicrm_loc_block clb ON clb.id = cd. loc_block_id
544 LEFT JOIN civicrm_email ce ON ce.id = clb.email_id ;' ;
545 $dao = CRM_Core_DAO
::executeQuery($query);
546 while($dao->fetch()) {
548 'sort_name' => $dao->name
,
549 'display_name' => $dao->name
,
550 'legal_name' => $dao->name
,
551 'organization_name' => $dao->name
,
552 'contact_type' => 'Organization'
554 $query = "SELECT cc.id FROM `civicrm_contact` cc
555 LEFT JOIN civicrm_email ce ON ce.contact_id = cc.id
556 WHERE cc.contact_type = 'Organization' AND cc.organization_name = '{$dao->name}' ";
558 $query .= " AND ce.email = '{$dao->email}' ";
560 $contactID = CRM_Core_DAO
::singleValueQuery($query);
561 $context[1] = $dao->name
;
562 if (empty($contactID)) {
563 $contact = CRM_Contact_BAO_Contact
::add($params);
564 $contactID = $contact->id
;
565 $context[0] = 'added';
568 $context[0] = 'merged';
570 $domainParams['contact_id'] = $contactID;
571 CRM_Core_BAO_Domain
::edit($domainParams, $dao->id
);
576 function task_4_3_alpha1_checkDBConstraints() {
577 //checking whether the foreign key exists before dropping it CRM-11260
578 $config = CRM_Core_Config
::singleton();
579 $dbUf = DB
::parseDSN($config->dsn
);
582 'autorenewal_msg_id' => array('tableName' => 'civicrm_membership_type', 'fkey' => 'FK_civicrm_membership_autorenewal_msg_id'),
583 'to_account_id' => array('tableName' => 'civicrm_financial_trxn', 'constraintName' => 'civicrm_financial_trxn_ibfk_2'),
584 'from_account_id' => array('tableName' => 'civicrm_financial_trxn', 'constraintName' => 'civicrm_financial_trxn_ibfk_1'),
585 'contribution_type_id' => array('tableName' => 'civicrm_contribution_recur', 'fkey' => 'FK_civicrm_contribution_recur_contribution_type_id'),
587 $query = "SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
588 WHERE table_name = 'civicrm_contribution_recur'
589 AND constraint_name = 'FK_civicrm_contribution_recur_contribution_type_id'
590 AND TABLE_SCHEMA = '{$dbUf['database']}'";
592 $dao = CRM_Core_DAO
::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
593 foreach($tables as $columnName => $value){
594 if ($value['tableName'] == 'civicrm_membership_type' ||
$value['tableName'] == 'civicrm_contribution_recur') {
595 $foreignKeyExists = CRM_Core_DAO
::checkConstraintExists($value['tableName'], $value['fkey']);
596 $fKey = $value['fkey'];
598 $foreignKeyExists = CRM_Core_DAO
::checkFKConstraintInFormat($value['tableName'], $columnName);
599 $fKey = "`FK_{$value['tableName']}_{$columnName}`";
601 if ($foreignKeyExists ||
$value['tableName'] == 'civicrm_financial_trxn') {
602 if ($value['tableName'] != 'civicrm_contribution_recur' ||
($value['tableName'] == 'civicrm_contribution_recur' && $dao->N
)) {
603 $constraintName = $foreignKeyExists ?
$fKey : $value['constraintName'];
604 CRM_Core_DAO
::executeQuery("ALTER TABLE {$value['tableName']} DROP FOREIGN KEY {$constraintName}", $params, TRUE, NULL, FALSE, FALSE);
606 CRM_Core_DAO
::executeQuery("ALTER TABLE {$value['tableName']} DROP INDEX {$fKey}", $params, TRUE, NULL, FALSE, FALSE);
609 // check if column contact_id is present or not in civicrm_financial_account
610 $fieldExists = CRM_Core_DAO
::checkFieldExists('civicrm_financial_account', 'contact_id', FALSE);
612 $query = "ALTER TABLE civicrm_financial_account ADD `contact_id` int(10) unsigned DEFAULT NULL COMMENT 'Version identifier of financial_type' AFTER `name`, ADD CONSTRAINT `FK_civicrm_financial_account_contact_id` FOREIGN KEY (`contact_id`) REFERENCES `civicrm_contact`(id);";
613 CRM_Core_DAO
::executeQuery($query, $params, TRUE, NULL, FALSE, FALSE);
618 * Read creation and modification times from civicrm_log; add
619 * them to civicrm_contact.
621 function convertTimestamps(CRM_Queue_TaskContext
$ctx, $startId, $endId) {
623 SELECT entity_id, min(modified_date) AS created, max(modified_date) AS modified
625 WHERE entity_table = 'civicrm_contact'
626 AND entity_id BETWEEN %1 AND %2
630 1 => array($startId, 'Integer'),
631 2 => array($endId, 'Integer'),
633 $dao = CRM_Core_DAO
::executeQuery($sql, $params);
634 while ($dao->fetch()) {
635 // FIXME civicrm_log.modified_date is DATETIME; civicrm_contact.modified_date is TIMESTAMP
636 CRM_Core_DAO
::executeQuery(
637 'UPDATE civicrm_contact SET created_date = %1, modified_date = %2 WHERE id = %3',
639 1 => array($dao->created
, 'String'),
640 2 => array($dao->modified
, 'String'),
641 3 => array($dao->entity_id
, 'Integer'),
650 * Update phones CRM-11292
652 * @return bool TRUE for success
654 static function phoneNumeric(CRM_Queue_TaskContext
$ctx) {
655 CRM_Core_DAO
::executeQuery(CRM_Contact_BAO_Contact
::DROP_STRIP_FUNCTION_43
);
656 CRM_Core_DAO
::executeQuery(CRM_Contact_BAO_Contact
::CREATE_STRIP_FUNCTION_43
);
657 CRM_Core_DAO
::executeQuery("UPDATE civicrm_phone SET phone_numeric = civicrm_strip_non_numeric(phone)");
662 * (Queue Task Callback)
664 static function task_4_3_x_runSql(CRM_Queue_TaskContext
$ctx, $rev) {
665 $upgrade = new CRM_Upgrade_Form();
666 $upgrade->processSQL($rev);
672 * Syntatic sugar for adding a task which (a) is in this class and (b) has
675 * After passing the $funcName, you can also pass parameters that will go to
676 * the function. Note that all params must be serializable.
678 protected function addTask($title, $funcName) {
679 $queue = CRM_Queue_Service
::singleton()->load(array(
681 'name' => CRM_Upgrade_Form
::QUEUE_NAME
,
684 $args = func_get_args();
685 $title = array_shift($args);
686 $funcName = array_shift($args);
687 $task = new CRM_Queue_Task(
688 array(get_class($this), $funcName),
692 $queue->createItem($task, array('weight' => -1));