Advertisement
stixlink

model framework yii

Sep 1st, 2014
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 12.59 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4.  * This is the model class for table "{{transaction}}".
  5.  *
  6.  * The followings are the available columns in table '{{transaction}}':
  7.  *
  8.  * @property integer $id
  9.  * @property integer $serial
  10.  * @property integer $date_create
  11.  * @property float   $balance
  12.  * @property float   $incoming
  13.  * @property float   $expenditure
  14.  * @property string  $type
  15.  */
  16. class Transaction extends CActiveRecord {
  17.  
  18.     static $typeExpend = 'expend';
  19.     static $typeIncoming = 'incoming';
  20.  
  21.     public $from = null;
  22.     public $to = null;
  23.     public $amount = 0.01;
  24.  
  25.     /**
  26.      * @return string the associated database table name
  27.      */
  28.     public function tableName() {
  29.  
  30.         return '{{transaction}}';
  31.     }
  32.  
  33.     /**
  34.      * @return array validation rules for model attributes.
  35.      */
  36.     public function rules() {
  37.  
  38.         return array(
  39.             array('serial, date_create, expenditure, incoming, balance', 'required'),
  40.             array('serial, date_create', 'numerical', 'integerOnly' => true),
  41.             array('expenditure, incoming, balance, amount', 'type', 'type' => 'float'),
  42.             array('from, to, amount', 'required', 'on' => 'transfer'),
  43.             array('from, to', 'length', 'max' => 6, 'on' => 'transfer'),
  44.             array('amount', 'numerical', 'integerOnly' => true, 'min' => '0.01', 'on' => 'transfer'),
  45.             array('to', 'differentAccountFromAndTo', 'on' => 'transfer'),
  46.             array('id, serial, date_create', 'safe', 'on' => 'search'),
  47.         );
  48.     }
  49.  
  50.     /**
  51.      * Валидация номера счета отправителя и получателя на совпадение
  52.      *
  53.      * @param $field
  54.      * @param $params
  55.      */
  56.     public function differentAccountFromAndTo($field, $params) {
  57.  
  58.         $labels = $this->attributeLabels();
  59.  
  60.         if (($this->to !== null && $this->from === null) && $this->from == $this->to) {
  61.             $this->addError($field, 'Счет отправителя совпадает со счетом получателя!');
  62.         }
  63.  
  64.     }
  65.  
  66.  
  67.     /**
  68.      * @return array relational rules.
  69.      */
  70.     public function relations() {
  71.  
  72.         return array();
  73.     }
  74.  
  75.     /**
  76.      * @return array customized type transaction labels (name=>label)
  77.      */
  78.     static public function typeLabels() {
  79.  
  80.         return array(
  81.             self::$typeExpend => 'Расход',
  82.             self::$typeIncoming => 'Доход'
  83.         );
  84.     }
  85.  
  86.     /**
  87.      * @param $type
  88.      *
  89.      * @return null
  90.      */
  91.     static public function getLabelType($type) {
  92.  
  93.         $labels = self::typeLabels();
  94.  
  95.         return isset($labels['$type']) ? $labels['$type'] : null;
  96.  
  97.     }
  98.  
  99.     /**
  100.      * Перобразует дату создания счета в читабельный формат
  101.      *
  102.      * @return date
  103.      */
  104.     public function getFormatedDateCreate() {
  105.  
  106.         return date("d.m.Y H:i:s", $this->date_create);
  107.     }
  108.  
  109.     /**
  110.      * @return array customized attribute labels (name=>label)
  111.      */
  112.     public function attributeLabels() {
  113.  
  114.         return array(
  115.             'id' => 'ID',
  116.             'serial' => 'Номер счета',
  117.             'from' => 'Счет отправителя',
  118.             'to' => 'Счет получателя',
  119.             'amount' => 'Сумма перевода',
  120.             'date_create' => 'Дата проведения',
  121.             'expenditure' => 'Расход',
  122.             'incoming' => 'Приход',
  123.             'balance' => 'Остаток',
  124.             'type' => 'Тип операции'
  125.  
  126.         );
  127.     }
  128.  
  129.     /**
  130.      * Возвращает объект CModel системного аккаунта
  131.      *
  132.      * @return CActiveRecord
  133.      */
  134.     public function getSystemAccount() {
  135.  
  136.         $account = new Account();
  137.  
  138.         return $account->findBySerial(Yii::app()->params['serialSystemAccount']);
  139.     }
  140.  
  141.     /**
  142.      * Проведение транзакции перевода
  143.      *
  144.      * @param Account $accountFrom
  145.      * @param Account $accountTo
  146.      * @param         $amount
  147.      *
  148.      * @return bool|null
  149.      */
  150.     static public function executeTransaction(Account $accountFrom, Account $accountTo, $amount) {
  151.  
  152.         self::validateAmountType($amount);
  153.  
  154.         $totalResult = true;
  155.         $transaction = Yii::app()->db->beginTransaction();
  156.  
  157.         try {
  158.             //Транзакция расхода
  159.             $amountWithCommission = Account::takeAmountWithCommission($amount);
  160.             $commission = round($amountWithCommission - $amount, 2);
  161.             if ($accountFrom->isValidAmount($amount)) {
  162.  
  163.                 $totalResult = $totalResult && self::executeTransactionFrom($accountFrom, $amountWithCommission);
  164.             } else {
  165.                 $accountFrom->addError('balance', 'У отправителя недостаточно средств для выполнения данной операции.');
  166.                 $transaction->rollback();
  167.  
  168.                 return false;
  169.             }
  170.  
  171.             //Пополнение системного счета
  172.             $totalResult = $totalResult && self::executeTransactionSystem($commission);
  173.  
  174.             //Транзакция прихода
  175.             $totalResult = $totalResult && self::executeTransactionTo($accountTo, $amount);
  176.  
  177.  
  178.             if (!$totalResult) {
  179.                 $transaction->rollback();
  180.  
  181.                 return false;
  182.             }
  183.  
  184.             $transaction->commit();
  185.  
  186.             return true;
  187.  
  188.         } catch
  189.         (Exception $e) {
  190.             $transaction->rollback();
  191.  
  192.             return null;
  193.         }
  194.  
  195.  
  196.     }
  197.  
  198.     /**
  199.      * Проведение транзакции снятия средств
  200.      *
  201.      * @param Account $accountFrom
  202.      * @param         $amount
  203.      *
  204.      * @return bool
  205.      * @throws CException
  206.      */
  207.     static public function executeTransactionFrom(Account $accountFrom, $amount) {
  208.  
  209.         self::validateAmountType($amount);
  210.  
  211.         $totalResult = true;
  212.  
  213.  
  214.         $transaction = Yii::app()->db->beginTransaction();
  215.         try {
  216.             $accountFrom->balance = $accountFrom->getBalanceMinusAmountAndCommissions($amount, false);
  217.             $totalResult = $totalResult && $accountFrom->save();
  218.  
  219.             $transactionFrom = new Transaction();
  220.             $transactionFrom->serial = $accountFrom->serial;
  221.             $transactionFrom->type = Transaction::$typeExpend;
  222.             $transactionFrom->expenditure = $amount;
  223.             $transactionFrom->incoming = 0.00;
  224.             $transactionFrom->balance = $accountFrom->balance;
  225.             $totalResult = $totalResult && $transactionFrom->save();
  226.  
  227.             if (!$totalResult) {
  228.                 $transaction->rollback();
  229.                 throw new CException('Ошибка проведения транзакции снятия средств');
  230.             }
  231.             $transaction->commit();
  232.  
  233.         } catch (Exception $e) {
  234.  
  235.             $transaction->rollback();
  236.             throw new CException('Ошибка проведения транзакции снятия средств');
  237.         }
  238.  
  239.         return $totalResult;
  240.  
  241.     }
  242.  
  243.     /**
  244.      * Проведение транзакции перевода комиссии на системный счет
  245.      *
  246.      * @param $amount
  247.      *
  248.      * @return bool
  249.      * @throws CException
  250.      */
  251.     static public function executeTransactionSystem($amount) {
  252.  
  253.         self::validateAmountType($amount);
  254.         $totalResult = true;
  255.  
  256.  
  257.         $transaction = Yii::app()->db->beginTransaction();
  258.         try {
  259.             $systemAccount = self::getSystemAccount();
  260.             $systemAccount->balance = round($systemAccount->getBalance() + $amount, 2);
  261.             $totalResult = $totalResult && $systemAccount->save();
  262.  
  263.             $transactionSystem = new Transaction();
  264.             $transactionSystem->serial = $systemAccount->serial;
  265.             $transactionSystem->type = Transaction::$typeIncoming;
  266.             $transactionSystem->expenditure = 0.00;
  267.             $transactionSystem->incoming = $amount;
  268.             $transactionSystem->balance = $systemAccount->balance;
  269.             $totalResult = $totalResult && $transactionSystem->save();
  270.  
  271.             if (!$totalResult) {
  272.                 $transaction->rollback();
  273.                 throw new CException('Ошибка проведения транзакции перевода комиссии на системный счет');
  274.             }
  275.             $transaction->commit();
  276.  
  277.         } catch (Exception $e) {
  278.  
  279.             $transaction->rollback();
  280.             throw new CException('Ошибка проведения транзакции перевода комиссии на системный счет');
  281.         }
  282.  
  283.         return $totalResult;
  284.  
  285.     }
  286.  
  287.     /**
  288.      * Проведение транзакции зачисления
  289.      *
  290.      * @param Account $accountTo
  291.      * @param         $amount
  292.      *
  293.      * @return bool
  294.      * @throws CException
  295.      */
  296.     static public function executeTransactionTo(Account $accountTo, $amount) {
  297.  
  298.         self::validateAmountType($amount);
  299.         $totalResult = true;
  300.  
  301.  
  302.         $transaction = Yii::app()->db->beginTransaction();
  303.         try {
  304.             $accountTo->balance = (float)$accountTo->getBalance() + $amount;
  305.             $totalResult = $totalResult && $accountTo->save();
  306.  
  307.             $transactionTo = new Transaction();
  308.             $transactionTo->serial = $accountTo->serial;
  309.             $transactionTo->type = Transaction::$typeIncoming;
  310.             $transactionTo->expenditure = 0.00;
  311.             $transactionTo->incoming = $amount;
  312.             $transactionTo->balance = $accountTo->balance;
  313.  
  314.             $totalResult = $totalResult && $transactionTo->save();
  315.  
  316.             if (!$totalResult) {
  317.                 $transaction->rollback();
  318.                 throw new CException('Ошибка проведения транзакции зачисления');
  319.             }
  320.             $transaction->commit();
  321.  
  322.         } catch (Exception $e) {
  323.             $transaction->rollback();
  324.             throw new CException('Ошибка проведения транзакции зачисления');
  325.         }
  326.  
  327.         return $totalResult;
  328.     }
  329.  
  330.     /**
  331.      * Вызывается перед валидацией данных
  332.      *
  333.      * @return bool
  334.      */
  335.     public function beforeValidate() {
  336.  
  337.         if ($this->isNewRecord) {
  338.             $this->date_create = time();
  339.         }
  340.  
  341.         return parent::beforeValidate();
  342.     }
  343.  
  344.  
  345.     /**
  346.      * Retrieves a list of models based on the current search/filter conditions.
  347.      *
  348.      * Typical usecase:
  349.      * - Initialize the model fields with values from filter form.
  350.      * - Execute this method to get CActiveDataProvider instance which will filter
  351.      * models according to data in model fields.
  352.      * - Pass data provider to CGridView, CListView or any similar widget.
  353.      *
  354.      * @return CActiveDataProvider the data provider that can return the models
  355.      * based on the search/filter conditions.
  356.      */
  357.     public function search($serial) {
  358.  
  359.         // @todo Please modify the following code to remove attributes that should not be searched.
  360.  
  361.         $criteria = new CDbCriteria;
  362.         $criteria->order = "date_create DESC";
  363.         $criteria->compare('id', $this->id);
  364.         $criteria->compare('serial', $serial);
  365.         $criteria->compare('expenditure', $this->expenditure);
  366.         $criteria->compare('incoming', $this->incoming);
  367.         $criteria->compare('balance', $this->balance);
  368.         $criteria->compare('type', $this->type);
  369. //        $criteria->compare('description', $this->description, true);
  370.         $criteria->compare('date_create', $this->date_create);
  371.  
  372.         return new CActiveDataProvider($this, array(
  373.             'criteria' => $criteria,
  374.         ));
  375.     }
  376.  
  377.     /**
  378.      * Returns the static model of the specified AR class.
  379.      * Please note that you should have this exact method in all your CActiveRecord descendants!
  380.      *
  381.      * @param string $className active record class name.
  382.      *
  383.      * @return Transaction the static model class
  384.      */
  385.     public static function model($className = __CLASS__) {
  386.  
  387.         return parent::model($className);
  388.     }
  389.  
  390.     /**
  391.      * @param $amount
  392.      *
  393.      * @throws CException
  394.      */
  395.     static public function validateAmountType($amount) {
  396.  
  397.         if (!is_float($amount) && !is_integer($amount)) {
  398.             throw new CException('Сумма должна быть типа float или integer');
  399.         }
  400.     }
  401. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement