<?php

/**
 * This is the model class for table "retenciones.historial_aportes_diferidos".
 * The followings are the available columns in table 'retenciones.historial_aportes_diferidos':
 *
 * @property int      $id
 * @property string   $id_aporte
 * @property string   $id_txt
 * @property int      $id_tipo_aporte
 * @property string   $monto_inicial_patrono
 * @property string   $monto_pagado_patrono
 * @property string   $deuda_actual_patrono
 * @property string   $monto_inicial_socio
 * @property string   $monto_pagado_socio
 * @property string   $deuda_actual_socio
 * @property int      $estatus_aporte
 * @property string   $fecha_registro
 * @property string   $fecha_operacion
 * @property bool     $actual
 * @property integere $nro_pago
 *
 * The followings are the available model relations:
 * @property EstatusAporteDiferido $estatusAporte
 * @property DatosTxtIntegrado     $idTxt
 * @property TipoAporteDiferido    $idTipoAporte
 */
class HistorialAportesDiferidos extends CActiveRecord
{
    public $restante_asociado;
    public $restante_patrono;
    public $resto_asociado;
    public $resto_patrono;
    public $pagado_asociado;
    public $pagado_patrono;
    public $diferido_patrono;
    public $diferido_asociado;
    public $diferido_patrono_archivo;
    public $diferido_asociado_archivo;
    public $cargado_patrono;
    public $cargado_socio; //variables para los archivos que tiene aportantes no definidos

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'retenciones.historial_aportes_diferidos';
    }

    /**
     * @return array validation rules for model attributes
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return [
            ['id_aporte, id_txt, fecha_operacion', 'required'],
            ['id_tipo_aporte, estatus_aporte', 'numerical', 'integerOnly' => true],
            ['monto_inicial_patrono, monto_pagado_patrono, deuda_actual_patrono, monto_inicial_socio, monto_pagado_socio, deuda_actual_socio', 'length', 'max' => 20],
            ['actual, restante_asociado, restante_patrono', 'safe'],
            // The following rule is used by search().
            // @todo Please remove those attributes that should not be searched.
            ['id, id_aporte, id_txt, id_tipo_aporte, monto_inicial_patrono, monto_pagado_patrono, deuda_actual_patrono, monto_inicial_socio, monto_pagado_socio, deuda_actual_socio, estatus_aporte, fecha_registro, fecha_operacion, actual, restante_asociado, restante_patrono, nro_pago', 'safe', 'on' => 'search'],
        ];
    }

    /**
     * @return array relational rules
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return [
            'estatusAporte' => [self::BELONGS_TO, 'EstatusAporteDiferido', 'estatus_aporte'],
            'idTxt' => [self::BELONGS_TO, 'DatosTxtIntegrado', 'id_txt'],
            'idTipoAporte' => [self::BELONGS_TO, 'TipoAporteDiferido', 'id_tipo_aporte'],
        ];
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'id_aporte' => 'Aporte',
            'id_txt' => 'Archivo',
            'id_tipo_aporte' => 'Tipo de aporte',
            'monto_inicial_patrono' => 'Deuda inicial patrono',
            'monto_pagado_patrono' => 'Monto pagado patrono',
            'deuda_actual_patrono' => 'Deuda actual patrono',
            'monto_inicial_socio' => 'Monto inicial socio',
            'monto_pagado_socio' => 'Monto pagado socio',
            'deuda_actual_socio' => 'Deuda actual socio',
            'estatus_aporte' => 'Estatus del aporte',
            'fecha_registro' => 'Fecha Registro',
            'fecha_operacion' => 'Fecha Operacion',
            'actual' => 'Actual',
            'nro_pago' => 'Pago #',
        ];
    }

    /**
     * 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()
    {
        // @todo Please modify the following code to remove attributes that should not be searched.

        $criteria = new CDbCriteria();

        $criteria->compare('id', $this->id);
        $criteria->compare('id_aporte', $this->id_aporte, true);
        $criteria->compare('id_txt', $this->id_txt, true);
        $criteria->compare('id_tipo_aporte', $this->id_tipo_aporte);
        $criteria->compare('monto_inicial_patrono', $this->monto_inicial_patrono, true);
        $criteria->compare('monto_pagado_patrono', $this->monto_pagado_patrono, true);
        $criteria->compare('deuda_actual_patrono', $this->deuda_actual_patrono, true);
        $criteria->compare('monto_inicial_socio', $this->monto_inicial_socio, true);
        $criteria->compare('monto_pagado_socio', $this->monto_pagado_socio, true);
        $criteria->compare('deuda_actual_socio', $this->deuda_actual_socio, true);
        $criteria->compare('estatus_aporte', $this->estatus_aporte);
        $criteria->compare('fecha_registro', $this->fecha_registro, true);
        $criteria->compare('fecha_operacion', $this->fecha_operacion, true);
        $criteria->compare('actual', $this->actual);
        $criteria->compare('nro_pago', $this->nro_pago);

        return new CActiveDataProvider($this, [
            'criteria' => $criteria,
        ]);
    }

    public function searchDiferidoInicial($id)
    {
        // @todo Please modify the following code to remove attributes that should not be searched.

        $criteria = new CDbCriteria();

        $criteria->compare('id', $this->id);
        $criteria->compare('id_aporte', $id);
        $criteria->compare('id_txt', $this->id_txt);
        $criteria->compare('id_tipo_aporte', $this->id_tipo_aporte);
        $criteria->compare('monto_inicial_patrono', $this->monto_inicial_patrono);
        $criteria->compare('monto_pagado_patrono', $this->monto_pagado_patrono);
        $criteria->compare('deuda_actual_patrono', $this->deuda_actual_patrono);
        $criteria->compare('monto_inicial_socio', $this->monto_inicial_socio);
        $criteria->compare('monto_pagado_socio', $this->monto_pagado_socio);
        $criteria->compare('deuda_actual_socio', $this->deuda_actual_socio);
        $criteria->compare('estatus_aporte', $this->estatus_aporte);
        $criteria->compare('fecha_registro', $this->fecha_registro);
        $criteria->compare('fecha_operacion', $this->fecha_operacion);
        $criteria->compare('nro_pago', $this->nro_pago);

        $criteria->addCondition('estatus_aporte = 1');
        $criteria->order = 'nro_pago asc';

        return new CActiveDataProvider($this, [
            'criteria' => $criteria,
        ]);
    }

    public function searchDiferidoAsociado($id)
    {
        // @todo Please modify the following code to remove attributes that should not be searched.

        $criteria = new CDbCriteria();

        $criteria->compare('id', $this->id);
        $criteria->compare('id_aporte', $id);
        $criteria->compare('id_txt', $this->id_txt);
        $criteria->compare('id_tipo_aporte', $this->id_tipo_aporte);
        $criteria->compare('monto_inicial_patrono', $this->monto_inicial_patrono);
        $criteria->compare('monto_pagado_patrono', $this->monto_pagado_patrono);
        $criteria->compare('deuda_actual_patrono', $this->deuda_actual_patrono);
        $criteria->compare('monto_inicial_socio', $this->monto_inicial_socio);
        $criteria->compare('monto_pagado_socio', $this->monto_pagado_socio);
        $criteria->compare('deuda_actual_socio', $this->deuda_actual_socio);
        $criteria->compare('estatus_aporte', $this->estatus_aporte);
        $criteria->compare('fecha_registro', $this->fecha_registro);
        $criteria->compare('fecha_operacion', $this->fecha_operacion);
        $criteria->compare('nro_pago', $this->nro_pago);

        $criteria->addCondition('estatus_aporte in (2,3)');
        $criteria->order = 'nro_pago asc';

        return new CActiveDataProvider($this, [
            'criteria' => $criteria,
        ]);
    }

    public function mayorValor($array)
    {
        $mayor_valor = 0;

        foreach ($array as $key => $value) {
            if ($mayor_valor >= $value->monto_inicial_socio) {
                $mayor_valor = $mayor_valor;
            }

            if ($mayor_valor < $value->monto_inicial_socio) {
                $mayor_valor = $value->monto_inicial_socio;
            }
        }

        return $mayor_valor;
    }

    /**
     * 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 HistorialAportesDiferidos the static model class
     */
    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    public static function diferenciaMontoDistribuido($idTxt, $diferencia)
    {
        $diferencia = self::truncate($diferencia);

        $aporte = self::model()->find(array(
            'condition' => 'id_txt=:id AND actual IS TRUE',
            'order' => 'monto_inicial_patrono DESC, monto_inicial_socio DESC',
            'params' => array(
                'id' => $idTxt,
            ),
        ));

        if ($diferencia < 0) {
            return self::restarDiferenciaMontoDistribuido($aporte, abs($diferencia));
        }

        return self::sumarDiferenciaMontoDistribuido($aporte, $diferencia);
    }

    public static function diferenciaMontoFaltante($idTxt, $diferencia)
    {
        $diferencia = self::truncate($diferencia);

        $aporte = self::model()->find(array(
            'condition' => 'id_txt=:id AND actual IS TRUE',
            'order' => 'deuda_actual_patrono DESC, deuda_actual_socio DESC',
            'params' => array(
                'id' => $idTxt,
            ),
        ));

        if ($diferencia < 0) {
            return self::restarDiferenciaMontoFaltante($aporte, abs($diferencia));
        }

        return self::sumarDiferenciaMontoFaltante($aporte, $diferencia);
    }

    public static function diferenciaMontoPagado($idTxt, $diferencia)
    {
        $diferencia = self::truncate($diferencia);

        $aporte = self::model()->find(array(
            'condition' => 'id_txt=:id AND actual IS TRUE',
            'order' => 'monto_pagado_socio DESC, monto_pagado_patrono DESC',
            'params' => array(
                'id' => $idTxt,
            ),
        ));

        if ($diferencia < 0) {
            return self::restarDiferenciaMontoPagado($aporte, abs($diferencia));
        }

        return self::sumarDiferenciaMontoPagado($aporte, $diferencia);
    }

    private static function restarDiferenciaMontoDistribuido($aporte, $diferencia)
    {
        if ($aporte->monto_inicial_patrono > 0) {
            $aporte->monto_inicial_patrono -= $diferencia;

            return $aporte->save(false);
        }

        if ($aporte->monto_inicial_socio > 0) {
            $aporte->monto_inicial_socio -= $diferencia;

            return $aporte->save(false);
        }
    }

    private static function sumarDiferenciaMontoDistribuido($aporte, $diferencia)
    {
        if ($aporte->monto_inicial_patrono > 0) {
            $aporte->monto_inicial_patrono += $diferencia;

            return $aporte->save(false);
        }

        if ($aporte->monto_inicial_socio > 0) {
            $aporte->monto_inicial_socio += $diferencia;

            return $aporte->save(false);
        }
    }

    private static function restarDiferenciaMontoFaltante($aporte, $diferencia)
    {
        if ($aporte->deuda_actual_patrono > 0) {
            $aporte->deuda_actual_patrono -= $diferencia;
            return $aporte->save();
        }

        if ($aporte->deuda_actual_socio > 0) {
            $aporte->deuda_actual_socio -= $diferencia;
            return $aporte->save();
        }
    }

    private static function sumarDiferenciaMontoFaltante($aporte, $diferencia)
    {
        if ($aporte->deuda_actual_patrono > 0) {
            $aporte->deuda_actual_patrono += $diferencia;
            return $aporte->save(false);
        }

        if ($aporte->deuda_actual_socio > 0) {
            $aporte->deuda_actual_socio += $diferencia;
            return $aporte->save(false);
        }
    }

    private static function restarDiferenciaMontoPagado($aporte, $diferencia)
    {
        if ($aporte->monto_pagado_patrono > 0) {
            $aporte->monto_pagado_patrono -= $diferencia;
            return $aporte->save();
        }

        if ($aporte->monto_pagado_socio > 0) {
            $aporte->monto_pagado_socio -= $diferencia;
            return $aporte->save();
        }
    }

    private static function sumarDiferenciaMontoPagado($aporte, $diferencia)
    {
        if ($aporte->monto_pagado_patrono > 0) {
            $aporte->monto_pagado_patrono += $diferencia;
            return $aporte->save(false);
        }

        if ($aporte->monto_pagado_socio > 0) {
            $aporte->monto_pagado_socio += $diferencia;
            return $aporte->save(false);
        }
    }

    public static function truncate($number, $digitos = 2)
    {
        return round($number, 2);
    }

    public static function eliminarAnteriores($id)
    {
        return self::model()->updateAll(['actual' => false], 'id_txt=:id', [':id' => $id]);
    }

    public static function generarMontosPagadosInicial($id)
    {
        return Yii::app()->getDb()->createCommand('
            UPDATE retenciones.historial_aportes_diferidos
            SET aporte_pago_patrono=ao.total_p,
                aporte_pago_asociado=ao.total_a
            FROM (SELECT
                    had.id_aporte as id,
                    ao.aporte_patrono,
                    coalesce(had.deuda_actual_patrono, 0) AS deuda_p,
                    ao.aporte_patrono - coalesce(had.deuda_actual_patrono, 0) AS total_p,
                    ao.aporte_asociado,
                    coalesce(had.deuda_actual_socio, 0) AS deuda_a,
                    ao.aporte_asociado - coalesce(had.deuda_actual_socio, 0) AS total_a
                FROM retenciones.historial_aportes_diferidos had
                INNER join retenciones.aporte_ordinario ao on had.id_aporte=ao.id
                WHERE had.id_txt=:id
                    AND actual IS TRUE
                    AND coalesce(ao.aporte_patrono, 0) > 0
                    AND coalesce(ao.aporte_asociado, 0) > 0
            ) AS ao
            WHERE id_aporte=ao.id;
        ')->bindValue('id', $id)->query();
    }

    public static function generarMontosPagadosFaltante($id, $numeroPago)
    {
        return Yii::app()->getDb()->createCommand('
            UPDATE retenciones.historial_aportes_diferidos
            SET aporte_pago_patrono=ao.aporte_pago_patrono,
                aporte_pago_asociado=ao.aporte_pago_asociado
            FROM (
                SELECT had.id_aporte AS id,
                       coalesce(hada.aporte_pago_patrono,0) - coalesce(had.monto_pagado_patrono,0) AS aporte_pago_patrono,
                       coalesce(hada.aporte_pago_asociado,0) - coalesce(had.monto_pagado_socio,0) AS aporte_pago_asociado,
                       had.nro_pago
                FROM retenciones.historial_aportes_diferidos had
                left join retenciones.historial_aportes_diferidos hada on hada.id_aporte=had.id_aporte AND hada.nro_pago=:nro_pago
                WHERE had.id_txt=:id
                  AND had.actual IS TRUE
            ) AS ao
            WHERE id_aporte=ao.id AND actual IS TRUE;
        ')->bindValues([
            'id' => $id,
            'nro_pago' => $numeroPago - 1,
        ])->queryRow();
    }

    public static function numeroPago($id)
    {
        return Yii::app()->getDb()->createCommand('
            SELECT nro_pago + 1 AS nro_pago
            FROM retenciones.historial_aportes_diferidos
            WHERE id_txt=:id
                AND actual IS TRUE
                AND nro_pago IS NOT NULL
            LIMIT 1;
        ')->bindValue('id', $id)->queryRow()['nro_pago'];
    }
}
