Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
1.34% |
22 / 1639 |
|
2.22% |
3 / 135 |
CRAP | n/a |
0 / 0 |
|
| ia_sqlErrors | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| ia_update | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
210 | |||
| ia_dontQuote | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
110 | |||
| ia_insert | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
132 | |||
| valExisteFile | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
| ia_fileName | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
| ia_guid | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| ia_OptionsSetData | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
210 | |||
| ia_Options_array | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
342 | |||
| ia_Options_KeyDisplay | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
42 | |||
| strit | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
3.33 | |||
| strit_array | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| fieldit | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
| strim | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
42 | |||
| stritc | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
| comillea | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| jsit | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| javait | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| param | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
20 | |||
| param_get | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| param_post | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| _keyTrimmed | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
| getParams | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
| arrayDiff | |
0.00% |
0 / 36 |
|
0.00% |
0 / 1 |
650 | |||
| array_is_list | n/a |
0 / 0 |
n/a |
0 / 0 |
2 | |||||
| array_list_diff | |
0.00% |
0 / 24 |
|
0.00% |
0 / 1 |
132 | |||
| file_upload_error | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
90 | |||
| uploadErrorStr | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
90 | |||
| ip_extract | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
30 | |||
| ip_server_set | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
| ip_get | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
| ip_getFull | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
| redirect | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
42 | |||
| siteRootUrl | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
| ia_convertBytes | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
30 | |||
| ia_errores_a_dime | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
| ia_report_status_collapsable | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
| file_size_formatted | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
| file_is_image | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
30 | |||
| file_icon | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
182 | |||
| ia_image_tag_size | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
72 | |||
| ia_img_format | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| ia_image_tagsize_fitmax | |
0.00% |
0 / 44 |
|
0.00% |
0 / 1 |
1122 | |||
| removeAccents | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| filename_safe | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| filename_extension | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
| error_last | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
| gAppRelate_set | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
| array_val | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
| _numOr0 | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| date_limit | |
0.00% |
0 / 51 |
|
0.00% |
0 / 1 |
702 | |||
| to_plural | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
380 | |||
| to_label | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
56 | |||
| ia_mktime_day | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| array2Select | |
0.00% |
0 / 54 |
|
0.00% |
0 / 1 |
650 | |||
| colores | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| die_Script | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| json_encode_ex | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
| table_jqgrid_existencias | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
12 | |||
| table_productos_remate | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| keyRemap | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| getLabelBodega | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
240 | |||
| getUrlBase | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
| getUrlTo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| unsetItem | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
| array_sort | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
90 | |||
| getEnums | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
| adjustBrightness | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
12 | |||
| limpiaDatos | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
30 | |||
| searchValueInArrayByColumn | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| get_url_origin | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
182 | |||
| get_full_url | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
| get_url_out_params | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| notasFaltantes | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
| bodegasResumenNumeroNotas | |
0.00% |
0 / 34 |
|
0.00% |
0 / 1 |
90 | |||
| miniLog | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
272 | |||
| bcformat | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
30 | |||
| numeric2string | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
42 | |||
| bcabs | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| producto_color_reset | |
0.00% |
0 / 41 |
|
0.00% |
0 / 1 |
210 | |||
| me_pregunto_notas_bodega | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
90 | |||
| ia_htmlentities | |
50.00% |
4 / 8 |
|
0.00% |
0 / 1 |
8.12 | |||
| mysqlDate2display | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
72 | |||
| mysqlDateTime2display | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
| mysqlTimestamp2display | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| color_id_nombre | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| color_id_activo | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| producto_general_id_nombre | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| producto_general_id_activo | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| checked | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
56 | |||
| selected | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
56 | |||
| statusBodegaSelect | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
6 | |||
| jsonRegExp | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| jsonLike | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
20 | |||
| strlike | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| fixJsonBuscaEnProperty | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
20 | |||
| getFueErrorNo | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
| fueErrorIguales | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
| fueErrorConfirmaIguales | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
12 | |||
| itemsIguales | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
| campoAtipo | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
| compareCaseInsensitive | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
90 | |||
| diasEntreFechas | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 | |||
| fechaDiff | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
156 | |||
| keyOrder | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
30 | |||
| keyOrderEnd | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
30 | |||
| getCurrentValueJson | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
| displayColumn | |
0.00% |
0 / 60 |
|
0.00% |
0 / 1 |
702 | |||
| viewJsCode | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
30 | |||
| is_container_number | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
| formatMe | |
0.00% |
0 / 38 |
|
0.00% |
0 / 1 |
702 | |||
| formatMeArray | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
42 | |||
| formatMeId | |
0.00% |
0 / 41 |
|
0.00% |
0 / 1 |
110 | |||
| the_error_handler | |
88.89% |
8 / 9 |
|
0.00% |
0 / 1 |
3.01 | |||
| the_exception_handler | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
| recomiendanOlla | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
240 | |||
| recomiendanOllaTable | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
| recomiendaSave | |
0.00% |
0 / 52 |
|
0.00% |
0 / 1 |
650 | |||
| topVentasBodega | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
20 | |||
| usuario_defaults_get | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
30 | |||
| usuario_defaults_set | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
| usedFilesTimes | |
0.00% |
0 / 112 |
|
0.00% |
0 / 1 |
1980 | |||
| getMTime | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
42 | |||
| getLastNModifiedFiles | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| file_debug_reporte | |
0.00% |
0 / 34 |
|
0.00% |
0 / 1 |
272 | |||
| keys2Tiny | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
56 | |||
| num2Key | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
| getDeviceInfo | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
| jqGridColsSorter_SelectLinkTo | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
56 | |||
| jqGridColsSorter_GetDefs | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
| units2grid | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
| jsCodeColChooser | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| bodega_x_dia_cache | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
20 | |||
| bodega_x_dia_ExistenciaMaximaTable | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| bodega_x_dia_recalc | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
| 1 | <?php |
| 2 | /** @noinspection PhpRedundantOptionalArgumentInspection */ |
| 3 | /** @noinspection PhpMissingReturnTypeInspection */ |
| 4 | /** @noinspection PhpMissingParamTypeInspection */ |
| 5 | /** @noinspection RegExpRedundantEscape */ |
| 6 | |
| 7 | /** 2021-12-21 Todo verde */ |
| 8 | |
| 9 | /** |
| 10 | * ia_util.php |
| 11 | * Utilerias |
| 12 | * @version 2.1.2012.09.23 |
| 13 | * @package utilerias |
| 14 | * pre-requisites: include config.php para array $gIAsql y $gIaTimeStart value, |
| 15 | * |
| 16 | */ |
| 17 | |
| 18 | use JetBrains\PhpStorm\ExpectedValues; |
| 19 | use JetBrains\PhpStorm\NoReturn; |
| 20 | use JetBrains\PhpStorm\Pure; |
| 21 | |
| 22 | // ////////////////////// SQL ////////////////////// |
| 23 | global $gIAsql; |
| 24 | if(!array_key_exists('set_autocommit',$gIAsql)) $gIAsql['set_autocommit']=null; |
| 25 | if(!array_key_exists('pconnect',$gIAsql)) $gIAsql['pconnect']=false; |
| 26 | if(!array_key_exists('trace',$gIAsql)) $gIAsql['trace']=false; |
| 27 | if(!array_key_exists('sql_trace',$gIAsql)) $gIAsql['sql_trace']=array(); |
| 28 | if(!array_key_exists('link',$gIAsql)) $gIAsql['link']=null; |
| 29 | if(!array_key_exists('err',$gIAsql)) $gIAsql['err']=''; |
| 30 | $gIAsql['affected_rows']=$gIAsql['begins']=$gIAsql['selected_rows']=0; |
| 31 | |
| 32 | $gIAsql['dont_quote']=array('NULL','CURDATE()','CURRENT_DATE()','CURRENT_DATE','CURRENT_DATETIME','CURRENT_TIME()','CURRENT_TIME','CURTIME()' |
| 33 | ,'CURRENT_TIMESTAMP()','CURRENT_TIMESTAMP','NOW()','LOCALTIMESTAMP','LOCALTIMESTAMP()','SYSDATE()','UNIX_TIMESTAMP()' |
| 34 | ,'UTC_DATE()','UTC_TIME()','UTC_TIMESTAMP()'); |
| 35 | |
| 36 | include_once(__DIR__.'/sqlConverter.php'); |
| 37 | /** |
| 38 | * ia_sqlErrors() |
| 39 | * |
| 40 | * @return string html <ul> con los errores |
| 41 | */ |
| 42 | function ia_sqlErrors():string { |
| 43 | global $gIAsql; |
| 44 | return $gIAsql['err'] === '' ? '' : "<ul>$gIAsql[err]</ul>"; |
| 45 | } |
| 46 | |
| 47 | /** |
| 48 | * ia_update() |
| 49 | * regresa un update $table set $key='$values[$key]',... WHERE $pkey='$primaryKey[$pkey]' AND |
| 50 | * @param string $table nombre de la tabla |
| 51 | * @param array $values 'campo'=>value, rutina protege apostrofes |
| 52 | * @param string|array $where en array hace 'campo'=value con AND, en string lo pone |
| 53 | * @param array $excludeQuote |
| 54 | * @param string $after_clause despues del where. |
| 55 | * @param string $before_clause entre update y table. |
| 56 | * @param boolean $inteligent_quotes en true no quotea lo que este en $gIAsql['dont_quote'] |
| 57 | * @param boolean $dontQuote en true no pone quotes alrededor de los valores, default false no pone quotes |
| 58 | * @return string |
| 59 | */ |
| 60 | function ia_update($table, $values = [], $where = [], |
| 61 | $excludeQuote=[], $after_clause='', $before_clause='', |
| 62 | $inteligent_quotes = true, $dontQuote = false):string { |
| 63 | global $gIAsql; |
| 64 | $upd=''; |
| 65 | foreach($values as $fieldName=>$v) { |
| 66 | if( is_null($v) ) |
| 67 | $upd.=", $fieldName=NULL"; |
| 68 | elseif( $dontQuote || ($inteligent_quotes && in_array(strtoupper(trim($v)),$gIAsql['dont_quote'])) || in_array($fieldName,$excludeQuote) || ia_dontQuote($v) ) |
| 69 | $upd.=", $fieldName=$v"; |
| 70 | else |
| 71 | $upd.=", $fieldName=".strit($v); |
| 72 | } |
| 73 | if(is_array($where)) { |
| 74 | $w=''; |
| 75 | foreach($where as $fieldName=>$v) |
| 76 | if( is_null($v) ) |
| 77 | $w.=" AND $fieldName IS NULL"; |
| 78 | elseif( $dontQuote || ($inteligent_quotes && in_array(strtoupper(trim($v)),$gIAsql['dont_quote'])) ) |
| 79 | $w.=" AND $fieldName = $v"; |
| 80 | else |
| 81 | $w.=" AND $fieldName = ".strit($v); |
| 82 | $w=substr($w,5); |
| 83 | } else |
| 84 | $w=$where; |
| 85 | |
| 86 | $comment = "/** ACTUALIZA $table **/"; |
| 87 | return "UPDATE $comment $before_clause $table SET ".substr($upd,1)." WHERE $w ".$after_clause; |
| 88 | } |
| 89 | |
| 90 | |
| 91 | function ia_dontQuote( $v):bool { |
| 92 | $paren = strpos($v,'('); |
| 93 | |
| 94 | if($paren === FALSE) |
| 95 | return false; |
| 96 | $close = strpos($v,')',$paren); |
| 97 | |
| 98 | if($close === FALSE || $close < $paren) |
| 99 | return false; |
| 100 | $blank = strpos($v,' '); |
| 101 | if($blank === FALSE || $paren < $blank && substr($v,-1==')') && substr_count ($v,'(') == substr_count ($v,')') ) { |
| 102 | $functions = array('DATE_ADD(','DATE_SUB('); |
| 103 | foreach($functions as $f) |
| 104 | if(stripos($v,$f) === 0) |
| 105 | return true; |
| 106 | } |
| 107 | return false; |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * ia_insert() |
| 112 | * regresa un insert $before_clause into $table($keys) values($vals) $after_clause; |
| 113 | * @param string $table nombre de la tabla |
| 114 | * @param array $values 'campo'=>value |
| 115 | * @param boolean $autoOnUpdate en true hace ON DUPLICATE UPDATE de no venir en after_clause |
| 116 | * @param string $after_clause poner despues de values: on duplicate key... |
| 117 | * @param string $before_clause entre insert y (campos) |
| 118 | * @param boolean $inteligent_quotes en true no quotea lo que este en $gIAsql['dont_quote'] |
| 119 | * @param boolean $dontQuote en true no pone quotes alrededor de los valores, default false no pone quotes |
| 120 | * @return string |
| 121 | * VCA 29-07-2021 hice una actualizacion a ON DUPLICATE KEY UPDATE |
| 122 | */ |
| 123 | function ia_insert($table, $values = [], $excludeQuote = [], $after_clause='', |
| 124 | $autoOnUpdate=false, $before_clause='', $inteligent_quotes=true, $dontQuote=false, $comment = ''): string |
| 125 | { |
| 126 | global $gIAsql; |
| 127 | $ins=''; |
| 128 | $val=''; |
| 129 | $upd=''; |
| 130 | |
| 131 | $TB = strtoupper($table); |
| 132 | if (empty($comment)) |
| 133 | $comment = "/** INSERTA $TB **/"; |
| 134 | |
| 135 | $alias = $table."_alias"; |
| 136 | |
| 137 | foreach($values as $fieldName=>$v) { |
| 138 | $ins.=",$fieldName"; |
| 139 | if( is_null($v) ) |
| 140 | $val.=",NULL"; |
| 141 | elseif(is_array($v)) { |
| 142 | $val.=','.strit( implode(',',$v)); |
| 143 | } elseif( $dontQuote || ($inteligent_quotes && in_array(strtoupper(trim($v)),$gIAsql['dont_quote'])) || in_array($fieldName,$excludeQuote) || ia_dontQuote($v) ) |
| 144 | $val.=",$v"; |
| 145 | else |
| 146 | $val.=','.strit($v); |
| 147 | $upd.=",$fieldName=$alias.$fieldName"; |
| 148 | } |
| 149 | if($autoOnUpdate) |
| 150 | $after_clause=" AS $alias ON DUPLICATE KEY UPDATE ".substr($upd,1); |
| 151 | return "INSERT $comment $before_clause INTO $table(".substr($ins,1).") VALUES(".substr($val,1).") $after_clause"; |
| 152 | |
| 153 | } |
| 154 | |
| 155 | /** |
| 156 | * ia_nameFile($Path, $elName) |
| 157 | * |
| 158 | * Path: para ubicaicón del archivo |
| 159 | * elName: Nombre original del archivo |
| 160 | * |
| 161 | */ |
| 162 | function valExisteFile($Path, $elName, $laextension, $cntInicial):string { |
| 163 | if(file_exists($Path."/".$elName.".".$laextension)){ |
| 164 | if(!str_contains($elName, "--_")){ |
| 165 | return valExisteFile($Path, $elName."--_".$cntInicial, $laextension, ++$cntInicial); |
| 166 | } |
| 167 | $nombreAnt = explode("--_",$elName); |
| 168 | return valExisteFile($Path, $nombreAnt[0]."--_".$cntInicial, $laextension, ++$cntInicial); |
| 169 | } |
| 170 | return $elName.".".$laextension; |
| 171 | } |
| 172 | |
| 173 | function ia_fileName($Path, $elName, $gWebDir):string { |
| 174 | $elName = sanitizeFileName($elName); |
| 175 | $fpp = pathinfo($elName); |
| 176 | $elName = array_key_exists('filename',$fpp) ? strtolower($fpp['filename']):''; |
| 177 | $elName = substr($elName,0,50); |
| 178 | $laextension = array_key_exists('extension',$fpp) ? strtolower($fpp['extension']):''; |
| 179 | |
| 180 | $newName = valExisteFile($Path, $elName, $laextension, 1); |
| 181 | valida_carpetas($Path,$gWebDir); |
| 182 | |
| 183 | return $newName; |
| 184 | } |
| 185 | |
| 186 | /** |
| 187 | * ia_guid() |
| 188 | * returns universal uuid de mysql: sin - en base 36 (29 caracteres maximo) reversed para menos carga a indices. |
| 189 | |
| 190 | * @param string $cmnt |
| 191 | * @return string uuid |
| 192 | */ |
| 193 | function ia_guid($cmnt='guid'):string { |
| 194 | $a=explode('-',ia_singleread("SELECT SQL_NO_CACHE /* $cmnt */ UUID()",'',false)); |
| 195 | return $a[4].$a[3].$a[2].$a[1].$a[0]; |
| 196 | // aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | * ia_SqlOptionsSetDataData() |
| 201 | * |
| 202 | * @param array $arr |
| 203 | * @param string|array $selected |
| 204 | * @param array $extra |
| 205 | * @param string $optionTag |
| 206 | * @return string |
| 207 | */ |
| 208 | function ia_OptionsSetData($arr, $selected='', $extra = [], $optionTag=''):string { |
| 209 | |
| 210 | $ret=''; |
| 211 | if($extra) foreach($extra as $k=>$v) |
| 212 | if(is_array($selected)) { |
| 213 | $ret.= PHP_EOL."<option value='$k' ".(array_key_exists($k,$selected) ? " SELECTED='selected' " : " ")." $optionTag >".ia_htmlentities($v)."</option>"; |
| 214 | } else { |
| 215 | $ret.= PHP_EOL."<option value='$k' ".(strcmp($selected,$k) ? " " : " SELECTED='selected' ")." $optionTag >".ia_htmlentities($v)."</option>"; |
| 216 | } |
| 217 | foreach($arr as $k=>$v) { |
| 218 | if(is_array($selected)) |
| 219 | $ret.= PHP_EOL."<option value='$k'".(array_key_exists($k,$selected) ? " SELECTED='selected' " : ""); |
| 220 | else |
| 221 | $ret.= PHP_EOL."<option data-data='$k' value='$k'".(strcmp($selected,$k) ? "" : " SELECTED='selected' "); |
| 222 | $i=0; $label=''; |
| 223 | if(is_array($v)) |
| 224 | foreach($v as $attr=>$val) { |
| 225 | if($i === 1) |
| 226 | $label=$val; |
| 227 | if( $i > 1 ) |
| 228 | $ret.=" data-$attr='$val'"; |
| 229 | $i++; |
| 230 | } |
| 231 | else |
| 232 | $label=$v; |
| 233 | |
| 234 | $ret.=" $optionTag>".ia_htmlentities($label)."</option>"; |
| 235 | } |
| 236 | return $ret; |
| 237 | } |
| 238 | |
| 239 | /////////////////////// |
| 240 | /** |
| 241 | * ia_Options_array() |
| 242 | * pone options de un <select> |
| 243 | * |
| 244 | * @param array $array [value]=display o value=array(value,display,'html-tag'=>tag_value,,'html-tag'=>tag_value,...) |
| 245 | * @param string $selected seleccionado actualmente |
| 246 | * @param string $optionAttr opcional, atriubtos a agreagar a cada option |
| 247 | * @param string $setColor true agrega style="color:color" de existir color en el $array |
| 248 | * @param null $value |
| 249 | * @param null $label |
| 250 | * @return string |
| 251 | */ |
| 252 | function ia_Options_array($array, $selected = '', $optionAttr = '', $setColor = '', $value = null, $label = null):string { |
| 253 | $pon=array('class','style','title'); |
| 254 | $ret=''; |
| 255 | $colorStyle = ''; |
| 256 | if( !empty( $array) ) foreach($array as $key =>$d) { |
| 257 | $opts=''; |
| 258 | $id=''; |
| 259 | $text=''; |
| 260 | |
| 261 | if(is_array($d) || is_object($d)) { |
| 262 | $i=0; |
| 263 | if($setColor !== '' ) |
| 264 | $colorStyle = array_key_exists($setColor, $d) ? |
| 265 | ' style="color:' . |
| 266 | ia_htmlentities($d[$setColor] === '#FFFFFF' ? 'black' : $d[$setColor]) . '" ' : |
| 267 | ''; |
| 268 | foreach($d as $k => $v) { |
| 269 | // dd_('jaja', $d); |
| 270 | $i++; |
| 271 | if($i===1) |
| 272 | $id=$v; |
| 273 | elseif($i===2) |
| 274 | $text=$v; |
| 275 | elseif($i>2) { |
| 276 | if(in_array($k,$pon)) |
| 277 | $opts.=" $k='".ia_htmlentities($v)."'"; |
| 278 | else |
| 279 | $opts.=" data-$k='".ia_htmlentities($v)."'"; |
| 280 | } |
| 281 | |
| 282 | if (!empty($value)) { |
| 283 | $id = $d[$value]; |
| 284 | } |
| 285 | if (!empty($label)) { |
| 286 | $text = $d[$label]; |
| 287 | } |
| 288 | } |
| 289 | } else { |
| 290 | $text = $d; |
| 291 | $id = $key; |
| 292 | } |
| 293 | |
| 294 | if(is_array($selected)) { |
| 295 | $ret.="\r\n<option $colorStyle value='$id' ".(in_array($id,$selected) ? " SELECTED='selected' " : "")." $optionAttr$opts>".ia_htmlentities($text)."</option>"; |
| 296 | } else { |
| 297 | $ret.="\r\n<option $colorStyle value='$id' ".(strcmp($selected,$id) ? "" : " SELECTED='selected' ")." $optionAttr$opts>".ia_htmlentities($text)."</option>"; |
| 298 | } |
| 299 | } |
| 300 | return $ret; |
| 301 | } |
| 302 | |
| 303 | /** |
| 304 | * ia_Options_KeyDisplay() |
| 305 | * pone options de un <select> |
| 306 | * |
| 307 | * @param array $array [value]=display |
| 308 | * @param array|string|null $selected value seleccionado actualmente |
| 309 | * @param string $optionAttr opcional, atriubtos a agreagar a cada option |
| 310 | * @return string |
| 311 | */ |
| 312 | function ia_Options_KeyDisplay($array, $selected='', $optionAttr=''):string { |
| 313 | $ret=''; |
| 314 | if( !empty( $array) ) foreach($array as $k=>$d) { |
| 315 | if(is_array($selected)) { |
| 316 | $ret.="\r\n<option value='$k' ".(in_array($k,$selected) ? " SELECTED='selected' " : "")."$optionAttr>".ia_htmlentities($d)."</option>"; |
| 317 | } else { |
| 318 | $ret.="\r\n<option value='$k' ".(strcmp($selected,$k) ? "" : " SELECTED='selected' ")."$optionAttr>".ia_htmlentities($d)."</option>"; |
| 319 | } |
| 320 | } |
| 321 | return $ret; |
| 322 | } |
| 323 | |
| 324 | /** |
| 325 | * Portege un string o fecha de caracteres extra para el sql query |
| 326 | * @param string|int|float|null $s el string a proteger |
| 327 | * @return string el string $s protegido |
| 328 | */ |
| 329 | function strit($s):string { |
| 330 | if($s === null) |
| 331 | $s = ''; |
| 332 | if(is_array($s)) return "''"; return "'".str_replace ("\\", "\\\\",str_replace("'","''", $s))."'"; } |
| 333 | |
| 334 | /** |
| 335 | * Protege los valores del array con strit |
| 336 | * |
| 337 | * @param array $array |
| 338 | * @return array |
| 339 | */ |
| 340 | function strit_array($array):array { |
| 341 | foreach($array as &$d) |
| 342 | $d = strit($d); |
| 343 | return $array; |
| 344 | } |
| 345 | |
| 346 | /** |
| 347 | * Protect with ` an sql name |
| 348 | * Quotes a: column/table/db name to `column name` respecting . table.column to `table`.`column` |
| 349 | * |
| 350 | * @param string $fieldName |
| 351 | * @return string |
| 352 | */ |
| 353 | function fieldit($fieldName):string { |
| 354 | if($fieldName === '' || $fieldName[0] === '(') |
| 355 | return $fieldName; |
| 356 | |
| 357 | $protected = []; |
| 358 | $n = explode('.',$fieldName); |
| 359 | foreach($n as $field) { |
| 360 | $protected[]= '`'.str_replace(['`',"\r","\n","\t","\0"], '', strim($field) ).'`'; |
| 361 | } |
| 362 | return implode('.', $protected); |
| 363 | } |
| 364 | |
| 365 | function strim($str):string|array { |
| 366 | if($str === null) |
| 367 | return ''; |
| 368 | if(is_array($str)) { |
| 369 | foreach($str as &$d) |
| 370 | $d = strim($d); |
| 371 | return $str; |
| 372 | } |
| 373 | $s1 = preg_replace('/[\pZ\pC]/muS',' ',$str); |
| 374 | if(preg_last_error()) { |
| 375 | $s1 = preg_replace('/[\pZ\pC]/muS',' ', iconv("UTF-8","UTF-8//IGNORE",$str)); |
| 376 | if(preg_last_error()) |
| 377 | return trim(preg_replace('/ {2,}/mS',' ',$str)); |
| 378 | } |
| 379 | return trim(preg_replace('/ {2,}/muS',' ',$s1)); |
| 380 | } |
| 381 | |
| 382 | |
| 383 | /** |
| 384 | * Portege un string o fecha de caracteres extra para el sql query |
| 385 | * @param string|int|float|null $s el string a proteger |
| 386 | * @return string el string $s protegido terminado con una coma |
| 387 | */ |
| 388 | function stritc($s):string { |
| 389 | if($s === null) |
| 390 | $s = ''; |
| 391 | return "'".str_replace ("\\", "\\\\",str_replace("'","''", $s))."',"; } |
| 392 | |
| 393 | /** |
| 394 | * comillea() |
| 395 | * |
| 396 | * @param string|int|float|null $s |
| 397 | * @return string |
| 398 | */ |
| 399 | function comillea($s):string { if($s===null) return '"null"'; return '"'.str_replace('"',"'", $s).'"'; } |
| 400 | /** |
| 401 | * jsit() |
| 402 | * |
| 403 | * @param string|int|float|null $s |
| 404 | * @return string |
| 405 | */ |
| 406 | function jsit($s):string { |
| 407 | if($s === null) |
| 408 | return 'null'; |
| 409 | return '"'.str_replace( array("\\","\"","\'"),array("\\\\","\\\"","\\\'"),$s).'"'; |
| 410 | } |
| 411 | |
| 412 | /** |
| 413 | * Portege un string de javascript entre $entre apostrofes ' o comillas |
| 414 | * @param string|int|float|null $s el string a proteger |
| 415 | * @param string $entre ' o " El string sera puesto entre ' o " |
| 416 | * @return string el string $s protegido |
| 417 | */ |
| 418 | function javait($s, $entre="'"):string { |
| 419 | if($s === null) |
| 420 | return "null"; |
| 421 | return $entre.str_replace ($entre, "\\'",str_replace("\\", "\\\\", $s)).$entre; |
| 422 | } |
| 423 | |
| 424 | /////////////////////////////////// params //////////////////////////////////////////////////// |
| 425 | |
| 426 | /** |
| 427 | * regresa el parametro llamado trimmed $name de $_REQUEST, si no existe busca en get, de no estar regresa $dflt |
| 428 | * @param string $name nombre del parametro a regresar |
| 429 | * @param mixed $dflt='' el valor a regresar de no existir el parametro. default '' |
| 430 | * @return mixed el parametro llamado $name en post o get array si es array, de no estar regresa $dflt |
| 431 | */ |
| 432 | function param($name, $dflt='', $trim=true):mixed { |
| 433 | if(str_contains($name, "remark")) { |
| 434 | return $_REQUEST[$name] ?? $dflt; |
| 435 | } |
| 436 | if(str_contains($name, "coment")) { |
| 437 | return $_REQUEST[$name] ?? $dflt; |
| 438 | } |
| 439 | return $trim ? strim($_REQUEST[$name] ?? $dflt) : $_REQUEST[$name] ?? $dflt; |
| 440 | } |
| 441 | |
| 442 | |
| 443 | /** |
| 444 | * regresa el parametro llamado $name en get en string o array, de no estar regresa $dflt |
| 445 | * @param string $name nombre del parametro a regresar |
| 446 | * @param mixed $dflt='' el valor a regresar de no existir el parametro. default '' |
| 447 | * @return mixed el parametro llamado $name en get, de no estar regresa $dflt |
| 448 | */ |
| 449 | #[Pure] function param_get($name, $dflt=''):mixed { |
| 450 | return _keyTrimmed($_GET, $name, $dflt); |
| 451 | } |
| 452 | |
| 453 | /** |
| 454 | * regresa el parametro trimmed llamado $name en post en string o array, de no estar regresa $dflt |
| 455 | * |
| 456 | * @param string $name nombre del parametro a regresar |
| 457 | * @param mixed $dflt='' el valor a regresar de no existir el parametro. default '' |
| 458 | * @return mixed el parametro llamado $name en post, de no estar regresa $dflt |
| 459 | */ |
| 460 | #[Pure] function param_post($name, $dflt=''):mixed { |
| 461 | return _keyTrimmed($_POST, $name, $dflt); |
| 462 | } |
| 463 | |
| 464 | /** |
| 465 | * regresa el parametro trimmed llamado $name del array $from en string o array, de no estar regresa $dflt. |
| 466 | * |
| 467 | * @param array $from |
| 468 | * @param string $name nombre del parametro a regresar |
| 469 | * @param mixed $dflt='' el valor a regresar de no existir el parametro. default '' |
| 470 | * @return mixed el parametro llamado $name en post, de no estar regresa $dflt |
| 471 | */ |
| 472 | function _keyTrimmed($from,string $name, $dflt):mixed { |
| 473 | if( !array_key_exists($name,$from)) |
| 474 | return $dflt; |
| 475 | if(is_array($from[$name])) { |
| 476 | $arr = []; |
| 477 | foreach($from[$name] as $k => $s) { |
| 478 | $arr[$k] = is_array($s) ? $s : strim($s); |
| 479 | } |
| 480 | return $arr; |
| 481 | } |
| 482 | return strim($from[$name]); |
| 483 | } |
| 484 | |
| 485 | /** |
| 486 | * @param string|null $type null, post or get |
| 487 | * @return array null: $_REQUEST, post:$_POST, get:$_GET |
| 488 | */ |
| 489 | function getParams($type = null):array |
| 490 | { |
| 491 | if($type === null) |
| 492 | return $_REQUEST ?? []; |
| 493 | return $type === 'post' ? $_POST ?? [] : $_GET ?? []; |
| 494 | } |
| 495 | |
| 496 | /** |
| 497 | * Obtiene la diferencia entre 2 arrays. Ejemplo tests/ejemplo_arrayDiff.php |
| 498 | * |
| 499 | * @param array $a |
| 500 | * @param array $b |
| 501 | * @param float $delta para floats la diferencia debe ser mayor que |
| 502 | * @return array [$keyConValorDiferente_1=>[$a[$k1], $b[$k1]], ...] |
| 503 | * |
| 504 | * @example tests/ejemplos/arrayDiff.php |
| 505 | */ |
| 506 | function arrayDiff(array $a, array $b, float $delta = 1E-2):array { |
| 507 | $diff = []; |
| 508 | if(array_is_list($a) && array_is_list($b)) { |
| 509 | return array_list_diff($a, $b); |
| 510 | } |
| 511 | foreach($a as $k => $d) { |
| 512 | if(!array_key_exists($k, $b)) { |
| 513 | $diff[$k] = [$d, null]; |
| 514 | continue; |
| 515 | } |
| 516 | $v = $b[$k]; |
| 517 | if($d === $v) |
| 518 | continue; |
| 519 | if(is_array($d)) { |
| 520 | if(is_array($v)) { |
| 521 | if($d == $v) |
| 522 | continue; |
| 523 | $subArrayDiff = arrayDiff($d, $v, $delta); |
| 524 | if(!empty($subArrayDiff)) |
| 525 | $diff[$k] = $subArrayDiff; |
| 526 | continue; |
| 527 | } |
| 528 | $diff[$k] = [$d, $v]; |
| 529 | continue; |
| 530 | } |
| 531 | if(is_array($v) || is_null($d) || is_null($v)) { |
| 532 | $diff[$k] = [$d, $v]; |
| 533 | continue; |
| 534 | } |
| 535 | if(is_float($d) && is_float($v) || |
| 536 | is_numeric($d) && is_numeric($v) |
| 537 | ) { |
| 538 | // dd_($d,$v, abs($d), abs($v), bccomp($d, $v, 2)); |
| 539 | // if(abs($d - $v) > $delta ) |
| 540 | // if (bccomp($d, $v, 2)!=0) |
| 541 | if(abs($d - $v) > $delta ) |
| 542 | $diff[$k] = [$d, $v]; |
| 543 | continue; |
| 544 | } |
| 545 | if((is_string($d) || $d instanceof Stringable) && |
| 546 | (is_string($v) || $v instanceof Stringable) |
| 547 | ) { |
| 548 | if(strcasecmp($d, $v)) |
| 549 | $diff[$k] = [$d, $v]; |
| 550 | continue; |
| 551 | } |
| 552 | if($d != $v) |
| 553 | $diff[$k] = [$d, $v]; |
| 554 | } |
| 555 | foreach( array_diff_key($b, array_intersect_key($b, $a)) as $k => $soloEnB) |
| 556 | $diff[$k] = [null, $soloEnB]; |
| 557 | return $diff; |
| 558 | } |
| 559 | |
| 560 | if (!function_exists('array_is_list')) { |
| 561 | function array_is_list(array $a) { |
| 562 | return $a === [] || (array_keys($a) === range(0, count($a) - 1)); |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | function array_list_diff(array $a, array $b, float $delta = 1E-2):array { |
| 567 | if(!array_is_list($a) || !array_is_list($b)) |
| 568 | return arrayDiff($a, $b, $delta); |
| 569 | $diff = []; |
| 570 | $bLen = count($b); |
| 571 | foreach($a as $k => $aValue) { |
| 572 | if($k > $bLen - 1) { |
| 573 | $diff[$k] = [$aValue, null]; |
| 574 | continue; |
| 575 | } |
| 576 | $bValue = $b[$k]; |
| 577 | if($aValue === $bValue) |
| 578 | continue; |
| 579 | if(is_array($aValue)) { |
| 580 | if(is_array($bValue)) { |
| 581 | $d = array_list_diff($aValue, $bValue, $delta); |
| 582 | if(!empty($d)) |
| 583 | $diff[$k] = $d; |
| 584 | continue; |
| 585 | } |
| 586 | $diff[$k] = [$aValue, $bValue]; |
| 587 | continue; |
| 588 | } |
| 589 | if(is_array($bValue)) { |
| 590 | $diff[$k] = [$aValue, $bValue]; |
| 591 | continue; |
| 592 | } |
| 593 | if(in_array($aValue, $b)) { |
| 594 | continue; |
| 595 | } |
| 596 | $diff[$k] = [$aValue, $bValue]; |
| 597 | } |
| 598 | return $diff; |
| 599 | } |
| 600 | |
| 601 | function file_upload_error($err):string { |
| 602 | if( $err==0) |
| 603 | return ''; |
| 604 | elseif( $err==1) |
| 605 | return 'El archivo es demasiado grande'; |
| 606 | elseif( $err==2) |
| 607 | return 'El archivo es demasiado grande'; |
| 608 | elseif($err==3) |
| 609 | return 'Solo subio parte del archivo'; |
| 610 | elseif( $err==4) |
| 611 | return 'No subio el archivo'; |
| 612 | elseif( $err==6) |
| 613 | return 'No subio el archivo a tmp'; |
| 614 | elseif( $err==7) |
| 615 | return 'Error al escribir el archivo'; |
| 616 | elseif( $err==8) |
| 617 | return 'Tipo de archivo invalido'; |
| 618 | else |
| 619 | return 'Error al subir el archivo'; |
| 620 | } |
| 621 | |
| 622 | /** |
| 623 | * uploadErrorStr() |
| 624 | * |
| 625 | * @param string|int $indx |
| 626 | * @return string |
| 627 | */ |
| 628 | function uploadErrorStr($indx):string { |
| 629 | if( $_FILES[$indx]['error']==0) |
| 630 | return ''; |
| 631 | elseif( $_FILES[$indx]['error']==1) |
| 632 | return 'El archivo es demasiado grande'; |
| 633 | elseif( $_FILES[$indx]['error']==2) |
| 634 | return 'El archivo es demasiado grande'; |
| 635 | elseif( $_FILES[$indx]['error']==3) |
| 636 | return 'Solo subio parte del archivo'; |
| 637 | elseif( $_FILES[$indx]['error']==4) |
| 638 | return 'No subio el archivo'; |
| 639 | elseif( $_FILES[$indx]['error']==6) |
| 640 | return 'No subio el archivo a tmp'; |
| 641 | elseif( $_FILES[$indx]['error']==7) |
| 642 | return 'Error al escribir el archivo'; |
| 643 | elseif( $_FILES[$indx]['error']==8) |
| 644 | return 'Tipo de archivo invalido'; |
| 645 | else |
| 646 | return 'Error al subir el archivo'; |
| 647 | } |
| 648 | |
| 649 | /////////////////////////////////////// ip ////////////////////////////////////////// |
| 650 | /** |
| 651 | * ip_extract() |
| 652 | * |
| 653 | * @param string $ip |
| 654 | * @return array |
| 655 | */ |
| 656 | function ip_extract($ip): array |
| 657 | { |
| 658 | if (filter_var($ip, FILTER_VALIDATE_IP)) |
| 659 | return [$ip]; |
| 660 | $array = []; |
| 661 | if (@preg_match("/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/", $ip, $array)) |
| 662 | return $array; |
| 663 | $regexIPV6 = '/((([0-9a-fA-F]){1,4})\\:){7}([0-9a-fA-F]){1,4}/i'; |
| 664 | $array = []; |
| 665 | if (@preg_match($regexIPV6, $ip, $array)) |
| 666 | return $array; |
| 667 | if(str_contains(strtolower($ip), 'localhost')) |
| 668 | return ['localhost']; |
| 669 | return []; |
| 670 | } |
| 671 | /** |
| 672 | * ip_server_set() |
| 673 | * |
| 674 | * @param string $cual |
| 675 | * @return bool |
| 676 | */ |
| 677 | function ip_server_set($cual):bool { |
| 678 | if( !array_key_exists($cual,$_SERVER) ) |
| 679 | return false; |
| 680 | return strcasecmp($_SERVER[$cual],'unknown') !== 0 && $_SERVER[$cual] !== ''; |
| 681 | } |
| 682 | /** |
| 683 | * ip_get() |
| 684 | * |
| 685 | * @return string |
| 686 | */ |
| 687 | function ip_get():string { |
| 688 | $keys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED', |
| 689 | 'HTTP_CLIENT_IP','HTTP_VIA','HTTP_COMING_FROM','HTTP_X_COMING_FROM', |
| 690 | 'REMOTE_HOST','REMOTE_ADDR' |
| 691 | ]; |
| 692 | foreach($keys as $key) |
| 693 | if(array_key_exists($key, $_SERVER)) { |
| 694 | $ip = ip_extract($_SERVER[$key]); |
| 695 | if(count($ip) >= 1) |
| 696 | return $ip[0]; |
| 697 | } |
| 698 | return ''; |
| 699 | } |
| 700 | /** |
| 701 | * ip_getFull() |
| 702 | * |
| 703 | * @return string |
| 704 | */ |
| 705 | #[Pure] function ip_getFull():string { |
| 706 | $keys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED', |
| 707 | 'HTTP_CLIENT_IP','HTTP_VIA','HTTP_COMING_FROM','HTTP_X_COMING_FROM', |
| 708 | 'REMOTE_HOST','REMOTE_ADDR' |
| 709 | ]; |
| 710 | $fullIp = []; |
| 711 | foreach($keys as $key) |
| 712 | if(array_key_exists($key, $_SERVER)) |
| 713 | $fullIp[] = "$key: " . $_SERVER[$key]; |
| 714 | return implode(', ', $fullIp); |
| 715 | } |
| 716 | |
| 717 | ////////////////////// HTML ////////////////////////////////////////////////////////////////////////// |
| 718 | |
| 719 | /** |
| 720 | * redirect() |
| 721 | * |
| 722 | * @param string $url |
| 723 | * @return void |
| 724 | */ |
| 725 | function redirect($url) { |
| 726 | $requestProtocol = array_key_exists('SERVER_PROTOCOL',$_SERVER) ? $_SERVER["SERVER_PROTOCOL"] : 'HTTP/1.0'; |
| 727 | $protocolArr = explode("/",$requestProtocol); |
| 728 | $protocolName = isset($protocolArr[1]) ? trim($protocolArr[0]) : 'HTTP/1.0'; |
| 729 | $protocolVersion = isset($protocolArr[1]) ? trim($protocolArr[1]): ''; |
| 730 | if (stristr($protocolName,"HTTP") && strtolower($protocolVersion) > "1.0" ) { |
| 731 | $httpStatusCode = 307; |
| 732 | } else { |
| 733 | $httpStatusCode = 302; |
| 734 | } |
| 735 | $httpStatusLine = "$requestProtocol $httpStatusCode Temporary Redirect"; |
| 736 | @header($httpStatusLine, TRUE, $httpStatusCode); |
| 737 | @header("Location: $url"); |
| 738 | } |
| 739 | |
| 740 | /** |
| 741 | * @return string root del site https://dominio/vitex sin la diagonal final |
| 742 | */ |
| 743 | function siteRootUrl():string { |
| 744 | global $gWebDir; |
| 745 | return |
| 746 | (empty($_SERVER['HTTPS']) ? "http://$_SERVER[SERVER_NAME]" : "https://$_SERVER[SERVER_NAME]") . |
| 747 | ":$_SERVER[SERVER_PORT]/$gWebDir"; |
| 748 | } |
| 749 | |
| 750 | /** |
| 751 | * ia_convertBytes() |
| 752 | * |
| 753 | * @param string|int|float $bytes |
| 754 | * @return string |
| 755 | */ |
| 756 | function ia_convertBytes($bytes):string { |
| 757 | if(empty($bytes) || !is_numeric($bytes)) |
| 758 | return $bytes; |
| 759 | if($bytes<0) { |
| 760 | $signo = '-'; |
| 761 | $bytes *= -1; |
| 762 | } else |
| 763 | $signo=''; |
| 764 | if($bytes<=1024) { |
| 765 | $decs=0; |
| 766 | $punto=''; |
| 767 | } else { |
| 768 | $decs=2; |
| 769 | $punto='.'; |
| 770 | } |
| 771 | $unit=array('b','Kb','Mb','Gb','Tb','Pb'); |
| 772 | |
| 773 | /** @noinspection PhpRedundantOptionalArgumentInspection */ |
| 774 | return $signo.@number_format($bytes/@pow(1024, |
| 775 | ($i=floor(log($bytes,1024)))), |
| 776 | $decs,$punto,',').' '.$unit[$i]; |
| 777 | } |
| 778 | |
| 779 | |
| 780 | /** |
| 781 | * ia_errores_a_dime() |
| 782 | * |
| 783 | * @param string $message |
| 784 | * @param string $file |
| 785 | * @param string $error_type |
| 786 | * @param int|string $line |
| 787 | * @param string $md5 |
| 788 | * @param bool $showSqlTrace |
| 789 | * @return void |
| 790 | * @noinspection PhpUnusedParameterInspection |
| 791 | */ |
| 792 | function ia_errores_a_dime($message = '', $file = '', $error_type = 'Manual', $line = 0, |
| 793 | $md5 = '', $showSqlTrace = false):void { |
| 794 | global $gSqlClass, $gNewDime; |
| 795 | require_once(__DIR__ . '/ErrorReporter/iaErrorReporter.php'); |
| 796 | $gNewDime = new iaErrorReporter($gSqlClass); // ia\Log\ |
| 797 | if(!empty($message)) { |
| 798 | $gNewDime->errorManual($message, $file, $error_type, $line, $md5); |
| 799 | } |
| 800 | $gNewDime->process(); |
| 801 | } |
| 802 | |
| 803 | |
| 804 | |
| 805 | /** |
| 806 | * |
| 807 | * |
| 808 | * @param bool $scriptTime |
| 809 | * @param bool $rusage |
| 810 | * @param bool $ram |
| 811 | * @param bool $sqlErrors |
| 812 | * @param bool $sqlTrace |
| 813 | * @param bool $phpErr |
| 814 | * @return string |
| 815 | * @noinspection PhpUnusedParameterInspection |
| 816 | */ |
| 817 | function ia_report_status_collapsable( |
| 818 | $scriptTime=true, $rusage=true, $ram=true, $sqlErrors=true, $sqlTrace=true, $phpErr=true):string { |
| 819 | global $gNewDime, $gSqlClass, $gDebugging; |
| 820 | if(empty($gNewDime)) |
| 821 | $gNewDime = new iaErrorReporter($gSqlClass); |
| 822 | if($gNewDime->displayErrors()) |
| 823 | echo "<script>gDisplayErrorInPage = true; jQuery(function(){ _displayErrorInPage(); }); </script>"; |
| 824 | else |
| 825 | echo "<script>gDisplayErrorInPage = false;</script>"; |
| 826 | if($gDebugging) |
| 827 | file_debug_reporte(); |
| 828 | return ''; |
| 829 | } |
| 830 | |
| 831 | |
| 832 | // files |
| 833 | /** |
| 834 | * file_size_formatted() |
| 835 | * |
| 836 | * @param string|int|float $size |
| 837 | * @return string |
| 838 | */ |
| 839 | function file_size_formatted($size):string { |
| 840 | $size = (float)$size; |
| 841 | if($size<1024) |
| 842 | return $size.'b'; |
| 843 | if($size<1024*1024) |
| 844 | return round($size/1024.00).'Kb'; |
| 845 | if($size<1024*1024*1024) |
| 846 | return round($size/(1024.00*1024.00),1).'Mb'; |
| 847 | return round($size/(1024.00*1024.00*1024.00),1).'Gb'; |
| 848 | } |
| 849 | |
| 850 | /** |
| 851 | * file_is_image() |
| 852 | * |
| 853 | * @param string $fileName |
| 854 | * @return bool |
| 855 | */ |
| 856 | function file_is_image($fileName):bool { |
| 857 | $dot=strrpos($fileName,'.'); |
| 858 | if($dot===FALSE) |
| 859 | return false; |
| 860 | $ext=substr($fileName,$dot+1); |
| 861 | return (strcasecmp($ext,'jpg') === 0 || strcasecmp($ext,'jpeg') === 0 || |
| 862 | strcasecmp($ext,'gif') === 0 || strcasecmp($ext,'png') === 0 ); |
| 863 | } |
| 864 | |
| 865 | /** |
| 866 | * file_icon() |
| 867 | * |
| 868 | * @param string $fileName |
| 869 | * @return string |
| 870 | */ |
| 871 | function file_icon($fileName):string { |
| 872 | global $gIApath; |
| 873 | |
| 874 | $dot=strrpos($fileName,'.'); |
| 875 | if($dot === FALSE) |
| 876 | return ''; |
| 877 | $ext=substr($fileName,$dot+1); |
| 878 | if(strcasecmp($ext,'jpg')===0 || strcasecmp($ext,'jpeg')===0 || |
| 879 | strcasecmp($ext,'gif')===0 || strcasecmp($ext,'png')===0 || |
| 880 | strcasecmp($ext,'bmp')===0 || strcasecmp($ext,'ico')===0 ) |
| 881 | return "$gIApath[WebPath]img/ext/jpg.gif"; |
| 882 | if(strcasecmp($ext,'avi')===0 || strcasecmp($ext,'mpeg')===0 || |
| 883 | strcasecmp($ext,'rm')===0 || strcasecmp($ext,'wmp')===0 ) |
| 884 | return "$gIApath[WebPath]img/ext/video.gif"; |
| 885 | $gifs=array('csv','doc','docx','gif','htm','html','jpeg','jpg','pdf','png','pps','ppsx','ppt','pptx','video','wav','xls','xlsx'); |
| 886 | if(in_array($ext,$gifs)) |
| 887 | return "$gIApath[WebPath]img/ext/$ext.gif"; |
| 888 | return "$gIApath[WebPath]img/ext/clip.gif"; |
| 889 | } |
| 890 | |
| 891 | // IMAGES |
| 892 | /** |
| 893 | * ia_image_tag_size() |
| 894 | * |
| 895 | * @param mixed $imageFile |
| 896 | * @return string |
| 897 | */ |
| 898 | function ia_image_tag_size(mixed $imageFile):string { |
| 899 | try { |
| 900 | if(!file_exists($imageFile) ) |
| 901 | return ''; |
| 902 | $size = filesize($imageFile); |
| 903 | if($size === FALSE) |
| 904 | $size = ''; |
| 905 | else |
| 906 | $size = file_size_formatted($size); |
| 907 | if(file_is_image($imageFile)) { |
| 908 | $arr = @getimagesize($imageFile); // 0=width, 1=height, 3=height, width tag |
| 909 | if($arr === FALSE || !is_array($arr) || sizeof($arr) < 4) |
| 910 | return $size; |
| 911 | return "w: $arr[0]px h:$arr[1]px $size"; |
| 912 | } |
| 913 | return $size; |
| 914 | } catch(Exception) { return ''; } |
| 915 | } |
| 916 | |
| 917 | /** |
| 918 | * @param int|float|string $w |
| 919 | * @param int|float|string $h |
| 920 | * @param bool $cssFormat |
| 921 | * @return string |
| 922 | */ |
| 923 | function ia_img_format($w, $h, $cssFormat):string { if($cssFormat) return "width: $w"."px; height: $h".'px'; return "width='$w' height='$h'"; } |
| 924 | |
| 925 | /** |
| 926 | * ia_image_tagsize_fitmax() |
| 927 | * ajusta imagen al tamaño |
| 928 | * @param mixed $imageFile path fisico a imagen o array(0=>w,1=>h) |
| 929 | * @param string|int $max_width maximo width deseado, 0 cualsea |
| 930 | * @param string|int $max_height maximo height deseado, 0 cualsea |
| 931 | * @param bool $cssFormat true regresa css flase |
| 932 | * @param bool $enLarge |
| 933 | * @return string en $cssFormat true width:npx; height:xpx en false width='xpx' height='ypx' |
| 934 | */ |
| 935 | function ia_image_tagsize_fitmax( $imageFile, $max_width, $max_height, |
| 936 | $cssFormat=true, $enLarge=false):string { |
| 937 | try { |
| 938 | if(is_array($imageFile)) |
| 939 | $arr=$imageFile; |
| 940 | else { |
| 941 | if (!file_exists($imageFile)) |
| 942 | return ''; |
| 943 | $arr=@getimagesize($imageFile); // 0=width, 1=height, 3=height, width tag |
| 944 | if($arr===FALSE || !is_array($arr) || sizeof($arr)<4) return ''; |
| 945 | } |
| 946 | $w=$arr[0]; |
| 947 | $h=$arr[1]; |
| 948 | |
| 949 | if(!empty($max_width) && !empty($max_height) ) { |
| 950 | |
| 951 | if($w==$max_width && $h==$max_height) |
| 952 | return ia_img_format($w,$h,$cssFormat); |
| 953 | if(!$enLarge && $w<=$max_width && $h<=$max_height) |
| 954 | return ia_img_format($w,$h,$cssFormat); |
| 955 | if($w==0 || $h==0) |
| 956 | return ia_img_format($max_width,$max_height,$cssFormat); |
| 957 | if($enLarge && $w <= $max_width && $h <= $max_height) { |
| 958 | if($w>$h) |
| 959 | return ia_img_format($max_width,round($max_width*$h/$w),$cssFormat); |
| 960 | else |
| 961 | return ia_img_format(round($max_height*$w/$h),$max_height,$cssFormat); |
| 962 | } |
| 963 | if( $w>$max_width && $h<=$max_height) |
| 964 | return ia_img_format($max_width,round($max_width*$h/$w),$cssFormat); |
| 965 | if( $w<=$max_width && $h>$max_height) |
| 966 | return ia_img_format(round($max_height*$w/$h),$max_height,$cssFormat); |
| 967 | // ambas mayores |
| 968 | if($w>=$h) |
| 969 | return ia_img_format($max_width,round($max_width*$h/$w),$cssFormat); |
| 970 | else |
| 971 | return ia_img_format(round($max_height*$w/$h),$max_height,$cssFormat); |
| 972 | } |
| 973 | if(empty($max_height)) { |
| 974 | |
| 975 | if($w==$max_width) |
| 976 | return ia_img_format($w,$h,$cssFormat); |
| 977 | if( $w <= $max_width) { |
| 978 | if( $enLarge ) |
| 979 | return ia_img_format($max_width,round($max_width*$h/$w),$cssFormat); |
| 980 | else |
| 981 | return ia_img_format($w,$h,$cssFormat); |
| 982 | } |
| 983 | return ia_img_format($max_width,round($max_width*$h/$w),$cssFormat); |
| 984 | } |
| 985 | if(empty($max_width)) { |
| 986 | |
| 987 | if($h == $max_height) |
| 988 | return ia_img_format($w,$h,$cssFormat); |
| 989 | if($h <= $max_height) { |
| 990 | if( $enLarge ) { |
| 991 | return ia_img_format(round($max_height*$w/$h),$max_height, $cssFormat); |
| 992 | } else { |
| 993 | return ia_img_format($w,$h,$cssFormat); |
| 994 | } |
| 995 | } |
| 996 | return ia_img_format(round($max_height*$w/$h),$max_height,$cssFormat); |
| 997 | } |
| 998 | return ia_img_format($w,$h,$cssFormat ); |
| 999 | } catch(Exception) { return ''; } |
| 1000 | } |
| 1001 | |
| 1002 | /** |
| 1003 | * removeAccents() |
| 1004 | * |
| 1005 | * @param string $str |
| 1006 | * @return string |
| 1007 | */ |
| 1008 | function removeAccents($str):string { |
| 1009 | //return URLify::filter($str); Ademas quita los caracteres raros https://github.com/jbroadway/urlify |
| 1010 | return URLify::downcode($str); |
| 1011 | //return strtr(utf8_decode($str), utf8_decode('àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ'), 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY'); |
| 1012 | } |
| 1013 | |
| 1014 | /** |
| 1015 | * filename_safe() |
| 1016 | * |
| 1017 | * @param string $fileName |
| 1018 | * @return string |
| 1019 | */ |
| 1020 | function filename_safe($fileName):string { |
| 1021 | if(str_starts_with($fileName, '.')) |
| 1022 | $fileName='_'.substr($fileName,1); |
| 1023 | return str_replace(array('|','>', '<', '&', ' ','(',')','-','*','?','!','|','`'.'´','"',"'".'..'.DIRECTORY_SEPARATOR,DIRECTORY_SEPARATOR,"\\","/",'[',']','{','}') |
| 1024 | ,'_',removeAccents($fileName)); |
| 1025 | } |
| 1026 | |
| 1027 | /** |
| 1028 | * filename_extension() |
| 1029 | * |
| 1030 | * @param mixed $fileName |
| 1031 | * @return string |
| 1032 | */ |
| 1033 | function filename_extension($fileName):string { |
| 1034 | $pos=strrchr($fileName,'.'); |
| 1035 | if($pos===FALSE || $pos==$fileName) |
| 1036 | return ''; |
| 1037 | return substr($pos,1); |
| 1038 | } |
| 1039 | |
| 1040 | /** |
| 1041 | * error_last() |
| 1042 | * |
| 1043 | * @return string |
| 1044 | */ |
| 1045 | function error_last():string { |
| 1046 | if ( !function_exists('error_get_last')) |
| 1047 | return ''; |
| 1048 | $tmp=error_get_last(); |
| 1049 | if($tmp) |
| 1050 | return "Error($tmp[type]): $tmp[message] at $tmp[file] line $tmp[line]"; |
| 1051 | else |
| 1052 | return ''; |
| 1053 | } |
| 1054 | |
| 1055 | |
| 1056 | /// ia_case specific |
| 1057 | global $gAppRelate; |
| 1058 | /** |
| 1059 | * gAppRelate_set() |
| 1060 | * |
| 1061 | * @return void |
| 1062 | */ |
| 1063 | function gAppRelate_set() { |
| 1064 | global $gAppRelate; |
| 1065 | if( empty($gAppRelate) ) |
| 1066 | $gAppRelate=new appRelate(); |
| 1067 | } |
| 1068 | |
| 1069 | /* @noinspection PhpUnused */ |
| 1070 | // function vale_where() {} |
| 1071 | |
| 1072 | /** |
| 1073 | * array_val() |
| 1074 | * Regresa el valor de key en el array o default de no existir |
| 1075 | * @param string $key |
| 1076 | * @param array $array |
| 1077 | * @param mixed $default |
| 1078 | * @return mixed valor de $key en el array o $default de no existir |
| 1079 | */ |
| 1080 | function array_val($key, $array, $default = false): mixed |
| 1081 | { |
| 1082 | if(array_key_exists($key,$array)) |
| 1083 | return $array[$key]; |
| 1084 | return $default; |
| 1085 | } |
| 1086 | |
| 1087 | function _numOr0($n):string|int|float { |
| 1088 | return is_numeric($n) ? $n : 0; |
| 1089 | } |
| 1090 | |
| 1091 | /** |
| 1092 | * date_limit() |
| 1093 | * |
| 1094 | * @param int|float|string|null $lim |
| 1095 | * @param string|null $base_date |
| 1096 | * @param bool $incluye_dom |
| 1097 | * @param bool $incluye_sab |
| 1098 | * @param bool $forzaInicioAno |
| 1099 | * @return string |
| 1100 | */ |
| 1101 | function date_limit($lim, $base_date = null, |
| 1102 | $incluye_dom = true, $incluye_sab = true, $forzaInicioAno = false):string { |
| 1103 | if(empty($lim)) { |
| 1104 | return ''; |
| 1105 | } |
| 1106 | if( preg_match('/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\d|3[0-1])$/', $lim) ) { |
| 1107 | return $lim; |
| 1108 | } |
| 1109 | if( is_numeric($lim)) { |
| 1110 | if(strlen($lim ) === 4) { |
| 1111 | return "$lim-01-01"; |
| 1112 | } |
| 1113 | if(strlen($lim ) > 6) { |
| 1114 | return Date('Y-m-d', $lim ); |
| 1115 | } |
| 1116 | } |
| 1117 | |
| 1118 | if(empty($base_date)) { |
| 1119 | $base_date = Date('Y-m-d'); |
| 1120 | } |
| 1121 | $baseTimeStamp = strtotime($base_date); |
| 1122 | $base_year = _numOr0(substr($base_date,0,4) ); |
| 1123 | |
| 1124 | |
| 1125 | $anos = $meses = $semanas = $dias = 0; |
| 1126 | $tmp=explode(' ',$lim); |
| 1127 | if($tmp) { |
| 1128 | foreach ($tmp as $d) { |
| 1129 | $d = trim($d); |
| 1130 | if (stripos($d, 'y') !== false) { |
| 1131 | $anos += _numOr0(str_ireplace('y', '', $d)); |
| 1132 | } elseif (stripos($d, 'm') !== false) |
| 1133 | $meses += _numOr0(str_ireplace('m', '', $d)); |
| 1134 | elseif (stripos($d, 'w') !== false) { |
| 1135 | $semanas += _numOr0(str_ireplace('w', '', $d)); |
| 1136 | } |
| 1137 | elseif (stripos($d, 'd') !== false) { |
| 1138 | $dias += _numOr0(str_ireplace('d', '', $d)); |
| 1139 | } |
| 1140 | else { |
| 1141 | $dias += _numOr0($d); |
| 1142 | } |
| 1143 | } |
| 1144 | } |
| 1145 | |
| 1146 | $fecha = mktime(0,0,0, |
| 1147 | (int)Date('n',$baseTimeStamp) + $meses, |
| 1148 | (int)Date('j',$baseTimeStamp) + $dias + ($semanas * 7), |
| 1149 | $base_year + $anos); |
| 1150 | |
| 1151 | $notSab = !$incluye_sab; |
| 1152 | $notDom = !$incluye_dom; |
| 1153 | if($notDom || $notSab) { |
| 1154 | $diffDias = abs(round(($fecha - $baseTimeStamp) / 86400) + 1); |
| 1155 | $masDias = floor($diffDias / 7) * ($notDom && $notSab ? 2 : 1); |
| 1156 | $diasem = (int)date("w", $fecha); |
| 1157 | if($diasem === 6 && $notSab) { |
| 1158 | $masDias++; |
| 1159 | } |
| 1160 | if($diasem === 0 && $notDom) { |
| 1161 | $masDias++; |
| 1162 | } |
| 1163 | $diasem = (int)date("w", $baseTimeStamp); |
| 1164 | if($diasem === 6 && $notSab) { |
| 1165 | $masDias++; |
| 1166 | } |
| 1167 | if($diasem === 0 && $notDom) { |
| 1168 | $masDias++; |
| 1169 | } |
| 1170 | $fecha=mktime(0,0,0, |
| 1171 | (int)Date('n', $fecha), |
| 1172 | (int)Date('j', $fecha) + $masDias, |
| 1173 | (int)Date('Y', $fecha) |
| 1174 | ); |
| 1175 | } |
| 1176 | |
| 1177 | return $forzaInicioAno ? Date('Y-01-01', $fecha) : Date('Y-m-d',$fecha); |
| 1178 | } |
| 1179 | |
| 1180 | /** |
| 1181 | * to_plural() |
| 1182 | * |
| 1183 | * @param string $word |
| 1184 | * @param bool $esMasculino |
| 1185 | * @return string |
| 1186 | */ |
| 1187 | function to_plural($word, $esMasculino = true):string { |
| 1188 | $w=substr($word,-1); |
| 1189 | |
| 1190 | if(strcasecmp('.',$w)==0) //VCA |
| 1191 | return $word; |
| 1192 | |
| 1193 | if( strcasecmp('a',$w)==0 || strcasecmp('e',$w)==0 || strcasecmp('i',$w)==0 || strcasecmp('o',$w)==0 || strcasecmp('u',$w)==0 |
| 1194 | || strcasecmp('á',$w)==0 || strcasecmp('é',$w)==0 || strcasecmp('í',$w)==0 || strcasecmp('ó',$w)==0 || strcasecmp('Ú',$w)==0 |
| 1195 | || strcasecmp('y',$w)==0 || strcasecmp('w',$w)==0 ) |
| 1196 | return $word.'s'; |
| 1197 | if(strcasecmp('z',$w)==0) |
| 1198 | return substr($word,0,-1).'ces'; |
| 1199 | $w2=substr($word,-2,1); |
| 1200 | if(strcasecmp('s',$w)==0 && ( strcasecmp('e',$w2)==0 || strcasecmp('u',$w2) )) |
| 1201 | return $word; |
| 1202 | if($esMasculino) |
| 1203 | return $word.'es'; |
| 1204 | else |
| 1205 | return $word.'as'; |
| 1206 | } |
| 1207 | |
| 1208 | /** |
| 1209 | * to_label() |
| 1210 | * |
| 1211 | * @param string $fieldName |
| 1212 | * @param bool $capWords |
| 1213 | * @param bool $htmlentities |
| 1214 | * @return string |
| 1215 | */ |
| 1216 | function to_label($fieldName, $capWords = true, $htmlentities = false ):string { |
| 1217 | $ret=preg_replace( |
| 1218 | array('/\baccion\b/i','/\baleman\b/i','/\balmacen\b/i','/\bano\b/i','/\banos\b/i','/\barea\b/i','/\bareas\b/i','/\barticulo\b/i','/\barticulos\b/i' |
| 1219 | ,'/\bbitacora\b/i','/\bbitacoras\b/i' |
| 1220 | ,'/\bcalculo\b/i','/\bcaracter\b/i','/\bcatalogo\b/i','/\bcatalogos\b/i','/\bcodigo\b/i','/\bcomentario\b/i','/\bcompania\b/i','/\bcompanias\b/i','/\bcp\b/i' |
| 1221 | ,'/\bdepostio\b/i','/\bdepostios\b/i','/\bdia\b/i','/\bdias\b/i','/\bdigito\b/i','/\bdigitos\b/i','/\bdolar\b/i','/\bdolares\b/i' |
| 1222 | ,'/\beconomia\b/i','/\belectronica\b/i','/\belectronico\b/i','/\belectronicos\b/i','/\bespanol\b/i' |
| 1223 | ,'/\binteres\b/i','/\bimagenes\b/i','/\bindice\b/i','/\bindices\b/i','/\bingles\b/i' |
| 1224 | ,'/\bfabrica\b/i','/\bfrances\b/i','/\bfotografica\b/i' |
| 1225 | ,'/\bgrafica\b/i' |
| 1226 | ,'/\bhuesped\b/i' |
| 1227 | ,'/\blimite\b/i' |
| 1228 | ,'/\bmaquina\b/i','/\bmaquinas\b/i','/\bmaximo\b/i','/\bmaximos\b/i','/\bmecancia\b/i','/\bmedico\b/i','/\bmexico\b/i','/\bmiercoles\b/i','/\bminimo\b/i','/\bminimos\b/i','/\bmusica\b/i' |
| 1229 | ,'/\bnumero\b/i','/\bnumeros\b/i' |
| 1230 | ,'/\bpagina\b/i','/\bpaginas\b/i','/\bpais\b/i','/\bpaises\b/i','/\bparticula\b/i','/\bpelicula\b/i','/\bpie\b/i','/\bpolitica\b/i','/\bportuges\b/i','/\bpublico\b/i' |
| 1231 | ,'/\brazon\b/i','/\bresumen\b/i' |
| 1232 | ,'/\bsabado\b/i' |
| 1233 | ,'/\btecnica\b/i','/\btelefono\b/i','/\btelefonos\b/i','/\btio\b/i','/\btitulo\b/i','/\btitulos\b/i','/\btunel\b/i' |
| 1234 | ,'/\bunica\b/i','/\bunico\b/i','/\bultimo\b/i','/\bultimos\b/i','/\bultima\b/i','/\bultimas\b/i' |
| 1235 | ,'/\busuario\b/i' |
| 1236 | ,'/ion\b/i' |
| 1237 | ) |
| 1238 | ,array('acción','alemán','almacén','año','años','área','áreas','artículo','artículos' |
| 1239 | ,'bitácora','bitácoras' |
| 1240 | ,'cálculo','caractér','catálogo','catálogos','código','comentario','compañía','compañias','C.P.' |
| 1241 | ,'depósito','depósitos','día','días','dígito','dígitos','dólar','dólares' |
| 1242 | ,'economía','electrónica','electrónico','electrónicos','español' |
| 1243 | ,'interés','imágenes','índice','índices','inglés' |
| 1244 | ,'fábrica','fránces','fotográfica' |
| 1245 | ,'gráfica' |
| 1246 | ,'huésped' |
| 1247 | ,'límite' |
| 1248 | ,'máquina','máquinas','máximo','máximos','mecánica','médico','México','miércoles','mínimo','mínimos','música' |
| 1249 | ,'número','números' |
| 1250 | ,'página','páginas','país','paises','partícula','película','pié','política','portugués','público' |
| 1251 | ,'razon','resumen' |
| 1252 | ,'sábado' |
| 1253 | ,'tecnica','teléfono','teléfonos','tio','título','títulos','túnel' |
| 1254 | ,'Única','Único','Último','Últimos','Última','Últimas' |
| 1255 | ,'usuario' |
| 1256 | ,'ión' |
| 1257 | ) |
| 1258 | ,preg_replace( |
| 1259 | array('/^idioma_/','/^kv_/','/^iac_/','/_id$/','/_/') |
| 1260 | ,array('','','','',' ') |
| 1261 | ,$fieldName ?? '' |
| 1262 | ) |
| 1263 | ); |
| 1264 | if($ret === 'rfc' || $ret === 'curp' || $ret === 'imss' || $ret === 'cp') |
| 1265 | return strtoupper($ret); |
| 1266 | if($capWords) |
| 1267 | $ret=ucwords($ret ?? ''); |
| 1268 | if($htmlentities) |
| 1269 | return ia_htmlentities( str_replace( array(' De ',' A ',' Del ',' Al ',' El ',' La ',' Las ',' Los '), array(' de ',' a ',' del ', ' al ', ' el ',' la ',' las ',' los '),$ret ) ); |
| 1270 | else |
| 1271 | return str_replace( array(' De ',' A ',' Del ',' Al ',' El ',' La ',' Las ',' Los '), array(' de ',' a ',' del ', ' al ', ' el ',' la ',' las ',' los '),$ret ); |
| 1272 | } |
| 1273 | |
| 1274 | |
| 1275 | |
| 1276 | /** |
| 1277 | * @param int|string $month |
| 1278 | * @param int|string $day |
| 1279 | * @param int|string $year |
| 1280 | * @return false|int |
| 1281 | */ |
| 1282 | function ia_mktime_day($month, $day, $year):false|int { |
| 1283 | return mktime(0,0,0,$month,$day,$year); |
| 1284 | } |
| 1285 | |
| 1286 | function array2Select( |
| 1287 | $datos, $key, $valor, $set_val = null, $identifier = 'select', $label = 'Seleccione', |
| 1288 | $onlyOptions = false, $addNull = true, $extra_data = [], $extra_html = ['html'=> '', 'keys' => []], $height_personal = null, |
| 1289 | $isSelectize = true, $group= null |
| 1290 | ): string |
| 1291 | { |
| 1292 | $class = (!$isSelectize) ? 'notSelectize' : 'selectize'; |
| 1293 | $select = $onlyOptions ? "" : "<select class='$class' name='$identifier' id='$identifier'>"; |
| 1294 | if($addNull) { |
| 1295 | $select .= "<option value=''>$label</option>"; |
| 1296 | } |
| 1297 | $keysReplace = $extra_html['keys'] ?? [];//'color_valor'; |
| 1298 | |
| 1299 | if (!empty($group)){ |
| 1300 | $datos = objetivisa_($datos, $group); |
| 1301 | foreach ($datos as $array_key => $items) { |
| 1302 | // dd_("ITEMS", $items); |
| 1303 | $options = ""; |
| 1304 | foreach ($items as $item) { |
| 1305 | $extraData = ""; |
| 1306 | foreach ($extra_data as $label_extra => $key_extra) { |
| 1307 | $dataLabel = (is_numeric($label_extra)) ? $key_extra: $label_extra; |
| 1308 | $extraData .= " data-$dataLabel='$item[$key_extra]' "; |
| 1309 | } |
| 1310 | $item = (array) $item; |
| 1311 | |
| 1312 | $data_extra_html = $extra_html['html'] ?? ''; |
| 1313 | foreach ($keysReplace as $keyReplace) { |
| 1314 | $strReplace = "{@$keyReplace}"; |
| 1315 | $data_extra_html = str_replace($strReplace, $item[$keyReplace], $data_extra_html); |
| 1316 | } |
| 1317 | if (!empty($data_extra_html)) { |
| 1318 | $data_extra_html = " data-extra_html='$data_extra_html' "; |
| 1319 | } |
| 1320 | $data_height_personal = ''; |
| 1321 | if (!empty($height_personal)) { |
| 1322 | $data_height_personal = " data-height_personal='$height_personal' "; |
| 1323 | } |
| 1324 | $selected = ""; |
| 1325 | if (is_array($set_val)) { |
| 1326 | if (in_array($item[$key], $set_val)) { |
| 1327 | $selected = "selected='selected'"; |
| 1328 | } |
| 1329 | } else { |
| 1330 | $selected = (string)$item[$key] === (string)$set_val ? "selected='selected'" : ""; |
| 1331 | } |
| 1332 | $options .= "<option value='".ia_htmlentities($item[$key])."' $selected $extraData $data_extra_html $data_height_personal>".ia_htmlentities($item[$valor])."</option>"; |
| 1333 | } |
| 1334 | $label = strtoupper($array_key); |
| 1335 | $select .= "<optgroup label='$label'>$options</optgroup>"; |
| 1336 | } |
| 1337 | } |
| 1338 | else { |
| 1339 | foreach ($datos as $item) { |
| 1340 | $extraData = ""; |
| 1341 | foreach ($extra_data as $label_extra => $key_extra) { |
| 1342 | $dataLabel = (is_numeric($label_extra)) ? $key_extra: $label_extra; |
| 1343 | $extraData .= " data-$dataLabel='$item[$key_extra]' "; |
| 1344 | } |
| 1345 | $item = (array) $item; |
| 1346 | |
| 1347 | $data_extra_html = $extra_html['html'] ?? ''; |
| 1348 | foreach ($keysReplace as $keyReplace) { |
| 1349 | $strReplace = "{@$keyReplace}"; |
| 1350 | $data_extra_html = str_replace($strReplace, $item[$keyReplace], $data_extra_html); |
| 1351 | } |
| 1352 | if (!empty($data_extra_html)) { |
| 1353 | $data_extra_html = " data-extra_html='$data_extra_html' "; |
| 1354 | } |
| 1355 | $data_height_personal = ''; |
| 1356 | if (!empty($height_personal)) { |
| 1357 | $data_height_personal = " data-height_personal='$height_personal' "; |
| 1358 | } |
| 1359 | $selected = ""; |
| 1360 | if (is_array($set_val)) { |
| 1361 | if (in_array($item[$key], $set_val)) { |
| 1362 | $selected = "selected='selected'"; |
| 1363 | } |
| 1364 | } else { |
| 1365 | $selected = (string)$item[$key] === (string)$set_val ? "selected='selected'" : ""; |
| 1366 | } |
| 1367 | |
| 1368 | $select .= "<option value='".ia_htmlentities($item[$key])."' $selected $extraData $data_extra_html $data_height_personal >" . ia_htmlentities($item[$valor])." </option>"; |
| 1369 | } |
| 1370 | } |
| 1371 | return $onlyOptions ? $select : "$select</select>"; |
| 1372 | |
| 1373 | } |
| 1374 | |
| 1375 | function colores($lang = 'es'):array |
| 1376 | { |
| 1377 | $colores = [ |
| 1378 | 'blue' => 'azul', |
| 1379 | 'green' => 'verde', |
| 1380 | 'red' => 'rojo', |
| 1381 | 'orange' => 'naranja', |
| 1382 | 'yellow' => 'amarillo', |
| 1383 | 'pink' => 'rosa', |
| 1384 | 'purple' => 'morado', |
| 1385 | 'black' => 'negro', |
| 1386 | 'white' => 'blanco', |
| 1387 | 'grey' => 'gris', |
| 1388 | 'gray' => 'gris', |
| 1389 | 'brown' => 'marrón', |
| 1390 | 'violet' => 'violeta', |
| 1391 | ]; |
| 1392 | if ($lang === 'es') { |
| 1393 | $colores = array_flip($colores); |
| 1394 | } |
| 1395 | return $colores; |
| 1396 | } |
| 1397 | |
| 1398 | #[NoReturn] |
| 1399 | function die_Script() |
| 1400 | { |
| 1401 | echo "<script>$(document).ready( function() { setTimeout(function() { $('#loadingMask').fadeOut(0); }, 10); });</script>"; |
| 1402 | ia_errores_a_dime(); |
| 1403 | die(); |
| 1404 | } |
| 1405 | |
| 1406 | function json_encode_ex($array, $flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE):string { |
| 1407 | $var = json_encode($array, $flags); |
| 1408 | preg_match_all('/(\"function.*?\")|(\"on_.*?\")|(\"\$d.*?\")|(\"colFmt.*?\")|(\"ia.*?\")/', $var, $matches); |
| 1409 | foreach ($matches[0] as $value) { |
| 1410 | $newval = str_replace(array('\n', '\t','\/'), array(PHP_EOL,"\t",'/'), trim($value, '"')); |
| 1411 | $var = str_replace($value, $newval, $var); |
| 1412 | } |
| 1413 | return $var; |
| 1414 | } |
| 1415 | |
| 1416 | /** |
| 1417 | * @param object|null $app |
| 1418 | * @param string $default |
| 1419 | * @param array $groupingOrder En que orden y que agrupaciones poner |
| 1420 | * @param string $labelPara |
| 1421 | * @param string $prefijo |
| 1422 | * @noinspection PhpUnusedParameterInspection |
| 1423 | */ |
| 1424 | function table_jqgrid_existencias(object|null $app = null, string $default = 'group_ProductoColorBodega', array $groupingOrder = [], |
| 1425 | string $labelPara = '', string $prefijo = '') |
| 1426 | { |
| 1427 | |
| 1428 | $existencias = new Existencias($app, $default, |
| 1429 | empty($groupingOrder) ? [$default] : $groupingOrder); |
| 1430 | $existencia = $existencias->getThisExistenciaList(); |
| 1431 | |
| 1432 | if(!empty($groupingOrder)) |
| 1433 | $existencia['groups'] = array_intersect_key($existencia['groups'], array_flip($groupingOrder)); |
| 1434 | $selectGroups = |
| 1435 | "<label for='groups_existencias'>con: </label> |
| 1436 | <select id='groups_existencias' class='notSelectize' style='cursor:pointer' onchange='setNewGrouping(this.value)'>". |
| 1437 | array2Select(datos: $existencia['groups'], key: 'value_group', valor: 'label', set_val: $default, onlyOptions: true, addNull: false) |
| 1438 | ."</select> |
| 1439 | <img style='cursor:pointer; margin-left: 2em;height:24px;width: 24px;border:0 silver solid;' src='../img/expandOne.png' alt='Expand one' title='Expand one' onclick='iaJqGridGrouping.expandOne(gridhandlerExistencia)' id='expand_one_existencias'> |
| 1440 | <img style='cursor:pointer; margin-left: 2em;height:32px; width:32px;border:0 silver solid;' src='../img/collapseAll.png' alt='Collapse all' title='Collapse all' onclick='iaJqGridGrouping.collapseAll(gridhandlerExistencia)' id='collapse_all_existencias'> |
| 1441 | <img style='cursor:pointer; margin-left: 2em;height:32px; width:32px ;border:0 silver solid;' src='../img/expandAll.png' alt='Expand all' title='Expand all' onclick='iaJqGridGrouping.expandAll(gridhandlerExistencia)' id='expand_all_existencias'> |
| 1442 | <style> |
| 1443 | img:hover{ |
| 1444 | opacity: .5; |
| 1445 | overflow:visible; |
| 1446 | border:0 solid rgba(0,0,0,0.7); |
| 1447 | box-sizing:border-box; |
| 1448 | transition: all 0.4s ease-in-out; } |
| 1449 | </style>"; |
| 1450 | |
| 1451 | echo "<fieldset class='lblgrp'><legend style='vertical-align: top;'> Existencia $labelPara $selectGroups</legend>"; |
| 1452 | include_once (dirname(__DIR__).'/bodega/componentes/jqgrid_existencias_list.php'); |
| 1453 | echo "</fieldset>"; |
| 1454 | } |
| 1455 | |
| 1456 | |
| 1457 | /** @noinspection PhpUnusedParameterInspection */ |
| 1458 | function table_productos_remate($params = []) |
| 1459 | { |
| 1460 | /*$queryProductos = "SELECT |
| 1461 | producto_general_id, producto, en_remate, es_saldo, min_price, |
| 1462 | producto value, producto label, producto_general_id real_value |
| 1463 | FROM producto_general WHERE activo = 'Si' ORDER BY producto"; |
| 1464 | $productos = ia_sqlArray($queryProductos, 'producto_general_id'); |
| 1465 | $queryColores = "SELECT |
| 1466 | pc.producto_general_id pg_id, pc.producto_color_id, pc.producto_general_id, pc.color_id, c.color, c.color_valor, |
| 1467 | pc.en_remate, pc.es_saldo |
| 1468 | FROM producto_color pc |
| 1469 | JOIN color c USING(color_id) ORDER BY c.orden, c.color"; |
| 1470 | $colores = ia_sqlSelectMultiKey($queryColores, 2);*/ |
| 1471 | return include_once (dirname(__DIR__).'/bodega/componentes/table_productos_remate_list.php'); |
| 1472 | } |
| 1473 | |
| 1474 | /** |
| 1475 | * Cambia keys de $array ['producto_id'=>3, 'color'=>4], $newKeys=['color'=>'color.color'] regresa ['producto_id'=>3, 'color.color'=>4] |
| 1476 | * |
| 1477 | * @param array $array ie ['producto_id'=>3, 'color'=>4] |
| 1478 | * @param array $newKeys ie ['color'=>'color.color'] |
| 1479 | * @return array ie ['producto_id'=>3, 'color.color'=>4] |
| 1480 | */ |
| 1481 | function keyRemap(array $array, array $newKeys):array { |
| 1482 | $reMapped = []; |
| 1483 | foreach($array as $k => $v) |
| 1484 | $reMapped[ $newKeys[$k] ?? $k] = $v; |
| 1485 | return $reMapped; |
| 1486 | } |
| 1487 | |
| 1488 | /** |
| 1489 | * Regresa el label para bodegas. |
| 1490 | * @param array $bodega - [bodega => 'verde', label_bodega|label=> 'Clavel', bodega_id=> 'abcd1278y', color|bodega_color=> '##008000']. |
| 1491 | * @param array $extraSettings - [returnColor=> true|false, returnNane=> true|false, returnLabel=> true|false, isAnchor=> true|false, urlAnchor: '../../../', titleAnchor: 'titulo de ancla']. |
| 1492 | * - returnColor: Para regresar indicador de color. |
| 1493 | * - returnNane: Para regresar el nombre de la bodega. |
| 1494 | * - returnLabel: Para regresar la clave de la bodega. |
| 1495 | * - isAnchor: Para indicar que es un anchor (<a href=link a la bodega></a>). |
| 1496 | * - urlAnchor: Para indicar la url del anchor. |
| 1497 | */ |
| 1498 | function getLabelBodega(array $bodega = [], array $extraSettings = []): string |
| 1499 | { |
| 1500 | if (!is_array($bodega) || count(array_keys($bodega)) == 0) return ''; |
| 1501 | |
| 1502 | $settings = array_merge( |
| 1503 | ['returnColor' => true, 'returnNane' => true, 'returnLabel' => true, 'isAnchor' => false, 'urlAnchor' => null, 'titleAnchor' => null, 'IsHtml' => true, |
| 1504 | 'classes' => '' |
| 1505 | ], |
| 1506 | $extraSettings) |
| 1507 | ; |
| 1508 | |
| 1509 | $color = $bodega['bodega_color'] ?? $bodega['color'] ?? '#FFF'; |
| 1510 | $sectionColor = $settings['returnColor'] ? "<i style='background-color:$color; width: 1em; height: 1em; display: inline-block;margin-right: 5px; border: 1px solid black;'></i>":''; |
| 1511 | $sectionName = $settings['returnNane'] ? $bodega['bodega'] ?? '': ''; |
| 1512 | $label = $bodega['label_bodega'] ?? $bodega['label'] ?? ''; |
| 1513 | if($label !== '.' && $label !== '') |
| 1514 | $sectionLabel = $settings['returnLabel'] ? "<i style='font-weight:100;font-size:smaller'>($label)</i>": ''; |
| 1515 | else |
| 1516 | $sectionLabel = ''; |
| 1517 | |
| 1518 | if(empty($settings['grupo'])) |
| 1519 | $grupo = ''; |
| 1520 | else |
| 1521 | $grupo = empty($bodega['grupo']) ? '' : ' <i style="font-size:0.7em;font-weight: 100">' . ia_htmlentities($bodega['grupo']) . '</i> '; |
| 1522 | |
| 1523 | if (!$settings['IsHtml']) { |
| 1524 | return "$sectionName ($label)"; |
| 1525 | } |
| 1526 | |
| 1527 | $clases = ''; |
| 1528 | if (!empty($settings['classes'])) |
| 1529 | $clases = $settings['classes']; |
| 1530 | |
| 1531 | if (!$settings['isAnchor']) |
| 1532 | return "<span class='$clases'>$sectionColor $sectionName $sectionLabel$grupo</span>"; |
| 1533 | |
| 1534 | if (empty($settings['urlAnchor'])) |
| 1535 | $settings['urlAnchor'] = getUrlBase()."backoffice/bodega.php?id=$bodega[bodega_id]&iagridvar=iajqgridbodega_var&iah=e"; |
| 1536 | |
| 1537 | $titleAnchor = ''; |
| 1538 | if (!empty($settings['titleAnchor'])) |
| 1539 | $titleAnchor = "title='" . ia_htmlentities($settings['titleAnchor']) . "'"; |
| 1540 | |
| 1541 | |
| 1542 | return "<a href='$settings[urlAnchor]' $titleAnchor><span class='$clases'>$sectionColor $sectionName $sectionLabel</span></a>$grupo"; |
| 1543 | } |
| 1544 | |
| 1545 | function getUrlBase(): string |
| 1546 | { |
| 1547 | if (isset($_SERVER["HTTPS"])) |
| 1548 | $url_base = $_SERVER["HTTPS"] === 'on' ? 'https': 'http'; |
| 1549 | else |
| 1550 | $url_base = 'http'; |
| 1551 | |
| 1552 | $url_base .= "://"; |
| 1553 | if ($_SERVER["SERVER_PORT"] != "80") { |
| 1554 | $url_base .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"]."/".explode("/", $_SERVER["REQUEST_URI"])[1]; |
| 1555 | } else { |
| 1556 | $url_base .= $_SERVER["SERVER_NAME"]."/".explode("/", $_SERVER["REQUEST_URI"])[1]; |
| 1557 | } |
| 1558 | return $url_base . "/"; |
| 1559 | } |
| 1560 | function getUrlTo($location = '') |
| 1561 | { |
| 1562 | return getUrlBase() . $location; |
| 1563 | } |
| 1564 | /** |
| 1565 | * Elimina los items de un array |
| 1566 | * @param array $array |
| 1567 | * @param string|array $value |
| 1568 | * @return array |
| 1569 | */ |
| 1570 | function unsetItem(array $array, string|array $value): array |
| 1571 | { |
| 1572 | if (is_array($value)) { |
| 1573 | foreach ($value as $v) { |
| 1574 | if (isset($array[$v])) |
| 1575 | unset($array[$v]); |
| 1576 | } |
| 1577 | } else { |
| 1578 | unset($array[$value]); |
| 1579 | } |
| 1580 | return $array; |
| 1581 | } |
| 1582 | |
| 1583 | /** |
| 1584 | * @param array $array |
| 1585 | * @param string $on |
| 1586 | * @param int $order |
| 1587 | * @return array |
| 1588 | */ |
| 1589 | function array_sort(array $array, string $on, $order=SORT_ASC): array |
| 1590 | { |
| 1591 | $new_array = array(); |
| 1592 | $sortable_array = array(); |
| 1593 | |
| 1594 | if (count($array) > 0) { |
| 1595 | foreach ($array as $k => $v) { |
| 1596 | if (is_array($v)) { |
| 1597 | foreach ($v as $k2 => $v2) { |
| 1598 | if ($k2 == $on) { |
| 1599 | $sortable_array[$k] = $v2; |
| 1600 | } |
| 1601 | } |
| 1602 | } else { |
| 1603 | $sortable_array[$k] = $v; |
| 1604 | } |
| 1605 | } |
| 1606 | |
| 1607 | switch ($order) { |
| 1608 | case SORT_ASC: |
| 1609 | asort($sortable_array); |
| 1610 | break; |
| 1611 | case SORT_DESC: |
| 1612 | arsort($sortable_array); |
| 1613 | break; |
| 1614 | } |
| 1615 | |
| 1616 | foreach ($sortable_array as $k => $v) { |
| 1617 | $new_array[$k] = $array[$k]; |
| 1618 | } |
| 1619 | } |
| 1620 | |
| 1621 | return $new_array; |
| 1622 | } |
| 1623 | |
| 1624 | function getEnums(string $table, string $field) |
| 1625 | { |
| 1626 | $method = __FUNCTION__; |
| 1627 | /** @noinspection SqlResolve */ |
| 1628 | $enum_value = |
| 1629 | ia_singleread("SELECT /*$method*/ REPLACE(REPLACE(SUBSTRING(COLUMN_TYPE,7), \"'\", ''), ')', '') values_ FROM information_schema.COLUMNS WHERE TABLE_NAME=".strit($table)." AND COLUMN_NAME=".strit($field)); |
| 1630 | |
| 1631 | if (empty($enum_value)) |
| 1632 | return []; |
| 1633 | |
| 1634 | $enums = explode(",", $enum_value); |
| 1635 | return array_combine($enums, $enums); |
| 1636 | } |
| 1637 | |
| 1638 | function adjustBrightness($hex, $steps) { |
| 1639 | |
| 1640 | $colorsDefault = [ |
| 1641 | 'blue' => "#0000FF", |
| 1642 | 'azul' => "#0000FF", |
| 1643 | 'green' => '#008000', |
| 1644 | 'verde' => '#008000', |
| 1645 | 'red' => '#FF0000', |
| 1646 | 'rojo' => '#FF0000', |
| 1647 | 'orange' => '#FFA500', |
| 1648 | 'naranja' => '#FFA500', |
| 1649 | 'yellow' => '#FFFF00', |
| 1650 | 'amarillo' => '#FFFF00', |
| 1651 | 'pink' => '#FFC0CB', |
| 1652 | 'rosa' => '#FFC0CB', |
| 1653 | 'purple' => '#800080', |
| 1654 | 'morado' => '#800080', |
| 1655 | 'black' => '#000000', |
| 1656 | 'negro' => '#000000', |
| 1657 | 'white' => '#FFFFFF', |
| 1658 | 'blanco' => '#FFFFFF', |
| 1659 | 'gray' => '#808080', |
| 1660 | 'grey' => '#808080', |
| 1661 | 'gris' => '#808080', |
| 1662 | 'brown' => '#A52A2A', |
| 1663 | 'cafe' => '#A52A2A', |
| 1664 | 'maroon' => '#800000', |
| 1665 | 'marrón' => '#800000', |
| 1666 | 'violet' => '#EE82EE', |
| 1667 | 'violeta' => '#EE82EE', |
| 1668 | ]; |
| 1669 | |
| 1670 | $hex = strtolower($hex); |
| 1671 | |
| 1672 | $hex = $colorsDefault[$hex] ?? $hex; |
| 1673 | |
| 1674 | // Steps should be between -255 and 255. Negative = darker, positive = lighter |
| 1675 | $steps = max(-255, min(255, $steps)); |
| 1676 | |
| 1677 | // Normalize into a six character long hex string |
| 1678 | $hex = str_replace('#', '', $hex); |
| 1679 | if (strlen($hex) == 3) { |
| 1680 | $hex = str_repeat(substr($hex,0,1), 2).str_repeat(substr($hex,1,1), 2).str_repeat(substr($hex,2,1), 2); |
| 1681 | } |
| 1682 | |
| 1683 | // Split into three parts: R, G and B |
| 1684 | $color_parts = str_split($hex, 2); |
| 1685 | $return = '#'; |
| 1686 | |
| 1687 | foreach ($color_parts as $color) { |
| 1688 | $color = hexdec($color); // Convert to decimal |
| 1689 | $color = max(0,min(255,$color + $steps)); // Adjust color |
| 1690 | $return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code |
| 1691 | } |
| 1692 | |
| 1693 | return $return; |
| 1694 | } |
| 1695 | |
| 1696 | function limpiaDatos(array $datos):array { |
| 1697 | // dd_($movimiento); |
| 1698 | // $exclude_case_upper = ['cp_cliente_direccion_id_destino', 'cliente']; |
| 1699 | foreach ($datos as $key => &$value) { |
| 1700 | $partes = explode("_", $key); |
| 1701 | if ($partes[count($partes)-1] == 'id') |
| 1702 | continue; |
| 1703 | |
| 1704 | if(array_key_exists($key,['quantity'=>'', 'rollos'=>''] )) { |
| 1705 | $value = str_replace(',', '', strim($value)); |
| 1706 | continue; |
| 1707 | } |
| 1708 | if(!is_array($value)) { |
| 1709 | $value = strim($value); |
| 1710 | // $value = mb_convert_case(strim($value), MB_CASE_UPPER); |
| 1711 | } |
| 1712 | } |
| 1713 | return $datos; |
| 1714 | } |
| 1715 | |
| 1716 | |
| 1717 | function searchValueInArrayByColumn($value, $array, $column) |
| 1718 | { |
| 1719 | $index = array_search($value, array_column($array, $column)); |
| 1720 | |
| 1721 | if ($index !== false) |
| 1722 | return $array[$index]; |
| 1723 | |
| 1724 | return []; |
| 1725 | |
| 1726 | } |
| 1727 | |
| 1728 | function get_url_origin($s = null, $use_forwarded_host=false) { |
| 1729 | $s = ($s == null) ? $_SERVER: $s; |
| 1730 | $ssl = ( ! empty($s['HTTPS']) && $s['HTTPS'] == 'on' ) ? true:false; |
| 1731 | $sp = strtolower( $s['SERVER_PROTOCOL'] ); |
| 1732 | $protocol = substr( $sp, 0, strpos( $sp, '/' )) . ( ( $ssl ) ? 's' : '' ); |
| 1733 | |
| 1734 | $port = $s['SERVER_PORT']; |
| 1735 | $port = ( ( ! $ssl && $port == '80' ) || ( $ssl && $port=='443' ) ) ? '' : ':' . $port; |
| 1736 | |
| 1737 | $host = ( $use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] ) ) ? $s['HTTP_X_FORWARDED_HOST'] : ( isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null ); |
| 1738 | $host = isset( $host ) ? $host : $s['SERVER_NAME'] . $port; |
| 1739 | |
| 1740 | return $protocol . '://' . $host; |
| 1741 | |
| 1742 | } |
| 1743 | |
| 1744 | function get_full_url( $s = null, $use_forwarded_host=false ) { |
| 1745 | $s = ($s == null) ? $_SERVER: $s; |
| 1746 | return get_url_origin( $s, $use_forwarded_host ) . $s['REQUEST_URI']; |
| 1747 | } |
| 1748 | |
| 1749 | function get_url_out_params($url = '') |
| 1750 | { |
| 1751 | $url = empty($url) ? get_full_url(): $url; |
| 1752 | |
| 1753 | $parts = explode("?",$url); |
| 1754 | return $parts[0] ; |
| 1755 | } |
| 1756 | |
| 1757 | |
| 1758 | function notasFaltantes ($bodega_id) |
| 1759 | { |
| 1760 | |
| 1761 | } |
| 1762 | |
| 1763 | |
| 1764 | /** @noinspection PhpRedundantOptionalArgumentInspection */ |
| 1765 | function bodegasResumenNumeroNotas(array $bodegas, array $bodegasHacerMovimientos, int &$totalFaltan, $con_label = true):string { |
| 1766 | $ret = ''; $minNumNota = 0; $totalFaltan = 0; |
| 1767 | foreach($bodegas as $bodega_id => $b) { |
| 1768 | if( ($b['activo'] ?? 'Si') === 'No' ) |
| 1769 | continue; |
| 1770 | |
| 1771 | $gaps = NotaBodega::numerosDeNotasFaltantes($bodega_id, $minNumNota, false, false); |
| 1772 | $maxNumber = ia_singleread("SELECT MAX(numero_as_num) FROM nota_bodega WHERE bodega_id=" . strit($bodega_id)); |
| 1773 | $maxNumber == '' ? 1 : (int)$maxNumber + 1; |
| 1774 | if($maxNumber == '') |
| 1775 | $maxNumber = 1; |
| 1776 | |
| 1777 | $lastNoteFormatted = number_format($maxNumber, 0, '', ','); |
| 1778 | //$newNumberFormatted = number_format($newNumber, 0, '', ','); |
| 1779 | $numFaltan = count($gaps); |
| 1780 | if($numFaltan === 0) { |
| 1781 | $missingCount = ' Faltan: 0 # de notas'; |
| 1782 | //$displayGaps = ''; |
| 1783 | } else { |
| 1784 | $totalFaltan += $numFaltan; |
| 1785 | if($numFaltan > 30) { |
| 1786 | $gaps = NotaBodega::numerosDeNotasFaltantes($bodega_id, $minNumNota, true, false); |
| 1787 | //$len = count($gaps) - 1; |
| 1788 | //echo "<li>len=$len gaps=" . print_r($gaps, true); |
| 1789 | //$gaps[$len] = $gaps[$len] -2; |
| 1790 | array_walk($gaps , |
| 1791 | function(&$n){ |
| 1792 | $n = number_format($n, 0, '', ','); |
| 1793 | } |
| 1794 | ); |
| 1795 | $displayGaps = implode(" al ", $gaps ); |
| 1796 | |
| 1797 | } else { |
| 1798 | array_walk($gaps , |
| 1799 | function(&$n){ |
| 1800 | $n = number_format($n, 0, '', ','); |
| 1801 | } |
| 1802 | ); |
| 1803 | $displayGaps = implode("; ", $gaps); |
| 1804 | } |
| 1805 | if($numFaltan === 1) { |
| 1806 | $laS = $laN = ''; |
| 1807 | } else { |
| 1808 | $laS = 's'; $laN = 'n'; |
| 1809 | } |
| 1810 | $missingCount = |
| 1811 | "<span class='bodega_boxResumenShadow' style='color:red;font-weight: 800'>Falta$laN " . number_format($numFaltan, 0, '', ',') . " nota$laS: " . |
| 1812 | " <span style='color:red;font-weight: 800;font-size:2em;float:right'>✗</span>" . |
| 1813 | "<p style='clear:both;padding-left:2em;text-overflow: ellipsis; overflow: hidden;max-width:500px;max-height:4em;color:red;font-weight: 800'>$displayGaps</span>" . |
| 1814 | "</span>"; |
| 1815 | } |
| 1816 | |
| 1817 | $label = "<span style='cursor:pointer;' title='Ver última nota' onclick='dialogConsultarExistencia.consulta_ultima_nota(\"$bodega_id\")'>" . getLabelBodega($b) . "</span> "; |
| 1818 | if(array_key_exists($bodega_id, $bodegasHacerMovimientos)) { |
| 1819 | $link = "<a style='background:none!important;text-decoration:underline;color:blue;font-weight:bold;' href='../bodega/alta_movimiento.php?bodega_id=$b[bodega_id]&movimientode"; |
| 1820 | $label .= "$link=entrada'>Entrada</a> $link=salida'>Salida</a>"; |
| 1821 | } |
| 1822 | |
| 1823 | $ret .= |
| 1824 | "<li><div style='white-space: pre;width:fit-content'>" . $label . "</div>" . |
| 1825 | " <span class='bodega_boxResumenShadow' style='color:black'>Last Note: $lastNoteFormatted $missingCount</span>"; |
| 1826 | } |
| 1827 | return $ret; |
| 1828 | } |
| 1829 | |
| 1830 | function miniLog(array $values):string { |
| 1831 | $m=''; |
| 1832 | if(array_key_exists('iac_edits',$values) ) { |
| 1833 | $m.="<b>Cambios:</b> <i>".number_format($values['iac_edits'], 0, '', ',')."</i>"; |
| 1834 | } |
| 1835 | if( array_key_exists('ultimo_cambio',$values) || array_key_exists('ultimo_cambio_por',$values) |
| 1836 | ) { |
| 1837 | if($m!='') |
| 1838 | $m.='. '; |
| 1839 | $m.="<b>Último cambio</b>"; |
| 1840 | if(array_key_exists('ultimo_cambio',$values) ) |
| 1841 | $m.=" el: <i>".mysqlDate2display($values['ultimo_cambio']) . " (" . fechaDiff(Date('Y-m-d H:i:s'), $values['ultimo_cambio']) . ")</i>"; |
| 1842 | if(array_key_exists('ultimo_cambio_por',$values) ) |
| 1843 | $m.=' por: <i>'.$values['ultimo_cambio_por']."</i>"; |
| 1844 | |
| 1845 | |
| 1846 | if(!empty($values['modificacion_importante_el']) && $values['modificacion_importante_el'] !== '0000-00-00 00:00:00') |
| 1847 | $m.=" <span style='color:red'>Mod Imp el: <i>".mysqlDate2display($values['modificacion_importante_el']) . " (" . fechaDiff(Date('Y-m-d H:i:s'), $values['modificacion_importante_el']) . ")</i></span>"; |
| 1848 | if(!empty($values['modificacion_importante_por']) ) |
| 1849 | $m.=' por: <i>'.$values['modificacion_importante_por']."</i>"; |
| 1850 | |
| 1851 | if(array_key_exists('iac_last_edit_ip',$values) ) |
| 1852 | $m.=' IP: <i>'.$values['iac_last_edit_ip']."</i>"; |
| 1853 | } |
| 1854 | if(array_key_exists('alta_db',$values) || array_key_exists('alta_por',$values) ) { |
| 1855 | if($m!='') |
| 1856 | $m.='. | '; |
| 1857 | $m.=" <b>Alta</b>"; |
| 1858 | if(array_key_exists('alta_db',$values) ) |
| 1859 | $m.=" el: <i>".mysqlDate2display($values['alta_db']) . " (" . fechaDiff(Date('Y-m-d H:i:s'), $values['alta_db']) . ")</i>"; |
| 1860 | if(array_key_exists('alta_por',$values) ) |
| 1861 | $m.=' por <i>'.$values['alta_por']."</i>"; |
| 1862 | } |
| 1863 | return $m; |
| 1864 | } |
| 1865 | |
| 1866 | /** |
| 1867 | * Redondea y pone comas a un numero en string, number_format para strings |
| 1868 | * |
| 1869 | * @param string|int|float|null|bool $num |
| 1870 | * @param int $decimals |
| 1871 | * @return string el $num con comas y redondeado al $decimals decimales |
| 1872 | */ |
| 1873 | function bcformat(string|int|float|null|bool $num, int $decimals=2):string { |
| 1874 | if($num === null || $num === '') |
| 1875 | return ''; |
| 1876 | if(!is_numeric($num)) |
| 1877 | return $num; |
| 1878 | $num = bcadd("0", numeric2string($num), $decimals); |
| 1879 | $int = strstr($num, '.', true); |
| 1880 | if($int === false) { |
| 1881 | $int = $num; |
| 1882 | $frac = ''; |
| 1883 | } else { |
| 1884 | $frac = strstr($num, '.'); |
| 1885 | } |
| 1886 | return preg_replace('/(\d)(?=(\d{3})+(?!\d))/mS', '$1,', $int) . $frac; |
| 1887 | } |
| 1888 | |
| 1889 | function numeric2string($number) { |
| 1890 | if(is_array($number)) { |
| 1891 | foreach($number as &$n) |
| 1892 | $n = numeric2string($n); |
| 1893 | return $number; |
| 1894 | } |
| 1895 | if(empty($number)) |
| 1896 | return "0"; |
| 1897 | if(!is_numeric($number) || stripos("$number", 'E') === false) |
| 1898 | return "$number"; |
| 1899 | return rtrim(rtrim(bcmul(sprintf("%.20f", $number ), '1', 20), '0'), '.'); |
| 1900 | } |
| 1901 | |
| 1902 | /** |
| 1903 | * Abs para bc math |
| 1904 | * |
| 1905 | * @param string $num |
| 1906 | * @param int $decimals |
| 1907 | * @return string |
| 1908 | */ |
| 1909 | function bcabs($num, $decimals):string { |
| 1910 | return bccomp("0", $num, $decimals) >= 0 ? |
| 1911 | bcmul("-1", $num, $decimals) : |
| 1912 | $num; |
| 1913 | } |
| 1914 | |
| 1915 | /** |
| 1916 | * Pasa la existencia de un producto-color de una bodega a cero, revisando permisos. |
| 1917 | * |
| 1918 | * @param string $producto_bodega_id |
| 1919 | * @return string|array empty ok producto fue reseted |
| 1920 | */ |
| 1921 | function producto_color_reset($producto_bodega_id, $execute = true, $solo_qty = false, &$existencia_return = []):string|array { |
| 1922 | // Valida Permisos del usuario |
| 1923 | if(!usuarioTipoRony() && !usuarioSupervisaBodega() && !puedePermisoUsuario(nombrePermiso: 'puede_hacer_reset_producto_color')) { |
| 1924 | return "SIN PERMISO"; |
| 1925 | } |
| 1926 | // Obtén bodega-producto-color a pasar a ceros |
| 1927 | $method = __FUNCTION__; |
| 1928 | $sql = "SELECT /*$method*/ pb.producto_bodega_id, pb.bodega_id, pb.producto_general_id, pb.color_id, |
| 1929 | pb.existencia_rollos, pb.existencia_quantity, |
| 1930 | pb.existencia_rollos as rollos, pb.existencia_quantity as quantity, |
| 1931 | pc.en_remate, pc.es_saldo, pc.lento, pc.super_lento, |
| 1932 | IF(existencia_rollos < 0 || existencia_quantity < 0, 'Entrada', 'Salida') as entrada_salida, |
| 1933 | (SELECT origen_bodega_id FROM origen_bodega WHERE bodega_id = pb.bodega_id) AS origen_id, |
| 1934 | -- '' as origen_id, |
| 1935 | 'Correccion' as es, 'Correccion' as tipo |
| 1936 | FROM producto_bodega pb |
| 1937 | LEFT OUTER JOIN producto_color pc on |
| 1938 | pb.producto_general_id = pc.producto_general_id AND pb.color_id=pc.color_id |
| 1939 | WHERE pb.producto_bodega_id = " .strit($producto_bodega_id); |
| 1940 | |
| 1941 | $existencia = ia_singleton($sql); |
| 1942 | if(empty($existencia)) { |
| 1943 | return "NOT FOUND"; |
| 1944 | } |
| 1945 | if(empty($existencia['en_remate'])) |
| 1946 | $existencia['en_remate'] = $existencia['es_saldo'] = $existencia['lento'] = $existencia['super_lento'] = 'No'; |
| 1947 | $existencia_return['existencia_quantity'] = $existencia['existencia_quantity']; |
| 1948 | $existencia_return['existencia_rollos'] = $existencia['existencia_rollos']; |
| 1949 | |
| 1950 | global $gIAParametros; |
| 1951 | $maxResetRollos = $gIAParametros['reset_max_rollos'] ?? "1"; |
| 1952 | $maxResetQuantity = $gIAParametros['reset_max_quantity'] ?? "5.00"; |
| 1953 | |
| 1954 | if(!usuarioTipoRony()) { |
| 1955 | // Si la existencia de rollos es mayor a $maxResetRollos |
| 1956 | if(bccomp(bcabs($existencia['rollos'], 0), $maxResetRollos, 0) > 0) |
| 1957 | return "INVALID ROLLS"; |
| 1958 | // Si la existencia de quantity es mayor a $maxResetQuantity |
| 1959 | if(bccomp(bcabs($existencia['quantity'], 2), $maxResetQuantity, 2) > 0) |
| 1960 | return "INVALID QUANTITY"; |
| 1961 | } |
| 1962 | |
| 1963 | |
| 1964 | $query[] = "INSERT INTO reset_history(bodega_id,producto_general_id,color_id,rollos,quantity,alta_por) |
| 1965 | VALUES ('{$existencia['bodega_id']}','{$existencia['producto_general_id']}','{$existencia['color_id']}', |
| 1966 | '{$existencia['rollos']}','{$existencia['quantity']}','{$_SESSION['usuario']}')"; |
| 1967 | |
| 1968 | // Pasa existencia en bodega del producto-color a ceros |
| 1969 | $set_campos = ["existencia_quantity" => '0.00', 'existencia_rollos' => '0.00']; |
| 1970 | if ($solo_qty) |
| 1971 | $set_campos = ["existencia_quantity" => '0.00']; |
| 1972 | |
| 1973 | $set_campos['ultimo_cambio'] = "NOW()"; |
| 1974 | $set_campos['ultimo_cambio_por'] = $_SESSION['usuario']; |
| 1975 | $sqlBuilder = new Iac\inc\sql\IacSqlBuilder(); |
| 1976 | $query[] = $sqlBuilder->update('producto_bodega', $set_campos, ['producto_bodega_id' => $producto_bodega_id], comment:$method); |
| 1977 | |
| 1978 | $existencia['rollos'] = $solo_qty ? "0" : bcmul($existencia['rollos'], "-1", 0); |
| 1979 | $existencia['quantity'] = bcmul($existencia['quantity'], "-1", 2); |
| 1980 | $existencia['fecha'] = Date('Y-m-d'); |
| 1981 | $existencia['entrada_salida'] = 'Entrada'; |
| 1982 | $existencia['tipo'] = 'Entrada'; |
| 1983 | $existencia['origen_id'] = AJUSTE_ORIGEN_ID; |
| 1984 | |
| 1985 | $bodegaExistenciaDiaria = new BodegaExistenciaDiaria(false); |
| 1986 | $resetItems = $bodegaExistenciaDiaria->sqlResetItem($existencia); |
| 1987 | if(is_array($resetItems)) |
| 1988 | $query = [...$query, ...$resetItems]; |
| 1989 | |
| 1990 | if (!$execute) |
| 1991 | return $query; |
| 1992 | return ia_transaction($query) ? "DB ERROR" : ""; |
| 1993 | } |
| 1994 | |
| 1995 | function me_pregunto_notas_bodega() { |
| 1996 | $method = __FUNCTION__; |
| 1997 | $return = []; |
| 1998 | $dias = 7; |
| 1999 | $devolucionesSql = |
| 2000 | "select /*$method*/ tipo, count(*) as 'num', count(*) * 100.0 / sum(count(*)) over() as 'avg' |
| 2001 | from nota_bodega |
| 2002 | WHERE tipo IN ('movimiento', 'devolucion', 'VENTA CLIENTE') AND fecha >= DATE_SUB(CURDATE(), INTERVAL $dias DAY) |
| 2003 | GROUP BY 1"; |
| 2004 | $devoluciones = ia_sqlArray($devolucionesSql, 'tipo'); |
| 2005 | if(!empty($devoluciones)) { |
| 2006 | if(array_key_exists('Devolucion', $devoluciones)) { |
| 2007 | if($devoluciones['Devolucion']['avg'] >= 0.5) |
| 2008 | $return[] = "<b class='bb'>" . $devoluciones['Devolucion']['num'] . " devoluciones</b> en los últimos $dias días, creo <b class='bb'>¿son muchas?</b>"; |
| 2009 | } else { |
| 2010 | $return[] = "¿<b class='bb'>Sin devoluciones</b> en los últimos $dias días?"; |
| 2011 | } |
| 2012 | } |
| 2013 | |
| 2014 | $productosVendidosSql = |
| 2015 | "SELECT /*$method*/ count(DISTINCT producto_general_id) |
| 2016 | FROM nota_bodega |
| 2017 | WHERE tipo IN ('movimiento', 'VENTA CLIENTE') AND fecha >= DATE_SUB(CURDATE(), INTERVAL $dias DAY)"; |
| 2018 | $productosVendidos = ia_singleread($productosVendidosSql, 0); |
| 2019 | if($productosVendidos !== false && $productosVendidos < 35) |
| 2020 | $return[] = "<b class='bb'>$productosVendidos productos vendidos</b> en los últimos $dias días, <b class='bb'>¿son pocos. no?</b>"; |
| 2021 | $edicionesImportantesSql = |
| 2022 | "SELECT /*$method*/ b.bodega, COUNT(*) |
| 2023 | from nota_bodega_autorizacion nba LEFT OUTER JOIN bodega b ON b.bodega_id=nba.bodega_id |
| 2024 | WHERE nba.ultimo_movimiento='modificacion'AND nba.ultimo_cambio > DATE_SUB(CURDATE(), INTERVAL $dias DAY) |
| 2025 | GROUP BY 1 |
| 2026 | HAVING COUNT(*)>5"; |
| 2027 | $edicionesImportantes = ia_sqlKeyValue($edicionesImportantesSql); |
| 2028 | if(!empty($edicionesImportantes)) |
| 2029 | foreach($edicionesImportantes as $bodega => $count) |
| 2030 | $return[] = "En la bodega <b class='bb'>$bodega</b> se realizaron <b class='bb'>$count modificaciones importantes</b> en los últimos $dias días, <b class='bb'>¿No son muchas?</b>"; |
| 2031 | |
| 2032 | |
| 2033 | return empty($return) ? "" : |
| 2034 | "<style>.light{font-weight: 100;}.bb{font-weight:800}</style><div class='light' style='color:red;font-family: Arial, sans-serif'><span style='color:red;'>Hmmm de las <b>notas de bodega</b>, me pregunto:</span><dl><dt>" . implode("<dt>", $return) . "</dl></div>" |
| 2035 | ."(solo en desarrollo existo)"; |
| 2036 | } |
| 2037 | |
| 2038 | function ia_htmlentities($s="",$forza=false,$hardblank=false) { |
| 2039 | if($hardblank && empty($s) ) return ' '; |
| 2040 | if(is_array($s)) { |
| 2041 | echo "<div style='clear:both'><hr />ia_htmlentites got array=<pre>".print_r($s,true)."<p>trace<p>"; |
| 2042 | debug_print_backtrace(); |
| 2043 | |
| 2044 | echo "</pre><hr></div>"; |
| 2045 | } |
| 2046 | if($s === null) |
| 2047 | $s = ''; |
| 2048 | return htmlentities($s,ENT_QUOTES | ENT_HTML401 | ENT_SUBSTITUTE | ENT_DISALLOWED,IACHARSET); |
| 2049 | } |
| 2050 | |
| 2051 | function mysqlDate2display($date, $full_time=false) { |
| 2052 | global $gIAData; |
| 2053 | if(empty($date) || $date === '0000-00-00') |
| 2054 | return ''; |
| 2055 | if(strlen($date) === 19) |
| 2056 | return mysqlDateTime2display($date, $full_time); |
| 2057 | |
| 2058 | //VCA |
| 2059 | $tmp=explode('-',$date); |
| 2060 | if(sizeof($tmp) !==3 ) return ''; |
| 2061 | if($tmp[2] > 35) |
| 2062 | $date = "$tmp[2]-$tmp[1]-$tmp[0]"; |
| 2063 | if(!checkdate((int)$tmp[1],(int)$tmp[2],(int)$tmp[0])) |
| 2064 | $date = date('Y-m-d'); |
| 2065 | |
| 2066 | try { |
| 2067 | return substr($date,8,2).'/'.$gIAData['monthShrot'][substr($date,5,2)+0].'/'.substr($date,2,2); |
| 2068 | } catch(Exception) { return $date; } |
| 2069 | } |
| 2070 | |
| 2071 | function mysqlDateTime2display($date, $full_time=false) { |
| 2072 | global $gIAData; |
| 2073 | if(empty($date)) |
| 2074 | return ''; |
| 2075 | if(strlen($date) === 19) |
| 2076 | try { |
| 2077 | return substr($date,8,2).'/' |
| 2078 | .$gIAData['monthShrot'][substr($date,5,2)+0] |
| 2079 | .'/'.substr($date,2,2).' ' |
| 2080 | .($full_time?substr($date,10):substr($date,10,6)); |
| 2081 | } catch(Exception) { return $date; } |
| 2082 | return $date; |
| 2083 | } |
| 2084 | |
| 2085 | function mysqlTimestamp2display($timestamp, $full_time=false) { return mysqlDateTime2display($timestamp, $full_time); } |
| 2086 | |
| 2087 | /** |
| 2088 | * Regresa el nombre del color_id (color), blanco en not found |
| 2089 | */ |
| 2090 | function color_id_nombre(string $color_id):string { |
| 2091 | static $coloresCache; |
| 2092 | if(empty($coloresCache)) { |
| 2093 | $function = __FUNCTION__; |
| 2094 | $coloresCache = ia_sqlKeyValue("SELECT /*$function*/ color_id, color FROM color"); |
| 2095 | } |
| 2096 | return $coloresCache[$color_id] ?? ''; |
| 2097 | } |
| 2098 | /** |
| 2099 | * Regresa true si esta activo el color, false inactivo o not found |
| 2100 | */ |
| 2101 | function color_id_activo(string $color_id):bool { |
| 2102 | static $coloresCache; |
| 2103 | if(empty($coloresCache)) { |
| 2104 | $function = __FUNCTION__; |
| 2105 | $coloresCache = ia_sqlKeyValue("SELECT /*$function*/ color_id, activo FROM color"); |
| 2106 | } |
| 2107 | return $coloresCache[$color_id] ?? '' === 'Si'; |
| 2108 | } |
| 2109 | /** |
| 2110 | * Regresa el nombre del producto_general_id (producto), blanco en not found |
| 2111 | */ |
| 2112 | function producto_general_id_nombre($producto_general_id):string { |
| 2113 | static $productosCache; |
| 2114 | if(empty($productosCache)) { |
| 2115 | $function = __FUNCTION__; |
| 2116 | $productosCache = ia_sqlKeyValue("SELECT /*$function*/ producto_general_id, producto FROM producto_general"); |
| 2117 | } |
| 2118 | return $productosCache[$producto_general_id] ?? ''; |
| 2119 | } |
| 2120 | /** |
| 2121 | * Regresa true si esta activo el producto, false inactivo o not found |
| 2122 | */ |
| 2123 | function producto_general_id_activo($producto_general_id):bool { |
| 2124 | static $productosCache; |
| 2125 | if(empty($productosCache)) { |
| 2126 | $function = __FUNCTION__; |
| 2127 | $productosCache = ia_sqlKeyValue("SELECT /*$function*/ producto_general_id, activo FROM producto_general"); |
| 2128 | } |
| 2129 | return $productosCache[$producto_general_id] ?? '' === 'Si'; |
| 2130 | } |
| 2131 | |
| 2132 | |
| 2133 | function checked($value, $checkedValues):string { |
| 2134 | $val = $value instanceof Stringable ? (string)$value : $value; |
| 2135 | $valueTag = " value='" . htmlentities($val) . "' "; |
| 2136 | if(is_array($checkedValues)) |
| 2137 | return $valueTag . (in_array($val, $checkedValues, false) ? "checked='checked' " : " "); |
| 2138 | if($checkedValues instanceof Stringable) |
| 2139 | return $valueTag . ((string)$checkedValues === $val ? "checked='checked' " : " "); |
| 2140 | return $valueTag . ($checkedValues == $value ? "checked='checked' " : " "); |
| 2141 | } |
| 2142 | |
| 2143 | /** |
| 2144 | * Returns htmlentity protected value tag, and selectedTag if $value in $selectedValues |
| 2145 | * |
| 2146 | * @param string|Stringable|int|float|bool|null $value |
| 2147 | * @param string|Stringable|array<int|string, string|int|float|bool|null> $selectedValues |
| 2148 | * @return string " value='$value' " or " value='$value' selected='selected' " |
| 2149 | */ |
| 2150 | function selected($value, $selectedValues):string { |
| 2151 | $val = $value instanceof Stringable ? (string)$value : $value; |
| 2152 | $valueTag = " value='" . htmlentities((string)$val) . "' "; |
| 2153 | if(is_array($selectedValues)) |
| 2154 | return $valueTag . (in_array($value, $selectedValues, false) ? " selected='selected' " : " "); |
| 2155 | if($selectedValues instanceof Stringable) |
| 2156 | return $valueTag . ((string)$selectedValues == $val ? " selected='selected' " : " "); |
| 2157 | return $valueTag . ($selectedValues == $value ? " selected='selected' " : " "); |
| 2158 | } |
| 2159 | |
| 2160 | function statusBodegaSelect($name, $id) { |
| 2161 | global $gIAParametros; |
| 2162 | $statusValues = explode(",", $gIAParametros['existencia_default_status']??''); |
| 2163 | foreach($statusValues as &$d) { |
| 2164 | $d = trim($d); |
| 2165 | } |
| 2166 | unset($d); |
| 2167 | return strim(" |
| 2168 | <style>.option-small{font-size:0.9em!important;font-weight: 100!important;font-family: Courier monospace monospace, monospace}</style> |
| 2169 | <select name='$name' id='$id' class='notSelectize multiselect' multiple style='width:17em;'> |
| 2170 | <option class='option-small'" . selected('donde', $statusValues) . " >Donde!</option> |
| 2171 | <option class='option-small'" . selected('ceros', $statusValues) . " >Ver Ceros</option> |
| 2172 | <option class='option-small'" . selected('negativos', $statusValues) . " >Solo Negativos</option> |
| 2173 | <option class='option-small'" . selected('sin_existencia', $statusValues) . " >Existencia Cero</option> |
| 2174 | <option class='option-small'" . selected('saldo', $statusValues) . " >Saldos</option> |
| 2175 | <option class='option-small'" . selected('pedir', $statusValues) . " >Remate</option> |
| 2176 | <option class='option-small'" . selected('super_saldo', $statusValues) . " >Dead Stock</option> |
| 2177 | <option class='option-small'" . selected('lento', $statusValues) . " >Lento</option> |
| 2178 | <option class='option-small'" . selected('super_lento', $statusValues) . " >Super Lento</option> |
| 2179 | </select> |
| 2180 | "); |
| 2181 | } |
| 2182 | |
| 2183 | /** |
| 2184 | * Para buscar por regExp, lento, en un campo json o text que guarda json con like en un $property del json el text $busca |
| 2185 | * |
| 2186 | * @param string $fieldName |
| 2187 | * @param string $property |
| 2188 | * @param string $busca |
| 2189 | * @return string |
| 2190 | */ |
| 2191 | function jsonRegExp($fieldName, $property, $busca):string { |
| 2192 | $fieldName = fieldit(trim($fieldName ?? '')); |
| 2193 | $property = substr(strit(trim($property ?? '')), 1, -1); |
| 2194 | $busca = substr(strit(strim($busca)), 1, -1); |
| 2195 | return /** @lang SQL */ |
| 2196 | "REGEXP_LIKE($fieldName, '.*\"$property\" *: *\"[a-z\\\\s,\\\\.\\\\d\\\\&]*{$busca}[a-z\\\s,\\\.\\\d\\\\&]*\"', 'i')"; |
| 2197 | } |
| 2198 | |
| 2199 | function jsonLike(string $tableName, string $fieldName, string $property, string $busca, string $op = 'cn'):string { |
| 2200 | switch($op) { |
| 2201 | case 'ew': |
| 2202 | $start = '%'; |
| 2203 | $end = ''; |
| 2204 | break; |
| 2205 | case 'bw': |
| 2206 | $start = ''; |
| 2207 | $end = '%'; |
| 2208 | break; |
| 2209 | default: |
| 2210 | $start = '%'; |
| 2211 | $end = '%'; |
| 2212 | } |
| 2213 | |
| 2214 | $fieldName = fieldit(trim($fieldName ?? '')); |
| 2215 | $property = substr(strit(trim($property ?? '')), 1, -1); |
| 2216 | $busca = substr(strit(strim($busca)), 1, -1); |
| 2217 | |
| 2218 | return /** lang SQL */ |
| 2219 | "EXISTS( |
| 2220 | SELECT 1 |
| 2221 | FROM nota_bodega nbj |
| 2222 | JOIN JSON_TABLE(nbj.$fieldName, '\$[*]' COLUMNS ( |
| 2223 | fue_error VARCHAR(2) PATH '\$.fue_error', |
| 2224 | lbl TEXT PATH '\$.$property' |
| 2225 | )) AS j |
| 2226 | WHERE nota_bodega.nota_bodega_id=nbj.nota_bodega_id AND j.fue_error='No' AND j.lbl LIKE '$start{$busca}$end' |
| 2227 | )"; |
| 2228 | } |
| 2229 | |
| 2230 | function strlike($str):string { |
| 2231 | return str_replace(array('%', '_'), array("\\%", "\\_"), $str ?? ''); |
| 2232 | } |
| 2233 | |
| 2234 | |
| 2235 | /** |
| 2236 | * si $tableName.$fieldName se guarda como json da el property que desplegar/buscar. blanco no es json |
| 2237 | * Para usarse por ejemplo con jsonLike |
| 2238 | * |
| 2239 | * @param $tableName |
| 2240 | * @param $fieldName |
| 2241 | * @return string vacia si $tableName.$fieldName no se guarda como json, el property que desplegar/buscar si si |
| 2242 | */ |
| 2243 | function fixJsonBuscaEnProperty($tableName, &$fieldName, $data, &$value_txt = ""):string { |
| 2244 | if(strlen($data) === 32 && preg_match_all('/[0-9a-f]/miS', $data, $matches, PREG_SET_ORDER, 0)) { |
| 2245 | $iactblConJsonFields = [ |
| 2246 | 'nota_bodega' => [4, |
| 2247 | 'ayudantes_json' => 'id', |
| 2248 | 'chofer_responsable' => 'figuratransporte_id', |
| 2249 | 'cliente' => 'cliente_id', |
| 2250 | 'numero_compra' => 'numero_compra_id', |
| 2251 | 'pedido_por' => 'id', |
| 2252 | |
| 2253 | 'tipo_nota_json' => 'tipo_nota', |
| 2254 | 'numero_tipo_nota_json' => 'numero_tipo_nota', |
| 2255 | 'quantity_tipo_nota_json' => 'quantity_tipo_nota', |
| 2256 | ], |
| 2257 | ]; |
| 2258 | } else { |
| 2259 | $iactblConJsonFields = [ |
| 2260 | 'nota_bodega' => [4, |
| 2261 | 'ayudantes_json' => 'lbl', |
| 2262 | 'chofer_responsable' => 'nombre', |
| 2263 | 'cliente' => 'nombre', |
| 2264 | 'numero_compra' => 'numero_compra', |
| 2265 | 'pedido_por' => 'lbl', |
| 2266 | |
| 2267 | 'tipo_nota_json' => 'tipo_nota', |
| 2268 | 'numero_tipo_nota_json' => 'numero_tipo_nota', |
| 2269 | 'quantity_tipo_nota_json' => 'quantity_tipo_nota', |
| 2270 | ], |
| 2271 | ]; |
| 2272 | } |
| 2273 | |
| 2274 | $iactblConJsonFieldsIdx = [ |
| 2275 | 'nota_bodega' => [ |
| 2276 | 'cliente' => ['alt' =>'cliente_actual'], |
| 2277 | 'numero_compra' => ['alt' =>'numero_compra_actual', 'val_txt' => " = ".strit($data)], |
| 2278 | ], |
| 2279 | ]; |
| 2280 | $tableName = trim(strtolower($tableName ?? '')); |
| 2281 | $fieldName = trim(strtolower($fieldName ?? '')); |
| 2282 | |
| 2283 | if($iactblConJsonFieldsIdx[$tableName][$fieldName]['alt'] ?? false) { |
| 2284 | $value_txt = $iactblConJsonFieldsIdx[$tableName][$fieldName]['val_txt'] ?? ""; |
| 2285 | $fieldName = $iactblConJsonFieldsIdx[$tableName][$fieldName]['alt'] ?? $fieldName; |
| 2286 | // $fi = $iactblConJsonFieldsIdx[$tableName][$fieldName]['fi'] ?? $fi; |
| 2287 | } |
| 2288 | return $iactblConJsonFields[$tableName][$fieldName] ?? ''; |
| 2289 | } |
| 2290 | |
| 2291 | /** |
| 2292 | * Regresa un array donde fue_error === 'No'. Limpia y muestra solo los activos |
| 2293 | * |
| 2294 | * @param string|array|null $json |
| 2295 | * @return array |
| 2296 | */ |
| 2297 | function getFueErrorNo($json):array { |
| 2298 | if(empty($json)) { |
| 2299 | return []; |
| 2300 | } |
| 2301 | if(is_string($json)) { |
| 2302 | $json = json_decode($json, true); |
| 2303 | } |
| 2304 | if(empty($json)) { |
| 2305 | return []; |
| 2306 | } |
| 2307 | return array_values(array_filter( |
| 2308 | $json, |
| 2309 | function($item) {return strcasecmp('No', $item['fue_error'] ?? 'No') === 0 ;} |
| 2310 | )); |
| 2311 | } |
| 2312 | |
| 2313 | /** |
| 2314 | * |
| 2315 | * |
| 2316 | * @param string|array|null $antes |
| 2317 | * @param string|array|null $despues = 'lbl' |
| 2318 | * @param string $display |
| 2319 | * @return bool true son Iguales, false hay diferencia |
| 2320 | */ |
| 2321 | function fueErrorIguales($antes, $despues, $display):bool { |
| 2322 | $eran = array_column(getFueErrorNo($antes), $display); |
| 2323 | $son = array_column(getFueErrorNo($despues), $display); |
| 2324 | $intersection = array_uintersect($eran, $son, 'compareCaseInsensitive'); |
| 2325 | return empty([ |
| 2326 | ...array_udiff($eran, $intersection, 'compareCaseInsensitive'), |
| 2327 | ...array_udiff($son, $intersection, 'compareCaseInsensitive') |
| 2328 | ]); |
| 2329 | } |
| 2330 | |
| 2331 | /** |
| 2332 | * |
| 2333 | * |
| 2334 | * @param string|array|null $antes |
| 2335 | * @param string|array|null $despues |
| 2336 | * @param string $display = 'lbl' |
| 2337 | * @param string $confirma = 'confirma' |
| 2338 | * @return bool true son Iguales, false hay diferencia |
| 2339 | */ |
| 2340 | function fueErrorConfirmaIguales($antes, $despues, $display, $confirma):bool { |
| 2341 | $eran = []; |
| 2342 | foreach(getFueErrorNo($antes) as $d) |
| 2343 | $eran[] = ($d[$display] ?? '¿?').($d[$confirma] ?? '¿?'); |
| 2344 | $son = []; |
| 2345 | foreach(getFueErrorNo($despues) as $d) |
| 2346 | $son[] = ($d[$display] ?? '¿?').($d[$confirma] ?? '¿?'); |
| 2347 | $intersection = array_uintersect($eran, $son, 'compareCaseInsensitive'); |
| 2348 | return empty([ |
| 2349 | ...array_udiff($eran, $intersection, 'compareCaseInsensitive'), |
| 2350 | ...array_udiff($son, $intersection, 'compareCaseInsensitive') |
| 2351 | ]); |
| 2352 | } |
| 2353 | |
| 2354 | function itemsIguales($antes, $despues):bool { |
| 2355 | if($antes === false || $despues === false) |
| 2356 | return true; |
| 2357 | $eran = []; |
| 2358 | foreach($antes as $a) |
| 2359 | $eran[] = bcadd($a['rollos'], '0', 0) . '|' . bcadd($a['quantity'], '0.00', 2) . '|' . |
| 2360 | substr($a['producto_bodega_id'], -32); |
| 2361 | $son = []; |
| 2362 | foreach($despues as $a) |
| 2363 | $son[] = bcadd($a['rollos'], '0', 0) . '|' . bcadd($a['quantity'], '0.00', 2) . '|' . |
| 2364 | substr($a['producto_bodega_id'], -32); |
| 2365 | $intersection = array_uintersect($eran, $son, 'compareCaseInsensitive'); |
| 2366 | return empty([ |
| 2367 | ...array_udiff($eran, $intersection, 'compareCaseInsensitive'), |
| 2368 | ...array_udiff($son, $intersection, 'compareCaseInsensitive') |
| 2369 | ]); |
| 2370 | } |
| 2371 | |
| 2372 | function campoAtipo($campo) { |
| 2373 | $modificacionImportante = |
| 2374 | ['producto_general_id'=>1, 'items'=>1, 'fecha'=>1, 'entrada_salida'=>1, 'origen_id'=>1,'tipo'=>1, |
| 2375 | 'total_rolls'=>1, 'total_quantity'=>1, 'paid'=>1, 'contenedor'=>1, 'numero'=>1, |
| 2376 | ]; |
| 2377 | if(array_key_exists($campo, $modificacionImportante)) |
| 2378 | return 'Modificación Importante'; |
| 2379 | $destinoMatch = ['ayudantes'=>1, 'ayudantes_json'=>1, 'pedido_por'=>1, 'cliente'=>1, 'numero_compra'=>1]; |
| 2380 | if(array_key_exists($campo, $destinoMatch)) |
| 2381 | return 'Destino Match'; |
| 2382 | $camposCash = ['tipo_nota'=>1, 'tipo_nota_json'=>1, 'pedido_por'=>1, 'numero_tipo_nota'=>1, 'numero_tipo_nota_json'=>1, |
| 2383 | 'quantity_tipo_nota'=>1, 'quantity_tipo_nota_json'=>1]; |
| 2384 | if(array_key_exists($campo, $camposCash)) |
| 2385 | return 'Campos Cash'; |
| 2386 | $recibido = ['recibido'=>1, 'recibido_el'=>1, 'recibido_por'=>1]; |
| 2387 | if(array_key_exists($campo, $recibido)) |
| 2388 | return 'Recibido'; |
| 2389 | return $campo; |
| 2390 | } |
| 2391 | |
| 2392 | /** @noinspection PhpUnused */ |
| 2393 | function compareCaseInsensitive($a, $b):int { |
| 2394 | if(is_array($a) || is_array($b)) { |
| 2395 | return $a <=> $b; |
| 2396 | } |
| 2397 | if($a instanceof \Stringable || $a === null) { |
| 2398 | $a = (string)$a; |
| 2399 | } |
| 2400 | if($b instanceof \Stringable || $b === null) { |
| 2401 | $b = (string)$b; |
| 2402 | } |
| 2403 | if(is_string($a) || is_string($b)) { |
| 2404 | return strcasecmp((string)$a, (string)$b); |
| 2405 | } |
| 2406 | return $a <=> $b; |
| 2407 | } |
| 2408 | |
| 2409 | /** |
| 2410 | * @param $fecha_min |
| 2411 | * @param $fecha_max |
| 2412 | * @return string |
| 2413 | */ |
| 2414 | function diasEntreFechas($fecha_min, $fecha_max):string { |
| 2415 | if(empty($fecha_min)) { |
| 2416 | return ''; |
| 2417 | } |
| 2418 | try { |
| 2419 | if(empty($fecha_max)) { |
| 2420 | $today = new DateTimeImmutable(); |
| 2421 | $interval = $today->diff(new DateTimeImmutable($fecha_min), true); |
| 2422 | } else { |
| 2423 | $minDate = new DateTimeImmutable($fecha_min); |
| 2424 | $interval = $minDate->diff(new DateTimeImmutable($fecha_max), true); |
| 2425 | } |
| 2426 | return " (" . |
| 2427 | number_format((int)$interval->format("%a"), 0, '', ',') . |
| 2428 | " días)"; |
| 2429 | } catch(Throwable) {} |
| 2430 | return ''; |
| 2431 | } |
| 2432 | |
| 2433 | /** |
| 2434 | * Regresa la diferencia en frase bonita de las 2 fechas |
| 2435 | * |
| 2436 | * @param string|int $dateTime1 mysqlDate o mysqlDateTime o timestamp |
| 2437 | * @param string|int $dateTime2 mysqlDate o mysqlDateTime o timestamp |
| 2438 | * @param int $maxParts |
| 2439 | * @return string |
| 2440 | */ |
| 2441 | function fechaDiff($dateTime1, $dateTime2, $maxParts = 2):string { |
| 2442 | $to = [ |
| 2443 | 'año' => 60*60*24*365, |
| 2444 | 'mes' => 60*60*24*30, |
| 2445 | 'día' => 60*60*24, |
| 2446 | 'hr' => 60*60, |
| 2447 | 'min' => 60, |
| 2448 | 'seg' => 1, |
| 2449 | ]; |
| 2450 | $plural = [ |
| 2451 | 'año' => 'años', |
| 2452 | 'mes' => 'meses', |
| 2453 | 'día' => 'dias', |
| 2454 | 'hr' => 'hrs', |
| 2455 | 'min' => 'min', |
| 2456 | 'seg' => 'seg', |
| 2457 | ]; |
| 2458 | $last = 'seg'; |
| 2459 | $format = []; |
| 2460 | if($dateTime1 instanceof Stringable) { |
| 2461 | $dateTime1 = (string)$dateTime1; |
| 2462 | } |
| 2463 | if(!is_numeric($dateTime1)) { |
| 2464 | $dateTime1 = strtotime($dateTime1); |
| 2465 | } |
| 2466 | if($dateTime2 instanceof Stringable) { |
| 2467 | $dateTime2 = (string)$dateTime2; |
| 2468 | } |
| 2469 | if(!is_numeric($dateTime2)) { |
| 2470 | $dateTime2 = strtotime($dateTime2); |
| 2471 | } |
| 2472 | $diff = abs( (float)$dateTime1 - (float)$dateTime2); |
| 2473 | $breakNow = 0; |
| 2474 | foreach($to as $label => $u) { |
| 2475 | if($breakNow >= $maxParts || ($breakNow > 0 && $label === $last)) { |
| 2476 | break; |
| 2477 | } |
| 2478 | $period = floor($diff/$u); |
| 2479 | if( $period >= 1 ) { |
| 2480 | $diff -= $period * $u; |
| 2481 | $format[] = $period . ' ' . ($period === 1.00 ? $label : $plural[$label]); |
| 2482 | $breakNow++; |
| 2483 | } elseif($breakNow === 1) { |
| 2484 | $breakNow++; |
| 2485 | } |
| 2486 | } |
| 2487 | return implode(", ", $format); |
| 2488 | } |
| 2489 | |
| 2490 | /** |
| 2491 | * Regresa $data ordenada por los keys de $keyOrder, de existir, en ese orden y luego el resto de keys de $data |
| 2492 | * |
| 2493 | * @param array<string, mixed> $data |
| 2494 | * @param array<int|string, int|string> $keyOrder |
| 2495 | * @return array<int|string, mixed> |
| 2496 | * |
| 2497 | * @example |
| 2498 | * keyOrder(['a' => 'la A', 'b' => 'la b', 'm' => 'la m', 'l'=>'la l', 'k'=>'la k'], ['k', 'm', 'l']); |
| 2499 | * ['k'=>'la k', 'm' => 'la m', 'l'=>'la l','a' => 'la A', 'b' => 'la b'] |
| 2500 | */ |
| 2501 | function keyOrder(array $data, array $keyOrder):array { |
| 2502 | $order = []; |
| 2503 | foreach($keyOrder as $key) |
| 2504 | if(array_key_exists($key, $data)) |
| 2505 | $order[$key] = $data[$key]; |
| 2506 | foreach($data as $key => $v) |
| 2507 | if(!array_key_exists($key,$order)) |
| 2508 | $order[$key] = $v; |
| 2509 | return $order; |
| 2510 | } |
| 2511 | |
| 2512 | /** |
| 2513 | * Regresa $data ordenada stable por los keys que no están en $keyOrder y luego los keys de $keyOrder, de existir, en ese orden |
| 2514 | * |
| 2515 | * @param array<int|string, mixed> $data |
| 2516 | * @param array<int|string, int|string> $keyOrder |
| 2517 | * @return array<int|string, mixed> |
| 2518 | * @example |
| 2519 | * keyOrderEnd(['a' => 'la A', 'b' => 'la b', 'm' => 'la m', 'l'=>'la l', 'k'=>'la k'], ['k', 'm', 'l']); |
| 2520 | * ['a' => 'la A', 'b' => 'la b', 'k'=>'la k', 'm' => 'la m', 'l'=>'la l'] |
| 2521 | */ |
| 2522 | function keyOrderEnd(array $data, array $keyOrder):array { |
| 2523 | $order = []; |
| 2524 | $by = array_flip($keyOrder); |
| 2525 | foreach($data as $key => $v) |
| 2526 | if(!array_key_exists($key,$by)) |
| 2527 | $order[$key] = $v; |
| 2528 | foreach($keyOrder as $key) |
| 2529 | if(array_key_exists($key, $data)) |
| 2530 | $order[$key] = $data[$key]; |
| 2531 | return $order; |
| 2532 | } |
| 2533 | |
| 2534 | function getCurrentValueJson($json):array |
| 2535 | { |
| 2536 | if (empty($json)) |
| 2537 | return []; |
| 2538 | $items_ok = getFueErrorNo($json); |
| 2539 | |
| 2540 | usort($items_ok, function($a, $b) { |
| 2541 | return new DateTime($b['alta_db']) <=> new DateTime($a['alta_db']); |
| 2542 | }); |
| 2543 | /*usort($items_ok, function ($a, $b) { |
| 2544 | return strtotime($b['alta_db']) - strtotime($a['alta_db']); |
| 2545 | });*/ |
| 2546 | return $items_ok[0]??[]; |
| 2547 | } |
| 2548 | |
| 2549 | function displayColumn($campo, $valor):string|bool|int|float |
| 2550 | { |
| 2551 | static $keyValue = []; |
| 2552 | if($campo === 'origen_bodega_id') |
| 2553 | $campo = 'origen_id'; |
| 2554 | if($valor === null) |
| 2555 | return ''; |
| 2556 | if(endsWith($campo, '_id')) { |
| 2557 | if(array_key_exists($campo, $keyValue)) |
| 2558 | return $keyValue[$campo][$valor] ?? $valor; |
| 2559 | switch ($campo) { |
| 2560 | case 'bodega_id': |
| 2561 | $keyValue[$campo] = ia_sqlKeyValue("SELECT bodega_id, bodega FROM bodega"); |
| 2562 | break; |
| 2563 | case 'cliente_id': |
| 2564 | $keyValue[$campo] = ia_sqlKeyValue("SELECT cliente_id, nombre FROM cliente"); |
| 2565 | break; |
| 2566 | case 'color_id': |
| 2567 | $keyValue[$campo] = ia_sqlKeyValue("SELECT color_id, color FROM color"); |
| 2568 | break; |
| 2569 | case 'contra_nota_bodega_id': |
| 2570 | return str_replace(';', ', ', $valor); |
| 2571 | case 'empresa_id': |
| 2572 | $keyValue[$campo] = ia_sqlKeyValue("SELECT empresa_id, empresa FROM empresa"); |
| 2573 | break; |
| 2574 | case 'nota_bodega_id': |
| 2575 | return ia_singleread("SELECT label FROM nota_bodega WHERE nota_bodega_id=" . strit($valor)); |
| 2576 | case 'nota_bodega_items_id': |
| 2577 | case 'nota_bodega_item_id': |
| 2578 | return ia_singleread("SELECT |
| 2579 | CONCAT(pg.producto, ' ', c.color, ' ', FORMAT(nbi.rollos, 0), ' rollos, ', FORMAT(nbi.quantity,2), u.unidad ) |
| 2580 | FROM nota_bodega_items nbi |
| 2581 | JOIN producto_general pg ON pg.producto_general_id = MID(nbi.producto_bodega_id, 34, 32) |
| 2582 | JOIN unidades u on pg.unidades_id = u.unidades_id |
| 2583 | JOIN color c ON c.color_id = nbi.color_id |
| 2584 | WHERE nota_bodega_item_id=" . strit($valor)); |
| 2585 | case 'origen_id': |
| 2586 | $keyValue[$campo] = ia_sqlKeyValue("SELECT origen_bodega_id, clave FROM origen_bodega"); |
| 2587 | break; |
| 2588 | case 'producto_general_id': |
| 2589 | $keyValue[$campo] = ia_sqlKeyValue("SELECT producto_general_id, producto FROM producto_general"); |
| 2590 | break; |
| 2591 | case 'tienda_id': |
| 2592 | $keyValue[$campo] = ia_sqlKeyValue("SELECT tienda_id, clave FROM tienda"); |
| 2593 | break; |
| 2594 | case 'unidades_id': |
| 2595 | $keyValue[$campo] = ia_sqlKeyValue("SELECT unidades_id, unidad FROM unidades"); |
| 2596 | break; |
| 2597 | } |
| 2598 | return $keyValue[$campo][$valor] ?? $valor . '?' . $campo; |
| 2599 | } |
| 2600 | |
| 2601 | $camposJsonFueError = [ |
| 2602 | 'ayudantes_json' => ['lbl' => 'lbl'], |
| 2603 | 'chofer_responsable' => ['lbl' =>'nombre'], |
| 2604 | 'cliente' => ['lbl' =>'nombre'], |
| 2605 | 'numero_compra' => ['lbl' =>'numero_compra'], |
| 2606 | 'pedido_por' => ['lbl' => 'lbl'], |
| 2607 | |
| 2608 | 'tipo_nota_json' => ['lbl' =>'tipo_nota'], |
| 2609 | 'numero_tipo_nota_json' => ['lbl' =>'numero_tipo_nota'], |
| 2610 | 'quantity_tipo_nota_json' => ['lbl' =>'quantity_tipo_nota'], |
| 2611 | ]; |
| 2612 | if(array_key_exists($campo, $camposJsonFueError)) { |
| 2613 | $lbl = $camposJsonFueError[$campo]['lbl'] ?? 'lbl'; |
| 2614 | //$confirma = $camposJsonFueError[$campo]['confirma'] ?? null; |
| 2615 | //if($confirma === null) |
| 2616 | return implode(", ", array_column(getFueErrorNo($valor), $lbl)); |
| 2617 | } |
| 2618 | |
| 2619 | if(str_contains($campo, 'numero') || str_contains($campo, 'number')) |
| 2620 | return $valor; |
| 2621 | if(is_numeric($valor)) { |
| 2622 | if(str_contains($campo, 'rollos') || str_contains($campo, 'rolls')) |
| 2623 | return bcformat((string)$valor, 0); |
| 2624 | return bcformat((string)$valor, 2); |
| 2625 | } |
| 2626 | |
| 2627 | if('items' === $campo) { |
| 2628 | $items = []; |
| 2629 | foreach($valor as $i) { |
| 2630 | $rollos = bcformat($i['rollos'],0); |
| 2631 | $quantity = bcformat($i['quantity'],2); |
| 2632 | $producto = displayColumn('producto_general_id', substr($i['producto_bodega_id'], 33, 32) ); |
| 2633 | $color = displayColumn('color_id', substr($i['producto_bodega_id'], -32) ); |
| 2634 | $items[] = "$producto $color $rollos rollos, $quantity"; |
| 2635 | } |
| 2636 | return "<ol><li>" . implode("<li>", $items) . "</li></ol>"; |
| 2637 | } |
| 2638 | return is_array($valor) ? print_r($valor, true) : $valor; |
| 2639 | } |
| 2640 | |
| 2641 | /** |
| 2642 | * echo viewJsCode("functionName", $label = 'Show Function'); // pone un div con boton para ver codigo de function |
| 2643 | * echo viewJsCode("#id", $label = 'Ver div o javascript o ... con id="id"'); // pone un div con boton para ver codigo del element |
| 2644 | * $gDebugging debe ser True!. |
| 2645 | * |
| 2646 | * |
| 2647 | * @param string $show nombre de una funcion de js o un selector #id |
| 2648 | * @param string $label Letrero del boton |
| 2649 | * @return string |
| 2650 | */ |
| 2651 | function viewJsCode($show, $label = '') { |
| 2652 | global $gDebugging; |
| 2653 | if(!$gDebugging) |
| 2654 | return ''; |
| 2655 | if(empty($label)) |
| 2656 | $label = "Show Me: $show"; |
| 2657 | if($show[0] === '#' || $show[0] === '.') { |
| 2658 | $do = "showBySelector(\"$show\", this)"; |
| 2659 | } else { |
| 2660 | $do = "showFunction($show, this)"; |
| 2661 | } |
| 2662 | return <<< JS |
| 2663 | <script> |
| 2664 | function showFunction(functionToShow, container) { |
| 2665 | $(container).parent().html($("<pre>").css({margin:"2em", padding:"1em", border:"1px solid blue"}). |
| 2666 | text(functionToShow.toString())); |
| 2667 | } |
| 2668 | function showBySelector(idToShow, container) { |
| 2669 | let pon = $("<pre>").css({margin:"2em", padding:"1em", border:"1px solid blue"}).html( |
| 2670 | $(idToShow)[0].outerHTML.replaceAll('<', "<").replaceAll('\>', "><br>") ); |
| 2671 | $(container).parent().html(pon); |
| 2672 | } |
| 2673 | </script> |
| 2674 | <div style="margin:1em"><button type='button' onclick='$do'>$label</button></div> |
| 2675 | JS; |
| 2676 | } |
| 2677 | |
| 2678 | /** |
| 2679 | * usage: global $gFn; echo <<<HEREDOC Hello, {$gFn(ucfirst($variableNombre))} HEREDOC; |
| 2680 | */ |
| 2681 | global $gFn; $gFn = function ($callable) {return $callable;}; |
| 2682 | |
| 2683 | /** |
| 2684 | * " AND color <> {$gStrIt($last_color)}" en vez de " AND color <> " . strit($last_color); |
| 2685 | */ |
| 2686 | global $gStrIt; $gStrIt = function($s) {return strit($s); }; |
| 2687 | global $gPermisoClick; |
| 2688 | /** |
| 2689 | * echo $gPermisoClick('nombrePermiso') o en <<< HTML .. {$permsioClick('puede_autorizar_notas_ultimo_movimiento')} |
| 2690 | * |
| 2691 | * @param string $permiso |
| 2692 | * @return string |
| 2693 | */ |
| 2694 | $gPermisoClick = function($permiso, $msg = '', $alwaysVisible = false, $extraParam = '{}') { |
| 2695 | if($alwaysVisible) { |
| 2696 | $display = 'inline-block'; |
| 2697 | $cssSuffix = '1'; |
| 2698 | } else { |
| 2699 | $display = 'none'; |
| 2700 | $cssSuffix = ''; |
| 2701 | } |
| 2702 | $onclick = "onclick='permisador.ponPermisoThis(this, $extraParam);'"; |
| 2703 | $title = '<div class="ui_tooltip_grid_notas_modificacion_importante_si bold txt_1_1em">Permiso: ' . ucwords(str_replace(['puede_', 'may_', '_'], ' ', $permiso)) . '</div>'; |
| 2704 | |
| 2705 | return Permisador::puede_consultar_permisos() !== 'Nada' ? |
| 2706 | "<span class='ui-icon ui-icon-key ClickPermiso$cssSuffix pointer tooltip_toolbar' $onclick title='$title' style='display:$display' data-permiso='$permiso' data-extraParam='$extraParam'></span>" . |
| 2707 | ($msg === '' ? '' : "<span class='ClickPermiso$cssSuffix pointer' $onclick data-permiso='$permiso' data-extraParam='$extraParam' style='background-color:white;color:blue;display:$display;font-size:14px'>$msg</span>") |
| 2708 | : ''; |
| 2709 | }; |
| 2710 | |
| 2711 | function is_container_number($container_number) { |
| 2712 | $container_number = strtoupper( trim($container_number) ); |
| 2713 | if(!preg_match('/[A-Z]{4}[0-9]{7}/i', $container_number)) |
| 2714 | return false; |
| 2715 | $code = [ |
| 2716 | 0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, |
| 2717 | 'A' => 10, 'B' => 12, 'C' => 13, 'D' => 14, 'E' => 15, 'F' => 16, 'G' => 17, 'H' => 18, 'I' => 19, 'J' => 20, |
| 2718 | 'K' => 21, 'L' => 23, 'M' => 24, 'N' => 25, 'O' => 26, 'P' => 27, 'Q' => 28, 'R' => 29, 'S' => 30, 'T' => 31, |
| 2719 | 'U' => 32, 'V' => 34, 'W' => 35, 'X' => 36, 'Y' => 37, 'Z' => 38 |
| 2720 | ]; |
| 2721 | $sum = 0; $m = 1; $len = strlen($container_number) - 1; |
| 2722 | for($i=0; $i < $len; ++$i) { |
| 2723 | $sum += $code[$container_number[$i]] * $m; |
| 2724 | $m = $m << 1; |
| 2725 | } |
| 2726 | $checkDigit = $sum - floor($sum/11) * 11; |
| 2727 | |
| 2728 | return $checkDigit == 10 ? $container_number[$len] == '0' : $checkDigit == $container_number[$len]; |
| 2729 | // http://www.gvct.co.uk/2011/09/how-is-the-check-digit-of-a-container-calculated/ |
| 2730 | /* |
| 2731 | $ok = 'Ok'; $mal = "<span style='color:red'>X</span>"; |
| 2732 | $cn = 'ymlu8744830'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2733 | $cn = 'YMLU8744830'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2734 | $cn = 'TCNU1945814'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2735 | $cn = 'SEGU5392270'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2736 | $cn = 'TGBU8864437'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2737 | |
| 2738 | $cn = 'GVTU300038'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2739 | $cn = 'GVTU3000380'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2740 | |
| 2741 | $cn = "SEGU5329271"; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2742 | |
| 2743 | $cn = 'SEGU5329210'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2744 | |
| 2745 | $cn = 'VTU3000389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2746 | $cn = 'V U3000389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2747 | $cn = '1VTU3000389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2748 | $cn = 'G1TU3000389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2749 | $cn = 'GV1U3000389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2750 | $cn = 'GVT13000389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2751 | $cn = 'GVTUa000389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2752 | $cn = 'GVTU3a00389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2753 | $cn = 'GVTU30a0389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2754 | $cn = 'GVTU300a389'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2755 | $cn = 'GVTU3000a89'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2756 | $cn = 'GVTU30003a9'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2757 | $cn = 'GVTU3000380'; echo "<li>$cn erroneo da erroneo: " . (is_container_number($cn) ? $mal : $ok); |
| 2758 | $cn = 'VTU3000389'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2759 | $cn = 'GVTU300038'; echo "<li>$cn = " . (is_container_number($cn) ? $ok : $mal); |
| 2760 | |
| 2761 | |
| 2762 | */ |
| 2763 | } |
| 2764 | |
| 2765 | /** |
| 2766 | * @param string $fieldName |
| 2767 | * @param int|float|bool|string|array|null $value |
| 2768 | * @param string $default |
| 2769 | * @return string |
| 2770 | */ |
| 2771 | function formatMe(string $fieldName, $value, string $default = ''):string { |
| 2772 | if($value instanceof stdClass) |
| 2773 | $value = json_decode(json_encode($value, JSON_OPTIONS_FOR_MYSQL),true); |
| 2774 | if($value === null) |
| 2775 | return ''; |
| 2776 | if($value === true) |
| 2777 | return "true"; |
| 2778 | if($value === false) |
| 2779 | return "false"; |
| 2780 | if(is_array($value)) |
| 2781 | return formatMeArray($value); |
| 2782 | |
| 2783 | $fieldName = strtolower($fieldName); |
| 2784 | |
| 2785 | if(str_ends_with($fieldName, '_id')) |
| 2786 | return formatMeId($fieldName, $value, $default); |
| 2787 | $intFlags = [ |
| 2788 | 'atrasado'=>1, |
| 2789 | 'paid'=>1, |
| 2790 | 'super_atrasado'=>1, |
| 2791 | 'pending'=>1, |
| 2792 | 'modificado'=>1, |
| 2793 | 'cobrado'=>1, |
| 2794 | 'delivered_directo'=>1, |
| 2795 | ]; |
| 2796 | if(is_numeric($value) && !str_contains($fieldName, 'num') && !str_contains($fieldName, 'consecutivo')) { |
| 2797 | if(str_contains($fieldName, 'lock') || array_key_exists($fieldName, $intFlags)) |
| 2798 | return (int)$value ? 'Si' : 'No'; |
| 2799 | if(str_contains($fieldName, 'roll') || str_contains($fieldName, 'verificaciones_') || $fieldName === 'iac_edits') |
| 2800 | $decimals = 0; |
| 2801 | elseif($fieldName === 'tc' || $fieldName === 'tipo_cambio') |
| 2802 | $decimals = 4; |
| 2803 | elseif(str_starts_with($fieldName, 'puntos')) |
| 2804 | $decimals = 4; |
| 2805 | else |
| 2806 | $decimals = 2; |
| 2807 | return bcformat($value, $decimals); |
| 2808 | } |
| 2809 | |
| 2810 | |
| 2811 | switch($fieldName) { |
| 2812 | case 'alta_db': |
| 2813 | case 'ultimo_cambio': |
| 2814 | return mysqlDateTime2display($value); |
| 2815 | case 'fecha': |
| 2816 | return mysqlDate2display($value); |
| 2817 | } |
| 2818 | if(str_contains($value, '-')) { |
| 2819 | $len = strlen($value); |
| 2820 | if($len === 10) |
| 2821 | if(count(explode('-', $value)) === 3) |
| 2822 | return mysqlDate2display($value); |
| 2823 | if($len === 19) |
| 2824 | return mysqlDate2display($value); |
| 2825 | } |
| 2826 | return (string)$value; |
| 2827 | } |
| 2828 | function formatMeArray(array $array, array|null $fieldNameOrder = null):string { |
| 2829 | $ret = [" <ol>"]; // espacio inicial importante |
| 2830 | if($fieldNameOrder === null) |
| 2831 | $fieldNameOrder = ['bodega_id', 'producto_general_id', 'color_id', 'quantity', 'unidades_id', 'rollos']; |
| 2832 | foreach($array as $k => $data) { |
| 2833 | if(is_array($data)) { |
| 2834 | $item = []; |
| 2835 | foreach($fieldNameOrder as $fieldName) |
| 2836 | if(array_key_exists($fieldName, $data)) |
| 2837 | $item[] = formatMe($fieldName, $data[$fieldName]); |
| 2838 | $ret[] = implode(" ", $item); |
| 2839 | } else |
| 2840 | $ret[] = formatMe($k, $data); |
| 2841 | } |
| 2842 | return implode(" <li>", $ret) . " </ol>"; // espacio inicial de <li> y </ol> son importantes |
| 2843 | } |
| 2844 | |
| 2845 | function formatMeId(string $fieldName, int|string $id, int|string|null $default = ''):string { |
| 2846 | if($default === null) |
| 2847 | $default = $id; |
| 2848 | $fieldName = strtolower($fieldName); |
| 2849 | static $labels; |
| 2850 | if(!isset($labels)) { |
| 2851 | $method = __METHOD__; |
| 2852 | /** @var $labels |
| 2853 | * Si es un array [fieldname=>[id=>label,...],.. ] |
| 2854 | * String inicia con SELECT y tiene '%id%' sustituye el '%id%' con $id y regresa el label (primera columna) |
| 2855 | * String inicia con SELECT se corre y arma el para la proxima vez fieldname=>[id=>label,...] |
| 2856 | * String no inicia con SELECT hace json_decode(obtenCatalogo(string), true) para llenar el array fieldname=>[id=>label,...] |
| 2857 | */ |
| 2858 | $labels = [ |
| 2859 | 'banco_id' => "SELECT /*$method*/ banco_id, banco FROM banco ORDER BY 2", |
| 2860 | 'banco_cuenta_id' => "SELECT /*$method*/ banco_cuenta_id, nombre FROM banco_cuenta ORDER BY 2", |
| 2861 | 'bodega_id' => "bodega_keyValue_all", |
| 2862 | 'categoria_id' => "categoria", |
| 2863 | 'cuentat_mov_id' => [], |
| 2864 | 'cliente_id' => "SELECT /*$method*/ cliente_id, nombre FROM cliente ORDER BY 2", |
| 2865 | 'color_id' => 'color_keyValue_all', |
| 2866 | 'cp_autotransporte' => |
| 2867 | "SELECT /*$method*/ cp.autotransporte_id,IF(e.empresa IS NULL,cp.PlacaVM, CONCAT_WS(' ',e.empresa, cp.PlacaVM) ) |
| 2868 | FROM cp_autotransporte cp LEFT OUTER JOIN empresa e on cp.empresa_id = e.empresa_id |
| 2869 | ORDER BY 2", |
| 2870 | |
| 2871 | 'cp_cliente_id' => "SELECT /*$method*/ cp_cliente_id, razon_social FROM cp_cliente ORDER BY 2", |
| 2872 | |
| 2873 | 'cp_figuratransporte_id' => "SELECT /*$method*/ cp.figuratransporte_id, |
| 2874 | IF(e.empresa IS NULL,cp.NombreFigura, CONCAT_WS(' ',e.empresa, cp.NombreFigura) ) |
| 2875 | FROM cp_figuratransporte cp LEFT OUTER JOIN empresa e on cp.empresa_id = e.empresa_id |
| 2876 | ORDER BY 2", |
| 2877 | 'cp_tipofiguratransporte_id' => "SELECT /*$method*/ cp_tipofiguratransporte_id, ClaveFiguraTransporte FROM cp_tipofiguratransporte ORDER BY 2", |
| 2878 | |
| 2879 | 'cp_cliente_direccion_id' => "SELECT /*$method*/ CONCAT_WS(' ', calle, numero_exterior, numero_interior, colonia, municipio) FROM cp_cliente_direccion WHERE cp_cliente_direccion_id='%id%'", |
| 2880 | |
| 2881 | 'cuentat_id' => "SELECT /*$method*/ cuentat_id, usuario FROM cuentat ORDER BY 2", |
| 2882 | 'empresa_id' => "SELECT /*$method*/ empresa_id, empresa FROM empresa ORDER BY 2", |
| 2883 | 'fabrica_id' => usuarioTipoRony() || Permisador::puede("pedido_china_fabrica", 'Nada') !== 'Nada' ? |
| 2884 | "SELECT /*$method*/ fabrica_id, fabrica FROM fabricas ORDER BY 2" : [], |
| 2885 | 'iac_usr_id' => "SELECT /*$method*/ iac_usr_id, nick FROM iac_usr ORDER BY 2", |
| 2886 | 'origen_bodega_id' => "SELECT /*$method*/ origen_bodega_id, clave FROM origen_bodega ORDER BY 2", |
| 2887 | 'producto_bodega_id' => |
| 2888 | "SELECT /*$method*/ producto_bodega_id, |
| 2889 | CONCAT(b.bodega, ': ', IF(pg.producto IS NULL OR c.color IS NULL, pc.producto, CONCAT_WS(' ', pg.producto, c.color))) |
| 2890 | FROM producto_bodega pc |
| 2891 | JOIN bodega b on pc.bodega_id = b.bodega_id |
| 2892 | LEFT OUTER JOIN producto_general pg on pc.producto_general_id = pg.producto_general_id |
| 2893 | LEFT OUTER JOIN color c on pc.color_id = c.color_id |
| 2894 | ORDER BY 2", |
| 2895 | 'producto_color_id' => |
| 2896 | "SELECT /*$method*/ producto_color_id, IF(pg.producto IS NULL OR c.color IS NULL, pc.producto, |
| 2897 | CONCAT_WS(' ', pg.producto, c.color)) |
| 2898 | FROM producto_color pc |
| 2899 | LEFT OUTER JOIN producto_general pg on pc.producto_general_id = pg.producto_general_id |
| 2900 | LEFT OUTER JOIN color c on pc.color_id = c.color_id |
| 2901 | ORDER BY 2", |
| 2902 | 'producto_general_id' => "producto_general_keyValue_all", |
| 2903 | 'tienda_id' => "SELECT /*$method*/ tienda_id, clave FROM tienda ORDER BY 2", |
| 2904 | 'unidades_id' => "SELECT /*$method*/ unidades_id, unidad FROM unidades ORDER BY 2", |
| 2905 | 'pagare_id' => |
| 2906 | "SELECT /*$method*/ |
| 2907 | CONCAT(IF(c.nombre IS NULL, '', c.nombre), ' #', d.numero, |
| 2908 | ' por $', d.quantity, ' debe $', d.saldo ' ', m.moneda, |
| 2909 | IF(d.paid = 0, CONCAT(' ', DATE_FORMAT(d.original_date, '%e/%b/%y')), ' PAID'), ' ', c2.categoria |
| 2910 | ) |
| 2911 | FROM pagare d |
| 2912 | JOIN moneda m on d.moneda_id = m.moneda_id |
| 2913 | LEFT OUTER JOIN cliente c on d.cliente_id = c.cliente_id |
| 2914 | LEFT OUTER JOIN categoria c2 on d.categoria_id = c2.categoria_id |
| 2915 | WHERE d.pagare_id='%id%'", |
| 2916 | |
| 2917 | 'nota_bodega_id' => |
| 2918 | "SELECT /*$method*/ CONCAT_WS(' ', |
| 2919 | DATE_FORMAT(fecha, '%e/%b/%y'), |
| 2920 | nb.numero, b.bodega, nb.entrada_salida, |
| 2921 | IF(nb.tipo='Movimiento', 'Venta Tienda', nb.tipo), |
| 2922 | IF(ob.clave IS NULL OR nb.tipo='Cancelacion' OR nb.tipo='Borrado' OR nb.tipo='Correccion' OR nb.tipo='Container', |
| 2923 | '', ob.clave) |
| 2924 | ) |
| 2925 | FROM nota_bodega nb JOIN bodega b on nb.bodega_id = b.bodega_id |
| 2926 | LEFT OUTER JOIN origen_bodega ob on nb.origen_id = ob.origen_bodega_id |
| 2927 | WHERE nb.nota_bodega_id='%id%'", |
| 2928 | ]; |
| 2929 | // sinonimos |
| 2930 | $labels['origen_id'] = $labels['origen_bodega_id']; |
| 2931 | $labels['producto_id'] = $labels['producto_general_id']; |
| 2932 | $labels['origen_cuentat_id'] = $labels['cuentat_transferto_id'] = $labels['cuentat_deliveredto_id'] = |
| 2933 | $labels['cuentat_id']; |
| 2934 | |
| 2935 | } |
| 2936 | if(!array_key_exists($fieldName, $labels)) |
| 2937 | return $default; |
| 2938 | $item = $labels[$fieldName]; |
| 2939 | if(is_string($item)) { |
| 2940 | if(str_contains($item, '%id%')) |
| 2941 | return (string)ia_singleread(str_replace("'%id%'" , strit($id), $item), 'N/A', 'SQL ERROR'); |
| 2942 | if(str_starts_with($item, "SELECT ")) |
| 2943 | $item = ia_sqlKeyValue($item); |
| 2944 | else |
| 2945 | $item = json_decode(obtenCatalogo($item), true); |
| 2946 | } |
| 2947 | if(is_array($item)) |
| 2948 | return $item[$id] ?? $default; |
| 2949 | return $default; |
| 2950 | } |
| 2951 | |
| 2952 | |
| 2953 | function the_error_handler($errno, $errstr, $errfile, $errline) { |
| 2954 | static $errYa; |
| 2955 | if (!(error_reporting() & $errno)) |
| 2956 | return false; |
| 2957 | $ya = $errYa[$errfile][$errline] ?? null; |
| 2958 | if($ya !== null) |
| 2959 | return false; |
| 2960 | $errYa[$errfile][$errline] = "$errno: " . htmlentities($errstr); |
| 2961 | ia_errores_a_dime("$errno: " .htmlentities($errstr) , $errfile, 'php', $errline, |
| 2962 | $errno.$errfile.$errline); |
| 2963 | return false; |
| 2964 | } |
| 2965 | function the_exception_handler($exception) { |
| 2966 | static $errYa; |
| 2967 | $ya = $errYa[$exception->getFile()][$exception->getLine()] ?? null; |
| 2968 | if($ya !== null) |
| 2969 | return; |
| 2970 | $errYa[$exception->getFile()][$exception->getLine()] = htmlentities($exception->getMessage()); |
| 2971 | ia_errores_a_dime(htmlentities($exception->getMessage(). " FIN DE SCRIPT") , $exception->getFile(), 'php', $exception->getLine(), |
| 2972 | $exception->getFile().$exception->getLine()); |
| 2973 | } |
| 2974 | set_error_handler('the_error_handler'); |
| 2975 | set_exception_handler('the_exception_handler'); |
| 2976 | |
| 2977 | function recomiendanOlla($ver = 'All') { |
| 2978 | $method = __METHOD__; |
| 2979 | $puede = Permisador::puede('puede_reporte_ventas'); |
| 2980 | if(!usuarioTipoRony() && $puede === 'Nada') |
| 2981 | return []; |
| 2982 | |
| 2983 | $programar = []; |
| 2984 | if(!usuarioTipoRony() && $puede == 'R/O') { |
| 2985 | $programarHeader = 'Pedir'; |
| 2986 | } else { |
| 2987 | $programarHeader = "Programa<br>" . ucwords($_SESSION['usuario'] ?? 'N/A'); |
| 2988 | if($ver !== 'Olla') { |
| 2989 | $sql = "SELECT /*$method*/ CONCAT(pg.producto, '_', c.color) as id, pg.producto, c.color, |
| 2990 | IF(digo = 'No Pedir', 'No Pedir', |
| 2991 | IF(digo = 'Complemento', CONCAT('Complemento ', IF(pri.quantity IS NULL OR pri.quantity=0, ' ', pri.quantity ) ) |
| 2992 | ,pri.quantity) ) as quantity |
| 2993 | FROM pedido_recomienda_items pri |
| 2994 | JOIN pedido_recomienda pr on pri.pedido_recomienda_id = pr.pedido_recomienda_id |
| 2995 | JOIN iac_usr iu on pr.iac_usr_id = iu.iac_usr_id |
| 2996 | JOIN producto_general pg on pri.producto_general_id = pg.producto_general_id |
| 2997 | JOIN color c on pri.color_id = c.color_id |
| 2998 | WHERE pr.activo = 'Si' AND pr.tipo = 'Programacion' AND pri.digo <> '' AND pr.iac_usr_id=" . strit($_SESSION['usuario_id']) . |
| 2999 | " ORDER BY 2, 3"; |
| 3000 | $programar = ia_sqlArray($sql, 'id'); |
| 3001 | } |
| 3002 | } |
| 3003 | if($ver === 'Programacion' || $ver === 'Programa') |
| 3004 | $olla = []; |
| 3005 | else { |
| 3006 | $sql = "SELECT /*$method*/ pg.producto, c.color, iu.nick, |
| 3007 | IF(digo = 'No Pedir', 'No Pedir', |
| 3008 | IF(digo = 'Complemento', CONCAT('Complemento ', IF(pri.quantity IS NULL OR pri.quantity=0, ' ', pri.quantity ) ) |
| 3009 | ,pri.quantity) ) as quantity |
| 3010 | FROM pedido_recomienda_items pri |
| 3011 | JOIN pedido_recomienda pr on pri.pedido_recomienda_id = pr.pedido_recomienda_id |
| 3012 | JOIN iac_usr iu on pr.iac_usr_id = iu.iac_usr_id |
| 3013 | JOIN producto_general pg on pri.producto_general_id = pg.producto_general_id |
| 3014 | JOIN color c on pri.color_id = c.color_id |
| 3015 | WHERE pr.activo = 'Si' AND pr.tipo = 'Olla' AND pri.digo <> '' |
| 3016 | ORDER BY 1, 2, 3"; |
| 3017 | $olla = ia_sqlSelectMultiKey($sql, 3); |
| 3018 | } |
| 3019 | $users = []; |
| 3020 | foreach($olla as $colores) |
| 3021 | foreach($colores as $usuarios) |
| 3022 | foreach($usuarios as $nick => $_) |
| 3023 | $users[$nick] = ''; |
| 3024 | |
| 3025 | $rec = []; |
| 3026 | foreach($olla as $producto => $colores) { |
| 3027 | foreach($colores as $color => $usuarios) { |
| 3028 | $key = $producto.'_'.$color; |
| 3029 | $rec[$key] =[ |
| 3030 | ...['producto' => $producto, 'color' => $color, $programarHeader => $programar[$key]['quantity'] ?? ''], |
| 3031 | ...$users |
| 3032 | ]; |
| 3033 | $in = &$rec[$key]; |
| 3034 | foreach($usuarios as $nick => $r) { |
| 3035 | $in[$nick] = $r['quantity']; |
| 3036 | } |
| 3037 | } |
| 3038 | } |
| 3039 | |
| 3040 | foreach(array_diff_key($programar, $rec) as $key => $c) |
| 3041 | $rec[$key] = ['producto' => $c['producto'], 'color' => $c['color'], $programarHeader => $c['quantity']]; |
| 3042 | return $rec; |
| 3043 | } |
| 3044 | function recomiendanOllaTable($ver = 'All') { |
| 3045 | $date = mysqlDateTime2display(Date('Y-m-d H:i:s')); |
| 3046 | $data = recomiendanOlla($ver); |
| 3047 | uasort($data, function($a, $b){ |
| 3048 | $da = strtoupper($a['producto']) <=> strtoupper($b['producto']); |
| 3049 | return $da ? $da : strtoupper($a['color']) <=> strtoupper($b['color']); |
| 3050 | }); |
| 3051 | return |
| 3052 | '<script> |
| 3053 | function tablaDaVer() { |
| 3054 | let numCols = $("#tablaDa tr").first().children().length; |
| 3055 | switch($("input[name=\'tablaDaColsVer\']:checked").val()) { |
| 3056 | case "Olla": |
| 3057 | $("td:nth-child(3)", "#tablaDa").hide(); |
| 3058 | $("th:nth-child(3)", "#tablaDa").hide(); |
| 3059 | for(let i = 4; i <= numCols; ++i) { |
| 3060 | $(`td:nth-child(${i})`, "#tablaDa").show(); |
| 3061 | $(`th:nth-child(${i})`, "#tablaDa").show(); |
| 3062 | } |
| 3063 | break; |
| 3064 | case "Programa": |
| 3065 | case "Programacion": |
| 3066 | $("td:nth-child(3)", "#tablaDa").show(); |
| 3067 | $("th:nth-child(3)", "#tablaDa").show(); |
| 3068 | for(let i = 4; i <= numCols; ++i) { |
| 3069 | $(`td:nth-child(${i})`, "#tablaDa").hide(); |
| 3070 | $(`th:nth-child(${i})`, "#tablaDa").hide(); |
| 3071 | } |
| 3072 | break; |
| 3073 | default: |
| 3074 | for(let i = 3; i <= numCols; ++i) { |
| 3075 | $(`td:nth-child(${i})`, "#tablaDa").show(); |
| 3076 | $(`th:nth-child(${i})`, "#tablaDa").show(); |
| 3077 | } |
| 3078 | } |
| 3079 | } |
| 3080 | function tablaDaExcel() { |
| 3081 | let ver = $("input[name=\'tablaDaColsVer\']:checked").val(); |
| 3082 | window.open("../bodega/olla2excel.php?ver=" + ver, "_blank"); |
| 3083 | setTimeout(function(){ $("#tablaDaExcel").off("click", tablaDaExcel).one("click", tablaDaExcel);}, 700); |
| 3084 | } |
| 3085 | jQuery(function(){ |
| 3086 | $("#recomiendaExport").append(exporter.toolBar("#tablaDa",{excel_table:false, fileName:"programar.csv"} ) ); |
| 3087 | $("#tablaDaExcel").off("click", tablaDaExcel).one("click", tablaDaExcel); |
| 3088 | }); |
| 3089 | </script><style>#tablaDa CAPTION{text-align:left}</style><div style="text-align: left;width:fit-content;">' . |
| 3090 | iaTableIt::getTableIt( |
| 3091 | $data, |
| 3092 | "<div id='recomiendaExport' style='white-space: nowrap;padding:0.5em 0.3em'>Recomendaciones para Programar <i style='font-weight: 100'>" . ucwords($_SESSION['usuario'] ?? 'N/A') . " $date</i><p style='padding-top:0.5em'>" . |
| 3093 | " <input onchange='tablaDaVer()' type='radio' name='tablaDaColsVer' id='tablaDaAll' value='All'><label for='tablaDaAll'> All</label> " . |
| 3094 | " <input onchange='tablaDaVer()' type='radio' name='tablaDaColsVer' id='tablaDaOlla' value='Olla'><label for='tablaDaOlla'> Olla</label> " . |
| 3095 | " <input onchange='tablaDaVer()' type='radio' name='tablaDaColsVer' id='tablaDaPrograma' value='Programa' checked><label for='tablaDaPrograma'> Programa</label> " . |
| 3096 | " <span id='tablaDaExcel' class='pointer' style='margin-left:1em;color:darkgreen;font-size:1.2em;font-weight: bold' title='Exportar a Excel'>🅇</span>" . |
| 3097 | "</div>", |
| 3098 | "tablaDa" |
| 3099 | ) . '</div>'; |
| 3100 | } |
| 3101 | |
| 3102 | /** |
| 3103 | * @param string $producto_general_id |
| 3104 | * @param string $color_id |
| 3105 | * @param string|int|float|null $quantity |
| 3106 | * @param string $digo '' borrado ya no esta capturado |
| 3107 | * @param string $remarks |
| 3108 | * @param string $tipo Olla o Programacion |
| 3109 | * @param bool $execute |
| 3110 | * @return bool|string |
| 3111 | * @throws Exception |
| 3112 | */ |
| 3113 | function recomiendaSave( |
| 3114 | string $producto_general_id, string $color_id, |
| 3115 | string|int|float|null $quantity, |
| 3116 | #[ExpectedValues(['Pedir', 'Falta', 'Complemento', 'No', 'No Pedir', 'Importante', ''])] |
| 3117 | string $digo, |
| 3118 | string $remarks = '', |
| 3119 | #[ExpectedValues(['Olla', 'Programacion'])] |
| 3120 | string $tipo = 'Olla', |
| 3121 | bool $execute = true |
| 3122 | ):bool|string { |
| 3123 | if(strcasecmp($tipo, 'Olla') && strcasecmp($tipo, 'Programacion')) |
| 3124 | return false; |
| 3125 | $function = __FUNCTION__; |
| 3126 | $builder = new \Iac\inc\sql\IacSqlBuilder(); |
| 3127 | $digo = ucwords(strtolower($digo ?? '')); |
| 3128 | $pedido_recomienda_id = getRecomiendaPedido(strcasecmp($tipo, 'Olla') === 0); |
| 3129 | |
| 3130 | if(($digo === 'Pedir' && empty($quantity)) || $digo === '') { |
| 3131 | $where = $builder->where([ |
| 3132 | 'producto_general_id' => $producto_general_id, |
| 3133 | 'color_id' => $color_id, |
| 3134 | 'pedido_recomienda_id' => $pedido_recomienda_id, |
| 3135 | ]); |
| 3136 | $sqlDelete[] = "DELETE /*$function*/ FROM pedido_recomienda_items WHERE $where"; |
| 3137 | if (!$execute) |
| 3138 | return $sqlDelete[0]; |
| 3139 | $sqlDelete[] = "DELETE /*$function*/ FROM pedir_producto WHERE " . |
| 3140 | $builder->where(['iac_usr_id' => $_SESSION['usuario_id'], 'producto_general_id' => $producto_general_id, 'color_id' => $color_id]); |
| 3141 | return !ia_transaction($sqlDelete); |
| 3142 | } |
| 3143 | # revisa datos |
| 3144 | if(!empty($quantity) && (!is_numeric($quantity) || ((float)$quantity < 0) )) |
| 3145 | return false; |
| 3146 | |
| 3147 | if(!array_key_exists($digo, ['Pedir'=>1, 'Falta'=>1, 'Complemento'=>1, 'Importante'=>1, 'No'=>1, 'No Pedir'=>1, ''=>1, 'Ya Pedido' => 1] ) ) |
| 3148 | return false; |
| 3149 | |
| 3150 | if($digo === 'No Pedir') |
| 3151 | $quantity = 0; |
| 3152 | elseif($quantity == '0' && $digo !== 'Complemento' && $digo !== 'Importante') |
| 3153 | $digo = 'No Pedir'; |
| 3154 | if($quantity === '') { |
| 3155 | $quantity = null; |
| 3156 | if($digo !== 'Complemento' && $digo !== 'No Pedir' && $digo !== 'Importante' && $digo !== 'Ya Pedido') |
| 3157 | $digo = ''; |
| 3158 | } |
| 3159 | $era = json_encode([ ['digo' => $digo, 'quantity' => $quantity] ], JSON_OPTIONS_FOR_MYSQL); |
| 3160 | $pedido_recomienda_id = getRecomiendaPedido(strcasecmp($tipo, 'Olla') === 0); |
| 3161 | $data = [ |
| 3162 | 'pedido_recomienda_id' => strit($pedido_recomienda_id), |
| 3163 | 'producto_general_id' => strit($producto_general_id), |
| 3164 | 'color_id' => strit($color_id), |
| 3165 | 'quantity' => $quantity === null ? 'NULL' : strit($quantity), |
| 3166 | 'digo' => strit($digo), |
| 3167 | 'era' => strit($era), |
| 3168 | ]; |
| 3169 | $insert = "INSERT /*$function()*/ INTO pedido_recomienda_items(" . implode(',', array_keys($data)) . ") " . |
| 3170 | "VALUES (" . implode(',', $data) . ") ON DUPLICATE KEY UPDATE "; |
| 3171 | foreach($data as $fieldName => $value) |
| 3172 | if($fieldName === 'era') |
| 3173 | $insert .= " era = $value, "; |
| 3174 | else |
| 3175 | $insert .= " $fieldName = $value,"; |
| 3176 | $insert .= "ultimo_cambio = NOW()"; |
| 3177 | |
| 3178 | if (!$execute) |
| 3179 | return $insert; |
| 3180 | $sql = [$insert]; |
| 3181 | |
| 3182 | if($digo === '') |
| 3183 | $sql[] = "DELETE /*$function*/ FROM pedir_producto WHERE " . |
| 3184 | $builder->where(['iac_usr_id' => $_SESSION['usuario_id'], 'producto_general_id' => $producto_general_id, 'color_id' => $color_id]); |
| 3185 | else { |
| 3186 | $pedir_producto = [ |
| 3187 | 'producto_general_id' => $producto_general_id, |
| 3188 | 'color_id' => $color_id, |
| 3189 | 'iac_usr_id' => $_SESSION['usuario_id'], |
| 3190 | 'quantity' => $quantity ?? '', |
| 3191 | 'comentario' => '', |
| 3192 | 'pedido_recomienda_items_id' => '', |
| 3193 | 'digo' => $digo, |
| 3194 | ]; |
| 3195 | $sql[] = $builder->insert('pedir_producto', $pedir_producto, true, '', ['comentario']); |
| 3196 | } |
| 3197 | |
| 3198 | return !ia_transaction($sql); |
| 3199 | } |
| 3200 | |
| 3201 | function topVentasBodega($top = 10) { |
| 3202 | $header = []; |
| 3203 | $ret = []; |
| 3204 | $lastYear = (int)Date('Y') - 1; |
| 3205 | $fechas = [ |
| 3206 | 'Todo' => ['2019-01-01', Date('Y-m-d')], |
| 3207 | 'Este Mes' => [Date('Y-m-01'), Date('Y-m-d')], |
| 3208 | '1 Mes' => [Date('Y-m-d', strtotime('1 month ago')), Date('Y-m-d')], |
| 3209 | '2 Meses' => [Date('Y-m-d', strtotime('2 month ago')), Date('Y-m-d')], |
| 3210 | '3 Meses' => [Date('Y-m-d', strtotime('3 month ago')), Date('Y-m-d')], |
| 3211 | '4 Meses' => [Date('Y-m-d', strtotime('4 month ago')), Date('Y-m-d')], |
| 3212 | '6 Meses' => [Date('Y-m-d', strtotime('6 month ago')), Date('Y-m-d')], |
| 3213 | '12 Meses' => [Date('Y-m-d', strtotime('1 year ago')), Date('Y-m-d')], |
| 3214 | |
| 3215 | 'Este Año' => [Date('Y-01-01'), Date('Y-m-d')], |
| 3216 | 'El Pasado' => [Date('$lastYear-01-01'), Date('$lastYear-m-d')], |
| 3217 | 'El Año Anterior' => [Date('$lastYear-01-01'), Date('$lastYear-12-31')], |
| 3218 | ]; |
| 3219 | $sql = "SELECT CONCAT(pg.producto,' ', c.color) as producto, |
| 3220 | SUM(bed.salida_venta_quantity - bed.entrada_devolucion_quantity) as quantity, |
| 3221 | u.unidad, |
| 3222 | SUM(bed.salida_venta_rollos - bed.entrada_devolucion_rollos) as rollos |
| 3223 | FROM bodega_existencia_diaria bed |
| 3224 | JOIN producto_general pg ON bed.producto_general_id=pg.producto_general_id |
| 3225 | JOIN unidades u on pg.unidades_id = u.unidades_id |
| 3226 | JOIN color c ON bed.color_id=c.color_id |
| 3227 | WHERE fecha >= ? AND fecha <= ? |
| 3228 | GROUP BY producto, u.unidad ORDER BY 2 DESC LIMIT $top"; |
| 3229 | |
| 3230 | global $gSqlClass; |
| 3231 | $query = $gSqlClass->mysqli->prepare($sql); |
| 3232 | |
| 3233 | foreach($fechas as $label => $f) { |
| 3234 | $rows = []; |
| 3235 | $n = 0; |
| 3236 | $header = "<th class='cen' colspan='4'>$label<div class='vdet'>" . mysqlDate2display($f[0]) . ' - ' . mysqlDate2display($f[1]) . "</div>"; |
| 3237 | $query->bind_param('ss', $f[0], $f[1]); |
| 3238 | foreach(ia_sqlArrayIndx($query) as $p) { |
| 3239 | $n++; |
| 3240 | $rows[] = "<td class='der'>$n<td>$p[producto]<td class='der'>" . |
| 3241 | bcformat($p['quantity'], 2) . "<td class='cen'>$p[unidad]"; |
| 3242 | } |
| 3243 | if(!empty($rows)) |
| 3244 | $ret[] = "<table class='laTabla'><thead><tr>$header</thead><tbody><tr>" . |
| 3245 | implode("<tr>", $rows) . "</tbody></table>"; |
| 3246 | |
| 3247 | } |
| 3248 | |
| 3249 | return "<div style='display:flex;flex-wrap: wrap'>" . implode("", $ret) . "</div>"; |
| 3250 | } |
| 3251 | |
| 3252 | /** |
| 3253 | * @param $url |
| 3254 | * @param $iac_usr_id |
| 3255 | * @return array ['nombre'=>'valor',...] para los defaults de iac_usr_id en la hoja $url |
| 3256 | */ |
| 3257 | function usuario_defaults_get(string $url='', string|int|float $iac_usr_id=''):array { |
| 3258 | global $gWebDir; |
| 3259 | if(empty($iac_usr_id)) |
| 3260 | $iac_usr_id = $_SESSION['usuario_id']; |
| 3261 | if(empty($url)) |
| 3262 | $url = str_replace("$_SERVER[CONTEXT_DOCUMENT_ROOT]/$gWebDir", "", $_SERVER['SCRIPT_FILENAME']); |
| 3263 | $method = __FUNCTION__; |
| 3264 | $defautls = ia_sqlKeyValue( |
| 3265 | "SELECT /*$method*/ nombre, valor |
| 3266 | FROM usuario_defaults |
| 3267 | WHERE url=" . strit($url) . " AND iac_usr_id=" . strit($iac_usr_id)); |
| 3268 | if(empty($defautls) ) |
| 3269 | return []; |
| 3270 | foreach($defautls as &$d) |
| 3271 | $d = json_decode($d, true); |
| 3272 | return $defautls; |
| 3273 | } |
| 3274 | |
| 3275 | function usuario_defaults_set(array $keyValue, string $url='', string|int|float $iac_usr_id='') { |
| 3276 | global $gWebDir; |
| 3277 | if(empty($iac_usr_id)) |
| 3278 | $iac_usr_id = $_SESSION['usuario_id']; |
| 3279 | if(empty($url)) |
| 3280 | $url = str_replace("$_SERVER[CONTEXT_DOCUMENT_ROOT]/$gWebDir", "", $_SERVER['SCRIPT_FILENAME']); |
| 3281 | $builder = new \Iac\inc\sql\IacSqlBuilder(); |
| 3282 | foreach($keyValue as $nombre => $valor) { |
| 3283 | ia_query($builder->insert( |
| 3284 | 'usuario_defaults', |
| 3285 | ['url' => $url, 'iac_usr_id' => $iac_usr_id, 'nombre' => $nombre, |
| 3286 | 'valor' => json_encode($valor, JSON_OPTIONS_FOR_MYSQL)], |
| 3287 | true) |
| 3288 | ); |
| 3289 | } |
| 3290 | } |
| 3291 | |
| 3292 | /** |
| 3293 | * Tablita con los archivos y su last modified time relacionados. Hmm Deducidos, agregar $extraFiles as needed |
| 3294 | * |
| 3295 | * @param array $extraFiles |
| 3296 | * @return string |
| 3297 | */ |
| 3298 | function usedFilesTimes(array $extraFiles = []):string { |
| 3299 | global $gDefaultClasses, $gIApath, $gIaHeader, $gVersionesExtraFiles; |
| 3300 | $docRoot = substr( $gIApath['DOCUMENT_ROOT'], 0 ,-1); |
| 3301 | $baseName = basename($_SERVER['SCRIPT_FILENAME']); |
| 3302 | $currentPath = str_replace($baseName, '', $_SERVER['SCRIPT_FILENAME']); |
| 3303 | $filePath = $gIApath['FilePath']; |
| 3304 | $used = []; |
| 3305 | |
| 3306 | $dime = getMTime($baseName); |
| 3307 | $used[$dime['file']] = $dime['mtime']; |
| 3308 | $dime = getMTime($baseName . '_acciones'); |
| 3309 | if(trim($dime['mtime']) !== 'N/A') |
| 3310 | $used[$dime['file']] = $dime['mtime']; |
| 3311 | $forceFiles = [ |
| 3312 | "backoffice/view/component/commons/dialog_consulta_existenciaColapsable.php", |
| 3313 | "backoffice/view/component/commons/dialogoExistencias.js", |
| 3314 | "backoffice/view/component/commons/dialogoReporteVentas.js", |
| 3315 | "" |
| 3316 | ]; |
| 3317 | foreach($forceFiles as $file) { |
| 3318 | $file = $filePath . $file; |
| 3319 | if(file_exists($file)) |
| 3320 | $used[$file] = Date('Y-m-d H:i', filemtime($file)); |
| 3321 | else |
| 3322 | $used[$file] = " N/A"; |
| 3323 | } |
| 3324 | foreach($gVersionesExtraFiles as $file) { |
| 3325 | switch($file[0]) { |
| 3326 | case '.': $file = $currentPath . $file; break; |
| 3327 | case '/': break; |
| 3328 | default: $file = $filePath . $file; |
| 3329 | } |
| 3330 | if(file_exists($file)) |
| 3331 | $used[$file] = Date('Y-m-d H:i', filemtime($file)); |
| 3332 | else |
| 3333 | $used[$file] = " N/A"; |
| 3334 | } |
| 3335 | |
| 3336 | $code = file_get_contents($_SERVER['SCRIPT_FILENAME']); |
| 3337 | if(empty($code)) |
| 3338 | $code = ''; |
| 3339 | $code .= $gIaHeader->html_head_get(); |
| 3340 | |
| 3341 | preg_match_all('/(include|require)(_once){0,1}\s*\(\s*["\'](.*)["\']\)/mUS', |
| 3342 | $code, $matches, PREG_SET_ORDER, 0); |
| 3343 | if(!empty($matches)) |
| 3344 | foreach($matches as $m) { |
| 3345 | $dime = getMTime(basename($m[3])); |
| 3346 | if(trim($dime['mtime']) !== 'N/A') { |
| 3347 | $used[$dime['file']] = $dime['mtime']; |
| 3348 | continue; |
| 3349 | } |
| 3350 | $file = $currentPath . $m[3]; |
| 3351 | if(file_exists($file)) |
| 3352 | $used[$file] = Date('Y-m-d H:i' ,filemtime($file)); |
| 3353 | else |
| 3354 | $used[$file] = ' N/A'; |
| 3355 | } |
| 3356 | unset($matches); |
| 3357 | |
| 3358 | preg_match_all('/<script\s*src\s*=\s*[\'"](.*)[\'"]/mUS', |
| 3359 | $code, $matches, PREG_SET_ORDER, 0); |
| 3360 | if(!empty($matches)) |
| 3361 | foreach($matches as $m) { |
| 3362 | $file =$m[1]; |
| 3363 | $iPos = strpos($file, '?'); |
| 3364 | if($iPos) |
| 3365 | $file = substr($file, 0, $iPos); |
| 3366 | if($file[0] === '.') |
| 3367 | $file = $currentPath . $file; |
| 3368 | elseif($file[0] === '/') |
| 3369 | $file = $docRoot . $file; |
| 3370 | if(file_exists($file)) |
| 3371 | $used[$file] = Date('Y-m-d H:i' ,filemtime($file)); |
| 3372 | else |
| 3373 | $used[$file] = ' N/A' . "de SCRIPT" ; |
| 3374 | } |
| 3375 | unset($matches); |
| 3376 | |
| 3377 | preg_match_all('/<link\s*href\s*=\s*[\'"](.*)[\'"]/mUS', |
| 3378 | $code, $matches, PREG_SET_ORDER, 0); |
| 3379 | if(!empty($matches)) |
| 3380 | foreach($matches as $m) { |
| 3381 | $file =$m[1]; |
| 3382 | $iPos = strpos($file, '?'); |
| 3383 | if($iPos) |
| 3384 | $file = substr($file, 0, $iPos); |
| 3385 | if($file[0] === '.') |
| 3386 | $file = $currentPath . $file; |
| 3387 | elseif($file[0] === '/') |
| 3388 | $file = $docRoot . $file; |
| 3389 | if(file_exists($file)) |
| 3390 | $used[$file] = Date('Y-m-d H:i' ,filemtime($file)); |
| 3391 | else |
| 3392 | $used[$file] = ' N/A' . "de LINK"; |
| 3393 | } |
| 3394 | unset($matches); |
| 3395 | |
| 3396 | preg_match_all('/url\s*:\s*[\'"](.*)[\'"]/mUS', |
| 3397 | $code, $matches, PREG_SET_ORDER, 0); |
| 3398 | if(!empty($matches)) |
| 3399 | foreach($matches as $m) { |
| 3400 | $file =$m[1]; |
| 3401 | $iPos = strpos($file, '?'); |
| 3402 | if($iPos) |
| 3403 | $file = substr($file, 0, $iPos); |
| 3404 | if($file[0] === '.') |
| 3405 | $file = $currentPath . $file; |
| 3406 | elseif($file[0] === '/') |
| 3407 | $file = $docRoot . $file; |
| 3408 | if(file_exists($file)) |
| 3409 | $used[$file] = Date('Y-m-d H:i' ,filemtime($file)); |
| 3410 | else |
| 3411 | $used[$file] = ' N/A' . "de LINK"; |
| 3412 | } |
| 3413 | unset($matches); |
| 3414 | |
| 3415 | |
| 3416 | $inc = ['config.php', 'ia_utilerias.php', 'helpers.php', 'vitex.php']; |
| 3417 | foreach($inc as $file) { |
| 3418 | $dime = getMTime($file); |
| 3419 | $used[$dime['file']] = $dime['mtime']; |
| 3420 | } |
| 3421 | foreach($extraFiles as $file) { |
| 3422 | $dime = getMTime($file); |
| 3423 | $used[$dime['file']] = $dime['mtime']; |
| 3424 | } |
| 3425 | |
| 3426 | foreach(get_declared_classes() as $class) { |
| 3427 | switch($class) { |
| 3428 | case 'ProcessLock': $class = 'vitex_process_lock'; break; |
| 3429 | case 'sqlMysqli': $class = 'sqlConverter'; break; |
| 3430 | case 'StringCompareJaroWinkler': $class = 'vitex_experimental'; break; |
| 3431 | case 'XLSXWriter': $class = 'xlsxwriter.class'; break; |
| 3432 | case 'XLSXWriter_BuffererWriter': $class = 'xlsxwriter.class'; break; |
| 3433 | case 'BancoCuentaMov': $class = 'tipos'; break; |
| 3434 | case 'Iac\inc\sql\IacSqlException': continue 2; |
| 3435 | } |
| 3436 | |
| 3437 | if( !array_key_exists($class, $gDefaultClasses) ) { |
| 3438 | $classFileName = basename($class) . ".php"; |
| 3439 | $dime = getMTime($classFileName); |
| 3440 | $used[$dime['file']] = $dime['mtime']; |
| 3441 | } |
| 3442 | } |
| 3443 | |
| 3444 | arsort($used); |
| 3445 | |
| 3446 | $count = count($used); |
| 3447 | $first = reset($used); |
| 3448 | $caption = "Versiones: " . basename($_SERVER['SCRIPT_FILENAME']) . " uses $count files. Último Cambio el $first"; |
| 3449 | $ret[] = "<table id='versionesFilesMTime' class='laTabla'><caption>$caption</caption><thead><tr><th>File</th><th>Last Modified</th></tr></thead><tbody>"; |
| 3450 | foreach($used as $class => $t) |
| 3451 | $ret[] = "<tr><td>$class<td>$t"; |
| 3452 | $ret[] = "</tbody></table>"; |
| 3453 | return "<details class='default' style='margin:1em;'><summary>$caption</summary><div>" . implode("", $ret) . "</div></details>"; |
| 3454 | } |
| 3455 | |
| 3456 | /** |
| 3457 | * Ayudante de usedFilesTimes |
| 3458 | * |
| 3459 | * @param string $file |
| 3460 | * @return array|string[] |
| 3461 | */ |
| 3462 | function getMTime($file):array { |
| 3463 | global $gIApath; |
| 3464 | static $path; |
| 3465 | if(empty($path)) { |
| 3466 | $path = explode(";", ini_get('include_path')); |
| 3467 | $path[] = "$gIApath[FilePath]backoffice"; |
| 3468 | $path[] = "$gIApath[FilePath]backoffice/ajax"; |
| 3469 | $path[] = "$gIApath[FilePath]bodega"; |
| 3470 | $path[] = "$gIApath[FilePath]cobranza"; |
| 3471 | $path[] = "$gIApath[FilePath]pedido"; |
| 3472 | $path[] = "$gIApath[FilePath]css2"; |
| 3473 | $path[] = "$gIApath[FilePath]js2"; |
| 3474 | } |
| 3475 | foreach($path as $p) |
| 3476 | if(file_exists("$p/$file")) |
| 3477 | return ['file' => "$p/$file", 'mtime' => Date('Y-m-d H:i', filemtime("$p/$file") )]; |
| 3478 | $p = "$gIApath[FilePath]inc"; |
| 3479 | foreach(['ErrorReporter', 'sql', 'Excel', 'iaJqGrid'] as $subDir) |
| 3480 | if(file_exists("$p/$subDir/$file")) |
| 3481 | return ['file' => "$p/$subDir/$file", 'mtime' => Date('Y-m-d H:i', filemtime("$p/$subDir/$file") )]; |
| 3482 | return ['file' => "$file", 'mtime' => ' N/A']; |
| 3483 | } |
| 3484 | |
| 3485 | function getLastNModifiedFiles($n = 25) { |
| 3486 | |
| 3487 | $file = fopen("C:\\wamp\\www\\vitex\\uploads\\fragmentLastModified.html","r"); |
| 3488 | while ($line = fgets($file, 4 * 4096)) { |
| 3489 | echo mb_convert_encoding($line, "UTF-8", "UTF-16"); |
| 3490 | } |
| 3491 | return true; |
| 3492 | /* |
| 3493 | $cmd = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe \"dir c:\\wamp\\www\\vitex\\ -r | where { \$_.fullname -notmatch 'txt|uploads|testie|idea|vscode|fontawesome-pro-6.4.0-web|vendor|json'} | Sort-Object LastWriteTime -Descending | Select-Object -first $n | select lastwritetime,hack,fullname\""; |
| 3494 | $output = shell_exec($cmd); |
| 3495 | |
| 3496 | preg_match('/^(\d.*)\s{3,}.*$/mS', $output, $matches); |
| 3497 | return "<details class='default'><summary>Last $matches[1]</summary><div>Last $n modified<pre class='code'>$output</pre></div></details>";*/ |
| 3498 | } |
| 3499 | |
| 3500 | /** |
| 3501 | * @return void |
| 3502 | * @noinspection PhpUnused |
| 3503 | */ |
| 3504 | function file_debug_reporte():void { |
| 3505 | global $gSqlClass, $gIApath, $gDime; |
| 3506 | $date = Date('d/M/y H:i'); |
| 3507 | $fileName = basename($_SERVER['REQUEST_URI']); |
| 3508 | if(str_contains($fileName, '?')) |
| 3509 | $fileName = strstr(basename($fileName), '?', true); |
| 3510 | if(str_contains($fileName, '&')) |
| 3511 | $fileName = strstr(basename($fileName), '&', true); |
| 3512 | if(str_contains($fileName, '#')) |
| 3513 | $fileName = strstr(basename($fileName), '#', true); |
| 3514 | |
| 3515 | $css = iaTimer::cssClases() . iaTableIt::getCssClases(); |
| 3516 | $fontFamily = 'font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'; |
| 3517 | $sqlTrace = $gSqlClass->trace_get(); |
| 3518 | $explain = []; |
| 3519 | foreach($sqlTrace as $id => $sql) { |
| 3520 | $s = ltrim(strtolower($sql)); |
| 3521 | if( |
| 3522 | !str_starts_with($s, 'show') && !str_starts_with($s, 'create') && |
| 3523 | !str_starts_with($s, 'alter') && !str_starts_with($s, 'drop') && |
| 3524 | !str_starts_with($s, 'explain') && |
| 3525 | !str_starts_with($s, 'set') && !str_starts_with($s, 'call') && |
| 3526 | !str_starts_with($s, 'commit') && !str_starts_with($s, 'rollback') |
| 3527 | ) |
| 3528 | $explain[$id] = "<li><pre>$sql</pre><pre>" . iaTableIt::getTableIt(ia_sqlArrayIndx("EXPLAIN $sql")) . "</pre>"; |
| 3529 | else |
| 3530 | $explain[$id] = "<li><pre>$sql</pre>"; |
| 3531 | } |
| 3532 | $iah = param('iah', param('h')); |
| 3533 | if(!empty($iah)) |
| 3534 | $fileName .= "_iah_$iah"; |
| 3535 | file_put_contents("$gIApath[FilePath]backoffice/txt/quePex_$fileName.html", |
| 3536 | "<!DOCTYPE html><html lang='es-MX'><head><title>q!Pex: $fileName</title><style> |
| 3537 | BODY{margin:1em;padding:1em;$fontFamily} |
| 3538 | PRE {margin:1em;padding:1em;border:1px blue solid;$fontFamily;width:fit-content} |
| 3539 | $css FIELDSET {width:fit-content} |
| 3540 | TABLE {white-space: normal} |
| 3541 | </style></head><body><h1>q!Pex: $fileName</h1><br>$date $_SESSION[usuario]<pre><fieldset>" . |
| 3542 | "<fieldset><legend>Request</legend>" . |
| 3543 | ToCode::variable('Request', $_REQUEST) . "\r\n" . |
| 3544 | "</fieldset>" . |
| 3545 | "<fieldset><legend>\$gDime</legend>" . |
| 3546 | ToCode::variable('gDime', empty($gDime) ? [] : $gDime) . "\r\n" . |
| 3547 | "</fieldset>" . |
| 3548 | "<fieldset><legend>Detected Errors</legend>" . |
| 3549 | ToCode::variable('PHP Last Error', error_get_last()) . "\r\n" . |
| 3550 | ToCode::variable('PHP Last JsonError', json_last_error_msg()) . "\r\n" . |
| 3551 | ToCode::variable('PHP Last RegExpError', preg_last_error_msg()) . "\r\n" . |
| 3552 | ToCode::variable('Sql_Errors', $gSqlClass->errorLog_get()) . "\r\n" . |
| 3553 | "</fieldset>" . |
| 3554 | "<fieldset><legend>Queries</legend>\r\n\r\n<ol>" . implode("\r\n\r\n", $explain) . "\r\n\r\n</ol>\r\n\r\n</fieldset>" . "\r\n" . |
| 3555 | "</fieldset>" . |
| 3556 | "<fieldset><legend>Timing</legend>" . |
| 3557 | iaTimer::table(null, true, true, true) . |
| 3558 | "</fieldset>" . |
| 3559 | "</pre>" . |
| 3560 | "</body></html>" |
| 3561 | ); |
| 3562 | } |
| 3563 | |
| 3564 | function keys2Tiny(array $data, $rowKeysToCompress = []) { |
| 3565 | if(empty($data)) |
| 3566 | return ['data'=>[], 'keyMap' => []]; |
| 3567 | |
| 3568 | $colN = 0; |
| 3569 | $keyMap = []; |
| 3570 | foreach(array_keys(reset($data)) as $key) |
| 3571 | $keyMap[$key] = num2Key($colN++); |
| 3572 | $rowKeys = array_flip($rowKeysToCompress); |
| 3573 | $reKeyed = []; |
| 3574 | foreach($data as $k => $d) { |
| 3575 | $row = []; |
| 3576 | foreach($d as $key => $value) |
| 3577 | if(array_key_exists($key, $rowKeys)) { |
| 3578 | if(!array_key_exists($value, $keyMap)) { |
| 3579 | $keyMap[$value] = num2Key(++$colN); |
| 3580 | } |
| 3581 | $row[$keyMap[$key]] = $keyMap[$value]; |
| 3582 | } else |
| 3583 | $row[$keyMap[$key]] = $value; |
| 3584 | $reKeyed[$k] = $row; |
| 3585 | } |
| 3586 | return [ |
| 3587 | 'data' => $reKeyed, |
| 3588 | 'keyMap' => $keyMap, 'rowKeyMap' => $rowKeys]; |
| 3589 | } |
| 3590 | |
| 3591 | /** |
| 3592 | * De número (0=A) a columna de excel |
| 3593 | * |
| 3594 | * @param int $colNum |
| 3595 | * @return string |
| 3596 | */ |
| 3597 | function num2Key(int $colNum):string { |
| 3598 | if($colNum < 0) |
| 3599 | return 'A'; |
| 3600 | if($colNum < 26) { |
| 3601 | return chr($colNum + 65); |
| 3602 | } |
| 3603 | if($colNum < 702) { |
| 3604 | return chr(64 + (int)($colNum / 26)) . chr(65 + $colNum % 26); |
| 3605 | } |
| 3606 | return chr(64 + (int)(($colNum - 26) / 676)) . chr(65 + (int)((($colNum - 26) % 676) / 26)) . chr(65 + $colNum % 26); |
| 3607 | } |
| 3608 | |
| 3609 | function getDeviceInfo():array { |
| 3610 | $device['ua'] = strtolower($_SERVER["HTTP_USER_AGENT"] ?? ''); |
| 3611 | $device['isMobile'] = str_contains($device['ua'], 'mobile') || str_contains($device['ua'], 'phone'); |
| 3612 | $device['isTablet'] = str_contains($device['ua'], "ipad") || str_contains($device['ua'], "tablet"); |
| 3613 | $device['isIpad'] = str_contains($device['ua'], "ipad"); |
| 3614 | return $device; |
| 3615 | } |
| 3616 | |
| 3617 | /** |
| 3618 | * Regresa html de un select box con las posiciones de columnas a usar de default, al seleccionar va a la hoja |
| 3619 | * |
| 3620 | * @param string $url pagina a que dirigirse ie |
| 3621 | * @param string $col_def_key ie posiciones de la hoja |
| 3622 | * @return string |
| 3623 | */ |
| 3624 | function jqGridColsSorter_SelectLinkTo(string $url, string $col_def_key):string { |
| 3625 | static $colTemplates; |
| 3626 | if(!is_array($colTemplates)) { |
| 3627 | $function = __FUNCTION__; |
| 3628 | $usuario = strit($_SESSION['usuario_id']); |
| 3629 | $colTemplates = ia_sqlSelectMultiKey( |
| 3630 | "SELECT /*$function*/ col_def_key, jqGridColsSorter_id, label, para_todos |
| 3631 | FROM jqGridColsSorter |
| 3632 | WHERE iac_usr_id = $usuario OR para_todos = 'Si' OR jqGridColsSorter_id <= 0 |
| 3633 | ORDER BY myDefault, label",2); |
| 3634 | } |
| 3635 | if(!array_key_exists($col_def_key, $colTemplates)) |
| 3636 | return ''; |
| 3637 | if(str_contains($url, '?')) |
| 3638 | $url .= '&'; |
| 3639 | else |
| 3640 | $url .= '?'; |
| 3641 | $options = "<option></option>"; |
| 3642 | foreach($colTemplates[$col_def_key] as $id => $d) { |
| 3643 | if($id <= 0) |
| 3644 | $class = 'colSortDefault'; |
| 3645 | elseif($d['para_todos'] === 'No') |
| 3646 | $class = 'colSortUsuario'; |
| 3647 | else |
| 3648 | $class = 'colSortParaTodos'; |
| 3649 | $options .= "<option value='{$url}jqGridColsSorter_id=$id' class='$class'>" . htmlentities($d['label']) . "</option>"; |
| 3650 | } |
| 3651 | //return "<select class='colSortSelect' onchange='window.open(this.value)'>$options</select>"; |
| 3652 | return "<select class='colSortSelect' onchange='window.location.href=this.value'>$options</select>"; |
| 3653 | } |
| 3654 | |
| 3655 | function jqGridColsSorter_GetDefs(string $col_def_key):array { |
| 3656 | $function = __FUNCTION__; |
| 3657 | $col_def = strit($col_def_key); |
| 3658 | $iac_usr_id = strit($_SESSION['usuario_id']); |
| 3659 | $colDef = ia_sqlArrayIndx( |
| 3660 | "SELECT /*$function*/ jqGridColsSorter_id as value, label, def, para_todos, myDefault, ocultar_ribbon |
| 3661 | FROM jqGridColsSorter |
| 3662 | WHERE col_def_key = $col_def AND (para_todos = 'Si' OR iac_usr_id = $iac_usr_id) |
| 3663 | ORDER BY myDefault, para_todos DESC, jqGridColsSorter.label" |
| 3664 | ); |
| 3665 | foreach($colDef as &$c) |
| 3666 | $c['def'] = json_decode($c['def']); |
| 3667 | return $colDef; |
| 3668 | } |
| 3669 | |
| 3670 | /** |
| 3671 | * Regresa values de string para edit y search options uso: |
| 3672 | * editoptions: {value: "<?php echo units2grid(); ?>"}, |
| 3673 | * searchoptions: {value: ":;<?php echo units2grid(); ?>", |
| 3674 | * |
| 3675 | * @return string |
| 3676 | */ |
| 3677 | function units2grid():string { |
| 3678 | $u = ia_sqlVector("SELECT /*units2grid*/ CONCAT(unidad, ':', unidad) FROM unidades WHERE vale='Active' ORDER BY unidades_id"); |
| 3679 | if($u === false) |
| 3680 | return "Kg:Kg;Mts:Mts;Pza:Pza;n/a:n/a"; |
| 3681 | $u[] = 'n/a:n/a'; |
| 3682 | return implode(";", $u); |
| 3683 | } |
| 3684 | |
| 3685 | function jsCodeColChooser(string $gridId):string { |
| 3686 | $savedCode = json_encode(jqGridColsSorter_GetDefs($gridId . '_') ); |
| 3687 | return <<< JS_CODE |
| 3688 | {$gridId}_cols = new jqGridColsSorter( |
| 3689 | $("#{$gridId}"), "{$gridId}_", "{$gridId}_cols", [], |
| 3690 | $savedCode |
| 3691 | ); |
| 3692 | {$gridId}_cols.putGetParam(); |
| 3693 | $("#iactoolbartable").find("TR").first().append("<TD id='putColsChooser'>"); |
| 3694 | $("#putColsChooser").append({$gridId}_cols.controles()); |
| 3695 | JS_CODE; |
| 3696 | } |
| 3697 | |
| 3698 | function bodega_x_dia_cache($from = null):void { |
| 3699 | if(empty($from)) { |
| 3700 | $from = min( |
| 3701 | Date('Y-m-d', strtotime('2 days ago')), |
| 3702 | ia_singleread("SELECT MAX(fecha) FROM bodega_x_dia", "2022-09-01") |
| 3703 | ); |
| 3704 | if(empty($from)) |
| 3705 | $from = "2022-09-01"; |
| 3706 | } |
| 3707 | $method = __FUNCTION__; |
| 3708 | $sql = " |
| 3709 | INSERT INTO bodega_x_dia(fecha, bodega, Existencia_Rollos, Existencia_Quantity_Kg, Existencia_Quantity_Mts, Existencia_Containers,Existencia_CIF_Today) |
| 3710 | (WITH /* $method */ dia as (SELECT MAX(fecha) as fecha, bodega_id, producto_general_id, color_id |
| 3711 | FROM bodega_existencia_diaria |
| 3712 | WHERE fecha <= ? |
| 3713 | GROUP BY bodega_id, producto_general_id, color_id |
| 3714 | HAVING MAX(fecha)) |
| 3715 | SELECT ?, bed.Bodega, |
| 3716 | SUM(bed.existencia_rollos) as Existencia_Rolls, |
| 3717 | SUM(IF(u.unidad = 'Kg', bed.existencia_quantity, 0)) as Existencia_Quantity_Kg, |
| 3718 | SUM(IF(u.unidad <> 'Kg',0, bed.existencia_quantity)) as Existencia_Quantity_Mts, |
| 3719 | SUM(IF(pg.container_quantity = 0, NULL, bed.existencia_quantity / pg.container_quantity)) as Existencia_Containers, |
| 3720 | SUM(IFNULL(pcb.cost_cif * bed.existencia_quantity, NULL)) as 'Existencia_CIF_Today' |
| 3721 | FROM bodega_existencia_diaria bed |
| 3722 | JOIN dia ON bed.fecha = dia.fecha AND bed.bodega_id = dia.bodega_id |
| 3723 | AND bed.producto_general_id = dia.producto_general_id |
| 3724 | AND bed.color_id = dia.color_id |
| 3725 | JOIN producto_general pg ON pg.producto_general_id = dia.producto_general_id |
| 3726 | LEFT OUTER JOIN unidades u ON u.unidades_id = pg.unidades_id |
| 3727 | LEFT OUTER JOIN producto_costs_bodega pcb ON pcb.producto_general_id = bed.producto_general_id AND pcb.fecha_fin IS NULL |
| 3728 | GROUP BY 1, 2) ON DUPLICATE KEY UPDATE |
| 3729 | Existencia_Rollos = VALUES(Existencia_Rollos), |
| 3730 | Existencia_Quantity_Kg = VALUES(Existencia_Quantity_Kg), |
| 3731 | Existencia_Quantity_Mts = VALUES(Existencia_Quantity_Mts), |
| 3732 | Existencia_Containers = VALUES(Existencia_Containers), |
| 3733 | Existencia_CIF_Today = VALUES(Existencia_CIF_Today) "; |
| 3734 | |
| 3735 | global $gSqlClass; |
| 3736 | $query = $gSqlClass->mysqli->prepare($sql); |
| 3737 | $period = new DatePeriod( |
| 3738 | DateTimeImmutable::createFromFormat('Y-m-d', $from), |
| 3739 | new DateInterval("P1D"), |
| 3740 | new DateTimeImmutable("now") |
| 3741 | ); |
| 3742 | foreach ($period as $date) { |
| 3743 | $d2 = $d1 = $date->format('Y-m-d'); |
| 3744 | $query->bind_param('ss', $d1, $d2); |
| 3745 | $query->execute(); |
| 3746 | } |
| 3747 | } |
| 3748 | function bodega_x_dia_ExistenciaMaximaTable($class = 'tblIt'):string { |
| 3749 | bodega_x_dia_cache(); |
| 3750 | $show = "WITH mx AS |
| 3751 | (SELECT bodega, MAX(Existencia_Containers) as Existencia_Containers |
| 3752 | FROM bodega_x_dia |
| 3753 | GROUP BY bodega |
| 3754 | ) |
| 3755 | SELECT bd.Bodega, bd.Existencia_Containers as Containers, bd.Existencia_Rollos as Rollos, |
| 3756 | bd.Existencia_Quantity_Kg as Qty_Kg, bd.Existencia_Quantity_Mts Qty_Mts, bd.Fecha |
| 3757 | FROM bodega_x_dia bd JOIN mx ON |
| 3758 | bd.bodega = mx.bodega AND bd.Existencia_Containers = mx.Existencia_Containers |
| 3759 | ORDER BY bd.bodega, bd.fecha"; |
| 3760 | $maxBodega = ia_sqlArray($show, 'Bodega'); |
| 3761 | return iaTableIt::getTableIt($maxBodega, |
| 3762 | "Containers Máximo por Bodega " . |
| 3763 | '<i onclick="toExcel(\'tblIt\', \'Existencia_maxima_por_bodega\')" style="color:green;cursor:pointer" class="fa-duotone fa-file-excel"></i>', |
| 3764 | tableClass: $class); |
| 3765 | } |
| 3766 | |
| 3767 | function bodega_x_dia_recalc() { |
| 3768 | $method = __FUNCTION__; |
| 3769 | $last = ia_singleread("SELECT /*$method*/ updated FROM bodega_x_dia_last"); |
| 3770 | if($last === false) { |
| 3771 | ia_query("CREATE /*$method*/ TABLE IF NOT EXISTS bodega_x_dia_last(updated DATETIME NOT NULL )"); |
| 3772 | ia_query("INSERT /*$method*/ INTO bodega_x_dia_last(updated) VALUES(NOW())"); |
| 3773 | $last = ia_singleread("SELECT /*$method*/ updated FROM bodega_x_dia_last"); |
| 3774 | } |
| 3775 | if($last === false || Date('Y-m-d H:i', strtotime("2 minutes ago")) < $last ) |
| 3776 | return; |
| 3777 | ia_query("UPDATE /*$method*/ bodega_x_dia_last SET updated=NOW()"); |
| 3778 | bodega_x_dia_cache('2022-09-01'); |
| 3779 | } |
| 3780 |