crear usuario externo
This commit is contained in:
418
Catalogos_Postales_Registro.sql
Normal file
418
Catalogos_Postales_Registro.sql
Normal file
@@ -0,0 +1,418 @@
|
||||
SET ANSI_NULLS ON;
|
||||
GO
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
GO
|
||||
SET XACT_ABORT ON;
|
||||
GO
|
||||
|
||||
/*
|
||||
Catálogos postales para el registro público.
|
||||
|
||||
Este script NO elimina, vacía ni recrea las tablas pobladas.
|
||||
Solamente agrega columnas/índices faltantes y crea o actualiza
|
||||
el procedimiento almacenado de consulta.
|
||||
*/
|
||||
|
||||
IF OBJECT_ID(N'dbo.Gral_SAT_CP', N'U') IS NULL
|
||||
THROW 51020, N'Falta la tabla poblada dbo.Gral_SAT_CP.', 1;
|
||||
IF OBJECT_ID(N'dbo.Gral_SAT_Municipio', N'U') IS NULL
|
||||
THROW 51021, N'Falta la tabla poblada dbo.Gral_SAT_Municipio.', 1;
|
||||
IF OBJECT_ID(N'dbo.Gral_SAT_Localidad', N'U') IS NULL
|
||||
THROW 51022, N'Falta la tabla poblada dbo.Gral_SAT_Localidad.', 1;
|
||||
IF OBJECT_ID(N'dbo.Gral_SAT_Colonia', N'U') IS NULL
|
||||
THROW 51023, N'Falta la tabla poblada dbo.Gral_SAT_Colonia.', 1;
|
||||
IF OBJECT_ID(N'dbo.Gral_SAT_Estado', N'U') IS NULL
|
||||
THROW 51024, N'Falta la tabla poblada dbo.Gral_SAT_Estado.', 1;
|
||||
IF OBJECT_ID(N'dbo.Gral_SAT_Pais', N'U') IS NULL
|
||||
THROW 51025, N'Falta la tabla poblada dbo.Gral_SAT_Pais.', 1;
|
||||
GO
|
||||
|
||||
/* Borrado lógico incremental para los catálogos utilizados. */
|
||||
DECLARE @Tablas TABLE ([Tabla] sysname NOT NULL PRIMARY KEY);
|
||||
INSERT INTO @Tablas ([Tabla])
|
||||
VALUES
|
||||
(N'Gral_SAT_CP'),
|
||||
(N'Gral_SAT_Municipio'),
|
||||
(N'Gral_SAT_Localidad'),
|
||||
(N'Gral_SAT_Colonia'),
|
||||
(N'Gral_SAT_Estado'),
|
||||
(N'Gral_SAT_Pais');
|
||||
|
||||
DECLARE @Tabla sysname;
|
||||
DECLARE @Sql nvarchar(max);
|
||||
DECLARE Catalogos CURSOR LOCAL FAST_FORWARD FOR SELECT [Tabla] FROM @Tablas ORDER BY [Tabla];
|
||||
|
||||
OPEN Catalogos;
|
||||
FETCH NEXT FROM Catalogos INTO @Tabla;
|
||||
|
||||
WHILE @@FETCH_STATUS = 0
|
||||
BEGIN
|
||||
IF COL_LENGTH(N'dbo.' + @Tabla, N'Borrado') IS NULL
|
||||
BEGIN
|
||||
SET @Sql = N'ALTER TABLE [dbo].' + QUOTENAME(@Tabla)
|
||||
+ N' ADD [Borrado] bit NOT NULL CONSTRAINT '
|
||||
+ QUOTENAME(N'DF_' + @Tabla + N'_Borrado')
|
||||
+ N' DEFAULT ((0)) WITH VALUES;';
|
||||
EXEC sys.sp_executesql @Sql;
|
||||
END;
|
||||
|
||||
IF COL_LENGTH(N'dbo.' + @Tabla, N'FechaBorrado') IS NULL
|
||||
BEGIN
|
||||
SET @Sql = N'ALTER TABLE [dbo].' + QUOTENAME(@Tabla)
|
||||
+ N' ADD [FechaBorrado] datetime2(0) NULL;';
|
||||
EXEC sys.sp_executesql @Sql;
|
||||
END;
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1
|
||||
FROM sys.check_constraints
|
||||
WHERE [parent_object_id] = OBJECT_ID(N'dbo.' + @Tabla)
|
||||
AND [name] = N'CK_' + @Tabla + N'_BorradoLogico'
|
||||
)
|
||||
BEGIN
|
||||
SET @Sql = N'ALTER TABLE [dbo].' + QUOTENAME(@Tabla)
|
||||
+ N' ADD CONSTRAINT ' + QUOTENAME(N'CK_' + @Tabla + N'_BorradoLogico')
|
||||
+ N' CHECK (([Borrado] = (0) AND [FechaBorrado] IS NULL)'
|
||||
+ N' OR ([Borrado] = (1) AND [FechaBorrado] IS NOT NULL));';
|
||||
EXEC sys.sp_executesql @Sql;
|
||||
END;
|
||||
|
||||
FETCH NEXT FROM Catalogos INTO @Tabla;
|
||||
END;
|
||||
|
||||
CLOSE Catalogos;
|
||||
DEALLOCATE Catalogos;
|
||||
GO
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1 FROM sys.indexes
|
||||
WHERE [object_id] = OBJECT_ID(N'dbo.Gral_SAT_CP')
|
||||
AND [name] = N'IX_Gral_SAT_CP_BusquedaRegistro'
|
||||
)
|
||||
CREATE NONCLUSTERED INDEX [IX_Gral_SAT_CP_BusquedaRegistro]
|
||||
ON [dbo].[Gral_SAT_CP] ([CP])
|
||||
INCLUDE ([CveCP], [ClaveSATEstado], [ClaveSATMunicipio], [ClaveSATLocalidad])
|
||||
WHERE [Borrado] = (0);
|
||||
GO
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1 FROM sys.indexes
|
||||
WHERE [object_id] = OBJECT_ID(N'dbo.Gral_SAT_Colonia')
|
||||
AND [name] = N'IX_Gral_SAT_Colonia_CP_Vigente'
|
||||
)
|
||||
CREATE NONCLUSTERED INDEX [IX_Gral_SAT_Colonia_CP_Vigente]
|
||||
ON [dbo].[Gral_SAT_Colonia] ([CP])
|
||||
INCLUDE ([CveColonia], [ClaveSATColonia], [NombreAsentamiento])
|
||||
WHERE [Borrado] = (0);
|
||||
GO
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1 FROM sys.indexes
|
||||
WHERE [object_id] = OBJECT_ID(N'dbo.Gral_SAT_Municipio')
|
||||
AND [name] = N'IX_Gral_SAT_Municipio_Claves_Vigente'
|
||||
)
|
||||
CREATE NONCLUSTERED INDEX [IX_Gral_SAT_Municipio_Claves_Vigente]
|
||||
ON [dbo].[Gral_SAT_Municipio] ([ClaveSATEstado], [ClaveSATMunicipio])
|
||||
INCLUDE ([CveMunicipio], [Descripcion])
|
||||
WHERE [Borrado] = (0);
|
||||
GO
|
||||
|
||||
IF NOT EXISTS
|
||||
(
|
||||
SELECT 1 FROM sys.indexes
|
||||
WHERE [object_id] = OBJECT_ID(N'dbo.Gral_SAT_Localidad')
|
||||
AND [name] = N'IX_Gral_SAT_Localidad_Claves_Vigente'
|
||||
)
|
||||
CREATE NONCLUSTERED INDEX [IX_Gral_SAT_Localidad_Claves_Vigente]
|
||||
ON [dbo].[Gral_SAT_Localidad] ([ClaveSATEstado], [ClaveSATLocalidad])
|
||||
INCLUDE ([CveLocalidad], [NombreLocalidad])
|
||||
WHERE [Borrado] = (0);
|
||||
GO
|
||||
|
||||
/* Claves normalizadas utilizadas por el registro. */
|
||||
IF OBJECT_ID(N'dbo.Clientes', N'U') IS NULL
|
||||
THROW 51026, N'Falta la tabla dbo.Clientes.', 1;
|
||||
|
||||
IF COL_LENGTH(N'dbo.Clientes', N'CveLocalidad') IS NULL
|
||||
ALTER TABLE [dbo].[Clientes] ADD [CveLocalidad] int NULL;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Pais', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Pais] P ON P.[CvePais]=C.[CvePais] WHERE C.[CvePais] IS NOT NULL AND P.[CvePais] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Pais] FOREIGN KEY ([CvePais]) REFERENCES [dbo].[Gral_SAT_Pais] ([CvePais]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Estado_Normalizado', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Estado] E ON E.[CveEstado]=C.[CveEstado] WHERE C.[CveEstado] IS NOT NULL AND E.[CveEstado] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Estado_Normalizado] FOREIGN KEY ([CveEstado]) REFERENCES [dbo].[Gral_SAT_Estado] ([CveEstado]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Municipio', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Municipio] M ON M.[CveMunicipio]=C.[CveMunicipio] WHERE C.[CveMunicipio] IS NOT NULL AND M.[CveMunicipio] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Municipio] FOREIGN KEY ([CveMunicipio]) REFERENCES [dbo].[Gral_SAT_Municipio] ([CveMunicipio]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Localidad', N'F') IS NULL
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Localidad] FOREIGN KEY ([CveLocalidad]) REFERENCES [dbo].[Gral_SAT_Localidad] ([CveLocalidad]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Colonia', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Colonia] CO ON CO.[CveColonia]=C.[CveColonia] WHERE C.[CveColonia] IS NOT NULL AND CO.[CveColonia] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Colonia] FOREIGN KEY ([CveColonia]) REFERENCES [dbo].[Gral_SAT_Colonia] ([CveColonia]);
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[PA_Gral_CodigoPostalGet]
|
||||
@CP varchar(5),
|
||||
@CveUsuarioEjecuta int,
|
||||
@ErrorMostrar varchar(max) OUTPUT,
|
||||
@ErrorTipo int OUTPUT,
|
||||
@Return bit OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0;
|
||||
SET @CP = LTRIM(RTRIM(@CP));
|
||||
|
||||
BEGIN TRY
|
||||
IF LEN(@CP) <> 5 OR @CP LIKE '%[^0-9]%'
|
||||
BEGIN
|
||||
SET @ErrorMostrar = 'El código postal debe contener exactamente 5 dígitos.';
|
||||
SET @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
DECLARE
|
||||
@CvePais int,
|
||||
@Pais varchar(100),
|
||||
@CveEstado int,
|
||||
@Estado varchar(50),
|
||||
@CveMunicipio int,
|
||||
@Municipio varchar(100),
|
||||
@CveLocalidad int,
|
||||
@Localidad varchar(100);
|
||||
|
||||
SELECT TOP (1)
|
||||
@CvePais = P.[CvePais],
|
||||
@Pais = P.[Descripcion],
|
||||
@CveEstado = E.[CveEstado],
|
||||
@Estado = E.[NombreEstado],
|
||||
@CveMunicipio = M.[CveMunicipio],
|
||||
@Municipio = M.[Descripcion],
|
||||
@CveLocalidad = L.[CveLocalidad],
|
||||
@Localidad = L.[NombreLocalidad]
|
||||
FROM [dbo].[Gral_SAT_CP] AS CP
|
||||
INNER JOIN [dbo].[Gral_SAT_Estado] AS E
|
||||
ON E.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND E.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Pais] AS P
|
||||
ON P.[ClaveSATPais] = E.[ClaveSATPais]
|
||||
AND P.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Municipio] AS M
|
||||
ON M.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND M.[ClaveSATMunicipio] = CP.[ClaveSATMunicipio]
|
||||
AND M.[Borrado] = (0)
|
||||
LEFT JOIN [dbo].[Gral_SAT_Localidad] AS L
|
||||
ON L.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND L.[ClaveSATLocalidad] = CP.[ClaveSATLocalidad]
|
||||
AND L.[Borrado] = (0)
|
||||
WHERE CP.[CP] = @CP
|
||||
AND CP.[Borrado] = (0);
|
||||
|
||||
IF @CvePais IS NULL OR @CveEstado IS NULL OR @CveMunicipio IS NULL
|
||||
BEGIN
|
||||
SET @ErrorMostrar = CONCAT(
|
||||
'El código postal ', @CP,
|
||||
' no existe o sus relaciones de país, estado y municipio están incompletas.');
|
||||
SET @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
SELECT
|
||||
@CvePais AS [CvePais],
|
||||
@Pais AS [Pais],
|
||||
@CveEstado AS [CveEstado],
|
||||
@Estado AS [Estado],
|
||||
@CveMunicipio AS [CveMunicipio],
|
||||
@Municipio AS [Municipio],
|
||||
@CveLocalidad AS [CveLocalidad],
|
||||
@Localidad AS [Localidad],
|
||||
COALESCE(NULLIF(@Localidad, ''), @Municipio) AS [Ciudad];
|
||||
|
||||
SELECT
|
||||
C.[CveColonia],
|
||||
C.[NombreAsentamiento]
|
||||
FROM [dbo].[Gral_SAT_Colonia] AS C
|
||||
WHERE C.[CP] = @CP
|
||||
AND C.[Borrado] = (0)
|
||||
ORDER BY C.[NombreAsentamiento];
|
||||
|
||||
SET @Return = 1;
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
SET @ErrorMostrar = 'Ocurrió un error al consultar el código postal; favor de contactar a Sistemas.';
|
||||
SET @ErrorTipo = 1;
|
||||
SET @Return = 0;
|
||||
DECLARE @E nvarchar(2048) = CONCAT(
|
||||
'Número: ', ERROR_NUMBER(),
|
||||
'; Procedimiento: ', ERROR_PROCEDURE(),
|
||||
'; Línea: ', ERROR_LINE(),
|
||||
'; Detalle: ', ERROR_MESSAGE());
|
||||
RAISERROR(N'%s', 10, 1, @E);
|
||||
END CATCH;
|
||||
END;
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[PA_Sis_RegistroClienteAdd]
|
||||
@NombreUsuario varchar(100),
|
||||
@HashContrasena varchar(500),
|
||||
@CorreoElectronico varchar(255),
|
||||
@RFC varchar(15),
|
||||
@RazonSocial varchar(200),
|
||||
@NombreComercial varchar(200) = NULL,
|
||||
@Direccion varchar(90),
|
||||
@NoExt varchar(20) = NULL,
|
||||
@NoInt varchar(50) = NULL,
|
||||
@Colonia varchar(100),
|
||||
@Ciudad varchar(100),
|
||||
@CveSATEstado int,
|
||||
@Pais varchar(100) = 'México',
|
||||
@CP varchar(5),
|
||||
@Telefono varchar(25) = NULL,
|
||||
@CvePais int,
|
||||
@CveMunicipio int,
|
||||
@CveLocalidad int = NULL,
|
||||
@CveColonia int,
|
||||
@HashToken char(64),
|
||||
@HorasExpiracion int = 24,
|
||||
@CveUsuarioEjecuta int,
|
||||
@ErrorMostrar varchar(max) OUTPUT,
|
||||
@ErrorTipo int OUTPUT,
|
||||
@Return bit OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0;
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE @CveRolEmpresa int, @CveUsuario int, @CveCliente int;
|
||||
DECLARE @NombreEstado varchar(50), @PaisCatalogo varchar(100);
|
||||
DECLARE @CiudadCatalogo varchar(100), @ColoniaCatalogo varchar(100);
|
||||
|
||||
SET @NombreUsuario = LTRIM(RTRIM(@NombreUsuario));
|
||||
SET @CorreoElectronico = LOWER(LTRIM(RTRIM(@CorreoElectronico)));
|
||||
SET @RFC = UPPER(REPLACE(LTRIM(RTRIM(@RFC)), ' ', ''));
|
||||
SET @CP = LTRIM(RTRIM(@CP));
|
||||
|
||||
SELECT @CveRolEmpresa = [CveRol]
|
||||
FROM [dbo].[Sis_Roles]
|
||||
WHERE [NombreRol] = 'Empresa' AND [Activo] = (1) AND [Borrado] = (0);
|
||||
|
||||
SELECT TOP (1)
|
||||
@NombreEstado = LEFT(E.[NombreEstado], 35),
|
||||
@PaisCatalogo = LEFT(P.[Descripcion], 50),
|
||||
@CiudadCatalogo = LEFT(COALESCE(NULLIF(L.[NombreLocalidad], ''), M.[Descripcion]), 50),
|
||||
@ColoniaCatalogo = LEFT(C.[NombreAsentamiento], 50)
|
||||
FROM [dbo].[Gral_SAT_CP] AS CP
|
||||
INNER JOIN [dbo].[Gral_SAT_Estado] AS E
|
||||
ON E.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND E.[CveEstado] = @CveSATEstado AND E.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Pais] AS P
|
||||
ON P.[ClaveSATPais] = E.[ClaveSATPais]
|
||||
AND P.[CvePais] = @CvePais AND P.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Municipio] AS M
|
||||
ON M.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND M.[ClaveSATMunicipio] = CP.[ClaveSATMunicipio]
|
||||
AND M.[CveMunicipio] = @CveMunicipio AND M.[Borrado] = (0)
|
||||
LEFT JOIN [dbo].[Gral_SAT_Localidad] AS L
|
||||
ON L.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND L.[ClaveSATLocalidad] = CP.[ClaveSATLocalidad] AND L.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Colonia] AS C
|
||||
ON C.[CP] = CP.[CP] AND C.[CveColonia] = @CveColonia AND C.[Borrado] = (0)
|
||||
WHERE CP.[CP] = @CP AND CP.[Borrado] = (0)
|
||||
AND (@CveLocalidad IS NULL OR L.[CveLocalidad] = @CveLocalidad);
|
||||
|
||||
IF @CveRolEmpresa IS NULL
|
||||
BEGIN
|
||||
SELECT @ErrorMostrar = 'No fue posible determinar el rol Empresa.', @ErrorTipo = 1;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
IF @NombreEstado IS NULL OR @PaisCatalogo IS NULL OR @CiudadCatalogo IS NULL OR @ColoniaCatalogo IS NULL
|
||||
BEGIN
|
||||
SELECT @ErrorMostrar = 'Los datos del código postal no coinciden con los catálogos vigentes. Actualiza el código postal.', @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
SELECT @Pais = @PaisCatalogo, @Ciudad = @CiudadCatalogo, @Colonia = @ColoniaCatalogo;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM [dbo].[Sis_Usuarios] WHERE [NombreUsuario] = @NombreUsuario)
|
||||
OR EXISTS (SELECT 1 FROM [dbo].[Sis_Usuarios] WHERE LOWER([CorreoElectronico]) = @CorreoElectronico)
|
||||
OR EXISTS (SELECT 1 FROM [dbo].[Clientes] WHERE UPPER(REPLACE(LTRIM(RTRIM([RFC])), ' ', '')) = @RFC)
|
||||
BEGIN
|
||||
SELECT @ErrorMostrar = 'Los datos ya fueron registrados por otra solicitud. Actualiza la página e inténtalo nuevamente.', @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
INSERT INTO [dbo].[Sis_Usuarios]
|
||||
([NombreUsuario], [HashContrasena], [CorreoElectronico], [CveRol], [Activo], [DebeCambiarContrasena], [CorreoVerificado])
|
||||
VALUES (@NombreUsuario, @HashContrasena, @CorreoElectronico, @CveRolEmpresa, (0), (0), (0));
|
||||
|
||||
SET @CveUsuario = CONVERT(int, SCOPE_IDENTITY());
|
||||
|
||||
INSERT INTO [dbo].[Clientes]
|
||||
([Nombre], [NombreComercial], [Direccion], [NoExt], [NoInt], [Colonia],
|
||||
[Ciudad], [Estado], [CveSATEstado], [Pais], [RFC], [CP], [Telefono],
|
||||
[Mail], [Estatus], [Fecha], [CveUsuario], [FechaIng],
|
||||
[CvePais], [CveEstado], [CveMunicipio], [CveLocalidad], [CveColonia])
|
||||
VALUES
|
||||
(@RazonSocial, NULLIF(@NombreComercial, ''), @Direccion, NULLIF(@NoExt, ''),
|
||||
NULLIF(@NoInt, ''), @Colonia, @Ciudad, @NombreEstado, @CveSATEstado,
|
||||
@Pais, @RFC, @CP, NULLIF(@Telefono, ''), @CorreoElectronico, (0),
|
||||
CONVERT(date, GETDATE()), @CveUsuario, GETDATE(),
|
||||
@CvePais, @CveSATEstado, @CveMunicipio, @CveLocalidad, @CveColonia);
|
||||
|
||||
SET @CveCliente = CONVERT(int, SCOPE_IDENTITY());
|
||||
|
||||
INSERT INTO [dbo].[Sis_UsuariosClientes]
|
||||
([CveUsuario], [CveCliente], [Orden], [EsPrincipal], [Activo], [CveUsuarioRegistro])
|
||||
VALUES (@CveUsuario, @CveCliente, (1), (1), (1), @CveUsuario);
|
||||
|
||||
INSERT INTO [dbo].[Sis_UsuariosVerificacionesCorreo]
|
||||
([CveUsuario], [CveClienteRegistro], [HashToken], [FechaExpiracion])
|
||||
VALUES (@CveUsuario, @CveCliente, @HashToken, DATEADD(HOUR, @HorasExpiracion, SYSDATETIME()));
|
||||
|
||||
COMMIT TRANSACTION;
|
||||
|
||||
SELECT @CveUsuario AS [CveUsuario], @CveCliente AS [CveCliente];
|
||||
SET @Return = 1;
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
|
||||
SELECT @ErrorMostrar = 'Ocurrió un error al crear el registro; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0;
|
||||
DECLARE @E nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', ERROR_PROCEDURE(), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE());
|
||||
RAISERROR(N'%s', 10, 1, @E);
|
||||
END CATCH;
|
||||
END;
|
||||
GO
|
||||
|
||||
/*
|
||||
Se registran para limpieza, pero la limpieza física queda deshabilitada.
|
||||
Habilitarla posteriormente requiere autorización expresa.
|
||||
*/
|
||||
IF OBJECT_ID(N'dbo.Sis_ConfigurarLimpieza', N'P') IS NOT NULL
|
||||
BEGIN
|
||||
EXEC [dbo].[Sis_ConfigurarLimpieza] @Esquema=N'dbo', @Tabla=N'Gral_SAT_CP', @DiasRetencion=365, @TamanoLote=500, @Habilitada=0;
|
||||
EXEC [dbo].[Sis_ConfigurarLimpieza] @Esquema=N'dbo', @Tabla=N'Gral_SAT_Municipio', @DiasRetencion=365, @TamanoLote=500, @Habilitada=0;
|
||||
EXEC [dbo].[Sis_ConfigurarLimpieza] @Esquema=N'dbo', @Tabla=N'Gral_SAT_Localidad', @DiasRetencion=365, @TamanoLote=500, @Habilitada=0;
|
||||
EXEC [dbo].[Sis_ConfigurarLimpieza] @Esquema=N'dbo', @Tabla=N'Gral_SAT_Colonia', @DiasRetencion=365, @TamanoLote=500, @Habilitada=0;
|
||||
EXEC [dbo].[Sis_ConfigurarLimpieza] @Esquema=N'dbo', @Tabla=N'Gral_SAT_Estado', @DiasRetencion=365, @TamanoLote=500, @Habilitada=0;
|
||||
EXEC [dbo].[Sis_ConfigurarLimpieza] @Esquema=N'dbo', @Tabla=N'Gral_SAT_Pais', @DiasRetencion=365, @TamanoLote=500, @Habilitada=0;
|
||||
END;
|
||||
GO
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using SIG.Web.AppCode.Contracts.Database;
|
||||
using SIG.Web.AppCode.Contracts.Search;
|
||||
using SIG.Web.AppCode.Contracts.Security;
|
||||
@@ -17,6 +19,7 @@ namespace SIG.Web.AppCode.Configuration
|
||||
public static IDbConnectionFactory DbConnectionFactory { get; private set; }
|
||||
public static IDbExecutor DbExecutor { get; private set; }
|
||||
public static IPasswordHasher PasswordHasher { get; private set; }
|
||||
public static ICaptchaService CaptchaService { get; private set; }
|
||||
public static IUserRepository UserRepository { get; private set; }
|
||||
public static IUserAdministrationRepository UserAdministrationRepository { get; private set; }
|
||||
public static IPublicRegistrationService PublicRegistrationService { get; private set; }
|
||||
@@ -34,6 +37,10 @@ namespace SIG.Web.AppCode.Configuration
|
||||
DbExecutor = new DbExecutor(DbConnectionFactory);
|
||||
|
||||
PasswordHasher = new PasswordHasher();
|
||||
CaptchaService = new RecaptchaV2Service(
|
||||
ReadBooleanSetting("RecaptchaEnabled", "SIG_RECAPTCHA_ENABLED", false),
|
||||
ReadSetting("RecaptchaSiteKey", "SIG_RECAPTCHA_SITE_KEY"),
|
||||
ReadSetting("RecaptchaSecretKey", "SIG_RECAPTCHA_SECRET_KEY"));
|
||||
|
||||
UserRepository = new UserRepository(DbExecutor);
|
||||
UserAdministrationRepository = new UserAdministrationRepository(DbExecutor);
|
||||
@@ -55,5 +62,21 @@ namespace SIG.Web.AppCode.Configuration
|
||||
UserAdministrationRepository,
|
||||
PasswordHasher,
|
||||
new SmtpEmailSender());
|
||||
} }
|
||||
}
|
||||
|
||||
private static string ReadSetting(string appSettingName, string environmentVariableName)
|
||||
{
|
||||
string environmentValue = Environment.GetEnvironmentVariable(environmentVariableName);
|
||||
return string.IsNullOrWhiteSpace(environmentValue)
|
||||
? ConfigurationManager.AppSettings[appSettingName]
|
||||
: environmentValue;
|
||||
}
|
||||
private static bool ReadBooleanSetting(string appSettingName, string environmentVariableName, bool defaultValue)
|
||||
{
|
||||
bool value;
|
||||
string configuredValue = ReadSetting(appSettingName, environmentVariableName);
|
||||
return bool.TryParse(configuredValue, out value) ? value : defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
12
SIG.Web/AppCode/Contracts/Security/ICaptchaService.cs
Normal file
12
SIG.Web/AppCode/Contracts/Security/ICaptchaService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using SIG.Web.AppCode.Models.Common;
|
||||
|
||||
namespace SIG.Web.AppCode.Contracts.Security
|
||||
{
|
||||
public interface ICaptchaService
|
||||
{
|
||||
bool IsEnabled { get; }
|
||||
bool IsConfigured { get; }
|
||||
string SiteKey { get; }
|
||||
DbResult<bool> Verify(string responseToken, string remoteIp, string expectedHostName);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ namespace SIG.Web.AppCode.Contracts.Security
|
||||
{
|
||||
DbResult<bool> Validate(PublicRegistrationDraft draft, string domainName);
|
||||
DbResult<List<StateOptionModel>> ListStates(string domainName);
|
||||
DbResult<PostalCodeLookupModel> GetPostalCode(string postalCode, string domainName);
|
||||
DbResult<bool> Register(PublicRegistrationDraft draft, string verificationBaseUrl, string domainName);
|
||||
DbResult<bool> Verify(string token, string domainName);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace SIG.Web.AppCode.Contracts.Security
|
||||
DbResult<UserAdministrationModel> GetUser(int userId, int executingUser, string domainName);
|
||||
DbResult<List<RoleOptionModel>> ListRoles(int executingUser, string domainName);
|
||||
DbResult<List<StateOptionModel>> ListStates(string domainName);
|
||||
DbResult<PostalCodeLookupModel> GetPostalCode(string postalCode, string domainName);
|
||||
DbResult<int> SaveUser(UserAdministrationModel user, string passwordHash, int executingUser, string domainName);
|
||||
DbResult<bool> DeleteUser(int userId, int executingUser, string domainName);
|
||||
DbResult<List<UserClientModel>> ListUserClients(int userId, int executingUser, string domainName);
|
||||
|
||||
@@ -20,6 +20,31 @@ namespace SIG.Web.AppCode.Models.Security
|
||||
public string Pais { get; set; }
|
||||
public string CP { get; set; }
|
||||
public string Telefono { get; set; }
|
||||
public int CvePais { get; set; }
|
||||
public int CveMunicipio { get; set; }
|
||||
public int CveLocalidad { get; set; }
|
||||
public int CveColonia { get; set; }
|
||||
}
|
||||
|
||||
public sealed class PostalCodeLookupModel
|
||||
{
|
||||
public PostalCodeLookupModel() { Colonias = new System.Collections.Generic.List<NeighborhoodOptionModel>(); }
|
||||
public int CvePais { get; set; }
|
||||
public string Pais { get; set; }
|
||||
public int CveEstado { get; set; }
|
||||
public string Estado { get; set; }
|
||||
public int CveMunicipio { get; set; }
|
||||
public string Municipio { get; set; }
|
||||
public int CveLocalidad { get; set; }
|
||||
public string Localidad { get; set; }
|
||||
public string Ciudad { get; set; }
|
||||
public System.Collections.Generic.List<NeighborhoodOptionModel> Colonias { get; set; }
|
||||
}
|
||||
|
||||
public sealed class NeighborhoodOptionModel
|
||||
{
|
||||
public int CveColonia { get; set; }
|
||||
public string NombreAsentamiento { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UserAdministrationModel
|
||||
|
||||
@@ -26,6 +26,29 @@ namespace SIG.Web.AppCode.Repositories.Security
|
||||
public DbResult<List<StateOptionModel>> ListStates(string domainName)
|
||||
{ return QueryList<StateOptionModel>("dbo.PA_Gral_EstadoList", 0, domainName, null); }
|
||||
|
||||
public DbResult<PostalCodeLookupModel> GetPostalCode(string postalCode, string domainName)
|
||||
{
|
||||
return _db.Execute(domainName, connection =>
|
||||
{
|
||||
using (IDbCommand command = connection.CreateCommand())
|
||||
{
|
||||
StoredProcedureCommand.Configure(command, "dbo.PA_Gral_CodigoPostalGet", 0);
|
||||
StoredProcedureCommand.AddInput(command, "@CP", postalCode, DbType.String);
|
||||
|
||||
PostalCodeLookupModel value;
|
||||
using (IDataReader reader = command.ExecuteReader())
|
||||
{
|
||||
value = reader.ToObject<PostalCodeLookupModel>();
|
||||
if (value != null && reader.NextResult())
|
||||
value.Colonias = reader.ToList<NeighborhoodOptionModel>();
|
||||
}
|
||||
|
||||
StoredProcedureCommand.EnsureSuccess(command);
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DbResult<int> SaveUser(UserAdministrationModel user, string passwordHash, int executingUser, string domainName)
|
||||
{
|
||||
return _db.Execute(domainName, connection =>
|
||||
@@ -94,6 +117,10 @@ namespace SIG.Web.AppCode.Repositories.Security
|
||||
StoredProcedureCommand.AddInput(c, "@Pais", draft.Pais, DbType.String);
|
||||
StoredProcedureCommand.AddInput(c, "@CP", draft.CP, DbType.String);
|
||||
StoredProcedureCommand.AddInput(c, "@Telefono", draft.Telefono, DbType.String);
|
||||
StoredProcedureCommand.AddInput(c, "@CvePais", draft.CvePais, DbType.Int32);
|
||||
StoredProcedureCommand.AddInput(c, "@CveMunicipio", draft.CveMunicipio, DbType.Int32);
|
||||
StoredProcedureCommand.AddInput(c, "@CveLocalidad", draft.CveLocalidad <= 0 ? (object)null : draft.CveLocalidad, DbType.Int32);
|
||||
StoredProcedureCommand.AddInput(c, "@CveColonia", draft.CveColonia, DbType.Int32);
|
||||
StoredProcedureCommand.AddInput(c, "@HashToken", tokenHash, DbType.StringFixedLength);
|
||||
StoredProcedureCommand.AddInput(c, "@HorasExpiracion", 24, DbType.Int32);
|
||||
});
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace SIG.Web.AppCode.Services.Security
|
||||
}
|
||||
|
||||
public DbResult<List<StateOptionModel>> ListStates(string domainName) { return _repository.ListStates(domainName); }
|
||||
public DbResult<PostalCodeLookupModel> GetPostalCode(string postalCode, string domainName) { return _repository.GetPostalCode(postalCode, domainName); }
|
||||
|
||||
public DbResult<bool> Register(PublicRegistrationDraft draft, string verificationBaseUrl, string domainName)
|
||||
{
|
||||
@@ -48,7 +49,7 @@ namespace SIG.Web.AppCode.Services.Security
|
||||
if (d == null) return "Captura los datos del registro.";
|
||||
if (string.IsNullOrWhiteSpace(d.NombreUsuario) || string.IsNullOrWhiteSpace(d.CorreoElectronico) || string.IsNullOrWhiteSpace(d.Contrasena)) return "Completa los datos de usuario.";
|
||||
if (d.Contrasena.Length < 8) return "La contraseña debe tener al menos 8 caracteres.";
|
||||
if (string.IsNullOrWhiteSpace(d.RFC) || string.IsNullOrWhiteSpace(d.RazonSocial) || string.IsNullOrWhiteSpace(d.Direccion) || string.IsNullOrWhiteSpace(d.Colonia) || string.IsNullOrWhiteSpace(d.Ciudad) || d.CveSATEstado <= 0) return "Completa los datos obligatorios de la empresa.";
|
||||
if (string.IsNullOrWhiteSpace(d.RFC) || string.IsNullOrWhiteSpace(d.RazonSocial) || string.IsNullOrWhiteSpace(d.Direccion) || string.IsNullOrWhiteSpace(d.Colonia) || string.IsNullOrWhiteSpace(d.Ciudad) || d.CveSATEstado <= 0 || d.CvePais <= 0 || d.CveMunicipio <= 0 || d.CveColonia <= 0) return "Completa y valida los datos obligatorios de la empresa y su código postal.";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
95
SIG.Web/AppCode/Services/Security/RecaptchaV2Service.cs
Normal file
95
SIG.Web/AppCode/Services/Security/RecaptchaV2Service.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using SIG.Web.AppCode.Contracts.Security;
|
||||
using SIG.Web.AppCode.Models.Common;
|
||||
|
||||
namespace SIG.Web.AppCode.Services.Security
|
||||
{
|
||||
public sealed class RecaptchaV2Service : ICaptchaService
|
||||
{
|
||||
private const string VerifyUrl = "https://www.google.com/recaptcha/api/siteverify";
|
||||
private readonly bool _enabled;
|
||||
private readonly string _secretKey;
|
||||
|
||||
public RecaptchaV2Service(bool enabled, string siteKey, string secretKey)
|
||||
{
|
||||
_enabled = enabled;
|
||||
SiteKey = (siteKey ?? string.Empty).Trim();
|
||||
_secretKey = (secretKey ?? string.Empty).Trim();
|
||||
}
|
||||
|
||||
public bool IsEnabled { get { return _enabled; } }
|
||||
public bool IsConfigured { get { return SiteKey.Length > 0 && _secretKey.Length > 0; } }
|
||||
public string SiteKey { get; private set; }
|
||||
|
||||
public DbResult<bool> Verify(string responseToken, string remoteIp, string expectedHostName)
|
||||
{
|
||||
if (!IsEnabled)
|
||||
return DbResult<bool>.Ok(true);
|
||||
|
||||
if (!IsConfigured)
|
||||
return DbResult<bool>.Fail("La validación No soy un robot todavía no está configurada. Contacta a Sistemas.", "Faltan RecaptchaSiteKey o RecaptchaSecretKey.", null);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(responseToken))
|
||||
return DbResult<bool>.Fail("Confirma que no eres un robot antes de crear la cuenta.", "Token reCAPTCHA vacío.", null);
|
||||
|
||||
try
|
||||
{
|
||||
string form = "secret=" + Uri.EscapeDataString(_secretKey)
|
||||
+ "&response=" + Uri.EscapeDataString(responseToken);
|
||||
if (!string.IsNullOrWhiteSpace(remoteIp))
|
||||
form += "&remoteip=" + Uri.EscapeDataString(remoteIp);
|
||||
|
||||
byte[] body = Encoding.UTF8.GetBytes(form);
|
||||
var request = (HttpWebRequest)WebRequest.Create(VerifyUrl);
|
||||
request.Method = "POST";
|
||||
request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
|
||||
request.ContentLength = body.Length;
|
||||
request.Timeout = 10000;
|
||||
request.ReadWriteTimeout = 10000;
|
||||
|
||||
using (Stream stream = request.GetRequestStream()) stream.Write(body, 0, body.Length);
|
||||
|
||||
string json;
|
||||
using (var response = (HttpWebResponse)request.GetResponse())
|
||||
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
|
||||
json = reader.ReadToEnd();
|
||||
|
||||
VerificationResponse verification = JsonConvert.DeserializeObject<VerificationResponse>(json);
|
||||
if (verification == null || !verification.Success)
|
||||
return DbResult<bool>.Fail("No fue posible validar que no eres un robot. Inténtalo nuevamente.", "reCAPTCHA rechazado: " + JoinCodes(verification), null);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(expectedHostName)
|
||||
&& !string.Equals(expectedHostName, verification.HostName, StringComparison.OrdinalIgnoreCase))
|
||||
return DbResult<bool>.Fail("La validación No soy un robot no corresponde a este sitio. Inténtalo nuevamente.", "Hostname reCAPTCHA inesperado.", null);
|
||||
|
||||
return DbResult<bool>.Ok(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return DbResult<bool>.Fail("El servicio No soy un robot no está disponible en este momento. Inténtalo nuevamente.", ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static string JoinCodes(VerificationResponse response)
|
||||
{
|
||||
return response == null || response.ErrorCodes == null ? "respuesta inválida" : string.Join(",", response.ErrorCodes);
|
||||
}
|
||||
|
||||
private sealed class VerificationResponse
|
||||
{
|
||||
[JsonProperty("success")]
|
||||
public bool Success { get; set; }
|
||||
|
||||
[JsonProperty("hostname")]
|
||||
public string HostName { get; set; }
|
||||
|
||||
[JsonProperty("error-codes")]
|
||||
public List<string> ErrorCodes { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="SIG.Web.Login" %>
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="SIG.Web.Login" CodePage="65001" %>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
@@ -155,16 +155,24 @@
|
||||
}
|
||||
|
||||
.login-card-icon {
|
||||
min-height: 92px;
|
||||
margin-bottom: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.login-card-icon img {
|
||||
width: 148px;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: inline-block;
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.login-card-icon .water-logo { width: 165px; }
|
||||
.login-card-icon .developer-logo { width: 78px; }
|
||||
|
||||
.login-card-title {
|
||||
margin: 0;
|
||||
font-size: 34px;
|
||||
@@ -214,11 +222,18 @@
|
||||
.input-icon > i {
|
||||
position: absolute;
|
||||
left: 17px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
color: #7a8ca9;
|
||||
font-size: 20px;
|
||||
line-height: 1;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.input-icon .form-control {
|
||||
@@ -258,36 +273,41 @@
|
||||
}
|
||||
|
||||
.login-options {
|
||||
margin-top: 18px;
|
||||
margin-top: 20px;
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
align-items: center;
|
||||
gap: 14px 22px;
|
||||
color: #173b70;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.login-links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
color: #173b70;
|
||||
font-size: 15px;
|
||||
justify-content: flex-end;
|
||||
gap: 22px;
|
||||
}
|
||||
|
||||
.login-options a {
|
||||
color: #0c63c7;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.login-options a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.login-options a:hover { text-decoration: underline; }
|
||||
|
||||
.remember-label {
|
||||
.remember-check {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.remember-label input {
|
||||
margin: 0;
|
||||
}
|
||||
.remember-check input { margin: 0 7px 0 0; vertical-align: middle; }
|
||||
.remember-check label { margin: 0; font-weight: 500; cursor: pointer; }
|
||||
|
||||
.login-footer-note {
|
||||
position: fixed;
|
||||
@@ -361,10 +381,9 @@
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.login-options {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.login-options { grid-template-columns: 1fr; align-items: stretch; }
|
||||
.login-links { justify-content: space-between; gap: 14px; }
|
||||
.login-options a { text-align: left; }
|
||||
|
||||
.login-footer-note {
|
||||
position: static;
|
||||
@@ -401,8 +420,8 @@
|
||||
<div class="login-card">
|
||||
<div class="login-card-header">
|
||||
<div class="login-card-icon">
|
||||
<img src="<%= ResolveUrl("~/Imagenes/logo-agua-hermosillo-blancol.png") %>" alt="Agua de Hermosillo" />
|
||||
<img src="<%= ResolveUrl("~/Imagenes/icono-desarrolladores-azul.png") %>" alt="Desarrolladores" />
|
||||
<img class="water-logo" src="<%= ResolveUrl("~/Imagenes/logo-agua-hermosillo-blancol.png") %>" alt="Agua de Hermosillo" />
|
||||
<img class="developer-logo" src="<%= ResolveUrl("~/Imagenes/icono-desarrolladores-azul_recorte.png") %>" alt="Desarrolladores" />
|
||||
</div>
|
||||
|
||||
<h2 class="login-card-title">
|
||||
@@ -421,7 +440,7 @@
|
||||
<div class="login-form-group">
|
||||
<label for="<%= TxtUsuario.ClientID %>">Usuario</label>
|
||||
<div class="input-icon">
|
||||
<i class="fa fa-user-o"></i>
|
||||
<i class="fa fa-user"></i>
|
||||
<asp:TextBox ID="TxtUsuario" runat="server" CssClass="form-control" placeholder="Ingrese su usuario"></asp:TextBox>
|
||||
</div>
|
||||
</div>
|
||||
@@ -437,13 +456,11 @@
|
||||
<asp:Button ID="BtnLogin" runat="server" Text="Iniciar sesión" CssClass="btn btn-login-main" OnClick="BtnLogin_Click" />
|
||||
|
||||
<div class="login-options">
|
||||
<label class="remember-label">
|
||||
<asp:CheckBox ID="ChkRecordarme" runat="server" />
|
||||
<span>Recordarme</span>
|
||||
</label>
|
||||
|
||||
<a href="javascript:void(0);">¿Olvidaste tu contraseña?</a>
|
||||
<a href="<%= ResolveUrl("~/Pages/Security/RegistroCliente.aspx") %>">Registrar mi empresa</a>
|
||||
<asp:CheckBox ID="ChkRecordarme" runat="server" CssClass="remember-check" Text="Recordarme" />
|
||||
<div class="login-links">
|
||||
<a href="javascript:void(0);">¿Olvidaste tu contraseña?</a>
|
||||
<a href="<%= ResolveUrl("~/Pages/Security/RegistroCliente.aspx") %>">Registrar mi empresa</a>
|
||||
</div>
|
||||
</div>
|
||||
</asp:Panel>
|
||||
</div>
|
||||
|
||||
@@ -1,37 +1,319 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RegistroCliente.aspx.cs" Inherits="SIG.Web.Pages.Security.RegistroCliente" ViewStateEncryptionMode="Always" %>
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RegistroCliente.aspx.cs" Inherits="SIG.Web.Pages.Security.RegistroCliente" ViewStateEncryptionMode="Always" CodePage="65001" %>
|
||||
<%@ Import Namespace="System.Web.Optimization" %>
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="es">
|
||||
<head runat="server">
|
||||
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Crear cuenta - Plataforma de Desarrolladores</title>
|
||||
<%: Styles.Render("~/Metronic/assets/global/css/cssV1") %>
|
||||
<style>.registration-page{background:#eef3f8;min-height:100vh;padding:35px 15px}.registration-card{max-width:920px;margin:auto;background:#fff;padding:30px;border-radius:8px;box-shadow:0 8px 28px rgba(0,0,0,.12)}.steps{display:flex;margin-bottom:28px}.step{flex:1;padding:12px;text-align:center;border-bottom:4px solid #cbd5df}.step.active{color:#167ac6;border-color:#167ac6;font-weight:700}.field{margin-bottom:15px}.actions{display:flex;justify-content:space-between;margin-top:25px}.required:after{content:' *';color:#d9534f}</style>
|
||||
<style>
|
||||
html, body { min-height: 100%; }
|
||||
body.registration-page {
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
padding: 42px 18px;
|
||||
position: relative;
|
||||
font-family: "Open Sans", "Segoe UI", Arial, sans-serif;
|
||||
color: #173b70;
|
||||
background: #123f6d url('<%= ResolveUrl("~/Imagenes/login-fondo-cerro-campana.jpg") %>') center center / cover fixed no-repeat;
|
||||
}
|
||||
body.registration-page::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: linear-gradient(135deg, rgba(3, 37, 72, .92), rgba(5, 78, 132, .75) 52%, rgba(3, 40, 77, .9));
|
||||
pointer-events: none;
|
||||
}
|
||||
.registration-shell { position: relative; z-index: 1; max-width: 1080px; margin: 0 auto; }
|
||||
.registration-card {
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 26px 70px rgba(1, 24, 48, .38);
|
||||
}
|
||||
.registration-header {
|
||||
min-height: 215px;
|
||||
padding: 34px 42px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 32px;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
background:
|
||||
linear-gradient(100deg, rgba(5, 53, 102, .98), rgba(11, 103, 184, .84)),
|
||||
url('<%= ResolveUrl("~/Imagenes/cerro-campana-referencia.jpg") %>') center 47% / cover no-repeat;
|
||||
}
|
||||
.registration-header::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: radial-gradient(circle at 82% 20%, rgba(35, 181, 255, .30), transparent 34%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.registration-brand, .registration-symbol { position: relative; z-index: 1; }
|
||||
.registration-brand img { width: 205px; height: auto; margin-bottom: 20px; }
|
||||
.registration-brand h1 { margin: 0 0 8px; font-size: 34px; line-height: 1.1; font-weight: 700; }
|
||||
.registration-brand p { margin: 0; max-width: 650px; color: rgba(255,255,255,.90); font-size: 16px; line-height: 1.55; }
|
||||
.registration-symbol {
|
||||
flex: 0 0 112px;
|
||||
width: 112px;
|
||||
height: 112px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 28px;
|
||||
background: rgba(255,255,255,.96);
|
||||
box-shadow: 0 12px 30px rgba(0,0,0,.18);
|
||||
}
|
||||
.registration-symbol img { width: 78px; height: auto; }
|
||||
.registration-content { padding: 34px 42px 38px; }
|
||||
.steps { display: flex; margin-bottom: 30px; position: relative; }
|
||||
.steps::before { content: ""; position: absolute; left: 25%; right: 25%; top: 21px; height: 3px; background: #dbe4ee; }
|
||||
.step { flex: 1; position: relative; z-index: 1; text-align: center; color: #7a8ca3; font-size: 14px; font-weight: 600; }
|
||||
.step-number {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
margin: 0 auto 9px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 3px solid #dbe4ee;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
color: #7a8ca3;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.step.active { color: #0b67c2; }
|
||||
.step.active .step-number { color: #fff; border-color: #1686e2; background: linear-gradient(135deg, #0c63bc, #1b98ef); box-shadow: 0 6px 16px rgba(15,112,205,.28); }
|
||||
.registration-message { display: block; margin: 0 0 24px; padding: 13px 16px; border: 0; border-left: 4px solid #d9534f; border-radius: 7px !important; }
|
||||
.form-section-title { margin: 0 0 6px; color: #173b70; font-size: 22px; font-weight: 700; }
|
||||
.form-section-help { margin: 0 0 24px; color: #718096; }
|
||||
.field { margin-bottom: 20px; }
|
||||
.field label { display: block; margin-bottom: 8px; color: #27496f; font-size: 14px; font-weight: 700; }
|
||||
.field .form-control {
|
||||
height: 50px;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid #d5dfeb;
|
||||
border-radius: 10px !important;
|
||||
background: #fff;
|
||||
color: #173b70;
|
||||
box-shadow: none;
|
||||
}
|
||||
.field .form-control:focus { border-color: #188be3; box-shadow: 0 0 0 3px rgba(24,139,227,.12); }
|
||||
.required::after { content: " *"; color: #d9534f; }
|
||||
.field .form-control[readonly], .field select.form-control:disabled { background: #eef4fa; color: #365a7d; opacity: 1; }
|
||||
.postal-code-control { display: flex; align-items: stretch; gap: 8px; }
|
||||
.postal-code-control .form-control { min-width: 0; flex: 1; }
|
||||
.postal-refresh {
|
||||
width: 50px;
|
||||
min-width: 50px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
border-radius: 10px !important;
|
||||
background: #1587e2;
|
||||
color: #fff;
|
||||
font-size: 17px;
|
||||
box-shadow: 0 5px 12px rgba(12,99,188,.20);
|
||||
}
|
||||
.postal-refresh:hover, .postal-refresh:focus { background: #0c63bc; color: #fff; text-decoration: none; }
|
||||
.postal-status { display: block; margin-top: 8px; color: #718096; font-size: 12px; line-height: 1.4; }
|
||||
.postal-status.success { color: #278251; }
|
||||
.actions { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 12px; padding-top: 22px; border-top: 1px solid #e9eef4; }
|
||||
.actions .btn { min-width: 140px; padding: 12px 20px; border-radius: 9px !important; font-weight: 700; }
|
||||
.actions .btn.blue, .actions .btn.green { border: 0; background: linear-gradient(90deg, #0c63bc, #1587e2) !important; box-shadow: 0 7px 16px rgba(12,99,188,.22); }
|
||||
.back-link { color: #526b87 !important; background: #eef3f7 !important; border: 0 !important; }
|
||||
.captcha-section { margin: 4px 0 22px; padding: 18px; border: 1px solid #dce6f0; border-radius: 10px; background: #f8fbfe; }
|
||||
.captcha-title { display: block; margin-bottom: 12px; color: #27496f; font-size: 14px; font-weight: 700; }
|
||||
.captcha-configuration { display: block; margin: 0; color: #a94442; line-height: 1.5; }
|
||||
.registration-security { margin-top: 16px; text-align: center; color: rgba(255,255,255,.82); font-size: 13px; }
|
||||
@media (max-width: 767px) {
|
||||
body.registration-page { padding: 16px 10px; }
|
||||
.registration-card { border-radius: 17px; }
|
||||
.registration-header { min-height: 0; padding: 27px 24px; }
|
||||
.registration-brand img { width: 165px; }
|
||||
.registration-brand h1 { font-size: 27px; }
|
||||
.registration-symbol { display: none; }
|
||||
.registration-content { padding: 27px 20px 28px; }
|
||||
.actions { align-items: stretch; flex-direction: column-reverse; }
|
||||
.actions .btn { width: 100%; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="registration-page">
|
||||
<form id="form1" runat="server">
|
||||
<asp:ScriptManager ID="SM" runat="server" />
|
||||
<div class="registration-card">
|
||||
<h2>Registro de empresa</h2><p>Los datos se guardarán hasta concluir ambas validaciones.</p>
|
||||
<asp:UpdatePanel ID="UpRegistro" runat="server" UpdateMode="Conditional"><ContentTemplate>
|
||||
<div class="steps"><div id="StepUser" runat="server" class="step active">1. Datos de usuario</div><div id="StepCompany" runat="server" class="step">2. Datos de empresa</div></div>
|
||||
<asp:Label ID="LblMessage" runat="server" CssClass="alert alert-danger" Visible="false" />
|
||||
<asp:MultiView ID="MvRegistration" runat="server" ActiveViewIndex="0">
|
||||
<asp:View ID="ViewUser" runat="server">
|
||||
<div class="row"><div class="col-md-6 field"><label class="required">Usuario</label><asp:TextBox ID="TxtUsername" runat="server" CssClass="form-control" MaxLength="100" /></div><div class="col-md-6 field"><label class="required">Correo electrónico</label><asp:TextBox ID="TxtEmail" runat="server" CssClass="form-control" TextMode="Email" MaxLength="255" /></div></div>
|
||||
<div class="row"><div class="col-md-6 field"><label class="required">Contraseña</label><asp:TextBox ID="TxtPassword" runat="server" CssClass="form-control" TextMode="Password" /></div><div class="col-md-6 field"><label class="required">Confirmar contraseña</label><asp:TextBox ID="TxtConfirmPassword" runat="server" CssClass="form-control" TextMode="Password" /></div></div>
|
||||
<div class="actions"><a href="../../Login.aspx" class="btn default">Volver al acceso</a><asp:Button ID="BtnNext" runat="server" CssClass="btn blue" Text="Continuar" OnClick="BtnNext_Click" /></div>
|
||||
</asp:View>
|
||||
<asp:View ID="ViewCompany" runat="server">
|
||||
<div class="row"><div class="col-md-6 field"><label class="required">Razón social</label><asp:TextBox ID="TxtBusinessName" runat="server" CssClass="form-control" MaxLength="200" /></div><div class="col-md-6 field"><label>Nombre comercial</label><asp:TextBox ID="TxtTradeName" runat="server" CssClass="form-control" MaxLength="200" /></div></div>
|
||||
<div class="row"><div class="col-md-4 field"><label class="required">RFC</label><asp:TextBox ID="TxtRfc" runat="server" CssClass="form-control text-uppercase" MaxLength="15" /></div><div class="col-md-8 field"><label class="required">Dirección</label><asp:TextBox ID="TxtAddress" runat="server" CssClass="form-control" MaxLength="90" /></div></div>
|
||||
<div class="row"><div class="col-md-3 field"><label>No. exterior</label><asp:TextBox ID="TxtExterior" runat="server" CssClass="form-control" MaxLength="20" /></div><div class="col-md-3 field"><label>No. interior</label><asp:TextBox ID="TxtInterior" runat="server" CssClass="form-control" MaxLength="50" /></div><div class="col-md-6 field"><label class="required">Colonia</label><asp:TextBox ID="TxtNeighborhood" runat="server" CssClass="form-control" MaxLength="50" /></div></div>
|
||||
<div class="row"><div class="col-md-4 field"><label class="required">Ciudad</label><asp:TextBox ID="TxtCity" runat="server" CssClass="form-control" MaxLength="50" /></div><div class="col-md-4 field"><label class="required">Estado</label><asp:DropDownList ID="DdlState" runat="server" CssClass="form-control" /></div><div class="col-md-4 field"><label>País</label><asp:TextBox ID="TxtCountry" runat="server" CssClass="form-control" MaxLength="50" Text="México" /></div></div>
|
||||
<div class="row"><div class="col-md-4 field"><label>Código postal</label><asp:TextBox ID="TxtPostalCode" runat="server" CssClass="form-control" MaxLength="10" /></div><div class="col-md-4 field"><label>Teléfono</label><asp:TextBox ID="TxtPhone" runat="server" CssClass="form-control" MaxLength="25" /></div></div>
|
||||
<div class="actions"><asp:Button ID="BtnBack" runat="server" CssClass="btn default" Text="Regresar" OnClick="BtnBack_Click" CausesValidation="false" /><asp:Button ID="BtnRegister" runat="server" CssClass="btn green" Text="Crear cuenta" OnClick="BtnRegister_Click" /></div>
|
||||
</asp:View>
|
||||
</asp:MultiView>
|
||||
</ContentTemplate></asp:UpdatePanel>
|
||||
</div>
|
||||
<asp:ScriptManager ID="SM" runat="server" />
|
||||
<div class="registration-shell">
|
||||
<div class="registration-card">
|
||||
<header class="registration-header">
|
||||
<div class="registration-brand">
|
||||
<img src="<%= ResolveUrl("~/Imagenes/logo-agua-hermosillo-blanco.png") %>" alt="Agua de Hermosillo" />
|
||||
<h1>Registro de empresa</h1>
|
||||
<p>Crea el acceso de tu empresa a la Plataforma de Desarrolladores. La información se guardará únicamente después de completar y validar ambos pasos.</p>
|
||||
</div>
|
||||
<div class="registration-symbol">
|
||||
<img src="<%= ResolveUrl("~/Imagenes/icono-desarrolladores-azul_recorte.png") %>" alt="Plataforma de Desarrolladores" />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="registration-content">
|
||||
<asp:UpdatePanel ID="UpRegistro" runat="server" UpdateMode="Conditional">
|
||||
<ContentTemplate>
|
||||
<div class="steps">
|
||||
<div id="StepUser" runat="server" class="step active"><span class="step-number">1</span><span>Datos de usuario</span></div>
|
||||
<div id="StepCompany" runat="server" class="step"><span class="step-number">2</span><span>Datos de empresa</span></div>
|
||||
</div>
|
||||
|
||||
<asp:Label ID="LblMessage" runat="server" CssClass="alert alert-danger registration-message" Visible="false" />
|
||||
|
||||
<asp:MultiView ID="MvRegistration" runat="server" ActiveViewIndex="0">
|
||||
<asp:View ID="ViewUser" runat="server">
|
||||
<h2 class="form-section-title">Datos para iniciar sesión</h2>
|
||||
<p class="form-section-help">El correo será utilizado para verificar y activar la cuenta.</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6 field"><label class="required">Usuario</label><asp:TextBox ID="TxtUsername" runat="server" CssClass="form-control" MaxLength="100" /></div>
|
||||
<div class="col-md-6 field"><label class="required">Correo electrónico</label><asp:TextBox ID="TxtEmail" runat="server" CssClass="form-control" TextMode="Email" MaxLength="255" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 field"><label class="required">Contraseña</label><asp:TextBox ID="TxtPassword" runat="server" CssClass="form-control" TextMode="Password" /></div>
|
||||
<div class="col-md-6 field"><label class="required">Confirmar contraseña</label><asp:TextBox ID="TxtConfirmPassword" runat="server" CssClass="form-control" TextMode="Password" /></div>
|
||||
</div>
|
||||
<div class="actions"><a href="../../Login.aspx" class="btn back-link">Volver al acceso</a><asp:Button ID="BtnNext" runat="server" CssClass="btn blue" Text="Continuar" OnClick="BtnNext_Click" /></div>
|
||||
</asp:View>
|
||||
|
||||
<asp:View ID="ViewCompany" runat="server">
|
||||
<h2 class="form-section-title">Información de la empresa</h2>
|
||||
<p class="form-section-help">Verificaremos que el RFC no se encuentre registrado antes de crear la cuenta.</p>
|
||||
<div class="row"><div class="col-md-6 field"><label class="required">Razón social</label><asp:TextBox ID="TxtBusinessName" runat="server" CssClass="form-control" MaxLength="200" /></div><div class="col-md-6 field"><label>Nombre comercial</label><asp:TextBox ID="TxtTradeName" runat="server" CssClass="form-control" MaxLength="200" /></div></div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 field"><label class="required">RFC</label><asp:TextBox ID="TxtRfc" runat="server" CssClass="form-control text-uppercase" MaxLength="15" /></div>
|
||||
<div class="col-md-6 field"><label>Teléfono</label><asp:TextBox ID="TxtPhone" runat="server" CssClass="form-control" MaxLength="25" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 field">
|
||||
<label class="required">Código postal</label>
|
||||
<div class="postal-code-control">
|
||||
<asp:TextBox ID="TxtPostalCode" runat="server" ClientIDMode="Static" CssClass="form-control" MaxLength="5" inputmode="numeric" autocomplete="postal-code" />
|
||||
<asp:LinkButton ID="BtnSearchPostalCode" runat="server" ClientIDMode="Static" CssClass="postal-refresh" OnClick="BtnSearchPostalCode_Click" CausesValidation="false" ToolTip="Actualizar datos del código postal" aria-label="Actualizar datos del código postal"><i class="fa fa-refresh" aria-hidden="true"></i></asp:LinkButton>
|
||||
</div>
|
||||
<asp:Label ID="LblPostalStatus" runat="server" CssClass="postal-status" Visible="false" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 field"><label>País</label><asp:TextBox ID="TxtCountry" runat="server" CssClass="form-control" MaxLength="50" Text="México" ReadOnly="true" /></div>
|
||||
<div class="col-md-4 field"><label class="required">Estado</label><asp:DropDownList ID="DdlState" runat="server" CssClass="form-control" Enabled="false" /></div>
|
||||
<div class="col-md-4 field"><label class="required">Ciudad o localidad</label><asp:TextBox ID="TxtCity" runat="server" CssClass="form-control" MaxLength="50" ReadOnly="true" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 field"><label class="required">Dirección</label><asp:TextBox ID="TxtAddress" runat="server" CssClass="form-control" MaxLength="90" /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 field"><label>No. exterior</label><asp:TextBox ID="TxtExterior" runat="server" CssClass="form-control" MaxLength="20" /></div>
|
||||
<div class="col-md-3 field"><label>No. interior</label><asp:TextBox ID="TxtInterior" runat="server" CssClass="form-control" MaxLength="50" /></div>
|
||||
<div class="col-md-6 field"><label class="required">Colonia</label><asp:DropDownList ID="DdlNeighborhood" runat="server" CssClass="form-control" /></div>
|
||||
</div>
|
||||
<asp:HiddenField ID="HfCvePais" runat="server" />
|
||||
<asp:HiddenField ID="HfCveMunicipio" runat="server" />
|
||||
<asp:HiddenField ID="HfCveLocalidad" runat="server" />
|
||||
<asp:HiddenField ID="HfResolvedPostalCode" runat="server" />
|
||||
<asp:Panel ID="PnlCaptchaSection" runat="server" CssClass="captcha-section">
|
||||
<span class="captcha-title">Validación de seguridad</span>
|
||||
<asp:Panel ID="PnlCaptcha" runat="server" ClientIDMode="Static" CssClass="g-recaptcha" />
|
||||
<asp:Label ID="LblCaptchaConfiguration" runat="server" CssClass="captcha-configuration" Text="La validación No soy un robot todavía no está configurada. Contacta a Sistemas." Visible="false" />
|
||||
</asp:Panel>
|
||||
<div class="actions"><asp:Button ID="BtnBack" runat="server" CssClass="btn back-link" Text="Regresar" OnClick="BtnBack_Click" CausesValidation="false" /><asp:Button ID="BtnRegister" runat="server" CssClass="btn green" Text="Crear cuenta" OnClick="BtnRegister_Click" /></div>
|
||||
</asp:View>
|
||||
</asp:MultiView>
|
||||
</ContentTemplate>
|
||||
</asp:UpdatePanel>
|
||||
</main>
|
||||
</div>
|
||||
<div class="registration-security"><i class="fa fa-shield"></i> Tus datos se transmiten de forma segura y no se guardan hasta finalizar el registro.</div>
|
||||
</div>
|
||||
</form>
|
||||
</body></html>
|
||||
<script>
|
||||
var sigPostalCodeTimer = null;
|
||||
var sigRecaptchaWidgetId = null;
|
||||
|
||||
function sigSolicitarCodigoPostal() {
|
||||
var input = document.getElementById('TxtPostalCode');
|
||||
var button = document.getElementById('BtnSearchPostalCode');
|
||||
if (!input || !button) return;
|
||||
|
||||
if (!/^\d{5}$/.test(input.value)) {
|
||||
input.setCustomValidity('El código postal debe contener exactamente 5 dígitos.');
|
||||
input.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
input.setCustomValidity('');
|
||||
button.click();
|
||||
}
|
||||
|
||||
function sigInicializarCodigoPostal() {
|
||||
var input = document.getElementById('TxtPostalCode');
|
||||
var button = document.getElementById('BtnSearchPostalCode');
|
||||
if (!input || !button || input.getAttribute('data-sig-cp-inicializado') === '1') return;
|
||||
|
||||
input.setAttribute('data-sig-cp-inicializado', '1');
|
||||
|
||||
input.addEventListener('input', function () {
|
||||
this.value = this.value.replace(/\D/g, '').substring(0, 5);
|
||||
this.setCustomValidity('');
|
||||
window.clearTimeout(sigPostalCodeTimer);
|
||||
if (this.value.length === 5)
|
||||
sigPostalCodeTimer = window.setTimeout(sigSolicitarCodigoPostal, 2000);
|
||||
});
|
||||
|
||||
input.addEventListener('keydown', function (event) {
|
||||
if (event.key !== 'Enter' && event.keyCode !== 13) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
window.clearTimeout(sigPostalCodeTimer);
|
||||
sigSolicitarCodigoPostal();
|
||||
});
|
||||
|
||||
button.addEventListener('click', function () {
|
||||
window.clearTimeout(sigPostalCodeTimer);
|
||||
var icon = this.querySelector('.fa-refresh');
|
||||
if (icon) icon.classList.add('fa-spin');
|
||||
});
|
||||
}
|
||||
|
||||
function sigRenderRecaptcha() {
|
||||
var container = document.getElementById('PnlCaptcha');
|
||||
if (!container || !window.grecaptcha || container.getAttribute('data-rendered') === '1') return;
|
||||
var siteKey = container.getAttribute('data-sitekey');
|
||||
if (!siteKey) return;
|
||||
sigRecaptchaWidgetId = window.grecaptcha.render(container, { sitekey: siteKey, theme: 'light' });
|
||||
container.setAttribute('data-rendered', '1');
|
||||
}
|
||||
|
||||
function sigRecaptchaLoaded() { sigRenderRecaptcha(); }
|
||||
|
||||
(function () {
|
||||
function initializePageControls() {
|
||||
sigInicializarCodigoPostal();
|
||||
sigRenderRecaptcha();
|
||||
}
|
||||
|
||||
if (window.Sys && Sys.WebForms) {
|
||||
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function () {
|
||||
sigRecaptchaWidgetId = null;
|
||||
initializePageControls();
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading')
|
||||
document.addEventListener('DOMContentLoaded', initializePageControls);
|
||||
else
|
||||
initializePageControls();
|
||||
}());
|
||||
</script>
|
||||
<script src="https://www.google.com/recaptcha/api.js?onload=sigRecaptchaLoaded&render=explicit&hl=es" async defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,48 +1,314 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
using SIG.Web.AppCode.Configuration;
|
||||
using SIG.Web.AppCode.Models.Common;
|
||||
using SIG.Web.AppCode.Models.Security;
|
||||
using SIG.Web.AppCode.Services.Database;
|
||||
|
||||
namespace SIG.Web.Pages.Security
|
||||
{
|
||||
public partial class RegistroCliente : Page
|
||||
{
|
||||
private const string DraftKey = "RegistrationDraft";
|
||||
private PublicRegistrationDraft Draft { get { return ViewState[DraftKey] as PublicRegistrationDraft; } set { ViewState[DraftKey] = value; } }
|
||||
|
||||
private PublicRegistrationDraft Draft
|
||||
{
|
||||
get { return ViewState[DraftKey] as PublicRegistrationDraft; }
|
||||
set { ViewState[DraftKey] = value; }
|
||||
}
|
||||
|
||||
private string DomainName { get { return Request.Url.Host; } }
|
||||
|
||||
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) LoadStates(); }
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
PnlCaptchaSection.Visible = AppServices.CaptchaService.IsEnabled;
|
||||
PnlCaptcha.Attributes["data-sitekey"] = AppServices.CaptchaService.SiteKey;
|
||||
PnlCaptcha.Visible = AppServices.CaptchaService.IsEnabled && AppServices.CaptchaService.IsConfigured;
|
||||
LblCaptchaConfiguration.Visible = AppServices.CaptchaService.IsEnabled && !AppServices.CaptchaService.IsConfigured;
|
||||
|
||||
if (!IsPostBack)
|
||||
{
|
||||
LoadStates();
|
||||
InitializeNeighborhoods();
|
||||
}
|
||||
}
|
||||
|
||||
protected void BtnNext_Click(object sender, EventArgs e)
|
||||
{
|
||||
HideMessage();
|
||||
if (string.IsNullOrWhiteSpace(TxtUsername.Text) || string.IsNullOrWhiteSpace(TxtEmail.Text) || TxtPassword.Text.Length < 8) { ShowMessage("Captura usuario, correo y una contraseña de al menos 8 caracteres."); return; }
|
||||
if (!string.Equals(TxtPassword.Text, TxtConfirmPassword.Text, StringComparison.Ordinal)) { ShowMessage("Las contraseñas no coinciden."); return; }
|
||||
Draft = new PublicRegistrationDraft { NombreUsuario = TxtUsername.Text.Trim(), CorreoElectronico = TxtEmail.Text.Trim(), Contrasena = TxtPassword.Text };
|
||||
MvRegistration.ActiveViewIndex = 1; SetStep(1);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(TxtUsername.Text)
|
||||
|| string.IsNullOrWhiteSpace(TxtEmail.Text)
|
||||
|| TxtPassword.Text.Length < 8)
|
||||
{
|
||||
ShowMessage("Captura usuario, correo y una contraseña de al menos 8 caracteres.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.Equals(TxtPassword.Text, TxtConfirmPassword.Text, StringComparison.Ordinal))
|
||||
{
|
||||
ShowMessage("Las contraseñas no coinciden.");
|
||||
return;
|
||||
}
|
||||
|
||||
Draft = new PublicRegistrationDraft
|
||||
{
|
||||
NombreUsuario = TxtUsername.Text.Trim(),
|
||||
CorreoElectronico = TxtEmail.Text.Trim(),
|
||||
Contrasena = TxtPassword.Text
|
||||
};
|
||||
|
||||
MvRegistration.ActiveViewIndex = 1;
|
||||
SetStep(1);
|
||||
}
|
||||
|
||||
protected void BtnBack_Click(object sender, EventArgs e) { MvRegistration.ActiveViewIndex = 0; SetStep(0); }
|
||||
protected void BtnBack_Click(object sender, EventArgs e)
|
||||
{
|
||||
MvRegistration.ActiveViewIndex = 0;
|
||||
SetStep(0);
|
||||
}
|
||||
|
||||
protected void BtnSearchPostalCode_Click(object sender, EventArgs e)
|
||||
{
|
||||
HideMessage();
|
||||
|
||||
string selectedNeighborhoodValue = DdlNeighborhood.SelectedValue;
|
||||
string selectedNeighborhoodText = DdlNeighborhood.SelectedItem == null
|
||||
? string.Empty
|
||||
: DdlNeighborhood.SelectedItem.Text.Trim();
|
||||
|
||||
string postalCode = (TxtPostalCode.Text ?? string.Empty).Trim();
|
||||
if (!Regex.IsMatch(postalCode, @"^\d{5}$"))
|
||||
{
|
||||
ClearPostalCodeResult();
|
||||
ShowMessage("El código postal debe contener exactamente 5 dígitos.");
|
||||
return;
|
||||
}
|
||||
|
||||
DbResult<PostalCodeLookupModel> result =
|
||||
AppServices.PublicRegistrationService.GetPostalCode(postalCode, DomainName);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
StoredProcedureException procedureException = result.Exception as StoredProcedureException;
|
||||
if (procedureException != null && procedureException.ErrorType == 2)
|
||||
ClearPostalCodeResult();
|
||||
|
||||
ShowMessage(result.UserMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.Data == null)
|
||||
{
|
||||
ClearPostalCodeResult();
|
||||
ShowMessage("El código postal no fue localizado.");
|
||||
return;
|
||||
}
|
||||
|
||||
PostalCodeLookupModel data = result.Data;
|
||||
ListItem stateItem = DdlState.Items.FindByValue(data.CveEstado.ToString());
|
||||
if (stateItem == null)
|
||||
{
|
||||
ClearPostalCodeResult();
|
||||
ShowMessage("El estado relacionado con el código postal no está disponible.");
|
||||
return;
|
||||
}
|
||||
|
||||
ClearPostalCodeResult();
|
||||
|
||||
DdlState.ClearSelection();
|
||||
stateItem.Selected = true;
|
||||
TxtCity.Text = data.Ciudad;
|
||||
TxtCountry.Text = data.Pais;
|
||||
|
||||
HfCvePais.Value = data.CvePais.ToString();
|
||||
HfCveMunicipio.Value = data.CveMunicipio.ToString();
|
||||
HfCveLocalidad.Value = data.CveLocalidad.ToString();
|
||||
HfResolvedPostalCode.Value = postalCode;
|
||||
|
||||
DdlNeighborhood.DataSource = data.Colonias;
|
||||
DdlNeighborhood.DataTextField = "NombreAsentamiento";
|
||||
DdlNeighborhood.DataValueField = "CveColonia";
|
||||
DdlNeighborhood.DataBind();
|
||||
DdlNeighborhood.Items.Insert(0, new ListItem("Selecciona una colonia...", "0"));
|
||||
|
||||
RestoreNeighborhoodSelection(selectedNeighborhoodValue, selectedNeighborhoodText);
|
||||
|
||||
if (data.Colonias == null || data.Colonias.Count == 0)
|
||||
{
|
||||
ShowMessage("El código postal fue localizado, pero no tiene colonias vigentes asociadas.");
|
||||
return;
|
||||
}
|
||||
|
||||
LblPostalStatus.Text = Server.HtmlEncode(
|
||||
string.Format("{0}, {1}. Se encontraron {2} colonias.", data.Ciudad, data.Estado, data.Colonias.Count));
|
||||
LblPostalStatus.CssClass = "postal-status success";
|
||||
LblPostalStatus.Visible = true;
|
||||
}
|
||||
|
||||
private void RestoreNeighborhoodSelection(string previousValue, string previousText)
|
||||
{
|
||||
ListItem matchingItem = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(previousValue) && previousValue != "0")
|
||||
{
|
||||
matchingItem = DdlNeighborhood.Items.FindByValue(previousValue);
|
||||
}
|
||||
|
||||
if (matchingItem == null && !string.IsNullOrWhiteSpace(previousText))
|
||||
{
|
||||
foreach (ListItem item in DdlNeighborhood.Items)
|
||||
{
|
||||
if (item.Value != "0"
|
||||
&& string.Equals(item.Text.Trim(), previousText, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
matchingItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingItem == null) return;
|
||||
|
||||
DdlNeighborhood.ClearSelection();
|
||||
matchingItem.Selected = true;
|
||||
}
|
||||
|
||||
protected void BtnRegister_Click(object sender, EventArgs e)
|
||||
{
|
||||
HideMessage(); PublicRegistrationDraft draft = Draft; if (draft == null) { ShowMessage("La información de usuario expiró. Vuelve al primer paso."); return; }
|
||||
draft.RazonSocial = TxtBusinessName.Text.Trim(); draft.NombreComercial = TxtTradeName.Text.Trim(); draft.RFC = TxtRfc.Text.Trim().ToUpperInvariant(); draft.Direccion = TxtAddress.Text.Trim(); draft.NoExt = TxtExterior.Text.Trim(); draft.NoInt = TxtInterior.Text.Trim(); draft.Colonia = TxtNeighborhood.Text.Trim(); draft.Ciudad = TxtCity.Text.Trim();
|
||||
int state; int.TryParse(DdlState.SelectedValue, out state); draft.CveSATEstado = state; draft.Pais = TxtCountry.Text.Trim(); draft.CP = TxtPostalCode.Text.Trim(); draft.Telefono = TxtPhone.Text.Trim(); Draft = draft;
|
||||
string verificationUrl = new Uri(Request.Url, ResolveUrl("~/Pages/Security/VerificarCorreo.aspx")).AbsoluteUri;
|
||||
DbResult<bool> result = AppServices.PublicRegistrationService.Register(draft, verificationUrl, DomainName);
|
||||
if (!result.Success) { ShowMessage(result.UserMessage); return; }
|
||||
Draft = null; Response.Redirect(ResolveUrl("~/Pages/Security/RegistroPendiente.aspx"), false); Context.ApplicationInstance.CompleteRequest();
|
||||
HideMessage();
|
||||
PublicRegistrationDraft draft = Draft;
|
||||
if (draft == null)
|
||||
{
|
||||
ShowMessage("La información de usuario expiró. Vuelve al primer paso.");
|
||||
return;
|
||||
}
|
||||
|
||||
string postalCode = (TxtPostalCode.Text ?? string.Empty).Trim();
|
||||
if (!Regex.IsMatch(postalCode, @"^\d{5}$")
|
||||
|| !string.Equals(postalCode, HfResolvedPostalCode.Value, StringComparison.Ordinal))
|
||||
{
|
||||
ShowMessage("Consulta o actualiza el código postal antes de crear la cuenta.");
|
||||
return;
|
||||
}
|
||||
|
||||
int cveColonia;
|
||||
int cvePais;
|
||||
int cveMunicipio;
|
||||
int cveLocalidad;
|
||||
int cveEstado;
|
||||
int.TryParse(DdlNeighborhood.SelectedValue, out cveColonia);
|
||||
int.TryParse(HfCvePais.Value, out cvePais);
|
||||
int.TryParse(HfCveMunicipio.Value, out cveMunicipio);
|
||||
int.TryParse(HfCveLocalidad.Value, out cveLocalidad);
|
||||
int.TryParse(DdlState.SelectedValue, out cveEstado);
|
||||
|
||||
if (cveColonia <= 0 || cvePais <= 0 || cveMunicipio <= 0 || cveEstado <= 0)
|
||||
{
|
||||
ShowMessage("Selecciona una colonia válida para el código postal consultado.");
|
||||
return;
|
||||
}
|
||||
|
||||
draft.RazonSocial = TxtBusinessName.Text.Trim();
|
||||
draft.NombreComercial = TxtTradeName.Text.Trim();
|
||||
draft.RFC = TxtRfc.Text.Trim().ToUpperInvariant();
|
||||
draft.Direccion = TxtAddress.Text.Trim();
|
||||
draft.NoExt = TxtExterior.Text.Trim();
|
||||
draft.NoInt = TxtInterior.Text.Trim();
|
||||
draft.Colonia = DdlNeighborhood.SelectedItem.Text;
|
||||
draft.Ciudad = TxtCity.Text.Trim();
|
||||
draft.CveSATEstado = cveEstado;
|
||||
draft.Pais = TxtCountry.Text.Trim();
|
||||
draft.CP = postalCode;
|
||||
draft.Telefono = TxtPhone.Text.Trim();
|
||||
draft.CvePais = cvePais;
|
||||
draft.CveMunicipio = cveMunicipio;
|
||||
draft.CveLocalidad = cveLocalidad;
|
||||
draft.CveColonia = cveColonia;
|
||||
Draft = draft;
|
||||
|
||||
DbResult<bool> captcha = AppServices.CaptchaService.Verify(
|
||||
Request.Form["g-recaptcha-response"],
|
||||
Request.UserHostAddress,
|
||||
Request.Url.Host);
|
||||
|
||||
if (!captcha.Success)
|
||||
{
|
||||
ShowMessage(captcha.UserMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
string verificationUrl =
|
||||
new Uri(Request.Url, ResolveUrl("~/Pages/Security/VerificarCorreo.aspx")).AbsoluteUri;
|
||||
DbResult<bool> result =
|
||||
AppServices.PublicRegistrationService.Register(draft, verificationUrl, DomainName);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
ShowMessage(result.UserMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
Draft = null;
|
||||
Response.Redirect(ResolveUrl("~/Pages/Security/RegistroPendiente.aspx"), false);
|
||||
Context.ApplicationInstance.CompleteRequest();
|
||||
}
|
||||
|
||||
private void LoadStates()
|
||||
{
|
||||
var result = AppServices.PublicRegistrationService.ListStates(DomainName); if (!result.Success) { ShowMessage(result.UserMessage); return; }
|
||||
DdlState.DataSource = result.Data; DdlState.DataTextField = "NombreEstado"; DdlState.DataValueField = "CveEstado"; DdlState.DataBind(); DdlState.Items.Insert(0, new System.Web.UI.WebControls.ListItem("Selecciona...", "0"));
|
||||
DbResult<System.Collections.Generic.List<StateOptionModel>> result =
|
||||
AppServices.PublicRegistrationService.ListStates(DomainName);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
ShowMessage(result.UserMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
DdlState.DataSource = result.Data;
|
||||
DdlState.DataTextField = "NombreEstado";
|
||||
DdlState.DataValueField = "CveEstado";
|
||||
DdlState.DataBind();
|
||||
DdlState.Items.Insert(0, new ListItem("Selecciona...", "0"));
|
||||
}
|
||||
|
||||
private void InitializeNeighborhoods()
|
||||
{
|
||||
DdlNeighborhood.Items.Clear();
|
||||
DdlNeighborhood.Items.Add(new ListItem("Captura y consulta el código postal...", "0"));
|
||||
}
|
||||
|
||||
private void ClearPostalCodeResult()
|
||||
{
|
||||
HfCvePais.Value = string.Empty;
|
||||
HfCveMunicipio.Value = string.Empty;
|
||||
HfCveLocalidad.Value = string.Empty;
|
||||
HfResolvedPostalCode.Value = string.Empty;
|
||||
TxtCity.Text = string.Empty;
|
||||
TxtCountry.Text = "México";
|
||||
DdlState.ClearSelection();
|
||||
if (DdlState.Items.Count > 0) DdlState.SelectedIndex = 0;
|
||||
InitializeNeighborhoods();
|
||||
LblPostalStatus.Visible = false;
|
||||
}
|
||||
|
||||
private void SetStep(int index)
|
||||
{
|
||||
StepUser.Attributes["class"] = index == 0 ? "step active" : "step";
|
||||
StepCompany.Attributes["class"] = index == 1 ? "step active" : "step";
|
||||
}
|
||||
|
||||
private void ShowMessage(string message)
|
||||
{
|
||||
LblMessage.Text = Server.HtmlEncode(message);
|
||||
LblMessage.Visible = true;
|
||||
}
|
||||
|
||||
private void HideMessage()
|
||||
{
|
||||
LblMessage.Visible = false;
|
||||
}
|
||||
private void SetStep(int index) { StepUser.Attributes["class"] = index == 0 ? "step active" : "step"; StepCompany.Attributes["class"] = index == 1 ? "step active" : "step"; }
|
||||
private void ShowMessage(string message) { LblMessage.Text = Server.HtmlEncode(message); LblMessage.Visible = true; }
|
||||
private void HideMessage() { LblMessage.Visible = false; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,21 @@ namespace SIG.Web.Pages.Security
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtAddress;
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtExterior;
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtInterior;
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtNeighborhood;
|
||||
protected global::System.Web.UI.WebControls.DropDownList DdlNeighborhood;
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtCity;
|
||||
protected global::System.Web.UI.WebControls.DropDownList DdlState;
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtCountry;
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtPostalCode;
|
||||
protected global::System.Web.UI.WebControls.LinkButton BtnSearchPostalCode;
|
||||
protected global::System.Web.UI.WebControls.Label LblPostalStatus;
|
||||
protected global::System.Web.UI.WebControls.HiddenField HfCvePais;
|
||||
protected global::System.Web.UI.WebControls.HiddenField HfCveMunicipio;
|
||||
protected global::System.Web.UI.WebControls.HiddenField HfCveLocalidad;
|
||||
protected global::System.Web.UI.WebControls.HiddenField HfResolvedPostalCode;
|
||||
protected global::System.Web.UI.WebControls.TextBox TxtPhone;
|
||||
protected global::System.Web.UI.WebControls.Panel PnlCaptchaSection;
|
||||
protected global::System.Web.UI.WebControls.Panel PnlCaptcha;
|
||||
protected global::System.Web.UI.WebControls.Label LblCaptchaConfiguration;
|
||||
protected global::System.Web.UI.WebControls.Button BtnBack;
|
||||
protected global::System.Web.UI.WebControls.Button BtnRegister;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
<Compile Include="AppCode\Contracts\Security\ILoginAttemptRepository.cs" />
|
||||
<Compile Include="AppCode\Contracts\Security\ILoginService.cs" />
|
||||
<Compile Include="AppCode\Contracts\Security\IEmailSender.cs" />
|
||||
<Compile Include="AppCode\Contracts\Security\ICaptchaService.cs" />
|
||||
<Compile Include="AppCode\Contracts\Security\IPublicRegistrationService.cs" />
|
||||
<Compile Include="AppCode\Contracts\Security\IUserAdministrationRepository.cs" />
|
||||
<Compile Include="AppCode\Contracts\Security\IPasswordHasher.cs" />
|
||||
@@ -119,6 +120,7 @@
|
||||
<Compile Include="AppCode\Services\Security\LoginService.cs" />
|
||||
<Compile Include="AppCode\Services\Security\PasswordHasher.cs" />
|
||||
<Compile Include="AppCode\Services\Security\PublicRegistrationService.cs" />
|
||||
<Compile Include="AppCode\Services\Security\RecaptchaV2Service.cs" />
|
||||
<Compile Include="AppCode\Services\Security\SmtpEmailSender.cs" />
|
||||
<Compile Include="AppCode\Services\Security\PermissionService.cs" />
|
||||
<Compile Include="AppCode\Services\Security\WebFormsUserContextProvider.cs" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="domainConnections" type="System.Configuration.NameValueSectionHandler" />
|
||||
@@ -21,10 +21,15 @@
|
||||
<add key="SmtpUser" value="" />
|
||||
<add key="SmtpPassword" value="" />
|
||||
<add key="EmailFrom" value="" />
|
||||
<!-- reCAPTCHA v2: al desactivarlo no se muestra ni se valida. La clave secreta nunca se envía al navegador. -->
|
||||
<add key="RecaptchaEnabled" value="true" />
|
||||
<add key="RecaptchaSiteKey" value="6LeVOFQtAAAAAOxZKnBiKFlnMnd90aR1PwJmUGgJ" />
|
||||
<add key="RecaptchaSecretKey" value="6LeVOFQtAAAAAMGFabwoBAk6VG6b16d46hahBSwY" />
|
||||
</appSettings>
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.8.1" />
|
||||
<httpRuntime targetFramework="4.8.1" maxRequestLength="102400" executionTimeout="600" />
|
||||
<globalization requestEncoding="utf-8" responseEncoding="utf-8" fileEncoding="utf-8" culture="es-MX" uiCulture="es-MX" />
|
||||
<pages controlRenderingCompatibilityVersion="4.0" clientIDMode="AutoID">
|
||||
<namespaces>
|
||||
<add namespace="System.Web.Optimization" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SET ANSI_NULLS ON;
|
||||
SET ANSI_NULLS ON;
|
||||
GO
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
GO
|
||||
@@ -220,6 +220,38 @@ BEGIN
|
||||
END;
|
||||
GO
|
||||
|
||||
/* Claves normalizadas utilizadas por el registro. */
|
||||
IF OBJECT_ID(N'dbo.Clientes', N'U') IS NULL
|
||||
THROW 51026, N'Falta la tabla dbo.Clientes.', 1;
|
||||
|
||||
IF COL_LENGTH(N'dbo.Clientes', N'CveLocalidad') IS NULL
|
||||
ALTER TABLE [dbo].[Clientes] ADD [CveLocalidad] int NULL;
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Pais', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Pais] P ON P.[CvePais]=C.[CvePais] WHERE C.[CvePais] IS NOT NULL AND P.[CvePais] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Pais] FOREIGN KEY ([CvePais]) REFERENCES [dbo].[Gral_SAT_Pais] ([CvePais]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Estado_Normalizado', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Estado] E ON E.[CveEstado]=C.[CveEstado] WHERE C.[CveEstado] IS NOT NULL AND E.[CveEstado] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Estado_Normalizado] FOREIGN KEY ([CveEstado]) REFERENCES [dbo].[Gral_SAT_Estado] ([CveEstado]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Municipio', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Municipio] M ON M.[CveMunicipio]=C.[CveMunicipio] WHERE C.[CveMunicipio] IS NOT NULL AND M.[CveMunicipio] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Municipio] FOREIGN KEY ([CveMunicipio]) REFERENCES [dbo].[Gral_SAT_Municipio] ([CveMunicipio]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Localidad', N'F') IS NULL
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Localidad] FOREIGN KEY ([CveLocalidad]) REFERENCES [dbo].[Gral_SAT_Localidad] ([CveLocalidad]);
|
||||
GO
|
||||
|
||||
IF OBJECT_ID(N'dbo.FK_Clientes_Gral_SAT_Colonia', N'F') IS NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM [dbo].[Clientes] C LEFT JOIN [dbo].[Gral_SAT_Colonia] CO ON CO.[CveColonia]=C.[CveColonia] WHERE C.[CveColonia] IS NOT NULL AND CO.[CveColonia] IS NULL)
|
||||
ALTER TABLE [dbo].[Clientes] WITH CHECK ADD CONSTRAINT [FK_Clientes_Gral_SAT_Colonia] FOREIGN KEY ([CveColonia]) REFERENCES [dbo].[Gral_SAT_Colonia] ([CveColonia]);
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[PA_Sis_RegistroClienteAdd]
|
||||
@NombreUsuario varchar(100),
|
||||
@HashContrasena varchar(500),
|
||||
@@ -230,12 +262,16 @@ CREATE OR ALTER PROCEDURE [dbo].[PA_Sis_RegistroClienteAdd]
|
||||
@Direccion varchar(90),
|
||||
@NoExt varchar(20) = NULL,
|
||||
@NoInt varchar(50) = NULL,
|
||||
@Colonia varchar(50),
|
||||
@Ciudad varchar(50),
|
||||
@Colonia varchar(100),
|
||||
@Ciudad varchar(100),
|
||||
@CveSATEstado int,
|
||||
@Pais varchar(50) = 'México',
|
||||
@CP varchar(10) = NULL,
|
||||
@Pais varchar(100) = 'México',
|
||||
@CP varchar(5),
|
||||
@Telefono varchar(25) = NULL,
|
||||
@CvePais int,
|
||||
@CveMunicipio int,
|
||||
@CveLocalidad int = NULL,
|
||||
@CveColonia int,
|
||||
@HashToken char(64),
|
||||
@HorasExpiracion int = 24,
|
||||
@CveUsuarioEjecuta int,
|
||||
@@ -247,72 +283,96 @@ BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0;
|
||||
|
||||
BEGIN TRY
|
||||
DECLARE @CveRolEmpresa int;
|
||||
DECLARE @CveUsuario int;
|
||||
DECLARE @CveCliente int;
|
||||
DECLARE @NombreEstado varchar(35);
|
||||
DECLARE @CveRolEmpresa int, @CveUsuario int, @CveCliente int;
|
||||
DECLARE @NombreEstado varchar(50), @PaisCatalogo varchar(100);
|
||||
DECLARE @CiudadCatalogo varchar(100), @ColoniaCatalogo varchar(100);
|
||||
|
||||
SET @NombreUsuario = LTRIM(RTRIM(@NombreUsuario));
|
||||
SET @CorreoElectronico = LOWER(LTRIM(RTRIM(@CorreoElectronico)));
|
||||
SET @RFC = UPPER(REPLACE(LTRIM(RTRIM(@RFC)), ' ', ''));
|
||||
SET @CP = LTRIM(RTRIM(@CP));
|
||||
|
||||
SELECT @CveRolEmpresa = [CveRol]
|
||||
FROM [dbo].[Sis_Roles]
|
||||
WHERE [NombreRol] = 'Empresa' AND [Activo] = (1) AND [Borrado] = (0);
|
||||
|
||||
SELECT @NombreEstado = LEFT([NombreEstado], 35)
|
||||
FROM [dbo].[Gral_SAT_Estado]
|
||||
WHERE [CveEstado] = @CveSATEstado AND [Borrado] = (0);
|
||||
SELECT TOP (1)
|
||||
@NombreEstado = LEFT(E.[NombreEstado], 35),
|
||||
@PaisCatalogo = LEFT(P.[Descripcion], 50),
|
||||
@CiudadCatalogo = LEFT(COALESCE(NULLIF(L.[NombreLocalidad], ''), M.[Descripcion]), 50),
|
||||
@ColoniaCatalogo = LEFT(C.[NombreAsentamiento], 50)
|
||||
FROM [dbo].[Gral_SAT_CP] AS CP
|
||||
INNER JOIN [dbo].[Gral_SAT_Estado] AS E
|
||||
ON E.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND E.[CveEstado] = @CveSATEstado AND E.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Pais] AS P
|
||||
ON P.[ClaveSATPais] = E.[ClaveSATPais]
|
||||
AND P.[CvePais] = @CvePais AND P.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Municipio] AS M
|
||||
ON M.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND M.[ClaveSATMunicipio] = CP.[ClaveSATMunicipio]
|
||||
AND M.[CveMunicipio] = @CveMunicipio AND M.[Borrado] = (0)
|
||||
LEFT JOIN [dbo].[Gral_SAT_Localidad] AS L
|
||||
ON L.[ClaveSATEstado] = CP.[ClaveSATEstado]
|
||||
AND L.[ClaveSATLocalidad] = CP.[ClaveSATLocalidad] AND L.[Borrado] = (0)
|
||||
INNER JOIN [dbo].[Gral_SAT_Colonia] AS C
|
||||
ON C.[CP] = CP.[CP] AND C.[CveColonia] = @CveColonia AND C.[Borrado] = (0)
|
||||
WHERE CP.[CP] = @CP AND CP.[Borrado] = (0)
|
||||
AND (@CveLocalidad IS NULL OR L.[CveLocalidad] = @CveLocalidad);
|
||||
|
||||
IF @CveRolEmpresa IS NULL OR @NombreEstado IS NULL
|
||||
IF @CveRolEmpresa IS NULL
|
||||
BEGIN
|
||||
SET @ErrorMostrar = 'No fue posible determinar el rol Empresa o el estado seleccionado.';
|
||||
SET @ErrorTipo = 1;
|
||||
SELECT @ErrorMostrar = 'No fue posible determinar el rol Empresa.', @ErrorTipo = 1;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
IF @NombreEstado IS NULL OR @PaisCatalogo IS NULL OR @CiudadCatalogo IS NULL OR @ColoniaCatalogo IS NULL
|
||||
BEGIN
|
||||
SELECT @ErrorMostrar = 'Los datos del código postal no coinciden con los catálogos vigentes. Actualiza el código postal.', @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
SELECT @Pais = @PaisCatalogo, @Ciudad = @CiudadCatalogo, @Colonia = @ColoniaCatalogo;
|
||||
|
||||
IF EXISTS (SELECT 1 FROM [dbo].[Sis_Usuarios] WHERE [NombreUsuario] = @NombreUsuario)
|
||||
OR EXISTS (SELECT 1 FROM [dbo].[Sis_Usuarios] WHERE LOWER([CorreoElectronico]) = @CorreoElectronico)
|
||||
OR EXISTS (SELECT 1 FROM [dbo].[Clientes] WHERE UPPER(REPLACE(LTRIM(RTRIM([RFC])), ' ', '')) = @RFC)
|
||||
BEGIN
|
||||
SET @ErrorMostrar = 'Los datos ya fueron registrados por otra solicitud. Actualiza la página e inténtalo nuevamente.';
|
||||
SET @ErrorTipo = 2;
|
||||
SELECT @ErrorMostrar = 'Los datos ya fueron registrados por otra solicitud. Actualiza la página e inténtalo nuevamente.', @ErrorTipo = 2;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
INSERT INTO [dbo].[Sis_Usuarios]
|
||||
([NombreUsuario], [HashContrasena], [CorreoElectronico], [CveRol], [Activo],
|
||||
[DebeCambiarContrasena], [CorreoVerificado])
|
||||
VALUES
|
||||
(@NombreUsuario, @HashContrasena, @CorreoElectronico, @CveRolEmpresa, (0), (0), (0));
|
||||
([NombreUsuario], [HashContrasena], [CorreoElectronico], [CveRol], [Activo], [DebeCambiarContrasena], [CorreoVerificado])
|
||||
VALUES (@NombreUsuario, @HashContrasena, @CorreoElectronico, @CveRolEmpresa, (0), (0), (0));
|
||||
|
||||
SET @CveUsuario = CONVERT(int, SCOPE_IDENTITY());
|
||||
|
||||
INSERT INTO [dbo].[Clientes]
|
||||
([Nombre], [NombreComercial], [Direccion], [NoExt], [NoInt], [Colonia],
|
||||
[Ciudad], [Estado], [CveSATEstado], [Pais], [RFC], [CP], [Telefono],
|
||||
[Mail], [Estatus], [Fecha], [CveUsuario], [FechaIng])
|
||||
[Mail], [Estatus], [Fecha], [CveUsuario], [FechaIng],
|
||||
[CvePais], [CveEstado], [CveMunicipio], [CveLocalidad], [CveColonia])
|
||||
VALUES
|
||||
(@RazonSocial, NULLIF(@NombreComercial, ''), @Direccion, NULLIF(@NoExt, ''),
|
||||
NULLIF(@NoInt, ''), @Colonia, @Ciudad, @NombreEstado, @CveSATEstado,
|
||||
COALESCE(NULLIF(@Pais, ''), 'México'), @RFC, NULLIF(@CP, ''),
|
||||
NULLIF(@Telefono, ''), @CorreoElectronico, (0), CONVERT(date, GETDATE()),
|
||||
@CveUsuario, GETDATE());
|
||||
@Pais, @RFC, @CP, NULLIF(@Telefono, ''), @CorreoElectronico, (0),
|
||||
CONVERT(date, GETDATE()), @CveUsuario, GETDATE(),
|
||||
@CvePais, @CveSATEstado, @CveMunicipio, @CveLocalidad, @CveColonia);
|
||||
|
||||
SET @CveCliente = CONVERT(int, SCOPE_IDENTITY());
|
||||
|
||||
INSERT INTO [dbo].[Sis_UsuariosClientes]
|
||||
([CveUsuario], [CveCliente], [Orden], [EsPrincipal], [Activo], [CveUsuarioRegistro])
|
||||
VALUES
|
||||
(@CveUsuario, @CveCliente, (1), (1), (1), @CveUsuario);
|
||||
VALUES (@CveUsuario, @CveCliente, (1), (1), (1), @CveUsuario);
|
||||
|
||||
INSERT INTO [dbo].[Sis_UsuariosVerificacionesCorreo]
|
||||
([CveUsuario], [CveClienteRegistro], [HashToken], [FechaExpiracion])
|
||||
VALUES
|
||||
(@CveUsuario, @CveCliente, @HashToken, DATEADD(HOUR, @HorasExpiracion, SYSDATETIME()));
|
||||
VALUES (@CveUsuario, @CveCliente, @HashToken, DATEADD(HOUR, @HorasExpiracion, SYSDATETIME()));
|
||||
|
||||
COMMIT TRANSACTION;
|
||||
|
||||
@@ -321,9 +381,7 @@ BEGIN
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
|
||||
SET @ErrorMostrar = 'Ocurrió un error al crear el registro; favor de contactar a Sistemas.';
|
||||
SET @ErrorTipo = 1;
|
||||
SET @Return = 0;
|
||||
SELECT @ErrorMostrar = 'Ocurrió un error al crear el registro; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0;
|
||||
DECLARE @E nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', ERROR_PROCEDURE(), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE());
|
||||
RAISERROR(N'%s', 10, 1, @E);
|
||||
END CATCH;
|
||||
|
||||
Reference in New Issue
Block a user