]> git.llucax.com Git - mecon/meconlib.git/blob - lib/MECON/Feriado.php
Se agrega un método para acumular secuencias y generar gráficos de barras acumulativos.
[mecon/meconlib.git] / lib / MECON / Feriado.php
1 <?php /* vim: set binary expandtab tabstop=4 shiftwidth=4 textwidth=80:
2 -------------------------------------------------------------------------------
3                              Ministerio de Economía
4                                     meconlib
5 -------------------------------------------------------------------------------
6 This file is part of meconlib.
7
8 meconlib is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2 of the License, or (at your option)
11 any later version.
12
13 meconlib is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16  
17 You should have received a copy of the GNU General Public License; if not,
18 write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 Boston, MA  02111-1307  USA
20 -------------------------------------------------------------------------------
21 Creado: mié abr 10 18:05:33 ART 2002                               |
22 Autor:  Leandro Lucarella <llucar@mecon.gov.ar>
23 -------------------------------------------------------------------------------
24 $Id$
25 -----------------------------------------------------------------------------*/
26
27 require_once 'Date.php';
28 require_once 'Date/Span.php';
29
30 /**
31  * Información sobre feriados.
32  *
33  * Abstracción para hacer ABM sobre la información de los días feriados.
34  * También sirve para hacer consultas y búsquedas.
35  *
36  * @package HE
37  * @version $Rev$
38  * @author  Leandro Lucarella <llucar@mecon.gov.ar>
39  * @todo Probar. Agregar _updateDBInfo() a todas las funciones de Date que
40  *       modifiquen la fecha.
41  */
42 class MECON_Feriado extends Date {
43
44     /**
45      * Base de datos a usar para las consultas.
46      * @private
47      */
48     var $_db;
49
50     /**
51      * Tipo de día (Feriado, Laborable o No Laborable).
52      * @private
53      */
54     var $_tipo;
55
56     /// Hora en la que empieza el feriado.
57     var $desde;
58
59     /// Descripción del feriado.
60     var $descripcion;
61
62     function MECON_Feriado($db, $date = null) {
63         $this->_db = $db;
64         parent::Date($date);
65     }
66
67     function setDate($date = null) {
68         parent::setDate($date);
69         $this->_updateDBInfo($date);
70     }
71
72     function copy($date) {
73         parent::copy($date);
74         if (@$date->_tipo) {
75             $this->_tipo = $date->_tipo;
76             $this->desde = $date->desde;
77             $this->descripcion = $date->descripcion;
78         } else {
79             $this->_updateDBInfo();
80         }
81     }
82
83     function setYear($y) {
84         parent::setYear($y);
85         $this->_updateDBInfo();
86     }
87
88     function setMonth($m) {
89         parent::setMonth($m);
90         $this->_updateDBInfo();
91     }
92
93     function setDay($d) {
94         parent::setDay($d);
95         $this->_updateDBInfo();
96     }
97
98     function setHour($h) {
99         parent::setHour($h);
100         $this->_updateDBInfo();
101     }
102
103     function setMinute($m) {
104         parent::setMinute($m);
105         $this->_updateDBInfo();
106     }
107
108     function setSecond($s) {
109         parent::setSecond($s);
110         $this->_updateDBInfo();
111     }
112
113     function _updateDBInfo() {
114         // Resetea valores.
115         $this->desde = null;
116         $this->descripcion = null;
117         // Se fija según el tipo de día.
118         $dia = $this->format('%w');
119         switch ($dia) {
120             case 0: // Domingo.
121                 $this->_tipo = 'feriado';
122                 break;
123             case 6: // Sábado.
124                 $tipo = 'no laborable';
125                 // sigue abajo, no hay break.
126             default: // Cualquier día.
127                 $this->_tipo = isset($tipo) ? $tipo : 'laborable';
128                 // Verificamos si hay algo en la DB.
129                 $fecha = $this->getDate();
130                 $datos = $this->_db->getRow("SELECT * FROM novedades.feriados WHERE fecha = '$fecha'", null, DB_FETCHMODE_ASSOC);
131                 // Si hay un error, lo pasamos a quien nos llama.
132                 if (DB::isError($datos)) {
133                     return $datos;
134                 // Si hay un resultado, actualizamos los datos.
135                 } elseif ($datos) {
136                     $this->_tipo = $datos['tipo'];
137                     $this->desde = $datos['desde'];
138                     $this->descripcion = $datos['descripcion'];
139                 }
140         }
141         return true;
142     }
143
144     /**
145      * Obtiene el tipo de día (teniendo en cuenta la hora).
146      * 
147      * Si el día es asueto se fija la hora almacenada en esta fecha y devuelve
148      * 'asueto' o 'laborable' dependiendo de a partir de qué hora se declaró el
149      * asueto.
150      *
151      * @return 'laborable', 'no laborable', 'asueto' o 'feriado'.
152      */
153     function getTipo() {
154         if ($this->_tipo == 'asueto') {
155             $desde = new Date_Span($this->desde);
156             $hora = new Date_Span($this->format('%H:%M'));
157             if ($hora->greaterEqual($desde)) {
158                 return $this->_tipo;
159             } else {
160                 // Posible pitfall, en teoría sólo puede declararse asueto un
161                 // día laborable.
162                 return 'laborable';
163             }
164         } else {
165             return $this->_tipo;
166         }
167     }
168
169     /**
170      * Indica si un día es laborable.
171      *
172      * @return bool   false si no es laborable (o hubo error).
173      *
174      * @access public
175      */
176     function esLaborable() {
177         return $this->getTipo() == 'laborable';
178     }
179
180     /**
181      * Indica si un día es no laborable.
182      *
183      * @return bool   false si no es no laborable (o hubo error).
184      *
185      * @access public
186      */
187     function esNoLaborable() {
188         return $this->getTipo() == 'no laborable';
189     }
190
191     /**
192      * Indica si un día es feriado.
193      *
194      * @return bool   false si no es feriado (o hubo error).
195      *
196      * @access public
197      */
198     function esFeriado() {
199         return $this->getTipo() == 'feriado';
200     }
201
202     /**
203      * Indica si un día es asueto.
204      *
205      * @param  string $fecha Fecha de a chequear (el día actual por
206      *                       defecto).
207      * @param  string $hora  Hora en la que se quiere chequear.
208      *
209      * @return bool   false si no es asueto (o hubo error).
210      *
211      * @access public
212      */
213     function esAsueto() {
214         return $this->getTipo() == 'asueto';
215     }
216
217     /**
218      * Busca feriados que se encuentren en un rango de fechas.
219      *
220      * Ejemplo:
221      * if ( $feriado->buscarRango( '2002/10/01', '2002/12/31' ) )
222      *     while ( $f = $feriado->siguiente() )
223      *         var_dump( $f );
224      * elseif ( $feriado->error() )
225      *     die( 'Errores: ' . $feriado->errores();
226      * else
227      *     print( 'No se encontraron feriados en ese rango de fechas' );
228      *
229      * @param  string $ini   Fecha de inicio del rango en donde buscar (por
230      *                       defecto el primer día del mes en curso).
231      * @param  string $fin   Fecha de fin del rango en donde buscar (por
232      *                       defecto el último día del mes en curso).
233      * @param  array $orden  Órden de los resultados. Es un array
234      *                       asociativo con el campo por el cual ordenar
235      *                       como clave y si es descendente o ascendente
236      *                       como valor. Por defecto se toma fecha
237      *                       ascendente.
238      *
239      * @return bool  false si no se encontró nada (o hubo error).
240      *
241      * @todo Pasar a método estático.
242      */
243     function buscarRango( $ini = '', $fin = '', $orden = null ) {
244
245         $ini = empty( $ini ) ? strftime( '%Y/01/01', time() ) : $ini;
246         $fin = empty( $fin ) ? strftime( '%Y/12/31', time() ) : $fin;
247         $ord = ( $ord != 'fecha' and $ord != 'descripcion' and $ord != 'tipo' ) ? 'fecha' : $ord;
248
249         // Valida ambas fechas y que una sea anterior a la otra.
250         if ( ! $this->_es_anterior( $ini, $fin ) )
251             return false;
252
253         // Si no se especifica orden lo inicializa.
254         if ( is_null( $orden ) )
255             $orden = array('fecha' => HE_DB_ASC);
256
257         // Genera un array con las clausulas del ORDER BY del query
258         $order = array();
259         foreach ( $orden as $campo => $ord )
260             $order[] = sprintf( "%s %s", $campo, $ord );
261             
262         // Si no son arrays sale con error.
263         if ( ! is_array( $campos ) or ! is_array( $orden ) ) {
264             $this->raiseError( 'Parámetro incorrecto, no es un array', HE_ERROR );
265             return false;
266         }
267
268         // Prepara el query con el rango de fechas
269         $query = sprintf(
270             'SELECT *
271                 FROM
272                     %s.%s
273                 WHERE
274                     %s <= fecha AND
275                     fecha <= %s
276                 %s',
277             $this->_basededatos,
278             $this->_tabla,
279             $this->_db->quote( $ini ),
280             $this->_db->quote( $fin ),
281             $order ? ( ' ORDER BY ' . join( ',', $order ) ) : ''
282         );
283
284         $resultado =& $this->_db->query( $query );
285         if ( DB::isError( $resultado ) ) {   // Hubo un error
286             $this->_error->agregar( $resultado );
287             return false;
288         } elseif ( $resultado->numRows() ) { // Tiene algún resultado
289             $this->_resultado =& $resultado;
290             return true;
291         } else {
292             return false;
293         }
294
295     }
296
297 }
298
299 // $Id$
300 ?>