Commit 53169901 authored by DaveD's avatar DaveD
Browse files

add financial type and payment method to report

parent 81de2bab
<?php
require_once('CRM/Report/Form.php');
require_once('CRM/Utils/Type.php');
use CRM_Cdntaxreceipts_ExtensionUtil as E;
class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
......@@ -19,7 +18,7 @@ class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
'fields' =>
array(
'sort_name' =>
array('title' => ts('Contact Name', array('domain' => 'org.civicrm.cdntaxreceipts')),
array('title' => E::ts('Contact Name (Current Value)'),
'required' => TRUE,
),
'id' =>
......@@ -117,6 +116,46 @@ class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
),
'grouping' => 'tax-fields',
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
'fields' => array(
'financial_type_id' => array(
'title' => E::ts('Financial Type (current value)'),
'default' => FALSE,
'type' => CRM_Utils_Type::T_STRING,
// look up words in alterDisplay
'dbAlias' => "GROUP_CONCAT(DISTINCT line_item_civireport.financial_type_id ORDER BY line_item_civireport.contribution_id SEPARATOR ',')",
),
),
'filters' => array(),
'grouping' => 'tax-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'payment_instrument_id' => array(
'title' => E::ts('Payment Method (current value)'),
'default' => FALSE,
'type' => CRM_Utils_Type::T_STRING,
// look up words in alterDisplay
'dbAlias' => "GROUP_CONCAT(DISTINCT contribution_civireport.payment_instrument_id ORDER BY contribution_civireport.id SEPARATOR ',')",
),
),
'filters' => array(
/* The problem with this is you then need to join on this table
* in the statistics section and it messes up the grouping because
* it's only expecting one table involved.
*
'payment_instrument_id' => array(
'title' => E::ts('Payment Method (current value)'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_BAO_Contribution::buildOptions('payment_instrument_id', 'get'),
'type' => CRM_Utils_Type::T_INT,
),
*/
),
'grouping' => 'tax-fields',
),
);
parent::__construct();
......@@ -165,8 +204,11 @@ class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
INNER JOIN cdntaxreceipts_log_contributions {$this->_aliases['civicrm_cdntaxreceipts_log_contributions']}
ON {$this->_aliases['civicrm_cdntaxreceipts_log']}.id = {$this->_aliases['civicrm_cdntaxreceipts_log_contributions']}.receipt_id
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_cdntaxreceipts_log']}.contact_id ";
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_cdntaxreceipts_log']}.contact_id
LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contribution']}.id = {$this->_aliases['civicrm_cdntaxreceipts_log_contributions']}.contribution_id
LEFT JOIN civicrm_line_item {$this->_aliases['civicrm_line_item']}
ON {$this->_aliases['civicrm_line_item']}.contribution_id = {$this->_aliases['civicrm_cdntaxreceipts_log_contributions']}.contribution_id";
}
function where() {
......@@ -295,6 +337,9 @@ class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
function alterDisplay(&$rows) {
// custom code to alter rows
$entryFound = FALSE;
$defined_financial_types = CRM_Contribute_BAO_Contribution::buildOptions('financial_type_id', 'validate');
$defined_payment_methods = CRM_Contribute_BAO_Contribution::buildOptions('payment_instrument_id', 'validate');
foreach ($rows as $rowNum => $row) {
// change contact name with link
......@@ -357,6 +402,24 @@ class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
}
}
if (array_key_exists('civicrm_line_item_financial_type_id', $row)) {
$financial_types = explode(',', $row['civicrm_line_item_financial_type_id']);
$financial_types = array_map(function($t) use ($defined_financial_types) {
return $defined_financial_types[$t] ?? E::ts('Unknown');
}, $financial_types);
$rows[$rowNum]['civicrm_line_item_financial_type_id'] = implode(', ', $financial_types);
$entryFound = TRUE;
}
if (array_key_exists('civicrm_contribution_payment_instrument_id', $row)) {
$payment_methods = explode(',', $row['civicrm_contribution_payment_instrument_id']);
$payment_methods = array_map(function($t) use ($defined_payment_methods) {
return $defined_payment_methods[$t] ?? E::ts('Unknown');
}, $payment_methods);
$rows[$rowNum]['civicrm_contribution_payment_instrument_id'] = implode(', ', $payment_methods);
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
......@@ -376,9 +439,11 @@ class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
ROUND(AVG({$this->_aliases['civicrm_cdntaxreceipts_log']}.receipt_amount), 2) as avg
";
// @todo FIXME
$where = $this->getRidOfLineItemsAclWhere();
$sql = "{$select}
FROM cdntaxreceipts_log {$this->_aliases['civicrm_cdntaxreceipts_log']}
{$this->_where}";
{$where}";
$dao = CRM_Core_DAO::executeQuery($sql);
......@@ -403,5 +468,23 @@ class CRM_Cdntaxreceipts_Form_Report_ReceiptsIssued extends CRM_Report_Form {
);
return $statistics;
}
/**
* @todo FIXME Core contains a built-in ACL on line items where it restricts
* the entity_table, but it messes up our grouping here. So as a quickfix
* this removes it. In this report we know the line items are always related
* to contributions, but this is still a bit risky and not the right way to
* do this.
* @return string
*/
private function getRidOfLineItemsAclWhere(): string {
$where = $this->_where;
$lineItemsAclWhere = implode(' AND ', CRM_Price_BAO_LineItem::getSelectWhereClause($this->_aliases['civicrm_line_item']));
if (!empty($lineItemsAclWhere) && strpos($where, "AND $lineItemsAclWhere") !== FALSE) {
$where = str_replace("AND $lineItemsAclWhere", ' ', $where);
}
return $where;
}
}
<?xml version="1.0"?>
<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/phpunit/bootstrap.php">
<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" cacheResult="false" bootstrap="tests/phpunit/bootstrap.php">
<testsuites>
<testsuite name="My Test Suite">
<directory>./tests/phpunit</directory>
......
<?php
/**
* @group headless
*/
class CRM_Cdntaxreceipts_ReceiptsIssuedReportTest extends CRM_Cdntaxreceipts_Base {
public function setUp(): void {
parent::setUp();
$this->setDeliveryMethod(CDNTAX_DELIVERY_PRINT_ONLY);
}
public function tearDown(): void {
$this->_tablesToTruncate = [
'civicrm_contact',
];
$this->quickCleanUpFinancialEntities();
parent::tearDown();
}
/**
* Basic test with defaults
*/
public function testReport() {
// create contribution
$contact_id = $this->individualCreate([], 1);
$datestr = date('Y-m-d');
$contribution_id = civicrm_api3('Contribution', 'create', [
'contact_id' => $contact_id,
'financial_type_id' => 'Donation',
'total_amount' => '10',
'receive_date' => $datestr,
])['id'];
// Need it in DAO format
$contribution = new CRM_Contribute_DAO_Contribution();
$contribution->id = $contribution_id;
$contribution->find(TRUE);
// issue receipt
list($result, $method) = cdntaxreceipts_issueTaxReceipt($contribution);
$this->assertTrue($result);
$this->assertEquals('print', $method);
// run report
$data = civicrm_api3('report_template', 'getrows', ['report_id' => 'cdntaxreceipts/receiptsissued'])['values'];
$this->assertEquals([
[
'civicrm_contact_sort_name' => 'Miller, Joe',
'civicrm_contact_id' => $contact_id,
'civicrm_cdntaxreceipts_log_issued_on' => $datestr,
'civicrm_cdntaxreceipts_log_receipt_amount' => '10.00',
'civicrm_cdntaxreceipts_log_receipt_no' => 'C-00000001',
'civicrm_cdntaxreceipts_log_issue_type' => 'Single',
'civicrm_cdntaxreceipts_log_issue_method' => 'Print',
'civicrm_cdntaxreceipts_log_uid' => 1,
'civicrm_cdntaxreceipts_log_receipt_status' => 'Issued',
'civicrm_cdntaxreceipts_log_email_opened' => NULL,
'civicrm_cdntaxreceipts_log_contributions_contribution_id' => 1,
'civicrm_contact_sort_name_link' => '/index.php?q=civicrm/contact/view&amp;reset=1&amp;cid=' . $contact_id,
'civicrm_contact_sort_name_hover' => 'View Contact Summary for this Contact',
]
], $data);
}
/**
* Test optional columns with one line item.
*/
public function testFinancialTypeSingle() {
// create contribution
$contact_id = $this->individualCreate([], 1);
$datestr = date('Y-m-d');
$contribution_id = civicrm_api3('Contribution', 'create', [
'contact_id' => $contact_id,
'financial_type_id' => 'Donation',
'total_amount' => '10',
'receive_date' => $datestr,
])['id'];
// Need it in DAO format
$contribution = new CRM_Contribute_DAO_Contribution();
$contribution->id = $contribution_id;
$contribution->find(TRUE);
// issue receipt
list($result, $method) = cdntaxreceipts_issueTaxReceipt($contribution);
// run report
$data = civicrm_api3('report_template', 'getrows', [
'report_id' => 'cdntaxreceipts/receiptsissued',
'fields' => [
'sort_name' => 1,
'issued_on' => 1,
'receipt_amount' => 1,
'receipt_no' => 1,
'issue_type' => 1,
'issue_method' => 1,
'uid' => 1,
'receipt_status' => 1,
'email_opened' => 1,
'contribution_id' => 1,
'financial_type_id' => 1,
'payment_instrument_id' => 1,
],
])['values'];
$this->assertEquals([
[
'civicrm_contact_sort_name' => 'Miller, Joe',
'civicrm_contact_id' => $contact_id,
'civicrm_cdntaxreceipts_log_issued_on' => $datestr,
'civicrm_cdntaxreceipts_log_receipt_amount' => '10.00',
'civicrm_cdntaxreceipts_log_receipt_no' => 'C-00000001',
'civicrm_cdntaxreceipts_log_issue_type' => 'Single',
'civicrm_cdntaxreceipts_log_issue_method' => 'Print',
'civicrm_cdntaxreceipts_log_uid' => 1,
'civicrm_cdntaxreceipts_log_receipt_status' => 'Issued',
'civicrm_cdntaxreceipts_log_email_opened' => NULL,
'civicrm_cdntaxreceipts_log_contributions_contribution_id' => 1,
'civicrm_line_item_financial_type_id' => 'Donation',
'civicrm_contribution_payment_instrument_id' => 'Check',
'civicrm_contact_sort_name_link' => '/index.php?q=civicrm/contact/view&amp;reset=1&amp;cid=' . $contact_id,
'civicrm_contact_sort_name_hover' => 'View Contact Summary for this Contact',
]
], $data);
}
}
......@@ -16,11 +16,13 @@ class ReceiptsIssuedReportTest extends CdntaxreceiptsBase {
parent::setUp();
$this->createUserAndLogIn();
$this->contact = $this->createContact();
$this->setDeliveryMethod(CDNTAX_DELIVERY_PRINT_ONLY);
}
/**
* Basic test with defaults.
*/
public function testReport() {
$this->setDeliveryMethod(CDNTAX_DELIVERY_PRINT_ONLY);
$contribution = civicrm_api3('Contribution', 'create', [
'contact_id' => $this->contact['id'],
'financial_type_id' => 'Donation',
......@@ -28,30 +30,198 @@ class ReceiptsIssuedReportTest extends CdntaxreceiptsBase {
'receive_date' => date('Y-m-d'),
]);
// go to the contribution
$this->drupalGet(\CRM_Utils_System::url("civicrm/contact/view/contribution", "reset=1&id={$contribution['id']}&cid={$this->contact['id']}&action=view", TRUE, NULL, FALSE));
$this->issueReceipt($contribution['id'], $this->contact['id']);
// go to the report
$this->drupalGet(\CRM_Utils_System::url('civicrm/report/cdntaxreceipts%3Areceiptsissued', 'reset=1', TRUE, NULL, FALSE));
$this->assertPageHasNoErrorMessages();
// click the tax receipt button
$this->getSession()->getPage()->pressButton('Tax Receipt');
// click the button
$this->getSession()->getPage()->pressButton('_qf_ReceiptsIssued_submit');
$this->htmlOutput();
$this->assertPageHasNoErrorMessages();
$this->assertSession()->waitForElementVisible('css', '.crm-button_qf_ViewTaxReceipt_next');
$this->getSession()->getPage()->pressButton('_qf_ViewTaxReceipt_next-bottom');
$this->assertSession()->pageTextContains('Tax Receipts - Receipts Issued');
$this->assertSession()->pageTextContains('C-00000001');
$this->assertSession()->pageTextContains('Total Amount Issued');
$this->assertSession()->pageTextContains('$ 10.00');
}
/**
* Test optional columns with one line item.
*/
public function testFinancialTypeSingle() {
$contribution = civicrm_api3('Contribution', 'create', [
'contact_id' => $this->contact['id'],
'financial_type_id' => 'Donation',
'total_amount' => '10',
'receive_date' => date('Y-m-d'),
]);
$this->issueReceipt($contribution['id'], $this->contact['id']);
// go to the report
$this->drupalGet(\CRM_Utils_System::url('civicrm/report/cdntaxreceipts%3Areceiptsissued', 'reset=1', TRUE, NULL, FALSE));
$this->assertPageHasNoErrorMessages();
// select the financial type and payment method columns
$this->getSession()->getPage()->checkField('fields_financial_type_id');
$this->getSession()->getPage()->checkField('fields_payment_instrument_id');
$this->htmlOutput();
// click the button
$this->getSession()->getPage()->pressButton('_qf_ReceiptsIssued_submit');
$this->htmlOutput();
$this->assertPageHasNoErrorMessages();
$this->assertSession()->pageTextContains('Financial Type (current value)');
$this->assertSession()->pageTextContains('Donation');
$this->assertSession()->pageTextContains('Payment Method (current value)');
$this->assertSession()->pageTextContains('Check');
}
/**
* Test optional columns with two line items.
*/
public function testFinancialTypeMultiple() {
$priceFields = $this->createPriceSet();
$contribution_id = $this->createContributionFromPriceFields($priceFields);
$this->issueReceipt($contribution_id, $this->contact['id']);
// go to the report
$this->drupalGet(\CRM_Utils_System::url('civicrm/report/cdntaxreceipts%3Areceiptsissued', 'reset=1', TRUE, NULL, FALSE));
$this->assertPageHasNoErrorMessages();
// select the financial type and payment method columns
$this->getSession()->getPage()->checkField('fields_financial_type_id');
$this->getSession()->getPage()->checkField('fields_payment_instrument_id');
// click the button
$this->getSession()->getPage()->pressButton('_qf_ReceiptsIssued_submit');
$this->htmlOutput();
$this->assertPageHasNoErrorMessages();
$this->assertSession()->pageTextContains('Tax Receipts - Receipts Issued');
$this->assertSession()->pageTextContains('C-00000001');
$this->assertSession()->pageTextContains('Total Amount Issued');
$this->assertSession()->pageTextContains('Financial Type (current value)');
$this->assertSession()->pageTextContains('Event Fee, Donation');
$this->assertSession()->pageTextContains('Payment Method (current value)');
$this->assertSession()->pageTextContains('Check');
// Amount should only be the donation part
// @todo how do you check that this is in the right spot? It's in a cell
// in a table, but might appear somewhere else too giving a false positive.
$this->assertSession()->pageTextContains('$ 10.00');
}
/**
* Helper to click the buttons.
*
* @param int $contribution_id
* @param int $contact_id
*/
private function issueReceipt(int $contribution_id, int $contact_id) {
// go to the contribution
$this->drupalGet(\CRM_Utils_System::url("civicrm/contact/view/contribution", "reset=1&id={$contribution_id}&cid={$contact_id}&action=view", TRUE, NULL, FALSE));
$this->htmlOutput();
$this->assertPageHasNoErrorMessages();
// click the tax receipt button
$this->getSession()->getPage()->pressButton('Tax Receipt');
$this->assertPageHasNoErrorMessages();
$this->assertSession()->waitForElementVisible('css', '.crm-button_qf_ViewTaxReceipt_next');
$this->getSession()->getPage()->pressButton('_qf_ViewTaxReceipt_next-bottom');
$this->assertPageHasNoErrorMessages();
}
/**
* Make a price set with an event component and a donation component.
* Partly copied from CiviUnitTestCase.
* @return array
*/
private function createPriceSet(): array {
$paramsSet['title'] = 'Price Set' . substr(sha1(rand()), 0, 7);
$paramsSet['name'] = \CRM_Utils_String::titleToVar($paramsSet['title']);
$paramsSet['is_active'] = TRUE;
$paramsSet['financial_type_id'] = 'Event Fee';
$paramsSet['extends'] = 1;
$priceSet = civicrm_api3('price_set', 'create', $paramsSet);
$paramsField = [
'label' => 'Price Field',
'name' => \CRM_Utils_String::titleToVar('Price Field'),
'html_type' => 'Radio',
'option_label' => ['1' => 'Price Field 1', '2' => 'Price Field 2'],
'option_value' => ['1' => 75, '2' => 100],
'option_name' => ['1' => 'Price Field 1', '2' => 'Price Field 2'],
'option_weight' => ['1' => 1, '2' => 2],
'option_amount' => ['1' => 75, '2' => 100],
'is_display_amounts' => 1,
'weight' => 1,
'options_per_line' => 1,
'is_active' => ['1' => 1, '2' => 1],
'price_set_id' => $priceSet['id'],
'is_enter_qty' => 0,
'financial_type_id' => \CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', 'Event Fee', 'id', 'name'),
];
$priceField = \CRM_Price_BAO_PriceField::create($paramsField);
$returnValue = [civicrm_api3('PriceFieldValue', 'get', ['price_field_id' => $priceField->id])];
$paramsField = [
'label' => 'Donation Field',
'name' => \CRM_Utils_String::titleToVar('Donation Field'),
'html_type' => 'Radio',
'option_label' => ['1' => 'Donation Field 1', '2' => 'Donation Field 2'],
'option_value' => ['1' => 10, '2' => 20],
'option_name' => ['1' => 'Donation Field 1', '2' => 'Donation Field 2'],
'option_weight' => ['1' => 1, '2' => 2],
'option_amount' => ['1' => 10, '2' => 20],
'is_display_amounts' => 1,
'weight' => 1,
'options_per_line' => 1,
'is_active' => ['1' => 1, '2' => 1],
'price_set_id' => $priceSet['id'],
'is_enter_qty' => 0,
'financial_type_id' => \CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialType', 'Donation', 'id', 'name'),
];
$priceField = \CRM_Price_BAO_PriceField::create($paramsField);
$returnValue[] = civicrm_api3('PriceFieldValue', 'get', ['price_field_id' => $priceField->id]);
return $returnValue;
}
/**
* Kind of copied from CRMTraits_Financial_PriceSetTrait
* @param array $priceFields
* @return int
*/
private function createContributionFromPriceFields(array $priceFields): int {
$params = [
'contact_id' => $this->contact['id'],
'total_amount' => 85,
'financial_type_id' => 'Event Fee',
'contribution_status_id' => 'Pending',
];
foreach ($priceFields as $pf) {
foreach ($pf['values'] as $key => $priceField) {
$params['line_items'][]['line_item'][$key] = [
'price_field_id' => $priceField['price_field_id'],
'price_field_value_id' => $priceField['id'],
'label' => $priceField['label'],
'field_title' => $priceField['label'],
'qty' => 1,
'unit_price' => $priceField['amount'],
'line_total' => $priceField['amount'],
'financial_type_id' => $priceField['financial_type_id'],
'entity_table' => 'civicrm_contribution',
];
// just use the first option for each field
break;
}
}
$order = civicrm_api3('Order', 'create', $params);
civicrm_api3('Payment', 'create', [
'contribution_id' => $order['id'],
'total_amount' => $params['total_amount'],
]);
return $order['id'];
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment