unit Sincronizacion; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, RdxBotones, RdxBarras, ExtCtrls, RdxPaneles, OleServer, OutlookXP, DB, IBCustomDataSet, StdCtrls, TablaProveedores, TablaClientes, TablaAgenda; type tContactos = (tcProveedores, tcClientes); TfSincronizacion = class(TForm) BarraContadores: TRdxBarraSuperior; imgSombra: TImage; brInferior: TRdxBarraInferior; bCerrar: TRdxBoton; Outlook: TOutlookApplication; Label1: TLabel; eProgress1: TLabel; eFechaUltimaSinc: TLabel; Label2: TLabel; eProgress2: TLabel; Image1: TImage; Image2: TImage; Image3: TImage; Label3: TLabel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormActivate(Sender: TObject); private ContactsFolder: MAPIFolder; CalendarFolder: MAPIFolder; NmSpace: NameSpace; FTablaContactos : TIBDataSet; FTablaAgenda : TIBDataSet; FUltimaSincronizacion : TDateTime; FCategoriaClientes : String; FCategoriaProveedores : String; function DarUltimaSincronizacion : TDateTime; procedure ActualizarFechaSincronizacion; procedure SincronizarContactos (TipoContacto : tContactos); procedure SincronizarAgenda; procedure AnadirClientesNuevos; procedure AnadirProveedoresNuevos; procedure EliminarClientesSobrantes; procedure EliminarProveedoresSobrantes; procedure InsertarProveedorBD (Contacto : TContactItem; Proveedor : TDatosProveedor); procedure InsertarClienteBD (Contacto : TContactItem; Cliente : TDatosCliente); procedure ActualizarProveedorOutlook (Contacto : TContactItem; Proveedor : TDatosProveedor); procedure ActualizarProveedorBD (Contacto : TContactItem; Proveedor : TDatosProveedor); procedure ActualizarClienteOutlook (Contacto : TContactItem; Cliente : TDatosCliente); procedure ActualizarClienteBD (Contacto : TContactItem; Cliente : TDatosCliente); public { Public declarations } end; var fSincronizacion: TfSincronizacion; implementation {$R *.dfm} uses IBSQL, Framework, BaseDatos, Mensajes, StrFunc, RdxEmpresaActiva, IBQuery, SincronizarCalendario; procedure TfSincronizacion.ActualizarClienteBD(Contacto: TContactItem; Cliente: TDatosCliente); var Cadena : String; begin with Contacto, Cliente do begin if FullName <> Nombre then Nombre := FullName; if not EsCadenaVacia(Calle) then begin Cadena := Calle; if not EsCadenaVacia(Numero) then Cadena := Cadena + ', ' + Numero; if not EsCadenaVacia(Piso) then Cadena := Cadena + ' ' + Piso; end; if Cadena <> BusinessAddressStreet then begin Calle := BusinessAddressStreet; Piso := ''; Numero := ''; end; if BusinessAddressPostalCode <> CodigoPostal then CodigoPostal := BusinessAddressPostalCode; if BusinessAddressCity <> Poblacion then Poblacion := BusinessAddressCity; if BusinessAddressState <> Provincia then Provincia := BusinessAddressState; if Email1Address <> Correo then Correo := Email1Address; if BusinessTelephoneNumber <> Telefono1 then Telefono1 := BusinessTelephoneNumber; if Business2TelephoneNumber <> Telefono2 then Telefono2 := Business2TelephoneNumber; if BusinessFaxNumber <> Fax then Fax := BusinessFaxNumber; if MobileTelephoneNumber <> Movil1 then Movil1 := MobileTelephoneNumber; if HomeTelephoneNumber <> Movil2 then Movil2 := HomeTelephoneNumber; if Body <> Observaciones then Observaciones := Body; SalvarDatos; end; end; procedure TfSincronizacion.ActualizarClienteOutlook(Contacto: TContactItem; Cliente: TDatosCliente); begin with Contacto, Cliente do begin CustomerID := Codigo; FullName := Nombre; FileAs := FullName; if not EsCadenaVacia(Calle) then begin BusinessAddressStreet := Calle; if not EsCadenaVacia(Numero) then BusinessAddressStreet := BusinessAddressStreet + ', ' + Numero; if not EsCadenaVacia(Piso) then BusinessAddressStreet := BusinessAddressStreet + ' ' + Piso; end; BusinessAddressPostalCode := CodigoPostal; BusinessAddressCity := Poblacion; BusinessAddressState := Provincia; Email1Address := Correo; BusinessTelephoneNumber := Telefono1; Business2TelephoneNumber := Telefono2; BusinessFaxNumber := Fax; MobileTelephoneNumber := Movil1; HomeTelephoneNumber := Movil2; Body := Observaciones; Categories := FCategoriaClientes; Save; end; end; procedure TfSincronizacion.ActualizarProveedorBD(Contacto: TContactItem; Proveedor: TDatosProveedor); var Cadena : String; begin with Contacto, Proveedor do begin if FullName <> Nombre then Nombre := FullName; if not EsCadenaVacia(Calle) then begin Cadena := Calle; if not EsCadenaVacia(Numero) then Cadena := Cadena + ', ' + Numero; if not EsCadenaVacia(Piso) then Cadena := Cadena + ' ' + Piso; end; if Cadena <> BusinessAddressStreet then begin Calle := BusinessAddressStreet; Piso := ''; Numero := ''; end; if BusinessAddressPostalCode <> CodigoPostal then CodigoPostal := BusinessAddressPostalCode; if BusinessAddressCity <> Poblacion then Poblacion := BusinessAddressCity; if BusinessAddressState <> Provincia then Provincia := BusinessAddressState; if Email1Address <> Correo then Correo := Email1Address; if BusinessTelephoneNumber <> Telefono1 then Telefono1 := BusinessTelephoneNumber; if Business2TelephoneNumber <> Telefono2 then Telefono2 := Business2TelephoneNumber; if BusinessFaxNumber <> Fax then Fax := BusinessFaxNumber; if MobileTelephoneNumber <> Movil1 then Movil1 := MobileTelephoneNumber; if HomeTelephoneNumber <> Movil2 then Movil2 := HomeTelephoneNumber; if Body <> Observaciones then Observaciones := Body; SalvarDatos; end; end; procedure TfSincronizacion.ActualizarProveedorOutlook( Contacto: TContactItem; Proveedor : TDatosProveedor); begin with Contacto, Proveedor do begin CustomerID := Codigo; FullName := Nombre; FileAs := FullName; if not EsCadenaVacia(Calle) then begin BusinessAddressStreet := Calle; if not EsCadenaVacia(Numero) then BusinessAddressStreet := BusinessAddressStreet + ', ' + Numero; if not EsCadenaVacia(Piso) then BusinessAddressStreet := BusinessAddressStreet + ' ' + Piso; end; BusinessAddressPostalCode := CodigoPostal; BusinessAddressCity := Poblacion; BusinessAddressState := Provincia; Email1Address := Correo; BusinessTelephoneNumber := Telefono1; Business2TelephoneNumber := Telefono2; BusinessFaxNumber := Fax; MobileTelephoneNumber := Movil1; HomeTelephoneNumber := Movil2; Body := Observaciones; Categories := FCategoriaProveedores; Save; end; end; procedure TfSincronizacion.FormCreate(Sender: TObject); var DLLHandle: THandle; begin FTablaContactos := NIL; FTablaAgenda := NIL; try Outlook.Connect; NmSpace := Outlook.GetNamespace('MAPI'); NmSpace.Logon('', '', False, False); ContactsFolder := NmSpace.GetDefaultFolder(olFolderContacts); CalendarFolder := NmSpace.GetDefaultFolder(olFolderCalendar); DLLHandle := LoadLibrary('RAPI.DLL'); if DLLHandle < 32 then raise SysUtils.Exception.Create(''); except raise SysUtils.Exception.Create('Microsoft ActiveSync no está instalado.'); end; FTablaContactos := TIBDataSet.Create(Self); with FTablaContactos do begin Database := dmBaseDatos.BD; Transaction := dmBaseDatos.Transaccion; end; FTablaAgenda := TIBDataSet.Create(Self); with FTablaAgenda do begin Database := dmBaseDatos.BD; Transaction := dmBaseDatos.Transaccion; end; FUltimaSincronizacion := DarUltimaSincronizacion; FCategoriaClientes := dmBaseDatos.DarValorConfiguracion('CAT_PPC_CLIENTES'); FCategoriaProveedores := dmBaseDatos.DarValorConfiguracion('CAT_PPC_PROVEEDORES'); if EsCadenaVacia(FCategoriaClientes) or EsCadenaVacia(FCategoriaProveedores) then raise SysUtils.Exception.Create('No están definidas las categorías de los contactos para el PocketPC.'); end; procedure TfSincronizacion.FormDestroy(Sender: TObject); begin dmBaseDatos.Rollback; if Assigned (FTablaContactos) then begin FTablaContactos.Close; FTablaContactos.Free; end; FTablaContactos := NIL; if Assigned (FTablaAgenda) then begin FTablaAgenda.Close; FTablaAgenda.Free; end; FTablaAgenda := NIL; NmSpace.Logoff; Outlook.Disconnect; end; procedure TfSincronizacion.FormShow(Sender: TObject); begin eFechaUltimaSinc.Caption := 'Ultima sincronización: ' + VarToStr(FUltimaSincronizacion); end; procedure TfSincronizacion.EliminarClientesSobrantes; var Contacto : TContactItem; Filter: Widestring; Id: IDispatch; Total : Integer; Contador : Integer; DatosContacto : TObjeto; Clientes : Items; begin Clientes := ContactsFolder.Items.Restrict('[Categorías] = "' + FCategoriaClientes + '"'); Contacto := TContactItem.Create(Self); FTablaContactos.Open; FTablaContactos.Last; try Contacto.ConnectKind := ckRunningOrNew; Total := Clientes.Count - FTablaContactos.RecordCount; Id := Clientes.GetLast; if Total > 0 then begin Contador := 0; while (Contador < Total) and Assigned(Id) do begin FTablaContactos.First; Contacto.ConnectTo(Id as ContactItem); if not FTablaContactos.Locate('CODIGO', Contacto.CustomerID, []) then begin Contacto.Delete; Contador := Contador + 1; end; Id := Clientes.GetPrevious; end; end; finally FTablaContactos.Close; Contacto.Free; end; end; procedure TfSincronizacion.SincronizarContactos(TipoContacto : tContactos); var Contacto : TContactItem; Filter: Widestring; Id: IDispatch; Contador : Integer; DatosContacto : TObjeto; begin Contador := 0; FTablaContactos.Open; with FTablaContactos do begin Last; First; while not EOF do begin if TipoContacto = tcProveedores then eProgress1.Caption := IntToStr(Contador) + ' proveedores sincronizados.' else eProgress2.Caption := IntToStr(Contador) + ' clientes sincronizados.'; Self.Refresh; Application.ProcessMessages; Filter :='[CustomerID] = "' + FieldByName('CODIGO').AsString + '"'; Id := ContactsFolder.Items.Find(Filter); if (Id = nil) then begin Contacto := TContactItem.Create(Self); Contacto.ConnectKind := ckRunningOrNew; Contacto.ConnectTo(ContactsFolder.Items.Add(olContactItem) as _ContactItem); try if TipoContacto = tcProveedores then begin DatosContacto := TDatosProveedor.Create(FieldByName('CODIGO').AsString); ActualizarProveedorOutlook(Contacto, DatosContacto as TDatosProveedor); end else begin DatosContacto := TDatosCliente.Create(FieldByName('CODIGO').AsString); ActualizarClienteOutlook(Contacto, DatosContacto as TDatosCliente); end; finally Contacto.Free; DatosContacto.Free; end; end else begin Contacto := TContactItem.Create(Self); try Contacto.ConnectKind := ckRunningOrNew; Contacto.ConnectTo(Id as ContactItem); if (Contacto.LastModificationTime > FUltimaSincronizacion) or (FTablaContactos.FieldByName('ULTIMOCAMBIO').AsDateTime > FUltimaSincronizacion) then begin Contador := Contador + 1; if TipoContacto = tcProveedores then begin DatosContacto := TDatosProveedor.Create(FieldByName('CODIGO').AsString); if (Contacto.LastModificationTime > FieldByName('ULTIMOCAMBIO').AsDateTime) then ActualizarProveedorBD(Contacto, DatosContacto as TDatosProveedor) else ActualizarProveedorOutlook(Contacto, DatosContacto as TDatosProveedor); end else begin DatosContacto := TDatosCliente.Create(FieldByName('CODIGO').AsString); if (Contacto.LastModificationTime > FieldByName('ULTIMOCAMBIO').AsDateTime) then ActualizarClienteBD(Contacto, DatosContacto as TDatosCliente) else ActualizarClienteOutlook(Contacto, DatosContacto as TDatosCliente); end; DatosContacto.Free; end; finally Contacto.Free; end; end; Contador := Contador + 1; Next; end; end; if TipoContacto = tcProveedores then eProgress1.Caption := IntToStr(Contador) + ' proveedores sincronizados.' else eProgress2.Caption := IntToStr(Contador) + ' clientes sincronizados.'; FTablaContactos.Close; end; procedure TfSincronizacion.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end; procedure TfSincronizacion.FormActivate(Sender: TObject); begin OnActivate := NIL; Screen.Cursor := crHourGlass; Self.Refresh; Application.ProcessMessages; // Sincronizar los contactos AnadirProveedoresNuevos; AnadirClientesNuevos; with FTablaContactos do begin Close; SelectSQL.Clear; SelectSQL.Add('select * from proveedores order by codigo'); Prepare; end; SincronizarContactos(tcProveedores); EliminarProveedoresSobrantes; Image1.Visible := True; Self.Refresh; Application.ProcessMessages; with FTablaContactos do begin Close; Database := dmBaseDatos.BD; Transaction := dmBaseDatos.Transaccion; SelectSQL.Clear; SelectSQL.Add('select first 100 CLIENTES.CODIGO, CLIENTES.NIFCIF, CLIENTES.NOMBRE, PROCEDENCIA, VENDEDOR, '); SelectSQL.Add('CALLE, NUMERO, PISO, CODIGOPOSTAL, POBLACION, PROVINCIA, '); SelectSQL.Add('TELEFONO1, TELEFONO2, MOVIL1, MOVIL2, FAX, CORREO, '); SelectSQL.Add('PERSONACONTACTO, OBSERVACIONES, ULTIMOCAMBIO '); SelectSQL.Add('from CLIENTES left join SUCURSALESCLIENTE on '); SelectSQL.Add('(SUCURSALESCLIENTE.CODIGOCLIENTE = CLIENTES.CODIGO and '); SelectSQL.Add('SUCURSALESCLIENTE.TIPO = ''P'') '); SelectSQL.Add('order by CLIENTES.FECHAALTA DESC, CLIENTES.CODIGO desc'); Prepare; end; SincronizarContactos(tcClientes); EliminarClientesSobrantes; Image2.Visible := True; // Sincronizar la agenda (calendario) with FTablaAgenda do begin Close; SelectSQL.Clear; SelectSQL.Add('select * from AGENDA '); SelectSQL.Add('where UPPER(USUARIO) = UPPER(:USUARIO) '); SelectSQL.Add('order by FECHAALTA'); with DeleteSQL do begin Add('delete from AGENDA '); Add('where (CODIGO = :CODIGO)'); end; ParamByName('USUARIO').AsString := dmBaseDatos.Usuario; Prepare; end; SincronizarAgenda; // Fin ActualizarFechaSincronizacion; FUltimaSincronizacion := DarUltimaSincronizacion; dmBaseDatos.Commit; Image3.Visible := True; bCerrar.Enabled := True; Self.Refresh; Application.ProcessMessages; Screen.Cursor := crDefault; end; procedure TfSincronizacion.AnadirClientesNuevos; var Contacto : TContactItem; Id: IDispatch; DatosContacto : TObjeto; Clientes : Items; DatosCliente : TDatosCliente; begin Clientes := ContactsFolder.Items.Restrict('[Categorías] = "' + FCategoriaClientes + '"'); Contacto := TContactItem.Create(Self); try Contacto.ConnectKind := ckRunningOrNew; Id := Clientes.GetFirst; while Assigned(Id) do begin Contacto.ConnectTo(Id as ContactItem); if EsCadenaVacia(Contacto.CustomerID) then begin DatosCliente := TDatosCliente.Create; try InsertarClienteBD(Contacto, DatosCliente); ActualizarClienteOutlook(Contacto, DatosCliente); finally DatosCliente.Free; end; end; Id := Clientes.GetNext; end; finally Contacto.Free; end; end; procedure TfSincronizacion.InsertarClienteBD(Contacto: TContactItem; Cliente: TDatosCliente); begin with Contacto, Cliente do begin Nombre := FullName; Calle := BusinessAddressStreet; Piso := ''; Numero := ''; CodigoPostal := BusinessAddressPostalCode; Poblacion := BusinessAddressCity; Provincia := BusinessAddressState; Correo := Email1Address; Telefono1 := BusinessTelephoneNumber; Telefono2 := Business2TelephoneNumber; Fax := BusinessFaxNumber; Movil1 := MobileTelephoneNumber; Movil2 := HomeTelephoneNumber; Observaciones := Body; SalvarDatos; end; end; procedure TfSincronizacion.InsertarProveedorBD(Contacto: TContactItem; Proveedor: TDatosProveedor); begin with Contacto, Proveedor do begin Nombre := FullName; Calle := BusinessAddressStreet; Piso := ''; Numero := ''; CodigoPostal := BusinessAddressPostalCode; Poblacion := BusinessAddressCity; Provincia := BusinessAddressState; Correo := Email1Address; Telefono1 := BusinessTelephoneNumber; Telefono2 := Business2TelephoneNumber; Fax := BusinessFaxNumber; Movil1 := MobileTelephoneNumber; Movil2 := HomeTelephoneNumber; Observaciones := Body; SalvarDatos; end; end; procedure TfSincronizacion.AnadirProveedoresNuevos; var Contacto : TContactItem; Id: IDispatch; DatosContacto : TObjeto; Proveedores : Items; DatosProveedor : TDatosProveedor; begin Proveedores := ContactsFolder.Items.Restrict('[Categorías] = "' + FCategoriaProveedores + '"'); Contacto := TContactItem.Create(Self); try Contacto.ConnectKind := ckRunningOrNew; Id := Proveedores.GetFirst; while Assigned(Id) do begin Contacto.ConnectTo(Id as ContactItem); if EsCadenaVacia(Contacto.CustomerID) then begin DatosProveedor := TDatosProveedor.Create; try InsertarProveedorBD(Contacto, DatosProveedor); ActualizarProveedorOutlook(Contacto, DatosProveedor); finally DatosProveedor.Free; end; end; Id := Proveedores.GetNext; end; finally Contacto.Free; end; end; procedure TfSincronizacion.EliminarProveedoresSobrantes; var Contacto : TContactItem; Filter: Widestring; Id: IDispatch; Total : Integer; Contador : Integer; DatosContacto : TObjeto; Proveedores : Items; begin Proveedores := ContactsFolder.Items.Restrict('[Categorías] = "' + FCategoriaProveedores + '"'); Contacto := TContactItem.Create(Self); FTablaContactos.Open; FTablaContactos.Last; try Contacto.ConnectKind := ckRunningOrNew; Total := Proveedores.Count - FTablaContactos.RecordCount; Id := Proveedores.GetLast; if Total > 0 then begin Contador := 0; while (Contador < Total) and Assigned(Id) do begin FTablaContactos.First; Contacto.ConnectTo(Id as ContactItem); if not FTablaContactos.Locate('CODIGO', Contacto.CustomerID, []) then begin Contacto.Delete; Contador := Contador + 1; end; Id := Proveedores.GetPrevious; end; end; finally FTablaContactos.Close; Contacto.Free; end; end; function TfSincronizacion.DarUltimaSincronizacion: TDateTime; var oSQL : TIBQuery; begin oSQL := TIBQuery.Create(Self); with oSQL do begin Database := dmBaseDatos.BD; Transaction := dmBaseDatos.Transaccion; SQL.Add('select ULTIMASINCRONIZACION '); SQL.Add('from USUARIOS '); SQL.Add('where UPPER(USUARIO) = UPPER(:USUARIO)'); ParamByName('USUARIO').AsString := dmBaseDatos.Usuario; try Prepare; Open; Result := FieldByName('ULTIMASINCRONIZACION').AsDateTime; finally Close; Transaction := NIL; Free; end; end; end; procedure TfSincronizacion.ActualizarFechaSincronizacion; var oSQL : TIBSQL; begin oSQL := TIBSQL.Create(nil); with oSQL do begin Database := dmBaseDatos.BD; Transaction := dmBaseDatos.Transaccion; SQL.Add('update USUARIOS set '); SQL.Add('ULTIMASINCRONIZACION = CURRENT_TIME '); SQL.Add('where UPPER(USUARIO) = UPPER(:USUARIO)'); ParamByName('USUARIO').AsString := dmBaseDatos.Usuario; try Prepare; ExecQuery; finally Close; Transaction := NIL; Free; end; end; end; procedure TfSincronizacion.SincronizarAgenda; var CitaItem : TAppointmentItem; AppItem : AppointmentItem; Filter: Widestring; Id: IDispatch; Citas : Items; i, Contador : Integer; DatosVisita : TDatosVisita; StoreID : OleVariant; SincCal : TSincCalendario; begin Contador := 0; SincCal := TSincCalendario.Create(Self); try SincCal.CalendarioBD := FTablaAgenda; SincCal.UltimaSincronizacion := FUltimaSincronizacion; SincCal.Sincronizar; finally SincCal.Free; end; end; end.