|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace App\UseCases; |
| 4 | + |
| 5 | +use App\Transaction; |
| 6 | + |
| 7 | + |
| 8 | +class TransactionService |
| 9 | +{ |
| 10 | + public function create($debit_user, $credit_user, $amount) |
| 11 | + { |
| 12 | + \DB::transaction(function () use($debit_user, $credit_user, $amount) { |
| 13 | + |
| 14 | + while ($transaction_key = str_random(32)) { |
| 15 | + if (!\App\Transaction::where('transaction_key', $transaction_key)->first()) { |
| 16 | + break; |
| 17 | + } |
| 18 | + } |
| 19 | + |
| 20 | + $debit_user_balance = $debit_user->balance->fresh()->balance - $amount; |
| 21 | + $credit_user_balance = $credit_user->balance->fresh()->balance + $amount; |
| 22 | + |
| 23 | + $tr1 = Transaction::create([ |
| 24 | + 'user_id' => $credit_user->id, |
| 25 | + 'transaction_key' => $transaction_key, |
| 26 | + 'amount' => $amount, |
| 27 | + 'user_balance' => $credit_user_balance, |
| 28 | + 'transaction_type' => config('transaction.types.credit'), |
| 29 | + ]); |
| 30 | + |
| 31 | + $tr2 = Transaction::create([ |
| 32 | + 'user_id' => $debit_user->id, |
| 33 | + 'transaction_key' => $transaction_key, |
| 34 | + 'amount' => $amount, |
| 35 | + 'user_balance' => $debit_user_balance, |
| 36 | + 'transaction_type' => config('transaction.types.debit'), |
| 37 | + ]); |
| 38 | + |
| 39 | + if ($success = $tr1 && $tr2) { |
| 40 | + $success &= $debit_user->balance()->update(['balance' => $debit_user_balance]); |
| 41 | + $success &= $credit_user->balance()->update(['balance' => $credit_user_balance]); |
| 42 | + } |
| 43 | + |
| 44 | + if(!$success){ |
| 45 | + throw new \Exception('Database error!'); |
| 46 | + } |
| 47 | + }); |
| 48 | + } |
| 49 | + |
| 50 | + public function update($key, $amount) |
| 51 | + { |
| 52 | + |
| 53 | + $transactions = Transaction::where('transaction_key', $key)->get(); |
| 54 | + |
| 55 | + if ($transactions->isEmpty()) { |
| 56 | + throw new \Exception('Not valid transaction key!'); |
| 57 | + } |
| 58 | + |
| 59 | + \DB::transaction(function () use($transactions, $amount) { |
| 60 | + |
| 61 | + $success = true; |
| 62 | + $oldAmount = $transactions->first()->amount; |
| 63 | + |
| 64 | + foreach($transactions as $tr){ |
| 65 | + if($tr->transaction_type == config('transaction.types.debit')){ |
| 66 | + $diffBalance = $oldAmount - $amount; |
| 67 | + $exceptionMessage = 'Too mutch amount!'; |
| 68 | + }else{ |
| 69 | + $diffBalance = $amount - $oldAmount; |
| 70 | + $exceptionMessage = 'Too small amount!'; |
| 71 | + } |
| 72 | + |
| 73 | + $oldBalance = $tr->user_balance + $diffBalance; |
| 74 | + $newBalanse = $tr->user->balance->balance + $diffBalance; |
| 75 | + |
| 76 | + if($newBalanse < 0 || $oldBalance < 0){ |
| 77 | + throw new \Exception($exceptionMessage); |
| 78 | + } |
| 79 | + |
| 80 | + $success &= $tr->update([ |
| 81 | + 'amount' => $amount, |
| 82 | + 'user_balance' => $oldBalance, |
| 83 | + ]); |
| 84 | + |
| 85 | + $success &= $tr->user->balance()->update(['balance' => $newBalanse]); |
| 86 | + } |
| 87 | + |
| 88 | + if(!$success){ |
| 89 | + throw new \Exception('Database error!'); |
| 90 | + } |
| 91 | + }); |
| 92 | + } |
| 93 | + |
| 94 | + public function getByKey($key) |
| 95 | + { |
| 96 | + $transactions = Transaction::where('transaction_key', $key)->with('user')->get(); |
| 97 | + |
| 98 | + $transaction = []; |
| 99 | + |
| 100 | + foreach ($transactions as $tr) { |
| 101 | + if ($tr->transaction_type == config('transaction.types.debit')) { |
| 102 | + $transaction['debit_user_name'] = $tr->user->name; |
| 103 | + $transaction['debit_user_balance'] = $tr->user_balance; |
| 104 | + } else { |
| 105 | + $transaction['crebit_user_name'] = $tr->user->name; |
| 106 | + $transaction['crebit_user_balance'] = $tr->user_balance; |
| 107 | + } |
| 108 | + $transaction['transaction_key'] = $tr->transaction_key; |
| 109 | + $transaction['amount'] = $tr->amount; |
| 110 | + $transaction['created_at'] = (string) $tr->created_at; |
| 111 | + } |
| 112 | + |
| 113 | + return $transaction; |
| 114 | + } |
| 115 | +} |
0 commit comments