-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
412 lines (348 loc) · 21.8 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import sqlite3
import tk as tk
def salirDelPrograma(): # funcion para salir del programa
valor = messagebox.askquestion("Salir", "¿Realmente quiere salir del programa?")
if valor == "yes":
root.destroy() # cierra el programa
class Producto():
db="database/productos.db"
def __init__(self, root):
self.ventana= root
self.ventana.title("App Gestor de Productos")
self.ventana.resizable(1,1)#redimencionable
self.ventana.wm_iconbitmap("recursos/logocuart.ico")
# creacion del contenedor Frame principal
frame = LabelFrame(self.ventana,
text="Registrar un nuevo Producto") # hay que pasarle donde queremos que se ejecute
# posicionar frame, columnspan=cantidad de columnas,pady=margen
frame.grid(row=0, column=0, columnspan=3, pady=20)
# Label Nombre
self.etiqueta_nombre= Label(frame, text="Nombre: ")
#posicionar
self.etiqueta_nombre.grid(row=1,column=0)
#entry nombre
self.nombre= Entry(frame)
self.nombre.focus()
#posicion
self.nombre.grid(row=1, column=1)
# Label Precio
self.etiqueta_precio = Label(frame, text="Precio: ")
# posicionar
self.etiqueta_precio.grid(row=2, column=0)
# entry precio
self.precio = Entry(frame)
# posicion
self.precio.grid(row=2, column=1)
# Label Categoria
self.etiqueta_categoria = Label(frame, text="Categoria: ")
# posicionar
self.etiqueta_categoria.grid(row=3, column=0)
# entry categoria
self.categoria = Entry(frame)
# posicion
self.categoria.grid(row=3, column=1)
# Label stock
self.etiqueta_stock = Label(frame, text='Stock: ')
self.etiqueta_stock.grid(row=2, column=2)
# Entry stock
self.stock = Entry(frame)
self.stock.grid(row=2, column=3)
#Boton de añadir producto #en command el metodo add sin parentesis!!
self.boton_aniadir= ttk.Button(frame,text = "Guardar Producto", command= self.add_producto)
self.boton_aniadir.grid(row=4, columnspan= 2, sticky= W + E)
# Mensaje informativo para el usuario
self.mensaje = Label(text='', fg='green')
self.mensaje.grid(row=3, column=0, columnspan=2, sticky=W + E)
#Tabla Productos
style = ttk.Style()
# Se modifica la fuente de la tabla
style.configure("mystyle.Treeview", highlightthickness=0, bd=0, font=('Calibri',11))
# Se modifica la fuente de las cabeceras
style.configure("mystyle.Treeview.Heading", font=('Calibri', 13, 'bold'))
# Eliminamos los bordes
style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky':'nswe'})])
# TABLA DE PRODCUTOS (Treeview)
# Estilo propio
s = ttk.Style()
s.configure('my.Treeview', highlightthickness=0, bd=0, font=('Calibri', 11)) # fuente de la tabla
s.configure('my.Treeview.Heading', font=('Calibri', 13, 'bold')) # fuente de las cabeceras
s.layout('my.Treeview', [('my.Treeview.treearea', {'sticky': 'nswe'})]) # eliminase los bordes
# Estrutura de la tabla
self.tabla = ttk.Treeview(height=20, columns=('#0', '#1', '#2'), style='my.Treeview')
self.tabla.grid(row=5, column=0, columnspan=4)
self.tabla.heading('#0', text='NOMBRE ⚀', anchor='center')
self.tabla.heading('#1', text='PRECIO ⚁', anchor='center')
self.tabla.heading('#2', text='CATEG ⚂', anchor='center')
self.tabla.heading('#3', text='CANT ⚃', anchor='center')
self.tabla.column('#1', anchor='center')
self.tabla.column('#3', anchor='center')
#Boton de Eliminar y Editar
s=ttk.Style()
s.configure("my.TButton", font=("calibri", 14, "bold"))
boton_eliminar=ttk.Button(text= "ELIMINAR", style="my.TButton",command= self.del_producto)
boton_eliminar.grid(row=6, column=0, sticky=W+E)
boton_editar=ttk.Button(text="EDITAR", style="my.TButton",command=self.edit_producto)
boton_editar.grid(row=6, column=1, sticky=W + E)
#Barra de despazamiento
barra = Scrollbar(self.ventana, orient='vertical', command=self.tabla.yview)
barra.grid(column=4, row=5, sticky='ns')
self.tabla.configure(yscrollcommand=barra.set)
#actualizamos tabla
self.get_productos()
def db_consulta(self, consulta, parametros=()):#recibe consulta
with sqlite3.connect(self.db) as con: #establecer connexion con la base de datos
cursor=con.cursor()
resultado=cursor.execute(consulta,parametros)#obenemos resultado
con.commit()
return resultado #devuelve
def get_productos(self):
registros_tabla= self.tabla.get_children()
for fila in registros_tabla:#primero la elimino
self.tabla.delete(fila)
query= "SELECT * FROM producto ORDER BY nombre DESC"
registros_db= self.db_consulta(query)
for fila in registros_db: #luego la creo nuevamente
print(fila)
self.tabla.insert("", 0, text= fila[1], values=(fila[2],fila[3],fila[4]))
def validacion_nombre(self):
nombre_introducido_por_usuario = self.nombre.get()
return len(nombre_introducido_por_usuario) != 0
def validacion_precio(self):
precio_introducido_por_usuario = self.precio.get()
return len(precio_introducido_por_usuario) != 0
def validacion_categoria(self):
categoria_introducido_por_usuario = self.categoria.get()
return len(categoria_introducido_por_usuario) != 0
def validacion_stock(self):
stock_introducido_por_usuario = self.stock.get()
return len(stock_introducido_por_usuario) != 0
def add_producto(self):
if self.validacion_nombre() and self.validacion_precio() and self.validacion_categoria() and self.validacion_stock():
query= "INSERT INTO producto VALUES(NULL,?,?,?,?)"
parametros=(self.nombre.get(),self.precio.get(),self.categoria.get(),self.stock.get())#tiene que ser una tupla
self.db_consulta(query,parametros)
self.mensaje['text'] = 'Producto {} añadido con éxito'.format(self.nombre.get())
self.nombre.delete(0, END) # Borrar el campo nombre del formulario
self.precio.delete(0, END) # Borrar el campo precio del formulario
self.categoria.delete(0, END) # Borrar el campo categoria del formulario
self.stock.delete(0, END) # Borrar el campo stock del formulario
elif (not self.validacion_nombre() or not self.validacion_precio() or not self.validacion_categoria()
or not self.validacion_stock() ):
self.mensaje['text'] = ('TODOS LOS CAMPOS SON OBLIGATORIOS')
self.get_productos()#volvemos a actualizar la lista
def del_producto(self):
self.mensaje['text'] = '' # Mensaje inicialmente vacio
# Comprobacion de que se seleccione un producto para poder eliminarlo
try:
self.tabla.item(self.tabla.selection())['text'][0]
except IndexError as e:
self.mensaje['text'] = 'Por favor, seleccione un producto'
return
self.mensaje['text'] = ''
nombre = self.tabla.item(self.tabla.selection())['text']
query = 'DELETE FROM producto WHERE nombre = ?' # Consulta SQL
self.db_consulta(query, (nombre,)) # Ejecutar la consulta
self.mensaje['text'] = 'Producto {} eliminado con éxito'.format(nombre)
self.get_productos() # Actualizar la tabla de productos
def edit_producto(self):
self.mensaje['text'] = '' # Mensaje inicialmente vacio
try:
self.tabla.item(self.tabla.selection())['text'][0]
except IndexError as e:
self.mensaje['text'] = 'Por favor, seleccione un producto'
return
nombre = self.tabla.item(self.tabla.selection())['text']
old_precio = self.tabla.item(self.tabla.selection())['values'][0] # El precio se encuentra dentro de una lista
categoria = self.tabla.item(self.tabla.selection())['values'][
1] # La categoria se encuentra dentro de una lista
stock = self.tabla.item(self.tabla.selection())['values'][2] # El stock se encuentra dentro de una lista
# Ventana nueva(editar producto)
self.ventana_editar = Toplevel() # Crear una ventana por delante de la principal
self.ventana_editar.title = "Editar Producto" # Titulo de la ventana
self.ventana_editar.resizable(1, 1) # Activar la redimension de la ventana. Para desactivarla: (0, 0)
self.ventana_editar.wm_iconbitmap('recursos/logocuart.ico') # Icono de la ventana
titulo = Label(self.ventana_editar, text='Edición de Productos', font=('Calibri', 50, 'bold'))
titulo.grid(column=0, row=0)
# Creacion del contenedor Frame de la ventana de Editar Producto
frame_ep = LabelFrame(self.ventana_editar, text="Editar el siguiente Producto",
font=('Calibri', 16, 'bold')) # frame_ep: Frame Editar Producto
frame_ep.grid(row=1, column=0, columnspan=20, pady=20)
# Label Nombre antiguo
self.etiqueta_nombre_anituguo = Label(frame_ep, text="Nombre antiguo: ",
font=('Calibri', 13)) # Etiqueta de texto ubicada en el frame
self.etiqueta_nombre_anituguo.grid(row=2, column=0) # Posicionamiento a traves de grid
# Entry Nombre antiguo (texto que no se podra modificar)
self.input_nombre_antiguo = Entry(frame_ep, textvariable=StringVar(self.ventana_editar, value=nombre),
state='readonly', font=('Calibri', 13, 'bold'))
self.input_nombre_antiguo.grid(row=2, column=1)
# Label Nombre nuevo
self.etiqueta_nombre_nuevo = Label(frame_ep, text="Nombre nuevo: ", font=('Calibri', 13))
self.etiqueta_nombre_nuevo.grid(row=3, column=0)
# Entry Nombre nuevo (texto que si se podra modificar)
self.input_nombre_nuevo = Entry(frame_ep, font=('Calibri', 13))
self.input_nombre_nuevo.grid(row=3, column=1)
self.input_nombre_nuevo.focus() # Para que el foco del raton vaya a este Entry al inicio
# Label Precio antiguo
self.etiqueta_precio_anituguo = Label(frame_ep, text="Precio antiguo: ",
font=('Calibri', 13)) # Etiqueta de texto ubicada en el frame
self.etiqueta_precio_anituguo.grid(row=4, column=0) # Posicionamiento a traves de grid
# Entry Precio antiguo(texto que no se podra modificar)
self.input_precio_antiguo = Entry(frame_ep, textvariable=StringVar(self.ventana_editar, value=old_precio),
state='readonly', font=('Calibri', 13, 'bold'))
self.input_precio_antiguo.grid(row=4, column=1)
# Label Precio nuevo
self.etiqueta_precio_nuevo = Label(frame_ep, text="Precio nuevo: ", font=('Calibri', 13))
self.etiqueta_precio_nuevo.grid(row=5, column=0)
# Entry Precio nuevo (texto que si se podra modificar)
self.input_precio_nuevo = Entry(frame_ep, font=('Calibri', 13))
self.input_precio_nuevo.grid(row=5, column=1)
# Label Categoria antigua
self.etiqueta_categoria_antiugua = Label(frame_ep, text="Categoria antigua: ",
font=('Calibri', 13)) # Etiqueta de texto ubicada en el frame
self.etiqueta_categoria_antiugua.grid(row=6, column=0) # Posicionamiento a traves de grid
# Entry Categoria antigua(texto que no se podra modificar)
self.input_categoria_antiugua = Entry(frame_ep, textvariable=StringVar(self.ventana_editar, value=categoria),
state='readonly', font=('Calibri', 13, 'bold'))
self.input_categoria_antiugua.grid(row=6, column=1)
# Label Categoria nueva
self.etiqueta_categoria_nueva = Label(frame_ep, text="Categoria nueva: ", font=('Calibri', 13))
self.etiqueta_categoria_nueva.grid(row=7, column=0)
# Entry Categoria nuevo (texto que si se podra modificar)
self.input_categoria_nueva = Entry(frame_ep, font=('Calibri', 13))
self.input_categoria_nueva.grid(row=7, column=1)
# Label Stock antiguo
self.etiqueta_stock_anituguo = Label(frame_ep, text="Stock antiguo: ",
font=('Calibri', 13)) # Etiqueta de texto ubicada en el frame
self.etiqueta_stock_anituguo.grid(row=8, column=0) # Posicionamiento a traves de grid
# Entry Stock antiguo(texto que no se podra modificar)
self.input_stock_anituguo = Entry(frame_ep, textvariable=StringVar(self.ventana_editar, value=stock),
state='readonly', font=('Calibri', 13, 'bold'))
self.input_stock_anituguo.grid(row=8, column=1)
# Label Stock nuevo
self.etiqueta_stock_nuevo = Label(frame_ep, text="Stock nuevo: ", font=('Calibri', 13))
self.etiqueta_stock_nuevo.grid(row=9, column=0)
# Entry Stock nuevo (texto que si se podra modificar)
self.input_stock_nuevo = Entry(frame_ep, font=('Calibri', 13))
self.input_stock_nuevo.grid(row=9, column=1)
# Boton Actualizar Producto
s = ttk.Style()
s.configure('my.TButton', font=('Calibri', 14, 'bold'))
self.boton_actualizar = ttk.Button(frame_ep, text="Actualizar Producto", command=lambda:
self.actualizar_productos(self.input_nombre_nuevo.get(),
self.input_nombre_antiguo.get(),
self.input_precio_nuevo.get(),
self.input_precio_antiguo.get(),
self.input_categoria_nueva.get(),
self.input_categoria_antiugua.get(),
self.input_stock_nuevo.get(),
self.input_stock_anituguo.get()))
self.boton_actualizar.grid(row=10, columnspan=2, sticky=W + E)
def actualizar_productos(self, nuevo_nombre, antiguo_nombre, nuevo_precio, antiguo_precio, nueva_categoria,
antigua_categoria, nuevo_stock, antiguo_stock):
producto_modificado = False
query = 'UPDATE producto SET nombre = ?, precio = ?, categoria = ?, stock = ? WHERE nombre = ? AND precio = ? AND categoria = ? AND stock = ?'
if nuevo_nombre != '' and nuevo_precio != '' and nueva_categoria != '' and nuevo_stock != '': # Si el usuario escribe nuevo nombre,nuevo precio,nueva categoria y nuevo stock se cambian
parametros = (nuevo_nombre, nuevo_precio, nueva_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre == '' and nuevo_precio != '' and nueva_categoria != '' and nuevo_stock != '':
# Si el usuario deja vacio el nuevo nombre, se mantiene el nombre anterior
parametros = (
antiguo_nombre, nuevo_precio, nueva_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre == '' and nuevo_precio == '' and nueva_categoria != '' and nuevo_stock != '':
# Si el usuario deja vacio el nuevo nombre y el precio, se mantiene el nombre y el precio anterior
parametros = (
antiguo_nombre, antiguo_precio, nueva_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre == '' and nuevo_precio == '' and nueva_categoria == '' and nuevo_stock != '':
# Si el usuario deja vacio el nuevo nombre, el precio y la categoria, se mantiene el nombre, el precio y la categoria anteriores
parametros = (
antiguo_nombre, antiguo_precio, antigua_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre == '' and nuevo_precio != '' and nueva_categoria == '' and nuevo_stock != '':
# Si el usuario deja vacio el nuevo nombre y la categoria, se mantiene el nombre y la categoria anterior
parametros = (
antiguo_nombre, nuevo_precio, antigua_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre == '' and nuevo_precio != '' and nueva_categoria == '' and nuevo_stock == '':
# Si el usuario deja vacio el nuevo nombre, la categoria y el stock, se mantiene el nombre y la categoria y el stock anterior
parametros = (
antiguo_nombre, nuevo_precio, antigua_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre == '' and nuevo_precio != '' and nueva_categoria != '' and nuevo_stock == '':
# Si el usuario deja vacio el nuevo nombre y el stock, se mantiene el nombre y el stock anterior
parametros = (
antiguo_nombre, nuevo_precio, nueva_categoria, antiguo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre == '' and nuevo_precio == '' and nueva_categoria != '' and nuevo_stock == '':
# Si el usuario deja vacio el nuevo nombre, el precio y el stock, se mantiene el nombre, el precio y el stock anterior
parametros = (
antiguo_nombre, nuevo_precio, nueva_categoria, antiguo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre != '' and nuevo_precio == '' and nueva_categoria != '' and nuevo_stock != '':
# Si el usuario deja vacio el nuevo precio, se mantiene el precio anterior
parametros = (
nuevo_nombre, antiguo_precio, nueva_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre != '' and nuevo_precio == '' and nueva_categoria == '' and nuevo_stock != '':
# Si el usuario deja vacio el nuevo precio y la categoria, se mantiene el precio y la categoria anterior
parametros = (
nuevo_nombre, antiguo_precio, antigua_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre != '' and nuevo_precio == '' and nueva_categoria == '' and nuevo_stock == '':
# Si el usuario deja vacio el nuevo precio, la categoria y el stock, se mantiene el precio, la categoria y el stock anterior
parametros = (
nuevo_nombre, antiguo_precio, antigua_categoria, antiguo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre != '' and nuevo_precio == '' and nueva_categoria != '' and nuevo_stock == '':
# Si el usuario deja vacio el nuevo precio y el stock, se mantiene el precio y el stock anterior
parametros = (
nuevo_nombre, antiguo_precio, nueva_categoria, antiguo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre != '' and nuevo_precio != '' and nueva_categoria == '' and nuevo_stock != '':
# Si el usuario deja vacio la nueva categoria, se mantiene la categoria anterior
parametros = (
nuevo_nombre, nuevo_precio, antigua_categoria, nuevo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre != '' and nuevo_precio != '' and nueva_categoria == '' and nuevo_stock == '':
# Si el usuario deja vacio la nueva categoria, se mantiene la categoria anterior
parametros = (
nuevo_nombre, nuevo_precio, antigua_categoria, antiguo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
elif nuevo_nombre != '' and nuevo_precio != '' and nueva_categoria != '' and nuevo_stock == '':
# Si el usuario deja vacio el nuevo stock, se mantiene el stock anterior
parametros = (
nuevo_nombre, nuevo_precio, nueva_categoria, antiguo_stock, antiguo_nombre, antiguo_precio,
antigua_categoria, antiguo_stock)
producto_modificado = True
if (producto_modificado):
self.db_consulta(query, parametros) # Ejecutar la consulta
self.ventana_editar.destroy() # Cerrar la ventana de edicion de productos
self.mensaje['text'] = 'El producto {} ha sido actualizado con éxito'.format(
antiguo_nombre) # Mostrar mensaje para el usuario
self.get_productos() # Actualizar la tabla de productos
else:
self.ventana_editar.destroy() # Cerrar la ventana de edicion de productos
self.mensaje['text'] = 'El producto {} NO ha sido actualizado'.format(
antiguo_nombre) # Mostrar mensaje para el usuario
if __name__ == "__main__":
root = Tk() # abrimos ventana grafica
app = Producto(root)#creo objeto primero y le paso la ventana
root.mainloop() #Con esto nuestra ventana queda abierta