Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F1841741
Wallet.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
Wallet.php
View Options
<?php
namespace
App
;
use
App\User
;
use
App\Traits\SettingsTrait
;
use
Carbon\Carbon
;
use
Iatstuti\Database\Support\NullableFields
;
use
Illuminate\Database\Eloquent\Model
;
use
Illuminate\Support\Facades\DB
;
/**
* The eloquent definition of a wallet -- a container with a chunk of change.
*
* A wallet is owned by an {@link \App\User}.
*
* @property integer $balance
*/
class
Wallet
extends
Model
{
use
NullableFields
;
use
SettingsTrait
;
public
$incrementing
=
false
;
protected
$keyType
=
'string'
;
public
$timestamps
=
false
;
protected
$attributes
=
[
'balance'
=>
0
,
'currency'
=>
'CHF'
];
protected
$fillable
=
[
'currency'
];
protected
$nullable
=
[
'description'
,
];
protected
$casts
=
[
'balance'
=>
'integer'
,
];
/**
* Add a controller to this wallet.
*
* @param \App\User $user The user to add as a controller to this wallet.
*
* @return void
*/
public
function
addController
(
User
$user
)
{
if
(!
$this
->
controllers
->
contains
(
$user
))
{
$this
->
controllers
()->
save
(
$user
);
}
}
public
function
chargeEntitlements
(
$apply
=
true
)
{
// This wallet has been created less than a month ago, this is the trial period
if
(
$this
->
owner
->
created_at
>=
Carbon
::
now
()->
subMonthsWithoutOverflow
(
1
))
{
// Move all the current entitlement's updated_at timestamps forward to one month after
// this wallet was created.
$freeMonthEnds
=
$this
->
owner
->
created_at
->
copy
()->
addMonthsWithoutOverflow
(
1
);
foreach
(
$this
->
entitlements
()->
get
()->
fresh
()
as
$entitlement
)
{
if
(
$entitlement
->
updated_at
<
$freeMonthEnds
)
{
$entitlement
->
updated_at
=
$freeMonthEnds
;
$entitlement
->
save
();
}
}
return
0
;
}
$charges
=
0
;
$discount
=
$this
->
getDiscountRate
();
DB
::
beginTransaction
();
// used to parent individual entitlement billings to the wallet debit.
$entitlementTransactions
=
[];
foreach
(
$this
->
entitlements
()->
get
()->
fresh
()
as
$entitlement
)
{
// This entitlement has been created less than or equal to 14 days ago (this is at
// maximum the fourteenth 24-hour period).
if
(
$entitlement
->
created_at
>
Carbon
::
now
()->
subDays
(
14
))
{
continue
;
}
// This entitlement was created, or billed last, less than a month ago.
if
(
$entitlement
->
updated_at
>
Carbon
::
now
()->
subMonthsWithoutOverflow
(
1
))
{
continue
;
}
// updated last more than a month ago -- was it billed?
if
(
$entitlement
->
updated_at
<=
Carbon
::
now
()->
subMonthsWithoutOverflow
(
1
))
{
$diff
=
$entitlement
->
updated_at
->
diffInMonths
(
Carbon
::
now
());
$cost
=
(
int
)
(
$entitlement
->
cost
*
$discount
*
$diff
);
$charges
+=
$cost
;
// if we're in dry-run, you know...
if
(!
$apply
)
{
continue
;
}
$entitlement
->
updated_at
=
$entitlement
->
updated_at
->
copy
()
->
addMonthsWithoutOverflow
(
$diff
);
$entitlement
->
save
();
if
(
$cost
==
0
)
{
continue
;
}
$entitlementTransactions
[]
=
$entitlement
->
createTransaction
(
\App\Transaction
::
ENTITLEMENT_BILLED
,
$cost
);
}
}
if
(
$apply
)
{
$this
->
debit
(
$charges
,
$entitlementTransactions
);
}
DB
::
commit
();
return
$charges
;
}
/**
* Calculate for how long the current balance will last.
*
* Returns NULL for balance < 0 or discount = 100% or on a fresh account
*
* @return \Carbon\Carbon|null Date
*/
public
function
balanceLastsUntil
()
{
if
(
$this
->
balance
<
0
||
$this
->
getDiscount
()
==
100
)
{
return
null
;
}
// retrieve any expected charges
$expectedCharge
=
$this
->
expectedCharges
();
// get the costs per day for all entitlements billed against this wallet
$costsPerDay
=
$this
->
costsPerDay
();
if
(!
$costsPerDay
)
{
return
null
;
}
// the number of days this balance, minus the expected charges, would last
$daysDelta
=
(
$this
->
balance
-
$expectedCharge
)
/
$costsPerDay
;
// calculate from the last entitlement billed
$entitlement
=
$this
->
entitlements
()->
orderBy
(
'updated_at'
,
'desc'
)->
first
();
$until
=
$entitlement
->
updated_at
->
copy
()->
addDays
(
$daysDelta
);
// Don't return dates from the past
if
(
$until
<
Carbon
::
now
()
&&
!
$until
->
isToday
())
{
return
null
;
}
return
$until
;
}
/**
* Controllers of this wallet.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public
function
controllers
()
{
return
$this
->
belongsToMany
(
'App
\U
ser'
,
// The foreign object definition
'user_accounts'
,
// The table name
'wallet_id'
,
// The local foreign key
'user_id'
// The remote foreign key
);
}
/**
* Retrieve the costs per day of everything charged to this wallet.
*
* @return float
*/
public
function
costsPerDay
()
{
$costs
=
(
float
)
0
;
foreach
(
$this
->
entitlements
as
$entitlement
)
{
$costs
+=
$entitlement
->
costsPerDay
();
}
return
$costs
;
}
/**
* Add an amount of pecunia to this wallet's balance.
*
* @param int $amount The amount of pecunia to add (in cents).
* @param string $description The transaction description
*
* @return Wallet Self
*/
public
function
credit
(
int
$amount
,
string
$description
=
''
):
Wallet
{
$this
->
balance
+=
$amount
;
$this
->
save
();
\App\Transaction
::
create
(
[
'object_id'
=>
$this
->
id
,
'object_type'
=>
\App\Wallet
::
class
,
'type'
=>
\App\Transaction
::
WALLET_CREDIT
,
'amount'
=>
$amount
,
'description'
=>
$description
]
);
return
$this
;
}
/**
* Deduct an amount of pecunia from this wallet's balance.
*
* @param int $amount The amount of pecunia to deduct (in cents).
* @param array $eTIDs List of transaction IDs for the individual entitlements that make up
* this debit record, if any.
* @return Wallet Self
*/
public
function
debit
(
int
$amount
,
array
$eTIDs
=
[]):
Wallet
{
if
(
$amount
==
0
)
{
return
$this
;
}
$this
->
balance
-=
$amount
;
$this
->
save
();
$transaction
=
\App\Transaction
::
create
(
[
'object_id'
=>
$this
->
id
,
'object_type'
=>
\App\Wallet
::
class
,
'type'
=>
\App\Transaction
::
WALLET_DEBIT
,
'amount'
=>
$amount
]
);
\App\Transaction
::
whereIn
(
'id'
,
$eTIDs
)->
update
([
'transaction_id'
=>
$transaction
->
id
]);
return
$this
;
}
/**
* The discount assigned to the wallet.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public
function
discount
()
{
return
$this
->
belongsTo
(
'App
\D
iscount'
,
'discount_id'
,
'id'
);
}
/**
* Entitlements billed to this wallet.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public
function
entitlements
()
{
return
$this
->
hasMany
(
'App
\E
ntitlement'
);
}
/**
* Calculate the expected charges to this wallet.
*
* @return int
*/
public
function
expectedCharges
()
{
return
$this
->
chargeEntitlements
(
false
);
}
/**
* Return the exact, numeric version of the discount to be applied.
*
* Ranges from 0 - 100.
*
* @return int
*/
public
function
getDiscount
()
{
return
$this
->
discount
?
$this
->
discount
->
discount
:
0
;
}
/**
* The actual discount rate for use in multiplication
*
* Ranges from 0.00 to 1.00.
*/
public
function
getDiscountRate
()
{
return
(
100
-
$this
->
getDiscount
())
/
100
;
}
/**
* A helper to display human-readable amount of money using
* the wallet currency and specified locale.
*
* @param int $amount A amount of money (in cents)
* @param string $locale A locale for the output
*
* @return string String representation, e.g. "9.99 CHF"
*/
public
function
money
(
int
$amount
,
$locale
=
'de_DE'
)
{
$amount
=
round
(
$amount
/
100
,
2
);
// Prefer intl extension's number formatter
if
(
class_exists
(
'NumberFormatter'
))
{
$nf
=
new
\NumberFormatter
(
$locale
,
\NumberFormatter
::
CURRENCY
);
$result
=
$nf
->
formatCurrency
(
$amount
,
$this
->
currency
);
// Replace non-breaking space
return
str_replace
(
"
\x
C2
\x
A0"
,
" "
,
$result
);
}
return
sprintf
(
'%.2f %s'
,
$amount
,
$this
->
currency
);
}
/**
* The owner of the wallet -- the wallet is in his/her back pocket.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public
function
owner
()
{
return
$this
->
belongsTo
(
'App
\U
ser'
,
'user_id'
,
'id'
);
}
/**
* Payments on this wallet.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public
function
payments
()
{
return
$this
->
hasMany
(
'App
\P
ayment'
);
}
/**
* Remove a controller from this wallet.
*
* @param \App\User $user The user to remove as a controller from this wallet.
*
* @return void
*/
public
function
removeController
(
User
$user
)
{
if
(
$this
->
controllers
->
contains
(
$user
))
{
$this
->
controllers
()->
detach
(
$user
);
}
}
/**
* Any (additional) properties of this wallet.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public
function
settings
()
{
return
$this
->
hasMany
(
'App
\W
alletSetting'
);
}
/**
* Retrieve the transactions against this wallet.
*
* @return \Illuminate\Database\Eloquent\Builder Query builder
*/
public
function
transactions
()
{
return
\App\Transaction
::
where
(
[
'object_id'
=>
$this
->
id
,
'object_type'
=>
\App\Wallet
::
class
]
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Mon, Aug 25, 3:45 PM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
225522
Default Alt Text
Wallet.php (10 KB)
Attached To
Mode
R2 kolab
Attached
Detach File
Event Timeline
Log In to Comment