Добрый день!
Появилась необходимость синхронизации контрагентов межу двумя базами.
Одна база Terrasoft 3.3 Sales - Вторая ТС 3.2 X15. MS SQL 2005.
Подскажите пожалуйста как лучше реализовать такую синхронизацию.
Заранее спасибо!
Нравится
И все-таки. Нужна именно синхронизация. Или импорт из старой базы в новую ?
Мне кажется, проще всего написать скрипт, который курсором проходится по записям таблицы контрагентов одной базы, проверяет, есть ли контрагент с текущим названием во второй базе, и если нет, добавляет его. Потом аналогично для второй базы. Для того, чтобы каждый раз не проверять все записи, можно создать системный параметр "Последняя дата импорта" и проверять только те записи, дата изменения которых больше значения этого параметра.
Второй вариант - импорт в Excel из одной базы и загрузка в другую, а потом наоборот.
Слабые места этих вариантов:
1) В общем случае невозможно будет удалить контрагент, который присутствует в двух базах. Если возникнет необходимость в удалении, нужно будет сначала удалить его из двух баз, а только потом проводить синхронизацию.
2) Поскольку работа будет вестись в двух базах, непонятно, какая из них "главнее". Следовательно, возникают проблемы с обновлением записей (записи контрагентов с одинаковыми названиями могут содержать разную информацию).
3) А еще можно триггер написать.
ps. не следует забывать о связанных таблицах, "Средства связи", "Адреса" и т.д
По-сути, речь идет о репликации в рамках определенного набора таблиц (tbl_Account и все связанные с ней, включая справочники) - как вариант возможно пойти по этому пути, только настраивать репликацию на уровне серверов, не привлекая возможности Terrasoft.
В любом случае решение задачи очень нетривиально и "подводных камней" содержит больше чем пользы от такого решения. Я бы подумал о переводе второй базы на более новую версию, разовой синхронизации данных и внесении правок в конфигурацию для нужд двух разных офисов/групп пользователей - затраты на такую работу будут сравнимы.
Если же задача очень узкая - только определенные несколько полей в контрагентах - можно попробовать спланировать триггеры или хп для синхронизации (имхо проще), запускаемые по событиям из клиента Terrasoft: правка записи, создание новой, удаление (самое нетривиальное именно тут, решение "в лоб" - запретить удалять вообще:smile:)
Спасибо!
Решил пока сделать с помощью действия "Добавить контакт во вторую БД".
[javascript]
function amiAddToAnotherBaseOnExecute(ActionMenuItem, Sender) {
var AccountName = BaseWorkspace.GridDataset.ValAsGUID('Name');
.......
var TS = CreateObject("TSDskObjectLibrary.DskConnector");
var LoggedIn = TS.Login("AnotherBase");
var sqAccount = TS.Services.GetNewItemByUSI("sq_Account");
var dsAccount = dsAccount.Open();
dsAccount.Append();
dsAccount.Values('Name') = AccountName
............
dsAccount.Post();
dsAccount.Close();
}
[/javascript]
Пример подключения взял из интеграции с 1С. но ругается что нет объекта на строчку:
[javascript]
var TS = CreateObject("TSDskObjectLibrary.DskConnector");
[/javascript]
Подскажите пожалуйста как в скрипте террасофта подключаться к конфигурации другой БД.
Заранее спасибо!
"Serega" написал:Подскажите пожалуйста как в скрипте террасофта подключаться к конфигурации другой БД.
Заранее спасибо!
Пример
"Serega" написал:Решил пока сделать с помощью действия "Добавить контакт во вторую БД".
Решение не очень изящное, но тогда нужно продумать еще действие для изменения. И завязать их на автоматическую работу - чтобы исключить человеческий фактор.
"Глова Сергей" написал:Пример
Спасибо! Но в указанном примере не видна моя вторая конфигурация
[javascript]
Configuration = Connector.Configurations.Items(CurrentConfiguration);
[/javascript]
т.к. вторая конфигурация 3.3, а первая 3.2. Что делать в таком случае?
"Serega" написал:т.к. вторая конфигурация 3.3, а первая 3.2. Что делать в таком случае?
Не обратил внимания, что версии разные. Тогда проще будет через ADO сервисы сделать.
Но все таки, мой совет - напишите триггер на стороне БД.
Я бы подбные вещи решал так:
1. первичная синхранизация - разово перебросили все что надо из одной БД в другую.
2. синхранизация на уровне триггеров, если БД не на одном сервере - линковать их.
3. для каждой синхранизируемой таблици определить триггера на insert, update, delete. Если структуры БД одинаковы то можно написать хранимую процедуру, которая будет отталкиваться от названия таблици и типа (I, U, D). А потом еще и скрипт, который сам создаст все триггера ибо по виду они будут практически одинаковыми .
В результате избавите пользователей от кликов - 1, получите синхранизацию в практически реальном врмене - 2.
По-хорошему еще б куда ошибки логировать ...
"Глова Сергей" написал:Но все таки, мой совет - напишите триггер на стороне БД.
Пытаюсь написать тригер на обновление:
[sql]
USE [base1]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_AddToAnotherBaseUpdate] ON [dbo].[tbl_Account]
FOR UPDATE
AS
DECLARE @Name VARCHAR(50),
@OffName VARCHAR(50)
DECLARE CUR1 CURSOR FOR
SELECT
[Name]
,[OfficialAccountName]
FROM inserted
OPEN CUR1
FETCH NEXT FROM CUR1 INTO @Name, @OffName
WHILE @@FETCH_STATUS=0
BEGIN
if not exists (select * from [base2].[dbo].[tbl_Account] where [Name] = @Name )
INSERT INTO [base2].[dbo].[tbl_Account] ([ID], [Name], [OfficialAccountName])
VALUES(newid(), @Name, @OffName)
else
UPDATE [base2].[dbo].[tbl_Account]
SET [OfficialAccountName] = @OffName
where [Name] = @Name
END
CLOSE CUR1
DEALLOCATE CUR1
[/sql]
Но при таком тригере карточка контрагента просто зависает (((
а курсор зачем? вы ж одну запись меняете
+ насчет [sql]
IF NOT EXISTS (SELECT * FROM [base2].[dbo].[tbl_Account] WHERE [Name] = @Name )
[/sql] это не хорошо, название могли с лишним пробелом/с буковками разными заглавными/строчными написать...
имхо - по ИНН или чему подобному лучше сравнивать
при репликации для таких целей ID используют не зря
"Serega" написал:Но при таком тригере карточка контрагента просто зависает
Курсоры лучше не трогайте, когда их можно не трогать, они крайне ресурсоемки.
Да и не нужны они в вашем случае.
Зачем на апдейт проверять существование контрагента?
Идея в том, что бы вначале одним запросом или импортом или еще чем актуализировать данные на обоих БД.
А потом ваш триггер на апдейт будет выгдеть как-то так:
[sql]
UPDATE [base2].[dbo].[tbl_Account]
SET [base2].[dbo].[tbl_Account].[OfficialAccountName] = u.[OfficialAccountName],
SET [base2].[dbo].[tbl_Account].[Name] = u.[Name]
FROM inserted u
where u.[ID] = [base2].[dbo].[tbl_Account].[ID]
[/sql]
Соотвественно на insert можно пользховаться конструкцией insert select * from inserted.
ЗЫ. может чего напутал с синтаксисом, так что проверяйте в гугле )
ЗЫЗЫ. зацикливается у вас потому что вы сам курсор в цикле не переводите...
надо в тело цикла добавить FETCH NEXT FROM CUR1 INTO @Name, @OffName