Ejercicio
Finanzas Domésticas
Objectivo
Desarrollar un programa Python que pueda almacenar hasta 10000 registros de gastos e ingresos para crear un pequeño sistema de contabilidad doméstica. Para cada gasto (o ingreso), se debe guardar la siguiente información:
• Fecha (8 caracteres: formato AAAAMMDD)
• Descripción del gasto o ingreso
• Categoría
• Monto (positivo para ingresos, negativo para gastos)
El programa debe permitir al usuario realizar las siguientes operaciones:
1 - Agregar un nuevo gasto (la fecha debe "parecer correcta": día 01 a 31, mes 01 a 12, año entre 1000 y 3000). La descripción no debe estar vacía. No es necesario validar los demás datos.
2 - Mostrar todos los gastos de una determinada categoría (por ejemplo, "educación") entre dos fechas específicas (por ejemplo, entre "20110101" y "20111231"). Muestra el número, la fecha (formato DD/MM/AAAA), la descripción, la categoría entre paréntesis y el importe con dos decimales, todo en la misma línea, separados por guiones. Al final, muestra el importe total de los datos mostrados.
3 - Busca gastos que contengan un texto determinado (en la descripción o categoría, sin distinguir entre mayúsculas y minúsculas). Muestra el número, la fecha y la descripción (truncados a 50 caracteres si son más largos). Notifica al usuario si no se encuentra ninguno.
4 - Modifica un registro (solicita al usuario el número de registro, muestra el valor anterior de cada campo y permite al usuario presionar Enter para dejar cualquier campo sin cambios). Advierte (pero no vuelve a preguntar) si el usuario ingresa un número de registro incorrecto. No es necesario validar ningún dato.
5 - Elimina registros, comenzando por el número ingresado por el usuario. Advierte (pero no vuelve a preguntar) si se ingresa un número incorrecto. Muestra el registro que se eliminará y solicita confirmación antes de eliminarlo.
6 - Ordenar los datos alfabéticamente por fecha y (si las fechas coinciden) por descripción.
7 - Normalizar las descripciones: eliminar los espacios finales y los espacios duplicados. Si una descripción está toda en mayúsculas, convertirla a minúsculas (excepto la primera letra, que permanece en mayúsculas).
P - Salir de la aplicación (como no almacenamos la información, los datos se perderán).
Ejemplo de ejercicio de Python
Mostrar código Python
import re
from datetime import datetime
# List to store records
records = []
# Loop for user interaction
while True:
# Show menu
print("\nMenu:")
print("1 - Add a new expense")
print("2 - Show all expenses of a category between two dates")
print("3 - Search for expenses containing a certain text")
print("4 - Modify a record")
print("5 - Delete records")
print("6 - Sort data")
print("7 - Normalize descriptions")
print("Q - Quit")
choice = input("Choose an option: ").strip().lower()
if choice == '1': # Add a new expense
date = input("Enter date (YYYYMMDD): ")
while True:
try:
datetime.strptime(date, "%Y%m%d")
break
except ValueError:
print("Invalid date format. Please enter a valid date (YYYYMMDD).")
date = input("Enter date (YYYYMMDD): ")
description = input("Enter description: ").strip()
while not description:
print("Description cannot be empty.")
description = input("Enter description: ").strip()
category = input("Enter category: ").strip()
amount = input("Enter amount (positive for income, negative for expense): ")
while not amount.replace('.', '', 1).isdigit() or float(amount) == 0:
print("Invalid amount. Enter a valid number (positive for income, negative for expense).")
amount = input("Enter amount (positive for income, negative for expense): ")
records.append({
'date': date,
'description': description,
'category': category,
'amount': float(amount)
})
elif choice == '2': # Show all expenses of a category between two dates
category = input("Enter category: ").strip()
start_date = input("Enter start date (YYYYMMDD): ")
end_date = input("Enter end date (YYYYMMDD): ")
while True:
try:
datetime.strptime(start_date, "%Y%m%d")
datetime.strptime(end_date, "%Y%m%d")
break
except ValueError:
print("Invalid date format. Please enter valid dates (YYYYMMDD).")
start_date = input("Enter start date (YYYYMMDD): ")
end_date = input("Enter end date (YYYYMMDD): ")
total_amount = 0.0
count = 0
for i, record in enumerate(records):
if record['category'].lower() == category.lower() and start_date <= record['date'] <= end_date:
print(f"{i+1} - {record['date'][6:8]}/{record['date'][4:6]}/{record['date'][:4]} - {record['description']} - ({record['category']}) - {record['amount']:.2f}")
total_amount += record['amount']
count += 1
if count > 0:
print(f"Total: {total_amount:.2f}")
else:
print("No records found.")
elif choice == '3': # Search for expenses containing a certain text
search_text = input("Enter the text to search for: ").strip().lower()
count = 0
for i, record in enumerate(records):
if search_text in record['description'].lower() or search_text in record['category'].lower():
print(f"{i+1} - {record['date'][6:8]}/{record['date'][4:6]}/{record['date'][:4]} - {record['description'][:50]}...")
count += 1
if count == 0:
print("No records found.")
elif choice == '4': # Modify a record
record_number = input("Enter record number to modify: ")
while not record_number.isdigit() or int(record_number) < 1 or int(record_number) > len(records):
print("Invalid record number.")
record_number = input("Enter record number to modify: ")
record_index = int(record_number) - 1
record = records[record_index]
print(f"Current record: {record['date']} - {record['description']} - {record['category']} - {record['amount']:.2f}")
date = input(f"Enter new date (current: {record['date']}): ").strip()
if date:
record['date'] = date
description = input(f"Enter new description (current: {record['description']}): ").strip()
if description:
record['description'] = description
category = input(f"Enter new category (current: {record['category']}): ").strip()
if category:
record['category'] = category
amount = input(f"Enter new amount (current: {record['amount']:.2f}): ").strip()
if amount:
record['amount'] = float(amount)
elif choice == '5': # Delete records
start_record = input("Enter starting record number to delete: ")
end_record = input("Enter ending record number to delete: ")
while not start_record.isdigit() or not end_record.isdigit() or int(start_record) > int(end_record) or int(start_record) < 1 or int(end_record) > len(records):
print("Invalid record numbers.")
start_record = input("Enter starting record number to delete: ")
end_record = input("Enter ending record number to delete: ")
for i in range(int(start_record) - 1, int(end_record)):
print(f"Deleting record: {records[i]}")
confirm = input("Are you sure? (y/n): ").strip().lower()
if confirm == 'y':
del records[i]
break
elif choice == '6': # Sort data
records.sort(key=lambda x: (x['date'], x['description'].lower()))
print("Records sorted.")
elif choice == '7': # Normalize descriptions
for record in records:
record['description'] = re.sub(' +', ' ', record['description']).strip()
if record['description'].isupper():
record['description'] = record['description'].capitalize()
print("Descriptions normalized.")
elif choice == 'q': # Quit
break
else:
print("Invalid choice. Please try again.")
Output
Case 1:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 1
Enter date (YYYYMMDD): 20231225
Enter description: Christmas gifts
Enter category: Gifts
Enter amount (positive for income, negative for expense): -200
Case 2:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 2
Enter category: Gifts
Enter start date (YYYYMMDD): 20231201
Enter end date (YYYYMM31): 20231231
1 - 25/12/2023 - Christmas gifts - (Gifts) - -200.00
Total: -200.00
Case 3:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 3
Enter the text to search for: gifts
1 - 25/12/2023 - Christmas gifts...
Case 4:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 4
Enter record number to modify: 1
Current record: 20231225 - Christmas gifts - Gifts - -200.00
Enter new date (current: 20231225):
Enter new description (current: Christmas gifts):
Enter new category (current: Gifts):
Enter new amount (current: -200.00):
Case 5:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 5
Enter starting record number to delete: 1
Enter ending record number to delete: 1
Deleting record: {'date': '20231225', 'description': 'Christmas gifts', 'category': 'Gifts', 'amount': -200.0}
Are you sure? (y/n): y
Case 6:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 6
Records sorted.
Case 7:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: 7
Descriptions normalized.
Case 8:
Menu:
1 - Add a new expense
2 - Show all expenses of a category between two dates
3 - Search for expenses containing a certain text
4 - Modify a record
5 - Delete records
6 - Sort data
7 - Normalize descriptions
Q - Quit
Choose an option: q
Código de ejemplo copiado
Comparte este ejercicio de Python