transaction = TransactionInterface::apply_transaction($wallet_interface, $_inp, $_type,$deposit_gold ,$deposit_cash,$gold_block,$meta,$allow_negative); } static function validate_last_transaction($wallet_id) { // $last_transaction = Transaction::where('wallet', '=', $wallet_id)->orderBy('created_at', 'DESC')->first(); // if ($last_transaction and $last_transaction->hash !== TransactionInterface::generate_hash($last_transaction)) { // throw new Exceptions\LastTransactionValidateFailed(); // } } private static function generate_hash($transaction) { $last_transaction_hash = ''; $last_user_transaction = Transaction::where('wallet', '=', $transaction->wallet)->orderBy('created_at', 'DESC'); if ($last_user_transaction->count() and $last_user_transaction->first() != $transaction) { $last_transaction_hash = $last_user_transaction->first()->hash; } return hash('sha256', hash('sha256', $transaction->gold) . hash('sha256', $transaction->cash) . hash('sha256', $transaction->wallet) . "yhoenszeaf" . $last_transaction_hash ); } private static function set_hash($transaction) { $transaction->hash = TransactionInterface::generate_hash($transaction); $transaction->save(); } /** * کف موجودی طلا — فقط سمت کسر. شارژ مثبت هیچ‌وقت بسته نمی‌شود، حتی اگر مانده منفی باشد. * ستون gold از نوع float است، پس رواداری نسبی می‌گذاریم تا «فروش کل موجودی» به خطای گرد کردن نخورد. */ private static function assert_gold_floor($wallet, $_inp, $deposit_gold) { if ($deposit_gold || !isset($_inp['gold'])) { return; } $requested = abs((float) $_inp['gold']); if ($requested <= 0) { return; } $balance = (float) $wallet->gold; $tolerance = 1e-6 + abs($balance) * 1e-6; if ($balance + $tolerance < $requested) { throw new UnprocessableEntityHttpException('مقدار وارد شده بیشتر از موجودی طلای شماست'); } } /** کف موجودی ریالی — فقط سمت کسر؛ واریز و شارژ مثبت همیشه باز است. */ private static function assert_cash_floor($wallet, $_inp, $deposit_cash) { if ($deposit_cash || !isset($_inp['cash'])) { return; } $requested = abs((float) $_inp['cash']); if ($requested > 0 && (float) $wallet->cash < $requested) { throw new UnprocessableEntityHttpException('موجودی ریالی کافی نیست'); } } /** * @param bool $allow_negative فقط برای تطبیق مانده با سیستم حسابداری؛ آنجا مانده می‌تواند * واقعاً منفی باشد و کیف باید همان را بازتاب دهد. */ public static function apply_transaction($wallet_interface, $_inp, $_type,$deposit_gold,$deposit_cash,$gold_block, $meta = [], $allow_negative = false) { $wallet = $wallet_interface->wallet; TransactionInterface::validate_last_transaction($wallet->id); #-------------Check Balance -------- if (!$allow_negative) { TransactionInterface::assert_gold_floor($wallet, $_inp, $deposit_gold); TransactionInterface::assert_cash_floor($wallet, $_inp, $deposit_cash); } // $_inp['value'] = abs($_inp['value']) * ($deposit ? 1 : -1); if (isset($_inp['gold'])){ $_inp['gold'] = abs($_inp['gold']) * ($deposit_gold ? 1 : -1); $wallet->gold += $_inp['gold']; } if (isset($_inp['cash'])){ $_inp['cash'] = abs($_inp['cash']) * ($deposit_cash ? 1 : -1); $wallet->cash += $_inp['cash']; } if($gold_block != 0){ $wallet->gold_block += $gold_block; } $_inp['balance_gold'] = $wallet->gold; $_inp['balance_cash'] = $wallet->cash; $_inp['wallet'] = $wallet->id; $_inp['type'] = $_type; // $_inp['transaction_type'] = $_type; $_inp['customer_id'] = $wallet->owner; // $_inp['balance'] = $wallet->cash + $_inp['cash']; $transaction_validate_rules = [ 'wallet' => 'required', 'type' => 'required', 'expire_at' => 'date', 'cash' => 'integer', 'note' => 'string', 'balance' => 'integer', ]; $transaction_validator = Validator::make($_inp, $transaction_validate_rules); if ($transaction_validator->failed()) { throw ValidationException::withMessages($transaction_validator->errors()->all()); } $transaction = Transaction::create($_inp); $transaction->save(); TransactionInterface::set_hash($transaction); $meta['transaction'] = $transaction->id; $transaction_metas = TransactionMeta::create($meta); // if ($_inp['type'] == 1) { // $wallet->cash += $_inp['value']; // } elseif ($_inp['type'] == 2) { // $wallet->gold += $_inp['value']; // } $wallet->save(); $wallet_interface->set_hash(); return $transaction; } }