first commit: sistema de gestión de inventario y asignación de vehículos

This commit is contained in:
Cap. Miguel Arcangel Ollarves Mayorquin 2026-06-02 15:30:30 -04:00
commit 03246274cf
5061 changed files with 2274258 additions and 0 deletions

163
README.md Normal file
View File

@ -0,0 +1,163 @@
## Título
Sistema de Gestión de Artículos y Unidades (ProyectoServing)
## Descripción
Proyecto Django para el registro, asignación y control de artículos por unidades, con comprobantes de movimiento y un módulo de inventario básico.
## Stickers
Usa estas imágenes como "stickers" en la documentación o UI (ya incluidas en el repo):
![sticker-logo](../static/imagenes/logo.png)
![sticker-logo2](../static/imagenes/logo2.png)
![sticker-icon](../static/imagenes/icon.ico)
Si quieres añadir más stickers, añádelos en `static/imagenes/stickers/` y referencia la ruta relativa desde la raíz del proyecto.
## Stack tecnológico
- Python (se recomienda 3.11+; los .pyc en el repo sugieren 3.12/3.13)
- Django 5.0.3
- Base de datos: configurable (MySQL, PostgreSQL o SQLite), dependencias: `mysqlclient`, `psycopg2`, `PyMySQL`
- Bibliotecas notables (ver `sistema/requirements.txt`): `django-adminlte3`, `django-select2`, `Pillow`, `reportlab`, `qrcode`, `django-wkhtmltopdf`
## Modelos de datos (resumen)
Las clases principales están en `serving/models.py`:
- Articulo
- Campos: `articulo`, `description`, `marca`, `modelo`, `serial`, `unidad_medida`, `fecha`, `fecha_registro`, `cantidad`, `precio`
- Métodos: `__str__`, `total()` (cantidad * precio)
- Comprobante
- Campos: `e_o_s`, `conceptos`, `observaciones`, `concepto_movimiento`, `numero_movimiento`, `grupo`, `subgrupo`
- Unidad
- Campos: `nombreUnidad`, `comandante`, `ubicacion`, `telefono`
- Relación: `articulos` ManyToMany con `Articulo` a través de `ArticuloUnidad`
- ArticuloUnidad (tabla intermedia)
- Campos: FK a `Articulo` y `Unidad`, FK a `Comprobante` (nullable), `marca`, `modelo`, `serial`, `movimiento`, `description`, `unidad_medida`, `fecha_salida`, `cantidad`, `precio`
- Métodos: `__str__`, `total()`
- PruebaUnidad (registro de prueba similar a ArticuloUnidad)
Ejemplo de forma de datos (JSON) para un `Articulo`:
{
"articulo": "Proyector X",
"marca": "MarcaA",
"modelo": "MX-100",
"serial": "SN12345",
"unidad_medida": "unidad",
"cantidad": 2,
"precio": "350.00"
}
## Requisitos previos
- Tener Python 3.11+ instalado.
- Git (opcional).
- En Windows PowerShell: crear y activar un entorno virtual.
- Archivo de dependencias: `sistema/requirements.txt` (contiene todas las librerías necesarias).
## Instalación y configuración (Windows PowerShell)
1) Abrir PowerShell en la carpeta raíz del proyecto (`e:/PROYECTOS/ProyectoServing/sistema`).
2) Crear y activar entorno virtual:
```powershell
python -m venv .venv; .\.venv\Scripts\Activate.ps1
```
3) Instalar dependencias:
```powershell
python -m pip install --upgrade pip; pip install -r requirements.txt
```
4) Configurar variables de entorno (recomendado):
- `DJANGO_SECRET_KEY` — clave secreta.
- `DJANGO_DEBUG``False` en producción.
- `DATABASE_URL` o editar `sistema/settings.py` para ajustar `DATABASES`.
Puedes exportar variables en PowerShell así (temporalmente):
```powershell
$env:DJANGO_SECRET_KEY = "tu_secret_key"
$env:DJANGO_DEBUG = "True"
```
5) Migraciones y superusuario:
```powershell
python ..\manage.py migrate; python ..\manage.py createsuperuser
```
6) Ejecutar servidor local:
```powershell
python ..\manage.py runserver
```
## Uso del sistema
- Iniciar sesión en `http://127.0.0.1:8000/` con el superusuario.
- Desde el panel admin o las vistas públicas del app `serving` podrás:
- Crear/editar `Articulo`.
- Registrar `Comprobante` y asignar movimientos.
- Crear `Unidad` y vincular artículos mediante `ArticuloUnidad`.
- Generar reportes o comprobantes (algunas dependencias dan soporte a PDF/QR).
## Módulos del sistema
- `serving/` — app principal con modelos, vistas, formularios y templates.
- `sistema/` — configuración del proyecto Django (`settings.py`, `urls.py`, `wsgi/asgi`).
- `templates/` — plantillas base y por módulo (ver `templates/` y subcarpetas).
- `static/` y `staticfiles/` — assets: CSS, JS y `imagenes/` (logos y stickers).
## Seguridad
- No dejar `DEBUG = True` en producción.
- Guardar `SECRET_KEY` en variables de entorno, no en el repositorio.
- Configurar `ALLOWED_HOSTS` en `sistema/settings.py`.
- Usar conexión segura (HTTPS) y marcar cookies seguras (`SESSION_COOKIE_SECURE`, `CSRF_COOKIE_SECURE`).
- Restringir accesos en el admin y usar contraseñas fuertes.
- Revisar dependencias y mantenerlas actualizadas; ejecutar escáneres de seguridad sobre el entorno.
## Posibles mejoras
- Añadir API REST (Django REST Framework) para integraciones.
- Implementar tests unitarios y de integración automatizados.
- Añadir control de permisos más fino (roles/GRANT) para módulos.
- Mejorar la interfaz con componentes JS modernos o SPA.
- Soporte de importación/exportación (CSV/Excel) robusto.
- Auditoría de cambios (historial de movimientos por artículo).
## Mapa rápido de archivos relevantes
- `serving/models.py` — modelos del dominio.
- `serving/views.py`, `serving/forms.py`, `serving/urls.py` — lógica y rutas.
- `sistema/settings.py` — configuración del proyecto.
- `sistema/requirements.txt` — dependencias (ruta: `sistema/requirements.txt`).
## Estado de requisitos del usuario
- Título — Hecho
- Descripción — Hecho
- Stack tecnológico — Hecho
- Modelos de datos — Hecho (resumen a partir de `serving/models.py`)
- Requisitos previos — Hecho (referencia a `sistema/requirements.txt`)
- Uso del sistema — Hecho
- Módulos del sistema — Hecho
- Seguridad — Hecho
- Instalación y configuración — Hecho (instrucciones PowerShell)
- Posibles mejoras — Hecho
Si quieres, puedo:
- Añadir badges (build, dependabot) o más imágenes-stickers específicas.
- Generar un pequeño script `setup.ps1` que automatice los pasos de instalación.

33036
get-pip.py Normal file

File diff suppressed because it is too large Load Diff

22
manage.py Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sistema.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

BIN
requirements.txt Normal file

Binary file not shown.

0
serving/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
serving/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
serving/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class ServingConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'serving'

55
serving/forms.py Normal file
View File

@ -0,0 +1,55 @@
from django import forms
from .models import Unidad, Articulo, ArticuloUnidad, Comprobante
class FormUnidad(forms.ModelForm):
class Meta:
model = Unidad
fields=['nombreUnidad', 'telefono', 'ubicacion', 'comandante']
class FormArticulo(forms.ModelForm):
class Meta:
model = Articulo
fields = [
"articulo",
"cantidad",
"precio",
"unidad_medida",
"serial",
"marca",
"modelo",
"fecha_registro",
"description",
]
def clean_articulo(self):
articulo = self.cleaned_data.get('articulo')
if Articulo.objects.filter(articulo=articulo).exists():
raise forms.ValidationError("El artículo ya existe.")
return articulo
class FormEnvio(forms.ModelForm):
class Meta:
model = ArticuloUnidad
fields = [
"articulo",
"cantidad",
"unidad",
"comprobante",
]
class FormComprobante(forms.ModelForm):
class Meta:
model = Comprobante
fields = [
"grupo",
"subgrupo",
"conceptos",
"observaciones",
"numero_movimiento",
"concepto_movimiento",
"e_o_s",
]

View File

84
serving/models.py Normal file
View File

@ -0,0 +1,84 @@
from django.db import models
class Articulo(models.Model):
articulo = models.CharField(max_length=300, verbose_name="Articulo")
description = models.TextField(null=True , verbose_name="Descripcion")
marca = models.CharField(max_length=300, verbose_name="Marca", blank=True)
modelo = models.CharField(max_length=300, verbose_name="Modelo", blank=True)
serial = models.CharField(max_length=300, verbose_name="Serial")
unidad_medida = models.CharField(max_length=100, verbose_name="Unidad de Medida")
fecha = models.DateField(auto_now_add=True)
fecha_registro = models.CharField(max_length=300, verbose_name="Fecha")
cantidad = models.IntegerField(default=0)
precio = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return f"{self.articulo}-{self.marca}-{self.modelo}-{self.serial}-{self.unidad_medida}-{self.fecha_registro}"
def total(self):
return self.cantidad * self.precio
class Comprobante(models.Model):
e_o_s = models.CharField(max_length=300, verbose_name="Condicion", null=True)
conceptos = models.CharField(max_length=300, verbose_name="Concepto", null=True)
observaciones = models.TextField(null=True)
concepto_movimiento = models.IntegerField(default=0, null=True)
numero_movimiento = models.IntegerField(default=0, null=True)
grupo = models.IntegerField(default=0, null=True)
subgrupo = models.IntegerField(default=0, null=True)
def __str__(self):
return f"{self.e_o_s} - {self.conceptos}"
class Unidad(models.Model):
nombreUnidad = models.CharField(max_length=200, verbose_name="Nombre de la Unidad")
comandante = models.CharField(max_length=200, verbose_name="Comandante")
ubicacion = models.TextField(null=True)
telefono = models.CharField(max_length=200, verbose_name="telefono")
articulos = models.ManyToManyField(Articulo, through="ArticuloUnidad")
def __str__(self):
return f'{self.nombreUnidad} - {self.telefono}- {self.comandante}'
class ArticuloUnidad(models.Model):
articulo = models.ForeignKey(Articulo, on_delete=models.CASCADE)
unidad = models.ForeignKey(Unidad, on_delete=models.CASCADE)
comprobante = models.ForeignKey(Comprobante, on_delete=models.SET_NULL, null=True)
marca = models.CharField(max_length=300, verbose_name="Marca")
modelo = models.CharField(max_length=300, verbose_name="Modelo")
serial = models.CharField(max_length=300, verbose_name="Serial")
movimiento = models.CharField(max_length=200)
description = models.TextField(null=True, verbose_name="Descripcion")
unidad_medida = models.CharField(max_length=100, verbose_name="Unidad de Medida")
fecha_salida = models.DateField(auto_now_add=True)
cantidad = models.IntegerField(default=0)
precio = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return f"{self.articulo} - {self.precio} - {self.serial}- {self.marca}- {self.modelo} - {self.comprobante}"
def total(self):
return self.cantidad * self.precio
class PruebaUnidad(models.Model):
articulo = models.ForeignKey(Articulo, on_delete=models.CASCADE)
unidad = models.ForeignKey(Unidad, on_delete=models.CASCADE)
comprobante = models.CharField(max_length=100)
marca = models.CharField(max_length=300, verbose_name="Marca")
modelo = models.CharField(max_length=300, verbose_name="Modelo")
serial = models.CharField(max_length=300, verbose_name="Serial")
movimiento = models.CharField(max_length=200)
unidad_medida = models.CharField(max_length=100, verbose_name="Unidad de Medida")
fecha_salida = models.DateField(auto_now_add=True)
cantidad = models.IntegerField(default=0)
description = models.TextField(null=True, verbose_name="Descripcion")
precio = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return f"{self.articulo} - {self.precio} - {self.serial}- {self.marca}- {self.modelo}- {self.comprobante}"
def total(self):
return self.cantidad * self.precio

View File

@ -0,0 +1,151 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Comprobante</title>
<style>
@page{
size: letter landscape;
margin: 1cm 1cm 1cm 1cm;
}
table , td, th {
border: 1px solid #111111;
border-collapse: collapse;
}
td, th {
white-space: normal;
word-wrap: break-word;
color: black;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td colspan="20" style="padding: 3px;">04 - MINISTERIO DEL PODER POPULAR PARA LA DEFENSA</td>
</tr>
<tr>
<td colspan="20" style="padding: 3px;">0241 - SERVICIO DE INGENIERÍA DEL EJERCITO BOLIVARIANO</td>
</tr>
<tr>
<td colspan="20" style="padding: 3px;">CUARTEL MILITAR "CNEL. ABELARDO MÉRIDA". AV. SUCRE C/C AV. CASANOVA GODOY. MARACAY, EDO. ARAGUA.</td>
</tr>
<tr>
<td colspan="20" style="padding: 3px; text-align:center; font-size:15px;">COMPROBANTE GENERAL DE MOVIMIENTO DE MATERIAS</td>
</tr>
<tr>
<td colspan="5" style="padding: 3px; text-align:center;">UNIDAD</td>
<td colspan="9" style="padding: 3px; text-align:center;">MOVIMIENTO</td>
<td colspan="6" style="padding: 3px; text-align:center;">IDENTIFICACIÓN DEL COMPROBANTE</td>
</tr>
<tr>
<td colspan="5" rowspan="3" style="padding: 3px;">{{unidad.unidad.nombreUnidad}}<br> UBICACIÓN: <br> {{unidad.unidad.ubicacion}} <br></td>
<td colspan="5" rowspan="3" style="padding: 3px; text-align:center;">{{comprobante.e_o_s}}</td>
<td colspan="4" rowspan="3" style="padding: 3px;">CONCEPTO: <br> {{comprobante.conceptos}} </td>
<td colspan="4" style="padding: 2px;">CÓDIGO CONCEPTO MOVIMIENTO</td>
<td colspan="2" style="padding: 3px; text-align:center;">{{comprobante.concepto_movimiento}}</td>
</tr>
<tr>
<td colspan="4" style="padding: 2px;">NUMERO MOVIMIENTO</td>
<td colspan="2" style="padding: 3px; text-align:center;">{{comprobante.numero_movimiento}}</td>
</tr>
<tr>
<td colspan="4" style="padding: 2px;">FECHA DE LA OPERACIÓN</td>
<td colspan="2"style="padding: 3px; text-align:center;">{{fecha|date:"d M Y"}}</td>
</tr>
<tr>
<td colspan="20" style="padding: 5px;"></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td colspan="3" style="text-align:center;">CODIGO</td>
<td colspan="10" rowspan="2" style="text-align:center;">DESCRIPCIÓN</td>
<td rowspan="2" style="text-align:center;">UNIDAD DE MEDIDA</td>
<td rowspan="2" style="text-align:center;">CANT</td>
<td colspan="3" style="text-align:center; padding:3px;">VALOR UNITARIO BS</td>
<td colspan="3" style="text-align:center; padding:3px;">VALOR TOTAL BS</td>
</tr>
<tr>
<td style="text-align:center; padding:3px; font-size:7px;" colspan="1">GRUPO</td>
<td style="text-align:center; padding:3px; font-size:7px;" colspan="1">SUBGRUPO</td>
<td style="text-align:center; padding:3px; font-size:7px;" colspan="1">SECCION</td>
<td colspan="3" style="text-align:center;">VIENE...</td>
<td colspan="3" style="text-align:right;">{{total_precios}}</td>
</tr>
</table>
<table>
<tr>
<td style="text-align:center;" colspan="1">{{comprobante.grupo}}</td>
<td style="text-align:center;" colspan="1">{{comprobante.subgrupo}}</td>
<td style="text-align:center;" colspan="1"></td>
<td colspan="10" style="padding-top: 4px; margin: 8px;">MATERIALES DE CONSUMO.</td>
<td style="text-align:center;"></td>
<td style="text-align:center;"></td>
<td colspan="3" style="text-align: right;"></td>
<td colspan="3" style="text-align: right;"></td>
</tr>
{% for articulos in articulos %}
<tr>
<td style="text-align:center;" colspan="1"></td>
<td style="text-align:center;" colspan="1"></td>
<td style="text-align:center;" colspan="1"></td>
<td colspan="10" style="padding-top: 4px; margin: 8px;">{{articulos.articulo.articulo}}</td>
<td style="text-align:center; padding-top: 4px; margin: 8px; font-size:8px;">{{articulos.unidad_medida}}</td>
<td style="text-align:center; padding-top: 4px; margin: 8px;">{{articulos.cantidad}}</td>
<td colspan="3" style="text-align: right; padding-top: 4px; margin: 8px;">{{articulos.precio}}</td>
<td colspan="3" style="text-align: right; padding-top: 4px; margin: 8px;">{{articulos.total}}</td>
</tr>
{% endfor %}
<tr>
<td colspan="15"></td>
<td colspan="3" style="text-align:center; padding:3px; margin: 8px;">TOTAL:</td>
<td colspan="3" style="text-align: right; padding-top: 4px; margin: 8px;">{{total_precios}}</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td colspan="22" style="padding: 3px;"><b>OBSERVACIONES:</b> <span style="font-size: 10px;">"{{comprobante.observaciones}}"</span></td>
</tr>
<tr>
<td colspan="22" style="padding: 5px;"></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td colspan="6" style="padding: 3px;">NOMBRE DEL ORDENADOR</td>
<td colspan="6" style="padding: 3px;">NOMBRE DEL JEFE DEL ALMACÉN</td>
<td colspan="6" style="padding: 3px; font-size:9px;">NOMBRE DEL EMPLEADO QUE RECIBE O DESPACHA</td>
<td colspan="4" style="padding: 3px;">UNIDAD QUE RECIBE</td>
</tr>
<tr>
<td colspan="6" style="padding-top:30px; text-align:center;"><br> JEFE DEL SERVICIO DE INGENIERÍA DEL EJÉRCITO </td>
<td colspan="6" style="padding-top:30px; text-align:center;"><br> JEFE DEL GRUPO DE TRABAJO DE ABASTECIMIENTO </td>
<td colspan="6" style="padding-top:30px; text-align:center;"><br> JEFE DE RECEPCIÓN Y SUMINISTROS </td>
<td colspan="4" style="padding-top:30px; text-align:center;"> {{unidad.unidad.nombreUnidad}} <br> <br> FIRMA: __________</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,32 @@
{% extends 'base.html' %}
{% block titulo %}
Crear Articulo
{% endblock %}
{% block seccion %}
{% block titulodeseccion %} {% endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %} Crear Articulo{% endblock %}
{% endblock %}
{% block contenido %}
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3 class="card-title m-0">Registrar Articulo</h3>
</div>
</div>
<div class="card-body">
{% include 'articulos/formulario.html' %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends 'base.html' %}
{% block seccion %}
{% block titulodeseccion %} {% endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %} Crear Articulo{% endblock %}
{% endblock %}
{% block contenido %}
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3 class="card-title m-0">Registrar Articulo</h3>
</div>
</div>
<div class="card-body">
{% include 'articulos/formulario.html' %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,6 @@
<form method="post">
{% csrf_token %}
<p>¿Estás seguro de que quieres eliminar? "{{ articulo.articulo }}" </p>
{{ form }}
<input type="submit" value="Confirm">
</form>

View File

@ -0,0 +1,90 @@
<form action="" method="post">
{% csrf_token %}
<div class="form-group">
<label for="id_articulo">Articulo</label>
<input type="text" class="form-control" name="articulo" id="id_articulo" value="{{form.articulo.value}}" placeholder="Articulo">
{% for error in form.articulo.errors %}
{{ error }}
{% endfor %}
</div>
<div class="form-group">
<label for="description">Descripción</label>
<textarea class="form-control" name="description" id="description" rows="3" placeholder="Descripción">{{form.description.value}}</textarea>
{% for error in form.description.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group">
<label for="marca">Marca</label>
<input type="text" class="form-control" name="marca" id="marca" value="{{form.marca.value}}" placeholder="Marca">
{% for error in form.marca.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group">
<label for="modelo">Modelo</label>
<input type="text" class="form-control" name="modelo" id="modelo" value="{{form.modelo.value}}" placeholder="Modelo">
{% for error in form.modelo.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group">
<label for="serial">Serial</label>
<textarea class="form-control" name="serial" id="serial" rows="3" placeholder="Serial">{{form.serial.value}}</textarea>
{% for error in form.serial.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group">
<label for="unidad_medida">Unidad de Medida</label>
<select class="form-control" name="unidad_medida" id="unidad_medida">
<option value="UNIDAD">Unidad</option>
<option value="CAJA">Caja</option>
<option value="GALON">Galones</option>
<option value="PAQUETE">Paquete</option>
<option value="LITRO">Litro</option>
<option value="KILO">Kilo</option>
<option value="CUÑETE">Cuñete</option>
<option value="METRO">Metro</option>
</select>
{% for error in formu.unidad_medida.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group">
<label for="fecha_registro">Fecha de Entrada</label>
<input type="date" class="form-control" name="fecha_registro" id="fecha_registro" value="{{form.fecha_registro.value}}" placeholder="Fecha de Registro">
{% for error in form.fecha_registro.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group">
<label for="cantidad">Cantidad</label>
<input type="number" class="form-control" name="cantidad" id="cantidad" value="{{form.cantidad.value}}" placeholder="Cantidad">
{% for error in form.cantidad.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group">
<label for="precio">Precio</label>
<input type="number" class="form-control" name="precio" id="precio" value="{{form.precio.value}}" placeholder="Precio">
{% for error in form.precio.errors%}
{{error}}
{% endfor %}
</div>
<div class="d-flex justify-content-end card-outline mt-4">
<button type="submit" class="btn btn-dark">Guardar</button>
</div>
</form>

View File

@ -0,0 +1,152 @@
{% extends 'base.html' %}
{% block titulo %}Principal{% endblock %}
{% block seccion %}
{% block titulodeseccion %} Panel de Inventario {% endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %} Información{% endblock %}
{% endblock %}
{% block contenido %}
<!-- Small boxes (Stat box) -->
<div class="row justify-content-center text-center">
<div class="col-lg-2 col-8">
<!-- small box -->
<div class="small-box bg-dark">
<div class="inner">
<h3 class="text-center" style="font-size: 50px;">{{ articulo|length }}</h3>
<p>ARTICULOS</p>
</div>
<div class="icon">
<i class="ion ion-bag"></i>
</div>
<a href="#" class="small-box-footer">Más información <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-6">
<!-- small box -->
<div class="small-box bg-danger">
<div class="inner">
<h3 class="text-center" style="font-size: 50px;">{{ unidades }}</h3>
<p>UNIDADES</p>
</div>
<div class="icon">
<i class="ion ion-stats-bars"></i>
</div>
<a href="{% url 'unidad' %}" class="small-box-footer">Más información <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
<div class="col-lg-2 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3 class="text-center" style="font-size: 50px;">{{ usuarios }}</h3>
<p>USUARIOS</p>
</div>
<div class="icon">
<i class="ion ion-person-add"></i>
</div>
<a href="#" class="small-box-footer">Más información <i class="fas fa-arrow-circle-right"></i></a>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3></h3>
<a href="{% url 'crear_articulo' %}" class="btn btn-dark font-weight-bold"><i class="fas fa-solid fa-plus"></i> Agregar</a>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table id="example1" class="table align-items-center table-flush">
<thead class="thead-light">
<tr>
<th scope="col" class="text-center"></th>
<th scope="col" class="text-center">Fecha Actual</th>
<th scope="col" class="text-center">Fecha Entrada</th>
<th scope="col" class="text-center">Articulo</th>
<th scope="col" class="text-center">Marca</th>
<th scope="col" class="text-center">Modelo</th>
<th scope="col" class="text-center">Serial</th>
<th scope="col" class="text-center">Cantidad</th>
<th scope="col" class="text-center">Precio</th>
<th scope="col" class="text-center">Total</th>
<th scope="col" class="text-center">Acciones</th>
</tr>
</thead>
<tbody>
{% for articulo in articulo %}
<tr class="">
<td class="text-center">{{forloop.counter}}</td>
<td class="text-center">{{articulo.fecha|date:"d-m-y"}}</td>
<td class="text-center">{{articulo.fecha_registro}}</td>
<td class="text-center">{{articulo.articulo}}</td>
<td class="text-center">{{articulo.marca}}</td>
<td class="text-center">{{articulo.modelo}}</td>
<td class="text-center">{{articulo.serial}}</td>
<td class="text-center">{{articulo.cantidad}}</td>
<td class="text-center">{{articulo.precio}}</td>
<td class="text-center">{{articulo.total}}</td>
<td class="text-center">
<a href="{% url 'editar' articulo.id %}" class="btn btn-info"><i class="fas fa-solid fa-pen"></i></a> |
<a href="#" class="btn btn-danger" data-id="{{ articulo.id }}"><i class="fas fa-solid fa-trash"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$(document).ready(function() {
$(".btn-danger").click(function() {
let id = $(this).data('id');
Swal.fire({
title: '¿Estás seguro?',
text: "Si usted acepta ¡No podrás revertir esto! Eliminaras este Articulo",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Sí, bórralo!'
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
url: '/eliminar/' + id,
method: 'GET',
success: function(response) {
if (response.status === 'success') {
Swal.fire('¡Registro eliminado!', '', 'success');
} else {
location.reload();
}
}
});
}
});
});
});
</script>
{% endblock %}

380
serving/templates/base.html Normal file
View File

@ -0,0 +1,380 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{% block titulo %}{% endblock%}</title>
<!-- imagen Favicon -->
<link rel="icon" href="/static/imagenes/icon.ico" type="image/x-icon">
<!-- Google Font: Source Sans Pro -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback"/>
<!-- Ekko Lightbox -->
<link rel="stylesheet" href="/static/plugins/ekko-lightbox/ekko-lightbox.css"/>
<!-- Font Awesome Icons -->
<link rel="stylesheet" href="/static/plugins/fontawesome-free/css/all.min.css"/>
<!-- IonIcons -->
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"/>
<!-- overlayScrollbars -->
<link rel="stylesheet" href="/static/plugins/overlayScrollbars/css/OverlayScrollbars.min.css" />
<!-- DataTables -->
<link rel="stylesheet" href="/static/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css"/>
<link rel="stylesheet" href="/static/plugins/datatables-responsive/css/responsive.bootstrap4.min.css"/>
<link rel="stylesheet" href="/static/plugins/datatables-buttons/css/buttons.bootstrap4.min.css"/>
<!-- Select2 -->
<link rel="stylesheet" href="/static/plugins/select2/css/select2.min.css">
<link rel="stylesheet" href="/static/plugins/select2-bootstrap4-theme/select2-bootstrap4.min.css">
<!-- daterange picker -->
<link rel="stylesheet" href="/static/plugins/daterangepicker/daterangepicker.css">
<!-- iCheck for checkboxes and radio inputs -->
<link rel="stylesheet" href="/static/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
<!-- Bootstrap Color Picker -->
<link rel="stylesheet" href="/static/plugins/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css">
<!-- Tempusdominus Bootstrap 4 -->
<link rel="stylesheet" href="/static/plugins/tempusdominus-bootstrap-4/css/tempusdominus-bootstrap-4.min.css">
<!-- Bootstrap4 Duallistbox -->
<link rel="stylesheet" href="/static/plugins/bootstrap4-duallistbox/bootstrap-duallistbox.min.css">
<!-- BS Stepper -->
<link rel="stylesheet" href="/static/plugins/bs-stepper/css/bs-stepper.min.css">
<!-- dropzonejs -->
<link rel="stylesheet" href="/static/plugins/dropzone/min/dropzone.min.css">
<!-- SweetAlert2 -->
<link rel="stylesheet" href="/static/plugins/sweetalert2-theme-bootstrap-4/bootstrap-4.min.css">
<!-- Toastr -->
<link rel="stylesheet" href="/static/plugins/toastr/toastr.min.css">
<!-- Theme style -->
<link rel="stylesheet" href="/static/bootstrap5/css/bootstrap.min.css" />
<link rel="stylesheet" href="/static/dist/css/adminlte.min.css" />
</head>
<body class="hold-transition sidebar-mini ayout-fixed layout-navbar-fixed layout-footer-fixed">
<div class="wrapper">
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-widget="pushmenu" href="#" role="button"
><i class="fas fa-bars"></i
></a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a href="{% url 'articulos' %}" class="nav-link brand-text font-weight-bold">Inicio</a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a href="{% url 'unidad' %}" class="nav-link brand-text font-weight-bold">Unidad</a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a href="{% url 'envio_articulo'%}" class="nav-link brand-text font-weight-bold">Comprobante</a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a href="{% url 'admin' %}" class="nav-link brand-text font-weight-bold">Usuarios</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" data-widget="navbar-search" href="#" role="button">
<i class="fas fa-search"></i>
</a>
<div class="navbar-search-block">
<form class="form-inline">
<div class="input-group input-group-sm">
<input class="form-control form-control-navbar" type="search" placeholder="Buscar" aria-label="Search"/>
<div class="input-group-append">
<button class="btn btn-navbar" type="submit">
<i class="fas fa-search"></i>
</button>
<button class="btn btn-navbar" type="button" data-widget="navbar-search">
<i class="fas fa-times"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Notifications Dropdown Menu -->
<li class="nav-item dropdown">
<a class="nav-link" data-toggle="dropdown" href="#">
<img src="/static/dist/img/user2-160x160.jpg" class="img-circle elevation-1" alt="User Image" width="25px" height="25px"/>
<span class="brand-text font-weight-bold"> {{request.user.username}}</span>
</a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
<span class="dropdown-item dropdown-header"
>Configuración</span>
<div class="dropdown-divider"></div>
<a href="{% url 'logout' %}" class="dropdown-item"><i class="fas fa-solid fa-power-off"></i> Salir <span class="float-right text-muted text-sm">3 mins</span>
</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" data-widget="fullscreen" href="#" role="button">
<i class="fas fa-expand-arrows-alt"></i>
</a>
</li>
<li class="nav-item"></li>
</ul>
</nav>
<!-- /.navbar -->
<!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-primary elevation-4">
<!-- Brand Logo -->
<a href="#" class="brand-link">
<img src="/static/imagenes/logo2.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: 0.8"/>
<span class="brand-text font-weight-bold">SINGEJB</span>
</a>
<div class="sidebar">
<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
<!--
<li class="nav-item">
<a href="#" class="nav-link">
<i class="nav-icon fas fa-copy"></i>
<p>
Layout Options
<i class="fas fa-angle-left right"></i>
<span class="badge badge-info right">6</span>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="pages/layout/top-nav.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Top Navigation</p>
</a>
</li>
<li class="nav-item">
<a href="pages/layout/top-nav-sidebar.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Top Navigation + Sidebar</p>
</a>
</li>
<li class="nav-item">
<a href="pages/layout/boxed.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Boxed</p>
</a>
</li>
<li class="nav-item">
<a href="pages/layout/fixed-sidebar.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Fixed Sidebar</p>
</a>
</li>
<li class="nav-item">
<a href="pages/layout/fixed-sidebar-custom.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Fixed Sidebar <small>+ Custom Area</small></p>
</a>
</li>
<li class="nav-item">
<a href="pages/layout/fixed-topnav.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Fixed Navbar</p>
</a>
</li>
<li class="nav-item">
<a href="pages/layout/fixed-footer.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Fixed Footer</p>
</a>
</li>
<li class="nav-item">
<a href="pages/layout/collapsed-sidebar.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Collapsed Sidebar</p>
</a>
</li>
</ul>
</li>
-->
</ul>
</nav>
</div>
</aside>
<div class="content-wrapper">
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0">{% block titulodeseccion %}{% endblock%}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="#"> {% block etiqueta1 %}{% endblock%}</a></li>
<li class="breadcrumb-item">{% block etiqueta2 %}{% endblock%}</li>
<li>{% block etiqueta3 %}{% endblock%}</li>
</ol>
</div>
</div>
</div>
</div>
<div class="content">
<div class="container-fluid">
{% block contenido %}{% endblock %}
</div>
</div>
</div>
<!-- Main Footer -->
<footer class="main-footer">
<strong>Copyright &copy; 2024-2030 <a href="#">Dirección de Teconologia de la Información y las Comunicaciones</a>.</strong>
<div class="float-right d-none d-sm-inline-block">
<b>Version</b> 0.0.1
</div>
</footer>
</div>
<!-- ./wrapper -->
<!-- REQUIRED SCRIPTS -->
<!-- jQuery -->
<script src="/static/plugins/jquery/jquery.min.js"></script>
<!-- Bootstrap -->
<script src="/static/bootstrap5/js/bootstrap.bundle.min.js"></script>
<script src="/static/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- SweetAlert2 -->
<script src="/static/plugins/sweetalert2/sweetalert2.min.js"></script>
<!-- Toastr -->
<script src="/static/plugins/toastr/toastr.min.js"></script>
<!-- overlayScrollbars -->
<script src="/static/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js"></script>
<!-- AdminLTE -->
<script src="/static/dist/js/adminlte.js"></script>
<!-- Ekko Lightbox -->
<script src="/static/plugins/ekko-lightbox/ekko-lightbox.min.js"></script>
<!-- Filterizr-->
<script src="/static/plugins/filterizr/jquery.filterizr.min.js"></script>
<!-- OPTIONAL SCRIPTS -->
<script src="/static/plugins/chart.js/Chart.min.js"></script>
<!-- Select2 -->
<script src="/static/plugins/select2/js/select2.full.min.js"></script>
<!-- Bootstrap4 Duallistbox -->
<script src="/static/plugins/bootstrap4-duallistbox/jquery.bootstrap-duallistbox.min.js"></script>
<!-- InputMask -->
<script src="/static/plugins/moment/moment.min.js"></script>
<script src="/static/plugins/inputmask/jquery.inputmask.min.js"></script>
<!-- date-range-picker -->
<script src="/static/plugins/daterangepicker/daterangepicker.js"></script>
<!-- bootstrap color picker -->
<script src="/static/plugins/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js"></script>
<!-- Tempusdominus Bootstrap 4 -->
<script src="/static/plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js"></script>
<!-- Bootstrap Switch -->
<script src="/static/plugins/bootstrap-switch/js/bootstrap-switch.min.js"></script>
<!-- BS-Stepper -->
<script src="/static/plugins/bs-stepper/js/bs-stepper.min.js"></script>
<!-- dropzonejs -->
<script src="/static/plugins/dropzone/min/dropzone.min.js"></script>
<!-- PAGE PLUGINS -->
<!-- jQuery Mapael -->
<script src="/static/plugins/jquery-mousewheel/jquery.mousewheel.js"></script>
<script src="/static/plugins/raphael/raphael.min.js"></script>
<script src="/static/plugins/jquery-mapael/jquery.mapael.min.js"></script>
<script src="/static/plugins/jquery-mapael/maps/usa_states.min.js"></script>
<!-- DataTables & Plugins -->
<script src="/static/plugins/datatables/jquery.dataTables.min.js"></script>
<script src="/static/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js"></script>
<script src="/static/plugins/datatables-responsive/js/dataTables.responsive.min.js"></script>
<script src="/static/plugins/datatables-responsive/js/responsive.bootstrap4.min.js"></script>
<script src="/static/plugins/datatables-buttons/js/dataTables.buttons.min.js"></script>
<script src="/static/plugins/datatables-buttons/js/buttons.bootstrap4.min.js"></script>
<script src="/static/plugins/jszip/jszip.min.js"></script>
<script src="/static/plugins/pdfmake/pdfmake.min.js"></script>
<script src="/static/plugins/pdfmake/vfs_fonts.js"></script>
<script src="/static/plugins/datatables-buttons/js/buttons.html5.min.js"></script>
<script src="/static/plugins/datatables-buttons/js/buttons.print.min.js"></script>
<script src="/static/plugins/datatables-buttons/js/buttons.colVis.min.js"></script>
{% block js %}
{% endblock %}
<script>
$(function () {
$("#example1")
.DataTable({
responsive: false,
lengthChange: true,
autoWidth: false,
//buttons: ["copy", "csv", "excel", "pdf", "print", "colvis"],
language: {
"pageLength": "",
"decimal": "",
"emptyTable": "No hay datos",
"info": "Mostrando _START_ a _END_ de _TOTAL_ Registros",
"infoEmpty": "Mostrando 0 a 0 de 0 Registros",
"infoFiltered": "(Filtro de _MAX_ total Registros)",
"infoPostFix": "",
"thousands": ",",
"lengthMenu": "Mostrar _MENU_ Registros",
"loadingRecords": "Cargando...",
"processing": "Procesando...",
"search": "Buscar:",
"zeroRecords": "No se encontraron coincidencias",
"paginate": {
"first": "Primero",
"last": "Ultimo",
"next": "Próximo",
"previous": "Anterior",
},
"aria": {
"sortAscending": ": Activar orden de columna ascendente",
"sortDescending": ": Activar orden de columna desendente",
}
}
}).buttons().container().appendTo("#example1_wrapper .col-md-6:eq(0)");
$("#example2").DataTable({
paging: true,
lengthChange: false,
searching: false,
ordering: true,
info: true,
autoWidth: false,
responsive: true,
});
});
</script>
{% if messages %}
{% for message in messages %}
<script>
const Toast = Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
});
Toast.fire({
icon: "{{ message.tags }}",
title: "{{ message }}"
});
</script>
{% endfor %}
{% endif %}
</body>
</html>

View File

@ -0,0 +1,110 @@
<form action="" method="post">
{% csrf_token %}
<div class="row">
<div class="form-group col-md-3">
<label for="conceptos"> Conceptos</label>
<select class="form-control" name="conceptos" id="conceptos">
<option value=""> ------ Seleccione ------</option>
<option value="Inventario Inicial">Inventario Inicial</option>
<option value="Entradas por traspasos de otros almacenes">Entradas por traspasos de otros almacenes</option>
<option value="Compras">Compras</option>
<option value="Producción y transformación de materiales">Producción y transformación de materiales</option>
<option value="Suministros de otras entidades">Suministros de otras entidades</option>
<option value="Reintegros o devoluciones">Reintegros o devoluciones</option>
<option value="Reconstrucción de equipos">Reconstrucción de equipos</option>
<option value="Entradas por donación">Entradas por donación</option>
<option value="Entradas por Permuta">Entradas por Permuta</option>
<option value="Omisión en inventarios y sobrantes">Omisión en inventarios y sobrantes</option>
<option value="Incorporaciones para corregir registros anteriores">Incorporaciones para corregir registros
anteriores</option>
<option value="Entradas o incorporaciones por otros conceptos.">Entradas o incorporaciones por otros conceptos.
</option>
<option value="Salidas por traspasos a otros almacenes">Salidas por traspasos a otros almacenes</option>
<option value="Ventas">Ventas</option>
<option value="Entrega de bienes muebles en depósito">Entrega de bienes muebles en depósito</option>
<option value="Suministro de materiales de consumo">Suministro de materiales de consumo</option>
<option value="Desarme">Desarme</option>
<option value="Desincorporación por inservibilidad">Desincorporación por inservibilidad</option>
<option value="Desincorporación por deterioro">Desincorporación por deterioro</option>
<option value="Desincorporación por mermas">Desincorporación por mermas</option>
<option value="Faltantes por investigar">Faltantes por investigar</option>
<option value="Salidas por permuta">Salidas por permuta</option>
<option value="Salidas por donación">Salidas por donación</option>
<option value="Prestamos autorizados">Prestamos autorizados</option>
<option value="Desincorporación para corregir registros anteriores">Desincorporación para corregir registros
anteriores</option>
<option value="Salidas o desincorporaciones por otros conceptos">Salidas o desincorporaciones por otros conceptos
</option>
</select>
{% for error in formulario_comprobante.conceptos.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1">
<label for="concepto_movimiento">Codigo</label>
<input type="text" class="form-control" name="concepto_movimiento" id="concepto_movimiento" placeholder="0" >
{% for error in formulario_comprobante.concepto_movimiento.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-3">
<label for="observaciones"> Observaciones</label>
<textarea class="form-control" name="observaciones" id="observaciones" rows="1" placeholder="Observaciones"></textarea>
{% for error in formulario_comprobante.observaciones.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1">
<label for="e_o_s">Condición</label>
<select class="form-control" name="e_o_s" id="e_o_s">
<option value="">Seleccione</option>
<option value="ENTRADA">Entrada</option>
<option value="SALIDA">Salida</option>
</select>
{% for error in formulario_comprobante.e_o_s.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1">
<label for="numero_movimiento">Numero</label>
<input type="number" class="form-control" name="numero_movimiento" id="numero_movimiento" placeholder="0">
{% for error in formulario_comprobante.numero_movimiento.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1">
<label for="grupo"> Grupo</label>
<input type="number" class="form-control" name="grupo" id="grupo" placeholder="0">
{% for error in formulario_comprobante.grupo.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1">
<label for="subgrupo">Subgrupo</label>
<input type="number" class="form-control" name="subgrupo" id="subgrupo" placeholder="0">
{% for error in formulario_comprobante.subgrupo.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1 d-flex align-items-center" style="padding-top: 30px;">
<button type="submit" class="btn btn-dark">+</button>
</div>
</div>
</form>

View File

View File

@ -0,0 +1,240 @@
{% extends 'base.html' %}
{% block titulo %}Comprobante de Articulos{% endblock%}
{% block seccion %}
{% block titulodeseccion %} Comprobante de Articulos {%endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %}Formulario{% endblock %}
{% endblock %}
{% block contenido %}
<div class="row justify-content-center">
<div class="col-lg-10">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3 class="card-title m-0">Comprobante de Articulos</h3>
</div>
</div>
<div class="card-body">
{% include 'comprobante/formularios.html' %}
<div class="table-responsive-xxl">
<table class="table">
<thead>
<tr>
<th scope="col" class="text-center"></th>
<th scope="col" class="text-center">Condicion</th>
<th scope="col" class="text-center">Concepto</th>
<th scope="col" class="text-center">Observacion</th>
<th scope="col" class="text-center">Codigo</th>
<th scope="col" class="text-center">Numero</th>
<th scope="col" class="text-center">Grupo</th>
<th scope="col" class="text-center">Subgrupo</th>
</tr>
</thead>
<tbody>
{% if comprobantes %}
{% for seleccion in comprobantes %}
<tr>
<td class="text-center">{{forloop.counter}}</td>
<td class="text-center">{{seleccion.e_o_s}}</td>
<td class="text-center">{{seleccion.conceptos}}</td>
<td class="text-center">{{seleccion.observaciones}}</td>
<td class="text-center">{{seleccion.concepto_movimiento}}</td>
<td class="text-center">{{seleccion.numero_movimiento}}</td>
<td class="text-center">{{seleccion.grupo}}</td>
<td class="text-center">{{seleccion.subgrupo}}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="9" class="text-center">No hay articulos</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
{% include 'envios/formulario.html' %}
<div class="table-responsive-xxl">
<table class="table">
<thead>
<tr>
<th scope="col" class="text-center"></th>
<th scope="col" class="text-center">Articulo</th>
<th scope="col" class="text-center">Unidad de Medida</th>
<th scope="col" class="text-center">Cantidad</th>
<th scope="col" class="text-center">Valor Unitario</th>
<th scope="col" class="text-center">Valor Total</th>
</tr>
</thead>
<tbody>
{% if articulos_c %}
{% for comprobante in articulos_c %}
<tr>
<td class="text-center">{{forloop.counter}}</td>
<td class="text-center">{{comprobante.articulo.articulo}}</td>
<td class="text-center">{{comprobante.unidad_medida}}</td>
<td class="text-center">{{comprobante.cantidad}}</td>
<td class="text-center">{{comprobante.precio}}</td>
<td class="text-center">{{comprobante.total}}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="6" class="text-center">No hay articulos</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th colspan="10"></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th scope="col" style="text-align: center;">Total</th>
<th scope="col" style="text-align: center;">{{total_precios}}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div class="row">
<div class="col-12"><a href="{% url 'comprobante'%}" class="btn btn-dark float-left">Comprobante</a>
<form
method="post"
action="{% url 'borrar_todo' %}"
class="float-right"
>
{% csrf_token %}
<button type="submit" class="btn btn-danger">Elimina Todo</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$(document).ready(function () {
$("#conceptos").change(function () {
var conceptoSeleccionado = $(this).val();
var cantidad = 0;
switch (conceptoSeleccionado) {
case "Inventario Inicial":
cantidad = 1;
break;
case "Entradas por traspasos de otros almacenes":
cantidad = 2;
break;
case "Compras":
cantidad = 3;
break;
case "Producción y transformación de materiales":
cantidad = 6;
break;
case "Suministros de otras entidades":
cantidad = 7;
break;
case "Reintegros o devoluciones":
cantidad = 8;
break;
case "Reconstrucción de equipos":
cantidad = 10;
break;
case "Entradas por donación":
cantidad = 11;
break;
case "Reconstrucción de equipos":
cantidad = 10;
break;
case "Entradas por Permuta":
cantidad = 12;
break;
case "Omisión en inventarios y sobrantes":
cantidad = 14;
break;
case "Incorporaciones para corregir registros anteriores":
cantidad = 17;
break;
case "Entradas o incorporaciones por otros conceptos.":
cantidad = 19;
break;
case "Ventas":
cantidad = 52;
break;
case "Entrega de bienes muebles en depósito":
cantidad = 53;
break;
case "Desarme":
cantidad = 55;
break;
case "Desincorporación por inservibilidad":
cantidad = 56;
break;
case "Desincorporación por deterioro":
cantidad = 57;
break;
case "Desincorporación por mermas":
cantidad = 58;
break;
case "Faltantes por investigar":
cantidad = 60;
break;
case "Salidas por permuta":
cantidad = 61;
break;
case "Salidas por donación":
cantidad = 62;
break;
case "Prestamos autorizados":
cantidad = 63;
break;
case "Desincorporación para corregir registros anteriores":
cantidad = 66;
break;
case "Salidas o desincorporaciones por otros conceptos":
cantidad = 69;
break;
case "Suministro de materiales de consumo":
cantidad = 54;
break;
case "Salidas por traspasos a otros almacenes":
cantidad = 51;
break;
default:
cantidad = 0;
}
$("#concepto_movimiento").val(cantidad);
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,58 @@
<form action="" method="post">
{% csrf_token %}
<div class="row lign-items-center">
<div class="form-group col-md-4">
<label for="articulo_id">Articulo</label>
<select class="form-control" name="articulo" id="articulo_id" data-placeholder="Selecciona Articulos">
<option value="">Selecciones</option>
{% for articulo in articulo %}
<option value="{{articulo.id}}">{{articulo.articulo}} - {{articulo.cantidad}}</option>
{% endfor %}
</select>
{% for error in formulario_envio.articulo.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-4">
<label for="unidad_id">Unidad</label>
<select class="form-control" name="unidad" id="unidad_id">
<option value="">Selecciones</option>
{% for unidad in unidades %}
<option value="{{unidad.id}}">{{unidad.nombreUnidad}}</option>
{% endfor %}
</select>
{% for error in formulario_envio.unidad.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1">
<label for="comprobante">Codigo</label>
<select class="form-control" name="comprobante" id="comprobante">
{% for comprobante in comprobantes %}
<option value="{{comprobante.id}}"> {{forloop.counter}} - {{comprobante.concepto_movimiento}}</option>
{% endfor %}
</select>
{% for error in formulario_envio.comprobante.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-1">
<label for="cantidad"> Cantidad</label>
<input type="number" class="form-control" name="cantidad" id="cantidad">
{% for error in formulario_envio.cantidad.errors%}
{{error}}
{% endfor %}
</div>
<div class="form-group col-md-2 d-flex align-items-center" style="padding-top: 30px;">
<button type="submit" class="btn btn-dark">+</button>
</div>
</div>
</form>

View File

@ -0,0 +1,76 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Acceso SINGEJB </title>
<link rel="shortcut icon" type="image/png" href="/static/imagenes/icon.ico" />
<link rel="stylesheet" href="/static/plantilla1/src/assets/css/styles.min.css" />
</head>
<body>
<!-- Body Wrapper -->
<div class="page-wrapper" id="main-wrapper" data-layout="vertical" data-navbarbg="skin6" data-sidebartype="full"
data-sidebar-position="fixed" data-header-position="fixed">
<div
class="position-relative overflow-hidden radial-gradient min-vh-100 d-flex align-items-center justify-content-center">
<div class="d-flex align-items-center justify-content-center w-100">
<div class="row justify-content-center w-100">
<div class="col-md-8 col-lg-6 col-xxl-3">
<div class="card mb-0">
<div class="card-body">
<a href="./index.html" class="text-nowrap logo-img text-center d-block py-3 w-100">
<img src="/static/imagenes/logo2.png" width="180" alt="">
</a>
<p class="text-center"> <b>Servicio de Ingenieria del Ejército Bolivariano</b></p>
{% if form.errors %}
<p>Su nombre de usuario y contraseña no coinciden. Inténtalo de nuevo.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Su cuenta no tiene acceso a esta página. Para continuar, inicie sesión con una cuenta que tenga acceso.</p>
{% else %}
<p>Por favor inicie sesión para ver esta página.</p>
{% endif %}
{% endif %}
<form method="post" action="">
{% csrf_token %}
<div class="mb-3">
<label for="username" class="form-label">Nombre de usuario</label>
<input type="text" class="form-control" name="username" id="username" aria-describedby="emailHelp">
</div>
<div class="mb-4">
<label for="password" class="form-label">Contraseña</label>
<input type="password" class="form-control" name="password" id="password">
</div>
<div class="d-flex align-items-center justify-content-between mb-3">
<div class="form-check">
<input class="form-check-input primary" type="checkbox" value="" id="flexCheckChecked" checked>
<label class="form-check-label text-dark" for="flexCheckChecked">
Recuerda
</label>
</div>
<a class="text-primary fw-bold" href="{% url 'password_reset' %}">Has olvidado tu contraseña?</a>
</div>
<input type="submit" class="btn btn-primary w-100 fs-4 mb-4 rounded-2" value="Iniciar sesión">
<div class="d-flex align-items-center justify-content-center">
<!-- <p class="fs-4 mb-0 fw-bold">Eres Nuevo</p>
<a class="text-primary fw-bold ms-2" href="./authentication-register.html">Crea una cuenta</a> -->
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="/static/plantilla1/src/assets/libs/jquery/dist/jquery.min.js"></script>
<script src="/static/plantilla1/src/assets/libs/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,60 @@
{% extends 'base.html' %}
{% block titulo %}Articulo Recibidos{% endblock %}
{% block seccion %}
{% block titulodeseccion %} Historial de Articulos Recibidos {% endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %} Información{% endblock %}
{% endblock %}
{% block contenido %}
<div class="row">
<div class="col-lg-12">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table id="example1" class="table align-items-center table-flush">
<thead class="thead-light">
<tr>
<th scope="col"></th>
<th scope="col">Descripcion</th>
<th scope="col">Marca</th>
<th scope="col">Modelo</th>
<th scope="col">Serial</th>
<th scope="col">Cant</th>
<th scope="col">Comprobante</th>
<th scope="col">Asignado</th>
</tr>
</thead>
<tbody>
{% for objetos in articulo %}
<tr class="">
<td>{{forloop.counter}}</td>
<td>{{objetos.description}}</td>
<td>{{objetos.marca}}</td>
<td>{{objetos.modelo}}</td>
<td>{{objetos.serial}}</td>
<td>{{objetos.cantidad}}</td>
<td>{{objetos.comprobante.concepto_movimiento}}</td>
<td>{{objetos.fecha_salida|date:'d-m-Y'}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,29 @@
{% extends 'base.html' %}
{% block seccion %}
{% block titulodeseccion %} Unidad Registro {% endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %} Registro de Unidad{% endblock %}
{% endblock %}
{% block contenido %}
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3 class="card-title m-0">Unidad</h3>
</div>
</div>
<div class="card-body">
{% include 'unidad/formulario_unidad.html' %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,28 @@
{% extends 'base.html' %}
{% block seccion %}
{% block titulodeseccion %} Unidad Registro {% endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %} Registro de Unidad{% endblock %}
{% endblock %}
{% block contenido %}
<div class="row justify-content-center">
<div class="col-lg-6">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3 class="card-title m-0">Unidad</h3>
</div>
</div>
<div class="card-body">
{% include 'unidad/formulario_unidad.html' %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,6 @@
<form method="post">
{% csrf_token %}
<p>¿Estás seguro de que quieres eliminar? "{{ unidad.nombreUnidad }}" </p>
{{ form }}
<input type="submit" value="Confirm">
</form>

View File

@ -0,0 +1,30 @@
<form action="" method="post">
{% csrf_token %}
<div class="form-group">
<label for="nombreUnidad">Identificación de la Unidad</label>
<input type="text" class="form-control" name="nombreUnidad" id="nombreUnidad" value="{{form.nombreUnidad.value}}" placeholder="Nombre de la Unidad">
</div>
<div class="form-group">
<label for="comandante">Comandante</label>
<input type="text" class="form-control" name="comandante" id="comandante" value="{{form.comandante.value}}" placeholder="Nombre del Comandante">
</div>
<div class="form-group">
<label for="telefono">Telefono</label>
<input type="tel" class="form-control" name="telefono" id="telefono" value="{{form.telefono.value}}" placeholder="Telefono">
</div>
<div class="form-group">
<label for="ubicacion">Ubicacion</label>
<textarea class="form-control" name="ubicacion" id="ubicacion" rows="3" placeholder="Ubicacion...">{{form.ubicacion.value}}</textarea>
</div>
<div class="d-flex justify-content-end card-outline mt-4">
<button type="submit" class="btn btn-dark">Guardar</button>
</div>
</form>

View File

@ -0,0 +1,67 @@
{% extends 'base.html' %}
{% block titulo %}
Unidad
{% endblock %}
{% block seccion %}
{% block titulodeseccion %} Unidad {% endblock%}
{% block etiqueta1 %}Inicio{% endblock %}
{% block etiqueta2 %} Información{% endblock %}
{% endblock %}
{% block contenido %}
<div class="row">
<div class="col-lg-12">
<div class="card card-dark card-outline">
<div class="card-header">
<div class="d-flex justify-content-between">
<h3></h3>
<a href="{% url 'crear_unidad' %}" class="btn btn-dark font-weight-bold"><i class="fas fa-solid fa-plus"></i> Agregar</a>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table id="example1" class="table align-items-center table-flush">
<thead class="thead-light">
<tr>
<th scope="col"></th>
<th scope="col">Nombre de la Unidad</th>
<th scope="col">Comandante</th>
<th scope="col">Telefono</th>
<th scope="col">Ubicación</th>
<th scope="col">Acciones</th>
</tr>
</thead>
<tbody>
{% for unidad in unidad %}
<tr class="">
<td>{{forloop.counter}}</td>
<td>{{unidad.nombreUnidad}}</td>
<td>{{unidad.comandante}}</td>
<td>{{unidad.telefono}}</td>
<td>{{unidad.ubicacion}}</td>
<td>
<a href="{% url 'unidad_articulo' unidad.id %}" class="btn btn-dark"><i class="fas fa-solid fa-eye"></i></a> |
<a href="{% url 'editar_unidad' unidad.id %}" class="btn btn-info"><i class="fas fa-solid fa-pen"></i></a> |
<a href="{% url 'eliminar_unidad' unidad.id %}" class="btn btn-danger"><i class="fas fa-solid fa-trash"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

3
serving/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

56
serving/urls.py Normal file
View File

@ -0,0 +1,56 @@
from django.urls import path
from . import views
from django.conf import settings
from django.conf.urls.static import static
from serving.views import (
VistaInventario,
CrearArticulo,
VistaEnvio,
VistaUnidad,
CrearUnidad,
UnidadArticulo,
EditarVista,
EditarVistaUnidad,
EliminarVistaUnidad,
ComprobanteVista,
BorrarVistaComprobante,
AccesoVista,
CerrarVista,
Admin,
)
urlpatterns = [
path("", VistaInventario.as_view(), name="articulos"),
path("articulos/crear.html", CrearArticulo.as_view(), name="crear_articulo"),
path("articulos/editar/<int:pk>", EditarVista.as_view(), name="editar"),
path("eliminar/<int:id>", views.eliminar, name="eliminar"),
# envios
path("envios/envio_articulo", VistaEnvio.as_view(), name="envio_articulo"),
# Unidad
path("unidad/unidad_index", VistaUnidad.as_view(), name="unidad"),
path("unidad/crear_unidad", CrearUnidad.as_view(), name="crear_unidad"),
path(
"unidad/editar_unidad/<int:pk>",
EditarVistaUnidad.as_view(),
name="editar_unidad",
),
path(
"unidad/<int:pk>/eliminar_unidad/",
EliminarVistaUnidad.as_view(),
name="eliminar_unidad",
),
# subunidades
path(
"subunidad/unidad_articulo/<int:id>",
UnidadArticulo.as_view(),
name="unidad_articulo",
),
# comprobantes PDF
path("articulos/comprobante", ComprobanteVista.as_view(), name="comprobante"),
path("envios/borrartodo", BorrarVistaComprobante.as_view(), name="borrar_todo"),
# acceso vista
path("registration/login/", AccesoVista.as_view(), name="login"),
path("accounts/logout/", CerrarVista.as_view(), name="logout"),
path("admin", Admin.as_view(), name="admin"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

285
serving/views.py Normal file
View File

@ -0,0 +1,285 @@
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy, reverse
from django.views import View
from django.contrib import messages
from datetime import datetime
from django.contrib.auth.views import LogoutView, LoginView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout
from django.conf import settings
from django.http import HttpRequest, HttpResponse, QueryDict, HttpResponseRedirect, JsonResponse
from django.template.loader import get_template
from django.contrib.messages.views import SuccessMessageMixin
from xhtml2pdf import pisa
from django.contrib.staticfiles import finders
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic import RedirectView
from django.db.models import Sum, F
from django.contrib.auth.models import User
from .models import Unidad, Articulo, ArticuloUnidad, Comprobante , PruebaUnidad
from .forms import FormUnidad, FormArticulo, FormEnvio, FormComprobante
# vista de inventario
class VistaInventario(LoginRequiredMixin,View):
def get(self, request, *args, **kwargs):
articulo = Articulo.objects.all()
unidades = Unidad.objects.all().count()
usuarios = User.objects.all().count()
context = {'articulo':articulo, 'unidades':unidades, 'usuarios':usuarios}
return render(request, 'articulos/index.html', context)
class CrearArticulo(LoginRequiredMixin, CreateView):
form_class = FormArticulo
initial = {"key": "value"}
template_name = "articulos/crear.html"
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
context = {'formulario_articulo':form}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
form =self.form_class(request.POST)
if form.is_valid():
form.save()
return redirect('articulos')
else:
messages.error(request, "esto es una prueba de falla")
context = {"form": form}
return render(request, self.template_name, context )
class EditarVista(LoginRequiredMixin, UpdateView):
model = Articulo
form_class = FormArticulo
template_name = "articulos/editar.html"
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().get(request, self.template_name, *args, **kwargs)
def get_initial(self):
initial = super().get_initial()
# initial['serial'] = self.object.serial
return initial
def form_valid(self, formulario_articulo):
self.object = formulario_articulo.save()
return redirect('articulos')
@login_required
def eliminar(request, id):
try:
articulo = Articulo.objects.get(id=id)
articulo.delete()
messages.success(request, "Registro eliminado correctamente.")
except Articulo.DoesNotExist:
messages.error(request, 'Algo Salio Mal')
return redirect('articulos')
class ComprobanteVista(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
try:
fecha = datetime.now().date()
unidad = ArticuloUnidad.objects.first()
articulos = ArticuloUnidad.objects.all()
comprobante = Comprobante.objects.first()
total_precios = ArticuloUnidad.objects.annotate(total=Sum(F("cantidad") * F("precio"))).aggregate(total_sum=Sum("total"))["total_sum"]
template_path = "articulos/comprobante.html"
context = {
"articulos": articulos,
"total_precios": total_precios,
"comprobante": comprobante,
"unidad": unidad,
"fecha": fecha,
}
response = HttpResponse(content_type="application/pdf")
response["Content-Disposition"] = 'attachment; filename="comprobantes.pdf"'
template = get_template(template_path)
html = template.render(context)
# Crear el PDF
pisa_status = pisa.CreatePDF(html, dest=response)
if pisa_status.err:
messages.error(request, "Hubo errores al generar el PDF.")
return render(request, "articulos/comprobante.html", {"html": html})
return response
except Comprobante.DoesNotExist:
messages.error(request, "El comprobante no existe.")
return render(request, "articulos/comprobante.html")
except Exception as e:
messages.error(request, f"Ocurrió un error: {e}")
return render(request, "articulos/comprobante.html")
# ---------- fin de la vista inventario
# inicio de la vista de envio de articulos
class VistaEnvio(LoginRequiredMixin, CreateView):
form_class = FormEnvio
initial = {"key": "value"}
template_name = "envios/envio_articulo.html"
def get(self, request , *args, **kwargs):
articulo = Articulo.objects.all()
articulos_c = ArticuloUnidad.objects.all()
comprobantes = Comprobante.objects.all()
total_precios = ArticuloUnidad.objects.annotate(total=Sum(F("cantidad") * F("precio"))).aggregate(total_sum=Sum("total"))["total_sum"]
unidades = Unidad.objects.all()
context= {
"articulo": articulo,
"unidades": unidades,
"articulos_c": articulos_c,
"total_precios": total_precios,
"comprobantes": comprobantes,
}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
formulario_envio = self.form_class(request.POST)
if formulario_envio.is_valid():
unidad = formulario_envio.cleaned_data["unidad"]
cantidad = formulario_envio.cleaned_data["cantidad"]
articulo = formulario_envio.cleaned_data["articulo"]
comprobante = formulario_envio.cleaned_data["comprobante"]
if articulo.cantidad >= cantidad:
articulo.cantidad -= cantidad
articulo.save()
ArticuloUnidad.objects.create(
movimiento="Envío",
articulo=articulo,
unidad=unidad,
cantidad=cantidad,
unidad_medida=articulo.unidad_medida,
precio=articulo.precio,
serial=articulo.serial,
marca=articulo.marca,
description=articulo.description,
modelo=articulo.modelo,
)
PruebaUnidad.objects.create(
movimiento="Envío",
articulo=articulo,
unidad=unidad,
cantidad=cantidad,
unidad_medida=articulo.unidad_medida,
precio=articulo.precio,
serial=articulo.serial,
marca=articulo.marca,
comprobante = comprobante,
description=articulo.description,
modelo=articulo.modelo,
)
messages.success(request, "Se Inserto con Exito")
return redirect("envio_articulo")
else:
messages.error(request, "No hay suficientes articulos")
return redirect("envio_articulo")
else:
formulario_comprobante = FormComprobante(request.POST)
if formulario_comprobante.is_valid():
formulario_comprobante.save()
return redirect("envio_articulo")
else:
context = {
"formulario_envio": formulario_envio,
"formulario_comprobante": formulario_comprobante,
}
return render(request, self.template_name, context)
class BorrarVistaComprobante(LoginRequiredMixin, View):
template_name = "envios/borrartodo.html"
success_url = reverse_lazy("envio_articulo")
def get(self, request):
return render(request, self.template_name)
def post(self, request):
Comprobante.objects.all().delete()
ArticuloUnidad.objects.all().delete()
return HttpResponseRedirect(reverse_lazy("envio_articulo"))
# fin de la vista de articulos
class VistaUnidad(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
unidad = Unidad.objects.all()
context = {'unidad':unidad}
return render(request, 'unidad/unidad_index.html',context)
class CrearUnidad(LoginRequiredMixin, CreateView):
form_class = FormUnidad
initial = {"key": "value"}
template_name = "unidad/crear_unidad.html"
def get(self, request, *args, **kwargs):
formulario_unidad = self.form_class(initial=self.initial)
context = {'formulario_unidad':formulario_unidad}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
formulario_unidad = self.form_class(request.POST)
if formulario_unidad.is_valid():
formulario_unidad.save()
return redirect('unidad')
return render(request, self.template_name, {'formulario_unidad':formulario_unidad})
class UnidadArticulo(LoginRequiredMixin, View):
def get(self, request, id):
unidad= Unidad.objects.get(pk=id)
articulo = PruebaUnidad.objects.filter(unidad=unidad)
context={'articulo':articulo}
return render(request, 'subunidad/unidad_articulo.html',context)
class EditarVistaUnidad(LoginRequiredMixin, UpdateView):
model = Unidad
form_class = FormUnidad
template_name = "unidad/editar_unidad.html"
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().get(request, self.template_name, *args, **kwargs)
def get_initial(self):
initial = super().get_initial()
return initial
def form_valid(self, form):
self.object = form.save()
return redirect('unidad')
class EliminarVistaUnidad(LoginRequiredMixin, DeleteView):
model = Unidad
template_name = "unidad/eliminar_unidad.html"
success_url = reverse_lazy('unidad')
class AccesoVista(LoginView):
login_url = "registration/login.html"
redirect_field_name = "redirect_to"
class CerrarVista(RedirectView):
def get(self, request):
logout(request)
return redirect("login")
class Admin(View):
def get(self, request, *args, **kwargs):
return render(request, 'administrador/admin.html')

0
sistema/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

16
sistema/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for sistema project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sistema.settings')
application = get_asgi_application()

149
sistema/settings.py Normal file
View File

@ -0,0 +1,149 @@
"""
Django settings for sistema project.
Generated by 'django-admin startproject' using Django 5.0.4.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-e^u3__^x9+5*5-1%_3@dbx)h-=om)w(yt8l#q^a@=b1xjtn@n$'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"serving",
"xhtml2pdf",
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'sistema.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'sistema.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'serving',
'USER': 'root',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '3306',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES,STRICT_ALL_TABLES'",
},
},
}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = 'es'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
MEDIA_URL = '/imagenes/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
LOGIN_REDIRECT_URL = "/"
SESSION_EXPIRE_SECONDS = 200 # Expire después de 5 minutos
SESSION_EXPIRE_AFTER_LAST_ACTIVITY = True
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

25
sistema/urls.py Normal file
View File

@ -0,0 +1,25 @@
"""
URL configuration for sistema project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("", include("serving.urls")),
path("admin/", admin.site.urls),
path("accounts/", include("django.contrib.auth.urls")),
]

16
sistema/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for sistema project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sistema.settings')
application = get_wsgi_application()

5002
static/bootstrap5/css/bootstrap-grid.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,426 @@
/*!
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,423 @@
/*!
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: #0d6efd;
text-decoration: underline;
}
a:hover {
color: #0a58ca;
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: #d63384;
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.2rem 0.4rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v5.0.2 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10837
static/bootstrap5/css/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10813
static/bootstrap5/css/bootstrap.rtl.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6748
static/bootstrap5/js/bootstrap.bundle.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4967
static/bootstrap5/js/bootstrap.esm.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

5016
static/bootstrap5/js/bootstrap.js vendored Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More