Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * This is the model class for table "{{transaction}}".
- *
- * The followings are the available columns in table '{{transaction}}':
- *
- * @property integer $id
- * @property integer $serial
- * @property integer $date_create
- * @property float $balance
- * @property float $incoming
- * @property float $expenditure
- * @property string $type
- */
- class Transaction extends CActiveRecord {
- static $typeExpend = 'expend';
- static $typeIncoming = 'incoming';
- public $from = null;
- public $to = null;
- public $amount = 0.01;
- /**
- * @return string the associated database table name
- */
- public function tableName() {
- return '{{transaction}}';
- }
- /**
- * @return array validation rules for model attributes.
- */
- public function rules() {
- return array(
- array('serial, date_create, expenditure, incoming, balance', 'required'),
- array('serial, date_create', 'numerical', 'integerOnly' => true),
- array('expenditure, incoming, balance, amount', 'type', 'type' => 'float'),
- array('from, to, amount', 'required', 'on' => 'transfer'),
- array('from, to', 'length', 'max' => 6, 'on' => 'transfer'),
- array('amount', 'numerical', 'integerOnly' => true, 'min' => '0.01', 'on' => 'transfer'),
- array('to', 'differentAccountFromAndTo', 'on' => 'transfer'),
- array('id, serial, date_create', 'safe', 'on' => 'search'),
- );
- }
- /**
- * Валидация номера счета отправителя и получателя на совпадение
- *
- * @param $field
- * @param $params
- */
- public function differentAccountFromAndTo($field, $params) {
- $labels = $this->attributeLabels();
- if (($this->to !== null && $this->from === null) && $this->from == $this->to) {
- $this->addError($field, 'Счет отправителя совпадает со счетом получателя!');
- }
- }
- /**
- * @return array relational rules.
- */
- public function relations() {
- return array();
- }
- /**
- * @return array customized type transaction labels (name=>label)
- */
- static public function typeLabels() {
- return array(
- self::$typeExpend => 'Расход',
- self::$typeIncoming => 'Доход'
- );
- }
- /**
- * @param $type
- *
- * @return null
- */
- static public function getLabelType($type) {
- $labels = self::typeLabels();
- return isset($labels['$type']) ? $labels['$type'] : null;
- }
- /**
- * Перобразует дату создания счета в читабельный формат
- *
- * @return date
- */
- public function getFormatedDateCreate() {
- return date("d.m.Y H:i:s", $this->date_create);
- }
- /**
- * @return array customized attribute labels (name=>label)
- */
- public function attributeLabels() {
- return array(
- 'id' => 'ID',
- 'serial' => 'Номер счета',
- 'from' => 'Счет отправителя',
- 'to' => 'Счет получателя',
- 'amount' => 'Сумма перевода',
- 'date_create' => 'Дата проведения',
- 'expenditure' => 'Расход',
- 'incoming' => 'Приход',
- 'balance' => 'Остаток',
- 'type' => 'Тип операции'
- );
- }
- /**
- * Возвращает объект CModel системного аккаунта
- *
- * @return CActiveRecord
- */
- public function getSystemAccount() {
- $account = new Account();
- return $account->findBySerial(Yii::app()->params['serialSystemAccount']);
- }
- /**
- * Проведение транзакции перевода
- *
- * @param Account $accountFrom
- * @param Account $accountTo
- * @param $amount
- *
- * @return bool|null
- */
- static public function executeTransaction(Account $accountFrom, Account $accountTo, $amount) {
- self::validateAmountType($amount);
- $totalResult = true;
- $transaction = Yii::app()->db->beginTransaction();
- try {
- //Транзакция расхода
- $amountWithCommission = Account::takeAmountWithCommission($amount);
- $commission = round($amountWithCommission - $amount, 2);
- if ($accountFrom->isValidAmount($amount)) {
- $totalResult = $totalResult && self::executeTransactionFrom($accountFrom, $amountWithCommission);
- } else {
- $accountFrom->addError('balance', 'У отправителя недостаточно средств для выполнения данной операции.');
- $transaction->rollback();
- return false;
- }
- //Пополнение системного счета
- $totalResult = $totalResult && self::executeTransactionSystem($commission);
- //Транзакция прихода
- $totalResult = $totalResult && self::executeTransactionTo($accountTo, $amount);
- if (!$totalResult) {
- $transaction->rollback();
- return false;
- }
- $transaction->commit();
- return true;
- } catch
- (Exception $e) {
- $transaction->rollback();
- return null;
- }
- }
- /**
- * Проведение транзакции снятия средств
- *
- * @param Account $accountFrom
- * @param $amount
- *
- * @return bool
- * @throws CException
- */
- static public function executeTransactionFrom(Account $accountFrom, $amount) {
- self::validateAmountType($amount);
- $totalResult = true;
- $transaction = Yii::app()->db->beginTransaction();
- try {
- $accountFrom->balance = $accountFrom->getBalanceMinusAmountAndCommissions($amount, false);
- $totalResult = $totalResult && $accountFrom->save();
- $transactionFrom = new Transaction();
- $transactionFrom->serial = $accountFrom->serial;
- $transactionFrom->type = Transaction::$typeExpend;
- $transactionFrom->expenditure = $amount;
- $transactionFrom->incoming = 0.00;
- $transactionFrom->balance = $accountFrom->balance;
- $totalResult = $totalResult && $transactionFrom->save();
- if (!$totalResult) {
- $transaction->rollback();
- throw new CException('Ошибка проведения транзакции снятия средств');
- }
- $transaction->commit();
- } catch (Exception $e) {
- $transaction->rollback();
- throw new CException('Ошибка проведения транзакции снятия средств');
- }
- return $totalResult;
- }
- /**
- * Проведение транзакции перевода комиссии на системный счет
- *
- * @param $amount
- *
- * @return bool
- * @throws CException
- */
- static public function executeTransactionSystem($amount) {
- self::validateAmountType($amount);
- $totalResult = true;
- $transaction = Yii::app()->db->beginTransaction();
- try {
- $systemAccount = self::getSystemAccount();
- $systemAccount->balance = round($systemAccount->getBalance() + $amount, 2);
- $totalResult = $totalResult && $systemAccount->save();
- $transactionSystem = new Transaction();
- $transactionSystem->serial = $systemAccount->serial;
- $transactionSystem->type = Transaction::$typeIncoming;
- $transactionSystem->expenditure = 0.00;
- $transactionSystem->incoming = $amount;
- $transactionSystem->balance = $systemAccount->balance;
- $totalResult = $totalResult && $transactionSystem->save();
- if (!$totalResult) {
- $transaction->rollback();
- throw new CException('Ошибка проведения транзакции перевода комиссии на системный счет');
- }
- $transaction->commit();
- } catch (Exception $e) {
- $transaction->rollback();
- throw new CException('Ошибка проведения транзакции перевода комиссии на системный счет');
- }
- return $totalResult;
- }
- /**
- * Проведение транзакции зачисления
- *
- * @param Account $accountTo
- * @param $amount
- *
- * @return bool
- * @throws CException
- */
- static public function executeTransactionTo(Account $accountTo, $amount) {
- self::validateAmountType($amount);
- $totalResult = true;
- $transaction = Yii::app()->db->beginTransaction();
- try {
- $accountTo->balance = (float)$accountTo->getBalance() + $amount;
- $totalResult = $totalResult && $accountTo->save();
- $transactionTo = new Transaction();
- $transactionTo->serial = $accountTo->serial;
- $transactionTo->type = Transaction::$typeIncoming;
- $transactionTo->expenditure = 0.00;
- $transactionTo->incoming = $amount;
- $transactionTo->balance = $accountTo->balance;
- $totalResult = $totalResult && $transactionTo->save();
- if (!$totalResult) {
- $transaction->rollback();
- throw new CException('Ошибка проведения транзакции зачисления');
- }
- $transaction->commit();
- } catch (Exception $e) {
- $transaction->rollback();
- throw new CException('Ошибка проведения транзакции зачисления');
- }
- return $totalResult;
- }
- /**
- * Вызывается перед валидацией данных
- *
- * @return bool
- */
- public function beforeValidate() {
- if ($this->isNewRecord) {
- $this->date_create = time();
- }
- return parent::beforeValidate();
- }
- /**
- * Retrieves a list of models based on the current search/filter conditions.
- *
- * Typical usecase:
- * - Initialize the model fields with values from filter form.
- * - Execute this method to get CActiveDataProvider instance which will filter
- * models according to data in model fields.
- * - Pass data provider to CGridView, CListView or any similar widget.
- *
- * @return CActiveDataProvider the data provider that can return the models
- * based on the search/filter conditions.
- */
- public function search($serial) {
- // @todo Please modify the following code to remove attributes that should not be searched.
- $criteria = new CDbCriteria;
- $criteria->order = "date_create DESC";
- $criteria->compare('id', $this->id);
- $criteria->compare('serial', $serial);
- $criteria->compare('expenditure', $this->expenditure);
- $criteria->compare('incoming', $this->incoming);
- $criteria->compare('balance', $this->balance);
- $criteria->compare('type', $this->type);
- // $criteria->compare('description', $this->description, true);
- $criteria->compare('date_create', $this->date_create);
- return new CActiveDataProvider($this, array(
- 'criteria' => $criteria,
- ));
- }
- /**
- * Returns the static model of the specified AR class.
- * Please note that you should have this exact method in all your CActiveRecord descendants!
- *
- * @param string $className active record class name.
- *
- * @return Transaction the static model class
- */
- public static function model($className = __CLASS__) {
- return parent::model($className);
- }
- /**
- * @param $amount
- *
- * @throws CException
- */
- static public function validateAmountType($amount) {
- if (!is_float($amount) && !is_integer($amount)) {
- throw new CException('Сумма должна быть типа float или integer');
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement