From bc15e9e42adf45264a9e12d7811535f1c47689cd Mon Sep 17 00:00:00 2001 From: Jon Goldberg Date: Wed, 18 Sep 2019 15:43:12 -0400 Subject: [PATCH] include support for defining custom invoice date, due date, period begin and end --- CRM/Tbusainvoicegen/Timebank.php | 134 +++++++++++++++++++++++-------- api/v3/Invoicegen/Generate.php | 9 ++- 2 files changed, 106 insertions(+), 37 deletions(-) diff --git a/CRM/Tbusainvoicegen/Timebank.php b/CRM/Tbusainvoicegen/Timebank.php index 8250705..e2a8ff7 100644 --- a/CRM/Tbusainvoicegen/Timebank.php +++ b/CRM/Tbusainvoicegen/Timebank.php @@ -7,12 +7,20 @@ class CRM_Tbusainvoicegen_Timebank { const BILLABLEMEMBERFIELD = 'custom_236'; const BILLINGPERIODFIELD = 'custom_228'; const TBCREATED = 'custom_114'; + const INVOICEDATE = 'custom_244'; + const DUEDATE = 'custom_245'; + const PERIODBEGIN = 'custom_246'; + const PERIODEND = 'custom_247'; // Local dev settings. -// const TBBILLABLEFIELD = 'custom_9'; -// const BILLABLEMEMBERFIELD = 'custom_10'; -// const BILLINGPERIODFIELD = 'custom_11'; -// const TBCREATED = 'custom_27'; +// const TBBILLABLEFIELD = 'custom_9'; +// const BILLABLEMEMBERFIELD = 'custom_10'; +// const BILLINGPERIODFIELD = 'custom_11'; +// const TBCREATED = 'custom_27'; +// const INVOICEDATE = 'custom_30'; +// const DUEDATE = 'custom_31'; +// const PERIODBEGIN = 'custom_32'; +// const PERIODEND = 'custom_33'; /** * Set the pricing here. @@ -59,6 +67,30 @@ class CRM_Tbusainvoicegen_Timebank { */ private $creationDate; + /** + * The date the invoice is generated. + * @var DateTime + */ + private $invoiceDate; + + /** + * The date the invoice is due. + * @var DateTime + */ + private $invoiceDueDate; + + /** + * The date the invoice period begins. + * @var DateTime + */ + private $periodBegin; + + /** + * The date the invoice period begins. + * @var DateTime + */ + private $periodEnd; + /** * An array of all the contact IDs for whom a contribution already exists in this billing period. * @var array @@ -86,7 +118,14 @@ class CRM_Tbusainvoicegen_Timebank { * @param str $billingPeriod The billing period (e.g "2019-2" for the second 2019 payment) * @return array APIv3 standard response. */ - public static function generate($cid = NULL, $billingPeriod = NULL) { + public static function generate($params) { + $cid = $billingPeriod = NULL; + if (isset($params['contact_id'])) { + $cid = $params['contact_id']; + } + if (isset($params['billing_period'])) { + $billingPeriod = $params['billing_period']; + } self::setBillingPeriod($billingPeriod); // Get a list of contact IDs for everyone to generate an invoice for. $contacts = civicrm_api3('Contact', 'get', [ @@ -105,6 +144,9 @@ class CRM_Tbusainvoicegen_Timebank { continue; } $tb->creationDate = new DateTime($contact[self::TBCREATED]); + $tb->setInvoiceDate($params); + $tb->setDueDate($params); + $tb->setPeriodBeginEndDate($params); $tb->setPrice(); $tb->createContribution(); } @@ -152,6 +194,18 @@ class CRM_Tbusainvoicegen_Timebank { return $this->price; } + /** + * Sets the due date + */ + private function setInvoiceDate($params = []) { + if (isset($params['invoice_date'])) { + $this->invoiceDate = new DateTime($params['invoice_date']); + } + else { + $this->invoiceDate = new DateTime(); + } + } + /** * If the first annual anniversary of the TB is before the billing period, then the TB pays for the full billing period (6 months). * If the first annual anniversary of the TB is during any of the first 5 months of the billing period, then the TB pays a pro-rated fee for the number of full billing period months after the first annual anniversary of the TB (1 to 5 months). @@ -160,7 +214,7 @@ class CRM_Tbusainvoicegen_Timebank { private function monthsProRated() { // By default, we bill all 6 months in a billing period. $monthsProRated = 6; - $beginDate = $this->calculatePeriodBeginDate(self::$billingPeriod); + $beginDate = $this->periodBegin; $firstAnniversary = $this->creationDate->modify("+1 year"); $interval = $beginDate->diff($firstAnniversary); // First anniversary is before the billing period. @@ -182,10 +236,12 @@ class CRM_Tbusainvoicegen_Timebank { if (!$this->price) { return; } - $dueDate = $this->calculateDueDate(self::$billingPeriod); civicrm_api3('Contribution', 'create', [ 'financial_type_id' => 'CW License Fee', - 'date_received' => $dueDate, + self::DUEDATE => $this->invoiceDueDate->format('Y-m-d'), + self::INVOICEDATE => $this->invoiceDate->format('Y-m-d'), + self::PERIODBEGIN => $this->periodBegin->format('Y-m-d'), + self::PERIODEND => $this->periodEnd->format('Y-m-d'), 'total_amount' => $this->price, 'contact_id' => $this->cid, 'contribution_status_id' => 'Pending', @@ -195,42 +251,51 @@ class CRM_Tbusainvoicegen_Timebank { } /** - * Returns the due date as a string. - * @return string + * Sets the due date */ - public static function calculateDueDate($billingPeriod) { - list($year, $number) = explode('-', $billingPeriod); - if ($number == 1) { - $dueDate = $year . '-03-31'; + private function setDueDate($params = []) { + if (isset($params['due_date'])) { + $this->invoiceDueDate = new DateTime($params['due_date']); } else { - $dueDate = $year . '-09-30'; + list($year, $number) = explode('-', self::$billingPeriod); + if ($number == 1) { + $this->invoiceDueDate = new DateTime($year . '-03-31'); + } + else { + $this->invoiceDueDate = new DateTime($year . '-09-30'); + } } - return $dueDate; } /** - * Returns the first day of the billing period as a date. - * This is to calculate the "new timebank" pro-rated value. - * @return Date + * Sets the period begin/end date. */ - private static function calculatePeriodBeginDate($billingPeriod) { - list($year, $number) = explode('-', $billingPeriod); - if ($number == 1) { - $beginDate = new DateTime($year . '-01-01'); + private function setPeriodBeginEndDate($params) { + if (isset($params['period_begin_date'])) { + $this->periodBegin = new DateTime($params['period_begin_date']); } else { - $beginDate = new DateTime($year . '-07-01'); + list($year, $number) = explode('-', self::$billingPeriod); + if ($number == 1) { + $this->periodBegin = new DateTime($year . '-01-01'); + } + else { + $this->periodBegin = new DateTime($year . '-07-01'); + } + } + if (isset($params['period_end_date'])) { + $this->periodEnd = new DateTime($params['period_end_date']); + } + else { + list($year, $number) = explode('-', self::$billingPeriod); + if ($number == 1) { + $this->periodEnd = new DateTime($year . '-06-30'); + } + else { + $this->periodEnd = new DateTime($year . '-12-31'); + } } - return $beginDate; - } - - public static function calculatePeriod($billingPeriod) { - $beginDate = self::calculatePeriodBeginDate($billingPeriod); - $endDate = clone $beginDate; - $endDate->add(new DateInterval('P6M'))->sub(new DateInterval('P1D')); - $period = $beginDate->format('n/j/Y') . '-' . $endDate->format('n/j/Y'); - return $period; } /** @@ -242,8 +307,7 @@ class CRM_Tbusainvoicegen_Timebank { * @param str $billingPeriod */ public static function invoiceData($contactId, $billingPeriod) { - $invoiceData[0] = self::calculateDueDate($billingPeriod); - $invoiceData[1] = self::calculatePeriod($billingPeriod); + self::setBillingPeriod($billingPeriod); $invoiceData[2] = self::calculateTotalDue($contactId); return $invoiceData; } diff --git a/api/v3/Invoicegen/Generate.php b/api/v3/Invoicegen/Generate.php index e0ee0fa..5358737 100644 --- a/api/v3/Invoicegen/Generate.php +++ b/api/v3/Invoicegen/Generate.php @@ -10,8 +10,13 @@ use CRM_Tbusainvoicegen_ExtensionUtil as E; * @see http://wiki.civicrm.org/confluence/display/CRMDOC/API+Architecture+Standards */ function _civicrm_api3_invoicegen_Generate_spec(&$spec) { - $spec['contact_id']['api.required'] = 1; + $spec['contact_id']['description'] = 'Specify a timebank\'s contact ID to generate the invoice for, or leave blank to select all active timebanks.'; + $spec['billing_period']['description'] = 'The year, a dash, and a 1 or 2 for the first or second half of the year. E.g. 2019-2 for 7/1/19-12/31/19.'; $spec['billing_period']['api.required'] = 1; + $spec['invoice_date']['description'] = 'Date of the invoice(s) to generate, or leave blank for today\'s date. Format as: 2019-7-25'; + $spec['due_date']['description'] = 'Due date of the invoice(s), or leave blank for March 31st/September 30th (based on billing period. Format as: 2019-7-25'; + $spec['period_begin_date']['description'] = 'Period begin date, or leave blank for January 1st/July 1st (based on billing period). Format as: 2019-7-25'; + $spec['period_end_date']['description'] = 'Period end date, or leave blank for June 30th/December 31st (based on billing period). Format as: 2019-7-25'; } /** @@ -24,6 +29,6 @@ function _civicrm_api3_invoicegen_Generate_spec(&$spec) { * @throws API_Exception */ function civicrm_api3_invoicegen_Generate($params) { - $returnValues = CRM_Tbusainvoicegen_Timebank::generate($params['contact_id'], $params['billing_period']); + $returnValues = CRM_Tbusainvoicegen_Timebank::generate($params); return civicrm_api3_create_success($returnValues, $params, 'Invoicegen', 'generate'); }