Generacion de la cadena EDI (EDIFACT D01B)

Contenido/contents:
Introducion
Codigo Fuente
Uso de la funcion
Pagina anterior/Previous page

Introduccion
Este codigo lo desarrolle tomando como base la informacion publicada en la ONU del standard D01B, esta informacion es muy amplia e incluye muchos posibles segmentos.
En la practica, cada socio comercial elabora el mapa de los segmentos que realmente quieren emplear, En mi caso use la guia de implementacion de Wal-Mart.
Para accesar dicha guia tienen dos opciones:
  1. Entrar a la pagina de Retail link al area de comercio electronico y de ahi bajarlas. Necesitas ya estar registrado como usuario y al dia de hoy (Abril 28, 2005) solo estaban publicadas las guias de los estandares anteriores.

  2. Hablar a soporte de EDI en Wal Mart para que se las proporcionen.
Codigo Fuente
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
<?php
//
// +-------------------------------------------------------------------------------+
// | satxwalm.php : Genera factura EDIFACT D01B leyendo la BD                      |
// |                       Formato WalMart                                         |
// +-------------------------------------------------------------------------------+
// | Copyright (c) 2005  Fabrica de Jabon la Corona, SA de CV                      |
// +-------------------------------------------------------------------------------+
// | This program is free software; you can redistribute it and/or                 |
// | modify it under the terms of the GNU General Public License                   |
// | as published by the Free Software Foundation; either version 2                |
// | of the License, or (at your option) any later version.                        |
// |                                                                               |
// | This program is distributed in the hope that it will be useful,               |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of                |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 |
// | GNU General Public License for more details.                                  |
// |                                                                               |
// | You should have received a copy of the GNU General Public License             |
// | along with this program; if not, write to the Free Software                   |
// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.   |
// +-------------------------------------------------------------------------------+
// | Autor: Fernando Ortiz <fortiz@lacorona.com.mx>                                |
// +-------------------------------------------------------------------------------+
// | 21/Jun/2005 Se agrega el NAD+II del emisor de la factura                      |
// | 30/Jun/2005 Se agrega calificador de precio al PRI+AAA                        |
// |  1/Jul/2005 Se agrega el codigo de estado en NAD a dos posiciones             |
// | 30/Ago/2005 Cambia el calificador del PRI de EA a CA (precio por caja)        |
// |  5/Oct/2005 Se cambia la fecha a formato con segundos para el requisito del   |
// |             SAT de simultaneidad (2.22.6 II)                                  |
// |  4/Nov/2005 como el numero EAN del producto y el EAn de la surursal debe de   |
// |             coincidir con el numero de su orden de compra se lee de una       |
// |             exclusiva de paso de las ordenes de c ompra de walmart            |
// | 4/ene/2006  Se cambia el calificador de LIN de EA a SRV                       |
// | 2/mar/2006  Si no encuentra el codigo UPC en donde debe de ser agarra el del  |
// |             catalogo general del producto pero no se va en blanco.            |
// | 21/abr/2006 Si el numero de orden de compra de walmart es de mas de 10 posi-  |
// |             ciones, intenta 'arreglarla' para que la localize en ediordcom.   |
// |                                                                               |
// |             Borra el aviso de error aperak en el reenvio                      |
// | 24/abr/2006 Tambien se quita el caracter "'", por ejemplo de SAM'S , debido a |
// |             que el ' es el caracter separador de segmentos   ;)               |
// | 23/05/20076 Se toma g_auto del arreglo asociativo de la parte XML             |
// +-------------------------------------------------------------------------------+
//
function satxwalm($nufa, $data) {
// {{{ carga librerisa requeridas para obtener los datos
require_once("dbi/clfactur.class.php");      // Es el registro maestro de la factura
require_once("dbi/clflinea.class.php");      // Contiene un regisro por linea/partida de la factura
require_once("dbi/clbodega.class.php");      // Domicilio fiscal de los lugares/bodegas de facturacion
require_once("dbi/clclient.class.php");      // Archivo maestro de clientes
require_once("dbi/clproduc.class.php");      // Datos Generales del Producto
require_once "lib/numealet.php";             // Convierte de numeros a letras
require_once "lib/getfolio.php";             // Le suma uno al foliador y regresa el siguiente folio
global $conn;                                // Conexion adodb a la base de datos
// }}}
// {{{ Inicialice varibles / contadores globales
error_reporting(E_ALL);
$edidata = "";
$dc1 =  "'"; // chr(17);
$dc2 =  "'"; // chr(18);
$fact = new Clfactur($conn,$nufa);
$clie = new Clclient($conn,(int)$fact->row["factnucl"],"renglon");
$nuca = $clie->row["clienuca"];
if ($nuca==18 || $nuca==33 || $nuca==35 || $nuca==36 || $nuca==37) $ok=true;
else  die ("NO es factura de walmart!");
$bode = new Clbodega($conn,(int)$fact->row["factnubo"],'renglon');
$g_auto = $data['noAprobacion']; // Numero de autorizacion del SAT de los folios
 
// }}}
// {{{ Encabesados generales 
// +--------------------------------------------------------------------+
// | Genera los primeros segmentos del mensaje EDI                      |
// +--------------------------------------------------------------------+
//
$g_c_prod = 0; $g_t_seg = 0;
$g_ref_num = $conn->getOne("select fedifoli from cfdwalmart where fedinufa = '$nufa'"); // Lee el folio anterior si existe
if (!$g_ref_num) $g_ref_num = getfolio("cte",6,"SATXINVO",11); // Toma folio consecutivo para cada mensaje EDI
$edidata .= "UNA:+.?".$dc1;
$fech = date("ymd");
$hora = date("Hi");
$edidata .= "UNB+UNOB:1+JABON-CORONA:ZZ+925485MX00:8+$fech:$hora+".$g_ref_num.$dc2;
$edidata .= "UNG+INVOIC+JABON-CORONA:ZZ+925485MX00:8+$fech:$hora+".$g_ref_num."+UN+D:01B:AMC002".$dc2;
$edidata .= "UNH+".$g_ref_num."+INVOIC:D:01B:UN:AMC002".$dc2;
$edidata .= "BGM+380+".trim(substr($fact->row["factnufa"],4))."+9".$dc2; // 
$edidata .= "DTM+137:".iso_fech($fact->row["factfdoc"]). ":204".$dc2;
$edidata .= "FTX+ZZZ+++".satxwalm_fix(numealet($fact->row["factimto"]),512).$dc2;
$npec = trim($fact->row["factnpec"]);
if (strlen($npec)>10) {
    // Si el numero de orden de compra es de mas de 10 posiciones es que 'alguien' me hizo favor
    // de capturar a mano el pedido y no tomo la grabacion automatica via EDI del ORDERS
    $npec = str_replace(array('*','"',"'","=",'-'),"",$npec);
    echo "replace=$npec ";
    if (strlen($npec)>10) $npec = substr($npec,1);
    echo "sin=$npec ";
    if (strlen($npec)>10) $npec = substr(0,10);
    echo "sale=$npec ";
}
$cant = $conn->getOne("select count(*) from clflinea, clproduc where faliprod = prodprod and falinufa = '$nufa' and prodtico = 0");
if ($cant == 0) { // Via cedis lleva npec
   $edidata .= "RFF+ON:".$npec.$dc2;
   $edidata .= "DTM+171:".edi_fech($fact->row["factfpec"]).":102".$dc2;
} else { // Fue envio directo usa folio
    $folio_numero = $fact->row['factreci'];
    $folio_fecha = $fact->row['factrfec'];
    $edidata .= "RFF+DQ:".$folio_numero.$dc2;   // Folio de entrega
    $edidata .= "DTM+171:".edi_fech($folio_fecha).":102".$dc2;
}
$edidata .= "RFF+BT:".trim(substr($fact->row["factnufa"],0,4)).$dc2;
$edidata .= "RFF+ATZ:".$g_auto.$dc2;
$edidata .= "NAD+BY+7507003100001::9++NUEVA WAL MART DE MEXICO S DE RL DE:CV+".
                          "NEXTENGO NO 78:SANTA CRUZ ACAYUCAN+AZCAPOTZALCO+DF+02770".$dc2;
$edidata .= "RFF+GN:NWM9709244W4".$dc2;
$edidata .= "NAD+SU+7504000065005::9++FABRICA DE JABON LA CORONA,SA DE CV+".
                          "CARLOS B ZETINA NO 80+FRACC IND XALOSTOC+MC+55348".$dc2;
$edidata .= "RFF+GN:FJC780315E91".$dc2;
$eancode = "";
$prov = "";
$ordc = $conn->getRow("select * from ediordcom where ordcnpec matches '*".$npec."*'");
if (isset($ordc["ordcnpec"])) {
    $prov = $ordc["ordcprov"];
    $eancode = $ordc["ordcgln"];
} else {
    echo "sin ediordcom";
    $obs4 = $fact->row["factobs4"];
    $eancode = substr($obs4,20);
    $prov = (substr($obs4,0,10)=="PROVEEDOR:") ? substr($obs4,10,9) : "";
    if (!$prov) $prov = ($clie->row["clienuca"] == 33) ?  "227412640" : "172042132";
}
if ($eancode=="") $eancode = "7507003163884";
if ($prov=="") $prov = "000";
$edidata .= "RFF+IA:".$prov.$dc2; // nuestro numero de proveedor
if ($fact->row['factcoim']==3) {
    $dire = trim($bode->row["bodedirf"]);
    $colo = trim($bode->row["bodecolf"]);
    $pobl = trim(substr($bode->row["bodepobf"],6));
    $codp = (int)substr($bode->row["bodepobf"],0,5);
} else {
    $dire = trim($bode->row["bodedire"]);
    $colo = trim($bode->row["bodecolo"]);
    $pobl  = trim(substr($bode->row["bodepobl"],6));
    $codp = (int)substr($bode->row["bodepobl"],0,5);
}
$edo = edi_estado($pobl);
$edidata .= "NAD+II+7504000065005::9++FABRICA DE JABON LA CORONA,SA DE CV+".
                  satxwalm_fix($dire,35).":".
                  satxwalm_fix($colo,35)."+".
                  satxwalm_fix($pobl,35)."+".
                  satxwalm_fix($edo,3)."+".
                  satxwalm_fix($codp,17).$dc2;
$edidata .= "NAD+ST+".$eancode."::9++".satxwalm_fix($clie->row["clienone"]).":".
                  satxwalm_fix($clie->row["clienopr"],35)."+".
                  satxwalm_fix($clie->row["cliedire"],35).":".
                  satxwalm_fix($clie->row["cliecolo"],35)."+".
                  satxwalm_fix($clie->getPueb("cliecoes","cliemuni","cliepueb"),35)."+".
                  satxwalm_fix($clie->getrefe("cte",6,"FACTCOES","cliecoes",49,2),3)."+".
                  satxwalm_fix($clie->row["cliecodp"],17).$dc2;
$edidata .= "CUX+2:MXN:4++1".$dc2;
$edidata .= "PAT+1++5:3:D:30".$dc2;
$edidata .= "PCD+12:0".$dc2;
$g_t_seg += 18;
// }}}
// {{{   Para cada linea/partida de la factura (para cada producto
// +--------------------------------------------------------------------+
// | AHora si procesa la ocurrencia de productos de la factura          |
// +--------------------------------------------------------------------+
//
$fali = new Clflinea($conn, $nufa);
for ($i=0; $i<sizeof($fali->faliprod); $i++) {
    $nupr = (int)$fali->faliprod[$i];
    $prod = new Clproduc($conn, $nupr,'renglon');
    $g_c_prod++;
    $upc = "";
    if (isset($ordc['ordcnpec'])) {
        $upc = $conn->getOne("select ordcupc from ediordcom where ordcprod = $nupr and ordcnpec = '".$ordc["ordcnpec"]."'");
        if ($upc=="") {
            // Si no encuentra elproducto directo busca algun producto agrupador equivalente
            //   problemas entre nacional/autoservicios/paletizado
            $upc = $conn->getOne("select ordcupc
                                    from clproduc a, clproduc b, ediordcom
                                    where a.prodprod = $nupr
                                          and  a.prodagru = b.prodagru
                                          and b.prodprod = ordcprod
                                          and ordcnpec = '".$ordc["ordcnpec"]."'");
        }
    } 
    if ($upc=="") $upc = $prod->row["prodea13"];
    $edidata .= "LIN+".$g_c_prod."++".trim($upc).":SRV::9".$dc2;
    $edidata .= "PIA+1+".$prod->row["prodprod"].":SA".$dc2;
    $edidata .= "IMD+F++:::".trim($prod->row["proddeco"]).$dc2;
    $unif = (float)$fali->faliunif[$i]; if ($unif==0) $unif=1;
    $edidata .= "QTY+47:".$unif.":CA".$dc2;
    $edidata .= "QTY+59:".$prod->row["produnca"].":EA".$dc2;
    $edidata .= "MOA+203:".$fali->falineto[$i].$dc2;
    $prun = (double)$fali->falineto[$i] / $unif;
    $edidata .= "PRI+AAA:".$prun."::::CA".$dc2;
    $edidata .= "TAX+7+VAT+++:::".$fali->falipoim[$i].$dc2;
    $edidata .= "MOA+124:".$fali->faliimpu[$i].$dc2;
    $g_t_seg += 9;
}
// }}}
// {{{ Final del mensaje edifact
// +--------------------------------------------------------------------+
// | Agrega los segmentos finales con los totales y cifras de control   |
// +--------------------------------------------------------------------+
//
$edidata .= "UNS+S".$dc2;
$edidata .= "CNT+11:".$fact->row["facttoun"].$dc2;
$edidata .= "CNT+2:".$g_c_prod.$dc2;
$edidata .= "MOA+9:".$fact->row["factimto"].$dc2;
$edidata .= "MOA+79:".($fact->row["factneto"]+$fact->row["factnet2"]).$dc2;
$edidata .= "MOA+125:".($fact->row["factneto"]+$fact->row["factnet2"]).$dc2;
$edidata .= "TAX+7+VAT+++:::".$fact->row["factpoim"].$dc2;
$edidata .= "MOA+124:".$fact->row["factimpu"].$dc2;
$g_t_seg += 9;
$edidata .= "UNT+".$g_t_seg."+".$g_ref_num.$dc2;
$edidata .= "UNE+4+".$g_ref_num.$dc2;
$edidata .= "UNZ+1+".$g_ref_num.$dc2;
$ret=$conn->replace("cfdwalmart",array("fedinufa"=>$nufa,"fedifoli"=>$g_ref_num,"fediaper"=>null,"fedicont"=>null),
                    "fedinufa",true);
return($edidata);
}
// }}}
// {{{ Convierta la fecha en formato Informix d/m/a a formato edi YYYYMMDD
 
function edi_fech($fech) {
    return ("20".substr($fech,6,2).substr($fech,3,2).substr($fech,0,2));
}
// }}}
// {{{ Convierta la fecha en formato ISO YYYY-mm-ddThh:mm:ss
 
function iso_fech($fech) {
    return (str_replace(array(":","-"," "),"",$fech));  // Le quita los ':' porque es separador EDI
}
// }}}
// {{{ Convierte el estado al codigo 'standard' de 2 caracteres
function edi_estado($esta) {
    $coes="XX";
    if (stristr($esta,"AGUAS")) $coes="AS";              // AGUASCALIENTES      AS
    if (stristr($esta,"MEXICALI")) $coes="BC";           // BAJA CALIFORNIA     BC
    if (stristr($esta,"B.C.S.")) $coes="BS";             // BAJA CALIFORNIA SUR BS
    if (stristr($esta,"CAMPE")) $coes="CC";              // CAMPECHE            CC
    if (stristr($esta,"TUXTLA")) $coes="CS";             // CHIAPAS             CS
    if (stristr($esta,"TAPACHULA")) $coes="CS";          // CHIAPAS             CS
    if (stristr($esta,"CHIHUHUA")) $coes="CH";           // CHIHUAHUA           CH
    if (stristr($esta,"COAH")) $coes="CL";               // COAHUILA            CL
    if (stristr($esta,"COLIMA")) $coes="CM";             // COLIMA              CM
    if (stristr($esta,"D.F.")) $coes="DF";               // DISTRITO FEDERAL    DF
    if (stristr($esta,"DURANGO")) $coes="DG";            // DURANGO             DG
    if (stristr($esta,"IRAPUATO")) $coes="GT";           // GUANAJUATO          GT
    if (stristr($esta,"ACAPULCO")) $coes="GR";           // GUERRERO            GR
    if (stristr($esta,"HIDALGO")) $coes="HG";            // HIDALGO             HG
    if (stristr($esta,"GUADALAJARA")) $coes="JC";        // JALISCO             JC
    if (stristr($esta,"XALOSTOC")) $coes="MC";           // MEXICO              MC
    if (stristr($esta,"MORELIA")) $coes="MN";            // MICHOACAN           MN
    if (stristr($esta,"MORELOS")) $coes="MS";            // MORELOS             MS
    if (stristr($esta,"NAYARIT")) $coes="NT";            // NAYARIT             NT
    if (stristr($esta,"GARZA")) $coes="NL";              // NUEVO LEON          NL
    if (stristr($esta,"OAX")) $coes="OC";                // OAXACA              OC
    if (stristr($esta,"PUEBLA")) $coes="PL";             // PUEBLA              PL
    if (stristr($esta,"QUERETARO")) $coes="QT";          // QUERETARO           QT
    if (stristr($esta,"QUINTANA")) $coes="QR";           // QUINTANA ROO        QR
    if (stristr($esta,"SAN LUIS")) $coes="SP";           // SAN LUIS POTOSI     SP
    if (stristr($esta,"CULIACAN")) $coes="SL";           // SINALOA             SL
    if (stristr($esta,"HERMOSILLO")) $coes="SR";         // SONORA              SR
    if (stristr($esta,"VILLAHERMOSA")) $coes="TC";       // TABASCO             TC
    if (stristr($esta,"ALTAMIRA")) $coes="TS";           // TAMAULIPAS          TS
    if (stristr($esta,"TLAXCALA")) $coes="TL";           // TLAXCALA            TL
    if (stristr($esta,"CORDOBA")) $coes="VZ";            // VERACRUZ            VZ
    if (stristr($esta,"UMAN")) $coes="YN";               // YUCATÁN             YN
    if (stristr($esta,"ZACATECAS")) $coes="ZS";          // ZACATECAS           ZS
    return ($coes);
}
// }}}
// {{{ Convierte los caracteres no valides EDI a espacio (: + |) y or supuetso el '
 
function satxwalm_fix($str,$largo=-1) {
    $tmp = trim($str);
    for ($i=0;$i<strlen($tmp);$i++) {
        $a = ord($tmp{$i});
        if ($a < 32 || $a > 127) $tmp{$i} = "?";
    }
    $tmp = str_replace(array(":","+","|","'")," ",$tmp);
    if ($largo>0) $tmp = substr($tmp,0,$largo-1);
    return ($tmp);
}
// }}}
?>
Desafortunadamente esta funcion no puede ser muy general porque cada ERP es diferente y cada uno almacena y procesa la informacion de manera diferente. Si alguien quiere hacer un nivel de abstraccion superior que via metodos y propiedades cargue los datos para que le sirva a cualquiera les agradecere me informen.
Ejemplo de uso de la funcion
A continuacion esta un pequeño programa de 4 lineas que muestra como invocar esta funcion, ademas muestra un ejemplo de como regresa la informacion.
NOTA: La funcion regresa una sola cadena sin salto de lineas, la funcion str_replace cambia el delimitador de segmento standard (') por saltos de lineas para hacer mas amigable su revision.
1
2
3
4
5
6
<?php
require_once("lib/conecta.php");
require_once("satxinvo.php");
$edidata = satxinvo("XAFA591485");
echo str_replace("'","<br>",$edidata); 
?>
A continuacion esta un listado de lo que presenta el navegador al ejecutar el programa anterior:
UNA:+.?
UNB+UNOB:1+JABON-CORONA:ZZ+925485MX00:8+050330:1123+947
UNG+INVOIC+JABON-CORONA:ZZ+925485MX00:8+050330:1123+947+UN+D:01B:AMC002
UNH+947+INVOIC:D:01B:UN:AMC002
BGM+380+591485+9
DTM+137:20050810:102
FTX+ZZZ+++(DOSCIENTOS CATORCE MIL CIENTO TREINTA Y SEIS PESOS 12/100 M.N.)
RFF+ON:6388644155
DTM+171:20050809:102
RFF+BT:XAFA
RFF+ATZ:12345678
NAD+BY+7507003100001::9++NUEVA WAL MART DE MEXICO S DE RL DE:CV+NEXTENGO NO 78:SANTA CRUZ ACAYUCAN+AZCAPOTZALCO+DF+02770
RFF+GN:NWM9709244W4
NAD+SU+7504000065005::9++FABRICA DE JABON LA CORONA,SA DE CV+CARLOS B ZETINA NO 80+FRACC IND XALOSTOC+MC+55340
RFF+GN:FJC780315E91
RFF+IA:000227412
NAD+II+7504000065005::9++FABRICA DE JABON LA CORONA,SA DE CV+CARLOS B.ZETINA NO.80:COL INDUSTRIAL XALOSTOC+XALOSTOC, EDO. DE MEXICO+MC+55348
NAD+ST+7507003163884 ::9++C.D. CUATITLAN # 6388:NUEVA WAL-MART DE MEXICO, S RL CV+AV. TEJOCOTES S/N:FRACC,SN MARTIN OBISPO+CUAUTITLAN IZCALLI+MC+54769
CUX+2:MXN:4++1
PAT+1++5:3:D:30
PCD+12:0
LIN+1++0000075002343:EN::9
PIA+1+71017:SA
IMD+F++:::ACEITE 1 2 3 12 B 1 LT
QTY+47:1008:CA
QTY+59:12:EA
MOA+203:143323.49
PRI+AAA:142.18600198413::::CA
TAX+7+VAT+++:::0.0
MOA+124:0.0
LIN+2++0000075005443:EN::9
PIA+1+71018:SA
IMD+F++:::ACEITE 1 2 3 24 B 500 ML
QTY+47:252:CA
QTY+59:24:EA
MOA+203:36862.56
PRI+AAA:146.28::::CA
TAX+7+VAT+++:::0.0
MOA+124:0.0
LIN+3++0012005600017:EN::9
PIA+1+71019:SA
IMD+F++:::ACEITE 123 15B 1LT TRIPACK
QTY+47:189:CA
QTY+59:5:EA
MOA+203:33950.07
PRI+AAA:179.63::::CA
TAX+7+VAT+++:::0.0
MOA+124:0.0
UNS+S
CNT+11:1449
CNT+2:3
MOA+9:214136.12
MOA+79:214136.12
MOA+125:0.0
TAX+7+VAT+++:::0.0
MOA+124:0.0
UNT+54+947
UNE+4+947
UNZ+1+947
Ya con esta cadena se puede grabar un archivo, imprimirlo, grabarlo en un campo TEXT de su base de datos, etc. segun sus necesidades.