unit uGenerarPedidosCliUtils; interface uses Windows, SysUtils, Classes, pngimage, JSDialog, uBizPresupuestosCliente, uBizPedidosCliente; type TdmGenerarPedidosCli = class(TDataModule) JsListaPedidosGenerados: TJSDialog; end; function GenerarPedidoCliPre : Boolean; overload; function GenerarPedidoCliPre(const IDPresupuesto : Integer) : Boolean; overload; function GenerarPedidoCliPre(APresupuestos : IBizPresupuestoCliente) : Boolean; overload; function GenerarPedidos(APedidos : IBizPedidoCliente; AListaPresupuestos : IBizPresupuestoCliente): Boolean; function VerProcesoCompletoDeLosPedidosDelPresupuesto(APedidoCliente: Integer):Boolean; implementation {$R *.dfm} uses uDialogUtils, uBizDetallesPresupuestoCliente, uBizDetallesPedidoCliente, uPresupuestosClienteController, uPedidosClienteController, uClientesController, uDetallesPedidoClienteController, uControllerDetallesBase, uBizContactos, schPresupuestosClienteClient_Intf, schPedidosClienteClient_Intf, uDADataTable; var dmGenerarPedidosCli: TdmGenerarPedidosCli; APresupuestosClienteController : IPresupuestosClienteController; APedidosClienteController : IPedidosClienteController; ADetallesPedidosCliController : IDetallesPedidoClienteController; AClientesController : IClientesController; { Métodos auxiliares } procedure CopiarPresupuestoAPedido(APresupuesto: IBizPresupuestoCliente; APedido : IBizPedidoCliente); begin if not Assigned(APedido) then raise Exception.Create ('Albarán no asignado (CopiarPresupuestoAPedido)'); if not Assigned(APresupuesto) then raise Exception.Create ('Pedido no asignado (CopiarPresupuestoAPedido)'); if not APresupuesto.DataTable.Active then APresupuesto.DataTable.Active := True; // El albarán tiene que venir ya abierto y posicionado donde hay que copiar APedido.REFERENCIA_CLIENTE := APresupuesto.REFERENCIA_CLIENTE; APedido.TIPO_PEDIDO := APresupuesto.TIPO_PRESUPUESTO; APedido.IMPORTE_NETO := APresupuesto.IMPORTE_NETO; APedido.IMPORTE_PORTE := APresupuesto.IMPORTE_PORTE; APedido.DESCUENTO := APresupuesto.DESCUENTO; APedido.IMPORTE_DESCUENTO := APresupuesto.IMPORTE_DESCUENTO; APedido.BASE_IMPONIBLE := APresupuesto.BASE_IMPONIBLE; APedido.IVA := APresupuesto.IVA; APedido.IMPORTE_IVA := APresupuesto.IMPORTE_IVA; APedido.IMPORTE_TOTAL := APresupuesto.IMPORTE_TOTAL; APedido.DataTable.FieldByName(fld_PedidosClienteOBSERVACIONES).AsVariant := APresupuesto.DataTable.FieldByName(fld_PresupuestosClienteOBSERVACIONES).AsVariant; APedido.ID_FORMA_PAGO := APresupuesto.ID_FORMA_PAGO; APresupuestosClienteController.RecuperarCliente(APresupuesto); APedido.Cliente := APresupuesto.Cliente; //Siempre cogeremos la primera direcci¢n del contacto para el envio APedido.CALLE := APedido.Cliente.Direcciones.CALLE; APedido.CODIGO_POSTAL := APedido.Cliente.Direcciones.CODIGO_POSTAL; APedido.POBLACION := APedido.Cliente.Direcciones.POBLACION; APedido.PROVINCIA := APedido.Cliente.Direcciones.PROVINCIA; APedido.PAIS := APedido.Cliente.Direcciones.PAIS; APedido.PERSONA_CONTACTO := APedido.Cliente.Direcciones.PERSONA_CONTACTO; APedido.TELEFONO := APedido.Cliente.Direcciones.TELEFONO; end; procedure CopiarArticulosPresupuesto(AOrigen: IBizDetallesPresupuestoCliente; ADestino : IBizDetallesPedidoCliente); var i : integer; ADetallesController : IDetallesPedidoClienteController; begin if not Assigned(AOrigen) then raise Exception.Create ('Origen no asignado (CopiarArticulosPresupuesto)'); if not Assigned(ADestino) then raise Exception.Create ('Destino no asignado (CopiarArticulosPresupuesto)'); if not AOrigen.DataTable.Active then AOrigen.DataTable.Active := True; if not ADestino.DataTable.Active then ADestino.DataTable.Active := True; ADetallesController := TDetallesPedidoClienteController.Create; try //OJO IMPORTANTE //Siempre que vayamos a trabajar con los detalles debemos hacer un beginupdate de los mismos y un endupdate para //obligarle siempre a recalcular los detalles una sola vez ADetallesController.BeginUpdate(ADestino); AOrigen.DataTable.First; for i := 0 to AOrigen.DataTable.RecordCount - 1 do begin ADetallesController.Add(ADestino, TIPO_DETALLE_CONCEPTO); ADestino.Edit; ADestino.REFERENCIA := AOrigen.REFERENCIA; if AOrigen.ID_ARTICULO > 0 then ADestino.ID_ARTICULO := AOrigen.ID_ARTICULO; ADestino.CONCEPTO := AOrigen.CONCEPTO; ADestino.CANTIDAD := AOrigen.CANTIDAD; ADestino.IMPORTE_UNIDAD := AOrigen.IMPORTE_UNIDAD; ADestino.IMPORTE_TOTAL := AOrigen.IMPORTE_TOTAL; ADestino.DESCUENTO := AOrigen.DESCUENTO; ADestino.IMPORTE_PORTE := AOrigen.IMPORTE_PORTE; ADestino.VISIBLE := AOrigen.VISIBLE; ADestino.REFERENCIA_PROVEEDOR := AOrigen.REFERENCIA_PROVEEDOR; ADestino.Post; AOrigen.Next; end; finally ADetallesController.EndUpdate(ADestino); ADetallesController := NIL; end; end; procedure Inicializar; begin dmGenerarPedidosCli := TdmGenerarPedidosCli.Create(nil); APresupuestosClienteController := TPresupuestosClienteController.Create; APedidosClienteController := TPedidosClienteController.Create; ADetallesPedidosCliController := TDetallesPedidoClienteController.Create; AClientesController := TClientesController.Create; end; procedure Finalizar; begin FreeAndNIL(dmGenerarPedidosCli); APresupuestosClienteController := nil; APedidosClienteController := nil; ADetallesPedidosCliController := nil; AClientesController := nil; end; function GenerarPedidos(APedidos : IBizPedidoCliente; AListaPresupuestos : IBizPresupuestoCliente): Boolean; var APedidoActual : IBizPedidoCliente; APresupuestosController : IPresupuestosClienteController; I: Integer; bEnEdicion : Boolean; begin // ATENCIÓN!!! AFacturas tiene que estar vacio para no pisar facturas // ya generadas. if not Assigned(APedidos) then raise Exception.Create ('Pedidos no asignada (Anadir)'); if not Assigned(AListaPresupuestos) then raise Exception.Create ('Presupuestos no asignados (Anadir)'); if not APedidos.DataTable.Active then APedidos.DataTable.Active := True; if not AListaPresupuestos.DataTable.Active then AListaPresupuestos.DataTable.Active := True; APresupuestosController := TPresupuestosClienteController.Create; try // Ordenar por fecha de presupuesto AListaPresupuestos.DataTable.Sort([fld_PresupuestosClienteFECHA_PRESUPUESTO], [uDADataTable.sdAscending]); AListaPresupuestos.First; for I := 0 to AListaPresupuestos.DataTable.RecordCount - 1 do begin AListaPresupuestos._Cliente := NIL; APedidoActual := NIL; // Busco si hay alguna factura ya hecha de ese cliente APedidos.DataTable.First; if APedidos.DataTable.Locate(fld_PedidosClienteID_CLIENTE, AListaPresupuestos.ID_CLIENTE, []) then begin APedidoActual := APedidos; APedidosClienteController.RecuperarCliente(APedidoActual); APedidoActual.Cliente.DataTable.Active := True; APedidoActual.Edit; APedidoActual.REFERENCIA_CLIENTE := APedidoActual.REFERENCIA_CLIENTE + ' ' + AListaPresupuestos.REFERENCIA_CLIENTE; APedidoActual.Post; end else begin // No hay pedido de ese cliente. Creo una nueva APedidosClienteController.Anadir(APedidos); //Asignamos a el pedido la fecha pasada por parametro // AFacturas.FECHA_FACTURA := FechaFacturaNueva; APresupuestosController.RecuperarCliente(AListaPresupuestos); AListaPresupuestos.Cliente.DataTable.Active := True; APedidos.Cliente := AListaPresupuestos.Cliente; APedidos.REFERENCIA_CLIENTE := APedidos.REFERENCIA_CLIENTE + ' ' + AListaPresupuestos.REFERENCIA_CLIENTE; APedidoActual := APedidos; // Ya tengo el pedido. Le añado los conceptos del presupuesto APedidoActual.Detalles.DataTable.Last; // Añado una línea en blanco APedidosClienteController.DetallesController.Add(APedidoActual.Detalles, TIPO_DETALLE_CONCEPTO); with APedidoActual.Detalles do begin Edit; CONCEPTO := ''; Post; end; APedidosClienteController.Guardar(APedidoActual); end; // Ya tengo el pedido. Le añado los conceptos del presupuesto APedidoActual.Detalles.DataTable.Last; //No hay opcion a no copiar los detalles siempre se copiaran por ser articulos a pedir //Se pone la referencia del presupuesto y el total y nos olvidamos de los detalles { if not CopiarDetalles then begin AFacturasClienteController.DetallesController.Add(AFacturaActual.Detalles, TIPO_DETALLE_CONCEPTO); with AFacturaActual.Detalles do begin Edit; if (AListaAlbaranes.TIPO = CTE_TIPO_ALBARAN_DEV) then CONCEPTO := 'Orden Dev. ' + AListaAlbaranes.REFERENCIA + ' (Ref.Cliente: ' + AListaAlbaranes.REFERENCIA_CLIENTE + ') del ' + DateToStr(AListaAlbaranes.FECHA_ALBARAN) else CONCEPTO := 'Albarán ' + AListaAlbaranes.REFERENCIA + ' (Ref.Cliente: ' + AListaAlbaranes.REFERENCIA_CLIENTE + ') del ' + DateToStr(AListaAlbaranes.FECHA_ALBARAN); CANTIDAD := 1; IMPORTE_UNIDAD := AListaAlbaranes.BASE_IMPONIBLE; Post; end; end //Se copian los detalles del pedido a la factura else begin } // Añado el título APedidosClienteController.DetallesController.Add(APedidoActual.Detalles, TIPO_DETALLE_TITULO); with APedidoActual.Detalles do begin Edit; CONCEPTO := 'Presupuesto ' + AListaPresupuestos.REFERENCIA + ' (Ref.Cliente: ' + AListaPresupuestos.REFERENCIA_CLIENTE + ') del ' + DateToStr(AListaPresupuestos.FECHA_PRESUPUESTO); Post; end; // Añado el contenido del albarán CopiarArticulosPresupuesto(AListaPresupuestos.Detalles, APedidoActual.Detalles); //Ana pide quitar importe porte a nivel general ya que lo usa como articulo. //Reunion 10/09/2015 { APedidosClienteController.DetallesController.Add(APedidoActual.Detalles, TIPO_DETALLE_CONCEPTO); with APedidoActual.Detalles do begin Edit; CONCEPTO := 'Porte del presupuesto'; CANTIDAD := 1; IMPORTE_UNIDAD := AListaPresupuestos.IMPORTE_PORTE; Post; end; } //Ana pide quitar subtotal de los presupuestos copiados //Reunion 10/09/2015 // Añado el resumen { APedidosClienteController.DetallesController.Add(APedidoActual.Detalles, TIPO_DETALLE_SUBTOTAL); with APedidoActual.Detalles do begin Edit; CONCEPTO := 'Total del presupuesto ' + AListaPresupuestos.REFERENCIA; Post; end; } // end; //if not CopiarDetalles // Añado una línea en blanco APedidosClienteController.DetallesController.Add(APedidoActual.Detalles, TIPO_DETALLE_CONCEPTO); with APedidoActual.Detalles do begin Edit; CONCEPTO := ''; Post; end; // Guardo el pedido que acabo de generar o editar APedidoActual.CalcularImporteTotal; APedidosClienteController.Guardar(APedidoActual); // Asocio la factura con el albarán AListaPresupuestos.Edit; AListaPresupuestos.ID_PEDIDO := APedidoActual.ID; AListaPresupuestos.Post; APresupuestosController.Guardar(AListaPresupuestos); AListaPresupuestos.Next; end; Result := True; finally APresupuestosController := NIL; // HideHourglassCursor end; // Comprobar la lista de facturas generadas por si algún cliente es una // sucursal de otro cliente "central". // _CambiarFacturasClientesConSucursales(AFacturaActual); end; function GenerarPedidoCliPre : Boolean; overload; var APresupuestos : IBizPresupuestoCliente; begin Result := False; try if not Assigned(APresupuestosClienteController) then Inicializar; APresupuestos := APresupuestosClienteController.ElegirPresupuestos(APresupuestosClienteController.BuscarAceptados, 'Elija el presupuesto/s de cliente que desea utilizar para dar de alta el pedido de cliente.' + #10#13 + 'Si elige presupuestos de clientes diferentes se dará de alta un pedido por cada uno de ellos.' , True); if Assigned(APresupuestos) then Result := GenerarPedidoCliPre(APresupuestos); if Assigned(APresupuestosClienteController) then Finalizar; finally APresupuestos := Nil; end; end; function GenerarPedidoCliPre(const IDPresupuesto : Integer) : Boolean; overload; var APresupuesto : IBizPresupuestoCliente; begin Result := False; try if not Assigned(APresupuestosClienteController) then Inicializar; APresupuesto := APresupuestosClienteController.Buscar(IDPresupuesto); if Assigned(APresupuesto) then Result := GenerarPedidoCliPre(APresupuesto); if Assigned(APresupuestosClienteController) then Finalizar; finally APresupuesto := NIL; end; end; function GenerarPedidoCliPre(APresupuestos : IBizPresupuestoCliente) : Boolean; overload; var ARespuesta : Integer; APedidosNuevos: IBizPedidoCliente; i: integer; begin Result := False; if not Assigned(APresupuestos) then raise Exception.Create('Presupuestos de cliente no asignado (GenerarPedidoCliPre)'); if not APresupuestos.DataTable.Active then APresupuestos.DataTable.Active := True; if not Assigned(APresupuestosClienteController) then Inicializar; try APedidosNuevos := APedidosClienteController.Nuevo(False); if GenerarPedidos(APedidosNuevos, APresupuestos) then begin if APedidosNuevos.DataTable.RecordCount = 1 then ShowInfoMessage('El pedido se ha dado de alta con el código ' + APedidosNuevos.REFERENCIA) else begin with dmGenerarPedidosCli.JsListaPedidosGenerados.Content do begin Clear; APedidosNuevos.DataTable.Last; for i := 0 to APedidosNuevos.DataTable.RecordCount - 1 do begin if Length(APedidosNuevos.REFERENCIA) > 0 then Add(APedidosNuevos.REFERENCIA + ': ' + APedidosNuevos.NOMBRE); APedidosNuevos.DataTable.Prior; end; end; dmGenerarPedidosCli.JsListaPedidosGenerados.Execute; end; Result := True; end; finally APedidosNuevos := NIL; if Assigned(APedidosClienteController) then Finalizar; end; end; { function ElegirPedidoYGenerarPedidoCliPre(var IDAlbaran: Integer) : Boolean; overload; var APedido : IBizPedidoCliente; AAlbaran : IBizAlbaranCliente; begin Result := False; IDAlbaran := -1; AAlbaran := NIL; try if not Assigned(APedidosClienteController) then Inicializar; APedido := APedidosClienteController.ElegirPedidos(APedidosClienteController.BuscarPendientes, 'Elija el pedido de cliente que desea utilizar para dar de alta el albarán de cliente.' , False); if Assigned(APedido) then begin Result := GenerarPedidoCliPre(APedido, AAlbaran); if Result then IDAlbaran := AAlbaran.ID; end; finally if Assigned(APedidosClienteController) then Finalizar; end; end; } {function GenerarAlbaranes(AAlbaranes : IBizAlbaraneCliente; AListaPresupuestos : IBizPresupuestoCliente): Boolean; var AAlbaranActual : IBizAlbaranCliente; APresupuestosController : IPresupuestosClienteController; I: Integer; bEnEdicion : Boolean; begin // ATENCIÓN!!! AFacturas tiene que estar vacio para no pisar facturas // ya generadas. { if not Assigned(AAlbaranes) then raise Exception.Create ('Albaran no asignado (Anadir)'); if not Assigned(AListaPresupuestos) then raise Exception.Create ('Presupuestos no asignados (Anadir)'); if not AAlbaranes.DataTable.Active then AAlbaranes.DataTable.Active := True; if not AListaPresupuestos.DataTable.Active then AListaPresupuestos.DataTable.Active := True; // ShowHourglassCursor; // Application.ProcessMessages; APresupuestosController := TPresupuestosClienteController.Create; try // Ordenar por fecha de albaran AListaPresupuestos.DataTable.Sort([fld_PresupuestosClienteFECHA_PRESUPUESTO], [uDADataTable.sdAscending]); AListaPresupuestos.First; for I := 0 to AListaPresupuestos.DataTable.RecordCount - 1 do begin AListaPresupuestos._Cliente := NIL; AAlbaranActual := NIL; // Busco si hay alguna factura ya hecha de ese Proveedor AAlbaranes.DataTable.First; if AAlbaranes.DataTable.Locate(fld_AlbaranesClienteID_Cliente, AListaPresupuestos.ID_Cliente, []) then begin AAlbaranActual := AAlbaranes; AAlbaranesClienteController.RecuperarProveedor(AAlbaranActual); AAlbaranActual.Proveedor.DataTable.Active := True; end else begin // No hay factura de ese Proveedor. Creo una nueva AAlbaranesClienteController.Anadir(AAlbaranes); APresupuestosController.RecuperarProveedor(AListaPresupuestos); AAlbaranes.Proveedor := AListaPresupuestos.Proveedor; //Siempre asignaremos por defecto la referencia de factura de proveedor que tenga el primer albaran del proveedor bEnEdicion := (AAlbaranes.DataTable.State in dsEditModes); if not bEnEdicion then AAlbaranes.Edit; AAlbaranes.REFERENCIA_PROVEEDOR := AListaPresupuestos.REF_FACTURA_PROV; AAlbaranes.Post; if bEnEdicion then AAlbaranes.Edit; //Si el albaran es de tipo devolución hacemos la factura de tipo abono if (AListaPresupuestos.TIPO = CTE_TIPO_ALBARAN_DEV) then begin bEnEdicion := (AAlbaranes.DataTable.State in dsEditModes); if not bEnEdicion then AAlbaranes.Edit; AAlbaranes.TIPO := CTE_TIPO_ABONO; AAlbaranes.Post; if bEnEdicion then AAlbaranes.Edit; end; AAlbaranActual := AAlbaranes; end; // Ya tengo la factura. Le añado los conceptos del albarán AAlbaranActual.Detalles.DataTable.Last; // Añado el título AAlbaranesClienteController.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_TITULO); // Self.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_TITULO); with AAlbaranActual.Detalles do begin Edit; CONCEPTO := 'Albarán ' + AListaPresupuestos.REFERENCIA + ' del ' + DateToStr(AListaPresupuestos.FECHA_ALBARAN); Post; end; // Añado el contenido del albarán CopiarArticulosPresupuesto(AListaPresupuestos.Detalles, AAlbaranActual.Detalles); {En los albaranes a proveedor el porte es a nivel del artículo Self.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_CONCEPTO); with AAlbaranActual.Detalles do begin Edit; CONCEPTO := 'Porte del albarán'; CANTIDAD := 1; IMPORTE_UNIDAD := AListaPresupuestos.IMPORTE_PORTE; Post; end; } { // Añado el resumen AAlbaranesClienteController.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_SUBTOTAL); //Self.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_SUBTOTAL); with AAlbaranActual.Detalles do begin Edit; CONCEPTO := 'Total del albarán ' + AListaPresupuestos.REFERENCIA; Post; end; // Añado una línea en blanco AAlbaranesClienteController.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_CONCEPTO); // Self.DetallesController.Add(AAlbaranActual.Detalles, TIPO_DETALLE_CONCEPTO); with AAlbaranActual.Detalles do begin Edit; CONCEPTO := ''; Post; end; // Guardo la factura que acabo de generar o editar AAlbaranActual.CalcularImporteTotal; AAlbaranesClienteController.Guardar(AAlbaranActual); // Self.Guardar(AAlbaranActual); // Asocio la factura con el albarán AListaPresupuestos.Edit; AListaPresupuestos.ID_FACTURA := AAlbaranActual.ID; AListaPresupuestos.Post; APresupuestosController.Guardar(AListaPresupuestos); AListaPresupuestos.Next; end; Result := True; finally APresupuestosController := NIL; // HideHourglassCursor end; end; } function VerProcesoCompletoDeLosPedidosDelPresupuesto(APedidoCliente: Integer):Boolean; begin if not Assigned(APedidosClienteController) then Inicializar; Result := APedidosClienteController.VerProcesoCompleto(APedidoCliente); if Assigned(APedidosClienteController) then Finalizar; end; end.