/* */

24 de agosto de 2007

Problema 6.3

pendiente de revisión

Enunciado
Una empresa telefónica requiere facturar a sus abonados el servicio de llamadas. Dispone de los siguientes archivos:

ABONADOS.DAT, ordenado por nro_abonado

  • nro_abonado - longint, número de abonado, 9 dígitos
  • nombre - string[35], nombre del abonado
  • domicilio - string[50], domicilio de facturación
  • id_categ - (código de categoría) integer, entre 1 y 45

LLAMADAS.DAT, ordenado por nro_abonado
  • nro_abonado
  • destino - string[5]
  • duracion - integer, expresada en minutos
  • fecha - integer, día del mes
El valor del campo destino será: "LOCAL" para las llamadas locales o el código de destino que corresponda para las llamadas de larga distancia e internacionales. Las llamadas corresponden a un único mes.

IMPORTES.DAT:
  • id_categ - integer
  • valor_minuto - real, importe básico

Se pide

1 - Desarrollar un programa que imprima la facturación para los clientes de la empresa que realizaron llamadas durante el mes en curso, con el siguiente formato.



2 - Generar un archivo ERRORES.dat con el mismo formato de registro que LLAMADAS.dat, con las llamadas realizadas por abonados no registrados como clientes de la empresa.

3 - Al finalizar el proceso emitir un listado discriminando la facturación según el destino y el día del mes. Considerar que a lo sumo pueden existir 200 destinos diferentes.


Análisis
Este es un problema de apareo de archivos. El archivo de movimientos es LLAMADAS.dat, el archivo "maestro" de abonados es ABONADOS.dat. También tenemos un archivo (o tabla) de consulta de importe (del minuto) por categoría: IMPORTES.dat.

Dado que solo existen 45 categorías, el archivo IMPORTES.dat lo subiremos a un array para agilizar las consultas.

Los archivos LLAMADAS.dat (mov) y ABONADOS.dat (mae) tendremos que recorrerlos simultaneamente. Ambos están ordenados por el mismo campo: nro_abonado por lo tanto si leemos mov y luego leemos mae podrán darse los siguientes casos:

Si mov.nro_abonado es mayor que mae.nro_abonado entonces el abonado leido en mae no registró ninguna llamada en el mes.
Si mov.nro_abonado es igual a mae.nro_abonado entonces el abonado realizó llamadas. Las tenemos que procesar con corte de control sobre mov.
Si mov.nro_abonado es menor que mae.nro_abonado entonces la llamada/s corresponde/n a un abonado inexistente. También, con corte de contról las procesamos para grabarlas en el archivo de errores.

Para el punto 3 del enunciado tendremos que tener una matríz [1..200,1..31]. 200 destinos (a lo sumo) por 31 días del mes para acumular los importes discriminados. También necesitaremos un array paralelo de 200 strings para saber a que destino corresponde cada fila de la matríz.



Veamos la sección type.
 1:
2:const
3: // cantidad maxima de destinos
4: MAX_DESTINOS = 200;
5:
6: // cantidad maxima de categorias
7: MAX_CATEGORIAS = 45;
8:
9:type
10: // registro de abonados
11: RAbonado = record
12: nro_abonado: longint;
13: nombre: string[35];
14: domicilio: string[50];
15: id_categ: integer;
16: end;
17:
18: // tipo de archivo de abonados (maestro)
19: FAbonados = file of RAbonado;
20:
21: // registro de llamadas
22: RLlamada = record
23: nro_abonado: longint;
24: destino: string[5];
25: duracion: integer;
26: fecha: longint;
27: end;
28:
29: // tipo de archivo de llamadas (movimientos)
30: FLlamadas = file of RLlamada;
31:
32: // tipo de archivo de errores
33: FErrores = file of RLlamada;
34:
35: // registro de importes x categoria
36: RImporte = record
37: id_categ: integer;
38: valor_minuto: real;
39: end;
40:
41: // tipo de archivo de importes x categoria
42: FImportes = file of RImporte;
43:
44: // tipo array para subir el archivo de importes
45: AImportes = array[1..MAX_CATEGORIAS] of RImporte;
46:
47: // matrix para discriminar los importes facturados
48: MFacturacion = array[1..MAX_DESTINOS,1..31] of real;
49:
50: // array paralelo a la matriz
51: ADestinos = array[1..MAX_DESTINOS] of string[5];
52:
53:

Según lo que analizamos anteriormente desarrollaremos el programa principal.




.
El programa comienza subiendo el archivo de importes por categoría al array arrImp. Luego invoca al procedimiento abrirArchivos en que que se abrirán con reset los archivos LLAMADAS.dat y ABONADOS.dat y con rewrite el archivo ERRORES.dat. También se inicializa la matriz con todos valores cero (en el procedimiento inicializarMatriz) ya que cada posición será utilizada como un acumulador.

Para leer utilizamos las funciones leerMae y leerMov tal como se explicó en el capítulo 6.

Luego comenzamos a desarrollar el apareo entre los archivos de llamadas y abonados (ambos ordenados por el campo id_abonado). Leemos los dos archivos y comparamos.

Si el abonado leido en mov es mayor al abonado leido en mae entonces el abonado leido en mae no registró llamadas y debemos avanzar al siguiente abonado.

Si el abonado leido en mov es igual al abonado leido en mae entonces debemos procesar (recorriendo mov con corte de control) las llamadas efectuadas por el abonado para emitir su factura.

Si el abonado leido en mov es menor que el abonado leido en mae significa que se trata de llamadas realizadas por un abonado inexistente. Las debemos registrar como errores en el archivo err.

Así iteramos mientras ninguno de los dos archivos llegue al final. Cuando alguno de los dos archivos llega al final terminamos de iterar y preguntamos cual terminó.

Si terminó el archivo mae entonces todas las llamadas que quedan por procesar corresponden a abonados inexistentes. En cambio, si primero terminó mov todos los abonados que quedan sin procesar no realizaron llamadas.

Por último imprimimos el listado discriminado por destino y mes que nos piden en el enunciado.

Veamos primero los procedimientos más simples.



En el procedimiento registrarError debemos recorrer con corte de control el archivo mov, mientras no cambie de abonado y grabar cada registro leido en el archivo err.



Notemos que cuando ingresamos al procedimiento el registro rMov con la primer llamada del abonado inexistente ya está leido. Por este motivo directamente lo grabamos y luego leemos el siguiente registro.

En procesarErrores tenemos que recorrer el archivo mov hasta el finál grabando cada registro en el archivo err.



Veamos ahora el procedimiento facturar.



En este procedimiento emitimos la factura para el abonado que realizó llamadas. Para esto obtenemos toda la información que debemos mostrar tomándola de los registros rMov, rMae y el importe por minuto lo tomamos del array de importes arrImp.

También tenemos que acumular en la matriz mFact en la fila/columna que corresponda. La columna está identificada por el día de la llamada. La fila corresponde la destino de la llamada. Recordemos que manejamos un array paralelo a las filas de la matriz en el que vamos a buscarEInsertar los diferentes destinos. La función buscarEInsertarDest retorna la posición en la que encontró (en el array aDest) o en la que insertó el destino correspondiente a esta llamada.

Solo queda analizar el procedimiento imprimirImpDiscriminados que recorre la matriz y el array paralelo e imprimir los importes acumulados por día y destino.








.


No hay comentarios: