Entiendo lo que pides, esto fue lo que yo hice, tengo una tabla con los datos generales y otra con los detalles:
En la forma donde se captan los datos:
<?php
/* @var $this DatossalController */
/* @var $model Datossal */
/* @var $form CActiveForm */
?>
<script>
$(function(){
//Add, Save, Edit and Delete functions code
$(".btnEdit").on("click", Edit);
$(".btnDelete").on("click", Delete);
$("#btnAdd").on("click", Add);
});
function Add(){
if($('#producto option:selected').text()!=''){
var cantidad= $('#incantidad').val()==''?'0':$('#incantidad').val();
$("#tblData tbody").append(
"<tr class='even'>"+
"<td>"+ $('#producto option:selected').text()+"</td>"+
"<td>"+ cantidad +"</td>"+
"<td><img src='images/update.png' class='btnEdit' title='Actualizar' style='cursor:pointer'> <img src='images/delete.png' class='btnDelete' title='Eliminar' style='cursor:pointer'/></td>"+
"</tr>");
$(".btnEdit").off("click");
$(".btnDelete").off("click");
$(".btnEdit").on("click", Edit);
$(".btnDelete").on("click", Delete);
document.getElementById('incantidad').value ='';
$('#producto option:selected').remove();
}
else{
alert('No quedan productos para adicionar');
}
};
var oldCantidad;
function Edit(){
var par = $(this).parent().parent(); //tr
var tdCantidad = par.children("td:nth-child(2)");
var tdButtons = par.children("td:nth-child(3)");
oldCantidad=tdCantidad.html();
tdCantidad.html("<input type='text' id='txtCantidad' value='"+tdCantidad.html()+"'/>");
tdButtons.html("<img src='images/save.png' class='btnSave' title='Guardar' style='cursor:pointer'/> <img src='images/cancel.gif' class='btnCancel' title='Cancelar' style='cursor:pointer'/>");
$(".btnEdit").off("click");
$(".btnDelete").off("click");
$(".btnSave").on("click", Save);
$(".btnCancel").on("click", Cancel);
$(".btnEdit").on("click", Edit);
$(".btnDelete").on("click", Delete);
};
function Save(){
var par = $(this).parent().parent(); //tr
var tdCantidad = par.children("td:nth-child(2)");
var tdButtons = par.children("td:nth-child(3)");
tdCantidad.html(tdCantidad.children("input[type=text]").val());
tdButtons.html("<img src='images/update.png' class='btnEdit' title='Actualizar' style='cursor:pointer'/> <img src='images/delete.png' class='btnDelete' title='Eliminar' style='cursor:pointer'/>");
$(".btnEdit").off("click");
$(".btnDelete").off("click");
$(".btnEdit").on("click", Edit);
$(".btnDelete").on("click", Delete);
};
function Cancel(){
var par = $(this).parent().parent(); //tr
var tdCantidad = par.children("td:nth-child(2)");
var tdButtons = par.children("td:nth-child(3)");
tdCantidad.html(oldCantidad);
tdButtons.html("<img src='images/update.png' class='btnEdit' title='Actualizar' style='cursor:pointer'/> <img src='images/delete.png' class='btnDelete' title='Eliminar' style='cursor:pointer'/>");
$(".btnEdit").off("click");
$(".btnDelete").off("click");
$(".btnEdit").on("click", Edit);
$(".btnDelete").on("click", Delete);
};
var cont=1;
function Delete(){
var par = $(this).parent().parent(); //tr
$('#producto')
.append($("<option></option>")
.attr("value",cont)
.text(par.children("td:nth-child(1)").html()));
cont++;
par.remove();
};
$('#datossal-form').live('submit',function(event) {
var tbl = $('#tblData tbody tr').map(function() {
var row = $(this);
return { producto: row.find(':nth-child(1)').text(),
cantidad: row.find(':nth-child(2)').text()
};
}).get();
$.ajax({
url: 'index.php?r=datossal/salvarFactura',
type: 'POST',
dataType: 'text',
data: {"detalle":tbl,
"fecha": $('#Datossal_fecha').val(),
"codsalida":$('#Datossal_Codsalida').val(),
"cliente":$('#Datossal_CodCliente').val(),
"codueb":$('#Datossal_CodUEB').val(),
"codmon":$('#Datossal_CodMon').val(),
"modelid":$('#modelid').val()
},
success: function(data) {
window.location.href='index.php?r=datossal/admin';
}
});
return false;
});
</script>
<style>
.mystyle
{
background: white;
border-collapse: collapse;
width: 100%;
border: 1px #D0E3EF solid;
}
.mystyle th, .mystyle td
{
border: 1px white solid;
padding: 0.3em;
}
.mystyle th
{
color: white;
background: #69A8CD;
text-align: center;
}
.mystyle tr.even
{
background: #F8F8F8;
}
.mystyle tr.odd
{
background: #E5F1F4;
}
.mystyle tr.selected
{
background: #BCE774;
}
.mystyle tbody tr:hover
{
background: #ECFBD4;
}
</style>
Luego capto los datos generales en la misma forma y con esto capto los detalles de los productos:
<fieldset>
<legend>Lista de Productos</legend>
<table>
<tr>
<td>
<label>Producto</label>
<?php
$conceptos=array();
$todos=Productos::model()->findAll();
foreach ($todos as $producto) {
$esta=false;
foreach ($model->detalleFacturas as $value) {
if($producto->NProductos==$value->idProducto->NProductos){
$esta=true;
break;
}
}
if(!$esta)
$conceptos[$producto->Codprod]=$producto->NProductos;
}
echo CHtml::dropDownList('producto','', $conceptos);
?>
</td>
<td>
<label>Cantidad</label>
<input type="text" id="incantidad"/>
</td>
</tr>
<tr>
<td>
<input type="button" id="btnAdd" value="Adicionar Producto" />
</td>
</tr>
</table>
<table id="tblData" class="mystyle">
<thead>
<tr>
<th>Producto</th>
<th>Cantidad</th>
<th style="width:50px"></th>
</tr>
</thead>
<tbody>
<?php
foreach ($model->detalleFacturas as $value) {
echo "<tr>";
echo "<td>".$value->idProducto->NProductos."</td>";
echo "<td>".$value->cantidad."</td>";
echo "<td><img src='".Yii::app()->request->baseUrl."/images/update.png' class='btnEdit' title='Actualizar' style='cursor:pointer'>
<img src='".Yii::app()->request->baseUrl."/images/delete.png' class='btnDelete' title='Eliminar' style='cursor:pointer'/></td>";
echo "</tr>";
}
?>
</tbody>
</table>
</fieldset>
En el modelo de los datos generales escribo las relaciones:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'detalleFacturas' => array(self::HAS_MANY, 'Detallesfact', 'Id_sal'), // esta la necesito para los detalles de la forma
'codsalida' => array(self::BELONGS_TO, 'Tiposalida', 'Codsalida'),
'codCliente' => array(self::BELONGS_TO, 'Clientes', 'CodCliente'),
'codMon' => array(self::BELONGS_TO, 'Monedas', 'CodMon'),
'codUEB' => array(self::BELONGS_TO, 'Entidades', 'CodUEB'),
);
}
En el controlador hago lo siguiente, creo una accion salvar facturas, ya que cuando se crea tambien tiene que actualizar otra tabla llamada submayor, o sea, si doy una salida a un producto entonces le resta esa cantidad al saldo del submayor:
public function actionSalvarFactura()
{
$id=$_POST['modelid'];
if($id)
$model=$this->loadModel($id);
else
$model = new Datossal;
if(isset($_POST['detalle']))
{
$model->fecha=$_POST['fecha'];
$model->Codsalida=$_POST['codsalida'];
$model->CodCliente=$_POST['cliente'];
$model->CodUEB=$_POST['codueb'];
$model->CodMon=$_POST['codmon'];
if ($model->save()) {
Detallesfact::model()->deleteAll('Id_sal=:id', array(':id'=>$model->id));
foreach($_POST['detalle'] as $item){
//Insertar los detalles de la salida
$producto= Productos::model()->find('NProductos=:postID', array(':postID'=>$item['producto']));
$detalle=new Detallesfact;
$detalle->Id_sal=$model->id;
$detalle->Codprod=$producto->Codprod;
$detalle->cantidad=$item['cantidad'];
$detalle->save();
if(!$id){
$criteria=new CDbCriteria;
$criteria->addCondition('CodUEB=:coden');
$criteria->addCondition('Codprod=:codigo');
$criteria->params=array(':coden'=>$model->CodUEB , ':codigo'=>$producto->Codprod);
$objSubmp = Submayorprod::model()->find($criteria);
$objSubmp->SaldoAct = $objSubmp->SaldoAct - $item['cantidad'];
$objSubmp->save();
}
}
}
}
}
No se si sera la mejor pero me funciona bien