Adiciona ao repo os scripts e configs reais do motor que estavam fora do git,
e remove arquivos legados/abandonados.
Adicionados (30):
- scripts/docker-compose.m5.yml, openwa-compose.yml, minio-compose.yml
- scripts/openwa.env (sem secrets)
- scripts/{entrypoint,saleor-entrypoint,saleor-start}.sh
- scripts/{chatwoot-setup,compliance-check,health-check,resumo-diario}.sh
- scripts/{insert_workflow,telegram_user_login,telegram_user_monitor}.py
- scripts/requirements.txt
- scripts/traefik-conf/{traefik.yml,dynamic-config.yml}
- scripts/compliance/, scripts/calculators/, scripts/backups/
- scripts/{README.md,README-INSTALL.md,WHATSAPP-SETUP.md,.gitignore}
- .gitignore (atualizado)
Removidos (ja' em backup/untracked-lixo-2026-07-06/):
- agents/, crm/, hermes_skills_backup/, api-complive/, docs/ (legados)
- scripts/{wrapper.py,wrapper.sh}
- scripts/docker-compose.m5.yml.backup, traefik-conf/routes.yml.bak2
- scripts/saleor-media/RSA_*.{bak,old_*}
- scripts/n8n-workflows/webhook-saleor.json.bak2
- scripts/backups/20260622_0300/saleor_db.sql
- integracao_completa.sh, monitoramento_vps.sh
- ruvector.db (vazio)
Ignorados via .gitignore:
- vault/ (Obsidian KB)
- skills/ (duplicado de ~/.hermes/skills/)
- scripts/{saleor-media,traefik-acme,yt-pub-livesx,minio,n8n-workflows,skills}/
- scripts/backups/2026*_*/
187 lines
6.3 KiB
Python
Executable File
187 lines
6.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
Calculadora de Margem Líquida por Marketplace
|
||
Calcula o lucro real por canal considerando todas as fees.
|
||
|
||
Uso:
|
||
python calculators/marketplace_margin.py
|
||
python calculators/marketplace_margin.py --price 120 --cost 40 --marketplace shopee
|
||
"""
|
||
|
||
import argparse
|
||
from rich.console import Console
|
||
from rich.table import Table
|
||
from rich.prompt import FloatPrompt
|
||
|
||
console = Console()
|
||
|
||
MARKETPLACES = {
|
||
"shopee": {
|
||
"fee": 0.18,
|
||
"fee_name": "Taxa de Venda Shopee",
|
||
"payment_fee": 0.029,
|
||
"payment_name": "Taxa de Pagamento",
|
||
"shipping_subsidy": 0.10,
|
||
"shipping_name": "Subsídio Frete (média)",
|
||
"pkg_fee": 0.03,
|
||
"pkg_name": "Embalagem (média)",
|
||
},
|
||
"mercadolivre": {
|
||
"fee": 0.16,
|
||
"fee_name": "Taxa de Venda ML",
|
||
"payment_fee": 0.039,
|
||
"payment_name": "Taxa de Pagamento ML",
|
||
"shipping_subsidy": 0.10,
|
||
"shipping_name": "Subsídio Frete (média)",
|
||
"pkg_fee": 0.03,
|
||
"pkg_name": "Embalagem (média)",
|
||
},
|
||
"amazon": {
|
||
"fee": 0.15,
|
||
"fee_name": "Referral Fee Amazon",
|
||
"payment_fee": 0.0,
|
||
"payment_name": "Taxa de Pagamento (incluída)",
|
||
"shipping_subsidy": 0.08,
|
||
"shipping_name": "Custo Envio FBA (média)",
|
||
"pkg_fee": 0.04,
|
||
"pkg_name": "FBA Pick & Pack (média)",
|
||
},
|
||
"tiktok": {
|
||
"fee": 0.08,
|
||
"fee_name": "Taxa de Venda TikTok Shop",
|
||
"payment_fee": 0.019,
|
||
"payment_name": "Taxa de Pagamento",
|
||
"shipping_subsidy": 0.08,
|
||
"shipping_name": "Frete TikTok (média)",
|
||
"pkg_fee": 0.02,
|
||
"pkg_name": "Embalagem (média)",
|
||
},
|
||
"magalu": {
|
||
"fee": 0.19,
|
||
"fee_name": "Taxa de Venda Magalu",
|
||
"payment_fee": 0.025,
|
||
"payment_name": "Taxa de Pagamento",
|
||
"shipping_subsidy": 0.11,
|
||
"shipping_name": "Subsídio Frete (média)",
|
||
"pkg_fee": 0.03,
|
||
"pkg_name": "Embalagem (média)",
|
||
},
|
||
"site": {
|
||
"fee": 0.0,
|
||
"fee_name": "Fee Plataforma (Shopify ~2%)",
|
||
"payment_fee": 0.029,
|
||
"payment_name": "Taxa de Pagamento (Stripe/PagSeguro)",
|
||
"shipping_subsidy": 0.08,
|
||
"shipping_name": "Frete médio (Correios/próprio)",
|
||
"pkg_fee": 0.03,
|
||
"pkg_name": "Embalagem",
|
||
},
|
||
}
|
||
|
||
|
||
def calculate_margin(price: float, cost: float, marketplace: dict, channel_name: str):
|
||
"""Calcula margem para um canal."""
|
||
gross = price - cost
|
||
|
||
fee_amount = price * marketplace["fee"]
|
||
payment_amount = price * marketplace["payment_fee"]
|
||
shipping_amount = price * marketplace["shipping_subsidy"]
|
||
pkg_amount = price * marketplace["pkg_fee"]
|
||
|
||
total_fees = fee_amount + payment_amount + shipping_amount + pkg_amount
|
||
net_profit = gross - total_fees
|
||
margin_pct = (net_profit / price * 100) if price > 0 else 0
|
||
roi = ((net_profit / cost) * 100) if cost > 0 else 0
|
||
|
||
return {
|
||
"canal": channel_name,
|
||
"preco": price,
|
||
"custo": cost,
|
||
"lucro_bruto": gross,
|
||
"fee_venda": fee_amount,
|
||
"fee_pagto": payment_amount,
|
||
"fee_frete": shipping_amount,
|
||
"fee_pkg": pkg_amount,
|
||
"total_fees": total_fees,
|
||
"lucro_liquido": net_profit,
|
||
"margem_pct": margin_pct,
|
||
"roi_pct": roi,
|
||
}
|
||
|
||
|
||
def print_result(r: dict):
|
||
table = Table(title=f"📊 Margem — {r['canal']}", style="cyan")
|
||
table.add_column("Item", style="yellow")
|
||
table.add_column("Valor", justify="right", style="white")
|
||
|
||
table.add_row("Preço de Venda", f"R$ {r['preco']:.2f}")
|
||
table.add_row("Custo do Produto", f"R$ {r['custo']:.2f}")
|
||
table.add_row("Lucro Bruto", f"R$ {r['lucro_bruto']:.2f}")
|
||
table.add_row(" Fee de Venda", f"− R$ {r['fee_venda']:.2f}")
|
||
table.add_row(" Fee de Pagamento", f"− R$ {r['fee_pagto']:.2f}")
|
||
table.add_row(" Subsídio Frete", f"− R$ {r['fee_frete']:.2f}")
|
||
table.add_row(" Embalagem", f"− R$ {r['fee_pkg']:.2f}")
|
||
table.add_row("TOTAL DE FEES", f"− R$ {r['total_fees']:.2f}", style="red")
|
||
table.add_row("LUCRO LÍQUIDO", f"R$ {r['lucro_liquido']:.2f}", style="green bold")
|
||
table.add_row("Margem Líquida", f"{r['margem_pct']:.1f}%", style="green")
|
||
table.add_row("ROI sobre Custo", f"{r['roi_pct']:.1f}%", style="cyan")
|
||
|
||
console.print(table)
|
||
|
||
|
||
def print_comparison(price: float, cost: float):
|
||
"""Compara todos os marketplaces."""
|
||
table = Table(title="📊 Comparativo de Margem — Preço: R$ {:.2f}".format(price), style="cyan")
|
||
table.add_column("Canal", style="yellow")
|
||
table.add_column("Lucro Líquido", justify="right", style="white")
|
||
table.add_column("Margem %", justify="right")
|
||
table.add_column("ROI %", justify="right")
|
||
|
||
results = []
|
||
for name, config in MARKETPLACES.items():
|
||
r = calculate_margin(price, cost, config, name.title())
|
||
results.append(r)
|
||
|
||
# Sort by profit
|
||
results.sort(key=lambda x: x["lucro_liquido"], reverse=True)
|
||
|
||
for r in results:
|
||
style = "green" if r["lucro_liquido"] > 0 else "red"
|
||
table.add_row(
|
||
r["canal"],
|
||
f"R$ {r['lucro_liquido']:.2f}",
|
||
f"{r['margem_pct']:.1f}%",
|
||
f"{r['roi_pct']:.1f}%",
|
||
style=style,
|
||
)
|
||
|
||
console.print(table)
|
||
console.print()
|
||
console.print(f"[yellow]Custo do produto:[/yellow] R$ {cost:.2f} | [yellow]Margem bruta:[/yellow] {((price-cost)/price*100):.1f}%")
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description="Calculadora de margem por marketplace")
|
||
parser.add_argument("--price", type=float, help="Preço de venda")
|
||
parser.add_argument("--cost", type=float, help="Custo do produto")
|
||
parser.add_argument("--marketplace", type=str, choices=list(MARKETPLACES.keys()) + ["all"], default="all")
|
||
args = parser.parse_args()
|
||
|
||
if args.price and args.cost:
|
||
price = args.price
|
||
cost = args.cost
|
||
else:
|
||
console.print("[bold cyan]Calculadora de Margem por Marketplace[/bold cyan]\n")
|
||
price = FloatPrompt.ask("Preço de venda (R$)", default="120.0")
|
||
cost = FloatPrompt.ask("Custo do produto (R$)", default="40.0")
|
||
|
||
if args.marketplace == "all":
|
||
print_comparison(price, cost)
|
||
else:
|
||
config = MARKETPLACES[args.marketplace]
|
||
r = calculate_margin(price, cost, config, args.marketplace.title())
|
||
print_result(r)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main() |