U
    >Fj                    @   s  e d  ddlZe dejd ddlmZ e  ddlmZmZm	Z	m
Z
mZmZmZmZmZ ddlZddlZddlZddlmZ ddlZddlZddlZddlZddlZddlZddlZddlZddlmZmZmZ dd	l m!Z! dd
l"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z8 ddl6m9Z: ddl;m<Z<m=Z=m>Z>m?Z? ddl@mAZAmBZBmCZCmDZDmEZEmFZF ejGejHejeIddddZJejKeJrDeJejkrejLdeJ eJejM ejNOdd ejNd< ePedrDzeQeJ W n eRk
rB   Y nX zddlSaSW n eRk
rj   daSY nX zddlTmUZVmWZXmYZZ W nR e[k
r   zddl\mUZVmWZXmYZZ W n" e[k
r   dZVdZXdZZY nX Y nX zddl]Z]W n eRk
r   dZ]Y nX ejHejeIZ^e#_  ee`dejGe^dd Zad!eaj"d"< e#jbea_ce#jdeaj"d#< e#jeeaj"d$< e#jfrre#jfeaj"d%< e#jgre#jgeaj"d&< e#jgeaj"d'< G d(d) d)Zhe#jgreheajie#jgea_ieaje) e+ea eajkd*d+ Zleajmd,d- Zneaod.d/d0 Zpeaod1d2d3 Zqeajrd4d5gd6e-d7d8 Zseard9e-d:d; Zteard<e-d=d> Zud?d@ ZvdAdB ZwdCdD ZxdEdF ZyezezdGdHdIZ{dJdK Z|dLdM Z}dNdO Z~dPdQ ZdRdS ZdTdU ZdVZedWdXdYdZhZd[Zdd]d^Zd_d` Zdadb Zdcdd ZddedfZdgdh ZddidjZddkdlZdmdn Zdodp Zdqdr Zdsdt Zdudv Zdwdx Zdydz Zd{d| ZdddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdddZeajrdd5gd6e-dd Zeajrdd5gd6e-dd Zeajrdd5gd6e-dd Zeajrddgd6e-dd Zeajrdd5gd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrdd5gd6e-dd Zdd ZddÄ Zddń ZddǄ ZddɄ Zdd˄ Zdd̈́ Zddτ ZdddфZddӄ ZdddՄZddׄ Zeajrdd5gd6e-ddڄ Zeajrddgd6e-dd܄ Zeajrdd5gd6e-e/dd߄ Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrdd5gd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrdd5gd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrdd5gd6e-dd Zdd Zdd Zdd  Zeajrddgd6e-dd Zeajrddgd6e-dd Zeajrddgd6e-dd	 Zeajrd
d5gd6e-dd Zeajrddgd6e-dd Zeajrdd5gd6e-dd Zeajrdd5gd6e-dd Zeajrdd5gd6e-e.dd Zeajrddgd6e-dd ZeajԐdd Zearddd  Zeard!d"d# Zeajrd$dgd6e-d%d& Zeajrd'd(gd6e-d)d* Zeajrd+dgd6e-d,d- Zڐd.d/ Zېd0d1 Zܐd2d3 Zݐd4d5 Zސd6d7 Zߐd8d9 Zd:Zd;d< Zd=d> Zd?d@ ZdAdB ZddCdDZddEdFZddGdHZddIdJZddKdLZddMdNZdOdP ZddQdRZddSdTZdUdV ZdWdX ZeajrdYd5gd6dZd[ Zeajrd\d5gd6eajrd]d5gd6d^d_ Zeard`e-dadb Zeardcddde Zeardfe-dgdh Zeardie-e.djdk Zeardle-dmdn Zeardoe-e.dpdq Zeardre-e.dsdt Zeajrdudgd6e-e.dvdw Zeajrdxd5gd6e-e.dydz Zeard{e-e/d|d} Zeajrd~d5gd6e-e/dd Zeajrd~dgd6e-e/dd Zeajrddgd6e-e/dd Zeajrdd5gd6e-e.dd Z eajrddgd6e-e.dd Zeajrdd5gd6e-e.dd Zeajrdd(gd6e-e.dd Zeajrddgd6e-e.dd Zearde-dd Zeajrddgd6e-dd Zeajrdd5gd6e-dd Zeajrdd5gd6e-dd Zeajrdd(gd6e-dd Z	eajrddgd6e-dd Z
earde-dd Zeajrddgd6e-dd Zearde-dd Zearde-e.dd Zearde-dd Zeajrdd5gd6e-dd Zeajrddgd6e-e.dd Zeajrdd5gd6e-e.dd Zeajrdd5gd6e-e.dd Zeajrdd5gd6dÐdĄ ZezdŜdƐdǄZeajrdd5gd6dɐdʄ Zeajrddgd6dːd̄ Zezezeezd͜dΐdτZeajrddgd6e-dѐd҄ Zeajrdd5gd6dԐdՄ Zeajrdd5gd6dאd؄ Zeajrdd5gd6dڐdۄ Zeajrdd5gd6e-dݐdބ Zeajrddgd6e-dߐd Zeajrdd5gd6dd Z dd Z!eajrddgd6dd Z"eajrdd(gd6edddZ#eajrddgd6edddZ$eajrddgd6e-dd Z%eajrddgd6e-dd Z&earde-dd Z'eajrddgd6e-dd Z(earde-dd Z)dd Z*earde-d d Z+earddd Z,earde-dd Z-earde-d	d
 Z.eajrdd5gd6e-dd Z/eajrdd5gd6e-dd Z0eajrdd5gd6e.dd Z1eajrddgd6e.dd Z2eajrdd5gd6e-dd Z3eajrddgd6dd Z4eajrddgd6dd Z5eajrd dgd6e-d!d" Z6eajrd#d5gd6e.d$d% Z7eajrd&d5gd6e-d'd( Z8eajrd)dgd6d*d+ Z9eard,d-d. Z:eajrd/dgd6d0d1 Z;eajrd2dgd6d3d4 Z<eajrd5d5gd6d6d7 Z=eajrd8dgd6e-d9d: Z>eajrd;dgd6e-d<d= Z?eajrd>dgd6e-d?d@ Z@eajrdAdgd6e-dBdC ZAeajrdDd5gd6e-e.dEdF ZBeajrdGdgd6e-e.dHdI ZCeajrdJd5gd6e-e.dKdL ZDeajrdMdgd6e-e.dNdO ZEeajrdPd5gd6e-dQdR ZFeajrdSd5gd6e-e.dTdU ZGeajrdVdgd6e-e.dWdX ZHeajrdYdgd6e-e.dZd[ ZIeajrd\dgd6e-e.d]d^ ZJeajrd_dgd6e-e.d`da ZKeajrdbdgd6e-e.dcdd ZLeajrdedgd6e-e.dfdg ZMeajrdedgd6e-e.dhdi ZNeajrdjdgd6e-e.dkdl ZOeajrdmdgd6e-e.dndo ZPe`dpkrejGeajQeajRpdZSe dqd!dr e dsd!dr e dtejeajQd!dr e dud!dr e dtejeSd!dr e dvd!dr e dwd!dr zddxlmZ ejGe^dyZTeUeTdzd{d|fZVeVWd} eVWd~eX jYdd d eVWe  eVWd W 5 Q R X e deT d!dr W nD eZk
r Z[ ze de[ d!dr W 5 dZ[[[X Y nX e  eaj\dde#j]d dS (  zUSANDO APP CERTO    NzTEMPLATE PATH:	templates)load_dotenv)	Flaskrender_templatejsonifyrequestsessionredirecturl_formake_responseResponse)pprint)datedatetimetime)quote)Config)get_app_version)conectar)auth_bp)register_domain_blueprints)login_requiredrestaurant_onlygerente_required)	is_retail)obter_dados_loja)get_impressao_meta)uazapi)terminal_impressao)UsuariosLojaErrorcreate_usuariolist_usuariosupdate_usuario)ensure_pedido_periodos_tableensure_purge_eventexecutar_fechamentopreview_fechamentorelatorio_gerencial_periodoresumo_financeiro_fechamentoz.venvZLibzsite-packagesZpywin32_system32PATH add_dll_directory)find_best_printer_matchnormalize_printer_nameresolve_windows_printerZstatic)template_folderZstatic_folderTZTEMPLATES_AUTO_RELOADSESSION_COOKIE_SAMESITESESSION_COOKIE_SECURESESSION_COOKIE_DOMAINZAPPLICATION_ROOTZSESSION_COOKIE_PATHc                   @   s"   e Zd ZedddZdd ZdS )_PrefixMiddleware)prefixc                 C   s   || _ |pdd| _d S )Nr*   /)wsgi_apprstripr4   )selfr6   r4    r9   #/var/www/html/LojaOnline_hml/app.py__init__d   s    z_PrefixMiddleware.__init__c                 C   sp   | j }|rd|dpdpd}||kr6||d< d|d< n.||d rd||d< |t|d  p^d|d< | ||S )N	PATH_INFOr*   r5   SCRIPT_NAME)r4   get
startswithlenr6   )r8   environstart_responser4   pathr9   r9   r:   __call__h   s    
z_PrefixMiddleware.__call__N)__name__
__module____qualname__strr;   rD   r9   r9   r9   r:   r3   c   s   r3   c               
   C   sX   t  } t }t r d}d}nd }d }t tj| r8dnd| | ttd|||d	S )Nu9   AMBIENTE DE HOMOLOGAÇÃO — dados podem ser descartadosZhmlZvarejoZrestauranteusuario_logado)	Zapp_versionZ
url_prefixZbusiness_typer   Z	IS_RETAILis_platform_adminenvironment_labelZenvironment_bannerZenvironment_banner_kind)	r   r   rK   Zis_homologationr   
URL_PREFIXrJ   r   r>   )ZretailZ	env_labelZ
env_bannerZenv_banner_kindr9   r9   r:   inject_app_globals{   s"    
rM   c                 C   sP   | j dd}d|krLd| j d< d| j d< d| j d	< t | j d
< tj| j d< | S )uQ   Respostas HTML sempre frescas — evita ver layout antigo por cache do navegador.zContent-Typer*   z	text/htmlz$no-store, max-age=0, must-revalidatezCache-Controlzno-cacheZPragma0ZExpiresX-App-VersionzX-Environment)headersr>   r   r   ZENVIRONMENT)Zresponsectr9   r9   r:   _evitar_cache_html   s    


rR     c                 C   sJ   z0t tjpddr.tddtjddfW S W n tk
rD   Y nX | S )Nr*   /api/Fu   Rota não encontrada.)sucessoerrorC   rS   )rH   r   rC   r?   r   	Exception)er9   r9   r:   _api_not_found   s    rY     c                 C   s   zpt tjpddrnd }zttt| dd p.g }W n tk
rN   d }Y nX tddtjtj	|ddfW S W n tk
r   Y nX | S )Nr*   rT   Zvalid_methodsFu   Método não permitido.)rU   rV   rC   methodallowrZ   )
rH   r   rC   r?   sortedlistgetattrrW   r   r[   )rX   r\   r9   r9   r:   _api_method_not_allowed   s&    

r`   z/formas-pagamentoGET)methodsc                   C   s   t dS )Nzformas_pagamento.htmlr   r9   r9   r9   r:   formas_pagamento_page   s    rd   z/configuracoesc                  C   s0   t d} t| pi }|dd}td| |dS )N
id_clientenome
Minha Lojazconfiguracoes.htmlre   nome_fantasiar   r>   r   r   re   
dados_lojari   r9   r9   r:   configuracoes   s    
rm   z/configuracoes-dadosc                   C   s   t dS )uP   Tabela de configurações (JSON) — link a partir do painel de configurações.zconfiguracoes_dados.htmlrc   r9   r9   r9   r:   configuracoes_dados   s    rn   c                 C   s   t jtd}zLdd dtd d|  d| d	}t|ddd}|| W 5 Q R X W nJ tk
r } z,zt	d	|d
d W n tk
r   Y nX W 5 d}~X Y nX dS )uN   Registra erros em disco (útil quando o app roda com pythonw.exe sem console).zloja_erros.log
<============================================================z%Y-%m-%d %H:%M:%S autf-8encodingz[LOJA_ERROS.LOG]TflushN)
osrC   join	_BASE_DIRr   strftimeopenwriterW   print)ZtituloZdetalhes_textorC   ZblocofZlog_excr9   r9   r:   _append_loja_erro_log   s    "r   c                  C   s  d } d }zzt } |  }|d | d kr:|d |d | d krZ|d |d | d k	r|d | d kr|d |   W nV tk
r } z8z| r|   W n tk
r   Y nX td|d	d
 W 5 d }~X Y nX W 5 |r|   | r|    X d S )Nz2SHOW COLUMNS FROM deliverypendente LIKE 'obs_item'z:ALTER TABLE deliverypendente ADD COLUMN obs_item TEXT NULLz3SHOW COLUMNS FROM deliverypendente LIKE 'obs_geral'z;ALTER TABLE deliverypendente ADD COLUMN obs_geral TEXT NULLzSHOW TABLES LIKE 'mesa'z&SHOW COLUMNS FROM mesa LIKE 'obs_item'z.ALTER TABLE mesa ADD COLUMN obs_item TEXT NULLz[OBS COLUNAS ERRO]Trv   	closer   cursorexecutefetchonecommitrW   rollbackr~   conncurrX   r9   r9   r:   _ensure_obs_columns   s8    






$r   c              	   C   s   d dd t|pdD }|s$d S | d|f |  p<g }|D ]}d dd t|pXi dpbdD }|srqB||ks||s||rBz t|pi dpdpd W   S  tk
r   Y qBY qBX qBd S )	Nr*   c                 s   s   | ]}|  r|V  qd S Nisdigit.0chr9   r9   r:   	<genexpr>  s      z9_buscar_nropedido_aguarde_por_telefone.<locals>.<genexpr>a(  
        SELECT nropedido, telefone
        FROM pedido_diarios
        WHERE id_cliente = %s
          AND origem = 'DELIVERY'
          AND UPPER(COALESCE(status_pedido, '')) = 'AGUARDE'
          AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
        ORDER BY nropedido ASC
        c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      telefone	nropedidor   )ry   rH   r   fetchallr>   endswithintrW   )r   re   telefone_raw
tel_digitsrowsrowdb_telr9   r9   r:   &_buscar_nropedido_aguarde_por_telefone  s$    	& r   c                 C   s`   d dd t| pdD }d dd t|p.dD }|r@|sDdS ||kp^||p^||S )Nr*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   (  s      z)_telefones_compativeis.<locals>.<genexpr>c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   )  s      F)ry   rH   r   )Za_rawZb_rawrr   br9   r9   r:   _telefones_compativeis'  s
    r   )
table_namereturnc                 C   s"   | dkrdnd}d| d|  dS )Npedido_periodosarquivado_emzNULL AS arquivado_emz1
        SELECT origem, nropedido, data_criacao, zX, telefone, produto,
               quantidade, preco, obs_item, obs_geral
        FROM z
        WHERE id_cliente = %s
          AND UPPER(TRIM(COALESCE(origem, ''))) IN ('DELIVERY', 'BALCAO')
          AND UPPER(TRIM(COALESCE(status_pedido, ''))) = 'RECEBIDO'
        ORDER BY data_criacao DESC, chave DESC
        LIMIT 2000
    r9   )r   Zarq_colr9   r9   r:   _sql_historico_cliente_recebido/  s    r   c                 C   s4   g }| p
g D ]"}t |pi d|r|| q|S )Nr   )r   r>   append)r   r   outr   r9   r9   r:   &_filtrar_linhas_historico_por_telefone=  s
    r   c              
   C   s  i }| p
g D ]}t |pi dp$d  p2d}t|p<i dpFd}|dkrTq||f}||}|pli dp|pzi dpd}|d kr|||d k	rt |nd|t |pi dpd g d	}|||< n@|r|d
rt |t |d
pdkr||d
< t ||d< |dsHt |p&i dp2d }|rH||d< t |pRi dp^d }	|	r|d |	t|p~i dpdt|pi dpdt |pi dpd d qt| dd dd}
|
D ]}|	d
d  q|
S )Norigemr*   DELIVERYr   r   data_criacaor   	obs_geralr   r   data
_data_sortr   itensr   r   produtor   
quantidadeprecoobs_itemr   r   r   r   c                 S   s$   t | dpdt| dpdfS Nr   r*   r   r   rH   r>   r   xr9   r9   r:   <lambda>l      z4_agrupar_pedidos_historico_cliente.<locals>.<lambda>Tkeyreverse)
rH   r>   stripupperr   r   floatr]   valuespop)r   pedidosr   r   nror   bucketdata_refZog	item_nomeorderedr   r9   r9   r:   "_agrupar_pedidos_historico_clienteE  sT    "
 
,r   c              	   C   sb   g }dD ]F}z(|  t||f ||  p.g  W q tk
rL   Y qY qX qt||}t|S )N)pedido_diariosr   )r   r   extendr   rW   r   r   )r   re   r   r   Ztblr9   r9   r:   &_historico_cliente_from_pedido_tabelast  s    
r   c              
   C   st  |  d|f |  pg }t||}i }|D ]}t|dp@d}|dkrNq,d|f}||}	|	d kr|dp|dp|dp|dp|d	pd
}
|d|
d k	rt|
nd
|
t|dpd
 g d}	|	||< t|dpd
 }|r,|	d |t|dpdt|dp dt|dp2d
 d q,t	|
 dd dd}|D ]}|dd  q\|S )Nz~
        SELECT *
        FROM liquidada
        WHERE id_cliente = %s
        ORDER BY chave DESC
        LIMIT 2000
        r   r   ZLEGADOr   r   Z
datapedidoZdatahoraZ
created_atr*   r   r   r   r   r   r   r   r   c                 S   s$   t | dpdt| dpdfS r   r   r   r9   r9   r:   r     r   z3_historico_cliente_from_liquidada.<locals>.<lambda>Tr   r   )r   r   r   r   r>   rH   r   r   r   r]   r   r   )r   re   r   Zall_rowsr   r   r   r   r   r   r   r   r   r   r9   r9   r:   !_historico_cliente_from_liquidada  sd    




	r   c           
   
   C   s\  |r|dkrdS t  }|D ]R}t|p&i dp0d }| rz|t| W q ttfk
rj   Y qX qi }|rt	|}d
dgt| }| d| d|f| |  pg D ](}	|	rt|	dpd|t|	d	< q|D ]p}|sqt|dpd }| rNz|t|d|d
< W n" ttfk
rJ   d|d
< Y nX qd|d
< qdS )u   
    Preenche descricao_produto sem JOIN na query principal (evita erro SQL com
    codigoproduto não numérico, p.ex. AJUSTE_TECNICO, e diferenças de modo estrito).
    Ncodigoprodutor*   ,%szcSELECT chave, IFNULL(descricao, '') AS descricao FROM produtos WHERE id_cliente = %s AND chave IN ()	descricaochaveZdescricao_produto)setrH   r>   r   r   addr   	TypeError
ValueErrorr]   ry   r@   r   r   )
r   re   r   Zchaves_unicasrcpZdesc_mapZlistaphprr9   r9   r:   )_enriquecer_descricao_produto_pedido_rows  s>    
"
r   c                C   s  ddddddddd	d
ddddddddddddddddg}t |p@d  t|t |pXdt |pbdt |pldt |pvdt |pdt |pdt |pdt |	pdt |
pdt |pdt|pdt|pdt |pdt |pdt |pdt |pd||t |pdt|t |pd|d k	r(t|p$dnd |d k	rBt|p>dnd t |pNdg}d d!gt| }| d"d | d#| d$t| d S )%Nr   r   status_pedidostatus_comandar   ceprf   endereconrocasacomplementor   r   r   r   r   
dados_itemr   classe
cod_classecod_usuarioclientere   formapagamento
lancamentonrolancamento
entregadorr*   AGUARDENORMALr      , r   INSERT INTO pedido_diarios (
) VALUES (r   )	rH   r   r   r   r   ry   r@   r   tuple)r   r   r   re   r   r   rf   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   colsvalsr   r9   r9   r:    _insert_pedido_diarios_from_casa  sv    
















r   	CANCELADAABERTOABERTAr   ROTAuR   Comanda cancelada ou pedido em ROTA/RECEBIDO não pode ser alterado na tela /casa.pdc                 C   s   d|  dS )NUPPER(TRIM(COALESCE(z$.status_comanda, ''))) = 'CANCELADA'r9   aliasr9   r9   r:   _sql_comanda_canceladaC  s    r   c                 C   s   t | pd  dkS )Nr*   r   BALCAOrH   r   r   )r   r9   r9   r:   _origem_delivery_balcao_validaG  s    r  c                 C   sH   t  s
| S | d kri } nt| ts,t| } nt| } d| d< d| d< | S )Nbalcaomodor   r   )r   
isinstancedict)r   r9   r9   r:   _casa_forcar_balcao_se_varejoK  s    

r  c                 C   sR   t |pd  }t|s dS | dtd dt||t|f |  d k	S )Nr*   Fz}
        SELECT 1
        FROM pedido_diarios
        WHERE id_cliente = %s AND origem = %s AND nropedido = %s
          AND r   
        LIMIT 1
        )rH   r   r   r  r   r   r   r   )r   re   r   r   origr9   r9   r:   _comanda_esta_canceladaY  s    
r
  c                 C   s   d|  dS )zALinha ativa da comanda: status_pedido diferente de ITEM_REMOVIDO.r   z(.status_pedido, ''))) <> 'ITEM_REMOVIDO'r9   r   r9   r9   r:   _sql_linha_ativa_pedidoj  s    r  c                 C   s  t |pd  }t|s dS t|p(d}|dkr8dS | dt|||f |  pXi }tt|trp|	dn|d pzd}|dkrdS t
| |||rdS | d	td
 dt|||f |  rdS | dtd
 dt|||f |  pg }|sdS g }	|D ]T}
t|
tr8t |
	dp*d  }nt |
d pFd  }|	| q
dd |	D }|rdd|d  dfS dS )Nr*   )F)   Origem inválida. Use DELIVERY ou BALCAO.r   )F   Número do pedido inválido.z
        SELECT COUNT(*) AS n
        FROM pedido_diarios
        WHERE id_cliente = %s AND origem = %s AND nropedido = %s
        n)F   Pedido não encontrado.)Fu   Comanda já está cancelada.z
        SELECT 1
        FROM pedido_diarios pd
        WHERE pd.id_cliente = %s AND pd.origem = %s AND pd.nropedido = %s
          AND r   z`
          AND UPPER(TRIM(COALESCE(pd.status_pedido, ''))) = 'RECEBIDO'
        LIMIT 1
        )Fu,   Pedido já RECEBIDO não pode ser cancelado.z
        SELECT UPPER(TRIM(COALESCE(pd.status_pedido, ''))) AS st
        FROM pedido_diarios pd
        WHERE pd.id_cliente = %s AND pd.origem = %s AND pd.nropedido = %s
          AND z	
        )Tr*   stc                 S   s   g | ]}|t kr|qS r9   )_STATUS_PEDIDO_CANCELAVEL)r   r  r9   r9   r:   
<listcomp>  s      z*_comanda_pode_cancelar.<locals>.<listcomp>FzStatus do pedido (u   ) não permite cancelamento.)rH   r   r   r  r   r   r   r  r  r>   r
  r  r   r   )r   re   r   r   r	  nprow_nZtotal_linhasr   Zativasr   r  Z	invalidasr9   r9   r:   _comanda_pode_cancelaro  sV    $	r  c                 C   s   t |t |g}|r8t|r8d}|t|   nd}| d| dtd dt| | 	 rrdddd	S | d| d
t| | 	 rdddd	S dddd	S )Nz AND origem = %s z% AND origem IN ('DELIVERY','BALCAO') z_
        SELECT 1
        FROM pedido_diarios
        WHERE nropedido = %s AND id_cliente = %s z
          AND r   r  TComanda cancelada.)	bloqueadocomanda_canceladamotivo_bloqueiozg
          AND UPPER(TRIM(COALESCE(status_pedido, ''))) IN ('RECEBIDO','ROTA')
        LIMIT 1
        Fu   Pedido em ROTA ou já RECEBIDO.r*   )
r   r  r   rH   r   r   r   r   r   r   )r   re   r   r   paramsZorig_clauser9   r9   r:   _casa_pedido_bloqueado_info  s6    

r  c                 C   s.   t | |||}|dr*tdtddfS d S )Nr  FrU   rV     )r  r>   r   _MSG_CASA_BLOQUEADO)r   re   r   r   infor9   r9   r:   _assert_casa_editavel  s    
r   c                 C   sP   d}d}z(t }| }|d| f |  W 5 |r>|   |rJ|   X dS )uK   Garante linha do contador (commit imediato, fora da transação do pedido).NzGINSERT IGNORE INTO contadorpedido (contador, id_cliente) VALUES (0, %s))r   r   r   r   r   )re   r   r   r9   r9   r:   _ensure_contadorpedido_row  s    r!  c                 C   s   t dD ]}zP| d|f | d |  p0i }t|dp@d}|dkrTtd|W   S  tjjk
r } z8t	|ddd	kr|d
k rt
dd|   W Y q W 5 d}~X Y qX qdS )uQ   Incremento atômico via LAST_INSERT_ID; executar dentro da transação do pedido.   zWUPDATE contadorpedido SET contador = LAST_INSERT_ID(contador + 1) WHERE id_cliente = %szSELECT LAST_INSERT_ID() AS nr  r   zFalha ao alocar nropedidoerrnoNi     g{Gz?   )ranger   r   r   r>   RuntimeErrormysql	connectorErrorr_   r   sleep)r   re   attemptr   r  rX   r9   r9   r:   _alocar_proximo_nropedido  s"    

r-  c                 C   s.   |  d|f |  }|r*t|d d S dS )u@   Próximo número estimado (preview), sem incrementar o contador.9SELECT contador FROM contadorpedido WHERE id_cliente = %sZcontadorr   )r   r   r   )r   re   	resultador9   r9   r:   _preview_proximo_nropedido  s
    r0  c                  C   s   d } d }zz:t } |  }|d | d krB|d |   W nV tk
r } z8z| rd|   W n tk
rz   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )Nz8SHOW COLUMNS FROM deliverypendente LIKE 'status_comanda'zGALTER TABLE deliverypendente ADD COLUMN status_comanda VARCHAR(20) NULLz[STATUS_COMANDA COLUNA ERRO]Trv   r   r   r9   r9   r:   _ensure_status_comanda_column  s(    

$r1  c                  C   s0  d } d }zzt } |  }|d |d | d krF|d |d | d krf|d |d | d kr|d |d | d kr|d	 |   W nX tk
r } z8z| r|   W n tk
r   Y nX td
|dd W 5 d }~X Y nX W 5 |r|   | r*|    X d S )Na  
            CREATE TABLE IF NOT EXISTS pedido_diarios (
                chave INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
                origem VARCHAR(20) NOT NULL,
                nropedido INT NOT NULL,
                status_pedido VARCHAR(20) NULL,
                status_comanda VARCHAR(30) NULL,
                telefone VARCHAR(30) NULL,
                cep VARCHAR(20) NULL,
                nome VARCHAR(255) NULL,
                endereco VARCHAR(255) NULL,
                nrocasa VARCHAR(40) NULL,
                complemento VARCHAR(120) NULL,
                referencia VARCHAR(255) NULL,
                bairro VARCHAR(120) NULL,
                cidade VARCHAR(120) NULL,
                estado VARCHAR(10) NULL,
                codigoproduto VARCHAR(80) NULL,
                produto VARCHAR(255) NOT NULL,
                preco DECIMAL(10,2) DEFAULT 0,
                quantidade DECIMAL(10,3) DEFAULT 1,
                obs_item TEXT NULL,
                dados_item TEXT NULL,
                obs_geral TEXT NULL,
                classe VARCHAR(120) NULL,
                cod_classe INT NULL,
                cod_usuario INT NULL,
                cliente VARCHAR(255) NULL,
                id_cliente INT NOT NULL,
                formapagamento VARCHAR(80) NULL,
                lancamento INT NULL,
                nrolancamento BIGINT NULL,
                data_criacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                INDEX idx_pd_cliente_pedido (id_cliente, nropedido),
                INDEX idx_pd_origem_status (origem, status_pedido),
                INDEX idx_pd_status_comanda (status_comanda),
                INDEX idx_pd_codproduto (codigoproduto),
                INDEX idx_pd_lancamento (lancamento, nrolancamento)
            )
            3SHOW COLUMNS FROM pedido_diarios LIKE 'status_mesa'RALTER TABLE pedido_diarios ADD COLUMN status_mesa VARCHAR(20) NULL AFTER nropedidoz2SHOW COLUMNS FROM pedido_diarios LIKE 'entregador'zOALTER TABLE pedido_diarios ADD COLUMN entregador VARCHAR(150) NULL AFTER classez2SHOW COLUMNS FROM pedido_diarios LIKE 'dados_item'zIALTER TABLE pedido_diarios ADD COLUMN dados_item TEXT NULL AFTER obs_item7SHOW COLUMNS FROM pedido_diarios LIKE 'baixa_pagamento'TALTER TABLE pedido_diarios ADD COLUMN baixa_pagamento TEXT NULL AFTER formapagamentoz[PEDIDO_DIARIOS TABELA ERRO]Trv   r   r   r9   r9   r:   _ensure_pedido_diarios_table  s@    *







$r6  c                  C   s   d } d }zz:t } |  }|d | d kr:|d |   W nV tk
r } z8z| rd|   W n tk
rz   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )N-SHOW COLUMNS FROM formapagamento LIKE 'troco'zTALTER TABLE formapagamento ADD COLUMN troco CHAR(1) NOT NULL DEFAULT 'N' AFTER formaz"[FORMAPAGAMENTO TROCO COLUNA ERRO]Trv   r   r   r9   r9   r:   #_ensure_formapagamento_troco_columnj  s,    
$r8  c                  C   s   d } d }zz:t } |  }|d | d kr:|d |   W nV tk
r } z8z| rd|   W n tk
rz   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )Nz8SHOW COLUMNS FROM pedido_diarios LIKE 'valor_pago_troco'z^ALTER TABLE pedido_diarios ADD COLUMN valor_pago_troco DECIMAL(12,2) NULL AFTER formapagamentoz&[PEDIDO_DIARIOS VALOR_PAGO_TROCO ERRO]Trv   r   r   r9   r9   r:   '_ensure_pedido_diarios_valor_pago_troco  s,    
$r9  c                  C   s   d } d }zzZt } |  }|d | d kr:|d |d | d krZ|d |   W nV tk
r } z8z| r|   W n tk
r   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )Nz3SHOW COLUMNS FROM pedido_diarios LIKE 'imp_preparo'z_ALTER TABLE pedido_diarios ADD COLUMN imp_preparo CHAR(1) NOT NULL DEFAULT 'N' AFTER dados_itemz6SHOW COLUMNS FROM pedido_diarios LIKE 'imp_preparo_em'zTALTER TABLE pedido_diarios ADD COLUMN imp_preparo_em DATETIME NULL AFTER imp_preparoz%[PEDIDO_DIARIOS PREPARO COLUNAS ERRO]Trv   r   r   r9   r9   r:   &_ensure_pedido_diarios_preparo_columns  s2    


$r:  r   impressoras_produtoc                  C   s"  |r|sd S dd }d}|D ]R}z t |tr6||nd p<d}W n tk
rX   d}Y nX t| sd} qpq|sxd S g }	|D ]V}zt |tr||nd }W n tk
r   d }Y nX ||D ]}
|
r|	|
 qqtt|	}	|	sd S z| 	d | 
 pg }W n tk
r"   Y d S X g }|D ]\}t |trX|t|dpPd n.t |ttfr,|r,|t|d pd q,d	d
 |D }d }d|krd}nd|krd}|sd S dddddddddddddg}g }|D ](}| |kr||kr|| qd|kr*|dd ddgt|	 }g }t|g}|D ](}|d| d| d ||	 qP|rd|nd }d!d"d# |D }|rd!| }d$| d%| d&| d}z"| 	|t| | 
 pg }W n tk
r   Y d S X i }|D ]}t |ts qt|d'p0d }|sBq|D ]N}|dkr`|d}n
||}||D ]}
|
rr|
|krr|||
< qrqFq|sd S |D ]t}t |tsqt||pd }|rސq||}||D ](}|r||kr|| ||<  qqqd S )(Nc                 S   sR   t | pd }|sg S |g}| }| rN|dp:d}||krN|| |S )Nr*   rN   )rH   r   r   lstripr   )vsr   s2Znzr9   r9   r:   _code_variants  s    
z6_preencher_impressoras_produto.<locals>._code_variantsFr*   TzSHOW COLUMNS FROM produtosZFieldr   c                 S   s   h | ]}|r|  qS r9   lowerr   cr9   r9   r:   	<setcomp>  s      z1_preencher_impressoras_produto.<locals>.<setcomp>
impressoraimpressorasr   r   codigoZ
codprodutoZcod_produtoZcod_itemZproduto_codigoeancodbarraZ	codbarras
cod_barras
referenciarefr   r   p.z IN (r   z OR z1=0r   c                 S   s$   g | ]}|d krd| d| qS )r   rN  z AS r9   rC  r9   r9   r:   r    s      z2_preencher_impressoras_produto.<locals>.<listcomp>z$SELECT p.chave AS chave, COALESCE(p.z,'') AS setorz. FROM produtos p WHERE p.id_cliente = %s AND (setor)r  r  r>   rW   rH   r   r   r^   fromkeysr   r   r   rB  insertry   r@   r   r   ) r   re   r   src_cod_field
dest_fieldr@  Zprecisar   r=  Zcodessvr   Z	col_namesrD  Zcol_setZ	setor_col
candidatesZ
match_colsr   Zwhere_partsr  Z	where_sqlZsel_colsqZ	prod_rowsmapar   rO  ZvvZ	cur_setorZkey_rawr   r9   r9   r:   _preencher_impressoras_produto  s     









rX  c                 C   s   |r|p
d  sdS | d |  dkr.dS | d||  f |  }|sRdS t|trxt|dpjd   }nt|d pd   }|dkS )	z3True se cadastro da forma indica troco (S/SIM/1/Y).r*   Fr7  Nz
        SELECT UPPER(TRIM(COALESCE(troco, ''))) AS t
        FROM formapagamento
        WHERE id_cliente = %s AND UPPER(TRIM(forma)) = UPPER(TRIM(%s))
        LIMIT 1
        tr   )SSIM1Y)r   r   r   r  r  rH   r>   r   )r   re   Z
nome_formar   rY  r9   r9   r:   _forma_pagamento_exige_troco6  s     

	
r^  c                  C   sF  d } d }zzt } |  }|d | d kr<|d |d | d kr\|d |d | d kr||d |d | d kr|d |d	 | d kr|d
 |   W nX tk
r } z8z| r|   W n tk
r   Y nX td|dd W 5 d }~X Y nX W 5 |r2|   | r@|    X d S )Nz2SHOW COLUMNS FROM classificacao LIKE 'op_tamanhos'z:ALTER TABLE classificacao ADD COLUMN op_tamanhos TEXT NULLz0SHOW COLUMNS FROM classificacao LIKE 'op_massas'z8ALTER TABLE classificacao ADD COLUMN op_massas TEXT NULLz0SHOW COLUMNS FROM classificacao LIKE 'op_bordas'z8ALTER TABLE classificacao ADD COLUMN op_bordas TEXT NULLz4SHOW COLUMNS FROM classificacao LIKE 'op_coberturas'z<ALTER TABLE classificacao ADD COLUMN op_coberturas TEXT NULLz4SHOW COLUMNS FROM classificacao LIKE 'op_adicionais'z<ALTER TABLE classificacao ADD COLUMN op_adicionais TEXT NULLz#[CLASSIFICACAO OPCOES COLUNAS ERRO]Trv   r   r   r9   r9   r:   $_ensure_classificacao_opcoes_columnsP  s@    









$r_  c                  C   s   d } d }zz:t } |  }|d | d kr:|d |   W nV tk
r } z8z| rd|   W n tk
rz   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )Nz)SHOW COLUMNS FROM produtos LIKE 'barcode'zEALTER TABLE produtos ADD COLUMN barcode VARCHAR(50) NULL DEFAULT NULLz[PRODUTOS BARCODE COLUNA ERRO]Trv   r   r   r9   r9   r:   _ensure_produtos_barcode_columnt  s(    

$r`  c                  C   s   d } d }zz:t } |  }|d | d kr:|d |   W nV tk
r } z8z| rd|   W n tk
rz   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )Nz/SHOW COLUMNS FROM dadosloja LIKE 'tipo_negocio'zXALTER TABLE dadosloja ADD COLUMN tipo_negocio VARCHAR(20) NOT NULL DEFAULT 'restaurante'z$[DADOSLOJA TIPO_NEGOCIO COLUNA ERRO]Trv   r   r   r9   r9   r:   _ensure_tipo_negocio_column  s,    
$ra  c                  C   s   d } d }zz:t } |  }|d | d kr:|d |   W nV tk
r } z8z| rd|   W n tk
rz   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )Nz=SHOW COLUMNS FROM dadosloja LIKE 'cliente_obrigatorio_balcao'zYALTER TABLE dadosloja ADD COLUMN cliente_obrigatorio_balcao TINYINT(1) NOT NULL DEFAULT 0z2[DADOSLOJA CLIENTE_OBRIGATORIO_BALCAO COLUNA ERRO]Trv   r   r   r9   r9   r:   )_ensure_cliente_obrigatorio_balcao_column  s,    
$rb  c                  C   s   d } d }zz:t } |  }|d | d kr:|d |   W nV tk
r } z8z| rd|   W n tk
rz   Y nX td|dd W 5 d }~X Y nX W 5 |r|   | r|    X d S )N*SHOW COLUMNS FROM clientes LIKE 'cpf_cnpj'zAALTER TABLE clientes ADD COLUMN cpf_cnpj VARCHAR(20) DEFAULT NULLz[CLIENTES CPF_CNPJ COLUNA ERRO]Trv   r   r   r9   r9   r:    _ensure_clientes_cpf_cnpj_column  s,    
$rd  c               
   C   s   z|t   t  t  t  t  t  t  t  t  t	  t
  t  t  t  t  t  t  ddlm}  |   W n8 tk
r } ztd|dd t  W 5 d }~X Y nX d S )Nr   )ensure_retail_catalog_schemaz[SCHEMA BOOTSTRAP ERRO]Trv   )ra  rb  rd  r   r`  r1  r6  r8  r9  r#   r$   r_  _ensure_impressoras_table!_ensure_terminal_impressora_table_ensure_whatsapp_config_table_ensure_whatsapp_log_table_ensure_usuario_login_otp_tableZservices.retail_catalog_schemare  rW   r~   	traceback	print_exc)re  rX   r9   r9   r:   bootstrap_schema  s.    
rm  c                  C   sx  d } d }zJzt } |  }|d |d | sB|d |d | s^|d |d | sz|d |d | s|d	 |d
 | s|d |d | s|d |d | s|d |   W n\ tk
rP } z<z| r|   W n tk
r0   Y nX td|dd W 5 d }~X Y nX W 5 |rd|   | rr|    X d S )Nz
            CREATE TABLE IF NOT EXISTS impressoras (
                id INT AUTO_INCREMENT PRIMARY KEY,
                nomedaimpressora VARCHAR(255) NOT NULL,
                imprenro TINYINT NOT NULL DEFAULT 0
            )
            -SHOW COLUMNS FROM impressoras LIKE 'imprenro'zFALTER TABLE impressoras ADD COLUMN imprenro TINYINT NOT NULL DEFAULT 0,SHOW COLUMNS FROM impressoras LIKE 'caminho'zBALTER TABLE impressoras ADD COLUMN caminho VARCHAR(512) DEFAULT ''/SHOW COLUMNS FROM impressoras LIKE 'conta_mesa'zDALTER TABLE impressoras ADD COLUMN conta_mesa VARCHAR(1) DEFAULT 'N'5SHOW COLUMNS FROM impressoras LIKE 'comanda_delivery'zJALTER TABLE impressoras ADD COLUMN comanda_delivery VARCHAR(1) DEFAULT 'N'6SHOW COLUMNS FROM impressoras LIKE 'feed_final_linhas'zOALTER TABLE impressoras ADD COLUMN feed_final_linhas TINYINT NOT NULL DEFAULT 6/SHOW COLUMNS FROM impressoras LIKE 'id_cliente'z>ALTER TABLE impressoras ADD COLUMN id_cliente INT DEFAULT NULLz1SHOW COLUMNS FROM impressoras LIKE 'data_criacao'zSALTER TABLE impressoras ADD COLUMN data_criacao TIMESTAMP DEFAULT CURRENT_TIMESTAMPz[IMPRESSORAS TABELA ERRO]Trv   r   r   r9   r9   r:   rf    sR    	













$rf  c                  C   s   d} d}zzJt } |  }|d |d | sJ|d |d |   W nV tk
r } z8z| rt|   W n tk
r   Y nX td|dd W 5 d}~X Y nX W 5 |r|   | r|    X dS )	uA   Mapeamento terminal (PC) -> caminho_local por impressora lógica.Na  
            CREATE TABLE IF NOT EXISTS terminal_impressora (
                id INT AUTO_INCREMENT PRIMARY KEY,
                terminal_id VARCHAR(120) NOT NULL,
                impressora_id INT NOT NULL,
                caminho_local VARCHAR(512) NOT NULL DEFAULT '',
                id_cliente INT NOT NULL,
                data_criacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                UNIQUE KEY uq_terminal_imp (terminal_id, impressora_id, id_cliente)
            )
            zFSHOW INDEX FROM terminal_impressora WHERE Key_name = 'uq_terminal_imp'a  
                DELETE t1 FROM terminal_impressora t1
                INNER JOIN terminal_impressora t2
                  ON t1.terminal_id = t2.terminal_id
                 AND t1.impressora_id = t2.impressora_id
                 AND t1.id_cliente = t2.id_cliente
                 AND (
                   t1.data_criacao < t2.data_criacao
                   OR (t1.data_criacao = t2.data_criacao AND t1.id < t2.id)
                 )
                z
                ALTER TABLE terminal_impressora
                ADD UNIQUE KEY uq_terminal_imp (terminal_id, impressora_id, id_cliente)
                z![TERMINAL IMPRESSORA TABELA ERRO]Trv   r   r   r9   r9   r:   rg  '  s8    
$rg  c                  C   s   d} d}zz$t } |  }|d |   W nV tk
r } z8z| rN|   W n tk
rd   Y nX td|dd W 5 d}~X Y nX W 5 |r|   | r|    X dS )u   Configuração de WhatsApp (uazapi) por loja. 1 linha por id_cliente.

    Aditiva: CREATE TABLE IF NOT EXISTS, não toca em tabelas de venda/impressão.
    Na[  
            CREATE TABLE IF NOT EXISTS whatsapp_config (
                id INT AUTO_INCREMENT PRIMARY KEY,
                id_cliente INT NOT NULL,
                ativo TINYINT NOT NULL DEFAULT 0,
                instancia_nome VARCHAR(120) DEFAULT NULL,
                instancia_token VARCHAR(255) DEFAULT NULL,
                url VARCHAR(255) DEFAULT NULL,
                notif_delivery_copia TINYINT NOT NULL DEFAULT 0,
                notif_despacho TINYINT NOT NULL DEFAULT 0,
                notif_balcao_pronto TINYINT NOT NULL DEFAULT 0,
                notif_mesa_conta TINYINT NOT NULL DEFAULT 0,
                texto_despacho_cliente TEXT,
                texto_balcao_pronto TEXT,
                data_criacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                UNIQUE KEY uq_whatsapp_config_cliente (id_cliente)
            )
            z[WHATSAPP CONFIG TABELA ERRO]Trv   r   r   r   r   r   rW   r   r~   r   r9   r9   r:   rh  _  s(    $rh  c                  C   s   d} d}zz$t } |  }|d |   W nV tk
r } z8z| rN|   W n tk
rd   Y nX td|dd W 5 d}~X Y nX W 5 |r|   | r|    X dS )z)Auditoria de envios de WhatsApp por loja.Na  
            CREATE TABLE IF NOT EXISTS whatsapp_log (
                id INT AUTO_INCREMENT PRIMARY KEY,
                id_cliente INT DEFAULT NULL,
                telefone VARCHAR(40) DEFAULT NULL,
                evento VARCHAR(60) DEFAULT NULL,
                status VARCHAR(20) DEFAULT NULL,
                erro VARCHAR(500) DEFAULT NULL,
                data TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
            z[WHATSAPP LOG TABELA ERRO]Trv   rt  r   r9   r9   r:   ri    s(    $ri  c                  C   s   d} d}zz$t } |  }|d |   W nV tk
r } z8z| rN|   W n tk
rd   Y nX td|dd W 5 d}~X Y nX W 5 |r|   | r|    X dS )u7   Códigos OTP de login via WhatsApp (5 min, uso único).Na  
            CREATE TABLE IF NOT EXISTS usuario_login_otp (
                id INT AUTO_INCREMENT PRIMARY KEY,
                usuario VARCHAR(100) NOT NULL,
                codigo_hash VARCHAR(255) NOT NULL,
                expira_em DATETIME NOT NULL,
                usado TINYINT NOT NULL DEFAULT 0,
                criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                KEY idx_otp_usuario_ativo (usuario, usado, expira_em)
            )
            z[USUARIO_LOGIN_OTP TABELA ERRO]Trv   rt  r   r9   r9   r:   rj    s(    $rj  c                 C   s.   | pd   }|dks&|r*|dr*dS dS )z8Mapeia origem do pedido para flag na tabela impressoras.r*   mesa
conta_mesacomanda_delivery)r   rB  r>   )r   dadosor9   r9   r:   _impressora_purpose_from_origem  s    rz  z/api/casa/pedido-aguardec               
   C   sB  d } d }zztd}|s4tddddfW W S tjd}ddd	 t|pRdD }|sttd
ddW W S t } | j	d
d}t
|||}|std
ddW W xS td
d
t|dW W ^S  tk
r } z8td|d
d t  tdt|ddf W Y W S d }~X Y nX W 5 |r.|   | r<|    X d S )Nre   F   Sessão inválida.r    r   r*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      z*api_casa_pedido_aguarde.<locals>.<genexpr>T)rU   
encontrado
dictionary)rU   r}  r   z[CASA PEDIDO AGUARDE ERRO]rv     )r   r   r>   r   r   argsry   rH   r   r   r   r   rW   r~   rk  rl  )r   r   re   r   r   r   rX   r9   r9   r:   api_casa_pedido_aguarde  s0    
4r  z/api/casa/pedidos-aguardec               
   C   s  d} d}zzztd}|s8tddddfW W PS t rBdnd}t } | jd	d
}|d| dtd d|f |	 pg }g }|D ]}t
|pi dpd}|sq|pi dpd}|pi dp|pi dpd}	|||t|	 t
|pi dpdd qtd	|t|dW W ^S  tk
r }
 z8td|
d	d t  tdt|
ddf W Y W S d}
~
X Y nX W 5 |r|   | r|    X dS )u[   Lista pedidos distintos ainda em AGUARDE (ex.: após novo número sem concluir o anterior).Nre   Fr{  r  r|  zAND d.origem = 'BALCAO'z%AND d.origem IN ('DELIVERY','BALCAO')Tr~  ad  
            SELECT d.nropedido AS nropedido,
                   MAX(NULLIF(TRIM(d.telefone), '')) AS telefone,
                   MAX(NULLIF(TRIM(d.nome), '')) AS nome,
                   MAX(NULLIF(TRIM(d.cliente), '')) AS cliente,
                   COUNT(*) AS linhas
            FROM pedido_diarios d
            WHERE d.id_cliente = %s
              z
              AND UPPER(COALESCE(d.status_pedido, '')) = 'AGUARDE'
              AND UPPER(COALESCE(d.status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND NOT (dzU)
            GROUP BY d.nropedido
            ORDER BY d.nropedido DESC
            r   r   r   r*   rf   r   linhas)r   r   rf   r  )rU   r   totalz[CASA PEDIDOS AGUARDE ERRO]rv   r  )r   r   r>   r   r   r   r   r   r   r   r   r   rH   r   r@   rW   r~   rk  rl  )r   r   re   Z
origem_sqlr   r   r   r  telrf   rX   r9   r9   r:   api_casa_pedidos_aguarde  sR    
 
4r  z/api/casa/buscar-cepc               
   C   sL  t jdd } ddd | D }t|dkrDtdddd	fS ztjd
| ddddid}|jdkrtddddfW S |	 }|drtddddfW S td|dd  d|dd  |dpd|dpd|dpd|dpddW S  t
k
rF } z(td|dd tdddd f W Y S d}~X Y nX dS )!uJ   Consulta ViaCEP e retorna campos de endereço (delivery e balcão varejo).r   r*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   8  s      z&api_casa_buscar_cep.<locals>.<genexpr>   Fu   CEP deve ter 8 dígitos.r    zhttps://viacep.com.br/ws/z/json/   
User-Agentznovaloja-cep/1.0timeoutrP      u   CEP não encontrado.rS   rV   TN   -
logradourobairroZ
localidadeZuf)rU   r   r  r  cidadeestadoz[BUSCAR CEP ERRO]rv   zFalha ao consultar CEP.r  )r   r  r>   r   ry   r@   r   requestsstatus_codejsonrW   r~   )Zcep_rawZ
cep_digitsr   r   rX   r9   r9   r:   api_casa_buscar_cep3  s4    



r  z/api/casa/itemPOSTc            6          s  d } d }zƐztjddpi }t|}|d}|dp>i }|dpLd }|sptddd	d
fW W dS td}|stddd	dfW W <S t| t	 } z| 
  W n tk
r   Y nX | jdd}t|dpd  }|dpd }| }	|dkr|}
n(|	dr*d}
n|	dr<d}
nd}
d}z,|d k	rjt| dkrjt|nd}W n tk
r   d}Y nX |
dkr|dkr|dt||f | sd}|
dkr|stddd	d
fW W 	S |
dkr`ddd t|p
dD }|s4tddd	d
fW W 	S t|||}|sRt|||}|r`t|}|
dkr|st rt|pi }|drt|d|}|dp|dpd }t|stddd	d
fW W S |stddd	d
fW W S |
d kr|st||}|
dkrt|||}t rt|pFi }|dr|dpn|dpnd }t|stddd	d
fW W <S |stddd	d
fW W S t|rt|||||dp|dpd |dp|dpd d! |
dkrd"}|d#| d$t||f | pDg }d}|D ]6}|pZi d}|slqNt||sNd} qqN|rt|||}|rt|}ntdd%d&d'd(fW W S |rt|n|}|
dkr t|pddkr t||t||
}|r |   |W W S t|d)}t |d*t!rJ|d*ng }t|d+p^d " }d }t|d,p~d }|r|d-||f | pi }|d.}|d kr|# rt|}d }td/}|d k	rzt|}W n tk
r   d }Y nX |d kr`ttd0p*d } | r`|d1| |f | pTi }!|!d.}t|d2}"d3}#|	rRt$|d4k	rRt%d5t$|}$|d6|t||
f | pi }%t|%d7pd}&|&d5 }'|'d8krd5}'d9d: |D   rt%t&t$  fd;d<d=nd}( r$t% nt'|d>p4d})d }*t(|D ]\}+},t|,pXi dpd| pp|}-|$d4krd?|$ d@|- }.n|-}.t|,pi dAp|dApd}/t|,pi dBpd }0|,pi dC}1|1d kr|dC}1dD}2|+|(krt'|)}2t)||
||||dEp*d |dp<d |dFpNd |dGp`d |dHprd |/|.|2t'|dIpd5t|d,pd|0|1t|dJpd|dp|dpd |||#pd3|#dKkrdLndM|'d t|dN	pdt|dO	pddP |j*}*qD| +  td|*t||'d|dQW W S |dR|t||
f | 	pti }%t|%d7	pdd5 }3|3d8k	rd5}3t)||
||||dE	pd |d	pd |dF	pd |dG	pd |dH	pd t|dA
pd|t'|d>
p&dt'|dI
p8d5t|d,
pJdt|dB
p\d|dCt|dJ
pvd|d
p|d
pd |||#
pd3|#dKk
rdLndM|3d t|dN
pdt|dO
pddP |j*}4|"r |dSt||f | +  td|4t|dTW W S  tk
r }5 z| rB|   t,dU|5ddV z.t,dW| ddV t,dXtd ddV W n tk
r   Y nX t-.  tdt|5d	dYf W Y W S d }5~5X Y nX W 5 |r|   | r|    X d S )ZNTZsilentr   itemrf   r*   Fu   Nome do item é obrigatórior  r  re   uE   Sessão inválida: id_cliente não encontrado. Faça login novamente.r|  r~  r  r   )r   r   MESAr   r  r   r   r   z
                SELECT 1
                FROM pedido_diarios
                WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
                LIMIT 1
                u   nropedido é obrigatórioc                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      z$api_casa_add_item.<locals>.<genexpr>u!   Telefone inválido para Delivery.cliente_obrigatorio_balcaor   uJ   Cliente obrigatório no balcão: informe e localize ou cadastre o cliente.u;   Cliente obrigatório no balcão: informe o nome do cliente.)r   r   rf   r   z AND origem = 'DELIVERY'  AND UPPER(COALESCE(status_pedido, '')) = 'AGUARDE'  AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO' z
                SELECT DISTINCT telefone
                FROM pedido_diarios
                WHERE nropedido = %s AND id_cliente = %s
                
                z;Pedido atual pertence a outro telefone. Localize novamente.ZCONFLITO_TELEFONE_PEDIDO)rU   rV   rH  r  
fracionadopartesformadecobrarr   z
                SELECT chave
                FROM classificacao
                WHERE nomeclassificacao = %s AND id_cliente = %s
                LIMIT 1
                r   
id_usuariorI   
                    SELECT chave
                    FROM usuarios
                    WHERE usuario = %s AND id_cliente = %s
                    LIMIT 1
                    em_recuperacaor   r%  r   z
                SELECT COALESCE(MAX(lancamento), 0) AS max_lancamento
                FROM pedido_diarios
                WHERE id_cliente = %s AND nropedido = %s AND origem = %s
                max_lancamentoc                 S   s"   g | ]}t |pi d pdqS )r   r   )r   r>   r   pr9   r9   r:   r  %  s     z%api_casa_add_item.<locals>.<listcomp>c                    s    |  S r   r9   )iZprecosr9   r:   r   &  r   z#api_casa_add_item.<locals>.<lambda>)r   r   z1/rq   r   r   r           r   r   r   r   qtdr   r   
MODIFICADAr   r   r   r   r   re   r   r   rf   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rU   idr   r   r  r  
            SELECT COALESCE(MAX(lancamento), 0) AS max_lancamento
            FROM pedido_diarios
            WHERE id_cliente = %s AND nropedido = %s AND origem = %s
            z
                UPDATE pedido_diarios
                SET status_comanda = 'MODIFICADA'
                WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
                )rU   r  r   z[CASA ADD ITEM ERRO]rv   z[CASA ADD ITEM ERRO] payload=z'[CASA ADD ITEM ERRO] id_cliente_sessao=r  )/r   r   get_jsonr  r>   r   r   r   r!  r   start_transactionrW   r   rH   r   r?   r   r   r   ry   r   r   r   _normalizar_telefone_balcao_telefone_whatsapp_validor-   _propagar_telefone_balcao_pedidor   r   r   r   boolr  r^   rB  r   r@   maxr&  r   	enumerater   	lastrowidr   r~   rk  rl  )6r   r   r   r   r  rf   re   Zmodo_payloadr   Ztelefone_upperr   Znropedido_intZtelefone_digitsZpedido_aguardeZdados_loja_cfgZ	tel_checkZnome_clistatus_clauseZtelefones_pedidoZconflito_telefoner   Ztel_existenteZpedido_aguarde_telblockedr  r  r  r   Zclasse_nomeZrow_clsr   id_usuario_sessaorI   row_usrr  Zstatus_pedido_insertZqtd_escolhidarow_maxr  r   Z	maior_idxZ
preco_baseZ
last_pd_idr  parteZ
nome_parteZnome_parte_dbZ	cod_parteZ	obs_parteZdados_parteZpreco_parteZlancamento_simplesZnovo_idrX   r9   r  r:   api_casa_add_itemS  sD   


,

	

 


 



	

 	




	

&"$
&



"

4r  z/api/casa/<int:nropedido>c           .      C   sN  d }d }z zPt  td}|d krBtddddfW W S ttjdp\t rZdnd	 
 }t rz|d	krzd}ttjd
pd	  }ddd ttjdpdD }t }|jddd}d }d }zn|d | d k	rd}n|d | d k	rd}dD ],}	|d|	f | d k	r|	} qBqW n tk
rb   d }d }Y nX |dk}
|dk}|dk}ttjdpd	  }|
r|stdg ddW W pS d}|r|dkrdnd}|}|r|dkr
d}n|
r d}n
|r
d}d}d }| ||g}d!}|rJd"}| |g}|d#krJd }| ||g}|rj|r\d$}nd%}|| |r|d&| d'nd(}d}|r|rd)| d*}nd+}|r|rd,| nd}g }d-| d.| d/| d0| d0| d1}z"||t| | pg }W np tk
rv } zPtd2|dd3 t  d4| d5| d5| d6}||t| | pdg }W 5 d }~X Y nX |
rg }|D ]`}dd7d t|dpdD }|sq||ks||s||r|| q|}t||| t|||d8d9d: d;d< |D }d}d}d } |r|d= d>p<d	 }t|d= d?pVd	 }|d= d@}!|!d k	rt|!	 dkrzt|!} W n ttfk
r   d } Y nX i }"d}#|rJ|d= }$t|$dpd	  }#|$dpd|$dApd|$dBpd|$dCpd|$dDp,ddddd|$dEpBddF
}"n|r(|d#krn|dG| ||f n|dH| |f | pi }%t|%dpd	  }#|%r(t|%d>pd	 }|%dpd|%dApd|%dBpd|%dCpd|%dDpddddd|%dEp"ddF
}"dI}&|rb|d#krP|dJ| ||f n|dK| |f n|dL| ||f | pi }'t|'pi dMpdI	  pdI}&d}(d})d}*zLt||t| |#p|}+t |+dN}(t |+dO})t|+dPpd}*W n0 tk
r2   d}(|&t!k})|)r.d}(dQ}*Y nX td|||| |"|&|#pL||(|)|*dRW W S  tk
r& } ztdS|dd3 t  t" },zPdTdU| dVtddWt#tjt$|j% dX||,g}-t&dY|- W n tk
r   Y nX tdt|ddZf W Y W S d }~X Y nX W 5 |r:|   |rH|   X d S )[Nre   Fu5   Sessão sem loja (id_cliente). Faça login novamente.r  r|  r  r  deliveryr  ru  statusr*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      z(api_casa_listar_itens.<locals>.<genexpr>r   T)r  Zbuffered,SHOW COLUMNS FROM produtos LIKE 'impressora'rF  -SHOW COLUMNS FROM produtos LIKE 'impressoras'rG  r   rH  rJ  rK  rI  "SHOW COLUMNS FROM produtos LIKE %sZrecuperacao)r  ru  r   )rU   	registrosr   r   r   r  r   r   z AND d.origem = %s z= AND UPPER(COALESCE(d.status_pedido, '')) <> 'ITEM_REMOVIDO' z' AND d.origem IN ('DELIVERY','BALCAO') r   zK AND UPPER(COALESCE(d.status_pedido, '')) IN ('ABERTO','ABERTA','AGUARDE') z/ AND UPPER(COALESCE(d.status_pedido, '')) = %s COALESCE(p.,'') AS impressoras_produto'' AS impressoras_produtoz`p.id_cliente = d.id_cliente AND (p.chave = CAST(d.codigoproduto AS UNSIGNED) OR TRIM(COALESCE(p.z+,'')) = TRIM(COALESCE(d.codigoproduto,'')))zKp.id_cliente = d.id_cliente AND p.chave = CAST(d.codigoproduto AS UNSIGNED)LEFT JOIN produtos p ON a  
            SELECT d.chave AS chave, d.nropedido, d.produto, d.preco, d.quantidade, d.codigoproduto, d.classe, d.obs_item, d.dados_item, d.obs_geral,
                   '' AS descricao_produto, d.telefone, d.origem,
                   d.nome, d.endereco, d.nrocasa, d.complemento, d.cep,
                   COALESCE(d.lancamento, 0) AS lancamento,
                   COALESCE(d.formapagamento, '') AS formapagamento,
                   d.valor_pago_troco,
                   COALESCE(d.imp_preparo,'N') AS imp_preparo,
                   z/
            FROM pedido_diarios d
            zF
            WHERE d.nropedido = %s AND d.id_cliente = %s
            
            z+
            ORDER BY d.chave DESC
        z4[CASA] Falha ao executar query com join de produtos:rv   a  
                SELECT d.chave AS chave, d.nropedido, d.produto, d.preco, d.quantidade, d.codigoproduto, d.classe, d.obs_item, d.dados_item, d.obs_geral,
                       '' AS descricao_produto, d.telefone, d.origem,
                       d.nome, d.endereco, d.nrocasa, d.complemento, d.cep,
                       COALESCE(d.lancamento, 0) AS lancamento,
                       COALESCE(d.formapagamento, '') AS formapagamento,
                       d.valor_pago_troco,
                       COALESCE(d.imp_preparo,'N') AS imp_preparo,
                       '' AS impressoras_produto
                FROM pedido_diarios d
                WHERE d.nropedido = %s AND d.id_cliente = %s
                r  z3
                ORDER BY d.chave DESC
            c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   '  s      r   r;  rR  rS  c                 S   s   g | ]}t |qS r9   convert_typesr   r   r9   r9   r:   r  /  s     z)api_casa_listar_itens.<locals>.<listcomp>r   r   r   valor_pago_trocorf   r   r   r   r   )
r   rf   r   r   r   rL  r  r  r  r   a&  
                    SELECT d.telefone, d.nome, d.endereco, d.nrocasa, d.complemento, d.cep,
                           UPPER(COALESCE(d.origem, '')) AS origem,
                           UPPER(COALESCE(d.status_comanda, 'NORMAL')) AS st_comanda,
                           COALESCE(d.obs_geral, '') AS obs_geral
                    FROM pedido_diarios d
                    WHERE d.nropedido = %s AND d.id_cliente = %s
                      AND d.origem = %s
                    ORDER BY d.chave DESC
                    LIMIT 1
                    a:  
                    SELECT d.telefone, d.nome, d.endereco, d.nrocasa, d.complemento, d.cep,
                           UPPER(COALESCE(d.origem, '')) AS origem,
                           UPPER(COALESCE(d.status_comanda, 'NORMAL')) AS st_comanda,
                           COALESCE(d.obs_geral, '') AS obs_geral
                    FROM pedido_diarios d
                    WHERE d.nropedido = %s AND d.id_cliente = %s
                      AND d.origem IN ('DELIVERY','BALCAO')
                    ORDER BY d.chave DESC
                    LIMIT 1
                    r   a  
                    SELECT UPPER(COALESCE(status_comanda, 'NORMAL')) AS st
                    FROM pedido_diarios
                    WHERE nropedido = %s AND id_cliente = %s AND origem = %s
                    ORDER BY chave DESC
                    LIMIT 1
                    a-  
                    SELECT UPPER(COALESCE(status_comanda, 'NORMAL')) AS st
                    FROM pedido_diarios
                    WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
                    ORDER BY chave DESC
                    LIMIT 1
                    a  
                SELECT UPPER(COALESCE(status_comanda, 'NORMAL')) AS st
                FROM pedido_diarios
                WHERE nropedido = %s AND id_cliente = %s AND origem = %s
                ORDER BY chave DESC
                LIMIT 1
                r  r  r  r  r  )rU   r  r   r   r  r   r   r   pedido_bloqueado_casar  r  z[CASA LISTA ERRO]ro   z
nropedido=zid_cliente_session=zrequest.args=: z[api_casa_listar_itens]r  )'r   r:  r   r>   r   rH   r   r  r   r   rB  r   ry   r   r   r   r   rW   r   r   r   r~   rk  rl  r   r   rX  r   r   r   r  r   r  STATUS_COMANDA_CANCELADA
format_excr  typerE   r   ).r   r   r   re   r  Z
status_reqZtelefone_reqprod_imp_colprod_cod_colcandZmodo_is_deliveryZmodo_is_recuperacaoZmodo_is_balcao_ou_mesaZ
origem_reqZ	origem_dbZstatus_finalr  Zorigem_clauser  Zstatus_removido_clauseimp_seljoin_on	join_prodregsZ
query_mainrX   query_fallbackZ	filtradosr   r   r   Z
forma_headZvalor_pago_troco_headZvrawcliente_dataZorigem_encontradabaseZbase_anyr   Zrow_scr  r  r  Zinfo_blktbctxr9   r9   r:   api_casa_listar_itens  s   
&$









 $"



(
	4r  z,/api/casa/<int:nropedido>/item/<int:item_id>ZPATCHc              
   C   s<  d }d }zztjddpi }|dd }|dd }|dd }|d krv|d krv|d krvtdddd	fW W S td
}t }| }t||| }	|	r|	W W rS g }
g }|d k	rt	|pd}|dkrtdddd	fW W 4S |

d |
| |d k	r"|

d |
t|  |d k	rH|

d |
t|  ||| |g |dd|
 d| |  |jdkrtddddfW W ~S tddiW W lS  tk
r } zF|r|  td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r(|   |r6|   X d S )NTr  r  r   r   FNada para atualizarr  r  re   r   "Quantidade deve ser maior que zeroquantidade = %sobs_item = %sdados_item = %szUPDATE pedido_diarios SET r   z\ WHERE chave = %s AND nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')   Item não encontradorS   rU   z[CASA PATCH ITEM ERRO]rv   r  )r   r   r  r>   r   r   r   r   r   r   r   rH   r   r   r   ry   r   rowcountrW   r   r~   rk  rl  )r   item_idr   r   r   qtd_rawr   r   re   r  	set_partsr  r  rX   r9   r9   r:   api_casa_alterar_item  s`    






4r  z#/api/casa/<int:nropedido>/obs-geralc              
   C   s  d }d }zztjddpi }|dp(d }td}t }| }t||| }|r`|W W S |	d|| |f |
  tddiW W hS  tk
r } zD|r|  td|dd	 t  td
t|ddf W Y W S d }~X Y nX W 5 |r |   |r|   X d S )NTr  r   r*   re   zuUPDATE pedido_diarios SET obs_geral = %s WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')rU   z[CASA OBS GERAL ERRO]rv   Fr  r  )r   r   r  r>   r   r   r   r   r   r   r   r   rW   r   r~   rk  rl  rH   )r   r   r   r   r   re   r  rX   r9   r9   r:   api_casa_obs_geral	  s6    

4r  ZDELETEc              
   C   s  d }d }zj ztd}t }| }t||| }|rD|W W 4S |d|| |f | }|s|tddddfW W  S t	|d pd}t
|d pd	 }t
|d
 pd	 pd}	|dkr|d| ||	|f n|d|| ||	f |j}
|  td|
dW W lS  tk
rp } zF|r,|  td|dd t  tdt
|ddf W Y W S d }~X Y nX W 5 |r|   |r|   X d S )Nre   ab  
            SELECT COALESCE(lancamento, 0) AS lancamento,
                   UPPER(COALESCE(status_pedido,'')) AS status_pedido,
                   UPPER(COALESCE(origem,'')) AS origem
            FROM pedido_diarios
            WHERE chave = %s AND nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
            LIMIT 1
            Fr  r  rS   r   r   r*   r%  r   z
                UPDATE pedido_diarios
                SET status_pedido = 'ITEM_REMOVIDO'
                WHERE nropedido = %s AND id_cliente = %s AND origem = %s AND lancamento = %s
                z
                UPDATE pedido_diarios
                SET status_pedido = 'ITEM_REMOVIDO'
                WHERE chave = %s AND nropedido = %s AND id_cliente = %s AND origem = %s
                TrU   Z	removidosz[CASA DELETE ITEM ERRO]rv   r  )r   r   r>   r   r   r   r   r   r   r   rH   r   r  r   rW   r   r~   rk  rl  )r   r  r   r   re   r  r   r   Zstatus_pedido_alvoZorigem_alvoremovidos_pdrX   r9   r9   r:   api_casa_remover_item.	  sR    

	
4r  c              
   C   s   d }d }zzdtd}t }| }t||| }|r>|W W S |d| |f |j}|  t	d|dW W hS  t
k
r } zD|r|  td|dd t  t	dt|dd	f W Y W S d }~X Y nX W 5 |r|   |r|   X d S )
Nre   z
            UPDATE pedido_diarios
            SET status_pedido = 'ITEM_REMOVIDO'
            WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
            Tr  z[CASA LIMPAR PEDIDO ERRO]rv   Fr  r  )r   r   r>   r   r   r   r   r  r   r   rW   r   r~   rk  rl  rH   )r   r   r   re   r  r  rX   r9   r9   r:   api_casa_limpar_pedidon	  s4    

4r  z(/api/casa/<int:nropedido>/formapagamentoc              
   C   sp  d }d }zBztjddpi }|dp,d }|sPtddddfW W  S td	}|d
d }d }|d k	rt| dkrztt| 	dd}W n2 t
tfk
r   tddddf Y W W S X t }| }t  t||| }|r|W W LS |d| |f | p d}	t|	r2|	d ndp:d}
t|||}d }|r|d krxtddddfW W S |d |
k rtddddfW W S |}d}|d| d| |f | pd}t|r|d ndpd}|dkr|d| |f | pd}t|r"|d ndp*d}|dkr>d}nV|d| |f | pZd}t|rl|d ndptd}|dkrd}nd|  d}td|ddfW W S |d| d||| |f |  tdd d!W W lS  tk
rH } zF|r|  td"|dd# t  tdt|dd$f W Y W S d }~X Y nX W 5 |r\|   |rj|   X d S )%NTr  formar*   Fu"   Forma de pagamento é obrigatóriar  r  re   r  r   .u   Valor pago inválido.a-  
            SELECT COALESCE(SUM(COALESCE(preco, 0) * COALESCE(quantidade, 0)), 0) AS tot
            FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
              AND UPPER(TRIM(COALESCE(status_pedido, ''))) <> 'ITEM_REMOVIDO'
            r9   r   zGInforme com quanto o cliente vai pagar (valor maior ou igual ao total).gư>z6Valor pago deve ser maior ou igual ao total do pedido.zA AND UPPER(TRIM(COALESCE(status_pedido, ''))) <> 'ITEM_REMOVIDO' z
            SELECT COUNT(*) FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
            r  r   z
                SELECT COUNT(*) FROM pedido_diarios
                WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
                u^   Não há itens ativos neste pedido (itens removidos). Adicione itens ou abra o pedido correto.zLSELECT COUNT(*) FROM pedido_diarios WHERE nropedido = %s AND id_cliente = %sux   Pedido encontrado com outra origem (ex.: mesa). Na /casa só é possível definir pagamento em pedidos delivery/balcão.zPedido #um    não encontrado para esta loja ou ainda sem linhas em pedido_diarios. Recarregue a tela e confira o número.rS   a  
            UPDATE pedido_diarios
            SET formapagamento = %s,
                valor_pago_troco = CASE WHEN origem = 'DELIVERY' THEN %s ELSE NULL END
            WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
            zForma de pagamento atualizadarU   mensagemz[CASA FORMAPAGAMENTO ERRO]rv   r  )r   r   r  r>   r   r   r   rH   r   replacer   r   r   r   r9  r   r   r   r^  r   r   rW   r   r~   rk  rl  )r   r   r   r   r  re   Zraw_vpZ	valor_reqr  Zrow_totZtotal_pedidoZexigeZvalor_para_deliveryZwc_ativor  Zn_ativosZrow_gZ
n_qualquermsgZrow_aZn_outra_origemrX   r9   r9   r:   api_casa_formapagamento	  s    
 	






4r  z%/api/casa/<int:nropedido>/ajuste-itemc                 C   s&  d }d }zztjddpi }t|dp.d}|dkrTtddddfW W S td	}t }|jdd
}t	||| }|r|W W zS |
d| |f | }|stddddfW W DS d }|d}|d krtddddfW W S d }	td}
|
d k	r2zt|
}	W n tk
r0   d }	Y nX |	d krttdpLd }|r|
d||f | pvi }|d}	|	d krtddddfW W `S t|dpd dkrdnd}|dkrdnd}d}t|dpd  p&t|dpd dr$dnd}|
d t| |||f |
d!|t| |f | pbi }t|d"ptdd# }|d$krd#}t||| |t|dpdt|d%pdt|d&pdt|d'pdt|d(pdt|d)pd||t|d*dt|d+pd ddt|d,pD|d&pDd||	|d-|d t|d.pbdt|d/ptdd0 |  td||d1W W lS  tk
r } zF|r|  td2|dd3 t  tdt|dd4f W Y W S d }~X Y nX W 5 |r|   |r |   X d S )5NTr  valorr   F+Valor do ajuste deve ser diferente de zero.r  r  re   r~  a  
            SELECT telefone, cep, nome, endereco, nrocasa, complemento, cliente, formapagamento,
                   cod_classe, entregador, origem,
                   UPPER(COALESCE(status_pedido,'')) AS status_pedido
            FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem IN ('DELIVERY','BALCAO')
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            ORDER BY chave DESC
            LIMIT 1
            z%Pedido sem itens para aplicar ajuste.rS   r   u<   Não foi possível resolver cod_classe para ajuste técnico.r  rI   r*   r  r   u;   Não foi possível resolver cod_usuario do usuário logado.r   r   r   
TAXA EXTRADESCONTOAJUSTE_TECNICOr   r   r   r   z
            DELETE FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND codigoproduto = %s AND origem = %s
            r  r  r   r  r   rf   r   r   r         ?r   r   r  r   r   r  rU   r   r  z[CASA AJUSTE ITEM ERRO]rv   r  )r   r   r  r   r>   r   r   r   r   r   r   r   r   rW   rH   r   r   r?   r   r   r   r~   rk  rl  )r   r   r   r   r  re   r  r  r   r   r  rI   r  status_insertr   r   Z	origem_pdr  r   rX   r9   r9   r:   api_casa_ajuste_item
  s    






	

&F
4r  z/api/casa/ddd-padraoc               
   C   s   zXt d} t| }t|pi dp&d }ddd |D d d }td|dW S  tk
r } z4td	|dd
 t	
  tdt|ddf W Y S d }~X Y nX d S )Nre   dddr*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   
  s      z&api_casa_ddd_padrao.<locals>.<genexpr>r$  T)rU   r  z[CASA DDD PADRAO ERRO]rv   Fr  r  )r   r>   r   rH   r   ry   r   rW   r~   rk  rl  )re   rx  r  rX   r9   r9   r:   api_casa_ddd_padrao
  s    
r  c                  C   s`   t tdpd  dkr4dtddddffS td	} | sXdtdd
ddffS | dfS )uT   Retorna (id_cliente, None) se ok; (None, resposta_json) se inválido/sem permissão.funcaor*   ZgerenteNFzAcesso restrito a gerentes.r    re   r{  r|  )rH   r   r>   r   rB  r   )re   r9   r9   r:   _whatsapp_id_cliente_ou_401
  s    
r  c                 C   sX   z<t | }ddd t|pi dp&dD d d }|W S  tk
rR   Y dS X d S )Nr*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   
  s      z%_whatsapp_ddd_loja.<locals>.<genexpr>r  r$  )r   ry   rH   r>   rW   )re   rx  r  r9   r9   r:   _whatsapp_ddd_loja
  s    .r  c                 C   s   d dd t| pi dpdD }d dd t| p8i dpBdD }|rh|rht|dkrh|| }|spdS t|dkrd	|d
d  d|dd  d|dd
  S t|dkrd	|d
d  d|dd  d|dd
  S |S )z@Telefone da loja formatado como (DD) NNNNN-NNNN para a mensagem.r*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   
  s      z#_wa_tel_loja_fmt.<locals>.<genexpr>r   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r   
  s      r  	      (Nr%  z)    r  
   r  )ry   rH   r>   r@   )rl   r  r  r9   r9   r:   _wa_tel_loja_fmt
  s    &&..r  c                 C   s   t | dpd }t | dp$d }t | dp:d }t | dpPd }|s`|rx| d| d nd}dd |||fD }d	|S )
uK   Monta a linha de endereço do cliente a partir da linha agregada do pedido.r   r*   r   r  r  r   c                 S   s   g | ]}|r|qS r9   r9   r  r9   r9   r:   r  
  s      z(_wa_endereco_cliente.<locals>.<listcomp> - )rH   r>   r   ry   )pedZruar   r  r  r  r  r9   r9   r:   _wa_endereco_cliente
  s    $r  c           
      C   s   t | pi dpd }t |dp2|dp2d }t |dpHd }t| }g }|rr|d| d |rd| dnd}	||	 d| d	 |r|d
| d n
|d |r|d |d|  d|S )Nrf   r*   r   u	   🏍️ **   Olá, ! Seu pedido *#u   * saiu para entrega 🚀zO entregador *u   * está a caminho 😊u   Já está a caminho 😊u   📞 Dúvidas? ro   )rH   r>   r   r  r   ry   )
rl   r  entr   	nome_lojar   r   tel_lojar  saudr9   r9   r:   _montar_msg_despacho_cliente
  s      

r  c              
   C   s  t | dp| dpd }t | dp.d }t | dpDd }t | dpZd }t | dppd }zt| dpd	}W n ttfk
r   d
}Y nX d|d dddddd}	t| }
d| dg}|r|d|  |r|d|  |r|d |d |D ]}|dp@d	}z*t|t	t|krbt	|nt|}W n ttfk
r   |}Y nX t |dpd }|r.|d| d|  q.|d |
r|d|
  g }|r|d|  |r|d|  |r.|dd
|  g }|rH|d|  |d|	  |d 
| |
r|d!t|
  d"
|S )#Nrf   r   r*   r   r   rL  r   r  r   r  zR$ z,.2fr   Xr  u   🛵 *Entrega - Pedido #r  u   👤 Cliente: u   📞 u   🛍️ *Itens*r   r   u   • zx    📍 zCompl.: zRef.: u   🏠 z / u   💳 u   💰 Total: u     •  u>   🗺️ Mapa: https://www.google.com/maps/search/?api=1&query=ro   )rH   r>   r   r   r   r   r  r  r   r   ry   r   )r  r   r   r   r  ZcomplrM  r  r  Z	total_fmtr   r  itr  ZqfprodextraZ	pag_totalr9   r9   r:   _montar_msg_despacho_entregador
  s\     
$

*

r$  c                 C   sF   t | pd }|r"| dr&dS ddd |D }t|dkS )u:   True se telefone parece real (não placeholder BALCAO{n}).r*   r   Fc                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      z,_telefone_whatsapp_valido.<locals>.<genexpr>r  )rH   r   r   r?   ry   r@   )r   rY  digitsr9   r9   r:   r    s
    r  c           	   	   C   s  zt |p
d}W n ttfk
r,   d}Y nX t| p6d }| }ddd |D }|dksx|drt|dk r|dkrd| S dS |dst|dkrt	|pi }ddd t|
d	pdD d
d }t|dkr|r|| S |S |dkr
d| S dS )z=Placeholder BALCAO{n} ou celular normalizado com DDD da loja.r   r*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      z._normalizar_telefone_balcao.<locals>.<genexpr>)r*   r   r   r  c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      r  Nr$  )r  r  )r   r   r   rH   r   r   ry   r?   r@   r   r>   )	r   r   re   r   tel_payloadZ	tel_upperr   Zdados_loja_bZddd_br9   r9   r:   r    s     
*r  c              	   C   s   zt |p
d}W n ttfk
r*   Y dS X |dkr8dS t|||}t|sPdS dg}|g}	t|pdd }
|
r|ddg |	|
t|p|
 g |	||g | dd	| d	t
|	 d
S )uN   Atualiza telefone (e opcionalmente nome) em todas as linhas do pedido balcão.r   Fztelefone = %sr*   z	nome = %szcliente = %sz+
        UPDATE pedido_diarios
        SET r   z
        WHERE id_cliente = %s AND origem = 'BALCAO' AND nropedido = %s
          AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
        T)r   r   r   r  r  rH   r   r   r   ry   r   )r   re   r   r   rf   r   r   r   setsr  Z
nome_limpor9   r9   r:   r  #  s.    	r  c                 C   sv   g }t  }t| pddD ].}| }|r||kr6q|| || q|D ]}t|rP|  S qP|rr|d S dS )uI   Escolhe celular real entre vários telefones concatenados (GROUP_CONCAT).r*   r   r   )r   rH   splitr   r   r   r  )telefones_concat
candidatosvistosr  rY  r9   r9   r:   _telefone_de_concatA  s    

r,  c                 C   sx  t |dp|dpd }t | p(i dp2d }t| }ddd t | pTi dp^d t | pli dpvd fD }t |pd }|r|d	|d
t |d|d|d|S g }	|r|	d| d |rd| dnd}
|	|
 d| d |	d |s$|rZ|	d |rD|	d|  |rZ|	d|  |	d |	d d|	S )Nrf   r   r*   r   c                 s   s   | ]}|r|V  qd S r   r9   r  r9   r9   r:   r   U  s   z,_montar_msg_balcao_pronto.<locals>.<genexpr>r   r  z{nome}z{pedido}z{loja}z
{telefone}z
{endereco}u	   🍽️ *r  r  r  r  u   * está pronto 🎉u   Já pode retirar no balcão.u   📞 *Fale com a loja:* r   u    Obrigado pela preferência! 🙏ro   )rH   r>   r   r  ry   r  r   )rl   r  r   texto_customr   r  r  Zend_lojaZcustomr  r  r9   r9   r:   _montar_msg_balcao_prontoQ  sN     
    



r.  c                 C   sz  t  r
dS t| pi }tt|dp(do:t|d}|rRt|dpNdsVdS d}d}zjt }|jdd}|	d| |f |
 pi }|	d	| |f | pg }|	d
|| f |
 pi }	W 5 |r|  |r|  X t| pi }
t| }t|dpd }|r8t|
||	|}tj| ||d|d t|	dpHd }|rvt|||}tj| ||d|d dS )uL   Dispara avisos de despacho (cliente + entregador). Não-bloqueante, isolado.Nativor   instancia_tokennotif_despachoTr~  ah  
            SELECT MAX(nome) AS nome, MAX(cliente) AS cliente, MAX(telefone) AS telefone,
                   MAX(endereco) AS endereco, MAX(nrocasa) AS nrocasa,
                   MAX(complemento) AS complemento, MAX(referencia) AS referencia,
                   MAX(bairro) AS bairro, MAX(cidade) AS cidade,
                   MAX(formapagamento) AS formapagamento,
                   SUM(COALESCE(preco,0)*COALESCE(quantidade,0)) AS total
            FROM pedido_diarios
            WHERE id_cliente=%s AND origem='DELIVERY' AND nropedido=%s
              AND UPPER(COALESCE(status_pedido,''))='ROTA'
            z
            SELECT produto, quantidade
            FROM pedido_diarios
            WHERE id_cliente=%s AND origem='DELIVERY' AND nropedido=%s
              AND UPPER(COALESCE(status_pedido,''))='ROTA'
            ORDER BY chave
            zNSELECT nome, telefone FROM entregador WHERE chave=%s AND id_cliente=%s LIMIT 1r   r*   Zdespacho_clienteZeventoZ
ddd_padraoZdespacho_entregador)r   uazapi_serviceobter_configr  r   r>   r   r   r   r   r   r   r   r  rH   r   r  Zenviar_texto_asyncr$  )re   r   codigo_entregadorcfgr/  r   r   r  r   r  rl   r  Ztel_cliZmsg_cliZtel_entZmsg_entr9   r9   r:   _notificar_despacho_whatsapps  sh    $

        r7  z/api/whatsapp/configc                  C   s  t  \} }|r|S zt| p i }tdt|dp4d|dpBdt|dt|dp\dt|dpldt|d	p|dt|d
pd|dpd|dpdd
W S  tk
r } z4td|dd t	
  tdt|ddf W Y S d }~X Y nX d S )NTr/  r   instancia_nomer*   r0  notif_delivery_copiar1  notif_balcao_prontonotif_mesa_contatexto_despacho_clientetexto_balcao_pronto)
rU   r/  r8  Z	tem_tokenr9  r1  r:  r;  r<  r=  z[WHATSAPP CONFIG GET ERRO]rv   Fr  r  )r  r3  r4  r   r   r>   r  rW   r~   rk  rl  rH   )re   errr6  rX   r9   r9   r:   api_whatsapp_config_get  s*    

r?  c                     s  t  \} }|r|S d }d }zHztjddp.i   fdd}t }| }|d| f | }|d|d|d|d	|d
 dpd  dpd f}|r|d|| f  n|d|| f  |	  t
dddW W S  tk
r` } zbz|r|  W n tk
r   Y nX td|dd t  t
dt|ddf W Y W S d }~X Y nX W 5 |rt|  |r|  X d S )NTr  c                    s"   t  |   dkrdS dS )N)r\  truesimonyesr   r   )rH   r>   r   rB  )rf   bodyr9   r:   _flag  s    z'api_whatsapp_config_post.<locals>._flagz<SELECT id FROM whatsapp_config WHERE id_cliente = %s LIMIT 1r/  r9  r1  r:  r;  r<  r=  aG  
                UPDATE whatsapp_config
                   SET ativo = %s, notif_delivery_copia = %s, notif_despacho = %s,
                       notif_balcao_pronto = %s, notif_mesa_conta = %s,
                       texto_despacho_cliente = %s, texto_balcao_pronto = %s
                 WHERE id_cliente = %s
                a,  
                INSERT INTO whatsapp_config
                    (ativo, notif_delivery_copia, notif_despacho, notif_balcao_pronto,
                     notif_mesa_conta, texto_despacho_cliente, texto_balcao_pronto, id_cliente)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
                u!   Configuração de WhatsApp salva.r  z[WHATSAPP CONFIG POST ERRO]rv   Fr  r  )r  r   r   r  r   r   r   r   r>   r   r   rW   r   r~   rk  rl  rH   )re   r>  r   r   rF  existecamposrX   r9   rD  r:   api_whatsapp_config_post  sX    
		4rI  z/api/whatsapp/servidor-statusc                  C   s   t  } tddi| S )u=   Diagnóstico uazapi no .env do servidor (sem expor segredos).rU   T)r3  Zservidor_env_statusr   )r  r9   r9   r:   api_whatsapp_servidor_status  s    rJ  z/api/whatsapp/instancia/criarc                  C   sx   t  \} }|r|S tjddp i }|dp.d p<d|  }t| |}t|dd|dd	|drrd
ndfS )NTr  rf   r*   Zloja_okFrV   r  r  r  )r  r   r  r>   r   r3  Zcriar_instanciar   )re   r>  rE  rf   resr9   r9   r:   api_whatsapp_instancia_criar  s    
rM  z /api/whatsapp/instancia/conectarc                  C   s   t  \} }|r|S tjddp i }tj| |dp4d d}t|dd|d|d|d	|d
d|drzdndfS )NTr  phone)rN  rK  Fqrcodepaircoder  rV   )rU   rO  rP  r  rV   r  r  )r  r   r  r3  Zconectar_instanciar>   r   )re   r>  rE  rL  r9   r9   r:   api_whatsapp_instancia_conectar)  s    

rQ  z/api/whatsapp/instancia/statusc                  C   sL   t  \} }|r|S t| }t|dd|dd|dd|ddS )NrK  Fr  ZdisconnectedconfiguradorV   )rU   r  rR  rV   )r  r3  Zstatus_instanciar   r>   re   r>  rL  r9   r9   r:   api_whatsapp_instancia_status:  s    




rT  z#/api/whatsapp/instancia/desconectarc                  C   sJ   t  \} }|r|S t| }t|dd|dd|drDdndfS )NrK  FrV   r  r  r  )r  r3  Zdesconectar_instanciar   r>   rS  r9   r9   r:   "api_whatsapp_instancia_desconectarI  s
    

rU  z/api/whatsapp/enviar-testec                  C   s   t  \} }|r|S tjddp i }|dp.d }|sJtddddfS |d	pVd
 }tj| ||dt| d}t|dd|dd|drdndfS )NTr  r   r*   FzInforme um telefone.r  r  r  z*Mensagem de teste do sistema (LojaOnline).tester2  rK  rV   r  )	r  r   r  r>   r   r   r3  enviar_textor  )re   r>  rE  r   r  rL  r9   r9   r:   api_whatsapp_enviar_testeS  s     
    rX  z/api/whatsapp/recursosc                  C   s  z4t d} | s&tddddfW S t| p2i }tt|dpDdoVt|d}t| pbi }|d	ppd
 t	|dpd
 t	|dpd
 |dpd
 |dpd
 |dpd
 d}td|tt|dpdtt|dpdtt|dpdtt|dp(d|dW S  t
k
r } z,td|dd tdt	|ddf W Y S d}~X Y nX dS )u   Informa ao PDV quais recursos de WhatsApp estão ligados (sem expor token).

    Disponível para qualquer usuário logado (o atendente do /casa pode não ser gerente).
    re   Fr{  r  r|  r/  r   r0  rf   r*   r   r  r   r  r  )rf   r   r  r   r  r  Tr9  r1  r:  r;  )rU   r/  r9  r1  r:  r;  lojaz[WHATSAPP RECURSOS ERRO]rv   r  N)r   r>   r   r3  r4  r  r   r   r   rH   rW   r~   )re   r6  r/  rx  rY  rX   r9   r9   r:   api_whatsapp_recursosd  s4    
$
	rZ  z/api/whatsapp/enviar-pedidoc               
   C   s  z@t d} | s&tddddfW S tjddp4i }|dpBd	 }|d
pTd	 }|srtddddfW S |stddddfW S t| pi }tt	|dpdrt|dstddddfW S tt	|dpdstddddfW S tj
| ||dt| d}t|dd|dd|dr<dndfW S  tk
r } z4td|dd t  tdt|ddf W Y S d}~X Y nX dS )uR   Envia a cópia do pedido (texto) ao cliente. Manual, não bloqueia o fluxo do PDV.re   Fr{  r  r|  Tr  r   r*   conteudou#   Telefone do cliente não informado.r  u   Conteúdo do pedido vazio.r/  r   r0  )   WhatsApp não está ativo para esta loja.r9  u?   Envio de cópia (delivery) está desligado nas configurações.Zdelivery_copiar2  rK  rV   r  z[WHATSAPP ENVIAR PEDIDO ERRO]rv   r  N)r   r>   r   r   r  r   r3  r4  r  r   rW  r  rW   r~   rk  rl  rH   )re   rE  r   r[  r6  rL  rX   r9   r9   r:   api_whatsapp_enviar_pedido  s8    
$   2r]  z/api/whatsapp/avisar-prontoc               
   C   s^  d} d}z0ztd}|s8tddddfW W S tjddpFi }t|d	pVd
  }|d
krtddddfW W S zt	|dpd}W n t
tfk
r   d}Y nX |dkrtddddfW W dS t|pi }tt	|dpdrt|ds*tddddfW W S tt	|dp<ds^tddddfW W S t } | jdd}|d||f | pi }|dstddddfW W S t|dpd }t|dpd }	|	dkrtddddfW W 6S |d kr,tdd!ddfW W S t|d}
t|
s\tdd"ddfW W S t|phi }t||||d#d$}tj||
|d%t|d&}t|d'd|d(|d'rd)ndd*|d'rd+ndfW W ^S  tk
r6 } z8td,|dd- t  tdt|dd.f W Y W S d}~X Y nX W 5 |rJ|   | rX|    X dS )/uH   Avisa cliente balcão que o pedido está pronto (manual pelo dashboard).Nre   Fr{  r  r|  Tr  r   r   u,   Aviso pronto disponível apenas para BALCAO.r  r   r   u   Informe nropedido válido.r/  r0  r\  r:  uE   Aviso de pedido pronto (balcão) está desligado nas configurações.r~  a  
            SELECT MAX(nome) AS nome, MAX(cliente) AS cliente,
                   GROUP_CONCAT(DISTINCT telefone SEPARATOR ',') AS telefones_concat,
                   MAX(UPPER(COALESCE(status_pedido, ''))) AS status_pedido,
                   MAX(UPPER(COALESCE(status_comanda, 'NORMAL'))) AS status_comanda
            FROM pedido_diarios
            WHERE id_cliente = %s AND origem = 'BALCAO' AND nropedido = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            r)  r  rS   r   r*   r   r   r   r  )r   r   u>   Pedido não está em ABERTO (não é possível avisar pronto).u:   Cliente sem celular válido (informe telefone no balcão).r=  )r-  Zbalcao_prontor2  rK  rV   zCliente avisado no WhatsApp.rU   rV   r  r  z[WHATSAPP AVISAR PRONTO ERRO]rv   r  )r   r   r>   r   r   r  rH   r   r   r   r   r   r3  r4  r  r   r   r   r   r,  r  r   r.  rW  r  rW   r~   rk  rl  )r   r   re   rE  r   r   r6  r  r  Zst_comr   rl   r  rL  rX   r9   r9   r:   api_whatsapp_avisar_pronto  s    

(	


      

4r_  z/api/casa/historico-clientec               
   C   sJ  d } d }zztd}|s4tddddfW W S ddd ttjd	pNdD }|sttdd
ddfW W S t } | j	dd}t
|t||}|st|t||}tdt||d d dW W ^S  tk
r" } z8td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r6|   | rD|    X d S )Nre   Fr{  r  r|  r*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      z-api_casa_historico_cliente.<locals>.<genexpr>r      Telefone é obrigatórior  Tr~  r$  )rU   Ztotal_pedidosr   z[CASA HISTORICO CLIENTE ERRO]rv   r  )r   r   r>   r   ry   rH   r   r  r   r   r   r   r   r@   rW   r~   rk  rl  )r   r   re   r   r   rX   r9   r9   r:   api_casa_historico_cliente  s.    
$"4ra  c                  C   s    t jdpd } | r| S dS )uW   Pasta base dos .txt do /casa (override: variável de ambiente LOJA_PEDIDOS_SALVOS_DIR).ZLOJA_PEDIDOS_SALVOS_DIRr*   zC:\Geral\Pedidos_Salvos)rx   rA   r>   r   )r  r9   r9   r:   _dir_pedidos_salvos_configurado  s    rb  c                  C   s   t jt } t jt jt}t jt j|d}t jt jt d}t	 }g }| ||fD ]4}t j
t j|}||krf|| || qf|S )NZpedidos_salvos_exportZLojaOnline_Pedidos_Salvos)rx   rC   abspathrb  dirname__file__ry   tempfile
gettempdirr   normcasenormpathr   r   )ZprimaryhereZfallback_projZfallback_tempseenr   r  kr9   r9   r:   _uniq_base_dirs_candidates  s    
rm  c                 C   s  t d}t d}d|pd d| d}t| p2d }|rN|d| d	7 }t }d
}t|D ]\}	}
zbtj|
|}tj	|dd tj||}t
|ddd}|| W 5 Q R X |||	dkfW   S  tk
r } z|}W Y q`W 5 d
}~X Y q`X q`|r|tdd
S )u   
    Grava o .txt do pedido. Tenta em ordem: pasta configurada, projeto, %TEMP%.
    Qualquer OSError em uma pasta tenta a seguinte (ex.: C:\Geral sem permissão).
    Retorna (caminho_completo, nome_arquivo, usou_fallback).
    z%Y-%m-%dz%H%M%Spedido_Z
sem_numero_z.txtr*   z
FORMA DE PAGAMENTO: ro   NT)exist_okwrs   rt   r   u.   Não foi possível gravar o arquivo do pedido.)r   r{   rH   r   rm  r  rx   rC   ry   makedirsr|   r}   OSError)r[  r   forma_pagamentoZdata_dirZsufixonome_arquivoZcorpor*  Zultimoidxbase_dirZpastacaminhor   rX   r9   r9   r:   _salvar_txt_pedido_casa,  s,    

ry  z/api/casa/salvar-txtc            	   
   C   s   zt jddpi } t| ddp"d }t| dp8d}t| ddpLd }|sltdd	d
dfW S t|||\}}}d||d}|rd|d< t|W S  tk
r } z4t	d|dd t
  tdt|d
df W Y S d }~X Y nX d S )NTr  r[  r*   r   r   rt  Fu   Conteúdo vazio para salvarr  r  )rU   rx  arquivouG  Não foi possível gravar em C:\Geral\Pedidos_Salvos (permissão negada ou pasta bloqueada). O arquivo foi salvo em pasta alternativa (projeto ou %TEMP%\LojaOnline_Pedidos_Salvos). Defina LOJA_PEDIDOS_SALVOS_DIR com um caminho gravável ou dê permissão de escrita em C:\Geral\Pedidos_Salvos (utilizador do serviço / Python).Zavisoz[CASA SALVAR TXT ERRO]rv   r  )r   r  rH   r>   r   r   r   ry  rW   r~   rk  rl  )	rx  r[  r   rt  rx  ru  Zusou_fallbackr   rX   r9   r9   r:   api_casa_salvar_txtK  s*      

r{  z/api/casa/confirmar-impressaoc               
   C   sR  t jddpi } | dpd  }|dk}zt| ddp@d}W n ttfk
rb   d}Y nX t| ddptd p~d	}|d
kr.|dkr.|s.d}d}zjzt
 }| }td}t|||}|r|W W 4S |d||f | pi }	tt|	ttfr|	d n|	dp"d }
| d}|
dkr|dk	rt||||| dpl| dpld | dp| dpd d |dtd d||f |  W nP tk
r
 } z0|r|  tdt|ddf W Y W S d}~X Y nX W 5 |r|	  |r,|	  X td|dt| ddpHddS )u<   Confirma pedido após impressão no Print Bridge (PC local).Tr  r   r*   Zfechamento_caixaZ
fechamentor   r   printerbridge-localcasaNre   znSELECT UPPER(COALESCE(MAX(origem), '')) AS origem FROM pedido_diarios WHERE nropedido = %s AND id_cliente = %sr   r   rf   r   r  a5  
                UPDATE pedido_diarios
                SET status_pedido = 'ABERTO'
                WHERE nropedido = %s
                  AND id_cliente = %s
                  AND origem IN ('DELIVERY','BALCAO')
                  AND UPPER(COALESCE(status_pedido, '')) = 'AGUARDE'
                  AND NOT (r   z)
                Fr  r  	confirmarcopiasr   )rU   r}  viar  )r   r  r>   r   rB  r   r   r   rH   r   r   r   r   r   r   r   r  r   r^   r   r  r   r   rW   r   r   )rx  r   	origem_fcr   r}  conn_status
cur_statusre   r  Zrow_origZ
origem_pedr&  rX   r9   r9   r:   api_casa_confirmar_impressaog  sn    

0
	4
r  z/api/preparo/marcarc                  C   s2  d } d }zzzt  td}|s>tddddfW W S tjddpLi }|dpZg }t|tstdd	dd
fW W S g }t	 }|D ]X}zt
t| }W n tk
r   Y qY nX |dks||krq|| || q|stdddd
fW W 
S t|dkr0tdddd
fW W S t } |   |  }ddgt| }	|d|	 dtt
|g|  | pg }
d}d}zz|
D ]p}|d7 }z(t|ts|d n|dpd}W n tk
r   d}Y nX t|  dkr|d7 }qW n tk
r*   d}d}Y nX |d|	 dtt
|g|  t
|jpZd}|   tdt
|t
|t
|dW W S  tk
r
 } zbz| r|   W n tk
r   Y nX td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r|   | r,|    X d S )Nre   Fr{  r  r|  Tr  idszids deve ser uma lista.r  r   u   Nenhum id válido para marcar.i,  u'   Muitos ids em uma única solicitação.r   r   z
            SELECT chave, UPPER(COALESCE(imp_preparo,'N')) AS imp_preparo
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND chave IN (z)
            r   Zimp_preparoNrZ  z
            UPDATE pedido_diarios
            SET imp_preparo = 'S', imp_preparo_em = NOW()
            WHERE id_cliente = %s
              AND chave IN (zH)
              AND UPPER(COALESCE(imp_preparo,'N')) <> 'S'
            )rU   r  ja_marcadosZatualizadosz[PREPARO MARCAR ERRO]rv   r  ) r   r:  r   r>   r   r   r  r  r^   r   r   rH   r   rW   r   r   r@   r   r  r   ry   r   r   r   r  r   r  r   r   r~   rk  rl  )r   r   re   r   r  Zids_okrk  r=  r  r   Zrows_preZtotal_matchr  r   flagupdatedrX   r9   r9   r:   api_preparo_marcar  s    



	(



4r  z/api/baixa/pedidosc                  C   s  d } d }zĐzdtd}t } | jdd}|d|f | pDg }g }|D ]}t|dpbd 	 t
krtqNt|dpddkrqNt|d	pd}t|d
pd}|dkr|dkrqNt|dpd t|dpd g}ddd |D }	t|dpd }
|
r6|	r2|	d |
 n|
}	|dkrFd}n2|dkrVd}n"t|dpfd 	 pvd}t|dpd }t|dpd }|t|dpd	 t|dpdt|dpdt|dpd t|dpd |	t|dp$d |dd k	rNt|dpJdnd |||d qNtd|dW W ^S  tk
r } z8td |dd! t  td"t|d#d$f W Y W S d }~X Y nX W 5 |r|   | r|    X d S )%Nre   Tr~  az  
            SELECT
                pd.origem,
                pd.nropedido,
                MAX(pd.chave) AS last_id,
                SUM(COALESCE(pd.preco, 0) * COALESCE(pd.quantidade, 0)) AS total,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(pd.status_pedido, ''))) IN ('ABERTO','ABERTA') THEN 1 ELSE 0 END) AS aberto_count,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(pd.status_pedido, ''))) = 'ROTA' THEN 1 ELSE 0 END) AS rota_count,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(pd.status_pedido, ''))) = 'AGUARDE' THEN 1 ELSE 0 END) AS aguarde_count,
                MAX(COALESCE(pd.cliente, pd.nome, '')) AS cliente,
                MAX(COALESCE(pd.telefone, '')) AS telefone,
                MAX(COALESCE(pd.endereco, '')) AS endereco,
                MAX(COALESCE(pd.nrocasa, '')) AS nrocasa,
                MAX(COALESCE(pd.complemento, '')) AS complemento,
                MAX(COALESCE(pd.formapagamento, '')) AS formapagamento,
                MAX(pd.valor_pago_troco) AS valor_pago_troco,
                MAX(COALESCE(pd.entregador, '')) AS entregador_codigo,
                MAX(UPPER(TRIM(COALESCE(pd.status_pedido, '')))) AS status_pedido,
                MAX(UPPER(TRIM(COALESCE(pd.status_comanda, '')))) AS status_comanda,
                MAX(e.nome) AS entregador_nome
            FROM pedido_diarios pd
            LEFT JOIN entregador e
              ON e.id_cliente = pd.id_cliente
             AND (
                  BINARY CAST(e.chave AS CHAR) = BINARY TRIM(COALESCE(pd.entregador, ''))
                  OR e.chave = CAST(NULLIF(TRIM(pd.entregador), '') AS UNSIGNED)
                 )
            WHERE pd.id_cliente = %s
              AND pd.origem IN ('DELIVERY','BALCAO')
              AND UPPER(TRIM(COALESCE(pd.status_pedido, ''))) <> 'ITEM_REMOVIDO'
            GROUP BY pd.origem, pd.nropedido
            ORDER BY last_id DESC
            LIMIT 250
            r   r*   aguarde_countr   aberto_count
rota_countr   r   r   c                 S   s   g | ]}|r|qS r9   r9   r  r9   r9   r:   r  D  s      z%api_baixa_pedidos.<locals>.<listcomp>r   r  r   r   r   entregador_codigoentregador_nomer   r   r  r   r   r   r  )r   r   r  r   r   r   r   r  r   r  r  rU   r   z[BAIXA PEDIDOS ERRO]rv   Fr  r  )r   r   r>   r   r   r   r   rH   r   r   r  r   ry   r   r   r   rW   r~   rk  rl  )r   r   re   r   r   r   r  r  Z	end_partsendcompZ	status_uiZcod_entZnome_entrX   r9   r9   r:   api_baixa_pedidos
  st    
"%
,

"4r  z/api/pedido/cancelar-comandac               
   C   sT  d } d }z&ztjddpi }t|dp.d  }zt|dpJd}W n tt	fk
rl   d}Y nX t|dp|d  }|dkrt
d	d
ddfW W S t|st
d	dddfW W hS |dkrt
d	dddfW W FS td}|st
d	dddfW W S t } |  }t||||\}}|sh|dkrLdnd}	t
d	|d|	fW W S |dtt||t|f t|jpd}
|   t
dd| d| d|t||
dW W lS  tk
r, } zF| r|   td|dd t  t
d	t|ddf W Y W S d }~X Y nX W 5 |r@|   | rN|    X d S )NTr  r   r*   r   r   confirmacaoZCANCELARFu2   Confirmação obrigatória (confirmacao=CANCELAR).r  r  r  r  re   r{  r|  r  rS   r  z
            UPDATE pedido_diarios
            SET status_comanda = %s
            WHERE id_cliente = %s AND origem = %s AND nropedido = %s
            z	Comanda #z (z) cancelada.)rU   r  r   r   Zlinhas_afetadasz[CANCELAR COMANDA ERRO]rv   r  )r   r   r  rH   r>   r   r   r   r   r   r   r  r   r   r   r  r   r  r  r   rW   r   r~   rk  rl  )r   r   r   r   r   r  re   ZpodeZmotivocoder  rX   r9   r9   r:   api_pedido_cancelar_comandam  sb    


	4r  z/api/dashboard/delivery-balcaoc                  C   s  d } d }zztd}ttjdp*d  }|dkrBd}t } | j	dd}d}t
d}|dkrtd	| }n8|dks|d
krd| d}n|dkrd| d}nd}t rdnd}|d| d| d|f | pg }g }|D ]}	t|	dpd}
t|	dpd}t|	dp&d}t|	dp:d}t|	dpNd  p^d}|tk}t|	dpxd  }t|	dpd}t||||\}}|rt}n|dkr|
dkr|dkr|dkrd}n\|dkr|
dkrd}nB|
dkrd }n2|dkrd!}n"t|	d"p.d   p>d }|||t|	d#t|	d$pdd t|	d%pzd t|	d&pd t|	d'pd t|	d(pd t|	d)pd t|	d*pd |	d+d k	rt|	d+pdnd |||||t|	d,p.dt|	d-p@dt|	d.d/d rd|	d. nt|	d.ptdd0 qtd|d1W W ^S  tk
r } z8td2|dd3 t  td4t|d5d6f W Y W S d }~X Y nX W 5 |r|   | r|    X d S )7Nre   r  r*   )r*   abertorecebidoZtodos	canceladoTr~  r   r  zAND r  zWAND UPPER(TRIM(COALESCE(pd.status_pedido, ''))) IN ('ABERTO','ABERTA','ROTA') AND NOT (r   r  zFAND UPPER(TRIM(COALESCE(pd.status_pedido, ''))) = 'RECEBIDO' AND NOT (zXAND UPPER(TRIM(COALESCE(pd.status_pedido, ''))) IN ('ABERTO','ABERTA','RECEBIDO','ROTA')zAND pd.origem = 'BALCAO'z&AND pd.origem IN ('DELIVERY','BALCAO')a  
            SELECT
                pd.origem,
                pd.nropedido,
                MAX(pd.chave) AS last_id,
                SUM(COALESCE(pd.preco, 0) * COALESCE(pd.quantidade, 0)) AS total,
                SUM(COALESCE(pd.quantidade, 0)) AS total_itens,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(pd.status_pedido, ''))) IN ('ABERTO','ABERTA') THEN 1 ELSE 0 END) AS aberto_count,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(pd.status_pedido, ''))) = 'ROTA' THEN 1 ELSE 0 END) AS rota_count,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(pd.status_pedido, ''))) = 'RECEBIDO' THEN 1 ELSE 0 END) AS recebido_count,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(pd.status_pedido, ''))) = 'AGUARDE' THEN 1 ELSE 0 END) AS aguarde_count,
                GROUP_CONCAT(DISTINCT pd.telefone SEPARATOR ',') AS telefones_concat,
                MAX(COALESCE(pd.nome, '')) AS nome,
                MAX(COALESCE(pd.endereco, '')) AS endereco,
                MAX(COALESCE(pd.nrocasa, '')) AS nrocasa,
                MAX(COALESCE(pd.complemento, '')) AS complemento,
                MAX(COALESCE(pd.entregador, '')) AS entregador,
                MAX(en.nome) AS entregador_nome,
                MAX(COALESCE(pd.formapagamento, '')) AS formapagamento,
                MAX(pd.valor_pago_troco) AS valor_pago_troco,
                MAX(UPPER(TRIM(COALESCE(pd.status_pedido, '')))) AS status_pedido,
                MAX(UPPER(TRIM(COALESCE(pd.status_comanda, 'NORMAL')))) AS status_comanda,
                MAX(COALESCE(pd.data_criacao, CURRENT_TIMESTAMP)) AS data_criacao
            FROM pedido_diarios pd
            LEFT JOIN entregador en
              ON en.id_cliente = pd.id_cliente
             AND (
                  BINARY CAST(en.chave AS CHAR) = BINARY TRIM(COALESCE(pd.entregador, ''))
                  OR en.chave = CAST(NULLIF(TRIM(pd.entregador), '') AS UNSIGNED)
                 )
            WHERE pd.id_cliente = %s
              z`
              AND UPPER(TRIM(COALESCE(pd.status_pedido, ''))) <> 'ITEM_REMOVIDO'
              zr
            GROUP BY pd.origem, pd.nropedido
            ORDER BY last_id DESC
            LIMIT 250
            r  r   r  recebido_countr  r   r   r   r   RECEBIDOr   r   r   r   r)  rf   r   r   r   r   r  r   r  r  total_itensr   	isoformat)r   r   r   rf   r   r   r   r   r  r   r  r   r   r  pode_cancelar_comandamotivo_nao_cancelarr  r  r   r  z[DASH DELIVERY/BALCAO ERRO]rv   Fr  r  )r   r   r>   rH   r   r  r   rB  r   r   r   r   r   r   r   r   r  r  r   r,  r   r_   r  r   rW   r~   rk  rl  )r   r   re   r  Zstatus_filter_sqlZcancelada_sqlZorigem_filter_sqlr   r   r   r  r  r  r  r   r  Zorig_rZnro_rpode_cancelarr  Zst_calcrX   r9   r9   r:   api_dashboard_delivery_balcao  s    


!&)
"(

"44r  z5/api/dashboard/pedido/<string:origem>/<int:nropedido>c                 C   s*  d }d }zztd}t| p"d  }|dkrPtddddfW W S t|pXddkrztdd	ddfW W S t }|j	d
d}|
d | d k	}|rdnd}|
d| d||t|f | pi }t|dpd}	|	dkrtddddfW W S |
d||t|f | p0g }
t|dpBd  pRd}|tk}t|||t|\}}td
|t|t|dpd t|dpd t|dpd t|dpd t|dpd t|dpd t|dpd t|dp(d |dd k	rRt|dpNdnd t|d pdd  |||||	t|d!pd d"d#d$ |
D d%W W ^S  tk
r } z8td&|d
d' t  tdt|dd(f W Y W S d }~X Y nX W 5 |r|   |r$|   X d S ))Nre   r*   r   F   Origem inválidar  r  r   u   Pedido inválidoTr~  r4  z6, MAX(COALESCE(baixa_pagamento,'')) AS baixa_pagamentoz, '' AS baixa_pagamentoa  
            SELECT
              MAX(COALESCE(pd.telefone,'')) AS telefone,
              MAX(COALESCE(pd.nome,'')) AS nome,
              MAX(COALESCE(pd.endereco,'')) AS endereco,
              MAX(COALESCE(pd.nrocasa,'')) AS nrocasa,
              MAX(COALESCE(pd.complemento,'')) AS complemento,
              MAX(COALESCE(pd.entregador,'')) AS entregador,
              MAX(en.nome) AS entregador_nome,
              MAX(COALESCE(pd.formapagamento,'')) AS formapagamento,
              MAX(pd.valor_pago_troco) AS valor_pago_troco,
              MAX(UPPER(TRIM(COALESCE(pd.status_pedido,'')))) AS status_pedido,
              MAX(UPPER(TRIM(COALESCE(pd.status_comanda,'NORMAL')))) AS status_comanda,
              SUM(COALESCE(pd.preco,0) * COALESCE(pd.quantidade,0)) AS total
              a  
            FROM pedido_diarios pd
            LEFT JOIN entregador en
              ON en.id_cliente = pd.id_cliente
             AND (
                  BINARY CAST(en.chave AS CHAR) = BINARY TRIM(COALESCE(pd.entregador, ''))
                  OR en.chave = CAST(NULLIF(TRIM(pd.entregador), '') AS UNSIGNED)
                 )
            WHERE pd.id_cliente = %s
              AND pd.origem = %s
              AND pd.nropedido = %s
              AND UPPER(TRIM(COALESCE(pd.status_pedido,''))) <> 'ITEM_REMOVIDO'
            r     Pedido não encontradorS   a  
            SELECT
              chave,
              produto,
              COALESCE(quantidade,0) AS quantidade,
              COALESCE(preco,0) AS preco,
              obs_item,
              dados_item
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = %s
              AND nropedido = %s
              AND UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO'
            ORDER BY chave ASC
            r   r   r   rf   r   r   r   r   r  r   r  r   baixa_pagamento)r   r   r   rf   r   r   r   r   r  r   r  r   r   r  r  r  r  r  c                 S   s   g | ]}t |qS r9   r  r   r  r9   r9   r:   r    s     z0api_dashboard_pedido_detalhe.<locals>.<listcomp>)rU   Zpedidor   z[DASH PEDIDO DETALHE ERRO]rv   r  )r   r   r>   rH   r   r   r   r   r   r   r   r   r   r   r  r  rW   r~   rk  rl  )r   r   r   r   re   r	  	has_baixaZselect_baixaheadr  r   r   r  r  r  rX   r9   r9   r:   api_dashboard_pedido_detalhe,  s    


"
4r  z!/api/dashboard/mesa/<int:mesanro>c                 C   s8  d }d }z
ztd}t| p"ddkrDtddddfW W S t }|jdd}|d	 | d krv|d
 |d | d kr|d |d | d k	}|d|t| f | pi }t	|dpd}|dkrtddddfW W S zt|dpd}W n t
k
r4   d}Y nX |dkrDd}|d|f | p^i }zt	|dprd}	W n t
k
r   d}	Y nX |	dk rd}	|	rtt	|t	|	d  dnd}
tt	|t	|
 d}|dkrtt	|t	| dnt	|}d}|rH|d|t| f | p.i }t|dp@d }|d|t| f | phg }tddt| t|dpd  |||
|||d	d d! |D d"W W ^S  t
k
r } z8td#|dd$ t  tdt|dd%f W Y W S d }~X Y nX W 5 |r$|   |r2|   X d S )&Nre   r   Fu   Mesa inválidar  r  Tr~  r2  r3  4SHOW COLUMNS FROM pedido_diarios LIKE 'pessoas_mesa'MALTER TABLE pedido_diarios ADD COLUMN pessoas_mesa INT NULL AFTER status_mesar4  a  
            SELECT
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' THEN COALESCE(preco,0) * COALESCE(quantidade,0) ELSE 0 END) AS subtotal,
              MAX(UPPER(COALESCE(status_mesa,''))) AS status_mesa,
              MAX(COALESCE(pessoas_mesa, 0)) AS pessoas_mesa
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = 'MESA'
              AND nropedido = %s
            subtotalu   Mesa não encontradarS   pessoas_mesar   VSELECT servicomesa FROM configuracao WHERE id_cliente = %s ORDER BY chave DESC LIMIT 1servicomesar        Y@r%  r*   z
                SELECT MAX(COALESCE(baixa_pagamento,'')) AS baixa_pagamento
                FROM pedido_diarios
                WHERE id_cliente = %s AND origem = 'MESA' AND nropedido = %s
                r  a  
            SELECT
              chave,
              produto,
              COALESCE(quantidade,0) AS quantidade,
              COALESCE(preco,0) AS preco,
              obs_item,
              dados_item
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = 'MESA'
              AND nropedido = %s
              AND UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO'
            ORDER BY chave ASC
            r  status_mesa)	r   mesanror  r  r  servicor  
por_pessoar  c                 S   s   g | ]}t |qS r9   r  r  r9   r9   r:   r    s     z.api_dashboard_mesa_detalhe.<locals>.<listcomp>)rU   ru  r   z[DASH MESA DETALHE ERRO]rv   r  )r   r   r>   r   r   r   r   r   r   r   rW   roundrH   r   r   r   r~   rk  rl  )r  r   r   re   r  r  r  r  r6  pctr  r  r  	baixa_txtZrow_br   rX   r9   r9   r:   api_dashboard_mesa_detalhe  s    












$(


4r  z/api/baixa/receberc                  C   s@  d } d }zztjddpi }t|dp.d}t|dp@d  }|dkrntdd	d
dfW W S |dkrtddd
dfW W S t	|dt
r|dng }g }d}|D ]}t	|tsqt|dpd }	z"tt|dpddd}
W n tk
r   d}
Y nX |	r|
dkr.qtt|
d}
||
7 }||	|
d q|svtddd
dfW W S td}t } |   | jdd}|d | d kr|d |d|||f | pi }t|dpd}t|dp d}t|dpd}t|dp(d}|dkrX|   tddd
d fW W S |dkr|dkr|   tdd!d
d"fW W S |dkr|   tdd#d
d"fW W fS tt|d}tt|d}t|| d}|d$kr|   tdd%|||d&dfW W 
S d}g }d}|D ]}t|dp:d }t|dpRd}t|||}|rtt|t| d}|| n`tt|t| d}||d$ kr&|   tdd'| d(|tt|dd)df  W W 6S q&t|t| d$kr4|   tdd*|tt|dd+dfW W S ttdt|t| d}|d$kr|dkr|   tdd,|||d-dfW W S || d$kr|   tdd.||||d/dfW W \S ttd0pd }|}d1||||||tt d2}tj|dd3}t|d1kr8t|d dp.d }nd4}|d5|||||f |jdkr~|   tdd6d
d7fW W S |   td8diW W S  tk
r } zbz| r|   W n tk
r   Y nX t d9|dd: t!"  tdt|d
d7f W Y W S d }~X Y nX W 5 |r,|   | r:|    X d S );NTr  r   r   r   r*   r   Fr  r  r  u   nropedido inválido
pagamentosr  r  r  r   r  r%  r  r  4Informe pelo menos uma forma de pagamento com valor.re   r~  r4  r5  a  
            SELECT
                SUM(COALESCE(preco, 0) * COALESCE(quantidade, 0)) AS total,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(status_pedido, ''))) IN ('ABERTO','ABERTA') THEN 1 ELSE 0 END) AS aberto_count,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(status_pedido, ''))) = 'ROTA' THEN 1 ELSE 0 END) AS rota_count,
                SUM(CASE WHEN UPPER(TRIM(COALESCE(status_pedido, ''))) = 'AGUARDE' THEN 1 ELSE 0 END) AS aguarde_count
            FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem = %s
              AND UPPER(TRIM(COALESCE(status_pedido, ''))) <> 'ITEM_REMOVIDO'
            r  r  r  r  u$   Pedido não encontrado ou sem itens.rS   z6Pedido precisa estar ABERTO ou em ROTA para dar baixa.r  u4   Pedido ainda está em AGUARDE e não pode dar baixa.{Gz?u*   Valores não fecham com o total do pedido.rU   rV   r  somadoZrestantez	A forma 'uK   ' não permite troco e não pode receber valor maior que o total do pedido.)rU   rV   r  r  uD   A soma das formas sem troco não pode ultrapassar o total do pedido.)rU   rV   r  Z	sem_trocoz]Nenhuma forma selecionada permite troco. Ajuste os valores para fechar o total sem excedente.)rU   rV   r  r  trocozdO troco excede o valor pago em formas que permitem troco. Atribua o excedente a uma forma com troco.)rU   rV   r  r  r  Zformas_com_trocorI   r   )r=  r   r   r  r  r  usuariotsensure_asciiMISTOa  
            UPDATE pedido_diarios
            SET status_pedido = 'RECEBIDO',
                baixa_pagamento = %s,
                formapagamento = %s
            WHERE nropedido = %s AND id_cliente = %s AND origem = %s
              AND UPPER(TRIM(COALESCE(status_pedido, ''))) <> 'ITEM_REMOVIDO'
              AND UPPER(TRIM(COALESCE(status_pedido, ''))) IN ('ABERTO','ABERTA','ROTA')
            u&   Não foi possível atualizar o pedido.r  rU   z[BAIXA RECEBER ERRO]rv   )#r   r   r  r   r>   rH   r   r   r   r  r^   r  r   r  rW   r  r   r   r   r  r   r   r   r   r^  r  r   r  dumpsr@   r  r   r~   rk  rl  )r   r   r   r   r   r  pagossomar  r  r  re   r   r  r  r  r  diffZtroco_pay_sumZtroco_pay_namesZnon_troco_sumZ
forma_nomeZ
valor_pagoZpermite_trocoZ	troco_valr  r  	baixa_objr  forma_finalrX   r9   r9   r:   api_baixa_receber  s8   
"







 


	


	4r  c                   C   sV   t js
d S tjdtd d tj  tjdtd d tj  d S )Nu*   [LOG][before_request] Sessão id_cliente: re   ro   u.   [LOG][before_request] Sessão usuario_logado: rI   )r   ZLOG_SESSION_DEBUGsysstderrr}   r   r>   rw   r9   r9   r9   r:   log_id_cliente_global  s    
r  z/pingc                   C   s   dS )N)Zpongr  r9   r9   r9   r9   r:   ping  s    r  z/rota_testec                   C   s   dS )NzRota de teste OK!r9   r9   r9   r9   r:   
rota_teste  s    r  z/api/salvar-forma-pagamentoc               
   C   s(  t  } | dd }t| ddp(d  }|dkr@dnd}td}|sdtdd	d
dfS zzBt
  t }| }|d|||f |  tddd
W W FS  tk
r } z"tdt|d
df W Y W S d }~X Y nX W 5 dt kr|r|	  dt kr"|r"|	  X d S )Nr  r*   r  rZ  r[  r\  r]  TRUErZ  r  re   F!   Forma de pagamento não informadar  r  r   r   zIINSERT INTO formapagamento (forma, troco, id_cliente) VALUES (%s, %s, %s)Tz)Forma de pagamento adicionada com sucessor  )r   r  r>   r   rH   r   r   r   localsr   r8  r   r   r   r   rW   )r   r  	troco_rawr  re   r   r   rX   r9   r9   r:   salvar_forma_pagamento  s.    
4  r  z'/api/editar-forma-pagamento/<int:chave>PUTc           	   
   C   s^  t  }t|ddpd }t|ddp0d  }|dkrHdnd}td}|sltdd	d
dfS zznt
  t }| }|d||| |f |jdkr|  tddd
dfW W dS |  tddd
W W HS  tk
r } z"tdt|d
df W Y W S d }~X Y nX W 5 dt kr>|r>|	  dt krX|rX|	  X d S )Nr  r*   r  r  rZ  r  re   Fr  r  r  r   r   z
            UPDATE formapagamento
            SET forma = %s, troco = %s
            WHERE chave = %s AND id_cliente = %s
            r      Registro não encontradorS   Tz)Forma de pagamento atualizada com sucessor  )r   r  rH   r>   r   r   r   r   r  r   r8  r   r   r   r  r   r   rW   )	r   r   r  r  r  re   r   r   rX   r9   r9   r:   editar_forma_pagamento  s4    


4  r  z(/api/excluir-forma-pagamento/<int:chave>c              
   C   s   t d}zzdt }| }|d| |f |jdkrV|  t	dddd	fW W bS |
  t	d
ddW W FS  tk
r } z"t	dt|ddf W Y W S d }~X Y nX W 5 dt kr|r|  dt kr|r|  X d S )Nre   r   r   z?DELETE FROM formapagamento WHERE chave = %s AND id_cliente = %sr   Fr  r  rS   Tu(   Forma de pagamento excluída com sucessor  )r   r>   r  r   r   r   r   r  r   r   r   rW   rH   )r   re   r   r   rX   r9   r9   r:   excluir_forma_pagamento1  s&    

4  r  c           	      C   s   d}t ||  }t || }t |d d t t | t t | t |d d   }dt t |t d|  }t|| dS )Ng     @r%  r   )mathradianssincosatan2sqrtr  )	Zlat1Zlon1Zlat2Zlon2RZdlatZdlonrr   rD  r9   r9   r:   haversine_kmG  s    D r  c              
   C   s   | rt |  dk rdS d}| ddd}ddi}zVtj|||d	d
}|jdkrTW dS | }|sfW dS t|d d t|d d fW S  tk
r } ztd| W Y dS d }~X Y nX d S )Nr  )NNz*https://nominatim.openstreetmap.org/searchr  r   )rV  formatlimitr  znovaloja-geocoder/1.0r  )r  rP   r  r  r   ZlatZlonz[GEOCODE ERRO])	r@   r   r  r>   r  r  r   rW   r~   )r   urlr  rP   r   r   rX   r9   r9   r:   geocodificarO  s     
"
r  c              
   C   s   zd}| d| d|  d| d| d
}t j|dddid	}|jd
krLW d S | }|rf|ddkrlW d S |dpxg }|sW d S |d d}	|	d krW d S t|	d dW S  tk
r }
 ztd|
 W Y d S d }
~
X Y nX d S )Nz/http://router.project-osrm.org/route/v1/drivingr5   r   ;z.?overview=false&alternatives=false&steps=falser  r  znovaloja-osrm/1.0r  r  r  ZOkroutesr   Zdistanceg     @@r%  z[OSRM ERRO])r  r>   r  r  r  rW   r~   )Zlat_lojaZlon_lojalat_clilon_clir  r  r   r   r  Zdist_mrX   r9   r9   r:   distancia_osrm_kma  s&    "

r  c              
   C   s
  t d}t|}|d }|d }| dd| dd| dd| dd| d	dd
g}ddd |D }t|\}}|dk	r|dk	rt||||}	|	dk	r|	||fS zt||||}
|
||fW S  tk
r } ztd| d||f W Y S d}~X Y nX dS )uD   Calcula distância entre a loja e o cliente usando dados cadastradosre   latitude	longituder   r*   r   r  r  r  ZBrasilr   c                 S   s   g | ]}|r|qS r9   r9   r  r9   r9   r:   r    s      z.calcular_distancia_cliente.<locals>.<listcomp>Nz[HAVERSINE ERRO]r   )r   NN)	r   r>   r   ry   r  r  r  rW   r~   )rx  re   rY  Zloja_latZloja_lonr  Zendereco_strr  r  Z	dist_osrmZdist_havrX   r9   r9   r:   calcular_distancia_clientex  s0    







 r  c                 C   s  d}d}zz^t }|jdd}|d|f | }|sPtd W W ^dS |d}|d}|dk	r| |k r|dk	rt|nd}td	|  d
| d|  |W W  S t	ddD ]v}|d| d}	|d| d}
|	dk	r| |	kr|
dk	rt|
nd}td	|  d| d|  |  W W ~S q|d}|dk	rLt|nd}td	|  d|  |W W >S  tk
r } ztd| W Y W dS d}~X Y nX W 5 z|r|   W n tk
r   Y nX z|r|   W n tk
r   Y nX X dS )u   Calcula taxa de entrega baseado na distância usando tabela txentrega.
    Se distância for menor que faixa1_d, utiliza faixa1_v (taxa mínima).
    Retorna o valor da taxa ou 0.0 se erro.NTr~  ;SELECT * FROM txentrega WHERE chave = 1 AND id_cliente = %sz5[TAXA ENTREGA] Nenhuma faixa configurada em txentregar  Zfaixa1_dfaixa1_vu   [TAXA ENTREGA] Distância u   km é menor que faixa1_d (u!   km), retornando taxa mínima: R$ r   r  faixa_d_vzkm cai na faixa z: R$ Z	faixa10_vz"km ultrapassa todas as faixas: R$ z[TAXA ENTREGA ERRO])
r   rW   r   r   r   r   r~   r>   r   r&  )	distanciare   r   r   r  Z	faixa_1_dZ	faixa_1_vtaxar  faixa_dfaixa_vZ
faixa_10_vZ
taxa_finalrX   r9   r9   r:   calcular_taxa_entrega  sP    




 r  c                 C   s   | s| S i }|   D ]\}}t|tjr6t|||< qt|trT|jddd||< qt|trl| ||< qt|tr|jdd||< qt|t	t
frt	|jddd||< q|||< q|S )uA   Converte tipos não-JSON (Decimal, datetime, bytes) para jsonify.rq   seconds)septimespecr  rs   r  errors)itemsr  decimalDecimalr   r   r  r   dt_timebytes	bytearraydecode)r   r   rl  r=  r9   r9   r:   r    s     



r  zGUPPER(TRIM(COALESCE({col},''))) IN ('S','SIM','1','Y','YES','T','TRUE')c                 C   s   | rdS dS )Nz
          CASE
            WHEN COALESCE(TRIM(caminho),'') <> '' THEN TRIM(caminho)
            ELSE TRIM(nomedaimpressora)
          END AS printer
        z!TRIM(nomedaimpressora) AS printerr9   has_caminhor9   r9   r:   _printer_select_sql  s    r	  c                 C   s   | rdS dS )NzO(COALESCE(TRIM(nomedaimpressora),'') <> '' OR COALESCE(TRIM(caminho),'') <> '')z)COALESCE(TRIM(nomedaimpressora),'') <> ''r9   r  r9   r9   r:   _printer_name_where  s    r
  c                 C   s   |  d |  d k	S )Nrs  r   r   )r   r9   r9   r:   _impressoras_has_id_cliente  s    
r  c                 C   s&   |d krdS t | sdS dt|ffS )Nr*   r9    AND id_cliente = %s)r  r   r   re   r9   r9   r:   _cliente_sql  s
    r  c           
   
   C   s   t |}t|}t| |\}}|rTtj|d}| d| d| d| | d| n| d| d| | d| |  }	|	r|	d r|	d S d S )Ncol
            SELECT z0
            FROM impressoras
            WHERE z
              AND zY
            ORDER BY COALESCE(imprenro,0) DESC, id DESC
            LIMIT 1
            X
            ORDER BY COALESCE(imprenro,0) DESC, id ASC
            LIMIT 1
            r   )r	  r
  r  _SQL_FLAG_SIMr  r   r   )
r   r  flag_columnre   sel
where_namecli_sql
cli_paramsflag_sqlr   r9   r9   r:   _fetch_printer_row  s:    
r  c           	      C   sp   t |}t|}t| |\}}dD ]H}| d| d| d| | d| |  }|r"|d r"|d   S q"d S )Nzimprenro = 1z1=1r  z1
            FROM impressoras
            WHERE () AND r  r   )r	  r
  r  r   r   )	r   r  re   r  r  r  r  r#  r   r9   r9   r:   _fetch_printer_fallback,  s(    
r  c                    s  d}d zzt }|   d   dk	dkrnzddlm} |dW n tk
rl   dY nX t	| pvd
  }d fdd	}|d	kr|d
W W S |dkr|dW W S t pt dW W S  tjjk
rV } zVz&t|dddkrW W Y :W ~dS W n tk
r0   Y nX td| W Y W LdS d}~X Y n8 tk
r } ztd| W Y W dS d}~X Y nX W 5 z r    W n tk
r   Y nX z|r|   W n tk
r   Y nX X dS )uJ   Obtém caminho ou nome da impressora conforme flags na tabela impressoras.Nro  r   r   re   r*   c                    sr   d }| r0  d|  d   r0t | }|s@t }|snd k	rn| r^t | d }|snt d }|S )N$SHOW COLUMNS FROM impressoras LIKE '')r   r   r  r  )flag_colr  r   r  re   r9   r:   _resolveQ  s    z%get_printer_from_db.<locals>._resolve>   r  r  rw  r     balcãorw  >   ru  contarv  rv  r#  iz  z[IMPRESSORA DB ERRO])N)r   rW   r   r   r   r   flaskr   r>   rH   r   rB  r  r(  r)  r*  r_   r~   )purposere   r   _sess	purpose_lr%  db_errrX   r9   r$  r:   get_printer_from_dbA  sZ    

  


 r-  c              	      s   t dt|\ d
 fdd	}|r>||}|r>|S dD ]F}d| d  d   }|rB|d	 rBt|d	   S qBdS )uU   Retorna id da impressora lógica conforme flags (mesma ordem de get_printer_from_db).TNc                    sl   | r0t j| d}d| d  d  nd  d   }|rh|d rht|d S d S )Nr  zR
                SELECT id
                FROM impressoras
                WHERE z
                  AND ze
                ORDER BY COALESCE(imprenro,0) DESC, id DESC
                LIMIT 1
                zd
                ORDER BY COALESCE(imprenro,0) DESC, id ASC
                LIMIT 1
                r   )r  r  r   r   r   )r#  r  r   r  r  r   r  r9   r:   _query  s,    
z(_fetch_impressora_id_row.<locals>._queryr  zG
            SELECT id
            FROM impressoras
            WHERE (r  r  r   )N)r
  r  r   r   r   )r   r  re   r/  iidr#  r   r9   r.  r:   _fetch_impressora_id_row  s,    
r1  c                    s`  d}d  zzt }|  dkrXzddlm} |dW n tk
rV   dY nX t| p`d 	 }d fdd	}|dkr|d	W W vS |d
kr|dW W `S t
 dpt
 ddW W BS  tk
r  } ztd|dd W Y W dS d}~X Y nX W 5 z r    W n tk
r.   Y nX z|r@|   W n tk
rX   Y nX X dS )u-   Id da impressora lógica para origem/purpose.Nr   r   re   r*   c                    sT   d }| rt  | }|s$t  d }|sPd k	rP| r@t  | d }|sPt  d d }|S r   )r1  )r#  r0  r  r9   r:   r%    s    z+get_impressora_id_from_db.<locals>._resolve>   r  r  rw  r  r&  rw  >   ru  r'  rv  rv  z[IMPRESSORA ID DB ERRO]Trv   )N)r   rW   r   r   r(  r   r>   rH   r   rB  r1  r~   )r)  re   r   r*  r+  r%  rX   r9   r  r:   get_impressora_id_from_db  sF    
  
 r2  c              	   C   s   t |}|sdS t | |s"dS z(|dk	rDt| dkrDt|nd}W n ttfk
rf   d}Y nX |dkr|t|| d}|sdS t 	| ||}|sdS |dfS )	u@   Resolve caminho_local do terminal. Bloqueia se não configurado.)Nu   terminal_id inválido.)NuY   Este terminal não está configurado. Acesse Configurações > Impressão deste terminal.Nr*   r   r)  re   )N;Nenhuma impressora habilitada no cadastro para esta origem.)Nuw   Caminho local não configurado para esta impressora neste terminal. Acesse Configurações > Impressão deste terminal.)
terminal_impressao_servicenormalize_terminal_idterminal_is_configuredrH   r   r   r   r   r2  Zget_printer_path)re   terminal_idr)  impressora_idtidr0  rx  r9   r9   r:   "_resolve_printer_path_for_terminal  s"    
(
r;  c                  C   s   t jdkrg S tdkr@zddl} | aW n tk
r>   g  Y S X g }ztjtjB }t|D ].}t|dkr\|d r\|t	|d 
  q\t }g }|D ](}| }||kr|| || q|W S  tk
r   g  Y S X dS )u9   Lista impressoras visíveis para o processo Python atual.win32Nr   r$  r%  )r  platform
win32printrW   ZPRINTER_ENUM_LOCALZPRINTER_ENUM_CONNECTIONSZEnumPrintersr@   r   rH   r   r   rB  r   )_win32printnomesflagsr  r+  Zunicosr  Zlkr9   r9   r:   list_installed_printers  s0    


rB  c              
   C   s6  t jdkrddt j fS tdkrhzddl}|aW n4 tk
rf } zdd| f W Y S d}~X Y nX zt|p|t p|d }|sW dS t }|}|r| d	d
 |D krd}t	rt	||\}}	|st
rt
||}|sdd| fW S |}t|}
zt|
dd}zt|
 t| tr*| }nt| jddd}|d7 }|r|  }d|ksjd|krt|d7 }nDd|kr|d7 }n0d|ksd|ksd|kr|d7 }n|d7 }n|d7 }t|
| t|
 W 5 t|
 X W 5 t|
 X W dS  tk
r0 } zdt|f W Y S d}~X Y nX dS )zdEnvia texto RAW para impressora no Windows. Retorna (True, None) em sucesso, (False, erro) em falha.r<  Fu6   Sistema atual sem suporte para impressão silenciosa: Nr   u   pywin32 não carregado: r*   )Fu*   Nenhuma impressora disponível no Windows.c                 S   s   h | ]}|  qS r9   rA  r   r   r9   r9   r:   rE  2  s     z"send_to_printer.<locals>.<setcomp>u'   Impressora não encontrada no Windows: r   )ZPedidoNZRAWcp1252r  r  s   dZbematechZdarumas   mZepsons   iZelginZtancaZdiebolds   V TN)r  r=  r>  rW   rH   GetDefaultPrinterr   rB  rB  _resolve_windows_printer_find_best_printer_matchZOpenPrinterZClosePrinterZStartDocPrinterZEndDocPrinterZStartPagePrinterr  r  encodeZWritePrinterZEndPagePrinter)r[  printer_namemarca_impressorar?  rX   Znome_pedidodisponiveisrf   melhor_mZhPrinterZhJobr   Zmarcar9   r9   r:   send_to_printer!  sb    
$







rO  c                 C   s  d}d}zzd| d}dddddddd}|D ]$}|drX|dd |d< q2|drx|dd |d	< q2|d
r|d
d |d< q2|dr|dd |d< q2|dr|dd }|d}	t|	dkr|	d  |d< t|	dkrX|	d  |d< q2d|kr2|dd }
zt|
|d< W q2   d|d< Y q2X q2|d sxtd W W 8dS t }|j	dd}t
d}|d|t|d pdf | pi }t|dpdd }|dkrd}d}t
d}|dk	r&zt|}W n tk
r$   d}Y nX |D ]:}|dd}t|ddpNd}t|ddpdd}|d d}|d!d}d"|krd#}d#}t|d$t|d pd||d |d	 |d |d |d |d t|pdt|pdt|pdt|pdt|pdddd|d%|d d|d&d'|d|p2ddd( td)| d*| d+| d,|d  d-| 
 q*|  W n4 tk
r } ztd.|   W 5 d}~X Y nX W 5 |rz|   W n   Y nX |rz|   W n   Y nX X dS )/znGrava dados do pedido na tabela pedido_diarios (origem DELIVERY), incluindo a forma de pagamento se fornecida.Nro   r*   r   )r   r   rf   r   r   r   r   zTel:r   zCEP:r   zNome:rf   zCompl:r   zEnd:r   r   r   r%  r   zPEDIDO NRO:r   u/   [DELIVERY PENDENTE] Sem telefone, não gravandoTr~  re   z
            SELECT COALESCE(MAX(lancamento), 0) AS max_lancamento
            FROM pedido_diarios
            WHERE id_cliente = %s AND nropedido = %s AND origem = 'DELIVERY'
            r  r  r  r   r  r   r   zTAXA ENTREGAZ	TXENTREGAr   r   r   r   r  z[PEDIDO_DIARIOS] z (cod: z
, classe: z) gravado para z
 | Forma: [DELIVERY PENDENTE ERRO] )r   r(  r?   r  r   r@   r   r~   r   r   r   r>   r   r   rW   r   r   rH   r   )r[  produtosrt  r   r   r  r  linhaZend_infor  Znro_strre   r  Zlancamento_blocor   r  r"  Z	prod_nomeZ
prod_precoZprod_qtdZ
prod_chaveZprod_classerX   r9   r9   r:   gravar_delivery_pendentea  s    
	













.rS  c                  C   s   t jtdd} ddt  ddt jt dtt jt jt dt 	  d	t d
t jt
j dt j|  dt j|  g	S )uS   Texto único usado em /onde-esta-o-servidor e /loja-build (pasta real do processo).r   painel_menu.htmlro   zAPP_VERSION=zArotas_diagnostico=/onde-esta-o-servidor /loja-build /__loja_buildzapp_py=z
app_mtime=zcwd=z	BASE_DIR=ztemplate_folder=zpainel_menu=zexiste_painel=)rx   rC   ry   rz   r   rc  re  r   getmtimegetcwdappr/   isfile)_pmr9   r9   r:   _loja_diagnostico_texto  s    
rZ  c                  C   s   t t dd} t | jd< | S )Nztext/plain; charset=utf-8)ZmimetyperO   )r   rZ  r   rP   )respr9   r9   r:   _loja_diagnostico_response  s    r\  z/onde-esta-o-servidorc                   C   s   t  S )uc   Confirma em texto plano qual app.py está a servir a porta (alinhar com a pasta que o Cursor abre).r\  r9   r9   r9   r:   onde_esta_o_servidor  s    r^  z/loja-buildz/__loja_buildc                   C   s   t  S )ud   Diagnóstico: mesmo conteúdo que /onde-esta-o-servidor (/loja-build evita bloqueios a URLs com __).r]  r9   r9   r9   r:   loja_build_info  s    r_  r5   c                  C   s^   t d} t| }|dd}tjtdd}td| |tj|d}t	|}t
 |jd< |S )Nre   rf   rg   r   rT  )re   ri   Z_painel_templaterO   )r   r>   r   rx   rC   ry   rz   r   rc  r   r   rP   )re   rl   ri   rY  htmlr[  r9   r9   r:   index  s    

ra  z/logoutc                   C   s0   t dd t dd t dd ttdS )u   Desloga o usuáriorI   Nre   r	  zauth.login_page)r   r   r	   r
   r9   r9   r9   r:   logout  s    rb  z/casac                  C   sj   t  r:ttjdpd  } | dkr:ttdd S t	d}t
|pNi }|dd}td	||d
S )u<   Página de pedidos (carrossel) / PDV balcão no modo varejo.r  r*   r  r  z?modo=balcaore   rf   rg   z
index.htmlrh   )r   rH   r   r  r>   r   rB  r	   r
   r   r   r   )r  re   rl   ri   r9   r9   r:   r    s    
r  z/delivery-pendente-viewc                  C   s,   t d} t| }|dd}td| |dS )u4   Página para visualizar pedidos pendentes de entregare   rf   rg   zdelivery_pendente.htmlrh   rj   rk   r9   r9   r:   delivery_pendente_view,  s    
rc  z/canceladasc                  C   s,   t d} t| }|dd}td| |dS )u*   Página para visualizar pedidos canceladosre   rf   rg   zcanceladas.htmlrh   rj   rk   r9   r9   r:   canceladas_view6  s    
rd  z	/comandasc                  C   s,   t d} t| }|dd}td| |dS )u)   Página para visualizar comandas fechadasre   rf   rg   zcomandas.htmlrh   rj   rk   r9   r9   r:   comandas_view?  s    
re  z/cadastrar-entregadorc                  C   s,   t d} t| }|dd}td| |dS )u#   Página de cadastro de entregadoresre   rf   rg   zcadastrar_entregador.htmlrh   rj   rk   r9   r9   r:   cadastrar_entregadorK  s    
rf  z/api/salvar-entregadorc            	   
   C   sN  d} d}z ztjpi }|dd }|dd }|dd }|sdtdddd	fW W S t } |  }td
}|	d||||f | 
  |j}td| d| d| d tdd| d| ddW W RS  tjjk
r& } z(td| tddddf W Y W S d}~X Y nX W 5 |r:|   | rH|    X dS )z2Salva um novo entregador na tabela de entregadoresNrf   r*   r   r   F   Nome é obrigatórior  r  re   zw
            INSERT INTO entregador (nome, telefone, endereco, id_cliente)
            VALUES (%s, %s, %s, %s)
        z[ENTREGADOR CADASTRADO]     (código: z, telefone: r   TEntregador 'u$   ' cadastrado com sucesso! (Código: r  
[DB ERROR]z+Erro ao salvar entregador no banco de dadosr  )r   r   r  r>   r   r   r   r   r   r   r   r  r~   r(  r)  r*  )	r   r   rx  rf   r   r   re   chave_geradar,  r9   r9   r:   salvar_entregadorU  s:    



0rl  z/api/listar-entregadoresc               
   C   s   d} d}zzFt } | jdd}td}|d|f | }td|dW W PS  tj	j
k
r } z(td| tdd	d
df W Y W S d}~X Y nX W 5 |r|   | r|    X dS )z'Lista todos os entregadores cadastradosNTr~  re   z
            SELECT chave, nome, telefone, endereco
            FROM entregador
            WHERE id_cliente = %s
            ORDER BY nome
        )rU   entregadoresrj  FzErro ao listar entregadoresr  r  r   r   r   r   r>   r   r   r   r(  r)  r*  r~   )r   r   re   rm  r,  r9   r9   r:   listar_entregadores  s*    

0ro  z/cadastrar-usuarioc                  C   s4   t d} t| }|dd}td| |t ddS )u;   Página de cadastro de usuários da loja (tabela usuarios).re   rf   rg   zcadastrar_usuario.htmlrI   )re   ri   rI   rj   rk   r9   r9   r:   cadastrar_usuario  s    
rp  z/api/usuarios-lojac               
   C   s   t d} | s tddddfS ztt| }td|dW S  tk
rx } ztd|jd|jf W Y S d }~X Y nN tk
r } z0t	d|dd	 t
  tdd
ddf W Y S d }~X Y nX d S )Nre   Fr{  r  r|  T)rU   usuariosz[USUARIOS_LOJA LIST]rv   u   Erro ao listar usuários.r  )r   r>   r   r!   r   r   messager  rW   r~   rk  rl  )re   rq  rX   r9   r9   r:   api_usuarios_loja_list  s    
*rs  c               
   C   sH  t d} | s tddddfS tjddp.i }|dp<d	}|d
pT|dpTd	}||krptddddfS zHtt| |d||dpd|d}tdd|d  d|dW S  tk
r } ztd|jd|j	f W Y S d }~X Y nP t
k
rB } z0td|dd t  tddddf W Y S d }~X Y nX d S )Nre   Fr{  r  r|  Tr  senhar*   senha_confirmacaosenha2$   Senha e confirmação não conferem.r  r  r	  Z	atendentewhatsappu
   Usuário 'z' cadastrado com sucesso.rU   r  r  z[USUARIOS_LOJA CREATE]rv   u   Erro ao cadastrar usuário.r  )r   r>   r   r   r  r    r   r   rr  r  rW   r~   rk  rl  )re   r   rt  rv  createdrX   r9   r9   r:   api_usuarios_loja_create  s8    
*r{  z/api/usuarios-loja/<int:chave>c           	   
   C   s  t d}|s tddddfS tjddp.i }|d}|d	pL|d
}|sV|rp||krptddddfS |d}d }|d k	rt|  dkrdnd}zRtt	|| |d||r|nd d|kr|dnd t dd}tdd|dW S  t
k
r2 } ztd|jd|jf W Y S d }~X Y nP tk
r } z0td|dd t  tddddf W Y S d }~X Y nX d S )Nre   Fr{  r  r|  Tr  rt  ru  rv  rw  r  r/  )r\  r@  r>  rA  rC  r   r   r	  rx  rI   )r	  r/  rt  rx  rI   u    Usuário atualizado com sucesso.ry  z[USUARIOS_LOJA UPDATE]rv   u   Erro ao atualizar usuário.r  )r   r>   r   r   r  rH   r   rB  r"   r   r   rr  r  rW   r~   rk  rl  )	r   re   r   rt  rv  Z	ativo_rawr/  r  rX   r9   r9   r:   api_usuarios_loja_update  sF    



	*r|  z/api/delivery-pedidos-despachoc               
   C   sB  t d} | s tddddfS d}d}zzt  t }|jdd}|d	| f | p\g }|D ]H}|d
dk	rbzt	|d
 |d
< W qb t
tfk
r   d|d
< Y qbX qbtd|dW W bS  tjjk
r } z8td|dd t  tdt|ddf W Y W S d}~X Y nX W 5 |r.|  |r<|  X dS )uf   Lista pedidos DELIVERY cujas linhas ativas estão todas em ABERTO (elegíveis para despacho → ROTA).re   Fr{  r  r|  NTr~  a  
            SELECT
                d.nropedido,
                MAX(NULLIF(TRIM(COALESCE(d.telefone, '')), '')) AS telefone,
                MAX(NULLIF(TRIM(COALESCE(d.cliente, '')), '')) AS cliente,
                MAX(NULLIF(TRIM(COALESCE(d.nome, '')), '')) AS nome,
                COALESCE(SUM(d.preco * d.quantidade), 0) AS total_valor,
                COUNT(*) AS linhas
            FROM pedido_diarios d
            WHERE d.id_cliente = %s
              AND d.origem = 'DELIVERY'
            GROUP BY d.nropedido
            HAVING SUM(CASE WHEN UPPER(COALESCE(d.status_pedido, '')) <> 'ITEM_REMOVIDO' THEN 1 ELSE 0 END) > 0
               AND SUM(
                    CASE
                      WHEN UPPER(COALESCE(d.status_pedido, '')) = 'ITEM_REMOVIDO' THEN 0
                      WHEN UPPER(COALESCE(d.status_pedido, '')) = 'ABERTO' THEN 0
                      ELSE 1
                    END
                ) = 0
            ORDER BY d.nropedido DESC
            Ztotal_valorr  r  z[DELIVERY_DESPACHO LIST]rv   r  )r   r>   r   r   r6  r   r   r   r   r   r   r   r(  r)  r*  r~   rk  rl  rH   )re   r   r   r   r  rX   r9   r9   r:   api_delivery_pedidos_despacho  s:    
4r}  z/api/despachar-deliveryc               
   C   s   t d} | s tddddfS tjddp.i }zt|dp@d	}W n ttfk
rb   d	}Y nX zt|d
ptd	}W n ttfk
r   d	}Y nX |d	ks|d	krtddddfS d}d}zzt	  t
 }|  |jdd}|d|| f | dkr*|  tddddfW W S |d| |f | pFi }t|dpXd	d	kr|  tddddfW W \S |d| |f | pi }t|dpd	d	kr|  tddddfW W S t|}|d|| |f t|dr
|jnd	}	|  zt| || W n2 tk
rX }
 ztd|
dd W 5 d}
~
X Y nX tdd|	dW W pS  tjjk
r } zF|r|  td|dd t  tdt|ddf W Y W S d}~X Y nX W 5 |r|  |r|  X dS ) uc   Grava código do entregador (chave) e altera status_pedido para ROTA nas linhas DELIVERY em ABERTO.re   Fr{  r  r|  Tr  r   r   r5  u/   Informe nropedido e codigo_entregador válidos.r  Nr~  zESELECT 1 FROM entregador WHERE chave = %s AND id_cliente = %s LIMIT 1u-   Entregador não encontrado para este cliente.rS   aB  
            SELECT COUNT(*) AS bad
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = 'DELIVERY'
              AND nropedido = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND UPPER(COALESCE(status_pedido, '')) <> 'ABERTO'
            ZbaduG   Pedido não está elegível (existem linhas que não estão em ABERTO).z
            SELECT COUNT(*) AS ok
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = 'DELIVERY'
              AND nropedido = %s
              AND UPPER(COALESCE(status_pedido, '')) = 'ABERTO'
            rK  z&Nenhuma linha ABERTO para este pedido.a   
            UPDATE pedido_diarios
            SET entregador = %s,
                status_pedido = 'ROTA'
            WHERE id_cliente = %s
              AND origem = 'DELIVERY'
              AND nropedido = %s
              AND UPPER(COALESCE(status_pedido, '')) = 'ABERTO'
            r  z[DESPACHO WHATSAPP]rv   u1   Pedido despachado (ROTA) e entregador atribuído.)rU   r  Zlinhas_atualizadasz[DESPACHAR_DELIVERY]r  )r   r>   r   r   r  r   r   r   r   r6  r   r  r   r   r   r   rH   hasattrr  r   r7  rW   r~   r(  r)  r*  rk  rl  )re   rE  r   r5  r   r   Zrow_badZrow_okZ
codigo_strZaffZ_waerX   r9   r9   r:   api_despachar_deliveryP  s    


		 
4r  z!/api/obter-entregador/<int:chave>c              
   C   s   d}d}zzht }|jdd}td}|d| |f | }|rXtd|dW W lS tddd	d
fW W TS W nJ tj	j
k
r } z(td| tddd	df W Y W S d}~X Y nX W 5 |r|   |r|   X dS )u)   Obtém dados de um entregador específicoNTr~  re   z
            SELECT chave, nome, telefone, endereco
            FROM entregador
            WHERE chave = %s AND id_cliente = %s
        )rU   r   F   Entregador não encontrador  rS   rj  zErro ao obter entregadorr  r   r   r   r   r>   r   r   r   r(  r)  r*  r~   r   r   r   re   r   r,  r9   r9   r:   obter_entregador  s.    

0r  z"/api/editar-entregador/<int:chave>c           	   
   C   sd  d}d}z6ztjpi }|dd }|dd }|dd }|sdtdddd	fW W S t }| }td
}|	d|||| |f |
  |jdkrtd| d|  d tdd| ddW W nS tddddfW W VS W nL tjjk
r< } z(td| tddddf W Y W S d}~X Y nX W 5 |rP|   |r^|   X dS )zEdita um entregador existenteNrf   r*   r   r   Frg  r  r  re   z
            UPDATE entregador 
            SET nome = %s, telefone = %s, endereco = %s
            WHERE chave = %s AND id_cliente = %s
        r   z[ENTREGADOR ATUALIZADO] rh  r   Tri  z' atualizado com sucesso!r  r  rS   rj  zErro ao editar entregadorr  )r   r   r  r>   r   r   r   r   r   r   r   r  r~   r(  r)  r*  )	r   r   r   rx  rf   r   r   re   r,  r9   r9   r:   editar_entregador  s<    




0r  z#/api/excluir-entregador/<int:chave>c              
   C   s  d}d}zzt }|jdd}td}|d| |f | }|s\tdddd	fW W S |d
| |f |  t	d|d  d|  d tdd|d  ddW W PS  t
jjk
r } z(t	d| tddddf W Y W S d}~X Y nX W 5 |r
|   |r|   X dS )zExclui um entregadorNTr~  re   z@SELECT nome FROM entregador WHERE chave = %s AND id_cliente = %sFr  r  rS   z;DELETE FROM entregador WHERE chave = %s AND id_cliente = %su   [ENTREGADOR EXCLUÍDO] rf   rh  r   ri  u   ' excluído com sucesso!r  rj  zErro ao excluir entregadorr  r   r   r   r   r>   r   r   r   r   r~   r(  r)  r*  r  r9   r9   r:   excluir_entregador  s0    

0r  z/cadastrar-classificacaoc                  C   s,   t d} t| }|dd}td| |dS )u'   Página de cadastro de classificaçõesre   rf   rg   zcadastrar_classificacao.htmlrh   rj   rk   r9   r9   r:   cadastrar_classificacao?  s    
r  z/api/salvar-classificacaoc                  C   s  d} d}zjztjpi }|dd }|d}|d}|d}|d}|d}|d	}	|d
}
|d}|stddddfW W S t } |  }td}|	d||||dk	rt
|  nd|||	|
||f
 |   |j}td| d| d tdd| ddW W RS  tjjk
rp } z(td| tddddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )u   Salva uma nova classificaçãoNnomeclassificacaor*   quantidadepartesnrofotor  op_tamanhos	op_massas	op_bordasop_coberturasop_adicionaisF'   Nome da classificação é obrigatórior  r  re   z
            INSERT INTO classificacao (nomeclassificacao, quantidadepartes, nrofoto, formadecobrar, op_tamanhos, op_massas, op_bordas, op_coberturas, op_adicionais, id_cliente)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        u   [CLASSIFICAÇÃO CADASTRADA] rh  r   T   Classificação 'z' cadastrada com sucesso!rj  u0   Erro ao salvar classificação no banco de dadosr  )r   r   r  r>   r   r   r   r   r   r   rH   r   r   r  r~   r(  r)  r*  )r   r   rx  r  r  r  r  r  r  r  r  r  re   rk  r,  r9   r9   r:   salvar_classificacaoH  sZ    











0r  z/api/listar-classificacoesc               
   C   s   d} d}zznt } | jdd}td}|d|f | }|D ](}|d|d |f | }||d< qBt|W W PS  tj	j
k
r } z(td	| td
dddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )u+   Lista todas as classificações cadastradasNTr~  re   a  
            SELECT chave, nomeclassificacao, quantidadepartes, nrofoto, formadecobrar,
                   op_tamanhos, op_massas, op_bordas, op_coberturas, op_adicionais
            FROM classificacao
            WHERE id_cliente = %s
            ORDER BY nomeclassificacao
        zQSELECT produto AS nome, preco FROM produtos WHERE classe = %s AND id_cliente = %sr  rQ  rj  Fu   Erro ao listar classificaçõesr  r  rn  )r   r   re   ZclassificacoesZclassifrQ  r,  r9   r9   r:   listar_classificacoes  s,    


0r  z$/api/obter-classificacao/<int:chave>c              
   C   s   d}d}zzbt }|jdd}td}|d| |f | }|rRt|W W lS tdddd	fW W TS W nJ tj	j
k
r } z(td
| tddddf W Y W S d}~X Y nX W 5 |r|   |r|   X dS )u/   Obtém dados de uma classificação específicaNTr~  re   a  
            SELECT chave, nomeclassificacao, quantidadepartes, nrofoto, formadecobrar,
                   op_tamanhos, op_massas, op_bordas, op_coberturas, op_adicionais
            FROM classificacao
            WHERE chave = %s AND id_cliente = %s
        F   Classificação não encontradar  rS   rj  u   Erro ao obter classificaçãor  r  r   r   r   re   Zclassificacaor,  r9   r9   r:   obter_classificacao  s(    

0r  z%/api/editar-classificacao/<int:chave>c                 C   s  d}d}zz<tjpi }|dd }|d}|d}|d}|d}|d}	|d	}
|d
}|d}|stddddfW W S t }| }td}|	d||||dk	rt
|  nd||	|
||| |f |  |jdkr0td| d|  d tdd| ddW W nS tddddfW W VS W nL tjjk
r } z(td| tddddf W Y W S d}~X Y nX W 5 |r|   |r|   X dS )u#   Edita uma classificação existenteNr  r*   r  r  r  r  r  r  r  r  Fr  r  r  re   a  
            UPDATE classificacao 
            SET nomeclassificacao = %s,
                quantidadepartes = %s,
                nrofoto = %s,
                formadecobrar = %s,
                op_tamanhos = %s,
                op_massas = %s,
                op_bordas = %s,
                op_coberturas = %s,
                op_adicionais = %s
            WHERE chave = %s AND id_cliente = %s
        r   u   [CLASSIFICAÇÃO ATUALIZADA] rh  r   Tr  z' atualizada com sucesso!r  rS   rj  u   Erro ao editar classificaçãor  )r   r   r  r>   r   r   r   r   r   r   rH   r   r   r  r~   r(  r)  r*  )r   r   r   rx  r  r  r  r  r  r  r  r  r  re   r,  r9   r9   r:   editar_classificacao  s^    











0r  z&/api/excluir-classificacao/<int:chave>c              
   C   s  d}d}zzt }|jdd}td}|d| |f | }|s\tdddd	fW W S |d
| |f |  t	d|d  d|  d tdd|d  ddW W PS  t
jjk
r } z(t	d| tddddf W Y W S d}~X Y nX W 5 |r
|   |r|   X dS )u   Exclui uma classificaçãoNTr~  re   zPSELECT nomeclassificacao FROM classificacao WHERE chave = %s AND id_cliente = %sFr  r  rS   z>DELETE FROM classificacao WHERE chave = %s AND id_cliente = %su   [CLASSIFICAÇÃO EXCLUÍDA] r  rh  r   r  u   ' excluída com sucesso!rj  u   Erro ao excluir classificaçãor  r  r  r  r9   r9   r:   excluir_classificacao  s0    

0r  z/dados-lojac                  C   s,   t d} t| }|dd}td| |dS )u%   Página de cadastro dos dados da lojare   rf   rg   zdados_loja.htmlrh   rj   rk   r9   r9   r:   rl   8  s    
rl   z/api/salvar-dados-lojac                  C   sN  d} d}z zvtjpi }|dd}|dd}|dd}|dd}|dd}|dd}|d	d}	|d
d}
|dd}|dd}|drdnd}td}|stddddfW W bS t } |  }|d|f |	 }|r|d|||||||	|
||||f nN|d||||||||	|
|||f |d|f |	 }|sj|d|f | 
  tdddW W S  tjjk
r } z0td|  tdt|ddf W Y W bS d}~X Y nP tk
r& } z0td|  tdt|ddf W Y W S d}~X Y nX W 5 |r:|   | rH|    X dS ) zSalva os dados da lojaNrf   r*   r   r  r  r   r   cnpjr  r  r  r  r   r   re   F%   id_cliente não encontrado na sessãor  r  z6SELECT id_cliente FROM dadosloja WHERE id_cliente = %sa
  
                UPDATE dadosloja 
                SET nome = %s, endereco = %s, bairro = %s, cidade = %s, cep = %s, telefone = %s, cnpj = %s, latitude = %s, longitude = %s, ddd = %s, cliente_obrigatorio_balcao = %s
                WHERE id_cliente = %s
            z
                INSERT INTO dadosloja (id_cliente, nome, endereco, bairro, cidade, cep, telefone, cnpj, latitude, longitude, ddd, cliente_obrigatorio_balcao)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            z;SELECT id_cliente FROM contadorpedido WHERE id_cliente = %sz@INSERT INTO contadorpedido (contador, id_cliente) VALUES (1, %s)Tz Dados da loja salvos com sucessor  
[ERRO DB] r  [ERRO] )r   r   r  r>   r   r   r   r   r   r   r   r(  r)  r*  r~   rH   rW   )r   r   rx  rf   r   r  r  r   r   r  r  r  r  r  re   rG  Zexiste_contadorrX   r9   r9   r:   salvar_dados_lojaA  sZ    

.4r  z/api/buscar-dados-lojac               
   C   s   d} d}zzbt } | jdd}td}|d|f | }|rVtd|dW W pS tdddW W \S W nR tj	j
k
r } z0td|  tdt|d	d
f W Y W S d}~X Y nX W 5 |r|   | r|    X dS )zBusca os dados da lojaNTr~  re   z5SELECT * FROM dadosloja WHERE id_cliente = %s LIMIT 1rU   rx  r  Fr  r  r   r   r   r   r>   r   r   r   r(  r)  r*  r~   rH   )r   r   re   rx  rX   r9   r9   r:   buscar_dados_loja  s$    
4r  z/cadastrar-taxac                  C   s,   t d} t| }|dd}td| |dS )u'   Página de cadastro de taxas de entregare   rf   rg   zcadastrar_taxa.htmlrh   rj   rk   r9   r9   r:   cadastrar_taxa  s    
r  z/api/dados-loja-infoc               
   C   sr   z"t d} t| }td|dW S  tk
rl } z,td|  tdt|ddf W Y S d}~X Y nX dS )	u-   Retorna informações da loja para exibiçãore   Tr  r  Fr  r  N)r   r>   r   r   rW   r~   rH   )re   rx  rX   r9   r9   r:   dados_loja_info  s    
r  z/api/impressao-metac               
   C   s   zt d} | s$tddddfW S zttjdp6d}W n ttfk
rX   d}Y nX tjd}tt| ||t d	}td
di|W S  t	k
r } z8t
d| dd t  tdt|ddf W Y S d}~X Y nX dS )uJ   Metadados do pedido para cabeçalho de impressão (atendente + data/hora).re   Fr{  r  r|  r   r   r   rI   rU   Tz[IMPRESSAO META ERRO] rv   r  N)r   r>   r   r   r   r  r   r   r   rW   r~   rk  rl  rH   )re   r   r   metarX   r9   r9   r:   api_impressao_meta  s(    

r  z/api/salvar-taxac               
   C   s  d} d}z\ztjpi }|dd}td}g }g }tddD ]`}|d| d}|d| d}	|d| d	 |d| d
 || ||	 qBt } |  }|	d||f |
 }
|
rdd| d}|| || |	|t| td| d|  nddgdd tddD  dd tddD  }dgt| }||g}tddD ]}||d| d qltddD ]}||d| d qdd| dd| d}|	|t| td| d|  |   tdddW W VS  tjjk
rb } z,td| tdt|ddf W Y W S d}~X Y nX W 5 |rv|   | r|    X dS ) z%Salva ou atualiza as taxas de entregaNr   r   re   r  r  r  r  z_d = %sz_v = %sz@SELECT chave FROM txentrega WHERE chave = %s AND id_cliente = %szUPDATE txentrega SET r   % WHERE chave = %s AND id_cliente = %sz [TAXA ENTREGA ATUALIZADA] chave z, id_cliente c                 S   s   g | ]}d | dqS )r  r  r9   r  r9   r9   r:   r    s     zsalvar_taxa.<locals>.<listcomp>c                 S   s   g | ]}d | dqS )r  r  r9   r  r9   r9   r:   r    s     r   zINSERT INTO txentrega (r   r   z[TAXA ENTREGA CRIADA] chave Tz$Taxas de entrega salvas com sucesso!r  rj  Fr  r  )r   r   r  r>   r   r&  r   r   r   r   r   ry   r   r~   r@   r   r   r(  r)  r*  rH   )r   r   rx  r   re   rH  valoresr  r  r  rG  sqlZcampos_insertplaceholdersZvalores_insertr,  r9   r9   r:   salvar_taxa  s^    




0
4r  z/api/obter-taxac               
   C   s   d} d}zzbt } | jdd}td}|d|f | }|rVtd|dW W lS tdddW W XS W nN tj	j
k
r } z,td| tdt|d	d
f W Y W S d}~X Y nX W 5 |r|   | r|    X dS )u'   Obtém as taxas de entrega configuradasNTr~  re   r  )rU   r  rj  Fr  r  r  )r   r   re   r  r,  r9   r9   r:   
obter_taxa  s$    

4r  z/api/buscar-taxa-padraoc               
   C   s   d} d}zztt } | jdd}td}|d|f | }|rh|drhtdt|d dW W pS tdddW W \S W nR t	j
jk
r } z0td	|  td
t|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )u9   Busca o valor da primeira faixa de entrega (taxa padrão)NTr~  re   z<SELECT faixa1_v FROM txentrega WHERE id_cliente = %s LIMIT 1r  )rU   Ztaxa_padraor   r  Fr  r  )r   r   r   r   r>   r   r   r   r   r(  r)  r*  r~   rH   )r   r   re   r  rX   r9   r9   r:   buscar_taxa_padrao7  s$    
4r  z/api/buscar-configuracaoc               
   C   s   d} d}zz~t } | jdd}td}|sDtddddfW W S |d	|f | }|rrtd|d
W W pS tddd
W W \S W nR tj	j
k
r } z0td|  tdt|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )u#   Busca as configurações do sistemaNTr~  re   Fr{  r  r|  LSELECT * FROM configuracao WHERE id_cliente = %s ORDER BY chave DESC LIMIT 1)rU   configr  r  )r   r   r   r   r>   r   r   r   r(  r)  r*  r~   rH   )r   r   re   r  rX   r9   r9   r:   buscar_configuracaoS  s(    
4r  )r   c              	   C   s\   |  d|  |  pg }t }|D ]0}z|t|d  W q& tk
rT   Y q&X q&|S )NzSHOW COLUMNS FROM r   )r   r   r   r   rH   rW   )r   r   r   r   r   r9   r9   r:   _get_table_columnsq  s    r  z/api/configuracao-sistemac               
      s  d } d }zzLtd}|s8tddddfW W S t } | jdd}|  }t|d |   d	d
dg} fdd|D }|stddddfW W S ddg| }|d| d|f |	 }dddd}i }	|D ]^}
|r0|
|kr0||
 d k	r0||
 }t
|tjr&t||	|
< n||	|
< q||
|	|
< qtd|	|t|dW W ^S  tk
r } z8td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r|   | r|    X d S )Nre   Fr{  r  r|  Tr~  configuracaonromesar  calculodistanciac                    s   g | ]}| kr|qS r9   r9   rC  r   r9   r:   r    s      z,api_configuracao_sistema.<locals>.<listcomp>-   Tabela configuracao sem colunas compatíveis.r  r   r   zSELECT zD FROM configuracao WHERE id_cliente = %s ORDER BY chave DESC LIMIT 1d   r   Sim)r  r  r  )rU   rx  rH  rG  z[CONFIG SISTEMA GET ERRO]rv   )r   r   r>   r   r   r   r  ry   r   r   r  r  r  r   r  rW   r~   rk  rl  rH   )r   r   re   Z	cur_plainwantedZ	availabler  r   defaultsrx  rl  r=  rX   r9   r  r:   api_configuracao_sistema}  sN    




4r  c                     s  d } d }z֐ztd}|s8tddddfW W S tjp@i }t|dtr\|dn|}t } | 	 }t
|d dd	d
g} fdd|D }|stddddfW W 2S i }d|krd|krztt|d|d< W n0 tk
r   tddddf Y W W S X d	|krrd	|krrzt|d	|d	< W n0 tk
rp   tddddf Y W W tS X d
|krd
|krt|d
pd  }|dkrdnd|d
< |stddddfW W S | j	dd}	|	d|f |	 }
|	   |
r^|
dr^ddd | D }t| |
d |g }|d| dt| n\dgt|  }ddgt| }|gt|  }|d d| d!| d"t| |   tdd#d$W W S  tjjk
r\ } zbz| r|   W n tk
r   Y nX td%|dd& t   tdt|ddf W Y W S d }~X Y n tk
r } zbz| r~|   W n tk
r   Y nX td%|dd& t   tdt|ddf W Y W S d }~X Y nX W 5 |r|   | r|    X d S )'Nre   Fr{  r  r|  rx  r  r  r  r  c                    s   g | ]}| kr|qS r9   r9   rC  r  r9   r:   r    s      z3api_salvar_configuracao_sistema.<locals>.<listcomp>r  r  u   nromesa inválido.r  u   servicomesa inválido.r*   )rA  r>  r\  r@  yrC  r  ZNaozNenhum campo para salvar.Tr~  zPSELECT chave FROM configuracao WHERE id_cliente = %s ORDER BY chave DESC LIMIT 1r   r   c                 S   s   g | ]}| d qS )z = %sr9   )r   rl  r9   r9   r:   r    s     zUPDATE configuracao SET r  r   zINSERT INTO configuracao (r   r   u,   Configuração do sistema salva com sucesso.r  z[CONFIG SISTEMA POST ERRO]rv   )!r   r   r>   r   r   r  r  r  r   r   r  r   r   rW   rH   r   rB  r   r   ry   keysr^   r   r   r@   r   r(  r)  r*  r   r~   rk  rl  )r   r   re   payloadZdata_inr  allowedZupdatesrawZcur_selr   r'  r  Zcols_insr  r,  rX   r9   r  r:   api_salvar_configuracao_sistema  s    



  
.4r  )r  r[  r  
origem_tagc                 C   s   |||p
ddd}t tdt|p dD ]}ztj|  |dd}W n8 tjk
r| } zdt|f W Y   S d}~X Y nX |jdkr(dd	|j d
|j	pddd  f  S q(dS )u:   Envia conteúdo ao serviço de impressão em URL (bridge).r~   r   )r[  Ztextor   r  #   )r  r  FNr  zHTTP r  r*   rE  )
r&  r  r   r  Zpostr   ZRequestExceptionrH   r  text)r  r[  r  r  rE  Z_ir[  excr9   r9   r:   _impressao_http_caminho  s    &
*r  z	/imprimirc            1   
   C   s  t jpi } t| ddpd }t| ddp2d }| dg }| dpRd  }|dk}| dd}zt| dd	pd	}W n ttfk
r   d	}Y nX zt| d
d}W n* ttfk
r   t	ddddf Y S X |dk s|dkr
t	ddddfS |s"t	ddddfS |dkr0g }t
|tsNt	ddddfS | ddk}	d}
t| dppd }|r^td}t|| }t|||| dd\}}|rt	d|ddfS | }|ds|drV|d }t||||pd\}}|st	d||d d!fS t jd"d#ks8t jrJt	d$||d%d&S ttd'S |}d$}
| d}|s6|dk	r6t| dkr6zt|}W n, ttfk
r   t	dd(ddf Y S X t }|jd$d)}|d* | dk	}|r|d+|f n|d,|f | }|  |  |s@t	dd-ddfS |d.pNd }|d/pbd }|s|st	dd0ddfS | }|ds|dr$|d }t||||pd\}}|st	d||p|d d!fS t jd"d#ks t jrt	d$|p||d%d&S ttd'S |p,| }d$}
td1 td2| d
  td3t| d
  td4|  |r|s|d5| d7 }|d7 }|	r|r|r|}n*|pttt|| d6pd pd7}g }nd}|	sf|rf|d8krf|sfzt||| W nP tk
rd } z0td9|  t   t	dd:dd;f W Y S d}~X Y nX |	sNt|| } tt| d6pd }!|
r|r|}n|p|!pt!j"d<krt#rt#$ nd}|r$t% }"|"rf| d=d> |"D krft&||"}#|#st	dd?| |"d@dfS |#}nBt% }"|"rf|rft| dAd> |"D krft&||"}#|#rf|#}t }$|$jd$d)}%td}&|%dB|&f |% }'d}(|'r|'dC})|)rdD|) }*|'|*}(|%r|%  |$r|$  tdE| dF g }t'|D ]N}+t(|||(\},}-|,s|)dG|+d  dH|-  tdI|+d  dJ|-  q|rnt	ddK*||d d;fS |d8kr6|d	kr6|s6d}.d}/zz4t }.|. }/td}&|/dL||&f |.+  W nL tk
r } z,|.r|.,  tdM| d$dN t   W 5 d}~X Y nX W 5 |/r&|/  |.r4|.  X t jd"d#ksPt jrrd$||dO}0|	rjdP|0dQ< t	|0S ttd'S dS )Ru   Endpoint de impressão silenciosa. Resolve nome da impressora pela ordem: parâmetro -> DB -> padrão do Windows.
    Retorna JSON com sucesso/erro e o nome da impressora utilizado.
    r[  r*   r}  rQ  r   r|  rt  r   r   r  r   Fu   Número de cópias inválido.r  r  r  u*   Número de cópias deve estar entre 1 e 5.u   Conteúdo de impressão vazio.Nu   Lista de produtos inválida.apenas_confirmar)Tr   r\  r@  rC  r8  re   r9  r)  r9  r
  zhttp://zhttps://ro   r~   rU   rV   r}  i  zX-Requested-WithZXMLHttpRequestTZhttp_caminho)rU   r}  r  r  ra  u   impressora_id inválido.r~  ro  zgSELECT id, nomedaimpressora, TRIM(COALESCE(caminho,'')) AS caminho FROM impressoras WHERE id=%s LIMIT 1zOSELECT id, nomedaimpressora, '' AS caminho FROM impressoras WHERE id=%s LIMIT 1u&   Impressora cadastrada não encontrada.rx  nomedaimpressoraz.Cadastro da impressora sem nome e sem caminho.z"[IMPRESSAO DEBUG] Dados recebidos:z  - copias (raw): z  - copias (type): z  - copias (convertido): zFORMA DE PAGAMENTO: )r)  r~  r  rP  z"Falha ao gravar delivery pendente.r  r<  c                 S   s   h | ]}|  qS r9   rA  rC  r9   r9   r:   rE    s     zimprimir.<locals>.<setcomp>u*   Impressora informada não foi encontrada: )rU   rV   impressoras_disponiveisc                 S   s   h | ]}|  qS r9   rA  rC  r9   r9   r:   rE    s     r  Zimp_comandadeliveryZ	marca_impz[IMPRESSAO] Imprimindo u    cópia(s)...u   Cópia r  u   [IMPRESSAO ERRO] Cópia z	 falhou: z; aF  
                    UPDATE pedido_diarios
                    SET status_pedido = 'ABERTO'
                    WHERE nropedido = %s
                      AND id_cliente = %s
                      AND origem IN ('DELIVERY','BALCAO')
                      AND UPPER(COALESCE(status_pedido, '')) = 'AGUARDE'
                    z[IMPRESSAO STATUS_PEDIDO ERRO] rv   )rU   r}  r  r  r  )-r   r  rH   r>   r   rB  r   r   r   r   r  r^   r   rz  r;  r?   r  rP   Zis_jsonr	   r
   r   r   r   r   r   r~   r  r-  rS  rW   rk  rl  r  r=  r>  rF  rB  rH  r&  rO  r   ry   r   r   )1rx  r[  printer_paramrQ  r   r  rt  r   r  r  Zskip_printer_enum_checkZterminal_id_rawZ
id_cli_impZpurpose_termZcaminho_termZerr_termZcl_termZconteudo_httpZok_httpZerr_httpZimpressora_id_rawr0  Zconn_impZcur_impZhas_caminho_colZrow_impZ	caminho_vZnome_vZclprinter_resolvedZerrosrX   r)  
printer_dbrL  rM  r   r   re   r  rK  Znro_impZcampo_marcar  rK  r>  r  r  r[  r9   r9   r:   imprimir  st   






"

(
*
(






r  z/testar-impressorac                  C   s   t tjddpd } t t p$d }| pL|pLtjdkrJtrJt	 nd}d}t
||\}}|rrtd|dS td||d	d
fS dS )z7Envia uma linha de teste para a impressora configurada.r}  r*   r<  Nu(   *** TESTE DE IMPRESSÃO - NOVALOJA ***
T)rU   r}  Fr  r  )rH   r   r  r>   r   r-  r  r=  r>  rF  rO  r   )r  r  r  rV  rK  r>  r9   r9   r:   testar_impressora  s    "r  z/api/impressoras-disponiveisc               
   C   s   znt ds tddddfW S t } d}tjdkr^tr^zt }W n tk
r\   d}Y nX td| |d	W S  tk
r } z4t	d
|dd t
  tdt|ddf W Y S d}~X Y nX dS )u?   Retorna impressoras disponíveis para diagnóstico no frontend.re   Fr{  r  r|  Nr<  T)rU   rG  Zpadraoz[IMPRESSORAS DISPONIVEIS ERRO]rv   r  )r   r>   r   rB  r  r=  r>  rF  rW   r~   rk  rl  rH   )r@  default_namerX   r9   r9   r:   r    s    

r  z/api/impressora-para-origemc               
   C   sJ  zt d} | s$tddddfW S tjdd}t|}tjd}tjd	}|rt| |||d
\}}|rtd|||t|ddfW S td|||t|dW S t	t
|| dpd }|stdd||ddfW S td|||dW S  tk
rD } z4td|dd t  tdt	|ddf W Y S d}~X Y nX dS )zMImpressora habilitada: casa/delivery (comanda_delivery) ou mesa (conta_mesa).re   Fr{  r  r|  r   r  r8  r9  r  )rU   rV   r   r)  r8  r
  T)rU   r}  r   r)  r8  r3  r*   r4  )rU   rV   r   r)  rS   )rU   r}  r   r)  z[IMPRESSORA ORIGEM ERRO]rv   r  N)r   r>   r   r   r  rz  r;  r5  r6  rH   r-  r   rW   r~   rk  rl  )id_clir   r)  r8  r9  r}  r>  rX   r9   r9   r:   api_impressora_para_origem  sh    



r  z/api/terminal-impressorasc                  C   s  zt   t  td} | s2tddddfW S ttjdpDd}|s`tdddd	fW S i }t	| |D ],}t
|d
pd |t|dpd< qpt }|jdd}zV|d | dk	}d}d}|rd}t| f}|d| d| | pg }	W 5 |  |  X g }
|	D ]t}t|dp6d}|
|t
|dpPd t
|dpfd t
|dp|d ||dd q"td|t| ||
dW S  tk
r } z4td|dd t  tdt
|ddf W Y S d}~X Y nX dS )u2   Lista impressoras lógicas + caminhos do terminal.re   Fr{  r  r|  r8  r*   Informe terminal_id.r  caminho_localr9  r   Tr~  rs  Nr9   . WHERE (id_cliente = %s OR id_cliente IS NULL)z
                SELECT id, nomedaimpressora,
                       UPPER(COALESCE(conta_mesa,'')) AS conta_mesa,
                       UPPER(COALESCE(comanda_delivery,'')) AS comanda_delivery
                FROM impressoraszV
                ORDER BY COALESCE(imprenro,0) DESC, nomedaimpressora
                r  r  rv  rw  )r9  r  rv  rw  r  )rU   r8  rR  rG  z[TERMINAL IMPRESSORAS GET ERRO]rv   r  )rg  rf  r   r>   r   r5  r6  r   r  Zload_terminal_configrH   r   r   r   r   r   r   r   r   r   r7  rW   r~   rk  rl  )r  r8  Zcfg_mapr   r   r   
has_id_cli	where_clir  r   rG  r   r0  rX   r9   r9   r:   api_terminal_impressoras_getQ  sj    
*






r  c               
   C   s:  zt   t  td} | s0tddddfW S tjddp>i }t|dpPd	}|sltdd
ddfW S |dpxg }t	|t
stddddfW S t| ||\}}|std|pdddfW S tdd|t| |dW S  tk
r4 } z4td|dd t  tdt|ddf W Y S d}~X Y nX dS )z"Salva caminhos locais do terminal.re   Fr{  r  r|  Tr  r8  r*   r  r  r   zitens deve ser uma lista.zFalha ao salvar.u!   Configuração do terminal salva.)rU   r  r8  rR  z [TERMINAL IMPRESSORAS POST ERRO]rv   r  N)rg  rf  r   r>   r   r   r  r5  r6  r  r^   Zsave_terminal_configr7  rW   r~   rk  rl  rH   )r  rE  r8  r   rK  r>  rX   r9   r9   r:   api_terminal_impressoras_post  s4    



r  z/api/impressoras-cadastroc                  C   s  d} d}zzt  td}|s>tddddfW W S t } | jdd}|d	 | dk	}|d
 | dk	}|d | dk	}|d | dk	}dddg}|	|rdnd |	|rdnd |	|rdnd |	|rdnd |}|d | dk	}	d}
d}d}|	rB|dk	rBd}
t
|f}d}|dd| d |
 d!| d!| | ptg }|r|t|d" tr|d#|d" kr|d}z|  }|d$ | dk	rLd%d& |D }|rLdd'gt| }|d(| d)t| d*d+ | pg D }|D ].}|d}|dk	r|t
|d"|d#< qW 5 z|r`|   W n tk
rx   Y nX X td|d,W W ^S  tk
r } z8td-|dd. t  tdt|dd/f W Y W S d}~X Y nX W 5 |r|   | r|    X dS )0zNImpressoras cadastradas na tabela impressoras (nome + caminho quando existir).Nre   Fr{  r  r|  Tr~  ro  rp  rq  rr  r  r  z COALESCE(imprenro,0) AS imprenroz%TRIM(COALESCE(caminho,'')) AS caminhoz'' AS caminhoz,UPPER(COALESCE(conta_mesa,'')) AS conta_mesaz'' AS conta_mesaz8UPPER(COALESCE(comanda_delivery,'')) AS comanda_deliveryz'' AS comanda_deliveryzKLEAST(GREATEST(COALESCE(feed_final_linhas, 6), 0), 20) AS feed_final_linhasz6 AS feed_final_linhasrs  r*   z4ORDER BY COALESCE(imprenro,0) DESC, nomedaimpressorar9   r  zNORDER BY (id_cliente IS NULL) ASC, COALESCE(imprenro,0) DESC, nomedaimpressorar  r   z
            FROM impressorasr  r   imprenrorn  c                 S   s(   g | ] }| d dk	rt| d qS )r  N)r>   r   r  r9   r9   r:   r    s      z,api_impressoras_cadastro.<locals>.<listcomp>r   z2SELECT id, imprenro FROM impressoras WHERE id IN (r   c                 S   s"   i | ]\}}t |t |pd qS r  r   )r   ridr   r9   r9   r:   
<dictcomp>  s      z,api_impressoras_cadastro.<locals>.<dictcomp>)rU   rG  z[IMPRESSORAS CADASTRO]rv   r  )r   rf  r   r>   r   r   r   r   r   r   r   ry   r   r  r  rW   r@   r   r~   rk  rl  rH   )r   r   Zid_cli_guardr  has_cmhas_cdhas_feedr   r  r  r  Zorder_clauser  r   Zcur_chkr  r  rW  r   r  rX   r9   r9   r:   api_impressoras_cadastro  s    









$



4r  c                 C   s$   t | pd  }|dkr dS dS )Nr*   )rZ  r[  r\  r]  ZYESr  rZ  r  r  )valuer  r9   r9   r:   _sn_flag  s    r  c                  C   s  d } d }zzt  td}|s>tddddfW W rS tjpFi }t|dpVd }t|dpld }zt	|d	pd
}W n. t
k
r   tddddf Y W W S X t|d}t|d}z$t	|dd k	r|dnd}	W n0 t
k
r*   tddddf Y W W S X td
td|	}	t } |  }|d | d k	}
|d | d k	}|d | d k	}|d | d k	}|d | d k	}|r|stddddfW W S |s|pd}dd	g}||g}|r|d || |r2|d || |rL|d || |rf|d ||	 |
r|d |t	| |dd| dddgt|  dt| |j}|
rd}t	|t	|f}nd }t	|f}|r
|d!kr
|d"| | |   td#d$|d%W W S  t
k
r } zbz| rJ|   W n t
k
rb   Y nX td&|d#d' t  tdt|dd(f W Y W S d }~X Y nX W 5 |r|   | r|    X d S ))Nre   Fr{  r  r|  r  r*   rx  r  r      imprenro inválido.r  rv  rw  feed_final_linhasr     feed_final_linhas inválido.   rs  ro  rp  rq  rr  2Informe o caminho (nome do Windows) da impressora.
IMPRESSORAINSERT INTO impressoras (r   r   r   r   id_cliente = %s AND id <> %sid <> %srZ  .UPDATE impressoras SET conta_mesa = 'N' WHERE Tz"Impressora cadastrada com sucesso.)rU   r  r  z [IMPRESSORAS CADASTRO POST ERRO]rv   r  )r   rf  r   r>   r   r   r  rH   r   r   rW   r  r  minr   r   r   r   r   ry   r@   r   r  r   r   r~   rk  rl  )r   r   r  r  rf   rx  r  rv  rw  r  r  r  r  r  r  r   r   Znew_idr  
params_clirX   r9   r9   r:   api_criar_impressora_cadastro  s    

 $ 














&
4r  z#/api/impressoras-cadastro/<int:pid>)pidc                 C   s  d }d }zڐzPt  td}|s>tddddfW W S tjpFi }t|dpVd }t|dpld }zt	|d	pd
}W n. t
k
r   tddddf Y W W 0S X t|d}t|d}	z$t	|dd k	r|dnd}
W n0 t
k
r*   tddddf Y W W S X td
td|
}
t }| }|d | d k	}|d | d k	}|d | d k	}|d | d k	}|d | d k	}|r|stddddfW W 
S |s|pd}d}t	| g}|r|d7 }|t	| ddg}||g}|rB|d || |r\|d || |rv|d  ||	 |r|d! ||
 |r|d" |t	| |d#d$| d%| t||  |jd
krtdd&dd'fW W S |rd(}t	|t	| f}nd)}t	| f}|rD|d*krD|d+| | |  td,d-d.W W S  t
k
r } zbz|r|  W n t
k
r   Y nX td/|d,d0 t  tdt|dd1f W Y W S d }~X Y nX W 5 |r|   |r|   X d S )2Nre   Fr{  r  r|  r  r*   rx  r  r   r  r  rv  rw  r  r  r  r  rs  ro  rp  rq  rr  r  r  zid = %sr  znomedaimpressora = %szimprenro = %szcaminho = %szconta_mesa = %szcomanda_delivery = %szfeed_final_linhas = %sid_cliente = %sUPDATE impressoras SET r   z WHERE    Impressora não encontrada.rS   r  r  rZ  r  Tz"Impressora atualizada com sucesso.r  z[IMPRESSORAS CADASTRO PUT ERRO]rv   r  )r   rf  r   r>   r   r   r  rH   r   r   rW   r  r  r  r   r   r   r   r   ry   r   r  r   r   r~   rk  rl  )r  r   r   r  r  rf   rx  r  rv  rw  r  r  r  r  r  r  whereZparams_wherer'  r  r  r  rX   r9   r9   r:   api_editar_impressora_cadastrou  s    

 $ 















&
4r  c                 C   st  d }d }zFzt  td}|s<tddddfW W S t }| }|d | d k	}|r~|dt	| t	|f n|dt	| f |j
d	krtdd
ddfW W S |  tdddW W S  tk
rL } z`z|r|  W n tk
r   Y nX td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r`|   |rn|   X d S )Nre   Fr{  r  r|  rs  z9DELETE FROM impressoras WHERE id = %s AND id_cliente = %sz%DELETE FROM impressoras WHERE id = %sr   r  rS   Tz Impressora removida com sucesso.r  z"[IMPRESSORAS CADASTRO DELETE ERRO]rv   r  )r   rf  r   r>   r   r   r   r   r   r   r  r   rW   r   r~   rk  rl  rH   )r  r   r   r  r  rX   r9   r9   r:   api_excluir_impressora_cadastro  s>    


4r  z/api/salvar-impressoras-origemc                     s  d } d z|zt  tds<tddddfW W NS tjpDi }t|dpTd }t|dpjd }t	 } | 
 d	  d k	fd
dtdfdd ttd fdd}|d| |d| |   tdddW W S  tk
r } zbz| r$|   W n tk
r<   Y nX td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 r   | r|    X d S )Nre   Fr{  r  r|  ru  r*   r  rs  c                      s    rdt ffS dS )Nz WHERE id_cliente = %sr  r  r9   )r  r  r9   r:   
_where_cli  s    z1api_salvar_impressoras_origem.<locals>._where_cli)r#  c                    sD     \}} d|  d  s(d S  d|  d| | d S )Nr!  r"  r  z = 'N'r  )r#  r  r  )r  r   r9   r:   _clear_flag  s
    
z2api_salvar_impressoras_origem.<locals>._clear_flag)r#  rJ  c           	   
      s(  |s |  d S  |  d}|g}r8d}| t d| dt|  }|r|d rg }|  dg}r| d | t | t|d  dd	| d
t| d S d| g}|dg}r| d | t dd	| dd	dgt|  dt| d S )Nr*   r  zBSELECT id FROM impressoras WHERE TRIM(nomedaimpressora) = TRIM(%s)z LIMIT 1r   z = 'S'r  r  r   z WHERE id = %sr  rZ  re   r  r   r   r   )r   r   r   r   r   ry   r@   )	r#  rJ  r  r  r   Z
upd_paramsZset_bitsr   r   )r  r   r  r  r9   r:   	_set_flag!  sF    


&z0api_salvar_impressoras_origem.<locals>._set_flagrv  rw  TzImpressoras salvas com sucesso.r  z [IMPRESSORAS SALVAR ORIGEM ERRO]rv   r  )r   rf  r   r>   r   r   r  rH   r   r   r   r   r   r   rW   r   r~   rk  rl  )r   r  Z	mesa_nameZdelivery_namer  rX   r9   )r  r  r   r  r  r:   api_salvar_impressoras_origem   sD    


(

4r  z/preparar-impressaoc               
   C   s   zt jp
i } | dd}| dg }|s<tddddfW S |td< |rzt|| W n8 tk
r } ztd	|  t	  W 5 d
}~X Y nX tddiW S  tk
r } z0td| t	  tdt
|ddf W Y S d
}~X Y nX d
S )u<   Prepara o pedido para impressão e grava em deliverypendenter[  r*   rQ  F   Conteúdo vazior  r  pedido_impressaorP  NrU   Tu   [PREPARAR IMPRESSÃO ERRO]r  )r   r  r>   r   r   rS  rW   r~   rk  rl  rH   )rx  r[  rQ  rX   r9   r9   r:   preparar_impressao]  s$    

r  z/visualizar-pedidoc                  C   sB   t dd} | sd} t d}t|}|dd}td| ||dS )	u@   Exibe página HTML com o pedido formatado e botão de impressãor  r*   u.   Nenhum pedido disponível para visualização.re   rf   rg   zvisualizar_pedido.html)r[  re   ri   rj   )r[  re   rl   ri   r9   r9   r:   visualizar_pedido{  s    
r  z
/gerar-pdfc               
   C   s  zddl m}  ddlm} ddlm} ddl}ddlm} tj	pDi }t
|ddpVd }|d	g }|dkrvg }t|tstd
dddfW S |std
dddfW S |rzt|| W n8 tk
r } ztd|  t  W 5 d}~X Y nX | d}	d|	 d}
|jd|
}|j|| d}| \}}|dd |d}|d }|D ]B}|dk r|  |dd |d }|d|| |d8 }qX|  tdd|
 |dW S  tk
r
 } z0td| t  td
t
|ddf W Y S d}~X Y nX dS )z^Gera PDF do pedido e salva em c:\novaloja1\pedidos\. Retorna o caminho relativo para download.r   )A4)canvas)mmNr   r[  r*   rQ  Fu   Lista de produtos inválidar  r  r  rP  z%Y%m%d_%H%M%Srn  z.pdfc:\novaloja1\pedidos)ZpagesizeZCourierr  ro   (      Tz	/pedidos/)rU   rz  caminho_completoz[GERAR PDF ERRO]r  )Zreportlab.lib.pagesizesr  Zreportlab.pdfgenr   Zreportlab.lib.unitsr  rx   r   r   r  rH   r>   r   r  r^   r   rS  rW   r~   rk  rl  nowr{   rC   ry   ZCanvasZsetFontr(  ZshowPageZ
drawStringsave)r  r   r  rx   r   rx  r[  rQ  rX   	timestampru  r  rD  ZlarguraZalturar  r  rR  r9   r9   r:   	gerar_pdf  s\    





r
  z/carrossel-imagensc                  C   s0  d } d }zzt } | jdd}td}|d|f | pBg }g }|D ]r}|d}|d}|d	}	|	d krxqLd
t	|	 d}
|
|
|d k	rt|nd|pdt	|dpdd qLtd zt| W n tk
r   Y nX t|W W S  tjjk
rN } z4td| t  tdt|ddf W Y W fS d }~X Y nT tk
r } z4td| t  tdt|ddf W Y W S d }~X Y nX W 5 z|r|   W n. tk
r } ztd| W 5 d }~X Y nX z| r|    W n. tk
r( } ztd| W 5 d }~X Y nX X d S )N[WARN] falha ao fechar cursor:"   [WARN] falha ao fechar conexÃ£o:Tr~  re   zrSELECT chave, nomeclassificacao, quantidadepartes, nrofoto AS nro_da_foto FROM classificacao WHERE id_cliente = %sr   r  Znro_da_fotoz/static/img/z.jpegr*   r  r   )rz  r   rf   r  z[CARROSSEL] imagens montadas:rj  Erro de banco de dadosrV   detalhesr  [ERROR]Erro interno no servidor)r   rW   r~   r   r   r   r>   r   r   r   r   rH   r   r   r(  r)  r*  rk  rl  )r   r   rX   re   r  Zimagensr   r   r  r   rz  r,  r9   r9   r:   carrossel_imagens  s\    





.
4r  c                  C   s  t jd} d}d}z
z\| s.tg W W  S t }|jdd}|	d| f |
 pXg }dd	 |D }t|W W S  tjjk
r } z4td
| t  tdt|ddf W Y W fS d}~X Y nT tk
r } z4td| t  tdt|ddf W Y W S d}~X Y nX W 5 z|r2|  W n. tk
rb } ztd| W 5 d}~X Y nX z|rt|  W n. tk
r } ztd| W 5 d}~X Y nX X dS )MRetorna produtos onde produtos.classe = nomeclassificacao recebido em 'nome'.rf   Nr  r  Tr~  z=SELECT produto, preco, classe FROM produtos WHERE classe = %sc                 S   s   g | ]}t |qS r9   r  r  r9   r9   r:   r    s     z,_produtos_filtrar_legacy.<locals>.<listcomp>rj  r  r  r  r  r  )r   r  r>   r   rW   r~   r   r   r   r   r   r(  r)  r*  rk  rl  rH   )rf   r   r   rX   
resultadosr,  r9   r9   r:   _produtos_filtrar_legacy  s<    
.
4r  z/produtos-filtrarc                  C   s  t jd} d}d}zzh| s.tg W W S t }|jdd}t	d}|
d| |f | pdg }d	d
 |D }t|W W S  tjjk
r } z4td| t  tdt|ddf W Y W fS d}~X Y nT tk
r( } z4td| t  tdt|ddf W Y W S d}~X Y nX W 5 z|r>|  W n. tk
rn } ztd| W 5 d}~X Y nX z|r|  W n. tk
r } ztd| W 5 d}~X Y nX X dS )r  rf   Nr  r  Tr~  re   zXSELECT produto, preco, classe, chave FROM produtos WHERE classe = %s AND id_cliente = %sc                 S   s   g | ]}t |qS r9   r  r  r9   r9   r:   r  7  s     z$produtos_filtrar.<locals>.<listcomp>rj  r  r  r  r  r  )r   r  r>   r   rW   r~   r   r   r   r   r   r   r(  r)  r*  rk  rl  rH   )rf   r   r   rX   re   r  r,  r9   r9   r:   produtos_filtrar&  s>    

.
4r  z/produto/<classe>c                 C   s  d }d }z6zt }|jdd}td|   td}|d| |f | }|	  t
| t|}|rzt|W W S td| d	d
fW W S W n tjjk
r } z4td| t  tdt|ddf W Y W fS d }~X Y nT tk
r< } z4td| t  tdt|ddf W Y W S d }~X Y nX W 5 z|rR|   W n. tk
r } ztd| W 5 d }~X Y nX z|r|   W n. tk
r } ztd| W 5 d }~X Y nX X d S )Nr  r  Tr~  z&[DEBUG] Consulta produto pela classe: re   z<SELECT * FROM produtos WHERE classe = %s AND id_cliente = %su   Produto nÃ£o encontrado)rV   r   rS   rj  r  r  r  r  r  )r   rW   r~   r   r   r   r>   r   r   r   r   r  r   r(  r)  r*  rk  rl  rH   )r   r   r   rX   re   r/  r,  r9   r9   r:   r   P  sB    

.
4r   z/buscar-clientec                  C   sJ  t jd} d }d }zz| s6tddidfW W S t }|jdd}t	d	}d

dd t| D }|d|f | pg }d }|D ]P}d

dd t|dpd
D }	|	sq|	|ks|	|s||	r|} qq|rt|}t|W W S tddidfW W S W n tjjk
rh }
 z4td|
 t  tdt|
ddf W Y W fS d }
~
X Y nT tk
r } z4td| t  tdt|ddf W Y W S d }~X Y nX W 5 z|r|  W n. tk
r  } ztd| W 5 d }~X Y nX z|r|  W n. tk
rB } ztd| W 5 d }~X Y nX X d S )Nr   r      [WARN] falha ao fechar conexão:rV   u   Telefone não fornecidor  Tr~  re   r*   c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      z!buscar_cliente.<locals>.<genexpr>zKSELECT * FROM clientes WHERE id_cliente = %s ORDER BY chave DESC LIMIT 1500c                 s   s   | ]}|  r|V  qd S r   r   r   r9   r9   r:   r     s      u   Cliente não encontradorS   rj  r  r  r  r  r  )r   r  r>   r   rW   r~   r   r   r   r   ry   rH   r   r   r   r  r(  r)  r*  rk  rl  )r   r   r   rX   re   r   r   r/  r   r   r,  r9   r9   r:   buscar_cliente  sT    
"
.
4r  z/forma-cobrarc                  C   s  t jdd} d }d }z4zt }|jdd}td}|	d| |f |
 }|  |r|d	rt|d	   }td
|iW W S td
diW W S W n tjjk
r } z4td| t  tdt|ddf W Y W fS d }~X Y nT tk
rH } z4td| t  tdt|ddf W Y W S d }~X Y nX W 5 z|r^|  W n. tk
r } ztd| W 5 d }~X Y nX z|r|  W n. tk
r } ztd| W 5 d }~X Y nX X d S )Nrf   r*   r  r  Tr~  re   zXSELECT formadecobrar FROM classificacao WHERE nomeclassificacao = %s AND id_cliente = %sr  r  Znormalrj  r  r  r  r  r  )r   r  r>   r   rW   r~   r   r   r   r   r   r   rH   rB  r   r   r(  r)  r*  rk  rl  )rf   r   r   rX   re   r/  r  r,  r9   r9   r:   forma_cobrar  sF    

.
4r  z/proximo-pedidoc                  C   s  d } d }z2z^tddd t } | jdd}td}|sPtdd	id
fW W S t||}td|iW W S  t	j
jk
r } zZtd| t  | rz|   W n tk
r   Y nX tdt|ddf W Y W fS d }~X Y nT tk
r8 } z4td| t  tdt|ddf W Y W S d }~X Y nX W 5 z|rN|   W n. tk
r~ } ztd| W 5 d }~X Y nX z| r|    W n. tk
r } ztd| W 5 d }~X Y nX X d S )Nr  r  uR   [WARN] /proximo-pedido — não reserva número; alocação em POST /api/casa/itemTrv   r~  re   rV   r  r  numerorj  r  r  r  r  r  r   rW   r~   r   r   r   r>   r   r0  r(  r)  r*  rk  rl  r   rH   r   r   rX   re   r  r,  r9   r9   r:   proximo_pedido  sD    


.
4r  z/numero-pedido-atualc                  C   s  d} d}zzRt } | jdd}td}|sDtddid	fW W S t||}td
|iW W S  t	j
jk
r } z@td| t  | r|   tdt|ddf W Y W fS d}~X Y nT tk
r } z4td| t  tdt|ddf W Y W S d}~X Y nX W 5 z|r(|   W n. tk
rX } ztd| W 5 d}~X Y nX z| rj|    W n. tk
r } ztd| W 5 d}~X Y nX X dS )u?   Retorna o próximo número de pedido SEM incrementar o contadorNr  r  Tr~  re   rV   r  r  r  rj  r  r  r  r  r  r  r  r9   r9   r:   numero_pedido_atual  s<    


.
4r  z/delivery-pendentec                  C   s  d} d}zzZt } | jdd}|dtdf | p>g }dd	 |D }t	dt
||d
W W S  tjjk
r } z4td| t  t	dt|ddf W Y W fS d}~X Y nT tk
r } z4td| t  t	dt|ddf W Y W S d}~X Y nX W 5 z|r$|   W n. tk
rT } ztd| W 5 d}~X Y nX z| rf|    W n. tk
r } ztd| W 5 d}~X Y nX X dS )zFLista todos os registros pendentes de entrega, agrupados por nropedidoNr  r  Tr~  a5  
            SELECT 
                MIN(COALESCE(nrolancamento, chave)) as chave,
                nropedido,
                telefone,
                cep,
                nome,
                endereco,
                nrocasa,
                complemento,
                MAX(entregador) as entregador,
                SUM(CAST(preco AS DECIMAL(10,2)) * CAST(quantidade AS DECIMAL(10,3))) as total_preco,
                COUNT(*) as total_produtos
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = 'DELIVERY'
              AND UPPER(COALESCE(status_pedido, '')) = 'AGUARDE'
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            GROUP BY nropedido, telefone, cep, nome, endereco, nrocasa, complemento
            ORDER BY MIN(chave) DESC
        re   c                 S   s   g | ]}t |qS r9   r  r  r9   r9   r:   r  ^  s     z,listar_delivery_pendente.<locals>.<listcomp>)rU   r  r  rj  r  r  r  r  r  )r   rW   r~   r   r   r   r   r>   r   r   r@   r(  r)  r*  rk  rl  rH   )r   r   rX   r  r,  r9   r9   r:   listar_delivery_pendente<  sB    

.
4r  z/atribuir-entregadorc                  C   s$  d} d}zztjpi }|d}|dd }|sNtddid	fW W NS |sjtdd
id	fW W 2S td}|stddid	fW W S t	 } | 
 }|d|||f |   td| d|  tdd| d| dW W S  tjjk
rB } z4td| t  tdt|ddf W Y W fS d}~X Y nT tk
r } z4td| t  tdt|ddf W Y W S d}~X Y nX W 5 z|r|   W n. tk
r } ztd| W 5 d}~X Y nX z| r|    W n. tk
r } ztd| W 5 d}~X Y nX X dS )z<Atribui um entregador a um pedido na tabela deliverypendenteNr  r  r   r   r*   rV   !   Número do pedido é obrigatórior  u"   Nome do entregador é obrigatóriore   r  z
            UPDATE pedido_diarios
            SET entregador = %s
            WHERE nropedido = %s AND id_cliente = %s AND origem = 'DELIVERY'
            z[ENTREGADOR] u    atribuído ao pedido TzEntregador r  rj  r  r  r  r  r  )r   rW   r~   r   r  r>   r   r   r   r   r   r   r   r(  r)  r*  rk  rl  rH   )r   r   rX   rx  r   r   re   r,  r9   r9   r:   atribuir_entregador|  sV    


	
.
4r!  z/api/diagnostico-comandac               
   C   s   d} d}zzXt } | jdd}|d | }|d | }td||rT|d nddW W TS  tjj	k
r } z,t
d	| td
t|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )z&Verifica a estrutura da tabela comandaNTr~  zDESCRIBE comandaz%SELECT COUNT(*) as total FROM comandar  r   )rU   colunasZtotal_registrosrj  Fr  r  )r   r   r   r   r   r   r   r(  r)  r*  r~   rH   )r   r   r"  r  r,  r9   r9   r:   diagnostico_comanda  s*    


4r#  z/fechar-comandac            
      C   sz  d} d}zz2tjpi }|d}|s@tddidfW W S td}|sftdd	idfW W S t } | j	d
d}|
d||f | }|stddidfW W FS |dd}|r| dkrtddidfW W S |
d||f |j}|
d||f |   td| d| d td
d| d|dW W S  tjjk
r }	 z4td|	 t  tdt|	ddf W Y W fS d}	~	X Y nT tk
r } z4td| t  tdt|ddf W Y W S d}~X Y nX W 5 z|r |   W n. tk
r0 } ztd| W 5 d}~X Y nX z| rB|    W n. tk
rr } ztd| W 5 d}~X Y nX X dS )zDTransfere um pedido de pedido_diarios para comanda (fecha a comanda)Nr  r  r   rV   r   r  re   r  Tr~  a  
            SELECT entregador
            FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem = 'DELIVERY'
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            ORDER BY chave DESC
            LIMIT 1
            r  rS   r   r*   u=   Não é possível fechar a comanda sem atribuir um entregadorae  
            INSERT INTO comanda
            (nropedido, telefone, cep, nome, endereco, nrocasa, complemento,
             codigoproduto, produto, preco, quantidade, classe, entregador, cliente, id_cliente, formapagamento)
            SELECT nropedido, telefone, cep, nome, endereco, nrocasa, complemento,
                   codigoproduto, produto, preco, quantidade, classe, entregador, cliente, id_cliente, formapagamento
            FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem = 'DELIVERY'
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
        
            DELETE FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem = 'DELIVERY'
            z[FECHAR COMANDA] Pedido z transferido para comanda ( registros)zComanda do pedido z fechada com sucessorU   r  registros_transferidosrj  Fr  r  r  )r   rW   r~   r   r  r>   r   r   r   r   r   r   r   r  r   r(  r)  r*  rk  rl  rH   )
r   r   rX   rx  r   re   r/  r   r'  r,  r9   r9   r:   fechar_comanda  sp    





.
4r(  z/cancelar-pedidoc                  C   s  d} d}zvztjpi }|d}|s>tddidfW W FS td}|sdtdd	idfW W  S t } | 	 }|
d
||f |j}|
d||f |   td| d| d tdd| d|dW W S  tjjk
r* } z4td| t  tdt|ddf W Y W fS d}~X Y nT tk
r| } z4td| t  tdt|ddf W Y W S d}~X Y nX W 5 z|r|   W n. tk
r } ztd| W 5 d}~X Y nX z| r|    W n. tk
r } ztd| W 5 d}~X Y nX X dS )z5Transfere um pedido de pedido_diarios para canceladasNr  r  r   rV   r   r  re   r  aL  
            INSERT INTO canceladas
            (nropedido, cliente, telefone, nome, cep, endereco, nrocasa, complemento,
             codigoproduto, produto, preco, quantidade, classe, entregador, id_cliente)
            SELECT nropedido, cliente, telefone, nome, cep, endereco, nrocasa, complemento,
                   codigoproduto, produto, preco, quantidade, classe, entregador, id_cliente
            FROM pedido_diarios
            WHERE nropedido = %s AND id_cliente = %s AND origem = 'DELIVERY'
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            r$  z[CANCELAR PEDIDO] Pedido z transferido para canceladas (r%  TzPedido z cancelado com sucessor&  rj  Fr  r  r  )r   rW   r~   r   r  r>   r   r   r   r   r   r  r   r(  r)  r*  rk  rl  rH   )r   r   rX   rx  r   re   r'  r,  r9   r9   r:   cancelar_pedidoC  s\    





.
4r)  z/salvar-clientec                  C   s  d } d }zz4tjpi }tdd  td t| td  td td|d  td	t|d  td
|d  tdt|d  td d |d}|stddidfW W ,S t } | j	dd}t
d}t|dpd  }|dk}|d||f | }|d|f | }	d}
|	r|	dp\d  }|dk}
td| d|
  d }d }|r|rt|dpd}t|dpd}nd}d}td| d |  n|
rX|dd}zt|}W n tk
r   d}Y nX t|\}}}|dkr4|n|}t||}td!| d |  nHt|ddpjd}t|ddpd}d }d }td"| d |  |d# | d k	}|d$ | d k	}|d% | d k	}|r|rf|rfd&}|d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d|||||d/d||f}nJ|r|sd0}|d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d||||||f}n|rP|sPd1}|d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d|||d/d||f}n`d2}|d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d||||f}||| |r|d3pd pd }|d4|||f |   tdd5|d6 ||d7W W S |r|rd8}||d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d|||||d/d|f}nJ|r|sd9}||d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d|||||f}n|r~|s~d:}||d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d|||d/d|f}n`d;}||d'd|d(d|d)d|d*d|d+d|d,d|d-d|d.d|||f}||| |r|d3pd pd }|d4|||f |   tdd<|j||d7W W S W n tjjk
r } zBtd=| t  | rz|   td>t|d?d@f W Y W fS d }~X Y nT tk
r } z4tdA| t  tdBt|d?d@f W Y W S d }~X Y nX W 5 z|r|   W n. tk
r@ } ztd| W 5 d }~X Y nX z| rR|    W n. tk
r } ztd| W 5 d }~X Y nX X d S )CNr  r  ro   rp   z'[SALVAR CLIENTE] REQUEST JSON COMPLETO:z![SALVAR CLIENTE] Dados recebidos:u     - Taxa do formulário (raw): Ztaxaentregau      - Taxa do formulário (type): u%     - Distância do formulário (raw): r  u&     - Distância do formulário (type): r   rV   r`  r  Tr~  re   origem_cadastror*   r  zZSELECT chave, taxaentrega, distancia FROM clientes WHERE telefone = %s AND id_cliente = %szMSELECT calculodistancia FROM configuracao WHERE chave = 1 AND id_cliente = %sr  r  rA  u2   [SALVAR CLIENTE] Configuração: calculodistancia=z, habilitado=r   u%   [SALVAR CLIENTE] Modo BALCÃO - Taxa=z, Dist=z'[SALVAR CLIENTE] Modo CALCULADO - Taxa=z$[SALVAR CLIENTE] Modo MANUAL - Taxa=z-SHOW COLUMNS FROM clientes LIKE 'lat_cliente'z%SHOW COLUMNS FROM clientes LIKE 'cep'rc  aa  UPDATE clientes SET 
                         nome = %s, endereco = %s, nrocasa = %s, complemento = %s,
                         referencia = %s, bairro = %s, cidade = %s, estado = %s,
                         taxaentrega = %s, distancia = %s, lat_cliente = %s, lon_cliente = %s, cep = %s
                         WHERE telefone = %s AND id_cliente = %srf   r   r   r   rL  r  r  r  r   aW  UPDATE clientes SET 
                         nome = %s, endereco = %s, nrocasa = %s, complemento = %s,
                         referencia = %s, bairro = %s, cidade = %s, estado = %s,
                         taxaentrega = %s, distancia = %s, lat_cliente = %s, lon_cliente = %s
                         WHERE telefone = %s AND id_cliente = %sa=  UPDATE clientes SET 
                         nome = %s, endereco = %s, nrocasa = %s, complemento = %s,
                         referencia = %s, bairro = %s, cidade = %s, estado = %s,
                         taxaentrega = %s, distancia = %s, cep = %s
                         WHERE telefone = %s AND id_cliente = %sa3  UPDATE clientes SET 
                         nome = %s, endereco = %s, nrocasa = %s, complemento = %s,
                         referencia = %s, bairro = %s, cidade = %s, estado = %s,
                         taxaentrega = %s, distancia = %s
                         WHERE telefone = %s AND id_cliente = %sZcpf_cnpjzIUPDATE clientes SET cpf_cnpj = %s WHERE telefone = %s AND id_cliente = %szCliente atualizado com sucessor   )rU   r  r   Zdistancia_calculadaZtaxa_calculadaa>  INSERT INTO clientes 
                         (telefone, nome, endereco, nrocasa, complemento, referencia, 
                          bairro, cidade, estado, taxaentrega, distancia, lat_cliente, lon_cliente, cep, id_cliente)
                         VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)a5  INSERT INTO clientes 
                         (telefone, nome, endereco, nrocasa, complemento, referencia, 
                          bairro, cidade, estado, taxaentrega, distancia, lat_cliente, lon_cliente, id_cliente)
                         VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)a  INSERT INTO clientes 
                         (telefone, nome, endereco, nrocasa, complemento, referencia, 
                          bairro, cidade, estado, taxaentrega, distancia, cep, id_cliente)
                         VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)a  INSERT INTO clientes 
                         (telefone, nome, endereco, nrocasa, complemento, referencia, 
                          bairro, cidade, estado, taxaentrega, distancia, id_cliente)
                         VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)zCliente cadastrado com sucessorj  r  r  r  r  r  )r   rW   r~   r   r  r>   r  r   r   r   r   rH   r   rB  r   r   r   r  r  r   r  r(  r)  r*  rk  rl  r   )r   r   rX   rx  r   re   r*  Zcadastro_balcaoZcliente_existenter  Zcalculo_habilitadoZcalculo_distr  r  Zdistancia_finalZtaxa_entregaZdistancia_brutaZdistancia_calcZtem_lat_lonZtem_cepZtem_cpf_cnpjr  r  Zcpf_valr,  r9   r9   r:   salvar_cliente  s   










































 

































 
.
4r+  z/api/comandasc               
   C   s
  d} d}zzJt } | jdd}td}|d|f | p@g }td|dW W S  tj	j
k
r } z(td| tdd	d
df W Y W XS d}~X Y nF tk
r } z(td| tddd
df W Y W S d}~X Y nX W 5 | r|   | r|    X dS )z4Retorna todos os registros da tabela comanda em JSONNTr~  re   z+SELECT * FROM comanda WHERE id_cliente = %srU   r  rj  Fr  r  r  r  r  r   r   r   r   r>   r   r   r   r(  r)  r*  r~   rW   r   r   re   r  r,  rX   r9   r9   r:   api_comandas   s,    

*
0r/  z/api/canceladasc               
   C   s
  d} d}zzJt } | jdd}td}|d|f | p@g }td|dW W S  tj	j
k
r } z(td| tdd	d
df W Y W XS d}~X Y nF tk
r } z(td| tddd
df W Y W S d}~X Y nX W 5 | r|   | r|    X dS )z7Retorna todos os registros da tabela canceladas em JSONNTr~  re   z.SELECT * FROM canceladas WHERE id_cliente = %sr,  rj  Fr  r  r  r  r  r-  r.  r9   r9   r:   api_canceladas   s,    

*
0r0  z /criar-coluna-cliente-canceladasc               
   C   s  d} d}zfzt } |  }|d | dkrD|d td |d | dkrl|d td |d | dkr|d	 td
 |d | dkr|d td tdddW W S  tjj	k
r  } z.td| tddt
|ddf W Y W `S d}~X Y nN tk
rl } z.td| tddt
|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )u^   Adiciona as colunas cliente nas tabelas canceladas, comanda e deliverypendente se não existirNz+SHOW COLUMNS FROM canceladas LIKE 'cliente'z;ALTER TABLE canceladas ADD COLUMN cliente VARCHAR(255) NULLu7   [INFO] Coluna 'cliente' adicionada à tabela canceladasz(SHOW COLUMNS FROM comanda LIKE 'cliente'z8ALTER TABLE comanda ADD COLUMN cliente VARCHAR(255) NULLu4   [INFO] Coluna 'cliente' adicionada à tabela comandaz1SHOW COLUMNS FROM deliverypendente LIKE 'cliente'zAALTER TABLE deliverypendente ADD COLUMN cliente VARCHAR(255) NULLu=   [INFO] Coluna 'cliente' adicionada à tabela deliverypendentez,SHOW COLUMNS FROM canceladas LIKE 'telefone'zKALTER TABLE canceladas ADD COLUMN telefone VARCHAR(20) NULL AFTER nropedidou8   [INFO] Coluna 'telefone' adicionada à tabela canceladasTzColunas adicionadas com sucessor  rj  Fr  )rU   rV   r  r  r  zErro interno)r   r   r   r   r   r~   r   r(  r)  r*  rH   rW   )r   r   r,  rX   r9   r9   r:   criar_coluna_cliente_canceladas !  s@    








0
6r1  z/pedidos/<path:filename>c                 C   s   ddl m} |d| S )z$Serve PDFs gerados da pasta pedidos.r   )send_from_directoryr  )r(  r2  )filenamer2  r9   r9   r:   
servir_pdf3!  s    r4  z/criar-tabela-usuariosc               
   C   s   d} d}zz`t } |  }|d |d | d dkrH|d |   td tddd	W W TS  tj	j
k
r } z,td
| tdt|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )u%   Cria a tabela de usuários para loginNa#  
            CREATE TABLE IF NOT EXISTS usuarios (
                chave INT AUTO_INCREMENT PRIMARY KEY,
                usuario VARCHAR(100) NOT NULL UNIQUE,
                senha VARCHAR(255) NOT NULL,
                data_criacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        z5SELECT COUNT(*) FROM usuarios WHERE usuario = 'admin'r   z?INSERT INTO usuarios (usuario, senha) VALUES ('admin', 'admin')z+[INFO] Tabela 'usuarios' criada com sucessoTu&   Tabela de usuários criada com sucessor  rj  Fr  r  )r   r   r   r   r   r   r~   r   r(  r)  r*  rH   )r   r   r,  r9   r9   r:   criar_tabela_usuarios9!  s&    




4r5  z/atualizar-cliente-comandac               
   C   s   d} d}zzPt } |  }|d |j}|   td| d td| ddW W TS  tj	j
k
r } z,td| td	t|d
df W Y W S d}~X Y nX W 5 |r|   | r|    X dS )z;Atualiza o campo cliente na tabela comanda copiando de nomeNzGUPDATE comanda SET cliente = nome WHERE cliente IS NULL OR cliente = ''z[INFO] z( registros atualizados na tabela comandaTz" registros atualizados com sucessor  rj  Fr  r  )r   r   r   r   r  r   r~   r   r(  r)  r*  rH   )r   r   Zregistros_atualizadosr,  r9   r9   r:   atualizar_cliente_comanda`!  s(    

4r6  z/verificar-estrutura-produtosc               
   C   s   d} d}zz8t } | jdd}|d | }td|dW W TS  tjjk
r } z,t	d| tdt
|dd	f W Y W S d}~X Y nX W 5 |r|   | r|    X dS )
z&Retorna a estrutura da tabela produtosNTr~  zDESCRIBE produtos)rU   r"  rj  Fr  r  )r   r   r   r   r   r   r(  r)  r*  r~   rH   )r   r   r"  r,  r9   r9   r:   verificar_estrutura_produtos!  s    

4r7  z/api/fechamento/previewc               
   C   s  zxt d} | s$tddddfW S tjddp2i }t|dpBd	 }t|d
pXd	 }tt| ||}t|W S  t	k
r } ztdt|ddf W Y S d}~X Y nT t
k
r } z4td|dd t  tdt|ddf W Y S d}~X Y nX dS )zFResumo de linhas RECEBIDO/ITEM_REMOVIDO no intervalo (pedido_diarios).re   F.   Sessão inválida: id_cliente não encontrado.r  r|  Tr  data_inicior*   data_fimr  Nz[FECHAMENTO PREVIEW]rv   r  )r   r>   r   r   r  rH   r   r&   r   r   rW   r~   rk  rl  re   r   ZdiZdfr   verX   r9   r9   r:   api_fechamento_preview!  s    

*r=  z!/api/fechamento/resumo-financeiroc               
   C   s  zxt d} | s$tddddfW S tjddp2i }t|dpBd	 }t|d
pXd	 }tt| ||}t|W S  t	k
r } ztdt|ddf W Y S d}~X Y nT t
k
r } z4td|dd t  tdt|ddf W Y S d}~X Y nX dS )uL   Totais por status e forma de pagamento no período (RECEBIDO/ITEM_REMOVIDO).re   Fr8  r  r|  Tr  r9  r*   r:  r  Nz[FECHAMENTO RESUMO FINANCEIRO]rv   r  )r   r>   r   r   r  rH   r   r(   r   r   rW   r~   rk  rl  r;  r9   r9   r:    api_fechamento_resumo_financeiro!  s    

*r>  z#/api/fechamento/relatorio-gerencialc               
   C   s  zxt d} | s$tddddfW S tjddp2i }t|dpBd	 }t|d
pXd	 }tt| ||}t|W S  t	k
r } ztdt|ddf W Y S d}~X Y nT t
k
r } z4td|dd t  tdt|ddf W Y S d}~X Y nX dS )uk   Prestação de contas: canais, pagamentos (JSON baixa), cancelamentos, produtos, horários, clientes novos.re   Fr8  r  r|  Tr  r9  r*   r:  r  Nz [FECHAMENTO RELATORIO GERENCIAL]rv   r  )r   r>   r   r   r  rH   r   r'   r   r   rW   r~   rk  rl  r;  r9   r9   r:   "api_fechamento_relatorio_gerencial!  s    

*r?  z/api/fechamento/executarc               
   C   s$  zt d} | s$tddddfW S tjddp2i }t|dpBd	 }t|d
pXd	 }tt| ||}|dst|dfW S t|W S  t	k
r } ztdt|ddf W Y S d}~X Y nT t
k
r } z4td|dd t  tdt|ddf W Y S d}~X Y nX dS )uF   Arquiva em pedido_periodos, remove do diário e grava relatório .txt.re   Fr8  r  r|  Tr  r9  r*   r:  rU   r  Nz[FECHAMENTO EXECUTAR]rv   r  )r   r>   r   r   r  rH   r   r%   r   r   rW   r~   rk  rl  r;  r9   r9   r:   api_fechamento_executar!  s"    


*r@  z /api/verificar-delivery-pendentec               
   C   s   d} d}zzZt } | jdd}td}|d|f | }|rJ|d nd}t|dk|dW W VS  tj	j
k
r } z.td	| td
dt|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )uY   Verifica se existem registros na tabela deliverypendente, contando apenas pedidos únicosNTr~  re   4  
            SELECT COUNT(DISTINCT nropedido) as total
            FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = 'DELIVERY'
              AND UPPER(COALESCE(status_pedido, '')) = 'AGUARDE'
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            r  r   rG  r  rj  FrG  r  rV   r  r  r   r   re   r/  r  r,  r9   r9   r:   verificar_delivery_pendente!  s.    

6rE  z/api/limpar-delivery-pendentec               
   C   s   d} d}zzpt } |  }td}|d|f | }|rF|d nd}|d|f |   td|| ddW W TS  t	j
jk
r } z,td	| td
t|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )z3Apaga todos os registros da tabela deliverypendenteNre   rA  r   a  
            DELETE FROM pedido_diarios
            WHERE id_cliente = %s
              AND origem = 'DELIVERY'
              AND UPPER(COALESCE(status_pedido, '')) = 'AGUARDE'
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            Tz" pedido(s) deletado(s) com sucesso)rU   Zregistros_deletadosr  rj  Fr  r  )r   r   r   r   r>   r   r   r   r   r(  r)  r*  r~   rH   )r   r   re   r/  Zpedidos_deletadosr,  r9   r9   r:   limpar_delivery_pendente"  sD    


"rF  z/api/verificar-comandasc               
   C   s   d} d}zzZt } | jdd}td}|d|f | }|rJ|d nd}t|dk|dW W VS  tj	j
k
r } z.td	| td
dt|ddf W Y W S d}~X Y nX W 5 |r|   | r|    X dS )uQ   Verifica se existem registros na tabela comandas, contando apenas pedidos únicosNTr~  re   LSELECT COUNT(DISTINCT nropedido) as total FROM comanda WHERE id_cliente = %sr  r   rB  rj  FrC  r  r  rD  r9   r9   r:   verificar_comandasS"  s(    

6rH  z#/api/transferir-comandas-liquidadasc               
   C   sl  d} d}z>zt } |  }td}|d|f | }|rH|d nd}|dkrp|d|f |d|f td|  |d|f td	|j  | 	  |d
|f | }|r|d nd}td|  t
d||| ddW W VS  tjjk
rD } z,td| t
dt|ddf W Y W S d}~X Y nX W 5 |rX|   | rf|    X dS )zHTransfere registros da tabela comanda para liquidada e reseta o contadorNre   rG  r   a  
                INSERT INTO liquidada 
                (nropedido, telefone, cep, nome, endereco, nrocasa, complemento, 
                 codigoproduto, produto, preco, quantidade, classe, entregador, cliente, data_criacao, id_cliente, formapagamento)
                SELECT nropedido, telefone, cep, nome, endereco, nrocasa, complemento,
                       codigoproduto, produto, preco, quantidade, classe, entregador, cliente, data_criacao, id_cliente, formapagamento
                FROM comanda WHERE id_cliente = %s
            z)DELETE FROM comanda WHERE id_cliente = %sz[RESET CONTADOR] id_cliente=z<UPDATE contadorpedido SET contador = 0 WHERE id_cliente = %sz"[RESET CONTADOR] Linhas afetadas: r.  z[RESET CONTADOR] Valor atual: Tz9 pedido(s) transferido(s) com sucesso e contador resetado)rU   r'  contador_atualr  rj  Fr  r  )r   r   r   r   r>   r   r   r~   r  r   r   r(  r)  r*  rH   )r   r   re   r/  Zpedidos_transferidosrI  Zcontador_valorr,  r9   r9   r:   transferir_comandas_liquidadass"  sP    


"rJ  z/api/formas-pagamentoc               
   C   s   d } d }zzft } | jdd}td}td|  |d|f | pNg }td|  td|dW W PS  t	k
r } z,td| td	t
|d
df W Y W S d }~X Y nX W 5 |r|   | r|    X d S )NTr~  re   u   [DEBUG] id_cliente na sessão: z2SELECT * FROM formapagamento WHERE id_cliente = %sz[DEBUG] Formas encontradas: )rU   formasz[ERRO FORMAS PAGAMENTO]Fr  r  )r   r   r   r   r>   r~   r   r   r   rW   rH   )r   r   re   rK  rX   r9   r9   r:   formas_pagamento_api"  s$    

4rL  z/api/mesa/<int:mesanro>c              
   C   s  zt   td}td|  dt|  d| dd t }|jdd}|s`tdd	d
dfW S d }d }zf|d |	 d k	rd}n|d |	 d k	rd}dD ]&}|d|f |	 d k	r|} qqW n t
k
r   d }d }Y nX z&|d |	 d kr|d W n2 t
k
rD } ztd|dd W 5 d }~X Y nX z&|d |	 d krj|d W n2 t
k
r } ztd|dd W 5 d }~X Y nX | |g}|rd| dnd}	d}
|r|rd| d}
nd}
|r|
rd|
 nd}d |	 d!| d"}td#|  d$| dd g }z||| | pFg }W nt t
k
r } zTtd%|dd t  d&}td'|  d$| dd ||| | pg }W 5 d }~X Y nX t|||d(d)d* |d+| |f |	 pi }t|d,p d-}t|d.pd-}|d-kr&d/n|d-kr4d0nd1}zt|d2pJd-}W n t
k
rj   d-}Y nX |d-krzd3}|  |  td|d4||d5W S  t
k
r } z0td6|dd t  tdd7d
d8f W Y S d }~X Y nX d S )9Nre   z0[DEBUG] /api/mesa/<mesanro> chamado com mesanro=z (type=z) e id_cliente=Trv   r~  Fr{  r  r|  r  rF  r  rG  r  r  r2  r3  z,[MESA] Falha ao garantir coluna status_mesa:r  r  z-[MESA] Falha ao garantir coluna pessoas_mesa:r  r  r  r*   zzp.id_cliente = pedido_diarios.id_cliente AND (p.chave = CAST(pedido_diarios.codigoproduto AS UNSIGNED) OR TRIM(COALESCE(p.z8,'')) = TRIM(COALESCE(pedido_diarios.codigoproduto,'')))zep.id_cliente = pedido_diarios.id_cliente AND p.chave = CAST(pedido_diarios.codigoproduto AS UNSIGNED)r  a9  
            SELECT
                chave AS id,
                nropedido AS mesanro,
                produto,
                preco,
                quantidade,
                codigoproduto,
                classe,
                id_cliente,
                COALESCE(lancamento, nrolancamento) AS lancamento,
                COALESCE(lancamento, nrolancamento) AS nrolancamento,
                obs_item,
                dados_item,
                IFNULL(produto, '') AS descricao_produto,
                COALESCE(imp_preparo,'N') AS imp_preparo,
                z-
            FROM pedido_diarios
            a  
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND UPPER(COALESCE(status_mesa, '')) <> 'RECEBIDO'
              AND id_cliente = %s
            ORDER BY chave ASC
        z#[DEBUG] Query pedido_diarios mesa: z params=z4[MESA] Falha ao executar query com join de produtos:a  
                SELECT
                    chave AS id,
                    nropedido AS mesanro,
                    produto,
                    preco,
                    quantidade,
                    codigoproduto,
                    classe,
                    id_cliente,
                    COALESCE(lancamento, nrolancamento) AS lancamento,
                    COALESCE(lancamento, nrolancamento) AS nrolancamento,
                    obs_item,
                    dados_item,
                    IFNULL(produto, '') AS descricao_produto,
                    COALESCE(imp_preparo,'N') AS imp_preparo,
                    '' AS impressoras_produto
                FROM pedido_diarios
                WHERE origem = 'MESA'
                  AND nropedido = %s
                  AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
                  AND UPPER(COALESCE(status_mesa, '')) <> 'RECEBIDO'
                  AND id_cliente = %s
                ORDER BY chave ASC
            z,[DEBUG] Query fallback pedido_diarios mesa: r   r;  r  a  
            SELECT
              SUM(CASE WHEN UPPER(COALESCE(status_mesa,'')) = 'CONTA' THEN 1 ELSE 0 END) AS conta_count,
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' AND UPPER(COALESCE(status_mesa,'')) <> 'RECEBIDO' THEN 1 ELSE 0 END) AS ativa_count,
              MAX(COALESCE(pessoas_mesa, 0)) AS pessoas_mesa
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
            conta_countr   ativa_countCONTAZATIVAZLIVREr  r   r   )rU   r  Zfontemesa_statusr  z"[ERRO] ao buscar produtos da mesa:z Erro ao buscar produtos da mesa.r  )r:  r   r>   r~   r  r   r   r   r   r   rW   r   r   rk  rl  rX  r   r   )r  re   r   r   r  r  r  rX   Z	params_pdr  r  r  Zquery_pdr  r  Zst_rowrM  rN  rP  r  r9   r9   r:   buscar_mesa"  s    
"




 
 
 
 

rQ  z/api/mesa/<int:mesanro>/pessoasc           	      C   sr  d }d }zDztjddpi }zt|dp0d}W n tk
rN   d}Y nX |dk s`|dkrztddd	d
fW W S td}|stddd	dfW W S t }|	  |j
dd}|d | d kr|d |d | d kr|d |d| |f | pi }t|dp*ddkrV|  tddd	dfW W  S t|dpfd  }|dkr|  tddd	dfW W S |d|| |f |  td|dW W S  tk
rJ } zbz|r|  W n tk
r   Y nX td|dd t  tdt|d	d f W Y W S d }~X Y nX W 5 |r^|   |rl|   X d S )!NTr  pessoasr   r   2   Fu+   Informe um número de pessoas entre 1 e 50.r  r  re   r{  r|  r~  r2  r3  r  r  a[  
            SELECT
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' THEN 1 ELSE 0 END) AS total_itens,
              MAX(UPPER(COALESCE(status_mesa,''))) AS status_mesa
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
            r  Mesa sem itens.rS   r  r*   r  u1   Mesa já está RECEBIDO e não pode ser alterada.r  z
            UPDATE pedido_diarios
            SET pessoas_mesa = %s
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO'
            )rU   r  z[MESA PESSOAS ERRO]rv   r  )r   r   r  r   r>   rW   r   r   r   r  r   r   r   r   rH   r   r   r   r~   rk  rl  )	r  r   r   r   rR  re   r   r  rX   r9   r9   r:   api_mesa_set_pessoasf#  sj    





	
4rU  z/api/mesa/<int:mesanro>/reabrirc                 C   s  d }d }z̐zBtd}|s8tddddfW W S t }|  |jdd}|d | d krr|d	 |d
| |f | pi }t	|dpddkr|
  tddddfW W S t	|dpddkr|
  tddddfW W S |d| |f |jdkr8|
  tddddfW W S |  tddiW W S  tk
r } zbz|rt|
  W n tk
r   Y nX td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r|   |r|   X d S )Nre   Fr{  r  r|  Tr~  r2  r3  a  
            SELECT
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' AND UPPER(COALESCE(status_mesa,'')) <> 'RECEBIDO' THEN 1 ELSE 0 END) AS total_ativos,
              SUM(CASE WHEN UPPER(COALESCE(status_mesa,'')) = 'CONTA' THEN 1 ELSE 0 END) AS conta_count
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
            total_ativosr   rT  rS   rM  u   Mesa não está em CONTA.r  a@  
            UPDATE pedido_diarios
            SET status_mesa = 'ABERTA'
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND UPPER(COALESCE(status_mesa, '')) = 'CONTA'
            u"   Não foi possível reabrir a mesa.r  rU   z[MESA REABRIR ERRO]rv   )r   r   r>   r   r   r  r   r   r   r   r   r  r   rW   r~   rk  rl  rH   )r  r   r   re   r   rX   r9   r9   r:   api_mesa_reabrir#  sZ    


		4rW  z"/api/mesa/<int:mesanro>/transferirc           	      C   s  d }d }zz tjddpi }zt|dp0d}W n tk
rN   d}Y nX |dkrrtddddfW W &S |t| krtdd	ddfW W  S td
}|stddddfW W S t }|	  |j
dd}|d | d kr|d |d| |f | pi }t|dp(ddkrT|  tddddfW W DS |d||f | ppi }t|dpddkr|  tddddfW W S |d|| |f |jdkr|  tddddfW W S |  tdt| t|dW W S  tk
r } zbz|r2|  W n tk
rJ   Y nX td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r|   |r|   X d S )NTr  parar   Fu   Mesa destino inválida.r  r  z*Mesa destino deve ser diferente da origem.re   r{  r|  r~  r2  r3  aL  
            SELECT
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' AND UPPER(COALESCE(status_mesa,'')) <> 'RECEBIDO' THEN 1 ELSE 0 END) AS ativos_origem
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
            Zativos_origemzMesa origem sem itens.rS   aM  
            SELECT
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' AND UPPER(COALESCE(status_mesa,'')) <> 'RECEBIDO' THEN 1 ELSE 0 END) AS ativos_destino
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
            Zativos_destinou   Mesa destino já possui itens.r  a:  
            UPDATE pedido_diarios
            SET nropedido = %s
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO'
              AND UPPER(COALESCE(status_mesa,'')) <> 'RECEBIDO'
            u%   Não foi possível transferir a mesa.r  )rU   derX  z[MESA TRANSFERIR ERRO]rv   )r   r   r  r   r>   rW   r   r   r   r  r   r   r   r   r  r   r~   rk  rl  rH   )	r  r   r   r   Z	mesa_parare   Zrow_oZrow_drX   r9   r9   r:   api_mesa_transferir#  sv    



	4rZ  z/api/mesa/<int:mesanro>/statusc                 C   s  d }d }zzVtjddpi }t|dp.d  }|dkr\tdddd	fW W S td
}|stddddfW W jS t	 }|
  |jdd}|d | d kr|d |d| |f | pi }t|dpddkr|  tddddfW W S |dkr<|  tddddfW W S |d| |f |  tddiW W S  tk
r } zbz|r|  W n tk
r   Y nX td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |r|   |r|   X d S )NTr  r  r*   )rO  r  Fu   Status inválido.r  r  re   r{  r|  r~  r2  r3  aK  
            SELECT
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' AND UPPER(COALESCE(status_mesa,'')) <> 'RECEBIDO' THEN 1 ELSE 0 END) AS total_ativos
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
            rV  r   rT  rS   r  z4Use o recebimento da mesa para marcar como RECEBIDO.r  aC  
            UPDATE pedido_diarios
            SET status_mesa = 'CONTA'
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND UPPER(COALESCE(status_mesa, '')) <> 'RECEBIDO'
            rU   z[MESA STATUS ERRO]rv   r  )r   r   r  rH   r>   r   r   r   r   r   r  r   r   r   r   r   r   rW   r~   rk  rl  )r  r   r   r   r  re   r   rX   r9   r9   r:   api_mesa_set_statusY$  s\    



	4r[  z/api/mesa/<int:mesanro>/receberc                 C   s  d }d }zĐz:tjddpi }t|dtr:|dng }g }d}|D ]}t|tsZqJt|dphd }z"t	t|dpd
d	d
}	W n tk
r   d}	Y nX |rJ|	dkrqJtt	|	d}	||	7 }|||	d qJ|stddddfW W S td}
|
s,tddddfW W S t }|  |jdd}|d | d krh|d |d | d kr|d |d| |
f | pi }t	|dpd}t|dpd}t|dpd}|dkr|  tddddfW W S |dkr<|  tdddd fW W S |dkrh|  tdd!dd fW W jS |d"|
f | pi }zt	|d#pd}W n tk
r   d}Y nX |dk rd}|rtt	|t	|d$  dnd}tt	|t	| d}tt	|d}t|| d}|d%krN|  tdd&|||d'dfW W S ttdt	|t	| d}ttd(pzd }d)d*t| tt	|d|||||tt d+
}tj|dd,}t|d)krt|d dpd }nd-}|d.||| |
f |jdkr0|  tdd/dd0fW W S |  td1diW W S  tk
r } zbz|rl|  W n tk
r   Y nX td2|dd3 t   tdt|dd0f W Y W S d }~X Y nX W 5 |r|   |r|   X d S )4NTr  r  r  r  r*   r  r   r   r  r%  r  Fr  r  r  re   r{  r|  r~  r4  r5  r2  r3  a  
            SELECT
              SUM(COALESCE(preco, 0) * COALESCE(quantidade, 0)) AS subtotal,
              SUM(CASE WHEN UPPER(COALESCE(status_mesa,'')) = 'CONTA' THEN 1 ELSE 0 END) AS conta_count,
              SUM(CASE WHEN UPPER(COALESCE(status_pedido,'')) <> 'ITEM_REMOVIDO' AND UPPER(COALESCE(status_mesa,'')) NOT IN ('CONTA','RECEBIDO') THEN 1 ELSE 0 END) AS outros_ativos
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND UPPER(COALESCE(status_mesa, '')) <> 'RECEBIDO'
            r  rM  outros_ativosrT  rS   z)Mesa precisa estar em CONTA para receber.r  u$   Mesa não está totalmente em CONTA.r  r  r  r  u(   Valores não fecham com o total da mesa.r  rI   r   r  )
r=  r   r   r  r  r  r  r  r  r  r  r  a  
            UPDATE pedido_diarios
            SET status_mesa = 'RECEBIDO',
                baixa_pagamento = %s,
                formapagamento = %s
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND UPPER(COALESCE(status_mesa, '')) = 'CONTA'
            u$   Não foi possível atualizar a mesa.r  rU   z[MESA RECEBER ERRO]rv   )!r   r   r  r  r>   r^   r  rH   r   r   r  rW   r  r   r   r   r   r  r   r   r   r   r   r  r   r  r  r@   r  r   r~   rk  rl  )r  r   r   r   r  r  r  r  r  r  re   r   r  rM  r\  r6  r  r  r  r  r  r  r  r  r  rX   r9   r9   r:   api_mesa_receber$  s    
"










$
 

4r]  z*/api/mesa/<int:mesanro>/item/<int:item_id>c           	   
   C   s>  zt d}td| d|  d| dd |sDtddd	d
fW S t }|jdd}|d | d krv|d |d| |f | r|  |  tddd	dfW S |d|| |f | }|s|  |  tddd	dfW S |dp|d}t	|dpd
 }|d k	rtt|dkrt|dkr\|d| |t|f n|d| |t|f n0|dkr|d|| |f n|d|| |f |  |  |  tddd	W S  tk
r8 } zNdt kr|r|  td| dd t  tdd d	d!f W Y S d }~X Y nX d S )"Nre   z[DEBUG] Removendo item z	 da mesa z para id_cliente=Trv   Fr{  r  r|  r~  r2  r3    
            SELECT 1
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_mesa, '')) IN ('CONTA', 'RECEBIDO')
            LIMIT 1
            -   Mesa está em CONTA e não pode ser alterada.r  a   
            SELECT *
            FROM pedido_diarios
            WHERE chave = %s
              AND nropedido = %s
              AND origem = 'MESA'
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            LIMIT 1
            u5   Item não encontrado ou não pertence a este cliente.rS   r   r   r   r   r   a  
                    DELETE FROM pedido_diarios
                    WHERE origem = 'MESA'
                      AND nropedido = %s
                      AND id_cliente = %s
                      AND COALESCE(nrolancamento, lancamento) = %s
                    a7  
                    UPDATE pedido_diarios
                    SET status_pedido = 'ITEM_REMOVIDO'
                    WHERE origem = 'MESA'
                      AND nropedido = %s
                      AND id_cliente = %s
                      AND COALESCE(nrolancamento, lancamento) = %s
                    z
                    DELETE FROM pedido_diarios
                    WHERE chave = %s
                      AND origem = 'MESA'
                      AND nropedido = %s
                      AND id_cliente = %s
                    a  
                    UPDATE pedido_diarios
                    SET status_pedido = 'ITEM_REMOVIDO'
                    WHERE chave = %s
                      AND origem = 'MESA'
                      AND nropedido = %s
                      AND id_cliente = %s
                    zItem removido com sucesso.r   z [ERRO] ao remover item da mesa: zErro ao remover item da mesa.r  )r   r>   r~   r   r   r   r   r   r   rH   r   r   r   rW   r  r   rk  rl  )	r  r  re   r   r   r  r   Zstatus_itemrX   r9   r9   r:   remover_item_mesa/%  st    


	


r`  c              
   C   sv  d }d }zHztjddpi }|dd }|dd }|dd }|d krv|d krv|d krvtdddd	fW W S td
}t }| }|d |	 d kr|d |d| |f |	 rtddddfW W vS g }	g }
|d k	r6t
|pd}|dkr"tdddd	fW W 4S |	d |
| |d k	r\|	d |
t|  |d k	r|	d |
t|  |
|| |g |dd|	 d|
 |  |jdkrtddddfW W ~S tddiW W lS  tk
rN } zF|r
|  td|dd t  tdt|ddf W Y W S d }~X Y nX W 5 |rb|   |rp|   X d S )NTr  r  r   r   Fr  r  r  re   r2  r3  r^  r_  r  r   r  r  r  r  z3
            UPDATE pedido_diarios
            SET r   z
            WHERE chave = %s
              AND nropedido = %s
              AND origem = 'MESA'
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
               Item não encontrado.rS   rU   z[MESA PATCH ITEM ERRO]rv   r  )r   r   r  r>   r   r   r   r   r   r   r   r   rH   r   r   ry   r   r  rW   r   r~   rk  rl  )r  r  r   r   r   r  r   r   re   r  r  r  rX   r9   r9   r:   alterar_item_mesa%  sp    


	







	4rb  z#/api/mesa/<int:mesanro>/ajuste-itemc                 C   sP  d }d }z"ztjddpi }t|dp.d}|dkrZd}td||ddfW W S td	}|sd
}td||ddfW W S t }|  |j	dd}|
d | d kr|
d |
d| |f | r|  d}td||ddfW W ,S |
d| |f | }|s:|
d| |f | }|sh|  d}td||ddfW W S |d}|d}	|	d krtd}
|
d k	rzt|
}	W n tk
r   d }	Y nX |	d krttdpd }|r|
d||f | pi }|d}	t|dp"d dkr4dnd}|dkrFdnd }d!}d!}t|d"pbd }|
d | d k	}|
d# | d k	}|s|  tdd$d%d&fW W rS |
d'| |f |
d(|| f | pi }t|d)pdd* }d+d,dd-d.d/d0d1d2d3ddd4d	d5g}d6t| |d7||t|d8||||	d||g}|rn|d9d: |d9d; d<d=gt| }|
d>d<| d?| d@t| |  td||dAW W lS  tk
r( } zF|r|  tdB|ddC t  tdt|d%d&f W Y W S d }~X Y nX W 5 |r<|   |rJ|   X d S )DNTr  r  r   r  Fr^  r  re   r{  r|  r~  r2  r3  r^  r_  r  a  
            SELECT cod_classe, cod_usuario, status_pedido
            FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
              AND UPPER(TRIM(COALESCE(codigoproduto, ''))) <> 'AJUSTE_TECNICO'
            ORDER BY chave DESC
            LIMIT 1
            al  
                SELECT cod_classe, cod_usuario, status_pedido
                FROM pedido_diarios
                WHERE origem = 'MESA'
                  AND nropedido = %s
                  AND id_cliente = %s
                  AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
                ORDER BY chave DESC
                LIMIT 1
                zEMesa vazia: lance pelo menos um item antes da taxa extra ou desconto.r   r   r  rI   r*   zISELECT chave FROM usuarios WHERE usuario = %s AND id_cliente = %s LIMIT 1r   r   r   r   r   r  r  r   z2SHOW COLUMNS FROM pedido_diarios LIKE 'lancamento'z,Coluna lancamento ausente em pedido_diarios.r  r  z
            DELETE FROM pedido_diarios
            WHERE origem = 'MESA'
              AND nropedido = %s
              AND id_cliente = %s
              AND UPPER(TRIM(COALESCE(codigoproduto, ''))) = 'AJUSTE_TECNICO'
            z
            SELECT COALESCE(MAX(COALESCE(lancamento, 0)), 0) AS max_lancamento
            FROM pedido_diarios
            WHERE origem = 'MESA' AND id_cliente = %s AND nropedido = %s
            r  r   r   r   r   r   r   r   r   r   r   r   r   r  r   r  r%  r  r   r   r   r   r   r   r  z[MESA AJUSTE ITEM ERRO]rv   )r   r   r  r   r>   r   r   r   r  r   r   r   r   r   rW   rH   r   r   rQ  ry   r@   r   r   r~   rk  rl  )r  r   r   r   r  r  re   r  r   r   r  rI   Zrow_ur  r   r   r   r   Zhas_status_mesa_colZhas_lancamento_colZrow_lancZlancamento_atualr   r   r  rX   r9   r9   r:   api_mesa_ajuste_item%  s
   


	









&

4rc  z./api/mesa/<int:mesanro>/item/<int:item_id>/obsc              
   C   sp  d }d }zBztjddpi }|dp*d }td}t }| }|d |	 d krh|d |d| |f |	 rt
d	d
ddfW W S |d||| |f |  |jdkrt
d	dddfW W zS t
ddiW W hS  tk
rH } zB|r|  td|dd t  t
d	dddf W Y W S d }~X Y nX W 5 |r\|   |rj|   X d S )NTr  r   r*   re   r2  r3  r^  Fr_  r  r  a  
            UPDATE pedido_diarios
            SET obs_item = %s
            WHERE chave = %s
              AND nropedido = %s
              AND origem = 'MESA'
              AND id_cliente = %s
              AND UPPER(COALESCE(status_pedido, '')) <> 'ITEM_REMOVIDO'
            r   ra  rS   rU   z[MESA OBS_ITEM ERRO]rv   u$   Erro ao salvar observação do item.r  )r   r   r  r>   r   r   r   r   r   r   r   r   r  rW   r   r~   rk  rl  )r  r  r   r   r   r   re   rX   r9   r9   r:   atualizar_obs_item_mesa&  sF    


		

0rd  __main__z?
==============================================================rv   z-[LojaOnline] A arrancar a partir desta pasta:rq   z,[LojaOnline] Templates (HTML) carregados de:z<[LojaOnline] Menu principal (/) = templates/painel_menu.htmlz?==============================================================
r  zultimo_arranque_loja.txtrq  rs   rt   zGerado automaticamente ao iniciar app.py nesta pasta.
Se o caminho abaixo NAO for a pasta do Cursor, o servidor nao e o mesmo projeto.

zquando_local=r  r  z

ro   z%[LojaOnline] Diagnostico gravado em: z?[LojaOnline] Nao foi possivel gravar ultimo_arranque_loja.txt: z0.0.0.0i  )hostportdebug)r   )r   )N)N)r   r;  )N)NN)N)NN)N)NN)NN)NN)NN)NN)N(^  r~   rx   rC   rc  Zdotenvr   r(  r   r   r   r   r   r	   r
   r   r   Zmysql.connectorr(  r  rk  r   r  r  rer  r   rf  r  unicodedatar   r   r  urllib.parser   r  r   versionr   Zdatabaser   Zauth_routesr   Z
blueprintsr   Z
decoratorsr   r   r   Zservices.business_moder   Zservices.dados_lojar   Zservices.impressao_layoutr   Zservicesr   r3  r   r5  Zservices.usuarios_lojar   r    r!   r"   Zservices.fechamento_periodor#   r$   r%   r&   r'   r(   ry   rd  re  Z_PYWIN32_SYSisdirrQ  pathseprA   r>   r~  r+   rW   r>  Z!deploy.print_bridge.printer_matchr,   rH  r-   Z_normalize_printer_namer.   rG  ImportErrorZprinter_matchZwin32apirz   Zvalidate_requiredrE   rW  Z
SECRET_KEYZ
secret_keyr0   r1   r2   rL   r3   r6   Zregister_blueprintZcontext_processorrM   Zafter_requestrR   ZerrorhandlerrY   r`   Zrouterd   rm   rn   r   r   r   r   rH   r   r   r   r   r   r   r   r  	frozensetr  r  r   r  r  r
  r  r  r  r   r!  r-  r0  r1  r6  r8  r9  r:  rX  r^  r_  r`  ra  rb  rd  rm  rf  rg  rh  ri  rj  rz  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r$  r  r  r  r,  r.  r7  r?  rI  rJ  rM  rQ  rT  rU  rX  rZ  r]  r_  ra  rb  rm  ry  r{  r  r  r  r  r  r  r  r  Zbefore_requestr  r  r  r  r  r  r  r  r  r  r  r  r  r	  r
  r  r  r  r  r-  r1  r2  r;  rB  rO  rS  rZ  r\  r^  r_  ra  rb  r  rc  rd  re  rf  rl  ro  rp  rs  r{  r|  r}  r  r  r  r  r  r  r  r  r  r  rl   r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r
  r  r  r  r   r  r  r  r  r  r!  r#  r(  r)  r+  r/  r0  r1  r4  r5  r6  r7  r=  r>  r?  r@  rE  rF  rH  rJ  rL  rQ  rU  rW  rZ  r[  r]  r`  rb  rc  rd  Z	root_pathr/   _tplZ_markerr|   Z_mfr}   r  r  rs  _erunZFLASK_DEBUGr9   r9   r9   r:   <module>   s  , 	$






	
/:'];&	K{$38-##9  M  83>!n 
	2	"E@
"N
B]a: rw E	

  8	 >63@|





	
*"
 '7n#,&
:!F&
A


D3[ `4A[_c&[

A
3'
(
2
3
+*)>? cL  .2
&'7? LC[A oJ 97..