Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

@@ -2,9 +2,9 @@
/**
* @brief Invoices
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @subpackage Nexus
* @since 11 Feb 2014
* @version SVN_VERSION_NUMBER
@@ -98,8 +98,8 @@ class _invoices extends \IPS\Dispatcher\Controller
}
/* Display */
\IPS\Output::i()->title = $customer ? \IPS\Member::loggedIn()->language()->addToStack( 'members_invoices', FALSE, array( 'sprintf' => array( $customer->cm_name ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_payments_invoices');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( 'title', (string) $table );
\IPS\Output::i()->title = $customer ? \IPS\Member::loggedIn()->language()->addToStack( 'members_invoices', FALSE, array( 'sprintf' => array( $customer->cm_name ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_payments_invoices');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( 'title', (string) $table );
}
/**
@@ -123,7 +123,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$transactions = NULL;
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'transactions_manage' ) and ( !isset( \IPS\Request::i()->table ) ) )
{
$transactions = \IPS\nexus\Transaction::table( array( array( 't_invoice=?', $invoice->id ) ), $invoice->acpUrl(), 'i' );
$transactions = \IPS\nexus\Transaction::table( array( array( 't_invoice=? and t_status<>?', $invoice->id, \IPS\nexus\Transaction::STATUS_PENDING ) ), $invoice->acpUrl(), 'i' );
$transactions->limit = 50;
$transactions->tableTemplate = array( \IPS\Theme::i()->getTemplate('invoices'), 'transactionsTable' );
$transactions->rowsTemplate = array( \IPS\Theme::i()->getTemplate('invoices'), 'transactionsTableRows' );
@@ -219,7 +219,7 @@ class _invoices extends \IPS\Dispatcher\Controller
/* Any pending transactions? */
if ( !isset( \IPS\Request::i()->override ) and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'transactions_manage' ) )
{
$pendingTransactions = $invoice->transactions( array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW ) );
$pendingTransactions = $invoice->transactions( array( \IPS\nexus\Transaction::STATUS_WAITING, \IPS\nexus\Transaction::STATUS_HELD, \IPS\nexus\Transaction::STATUS_REVIEW, \IPS\nexus\Transaction::STATUS_GATEWAY_PENDING ) );
if ( count( $pendingTransactions ) )
{
$transUrl = $invoice->acpUrl();
@@ -248,7 +248,7 @@ class _invoices extends \IPS\Dispatcher\Controller
) );
/* Send Email */
\IPS\Email::buildFromTemplate( 'nexus', 'invoiceMarkedPaid', array( $invoice, $invoice->summary() ) )
\IPS\Email::buildFromTemplate( 'nexus', 'invoiceMarkedPaid', array( $invoice, $invoice->summary() ), \IPS\Email::TYPE_TRANSACTIONAL )
->send(
$invoice->member,
array_map(
@@ -276,7 +276,8 @@ class _invoices extends \IPS\Dispatcher\Controller
public function card()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'chargetocard' );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'customer.css', 'nexus', 'admin' ) );
/* Load Invoice */
try
{
@@ -305,7 +306,7 @@ class _invoices extends \IPS\Dispatcher\Controller
{
$amountToPay = $invoice->amountToPay()->amount;
$form = new \IPS\Helpers\Form( 'amount', 'continue' );
$form->add( new \IPS\Helpers\Form\Number( 't_amount', $amountToPay, TRUE, array( 'min' => 0.01, 'max' => $amountToPay, 'decimals' => TRUE ), NULL, NULL, $invoice->currency ) );
$form->add( new \IPS\Helpers\Form\Number( 't_amount', $amountToPay, TRUE, array( 'min' => 0.01, 'max' => (string) $amountToPay, 'decimals' => TRUE ), NULL, NULL, $invoice->currency ) );
if ( $values = $form->values() )
{
return $values;
@@ -321,7 +322,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$paymentMethodsToggles = array();
foreach ( $gateways as $gateway )
{
foreach ( $gateway->paymentScreen( $invoice, $amountToPay ) as $element )
foreach ( $gateway->paymentScreen( $invoice, $amountToPay, $invoice->member ) as $element )
{
if ( !$element->htmlId )
{
@@ -433,11 +434,11 @@ class _invoices extends \IPS\Dispatcher\Controller
$amountToPay = $invoice->amountToPay()->amount;
$credits = $invoice->member->cm_credits;
$credit = $credits[ $invoice->currency ]->amount;
$maxCanCharge = ( $credit < $amountToPay ) ? $credit : $amountToPay;
$maxCanCharge = ( $credit->compare( $amountToPay ) === -1 ) ? $credit : $amountToPay;
/* Build Form */
$form = new \IPS\Helpers\Form( 'amount', 'invoice_charge_to_credit' );
$form->add( new \IPS\Helpers\Form\Number( 't_amount', $maxCanCharge, TRUE, array( 'min' => 0.01, 'max' => $maxCanCharge, 'decimals' => TRUE ), NULL, NULL, $invoice->currency ) );
$form->add( new \IPS\Helpers\Form\Number( 't_amount', $maxCanCharge, TRUE, array( 'min' => 0.01, 'max' => (string) $maxCanCharge, 'decimals' => TRUE ), NULL, NULL, $invoice->currency ) );
/* Handle submissions */
if ( $values = $form->values() )
@@ -452,7 +453,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$transaction->approve( NULL );
$transaction->sendNotification();
$credits[ $invoice->currency ]->amount -= $values['t_amount'];
$credits[ $invoice->currency ]->amount = $credits[ $invoice->currency ]->amount->subtract( $transaction->amount->amount );
$invoice->member->cm_credits = $credits;
$invoice->member->save();
@@ -527,9 +528,24 @@ class _invoices extends \IPS\Dispatcher\Controller
{
\IPS\Output::i()->error( 'node_error', '2X190/D', 404, '' );
}
/* Get the address */
$address = NULL;
if ( $invoice->billaddress )
{
$address = $invoice->billaddress;
}
else
{
try
{
$address = \IPS\nexus\Customer\Address::constructFromData( \IPS\Db::i()->select( '*', 'nexus_customer_addresses', array( "member=? AND primary_billing=?", $invoice->member->member_id, 1 ) )->first() )->address;
}
catch( \UnderflowException $e ) {}
}
/* Get output */
$output = \IPS\Theme::i()->getTemplate( 'invoices', 'nexus', 'global' )->printInvoice( $invoice, $invoice->summary() );
$output = \IPS\Theme::i()->getTemplate( 'invoices', 'nexus', 'global' )->printInvoice( $invoice, $invoice->summary(), $address );
\IPS\Output::i()->title = 'I' . $invoice->id;
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->blankTemplate( $output ) );
}
@@ -585,7 +601,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$form->add( $field );
/* Partial refund? */
$field = new \IPS\Helpers\Form\Number( $transaction->id . '_refund_amount', ( $transaction->status === \IPS\nexus\Transaction::STATUS_PART_REFUNDED ? $transaction->amount->amount - $transaction->partial_refund->amount : 0 ), TRUE, array( 'unlimited' => 0, 'unlimitedLang' => \IPS\Member::loggedIn()->language()->addToStack( 'refund_full', FALSE, array( 'sprintf' => array( $transaction->amount ) ) ), 'max' => ( $transaction->amount->amount - $transaction->partial_refund->amount ), 'decimals' => TRUE ), NULL, NULL, $transaction->amount->currency, $transaction->id . '_refund_amount' );
$field = new \IPS\Helpers\Form\Number( $transaction->id . '_refund_amount', ( $transaction->status === \IPS\nexus\Transaction::STATUS_PART_REFUNDED ? (string) $transaction->amount->amount->subtract( $transaction->partial_refund->amount ) : 0 ), TRUE, array( 'unlimited' => 0, 'unlimitedLang' => \IPS\Member::loggedIn()->language()->addToStack( 'refund_full', FALSE, array( 'sprintf' => array( $transaction->amount ) ) ), 'max' => (string) $transaction->amount->amount->subtract( $transaction->partial_refund->amount ), 'decimals' => TRUE ), NULL, NULL, $transaction->amount->currency, $transaction->id . '_refund_amount' );
$field->label = \IPS\Member::loggedIn()->language()->addToStack( 'refund_amount' );
$form->add( $field );
}
@@ -595,7 +611,7 @@ class _invoices extends \IPS\Dispatcher\Controller
if ( $invoice->status === \IPS\nexus\Invoice::STATUS_PAID )
{
$statusOptions = array();
if ( $invoice->total->amount !== (float) 0 )
if ( !$invoice->total->amount->isZero() )
{
$statusOptions[ \IPS\nexus\Invoice::STATUS_PENDING ] = 'refund_invoice_pending';
}
@@ -724,6 +740,9 @@ class _invoices extends \IPS\Dispatcher\Controller
{
\IPS\Dispatcher::i()->checkAcpPermission( 'invoices_delete' );
/* Make sure the user confirmed the deletion */
\IPS\Request::i()->confirmedDelete();
/* Load Transaction */
try
{
@@ -758,21 +777,39 @@ class _invoices extends \IPS\Dispatcher\Controller
/* Init */
\IPS\Dispatcher::i()->checkAcpPermission( 'invoices_add' );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_store.js', 'nexus', 'admin' ) );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('generate_invoice');
$url = \IPS\Http\Url::internal("app=nexus&module=payments&controller=invoices&do=generate");
if ( isset( \IPS\Request::i()->member ) )
{
$url = $url->setQueryString( 'member', \IPS\Request::i()->member );
}
/* Are we editing an invoice? */
$invoice = NULL;
if ( isset( \IPS\Request::i()->id ) )
{
try
{
$invoice = \IPS\nexus\Invoice::load( \IPS\Request::i()->id );
if ( $invoice->status === \IPS\nexus\Invoice::STATUS_PAID )
{
\IPS\Output::i()->error( 'cannot_edit_paid_invoice', '2X190/F', 403, '' );
}
$url = $url->setQueryString( 'id', \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e ) { }
}
\IPS\Output::i()->title = $invoice ? \IPS\Member::loggedIn()->language()->addToStack( 'invoice_number', FALSE, array( 'sprintf' => array( $invoice->id ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('generate_invoice');
/* Select Customer */
$steps = array();
if ( !isset( \IPS\Request::i()->member ) )
if ( !isset( \IPS\Request::i()->member ) and !$invoice )
{
$steps['invoice_generate_member'] = function( $data )
{
$form = new \IPS\Helpers\Form('customer', 'continue');
$form->add( new \IPS\Helpers\Form\Member( 'invoice_generate_member' ) );
$form->add( new \IPS\Helpers\Form\Member( 'invoice_generate_member', NULL, TRUE ) );
if ( $values = $form->values() )
{
return array( 'member' => $values['invoice_generate_member']->member_id );
@@ -782,9 +819,9 @@ class _invoices extends \IPS\Dispatcher\Controller
}
/* Select Addresses */
$steps['invoice_generate_settings'] = function( $data )
$steps['invoice_generate_settings'] = function( $data ) use ( $invoice )
{
$customer = \IPS\nexus\Customer::load( isset( \IPS\Request::i()->member ) ? \IPS\Request::i()->member : $data['member'] );
$customer = $invoice ? $invoice->member : ( \IPS\nexus\Customer::load( isset( \IPS\Request::i()->member ) ? \IPS\Request::i()->member : $data['member'] ) );
$form = new \IPS\Helpers\Form('settings', 'continue');
@@ -792,7 +829,7 @@ class _invoices extends \IPS\Dispatcher\Controller
$currencies = \IPS\nexus\Money::currencies();
if ( count( $currencies ) > 1 )
{
$form->add( new \IPS\Helpers\Form\Radio( 'currency', $customer->defaultCurrency(), TRUE, array( 'options' => array_combine( $currencies, $currencies ) ) ) );
$form->add( new \IPS\Helpers\Form\Radio( 'currency', $invoice ? $invoice->currency : $customer->defaultCurrency(), TRUE, array( 'options' => array_combine( $currencies, $currencies ) ) ) );
}
$statusOptions = array();
$statusOptions[ \IPS\nexus\Invoice::STATUS_PAID ] = 'invoice_status_paid';
@@ -802,47 +839,58 @@ class _invoices extends \IPS\Dispatcher\Controller
$statusOptions[ \IPS\nexus\Invoice::STATUS_EXPIRED ] = 'invoice_status_expd';
}
$statusOptions[ \IPS\nexus\Invoice::STATUS_CANCELED ] = 'invoice_status_canc';
$form->add( new \IPS\Helpers\Form\Radio( 'invoice_status', \IPS\nexus\Invoice::STATUS_PENDING, TRUE, array( 'options' => $statusOptions ) ) );
$form->add( new \IPS\Helpers\Form\Text( 'invoice_title', NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\Text( 'invoice_po_number', NULL, FALSE, array( 'maxLength' => 255 ) ) );
$form->add( new \IPS\Helpers\Form\TextArea( 'invoice_notes', NULL ) );
$form->add( new \IPS\Helpers\Form\Radio( 'invoice_status', $invoice ? $invoice->status : \IPS\nexus\Invoice::STATUS_PENDING, TRUE, array( 'options' => $statusOptions ) ) );
$form->add( new \IPS\Helpers\Form\Text( 'invoice_title', $invoice ? $invoice->title : NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\Text( 'invoice_po_number', $invoice ? $invoice->po_number : NULL, FALSE, array( 'maxLength' => 255 ) ) );
$form->add( new \IPS\Helpers\Form\TextArea( 'invoice_notes', $invoice ? $invoice->notes : NULL ) );
$form->addHeader( 'invoice_generate_addresses' );
$addresses = \IPS\Db::i()->select( '*', 'nexus_customer_addresses', array( 'member=?', isset( \IPS\Request::i()->member ) ? \IPS\Request::i()->member : $data['member'] ) );
$addresses = \IPS\Db::i()->select( '*', 'nexus_customer_addresses', array( 'member=?', $customer->member_id ) );
if ( count( $addresses ) )
{
$billing = NULL;
$shipping = 'x';
$primaryBillingAddressId = NULL;
$chosenBillingAddressId = 0;
$primaryShippingAddressId = 'x';
$chosenShippingAddressid = 0;
$options = array();
foreach ( new \IPS\Patterns\ActiveRecordIterator( $addresses, 'IPS\nexus\Customer\Address' ) as $address )
{
$options[ $address->id ] = (string) $address->address;
if ( $address->primary_billing )
{
$billing = $address->id;
$primaryBillingAddressId = $address->id;
}
if ( $address->primary_shipping )
{
$shipping = $address->id;
$primaryShippingAddressId = $address->id;
}
if ( $invoice and $invoice->billaddress and $invoice->billaddress == $address->address )
{
$chosenBillingAddressId = $address->id;
}
if ( $invoice and $invoice->shipaddress and $invoice->shipaddress == $address->address )
{
$chosenShippingAddressid = $address->id;
}
}
$options[0] = 'other';
$form->add( new \IPS\Helpers\Form\Radio( 'billing_address', $billing, TRUE, array( 'options' => $options, 'toggles' => array( 0 => array( 'new_billing_address' ) ) ) ) );
$newAddress = new \IPS\Helpers\Form\Address( 'new_billing_address', NULL, FALSE, array(), NULL, NULL, NULL, 'new_billing_address' );
$form->add( new \IPS\Helpers\Form\Radio( 'billing_address', ( $invoice and $invoice->billaddress ) ? $chosenBillingAddressId : $primaryBillingAddressId, TRUE, array( 'options' => $options, 'toggles' => array( 0 => array( 'new_billing_address' ) ) ) ) );
$newAddress = new \IPS\Helpers\Form\Address( 'new_billing_address', $invoice ? $invoice->billaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_billing_address' );
$newAddress->label = ' ';
$form->add( $newAddress );
$form->add( new \IPS\Helpers\Form\Radio( 'shipping_address', ( $shipping == $billing ) ? 'x' : $shipping, TRUE, array( 'unlimited' => 'x', 'unlimitedLang' => 'same_as_billing_address', 'options' => $options, 'toggles' => array( 0 => array( 'new_shipping_address' ) ) ) ) );
$newAddress = new \IPS\Helpers\Form\Address( 'new_shipping_address', NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' );
$form->add( new \IPS\Helpers\Form\Radio( 'shipping_address', ( $invoice and $invoice->shipaddress ) ? $chosenShippingAddressid : ( ( $primaryShippingAddressId == $primaryBillingAddressId ) ? 'x' : $primaryShippingAddressId ), TRUE, array( 'options' => array( 'x' => 'same_as_billing_address' ) + $options, 'toggles' => array( 0 => array( 'new_shipping_address' ) ) ) ) );
$newAddress = new \IPS\Helpers\Form\Address( 'new_shipping_address', $invoice ? $invoice->shipaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' );
$newAddress->label = ' ';
$form->add( $newAddress );
}
else
{
$form->add( new \IPS\Helpers\Form\Address( 'new_billing_address', NULL, TRUE ) );
$form->add( new \IPS\Helpers\Form\Checkbox( 'same_shipping_address', TRUE, FALSE, array( 'togglesOff' => array( 'new_shipping_address' ) ) ) );
$form->add( new \IPS\Helpers\Form\Address( 'new_shipping_address', NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' ) );
$form->add( new \IPS\Helpers\Form\Address( 'new_billing_address', $invoice ? $invoice->billaddress : NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\Radio( 'shipping_address', ( $invoice and $invoice->shipaddress and $invoice->shipaddress != $invoice->billaddress ) ? '1' : 'x', FALSE, array( 'options' => array( 'x' => 'same_as_billing_address', '1' => 'other' ), 'toggles' => array( '1' => array( 'new_shipping_address' ) ) ) ) );
$form->add( new \IPS\Helpers\Form\Address( 'new_shipping_address', $invoice ? $invoice->billaddress : NULL, FALSE, array(), NULL, NULL, NULL, 'new_shipping_address' ) );
}
if ( $values = $form->values() )
@@ -855,18 +903,19 @@ class _invoices extends \IPS\Dispatcher\Controller
{
if( $values['new_billing_address'] === NULL OR empty( $values['new_billing_address']->addressLines ) or !$values['new_billing_address']->city or !$values['new_billing_address']->country or ( !$values['new_billing_address']->region and array_key_exists( $values['new_billing_address']->country, \IPS\GeoLocation::$states ) ) or !$values['new_billing_address']->postalCode )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('billing_address_required');
return $form;
$data['billaddress'] = NULL;
}
else
{
$data['billaddress'] = $values['new_billing_address'];
}
$data['billaddress'] = $values['new_billing_address'];
}
if ( count( $addresses ) and $values['shipping_address'] and $values['shipping_address'] !== 'x' )
{
$data['shipaddress'] = \IPS\nexus\Customer\Address::load( $values['shipping_address'] )->address;
}
elseif ( ( isset( $values['same_shipping_address'] ) and $values['same_shipping_address'] ) or $values['shipping_address'] === 'x' )
elseif ( $values['shipping_address'] === 'x' )
{
$data['shipaddress'] = $data['billaddress'];
}
@@ -874,19 +923,25 @@ class _invoices extends \IPS\Dispatcher\Controller
{
if( $values['new_shipping_address'] === NULL OR empty( $values['new_shipping_address']->addressLines ) or !$values['new_shipping_address']->city or !$values['new_shipping_address']->country or ( !$values['new_shipping_address']->region and array_key_exists( $values['new_shipping_address']->country, \IPS\GeoLocation::$states ) ) or !$values['new_shipping_address']->postalCode )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('shipping_address_required');
return $form;
$data['shipaddress'] = NULL;
}
else
{
$data['shipaddress'] = $values['new_shipping_address'];
}
$data['shipaddress'] = $values['new_shipping_address'];
}
$data['currency'] = isset( $values['currency'] ) ? $values['currency'] : $customer->defaultCurrency();
$data['status'] = $values['invoice_status'];
$data['title'] = $values['invoice_title'];
$data['po_number'] = $values['invoice_po_number'];
$data['notes'] = $values['invoice_notes'];
if ( $invoice )
{
$data['items'] = $invoice->items;
}
return $data;
}
@@ -894,13 +949,22 @@ class _invoices extends \IPS\Dispatcher\Controller
};
/* Add Items */
$steps['invoice_generate_items'] = function( $data ) use ( $url )
$steps['invoice_generate_items'] = function( $data ) use ( $url, $invoice )
{
$invoice = new \IPS\nexus\Invoice;
$invoice->member = \IPS\Member::load( isset( \IPS\Request::i()->member ) ? \IPS\Request::i()->member : $data['member'] );
if ( !$invoice )
{
$invoice = new \IPS\nexus\Invoice;
$invoice->member = \IPS\Member::load( isset( \IPS\Request::i()->member ) ? \IPS\Request::i()->member : $data['member'] );
}
$invoice->currency = $data['currency'];
$invoice->billaddress = $data['billaddress'];
$invoice->shipaddress = $data['shipaddress'];
if ( $data['billaddress'] )
{
$invoice->billaddress = $data['billaddress'];
}
if ( $data['shipaddress'] )
{
$invoice->shipaddress = $data['shipaddress'];
}
$invoice->items = isset( $data['items'] ) ? json_encode( $data['items'] ) : json_encode( array() );
if ( isset( \IPS\Request::i()->continue ) )
@@ -1102,7 +1166,7 @@ class _invoices extends \IPS\Dispatcher\Controller
if ( $values = $form->values() )
{
\IPS\DB::i()->update( 'core_tasks', array( 'enabled' => (int) (bool) $values['cm_invoice_expireafter'] ), "`key`='expireInvoices'" );
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => (int) (bool) $values['cm_invoice_expireafter'] ), "`key`='expireInvoices'" );
$form->saveAsSettings();
\IPS\Session::i()->log( 'acplogs__invoice_settings' );