Wallet.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. // Copyright 2019 Hackware SpA <human@hackware.cl>
  3. // This file is part of "Hackware Web Services Wallet" and licensed under
  4. // the terms of the GNU Affero General Public License version 3, or (at your
  5. // option) a later version. You should have received a copy of this license
  6. // along with the software. If not, see <https://www.gnu.org/licenses/>.
  7. namespace Hawese\Wallet;
  8. use Hawese\Core\User;
  9. use Hawese\Core\Exceptions\ModelObjectNotFoundException;
  10. use Illuminate\Database\Query\Builder;
  11. use Illuminate\Support\Carbon;
  12. class Wallet extends TableModel
  13. {
  14. public static $table = 'wallets';
  15. public static $attributes = [
  16. 'user_uid' => ['required', 'string', 'min:3', 'max:100'],
  17. 'currency_code' => [
  18. 'required', 'string', 'size:3', 'exists:currencies,code'
  19. ],
  20. 'created_at' => ['nullable', 'date'],
  21. 'updated_at' => ['nullable', 'date'],
  22. 'deleted_at' => ['nullable', 'date']
  23. ];
  24. public static $primary_key = 'user_uid';
  25. protected static $incrementing = false;
  26. public function __construct($data)
  27. {
  28. // Virtual properties
  29. $this->appendInstanceAttribute('due_at');
  30. $this->appendInstanceAttribute('balance');
  31. parent::__construct($data);
  32. }
  33. public function setDueAt($value) : void
  34. {
  35. $this->dateSetter('due_at', $value);
  36. }
  37. public function getDueAt()
  38. {
  39. if (!array_key_exists('due_at', $this->data)) {
  40. $query = Transaction::select(['due_at'])
  41. ->where('user_uid', '=', $this->user_uid)
  42. ->whereNotNull('due_at')
  43. ->orderBy('due_at', 'asc');
  44. $this->due_at = $query->exists() ? $query->first()->due_at : null;
  45. }
  46. return $this->data['due_at'];
  47. }
  48. public function getBalance()
  49. {
  50. if (!array_key_exists('balance', $this->data)) {
  51. $this->balance = Transaction::select(['balance'])
  52. ->where('user_uid', '=', $this->user_uid)
  53. ->latest('id')->first()->balance;
  54. }
  55. return $this->data['balance'];
  56. }
  57. /*
  58. // I will leave it here just in case, probably will delete it in future.
  59. // It preprocesses due_at and balance values, but seems too hacky for me.
  60. public static function select(?array $attributes = null) : Builder
  61. {
  62. return app('db')->table(static::$table)
  63. ->select(array_merge(
  64. array_map(
  65. function ($attribute) {
  66. return self::$table . '.' . $attribute;
  67. },
  68. static::attributes()
  69. ),
  70. [app('db')->raw('MIN(due_at) as due_at,' .
  71. '(SELECT balance' .
  72. ' FROM ' . Transaction::$table . ' WHERE ' .
  73. Transaction::$table.'.user_uid = '.self::$table.'.user_uid'
  74. . ' ORDER BY id DESC LIMIT 1) as balance')]
  75. ))
  76. ->leftJoin(
  77. Transaction::$table,
  78. Transaction::$table . '.user_uid',
  79. '=',
  80. self::$table . '.user_uid'
  81. )
  82. ->groupBy(
  83. 'wallets.user_uid',
  84. 'currency_code',
  85. 'wallets.created_at',
  86. 'wallets.updated_at',
  87. 'wallets.deleted_at'
  88. );
  89. }
  90. */
  91. public function insert(): bool
  92. {
  93. // FIXME: Validated twice! Check hawese-core issue #5
  94. // FIXME: Use findByEmailOrCreate instead (check usage of ->insert())
  95. $this->validate();
  96. try {
  97. $user = User::find($this->user_uid);
  98. } catch (ModelObjectNotFoundException $e) {
  99. $user = new User(['uid' => $this->user_uid]);
  100. if (strpos($this->user_uid, '@') !== false) {
  101. $user->email = $this->user_uid; // TODO: Sure about this?
  102. }
  103. $user->insert();
  104. }
  105. return parent::insert();
  106. }
  107. public function initialTransaction() : bool
  108. {
  109. $transaction = new Transaction([
  110. 'user_uid' => $this->user_uid,
  111. 'currency_id' => Currency::findByCode($this->currency_code)->id,
  112. 'amount' => '0',
  113. 'type' => 'system',
  114. 'description' => 'Wallet creation'
  115. ]);
  116. return $transaction->insert();
  117. }
  118. public function isOwner(User $user): bool
  119. {
  120. return $this->user_uid === $user->uid;
  121. }
  122. }