X-Git-Url: https://git.llucax.com/software/sercom.git/blobdiff_plain/eba8ae20f2fa25c6717e5d8c4b10046e38aac67b..2cccd648ebe3e070f6f550e2444052c30f1a29fd:/sercom/subcontrollers/misentregas/__init__.py?ds=inline diff --git a/sercom/subcontrollers/misentregas/__init__.py b/sercom/subcontrollers/misentregas/__init__.py index a516c88..3cb127b 100644 --- a/sercom/subcontrollers/misentregas/__init__.py +++ b/sercom/subcontrollers/misentregas/__init__.py @@ -2,7 +2,7 @@ #{{{ Imports import cherrypy -from turbogears import controllers, expose, redirect +from turbogears import controllers, expose, redirect, url from turbogears import validate, flash, error_handler from turbogears import validators as V from turbogears import widgets as W @@ -10,8 +10,10 @@ from turbogears import identity from turbogears import paginate from docutils.core import publish_parts from sercom.subcontrollers import validate as val -from sercom.model import Entrega, Correccion, Curso, Ejercicio, InstanciaDeEntrega +from sercom.model import ComandoEjecutado, ComandoPruebaEjecutado, Entrega, Correccion, Curso, Ejercicio, InstanciaDeEntrega, Grupo, Miembro, AlumnoInscripto from sqlobject import * +from zipfile import ZipFile, BadZipfile +from cStringIO import StringIO #}}} @@ -34,7 +36,9 @@ def validate_new(data): def get_ejercicios_activos(): # TODO : Mostrar solo los ejercicios con instancias de entrega activos - return [(0, _(u'--'))] + [(fk.id, fk.shortrepr()) for fk in Ejercicio.select()] + return [(0, _(u'--'))] + [(a.id, a.shortrepr()) for a in (Ejercicio.select( + AND(Ejercicio.q.id==InstanciaDeEntrega.q.ejercicioID, InstanciaDeEntrega.q.inicio <= DateTimeCol.now(), + InstanciaDeEntrega.q.fin >= DateTimeCol.now())))] ajax = """ function clearInstancias () @@ -94,6 +98,7 @@ class EntregaForm(W.TableForm): javascript = [W.JSSource("MochiKit.DOM.focusOnLoad('form_ejercicio');"), W.JSSource(ajax)] form = EntregaForm() + #}}} #{{{ Controlador @@ -101,6 +106,8 @@ class MisEntregasController(controllers.Controller, identity.SecureResource): """Basic model admin interface""" require = identity.has_permission('entregar') + hide_to_admin = 1 + @expose() def default(self, tg_errors=None): """handle non exist urls""" @@ -110,42 +117,118 @@ class MisEntregasController(controllers.Controller, identity.SecureResource): def index(self): raise redirect('list') - @expose(template='kid:%s.templates.new' % __name__) - def new(self, **kw): - """Create new records in model""" - return dict(name=name, namepl=namepl, form=form, values=kw) - @expose(template='kid:%s.templates.list' % __name__) @paginate('records') def list(self): """List records in model""" - r = cls.select(cls.q.entregadorID == identity.current.user.id) + # Un admin no tiene sentido en este area y por las dudas + # lo mando al home. + if 'admin' in identity.current.permissions: + raise redirect(url("/dashboard")) + + # Grupos en los que el usuario formo parte + m = [i.grupo.id for i in Grupo.selectByAlumno(identity.current.user)] + try: + entregador = AlumnoInscripto.selectByAlumno(identity.current.user) + m.append(entregador.id) + except: + pass + r = cls.select(IN(cls.q.entregadorID, m)) return dict(records=r, name=name, namepl=namepl) - @expose(template='kid:%s.templates.show' % __name__) - def show(self,id, **kw): - """Show record in model""" - r = validate_get(id) - if r.observaciones is None: - r.obs = '' - else: - r.obs = publish_parts(r.observaciones, writer_name='html')['html_body'] - return dict(name=name, namepl=namepl, record=r) + @expose(template='kid:%s.templates.new' % __name__) + def new(self, **kw): + """Create new records in model""" + return dict(name=name, namepl=namepl, form=form, values=kw) @validate(form=form) @error_handler(new) @expose() def create(self, archivo, ejercicio, **kw): """Save or create record to model""" - kw['archivos'] = archivo.file.read() - kw['entregador'] = identity.current.user + archivo = archivo.file.read() + try: + zfile = ZipFile(StringIO(archivo), 'r') + except BadZipfile: + flash(_(u'El archivo ZIP no es válido')) + raise redirect('list') + if zfile.testzip() is not None: + flash(_(u'El archivo ZIP tiene errores de CRC')) + raise redirect('list') + + # por defecto el entregador es el user loggeado + entregador = AlumnoInscripto.selectByAlumno(identity.current.user) + + ejercicio = Ejercicio.get(int(ejercicio)) + if ejercicio.grupal: + # Como es grupal, tengo que hacer que la entrega la haga + # mi grupo y no yo personalmente. Busco el grupo + # activo. + + # Con esto obtengo todos los grupos a los que pertenece el Alumno + # y que estan activos + try: + # TODO : Falta filtrar por curso!! + m = Miembro.select( + AND( + Miembro.q.alumnoID == AlumnoInscripto.q.id, + AlumnoInscripto.q.alumnoID == identity.current.user.id, + Miembro.q.baja == None + ) + ).getOne() + except: + flash(_(u'No puedes realizar la entrega ya que el ejercicio es Grupal y no perteneces a ningún grupo.')) + raise redirect('list') + + entregador = m.grupo + kw['archivos'] = archivo + kw['entregador'] = entregador validate_new(kw) flash(_(u'Se creó una nueva %s.') % name) raise redirect('list') - @expose("json") + @expose(template='kid:%s.templates.corrida' % __name__) + def corrida(self, entregaid): + e = validate_get(entregaid) + return dict(entrega=e) + + @expose() + def get_archivo(self, entregaid): + from cherrypy import request, response + r = validate_get(entregaid) + response.headers["Content-Type"] = "application/zip" + response.headers["Content-disposition"] = "attachment;filename=Ej_%s-Entrega_%s-%s.zip" % (r.instancia.ejercicio.numero, r.instancia.numero, r.entregador.nombre) + return r.archivos + + @expose() + def file(self, id): + from cherrypy import request, response + r = ComandoEjecutado.get(id) + response.headers["Content-Type"] = "application/zip" + response.headers["Content-disposition"] = "attachment;filename=comando_ejecutado_%d.zip" % (r.id) + return r.archivos + + @expose() + def diff(self, id): + from cherrypy import request, response + r = ComandoEjecutado.get(id) + response.headers["Content-Type"] = "application/zip" + response.headers["Content-disposition"] = "attachment;filename=diferencias_%d.zip" % (r.id) + return r.diferencias + + @expose(template='kid:%s.templates.diff' % __name__) + def verdiff(self, id): + r = ComandoEjecutado.get(id) + zip = ZipFile(StringIO(r.diferencias), 'r') + return dict(zip=zip) + + @expose('json') def instancias(self, ejercicio_id): - c = Ejercicio.get(ejercicio_id) - return dict(instancias=c.instancias) + instancias = InstanciaDeEntrega.select(AND( + InstanciaDeEntrega.q.ejercicioID == ejercicio_id, + InstanciaDeEntrega.q.activo == True, + InstanciaDeEntrega.q.inicio <= DateTimeCol.now(), + InstanciaDeEntrega.q.fin >= DateTimeCol.now())) + return dict(instancias=instancias) #}}}