This commit is contained in:
aespin 2024-08-20 09:11:15 +02:00
commit 5fb06ce38a
42 changed files with 26599 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

46
.air.toml Normal file
View File

@ -0,0 +1,46 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "templ generate && go build -o ./tmp/main ."
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = [".*_templ.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
tmp
vendor

34
Makefile Normal file
View File

@ -0,0 +1,34 @@
# Variables
IMAGE_NAME = registry.espin.casa/cml04-mediciones
CONTAINER_NAME = cml04-mediciones
# Check if Docker or Podman is available
DOCKER := $(shell command -v docker 2> /dev/null)
PODMAN := $(shell command -v podman 2> /dev/null)
# Determine which command to use based on availability
ifdef DOCKER
DOCKER_CMD := docker
else ifdef PODMAN
DOCKER_CMD := podman
else
$(error "Neither Docker nor Podman is installed on this system.")
endif
# Build the Docker image
build:
$(DOCKER_CMD) build -t $(IMAGE_NAME) -f docker/Dockerfile .
# Run the container
run:
@templ generate
@$(DOCKER_CMD) run $(IMAGE_NAME)
# Stop and remove the container
stop:
$(DOCKER_CMD) stop $(CONTAINER_NAME)
$(DOCKER_CMD) rm $(CONTAINER_NAME)
# Remove the Docker image
clean:
$(DOCKER_CMD) rmi $(IMAGE_NAME)

0
README.md Normal file
View File

4
assets/css/app.css Normal file
View File

@ -0,0 +1,4 @@
tr.htmx-swapping td {
opacity: 0;
transition: opacity 1s ease-out;
}

13062
assets/css/bulma.css vendored Normal file

File diff suppressed because it is too large Load Diff

71
assets/css/bulma.css.map Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
assets/img/H-I-UC-UB.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
assets/img/Perfiles.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
assets/img/UPN.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
assets/img/ruler.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
assets/img/viga.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

10716
assets/js/jquery.js vendored Normal file

File diff suppressed because it is too large Load Diff

376
assets/js/mediciones.js Normal file
View File

@ -0,0 +1,376 @@
// Al cargar documento
$(document).ready(function () {
// Obtener el listado de ordenes de fabricación
ProductionOrderList();
let producto = localStorage.getItem("producto");
let po = localStorage.getItem("production_order");
Refresco(producto, po);
// Obtener tolerancias y mediciones
$("#orden_fabricacion").change(function () {
var po = $(this).val();
var text = $("#orden_fabricacion option:selected").text();
var partes = text.split("-");
var producto = partes[1].trim();
// guardar en local las variables
localStorage.setItem('production_order', po);
localStorage.setItem('producto', producto);
// refresco pantalla
Refresco(producto, po);
});
$("#medicion_form").on("submit", function (event) {
event.preventDefault();
});
$("#long-muestra").on("keyup", function (event) {
PesoMetro();
});
$("#kg-muestra").on("keyup", function (event) {
PesoMetro();
});
});
function SetProducto(producto) {
// set producto
$("#producto").val(producto);
}
function PesoMetro() {
let longMuestra = $("#long-muestra").val();
let pesoMuestra = $("#kg-muestra").val();
let ggMuestra = longMuestra / pesoMuestra;
$("#gmm-muestra").val(ggMuestra.toFixed(2));
}
function Refresco(producto, po) {
// tolerancias para el producto
GetTolerancias(producto);
// mediciones para la po
ObtenerMediciones(po);
// datos de la po
ProductionOrder(po);
// set producto
SetProducto(producto);
// set cartel mediciones
CartelMediciones(producto);
}
function CartelMediciones(producto) {
$("#encabezado-mediciones").text("Mediciones antes del enderezado para el producto: " + producto);
}
function ProductionOrderList() {
$.ajax({
type: "GET",
url: "/po/list",
dataType: "json",
success: function (data) {
$.each(data.OrdenFabricacion, function (index, value) {
$("#orden_fabricacion").append("<option class='has-text-weight-bold' value='" + value.POrderNo + "'>" + value.POrderNo + " - " + value.FSection + "</option>");
});
},
error: function () {
alert("obtener lista de ordenes de produccion ha fallado");
}
});
}
function GetTolerancias(producto) {
fetch("/tolerance/get", {
// tolerancias
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ Medida: producto })
}).then(response => {
if (!response.ok) {
throw new Error('network response was not ok');
}
return response.json();
}).then(data => {
// get tolerancia only
var tolerancia = data.Tolerancia;
// save into local storage
localStorage.setItem('tolerancia', JSON.stringify(tolerancia));
// set tolerancias max
var tolMaxHeaders = document.querySelectorAll("#tol-max th");
// set values
tolMaxHeaders[1].innerText = tolerancia.MMax;
tolMaxHeaders[2].innerText = tolerancia.HMax;
tolMaxHeaders[3].innerText = tolerancia.SMax;
tolMaxHeaders[4].innerText = tolerancia.TMax;
tolMaxHeaders[5].innerText = tolerancia.BMax;
tolMaxHeaders[7].innerText = "Máx: " + tolerancia.AsimMax;
tolMaxHeaders[9].innerText = "Máx: " + tolerancia.AsimMax;
// set tolerancias max rec
var tolMaxRecHeaders = document.querySelectorAll("#tol-max-rec th");
// set values
tolMaxRecHeaders[1].innerText = (tolerancia.MNom + ((tolerancia.MMax - tolerancia.MNom) * 0.75)).toFixed(2);
tolMaxRecHeaders[2].innerText = (tolerancia.HNom + ((tolerancia.HMax - tolerancia.HNom) * 0.75)).toFixed(2);
tolMaxRecHeaders[3].innerText = (tolerancia.SNom + ((tolerancia.SMax - tolerancia.SNom) * 0.75)).toFixed(2);
tolMaxRecHeaders[4].innerText = (tolerancia.TNom + ((tolerancia.TMax - tolerancia.TNom) * 0.75)).toFixed(2);
tolMaxRecHeaders[5].innerText = (tolerancia.BNom + ((tolerancia.BMax - tolerancia.BNom) * 0.75)).toFixed(2);
// set nominales
var tolNomHeaders = document.querySelectorAll("#tol-nominal th");
// set nominales values
tolNomHeaders[1].innerText = (tolerancia.MNom).toFixed(2);
tolNomHeaders[2].innerText = (tolerancia.HNom).toFixed(2);
tolNomHeaders[3].innerText = (tolerancia.SNom).toFixed(2);
tolNomHeaders[4].innerText = (tolerancia.TNom).toFixed(2);
tolNomHeaders[5].innerText = (tolerancia.BNom).toFixed(2);
// set tolerancias min rec
var tolMinRecHeaders = document.querySelectorAll("#tol-min-rec th")
// set values
tolMinRecHeaders[1].innerText = (tolerancia.MNom - ((tolerancia.MNom - tolerancia.MMin) * 0.75)).toFixed(2);
tolMinRecHeaders[2].innerText = (tolerancia.HNom - ((tolerancia.HNom - tolerancia.HMin) * 0.75)).toFixed(2);
tolMinRecHeaders[3].innerText = (tolerancia.SNom - ((tolerancia.SNom - tolerancia.SMin) * 0.75)).toFixed(2);
tolMinRecHeaders[4].innerText = (tolerancia.TNom - ((tolerancia.TNom - tolerancia.TMin) * 0.75)).toFixed(2);
tolMinRecHeaders[5].innerText = (tolerancia.BNom - ((tolerancia.BNom - tolerancia.BMin) * 0.75)).toFixed(2);
tolMinRecHeaders[7].innerText = "Rec: " + tolerancia.AsimMax * 0.75;
tolMinRecHeaders[9].innerText = "Rec: " + tolerancia.AsimMax * 0.75;
// set tolerancias min
var tolMinHeaders = document.querySelectorAll("#tol-min th")
// set values
tolMinHeaders[1].innerText = (tolerancia.MMin).toFixed(2);
tolMinHeaders[2].innerText = (tolerancia.HMin).toFixed(2);
tolMinHeaders[3].innerText = (tolerancia.SMin).toFixed(2);
tolMinHeaders[4].innerText = (tolerancia.TMin).toFixed(2);
tolMinHeaders[5].innerText = (tolerancia.BMin).toFixed(2);
});
}
function ObtenerMediciones(po) {
$.ajax({
url: "/mediciones/get",
type: "POST",
data: JSON.stringify({ production_order: po }),
dataType: "json",
success: function (data) {
var mediciones = data.Mediciones;
// get table body to append data
var medicionesTable = document.getElementById('mediciones-po');
// clean table body
medicionesTable.innerHTML = '';
// iterate over data array
mediciones.forEach(function (medicion) {
// tolerancias
var tolerancia = localStorage.getItem('tolerancia');
tolerancia = JSON.parse(tolerancia);
// create new row
var newRow = medicionesTable.insertRow();
// medicion tipo
var medicionTipo = newRow.insertCell();
if (medicion.MedicionTipo === 1) {
medicionTipo.textContent = 'M';
} else {
medicionTipo.textContent = 'C';
}
medicionTipo.className = 'is-size-4 has-text-weight-bold';
// hora
var horaCell = newRow.insertCell();
horaVal = new Date(medicion.CreatedAt);
var hora = horaVal.getHours();
var minutos = horaVal.getMinutes();
// Formatear la hora para que tenga dos dígitos
hora = hora < 10 ? '0' + hora : hora;
minutos = minutos < 10 ? '0' + minutos : minutos;
// Crear una cadena con la hora formateada
var horaString = hora + ':' + minutos;
horaCell.textContent = horaString;
horaCell.className = 'is-size-4 has-text-weight-bold';
// colada
var colada = newRow.insertCell();
colada.textContent = medicion.Colada;
colada.className = 'is-size-4 has-text-weight-bold';
// masa unitaria longitud
var masa_longitud = newRow.insertCell();
masa_longitud.textContent = medicion.MasaUnitaria.Longitud;
masa_longitud.className = 'is-size-4 has-text-weight-bold';
// masa unitaria peso
var masa_peso = newRow.insertCell();
masa_peso.textContent = medicion.MasaUnitaria.Peso;
masa_peso.className = 'is-size-4 has-text-weight-bold';
// g/mm
var gmm = medicion.MasaUnitaria.GramosMM;
gmmCell = newRow.insertCell();
gmmCell.textContent = gmm;
if (gmm > parseFloat(tolerancia.MMax) || gmm < parseFloat(tolerancia.MMin)) {
gmmCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
gmmCell.className = 'is-size-4 has-text-weight-bold';
}
// altura perfil
var altura_perfil = medicion.AlturaPerfil;
alturaPerfilCell = newRow.insertCell();
alturaPerfilCell.textContent = altura_perfil;
if (altura_perfil > tolerancia.HMax || altura_perfil < tolerancia.HMin) {
alturaPerfilCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
alturaPerfilCell.className = 'is-size-4 has-text-weight-bold';
}
// espesor alma
var espesor_alma = medicion.EspesorAlma;
espesorAlmaCell = newRow.insertCell();
espesorAlmaCell.textContent = espesor_alma;
if (espesor_alma > tolerancia.SMax || espesor_alma < tolerancia.SMin) {
espesorAlmaCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
espesorAlmaCell.className = 'is-size-4 has-text-weight-bold';
}
// espesor ala motor superior
var esp_alas_sup_lado_motor = medicion.EspesoresAlas.LadoMotorSup;
espesorAlaMotorSupCell = newRow.insertCell();
espesorAlaMotorSupCell.textContent = esp_alas_sup_lado_motor;
if (esp_alas_sup_lado_motor > tolerancia.TMax || esp_alas_sup_lado_motor < tolerancia.TMin) {
espesorAlaMotorSupCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
espesorAlaMotorSupCell.className = 'is-size-4 has-text-weight-bold';
}
// espesor ala motor inferior
var esp_alas_lado_motor = medicion.EspesoresAlas.LadoMotorInf;
espesorAlaMotorInfCell = newRow.insertCell();
espesorAlaMotorInfCell.textContent = esp_alas_lado_motor;
if (esp_alas_lado_motor > tolerancia.TMax || esp_alas_lado_motor < tolerancia.TMin) {
espesorAlaMotorInfCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
espesorAlaMotorInfCell.className = 'is-size-4 has-text-weight-bold';
}
// espesor ala operador superior
var esp_ala_ope_sup = medicion.EspesoresAlas.LadoOperadorSup;
espesorAlaOperadorSupCell = newRow.insertCell();
espesorAlaOperadorSupCell.textContent = esp_ala_ope_sup;
if (esp_ala_ope_sup > tolerancia.TMax || esp_ala_ope_sup < tolerancia.TMin) {
espesorAlaOperadorSupCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
espesorAlaOperadorSupCell.className = 'is-size-4 has-text-weight-bold';
}
// espesor ala operador inferior
var esp_ala_ope_inf = medicion.EspesoresAlas.LadoOperadorInf;
espesorAlaOperadorInfCell = newRow.insertCell();
espesorAlaOperadorInfCell.textContent = esp_ala_ope_inf;
if (esp_ala_ope_inf > tolerancia.TMax || esp_ala_ope_inf < tolerancia.TMin) {
espesorAlaOperadorInfCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
espesorAlaOperadorInfCell.className = 'is-size-4 has-text-weight-bold';
}
// anchura alas lado motor
var anch_alas_motor = medicion.AnchuraAlas.LadoMotor;
anchuraAlaLadoMotorCell = newRow.insertCell();
anchuraAlaLadoMotorCell.textContent = anch_alas_motor;
if (anch_alas_motor > tolerancia.BMax || anch_alas_motor < tolerancia.BMin) {
anchuraAlaLadoMotorCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
anchuraAlaLadoMotorCell.className = 'is-size-4 has-text-weight-bold';
}
// anchura alas lado operador
var anch_alas_operador = medicion.AnchuraAlas.LadoOperador;
anchuraAlaLadoOperadorCell = newRow.insertCell();
anchuraAlaLadoOperadorCell.textContent = anch_alas_operador;
if (anch_alas_operador > tolerancia.BMax || anch_alas_operador < tolerancia.BMin) {
anchuraAlaLadoOperadorCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
anchuraAlaLadoOperadorCell.className = 'is-size-4 has-text-weight-bold';
}
// asimetria del alma lado motor superior
asimetriaAlmaLadoMotorSupCell = newRow.insertCell();
asimetriaAlmaLadoMotorSupCell.textContent = medicion.AsimetriaAlma.LadoMotorSup;
asimetriaAlmaLadoMotorSupCell.className = 'is-size-4 has-text-weight-bold';
// asimetria del alma lado motor inferior
asimetriaAlmaLadoMotorInfCell = newRow.insertCell();
asimetriaAlmaLadoMotorInfCell.textContent = medicion.AsimetriaAlma.LadoMotorInf;
asimetriaAlmaLadoMotorInfCell.className = 'is-size-4 has-text-weight-bold';
//tolerancia asimetria recomendada
tolerancia.AsimRec = tolerancia.AsimMax - ((tolerancia.AsimMax) * .25)
// dif asimetria del alma lado motor sup - inferior
var dif_asi_alm_motor = (medicion.AsimetriaAlma.LadoMotorSup - medicion.AsimetriaAlma.LadoMotorInf).toFixed(2);
difAsimetriaAlmaLadoMotorCell = newRow.insertCell();
difAsimetriaAlmaLadoMotorCell.textContent = dif_asi_alm_motor;
if (dif_asi_alm_motor > tolerancia.AsimMax || dif_asi_alm_motor < tolerancia.AsimRec) {
difAsimetriaAlmaLadoMotorCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
difAsimetriaAlmaLadoMotorCell.className = 'is-size-4 has-text-weight-bold';
}
// asimetria del alma lado operador superior
asimetriaAlmaLadoOperadorSupCell = newRow.insertCell();
asimetriaAlmaLadoOperadorSupCell.textContent = medicion.AsimetriaAlma.LadoOperadorSup;
asimetriaAlmaLadoOperadorSupCell.className = 'is-size-4 has-text-weight-bold';
// asimetria del alma lado operador inferior
asimetriaAlmaLadoOperadorInfCell = newRow.insertCell();
asimetriaAlmaLadoOperadorInfCell.textContent = medicion.AsimetriaAlma.LadoOperadorInf;
asimetriaAlmaLadoOperadorInfCell.className = 'is-size-4 has-text-weight-bold';
// dif asimetria del alma lado operador sup - inferior
var dif_asi_alm_operador = (medicion.AsimetriaAlma.LadoOperadorSup - medicion.AsimetriaAlma.LadoOperadorInf).toFixed(2);
difAsimetriaAlmaLadoOperadorCell = newRow.insertCell();
difAsimetriaAlmaLadoOperadorCell.textContent = dif_asi_alm_operador;
if (dif_asi_alm_operador > tolerancia.AsimMax || dif_asi_alm_operador < tolerancia.AsimRec) {
difAsimetriaAlmaLadoOperadorCell.className = 'is-size-4 has-text-weight-bold has-background-danger has-text-white';
} else {
difAsimetriaAlmaLadoOperadorCell.className = 'is-size-4 has-text-weight-bold';
}
})
},
error: function (error) {
console.error("Error:", error)
}
});
}
function ProductionOrder(po) {
$.ajax({
url: "/po/get/" + po,
type: "GET",
success: function (data) {
let res = JSON.parse(data);
let poData = res.OrdenFabricacion;
$("#calidad").val(poData.SteelGrad);
},
error: function (error) {
console.error('Error:', error);
}
});
}
function GuardarMedicion() {
// form data
const formData = $("#medicion_form").serialize();
// form data como array
let data = $("#medicion_form").serializeArray();
// check form data
let allValuesPresent = checkAllValues(data);
// si todo ok
if (allValuesPresent) {
$.ajax({
url: "/medicion/create",
type: "POST",
data: formData,
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
success: function (data) {
alert("medición enviada correctamente!");
let po = localStorage.getItem('production_order');
// mediciones para la po
ObtenerMediciones(po);
},
error: function (error) {
console.error('Error:', error);
}
});
} else {
alert("se deben rellenar todos los campos");
}
function checkAllValues(data) {
var valuesPresent = true;
data.forEach(function (item) {
if (item.value.trim() === '' && item.name !== 'observaciones') {
valuesPresent = false;
return false;
}
console.log(item);
});
return valuesPresent;
}
return false;
}

97
assets/js/reporting.js Normal file
View File

@ -0,0 +1,97 @@
$(document).ready(function () {
// carga las fechas por defecto
CargaFechas();
});
function Report() {
// form data
const formData = $("#report_form").serialize();
$.ajax({
url: "/report/get",
type: "POST",
data: formData,
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
xhrFields: {
// make sure the response knows we're expecting a binary type in return.
// this is important, without it the excel file is marked corrupted.
responseType: 'arraybuffer'
}
}).done(function (data, status, xmlHeaderRequest) {
var downloadLink = document.createElement('a');
var blob = new Blob([data],
{
type: xmlHeaderRequest.getResponseHeader('Content-Type')
});
var url = window.URL || window.webkitURL;
var downloadUrl = url.createObjectURL(blob);
var fileName = 'mediciones' + '.xls';
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, fileName);
} else {
if (fileName) {
if (typeof downloadLink.download === 'undefined') {
window.location = downloadUrl;
} else {
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
url.revokeObjectURL(downloadUrl);
},
100);
}
});
}
function CargaFechas() {
// Calcula la fecha del día actual a las 6:00:00 de la mañana
var today = new Date();
today.setHours(6);
today.setMinutes(0);
today.setSeconds(0);
var dateTime1 = today;
// Calcula la fecha del día anterior a las 6:00:00 de la mañana
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
yesterday.setHours(6);
yesterday.setMinutes(0);
yesterday.setSeconds(0);
var dateTime2 = yesterday;
// Selecciona los campos input de tipo datetime-local
var dateTimeInput1 = $("#fecha-inicio");
var dateTimeInput2 = $("#fecha-final");
// Rellena el primer campo con la fecha del día actual a las 6:00:00 de la mañana
dateTimeInput2.val(dateTime1.toISOString().split("T")[0] + "T" + dateTime1.toTimeString().split(" ")[0]);
// Rellena el segundo campo con la fecha del día anterior a las 6:00:00 de la mañana
dateTimeInput1.val(dateTime2.toISOString().split("T")[0] + "T" + dateTime2.toTimeString().split(" ")[0]);
}

BIN
bin/myapp Executable file

Binary file not shown.

28
celsa2048.crt Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIE0zCCA7ugAwIBAgIJANu+mC2Jt3uTMA0GCSqGSIb3DQEBCwUAMIGhMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2Ux
FTATBgNVBAoTDFpzY2FsZXIgSW5jLjEVMBMGA1UECxMMWnNjYWxlciBJbmMuMRgw
FgYDVQQDEw9ac2NhbGVyIFJvb3QgQ0ExIjAgBgkqhkiG9w0BCQEWE3N1cHBvcnRA
enNjYWxlci5jb20wHhcNMTQxMjE5MDAyNzU1WhcNNDIwNTA2MDAyNzU1WjCBoTEL
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcTCFNhbiBK
b3NlMRUwEwYDVQQKEwxac2NhbGVyIEluYy4xFTATBgNVBAsTDFpzY2FsZXIgSW5j
LjEYMBYGA1UEAxMPWnNjYWxlciBSb290IENBMSIwIAYJKoZIhvcNAQkBFhNzdXBw
b3J0QHpzY2FsZXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
qT7STSxZRTgEFFf6doHajSc1vk5jmzmM6BWuOo044EsaTc9eVEV/HjH/1DWzZtcr
fTj+ni205apMTlKBW3UYR+lyLHQ9FoZiDXYXK8poKSV5+Tm0Vls/5Kb8mkhVVqv7
LgYEmvEY7HPY+i1nEGZCa46ZXCOohJ0mBEtB9JVlpDIO+nN0hUMAYYdZ1KZWCMNf
5J/aTZiShsorN2A38iSOhdd+mcRM4iNL3gsLu99XhKnRqKoHeH83lVdfu1XBeoQz
z5V6gA3kbRvhDwoIlTBeMa5l4yRdJAfdpkbFzqiwSgNdhbxTHnYYorDzKfr2rEFM
dsMU0DHdeAZf711+1CunuQIDAQABo4IBCjCCAQYwHQYDVR0OBBYEFLm33UrNww4M
hp1d3+wcBGnFTpjfMIHWBgNVHSMEgc4wgcuAFLm33UrNww4Mhp1d3+wcBGnFTpjf
oYGnpIGkMIGhMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8G
A1UEBxMIU2FuIEpvc2UxFTATBgNVBAoTDFpzY2FsZXIgSW5jLjEVMBMGA1UECxMM
WnNjYWxlciBJbmMuMRgwFgYDVQQDEw9ac2NhbGVyIFJvb3QgQ0ExIjAgBgkqhkiG
9w0BCQEWE3N1cHBvcnRAenNjYWxlci5jb22CCQDbvpgtibd7kzAMBgNVHRMEBTAD
AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAw0NdJh8w3NsJu4KHuVZUrmZgIohnTm0j+
RTmYQ9IKA/pvxAcA6K1i/LO+Bt+tCX+C0yxqB8qzuo+4vAzoY5JEBhyhBhf1uK+P
/WVWFZN/+hTgpSbZgzUEnWQG2gOVd24msex+0Sr7hyr9vn6OueH+jj+vCMiAm5+u
kd7lLvJsBu3AO3jGWVLyPkS3i6Gf+rwAp1OsRrv3WnbkYcFf9xjuaf4z0hRCrLN2
xFNjavxrHmsH8jPHVvgc1VD0Opja0l/BRVauTrUaoW6tE+wFG5rEcPGS80jjHK4S
pB5iDj2mUZH1T8lzYtuZy0ZPirxmtsk3135+CKNa2OCAhhFjE0xd
-----END CERTIFICATE-----

42
docker/Dockerfile Normal file
View File

@ -0,0 +1,42 @@
# Etapa de compilación
FROM golang:1.22-bookworm AS builder
ENV TZ=Europe/Madrid
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ADD celsa2048.crt /usr/local/share/ca-certificates/celsa2048.crt
RUN chmod 644 /usr/local/share/ca-certificates/celsa2048.crt
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates
RUN update-ca-certificates
WORKDIR /app
COPY . .
RUN go get -d -v ./...
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod=mod -ldflags "-s -w" -o myapp main.go
# Etapa de producción
FROM debian:stable
ENV TZ=Europe/Madrid
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ADD celsa2048.crt /usr/local/share/ca-certificates/celsa2048.crt
RUN chmod 644 /usr/local/share/ca-certificates/celsa2048.crt
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates
RUN update-ca-certificates
WORKDIR /root/
COPY --from=builder /app/myapp .
COPY templates/ /root/templates
COPY assets/ /root/assets
COPY mediciones.xlsx /root
CMD ["./myapp"]

28
go.mod Normal file
View File

@ -0,0 +1,28 @@
module git.espin.casa/albert/cml04-mediciones
go 1.22.1
require (
git.espin.casa/albert/logger v0.0.0-20240312060442-59b35e5c6996
github.com/julienschmidt/httprouter v1.3.0
)
require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.3 // indirect
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
require (
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/xuri/excelize/v2 v2.8.1
golang.org/x/sys v0.17.0 // indirect
gorm.io/gorm v1.25.10
)

49
go.sum Normal file
View File

@ -0,0 +1,49 @@
git.espin.casa/albert/logger v0.0.0-20240312060442-59b35e5c6996 h1:gOY7u2z9gMOdp0Q1Rod9XvoM0gL84SBXR7n/VxrgvtE=
git.espin.casa/albert/logger v0.0.0-20240312060442-59b35e5c6996/go.mod h1:dacFMi82f5ysDOaJQm0QmQaJZ7mwGFiayJ2iS+JKAfQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=

74
internal/app/app.go Normal file
View File

@ -0,0 +1,74 @@
package app
import (
"flag"
"net/http"
"os"
"os/signal"
"syscall"
"git.espin.casa/albert/cml04-mediciones/internal/client"
"git.espin.casa/albert/cml04-mediciones/internal/routes"
"git.espin.casa/albert/logger"
"github.com/julienschmidt/httprouter"
)
func Run() error {
// setup flags
httpAddr := flag.String("bind-addr", "0.0.0.0:9100", "HTTP server address")
apiAddr := flag.String("api-addr", "mediciones-service", "REST API server address")
apiPort := flag.Int("api-port", 3000, "REST API server port")
//apiAddr := flag.String("api-addr", "10.1.152.13", "REST API server address")
//apiPort := flag.Int("api-port", 9210, "REST API server port")
logLevel := flag.String("level", "debug", "Log level")
flag.Parse()
// setup logger
log := logger.New(os.Stdout, *logLevel)
// create router
router := httprouter.New()
// create api client
client := client.NewClient(&client.ClientConfig{
Host: *apiAddr,
Port: *apiPort,
Base: "api/v1",
})
// create routes
routes.CreateRoutes(router, client)
// serve static files
router.ServeFiles("/assets/*filepath", http.Dir("assets"))
// start the http server
go func() {
http.ListenAndServe(*httpAddr, router)
}()
// info banner
log.Info("started cml04-mediciones service", logger.LogFields{
"http_bind_address": *httpAddr,
"api_address": *apiAddr,
"api_port": *apiPort,
"log_level": *logLevel,
})
// wait signal to finish
signal := WaitSignal()
log.Info("signal received", logger.LogFields{
"signal": signal,
})
return nil
}
// WaitSignal catching exit signal
func WaitSignal() os.Signal {
ch := make(chan os.Signal, 2)
signal.Notify(
ch,
syscall.SIGINT,
syscall.SIGQUIT,
syscall.SIGTERM,
)
for {
sig := <-ch
switch sig {
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM:
return sig
}
}
}

199
internal/client/client.go Normal file
View File

@ -0,0 +1,199 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"git.espin.casa/albert/cml04-mediciones/internal/types"
)
type IMediciones interface {
// production orders from SAP
GetProductionOrder(ctx context.Context, req types.GetProductionOrderReq) (res types.GetProductionOrderRes, err error)
GetProductionOrders(ctx context.Context, req types.GetProductionOrdersReq) (res types.GetProductionOrdersRes, err error)
// mediciones
GetMedicion(ctx context.Context, req types.GetMedicionReq) (res types.GetMedicionRes, err error)
GetMediciones(ctx context.Context, req types.GetMedicionesReq) (res types.GetMedicionesRes, err error)
PostMediciones(ctx context.Context, req types.PostMedicionesReq) (res types.PostMedicionesRes, err error)
// ususarios
GetUsuario(ctx context.Context, req types.GetUsuarioReq) (res types.GetUsuarioRes, err error)
CreateUsuario(ctx context.Context, req types.CreateUsuarioReq) (res types.CreateUsuarioRes, err error)
ValidarUsuario(ctx context.Context, req types.ValidarUsuarioReq) (res types.ValidarUsuarioRes, err error)
// tolerancias
GetTolerancia(ctx context.Context, req types.GetToleranciaReq) (res types.GetToleranciaRes, err error)
// datos excel
GetExcelData(ctx context.Context, req types.GetExcelReq) (res types.GetExcelRes, err error)
}
type client struct {
url string
}
// GetExcelData implements IMediciones.
func (c client) GetExcelData(ctx context.Context, req types.GetExcelReq) (res types.GetExcelRes, err error) {
// encode request
data, err := json.Marshal(req)
if err != nil {
return types.GetExcelRes{}, err
}
resp, err := http.Post(c.url+"/excel/get", "application/json", bytes.NewBuffer(data))
if err != nil {
return types.GetExcelRes{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return types.GetExcelRes{}, err
}
if err := json.Unmarshal(body, &res); err != nil {
return types.GetExcelRes{}, err
}
return
}
// GetTolerancia implements IMediciones.
func (c client) GetTolerancia(ctx context.Context, req types.GetToleranciaReq) (res types.GetToleranciaRes, err error) {
// encode request
data, err := json.Marshal(req)
if err != nil {
return types.GetToleranciaRes{}, err
}
resp, err := http.Post(c.url+"/tolerance", "application/json", bytes.NewBuffer(data))
if err != nil {
return types.GetToleranciaRes{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return types.GetToleranciaRes{}, err
}
if err := json.Unmarshal(body, &res); err != nil {
return types.GetToleranciaRes{}, err
}
return
}
// CreateUsuario implements IMediciones.
func (c client) CreateUsuario(ctx context.Context, req types.CreateUsuarioReq) (types.CreateUsuarioRes, error) {
panic("unimplemented")
}
// GetMedicion implements IMediciones.
func (c client) GetMedicion(ctx context.Context, req types.GetMedicionReq) (types.GetMedicionRes, error) {
panic("unimplemented")
}
// GetMediciones implements IMediciones.
func (c client) GetMediciones(ctx context.Context, req types.GetMedicionesReq) (res types.GetMedicionesRes, err error) {
// encode request
data, err := json.Marshal(req)
if err != nil {
return types.GetMedicionesRes{}, err
}
resp, err := http.Post(c.url+"/mediciones", "application/json", bytes.NewBuffer(data))
if err != nil {
return types.GetMedicionesRes{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return types.GetMedicionesRes{}, err
}
if err := json.Unmarshal(body, &res); err != nil {
return types.GetMedicionesRes{}, err
}
return
}
// GetProductionOrder implements IMediciones.
func (c client) GetProductionOrder(ctx context.Context, req types.GetProductionOrderReq) (res types.GetProductionOrderRes, err error) {
data, err := json.Marshal(req)
if err != nil {
return types.GetProductionOrderRes{}, err
}
resp, err := http.Post(c.url+"/po", "application/json", bytes.NewBuffer(data))
if err != nil {
return types.GetProductionOrderRes{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return types.GetProductionOrderRes{}, err
}
if err := json.Unmarshal(body, &res); err != nil {
return types.GetProductionOrderRes{}, err
}
return
}
// GetProductionOrders implements IMediciones.
func (c client) GetProductionOrders(ctx context.Context, req types.GetProductionOrdersReq) (res types.GetProductionOrdersRes, err error) {
// encode request
data, err := json.Marshal(req)
if err != nil {
return types.GetProductionOrdersRes{}, err
}
resp, err := http.Post(c.url+"/pos", "application/json", bytes.NewBuffer(data))
if err != nil {
return types.GetProductionOrdersRes{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return types.GetProductionOrdersRes{}, err
}
if err := json.Unmarshal(body, &res); err != nil {
return types.GetProductionOrdersRes{}, err
}
return
}
// GetUsuario implements IMediciones.
func (c client) GetUsuario(ctx context.Context, req types.GetUsuarioReq) (res types.GetUsuarioRes, err error) {
panic("unimplemented")
}
// PostMediciones implements IMediciones.
func (c client) PostMediciones(ctx context.Context, req types.PostMedicionesReq) (res types.PostMedicionesRes, err error) {
// encode request
data, err := json.Marshal(req)
if err != nil {
return types.PostMedicionesRes{}, err
}
resp, err := http.Post(c.url+"/medicion/create", "application/json", bytes.NewBuffer(data))
if err != nil {
return types.PostMedicionesRes{}, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return types.PostMedicionesRes{}, err
}
if err := json.Unmarshal(body, &res); err != nil {
return types.PostMedicionesRes{}, err
}
return
}
// ValidarUsuario implements IMediciones.
func (c client) ValidarUsuario(ctx context.Context, req types.ValidarUsuarioReq) (types.ValidarUsuarioRes, error) {
panic("unimplemented")
}
type ClientConfig struct {
Host string
Port int
Base string
}
func NewClient(conf *ClientConfig) IMediciones {
url := fmt.Sprintf("http://%s:%d/%s", conf.Host, conf.Port, conf.Base)
return client{
url: url,
}
}

View File

@ -0,0 +1,20 @@
package handlers
import (
"html/template"
"net/http"
"git.espin.casa/albert/cml04-mediciones/internal/client"
"github.com/julienschmidt/httprouter"
)
func IndexHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
t, _ := template.ParseFiles("templates/index.html")
err := t.Execute(w, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}

View File

@ -0,0 +1,162 @@
package handlers
import (
"encoding/json"
"fmt"
"html/template"
"io"
"net/http"
"strconv"
"time"
"git.espin.casa/albert/cml04-mediciones/internal/client"
"git.espin.casa/albert/cml04-mediciones/internal/types"
"github.com/julienschmidt/httprouter"
)
func MedicionesViewHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
t, _ := template.ParseFiles("templates/mediciones.html")
err := t.Execute(w, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}
func MedicionCreateHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// parse form values
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// get form values
turno := r.FormValue("turno")
// masa unitaria
peso, _ := strconv.ParseFloat(r.FormValue("kg-muestra"), 64)
long, _ := strconv.ParseFloat(r.FormValue("long-muestra"), 64)
gmm, _ := strconv.ParseFloat(r.FormValue("gmm-muestra"), 64)
// altura perfil
alturaPerfil, _ := strconv.ParseFloat(r.FormValue("h"), 64)
// espesor alma
espesorAlma, _ := strconv.ParseFloat(r.FormValue("s"), 64)
// espesores alas
espesorAlaT1, _ := strconv.ParseFloat(r.FormValue("t1"), 64)
espesorAlaT2, _ := strconv.ParseFloat(r.FormValue("t2"), 64)
espesorAlaT3, _ := strconv.ParseFloat(r.FormValue("t3"), 64)
espesorAlaT4, _ := strconv.ParseFloat(r.FormValue("t4"), 64)
// anchuras alas
anchoAlaB1, _ := strconv.ParseFloat(r.FormValue("b1"), 64)
anchoAlaB2, _ := strconv.ParseFloat(r.FormValue("b2"), 64)
// asimetrias
asimetriaE1, _ := strconv.ParseFloat(r.FormValue("e1"), 64)
asimetriaE2, _ := strconv.ParseFloat(r.FormValue("e2"), 64)
asimetriaE3, _ := strconv.ParseFloat(r.FormValue("e3"), 64)
asimetriaE4, _ := strconv.ParseFloat(r.FormValue("e4"), 64)
// orden fabricacion
ordenFabricacion, _ := strconv.ParseInt(r.FormValue("orden_fabricacion"), 10, 64)
// enraye
enraye := r.FormValue("enraye") == "on"
// numero de barra
numeroBarra, _ := strconv.ParseInt(r.FormValue("numero_barra"), 10, 64)
// id barra nivel 3
idBarraNivel3 := fmt.Sprintf("%010d%05d", ordenFabricacion, numeroBarra)
// tipo muestra
tipoMuestra, _ := strconv.ParseInt(r.FormValue("tipo_muestra"), 10, 64)
// marca CELSA
marcaCelsa := r.FormValue("marca") == "on"
// usuario
operador := r.FormValue("usuario")
// colada
colada := r.FormValue("colada")
// producto
producto := r.FormValue("producto")
// calidad
calidad := r.FormValue("calidad")
// observaciones
observaciones := r.FormValue("observaciones")
_, err := client.PostMediciones(r.Context(), types.PostMedicionesReq{
Sender: "mediciones-ui",
Medicion: &types.Mediciones{
MedicionID: 0,
POrderNo: int(ordenFabricacion),
Observaciones: observaciones,
Colada: colada,
MedicionTipo: types.MedicionTipo(tipoMuestra),
MasaUnitaria: types.MasaUnitaria{Longitud: long, Peso: peso, GramosMM: gmm},
AlturaPerfil: alturaPerfil,
EspesorAlma: espesorAlma,
EspesoresAlas: types.EspesoresAlas{LadoMotorSup: espesorAlaT4, LadoMotorInf: espesorAlaT3, LadoOperadorSup: espesorAlaT2, LadoOperadorInf: espesorAlaT1},
AnchuraAlas: types.AnchuraAlas{LadoMotor: anchoAlaB1, LadoOperador: anchoAlaB2},
AsimetriaAlma: types.AsimetriaAlma{LadoMotorSup: asimetriaE1, LadoMotorInf: asimetriaE2, LadoOperadorSup: asimetriaE3, LadoOperadorInf: asimetriaE4},
Firmada: false,
Operador: operador,
Enraye: enraye,
MarcaCelsa: marcaCelsa,
Turno: turno,
IDBarra: idBarraNivel3,
Producto: producto,
Calidad: calidad,
},
TimeStamp: time.Now().UTC().Format(time.RFC3339),
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
//http.Redirect(w, r, "/mediciones/view", http.StatusSeeOther)
}
}
func MedicionesGetHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// request data struct
type MedicionesRequestData struct {
ProductionOrder string `json:"production_order"`
}
// request data holder
req := &MedicionesRequestData{}
// read body request
data, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer r.Body.Close()
if err := json.Unmarshal(data, req); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// get po
po, err := strconv.Atoi(req.ProductionOrder)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// request mediciones by po
res, err := client.GetMediciones(r.Context(), types.GetMedicionesReq{
Sender: "mediciones-ui",
POrderNo: po,
TimeStamp: time.Now().UTC().Format(time.RFC3339),
})
// handle error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// encode response
resp, err := json.Marshal(&res)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// write header 200
w.WriteHeader(http.StatusOK)
// set header content type
w.Header().Set("Content-type", "application/json")
// write response
w.Write(resp)
}
}

71
internal/handlers/po.go Normal file
View File

@ -0,0 +1,71 @@
package handlers
import (
"encoding/json"
"net/http"
"strconv"
"time"
"git.espin.casa/albert/cml04-mediciones/internal/client"
"git.espin.casa/albert/cml04-mediciones/internal/types"
"github.com/julienschmidt/httprouter"
)
func OrdenesProduccionListHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res, err := client.GetProductionOrders(r.Context(), types.GetProductionOrdersReq{
Sender: "mediciones-ui",
Limit: 100,
TimeStamp: time.Now().UTC().Format(time.RFC3339),
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// encode response
resp, err := json.Marshal(&res)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// write header 200
w.WriteHeader(http.StatusOK)
// set header content type
w.Header().Set("Content-type", "application/json")
// write response
w.Write(resp)
}
}
func OrdenProduccionHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
// convert to int
po, err := strconv.Atoi(p.ByName("po"))
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
//
res, err := client.GetProductionOrder(r.Context(), types.GetProductionOrderReq{
Sender: "mediciones-ui",
PoNo: po,
TimeStamp: time.Now().UTC().Format(time.RFC3339),
})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// encode response
resp, err := json.Marshal(&res)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// write header 200
w.WriteHeader(http.StatusOK)
// set header content type
w.Header().Set("Content-type", "application/json")
// write response
w.Write(resp)
}
}

123
internal/handlers/report.go Normal file
View File

@ -0,0 +1,123 @@
package handlers
import (
"context"
"fmt"
"net/http"
"time"
"git.espin.casa/albert/cml04-mediciones/internal/client"
"git.espin.casa/albert/cml04-mediciones/internal/types"
"github.com/julienschmidt/httprouter"
"github.com/xuri/excelize/v2"
)
const (
ExcelFile = "mediciones.xlsx"
ExcelSheet = "Mediciones"
)
func CreateExcelSheet(ctx context.Context, mediciones []types.Mediciones) ([]byte, error) {
// open excel file
f, err := excelize.OpenFile(ExcelFile)
if err != nil {
return nil, err
}
defer f.Close()
// iterate over mediciones
for i, medicion := range mediciones {
f.SetCellValue(ExcelSheet, fmt.Sprintf("A%d", i+2), medicion.Producto)
f.SetCellValue(ExcelSheet, fmt.Sprintf("B%d", i+2), medicion.Calidad)
f.SetCellValue(ExcelSheet, fmt.Sprintf("C%d", i+2), medicion.Operador)
f.SetCellValue(ExcelSheet, fmt.Sprintf("D%d", i+2), medicion.CreatedAt.Format("02/01/2006"))
f.SetCellValue(ExcelSheet, fmt.Sprintf("E%d", i+2), medicion.CreatedAt.Format("15:04:05"))
f.SetCellValue(ExcelSheet, fmt.Sprintf("F%d", i+2), medicion.POrderNo)
f.SetCellValue(ExcelSheet, fmt.Sprintf("G%d", i+2), medicion.IDBarra)
f.SetCellValue(ExcelSheet, fmt.Sprintf("H%d", i+2), medicion.Colada)
f.SetCellValue(ExcelSheet, fmt.Sprintf("I%d", i+2), medicion.GetMedicionTipo())
f.SetCellValue(ExcelSheet, fmt.Sprintf("J%d", i+2), medicion.MasaUnitaria.Longitud)
f.SetCellValue(ExcelSheet, fmt.Sprintf("K%d", i+2), medicion.MasaUnitaria.Peso)
f.SetCellValue(ExcelSheet, fmt.Sprintf("L%d", i+2), medicion.MasaUnitaria.GramosMM)
f.SetCellValue(ExcelSheet, fmt.Sprintf("M%d", i+2), medicion.AlturaPerfil)
f.SetCellValue(ExcelSheet, fmt.Sprintf("N%d", i+2), medicion.EspesorAlma)
f.SetCellValue(ExcelSheet, fmt.Sprintf("O%d", i+2), medicion.EspesoresAlas.LadoMotorInf)
f.SetCellValue(ExcelSheet, fmt.Sprintf("P%d", i+2), medicion.EspesoresAlas.LadoMotorSup)
f.SetCellValue(ExcelSheet, fmt.Sprintf("Q%d", i+2), medicion.EspesoresAlas.LadoOperadorInf)
f.SetCellValue(ExcelSheet, fmt.Sprintf("R%d", i+2), medicion.EspesoresAlas.LadoOperadorSup)
f.SetCellValue(ExcelSheet, fmt.Sprintf("S%d", i+2), medicion.AnchuraAlas.LadoOperador)
f.SetCellValue(ExcelSheet, fmt.Sprintf("T%d", i+2), medicion.AnchuraAlas.LadoMotor)
f.SetCellValue(ExcelSheet, fmt.Sprintf("U%d", i+2), (medicion.AsimetriaAlma.LadoMotorSup - medicion.AsimetriaAlma.LadoMotorInf))
f.SetCellValue(ExcelSheet, fmt.Sprintf("V%d", i+2), (medicion.AsimetriaAlma.LadoOperadorSup - medicion.AsimetriaAlma.LadoOperadorInf))
f.SetCellValue(ExcelSheet, fmt.Sprintf("W%d", i+2), (medicion.Observaciones))
}
// write excel file to buffer
buffer, err := f.WriteToBuffer()
if err != nil {
return nil, err
}
// return
return buffer.Bytes(), nil
}
func ReportHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
// parse form values
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// get dates
fechaInicio := r.FormValue("fecha-inicio")
fechaFinal := r.FormValue("fecha-final")
// get product
producto := r.FormValue("producto")
// parse time strings
sInicio, err := time.Parse("2006-01-02T15:04", fechaInicio)
// handle error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// parse time strings
sFinal, err := time.Parse("2006-01-02T15:04", fechaFinal)
// handle error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// api request
request := types.GetExcelReq{
Sender: "mediciones-ui",
Product: producto,
StartTime: sInicio.Format("02/01/2006 15:04:05"),
EndTime: sFinal.Format("02/01/2006 15:04:05"),
TimeStamp: time.Now().UTC().Format(time.RFC3339),
}
// requesting
res, err := client.GetExcelData(
r.Context(),
request,
)
// handle error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// create excel file
data, err := CreateExcelSheet(r.Context(), res.Mediciones)
// handle error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
downloadName := time.Now().UTC().Format("mediciones-20060102150405.xlsx")
// set header content type
w.Header().Set("Content-type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
w.Header().Set("Content-Description", "File Transfer")
w.Header().Set("Content-Disposition", "attachment; filename="+downloadName)
// write header 200
w.WriteHeader(http.StatusOK)
// write response
w.Write(data)
}
}

View File

@ -0,0 +1,59 @@
package handlers
import (
"encoding/json"
"io"
"net/http"
"time"
"git.espin.casa/albert/cml04-mediciones/internal/client"
"git.espin.casa/albert/cml04-mediciones/internal/types"
"github.com/julienschmidt/httprouter"
)
func TolerancesGetHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// request data struct
type ToleranciaRequestData struct {
Medida string `json:"medida"`
}
// request data holder
req := &ToleranciaRequestData{}
// read body request
data, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer r.Body.Close()
if err := json.Unmarshal(data, req); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
medida := req.Medida
// request mediciones by po
res, err := client.GetTolerancia(r.Context(), types.GetToleranciaReq{
Sender: "mediciones-ui",
Medida: medida,
TimeStamp: time.Now().UTC().Format(time.RFC3339),
})
// handle error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// encode response
resp, err := json.Marshal(&res)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// write header 200
w.WriteHeader(http.StatusOK)
// set header content type
w.Header().Set("Content-type", "application/json")
// write response
w.Write(resp)
}
}

View File

@ -0,0 +1,20 @@
package handlers
import (
"html/template"
"net/http"
"git.espin.casa/albert/cml04-mediciones/internal/client"
"github.com/julienschmidt/httprouter"
)
func VistasGetHandler(client client.IMediciones) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
t, _ := template.ParseFiles("templates/view.html")
err := t.Execute(w, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}

19
internal/routes/routes.go Normal file
View File

@ -0,0 +1,19 @@
package routes
import (
"git.espin.casa/albert/cml04-mediciones/internal/client"
"git.espin.casa/albert/cml04-mediciones/internal/handlers"
"github.com/julienschmidt/httprouter"
)
func CreateRoutes(r *httprouter.Router, client client.IMediciones) {
r.GET("/", handlers.IndexHandler(client))
r.GET("/mediciones/view", handlers.MedicionesViewHandler(client))
r.POST("/medicion/create", handlers.MedicionCreateHandler(client))
r.POST("/mediciones/get", handlers.MedicionesGetHandler(client))
r.POST("/tolerance/get", handlers.TolerancesGetHandler(client))
r.GET("/vista/get", handlers.VistasGetHandler(client))
r.GET("/po/list", handlers.OrdenesProduccionListHandler(client))
r.GET("/po/get/:po", handlers.OrdenProduccionHandler(client))
r.POST("/report/get", handlers.ReportHandler(client))
}

14
internal/types/excel.go Normal file
View File

@ -0,0 +1,14 @@
package types
type GetExcelReq struct {
Sender string
Product string
StartTime string
EndTime string
TimeStamp string
}
type GetExcelRes struct {
Mediciones []Mediciones
TimeStamp string
}

9
internal/types/firmas.go Normal file
View File

@ -0,0 +1,9 @@
package types
import "gorm.io/gorm"
type Firmas struct {
gorm.Model
Responsable string
POrderNo int
}

View File

@ -0,0 +1,119 @@
package types
import (
"time"
"gorm.io/gorm"
)
type MedicionTipo uint8
const (
MedicionMedio MedicionTipo = iota + 1
MedicionCola
)
var (
MedicionTipoString = map[MedicionTipo]string{
MedicionMedio: "MEDIO",
MedicionCola: "COLA",
}
)
type MasaUnitaria struct {
Longitud float64
Peso float64
GramosMM float64
}
type EspesoresAlas struct {
LadoMotorSup float64
LadoMotorInf float64
LadoOperadorSup float64
LadoOperadorInf float64
}
type AsimetriaAlma struct {
LadoMotorSup float64
LadoMotorInf float64
LadoOperadorSup float64
LadoOperadorInf float64
}
type AnchuraAlas struct {
LadoMotor float64
LadoOperador float64
}
type Mediciones struct {
MedicionID uint64 `gorm:"primaryKey;autoIncrement:true"`
POrderNo int `gorm:"index"`
Observaciones string
Colada string
MedicionTipo MedicionTipo
MasaUnitaria MasaUnitaria `gorm:"embedded;embeddedPrefix:masa_unitaria_"`
AlturaPerfil float64
EspesorAlma float64
EspesoresAlas EspesoresAlas `gorm:"embedded;embeddedPrefix:espesor_alas_"`
AnchuraAlas AnchuraAlas `gorm:"embedded;embeddedPrefix:anchura_alas_"`
AsimetriaAlma AsimetriaAlma `gorm:"embedded;embeddedPrefix:asimetria_alma_"`
Firmada bool
Operador string
Enraye bool
MarcaCelsa bool
Turno string
IDBarra string
Producto string
Calidad string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
func (m *Mediciones) GetMedicionTipo() string {
return MedicionTipoString[m.MedicionTipo]
}
func (m *Mediciones) BeforeCreate(tx *gorm.DB) (err error) {
m.CreatedAt = time.Now()
m.UpdatedAt = time.Now()
return
}
func (m *Mediciones) BeforeUpdate(tx *gorm.DB) (err error) {
m.UpdatedAt = time.Now()
return
}
type GetMedicionReq struct {
Sender string
MedicionID uint64
TimeStamp string
}
type GetMedicionRes struct {
Medicion *Mediciones
TimeStamp string
}
type GetMedicionesReq struct {
Sender string
POrderNo int
TimeStamp string
}
type GetMedicionesRes struct {
Mediciones []Mediciones
TimeStamp string
}
type PostMedicionesReq struct {
Sender string
Medicion *Mediciones
TimeStamp string
}
type PostMedicionesRes struct {
Message string
TimeStamp string
}

171
internal/types/ordenes.go Normal file
View File

@ -0,0 +1,171 @@
package types
import (
"time"
"gorm.io/gorm"
)
type OrdenFabricacion struct {
Inst string
DateTime string
POrderNo int `gorm:"primaryKey"`
SchedulNo int
SeqNumber int
PptimeWfc string
PptimeMsc string
SteelGrad string
ITemp string
IHeight string
IWidth string
ISection string
HeatingSt int
FTarTemp string
FSection string
FSectType string
TotWeight string
TBeamBla int
TCustOrd int
TestLen int
PostFlag string
ModuloX string
OvWTolU string
OvWTolL string
OvHTolU string
OvHTolL string
WeTTolU string
WeTTolL string
WeHTolU string
WeHTolL string
FlWDsU string
FlWDsL string
FlWOsU string
FlWOsL string
WeMetTU string
WeMetTL string
WeCenTol string
WeSquTol string
FlParTol string
BdRollID string
UrRollID string
EdRollID string
UfRollID string
SmRollID string
Grupo6 string
StName string
StWeighM string
StLen1 string
StLen2 string
StLen3 string
StLen4 string
StLen5 string
StLen6 string
StLen7 string
StLen8 string
StLen9 string
StLen10 string
StLen11 string
StLen12 string
Marfab int
Sortb string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
func (o *OrdenFabricacion) BeforeCreate(tx *gorm.DB) (err error) {
o.CreatedAt = time.Now()
o.UpdatedAt = time.Now()
return
}
func (o *OrdenFabricacion) BeforeUpdate(tx *gorm.DB) (err error) {
o.UpdatedAt = time.Now()
return
}
type T10001 struct {
Inst string `json:"INST"`
DateTime string `json:"DATE_TIME"`
POrderNo int `json:"P_ORDER_NO"`
SchedulNo int `json:"SCHEDUL_NO"`
SeqNumber int `json:"SEQ_NUMBER"`
PptimeWfc string `json:"PPTIME_WFC"`
PptimeMsc string `json:"PPTIME_MSC"`
SteelGrad string `json:"STEEL_GRAD"`
ITemp string `json:"I_TEMP"`
IHeight string `json:"I_HEIGHT"`
IWidth string `json:"I_WIDTH"`
ISection string `json:"I_SECTION"`
HeatingSt int `json:"HEATING_ST"`
FTarTemp string `json:"F_TAR_TEMP"`
FSection string `json:"F_SECTION"`
FSectType string `json:"F_SECT_TYPE"`
TotWeight string `json:"TOT_WEIGHT"`
TBeamBla int `json:"T_BEAM_BLA"`
TCustOrd int `json:"T_CUST_ORD"`
TestLen int `json:"TEST_LEN"`
PostFlag string `json:"POST_FLAG"`
ModuloX string `json:"MODULO_X"`
OvWTolU string `json:"OV_W_TOL_U"`
OvWTolL string `json:"OV_W_TOL_L"`
OvHTolU string `json:"OV_H_TOL_U"`
OvHTolL string `json:"OV_H_TOL_L"`
WeTTolU string `json:"WE_T_TOL_U"`
WeTTolL string `json:"WE_T_TOL_L"`
WeHTolU string `json:"WE_H_TOL_U"`
WeHTolL string `json:"WE_H_TOL_L"`
FlWDsU string `json:"FL_W_DS_U"`
FlWDsL string `json:"FL_W_DS_L"`
FlWOsU string `json:"FL_W_OS_U"`
FlWOsL string `json:"FL_W_OS_L"`
WeMetTU string `json:"WE_MET_T_U"`
WeMetTL string `json:"WE_MET_T_L"`
WeCenTol string `json:"WE_CEN_TOL"`
WeSquTol string `json:"WE_SQU_TOL"`
FlParTol string `json:"FL_PAR_TOL"`
BdRollID string `json:"BD_ROLL_ID"`
UrRollID string `json:"UR_ROLL_ID"`
EdRollID string `json:"ED_ROLL_ID"`
UfRollID string `json:"UF_ROLL_ID"`
SmRollID string `json:"SM_ROLL_ID"`
Grupo6 string `json:"GRUPO6"`
StName string `json:"ST_NAME"`
StWeighM string `json:"ST_WEIGH_M"`
StLen1 string `json:"ST_LEN_1"`
StLen2 string `json:"ST_LEN_2"`
StLen3 string `json:"ST_LEN_3"`
StLen4 string `json:"ST_LEN_4"`
StLen5 string `json:"ST_LEN_5"`
StLen6 string `json:"ST_LEN_6"`
StLen7 string `json:"ST_LEN_7"`
StLen8 string `json:"ST_LEN_8"`
StLen9 string `json:"ST_LEN_9"`
StLen10 string `json:"ST_LEN_10"`
StLen11 string `json:"ST_LEN_11"`
StLen12 string `json:"ST_LEN_12"`
Marfab int `json:"MARFAB"`
Sortb string `json:"SORTB"`
}
type GetProductionOrderReq struct {
Sender string
PoNo int
TimeStamp string
}
type GetProductionOrderRes struct {
OrdenFabricacion *OrdenFabricacion
TimeStamp string
}
type GetProductionOrdersReq struct {
Sender string
Limit int
TimeStamp string
}
type GetProductionOrdersRes struct {
OrdenFabricacion []OrdenFabricacion
TimeStamp string
}

View File

@ -0,0 +1,69 @@
package types
import (
"time"
"gorm.io/gorm"
)
type Tolerancia struct {
Medida string `gorm:"primaryKey"`
MMax float64
MMin float64
HMax float64
HMin float64
SMax float64
SMin float64
TMax float64
TMin float64
BMax float64
BMin float64
ParalMax float64
AsimMax float64
Curvatura float64
Escuadrado float64
Longitud float64
FlechaMax float64
FlechaLat float64
MNom float64
HNom float64
SNom float64
TNom float64
BNom float64
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
type GetToleranciaReq struct {
Sender string
Medida string
TimeStamp string
}
type GetToleranciaRes struct {
Tolerancia Tolerancia
TimeStamp string
}
type CreateToleranceReq struct {
Sender string
Tolerancia Tolerancia
TimeStamp string
}
type CreateToleranceRes struct {
Message string
TimeStamp string
}
func (t *Tolerancia) BeforeCreate(tx *gorm.DB) (err error) {
t.CreatedAt = time.Now()
t.UpdatedAt = time.Now()
return
}
func (t *Tolerancia) BeforeUpdate(tx *gorm.DB) (err error) {
t.UpdatedAt = time.Now()
return
}

View File

@ -0,0 +1,74 @@
package types
import (
"time"
"gorm.io/gorm"
)
type Rol uint8
const (
Admin Rol = iota + 1
Operador
JefeTurno
)
type Usuario struct {
Email string `gorm:"primaryKey"`
Password string
Enabled bool
Rol Rol
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
func (u *Usuario) TableName() string {
return "usuarios"
}
type GetUsuarioReq struct {
Sender string
Email string
TimeStamp string
}
type GetUsuarioRes struct {
Usuario *Usuario
TimeStamp string
}
type CreateUsuarioReq struct {
Sender string
Usuario *Usuario
TimeStamp string
}
type CreateUsuarioRes struct {
Message string
TimeStamp string
}
type ValidarUsuarioReq struct {
Sender string
Email string
Pass string
TimeStamp string
}
type ValidarUsuarioRes struct {
Message string
TimeStamp string
}
func (u *Usuario) BeforeCreate(tx *gorm.DB) (err error) {
u.CreatedAt = time.Now()
u.UpdatedAt = time.Now()
return
}
func (u *Usuario) BeforeUpdate(tx *gorm.DB) (err error) {
u.UpdatedAt = time.Now()
return
}

13
main.go Normal file
View File

@ -0,0 +1,13 @@
package main
import (
"log"
"git.espin.casa/albert/cml04-mediciones/internal/app"
)
func main() {
if err := app.Run(); err != nil {
log.Fatalf("start cml04 mediciones failed: %s", err.Error())
}
}

BIN
mediciones.xlsx Normal file

Binary file not shown.

111
templates/index.html Normal file

File diff suppressed because one or more lines are too long

565
templates/mediciones.html Normal file

File diff suppressed because one or more lines are too long

152
templates/view.html Normal file

File diff suppressed because one or more lines are too long