Version 4.1.19
This commit is contained in:
1 parent
28bd025b35
commit
2bd5025018
2674 files changed
+233518
-77766
No files matched your search
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Purchase Model
|
||||
* @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 10 Feb 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
@@ -107,11 +107,34 @@ class _Purchase extends \IPS\Node\Model
|
||||
{
|
||||
$childCount = $this->childrenCount( NULL, NULL, TRUE, array( array( 'ps_show=1' ) ) );
|
||||
$hasCustomFields = count( $this->custom_fields );
|
||||
|
||||
try
|
||||
{
|
||||
$description = call_user_func( array( $this->extension(), 'getPurchaseNameInfo' ), $this );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$description = array();
|
||||
}
|
||||
if ( $this->grouped_renewals )
|
||||
{
|
||||
$description[] = \IPS\Member::loggedIn()->language()->addToStack('purchase_grouped');
|
||||
}
|
||||
elseif ( $this->renewals )
|
||||
{
|
||||
$renewals = (string) $this->renewals;
|
||||
if ( $this->renewals->tax )
|
||||
{
|
||||
$renewals .= \IPS\Member::loggedIn()->language()->addToStack( 'plus_tax_rate', NULL, array( 'sprintf' => array( $this->renewals->tax->_title ) ) );
|
||||
}
|
||||
$description[] = $renewals;
|
||||
}
|
||||
$description = implode( ' · ', $description );
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'trees', 'core' )->row(
|
||||
$url,
|
||||
$this->id,
|
||||
$hasCustomFields ? \IPS\Theme::i()->getTemplate( 'purchases', 'nexus' )->link( $this ) : $this->name,
|
||||
( $hasCustomFields and !$childCount ) ? \IPS\Theme::i()->getTemplate( 'purchases', 'nexus' )->link( $this, FALSE, FALSE, TRUE ) : $this->_name,
|
||||
$childCount,
|
||||
array_merge( array(
|
||||
'view' => array(
|
||||
@@ -120,13 +143,13 @@ class _Purchase extends \IPS\Node\Model
|
||||
'icon' => 'search',
|
||||
)
|
||||
), $this->buttons( $ref ) ),
|
||||
$this->grouped_renewals ? \IPS\Member::loggedIn()->language()->addToStack('purchase_grouped') : ( (string) ( $this->renewals ?: '' ) ),
|
||||
$description,
|
||||
$this->getIcon(),
|
||||
NULL,
|
||||
$this->id == \IPS\Request::i()->root,
|
||||
NULL,
|
||||
NULL,
|
||||
!$this->active ? ( $this->cancelled ? array( 'style5', 'canceled' ) : array( 'style6', 'expired' ) ) : NULL,
|
||||
!$this->active ? ( $this->cancelled ? array( 'style5', 'purchase_canceled' ) : array( 'style6', 'purchase_expired' ) ) : NULL,
|
||||
$hasCustomFields
|
||||
);
|
||||
}
|
||||
@@ -293,6 +316,10 @@ class _Purchase extends \IPS\Node\Model
|
||||
if ( !$this->expire or $this->expire->getTimestamp() > time() )
|
||||
{
|
||||
$this->active = TRUE;
|
||||
if ( $this->_data['cancelled'] )
|
||||
{
|
||||
$this->onReactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +388,7 @@ class _Purchase extends \IPS\Node\Model
|
||||
*/
|
||||
public function get_renewals()
|
||||
{
|
||||
if( $this->_data['renewals'] )
|
||||
if( isset( $this->_data['renewals'] ) and $this->_data['renewals'] )
|
||||
{
|
||||
$tax = NULL;
|
||||
if ( $this->_data['tax'] )
|
||||
@@ -558,6 +585,38 @@ class _Purchase extends \IPS\Node\Model
|
||||
$this->_data['grouped_renewals'] = !is_null( $data ) ? json_encode( $data ) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get billing agreement
|
||||
*
|
||||
* @return \IPS\nexus\Customer\BillingAgreement|NULL
|
||||
*/
|
||||
public function get_billing_agreement()
|
||||
{
|
||||
if ( $this->_data['billing_agreement'] )
|
||||
{
|
||||
try
|
||||
{
|
||||
return \IPS\nexus\Customer\BillingAgreement::load( $this->_data['billing_agreement'] );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$this->_data['billing_agreement'] = NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set billing agreement
|
||||
*
|
||||
* @param \IPS\nexus\Customer\BillingAgreement|NULL $billingAgreement The billing agreement
|
||||
* @return void
|
||||
*/
|
||||
public function set_billing_agreement( \IPS\nexus\Customer\BillingAgreement $billingAgreement = NULL )
|
||||
{
|
||||
$this->_data['billing_agreement'] = $billingAgreement === NULL ? NULL : $billingAgreement->id;
|
||||
}
|
||||
|
||||
/* !Properties and syncing */
|
||||
|
||||
/**
|
||||
@@ -569,12 +628,27 @@ class _Purchase extends \IPS\Node\Model
|
||||
* Get extension
|
||||
*
|
||||
* @return \IPS\nexus\Invoice\Item\Purchase
|
||||
* @throws \OutOfRangeException
|
||||
*/
|
||||
protected function extension()
|
||||
{
|
||||
if ( $this->extension === NULL )
|
||||
{
|
||||
foreach ( \IPS\Application::load( $this->app )->extensions( 'nexus', 'Item', FALSE ) as $ext )
|
||||
/* Load the app. \IPS\Application::load() throws UnexpectedValueException
|
||||
if the Application.php does not exist, which we'll standardize to
|
||||
OutOfRangeException so areas calling this method only need to check
|
||||
for that */
|
||||
try
|
||||
{
|
||||
$app = \IPS\Application::load( $this->app );
|
||||
}
|
||||
catch ( \UnexpectedValueException $e )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
|
||||
/* Find the extension */
|
||||
foreach ( $app->extensions( 'nexus', 'Item', FALSE ) as $ext )
|
||||
{
|
||||
if ( $ext::$type == $this->type )
|
||||
{
|
||||
@@ -582,6 +656,12 @@ class _Purchase extends \IPS\Node\Model
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't have it? */
|
||||
if ( !$this->extension )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
}
|
||||
return $this->extension;
|
||||
}
|
||||
@@ -742,6 +822,23 @@ class _Purchase extends \IPS\Node\Model
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ACP Support View HTML
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function acpSupportView()
|
||||
{
|
||||
try
|
||||
{
|
||||
return call_user_func( array( $this->extension(), 'acpSupportView' ), $this );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Support Severity
|
||||
*
|
||||
@@ -758,6 +855,23 @@ class _Purchase extends \IPS\Node\Model
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get renewal payment methods IDs
|
||||
*
|
||||
* @return array|NULL
|
||||
*/
|
||||
public function renewalPaymentMethodIds()
|
||||
{
|
||||
try
|
||||
{
|
||||
return call_user_func( array( $this->extension(), 'renewalPaymentMethodIds' ), $this );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call on*
|
||||
@@ -779,12 +893,67 @@ class _Purchase extends \IPS\Node\Model
|
||||
throw new \BadMethodCallException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get output for API
|
||||
*
|
||||
* @return array
|
||||
* @apiresponse int id ID number
|
||||
* @apiresponse string name Name
|
||||
* @apiresponse string itemApp Key for application. For example, 'nexus' for products and renewals; 'downloads' for Downloads files
|
||||
* @apiresponse string itemType Key for item type. For example, 'package' for products; 'file' for Downloads files.
|
||||
* @apiresponse int itemId The ID for the item. For example, the product ID or the file ID.
|
||||
* @apiresponse \IPS\nexus\Customer customer Customer
|
||||
* @apiresponse datetime purchased Purchased date
|
||||
* @apiresponse datetime expires Expiration date
|
||||
* @apiresponse bool active If purchase is currently active (not expired)
|
||||
* @apiresponse bool canceled If purchase has been canceled
|
||||
* @apiresponse \IPS\nexus\Purchase\RenewalTerm renewalTerm Renewal term
|
||||
* @apiresponse object customFields Values for custom fields
|
||||
* @apiresponse \IPS\nexus\Purchase parent Parent purchase
|
||||
* @apiresponse bool show If this purchase shows in the client area and AdminCP
|
||||
* @apiresponse string licenseKey License key
|
||||
* @apiresponse string image If the item has a relevant image (for exmaple, product image, Downloads file screenshot), the URL to it
|
||||
* @apiresponse string url The URL for the customer to view this purchase in the client area
|
||||
*/
|
||||
public function apiOutput()
|
||||
{
|
||||
$parent = NULL;
|
||||
if ( $this->parent )
|
||||
{
|
||||
try
|
||||
{
|
||||
$parent = static::load( $this->parent )->apiOutput();
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
}
|
||||
|
||||
return array(
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'itemApp' => $this->app,
|
||||
'itemType' => $this->type,
|
||||
'itemId' => $this->item_id,
|
||||
'customer' => $this->member->apiOutput(),
|
||||
'purchased' => $this->start->rfc3339(),
|
||||
'expires' => $this->expire ? $this->expire->rfc3339() : null,
|
||||
'active' => (bool) $this->active,
|
||||
'canceled' => (bool) $this->cancelled,
|
||||
'renewalTerm' => $this->renewals ? $this->renewals->apiOutput() : null,
|
||||
'customFields' => $this->custom_fields,
|
||||
'parent' => $parent,
|
||||
'show' => (bool) $this->show,
|
||||
'licenseKey' => $this->licenseKey() ? $this->licenseKey()->key : null,
|
||||
'image' => $this->image() ? ( (string) $this->image()->url ) : null,
|
||||
'url' => (string) $this->url(),
|
||||
);
|
||||
}
|
||||
|
||||
/* !License Keys */
|
||||
|
||||
/**
|
||||
* @brief License key
|
||||
*/
|
||||
protected $licenseKey;
|
||||
public $licenseKey;
|
||||
|
||||
/**
|
||||
* Get license key
|
||||
@@ -897,6 +1066,11 @@ class _Purchase extends \IPS\Node\Model
|
||||
*/
|
||||
public function canChangeExpireDate()
|
||||
{
|
||||
if ( $this->billing_agreement and !$this->billing_agreement->canceled )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return call_user_func( array( $this->extension(), 'canChangeExpireDate' ), $this );
|
||||
@@ -924,14 +1098,20 @@ class _Purchase extends \IPS\Node\Model
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( !$admin and $this->cancelled or !$this->expire or !$this->renewals )
|
||||
if ( $this->cancelled or !$this->renewals or ( $this->billing_agreement and !$this->billing_agreement->canceled ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( !$admin and $pendingInvoice = $this->invoice_pending and $pendingInvoice->status === $pendingInvoice::STATUS_PENDING )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$date = call_user_func( array( $this->extension(), 'canRenewUntil' ), $this, $admin );
|
||||
|
||||
|
||||
if ( $inCycles and $date instanceof \IPS\DateTime )
|
||||
{
|
||||
$now = \IPS\DateTime::create();
|
||||
@@ -967,7 +1147,7 @@ class _Purchase extends \IPS\Node\Model
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return !$this->grouped_renewals and $this->renewals and $this->active;
|
||||
return !$this->grouped_renewals and ( !$this->billing_agreement or $this->billing_agreement->canceled ) and $this->renewals and $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -984,7 +1164,7 @@ class _Purchase extends \IPS\Node\Model
|
||||
{
|
||||
if( $this->_url === NULL )
|
||||
{
|
||||
$this->_url = \IPS\Http\Url::internal( "app=nexus&module=clients&controller=purchases&do=view&id={$this->id}", 'front', 'clientspurchase', array( \IPS\Http\Url::seoTitle( $this->name ) ), \IPS\Settings::i()->nexus_https );
|
||||
$this->_url = \IPS\Http\Url::internal( "app=nexus&module=clients&controller=purchases&do=view&id={$this->id}", 'front', 'clientspurchase', array( \IPS\Http\Url\Friendly::seoTitle( $this->name ) ), \IPS\Settings::i()->nexus_https );
|
||||
}
|
||||
|
||||
return $this->_url;
|
||||
@@ -1017,12 +1197,19 @@ class _Purchase extends \IPS\Node\Model
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
\IPS\File::unclaimAttachments( 'nexus_Purchases', $this->id, NULL, 'purchase' );
|
||||
|
||||
foreach ( $this->children() as $child )
|
||||
{
|
||||
$child->delete();
|
||||
}
|
||||
|
||||
$this->onDelete();
|
||||
|
||||
try
|
||||
{
|
||||
$this->onDelete();
|
||||
}
|
||||
catch ( \BadMethodCallException $e ) {}
|
||||
|
||||
parent::delete();
|
||||
}
|
||||
|
||||
@@ -1049,33 +1236,27 @@ class _Purchase extends \IPS\Node\Model
|
||||
/* Remember what our term is */
|
||||
$term = $this->renewals->getTerm();
|
||||
$this->grouped_renewals = array( 'term' => $term['term'], 'unit' => $term['unit'], 'price' => $this->renewals->cost->amount, 'currency' => $this->renewals->cost->currency, 'tax' => $this->renewals->tax ? $this->renewals->tax->id : 0 );
|
||||
$this->save();
|
||||
|
||||
/* If the parent also has a renewal term, merge them */
|
||||
if ( $parent->renewals )
|
||||
/* Add our term to the parent... */
|
||||
if ( !$this->cancelled )
|
||||
{
|
||||
$parentCostPerDay = $parent->renewals->costPerDay();
|
||||
$itemCostPerDay = $this->renewals->costPerDay();
|
||||
if ( $parentCostPerDay->currency !== $itemCostPerDay->currency )
|
||||
/* If the parent also has a renewal term, merge them */
|
||||
if ( $parent->renewals )
|
||||
{
|
||||
throw new \DomainException('currencies_dont_match');
|
||||
$parent->renewals = new \IPS\nexus\Purchase\RenewalTerm( $parent->renewals->add( $this->renewals ), $parent->renewals->interval, $parent->renewals->tax );
|
||||
$parent->save();
|
||||
}
|
||||
|
||||
$sum = $parentCostPerDay->amount + $itemCostPerDay->amount;
|
||||
$increase = 1 / ( $parentCostPerDay->amount / $sum );
|
||||
$newRenewalPrice = new \IPS\nexus\Money( $parent->renewals->cost->amount * $increase, $itemCostPerDay->currency );
|
||||
|
||||
$parent->renewals = new \IPS\nexus\Purchase\RenewalTerm( $newRenewalPrice->round(), $parent->renewals->interval, $parent->renewals->tax );
|
||||
$parent->save();
|
||||
}
|
||||
/* Otherwise just set the parent to this */
|
||||
else
|
||||
{
|
||||
$parent->renewals = $this->renewals;
|
||||
if ( !$parent->expire )
|
||||
/* Otherwise just set the parent to this */
|
||||
else
|
||||
{
|
||||
$parent->expire = $this->expire;
|
||||
$parent->renewals = $this->renewals;
|
||||
if ( !$parent->expire )
|
||||
{
|
||||
$parent->expire = $this->expire;
|
||||
}
|
||||
$parent->save();
|
||||
}
|
||||
$parent->save();
|
||||
}
|
||||
|
||||
/* Cancel any pending invoices as they're no longer valid */
|
||||
@@ -1119,49 +1300,45 @@ class _Purchase extends \IPS\Node\Model
|
||||
if ( $this->renewals )
|
||||
{
|
||||
/* Restore parent renewal term */
|
||||
if ( $parent->renewals )
|
||||
if ( $parent->renewals and !$this->cancelled )
|
||||
{
|
||||
$parentCostPerDay = $parent->renewals->costPerDay();
|
||||
$itemCostPerDay = $this->renewals->costPerDay();
|
||||
if ( $parentCostPerDay->currency !== $itemCostPerDay->currency )
|
||||
$newRenewalPrice = $parent->renewals->subtract( $this->renewals );
|
||||
if ( $newRenewalPrice->amount->isZero() )
|
||||
{
|
||||
throw new \DomainException('currencies_dont_match');
|
||||
}
|
||||
$sum = $parentCostPerDay->amount - $itemCostPerDay->amount;
|
||||
|
||||
if ( $sum and ( $parentCostPerDay->amount / $sum ) )
|
||||
{
|
||||
$increase = 1 / ( $parentCostPerDay->amount / $sum );
|
||||
$newRenewalPrice = new \IPS\nexus\Money( $parent->renewals->cost->amount * $increase, $parent->renewals->cost->currency );
|
||||
$parent->renewals = new \IPS\nexus\Purchase\RenewalTerm( $newRenewalPrice->round(), $parent->renewals->interval, $parent->renewals->tax );
|
||||
$parent->renewals = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
$parent->renewals = NULL;
|
||||
$parent->renewals = new \IPS\nexus\Purchase\RenewalTerm( $newRenewalPrice, $parent->renewals->interval, $parent->renewals->tax );
|
||||
}
|
||||
$parent->save();
|
||||
}
|
||||
|
||||
/* Restore this purchase renewal term */
|
||||
$groupedRenewals = $this->grouped_renewals;
|
||||
try
|
||||
if ( $groupedRenewals['term'] and $groupedRenewals['unit'] )
|
||||
{
|
||||
$tax = ( isset( $groupedRenewals['tax'] ) and $groupedRenewals['tax'] ) ? \IPS\nexus\Tax::load( $groupedRenewals['tax'] ) : NULL;
|
||||
try
|
||||
{
|
||||
$tax = ( isset( $groupedRenewals['tax'] ) and $groupedRenewals['tax'] ) ? \IPS\nexus\Tax::load( $groupedRenewals['tax'] ) : NULL;
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$tax = NULL;
|
||||
}
|
||||
$this->renewals = new \IPS\nexus\Purchase\RenewalTerm(
|
||||
new \IPS\nexus\Money( $groupedRenewals['price'], isset( $groupedRenewals['currency'] ) ? $groupedRenewals['currency'] : $this->member->defaultCurrency() ),
|
||||
new \DateInterval( 'P' . $groupedRenewals['term'] . mb_strtoupper( $groupedRenewals['unit'] ) ),
|
||||
$tax
|
||||
);
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$tax = NULL;
|
||||
}
|
||||
$this->renewals = new \IPS\nexus\Purchase\RenewalTerm(
|
||||
new \IPS\nexus\Money( $groupedRenewals['price'], isset( $groupedRenewals['currency'] ) ? $groupedRenewals['currency'] : $this->member->defaultCurrency() ),
|
||||
new \DateInterval( 'P' . $groupedRenewals['term'] . mb_strtoupper( $groupedRenewals['unit'] ) ),
|
||||
$tax
|
||||
);
|
||||
$this->expire = $parent->expire;
|
||||
$this->grouped_renewals = NULL;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/* Ungroup */
|
||||
$this->grouped_renewals = NULL;
|
||||
$this->save();
|
||||
|
||||
/* Cancel any pending invoices as they're no longer valid */
|
||||
if ( $invoice = $parent->invoice_pending )
|
||||
{
|
||||
@@ -1214,8 +1391,10 @@ class _Purchase extends \IPS\Node\Model
|
||||
$return = array_merge( $return, call_user_func( array( $this->extension(), 'acpButtons' ), $this, $url ) );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
|
||||
$parent = $this->parent();
|
||||
|
||||
if ( !$this->grouped_renewals and $this->renewals and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'invoices_add' ) )
|
||||
if ( !$this->grouped_renewals and ( !$this->billing_agreement or $this->billing_agreement->canceled ) and $this->renewals and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'invoices_add' ) )
|
||||
{
|
||||
$return['renew'] = array(
|
||||
'icon' => 'refresh',
|
||||
@@ -1225,7 +1404,7 @@ class _Purchase extends \IPS\Node\Model
|
||||
);
|
||||
}
|
||||
|
||||
if ( $this->parent() and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_edit' ) )
|
||||
if ( ( !$this->billing_agreement or $this->billing_agreement->canceled ) and $this->parent() and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_edit' ) )
|
||||
{
|
||||
if ( !$this->grouped_renewals )
|
||||
{
|
||||
@@ -1247,7 +1426,7 @@ class _Purchase extends \IPS\Node\Model
|
||||
}
|
||||
}
|
||||
|
||||
if( !$this->grouped_renewals and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_transfer' ) )
|
||||
if( ( !$this->billing_agreement or $this->billing_agreement->canceled ) and !$this->grouped_renewals and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_transfer' ) )
|
||||
{
|
||||
$return['transfer'] = array(
|
||||
'icon' => 'user',
|
||||
@@ -1257,7 +1436,7 @@ class _Purchase extends \IPS\Node\Model
|
||||
);
|
||||
}
|
||||
|
||||
if ( !$this->grouped_renewals and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_cancel' ) )
|
||||
if ( ( !$this->billing_agreement or $this->billing_agreement->canceled ) and ( !$this->grouped_renewals or !$parent or !$parent->billing_agreement or $parent->billing_agreement->canceled ) and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_cancel' ) )
|
||||
{
|
||||
if ( $this->cancelled )
|
||||
{
|
||||
@@ -1279,7 +1458,7 @@ class _Purchase extends \IPS\Node\Model
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$this->grouped_renewals and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_delete' ) )
|
||||
if ( ( !$this->billing_agreement or $this->billing_agreement->canceled ) and ( !$this->grouped_renewals or !$parent or !$parent->billing_agreement or $parent->billing_agreement->canceled ) and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'customers', 'purchases_delete' ) )
|
||||
{
|
||||
$return['delete'] = array(
|
||||
'icon' => 'times-circle',
|
||||
|
||||
Reference in new issue
Block a user