Page 1 of 1

dudas para crear documentos con cabecera y detalle

Posted: Thu Jan 26, 2006 9:22 pm
by lubin
Buen dia con todos....

la consulta es la siguiente: tengo el problema al desear generar un documento ejem. Factura que tiene cabecera (datos del Cliente con Gets) y detalle (relacion de Productos que es con un listbox) todo esto dentro de un cuadro de dialogo

Sucede que deseo llenar la cabecera y luego de tener _ obligatorios llenos con un click a un boton se genera el nuevo numero del documento correlativo XNRO_NEW="9999" y se habilita el Listbox del detalle el cual funciona con un un SELECT NRO_FA FOR XNRO_NEW el cual debe filtrar solo los detalles de la nueva factura Nr.9999,, he aqui donde nace el problema... cuando lleno el primer detalle y retorno a la ventana del documento el ListBox muestra otros registros, pese a haber cambiado del Filtro con el metodo SetFilter ..... oLbx:setfilter("FAC_DETA->NR_DOC", XNRO_NEW)

Un comentario adicional: para aliviar el problema temporalmente he tenido que hacer lo siguiente : antes de entrar a la ventana del Documento (que tiene la cebecera y detalle) preguntat si desea crear un docuemnto, y generar el Nro del nuevo documento y recien ingresar a la ventana ... ahi todo funciona ok....

Espero haberme explicado bien. les agradecere una luz .... en el camino..

Mil gracias



Lubin

Re: dudas para crear documentos con cabecera y detalle

Posted: Fri Jan 27, 2006 4:54 pm
by R.F.
Lubin:


Mas facil, mete un SCOPE en el detalle del documento y nunca tendras el problema de que "borre" el filtro.

detalle ->(OrdScope(0,XNRO_NEW))
detalle->(OrdScope(1,XNRO_NEW))

Y listo, todos los registros quedaran filtrado automaticamente.

OJO, esto solo aplica a indices CDX.

Posted: Sat Jan 28, 2006 1:19 am
by Willi Quintana
Hola, me parece que seria mejor que ya al momento de imprimir tu factura, tomes el numero que corresponda, pueda que otro usuario de la red tambien este facturando...

Salu2
Willi

Re: dudas para crear documentos con cabecera y detalle

Posted: Mon Jan 30, 2006 3:11 pm
by lubin
Rene , Gracias por la Respuesta, si bien es una alternativa, solo que aun estoy usando los indices NTX
De todas formas va pa mi libro , :-)


Lubin

RF wrote:Lubin:


Mas facil, mete un SCOPE en el detalle del documento y nunca tendras el problema de que "borre" el filtro.

detalle ->(OrdScope(0,XNRO_NEW))
detalle->(OrdScope(1,XNRO_NEW))

Y listo, todos los registros quedaran filtrado automaticamente.

OJO, esto solo aplica a indices CDX.

Posted: Mon Jan 30, 2006 3:21 pm
by lubin
Gracias Willi por la Respuesta

Pero quiza no me entendieron en algo, mi problema no es al imprimir las Factura si no al crear la Factura, pues tengo un control de correlativos de documentos que controla el bloqueo de los documentos (un Contador) el cual asigna el Nro de la Factura al Encabezado una vez que se ingresaron todos los datos de la cabecera (cliente, fecha,direccion, telefono), pasando al Listbox del Detalle, ahi es donde este listbox no funciona correctamente al agregar los items (productos) de la Factura.

de todos modos mil gracias,,, quizas puedas encender la luzzzz :wink:
Lubin

Posted: Fri Feb 03, 2006 2:01 am
by DanielPuente
Lubin:

Por un lado el set filter deberia funcionar, que browse usas ?. Yo no lo uso (uso scopes) pero por ejemplo para wbrowse la sintaxis es:

::SetFilter( cField, uVal1, uVal2 )

Por lo que en tu codigo te falta el limite "hasta" del filtro (tenes solo el "desde", aunque hay un:

DEFAULT uVal2 := uVal1

O sea que si el valor es el mismo de inicio y fin igual deberia funcionar.

oLbx:setfilter("FAC_DETA->NR_DOC", XNRO_NEW)

Si te fijas lo que hace ::Setfilter() en la clase para filtrar (ademas de contemplar el filtrado x indices, detectar si el rdd es cdx, ads y demas ) es modificar ::bGoTop, ::bGoBottom y ::bSkip. Eso significa que si tenes un indice x la expresion que queres filtrar podes hacer algo como esto incluso con indices ntx:

oBrw2:bGoTop := { || Inicio ( cFiltro, oBrw2 ) }

oBrw2:bGoBottom := { || Fin ( cFiltro, oBrw2 ) }

oBrw2:bSkip :={|n| Moveb("brow",cFiltro,n)}

oBrw2:bLogicLen := { || cCantReg }

FUNCTION Inicio( xKey, oBrw )
DBSEEK( xKey ) // Busca tu clave en la base y si la encuentra ahi es el inicio logico de tu browse
oBrw:Refresh()
return nil


FUNCTION Fin( xKey, oBrw )
DBSEEK( Ultima( xKey ), .T. )
DBSKIP( -1 ) // Busca el valor siguiente
oBrw:Refresh()
return nil

FUNCTION Ultima( xValue )
LOCAL cType := VALTYPE( xValue )
LOCAL xNext

DO CASE
CASE ( cType == "C" )
xValue := STUFF( xValue, LEN( xValue ), 1, ;
CHR( ASC( RIGHT( xValue, 1 ) ) + 1 ) )

CASE ( cType == "N" )
xValue++

CASE ( cType == "D" )
xValue++
ENDCASE
xNext := xValue
RETURN( xNext )

FUNCTION Moveb(cAlias,cKey,nReg)
LOCAL nNext:=0

IF nReg=0 .OR. (cAlias)->(LastRec())=0 .OR. !(&((cAlias)->(IndexKey(0)))=cKey)
(cAlias)->(DbSkip(0))
ELSEIF nReg>0 .AND. (cAlias)->(RecNo())<>(cAlias)->(LastRec())+1

DO WHILE nNext<=nReg .AND. !(cAlias)->(EoF()) .AND. &((cAlias)->(IndexKey(0)))=cKey

(cAlias)->(DbSkip())
nNext++
ENDDO
(cAlias)->(DbSkip(-1))
nNext--
ELSEIF nReg<0
DO WHILE nNext>=nReg .AND. !BOF() .AND. &((cAlias)->(IndexKey(0)))=cKey
(cAlias)->(DbSkip(-1))
nNext--
ENDDO
IF !BOF()
(cAlias)->(DbSkip())
ENDIF
nNext++
ENDIF
RETURN (nNext)


Todo esto siempre con wbrowse de Hernan Ceccarelli que es lo que yo uso. Buscate en dbwide el programa ca-windows del amigo Alfredo Arteaga que viene con parte del codigo fuente y aprenderas estas y unas cuantas cositas mas.

Otra cosa que podes hacer es usar un transitorio (cada terminal usa SU transitorio en su c: en forma exclusiva), donde guardas los registros de la factura previo dbzap() x cada factura y despues volcas los registros a la dbf. Y obviamente browseas esos registros del transitorio.


Saludos,

Posted: Fri Feb 03, 2006 4:21 pm
by lubin
Buen dia Daniel

Muchas gracias por el dato, esta respuesta bastante clara, seguro que puede aliviar mi dolor de cabeza, voy a analizarla y aplicarla, pues tambien he activado el Wbrowse de Hernan C..

Solo para redondear la idea, y aclarar el concepto del uso de scopes que mencionas, ¿estas son referidas a estas funciones (inicio,Fin, etc)?? , bueno te comentare que en clipper puro, yo tambien desarrolle mi propio browse que me resolvia algunos problemas que tenia con ese browse y tenia funciones parecidas a las tuyas, pero obviamente sin los conceptos de Objetos .... asi que yo pensaria poner tu aporte como partes de las funciones standares de las aplicaciones, y usarlas para los diversos documentos que a crear, pues po lo que veo son bastantes standarizadas y genericas. ten la seguridad que les contare los resultados..

estare en contacto.. !!

muchas gracias por ello ...

Lubin

DanielPuente wrote:Lubin:

Por un lado el set filter deberia funcionar, que browse usas ?. Yo no lo uso (uso scopes) pero por ejemplo para wbrowse la sintaxis es:

::SetFilter( cField, uVal1, uVal2 )

Por lo que en tu codigo te falta el limite "hasta" del filtro (tenes solo el "desde", aunque hay un:

DEFAULT uVal2 := uVal1

O sea que si el valor es el mismo de inicio y fin igual deberia funcionar.

oLbx:setfilter("FAC_DETA->NR_DOC", XNRO_NEW)

Si te fijas lo que hace ::Setfilter() en la clase para filtrar (ademas de contemplar el filtrado x indices, detectar si el rdd es cdx, ads y demas ) es modificar ::bGoTop, ::bGoBottom y ::bSkip. Eso significa que si tenes un indice x la expresion que queres filtrar podes hacer algo como esto incluso con indices ntx:

oBrw2:bGoTop := { || Inicio ( cFiltro, oBrw2 ) }

oBrw2:bGoBottom := { || Fin ( cFiltro, oBrw2 ) }

oBrw2:bSkip :={|n| Moveb("brow",cFiltro,n)}

oBrw2:bLogicLen := { || cCantReg }

FUNCTION Inicio( xKey, oBrw )
DBSEEK( xKey ) // Busca tu clave en la base y si la encuentra ahi es el inicio logico de tu browse
oBrw:Refresh()
return nil


FUNCTION Fin( xKey, oBrw )
DBSEEK( Ultima( xKey ), .T. )
DBSKIP( -1 ) // Busca el valor siguiente
oBrw:Refresh()
return nil

FUNCTION Ultima( xValue )
LOCAL cType := VALTYPE( xValue )
LOCAL xNext

DO CASE
CASE ( cType == "C" )
xValue := STUFF( xValue, LEN( xValue ), 1, ;
CHR( ASC( RIGHT( xValue, 1 ) ) + 1 ) )

CASE ( cType == "N" )
xValue++

CASE ( cType == "D" )
xValue++
ENDCASE
xNext := xValue
RETURN( xNext )

FUNCTION Moveb(cAlias,cKey,nReg)
LOCAL nNext:=0

IF nReg=0 .OR. (cAlias)->(LastRec())=0 .OR. !(&((cAlias)->(IndexKey(0)))=cKey)
(cAlias)->(DbSkip(0))
ELSEIF nReg>0 .AND. (cAlias)->(RecNo())<>(cAlias)->(LastRec())+1

DO WHILE nNext<=nReg .AND. !(cAlias)->(EoF()) .AND. &((cAlias)->(IndexKey(0)))=cKey

(cAlias)->(DbSkip())
nNext++
ENDDO
(cAlias)->(DbSkip(-1))
nNext--
ELSEIF nReg<0
DO WHILE nNext>=nReg .AND. !BOF() .AND. &((cAlias)->(IndexKey(0)))=cKey
(cAlias)->(DbSkip(-1))
nNext--
ENDDO
IF !BOF()
(cAlias)->(DbSkip())
ENDIF
nNext++
ENDIF
RETURN (nNext)


Todo esto siempre con wbrowse de Hernan Ceccarelli que es lo que yo uso. Buscate en dbwide el programa ca-windows del amigo Alfredo Arteaga que viene con parte del codigo fuente y aprenderas estas y unas cuantas cositas mas.

Otra cosa que podes hacer es usar un transitorio (cada terminal usa SU transitorio en su c: en forma exclusiva), donde guardas los registros de la factura previo dbzap() x cada factura y despues volcas los registros a la dbf. Y obviamente browseas esos registros del transitorio.


Saludos,