This topic is locked

Guide 7 - Synchronize update between Master and Detail

12/29/2020 1:02:10 PM
PHPRunner Tips and Tricks
fhumanes author


This example that I have done is motivated because there is a lot of concern in synchronizing the update of "Master and Detail", for example, in an "Factura" with the lines of the "Factura" and that this example serves for this and other cases where we have this relationship of Master and Detail.
To explain it, I put the images of the example.



Objective:
You want to show the information of the Master "Invoice" where you have the total evaluation of the products, which are all at the bottom of the page.
In the action of registering the "Factura" (Invoice), in that same action it will be possible to inform the detail of the products and the total of the invoice will be refreshed by JavaScript (including the cancellation of any product registration).
In the case of revision or edition of the "Factura", this same update will be made for each change that occurs in products and another alternative method will be used, with a refresh of the "Factura" edition page.
Technical Solution
As I have indicated, there is a different treatment for the "Add" action and the "Edit" action, so we use a session variable and a proxy variable, so that in the management of the "Lines" we know what action we are in. .
There is a "Tips" in the PHPRunner Forum "Calculating order totals on the fly" which is where I started, but unlike him, I leave you a complete example and some characteristics that are not described in the aforementioned article.
One of those special features is how to “Reload” the page when we have done one or more “delete” of invoice lines.
Step to describe the codes made:
In "Factura".
In both Add and Edit, “Before Display” event

At this point, the session variables "ACTION" are defined, which indicates whether we are in Add or Edit, and the variable "IDFACTURA", which is the primary key that identifies the Invoice.

$_SESSION["ACTION"] = "Add";


In Add, “After record added” event, is where we create the session variable “INVOICE ID”, since until we do the insert we do not have this value.

$_SESSION['IDFACTURA'] = $values['idfactura'];


In both Add and Edit, “Javascript Onload event” we put in “readonly” the variables that we do not want to be updated directly and we create a JS variable to save the page object. We will use this object later to produce the "Reload" of the page.

var TotalFactura = Runner.getControl(pageid, 'Totalfactura');

// TotalFactura.makeReadonly();
var cliente_idcliente = Runner.getControl(pageid, 'cliente_idcliente');

cliente_idcliente.makeReadonly();

var Nif = Runner.getControl(pageid, 'Nif');

Nif.makeReadonly();

var Domicilio = Runner.getControl(pageid, 'Domicilio');

Domicilio.makeReadonly();

var RestoDomicilio = Runner.getControl(pageid, 'RestoDomicilio');

RestoDomicilio.makeReadonly();

var Email = Runner.getControl(pageid, 'Email');

Email.makeReadonly();
// Para Reload of page EDIT

window.customersPage = pageObj;


In "Linea Factura".
In List, these two events are used to produce the "Reload" of the page when "Linea Factura" are eliminated. Event "After record deleted".

When the records have been removed, two proxy variables are loaded (to upload to the browser) "RELOAD" and "IDFACTURA".

In addition, the PHP code that recalculates the "TotalFactura" is called and the "Factura" record is updated.

$pageObject->setProxyValue("RELOAD", "Sí");

$pageObject->setProxyValue("IDFACTURA", $_SESSION['IDFACTURA']);
include "MyCode/total.php"; // Actualizar total


<?php

$idfactura = $_SESSION['IDFACTURA'];

$sql = "SELECT sum(Valor) total FROM linea_factura where factura_idfactura = $idfactura";

$rs = DB::Query($sql);

$data = $rs->fetchAssoc();

$total = $data['total'];

$sql = "update factura set TotalFactura = $total where idfactura = $idfactura";

DB::Exec($sql);

?>


In List, "Javascript Onload event" event.

If the “RELOAD” variable exists, it is because “DELETE” of records has been made and a RELOAD of the page (previously saved) is made, corresponding to the “FACTURA” record. "IDFACTURA" is used to show that same record again.

// Reload age Master

if( proxy['RELOAD'] ) {

window.customersPage.reload({editid1:proxy['IDFACTURA']});

}


In both Add and Edit, the event “After record added / updated” has been used.

To run the process that updates "TotalFactura" of the invoice lines.

include "MyCode/total.php"; // Actualizar total


_In both Add and Edit, the “Before display” event_is used.

To create the proxy variables (uploaded to the browser) "ACTION" and "IDFACTURA".

$pageObject->setProxyValue("ACTION", $_SESSION["ACTION"]);

$pageObject->setProxyValue("IDFACTURA", $_SESSION['IDFACTURA']);


In Add the "Javascript Onload event" is used.

To do the calculations multiply the Price by the Quantity. You will see that at this point, when using the marking of the numbers such as Spain, the decimal symbol is the comma "," and in this case it is necessary to pass it to point ".", To perform operations in javascript.

Also, it makes a difference if we are in the ACTION = Add, because in the case of Add, the recalculation of "TotalFactura" is done in javascript and otherwise, when the Add is accepted, the page is reloaded.

function calcTotals() { // Cálculo de "TotalFactura" y su almacenamiento

var total= 0;

$("tr[id*=gridRow]").each(function() {

var id=$(this).attr('id');

id = id.substring(7);

total = total + parseFloat(($("#readonly_value_Valor_"+id).val()).replace(",", "."));

});

$("#value_TotalFactura_1").val(total);

};

var ACTION = proxy['ACTION']; // Para conocer la página del Máster
var producto_idproducto = Runner.getControl(pageid, 'producto_idproducto');

producto_idproducto.makeReadonly();

var Precio = Runner.getControl(pageid, 'Precio');

Precio.makeReadonly();

var Valor = Runner.getControl(pageid, 'Valor');

Valor.makeReadonly();

var Cantidad = Runner.getControl(pageid, 'Cantidad');

Cantidad.makeReadonly();
Precio.on('change', function(e){

Cantidad.makeReadWrite();

if ( Cantidad.getValue() != 0 ) {

Valor.setValue(parseFloat(Precio.getValue().replace(",", ".")) * parseFloat(Cantidad.getValue().replace(",", ".")));

if (ACTION == 'Add') {

calcTotals();

}

}

});
Cantidad.on('change', function(e){

Valor.setValue(parseFloat(Precio.getValue().replace(",", ".")) * parseFloat(Cantidad.getValue().replace(",", ".")));

if (ACTION == 'Add') {

calcTotals();

}

});
if(inlineRow){ // En el caso de que se cancele una operación de Add Línea

inlineRow.onCancel = function(){

if (ACTION == 'Add') {

calcTotals();

}

};

}
// Reload age Master

this.on('afterInlineAdd', function(){

if (ACTION != 'Add') {

window.customersPage.reload({editid1:proxy['IDFACTURA']});

}

});


In Edit the “Javascrit Onload event” is used.

To do the Quantity Price calculations and to do the Master's "Reload" when the operations have been completed.

var producto_idproducto = Runner.getControl(pageid, 'producto_idproducto');

producto_idproducto.makeReadonly();

var Precio = Runner.getControl(pageid, 'Precio');

Precio.makeReadonly();

var Valor = Runner.getControl(pageid, 'Valor');

Valor.makeReadonly();

var Cantidad = Runner.getControl(pageid, 'Cantidad');

// Cantidad.makeReadonly();
Precio.on('change', function(e){

// Cantidad.makeReadWrite();

if ( Cantidad.getValue() != 0 ) {

Valor.setValue(parseFloat(Precio.getValue().replace(",", ".")) * parseFloat(Cantidad.getValue().replace(",", ".")));

}

});
Cantidad.on('change', function(e){

Valor.setValue(parseFloat(Precio.getValue().replace(",", ".")) * parseFloat(Cantidad.getValue().replace(",", ".")));



});
// Reload age Master

this.on('afterInlineEdit', function(){

window.customersPage.reload({editid1:proxy['IDFACTURA']});

});


As in all occasions, you can ask me any questions or problems in my email account [email="fernandohumanes@gmail.com"]fernandohumanes@gmail.com[/email]
Also, I leave the example on my website so that you can reproduce it on your computers.