Total de Ventas Agrupado por Cliente y Mes
Imaginemos que queremos calcular el total de ventas agrupado por cliente y por mes. La idea es obtener los totales mensuales para cada cliente usando una estructura de datos que combine defaultdict
y lambda
para crear diccionarios anidados.
Usamos defaultdict
para crear un diccionario de diccionarios donde cada cliente tiene un subdiccionario con el total de ventas para cada mes.
from collections import defaultdict
from odoo import models, fields, api
from datetime import datetime
class SalesReport(models.Model):
_name = 'sales.report'
_description = 'Sales Report Grouped by Client and Month'
@api.model
def calculate_sales_totals_by_client_and_month(self):
# Crear una estructura de defaultdict donde cada cliente tiene un
# defaultdict para meses
sales_totals = defaultdict(lambda: defaultdict(float))
# Obtener todas las facturas confirmadas
invoices = self.env['account.move'].search([
('state', '=', 'posted'),
('move_type', '=', 'out_invoice')
])
for invoice in invoices:
client_id = invoice.partner_id.id
amount = invoice.amount_total
# Obtener el mes de la factura en formato Año-Mes
invoice_date = fields.Date.from_string(invoice.invoice_date)
month_key = invoice_date.strftime('%Y-%m')
# Acumular ventas usando defaultdict con estructuras anidadas
sales_totals[client_id][month_key] += amount
# Salida mostrando las ventas totales por cliente y por mes
for client_id, monthly_totals in sales_totals.items():
print(f"\nCliente {client_id} - Totales Mensuales:")
for month, total in monthly_totals.items():
print(f" Mes {month}: Total de Ventas: {total}")
Usamos defaultdict(lambda: defaultdict(float))
, que crea automáticamente un subdiccionario defaultdict(float)
cada vez que un nuevo client_id
se encuentra. Esto permite agrupar fácilmente los montos de ventas por mes sin tener que verificar manualmente la existencia de la clave del mes para cada cliente.
Cada invoice se procesa extrayendo el client_id
y el amount_total
. Luego, se calcula el month_key en formato 'YYYY-MM'
usando strftime
, que será la clave para los totales de ventas mensuales.
En la línea sales_totals[client_id][month_key] += amount
, el uso de defaultdict
simplifica la operación, ya que los subdiccionarios de cada cliente se crean automáticamente y los valores de ventas se inicializan a 0.0.
Salida de ejemplo:
Cliente 1 - Totales Mensuales:
Mes 2024-01: Total de Ventas: 5000.0
Mes 2024-02: Total de Ventas: 3000.0
Cliente 2 - Totales Mensuales:
Mes 2024-01: Total de Ventas: 2000.0
Mes 2024-03: Total de Ventas: 4500.0
Beneficios del enfoque con defaultdict
Esta estructura es muy flexible y fácil de leer, y defaultdict
permite omitir verificaciones repetitivas. Esto es útil en casos de informes de ventas o análisis de datos donde necesitamos obtener agregaciones en múltiples niveles, como cliente y mes.