<?php
namespace App\Jaxon\Idempiere;
use App\Constant;
use App\Entity\Idempiere\AdOrg;
use App\Entity\Idempiere\AdSequence;
use App\Entity\Idempiere\AdUser;
use App\Entity\Idempiere\COrder;
use App\Entity\Idempiere\COrderline;
use App\Entity\Idempiere\CTax;
use App\Entity\Idempiere\MProduct;
use App\Entity\Idempiere\MProductprice;
use App\Entity\Idempiere\MWarehouse;
use App\Jaxon\Base;
use App\Repository\Idempiere\AdSequenceRepository;
use App\Repository\Idempiere\MProductpriceRepository;
use App\Repository\Idempiere\MProductRepository;
use Exception;
use Jaxon\Response\Response;
class Orderline extends Base
{
/**
* Habilitar campo para cambiar cantidades
* de una linea en la orden
*
* @param int $C_Orderline_ID Identificador de la linea
*
* @return Response Jaxon Reponse
*/
public function changeQty(
Int $C_Orderline_ID
)
{
$ROrderline = $this->manager->getRepository(COrderline::class);
$orderline = $ROrderline->find( $C_Orderline_ID );
$qty = $orderline->getQtyentered();
$jxnr = new Response;
$input=
'<input
type="number"
step="0.01"
value="'. number_format($qty, 2) .'"
onblur="App.Jaxon.Idempiere.Orderline.setQty(\''. $C_Orderline_ID .'\', this.value)"
>';
return $jxnr->assign($C_Orderline_ID . '_qty', 'innerHTML', $input);
}
/**
* Habilitar campo para cambiar precios
* de una linea en la orden
*
* @param int $C_Orderline_ID Identificador de la linea
*
* @return Response Jaxon Reponse
*/
public function changePrc(
Int $C_Orderline_ID
)
{
$ROrderline = $this->manager->getRepository(COrderline::class);
$orderline = $ROrderline->find( $C_Orderline_ID );
$prc = $orderline->getPriceactual();
$jxnr = new Response;
$input=
'<input
type="number"
step="0.01"
value="'. number_format($prc, 2) .'"
onblur="App.Jaxon.Idempiere.Orderline.setPrc(\''. $C_Orderline_ID .'\', this.value)"
>';
return $jxnr->assign($C_Orderline_ID . '_prc', 'innerHTML', $input);
}
/**
* Crear linea en la orden
*
* @param int $m_productprice_id Identificacdor del precio del producto
* @param array $formData Datos de la orden
*
* @return Response Jaxon Reponse
*/
# TODO: Cambiar monto de la orden
public function create(
Int $m_productprice_id
): Response
{
$jxnr = new Response;
/**
* Var Session
*/
/** @var AdUser */
$user = $this->session->get('user', null);
/** @var COrder */
$order = $this->session->get('order', null);
/** @var MWarehouse */
$warehouse = $this->session->get('warehouse', null);
##############################################################
/**
* Entity Repositorys
*/
/** @var MProductpriceRepository */
$RProductprice = $this->manager->getRepository(MProductprice::class);
$productprice = $RProductprice->find($m_productprice_id);
/** @var MProductRepository */
$RProduct = $this->manager->getRepository(MProduct::class);
$product = $RProduct->find($productprice->getMProductId());
##############################################################
// Verifica si el producto tiene stock
if( $RProduct->findStorage($product->getId(), $warehouse->getId()) <= 0 )
return $jxnr->script( self::displayError("Producto sin Stock", "Este producto no cuenta con cantidades disponibles.") );
// Verifica si el producto ya esta registrado en la orden
$ROrderline = $this->manager->getRepository(COrderline::class);
if( count( $ROrderline->findBy(['c_order_id' => $order->getId(), 'm_product_id' => $product->getId(), 'isactive' => 'Y']) ) > 0 )
return $jxnr->script( self::displayError("Producto Repetido", "Este producto se encuentra registrado, modifique la cantidad de ser necesario.") );
$orderlines = $ROrderline->findBy(['c_order_id' => $order->getId()]);
/** @var AdSequenceRepository Sequence Repository */
$RSequence = $this->manager->getRepository(AdSequence::class);
$Orderline = new COrderline();
$Orderline
->setAdClientId( $order->getAdClientId() )
->setAdOrgId( $order->getAdOrgId() )
->setCActivityId( Constant::C_Activity_ID )
->setCBpartnerId( $order->getCBpartner()->getId() )
->setCBpartnerLocationId( $order->getCBpartnerLocation()->getId() )
->setCCurrencyId( $order->getCCurrency()->getId() )
->setCOrderId( $order->getId() )
->setCOrderlineId( $RSequence->findNextSequence( $ROrderline->sequence ) )
->setCUomId( $product->getCUomId() )
->setLine( (count($orderlines) + 1) * 10 )
->setLinenetamt( $productprice->getPricelist() )
->setMProduct( $product )
->setMWarehouseId( $order->getMWarehouseId() )
->setPriceactual( $productprice->getPricelist() )
->setPriceentered( $productprice->getPricelist() )
->setPricelist( $productprice->getPricelist() )
->setQtyentered(1)
->setQtyordered(1)
->setQtyreserved(1);
$date = new \DateTime("now");
$Orderline
->setCreated( $date )
->setCreatedby( $user->getId() )
->setUpdated( $date )
->setUpdatedby( $user->getId() )
->setIsactive('Y')
->setDateordered( $date )
->setCOrderlineUu( $RSequence->findNextUU() );
$RTax = $this->manager->getRepository(CTax::class);
$tax = $RTax->findBy([
'ad_client_id' => $order->getAdClientId(),
'c_taxcategory_id' => $product->getCTaxcategoryId(),
'sopotype' => ['S', 'B'],
'isdefault' => 'Y',
'isactive' => 'Y'
]);
$Orderline->setCTaxId( $tax[0]->getId() );
$this->manager->persist($Orderline);
$ROrder = $this->manager->getRepository(COrder::class);
$order = $ROrder->find( $order->getId() );
$order->setTotallines( $order->getTotallines() + $Orderline->getLinenetamt() );
$order->setGrandtotal( $order->getTotallines() );
$this->manager->persist($order);
try {
$this->manager->flush();
$this->manager->clear();
$html =
'<tr class="text-center orderline" id="'. $Orderline->getId() .'">
<td class="text-center">' . $Orderline->getLine() .'</td>
<td class="text-left">' . $Orderline->getMProduct()->getName() .'</td>
<td class="text-center">' . $Orderline->getMProduct()->getValue() .'</td>
<td class="text-right prc" id="'. $Orderline->getId() . '_prc">
<p onclick="App.Jaxon.Idempiere.Orderline.changePrc(\''. $Orderline->getId() .'\')">'. number_format($Orderline->getPriceactual(), 2) .'</p>
</td>
<td class="text-right qty" id="'. $Orderline->getId() . '_qty">
<p onclick="App.Jaxon.Idempiere.Orderline.changeQty(\''. $Orderline->getId() .'\')">'. number_format($Orderline->getQtyordered(), 2) .'</p>
</td>
<td class="text-right amt" id="'. $Orderline->getId() . '_amt">
'. number_format($Orderline->getLinenetamt(), 2) .'
</td>
<td class="btn-action">
<i onclick="App.Jaxon.Base.actionConfirm(\'Orderline\', \'delete\', \''. $Orderline->getId() .'\')" class="fas fa-trash text-danger"></i>
</td>
</tr>';
$jxnr
->prepend('tablaProductos', 'innerHTML', $html)
->assign('totallines', 'value', number_format($order->getTotallines(), 2))
->assign('grandtotal', 'value', number_format($order->getGrandtotal(), 2))
->script('$("#productModal").modal("hide")');
} catch (Exception $e) {
$jxnr->script(self::displayError("Oops!", "Ha fallado al crear la Linea", $e) );
}
return $jxnr;
}
/**
* Borra una linea de una orden temporal
*
* @param int $C_Orderline_ID Identificador de la linea
*
* @return Response Jaxon Reponse
*/
# TODO: Crear metodo para reordenar lineas
public function delete(
Int $C_Orderline_ID
)
{
$ROrderline = $this->manager->getRepository(COrderline::class);
$orderline = $ROrderline->find( $C_Orderline_ID );
$oAmt = $orderline->getLinenetamt();
$orderline->setIsactive('N');
$this->manager->persist($orderline);
$ROrder = $this->manager->getRepository(COrder::class);
$order = $ROrder->find( $orderline->getCOrderId() );
$order->setTotallines( $order->getTotallines() - $oAmt ); // Restar monto viejo de la linea
$order->setGrandtotal( $order->getTotallines() );
$this->manager->persist($order);
$jxnr = new Response;
try {
$this->manager->flush();
$this->manager->clear();
$jxnr
->remove($C_Orderline_ID)
->assign('totallines', 'value', number_format($order->getTotallines(), 2))
->assign('taxamt', 'value', number_format($order->getGrandtotal() - $order->getTotallines(), 2))
->assign('grandtotal', 'value', number_format($order->getGrandtotal(), 2));
} catch (Exception $e) {
$jxnr->script(self::displayError("Oops!", "Ha fallado al borrar la Linea", $e) );
}
return $jxnr;
}
/**
* Lista los productos coincidentes
*
* @param string $value Codigo o Nombre del producto
* @param array $formData Datos del formulario
*
* @return Response Jaxon Reponse
*/
public function getProducts(
String $value = '',
Array $formData
): Response
{
$jxnr = new Response;
/**
* Session
*/
/** @var AdUser */
$user = $this->session->get('user', null);
/** @var AdOrg */
$organization = $this->session->get('organization', null);
/** @var MWarehouse */
$warehouse = $this->session->get('warehouse', null);
####################################################################
/**
* Repositorios
*/
/** @var MProductRepository */
$RProduct = $this->manager->getRepository(MProduct::class);
/** @var MProductpriceRepository */
$RProductprice = $this->manager->getRepository(MProductprice::class);
####################################################################
// La organizacion debe ser seleccionada para listar los productos
if(!isset($organization) || $formData['organization'] == 0)
return $jxnr->script('Swal.fire("Oops!", "Primero debe seleccionar una organización!", "warning")');
// La lista de precio debe ser seleccionada para mostrar los precios de los articulos
if(!isset($formData['pricelist']) || $formData['pricelist'] == 0)
return $jxnr->script('Swal.fire("Oops!", "No has seleccionado una lista de precio!", "warning")');
/** Datos */
$pps = $RProductprice->findProductPrices($formData['pricelist'], $value);
$html= '<table id="productTable" class="table"><thead><tr><th>Marca</th><th>Nombre</th><th>Código</th><th>Cantidad</th><th>Precio</th></tr></thead><tbody>';
if( count($pps) > 0) {
foreach ($pps as $pp) {
$html .=
'<tr style="font-size: 0.9rem; cursor: pointer;" onclick="App.Jaxon.Idempiere.Orderline.create(\''. $pp->getId() .'\', jaxon.getFormValues(\'order\'))">
<td>'.$pp->getMProduct()->getSmMarca()->getName().'</td>
<td>'.$pp->getMProduct()->getName().'</td>
<td>'.$pp->getMProduct()->getValue().'</td>
<td>'. number_format($RProduct->findStorage($pp->getMProductId(), $warehouse->getId()), 2) .'</td>
<td>$'.$pp->getPricestd().'</td>
</tr>';
}
} else {
$html .= '<tr><td colspan="2">NO SE HA ENCONTRADO NINGUN PRODUCTO</td></tr>';
}
$html .= '</tbody></table>';
$jxnr
->assign('products', 'innerHTML', $html)
->script('$("#productTable").dataTable({ columnDefs: [{ orderable: true, targets: 0 }], order: [[1, "asc" ]], responsive: true, lengthChange: false, autoWidth: false, dom: \'<"row"<"col-sm-12 col-md-12"f>><"row"<"col-sm-12"rt>><"row"<"col-sm-12 col-md-5"i><"col-sm-12 col-md-7"p>>\', buttons: ["copy", "csv", "excel", "pdf", "print", "colvis"] })');
return $jxnr;
}
/**
* Cambiar cantidad de un producto en una linea
*
* @param int $C_Orderline_ID Identificador de la linea
* @param float $qty Cantidad
*
* @return Response Jaxon Reponse
*/
# TODO: Verificar las cantidades disponibles
public function setQty(
Int $C_Orderline_ID,
Float $qty
)
{
$ROrderline = $this->manager->getRepository(COrderline::class);
$orderline = $ROrderline->find( $C_Orderline_ID );
$orderline->setQtyordered( $qty );
$orderline->setQtyentered( $qty );
$orderline->setQtyreserved( $qty );
$oAmt = $orderline->getLinenetamt();
$orderline->setLinenetamt( $orderline->getPriceactual() * $qty );
//
$this->manager->persist($orderline);
//
$ROrder = $this->manager->getRepository(COrder::class);
$order = $ROrder->find( $orderline->getCOrderId() );
$amt = $order->getTotallines() - $oAmt; // Restar monto viejo de la linea
$order->setTotallines( $amt + $orderline->getLinenetamt() );
$order->setGrandtotal( $order->getTotallines() );
$this->manager->persist($order);
$jxnr = new Response;
try {
$this->manager->flush();
$this->manager->clear();
$jxnr
->assign($C_Orderline_ID . '_qty', 'innerHTML', '<p onclick="App.Jaxon.Idempiere.Orderline.changeQty(\''. $orderline->getId() .'\')">'. number_format($qty, 2) .'</p>')
->assign($C_Orderline_ID . '_amt', 'innerHTML', number_format($orderline->getLinenetamt(), 2))
->assign('totallines', 'value', number_format($order->getTotallines(), 2))
->assign('taxamt', 'value', number_format($order->getGrandtotal() - $order->getTotallines(), 2))
->assign('grandtotal', 'value', number_format($order->getGrandtotal(), 2));
} catch (Exception $e) {
$jxnr->script(self::displayError("Oops!", "Ha fallado el guardado automatico de la Linea", $e) );
}
return $jxnr;
}
/**
* Cambiar precio de un producto en una linea
*
* @param int $C_Orderline_ID Identificador de la linea
* @param float $prc Precio
*
* @return Response Jaxon Reponse
*/
# TODO: Verificar las cantidades disponibles
public function setPrc(
Int $C_Orderline_ID,
Float $prc
)
{
$ROrderline = $this->manager->getRepository(COrderline::class);
$orderline = $ROrderline->find( $C_Orderline_ID );
$orderline->setPriceactual($prc);
$orderline->setPriceentered($prc);
$orderline->setPricelist($prc);
$oAmt = $orderline->getLinenetamt();
$orderline->setLinenetamt( $orderline->getPriceactual() * $orderline->getQtyentered() );
//
$this->manager->persist($orderline);
//
$ROrder = $this->manager->getRepository(COrder::class);
$order = $ROrder->find( $orderline->getCOrderId() );
$amt = $order->getTotallines() - $oAmt; // Restar monto viejo de la linea
$order->setTotallines( $amt + $orderline->getLinenetamt() );
$order->setGrandtotal( $order->getTotallines() );
$this->manager->persist($order);
$jxnr = new Response;
try {
$this->manager->flush();
$this->manager->clear();
$jxnr
->assign($C_Orderline_ID . '_prc', 'innerHTML', '<p onclick="App.Jaxon.Idempiere.Orderline.changePrc(\''. $orderline->getId() .'\')">'. number_format($prc, 2) .'</p>')
->assign($C_Orderline_ID . '_amt', 'innerHTML', number_format($orderline->getLinenetamt(), 2))
->assign('totallines', 'value', number_format($order->getTotallines(), 2))
->assign('taxamt', 'value', number_format($order->getGrandtotal() - $order->getTotallines(), 2))
->assign('grandtotal', 'value', number_format($order->getGrandtotal(), 2));
} catch (Exception $e) {
$jxnr->script(self::displayError("Oops!", "Ha fallado el guardado automatico de la Linea", $e) );
}
return $jxnr;
}
}
?>