def dias_de_deposito_events(begin, end): """ Eventos que mostram a quantia que se espera que as bandeiras depositem referente a pagamentos com cartão. """ pagamentos = PagamentoComCartao.objects.filter( data_do_deposito__range=(begin, end)) dias = {} for p in pagamentos: dias.setdefault(p.data_do_deposito, []).append(p) for data, pagamentos in dias.items(): valor_total = sum((p.valor - p.taxa) for p in pagamentos) nome = u"Entrada dos cartões: R$ {0}".format( format_currency(valor_total)) descricao = "\n".join( u"R$ ({pgto} - {taxa}), {bandeira}, {data}".format( bandeira=p.bandeira, pgto=format_currency(p.valor), taxa=format_currency(p.taxa), data=format_date(p.venda.dia.data)) for p in pagamentos) yield Event(data, nome, descricao)
def colorir_num(input): """Recebe um número e retorna o número marcado com a classe 'pos' se for positivo, ou 'neg' se for negativo.""" try: if input > 0: s = 'R$ <span class="pos">%s</span>' % (format_currency(input)) elif input == 0: s = 'R$ %s' % (format_currency(input)) else: s = 'R$ <span class="neg">%s</span>' % (format_currency(input)) return mark_safe(s) except (ValueError, TypeError): return input
def colorir_num(input): """Recebe um número e retorna o número marcado com a classe 'pos' se for positivo, ou 'neg' se for negativo.""" try: if input > 0: s = 'R$ <span class="pos">%s</span>' % (format_currency(input)) elif input == 0: s = 'R$ %s' % (format_currency(input)) else: s = 'R$ <span class="neg">%s</span>' % (format_currency(input)) return mark_safe(s) except (ValueError, TypeError): return input
def pgtos_por_bandeira(dias): pgtos = PagamentoComCartao.objects.filter(venda__dia__in=dias) agrupado = {} for pgto in pgtos: key = (pgto.bandeira.nome) somar_dict(agrupado, key, { "pagamentos": 1, "entrada": pgto.valor, }) dados = [] for grupo in agrupado.keys(): row = {} row["bandeira"] = grupo row["pagamentos"] = agrupado[grupo]["pagamentos"] row["entrada"] = format_currency(agrupado[grupo]["entrada"]) dados.append(row) headers = ("bandeira", "pagamentos", "entrada") body = [[row[col] for col in headers] for row in dados] return { "title": "Pagamentos com cartão por bandeira", "headers": headers, "body": body }
def pgtos_por_bandeira(dias): pgtos = PagamentoComCartao.objects.filter(venda__dia__in=dias) agrupado = {} for pgto in pgtos: key = (pgto.bandeira.nome) somar_dict(agrupado, key, { "pagamentos": 1, "entrada": pgto.valor, }) dados = [] for grupo in agrupado.keys(): row = {} row["bandeira"] = grupo row["pagamentos"] = agrupado[grupo]["pagamentos"] row["entrada"] = format_currency(agrupado[grupo]["entrada"]) dados.append(row) headers = ("bandeira", "pagamentos", "entrada") body = [[row[col] for col in headers] for row in dados] return { "title": "Pagamentos com cartão por bandeira", "headers": headers, "body": body }
def vendas_por_dia_da_semana(dias): vendas = Venda.objects.filter(dia__in=dias) agrupado = {} for venda in vendas: key = venda.dia.categoria_semanal() somar_dict(agrupado, key, { "vendas": 1, "entrada": venda.conta, "pessoas": venda.num_pessoas, "permanencia_media": venda.permanencia }) dados = [] headers = ("categoria_semanal", "vendas", "entrada", "pessoas", "permanencia_media") for grupo in agrupado.keys(): row = {} row["categoria_semanal"] = grupo for i, header in enumerate(headers[1:]): row[header] = agrupado[grupo][header] row["entrada"] = format_currency(row["entrada"]) if row["permanencia_media"]: row["permanencia_media"] = secs_to_time(row["permanencia_media"] / row["vendas"]) else: row["permanencia_media"] = 0 dados.append(row) body = [[row[col] for col in headers] for row in dados] return { "title": "Vendas por dia de semana", "headers": headers, "body": body }
def vendas_por_mesa(dias): def split_and_strip(string, sep=","): """Splits a string using `sep` as a separator, and strips whitespace from the splitted results.""" return map(lambda s: s.strip(), string.split(sep)) def primeira_mesa(mesas): try: return int(split_and_strip(mesas)[0]) except: return split_and_strip(mesas)[0] vendas = Venda.objects.filter(dia__in=dias) agrupado = vendas.values("mesa").order_by("mesa") dados = agrupado.annotate(vendas=Count("id"), entrada=Sum("conta"), pessoas=Sum("num_pessoas"), permanencia_media=Avg("permanencia")) headers = ("mesa", "vendas", "entrada", "pessoas", "permanencia_media") for row in dados: row["permanencia_media"] = secs_to_time(row["permanencia_media"]) row["entrada"] = format_currency(row["entrada"]) row["mesa"] = row["mesa"].replace("/", ",") body = [[row[col] for col in headers] for row in dados] body.sort(key=lambda row: primeira_mesa(row[0])) return { "title": "Vendas por mesa", "headers": headers, "body": body }
def vendas_por_mesa(dias): def split_and_strip(string, sep=","): """Splits a string using `sep` as a separator, and strips whitespace from the splitted results.""" return map(lambda s: s.strip(), string.split(sep)) def primeira_mesa(mesas): try: return int(split_and_strip(mesas)[0]) except: return split_and_strip(mesas)[0] vendas = Venda.objects.filter(dia__in=dias) agrupado = vendas.values("mesa").order_by("mesa") dados = agrupado.annotate(vendas=Count("id"), entrada=Sum("conta"), pessoas=Sum("num_pessoas"), permanencia_media=Avg("permanencia")) headers = ("mesa", "vendas", "entrada", "pessoas", "permanencia_media") for row in dados: row["permanencia_media"] = secs_to_time(row["permanencia_media"]) row["entrada"] = format_currency(row["entrada"]) row["mesa"] = row["mesa"].replace("/", ",") body = [[row[col] for col in headers] for row in dados] body.sort(key=lambda row: primeira_mesa(row[0])) return {"title": "Vendas por mesa", "headers": headers, "body": body}
def colorir_num_inverso(input): """Recebe um número e retorna o número marcado com a classe 'neg' se for positivo, ou 'pos' se for negativo -- ou seja, colore ele ao contrário do usual. Usado no mostrador de 10% a pagar -- que é bom se estiver negativo.""" try: if input > 0: s = 'R$ <span class="neg">%s</span>' % (format_currency(input)) elif input == 0: s = 'R$ %s' % (format_currency(input)) else: s = 'R$ <span class="pos">%s</span>' % (format_currency(input)) return mark_safe(s) except (ValueError, TypeError): return input
def colorir_num_inverso(input): """Recebe um número e retorna o número marcado com a classe 'neg' se for positivo, ou 'pos' se for negativo -- ou seja, colore ele ao contrário do usual. Usado no mostrador de 10% a pagar -- que é bom se estiver negativo.""" try: if input > 0: s = 'R$ <span class="neg">%s</span>' % (format_currency(input)) elif input == 0: s = 'R$ %s' % (format_currency(input)) else: s = 'R$ <span class="pos">%s</span>' % (format_currency(input)) return mark_safe(s) except (ValueError, TypeError): return input
def autolabel(ax, rects): """ Rotula cada uma das barras com seu valor correspondente (ie total de despesas do mês) """ for rect in rects: height = rect.get_height() text_x = rect.get_x() + rect.get_width() / 2.0 if rect.get_y() < 0: text_y = -1 * (height + 900) else: text_y = height + 400 ax.text(text_x, text_y, "{0}".format(format_currency(height)), ha='center', va='bottom', size='8')
def vendas_por_cidade(dias): vendas = Venda.objects.filter(dia__in=dias) agrupado = vendas.values("cidade_de_origem") dados = agrupado.annotate(vendas=Count("id"), entrada=Sum("conta"), pessoas=Sum("num_pessoas"), permanencia_media=Avg("permanencia")) headers = ("cidade_de_origem", "vendas", "entrada", "pessoas", "permanencia_media") for row in dados: row["entrada"] = format_currency(row["entrada"]) row["permanencia_media"] = secs_to_time(row["permanencia_media"]) if not row["cidade_de_origem"]: row["cidade_de_origem"] = "---" body = [[row[col] for col in headers] for row in dados] return {"title": "Vendas por cidade", "headers": headers, "body": body}
def autolabel(ax, rects): """ Rotula cada uma das barras com seu valor correspondente (ie resultado do mês) """ for rect in rects: height = rect.get_height() text_x = rect.get_x() + rect.get_width() / 2.0 if rect.get_y() < 0: height *= -1 text_y = height - 500 else: text_y = height + 200 ax.text(text_x, text_y, "{0}".format(format_currency(height)), ha='center', va='bottom', size='8')
def vendas_por_categoria(dias): vendas = Venda.objects.filter(dia__in=dias) agrupado = vendas.values("categoria") dados = agrupado.annotate(vendas=Count("id"), entrada=Sum("conta"), pessoas=Sum("num_pessoas"), permanencia_media=Avg("permanencia")) headers = ("categoria", "vendas", "entrada", "pessoas", "permanencia_media") for row in dados: row["entrada"] = format_currency(row["entrada"]) row["permanencia_media"] = secs_to_time(row["permanencia_media"]) body = [[row[col] for col in headers] for row in dados] for row in body: row[0] = dict(Venda.CATEGORIA_CHOICES)[row[0]] return {"title": "Vendas por categoria", "headers": headers, "body": body}
def vendas_por_cidade(dias): vendas = Venda.objects.filter(dia__in=dias) agrupado = vendas.values("cidade_de_origem") dados = agrupado.annotate(vendas=Count("id"), entrada=Sum("conta"), pessoas=Sum("num_pessoas"), permanencia_media=Avg("permanencia")) headers = ("cidade_de_origem", "vendas", "entrada", "pessoas", "permanencia_media") for row in dados: row["entrada"] = format_currency(row["entrada"]) row["permanencia_media"] = secs_to_time(row["permanencia_media"]) if not row["cidade_de_origem"]: row["cidade_de_origem"] = "---" body = [[row[col] for col in headers] for row in dados] return { "title": "Vendas por cidade", "headers": headers, "body": body }
def autolabel(ax, rects): """ Rotula cada uma das barras com seu valor correspondente (ie total de despesas do mês) """ for rect in rects: height = rect.get_height() text_x = rect.get_x() + rect.get_width() / 2.0 if rect.get_y() < 0: text_y = -1 * (height + 900) else: text_y = height + 400 ax.text(text_x, text_y, "{0}".format(format_currency(height)), ha='center', va='bottom', size='8')
def vendas_por_dia_da_semana(dias): vendas = Venda.objects.filter(dia__in=dias) agrupado = {} for venda in vendas: key = venda.dia.categoria_semanal() somar_dict( agrupado, key, { "vendas": 1, "entrada": venda.conta, "pessoas": venda.num_pessoas, "permanencia_media": venda.permanencia }) dados = [] headers = ("categoria_semanal", "vendas", "entrada", "pessoas", "permanencia_media") for grupo in agrupado.keys(): row = {} row["categoria_semanal"] = grupo for i, header in enumerate(headers[1:]): row[header] = agrupado[grupo][header] row["entrada"] = format_currency(row["entrada"]) if row["permanencia_media"]: row["permanencia_media"] = secs_to_time(row["permanencia_media"] / row["vendas"]) else: row["permanencia_media"] = 0 dados.append(row) body = [[row[col] for col in headers] for row in dados] return { "title": "Vendas por dia de semana", "headers": headers, "body": body }
def autolabel(ax, rects): """ Rotula cada uma das barras com seu valor correspondente (ie resultado do mês) """ for rect in rects: height = rect.get_height() text_x = rect.get_x() + rect.get_width() / 2.0 if rect.get_y() < 0: height *= -1 text_y = height - 500 else: text_y = height + 200 ax.text(text_x, text_y, "{0}".format(format_currency(height)), ha='center', va='bottom', size='8')
def vendas_por_categoria(dias): vendas = Venda.objects.filter(dia__in=dias) agrupado = vendas.values("categoria") dados = agrupado.annotate(vendas=Count("id"), entrada=Sum("conta"), pessoas=Sum("num_pessoas"), permanencia_media=Avg("permanencia")) headers = ("categoria", "vendas", "entrada", "pessoas", "permanencia_media") for row in dados: row["entrada"] = format_currency(row["entrada"]) row["permanencia_media"] = secs_to_time(row["permanencia_media"]) body = [[row[col] for col in headers] for row in dados] for row in body: row[0] = dict(Venda.CATEGORIA_CHOICES)[row[0]] return { "title": "Vendas por categoria", "headers": headers, "body": body }
def body(self): despesas = list(DespesaDeCaixa.objects.filter(dia__in=self.data)) + \ list(MovimentacaoBancaria.objects.filter(dia__in=self.data, valor__lt=0)) self._total_despesas = Decimal(sum(d.valor for d in despesas)) if not self._total_despesas: return [] vendas = Venda.objects.filter(dia__in=self.data) total_vendas = Decimal(sum(v.conta for v in vendas)) categoria_dict_dict = {} # Acumula despesas com `categoria == None` outros = { "total": Decimal("0"), } for despesa in despesas: if despesa.categoria: caminho_categorias = [despesa.categoria] + despesa.categoria.ascendentes for categoria in caminho_categorias: categoria_dict = categoria_dict_dict.setdefault(categoria.slug, { "total": Decimal("0"), "outros": { "total": Decimal("0"), }, }) categoria_dict["total"] += despesa.valor categoria_dict = categoria_dict_dict[categoria.slug] # Se a categoria tem filhos, a despesa deve ser categorizada como # "Outros". # # Ex: se há "Fornecedor > Vinhos" e a despesa está como # "Fornecedor", deve ser listada como "Fornecedor > Outros" if despesa.categoria.filhas.count(): categoria_dict["outros"]["total"] += despesa.valor else: logger.debug(u"Despesa sem categoria: {0}".format(despesa)) outros["total"] += despesa.valor logger.debug(u"Total de despesas sem categoria: {0}".format(len([d for d in despesas if not d.categoria]))) # Calcula porcentagem em relação à despesa total for categoria_dict in categoria_dict_dict.values(): razao_das_despesas = abs(categoria_dict["total"] / self._total_despesas) razao_das_vendas = abs(categoria_dict["total"] / total_vendas) categoria_dict["porcentagem_das_despesas"] = "{:.2%}".format(razao_das_despesas) categoria_dict["porcentagem_das_vendas"] = "{:.2%}".format(razao_das_vendas) if categoria_dict["outros"]["total"]: razao_das_despesas = abs(categoria_dict["outros"]["total"] / self._total_despesas) razao_das_vendas = abs(categoria_dict["outros"]["total"] / total_vendas) categoria_dict["outros"]["porcentagem_das_despesas"] = "{:.2%}".format(razao_das_despesas) categoria_dict["outros"]["porcentagem_das_vendas"] = "{:.2%}".format(razao_das_vendas) razao_das_despesas_outros = abs(outros["total"] / self._total_despesas) razao_das_vendas_outros = abs(outros["total"] / total_vendas) outros["porcentagem_das_despesas"] = "{:.2%}".format(razao_das_despesas_outros) outros["porcentagem_das_vendas"] = "{:.2%}".format(razao_das_vendas_outros) categoria_tuple_list = [] for slug, categoria_dict in categoria_dict_dict.items(): categoria = CategoriaDeMovimentacao.objects.get(slug=slug) if categoria.filhas.count(): nome = u"{0} - Total".format(categoria.nome_completo) else: nome = categoria.nome_completo categoria_tuple_list.append(( nome, format_currency(categoria_dict["total"]), categoria_dict["porcentagem_das_despesas"], categoria_dict["porcentagem_das_vendas"], )) if categoria_dict["outros"]["total"]: categoria_tuple_list.append(( categoria.SEPARADOR.join([categoria.nome_completo, "Outros"]), format_currency(categoria_dict["outros"]["total"]), categoria_dict["outros"]["porcentagem_das_despesas"], categoria_dict["outros"]["porcentagem_das_vendas"], )) if outros["total"]: categoria_tuple_list.append(( u"Outros", format_currency(outros["total"]), outros["porcentagem_das_despesas"], outros["porcentagem_das_vendas"], )) return sorted(categoria_tuple_list, key=lambda r: r[0]) # Ordena por nome completo da categoria
def body(self): despesas = list(DespesaDeCaixa.objects.filter(dia__in=self.data)) + \ list(MovimentacaoBancaria.objects.filter(dia__in=self.data, valor__lt=0)) self._total_despesas = Decimal(sum(d.valor for d in despesas)) if not self._total_despesas: return [] vendas = Venda.objects.filter(dia__in=self.data) total_vendas = Decimal(sum(v.conta for v in vendas)) categoria_dict_dict = {} # Acumula despesas com `categoria == None` outros = { "total": Decimal("0"), } for despesa in despesas: if despesa.categoria: caminho_categorias = [despesa.categoria ] + despesa.categoria.ascendentes for categoria in caminho_categorias: categoria_dict = categoria_dict_dict.setdefault( categoria.slug, { "total": Decimal("0"), "outros": { "total": Decimal("0"), }, }) categoria_dict["total"] += despesa.valor categoria_dict = categoria_dict_dict[categoria.slug] # Se a categoria tem filhos, a despesa deve ser categorizada como # "Outros". # # Ex: se há "Fornecedor > Vinhos" e a despesa está como # "Fornecedor", deve ser listada como "Fornecedor > Outros" if despesa.categoria.filhas.count(): categoria_dict["outros"]["total"] += despesa.valor else: logger.debug(u"Despesa sem categoria: {0}".format(despesa)) outros["total"] += despesa.valor logger.debug(u"Total de despesas sem categoria: {0}".format( len([d for d in despesas if not d.categoria]))) # Calcula porcentagem em relação à despesa total for categoria_dict in categoria_dict_dict.values(): razao_das_despesas = abs(categoria_dict["total"] / self._total_despesas) razao_das_vendas = abs(categoria_dict["total"] / total_vendas) categoria_dict["porcentagem_das_despesas"] = "{:.2%}".format( razao_das_despesas) categoria_dict["porcentagem_das_vendas"] = "{:.2%}".format( razao_das_vendas) if categoria_dict["outros"]["total"]: razao_das_despesas = abs(categoria_dict["outros"]["total"] / self._total_despesas) razao_das_vendas = abs(categoria_dict["outros"]["total"] / total_vendas) categoria_dict["outros"][ "porcentagem_das_despesas"] = "{:.2%}".format( razao_das_despesas) categoria_dict["outros"][ "porcentagem_das_vendas"] = "{:.2%}".format( razao_das_vendas) razao_das_despesas_outros = abs(outros["total"] / self._total_despesas) razao_das_vendas_outros = abs(outros["total"] / total_vendas) outros["porcentagem_das_despesas"] = "{:.2%}".format( razao_das_despesas_outros) outros["porcentagem_das_vendas"] = "{:.2%}".format( razao_das_vendas_outros) categoria_tuple_list = [] for slug, categoria_dict in categoria_dict_dict.items(): categoria = CategoriaDeMovimentacao.objects.get(slug=slug) if categoria.filhas.count(): nome = u"{0} - Total".format(categoria.nome_completo) else: nome = categoria.nome_completo categoria_tuple_list.append(( nome, format_currency(categoria_dict["total"]), categoria_dict["porcentagem_das_despesas"], categoria_dict["porcentagem_das_vendas"], )) if categoria_dict["outros"]["total"]: categoria_tuple_list.append(( categoria.SEPARADOR.join( [categoria.nome_completo, "Outros"]), format_currency(categoria_dict["outros"]["total"]), categoria_dict["outros"]["porcentagem_das_despesas"], categoria_dict["outros"]["porcentagem_das_vendas"], )) if outros["total"]: categoria_tuple_list.append(( u"Outros", format_currency(outros["total"]), outros["porcentagem_das_despesas"], outros["porcentagem_das_vendas"], )) return sorted( categoria_tuple_list, key=lambda r: r[0]) # Ordena por nome completo da categoria