Add create invoice page to members billing
authorSteve Sutton <steve@gaslightmedia.com>
Wed, 9 Jan 2019 21:45:16 +0000 (16:45 -0500)
committerSteve Sutton <steve@gaslightmedia.com>
Wed, 9 Jan 2019 21:45:16 +0000 (16:45 -0500)
This is to add an invoice from members billing tab.
Prorating the invoice.
WIP - prorate

classes/billingSupport.php
models/admin/member/billing.php
setup/commonHooks.php
views/admin/billing/createInvoice.html [new file with mode: 0644]
views/admin/billing/memberBillingSubHeader.html

index bf7c836..b81e23b 100644 (file)
@@ -1865,5 +1865,79 @@ class GlmBillingSupport
         return true;
     }
 
+    /**
+     * Returns a timestamp of current invoice date if there's settings for invoice date
+     */
+    public function getCurrentInvoiceDate()
+    {
+        $currentInvoiceDate = false;
+        $renewalDayStatic = $this->config['settings']['renewal_day_static'];
+        $renewalDay       = $this->config['settings']['renewal_day'];
+        $renewalMonth     = $this->config['settings']['renewal_month'];
+        if ( $renewalDayStatic && $renewalDay && $renewalMonth ) {
+            $currentInvoiceDate = mktime( 0, 0, 1, $renewalMonth, $renewalDay, date( 'Y' ) );
+            if ( $currentInvoiceDate > time() ) {
+                $currentInvoiceDate = mktime( 0, 0, 1, $renewalMonth, $renewalDay, date( 'Y' ) - 1 );
+            }
+        }
+        return $currentInvoiceDate;
+    }
+    /**
+     * Returns a timestamp of next invoice date if there's settings for invoice date
+     */
+    public function getNextInvoiceDate()
+    {
+        $nextInvoiceDate = false;
+        $renewalDayStatic = $this->config['settings']['renewal_day_static'];
+        $renewalDay       = $this->config['settings']['renewal_day'];
+        $renewalMonth     = $this->config['settings']['renewal_month'];
+        if ( $renewalDayStatic && $renewalDay && $renewalMonth ) {
+            $nextInvoiceDate = mktime( 12, 59, 59, $renewalMonth, $renewalDay, date( 'Y' ) );
+            if ( $nextInvoiceDate <= time() ) {
+                $nextInvoiceDate = mktime( 12, 59, 59, $renewalMonth, $renewalDay, date( 'Y' ) + 1 );
+            }
+        }
+        return $nextInvoiceDate;
+    }
+    /**
+     * Get a prorated price for this member based on the date field from
+     * the form (billing) submit
+     *
+     * @param array  $invoiceData   Member Data
+     * @param string $date          The date for pro rating
+     * @param string $dynamicAmount The dynamic amount to use
+     *
+     * @return float
+     */
+    public function getProRatedPrice( $invoiceData, $date, $dynamicAmount )
+    {
+        $nextInvoiceDate = $this->getNextInvoiceDate();
+        $invDate         = new DateTime( date( 'c', $nextInvoiceDate ) );
+        if (   $invoiceData['dynamic_amount'] && filter_var( $dynamicAmount, FILTER_VALIDATE_FLOAT ) ) {
+            return (float)$dynamicAmount;
+        }
+        $transactionDate = new DateTime( date( 'c', strtotime( $date ) ) );
+        // Need to know when the invDate is before or after the transactionDate
+        $dateInterval = date_diff( $invDate, $transactionDate );
+        // echo '<pre>$dateInterval: ' . print_r( $dateInterval, true ) . '</pre>';
+        $cDate = date_diff( $invDate, $nextInvoiceDate );
+        if ( $cDate->invert ) {
+            return (float)$invoiceData['amount'];
+        } else if ( !$cDate->invert ) {
+            // pro-rated for next year
+            // increase the invoice date by one year
+            $timestamp = $invDate->getTimestamp();
+            $nextYear  = strtotime( '+ 1 year', $timestamp );
+            if ($nextYear) {
+                $invDate = new DateTime( date( 'c', $nextYear ) );
+            }
+        } else if ($cDate == 1) {
+            return $invoiceData['amount'];
+        }
+        // Get the number of days difference
+        $days = round( $cDate->days );
+        $dailyPrice = (float)( $invoiceData['amount'] / 365 );
+        return (float)round( ( $days * $dailyPrice ), 2 );
+    }
 }
 
index ee8ece7..c9f2732 100644 (file)
@@ -135,6 +135,9 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
         $lockedWhereT   = 'true';
         $lockedWhere    = 'true';
 
+        // For invoice create page
+        $nextInvoiceDate = false;
+
         // Call in the support class
         $BillingSupport = new GlmBillingSupport( $this->wpdb, $this->config );
 
@@ -196,24 +199,135 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
         $account_status = apply_filters( 'glm-billing-get-account-status', '', $accountID );
 
         switch ( $option ) {
+        case 'createInvoice':
+
+
+            $dateOne = '10/01/2019';
+            $dateTwo = '10/01/2019';
+            echo '<pre>$dateTwo: ' . print_r( $dateTwo, true ) . '</pre>';
+            $nextDate = $BillingSupport->getNextInvoiceDate();
+            $nextD = date( 'm/d/Y', $nextDate );
+            echo '<pre>$nextD: ' . print_r( $nextD, true ) . '</pre>';
+
+            $dateInt = date_diff( new DateTime( $nextD ), new DateTime( $dateTwo ) );
+            echo '<pre>$dateInt: ' . print_r( $dateInt, true ) . '</pre>';
+
+            $view            = 'createInvoice';
+            $nextInvoiceDate = $BillingSupport->getNextInvoiceDate();
+            if ( $nextInvoiceDate ) {
+                $nextInvoiceDate = date( 'm/d/Y', $nextInvoiceDate );
+            }
+
+            // Get list of payable invoice_types
+            $payable_types = $BillingSupport->getAllPayableInvoiceTypes();
+
+            // Load DataClass for Management.
+            require_once GLM_MEMBERS_BILLING_PLUGIN_CLASS_PATH . '/data/dataManagement.php';
+            $Management = new GlmDataBillingManagement( $this->wpdb, $this->config );
+            $management = $Management->getEntry( 1 );
+
+            // Need to see if there's an account for this member.
+            require_once GLM_MEMBERS_BILLING_PLUGIN_CLASS_PATH . '/data/dataAccounts.php';
+            $account = $Accounts->editEntry( $accountID );
+            if ( $account && $account['fieldData'] ) {
+                $invoiceTypeId = $account['fieldData']['invoice_type'];
+
+                if ( $invoiceTypeId ) {
+                    $member_invoice = $BillingSupport->getInvoiceTypeById( $invoiceTypeId );
+                }
+            }
+
+            $invoiceTypes = $BillingSupport->getAllPayableInvoiceTypes();
+
+            break;
+
+        case 'createNewInvoice':
+            $view = 'createInvoice';
+            // echo '<pre>$_REQUEST: ' . print_r( $_REQUEST, true ) . '</pre>';
+
+            $memberId      = filter_var( $_REQUEST['member'], FILTER_VALIDATE_INT );
+            $accountId     = filter_var( $_REQUEST['account_id'], FILTER_VALIDATE_INT );
+            $dynamicAmount = filter_var( $_REQUEST['dynamic_amount'], FILTER_VALIDATE_FLOAT );
+            $invoiceDate   = filter_var( $_REQUEST['invoice_date'], FILTER_SANITIZE_STRING );
+
+            // echo '<pre>$memberId: ' . print_r( $memberId, true ) . '</pre>';
+            // echo '<pre>$accountId: ' . print_r( $accountId, true ) . '</pre>';
+            // echo '<pre>$dynamicAmount: ' . print_r( $dynamicAmount, true ) . '</pre>';
+            // echo '<pre>$invoiceDate: ' . print_r( $invoiceDate, true ) . '</pre>';
+
+            $Accounts = new GlmDataAccounts( $this->wpdb, $this->config );
+            $account = $Accounts->editEntry( $accountID );
+            if ( $account && $account['fieldData']['invoice_type'] ) {
+                $invoiceTypeId = $account['fieldData']['invoice_type'];
+            }
+            // echo '<pre>$invoiceTypeId: ' . print_r( $invoiceTypeId, true ) . '</pre>';
+
+            // Create an invoice w/line item for this accounts payment type
+            if ( $invoiceTypeId && $memberId && $accountId ) {
+                $invoiceData = $BillingSupport->getInvoiceTypeById( $invoiceTypeId );
+                // Amount maybe pro-rated
+                $amount = $BillingSupport->getProRatedPrice( $invoiceData, $invoiceData, $dynamicAmount );
+                // Create invoice.
+                $this->wpdb->insert(
+                    GLM_MEMBERS_BILLING_PLUGIN_DB_PREFIX . 'invoices',
+                    array(
+                        'transaction_time' => date( 'Y-m-d H:i:s' ),
+                        'account'          => $accountId,
+                        'amount_total'     => $amount,
+                        'balance'          => $amount,
+                        'due_date'         => date( 'Y-m-d', strtotime( $invoiceDate ) ),
+                        'paid'             => 0,
+                        'notes'            => '',
+                        'renewal'          => true,
+                        'recurring'        => true,
+                        'recurrence'       => 20
+                    ),
+                    array(
+                        '%s', // transaction_time
+                        '%d', // account
+                        '%s', // amount
+                        '%s', // balance
+                        '%s', // due_date
+                        '%s', // paid
+                        '%s', // notes
+                        '%s', // renewal
+                        '%s', // recurring
+                        '%s', // recurrence
+                    )
+                );
+                $invoiceId = $this->wpdb->insert_id;
+                $BillingSupport->createLineItemForInvoice(
+                    array(
+                        'invoice_id'     => $invoiceId,
+                        'line_item_type' => $invoiceData['id'],
+                        'account'        => $accountId,
+                        'name'           => $invoiceData['name'],
+                        'amount'         => $amount,
+                        'due_date'       => date( 'Y-m-d', strtotime( $invoiceDate ) ),
+                        'recurring'      => $invoiceData['recurring'],
+                        'recurrence'     => $invoiceData['recurrence'],
+                    )
+                );
+                $BillingSupport->recordInvoice( $invoiceId, $accountId, $amount );
+            }
+
+            break;
+
         case 'renew':
             $view = 'renew';
 
             // Get list of payable invoice_types
             $payable_types = $BillingSupport->getAllPayableInvoiceTypes();
-            // echo '<pre>$payable_types: ' . print_r( $payable_types, true ) . '</pre>';
 
             $member_invoice_id = $BillingSupport->getMembersInvoiceTypeByRefDest( $this->memberID );
             if ( $member_invoice_id ) {
                 $member_invoice = $BillingSupport->getInvoiceTypeById( $member_invoice_id );
             }
-            // echo '<pre>$member_invoice: ' . print_r( $member_invoice, true ) . '</pre>';
 
             // TODO: If there's no member_invoice then we can't create an invoice for renewal.
 
             // Get a list of this accounts employees. If they have any.
             $employees = $BillingSupport->getListOfAccountEmployees( $this->memberID );
-            // echo '<pre>$employees: ' . print_r( $employees, true ) . '</pre>';
 
             // Load DataClass for Management.
             require_once GLM_MEMBERS_BILLING_PLUGIN_CLASS_PATH . '/data/dataManagement.php';
@@ -227,10 +341,8 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
             // Need to get the accounts
             $Accounts = new GlmDataAccounts( $this->wpdb, $this->config );
             $accounts = $Accounts->getSimpleAccountList( "T.boss <> true AND T.boss IS NOT NULL AND T.invoice_type != 0", 'ref_name' );
-            // echo '<pre>$accounts: ' . print_r( $accounts, true ) . '</pre>';
 
             $invoiceTypes = $BillingSupport->getAllPayableInvoiceTypes();
-            // echo '<pre>$invoiceTypes: ' . print_r( $invoiceTypes, true ) . '</pre>';
 
             break;
 
@@ -409,9 +521,6 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
             $InvoiceTypesObj = new GlmDataInvoiceTypes( $this->wpdb, $this->config );
             $invoiceTypes    = $InvoiceTypesObj->getList();
 
-            // echo '<pre>$invoiceTypes: ' . print_r( $invoiceTypes, true ) . '</pre>';
-
-
             // Need to see if there's an account for this member.
             $accountID = $this->wpdb->get_var(
                 $this->wpdb->prepare(
@@ -422,22 +531,6 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
                 )
             );
 
-            // $contactID = $this->wpdb->get_var(
-            //     $this->wpdb->prepare(
-            //         "SELECT id
-            //            FROM " . GLM_MEMBERS_CONTACTS_PLUGIN_DB_PREFIX . "contacts
-            //           WHERE ref_dest = %d",
-            //         $this->memberID
-            //     )
-            // );
-            // echo '<pre>$contactID: ' . print_r( $contactID, true ) . '</pre>';
-            // require_once GLM_MEMBERS_CONTACTS_PLUGIN_CLASS_PATH . '/data/dataContacts.php';
-            // $Contact = new GlmDataContacts( $this->wpdb, $this->config );
-            // $user_id = $Contact->getWPUserId( $contactID );
-            // echo '<pre>$user_id: ' . print_r( $user_id, true ) . '</pre>';
-            // $Contact->updateContactRole( $contactID, 'glm_members_member_contact', 'glm_members_own_entity_manager' );
-
-            // echo '<pre>$accountID: ' . print_r( $accountID, true ) . '</pre>';
             // Grab the employee data
             if ( $accountID ) {
                 // Get a list of this accounts employees. If they have any.
@@ -448,7 +541,6 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
             // Check to see if we're adding an account or editing one.
             if ( isset( $_REQUEST['ref_name'] ) ) {
                 $_REQUEST['anniversary_date'] = date('Y-m-d', strtotime($_REQUEST['anniversary_date']));
-                // echo '<pre>$_REQUEST: ' . print_r( $_REQUEST, true ) . '</pre>';
                 // if there's no id then add account.
                 if ( !isset( $_REQUEST['id'] ) ) {
                     $account = $Accounts->insertEntry();
@@ -516,7 +608,6 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
                         unset( $employees[$employee_id] );
                     }
                 }
-                // echo '<pre>$employees: ' . print_r( $employees, true ) . '</pre>';
                 // If there's employees data then add them to this account
                 if ( isset($accountID) && $accountID && isset( $_REQUEST['employees'] ) && is_array( $_REQUEST['employees'] ) && !empty( $_REQUEST['employees'] ) ) {
                     foreach ( $_REQUEST['employees'] as $employee_id => $hasKey ) {
@@ -793,6 +884,7 @@ class GlmMembersAdmin_member_billing // extends GlmDataBilling
             'invoiceTypes'       => $invoiceTypes,
             'paymentMethods'     => $this->config['alt_payment_method'],
             'renewalFormSession' => $renewalFormSession,
+            'nextInvoiceDate'    => $nextInvoiceDate,
         );
 
         // Return status, any suggested view, and any data to controller.
index 6dc155d..533bd2c 100644 (file)
@@ -106,3 +106,26 @@ add_filter( 'glm-billing-account-has-renewal', function( $content, $account_id )
         )
     );
 }, 10, 2 );
+
+add_filter( 'glm-billing-account-has-invoice', function( $content, $account_id ){
+    $hasInvoice = false;
+
+    require_once GLM_MEMBERS_BILLING_PLUGIN_CLASS_PATH.'/billingSupport.php';
+    $BillingSupport     = new GlmBillingSupport( $this->wpdb, $this->config );
+    $currentInvoiceDate = $BillingSupport->getCurrentInvoiceDate();
+    $nextInvoiceDate    = $BillingSupport->getNextInvoiceDate();
+    if ( $currentInvoiceDate && $nextInvoiceDate ) {
+        $hasInvoice = $this->wpdb->get_var(
+            $this->wpdb->prepare(
+                "SELECT count(id)
+                   FROM " . GLM_MEMBERS_BILLING_PLUGIN_DB_PREFIX  . "invoices
+                  WHERE account = %d
+                    AND due_date BETWEEN %s and %s",
+                $account_id,
+                date( 'Y-m-d' , $currentInvoiceDate ),
+                date( 'Y-m-d', $nextInvoiceDate )
+            )
+        );
+    }
+    return $hasInvoice;
+}, 10, 2 );
diff --git a/views/admin/billing/createInvoice.html b/views/admin/billing/createInvoice.html
new file mode 100644 (file)
index 0000000..218b4e2
--- /dev/null
@@ -0,0 +1,78 @@
+{include file='admin/member/header.html'}
+{include file='admin/billing/memberBillingSubHeader.html'}
+
+<h3>Membership Renewal</h3>
+<div id="billing-payment-form" class="glm-billing-form">
+
+    {if $paymentSuccess}<span class="glm-notice glm-flash-updated">Payment Completed</span>{/if}
+    {if $paymentError}<span class="glm-notice glm-flash-updated">Error With Payment</span>{/if}
+
+    {if $messages}
+        {foreach $messages as $message}
+            <div class="">{$message}</div>
+        {/foreach}
+    {/if}
+
+    <form action="{$thisUrl}?page={$thisPage}" method="post" onSubmit="return checkForm(this);">
+        <input type="hidden" name="page" value="{$thisPage}" />
+        <input type="hidden" name="glm_action" value="billing" />
+        <input type="hidden" name="option" value="createNewInvoice" />
+        <input type="hidden" name="member" value="{$memberID}" />
+        <input type="hidden" name="account_id" value="{$account_data.id}" />
+
+        {if $member_invoice}
+        <div class="glm-billing-field">
+            <div class="glm-billing-label glm-required">
+                Payment Type
+            </div>
+            <div class="glm-billing-input">
+                {$member_invoice.name} ${$member_invoice.amount}
+            </div>
+        </div>
+        <div>
+            <div class="glm-billing-label glm-required">
+                Invoice Date
+            </div>
+            <div class="glm-billing-input">
+                <input name="invoice_date" value="{$nextInvoiceDate}" required />
+            </div>
+        </div>
+        <div>
+            <div class="glm-billing-label{if isset($member_invoice.dynamic_amount) && $member_invoice.dynamic_amount} glm-required{/if}">
+                Dynamic Amount (dollar amount without $)
+            </div>
+            <div class="glm-billing-input">
+                <input name="dynamic_amount" pattern="{literal}^\d+(?:\.\d{0,2})?${/literal}"{if isset($member_invoice.dynamic_amount) && $member_invoice.dynamic_amount} required{/if} />
+            </div>
+        </div>
+        {/if}
+
+        <input class="button button-primary" type="submit" name="renewal_submit" id="renewal_submit" value="Create New Invoice" />
+
+    </form>
+</div>
+
+<script>
+function checkForm( form )
+{
+    form.renewal_submit.disabled = true;
+    form.renewal_submit.value = 'Processing...';
+    return true;
+}
+
+jQuery(document).ready(function($){
+
+    // Setup the date picker for the input field with the name invoice_date
+    $('input[name="invoice_date"]').datepicker({
+        dateFormat: 'mm/dd/yy',
+        defaultDate: '{$nextInvoiceDate}'
+    });
+
+    // Flash certain elements for a short time after display
+    $(".glm-flash-updated").fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500);
+
+});
+</script>
+
+
+{include file='admin/footer.html'}
index 7365fbb..6545521 100644 (file)
                 </li>
             {/if}
             {if isset( $billing_settings.uptravel_payment_form ) && $billing_settings.uptravel_payment_form}
+                {$hasInvoice = apply_filters('glm-billing-account-has-invoice', false, $accountID )}
                 <li>
-                    <a href="{$thisUrl}?page=glm-members-admin-menu-member&glm_action=billing&member={$memberID}&option=makepaymentadjustment">Make A Payment</a>
+                    {if $hasInvoice}
+                        <a href="{$thisUrl}?page=glm-members-admin-menu-member&glm_action=billing&member={$memberID}&option=makepaymentadjustment">Make A Payment</a>
+                    {else}
+                        <a href="{$thisUrl}?page=glm-members-admin-menu-member&glm_action=billing&member={$memberID}&option=createInvoice">Create Invoice</a>
+                    {/if}
                 </li>
             {else}
                 <li>