Compare commits

...

1 Commits

Author SHA1 Message Date
d7e682c1ec Configuration api print Calzabana 2025-09-21 14:32:58 -05:00
9 changed files with 528 additions and 44 deletions

BIN
Api/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -5,8 +5,9 @@ import sys
import json
from pydantic import BaseModel
from datetime import datetime
from datetime import datetime, timedelta
import tempfile
from PIL import Image
from .qr_generator import QRCodeGenerator
app = FastAPI(
@ -25,11 +26,16 @@ class Info(BaseModel):
def print_bill(data, address, waiter):
d = data
# Crea una instancia de la impresora ficticia
# printer = Network(str(address))
printer = Network(str(address))
# Abrir el cajo solo las impreroras que tiene esa funcion tambien puede ser 1
printer.cashdraw(2)
# printer.open()
printer = Dummy()
# Imprimer logo
# printer = Dummy()
# Imprime el encabezado
printer.set(align='center', bold=False, height=1, width=1)
printer.image("/app/assets/logo.png")
printer.ln()
printer.text(d["shop_name"]+'\n')
printer.text(d["shop_nit"]+'\n')
printer.text(d["shop_address"]+'\n')
@ -37,22 +43,21 @@ def print_bill(data, address, waiter):
printer.textln('===============================================')
text = d['state']
printer.textln(text)
if d['invoice'] and d['invoice']['resolution']:
text = "Resolucion de Facturacion # " + \
str(d['invoice']['resolution']['resolution_number']) \
+ "\nValida desde " + \
d['invoice']['resolution']['valid_date_time_from'] + \
" hasta "+str(d['invoice']['resolution']['valid_date_time_to'])
printer.textln(text)
printer.ln()
text = "Factura #: " + d['invoice']['invoice_number']
printer.textln(text)
#if d['invoice'] and d['invoice']['resolution']:
# text = "Resolucion de Facturacion # " + \
# str(d['invoice']['resolution']['resolution_number']) \
# + "\nValida desde " + \
# d['invoice']['resolution']['valid_date_time_from'] + \
# " hasta "+str(d['invoice']['resolution']['valid_date_time_to'])
# printer.textln(text)
# printer.ln()
# text = "Factura #: " + d['invoice']['invoice_number']
# printer.textln(text)
printer.text("Cliente: " + d["party"]+'\n')
printer.text("CC/NIT: " + d["tax_identifier_code"]+'\n')
printer.text("Direccion: " + d["address"]+'\n')
text = 'MESA: ' + str(d['table'] + "\n")
printer.text(text)
printer.textln('===============================================')
printer.textln('====================================')
printer.ln()
for line in d["lines"]:
if line['type'] != 'title':
@ -67,8 +72,6 @@ def print_bill(data, address, waiter):
printer.textln('================================================')
text = "Descuento Realizado: "+str(d["total_discount"])+"\n"
printer.text(text)
text = "Propina: "+str(d["total_tip"])+"\n"
printer.text(text)
text = "Total (sin impuestos): "+str(d["untaxed_amount"])+"\n"
printer.text(text)
text = "Impuestos (INC): "+str(d["tax_amount"])+"\n"
@ -85,31 +88,29 @@ def print_bill(data, address, waiter):
printer.textln(text)
printer.set(align='center', bold=False, height=1, width=1)
printer.textln('==============================================\n')
if d["fe_cufe"]:
QR = QRCodeGenerator(d["fe_cufe"]).generate_qr()
with tempfile.NamedTemporaryFile(
delete=True, suffix='.png', dir='/tmp') as temp_file:
temp_filename = temp_file.name
QR.save(temp_filename)
printer.image(f"{temp_filename}")
printer.set(align='left', bold=False, height=1, width=1)
text = str("CUFE: " + d['cufe'])
printer.textln(text)
#if d["fe_cufe"]:
# QR = QRCodeGenerator(d["fe_cufe"]).generate_qr()
# with tempfile.NamedTemporaryFile(
# delete=True, suffix='.png', dir='/tmp') as temp_file:
# temp_filename = temp_file.name
# QR.save(temp_filename)
# printer.image(f"{temp_filename}")
# printer.set(align='left', bold=False, height=1, width=1)
# text = str("CUFE: " + d['cufe'])
# printer.textln(text)
printer.set(align='center', bold=False, height=1, width=1)
printer.text("Sigue nuestras redes sociales\n")
printer.text("@bicipizza\n")
printer.text("Recuerde que la propina es voluntaria.\n")
printer.text("Gracias por visitarnos, vuelva pronto.\n")
printer.text("SOFTWARE POTENCIADO POR ONECLUSTER.ORG.\n")
format_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
printer.text("SOFTWARE POTENCIADO POR ONECLUSTER.COM.CO\n")
adjusted_time = datetime.now() - timedelta(hours=5)
format_date_time = adjusted_time.strftime('%Y-%m-%d %H:%M:%S')
printer.text(str(format_date_time)+'\n')
if waiter:
printer.text("Atendido Por: \n")
printer.text(str(waiter)+'\n')
# Corta el papel (solo para impresoras que soportan esta función)
# printer.cut()
# printer.close()
printer.cut()
printer.close()
# Obtiene el contenido del ticket de prueba
ticket_contenido = printer.output
# Imprime el contenido en la consola

238
Api/main2.py Normal file
View File

@ -0,0 +1,238 @@
from fastapi import FastAPI, Response
from escpos.printer import Dummy
from escpos.printer import Network
import sys
import json
from pydantic import BaseModel
from datetime import datetime, timedelta
import tempfile
from .qr_generator import QRCodeGenerator
app = FastAPI(
title="Print Server FastAPI",
description="Server that receive request for printing",
version="0.0.1"
)
class Info(BaseModel):
content: str
ip_printer: str
user_name: str
def print_bill(data, address, waiter):
d = data
# Crea una instancia de la impresora ficticia
printer = Network(str(address))
# Abrir el cajo solo las impreroras que tiene esa funcion tambien puede ser 1
printer.cashdraw(2)
# printer.open()
# printer = Dummy()
# Imprime el encabezado
printer.set(align='center', bold=False, height=1, width=1)
printer.text(d["shop_name"]+'\n')
printer.text(d["shop_nit"]+'\n')
printer.text(d["shop_address"]+'\n')
printer.set(align='left', bold=False, height=1, width=1)
printer.textln('===============================================')
text = d['state']
printer.textln(text)
#if d['invoice'] and d['invoice']['resolution']:
# text = "Resolucion de Facturacion # " + \
# str(d['invoice']['resolution']['resolution_number']) \
# + "\nValida desde " + \
# d['invoice']['resolution']['valid_date_time_from'] + \
# " hasta "+str(d['invoice']['resolution']['valid_date_time_to'])
# printer.textln(text)
# printer.ln()
# text = "Factura #: " + d['invoice']['invoice_number']
# printer.textln(text)
printer.text("Cliente: " + d["party"]+'\n')
printer.text("CC/NIT: " + d["tax_identifier_code"]+'\n')
printer.text("Direccion: " + d["address"]+'\n')
printer.text(text)
printer.textln('===============================================')
printer.ln()
for line in d["lines"]:
if line['type'] != 'title':
text = line['product']
printer.text(text)
printer.ln()
text = str(line['quantity']) + " " + " $" + \
line["unit_price"] + "\n"
printer.text(text)
printer.set(align='right', bold=False, height=1, width=1)
printer.textln('================================================')
text = "Descuento Realizado: "+str(d["total_discount"])+"\n"
printer.text(text)
text = "Total (sin impuestos): "+str(d["untaxed_amount"])+"\n"
printer.text(text)
text = "Impuestos (INC): "+str(d["tax_amount"])+"\n"
printer.text(text)
text = "Total: "+str(d["total"])+"\n"
printer.text(text)
printer.ln()
if 'payments' in d.keys():
printer.textln("Pagos: ")
printer.textln('================================================')
for payment in d['payments']:
text = str(payment["statement"])+" $"+str(payment["amount"])
printer.textln(text)
printer.set(align='center', bold=False, height=1, width=1)
printer.textln('==============================================\n')
#if d["fe_cufe"]:
# QR = QRCodeGenerator(d["fe_cufe"]).generate_qr()
# with tempfile.NamedTemporaryFile(
# delete=True, suffix='.png', dir='/tmp') as temp_file:
# temp_filename = temp_file.name
# QR.save(temp_filename)
# printer.image(f"{temp_filename}")
# printer.set(align='left', bold=False, height=1, width=1)
# text = str("CUFE: " + d['cufe'])
# printer.textln(text)
printer.set(align='center', bold=False, height=1, width=1)
printer.text("Gracias por visitarnos, vuelva pronto.\n")
printer.text("SOFTWARE POTENCIADO POR ONECLUSTER.COM.CO\n")
adjusted_time = datetime.now() - timedelta(hours=5)
format_date_time = adjusted_time.strftime('%Y-%m-%d %H:%M:%S')
printer.text(str(format_date_time)+'\n')
if waiter:
printer.text("Atendido Por: \n")
printer.text(str(waiter)+'\n')
# Corta el papel (solo para impresoras que soportan esta función)
printer.cut()
printer.close()
# Obtiene el contenido del ticket de prueba
ticket_contenido = printer.output
# Imprime el contenido en la consola
sys.stdout.write(ticket_contenido.decode('utf-8', errors='ignore'))
def print_customer_order(data, address, waiter):
d = data
# Crea una instancia de la impresora ficticia
printer = Network(str(address))
printer.open()
# printer = Dummy()
# Imprime el encabezado
printer.set(align='center', bold=False, height=1, width=1)
format_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
printer.text(str(format_date_time)+'\n')
if waiter:
printer.text("Pedido Por: \n")
printer.text(str(waiter)+'\n')
printer.set(
align='center', bold=False, height=2, width=2, custom_size=True
)
printer.text('========================\n')
text = 'MESA: ' + str(d['table'] + "\n")
printer.text(text)
printer.text('========================\n')
printer.set(align='left', bold=False, height=6, width=6)
combination_pizza = False
pizza = 0
for line in d["lines"]:
if line['type'] != 'title':
if combination_pizza and pizza < 2:
printer.set(
align='center',
bold=False,
height=2,
width=2,
custom_size=True)
pizza += 1
elif pizza >= 2:
combination_pizza = False
printer.set(
align='left',
bold=False,
height=2,
width=2, custom_size=True
)
else:
printer.set(
align='left',
bold=False,
height=2,
width=2,
custom_size=True)
text = line['product'] + " " + str(line['quantity']) + "\n"
printer.text(text)
if line['description']:
text = line['description'] + "\n"
printer.text(text)
if pizza == 2:
printer.ln()
pizza = 0
combination_pizza = False
else:
printer.set(
align='left', bold=True, height=2, width=2, custom_size=True
)
printer.text("\nPIZZA COMBINADA\n")
combination_pizza = True
pizza = 0
# if d["deleted_lines"]:
# for line in d["deleted_lines"]:
# text = line['product'] + " " + str(
# line['quantity']) + " " + str(
# line['unit'])
# printer.text(text)
# Corta el papel (solo para impresoras que soportan esta función)
printer.cut()
printer.close()
# Obtiene el contenido del ticket de prueba
# ticket_contenido = printer.output
# Imprime el contenido en la consola
# sys.stdout.write(ticket_contenido.decode('utf-8', errors='replace'))
@app.post("/print_bill")
def print_ticket_bill(info: Info):
info = dict(info)
data = info["content"]
address = info["ip_printer"]
waiter = info["user_name"]
data = json.loads(data.replace("'", "\""))
print_bill(data, address, waiter)
message = "!Impresion Realizada!"
return Response(content=message, status_code=200)
@app.post("/order_kitchen")
def print_ticket_file_kitchen(info: Info):
info = dict(info)
data = info["content"]
address = info["ip_printer"]
waiter = info["user_name"]
data = json.loads(data.replace("'", "\""))
print_customer_order(data, address, waiter)
message = "!Impresion Realizada!"
return Response(content=message, status_code=200)
@app.post("/order_bar")
def print_ticket_file_bar(info: Info):
info = dict(info)
data = info["content"]
address = info["ip_printer"]
waiter = info["user_name"]
data = json.loads(data.replace("'", "\""))
print_customer_order(data, address, waiter)
message = "!Impresion Realizada!"
return Response(content=message, status_code=200)

View File

@ -1,18 +1,23 @@
# Usa una imagen base de Python
FROM python:3.11-slim
# Establece el directorio de trabajo
WORKDIR /app
# Copia el archivo de requerimientos y lo instala
COPY ./requirements.txt /tmp/
RUN pip install --no-cache-dir -r /tmp/requirements.txt
# Instala dependencias para manejo de imágenes
RUN apt-get update && apt-get install -y \
libjpeg-dev \
zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*
# Copia el código fuente
# Crea directorio para assets
RUN mkdir -p /app/assets
# Copia requirements e instala dependencias
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copia el resto del código
COPY . .
# Expone el puerto que usará FastAPI
EXPOSE 8000
# Comando de arranque
CMD ["uvicorn", "Api.main:app", "--host", "0.0.0.0", "--port", "8000"]

0
assets/logo.png Normal file
View File

View File

@ -1,12 +1,17 @@
version: '3.8'
services:
# Servicio de FastAPI
escpos:
build: .
build:
context: .
dockerfile: Dockerfile
container_name: escpos
command: uvicorn Api.main:app --host 0.0.0.0 --port 8000 --reload
restart: always
volumes:
- .:/app
- ./logo.png:/app/assets/logo.png # Monta el logo específicamente
ports:
- "8050:8000"
environment:
- LOGO_PATH=/app/assets/logo.png # Variable de entorno opcional

BIN
logo.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

235
main.py Normal file
View File

@ -0,0 +1,235 @@
from fastapi import FastAPI, Response
from escpos.printer import Dummy
from escpos.printer import Network
import sys
import json
from pydantic import BaseModel
from datetime import datetime
import tempfile
from .qr_generator import QRCodeGenerator
app = FastAPI(
title="Print Server FastAPI",
description="Server that receive request for printing",
version="0.0.1"
)
class Info(BaseModel):
content: str
ip_printer: str
user_name: str
def print_bill(data, address, waiter):
d = data
# Crea una instancia de la impresora ficticia
printer = Network(str(address))
# printer.open()
# printer = Dummy()
# Imprime el encabezado
printer.set(align='center', bold=False, height=1, width=1)
printer.text(d["shop_name"]+'\n')
printer.text(d["shop_nit"]+'\n')
printer.text(d["shop_address"]+'\n')
printer.set(align='left', bold=False, height=1, width=1)
printer.textln('===============================================')
text = d['state']
printer.textln(text)
if d['invoice'] and d['invoice']['resolution']:
text = "Resolucion de Facturacion # " + \
str(d['invoice']['resolution']['resolution_number']) \
+ "\nValida desde " + \
d['invoice']['resolution']['valid_date_time_from'] + \
" hasta "+str(d['invoice']['resolution']['valid_date_time_to'])
printer.textln(text)
printer.ln()
text = "Factura #: " + d['invoice']['invoice_number']
printer.textln(text)
printer.text("Cliente: " + d["party"]+'\n')
printer.text("CC/NIT: " + d["tax_identifier_code"]+'\n')
printer.text("Direccion: " + d["address"]+'\n')
printer.text(text)
printer.textln('===============================================')
printer.ln()
for line in d["lines"]:
if line['type'] != 'title':
text = line['product']
printer.text(text)
printer.ln()
text = str(line['quantity']) + " " + " $" + \
line["unit_price"] + "\n"
printer.text(text)
printer.set(align='right', bold=False, height=1, width=1)
printer.textln('================================================')
text = "Descuento Realizado: "+str(d["total_discount"])+"\n"
printer.text(text)
text = "Total (sin impuestos): "+str(d["untaxed_amount"])+"\n"
printer.text(text)
text = "Impuestos (INC): "+str(d["tax_amount"])+"\n"
printer.text(text)
text = "Total: "+str(d["total"])+"\n"
printer.text(text)
printer.ln()
if 'payments' in d.keys():
printer.textln("Pagos: ")
printer.textln('================================================')
for payment in d['payments']:
text = str(payment["statement"])+" $"+str(payment["amount"])
printer.textln(text)
printer.set(align='center', bold=False, height=1, width=1)
printer.textln('==============================================\n')
#if d["fe_cufe"]:
# QR = QRCodeGenerator(d["fe_cufe"]).generate_qr()
# with tempfile.NamedTemporaryFile(
# delete=True, suffix='.png', dir='/tmp') as temp_file:
# temp_filename = temp_file.name
# QR.save(temp_filename)
# printer.image(f"{temp_filename}")
# printer.set(align='left', bold=False, height=1, width=1)
# text = str("CUFE: " + d['cufe'])
# printer.textln(text)
printer.set(align='center', bold=False, height=1, width=1)
printer.text("Gracias por visitarnos, vuelva pronto.\n")
printer.text("SOFTWARE POTENCIADO POR ONECLUSTER.ORG.\n")
format_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
printer.text(str(format_date_time)+'\n')
if waiter:
printer.text("Atendido Por: \n")
printer.text(str(waiter)+'\n')
# Corta el papel (solo para impresoras que soportan esta función)
printer.cut()
printer.close()
# Obtiene el contenido del ticket de prueba
ticket_contenido = printer.output
# Imprime el contenido en la consola
sys.stdout.write(ticket_contenido.decode('utf-8', errors='ignore'))
def print_customer_order(data, address, waiter):
d = data
# Crea una instancia de la impresora ficticia
printer = Network(str(address))
printer.open()
# printer = Dummy()
# Imprime el encabezado
printer.set(align='center', bold=False, height=1, width=1)
format_date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
printer.text(str(format_date_time)+'\n')
if waiter:
printer.text("Pedido Por: \n")
printer.text(str(waiter)+'\n')
printer.set(
align='center', bold=False, height=2, width=2, custom_size=True
)
printer.text('========================\n')
text = 'MESA: ' + str(d['table'] + "\n")
printer.text(text)
printer.text('========================\n')
printer.set(align='left', bold=False, height=6, width=6)
combination_pizza = False
pizza = 0
for line in d["lines"]:
if line['type'] != 'title':
if combination_pizza and pizza < 2:
printer.set(
align='center',
bold=False,
height=2,
width=2,
custom_size=True)
pizza += 1
elif pizza >= 2:
combination_pizza = False
printer.set(
align='left',
bold=False,
height=2,
width=2, custom_size=True
)
else:
printer.set(
align='left',
bold=False,
height=2,
width=2,
custom_size=True)
text = line['product'] + " " + str(line['quantity']) + "\n"
printer.text(text)
if line['description']:
text = line['description'] + "\n"
printer.text(text)
if pizza == 2:
printer.ln()
pizza = 0
combination_pizza = False
else:
printer.set(
align='left', bold=True, height=2, width=2, custom_size=True
)
printer.text("\nPIZZA COMBINADA\n")
combination_pizza = True
pizza = 0
# if d["deleted_lines"]:
# for line in d["deleted_lines"]:
# text = line['product'] + " " + str(
# line['quantity']) + " " + str(
# line['unit'])
# printer.text(text)
# Corta el papel (solo para impresoras que soportan esta función)
printer.cut()
printer.close()
# Obtiene el contenido del ticket de prueba
# ticket_contenido = printer.output
# Imprime el contenido en la consola
# sys.stdout.write(ticket_contenido.decode('utf-8', errors='replace'))
@app.post("/print_bill")
def print_ticket_bill(info: Info):
info = dict(info)
data = info["content"]
address = info["ip_printer"]
waiter = info["user_name"]
data = json.loads(data.replace("'", "\""))
print_bill(data, address, waiter)
message = "!Impresion Realizada!"
return Response(content=message, status_code=200)
@app.post("/order_kitchen")
def print_ticket_file_kitchen(info: Info):
info = dict(info)
data = info["content"]
address = info["ip_printer"]
waiter = info["user_name"]
data = json.loads(data.replace("'", "\""))
print_customer_order(data, address, waiter)
message = "!Impresion Realizada!"
return Response(content=message, status_code=200)
@app.post("/order_bar")
def print_ticket_file_bar(info: Info):
info = dict(info)
data = info["content"]
address = info["ip_printer"]
waiter = info["user_name"]
data = json.loads(data.replace("'", "\""))
print_customer_order(data, address, waiter)
message = "!Impresion Realizada!"
return Response(content=message, status_code=200)