Iniciar Sesión

Ver la Versión Completa : [Duda] [AYUDA] reporte de ventas de local


Marengo97
23 de febrero de 2023, 04:22
Hola familia, aquí mi duda. Estoy realizando un programa como estudio donde registro ventas de productos de una tienda, el programa tiene que generar un reporte de las ventas realizadas para luego utilizarla en otro programa que aun no he hecho, mi duda es la siguiente, para hacerlo mas desafiante se me ocurrio que podria por medio de logica automatizar al programa para que pueda reconocer cuando un producto que se vendio se repite y asi en uno de los campos del archivo indexado (el reporte de ventas) vaya sumando la cantidad que se vendio de ese producto..y no se realmente si es posible algo así y no se como hacerlo o no es posible, estoy entre varias ideas pero que no llegan a ningun lado y apreciaría mucho una ayuda, espero se haya entendio lo que hace el programa y mi duda existencial :lamet:

Entre otras cosas tambien el programa genera un ticket para el cliente, esa parte aun no llegue porque estoy estancado en el reporte.

E aqui el código, cualquier consejo o mejora que pueda aplicar seria genial porque soy un principiante aun en esto :) hasta ahora me han ayudado mucho en esta comunidad y he mejorado gracias a eso!
IDENTIFICATION DIVISION.
PROGRAM-ID. VENTAS-LOCAL.

DATE-WRITTEN. 19/2/2023.
AUTHOR. LUCAS GALEANO.

ENVIRONMENT DIVISION.

INPUT-OUTPUT SECTION.

FILE-CONTROL.
SELECT REPORTE-VENTAS ASSIGN TO "VENTAS.DAT"
ORGANIZATION IS INDEXED
ACCESS MODE IS DYNAMIC
RECORD KEY IS ID-PRODUCTO.

SELECT STOCK-MAESTRO ASSIGN TO "STOCK-MAESTRO.DAT"
ORGANIZATION IS INDEXED
ACCESS MODE IS DYNAMIC
RECORD KEY IS LLAVE-NUMERO-PRODUCTO.

SELECT TICKET ASSIGN TO "TICKET.DAT"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.

FILE SECTION.

FD REPORTE-VENTAS.

01 VENTA.
05 LLAVE-VENTAS.
10 ID-PRODUCTO PIC 9(2).
05 NOMBRE PIC X(20).
05 U-VENDIDAS PIC 9(2).
05 PRECIO-BASE PIC 9(4).

FD STOCK-MAESTRO.

01 LLAVE.
05 LLAVE-NUMERO-PRODUCTO PIC 9(2).
01 REG-PRODUCTOS.
05 NOMBRE-PRO PIC X(20).
05 CANTIDAD-INICIAL PIC 9(3).
05 ENTRADA PIC 9(3).
05 SALIDA PIC 9(3).
05 TOTAL PIC 9(3).
05 VALOR-VENTA PIC 9(5).
FD TICKET.

01 TICKET-DATOS.
05 TABLA OCCURS 100.
10 CANTIDAD PIC 9(2).
10 NOMBRE-PRO-T PIC X(20).
10 PRECIO PIC 9(5).
10 TOTAL-T PIC 9(5).
10 RECIBIMOS PIC 9(5).
10 VUELTO PIC 9(5).

WORKING-STORAGE SECTION.

*>************************************************** *********************
*> * MENU INTERFAZ *
*>************************************************** *********************
01 WS-TITULO.
05 FILLER PIC X(38).
05 FILLER PIC X(4) VALUE "MENU".
05 FILLER PIC X(38).

01 WS-OPC-1.
05 FILLER PIC X(36) VALUE SPACES.
05 FILLER PIC X(17) VALUE "1.REGISTRAR VENTA".
05 FILLER PIC X(36) VALUE SPACES.
01 WS-OPC-2.
05 FILLER PIC X(36) VALUE SPACES.
05 FILLER PIC X(17) VALUE "2.PROCESAR TICKET".
05 FILLER PIC X(36) VALUE SPACES.
01 WS-OPC-3.
05 FILLER PIC X(36) VALUE SPACES.
05 FILLER PIC X(17) VALUE "3.IMPRIMIR TICKET".
05 FILLER PIC X(36) VALUE SPACES.

01 WS-OPC-0.
05 FILLER PIC X(36) VALUE SPACES.
05 FILLER PIC X(7) VALUE "0.SALIR.".
05 FILLER PIC X(36) VALUE SPACES.

*>************************************************** *********************
*>* TICKET *
*>************************************************** *********************

01 WS-COLUMNA1.
05 FILLER PIC X(10) VALUE SPACES.
05 FILLER PIC X(59) VALUE ALL "=".
05 FILLER PIC X(10) VALUE SPACES.



01 WS-COLUMNA2.
05 FILLER PIC X(10) VALUE SPACES.
05 FILLER PIC X(59) VALUE ALL "=".
05 FILLER PIC X(10) VALUE SPACES.

01 WS-LINEA-PRODUCTO.
05 FILLER PIC X(15) VALUE SPACES.
05 WS-CANTIDAD PIC 9(2).
05 WS-NOMBRE-PRO PIC X(20).
05 FILLER PIC X(30) VALUE SPACES.
05 WS-PRECIO PIC 9(5).
05 FILLER PIC X(15) VALUE SPACES.

01 WS-LINEA-TOTAL.
05 FILLER PIC X(37).
05 FILLER PIC X(7) VALUE "TOTAL: ".
05 WS-TOTAL PIC 9(5).
05 FILLER PIC X(37).

01 WS-LINEA-RECIBO.
05 FILLER PIC X(34).
05 FILLER PIC X(11) VALUE "RECIBIMOS: ".
05 WS-RECIBIMOS PIC 9(5).
05 FILLER PIC X(34).

01 WS-LINEA-VUELTO.
05 FILLER PIC X(36).
05 FILLER PIC X(8) VALUE "VUELTO: ".
05 WS-VUELTO PIC 9(5).
05 FILLER PIC X(36).

77 WS-TERMINAR-PROG PIC X(2) VALUE "NO".
77 WS-CONTINUAR PIC X(2) VALUE "SI".
77 WS-REG-EXISTE PIC X VALUE "T".
77 WS-OPC PIC 9.

PROCEDURE DIVISION.

010-MENU.
OPEN OUTPUT REPORTE-VENTAS.
OPEN I-O STOCK-MAESTRO.
OPEN OUTPUT TICKET.
PERFORM UNTIL WS-TERMINAR-PROG = "SI"
DISPLAY WS-TITULO
DISPLAY " "
DISPLAY WS-OPC-1
DISPLAY " "
DISPLAY WS-OPC-2
DISPLAY " "
DISPLAY WS-OPC-3
DISPLAY " "
DISPLAY WS-OPC-0
ACCEPT WS-OPC
EVALUATE WS-OPC
WHEN 1 PERFORM 020-REGISTRAR-VENTA
WHEN 2 PERFORM PROCESAR-TICKET
WHEN 3 PERFORM IMPRIMIR-TICKET
WHEN 0 MOVE "SI" TO WS-TERMINAR-PROG
END-EVALUATE
END-PERFORM.
CLOSE REPORTE-VENTAS.
CLOSE STOCK-MAESTRO.
CLOSE TICKET.
STOP RUN.

020-REGISTRAR-VENTA.
PERFORM UNTIL WS-CONTINUAR = "NO"
DISPLAY "INGRESE ID DEL PRODUCTO: " WITH NO ADVANCING
ACCEPT LLAVE-NUMERO-PRODUCTO
READ STOCK-MAESTRO
INVALID KEY MOVE "F" TO WS-REG-EXISTE
END-READ
IF WS-REG-EXISTE = "F" THEN
DISPLAY " "
DISPLAY "PRODUCTO FUERA DE STOCK."
ELSE
DISPLAY " "
DISPLAY "PRODUCTO: " WITH NO ADVANCING
DISPLAY NOMBRE-PRO WITH NO ADVANCING
DISPLAY "STOCK: " WITH NO ADVANCING
DISPLAY TOTAL WITH NO ADVANCING
DISPLAY "PRECIO: " WITH NO ADVANCING
DISPLAY VALOR-VENTA
DISPLAY " "
DISPLAY "INGRESE EL MES ACTUAL: " WITH NO ADVANCING
MOVE LLAVE-NUMERO-PRODUCTO TO ID-PRODUCTO
MOVE NOMBRE-PRO TO NOMBRE
WRITE VENTA

JCantero
23 de febrero de 2023, 11:00
@Marengo97, efectivamente esa seria la idea.

Observación1. Lo primero es que al realizar la venta, no solo tendrias que ver si existe el producto o no, sino tambien que tengas stock para venderlo.

Observación2. En la FD de ventas no necesitas tener la descripción pues hay que evitar los campos duplicados.

Y entrando en tu duda, tienes que inicializar registro de VENTA, leer REPORTE-VENTA, incrementar el numero de elementos vendidos, si NO existia WRITE VESTAS, si existia REWRITE VENTAS

Para esto ultimo necesitas un "file status", para reconocer si un registro existe o no.

Te recomiendo que le eches un vistazo al post de FPAIX: [Información] Ejemplos de manejo de archivos y tecla de funcion (https://www.cobolforo.es/showthread.php?1594-Ejemplos-de-manejo-de-archivos-y-tecla-de-funcion)

En el hace un mantenimiento de un fichero indexado. Dedicale tiempo y pregunta lo que no entiendas.

Para hacer lo que tu quieres necesitas añadir estas cosas:

en SELECT


SELECT REPORTE-VENTAS ASSIGN TO "VENTAS.DAT"
ORGANIZATION IS INDEXED
ACCESS MODE IS DYNAMIC
RECORD KEY IS ID-PRODUCTO
FILE STATUS FS-REPORTE-VENTAS.


en WORKING ( para hacerlo bien, al abrir el fichero (open i-o) hay que preguntar si f-noexiste-REPORTE-VENTAS (ya que metera un 35 en el file status)y si no permitir crearlo y hacer (open output), cuando leas preguntar esta-REPORTE-VENTAS para despues hacer un write o rewrite)


01 FS-REPORTE-VENTAS PIC XX.
88 esta-REPORTE-VENTAS value '00' '02'.
88 n-esta-REPORTE-VENTAS value '23'.
88 fin-REPORTE-VENTAS value '46' '10'.
88 bloqueado-REPORTE-VENTAS value '99' '90'.
88 f-bloqueado-REPORTE-VENTAS value '38' '93'.
88 f-noexiste-REPORTE-VENTAS value '35'.


En PROCEDURE


PROCEDURE DIVISION.
DECLARATIVES.
File-Error SECTION.
USE AFTER STANDARD ERROR PROCEDURE ON reporte-ventas.
END DECLARATIVES.


ante de hacer el write ventas:

initialize venta
MOVE LLAVE-NUMERO-PRODUCTO TO ID-PRODUCTO
read reporte-ventas end-read
add unidades-vendidas to u-vendidas
if esta-REPORTE-VENTAS then
rewrite venta end-rewrite
else
write venta end-write
end-if.


y si lo quieres multiproceso tienes que controlar que este bloqueado el registro venta pero esto ya es afinar muchos


initialize venta
MOVE LLAVE-NUMERO-PRODUCTO TO ID-PRODUCTO
perform test after until not bloqueado-REPORTE-VENTAS
read reporte-ventas end-read
if bloqueado-REPORTE-VENTAS then
display 'Registro bloqueado. Pulse intro para reintentar'
accept ws-continuar
end-if
end-perform
add unidades-vendidas to u-vendidas
if esta-REPORTE-VENTAS then
rewrite venta end-rewrite
else
write venta end-write
end-if.


Pregunta lo que no entiendas, pero revisa el link que te he puesto.

JCantero
23 de febrero de 2023, 12:11
Se me olvidaba, reporte-ventas debe estar abierto i-o, si deseas inicializar el fichero cada vez:


open output reporte-ventas.
close reporte-ventas.
open i-o reporte-ventas.

Marengo97
25 de febrero de 2023, 01:32
@Marengo97, efectivamente esa seria la idea.

Observación1. Lo primero es que al realizar la venta, no solo tendrias que ver si existe el producto o no, sino tambien que tengas stock para venderlo.

Observación2. En la FD de ventas no necesitas tener la descripción pues hay que evitar los campos duplicados.

Y entrando en tu duda, tienes que inicializar registro de VENTA, leer REPORTE-VENTA, incrementar el numero de elementos vendidos, si NO existia WRITE VESTAS, si existia REWRITE VENTAS

Para esto ultimo necesitas un "file status", para reconocer si un registro existe o no.

Te recomiendo que le eches un vistazo al post de FPAIX: [Información] Ejemplos de manejo de archivos y tecla de funcion (https://www.cobolforo.es/showthread.php?1594-Ejemplos-de-manejo-de-archivos-y-tecla-de-funcion)

En el hace un mantenimiento de un fichero indexado. Dedicale tiempo y pregunta lo que no entiendas.

Para hacer lo que tu quieres necesitas añadir estas cosas:

en SELECT


SELECT REPORTE-VENTAS ASSIGN TO "VENTAS.DAT"
ORGANIZATION IS INDEXED
ACCESS MODE IS DYNAMIC
RECORD KEY IS ID-PRODUCTO
FILE STATUS FS-REPORTE-VENTAS.


en WORKING ( para hacerlo bien, al abrir el fichero (open i-o) hay que preguntar si f-noexiste-REPORTE-VENTAS (ya que metera un 35 en el file status)y si no permitir crearlo y hacer (open output), cuando leas preguntar esta-REPORTE-VENTAS para despues hacer un write o rewrite)


01 FS-REPORTE-VENTAS PIC XX.
88 esta-REPORTE-VENTAS value '00' '02'.
88 n-esta-REPORTE-VENTAS value '23'.
88 fin-REPORTE-VENTAS value '46' '10'.
88 bloqueado-REPORTE-VENTAS value '99' '90'.
88 f-bloqueado-REPORTE-VENTAS value '38' '93'.
88 f-noexiste-REPORTE-VENTAS value '35'.


En PROCEDURE


PROCEDURE DIVISION.
DECLARATIVES.
File-Error SECTION.
USE AFTER STANDARD ERROR PROCEDURE ON reporte-ventas.
END DECLARATIVES.


ante de hacer el write ventas:

initialize venta
MOVE LLAVE-NUMERO-PRODUCTO TO ID-PRODUCTO
read reporte-ventas end-read
add unidades-vendidas to u-vendidas
if esta-REPORTE-VENTAS then
rewrite venta end-rewrite
else
write venta end-write
end-if.


y si lo quieres multiproceso tienes que controlar que este bloqueado el registro venta pero esto ya es afinar muchos


initialize venta
MOVE LLAVE-NUMERO-PRODUCTO TO ID-PRODUCTO
perform test after until not bloqueado-REPORTE-VENTAS
read reporte-ventas end-read
if bloqueado-REPORTE-VENTAS then
display 'Registro bloqueado. Pulse intro para reintentar'
accept ws-continuar
end-if
end-perform
add unidades-vendidas to u-vendidas
if esta-REPORTE-VENTAS then
rewrite venta end-rewrite
else
write venta end-write
end-if.


Pregunta lo que no entiendas, pero revisa el link que te he puesto.

Estuve analizando el programa que me pasaste y la verdad es muy bueno, tiene varias cosas que agarrar como ejemplo, aunque es dificil de leer a veces, digamos que lo entendi en su mayoria excepto algunas cosas, si te parece puedo preguntarte sobre esto en relacion con mi programa por privado asi no hacer del posteo algo muy extenso.

Igual aprovecho para preguntarte sobre el FD reporte-ventas, segun me dijiste es mejor que solo declare su longitud total y ya, para evitar campos duplicados, podrias explicarme mas por que es mejor hacerlo así?, capaz es evidente la respuesta pero a veces teng esos dilemas si usar la working-storage o trabajar mas desde el FD, ahora yo removi los campos del FD pero, ¿si no declaro la llave del archivo que hago?, o puedo eliminar todos los demas campos del Fd excepto el de la llave?

Marengo97
25 de febrero de 2023, 08:14
Mirá, probé utilizando tablas, ya a estas alturas estoy experimentando y estoy incluso mas perdido el output me sale asi:
00 01 00000
No me suma la cantidad de unidades vendidas (ws-u-vendidas) no importa cuantas veces repita y por algun motivo me muestra el nombre en espacios...estoy perdiendo la cordura :yoquese: jaja
y encima estoy lidiendo con el error "not numeric" constantemente por los espacios que pasan con el MOVE.
REGISTRAR-VENTA.
PERFORM varying I from 1 by 1 until WS-CONTINUAR
equals "n" or
I > 100
INITIALIZE REG-PRODUCTOS LLAVE WS-VENTA
DISPLAY "INGRESE ID DEL PRODUCTO: " WITH NO ADVANCING
ACCEPT LLAVE-NUMERO-PRODUCTO
MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-AUX
READ STOCK-MAESTRO
INVALID KEY MOVE "F" TO WS-REG-EXISTE
END-READ
IF WS-REG-EXISTE = "F" THEN
DISPLAY " "
DISPLAY "PRODUCTO FUERA DE STOCK."
ELSE
DISPLAY "INGRESE EL MES ACTUAL: " WITH NO ADVANCING
ACCEPT WS-MES(I)

MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-PRODUCTO(I)
MOVE NOMBRE-PRO TO WS-NOMBRE(I)
COMPUTE VALOR-VENTA = FUNCTION NUMVAL(VALOR-VENTA)
MOVE VALOR-VENTA TO WS-PRECIO-BASE(I)

SEARCH ALL WS-TABLA

AT END MOVE "T" TO WS-REG-EXISTE
WHEN WS-ID-PRODUCTO(I) = WS-AUX-INDICE

COMPUTE WS-U-VENDIDAS(I) = WS-U-VENDIDAS(I)+ 1
DISPLAY "SE ACTUALIZÓ EL REGISTRO."
DISPLAY WS-TABLA(I)
END-SEARCH
END-PERFORM.


- - - Updated - - -

Cita de mi comentario: Uso las tablas porque borre la descripcion de FD como me habias aconsejado por lo tanto paso los datos por una tabla y luego habrian de ser escritas en el reporte-ventas.

JCantero
25 de febrero de 2023, 17:57
@Marengo97, la sugerencia de no repetir campos era porque nombre lo puedes leer de stock-maestro.

El problema que veo en la reforma que has hecho es que debes marcar lo que hay que ejecutar despues del else. Eso se hace con end-if.


REGISTRAR-VENTA.
PERFORM varying I from 1 by 1 until WS-CONTINUAR
equals "n" or
I > 100
INITIALIZE REG-PRODUCTOS LLAVE WS-VENTA
DISPLAY "INGRESE ID DEL PRODUCTO: " WITH NO ADVANCING
ACCEPT LLAVE-NUMERO-PRODUCTO
MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-AUX
READ STOCK-MAESTRO
INVALID KEY MOVE "F" TO WS-REG-EXISTE
END-READ
IF WS-REG-EXISTE = "F" THEN
DISPLAY " "
DISPLAY "PRODUCTO FUERA DE STOCK."
ELSE
DISPLAY "INGRESE EL MES ACTUAL: " WITH NO ADVANCING
ACCEPT WS-MES(I)

MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-PRODUCTO(I)
MOVE NOMBRE-PRO TO WS-NOMBRE(I)
COMPUTE VALOR-VENTA = FUNCTION NUMVAL(VALOR-VENTA)
MOVE VALOR-VENTA TO WS-PRECIO-BASE(I)
SEARCH ALL WS-TABLA

AT END MOVE "T" TO WS-REG-EXISTE
WHEN WS-ID-PRODUCTO(I) = WS-AUX-INDICE

COMPUTE WS-U-VENDIDAS(I) = WS-U-VENDIDAS(I)+ 1
DISPLAY "SE ACTUALIZÓ EL REGISTRO."
DISPLAY WS-TABLA(I)
END-SEARCH
end-if
END-PERFORM.

Marengo97
25 de febrero de 2023, 18:49
@Marengo97, la sugerencia de no repetir campos era porque nombre lo puedes leer de stock-maestro.

El problema que veo en la reforma que has hecho es que debes marcar lo que hay que ejecutar despues del else. Eso se hace con end-if.


REGISTRAR-VENTA.
PERFORM varying I from 1 by 1 until WS-CONTINUAR
equals "n" or
I > 100
INITIALIZE REG-PRODUCTOS LLAVE WS-VENTA
DISPLAY "INGRESE ID DEL PRODUCTO: " WITH NO ADVANCING
ACCEPT LLAVE-NUMERO-PRODUCTO
MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-AUX
READ STOCK-MAESTRO
INVALID KEY MOVE "F" TO WS-REG-EXISTE
END-READ
IF WS-REG-EXISTE = "F" THEN
DISPLAY " "
DISPLAY "PRODUCTO FUERA DE STOCK."
ELSE
DISPLAY "INGRESE EL MES ACTUAL: " WITH NO ADVANCING
ACCEPT WS-MES(I)

MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-PRODUCTO(I)
MOVE NOMBRE-PRO TO WS-NOMBRE(I)
COMPUTE VALOR-VENTA = FUNCTION NUMVAL(VALOR-VENTA)
MOVE VALOR-VENTA TO WS-PRECIO-BASE(I)
SEARCH ALL WS-TABLA

AT END MOVE "T" TO WS-REG-EXISTE
WHEN WS-ID-PRODUCTO(I) = WS-AUX-INDICE

COMPUTE WS-U-VENDIDAS(I) = WS-U-VENDIDAS(I)+ 1
DISPLAY "SE ACTUALIZÓ EL REGISTRO."
DISPLAY WS-TABLA(I)
END-SEARCH
end-if
END-PERFORM.


No habia notado que olvide poner el end-if, pero aun con el end-if sucede lo mismo, no suma las unidades vendidas y el campo de nombre del producto lo muestra en espacios vacios.

- - - Updated - - -

@Marengo97, la sugerencia de no repetir campos era porque nombre lo puedes leer de stock-maestro.

El problema que veo en la reforma que has hecho es que debes marcar lo que hay que ejecutar despues del else. Eso se hace con end-if.


REGISTRAR-VENTA.
PERFORM varying I from 1 by 1 until WS-CONTINUAR
equals "n" or
I > 100
INITIALIZE REG-PRODUCTOS LLAVE WS-VENTA
DISPLAY "INGRESE ID DEL PRODUCTO: " WITH NO ADVANCING
ACCEPT LLAVE-NUMERO-PRODUCTO
MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-AUX
READ STOCK-MAESTRO
INVALID KEY MOVE "F" TO WS-REG-EXISTE
END-READ
IF WS-REG-EXISTE = "F" THEN
DISPLAY " "
DISPLAY "PRODUCTO FUERA DE STOCK."
ELSE
DISPLAY "INGRESE EL MES ACTUAL: " WITH NO ADVANCING
ACCEPT WS-MES(I)

MOVE LLAVE-NUMERO-PRODUCTO TO WS-ID-PRODUCTO(I)
MOVE NOMBRE-PRO TO WS-NOMBRE(I)
COMPUTE VALOR-VENTA = FUNCTION NUMVAL(VALOR-VENTA)
MOVE VALOR-VENTA TO WS-PRECIO-BASE(I)
SEARCH ALL WS-TABLA

AT END MOVE "T" TO WS-REG-EXISTE
WHEN WS-ID-PRODUCTO(I) = WS-AUX-INDICE

COMPUTE WS-U-VENDIDAS(I) = WS-U-VENDIDAS(I)+ 1
DISPLAY "SE ACTUALIZÓ EL REGISTRO."
DISPLAY WS-TABLA(I)
END-SEARCH
end-if
END-PERFORM.


Podrias mostrarme como quedaria la FD de reporte-ventas segun lo que me indicas?, no logro ver como es que deberia de quedar.

JCantero
25 de febrero de 2023, 22:46
@Marengo97, lo de la FD era una sugerencia. Dejalo asi aunque este duplicado y cuando vayas aumentando el nivel lo vemos