This commit is contained in:
2025-04-12 16:31:09 -07:00
3 changed files with 426 additions and 86 deletions

View File

@@ -481,15 +481,16 @@ Public Class ClsOP
Return Retorno
End Function
Public Function GetEstatusOP(CveEmpresa As Integer, Optional CveEstatusOP As Integer = -1, Optional TipoEstatus As Integer = -1, Optional Estatus As Integer = -1) As Boolean
Public Function GetEstatusOP(CveEmpresa As Integer, Optional CveEstatusOP As Integer = -1, Optional TipoEstatus As Integer = -1, Optional Estatus As Integer = -1, Optional CveUsuario As Integer = -1) As Boolean
Dim Retorno As Boolean = False
DataAdapter("PA_OP_EstatusOPGet")
With SqlAdapter.SelectCommand.Parameters
.Add("@CveEmpresa", SqlDbType.Int).Value = CveEmpresa
.Add("@CveEstatusOP", SqlDbType.Int).Value = CveEstatusOP
.Add("@TipoEstatus", SqlDbType.Int).Value = TipoEstatus
.Add("@Estatus", SqlDbType.Int).Value = Estatus
.Add("@cveEmpresa", SqlDbType.Int).Value = CveEmpresa
.Add("@cveEstatusOP", SqlDbType.Int).Value = CveEstatusOP
.Add("@tipoEstatus", SqlDbType.Int).Value = TipoEstatus
.Add("@estatus", SqlDbType.Int).Value = Estatus
.Add("@cveUsuario", SqlDbType.Int).Value = CveUsuario
End With
Try
SqlAdapter.Fill(Data)

View File

@@ -279,6 +279,36 @@
padding: 5px;
margin-top: 10px;
}
.quantity-control {
position: relative;
display: flex;
align-items: center;
width: 120px;
}
.quantity-input {
width: 70px !important;
padding-right: 30px;
}
.quantity-buttons {
position: absolute;
right: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.btn-quantity {
padding: 0;
width: 22px;
height: 18px;
line-height: 1;
border: 1px solid #ddd;
background: #f8f9fa;
cursor: pointer;
}
</style>
</asp:Content>
@@ -466,7 +496,8 @@
<div class="col-md-12">
<div class="section-title">Productos</div>
<asp:GridView ID="GvProductos" runat="server" AutoGenerateColumns="False"
CssClass="table table-striped table-hover" GridLines="None" Width="100%">
CssClass="table table-striped table-hover" GridLines="None" Width="100%"
OnRowDataBound="GvProductos_RowDataBound">
<Columns>
<asp:BoundField DataField="PSCodigo" HeaderText="Producto" />
<asp:BoundField DataField="UnidadMedida" HeaderText="UM" />
@@ -754,67 +785,115 @@
<h4 class="modal-title">Finalizar Orden de Producción #<%= LblFolio.Text %></h4>
</div>
<div class="modal-body">
<!-- Almacén de Materia Prima (Fijo) -->
<!-- Sección de Almacenes -->
<div class="row">
<div class="col-md-6 form-group">
<label>Almacén de Salida (Materia Prima):</label>
<!-- Almacén Salida MP -->
<div class="col-md-4 form-group">
<label>Almacén Salida (MP):</label>
<asp:DropDownList ID="DdlAlmacenOrigenSalidaMP" runat="server"
DataTextField="Almacen" DataValueField="CveAlmacen"
CssClass="form-control select2me" />
</div>
<!-- Almacén de Producto Terminado (Dropdown) -->
<div class="col-md-6 form-group">
<label>Almacén de Entrada (Producto Terminado):</label>
<!-- Almacén Entrada PT -->
<div class="col-md-4 form-group">
<label>Almacén Entrada (PT):</label>
<asp:DropDownList ID="DdlAlmacenTerminado" runat="server"
DataTextField="Almacen" DataValueField="CveAlmacen"
CssClass="form-control select2me" />
</div>
<!-- Almacén Devoluciones -->
<div class="col-md-4 form-group">
<label>Almacén Devoluciones:</label>
<asp:DropDownList ID="DdlAlmacenDevolucion" runat="server"
DataTextField="Almacen" DataValueField="CveAlmacen"
CssClass="form-control select2me" />
</div>
</div>
<!-- GridViews -->
<div class="row">
<div class="col-md-12">
<div class="section-title">Producto Terminado</div>
<asp:GridView ID="GvProductoTerminado" runat="server" AutoGenerateColumns="False"
CssClass="table table-striped table-hover" GridLines="None" Width="100%">
CssClass="table table-striped table-hover" GridLines="None" Width="100%"
OnRowDataBound="GvProductoTerminado_RowDataBound">
<Columns>
<asp:BoundField DataField="PSCodigo" HeaderText="Producto" />
<asp:BoundField DataField="UnidadMedida" HeaderText="UM" />
<asp:BoundField DataField="Cantidad" HeaderText="Cantidad" DataFormatString="{0:N2}" />
<asp:TemplateField HeaderText="Cantidad">
<ItemTemplate>
<asp:TextBox ID="TxtCantidadPT" runat="server"
Text='<%# Bind("Cantidad") %>'
CssClass="form-control"
TextMode="Number"
min="0"
step="1"
data-original='<%# Eval("Cantidad") %>'
onchange="validarCantidad(this)" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="section-title">Materia Prima</div>
<asp:GridView ID="GvMPUtilizada" runat="server" AutoGenerateColumns="False"
<asp:GridView ID="GvMPUtilizada" runat="server" AutoGenerateColumns="False" DataKeyNames="CvePSMateriaPrima, CveUMMateriaPrima"
CssClass="table table-striped table-hover" GridLines="None" Width="100%">
<Columns>
<asp:BoundField DataField="PSCodigo" HeaderText="Producto" />
<asp:BoundField DataField="Cantidad" HeaderText="Cantidad" DataFormatString="{0:N2}" />
<asp:TemplateField HeaderText="Devolución">
<ItemTemplate>
<asp:TextBox ID="TxtDevolucionMP" runat="server"
Text="0"
CssClass="form-control"
TextMode="Number"
min="0"
step="1"
data-original='<%# Eval("Cantidad") %>'
onchange="validarCantidad(this)" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</div>
</div>
<div class="modal-footer">
<%-- Botón Guardar --%>
<asp:Button ID="BtnGuardarFinalizarOP" runat="server" Text="Guardar"
CssClass="btn btn-primary" OnClick="BtnGuardarFinalizarOP_Click" />
<%-- Botón Cerrar --%>
<button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>
</div>
<asp:Button ID="BtnGuardarFinalizarOP" runat="server" Text="Guardar"
CssClass="btn btn-primary" OnClick="BtnGuardarFinalizarOP_Click" />
<button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
</asp:Content>
<asp:Content ID="Content8" ContentPlaceHolderID="JS" runat="Server">
<script>
function validarCantidad(input) {
var valor = parseFloat(input.value) || 0;
var maximo = parseFloat(input.getAttribute('data-original')) || 0;
if (valor > maximo) {
input.value = maximo.toFixed(4);
alert("¡La cantidad no puede superar el valor original!");
}
}
</script>
</asp:Content>

View File

@@ -41,7 +41,15 @@ Partial Class OP_OP
Private Property DtMO As DataTable
Get
Return DirectCast(ViewState("DtMO"), DataTable)
If ViewState("DtMO") Is Nothing Then
DtMO = New DataTable()
DtMO.Columns.Add("CvePS", GetType(Integer)) ' Producto asociado
DtMO.Columns.Add("CvePuesto", GetType(Integer))
DtMO.Columns.Add("Puesto", GetType(String))
DtMO.Columns.Add("CostoHora", GetType(Decimal))
DtMO.Columns.Add("Total", GetType(Decimal))
End If
Return CType(ViewState("DtMO"), DataTable)
End Get
Set(value As DataTable)
ViewState("DtMO") = value
@@ -50,13 +58,31 @@ Partial Class OP_OP
Private Property DtCI As DataTable
Get
Return DirectCast(ViewState("DtCI"), DataTable)
If ViewState("DtCI") Is Nothing Then
DtCI = New DataTable()
DtCI.Columns.Add("CvePS", GetType(Integer)) ' Producto asociado
DtCI.Columns.Add("CvePSMateriaPrima", GetType(Integer))
DtCI.Columns.Add("productoMateriaPrima", GetType(String))
DtCI.Columns.Add("Cantidad", GetType(Decimal))
DtCI.Columns.Add("PU", GetType(Decimal))
DtCI.Columns.Add("Total", GetType(Decimal))
End If
Return CType(ViewState("DtCI"), DataTable)
End Get
Set(value As DataTable)
ViewState("DtCI") = value
End Set
End Property
Private Property TipoEstatus As Integer
Get
Return ViewState("TipoEstatus").ToString.ToEntero
End Get
Set(value As Integer)
ViewState("TipoEstatus") = value
End Set
End Property
Private Property DtMPAgregados As DataTable
Get
If ViewState("DtMPAgregados") Is Nothing Then
@@ -74,12 +100,27 @@ Partial Class OP_OP
End Set
End Property
Private Property DtDevoluciones As DataTable
Get
If ViewState("DtDevoluciones") Is Nothing Then
DtDevoluciones = New DataTable()
DtDevoluciones.Columns.Add("CvePS", GetType(Integer))
DtDevoluciones.Columns.Add("Devolucion", GetType(Decimal))
DtDevoluciones.Columns.Add("CveAlmacenDevolucion", GetType(Integer))
End If
Return CType(ViewState("DtDevoluciones"), DataTable)
End Get
Set(value As DataTable)
ViewState("DtDevoluciones") = value
End Set
End Property
#End Region
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
CveOP = If(Request("CveOP") <> "", Request("CveOP").ToString.ToEntero, "-1".ToEntero)
TipoEstatus = -1
CreaPS()
SetValues()
End If
@@ -106,6 +147,7 @@ Partial Class OP_OP
DtMP.Columns.Add("UnidadMedida", GetType(String))
DtMP.Columns.Add("Cantidad", GetType(Decimal))
DtMP.Columns.Add("Surtido", GetType(Decimal))
'DtMP.Columns.Add("CvePSProducto", GetType(Integer))
'DtMP.Columns.Add("CveAlmacenDestino", GetType(Integer))
DtMO = New DataTable()
@@ -115,15 +157,17 @@ Partial Class OP_OP
DtMO.Columns.Add("CvePuesto", GetType(Integer))
DtMO.Columns.Add("Puesto", GetType(String))
DtMO.Columns.Add("Cantidad", GetType(Decimal))
DtMO.Columns.Add("CostoHora", GetType(Decimal))
DtMO.Columns.Add("Total", GetType(Decimal))
DtCI = New DataTable()
DtCI.Columns.Add("Tipo", GetType(String)) ' Producto, MP, MO, CI
DtCI.Columns.Add("Clave", GetType(Integer))
'DtCI.Columns.Add("CveUM", GetType(Integer))
'DtCI.Columns.Add("CvePSMateriaPrima", GetType(Integer))
'DtCI.Columns.Add("CveUMMateriaPrima", GetType(Integer))
DtCI.Columns.Add("productoMateriaPrima", GetType(String))
DtCI.Columns.Add("Cantidad", GetType(Decimal))
DtCI.Columns.Add("PU", GetType(Decimal))
DtCI.Columns.Add("Total", GetType(Decimal))
End Sub
@@ -133,24 +177,65 @@ Partial Class OP_OP
CargarClientes()
CargarCentrosDeCosto(DdlProyecto, DdlSubProyecto, LblProyecto, LblSubProyecto, divProyecto:=DivProyecto, VisualizacionReporte:=1)
CargarProductos()
CargaDatos()
If CveOP = -1 Then
DdlClientes.Enabled = True
DdlProyecto.Enabled = True
DdlSubProyecto.Enabled = True
DdlPS.Enabled = True
LnkSolicitarMP.Visible = False
BtnSimularMP.Visible = True
BtnFinalizarOP.Visible = False
If TipoEstatus = 3 Then
DeshabilitarControles() ' Deshabilita todos los controles relevantes
Else
DdlClientes.Enabled = False
DdlPS.Enabled = False
LnkSolicitarMP.Visible = False
BtnSimularMP.Visible = False
BtnFinalizarOP.Visible = True
CargaDatos()
If CveOP = -1 Then ' Nueva OP
DdlClientes.Enabled = True
DdlProyecto.Enabled = True
DdlSubProyecto.Enabled = True
DdlPS.Enabled = True
TxtEstatus.Enabled = True ' Estatus no editable
LnkSolicitarMP.Visible = False
BtnSimularMP.Visible = True
BtnFinalizarOP.Visible = False
Else ' OP existente no finalizada
If TipoEstatus <> 3 Then
DdlClientes.Enabled = True
DdlProyecto.Enabled = True
DdlSubProyecto.Enabled = True
DdlPS.Enabled = True
TxtDescripcion.Enabled = True
Txtfecha.Enabled = True
TxtEstatus.Enabled = True ' Estatus no editable
BtnAgregarProducto.Enabled = True
BtnSimularMP.Visible = False
BtnGuardarOP.Enabled = True
BtnFinalizarOP.Visible = True
imgCalendarioF.Enabled = True
LnkSolicitarMP.Visible = True
End If
End If
End If
UpOP.Update()
UpGvDatosOP.Update()
End Sub
Private Sub DeshabilitarControles()
' Deshabilitar DropDownLists
DdlClientes.Enabled = False
DdlProyecto.Enabled = False
DdlSubProyecto.Enabled = False
DdlPS.Enabled = False
' Deshabilitar TextBox y Date
TxtDescripcion.Enabled = False
Txtfecha.Enabled = False
imgCalendarioF.Enabled = False
TxtEstatus.Enabled = False
' Ocultar Botones
BtnAgregarProducto.Visible = False
BtnSimularMP.Visible = False
BtnGuardarOP.Visible = False
BtnFinalizarOP.Visible = False
LnkSolicitarMP.Visible = False
UpOP.Update()
UpGvDatosOP.Update()
End Sub
Private Sub CargaDatos()
@@ -169,6 +254,7 @@ Partial Class OP_OP
DdlPS.txtValue.Value = dr("CvePS").ToString
Txtfecha.Text = dr("Fecha").ToString
TxtDescripcion.Text = dr("Descripcion").ToString
TipoEstatus = dr("TipoEstatus").ToString.ToEntero
If ObjOP.GetProductosOP(CveOP, UsuarioActual.CveEmpresa) Then
@@ -221,7 +307,7 @@ Partial Class OP_OP
Dim newRow As DataRow = DtCI.NewRow()
newRow("Tipo") = "CI"
newRow("productoMateriaPrima") = rowCI("producto").ToString
newRow("Cantidad") = rowCI("Cantidad").ToString.ToDecimal
newRow("Costo") = rowCI("Costo").ToString.ToDecimal
DtCI.Rows.Add(newRow)
Next
@@ -292,6 +378,7 @@ Partial Class OP_OP
rowMP("PSCodigo") = drMP("productoMateriaPrima").ToString()
rowMP("UnidadMedida") = drMP("UnidadMedidaMateriaPrima").ToString()
rowMP("Cantidad") = drMP("Cantidad").ToString().ToDecimal()
'rowMP("CvePSProducto") = CvePS
rowMP("Surtido") = 0
DtMP.Rows.Add(rowMP)
Next
@@ -306,6 +393,8 @@ Partial Class OP_OP
rowMO("Clave") = CvePS
rowMO("Puesto") = drMO("Puesto").ToString()
rowMO("Cantidad") = drMO("Cantidad").ToString().ToDecimal()
rowMO("CostoHora") = drMO("precioHora").ToString.ToDecimal()
rowMO("Total") = drMO("Cantidad").ToString().ToDecimal() * drMO("precioHora").ToString().ToDecimal()
DtMO.Rows.Add(rowMO)
Next
End If
@@ -321,6 +410,8 @@ Partial Class OP_OP
'rowCI("CvePSMateriaPrima") = drCI("CvePSMateriaPrima").ToString().ToEntero()
rowCI("productoMateriaPrima") = drCI("productoMateriaPrima").ToString()
rowCI("Cantidad") = drCI("Cantidad").ToString().ToDecimal()
rowCI("PU") = drCI("ImporteCostoIndirecto").ToString().ToDecimal()
rowCI("Total") = rowCI("Cantidad").ToString().ToDecimal() * rowCI("PU").ToString().ToDecimal()
DtCI.Rows.Add(rowCI)
Next
End If
@@ -329,6 +420,12 @@ Partial Class OP_OP
End Sub
Protected Sub BtnEliminarProducto_Click(sender As Object, e As EventArgs)
' Verificar si la OP está finalizada
If TxtEstatus.Text = "Finalizada" Then
Alert("No se pueden eliminar productos de una OP finalizada.", TipoMensaje.MsgAdvertencia)
Exit Sub
End If
Dim btnEliminar As LinkButton = DirectCast(sender, LinkButton)
Dim CveProducto As Integer = btnEliminar.CommandArgument.ToEntero()
@@ -361,6 +458,13 @@ Partial Class OP_OP
Next
End Sub
Protected Sub GvProductos_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GvProductos.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim btnEliminar As LinkButton = DirectCast(e.Row.FindControl("BtnEliminar"), LinkButton)
btnEliminar.Visible = (TipoEstatus <> 3)
End If
End Sub
Protected Sub LnkSolicitarMP_Click(sender As Object, e As EventArgs)
' Cargar almacenes
DdlAlmacenOrigenMP.DataSource = GlobalDTAlmacen(UsuarioActual.CveEmpresa).FiltraParametros("CveTipoAlmacen = 1")
@@ -560,16 +664,16 @@ Partial Class OP_OP
Dim MensajeExistencia As New StringBuilder
MensajeExistencia.Append("No hay la existencia suficiente de los siguientes productos:<br/>")
'✅ 1. Validar existencias de MP
For Each row As GridViewRow In GvMPAgregados.Rows
'✅ Obtener claves CORRECTAS de la materia prima
Dim CveMP As Integer = GvMPAgregados.DataKeys(row.RowIndex)("CvePSMateriaPrima").ToString().ToEntero()
Dim CveUMMP As Integer = GvMPAgregados.DataKeys(row.RowIndex)("CveUMMateriaPrima").ToString().ToEntero()
Dim CantidadSolicitada As Decimal = DtMP.Rows(row.RowIndex)("Cantidad").ToString().ToDecimal()
'DtMP.Rows(row.RowIndex)("CveAlmacenDestino") = DdlAlmacenDestinoMP.SelectedValue.ToEntero()
'✅ Verificar existencias
Dim Existencia As Decimal = ObjInventario.GetExistenciasPS(
CvePS:=CveMP,
CveUnidadMedida:=CveUMMP,
@@ -596,7 +700,7 @@ Partial Class OP_OP
Exit Sub
End If
'✅ 2. Crear traspaso si todo está correcto
ObjInventario.IniciaTransacSQL()
Dim TieneError As Boolean = False
@@ -618,10 +722,10 @@ Partial Class OP_OP
TieneError = True
End If
'✅ 3. Agregar detalles del traspaso
If Not TieneError Then
For Each row As GridViewRow In GvMPAgregados.Rows
'✅ Usar claves de MATERIA PRIMA (CvePSMateriaPrima y CveUMMateriaPrima)
Dim CveMP As Integer = GvMPAgregados.DataKeys(row.RowIndex)("CvePSMateriaPrima").ToString().ToEntero()
Dim CveUMMP As Integer = GvMPAgregados.DataKeys(row.RowIndex)("CveUMMateriaPrima").ToString().ToEntero()
Dim Cantidad As Decimal = DtMP.Rows(row.RowIndex)("Cantidad").ToString().ToDecimal()
@@ -629,8 +733,8 @@ Partial Class OP_OP
If Not ObjInventario.AddTrasladoSolicitudDetalle(
CveTraspasoSolicitud,
Cantidad,
CveUMMP, '✅ Unidad de medida de la MP
CveMP, '✅ Clave de la MP
CveUMMP,
CveMP,
0, "", -1, "-1", "-1", MinFecha
) Then
TieneError = True
@@ -639,7 +743,7 @@ Partial Class OP_OP
Next
End If
'✅ 4. Confirmar o cancelar transacción
If Not TieneError Then
ObjInventario.Commit()
Alert($"Solicitud de Traspaso guardada. Folio: <b>{FolioSolicitud}</b>", TipoMensaje.MsgInformacion)
@@ -786,18 +890,35 @@ Partial Class OP_OP
End Sub
Protected Sub DdlAlmacenOrigenMP_SelectedIndexChanged(sender As Object, e As EventArgs)
' ✅ Mantener siempre el almacén de producción (tipo 28) en destino
DdlAlmacenDestinoMP.DataSource = GlobalDTAlmacen(UsuarioActual.CveEmpresa).FiltraParametros("CveTipoAlmacen = 28")
DdlAlmacenDestinoMP.DataBind()
' ✅ Opcional: Seleccionar el primer almacén de producción por defecto
If DdlAlmacenDestinoMP.Items.Count > 0 Then
DdlAlmacenDestinoMP.SelectedIndex = 0
End If
End Sub
#Region "Eventos de Botones"
Protected Sub GvProductoTerminado_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim originalQty As Decimal = Convert.ToDecimal(DataBinder.Eval(e.Row.DataItem, "Cantidad"))
Dim txtCantidad As TextBox = DirectCast(e.Row.FindControl("TxtCantidadPT"), TextBox)
txtCantidad.Attributes("data-original") = originalQty.ToString("0")
End If
End Sub
Protected Sub GvMPUtilizada_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim originalQty As Decimal = Convert.ToDecimal(DataBinder.Eval(e.Row.DataItem, "Cantidad"))
Dim txtDevolucion As TextBox = DirectCast(e.Row.FindControl("TxtDevolucionMP"), TextBox)
txtDevolucion.Attributes("data-original") = originalQty.ToString("0")
End If
End Sub
#Region "Finalizar"
Protected Sub BtnFinalizarOP_Click(sender As Object, e As EventArgs)
If CveOP = -1 Then Exit Sub
@@ -811,6 +932,11 @@ Partial Class OP_OP
DdlAlmacenTerminado.DataBind()
DdlAlmacenTerminado.Items.Insert(0, New ListItem("Seleccionar almacén", "-1"))
' Almacén de Devoluciones (Tipo 1)
DdlAlmacenDevolucion.DataSource = GlobalDTAlmacen(UsuarioActual.CveEmpresa).FiltraParametros("CveTipoAlmacen = 1")
DdlAlmacenDevolucion.DataBind()
DdlAlmacenDevolucion.Items.Insert(0, New ListItem("Seleccionar almacén", "-1"))
' 3. Cargar GridViews
GvProductoTerminado.DataSource = DtPS.FiltraParametros("Tipo = 'Producto'")
GvProductoTerminado.DataBind()
@@ -823,15 +949,42 @@ Partial Class OP_OP
End Sub
Protected Sub BtnGuardarFinalizarOP_Click(sender As Object, e As EventArgs)
Dim EstatusFinalizar As String = GlobalDTOPEstatus(UsuarioActual.CveEmpresa).FiltroPrimeroValor("EstatusOP", "TipoEstatus=3")
Dim CveEstatusFinalizar As Integer = GlobalDTOPEstatus(UsuarioActual.CveEmpresa).FiltroPrimeroValor("CveEstatusOP", "TipoEstatus=3").ToEntero()
If Not CveEstatusFinalizar > 0 Then
Alert("No se encontró el estatus de finalización de la OP.", TipoMensaje.MsgError)
Exit Sub
End If
If DdlAlmacenOrigenSalidaMP.SelectedValue = "-1" OrElse DdlAlmacenTerminado.SelectedValue = "-1" Then
Alert("Selecciona ambos almacenes.", TipoMensaje.MsgAdvertencia)
Exit Sub
End If
' Dim TotalCantidad As Decimal = DtMovimientos.SUMD("Cantidad")
'Inicia la transacción
For Each row As GridViewRow In GvProductoTerminado.Rows
Dim txtCantidad As TextBox = DirectCast(row.FindControl("TxtCantidadPT"), TextBox)
Dim cantidadIngresada As Decimal = txtCantidad.Text.ToDecimal()
Dim cantidadOriginal As Decimal = txtCantidad.Attributes("data-original").ToDecimal()
Dim CveMovimientoSalida As Integer = 0
If cantidadIngresada > cantidadOriginal Then
Alert("La cantidad del producto terminado no puede superar lo solicitado.", TipoMensaje.MsgAdvertencia)
Exit Sub
End If
Next
For Each row As GridViewRow In GvMPUtilizada.Rows
Dim txtDevolucion As TextBox = DirectCast(row.FindControl("TxtDevolucionMP"), TextBox)
Dim devolucionIngresada As Decimal = txtDevolucion.Text.ToDecimal()
Dim cantidadOriginal As Decimal = txtDevolucion.Attributes("data-original").ToDecimal()
If devolucionIngresada > cantidadOriginal Then
Alert("La devolución no puede superar la cantidad de materia prima solicitada.", TipoMensaje.MsgAdvertencia)
Exit Sub
End If
Next
Dim CveMovimientoSalida As Integer = 1
Dim CveMovimientoEntrada As Integer = 0
Dim IDPoliza As Integer = 0
Dim FolioSalida As Integer = 0
@@ -844,8 +997,13 @@ Partial Class OP_OP
Dim ErrorMovInv As Boolean = False
Dim TextoError As String = ""
Dim TipoMovimientoSalida As Integer = 8
Dim TipoMovimientoDev As Integer = 33
Dim CveConceptoEntrada As Integer = 9
Dim TotalCostoMP As Decimal = 0
'Dim TotalDevoluciones As Decimal = 0
Dim CveMovimientoDev As Integer = 0
Dim CostoDevoluciones As Decimal = 0
Dim ObjInventario As New ClsInventarios()
@@ -855,16 +1013,102 @@ Partial Class OP_OP
Try
CveMovimientoSalida = ObjInventario.AddMovimiento(DdlAlmacenOrigenSalidaMP.SelectedValue.ToEntero(), TipoMovimientoSalida, 1, Fecha, -1, UsuarioActual.CveUsuario, UsuarioActual.CveEmpresa, -1, -1, -1, -1, Observaciones:="Finalización OP #" & LblFolio.Text, Modulo:="OP/FinalizarOPSalida")
FolioEntrada = ObjInventario.Folio
Dim DtMPAlmacen As DataTable = Nothing
If CveMovimientoSalida > 0 Then
For Each rowMP As DataRow In DtMP.Select("Tipo = 'MP'")
If Not ObjInventario.AddMovimientoDetalle(CveMovimientoSalida, rowMP("Cantidad").ToString.ToDecimal(), rowMP("CveUMMateriaPrima").ToString.ToEntero(), rowMP("CvePSMateriaPrima").ToString.ToEntero(), 1) Then
ErrorMovInv = True : TextoError = "x" : Exit For
For Each rowMP As DataRow In DtMP.Select("Tipo = 'MP'")
Dim CvePS As Integer = rowMP("CvePSMateriaPrima").ToString.ToEntero
Dim CveUM As Integer = rowMP("CveUMMateriaPrima").ToString.ToEntero
Dim Cantidad As Decimal = rowMP("Cantidad").ToString.ToDecimal
' Registrar detalle
If Not ObjInventario.AddMovimientoDetalle(CveMovimientoSalida, Cantidad, CveUM, CvePS, 0) Then
ErrorMovInv = True
Exit For
End If
Next
If ObjInventario.GetMovimientosDetalle(CveMovimientoSalida, UsuarioActual.CveEmpresa) Then
TotalCostoMP = ObjInventario.DtResultados.SUMD("Total")
If Not ObjInventario.GetMovimientosDetalle(CveMovimientoSalida, UsuarioActual.CveEmpresa) Then
Throw New Exception("Error al cargar detalles del inventario")
End If
DtMPAlmacen = ObjInventario.DtResultados.Copy()
' 5. Calcular TotalCostoMP (ya está actualizado)
TotalCostoMP = ObjInventario.DtResultados.SUMD("Total")
Dim CostosPorProducto As New Dictionary(Of Integer, Decimal)
' 1. Recorrer cada Producto Terminado en la OP
For Each rowProducto As DataRow In DtPS.Select("Tipo = 'Producto'")
Dim CvePSProducto As Integer = rowProducto("Clave").ToString.ToEntero()
Dim CantidadProducto As Decimal = rowProducto("Cantidad").ToString.ToDecimal()
Dim TotalMPProducto As Decimal = 0
Dim TotalMOProducto As Decimal = 0
Dim TotalCIProducto As Decimal = 0
' 2. Calcular Costo de Materias Primas por Producto
For Each rowMP As DataRow In DtMP.Select($"Clave = {CvePSProducto}")
Dim CvePSMP As Integer = rowMP("CvePSMateriaPrima").ToString.ToEntero()
Dim CveUMMP As Integer = rowMP("CveUMMateriaPrima").ToString.ToEntero()
Dim PU As Decimal = DtMPAlmacen.FiltroPrimeroValor("PU", $"CvePS = {CvePSMP} AND CveUM = {CveUMMP}").ToDecimal()
TotalMPProducto += rowMP("Cantidad").ToString().ToDecimal() * PU
Next
' 3. Calcular Mano de Obra por Producto
For Each rowMO As DataRow In DtMO.Select($"Clave = {CvePSProducto}")
TotalMOProducto += rowMO("Total").ToString.ToDecimal()
Next
' 4. Calcular Costos Indirectos por Producto
For Each rowCI As DataRow In DtCI.Select($"Clave = {CvePSProducto}")
TotalCIProducto += rowCI("Total").ToString.ToDecimal()
Next
' 5. Sumar Total por Producto (MP + MO + CI)
Dim TotalProducto As Decimal = TotalMPProducto + TotalMOProducto + TotalCIProducto
CostosPorProducto.Add(CvePSProducto, TotalProducto)
Next
' 2. PROCESAR DEVOLUCIONES SI EXISTEN
If Not ErrorMovInv Then
Dim TotalDevoluciones As Decimal = GvMPUtilizada.Rows.Cast(Of GridViewRow)().Sum(Function(row) DirectCast(row.FindControl("TxtDevolucionMP"), TextBox).Text.ToDecimal())
If TotalDevoluciones > 0 Then
If DdlAlmacenDevolucion.SelectedValue = "-1" Then
Alert("Seleccione almacén para devoluciones", TipoMensaje.MsgAdvertencia)
Exit Sub
End If
CveMovimientoDev = ObjInventario.AddMovimiento(DdlAlmacenDevolucion.SelectedValue.ToEntero(), TipoMovimientoDev, 1, Fecha, -1, UsuarioActual.CveUsuario, UsuarioActual.CveEmpresa, -1, -1, -1, -1, Observaciones:=$"Devolución OP #{LblFolio.Text}", Modulo:="OP/Devoluciones", CveMovimientoRelacionado:=CveMovimientoSalida)
If CveMovimientoDev > 0 Then
For Each row As GridViewRow In GvMPUtilizada.Rows
Dim Devolucion As Decimal = row.FCTextBox("TxtDevolucionMP").Text.ToDecimal()
If Devolucion > 0 Then
Dim CvePS As Integer = row.DataKey("CvePSMateriaPrima").ToEntero 'GvMPUtilizada.DataKeys(row.RowIndex)("CvePSMateriaPrima").ToString.ToEntero()
Dim CveUM As Integer = row.DataKey("CveUMMateriaPrima").ToEntero 'GvMPUtilizada.DataKeys(row.RowIndex)("CveUMMateriaPrima").ToString.ToEntero()
Dim PU As Decimal = DtMPAlmacen.FiltroPrimeroValor("PU", $"CvePS = {CvePS} AND CveUM = {CveUM}").ToDecimal()
If Not ObjInventario.AddMovimientoDetalle(
CveMovimientoDev,
Devolucion,
CveUM,
CvePS,
PU
) Then
ErrorMovInv = True
End If
CostoDevoluciones += Devolucion * PU
End If
Next
End If
End If
End If
If Not ErrorMovInv Then
@@ -872,8 +1116,9 @@ Partial Class OP_OP
End If
If CveMovimientoEntrada > 0 AndAlso Not ErrorMovInv Then
Dim CantidadPT As Decimal = DtPS.AsEnumerable().Sum(Function(row) Convert.ToDecimal(row("Cantidad")))
Dim PU_PT As Decimal = If(CantidadPT > 0, TotalCostoMP / CantidadPT, 1)
Dim CostoPTAjustado As Decimal = TotalCostoMP - CostoDevoluciones
Dim CantidadPT As Decimal = DtPS.AsEnumerable().Sum(Function(r) r.Field(Of Decimal)("Cantidad"))
Dim PU_PT As Decimal = If(CantidadPT > 0, CostoPTAjustado / CantidadPT, 0)
For Each rowPT As DataRow In DtPS.Select("Tipo = 'Producto'")
If Not ObjInventario.AddMovimientoDetalle(CveMovimientoEntrada, rowPT("Cantidad").ToString.ToDecimal(), rowPT("CveUM").ToString.ToEntero(), rowPT("Clave").ToString.ToEntero(), PU_PT) Then
@@ -889,24 +1134,24 @@ Partial Class OP_OP
ErrorMovInv = True
End If
If Not ErrorMovInv AndAlso Not ObjConta.AddPrePolizasDetalle(CvePrePoliza, False, TotalCostoMP, TotalCostoMP, 68, "Producción PT OP #" & LblFolio.Text, "Producción PT OP #" & LblFolio.Text, CveMovimientoAlmacen:=CveMovimientoEntrada) Then
If Not ErrorMovInv AndAlso Not ObjConta.AddPrePolizasDetalle(CvePrePoliza, False, CostoPTAjustado, CostoPTAjustado, 68, "Producción PT OP #" & LblFolio.Text, "Producción PT OP #" & LblFolio.Text, CveMovimientoAlmacen:=CveMovimientoEntrada) Then
ErrorMovInv = True
End If
If Not ErrorMovInv Then
If Not ObjOP.UpdateEstatusOP(CveOP, 3, UsuarioActual.CveEmpresa) Then
ErrorMovInv = True : TextoError = "Error al actualizar estatus de la OP"
End If
End If
ObjConta.AddPrePolizasDetalle(CvePrePoliza, False, CostoDevoluciones, CostoDevoluciones, 95, "", $"OP #{LblFolio.Text}", CveMovimientoAlmacen:=CveMovimientoDev)
'If Not ErrorMovInv Then
' If Not ObjConta.ValidacionesPrePoliza(CvePrePoliza, UsuarioActual) Then
' ErrorMovInv = True : TextoError = "Error en validación de póliza"
' ElseIf ObjConta.ValorPolizaDescuadre > 0 Then
' ErrorMovInv = True : TextoError = "Descuadre en póliza contable"
' End If
'If Not ObjConta.ValidacionesPrePoliza(CvePrePoliza, UsuarioActual) Then
'ErrorMovInv = True : TextoError = "Error en validación de póliza"
'ElseIf ObjConta.ValorPolizaDescuadre > 0 Then
' ErrorMovInv = True : TextoError = "Descuadre en póliza contable"
'End If
'End If
End If
End If
@@ -914,16 +1159,32 @@ Partial Class OP_OP
If Not ErrorMovInv Then
ObjInventario.Commit()
Alert($"Orden de producción finalizada.
<br/><a class='Texto' href='/Inventarios/EntradasSalidas.aspx?CveMovimiento= {CveMovimientoEntrada}'>{ObjInventario.Folio}</a> ", TipoMensaje.MsgInformacion)
If ObjOP.UpdateEstatusOP(CveOP, CveEstatusFinalizar, UsuarioActual.CveEmpresa) Then
ObjInventario.Commit()
TxtEstatus.Text = EstatusFinalizar
DeshabilitarControles()
UpOP.Update()
UpGvDatosOP.Update()
Alert("Orden de producción finalizada.<br/>" & "<a class='Texto' href='/Inventarios/EntradasSalidas.aspx?CveMovimiento=" & CveMovimientoEntrada & "'>" & FolioEntrada & "</a>",
TipoMensaje.MsgInformacion)
RegistraScript("$('#DVModalFinalizarOP').modal('hide');")
Else
ObjInventario.RollBack()
Alert("Error al actualizar el estatus.", TipoMensaje.MsgError)
End If
Else
ObjInventario.RollBack()
Alert($"Error contable: {TextoError}", TipoMensaje.MsgError)
End If
RegistraScript("$('#DVModalFinalizarOP').modal('hide');")
CargaDatos()
Catch ex As Exception
ObjInventario.RollBack()
@@ -933,7 +1194,6 @@ Partial Class OP_OP
ObjConta.Dispose()
End Try
End Sub
#End Region
End Class