/** * Validaciones antes de actualizar o crear */ public function valida() { unset($this->_errores); if ($this->IDArticulo == '') { $this->_errores[] = "Debe indicar un código de artículo"; } // Las unidades deben ser distintas a 0 if ($this->Unidades == 0) { $this->_errores[] = "Debe indicar la cantidad"; } // Compruebo la existencia del artículo $articulo = new Articulos($this->IDArticulo); if ($articulo->getStatus() == 0) { $this->_errores[] = "El artículo indicado no existe"; unset($articulo); } // Si existe el articulo ... if (count($this->_errores) == 0) { // Si la descripcion está vacia, pongo la del artículo // Si trae algo, la respeto. if ($this->Descripcion == '') { $this->setDescripcion($articulo->getDescripcion()); } if ($this->Precio == '') { $this->setPrecio($articulo->getPmc()); } $this->TotalizaLinea(); // Si el artículo es inventariable y la linea es de salida: // Comprobar existencias sin tener en cuenta lote y ubicación if ($articulo->getInventario()->getIDTipo() == '1' and $this->Tipo == '0') { $existencias = new Existencias(); $stock = $existencias->getStock($this->IDArticulo, $this->IDAlmacen, 0, 0, -1, $this->UnidadMedida); if ($stock['RE'] < $this->getUnidades()) { $this->_alertas[] = "Stock insuficiente"; $this->_alertas[] = "------------------"; } $this->_alertas[] = "Disponible: " . $stock['DI']; $this->_alertas[] = "Real: " . $stock['RE']; $this->_alertas[] = "Reservado: " . $stock['RV']; $this->_alertas[] = "Pte. Entrada: " . $stock['PE']; } } unset($articulo); unset($existencias); return count($this->_errores) == 0; }
/** * Valida que la cantidad indicada esté disponible en * el almacén, ubicación y lote * * @return boolean */ public function validaLogico() { parent::validaLogico(); $articulo = new Articulos($this->IDArticulo); $bloqueoStock = $articulo->getBloqueoStock()->getIDTIpo() == '1'; if ($this->Unidades == 0) { $this->_errores[] = "Debe indicar una cantidad distinta a cero"; } $almacen = new Almacenes($this->IDAlmacen); //print_r($this); if ($almacen->getControlUbicaciones()->getIDTipo() == '1' and $this->IDUbicacion == 0) { $this->_errores[] = "Debe indicar la ubicación"; } unset($almacen); if ($bloqueoStock) { $udadMedidaVenta = $articulo->getUMV(); $udadMedidaAlmacen = $articulo->getUMA(); $stock = new Existencias(); $existencias = $stock->getStock($this->IDArticulo, $this->IDAlmacen, $this->IDLote, $this->IDUbicacion); unset($stock); // Calcular las cantidades de ese articulo, almacen, lote y ubicación que estan // en lineas de expediciones sin estar expedidas aún. O sea lo que está en // proceso de expedición. No tengo en cuenta los valores de la BD de la línea actual // porque puede que hayan cambiado. $filtro = "IDLinea<>'{$this->IDLinea}' and Expedida='0' and IDAlmacen='{$this->IDAlmacen}' and IDLote='{$this->IDLote}' and IDUbicacion='{$this->IDUbicacion}'"; $expedicion = new Expediciones(); $rows = $expedicion->cargaCondicion("sum(Unidades) as Unidades,sum(Pales) as Pales,sum(Cajas) as Cajas", $filtro); $row = $rows[0]; $row['Unidades'] += $this->Unidades; $row['Pales'] += $this->Pales; $row['Cajas'] += $this->Cajas; unset($expedicion); if ($existencias['DI'] < $articulo->convertUnit('UMV', 'UMA', $row['Unidades'])) { $this->_errores[] = "Hay " . round($articulo->convertUnit('UMA', 'UMV', $existencias['DI']), 2) . " {$udadMedidaVenta} (" . round($existencias['DI'], 2) . " {$udadMedidaAlmacen}) disponibles para ese lote y ubicación"; } if ($existencias['CA'] < $row['Cajas']) { $this->_errores[] = "Hay {$existencias['CA']} cajas disponibles para ese lote y ubicacion"; } if ($existencias['PT'] < $row['Pales']) { $this->_errores[] = "Hay {$existencias['PT']} pales disponibles para ese lote y ubicacion"; } } unset($articulo); return count($this->_errores) == 0; }
/** * Validaciones antes de actualizar o crear */ public function valida(array $rules) { unset($this->_errores); //Para tener disponibles los datos de la //cabecera del pedido $pedido = new PedidosCab($this->IDPedido); // Compruebo la existencia del artículo y que pertenezca a // la sucursal de la cabecera del pedido. if ($this->IDArticulo == '') { $this->_errores[] = "Debe indicar un código de artículo"; } else { $articulo = new Articulos($this->IDArticulo); if ($articulo->getStatus() == 0) { $this->_errores[] = "El artículo indicado no existe"; unset($articulo); } } // Si existe el articulo ... if (count($this->_errores) == 0) { $aviso = $articulo->getAvisosPedidos(); if ($aviso) { $this->_alertas[] = $aviso; } $this->checkPackingCompras($articulo); // Si la descripcion está vacia, pongo la del artículo // Si trae algo, la respeto. if ($this->Descripcion == '') { $this->setDescripcion($articulo->getDescripcion()); } // Si no se ha indicado precio, pongo el precio de costo de la ficha del articulo if ($this->Precio == '') { $this->setPrecio($articulo->getPrecioCosto()); } // Totalizar la linea de pedido $this->setImporte($this->Unidades * $this->Precio * (1 - $this->Descuento / 100)); //Comparar el precio respecto al PMC. //Si el importe neto (despues de dctos) unitario supera el P.M.C. se emite alerta if ($this->getImporte() / $this->getUnidades() > $articulo->getPmc()) { $this->_alertas[] = "El precio supera al Precio Medio de Compra: " . $articulo->getPmc(); } // Poner el mismo almacen de la cabecera del pedido y el agente en curso $this->setIDAlmacen($pedido->getIDAlmacen()->getIDAlmacen()); $this->setIDAgente($_SESSION['usuarioPortal']['Id']); // Si el proveedor no está sujeto a Iva, pongo a 0 el iva y el recargo if ($pedido->getIDProveedor()->getIva()->getIDTipo() == '0') { $this->setIva('0'); $this->setRecargo('0'); } else { // Si no se ha indicando iva, pongo el iva asociado al artículo, if ($this->Iva == '') { $this->setIva($articulo->getIDIva()->getIva()); } } // Si el artículo es inventariable: // Comprobar existencias sin tener en cuenta lote ni ubicación // de almacen. Solo se buscan existencias en el almacen indicado // en la línea del pedido if ($articulo->getInventario()->getIDTipo() == '1') { $existencias = new Existencias(); $stock = $existencias->getStock($this->IDArticulo, $this->IDAlmacen); // Se genera una alerta si hay stock disponible o pendiente de entrada if ($stock['PE'] > 0 or $stock['DI'] > 0) { $this->_alertas[] = "Hay stock"; $this->_alertas[] = "---------"; } $this->_alertas[] = "Disponible: " . $stock['DI']; $this->_alertas[] = "Real: " . $stock['RE']; $this->_alertas[] = "Reservado: " . $stock['RV']; $this->_alertas[] = "Pte. Entrada: " . $stock['PE']; } } unset($articulo); unset($pedido); unset($existencias); return count($this->_errores) == 0; }
/** * Recalcula y actualiza: * * 1) el precio medio de compra (Pmc) * 2) el precio de compra (Pvd) * 3) el margen o el pvp dependiendo del valor del parámetro ACTU_PRECIOS, en cualquier caso * estos valores se calculan respecto el precio medio de compra * 4) la fecha del último precio * * NOTA: Este método sobreentiende que primero se han acutalizado las existencias * por lo tanto las existencias anteriores son las actuales menos las compradas. * * La fórmula que se utiliza es: * * nuevoPmc = ( (existenciasAnteriores * PMC) + (unidadesCompradas * ultimoPrecioCompra) ) / (existenciasAnteriores + unidadesCompradas) * * @param float $unidadesCompradas La unidades compradas expresadas en la unidad de medida de compra * @param float $ultimoPrecioCompra El último precio de compra expresado en la unidad de medida de compra * @return boolean */ public function actualizaPrecios($unidadesCompradas, $ultimoPrecioCompra) { $exi = new Existencias(); $stock = $exi->getStock($this->IDArticulo, '', '', '', '', 'UMC'); unset($exi); $existenciasAnteriores = $stock['RE'] - $unidadesCompradas; $pmcUnidadCompra = $this->Pmc * $this->CUMC; if ($existenciasAnteriores + $unidadesCompradas != 0) { $nuevoPmc = ($existenciasAnteriores * $pmcUnidadCompra + $unidadesCompradas * $ultimoPrecioCompra) / ($existenciasAnteriores + $unidadesCompradas); $nuevoPmc = $nuevoPmc / $this->CUMC; $this->setPmc($nuevoPmc); } // Leo el parametro 'ACTU_PRECIOS' para ver el comportamiento a seguir // en el cambio de precio de venta o margen. Si no estuviera definido, // se respeta el PVP a costa del MARGEN $parametro = $_SESSION['usuarioPortal']['actuPrecios']; if ($parametro != 'MARGEN' and $parametro != 'PVP') { $parametro = 'MARGEN'; } // Calculo el nuevo margen o el nuevo precio de venta (según el parámetro) sobre el PRECIO MEDIO DE COSTO if ($this->Pmc == 0) { $this->Pmc = $this->Pvd; } if ($parametro == 'PVP') { $this->Pvp = $this->Pmc * (1 + $this->Margen / 100); } else { if ($this->Pmc != 0) { $this->Margen = 100 * ($this->Pvp / $this->Pmc - 1); } else { $this->Margen = 0; } } $this->setPvd($ultimoPrecioCompra / $this->CUMC); $this->setFechaUltimoPrecio(date('Y-m-d H:i:s')); return $this->save(); }
/** * Validaciones antes de actualizar o crear */ public function valida() { unset($this->_errores); if ($this->IDArticulo == '') { $this->_errores[] = "Debe indicar un código de artículo"; return count($this->_errores) == 0; } //Para tener disponibles los datos de la //cabecera del albaran $psto = new PstoCab($this->IDPsto); // Compruebo la existencia del artículo y que pertenezca a // la sucursal de la cabecera del albaran. $articulo = new Articulos($this->IDArticulo); if ($articulo->getStatus() == 0) { $this->_errores[] = "El artículo indicado no existe o no pertenece a esta sucursal"; unset($articulo); } // Si existe el articulo ... if (count($this->_errores) == 0) { $aviso = $articulo->getAvisosPresupuestos(); if ($aviso) { $this->_alertas[] = $aviso; } // Si es version CRISTAL, comprueba multiplos y calcula medidas if ($_SESSION['ver'] == 1) { $this->checkMultiplos($articulo); } $this->checkPackingVentas($articulo); // Si la descripcion está vacia, pongo la del artículo // Si trae algo, la respeto. if ($this->Descripcion == '') { $this->setDescripcion($articulo->getDescripcion()); } // Si hay promo, ver si se aplica en base a la cantidad mínima. // Si es aplicable, prevalece sobre el precio y dcto indicado y tambien // sobre la tarifa del cliente. $precios = $articulo->cotizar($psto); if ($precios['Promocion']) { $alerta = "Promocion hasta el " . $precios['Promocion']->getFinPromocion() . " y compra mínima " . $precios['Promocion']->getCantidadMinima(); if ($precios['Promocion']->getIDFP()->getIDFP()) { $alerta .= " y forma de pago " . $precios['Promocion']->getIDFP(); } $this->_alertas[] = $alerta; } // Si hay promo, se aplica si se iguala o supera la cantidad mínima y si // no se restringe la forma de pago y en caso contrario la forma de pago // fijada para la promocion es igual a la del presupuesto if ($precios['Promocion'] and $this->getUnidades() >= $precios['Promocion']->getCantidadMinima() and (!$precios['Promocion']->getIDFP()->getIDFP() or $psto->getIDFP()->getIDFP() == $precios['Promocion']->getIDFP()->getIDFP())) { $this->IDPromocion = $precios['Promocion']->getIDPromocion(); $this->Precio = $precios['Promo']['Precio']; $this->Descuento = $precios['Promo']['Descuento']; } else { // Si no hay promo, se aplica la tarifa, o se respeta el precio y descuento // indicado por el usuario si tiene permiso dependiendo de si su rol está // incluido en el parámetro ROLCP $this->IDPromocion = 0; if ($this->Precio == '' or !$_SESSION['usuarioPortal']['cambioPrecios']) { $this->setPrecio($precios['Tarifa']['Precio']); } if ($this->Descuento == '' or !$_SESSION['usuarioPortal']['cambioPrecios']) { $this->setDescuento($precios['Tarifa']['Descuento']); } } // Totalizar la linea $this->totalizaLinea($articulo); //Comprobar que no se venda por debajo del costo if ($this->Importe < $this->ImporteCosto) { $this->_alertas[] = "Venta negativa"; } // Poner el mismo almacen y comercial de la cabecera del albarán $this->setIDAlmacen($psto->getIDAlmacen()->getIDAlmacen()); $this->setIDComercial($psto->getIDComercial()->getIDAgente()); $this->setIDAgente($_SESSION['usuarioPortal']['Id']); // Si el cliente no está sujeto a Iva, pongo a 0 el iva y el recargo if ($psto->getIDCliente()->getIva()->getIDTipo() == '0') { $this->setIva('0'); $this->setRecargo('0'); } else { // Si no se ha indicando iva, pongo el iva y recargo asociado al artículo, if ($this->Iva == '') { $this->setIva($articulo->getIDIva()->getIva()); if ($psto->getIDCliente()->getRecargoEqu()->getIDTipo() == '1') { $this->setRecargo($articulo->getIDIva()->getRecargo()); } else { $this->setRecargo('0'); } } } // Si el artículo es inventariable: // Comprobar existencias sin tener en cuenta lote ni ubicación // de almacen. Solo se buscan existencias en el almacen indicado // en la línea del albarán if ($articulo->getInventario()->getIDTipo() == '1') { $existencias = new Existencias(); $stock = $existencias->getStock($this->IDArticulo, $this->IDAlmacen); if ($stock['DI'] < $this->getUnidades()) { $this->_alertas[] = "Stock insuficiente"; $this->_alertas[] = "------------------"; } $this->_alertas[] = "Disponible: " . $stock['DI']; $this->_alertas[] = "Real: " . $stock['RE']; $this->_alertas[] = "Reservado: " . $stock['RV']; $this->_alertas[] = "Pte. Entrada: " . $stock['PE']; } } unset($articulo); unset($psto); unset($existencias); return count($this->_errores) == 0; }
/** * Validaciones antes de actualizar o crear */ public function valida(array $rules = array()) { unset($this->_errores); if ($this->IDArticulo == '') { $this->_errores[] = "Debe indicar un código de artículo"; return count($this->_errores) == 0; } //Para tener disponibles los datos de la cabecera del albarán $albaran = new AlbaranesCab($this->IDAlbaran); // Compruebo la existencia del artículo $articulo = new Articulos($this->IDArticulo); if ($articulo->getStatus() == 0) { $this->_errores[] = "El artículo indicado no existe"; unset($articulo); } // Si existe el articulo ... if (count($this->_errores) == 0) { $aviso = $articulo->getAvisosAlbaranes(); if ($aviso) { $this->_alertas[] = $aviso; } // Si es version CRISTAL, comprueba múltiplos y calcula medidas if ($_SESSION['ver'] == 1) { $this->checkMultiplos($articulo); } $this->checkPackingVentas($articulo); // Pongo la descripcion del artículo si viene vacía o si el // usuario no tiene permiso para cambiarla. Ver parámetro ROLCP if ($this->Descripcion == '') { //or (!$_SESSION['usuarioPortal']['cambioPrecios']) ) $this->setDescripcion($articulo->getDescripcion()); } // Si hay promo, ver si se aplica en base a la cantidad mínima. // Si es aplicable, prevalece sobre el precio y dcto indicado y también // sobre la tarifa del cliente. $precios = $articulo->cotizar($albaran, $this->Unidades); if ($precios['Promocion']) { $alerta = "Promocion hasta el " . $precios['Promocion']->getFinPromocion() . " y compra mínima " . $precios['Promocion']->getCantidadMinima(); if ($precios['Promocion']->getIDFP()->getIDFP()) { $alerta .= " y forma de pago " . $precios['Promocion']->getIDFP(); } $this->_alertas[] = $alerta; } // Si hay promo, se aplica si se iguala o supera la cantidad mínima y si // no se restringe la forma de pago y en caso contrario la forma de pago // fijada para la promocion es igual a la del presupuesto if (is_object($precios['Promocion']) and $this->getUnidades() >= $precios['Promocion']->getCantidadMinima() and ($precios['Promocion']->getIDFP()->getIDFP() == 0 or $albaran->getIDFP()->getIDFP() == $precios['Promocion']->getIDFP()->getIDFP())) { $this->IDPromocion = $precios['Promocion']->getIDPromocion(); $this->Precio = $precios['Promo']['Precio']; $this->Descuento = $precios['Promo']['Descuento']; $this->PvpVigente = $precios['Promo']['Precio']; } else { $this->PvpVigente = $precios['Tarifa']['Precio']; // Si no hay promo, se aplica la tarifa, o se respeta el precio y descuento // indicado por el usuario si tiene permiso dependiendo de si su rol está // incluido en la VWP "rolesCambioPrecios" $this->IDPromocion = 0; if ($this->Precio == '' or !$_SESSION['usuarioPortal']['cambioPrecios']) { $this->setPrecio($precios['Tarifa']['Precio']); } if ($this->Descuento == '' or !$_SESSION['usuarioPortal']['cambioPrecios']) { $this->setDescuento($precios['Tarifa']['Descuento']); } } // Comprobar que no se venda por debajo del tope establecido para la familia o // el general establecido en VWP[erp][] $precioMinimo = $articulo->getPrecioMinimoVenta(); if ($this->Precio < $precioMinimo) { $this->_alertas[] = "El precio indicado es inferior al permitido " . $precioMinimo; $this->_errores[] = "El precio indicado es inferior al permitido "; } // Totalizar la linea $this->totalizaLinea($articulo); //Comprobar que no se venda por debajo del costo if ($this->Importe < $this->ImporteCosto) { $this->_alertas[] = "Venta negativa"; } // Poner el mismo almacen y comercial de la cabecera del albarán $this->setIDAlmacen($albaran->getIDAlmacen()->getIDAlmacen()); $this->setIDComercial($albaran->getIDComercial()->getIDAgente()); $this->setIDAgente($_SESSION['usuarioPortal']['Id']); // Si el cliente no está sujeto a Iva, pongo a 0 el iva y el recargo if ($albaran->getIDCliente()->getIva()->getIDTipo() == '0') { $this->setIva('0'); $this->setRecargo('0'); } else { // Si no se ha indicando iva, pongo el iva y recargo asociado al artículo, if ($this->Iva == '') { $this->setIva($articulo->getIDIva()->getIva()); if ($albaran->getIDCliente()->getRecargoEqu()->getIDTipo() == '1') { $this->setRecargo($articulo->getIDIva()->getRecargo()); } else { $this->setRecargo('0'); } } } // Si el artículo es inventariable: // Comprobar existencias sin tener en cuenta lote ni ubicación // de almacen. Solo se buscan existencias en el almacen indicado // en la línea del albarán if ($articulo->getInventario()->getIDTipo() == '1' and $_SESSION['VARIABLES']['WebPro']['erp']['alertaStock']) { $existencias = new Existencias(); $stock = $existencias->getStock($this->IDArticulo, $this->IDAlmacen, 0, 0, -1, $this->UnidadMedida); if ($stock['DI'] < $this->getUnidades()) { $this->_alertas[] = "Stock insuficiente"; $this->_alertas[] = "------------------"; } $this->_alertas[] = "Disponible: " . $stock['DI']; $this->_alertas[] = "Real: " . $stock['RE']; $this->_alertas[] = "Reservado: " . $stock['RV']; $this->_alertas[] = "Pte. Entrada: " . $stock['PE']; } } unset($articulo); unset($albaran); unset($existencias); return count($this->_errores) == 0; }
/** * Valida la idoneidad del movimiento. * * Chequea si se aplica o no la trazabilidad, la ubicacion y el bloqueo de stock * * @param char $signo El signo del movimiento (E=Entrada, S=Salida) * @return boolean */ private function validaMovimiento($signo) { $articulo = new Articulos($this->IDArticulo); $almacen = new Almacenes($this->IDAlmacen); $hayTrazabilidad = $articulo->getTrazabilidad()->getIDTipo(); $hayBloqueoStock = $articulo->getBloqueoStock()->getIDTipo(); $hayControlUbicaciones = $almacen->getControlUbicaciones()->getIDTipo(); if ($hayBloqueoStock) { $exi = new Existencias(); $stock = $exi->getStock($this->IDArticulo, $this->IDAlmacen, $this->IDLote, $this->IDUbicacion, '', 'UMA'); unset($exi); switch ($signo) { case 'S': $unidades = $this->UnidadesE + $this->UnidadesS; if ($unidades < 0) { $okBloqueoStock = true; } else { $okBloqueoStock = $stock['RE'] >= $unidades; } break; case 'E': $unidades = $this->UnidadesE + $this->UnidadesS; if ($unidades < 0) { $okBloqueoStock = $unidades + $stock['RE'] >= 0; } else { $okBloqueoStock = true; } break; } } else { $okBloqueoStock = true; } $okTrazabilidad = (!$hayTrazabilidad or $this->IDLote != 0); $okUbicacion = (!$hayControlUbicaciones or $this->IDUbicacion != 0); if (!$okBloqueoStock) { $this->_errores[] = "No hay stock suficiente para " . $articulo->getDescripcion(); } if (!$okTrazabilidad) { $this->_errores[] = "Debe indicar el lote para " . $articulo->getDescripcion(); } if (!$okUbicacion) { $this->_errores[] = "Debe indicar la ubicación para " . $articulo->getDescripcion(); } unset($articulo); unset($almacen); return count($this->_errores) == 0; }
/** * Preasigna stock sin control de trazabilidad ni de ubicación * * Si hay stock pero no es suficiente, se crea la línea de expedición proponiendo el que hay. * * Si NO hay stock: * * Caso 1) El artículo bloquea stock: no se crea la línea de expedición * Caso 2) El artículo NO bloquea stock: se crea la línea de expedición proponiendo 0 unidades * * @param AlbaranesLineas $lineaAlbaran * @param <type> $idRepartidor */ private function preasignaStock($entidad, $idEntidad, $linea, $idRepartidor = '') { echo "asdfasdfasdfasdfasdf"; $idLineaEntidad = $linea->getPrimaryKeyValue(); $articulo = $linea->getIDArticulo(); $idAlmacen = $linea->getIDAlmacen()->getIDAlmacen(); $unidades = $linea->getUnidades(); $unidadMedidaOrigen = $linea->getUnidadMedida(); $unidadesAlmacen = $articulo->convertUnit($unidadMedidaOrigen, 'UMA', $unidades); $bloqueoStock = $articulo->getBloqueoStock()->getIDTipo() == '1'; $exi = new Existencias(); $existencias = $exi->getStock($articulo->getIDArticulo(), $idAlmacen); unset($exi); if ($existencias['RE'] >= $unidadesAlmacen) { $asignado = $articulo->convertUnit('UMA', $unidadMedidaOrigen, $unidadesAlmacen); $stockInsuficiente = false; } else { $stockInsuficiente = true; $asignado = $articulo->convertUnit('UMA', $unidadMedidaOrigen, $existencias['RE']); } if ($asignado <= 0 and !$bloqueoStock) { $asignado = 0; } $lineaExpedicion = new Expediciones(); $lineaExpedicion->setEntidad($entidad); $lineaExpedicion->setIDEntidad($idEntidad); $lineaExpedicion->setIDLineaEntidad($idLineaEntidad); $lineaExpedicion->setIDAlmacen($idAlmacen); $lineaExpedicion->setIDAlmacenero($_SESSION['usuarioPortal']['Id']); $lineaExpedicion->setIDRepartidor($idRepartidor); $lineaExpedicion->setIDArticulo($articulo->getIDArticulo()); if ($existencias['RE'] > 0) { $asignado = $existencias['RE'] > $unidadesAlmacen ? $unidadesAlmacen : $existencias['RE']; } else { $asignado = 0; } $asignado = $articulo->convertUnit('UMA', $unidadMedidaOrigen, $asignado); $lineaExpedicion->setUnidades($asignado); $lineaExpedicion->setUnidadMedida($unidadMedidaOrigen); $lineaExpedicion->setIDLote(0); $lineaExpedicion->setIDUbicacion(0); $lineaExpedicion->setFlagTrazabilidad(0); $lineaExpedicion->setFlagUbicacion(0); $lineaExpedicion->setFlagSinStock($stockInsuficiente); $lineaExpedicion->create(); }