Finalización de Reportes y arreglos varios de controles y comportamientos...
This commit is contained in:
@@ -83,7 +83,10 @@ namespace GestionIntegral.Api.Controllers.Distribucion
|
||||
public async Task<IActionResult> UpdateMovimiento(int idParte, [FromBody] UpdateEntradaSalidaCanillaDto updateDto)
|
||||
{
|
||||
if (!TienePermiso(PermisoModificarMovimiento)) return Forbid();
|
||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||
|
||||
// Esta línea es la que dispara la validación del modelo 'updateDto'
|
||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||
|
||||
var userId = GetCurrentUserId();
|
||||
if (userId == null) return Unauthorized();
|
||||
|
||||
@@ -91,7 +94,7 @@ namespace GestionIntegral.Api.Controllers.Distribucion
|
||||
if (!exito)
|
||||
{
|
||||
if (error == "Movimiento no encontrado." || error == "No se puede modificar un movimiento ya liquidado.")
|
||||
return NotFound(new { message = error }); // Podría ser 404 o 400 dependiendo del error
|
||||
return NotFound(new { message = error });
|
||||
return BadRequest(new { message = error });
|
||||
}
|
||||
return NoContent();
|
||||
|
||||
@@ -117,5 +117,65 @@ namespace GestionIntegral.Api.Controllers.Distribucion
|
||||
}
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
// Endpoint para obtener las configuraciones de días para una publicación
|
||||
[HttpGet("{idPublicacion:int}/dias-semana")]
|
||||
[ProducesResponseType(typeof(IEnumerable<PublicacionDiaSemanaDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> GetConfiguracionDiasPublicacion(int idPublicacion)
|
||||
{
|
||||
// Podrías usar el mismo permiso de ver publicaciones o uno específico
|
||||
if (!TienePermiso(PermisoVer)) return Forbid();
|
||||
|
||||
var publicacion = await _publicacionService.ObtenerPorIdAsync(idPublicacion);
|
||||
if (publicacion == null) return NotFound(new { message = "Publicación no encontrada." });
|
||||
|
||||
var configs = await _publicacionService.ObtenerConfiguracionDiasAsync(idPublicacion);
|
||||
return Ok(configs);
|
||||
}
|
||||
|
||||
// Endpoint para actualizar las configuraciones de días para una publicación
|
||||
[HttpPut("{idPublicacion:int}/dias-semana")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> UpdateConfiguracionDiasPublicacion(int idPublicacion, [FromBody] UpdatePublicacionDiasSemanaRequestDto requestDto)
|
||||
{
|
||||
// Podrías usar el mismo permiso de modificar publicaciones o uno específico
|
||||
if (!TienePermiso(PermisoModificar)) return Forbid();
|
||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||
|
||||
var userId = GetCurrentUserId();
|
||||
if (userId == null) return Unauthorized();
|
||||
|
||||
var (exito, error) = await _publicacionService.ActualizarConfiguracionDiasAsync(idPublicacion, requestDto, userId.Value);
|
||||
if (!exito)
|
||||
{
|
||||
if (error == "Publicación no encontrada.") return NotFound(new { message = error });
|
||||
return BadRequest(new { message = error });
|
||||
}
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
// Endpoint para obtener publicaciones por día de la semana (para el modal de canillitas)
|
||||
[HttpGet("por-dia-semana")]
|
||||
[ProducesResponseType(typeof(IEnumerable<PublicacionDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<IActionResult> GetPublicacionesPorDia([FromQuery] byte dia) // dia: 0=Domingo, 1=Lunes...
|
||||
{
|
||||
// Generalmente, este endpoint no necesitaría un permiso estricto si solo devuelve datos públicos
|
||||
// pero puedes añadirlo si es necesario.
|
||||
// if (!TienePermiso(PermisoVer)) return Forbid();
|
||||
|
||||
if (dia > 6) // byte no puede ser negativo
|
||||
{
|
||||
return BadRequest(new { message = "El día de la semana debe estar entre 0 (Domingo) y 6 (Sábado)." });
|
||||
}
|
||||
var publicaciones = await _publicacionService.ObtenerPublicacionesPorDiaSemanaAsync(dia);
|
||||
return Ok(publicaciones);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,992 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
|
||||
<AutoRefresh>0</AutoRefresh>
|
||||
<DataSources>
|
||||
<DataSource Name="DSLiquidacionCanillas">
|
||||
<ConnectionProperties>
|
||||
<DataProvider>System.Data.DataSet</DataProvider>
|
||||
<ConnectString>/* Local Connection */</ConnectString>
|
||||
</ConnectionProperties>
|
||||
<rd:DataSourceID>ee328c50-edc3-4726-92dc-19ec72ac5a56</rd:DataSourceID>
|
||||
</DataSource>
|
||||
</DataSources>
|
||||
<DataSets>
|
||||
<DataSet Name="DSLiquidacionCanillas">
|
||||
<Query>
|
||||
<DataSourceName>DSLiquidacionCanillas</DataSourceName>
|
||||
<CommandText>/* Local Query */</CommandText>
|
||||
</Query>
|
||||
<Fields>
|
||||
<Field Name="Publicacion">
|
||||
<DataField>Publicacion</DataField>
|
||||
<rd:TypeName>System.String</rd:TypeName>
|
||||
</Field>
|
||||
<Field Name="Canilla">
|
||||
<DataField>Canilla</DataField>
|
||||
<rd:TypeName>System.String</rd:TypeName>
|
||||
</Field>
|
||||
<Field Name="TotalCantSalida">
|
||||
<DataField>TotalCantSalida</DataField>
|
||||
<rd:TypeName>System.Int32</rd:TypeName>
|
||||
</Field>
|
||||
<Field Name="TotalCantEntrada">
|
||||
<DataField>TotalCantEntrada</DataField>
|
||||
<rd:TypeName>System.Int32</rd:TypeName>
|
||||
</Field>
|
||||
<Field Name="TotalRendir">
|
||||
<DataField>TotalRendir</DataField>
|
||||
<rd:TypeName>System.Decimal</rd:TypeName>
|
||||
</Field>
|
||||
<Field Name="PrecioEjemplar">
|
||||
<DataField>PrecioEjemplar</DataField>
|
||||
<rd:TypeName>System.Decimal</rd:TypeName>
|
||||
</Field>
|
||||
</Fields>
|
||||
<rd:DataSetInfo>
|
||||
<rd:DataSetName>DSLiquidacionCanillas</rd:DataSetName>
|
||||
<rd:SchemaPath>C:\Users\dmolinari\source\repos\Cobol-VBNet\Reportes\DSLiquidacionCanillas.xsd</rd:SchemaPath>
|
||||
<rd:TableName>SP_DistCanillasLiquidacion</rd:TableName>
|
||||
<rd:TableAdapterFillMethod>Fill</rd:TableAdapterFillMethod>
|
||||
<rd:TableAdapterGetDataMethod>GetData</rd:TableAdapterGetDataMethod>
|
||||
<rd:TableAdapterName>SP_DistCanillasLiquidacionTableAdapter</rd:TableAdapterName>
|
||||
</rd:DataSetInfo>
|
||||
</DataSet>
|
||||
</DataSets>
|
||||
<ReportSections>
|
||||
<ReportSection>
|
||||
<Body>
|
||||
<ReportItems>
|
||||
<Tablix Name="Tablix1">
|
||||
<TablixBody>
|
||||
<TablixColumns>
|
||||
<TablixColumn>
|
||||
<Width>3.53124cm</Width>
|
||||
</TablixColumn>
|
||||
<TablixColumn>
|
||||
<Width>3.10854cm</Width>
|
||||
</TablixColumn>
|
||||
<TablixColumn>
|
||||
<Width>3.55834cm</Width>
|
||||
</TablixColumn>
|
||||
</TablixColumns>
|
||||
<TablixRows>
|
||||
<TablixRow>
|
||||
<Height>0.5cm</Height>
|
||||
<TablixCells>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox38">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>="Vendedor: " & First(Fields!Canilla.Value, "DSLiquidacionCanillas")</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
<FontWeight>Bold</FontWeight>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox38</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Style>None</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
<ColSpan>3</ColSpan>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell />
|
||||
<TablixCell />
|
||||
</TablixCells>
|
||||
</TablixRow>
|
||||
<TablixRow>
|
||||
<Height>0.5cm</Height>
|
||||
<TablixCells>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Publicacion">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Fields!Publicacion.Value</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Publicacion</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox13">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>Retirados</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox13</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="TotalCantSalida">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Fields!TotalCantSalida.Value</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>TotalCantSalida</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
</TablixCells>
|
||||
</TablixRow>
|
||||
<TablixRow>
|
||||
<Height>0.5cm</Height>
|
||||
<TablixCells>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox7">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value />
|
||||
<Style>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox7</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Style>None</Style>
|
||||
</TopBorder>
|
||||
<BottomBorder>
|
||||
<Style>None</Style>
|
||||
</BottomBorder>
|
||||
<LeftBorder>
|
||||
<Style>None</Style>
|
||||
</LeftBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox14">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>Devueltos</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox14</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox12">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Fields!TotalCantEntrada.Value</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox8</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
</TablixCells>
|
||||
</TablixRow>
|
||||
<TablixRow>
|
||||
<Height>0.5cm</Height>
|
||||
<TablixCells>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox27">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value />
|
||||
<Style>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox27</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Style>None</Style>
|
||||
</TopBorder>
|
||||
<BottomBorder>
|
||||
<Style>None</Style>
|
||||
</BottomBorder>
|
||||
<LeftBorder>
|
||||
<Style>None</Style>
|
||||
</LeftBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox28">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>Vendidos</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox28</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox29">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Fields!TotalCantSalida.Value-Fields!TotalCantEntrada.Value</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox29</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
</TablixCells>
|
||||
</TablixRow>
|
||||
<TablixRow>
|
||||
<Height>0.5cm</Height>
|
||||
<TablixCells>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox33">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value />
|
||||
<Style>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox33</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Style>None</Style>
|
||||
</TopBorder>
|
||||
<BottomBorder>
|
||||
<Style>None</Style>
|
||||
</BottomBorder>
|
||||
<LeftBorder>
|
||||
<Style>None</Style>
|
||||
</LeftBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox30">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>Precio Unitario</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox30</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox32">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Fields!PrecioEjemplar.Value</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
<Format>'$'#,0.00;'$'-#,0.00</Format>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox32</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
<rd:FormatSymbolCulture>es-AR</rd:FormatSymbolCulture>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
</TablixCells>
|
||||
</TablixRow>
|
||||
<TablixRow>
|
||||
<Height>0.5cm</Height>
|
||||
<TablixCells>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox35">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value />
|
||||
<Style />
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox35</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>None</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Style>None</Style>
|
||||
</TopBorder>
|
||||
<BottomBorder>
|
||||
<Style>None</Style>
|
||||
</BottomBorder>
|
||||
<LeftBorder>
|
||||
<Style>None</Style>
|
||||
</LeftBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox36">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>Importe Vendido</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
<FontWeight>Bold</FontWeight>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox36</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Color>Black</Color>
|
||||
<Width>2pt</Width>
|
||||
</TopBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox37">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Fields!TotalRendir.Value</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
<FontWeight>Bold</FontWeight>
|
||||
<Format>'$'#,0.00;'$'-#,0.00</Format>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox37</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Color>Black</Color>
|
||||
<Width>2pt</Width>
|
||||
</TopBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
<rd:FormatSymbolCulture>es-AR</rd:FormatSymbolCulture>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
</TablixCells>
|
||||
</TablixRow>
|
||||
<TablixRow>
|
||||
<Height>0.5cm</Height>
|
||||
<TablixCells>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox1">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value />
|
||||
<Style />
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox1</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>None</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Style>None</Style>
|
||||
</TopBorder>
|
||||
<BottomBorder>
|
||||
<Style>None</Style>
|
||||
</BottomBorder>
|
||||
<LeftBorder>
|
||||
<Style>None</Style>
|
||||
</LeftBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox2">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>Total A Rendir</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
<FontWeight>Bold</FontWeight>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox2</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Color>Black</Color>
|
||||
<Width>2pt</Width>
|
||||
</TopBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
<TablixCell>
|
||||
<CellContents>
|
||||
<Textbox Name="Textbox4">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Sum(Fields!TotalRendir.Value, "DSLiquidacionCanillas")</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
<FontWeight>Bold</FontWeight>
|
||||
<Format>'$'#,0.00;'$'-#,0.00</Format>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox4</rd:DefaultName>
|
||||
<Style>
|
||||
<Border>
|
||||
<Color>LightGrey</Color>
|
||||
<Style>Solid</Style>
|
||||
</Border>
|
||||
<TopBorder>
|
||||
<Color>Black</Color>
|
||||
<Width>2pt</Width>
|
||||
</TopBorder>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
<rd:FormatSymbolCulture>es-AR</rd:FormatSymbolCulture>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</CellContents>
|
||||
</TablixCell>
|
||||
</TablixCells>
|
||||
</TablixRow>
|
||||
</TablixRows>
|
||||
</TablixBody>
|
||||
<TablixColumnHierarchy>
|
||||
<TablixMembers>
|
||||
<TablixMember />
|
||||
<TablixMember />
|
||||
<TablixMember />
|
||||
</TablixMembers>
|
||||
</TablixColumnHierarchy>
|
||||
<TablixRowHierarchy>
|
||||
<TablixMembers>
|
||||
<TablixMember>
|
||||
<KeepWithGroup>After</KeepWithGroup>
|
||||
</TablixMember>
|
||||
<TablixMember>
|
||||
<Group Name="Publicacion">
|
||||
<GroupExpressions>
|
||||
<GroupExpression>=Fields!Publicacion.Value</GroupExpression>
|
||||
</GroupExpressions>
|
||||
</Group>
|
||||
<SortExpressions>
|
||||
<SortExpression>
|
||||
<Value>=Fields!Publicacion.Value</Value>
|
||||
</SortExpression>
|
||||
</SortExpressions>
|
||||
<TablixMembers>
|
||||
<TablixMember />
|
||||
<TablixMember />
|
||||
<TablixMember />
|
||||
<TablixMember />
|
||||
<TablixMember />
|
||||
</TablixMembers>
|
||||
</TablixMember>
|
||||
<TablixMember>
|
||||
<KeepWithGroup>Before</KeepWithGroup>
|
||||
</TablixMember>
|
||||
</TablixMembers>
|
||||
</TablixRowHierarchy>
|
||||
<DataSetName>DSLiquidacionCanillas</DataSetName>
|
||||
<Top>1.07592cm</Top>
|
||||
<Left>2.09225cm</Left>
|
||||
<Height>3.5cm</Height>
|
||||
<Width>10.19813cm</Width>
|
||||
<Style>
|
||||
<Border>
|
||||
<Style>None</Style>
|
||||
</Border>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</Tablix>
|
||||
<Textbox Name="Textbox39">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>EL DIA S.A.I.C. y F.</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style />
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox39</rd:DefaultName>
|
||||
<Top>0.01025cm</Top>
|
||||
<Left>2.09225cm</Left>
|
||||
<Height>0.5cm</Height>
|
||||
<Width>10.19813cm</Width>
|
||||
<ZIndex>1</ZIndex>
|
||||
<Style>
|
||||
<Border>
|
||||
<Style>None</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
<Textbox Name="Textbox40">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>Liquidación venta de diarios del:</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style>
|
||||
<TextAlign>Left</TextAlign>
|
||||
</Style>
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox39</rd:DefaultName>
|
||||
<Top>0.53236cm</Top>
|
||||
<Left>2.09225cm</Left>
|
||||
<Height>0.5cm</Height>
|
||||
<Width>4.43198cm</Width>
|
||||
<ZIndex>2</ZIndex>
|
||||
<Style>
|
||||
<Border>
|
||||
<Style>None</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
<Textbox Name="Textbox41">
|
||||
<CanGrow>true</CanGrow>
|
||||
<KeepTogether>true</KeepTogether>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
<TextRuns>
|
||||
<TextRun>
|
||||
<Value>=Parameters!FechaLiqui.Value</Value>
|
||||
<Style>
|
||||
<FontFamily>Roboto</FontFamily>
|
||||
<FontSize>8pt</FontSize>
|
||||
<Format>dd/MM/yyy</Format>
|
||||
</Style>
|
||||
</TextRun>
|
||||
</TextRuns>
|
||||
<Style>
|
||||
<TextAlign>Left</TextAlign>
|
||||
</Style>
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<rd:DefaultName>Textbox41</rd:DefaultName>
|
||||
<Top>0.53236cm</Top>
|
||||
<Left>6.44662cm</Left>
|
||||
<Height>0.5cm</Height>
|
||||
<Width>3.86292cm</Width>
|
||||
<ZIndex>3</ZIndex>
|
||||
<Style>
|
||||
<Border>
|
||||
<Style>None</Style>
|
||||
</Border>
|
||||
<PaddingLeft>2pt</PaddingLeft>
|
||||
<PaddingRight>2pt</PaddingRight>
|
||||
<PaddingTop>2pt</PaddingTop>
|
||||
<PaddingBottom>2pt</PaddingBottom>
|
||||
</Style>
|
||||
</Textbox>
|
||||
</ReportItems>
|
||||
<Height>4.66667cm</Height>
|
||||
<Style />
|
||||
</Body>
|
||||
<Width>14.8cm</Width>
|
||||
<Page>
|
||||
<PageHeight>21cm</PageHeight>
|
||||
<PageWidth>14.8cm</PageWidth>
|
||||
<LeftMargin>0cm</LeftMargin>
|
||||
<RightMargin>0cm</RightMargin>
|
||||
<TopMargin>0.5cm</TopMargin>
|
||||
<BottomMargin>0.5cm</BottomMargin>
|
||||
<ColumnSpacing>0.13cm</ColumnSpacing>
|
||||
<Style />
|
||||
</Page>
|
||||
</ReportSection>
|
||||
</ReportSections>
|
||||
<ReportParameters>
|
||||
<ReportParameter Name="FechaLiqui">
|
||||
<DataType>DateTime</DataType>
|
||||
<Prompt>ReportParameter1</Prompt>
|
||||
</ReportParameter>
|
||||
</ReportParameters>
|
||||
<ReportParametersLayout>
|
||||
<GridLayoutDefinition>
|
||||
<NumberOfColumns>4</NumberOfColumns>
|
||||
<NumberOfRows>2</NumberOfRows>
|
||||
<CellDefinitions>
|
||||
<CellDefinition>
|
||||
<ColumnIndex>0</ColumnIndex>
|
||||
<RowIndex>0</RowIndex>
|
||||
<ParameterName>FechaLiqui</ParameterName>
|
||||
</CellDefinition>
|
||||
</CellDefinitions>
|
||||
</GridLayoutDefinition>
|
||||
</ReportParametersLayout>
|
||||
<rd:ReportUnitType>Cm</rd:ReportUnitType>
|
||||
<rd:ReportID>3bfdc2c9-c7dc-47b8-b2b1-3512fa773a78</rd:ReportID>
|
||||
</Report>
|
||||
@@ -1384,5 +1384,78 @@ namespace GestionIntegral.Api.Controllers
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del reporte.");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("ticket-liquidacion-canilla/pdf")]
|
||||
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<IActionResult> GetTicketLiquidacionCanillaPdf(
|
||||
[FromQuery] DateTime fecha,
|
||||
[FromQuery] int idCanilla,
|
||||
[FromQuery] bool esAccionista = false) // Añadir esAccionista
|
||||
{
|
||||
// Usar PermisoVerComprobanteLiquidacionCanilla o uno específico si lo creas
|
||||
if (!TienePermiso(PermisoVerComprobanteLiquidacionCanilla)) return Forbid();
|
||||
|
||||
var (detalles, ganancias, error) = await _reportesService.ObtenerDatosTicketLiquidacionAsync(fecha, idCanilla);
|
||||
|
||||
if (error != null) return BadRequest(new { message = error });
|
||||
|
||||
// El PDF podría funcionar incluso si solo uno de los datasets tiene datos,
|
||||
// pero es bueno verificar si al menos hay detalles.
|
||||
if (detalles == null || !detalles.Any())
|
||||
{
|
||||
return NotFound(new { message = "No hay detalles de liquidación para generar el PDF." });
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LocalReport report = new LocalReport();
|
||||
string rdlcPath = esAccionista ?
|
||||
"Controllers/Reportes/RDLC/ReporteLiquidacionCanillasAcc.rdlc" :
|
||||
"Controllers/Reportes/RDLC/ReporteLiquidacionCanillas.rdlc";
|
||||
|
||||
if (!System.IO.File.Exists(rdlcPath))
|
||||
{
|
||||
_logger.LogError("Archivo RDLC no encontrado: {Path}", rdlcPath);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, $"Archivo de reporte no encontrado: {System.IO.Path.GetFileName(rdlcPath)}");
|
||||
}
|
||||
|
||||
using (var fs = new FileStream(rdlcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
report.LoadReportDefinition(fs);
|
||||
}
|
||||
|
||||
report.DataSources.Add(new ReportDataSource("DSLiquidacionCanillas", detalles));
|
||||
if (!esAccionista) // El reporte de accionistas podría no usar el dataset de ganancias, o usar uno diferente
|
||||
{
|
||||
report.DataSources.Add(new ReportDataSource("DSLiquidacionCanillasGanancias", ganancias ?? new List<LiquidacionCanillaGananciaDto>()));
|
||||
}
|
||||
|
||||
|
||||
var parameters = new List<ReportParameter>
|
||||
{
|
||||
// El RDLC espera "FechaLiqui"
|
||||
new ReportParameter("FechaLiqui", fecha.ToString("dd/MM/yyyy"))
|
||||
};
|
||||
// El nombre del canilla ya está en el DataSet "DSLiquidacionCanillas" (campo "Canilla")
|
||||
// Si el RDLC lo espera como parámetro, lo añadiríamos aquí.
|
||||
// var canilla = await _canillaRepository.GetByIdAsync(idCanilla);
|
||||
// parameters.Add(new ReportParameter("NombreCanillaParam", canilla?.NomApe ?? "N/A"));
|
||||
|
||||
report.SetParameters(parameters);
|
||||
|
||||
byte[] pdfBytes = report.Render("PDF");
|
||||
string tipo = esAccionista ? "Accionista" : "Canillita";
|
||||
string fileName = $"TicketLiquidacion_{tipo}_{idCanilla}_{fecha:yyyyMMdd}.pdf";
|
||||
return File(pdfBytes, "application/pdf", fileName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al generar PDF para Ticket Liquidación Canilla. Fecha: {Fecha}, Canilla: {IdCanilla}", fecha, idCanilla);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al generar el PDF del ticket.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,16 +263,14 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
|
||||
public async Task<bool> DeleteAsync(int idParte, int idUsuario, IDbTransaction transaction)
|
||||
{
|
||||
var actual = await GetByIdAsync(idParte); // No necesita TX, solo para el historial
|
||||
var actual = await GetByIdAsync(idParte); // Sigue siendo útil para el historial
|
||||
if (actual == null) throw new KeyNotFoundException("Registro E/S Canilla no encontrado para eliminar.");
|
||||
if (actual.Liquidado) throw new InvalidOperationException("No se puede eliminar un movimiento liquidado.");
|
||||
|
||||
|
||||
const string sqlDelete = "DELETE FROM dbo.dist_EntradasSalidasCanillas WHERE Id_Parte = @IdParteParam";
|
||||
const string sqlHistorico = @"
|
||||
INSERT INTO dbo.dist_EntradasSalidasCanillas_H
|
||||
(Id_Parte, Id_Publicacion, Id_Canilla, Fecha, CantSalida, CantEntrada, Id_Precio, Id_Recargo, Id_PorcMon, Observacion, Id_Usuario, FechaMod, TipoMod)
|
||||
VALUES (@IdParteHist, @IdPubHist, @IdCanillaHist, @FechaHist, @CantSalidaHist, @CantEntradaHist, @IdPrecioHist, @IdRecargoHist, @IdPorcMonHist, @ObsHist, @IdUsuarioHist, @FechaModHist, @TipoModHist);";
|
||||
INSERT INTO dbo.dist_EntradasSalidasCanillas_H
|
||||
(Id_Parte, Id_Publicacion, Id_Canilla, Fecha, CantSalida, CantEntrada, Id_Precio, Id_Recargo, Id_PorcMon, Observacion, Id_Usuario, FechaMod, TipoMod)
|
||||
VALUES (@IdParteHist, @IdPubHist, @IdCanillaHist, @FechaHist, @CantSalidaHist, @CantEntradaHist, @IdPrecioHist, @IdRecargoHist, @IdPorcMonHist, @ObsHist, @IdUsuarioHist, @FechaModHist, @TipoModHist);";
|
||||
|
||||
await transaction.Connection!.ExecuteAsync(sqlHistorico, new
|
||||
{
|
||||
|
||||
@@ -15,5 +15,8 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
Task<bool> DeleteAsync(int id, int idUsuario, IDbTransaction transaction); // Borrado físico con historial
|
||||
Task<bool> ExistsByNameAndEmpresaAsync(string nombre, int idEmpresa, int? excludeIdPublicacion = null);
|
||||
Task<bool> IsInUseAsync(int id);
|
||||
Task<IEnumerable<PublicacionDiaSemana>> GetConfiguracionDiasAsync(int idPublicacion);
|
||||
Task<IEnumerable<int>> GetPublicacionesIdsPorDiaSemanaAsync(byte diaSemana); // Devuelve solo IDs
|
||||
Task UpdateConfiguracionDiasAsync(int idPublicacion, IEnumerable<byte> diasActivos, IDbTransaction transaction);
|
||||
}
|
||||
}
|
||||
@@ -106,8 +106,8 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
WHERE Id_Publicacion = @IdParam";
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleOrDefaultAsync<Publicacion>(sql, new { IdParam = id });
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QuerySingleOrDefaultAsync<Publicacion>(sql, new { IdParam = id });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -134,7 +134,7 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error en ExistsByNameAndEmpresaAsync. Nombre: {Nombre}, IdEmpresa: {IdEmpresa}", nombre, idEmpresa);
|
||||
_logger.LogError(ex, "Error en ExistsByNameAndEmpresaAsync. Nombre: {Nombre}, IdEmpresa: {IdEmpresa}", nombre, idEmpresa);
|
||||
return true; // Asumir que existe en caso de error para prevenir duplicados
|
||||
}
|
||||
}
|
||||
@@ -176,7 +176,7 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
INSERT INTO dbo.dist_dtPublicaciones (Nombre, Observacion, Id_Empresa, CtrlDevoluciones, Habilitada)
|
||||
OUTPUT INSERTED.Id_Publicacion AS IdPublicacion, INSERTED.Nombre, INSERTED.Observacion, INSERTED.Id_Empresa AS IdEmpresa, INSERTED.CtrlDevoluciones, INSERTED.Habilitada
|
||||
VALUES (@Nombre, @Observacion, @IdEmpresa, @CtrlDevoluciones, @Habilitada);";
|
||||
|
||||
|
||||
var connection = transaction.Connection!;
|
||||
var inserted = await connection.QuerySingleAsync<Publicacion>(sqlInsert, nuevaPublicacion, transaction);
|
||||
if (inserted == null || inserted.IdPublicacion == 0) throw new DataException("Error al crear la publicación o al obtener el ID generado.");
|
||||
@@ -192,7 +192,7 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
NombreParam = inserted.Nombre,
|
||||
ObservacionParam = inserted.Observacion,
|
||||
IdEmpresaParam = inserted.IdEmpresa,
|
||||
HabilitadaParam = inserted.Habilitada ?? true,
|
||||
HabilitadaParam = inserted.Habilitada ?? true,
|
||||
IdUsuarioParam = idUsuario, // Renombrado para claridad con el parámetro de la función
|
||||
FechaModParam = DateTime.Now,
|
||||
TipoModParam = "Creada"
|
||||
@@ -267,5 +267,65 @@ namespace GestionIntegral.Api.Data.Repositories.Distribucion
|
||||
var rowsAffected = await connection.ExecuteAsync(sqlDelete, new { IdParam = id }, transaction);
|
||||
return rowsAffected == 1;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PublicacionDiaSemana>> GetConfiguracionDiasAsync(int idPublicacion)
|
||||
{
|
||||
const string sql = @"
|
||||
SELECT IdPublicacionDia, Id_Publicacion AS IdPublicacion, DiaSemana, Activo
|
||||
FROM dbo.dist_PublicacionDiaSemana
|
||||
WHERE Id_Publicacion = @IdPublicacion AND Activo = 1;"; // Solo los activos
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QueryAsync<PublicacionDiaSemana>(sql, new { IdPublicacion = idPublicacion });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener configuración de días para Publicacion ID: {IdPublicacion}", idPublicacion);
|
||||
return Enumerable.Empty<PublicacionDiaSemana>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<int>> GetPublicacionesIdsPorDiaSemanaAsync(byte diaSemana)
|
||||
{
|
||||
const string sql = @"
|
||||
SELECT pds.Id_Publicacion
|
||||
FROM dbo.dist_PublicacionDiaSemana pds
|
||||
INNER JOIN dbo.dist_dtPublicaciones p ON pds.Id_Publicacion = p.Id_Publicacion
|
||||
WHERE pds.DiaSemana = @DiaSemana AND pds.Activo = 1 AND (p.Habilitada = 1 OR p.Habilitada IS NULL);"; // Solo publicaciones habilitadas
|
||||
try
|
||||
{
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
return await connection.QueryAsync<int>(sql, new { DiaSemana = diaSemana });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener IDs de publicaciones por día de semana: {DiaSemana}", diaSemana);
|
||||
return Enumerable.Empty<int>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateConfiguracionDiasAsync(int idPublicacion, IEnumerable<byte> diasActivos, IDbTransaction transaction)
|
||||
{
|
||||
var connection = transaction.Connection!;
|
||||
|
||||
// 1. Eliminar configuraciones existentes para esta publicación (más simple que hacer upserts complejos)
|
||||
const string sqlDelete = "DELETE FROM dbo.dist_PublicacionDiaSemana WHERE Id_Publicacion = @IdPublicacion;";
|
||||
await connection.ExecuteAsync(sqlDelete, new { IdPublicacion = idPublicacion }, transaction);
|
||||
|
||||
// 2. Insertar las nuevas configuraciones activas
|
||||
if (diasActivos != null && diasActivos.Any())
|
||||
{
|
||||
const string sqlInsert = @"
|
||||
INSERT INTO dbo.dist_PublicacionDiaSemana (Id_Publicacion, DiaSemana, Activo)
|
||||
VALUES (@IdPublicacion, @DiaSemana, 1);"; // Siempre activo al insertar
|
||||
|
||||
var insertTasks = diasActivos.Select(dia =>
|
||||
connection.ExecuteAsync(sqlInsert, new { IdPublicacion = idPublicacion, DiaSemana = dia }, transaction)
|
||||
);
|
||||
await Task.WhenAll(insertTasks);
|
||||
}
|
||||
// No se necesita historial para esta tabla de configuración por ahora.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,5 +41,7 @@ namespace GestionIntegral.Api.Data.Repositories.Reportes
|
||||
Task<IEnumerable<ListadoDistribucionDistSimpleDto>> GetListadoDistribucionDistSimpleAsync(int idDistribuidor, int idPublicacion, DateTime fechaDesde, DateTime fechaHasta);
|
||||
Task<IEnumerable<ListadoDistribucionDistPromedioDiaDto>> GetListadoDistribucionDistPromedioDiaAsync(int idDistribuidor, int idPublicacion, DateTime fechaDesde, DateTime fechaHasta);
|
||||
Task<(IEnumerable<ListadoDistribucionDistSimpleDto> Simple, IEnumerable<ListadoDistribucionDistPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionDistribuidoresAsync(int idDistribuidor, int idPublicacion, DateTime fechaDesde, DateTime fechaHasta);
|
||||
Task<IEnumerable<LiquidacionCanillaDetalleDto>> GetLiquidacionCanillaDetalleAsync(DateTime fecha, int idCanilla);
|
||||
Task<IEnumerable<LiquidacionCanillaGananciaDto>> GetLiquidacionCanillaGananciasAsync(DateTime fecha, int idCanilla);
|
||||
}
|
||||
}
|
||||
@@ -479,5 +479,41 @@ namespace GestionIntegral.Api.Data.Repositories.Reportes
|
||||
return (Enumerable.Empty<ListadoDistribucionDistSimpleDto>(), Enumerable.Empty<ListadoDistribucionDistPromedioDiaDto>(), "Error interno al generar el reporte.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<LiquidacionCanillaDetalleDto>> GetLiquidacionCanillaDetalleAsync(DateTime fecha, int idCanilla)
|
||||
{
|
||||
const string spName = "dbo.SP_DistCanillasLiquidacion";
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("@fecha", fecha, DbType.DateTime);
|
||||
parameters.Add("@idCanilla", idCanilla, DbType.Int32);
|
||||
try
|
||||
{
|
||||
using var connection = _dbConnectionFactory.CreateConnection();
|
||||
return await connection.QueryAsync<LiquidacionCanillaDetalleDto>(spName, parameters, commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error SP {SPName} para Liquidacion Canilla Detalle. Fecha: {Fecha}, Canilla: {IdCanilla}", spName, fecha, idCanilla);
|
||||
return Enumerable.Empty<LiquidacionCanillaDetalleDto>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<LiquidacionCanillaGananciaDto>> GetLiquidacionCanillaGananciasAsync(DateTime fecha, int idCanilla)
|
||||
{
|
||||
const string spName = "dbo.SP_DistCanillasLiquidacionGanancias";
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("@fecha", fecha, DbType.DateTime);
|
||||
parameters.Add("@idCanilla", idCanilla, DbType.Int32);
|
||||
try
|
||||
{
|
||||
using var connection = _dbConnectionFactory.CreateConnection();
|
||||
return await connection.QueryAsync<LiquidacionCanillaGananciaDto>(spName, parameters, commandType: CommandType.StoredProcedure);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error SP {SPName} para Liquidacion Canilla Ganancias. Fecha: {Fecha}, Canilla: {IdCanilla}", spName, fecha, idCanilla);
|
||||
return Enumerable.Empty<LiquidacionCanillaGananciaDto>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace GestionIntegral.Api.Models.Distribucion
|
||||
{
|
||||
public class PublicacionDiaSemana
|
||||
{
|
||||
public int IdPublicacionDia { get; set; }
|
||||
public int IdPublicacion { get; set; } // FK a dist_dtPublicaciones
|
||||
public byte DiaSemana { get; set; } // 0 (Domingo) a 6 (Sábado)
|
||||
public bool Activo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
[CustomValidation(typeof(CreateBulkEntradaSalidaCanillaDto), nameof(ValidateNoDuplicatePublicationsInItems))]
|
||||
public class CreateBulkEntradaSalidaCanillaDto
|
||||
{
|
||||
[Required(ErrorMessage = "El ID del canillita es obligatorio.")]
|
||||
public int IdCanilla { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "La fecha del movimiento es obligatoria.")]
|
||||
public DateTime Fecha { get; set; } // Fecha común para todos los ítems
|
||||
public DateTime Fecha { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "Debe haber al menos un ítem de movimiento.")]
|
||||
[MinLength(1, ErrorMessage = "Debe agregar al menos una publicación.")]
|
||||
// La validación de cada item se hará por los atributos en EntradaSalidaCanillaItemDto
|
||||
public List<EntradaSalidaCanillaItemDto> Items { get; set; } = new List<EntradaSalidaCanillaItemDto>();
|
||||
|
||||
// Validar que no haya publicaciones duplicadas en la lista de items
|
||||
[CustomValidation(typeof(CreateBulkEntradaSalidaCanillaDto), nameof(ValidateNoDuplicatePublications))]
|
||||
public string? DuplicateError { get; set; }
|
||||
|
||||
public static ValidationResult? ValidateNoDuplicatePublications(CreateBulkEntradaSalidaCanillaDto dto, ValidationContext context)
|
||||
public static ValidationResult? ValidateNoDuplicatePublicationsInItems(CreateBulkEntradaSalidaCanillaDto instanceToValidate, ValidationContext context)
|
||||
{
|
||||
if (dto.Items != null)
|
||||
if (instanceToValidate == null)
|
||||
{
|
||||
var duplicatePublications = dto.Items
|
||||
.GroupBy(item => item.IdPublicacion)
|
||||
return new ValidationResult("El objeto principal de la solicitud es nulo.");
|
||||
}
|
||||
|
||||
if (instanceToValidate.Items == null)
|
||||
{
|
||||
return ValidationResult.Success; // O error si una lista nula de items es inválida
|
||||
}
|
||||
|
||||
if (instanceToValidate.Items.Any())
|
||||
{
|
||||
if (instanceToValidate.Items.Any(item => item == null))
|
||||
{
|
||||
return new ValidationResult("La lista de ítems contiene entradas nulas.", new[] { nameof(Items) });
|
||||
}
|
||||
|
||||
var duplicateGroups = instanceToValidate.Items
|
||||
.Where(item => item.IdPublicacion != 0) // Considerar solo IDs válidos si 0 no lo es
|
||||
.GroupBy(item => item.IdPublicacion)
|
||||
.Where(group => group.Count() > 1)
|
||||
.Select(group => group.Key)
|
||||
.ToList();
|
||||
|
||||
if (duplicatePublications.Any())
|
||||
if (duplicateGroups.Any())
|
||||
{
|
||||
return new ValidationResult($"No puede agregar la misma publicación varias veces. Publicaciones duplicadas: {string.Join(", ", duplicatePublications)}");
|
||||
var duplicatedIds = string.Join(", ", duplicateGroups.Select(g => g.Key));
|
||||
return new ValidationResult(
|
||||
$"No puede agregar la misma publicación varias veces. Publicaciones duplicadas IDs: {duplicatedIds}",
|
||||
new[] { nameof(Items) }
|
||||
);
|
||||
}
|
||||
}
|
||||
return ValidationResult.Success;
|
||||
|
||||
@@ -3,9 +3,11 @@ using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
[CustomValidation(typeof(EntradaSalidaCanillaItemDto), nameof(ValidateCantidadesItem))] // Aplicar a nivel de clase
|
||||
public class EntradaSalidaCanillaItemDto
|
||||
{
|
||||
[Required(ErrorMessage = "El ID de la publicación es obligatorio.")]
|
||||
[Range(1, int.MaxValue, ErrorMessage = "El ID de la publicación debe ser válido.")] // Asegurar que no sea 0
|
||||
public int IdPublicacion { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "La cantidad de salida es obligatoria.")]
|
||||
@@ -17,17 +19,26 @@ namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
public int CantEntrada { get; set; }
|
||||
|
||||
[StringLength(150)]
|
||||
public string? Observacion { get; set; } // Observación por línea
|
||||
public string? Observacion { get; set; }
|
||||
|
||||
// Validar que CantEntrada no sea mayor que CantSalida
|
||||
[CustomValidation(typeof(EntradaSalidaCanillaItemDto), nameof(ValidateCantidades))]
|
||||
public string? CantidadesError { get; set; }
|
||||
// Ya no necesitamos la propiedad CantidadesError para esta validación
|
||||
// public string? CantidadesError { get; set; }
|
||||
|
||||
public static ValidationResult? ValidateCantidades(EntradaSalidaCanillaItemDto item, ValidationContext context)
|
||||
public static ValidationResult? ValidateCantidadesItem(EntradaSalidaCanillaItemDto instanceToValidate, ValidationContext context)
|
||||
{
|
||||
if (item.CantEntrada > item.CantSalida)
|
||||
if (instanceToValidate == null)
|
||||
{
|
||||
return new ValidationResult("La cantidad de entrada (devolución) no puede ser mayor a la cantidad de salida (retiro) para esta publicación.", new[] { nameof(CantEntrada) });
|
||||
// Aunque el model binder debería crear la instancia, verificamos
|
||||
return ValidationResult.Success; // O un error si una instancia nula es inválida por sí misma
|
||||
}
|
||||
|
||||
if (instanceToValidate.CantEntrada > instanceToValidate.CantSalida)
|
||||
{
|
||||
// Asociar el error a ambas propiedades podría ser útil en la UI
|
||||
return new ValidationResult(
|
||||
"La cantidad de entrada (devolución) no puede ser mayor a la cantidad de salida (retiro).",
|
||||
new[] { nameof(CantEntrada), nameof(CantSalida) }
|
||||
);
|
||||
}
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
public class PublicacionDiaSemanaDto
|
||||
{
|
||||
public int IdPublicacionDia { get; set; } // Útil si se editan individualmente
|
||||
public int IdPublicacion { get; set; }
|
||||
public byte DiaSemana { get; set; } // 0 (Domingo) a 6 (Sábado)
|
||||
public bool Activo { get; set; } = true; // Por defecto activo al crear/mostrar
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,36 @@
|
||||
// Similar a E/S Distribuidores, la edición es limitada para no afectar cálculos complejos ya hechos.
|
||||
// Principalmente para corregir cantidades si aún no está liquidado.
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
// Aplicar el CustomValidation a nivel de clase
|
||||
[CustomValidation(typeof(UpdateEntradaSalidaCanillaDto), nameof(ValidateCantidades))]
|
||||
public class UpdateEntradaSalidaCanillaDto
|
||||
{
|
||||
[Required, Range(0, int.MaxValue)]
|
||||
public int CantSalida { get; set; }
|
||||
|
||||
[Required, Range(0, int.MaxValue)]
|
||||
public int CantEntrada { get; set; }
|
||||
|
||||
[StringLength(150)]
|
||||
public string? Observacion { get; set; }
|
||||
|
||||
[CustomValidation(typeof(UpdateEntradaSalidaCanillaDto), nameof(ValidateCantidades))]
|
||||
public string? CantidadesError { get; set; } // Dummy para validación
|
||||
|
||||
public static ValidationResult? ValidateCantidades(UpdateEntradaSalidaCanillaDto dto, ValidationContext context)
|
||||
// El método de validación ahora recibe la instancia completa del DTO
|
||||
public static ValidationResult? ValidateCantidades(UpdateEntradaSalidaCanillaDto instanceToValidate, ValidationContext context)
|
||||
{
|
||||
if (dto.CantEntrada > dto.CantSalida)
|
||||
if (instanceToValidate == null)
|
||||
{
|
||||
return new ValidationResult("La cantidad de entrada no puede ser mayor a la de salida.");
|
||||
// No debería ocurrir si el model binding funcionó, pero es una buena práctica.
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
if (instanceToValidate.CantEntrada > instanceToValidate.CantSalida)
|
||||
{
|
||||
// Asociar el error a las propiedades relevantes si es posible y útil
|
||||
return new ValidationResult(
|
||||
"La cantidad de entrada no puede ser mayor a la de salida.",
|
||||
new[] { nameof(CantEntrada), nameof(CantSalida) } // Opcional: nombres de miembros
|
||||
);
|
||||
}
|
||||
return ValidationResult.Success;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// Este DTO se usará para enviar la lista completa de días activos para una publicación.
|
||||
namespace GestionIntegral.Api.Dtos.Distribucion
|
||||
{
|
||||
public class UpdatePublicacionDiasSemanaRequestDto
|
||||
{
|
||||
// Lista de los días de la semana (0-6) en los que la publicación estará activa.
|
||||
// Si un día no está en esta lista, se considerará inactivo o se eliminará la configuración para ese día.
|
||||
public List<byte> DiasActivos { get; set; } = new List<byte>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class LiquidacionCanillaDetalleDto
|
||||
{
|
||||
public string Publicacion { get; set; } = string.Empty;
|
||||
public string Canilla { get; set; } = string.Empty; // Para el nombre del canilla en el reporte
|
||||
public int TotalCantSalida { get; set; }
|
||||
public int TotalCantEntrada { get; set; }
|
||||
public decimal TotalRendir { get; set; }
|
||||
public decimal PrecioEjemplar { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
public class LiquidacionCanillaGananciaDto
|
||||
{
|
||||
public string Publicacion { get; set; } = string.Empty;
|
||||
public decimal TotalRendir { get; set; } // Asumo que este es el 'monto de comisión'
|
||||
}
|
||||
@@ -222,10 +222,10 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
{
|
||||
if (connection is System.Data.Common.DbConnection dbConnOpen && connection.State == ConnectionState.Closed) await dbConnOpen.OpenAsync();
|
||||
else if (connection.State == ConnectionState.Closed) connection.Open();
|
||||
|
||||
|
||||
transaction = connection.BeginTransaction();
|
||||
|
||||
var esExistente = await _esCanillaRepository.GetByIdAsync(idParte);
|
||||
var esExistente = await _esCanillaRepository.GetByIdAsync(idParte); // Obtener el estado actual
|
||||
if (esExistente == null)
|
||||
{
|
||||
if (transaction?.Connection != null) transaction.Rollback();
|
||||
@@ -234,17 +234,16 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
|
||||
if (esExistente.Liquidado)
|
||||
{
|
||||
// Permiso MC006 es para "Eliminar Movimientos de Canillita Liquidados"
|
||||
if (!TienePermisoEspecifico("MC006"))
|
||||
if (!TienePermisoEspecifico("MC006")) // <--- AQUÍ ESTÁ LA VERIFICACIÓN
|
||||
{
|
||||
if (transaction?.Connection != null) transaction.Rollback();
|
||||
return (false, "No tiene permiso para eliminar movimientos ya liquidados. Se requiere permiso especial (MC006) o ser SuperAdmin.");
|
||||
}
|
||||
_logger.LogWarning("Usuario ID {IdUsuario} está eliminando un movimiento LIQUIDADO (IDParte: {IdParte}). Permiso MC006 verificado.", idUsuario, idParte);
|
||||
}
|
||||
// Si no está liquidado, el permiso MC004 ya fue verificado en el controlador.
|
||||
// Si no está liquidado, el permiso MC004 ya fue verificado en el controlador (o debería serlo).
|
||||
|
||||
var eliminado = await _esCanillaRepository.DeleteAsync(idParte, idUsuario, transaction);
|
||||
var eliminado = await _esCanillaRepository.DeleteAsync(idParte, idUsuario, transaction); // Ahora esto no lanzará la excepción por liquidado
|
||||
if (!eliminado)
|
||||
{
|
||||
// No es necesario hacer rollback aquí si DeleteAsync lanza una excepción,
|
||||
@@ -258,10 +257,10 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
_logger.LogInformation("Movimiento Canillita ID {IdParte} eliminado por Usuario ID {IdUsuario}.", idParte, idUsuario);
|
||||
return (true, null);
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
if (transaction?.Connection != null) try { transaction.Rollback(); } catch (Exception exR) { _logger.LogError(exR, "Rollback fallido KeyNotFoundException."); }
|
||||
return (false, "Movimiento no encontrado.");
|
||||
return (false, "Movimiento no encontrado.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -11,5 +11,8 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
Task<(PublicacionDto? Publicacion, string? Error)> CrearAsync(CreatePublicacionDto createDto, int idUsuario);
|
||||
Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdatePublicacionDto updateDto, int idUsuario);
|
||||
Task<(bool Exito, string? Error)> EliminarAsync(int id, int idUsuario);
|
||||
Task<IEnumerable<PublicacionDiaSemanaDto>> ObtenerConfiguracionDiasAsync(int idPublicacion);
|
||||
Task<IEnumerable<PublicacionDto>> ObtenerPublicacionesPorDiaSemanaAsync(byte diaSemana); // Devolvemos el DTO completo
|
||||
Task<(bool Exito, string? Error)> ActualizarConfiguracionDiasAsync(int idPublicacion, UpdatePublicacionDiasSemanaRequestDto requestDto, int idUsuario);
|
||||
}
|
||||
}
|
||||
@@ -202,5 +202,71 @@ namespace GestionIntegral.Api.Services.Distribucion
|
||||
return (false, $"Error interno al eliminar la publicación y sus dependencias: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PublicacionDiaSemanaDto>> ObtenerConfiguracionDiasAsync(int idPublicacion)
|
||||
{
|
||||
var configs = await _publicacionRepository.GetConfiguracionDiasAsync(idPublicacion);
|
||||
return configs.Select(c => new PublicacionDiaSemanaDto
|
||||
{
|
||||
IdPublicacionDia = c.IdPublicacionDia,
|
||||
IdPublicacion = c.IdPublicacion,
|
||||
DiaSemana = c.DiaSemana,
|
||||
Activo = c.Activo
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PublicacionDto>> ObtenerPublicacionesPorDiaSemanaAsync(byte diaSemana)
|
||||
{
|
||||
// Obtener IDs de las publicaciones configuradas para ese día
|
||||
var idsPublicaciones = await _publicacionRepository.GetPublicacionesIdsPorDiaSemanaAsync(diaSemana);
|
||||
|
||||
if (!idsPublicaciones.Any())
|
||||
{
|
||||
return Enumerable.Empty<PublicacionDto>();
|
||||
}
|
||||
|
||||
// Obtener los detalles completos de esas publicaciones
|
||||
// Podríamos optimizar esto si GetByIdAsync es eficiente o crear un GetByIdsAsync
|
||||
var publicacionesTasks = idsPublicaciones.Select(id => ObtenerPorIdAsync(id));
|
||||
var publicacionesResult = await Task.WhenAll(publicacionesTasks);
|
||||
|
||||
return publicacionesResult.Where(p => p != null).Select(p => p!); // Filtrar nulos y asegurar no nulabilidad
|
||||
}
|
||||
|
||||
|
||||
public async Task<(bool Exito, string? Error)> ActualizarConfiguracionDiasAsync(int idPublicacion, UpdatePublicacionDiasSemanaRequestDto requestDto, int idUsuario)
|
||||
{
|
||||
var publicacionExistente = await _publicacionRepository.GetByIdSimpleAsync(idPublicacion);
|
||||
if (publicacionExistente == null)
|
||||
{
|
||||
return (false, "Publicación no encontrada.");
|
||||
}
|
||||
|
||||
// Validar que los días de la semana estén en el rango correcto (0-6)
|
||||
if (requestDto.DiasActivos.Any(d => d > 6)) // byte no puede ser < 0
|
||||
{
|
||||
return (false, "Día de la semana inválido. Debe estar entre 0 (Domingo) y 6 (Sábado).");
|
||||
}
|
||||
|
||||
using var connection = _connectionFactory.CreateConnection();
|
||||
if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open();
|
||||
using var transaction = connection.BeginTransaction();
|
||||
try
|
||||
{
|
||||
await _publicacionRepository.UpdateConfiguracionDiasAsync(idPublicacion, requestDto.DiasActivos.Distinct(), transaction);
|
||||
// No se está implementando historial para PublicacionDiaSemana por ahora.
|
||||
// Si se necesitara, se añadiría aquí una llamada al repositorio para insertar en la tabla _H.
|
||||
|
||||
transaction.Commit();
|
||||
_logger.LogInformation("Configuración de días actualizada para Publicación ID {IdPublicacion} por Usuario ID {UserId}.", idPublicacion, idUsuario);
|
||||
return (true, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
try { transaction.Rollback(); } catch { }
|
||||
_logger.LogError(ex, "Error al actualizar configuración de días para Publicacion ID: {IdPublicacion}", idPublicacion);
|
||||
return (false, $"Error interno al actualizar la configuración de días: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,5 +63,11 @@ namespace GestionIntegral.Api.Services.Reportes
|
||||
)> ObtenerReporteCuentasDistribuidorAsync(int idDistribuidor, int idEmpresa, DateTime fechaDesde, DateTime fechaHasta);
|
||||
|
||||
Task<(IEnumerable<ListadoDistribucionDistSimpleDto> Simple, IEnumerable<ListadoDistribucionDistPromedioDiaDto> Promedios, string? Error)> ObtenerListadoDistribucionDistribuidoresAsync(int idDistribuidor, int idPublicacion, DateTime fechaDesde, DateTime fechaHasta);
|
||||
|
||||
Task<(
|
||||
IEnumerable<LiquidacionCanillaDetalleDto> Detalles,
|
||||
IEnumerable<LiquidacionCanillaGananciaDto> Ganancias,
|
||||
string? Error
|
||||
)> ObtenerDatosTicketLiquidacionAsync(DateTime fecha, int idCanilla);
|
||||
}
|
||||
}
|
||||
@@ -449,5 +449,46 @@ namespace GestionIntegral.Api.Services.Reportes
|
||||
return (Enumerable.Empty<ListadoDistribucionDistSimpleDto>(), Enumerable.Empty<ListadoDistribucionDistPromedioDiaDto>(), "Error interno al generar el reporte.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<(
|
||||
IEnumerable<LiquidacionCanillaDetalleDto> Detalles,
|
||||
IEnumerable<LiquidacionCanillaGananciaDto> Ganancias,
|
||||
string? Error
|
||||
)> ObtenerDatosTicketLiquidacionAsync(DateTime fecha, int idCanilla)
|
||||
{
|
||||
try
|
||||
{
|
||||
var detallesTask = _reportesRepository.GetLiquidacionCanillaDetalleAsync(fecha, idCanilla);
|
||||
var gananciasTask = _reportesRepository.GetLiquidacionCanillaGananciasAsync(fecha, idCanilla);
|
||||
|
||||
await Task.WhenAll(detallesTask, gananciasTask);
|
||||
|
||||
var detalles = await detallesTask;
|
||||
var ganancias = await gananciasTask;
|
||||
|
||||
if ((detalles == null || !detalles.Any()) && (ganancias == null || !ganancias.Any()))
|
||||
{
|
||||
// Podrías optar por no devolver error aquí si es válido que uno de los dos esté vacío
|
||||
// y manejarlo en el controlador o el RDLC.
|
||||
}
|
||||
|
||||
// Convertir fechas a UTC si es necesario para el RDLC (aunque estos DTOs no tienen fechas)
|
||||
|
||||
return (
|
||||
detalles ?? Enumerable.Empty<LiquidacionCanillaDetalleDto>(),
|
||||
ganancias ?? Enumerable.Empty<LiquidacionCanillaGananciaDto>(),
|
||||
null
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error en ReportesService al obtener datos para Ticket Liquidación Canilla. Fecha: {Fecha}, Canilla: {IdCanilla}", fecha, idCanilla);
|
||||
return (
|
||||
Enumerable.Empty<LiquidacionCanillaDetalleDto>(),
|
||||
Enumerable.Empty<LiquidacionCanillaGananciaDto>(),
|
||||
"Error interno al obtener los datos para el ticket de liquidación."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=TECNICA3;Database=gestionvbnet;User ID=apigestion;Password=1351;Encrypt=False;TrustServerCertificate=True;"
|
||||
"DefaultConnection": "Server=TECNICA3;Database=gestionvbnet;User ID=apigestion;Password=1351;Encrypt=False;MultipleActiveResultSets=True;TrustServerCertificate=True;"
|
||||
},
|
||||
"Jwt": {
|
||||
"Key": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=TECNICA3;Database=gestionvbnet;User ID=apigestion;Password=1351;Encrypt=False;TrustServerCertificate=True;"
|
||||
"DefaultConnection": "Server=TECNICA3;Database=gestionvbnet;User ID=apigestion;Password=1351;Encrypt=False;MultipleActiveResultSets=True;TrustServerCertificate=True;"
|
||||
},
|
||||
"Jwt": {
|
||||
"Key": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2",
|
||||
|
||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
||||
[assembly: System.Reflection.AssemblyCompanyAttribute("GestionIntegral.Api")]
|
||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+1182a4cdee4fcdb55dc3f2dbfeeb2ec2187f2bea")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+99532b03f191d55f42e738a90b97f9f1e0dc1a9c")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("GestionIntegral.Api")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("GestionIntegral.Api")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"C9goqBDGh4B0L1HpPwpJHjfbRNoIuzqnU7zFMHk1LhM=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["lgiSIq1Xdt6PC6CpA82eiZlqBZS3M8jckHELlrL00LI=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","OZUau2FUwouOUoP6Eot2qiZlqRHSBBkSPL6vHtWUfGI="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"C9goqBDGh4B0L1HpPwpJHjfbRNoIuzqnU7zFMHk1LhM=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["V/5slELlkFDzZ8iiVKV8Jt0Ia8AL5AZxPCWo9apx5lQ=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","k3qzLxTWHeeJhAuWKMdta6j24bmJ9BMRMjuFEEVCRu0=","x/sHyso3gy4zVCu3ljpnTYCqu8IGZNRok1JoXiabIP8=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","hUWSz0FL2Jxxt3J4cPvysP9naCA2/Cxeo8sJx8s2hvs="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"w3MBbMV9Msh0YEq9AW/8s16bzXJ93T9lMVXKPm/r6es=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["lgiSIq1Xdt6PC6CpA82eiZlqBZS3M8jckHELlrL00LI=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","OZUau2FUwouOUoP6Eot2qiZlqRHSBBkSPL6vHtWUfGI="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"w3MBbMV9Msh0YEq9AW/8s16bzXJ93T9lMVXKPm/r6es=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["V/5slELlkFDzZ8iiVKV8Jt0Ia8AL5AZxPCWo9apx5lQ=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y=","\u002BzMwu5DIAA49kPmSydn2WMzj\u002Bdcf0MC3YakKoR6HwYg=","FUb20tYUiusFv5/KhAPdh2OB4ArUWiGApXbQJdx8tX0=","pTWqrhLBwEeWg1GsRlTKzfOAnT1JEklZ8F1/EYlc1Nk=","Hu0oNH4YYNcbnR5Ts4qd5yzC5j5JbY2kEDXces8V1vs=","TKMARE0bLM2dm9NOqxxWztnuqao5IvCh24TEHCtht6I=","84UEEMEbmmNwHVXD5Iw3dtKHTZC0Zqbk3rIRO\u002BxOq4o=","qfTzsJ\u002B5ilLyrc6EhNm61KkSH37yRi85MtgW1\u002BUD2Vo=","4ayt/JAApEOfr0yjg9szkYMPzSs6x2k3QEwmrK5RZVY=","d0weYwKWe3mH5R2BURuNLkAyytO/viA6zivv9AcIBtQ=","Ssyx6SvSGgWMOzhc9pQpk6f6\u002BmVbKQNKeDJbvVA2tjs=","FSqDybxILZmKXw160ANhj76usnM83geRrbPvJxr89OA=","k3qzLxTWHeeJhAuWKMdta6j24bmJ9BMRMjuFEEVCRu0=","x/sHyso3gy4zVCu3ljpnTYCqu8IGZNRok1JoXiabIP8=","fdI2RZZ9M9QOVHCYU5cE\u002BgVVuT7ssRbMzdXvX8rHofc=","8ePFhqKT0OT9nEg3b5T7COC81U\u002BQBcf\u002BindBGyMy6z0=","/ghcduGmSd1I25YtYli\u002BqxF0xuscxc4cTDkbEC6XYVA=","/a3YEu0oBUeA5Qr2VMdppqLuz4CQPWJt2JfBl2dtUwA=","jEO/q4IO3UFTWxlyFwRr7kbGWcTIiS\u002BClxx3kahX/Fk=","4iYOCKYvhsROdGkA1hINVBejb6r8IkwFj9SNMKub3DM=","CeDswsZIn5a7t\u002BKeHJA222yhFvDVVEW1ky98Xxnxebc=","50j34YXOc950QSqaQBMtgezD3tV5mWWR9c5qZcYQoz4=","W/aX9jIKpjNEVoGrU6RXFOY8SDJVT6XB4Rg4QCaeQkQ=","16IbB\u002B3zYHZvsWbCQK6hBFmKJ6Z28SecBn2jm8R3w8I=","COJtHNQqycTJqXkFv2hhpLUT\u002B/AD4IWyQlmxkUVQPNk=","cp6a5bdvkLnUn3x47KQODzPycnx57RmWO\u002B9q8MuoGQo=","oKZRNhIQRaZrETEa3L6JiwIp0\u002BmjzJo193EWBoCuVUg=","sjwbCAEQX51sEWhYVGBihWUNBxniUKZALVJIGK\u002BYgsk=","A4m4kVcox60bvdkJ1CswoZADAT70WPcs4TAKdpMoUjM=","zSzyOuNcK0NQJLwK8Yg4sH4EflX7RPf65Fl2CZUWIGs=","hUWSz0FL2Jxxt3J4cPvysP9naCA2/Cxeo8sJx8s2hvs="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
@@ -1 +1 @@
|
||||
{"GlobalPropertiesHash":"nueagD6vos1qa5Z6EdwL+uix/UGN3umfwM2JskZDeIQ=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["lgiSIq1Xdt6PC6CpA82eiZlqBZS3M8jckHELlrL00LI=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
{"GlobalPropertiesHash":"nueagD6vos1qa5Z6EdwL+uix/UGN3umfwM2JskZDeIQ=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["V/5slELlkFDzZ8iiVKV8Jt0Ia8AL5AZxPCWo9apx5lQ=","bxlPVWHR7EivQofjz9PzA8dMpKpZqCfOZ\u002BHD\u002Bf1Ew9Y="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||
Reference in New Issue
Block a user