Автоматическая выписка счетов/документов

      При работе с системой возникла необходимость следующей доработки конфигурации:
При работе с клиентами на основании договора выписываются счета. Большинство из них стандартные и отличаются разве что датой ну и естественно контрагентом, продуктом и тд. Вся необходимая информация заложена в договоре, карточке контрагента, продукте к договору, всё стандартно. Хотелось бы реализовать механизм, когда при выборе соотвествующего действия в разделе договора, на основании всех договоров (естественно отобранных фильтрами по тех или иных критериях) осуществлялось создание счетов. Поля, которые следует изменять (дата, период оплаты и др.) можно вывести в отдельном окне и уже используя ети данные плюс значения из других полей формировать счета.
      Получиться создание грубо говоря по "одному клику", что в свою очередь каждый раз будет сохранять время сотрудников (самое важное!), при правильной реализации исключит возникновение бесконечных поисков "кому же я забыл выставить счет" и тд. Такая схема применительна и в других случаях, например, в разделе Документы, когда выписываются акты на те же счета. 
      Думаю те, кто сталкивался с подобными медитациями в террасофте ("не трогайте меня - я счета выписываю"))) поддержат/дополнят/исправят меня или посоветуют другой механизм реализаци...
      Вот такая идея, вернее сказать необходимость в моей ситуации:-)
      Дискуссия неизбежна!

Нравится

Поделиться

20 комментариев

Не вижу никаких проблем в реализации подобного функционала. Похожий функционал, например, есть в разделе Контакты, где Вы по одному действию создаете задачу для Контакта. Также похожие действия неоднократно разрабатывались в различных конфигурация. Например, по договору создавались счета, расходные накладные.

"Fishi" написал:Дискуссия неизбежна!

Дискутировать тут особо нечего, нужно закатывать рукава и создавать необходимый функционал.

"Агутин Алексей" написал:Похожий функционал, например, есть в разделе Контакты, где Вы по одному действию создаете задачу для Контакта.

TS X25 3.1.1.26. При выборе нескольких контактов и действии "Создать задачи" соответствующее количество раз открывается карточка редактирования задачи. Я же говорил об открытии карточки один раз и копировании полей в последующие. В данном случае действие для меня совсем не понятное, потому что вместо економии времени на вбивание полей в задачах, економится время разве что на выбор действия "Создать задачу" :confused: Возможно, в дальнейшых
"Агутин Алексей" написал:Также похожие действия неоднократно разрабатывались в различных конфигурация.

Вот потому и пишу, что задача казалось бы не такая уж и нестандартная, но на форуме о реализации что-то найти трудно. Ведь если у кого-то есть рабочая реализация, то не нужно будет изобретать велосипед, а достаточно просто внести изменения для соответствия своей кинфигурации. Не одним же только менеджарам время економить:wink:

В Вашем случаем обычно применяется следующая схема:
1) В раздел Договора добавляется пункт меню "Создать счет".
2) В обработчике события этого пункта меню вызывается окно редактирования Счета с предварительным заполнением полей. Состав и содержание полей для заполнения определяется Вами.
Как добавить пункт меню и показать окно редактирования можно прочитать в
FAQ

Добрый день.
Мы эту проблему решили не много по другому.
Создали Бизнес процесс, который запускается автоматически по одному на каждый счет. (В wa_InvoiceAction добавили параметров, что бы потом клонировать был удобно.) В БП действия следущие: Создается счет, добавляются продукты, ставится задача ответственному отправить счет. После ее завершения через два дня ставится задача другому ответственному отследить приход денег. Если нет, то опять через 2 дня отследить приход.
Все вроде бы довольны :smile:

"Хомутов Кирилл" написал:Добрый день.
Мы эту проблему решили не много по другому.
Создали Бизнес процесс, который запускается автоматически по одному на каждый счет. (В wa_InvoiceAction добавили параметров, что бы потом клонировать был удобно.) В БП действия следущие: Создается счет, добавляются продукты, ставится задача ответственному отправить счет. После ее завершения через два дня ставится задача другому ответственному отследить приход денег. Если нет, то опять через 2 дня отследить приход.
Все вроде бы довольны

upd:(не ту ссылку вставил)
http://community.terrasoft.ua/ideas/4262
Я так и думал, что многие через БП будут реализовывать :)
Хотел поинтересоваться, используете ли Вы при этом планирование, и если да - то как ?

Создали окошко, которое при onPrepare запускает БП, а в onShow закрывает само себя.
На сервере шедулер, там запускается террасофт с параметрами для запуска окна.
Сейчас там таких БП стало много и мы стали объединять окна.
Т.е. одна задача в планировщике запускает окошко, которое стартует серию БП.

Понятно, но хотелось бы реализовать функцмонал без помощи БП, следовательно через действие. И тут сразу возникает несколько вопросов.
Начнем с малого, чисто теоретически. Какой вариант посоветуете выбирать:
1. Действие в разделе Договора->Создать свой счет(станд. карточка счета)->Добавить продукт к счету(карт. продукт в счете)->Автоматически повторить действие для всех договоров.
2. Действие в разделе Договора->Окно редактирования (своя карточка с полями, которые будут вноситься в поля счета и продукта к счету)-> Создание скриптом счета и продукта к нему.
В первом случае необходимо использование TemplateWindow? Если да, то получается много лишних полей, которые могут заполнятся автоматически.
А во втором, если создавать окно, то какой датасет привязать, и можно ли обойтись одним окном?

Как мне думается, оба варианта имеют право на жизнь, оба имеют как преимущества, так и недостатки. Лично я бы склонился скорее ко второму, думаю, первый реализовать будет сложнее. Прокомментирую каждый.

1) упрощает задачу тем, что при подготовке карточек редактирования у Вас уже заполнены поля по умолчанию. Также в scr_DB есть функции, позволяющие скопировать в новый датасет все поля датасета, кроме системных (ID, CreatedOn, CreatedByID и т.д., полный список - в начале этого же скрипта) и вычисляемых. Это функции CopyRowData и CopyFullData. Думаю, основной недостаток - медленная работа (функции каждый раз проходят по всем полям датасета). Нужно также не забывать о полях, которые заполняются автоматически, но разные для каждой записи (например, номер счёта). Впрочем, последнее касается обоих вариантов.

2) в этом случае можно создать окно, наследуя wnd_BaseEdit. Датасет привязывать не нужно. При обработке btnOKOnClick можно выполнять необходимое действие: считывать установленные в окне значения и подставлять их в запросы на вставку в БД. Датасет раздела Договора можно передать в это окно как атрибут, а дальше - как удобнее: создать два сервиса InsertQuery или же использовать Connector.DBEngine.ExecuteCustomSQL(SQLText, Parameters). Одного окна вполне достаточно, но в запросах необходимо не забывать и о тех значениях, которые в окне редактирования заполняются автоматически: здесь их нужно включать в параметры.

Понимаю, что данные описания очень поверхностны, но надеюсь, кое-что прояснилось.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Спасибо за разъяснения ,теперь картина еще более прояснилась.
Думаю остановлюсь на втором варианте, но, закономерно возникает несколько вопросов:
1. В созданное окно добавил несколько DateTimeControl, NumericControl и LookupControl. Считывать последние, я так понимаю, нужно из LookupDataset, а вот DateTime и Numeric?
2. Можно ли в обработчике btnOKOnClick использовать function CreateInvoiceByContract() из wnd_ContractsWorkspaceScript? Если так, то вызов CreateNewWindowEdit(Self, 'wnd_InvoiceEdit', DefaultValues, Attributes) будет излишним и что вместо него прописать? И Attributes('IsCreatedByContractID') = ContractDataset.Values('ID') тоже ненужен, посколько там происходит вызов ProcessCopyOfferingDetail, а в данном случае продукт создается заведома известный и только некоторые поля берутся в зависимости от договора и созданной карточки. Но с другой стороны, Счет должен иметь привязку к Договору(или возможно лучше создавать связь самому в скрипте?).

Насчет CreateNewWindowEdit(), кажется, решение следующее:
InvoiceDataset.Append();
InvoiceID = Connector.GenGUID();
InvoiceDataset.Values('ID') = InvoiceID;
.....
InvoiceDataset.Post();

По первому пункту: значение LookupControl'a Вы можете получить так: LookupControlName.LookupDatasetLink.Dataset.Values('ID').

Что касается остальных перечисленных контролов, их значения получить просто: ControlName.Value. У DateTimeControl'ов перед присвоением значения полю датасета полезно проверять свойство DateTimeControlName.IsNull.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Вот только для LookupControl'a ругается "Источник данных не открыт"

Тогда можно в обработке события OnNotify окна анализировать атрибуты объекта Sender:

var ControlText = Sender.Attributes('DisplayFieldValues').CommaText;
var KeyValues = Sender.Attributes('KeyValues');
var ParamsArray = new Array();
for (var i = 0; i < KeyValues.Count; i++) {
	ParamsArray[i] = KeyValues.Items(i);
}

Таким образом после выбора значения в окне справочника Вы получаете выбранные ID (KeyValues) и отображаемые значения. Можно записать их в глобальные переменные и использовать в обработке OKOnClick.

Если полей типа "Справочник" несколько, можно в обработке их событий OnPrepareSelectWindow присваивать окну атрибут с названием контрола, а потом в OnNotify его анализировать.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

По ходу выполнения возник еще один вопрос. На форуме ответ так и не нашел:
В разделе, например Счета добавил действие. В результате на основании счета создается документ в разделе Документы. Как реализовать автоматическое добавление созданного документа в Подчиненные к выбранному счету?
В Договорах, как я понял, для действия "Создать счет" реализовано передачей атрибута IsCreatedByContractID в CreateNewWindowEdit, или я ошибаюсь?

Если у Вас есть оба ID: счёта и документа, которые записаны в переменные InvoiceID и DocumentID, можно прямо в действии, после создания документа, выполнить следующее:

var Parameters = CreateSPParameters();
CreateSPParameter(Parameters, 'ID', pdtGUID, Connector.GenGUID());
CreateSPParameter(Parameters, 'InvoiceID', pdtGUID, InvoiceID);
CreateSPParameter(Parameters, 'DocumentID', pdtGUID, DocumentID);
var SQLText = 'insert into tbl_DocumentInDocument (ID, ParentInvoiceID, ChildDocumentID) values (:ID, :InvoiceID, :DocumentID';
Connector.DBEngine.ExecuteCustomSQL(SQLText, Parameters);

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

"Лабьяк Олег Игоревич" написал:Если у Вас есть оба ID: счёта и документа, которые записаны в переменные InvoiceID и DocumentID

ID счета есть, а вот документ создается вызовом CreateNewWindowEdit, следовательно нужно как-то после его создания передавать ID, как проще всего реализовать?

Проще всего реализовать через механизм нотификации.

Например, при создании документа в качестве объекта NotifyObject указываете раздел "Договора" с помощью одноимённого атрибута. Дальше, в скрипте раздела договоров при обработке события wnd_ContractsWorkspaceOnNotify анализируете сообщение и объект, отправивший его. Если сообщение равно MSG_OK и название отправителя - wnd_DocumentEdit, выполняете запрос, приведённый выше.

Атрибут IsCreatedByContractID на самом деле используется для копирования продуктов из договора в счёт.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

В wnd_InvoicesWorkspaceOnNotify получаю ID счета и созданного документа, но при выполнении запроса появляется ошибка: "Ошибка выполнения метода 'wnd_InvoicesWorkspaceOnNotify'. Object expected «Call Stack»". Возможно нужно дополнительно подключить какой-то скрипт?
И ещё - в предпоследней строчке запроса не должно быть ":DocumentID)';" вместо ":DocumentID';"?;

Да, действительно, я пропустил закрывающуюся скобку...

Если ошибка возникает при выполнении CreateSPParameters или CreateSPParameter, значит, к Вашему скрипту не подключен скрипт scr_DB, либо же в этом скрипте отсутствуют данные функции. Привожу их текст:

function CreateSPParameters() {
    return System.CreateObject('TSObjectLibrary.Parameters');
}
 
function CreateSPParameter(Parameters, Name, DataType, Value) {
	var Parameter = Parameters.CreateItem();
	Parameter.Name = Name;
	Parameter.DataType = DataType;
	Parameter.Value = Value;
	Parameters.Add(Parameter);
	return Parameter;
}

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Добавил функции, всё работает.:lol:
Спасибо!

Показать все комментарии