Добрый день,

Возможно ли создать и вызвать БДшную функцию на сервере,

Например создать функцию(Через CREATE FUNCTION ) и добавить ее в скрипты в пакете

и потом как нибудь вызвать ее и получить то что она возвращает?

 

Заранее спасибо!

Нравится

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

так вам нужна функция или хранимка? в любом случае вот тема. Как вызвать из js кода свой сервис можно посмотреть на sdk / как добавить кусок C# кода в БП - элемент "задание-сценарий". Ну и в C# коде вызываете хранимку, в хранимке делаете что угодно, результат читаете с помощью datareader'а и далее по бизнес логике...

Варфоломеев Данила,

Спасибо за ссылку, мне нужна функция, но по идее процедурой тоже можно обойтись

Можно вызвать хранимую процедуру. Правильный вызов процедуры (пример):

DataValueTypeManager dataValueTypeManager =UserConnection.DataValueTypeManager; 

var dateTimeValue = new DateTime(2009, 01, 02, 22, 12, 0);

                    Stream stream = newMemoryStream(Encoding.Unicode.GetBytes("Тест большого бинарного объекта"));

                    var textDataValueType = newTextDataValueType(dataValueTypeManager);

                    var guidDataValueType = newGuidDataValueType(dataValueTypeManager);

                    var integerDataValueType = newIntegerDataValueType(dataValueTypeManager);

                    var floatDataValueType = newFloat2DataValueType(dataValueTypeManager);

                    var booleanDataValueType = newBooleanDataValueType(dataValueTypeManager);

                    var dateTimeDataValueType = newDateTimeDataValueType(dataValueTypeManager);

                    var idValue = new Guid("{BCDB8392-55BC-472A-A49D-22A975E0BEF6}");



                    StoredProcedure storedProcedure =

                           new StoredProcedure(Page.UserConnection,"tsp_TestStoredProcedure")

                           .WithParameter("IdParameter", idValue)

                           .WithVarParameter("VarIdParameter", idValue, guidDataValueType)

                           .WithParameter("TextParameter", "Украина")

                           .WithVarParameter("VarTextParameter", "Украина", textDataValueType)

                           .WithParameter("IntegerParameter", 10)

                           .WithVarParameter("VarIntegerParameter", 10, integerDataValueType)

                           .WithParameter("FloatParameter", 3.14)

                           .WithVarParameter("VarFloatParameter", 3.14, floatDataValueType)

                           .WithParameter("BooleanParameter", true)

                           .WithVarParameter("VarBooleanParameter", false, booleanDataValueType)

                           .WithParameter("DateTimeParameter", dateTimeValue)

                           .WithVarParameter("VarDateTimeParameter", dateTimeValue, dateTimeDataValueType)

                           .WithParameter("BinaryParameter", stream)

                           .WithVarParameter("VarBinaryParameter", stream)

                           .WithOutputParameter("ResultParameter", textDataValueType) as StoredProcedure;

storedProcedure.PackageName = Page.UserConnection.DBEngine.SystemPackageName;

storedProcedure.Execute();



Функция вызывается аналогично.

Add comment

Антон Малий,

Я понял, большое спасибо

Вот для функции:

public virtual string GenerateCardCVC(Guid cardId) {
	var udf = new UserDefinedFunction(UserConnection, "fn_GenerateCardCVC");
	udf.WithParameter("pCardId", cardId);
	return udf.ExecuteScalar<string>();
}

 

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

Помогите пожалуйста отфильтровать справочное поле на клиенте,

У меня есть объект CreditCard у которого есть деталь [залоговое обеспечение] они связаны между собой через колонку  [залоговое обеспечение].CCId(идентификатор кредитной карты).

Так же в объекте [залоговое обеспечение] есть справочное поле [Контакт] собственно именно его я и хочу отфильтровать. Чтобы в нем появлялись только те контакты которые присутствуют в другой детали в CreditCard - CC_TxParticipant(деталь) которые связаны так же как и [залоговое обеспечение] через колонку CCId(идентификатор кредитной карты).

 

В детали CC_TxParticipant есть два справочных поля - 1. Контакт 2. Тип контакта, так вот я не совсем понимаю как сделать так чтобы во время фильтра отсеивались контакты с определенным типом.

 

Сейчас для фильтрации только [Контактов] из CC_TxParticipant я делаю так:

"lookupListConfig": {
"filters": [
function() {
...
var allParticipantsFilter = this.Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "[CC_TxParticipant:Participant:Id].CC", master.value);
...
    }
]

где master.value = идентификатор CreditCard, потом добавляю фильтр в общий фильтр и так далее, таким образом я получаю только тех контактов которые присутствуют в детали CC_TxParticipant именно этого CreditCard

-----------------

Попробую объяснить подробнее

Есть следующие объекты:

 

0.[CreditCard] - к нему относятся 2 детали:

1.[CC_TxParticipant] - связана с [CreditCard] через колонку CCId(идентификатор [CreditCard])

2.[CC_CollateralData] - связана с [CreditCard] через колонку CCId(идентификатор [CreditCard])

 

В объекте [CC_TxParticipant] есть справочное поле Контакт, и справочное поле с типом участника.

В объекте [CC_CollateralData] есть справочное поле Контакт которое требуется отфильтровать таким образом, чтобы появлялись только те контакты которые находятся в детали объекта [CC_TxParticipant], кроме тех у которых скажем Тип участника не равен *какой то айди*.

На данный момент у меня получилось только отфильтровать таким образом чтобы отображались только те контакты которые находятся в объекте [CC_TxParticipant] без учета их типа.

master.value  в коде выше как раз является идентификатором [CreditCard]

Понимаю что объяснение получилось запутанное, поэтому заранее прошу прощения

Нравится

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

Добрый вечер.

Что бы отсеять контакты по типу нужно добавить фильтр где в качестве сравнения будет конфигурационная константа или id «типа контакта» (таблица ContactType). Например:

filterGroup.add("IsEmployeeType", Terrasoft.createColumnFilterWithParameter(                            Terrasoft.ComparisonType.EQUAL, "Contact.Type", ConfigurationConstants.ContactType.Employee));

При этом нужно не забыть указать зависимость на «ConfigurationConstants»:

define("ContactPageV2", ["ConfigurationConstants"],
function(ConfigurationConstants) {

Все типы констант вы можете посмотреть при отладке.

Или же можно сделать запрос используя id из таблицы ContactType:

 filterGroup.add("IsEmployeeType", Terrasoft.createColumnFilterWithParameter(                           Terrasoft.ComparisonType.EQUAL, "Contact.Type",” 806732EE-F36B-1410-A883-16D83CAB0980”));

 

VladKapitanchyk,

Добрый день,

Спасибо за совет, к сожалению построение обычного фильтра не составляет проблемы, мой вопрос несколько сложнее

Сериков Асхат Кайратович пишет:

VladKapitanchyk,

 мой вопрос несколько сложнее

Добрбый день! Если мы не правильно поняли, то просьба переформулировать запрос либо объяснить "на пальцах" . Мы ради будем помочь.

Вильшанский Дмитрий,

Добрый день,

прошу прощения за такой запутанный вопрос, переформулировал, надеюсь получилось

Добрый день.

Спасибо за совет, к сожалению построение обычного фильтра не составляет проблемы

Вам нужно составить фильтр из 2 условий. Т.е. добавить в фильтр группу 2 фильтра(фильтр контактов которые находятся в детали объекта [CC_TxParticipant], и фильтр контактов у которых Тип участника не равен *какой то айди*). На академии можно посмотреть. https://academy.terrasoft.ua/documents/technic-sdk/7-11/primenenie-filt…

VladKapitanchyk,

День добрый,

Разобрался, пытался перемудрить зачем то.

Спасибо большое

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

Доброго дня Террасофт!

В черговий раз звертаюся до Вас з допомогою!

27.04.2017 ми підписали договір №27/04/17 - 506 з Террасофтом на придбання 2-х ліцензій продукту bpm`online real estate. На той момент продукт нас повністю задовільняв, але з часом ми вирішили його налаштувати під себе. Знайшли інтегратора, але нам сказали що версія 7.7 якою ми користуємось на даний момент - застаріла. Після підтвердження можливості оновитися "хмарно" до версії 7.11 почалися наші проблеми з Афлексом.

Тестовий сайт на даній версії працював не стабільно, або ж не працював взагалі. Про це Афлексу ми писали - безрезультатно. Через деякий час все що ми на цьому сайті протестили і те що Афлекс не встиг виправити - видалили (ніби як сплив час тестового періоду). Афлекс надав нам новий тестовий сайт де все почалося з початку з тими ж помилками та багами, причому продукт вже bpm`online real estate development (переживаємо щоб з часом нам не пред'явили платити більше). Виправляв це все він теж не дуже оперативно. Врешті-решт зійшлися на критичній проблемі: об'єкти з лістингу не находять заявок, заявки не находять об'єктів з лістингу. Телефонні преговори з Василием Ипполитовим теж були безрезультатні. Він нас уважно слухав та обіцяв все виправити. Після цих дзвінків тех.підтримка Афлекса відповідала нам що живе спілкування не передбачене нашим тарифним планом!

Переписки продовжувались. В кінці-кінців, після спливу 6 місяців Афлекс нам продемонстрував що під їхній тестовий об'єкт в лістингу підтягується тестова заявка з лістингу і навпаки. Ок, але постає питання що нам робити з нашими об'єктами та заявками які не дружать в версії 7.11? Афлекс вперто уникає живого спілкування та вникнення в причину неможливості переходу нами з версії 7.7 на 7.11.

Звертаємось до Вас як розробника та ліцензіара з вимогою забезпечити нам робочий перехід з версії 7.7 на версію 7.11! В цьому випадку, можливо доберемо ще 1 ліцензію.

В разі, якщо до моменту закінчення нашого з Вами договору (квітень 2018 р.) ми не побачимо позитивних змін, спробуємо поширити серед інтернет спільноти та своїх колег-ріелторів інформацію з власного досвіду, про продукт Террасофта та його підтримку.

З надією на розуміння та співпрацю,

Данкін Олександр.

 

P.S. прошу з Афлексом нас не зводити. Це проста марна трата часу, який нам ніхто не збирається компенсовувати.

Нравится

1 комментарий

Здравствуйте, Александр!

Для решения вашей проблемы рекомендую связаться с вашим ответственным менеджером или обратиться в тех. поддержку Террасофта написав письмо на почту - support@terrasoft.ru или support@bpmonline.com

Так же я передал информацию о данном посте вашему ответственному менеджеру и создал обращение SR-0657862. 

Обращаю ваше внимание, community предназначено для решения вопросов связанных с разработкой. Здесь пользователи и разработчики решают вопросы с доработкой bpm'online.

При создании поста, пожалуйста, явно указывайте бизнес цель и какие ошибки возникают при её достижении.  

 

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

Добрый день, каким образом можно подружить bpm'online с Infratel или MigthyCall?

Нравится

3 комментария

Здравствуйте, Владимир!

В базовой версии bpm'online поддерживается интеграция со следующими телефониями https://academy.terrasoft.ru/documents/sales-enterprise/7-11/sravnenie-…

Если данная телефония позволяет создавать SIP подключения, то для решения вашей проблемы Вы можете использовать Webitel Any Voip Connector. https://marketplace.terrasoft.ru/app/any-voip-connector-bpmonline

По вопросу интеграции необходимо обратиться в их тех. поддержку support@webitel.ru

 

 

 

 

Добрый день Владимир.

Вариант второй. написать Свою интеграцию с данными телефониями. Дай бог API по данным телефониям в открытом доступе. Создатели и разработчики это компания Яндекс. Но конечно лучше интегрироваться с уже существующими провайдерами, такие как Webitel. Но если вы уже используете провайдера к примеру mightycall, то я бы пошел по пути написания собственной интеграции.

Добрый день, Владимир!

MightyCall - это новое название платформы Infratel. У разработчиков MightyCall есть документированный API системы, через который такая интеграция может быть реализована. Для версии Infratel 4.0 такой коннектор точно был. Думаю, что разработчики смогут выдать Вам API и проконсультировать по возможностями интеграции. Запросить API можно либо оставив запрос на сайте https://www.mightycall.ru/ либо в создав тикет на портале технической поддержки. 

Михаил, Вы неумышленно ввели в заблуждение коллегу. Яндекс использует ВАТС от MightyCall, это облачная платформа, а решение называется Яндекс.Телефония. Решение MightyCall/Infratel - это коробочное серверное решение для контактных центров, не ВАТС.

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

Коллеги, требуется помощь!

Программирую регулярное выполнение бизнес-процесса через планировщик таким образом:

первый элемент бизнес-процесса проверяет наличие триггера, и в случае отсутствия - создаёт триггер в БД. Т.е. при первом ручном запуске БП - он формирует себе "расписание" последующих запусков.

Пробовал использовать несколько способов, но все они не работают, в Библиотеке БП процесс присутствует, триггеры в БД заводятся. Но последующих запусков не происходит.

В чём может быть причина?

Доп. инфоормация:

Версия BPM 7.7 Bank Customer Journey. БД Oracle.

Триггеры находятся в состоянии WAITNG.

Пользователь для выполнения системных операций (SystemUser) Supervisor.

IIS перезапускал. Application Pool находится в режиме Универсальный.

Способы, которые я пробовал использовать:

CronTriggerImpl:

var cronExp = "0 0/5 * ? * * *";
 
if (!AppScheduler.DoesJobExist(jobName, jobGroup))
{
	var job = AppScheduler.CreateProcessJob(jobName, jobGroup, procName, userConnection.Workspace.Name, userConnection.CurrentUser.Name);
	var trigger = new CronTriggerImpl(jobName + "Trigger", jobGroup, cronExp);
	AppScheduler.Instance.ScheduleJob(job, trigger);
}

 

CronTriggerImpl:

var cronExp = "0 0/5 * ? * * *";
 
if (!AppScheduler.DoesJobExist(jobName, jobGroup))
{
	var job = AppScheduler.CreateProcessJob(jobName, jobGroup, procName, userConnection.Workspace.Name, userConnection.CurrentUser.Name);
	var trigger = new CronTriggerImpl(jobName + "Trigger", jobGroup, cronExp);
 
	trigger.MisfireInstruction = MisfireInstruction.CronTrigger.FireOnceNow;
	trigger.TimeZone = TimeZoneInfo.Utc;
 
	AppScheduler.Instance.ScheduleJob(job, trigger);
}

 

ScheduleMinutelyProcessJob:

int periodInMinutes = 3;
 
if (!AppScheduler.DoesJobExist(jobName, jobGroup))
{
	AppScheduler.ScheduleMinutelyProcessJob(jobName, jobGroup, procName,
		userConnection.Workspace.Name, userConnection.CurrentUser.Name, periodInMinutes);
}

 

SimpleTriggerImpl:

int startOffset = 4;
 
if (AppScheduler.DoesJobExist(jobName, jobGroup))
{
   AppScheduler.RemoveJob(jobName, jobGroup);
}
 
var job = AppScheduler.CreateProcessJob(jobName, jobGroup, procName, userConnection.Workspace.Name, userConnection.CurrentUser.Name);
var trigger = new SimpleTriggerImpl(jobName + "Trigger", jobGroup, DateTime.UtcNow.AddMinutes(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);

 

SimpleTriggerImpl от системного пользователя:

int startOffset = 4;
 
if (AppScheduler.DoesJobExist(jobName, jobGroup))
{
   AppScheduler.RemoveJob(jobName, jobGroup);
}
 
var job = AppScheduler.CreateProcessJob(jobName, jobGroup, procName, userConnection.Workspace.Name, userConnection.CurrentUser.Name, null, true);
var trigger = new SimpleTriggerImpl(jobName + "Trigger", jobGroup, DateTime.UtcNow.AddMinutes(startOffset));
AppScheduler.Instance.ScheduleJob(job, trigger);

 

При использовании всех вариантов - триггеры создаются в БД, но повторно не срабатывают. Куда копать?

Нравится

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

сайт пингуется периодически? (там вроде как пул приложений засыпает периодически, если пользователи долго не работают, и триггеры отваливаются)

Сайт пингуется. Так же есть уже заведённые (не мной, до меня) Job'ы c триггерами, которые регулярно запускаются с периодичностью в 2 минуты. Мои же триггеры не запускаются

Может, оно попыталось запуститься и свалилось. Иногда можно понять, глядя в базе на записи об этих триггерах в таблицах с названиями, начинающимися с QRTZ. Может, там найдутся подробности о произошедшем или видно разницу с нормально работающим.

Для контроля запускал такой скрипт (БД Oracle) -



SELECT sched_name,

       trigger_group,

       job_name,

       job_group,

       trigger_state,

         TO_DATE ('03-jan-0001', 'dd-mon-yyyy')

       + next_fire_time / (10000000 * 60 * 60 * 24)

           AS next_fire_time,

       TO_DATE ('03-jan-0001', 'dd-mon-yyyy')

       + prev_fire_time / (10000000 * 60 * 60 * 24)

           AS prev_fire_time

  FROM qrtz_triggers

он показывает что у моих триггеров prev_fire_time - пустое, а next_fire_time, к примеру, "28.11.2017 8:41:49".  У работающих же триггеров - оба значения заполнены, и примерно например, prev_fire_time: "28.11.2017 8:40:48"

 

 

Проверьте что бы название (не заголовок) целевых процессов совпадал со значением в переменной procName (при создании джоба).

Если не поможет напишите в тех. поддержку.

Олег, спасибо)

Вроде перепроверил заголовки. Уже !!! параллельно написал в поддержку платную. Давайте вместе найдём в чём затык!

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

Коллеги, добрый день! 

Работа с объектами bpm'online по протоколу OData через WCF-клиент.

Версия продукта BPM Bank Customer Journey 7.7

Вызов происходит в Windows-приложении на удалённой машине:

// C#
  // Отрабатывает корректно:
    var sys = this.SysSettingsCollection.Where(x => x.Code.Equals(settingsCode)).FirstOrDefault();
    if (sys == null)
    {
        return false;
    }
 // Выбрасывает исключение:
    var val = this.SysSettingsValueCollection.Where(x => x.SysSettingsId.Equals(sys.Id)).FirstOrDefault();
    //var val = this.SysSettingsValueCollection.Where(x => x.SysSettingsId.Value.Equals(sys.Id)).FirstOrDefault();
    //var val = this.SysSettingsValueCollection.Where(x => x.SysSettingsId == sys.Id).FirstOrDefault();
    //var val = this.SysSettingsValueCollection.Where(x => x.SysSettingsId.Value == sys.Id).FirstOrDefault();



Первый запрос отрабатывает нормально, а любой вариант из 4х последних строк выбрасывает исключение:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <code>4

    The MaxDataServiceVersion '2.0' is too low for the response. The lowest supported version is '3.0'.
    
    The MaxDataServiceVersion '2.0' is too low for the response. The lowest supported version is '3.0'.
    System.Data.Services.DataServiceException
           в System.Data.Services.RequestDescription.VerifyAndRaiseResponseVersion(Version version, IDataService service)&#xD;
           в System.Data.Services.RequestDescription.UpdateVersions(String acceptTypesText, ResourceSetWrapper resourceSet, IDataService service)&#xD;
           в System.Data.Services.RequestUriProcessor.ProcessRequestUri(Uri absoluteRequestUri, IDataService service, Boolean internalQuery)&#xD;
           в System.Data.Services.DataService`1.HandleRequest()
      
   

Где отрегулировать и какие настройки?

Нравится

1 комментарий

Добрый день, Михаил!

Судя из ошибки, проблема в том что не совпадают версии протокола. Необходимо убедиться, что версия на стороне DataService и на стороне клиента совпадают. 

Вы можете явно указать какую версию протокола использовать при инициализации DataService. Попробуйте явно указать версию.

Пример: 

var ctx&nbsp;=&nbsp;new DataServiceContext(uri,&nbsp;DataServiceProtocolVersion.V3);

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

Добрый день!

В рамках интеграции сайта клиента с bpm`online появилась необходимость добавлять с сайта файлы на деталь "Файлы и ссылки" обращения. Для этого был написал веб-сервис для добавления файла, так выглядит метод добавления:

 [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
        ResponseFormat = WebMessageFormat.Json)]
      public string InserCaseFile(CaseFileData data)
    {
      try
      {
        var appConnection = HttpContext.Current.Application["AppConnection"] as AppConnection;
        var userConnection = HttpContext.Current.Session["UserConnection"] as UserConnection;
        var caseFile = new Terrasoft.Configuration.CaseFile(userConnection);
 
    //    byte[] bytes = Convert.FromBase64String(data.File);
     ASCIIEncoding ascii = new ASCIIEncoding();
    var t = ascii.GetBytes(data.File);
	Stream stream = new MemoryStream(t);
 
          var id = Guid.NewGuid();
          caseFile.SetDefColumnValues();
           caseFile.Id = id;
           caseFile.Name = data.Name;
           caseFile.Size = (int)stream.Length;
           caseFile.SetStreamValue("Data", stream);
           caseFile.CaseId = new Guid(data.CaseId);
          caseFile.Save();
          return "Ok";
      }
      catch(Exception er)
      {
        return er.ToString();
      }
 
    }

Для тестирования с помощью SelectQuery веб-службы DataService был получен уже существующий в bpm файл *.txt, при получении значения из колонки Data в json возвращалась строка в кодировке 7-bit ASCII. 

При попытке записи этого значения с помощью описанного выше метода в таблицу CaseFile, на детали появляется файл, но при нажатии на него страница перезагружается и скачивания или открытия не происходит.

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

Нравится

4 комментария

Здравствуйте,

Посмотрите, как передается файл в ConfigurationFileApi, метод upload.

И принимается в схеме FileApiService, метод public string Upload(Stream fileContent)

я думаю, что проблема в том, что не указан тип файла... из-за этого не генерируется правильная ссылка на скачивание файла

Добрый день, коллеги.  Проблема была в TypeId, как и написал Максим. Спасибо.

я имею в виду поле TypeId='529BC2F8-0EE0-DF11-971B-001D60E938C6' (это тип File из таблицы FileType)

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

Здравствуйте!



Настраиваю процесс с отправкой письма. В теле письма хочу использовать параметры элементов из процесса, но как это сделать? Попробовал для проверки вставить код http://prntscr.com/gg187o, который используется для ссылки на элементы, но не сработало http://prntscr.com/gg18xr

Нравится

1 комментарий

Раньше делали через формулу. Создаёте параметр процесса (например MyBody, строка неогр. длины), создаёте "Формулу", в параметр MyBody кидаете будущее тело письма через форму. Далее создаёте элемент Email, указываете все параметры, кроме самого тела письма, заходите в расширенные параметры элемента и присваиваете параметру Body ваш параметр MyBody

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

Я хочу в процессе создать активность, в которой дата=текущая дата, а время - конкретное. Но стандартные элементы позволяют либо выбирать текущую дату (без времени), либо текущую дату и время. А как объединить текущую дату и конкретное время, которое я могу выбрать?

И как задать в параметрах дату на следующий день (на завтра)?http://prntscr.com/g4x2g2

Нравится

4 комментария

Вам требуется это сделать прямо в БП, или же у Вас автогенерируемая страница и ввод пользователем ?

выбрать текущую дату и прилепить к ней время

пишет:

Вам требуется это сделать прямо в БП, или же у Вас автогенерируемая страница и ввод пользователем ?

 Да, мне это нужно в процессе сделать

Дмитрий Степанов пишет:

выбрать текущую дату и прилепить к ней время

 В этом-то и вопрос, как прилепить то?

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

Добрый день!
Столкнулся с проблемой вывода в дашборде продаж, в которых ВСЕ заказы находятся в состоянии Отменен. В моем случае выводятся продажи, в которых есть заказы в состоянии Отменен.

Нравится

3 комментария

Здравствуйте!

В построителе выборки Вы можете использовать does not exists (или не существует) фильтр, в котором перечислить все остальные состояния отличные от 'Отменен'.
Более подробно о построении таких фильтров (пункт "Установка агрегирующего фильтра" - вместо количества нужно указать опцию не существует):
https://academy.terrasoft.ru/documents/sales-team/7-10/rasshirennyy-fil…

P.S. прикрепила скриншот для наглядности

Алла, спасибо за решение)

Добавьте еще условие, что заказы существуют. И при это не существуют заказы, в которых состояние отличное от "Отменен"

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