Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Примеры создания сценариев с помощью языка Java Script
Форумы общения пользователей продуктов АТОЛ > Программное обеспечение Front-Office > Frontol для Win32 — предприятия торговли
Страницы: 1, 2
АТОЛ: Герман Бойцов
Пример №1. Использование параметра E (идентификатор события) и получение значений счетчиков в сценарии

// Пример использования идентификатора события в сценарии
function EventToText(E)
{
switch (E) {
case 1: return "Открытие чека";
case 2: return "Добавление позиции";
case 3: return "Редактирование позиции";
case 4: return "Закрытие чека";
case 5: return "Отмена чека";
case 6: return "Ввод оплаты";
case 7: return "Сторно оплаты";
case 8: return "Ввод карты";
case 9: return "Отмена карты";
case 10: return "Ввод клиента";
case 11: return "Отмена клиента";
case 12: return "Ввод ручной скидки";
}
}

// Пример обращения к значениям счетчиков в сценарии
function CountersToText(RO)
{
Text = "Всего счетчиков " + RO.Counter.Count + "\n";
Text += "Ин." +
"\tКод" +
"\tВида"+
"\tЗначение" +
"\t\"Наименование Вида\"\n";
for (RO.Counter.Index = 1; RO.Counter.Index <= RO.Counter.Count; RO.Counter.Index++)
Text += RO.Counter.Index +
"\t" + RO.Counter.Code + // Код счетчика
"\t" + RO.Counter.TypeCode + // Код вида счетчика
"\t" + RO.Counter.Value + // Значение счетчика
"\t\"" + RO.Counter.TypeName + // Наименование вида счетчика
"\"\n";
return Text;
}

// Функция, с предопределенным именем, которая будет вызвана Frontol в начале обработки события
function BeforeAct(AO, RO, E)
{
Text = "До события " + EventToText(E) + "\n" + CountersToText(RO);
AO.ShowMessage(Text); // Вывод сообщения на экран кассира
}

// Функция, с предопределенным именем, которая будет вызвана Frontol в конце обработки события
function AfterAct(AO, RO, E)
{
Text = "После события " + EventToText(E) + "\n" + CountersToText(RO);
AO.ShowMessage(Text);
}



Пример №2. Учет накоплений и скидка на их основе

Создаем сценарий на момент действия Закрытие чека

function BeforeAct(AO, RO, E)
{
}
function AfterAct(AO, RO, E)
{
RO.Counter.AddValueByTypeCode(8, RO.SummWD * 0.0004);

/* 8 - код вида счетчиков в котором будут учитываться накопления.
В этом виде должны быть счетчики, привязанные к клиентам.
RO.SummWD - это сумма чека.
0.004 - например будем накапливать по 0.4% с чека. */
}




Создаем Объект скидки, в котором указываем этот сценарий.

Теперь, в зависимости от величины накоплений, сделаем разные скидки:

Создаем Группу условий, в которой будут Условия с разными ставками.

В Условии задаем на закладке Счетчики диапазон значений и вид счетчика.

При наличии в чеке счетчика требуемого вида со значением удовлетворяющим диапазону будет начислена заданная ставкой скидка. Для этой группы условий тоже необходим Объект скидки (можно использовать тот же самый что и для сценария).
POUL
Позновательно. Предложение выкладывать сюда скрипты работающих сценариев и их описания.
POUL
При введении бонусной карты скрипт подсчитывает максимальную скидку чека по минимальным ценам всех позиций и выводит сообщения со значением максимальной скидки на чек и количеством бонусов на карте.

Код
function BeforeAct(AO, RO, E)
{
if (RO.BuyCount>0)

    {var WMPrice = 0;
     var MaxSkidka = 0;
           for (RO.Pos.Index = 1;
           RO.Pos.Index <=
           RO.Pos.Count;
           RO.Pos.Index ++)

           {if (RO.Pos.Storno == 1)
             {continue;}
             else
             var WMPrice = WMPrice + RO.Pos.WareMinPrice * RO.Pos.Quantity;}

              AO.ShowMessage ("Максимальная скидка: " + (RO.SummForD - WMPrice) + " руб.")}

else AO.ShowMessage ("Введите карту после регистрации ВСЕХ покупок!");
  }

function AfterAct(AO, RO, E)
{
for (RO.Counter.Index = 1;
      RO.Counter.Index <=
      RO.Counter.Count;
      RO.Counter.Index ++)

      {if (RO.Counter.TypeCode == 1)
{AO.ShowMessage ("Баланс карты: " + RO.Counter.Value + " руб.");
AO.DisplayScroll ("Баланс карты: " + RO.Counter.Value + " руб.");}
}
}
POUL
Программировать надо. На Ява-скрbпте smile.gif

Код
function BeforeAct(AO, RO, E)
{
}
function AfterAct(AO, RO, E)
{
if (RO.Card.Count != 0)
{RO.Counter.AddValueByTypeCode(//Ваш тип кода счетчика//, 1);}
}


Момент действия - закрытие чека.
Также необходимо написать еще несколько сценариев для проверок и ограничений.
POUL
скрипт проверки наличия введенной карты

Код
function BeforeAct(AO, RO, E)
{
if (RO.Card.Count != 0)
AO.ShowError ("Карта уже введена");
}

function AfterAct(AO, RO, E)
{

}
POUL
Скрипты для бонусной программы.
Общая идея:
Клиент - владелец карты приводит другого клиента, которому тут же выдается дисконтная карта. Сначала вводится карта приводимого, потом приводящего. При закрытии чека карта приводящего приписывается к карте приводимого. При покупке приводимым на карты обоих записываются по 10% от суммы чека, при возврате списываются обратно. Записанные бонусы можно использовать для оплаты товаров.

При вводе карты:


Код
function BeforeAct(AO, RO, E, O)
{
if ((O.Value.substr (0, 7) != 2997777) || (O.Value.length != 13))    //Проверяем префикс карты и длину
AO.ShowError ("Карта не из этого магазина!");

if (RO.Card.Count >=2)                                               //Проверяем количество введенных в чек карт
AO.ShowError ("Ввод карты запрещен");

if (RO.Card.Count == 1)                                              //Если количество введенных карт в чеке = 1

{
   enter2ndkard = true;                                              //Разрешаем ввод 2-й карты
   Karta = O.Value.slice (7, O.Value.length);                        //Отбрасываем первые 7 знаков вводимой карты

   for (RO.Card.Index = 1;                                           //Перебираем введенные карты
        RO.Card.Index <=
        RO.Card.Count;
        RO.Card.Index ++)

      {if (RO.Card.Index == 1)                                       //Находим первую введенную карту

       for (RO.Card.Counter.Index = 1;                               //Перебираем счетчики на этой карте
            RO.Card.Counter.Index <=
            RO.Card.Counter.Count;
            RO.Card.Counter.Index ++)

         {if (RO.Card.Counter.TypeCode == 1)                         //Находим счетчик с кодом типа счетчика = 1
             {if (RO.Card.Counter.Value != 0)                        //Если он не = 0
                 enter2ndkard = false;}                              //Запрещаем ввод 2-й карты

          if (RO.Card.Counter.TypeCode == 2)                                  //Находим счетчик с кодом типа счетчика = 2
      {if ((RO.Card.Counter.Value == 0) && (enter2ndkard))                    //Если значение найденного счетчика = 0 и разрешен ввод 2-й карты
          RO.UserValues.Set ("Karta", Karta);                                 //Объявляем пользовательскую переменную с хвостом от вводимой карты
       if ((RO.Card.Counter.Value != (Karta || 0)) && (!enter2ndkard))        //Если значение найденного счетчика не равно хвосту от вводимой карты и не = 0, а первый счетчик не = 0
          AO.ShowError ("Ввод второй карты запрещен!");}}}           //Вываливаем ошибку
}
}


function AfterAct(AO, RO, E, O)
{

if (RO.Card.Count == 1)                                                                                  //Если количество введенных карт = 1

   for (RO.Counter.Index = 1;                                                                            //Перебираем счетчики на карте
        RO.Counter.Index <=
        RO.Counter.Count;
        RO.Counter.Index ++)

     {if (RO.Counter.TypeCode == 1)                                                                      //Находим счетчик с кодом типа счетчика = 1
          AO.ShowMessage ("Балланс карты: " + ((Math.round (RO.Counter.Value*100))/100) + " руб.");      //Выводим сообщение о сумме счетчика

      if (RO.Counter.TypeCode == 2)                                                                      //Находим счетчик с кодом типа счетчика = 2
      if (RO.Counter.Value != 0)                                                                         //Если он не нулевой и не null
        {KarPr = String (RO.Counter.Value);                                                              //Переводим его значение в строку
          do
          {KarPr = 0 + KarPr}                                                                            //Добиваем нулями слева
          while (KarPr.length < 6);                                                                      //До длины в 6 знаков
                                                                                                         ///////////////////////////////////////////////
         var WShell = new ActiveXObject("WScript.Shell");                                                //Программно нажимаем F8, вводим префикс карты,
             WShell.SendKeys ("^({F8})2997777" + KarPr + "~"); }}                                        //добитый нулями слева хвост карты из второго
                                                                                                         //счетчика и нажимаем ввод
}                                                                                                        //То есть программно вводим карту приведшего
                                                                                                         //Записанную на второй счетчик
function FuncAct(AO, RO)                                                                                 //////////////////////////////////////////////
{
}

function NoAction(AO, RO, POS)
{
}


297777 - префикс карты, который и не нужен и не влезал в счетчик. Отбрасывается при записи и пририсовывается при восстановлении.

При закрытии чека:


Код
function BeforeAct(AO, RO, E, O)
{
}



function AfterAct(AO, RO, E, O)
{
if (RO.Card.Count != 0)                                                              //Если количество введенных карт не = 0
{
   for (RO.Card.Index = 1;                                                           //Перебираем карты в чеке
        RO.Card.Index <=
        RO.Card.Count;
        RO.Card.Index ++)

  {
      if (RO.Card.Index == 1)                                                       //Находим первую введенную карту
   {
         for (RO.Card.Counter.Index = 1;                                            //Перебираем счетчики на первой карте
              RO.Card.Counter.Index <=
              RO.Card.Counter.Count;
              RO.Card.Counter.Index ++)


          {if (RO.Card.Counter.TypeCode == 1)                                       //Находим 1-й счетчик 1-й карты
           {if ((RO.ReceiptTypeCode == 1) || (RO.ReceiptTypeCode == 4))             //Если это чек продажи (код типа = 1) или возврата (код типа = 4)
                {RO.Card.Counter.AddValue ((RO.TotalDiscSumm)*(-1));                //Списываем с 1-го счетчика 1-й карты сумму скидки на чек
                 RO.Card.Counter.AddValue(Math.round(RO.SummWD * 10)/100);}         //Записываем в 1-й счетчик 1-й карты округленные 10% суммы чека со скидками

            if (RO.ReceiptTypeCode == 2)                                            //Если это чек возврата (код типа = 2)
               {RO.Card.Counter.AddValue(RO.TotalDiscSumm);                         //Записываем на 1-й счетчик 1-й карты сумму скидки на чек
                RO.Card.Counter.AddValue(Math.round(RO.SummWD * (-10))/100);}}      //Списываем с 1-го счетчика 1-й карты округленные 10% суммы чека со скидками


           if (RO.Card.Counter.TypeCode == 2)                                        //Находим счетчик с кодом типа счетчика = 2
              {if (RO.Card.Counter.Value == 0)                                       //Если его значение = 0, то есть карта карты приводящего нет
               {Karta = Number (RO.UserValues.Get ("Karta"));                        //Вытаскиваем пользовательскую переменную, объявленную в воде карты и переводим ее в число
                if (Karta != 0)                                                      //Если мы вытащини не 0
                RO.Card.Counter.AddValueByTypeCode (2, Karta);}}}                    //Записываем в счетчик с кодом типа счетчика = 2 хвост номера карты приведшего
   }

      if (RO.Card.Index == 2)                                                        //Находим вторую введенную карту
   {
         for (RO.Card.Counter.Index = 1;                                             //Перебираем счетчики на первой карте
              RO.Card.Counter.Index <=
              RO.Card.Counter.Count;
              RO.Card.Counter.Index ++)

            {if (RO.Card.Counter.TypeCode == 1)                                      //Если это счетчик №1
               {if ((RO.ReceiptTypeCode == 1) || (RO.ReceiptTypeCode == 4))          //Если это чек продажи (код типа = 1) или возврата (код типа = 4)
                     RO.Card.Counter.AddValue(Math.round(RO.SummWD * 10)/100);       //Записываем в 1-й счетчик 2-й карты округленные 10% суммы чека со скидками
                if (RO.ReceiptTypeCode == 2)                                         //Если это чек возврата (код типа = 2)
                    RO.Card.Counter.AddValue(Math.round(RO.SummWD * (-10))/100);}}   //Списываем с 1-го счетчика 2-й карты округленные 10% суммы чека со скидками
   }
  }
}
}

function FuncAct(AO, RO)
{
}

function NoAction(AO, RO, POS)
{
}


Скрипты можно соптимизировать, но сил и желания нет.
Может кому пригодится.
Владимир Д.
Интересная идея! +1 goodpost.gif
Лаврухин Алексей
Пример решенной задачи с помощью скриптов: http://blog.atol.ru/2009/12/02/diskont-na-javascript-primer/
Andrey_malin
Думаю будет полезно привести классический пример работы со счётчиками.
Задача: Есть карты для которых из товароучётной программы выгружается максимальная сумма покупки (что-то вроде материальной помощи или
покупки под зарплату).
Вот пример скрипта реализующего эту задачу.
Код
function BeforeAct(AO, RO, E, O)
{
for (RO.Counter.Index = 1;
      RO.Counter.Index <= RO.Counter.Count;
      RO.Counter.Index++)
      {
       switch (RO.Counter.TypeCode){                 //Здесь определяем коды используемых счётчико
              case 4: MaxLimit = RO.Counter.Value; //Счётчик содержащий максимальную сумму покупки.
                      break
              case 6: SumNakop = RO.Counter.Value; //Счётчик содержащий израсходованную сумму.
                      break         }
       }

MaxSkidka = MaxLimit - SumNakop;                 //Определяем масимальную сумму скидки на чек.

for (RO.Counter.Index = 1;                              //Расчёт значения предоставляемой скидки.
      RO.Counter.Index <= RO.Counter.Count;
      RO.Counter.Index++)
      {
       if (RO.Counter.TypeCode == 7)
          {
           if (RO.SummWD <= MaxSkidka)
              {
               RO.Counter.AddValue(-RO.Counter.Value);
               RO.Counter.AddValue(RO.SummWD);
               MaxSkidka = RO.SummWD;
              }
           else
              {
               RO.Counter.AddValue(-RO.Counter.Value);
               RO.Counter.AddValue(MaxSkidka);
              }
          }
      }
for (RO.Counter.Index = 1;                            
      RO.Counter.Index <= RO.Counter.Count;
      RO.Counter.Index++)
      {
       if (RO.Counter.TypeCode == 6)
          RO.Counter.AddValue(MaxSkidka);   //Увеличиваем значение счётчика расходования средств на сумму покупки.
      }
}


Для использования скрипта потребуется создать три счётчика, ставку скидки и условие.

Счётчики:
1: Сумма лимита из товароучётной программы (Автосоздание по карте);
2: Сумма израсходованных средств (Автосоздание карта);
3: Сумма скидки (Автосоздания нет).

Ставка скидки:
1: Тип -$, значение счётчик 3, автоматическая.

Условие:
1: Карта введена, ставка 1.

В объекте скидки указываем только Условие. Момент действия скрипта Ввод платежа.
Так же потребуется скрипт с моментом действия Ввод карты.
Код
function BeforeAct(AO, RO, E, O)
{
if (RO.Card.Count >0)                                  
   AO.ShowError("Карта уже введена!!!");

for (RO.Counter.Index =1;                                 //Проверяем наличие средств для оплаты по карте.
           RO.Counter.Index <= RO.Counter.Count;
           RO.Counter.Index++)
           {switch (RO.Counter.TypeCode) {
                   case 4:{Limit = RO.Counter.Value;
                           break}
                   case 6:{Rashod = RO.Counter.Value;
                           break}
                           }
           }
      if (Limit == Rashod)
         AO.ShowError("Лимит исчерпан!");

}
awerta
Может кому понадобиться!
Скидка на позицию, равная 20% от суммы чека или равная 100 руб., если 20 % от чека больше чем 100 руб.
С условием, что в чеке присутствует товар с минимальной ценой равной розничной, и стоимость этого товара исключается из общей суммы чека.
Плюс присутствует проверка на то, что такая скидка уже была сделана.


Код
function qwert(AO, RO, POS)
{
Summa = 0;
for (RO.Pos.Index = 1;
           RO.Pos.Index <=
           RO.Pos.Count;
           RO.Pos.Index ++)
{
if (RO.Pos.Storno == 1)
   {
   continue;
   }
else
   {
            if (RO.Pos.WareMinPrice == RO.Pos.Price)
               {

               }
            else
               {
               Summa = Summa + RO.Pos.SummForD;
               }
    }
}
for (RO.Counter.Index = 1; RO.Counter.Index <= RO.Counter.Count; RO.Counter.Index++)
    {
    if (RO.Counter.TypeCode == 3)
       {
       if (RO.Counter.Value == 0)
            {
            RO.Counter.AddValueByCode(3,1,1);
            Summa = Summa*0.2;
            if (Summa > 100)
            {
            Summa = 100;
            }
            return Summa;
            
            }
       }
    }
}
АТОЛ: Царюков Роман
желательно делать комментарии в коде....
для чего, например нужен счетчик, к чему этот счетчик привязан и т.д....
POUL
Вот этот момент совсем не понял:

Цитата
if (RO.Pos.WareMinPrice == RO.Pos.Price)
{

}


Можете объяснить?
80Serg
Здравствуйте, товарищи. На нашем предприятии возникла необходимость в такой скидке: скидка действует на определенное количество товара, например от 1 до 4 штук. Т.е если покупатель приобретает от 1-ой до 4-х штук товара, то возникает скидка. Однако, если покупатель берет 5 штук и более, скидка на первые 4 позиции не должна быть отменена. Т.е. скидка должна остаться для 4-х штук товара, но на пятую штуку и далее уже не распространяться.
Формулами и другими способами сделать не получается, поэтому предлагаю такую схему:

1. Создается Сценарий, который в зависимости от некоторого параметра будет выдавать разную скидку.
2. Создается Ставка скидки, где в качестве ставки указывается ссылка на сценарий. Ставка идет на позицию, автоматическая.
3. Создается Условие в одноименной справочнике, где прописывается Ставка и Сценарий, а самих условий нет.
4. Создается Классификатор, который косвенно будет задавать параметры скидки.
5. К классификатору привязываются товары.

Имя классификатора содержит параметры скидки и строится по следующему шаблону: НачКол_КонКол_ПроцентСкидки.
Например, классификатор с именем 1_4_10, означает, что скидка действует на товар с количеством от 1 до 4 и составляет 10% на товар.

Сценарий возникает при расчете автоматической скидки, т.е. момент действия сценария - Нет, а сам алгоритм создается в свободной процедуре NoAction, переименованной по своему усмотрению (у меня - DiscountVariable).
Итак при регистрации товара возникает сценарий автоматической скидки. В сценарии проверяется, есть ли у данного товара классификатор, если есть то это значит, что есть причина начислить скидку и параметры скидки нужно взять из наименования классификатора. Разбирается строка с именем классификатора и заполняются переменные - параметры скидки ( numBegin, numEnd, discount ). Далее по формуле считается скидка на данный товар (т.к. сценарий вызывается для каждой позиции в чеке. Кстати стоит объединение позиций). Формула такая:
ПроцентСкидкиНаТовар = ( ( ЦенаБезСкидки*ОбщееКолво – (КолвоСоСкидкой*ЦенаСоСкидкой + КолвоБезСкидки*ЦенаБезСкидки) ) / ЦенаБезСкидки*ОбщееКолво) * 100. Рассчитанная скидка возвращается в переменной TotalDisc.

Хочется еще сказать, что классификаторы загружаются из 1С. Я создал там справочник схемы скидок, каждый элемент которого соответствует классификатору. При этом во Фронтоле неизменными остаются элементы справочников Ставки, Условия, Сценарии, а классификаторы и Объекты скидок, каждый раз (при загрузке товаров) удаляются и создаются снова.

код файла goods.spr привожу ниже сценария.

Сценарий :

CODE
function BeforeAct(AO, RO, E, O)
{
}

function AfterAct(AO, RO, E, O)
{
}

function FuncAct(AO, RO)
{
}

function DiscountVariable(AO, RO, POS)

{
numBegin = 0;
numEnd = 0;
discount = 0;

param = "";
paramInt = 0;

CurrentClassifier = 0;
numFind = 0;

for (POS.Classifier.Index = 1;
POS.Classifier.Index <= POS.Classifier.Count;
POS.Classifier.Index++)
{
CurrentClassifier = POS.Classifier;
break;
}

if (CurrentClassifier != 0)
{

Name = CurrentClassifier.Name;
i = 1;
do
{
numFind = Name.search("_");
if (numFind != -1)
{
param = Name.substr(0, numFind);
Name = Name.substr(numFind + 1);
}
else
param = Name;

paramInt = parseInt(param);
if (i == 1)
numBegin = paramInt;
if (i == 2)
numEnd = paramInt;
if (i == 3)
discount = paramInt;

i++;
}
while(numFind != -1);
}

TotalDisc = 0;

WareQuantity = POS.Quantity;
WarePriceWODisc = POS.Price;
WarePriceWithDisc = WarePriceWODisc - (WarePriceWODisc * discount / 100);

WareQuantityWODisc = WareQuantity;
WareQuantityWithDisc = 0;
if (WareQuantity <= numEnd)
{
WareQuantityWODisc = 0;
WareQuantityWithDisc = WareQuantity;
}
else
{
WareQuantityWODisc = WareQuantity - numEnd;
WareQuantityWithDisc = numEnd;
}

TotalDisc =( (WarePriceWODisc * WareQuantity - (WareQuantityWithDisc * WarePriceWithDisc + WareQuantityWODisc * WarePriceWODisc ) ) / (WarePriceWODisc * WareQuantity) ) * 100;
return TotalDisc;
}



goods.spr:


CODE
##@@&&
#
$$$ADDQUANTITY
00098354;5706773223251;Ящик HOME BOX 32 л голубой РТ 2232-ГП;Ящик HOME BOX 32 л голубой РТ 2232-ГП;614,90;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00095462;4607126319229;Ящик HOUSE 60л штабелируемый оранжевый РТ9954/М-ОР;Ящик HOUSE 60л штабелируемый оранжевый РТ9954/М-ОР;288,60;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00095460;4607126319014;Ящик JUNIOR на роликах 30л красный РТ9034-КР;Ящик JUNIOR на роликах 30л красный РТ9034-КР;410,80;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00095461;4607126319045;Ящик JUNIOR на роликах 60л оранжевый РТ9046-ОРАНЖ;Ящик JUNIOR на роликах 60л оранжевый РТ9046-ОРАНЖ;494,00;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00078280;2200100584488;Ящик Multibox XS с крышкой многофункциональная флауер пауер;Ящик Multibox XS с крышкой многофункциональная флауер пауер;102,70;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00108670;4607016810720;Ящик д/игрушек 600*400*360 на колесах 4312068;Ящик д/игрушек 600*400*360 на колесах 4312068;800,80;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00108669;4607016814261;Ящик д/игрушек на кол.600*400*360 с апплик. 4313068;Ящик д/игрушек на кол.600*400*360 с апплик. 4313068;738,20;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00107499;8697444382032;Ящик д/инст.клас. 16 MANO C.O-16;Ящик д/инст.клас. 16 MANO C.O-16;480,70;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00107514;8697444384340;Ящик д/инст.клас. 3-х эт 20 MANO BL.O-20;Ящик д/инст.клас. 3-х эт 20 MANO BL.O-20;1358,50;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00108671;4607016815367;Ящик д/инструментов 510*260*270 4312560;Ящик д/инструментов 510*260*270 4312560;517,00;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00107101;4607016812502;Ящик складной с перфориров. стенками 32л. 4312282;Ящик складной с перфориров. стенками 32л. 4312282;318,10;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
00107079;4607016812090;Ящик Хобби 27*19*4см 4312285;Ящик Хобби 27*19*4см 4312285;112,80;0;0;0,1,1,0,0,0,0,1,1,,1;;;;;;1;;;1;0;;;;;;;;;;;;;;;
$$$DELETEALLCLASSIFIERLINKS
$$$DELETEALLDISCOBJECTS
$$$DELETEALLCLASSIFIERS
$$$ADDCLASSIFIERS
8;;0;2_8_6 ;;
$$$ADDDISCOBJECTS
8;;;;;;;;8;;;;;1;;;
$$$ADDCLASSIFIERS
5;;0;1_7_3 ;;
$$$ADDDISCOBJECTS
5;;;;;;;;5;;;;;1;;;
$$$ADDCLASSIFIERLINKS
5;1;00080608;
5;1;00103202;
5;1;00096178;
5;1;00085378;
5;1;00104275;
5;1;00086399;
5;1;00030047;
5;1;00070107;
5;1;00070108;
5;1;00049050;
5;1;00085377;
5;1;00086805;
5;1;00104087;
5;1;00096796;
5;1;00094931;
5;1;00096180;
5;1;00095222;
5;1;00031502;
5;1;00085712;
5;1;00080584;
5;1;00085376;
5;1;00101488;
5;1;00031504;
POUL
Для начинающих ссылка на адекватный справочник по JS:

http://wdh.suncloud.ru/js01.htm
Peter1234
Мой первый скрипт. Надеюсь, кому-то пригодится. Плюс будет интересно услышать комментарии от гуру.

Схема работы следующая.

1. Выпускаются карты сертификатов с какой-то нумерацией, идущей подряд.
2. Сертификатам присваивается какой-то номинал (в примере скрипта два номинала – 5000 руб. и 6000 руб.).
3. Карты продаются/выдаются клиентам без регистрации через фронтол. В моем случае просто стопку карт продали организации по безналу, а она раздала своим сотрудникам.
4. Клиенты приходят отоваривать сертификаты. Они могут набрать товара на любую сумму: меньше номинала сертификата, больше или равно. Клиенты могут одновременно отоварить два и более сертификата разных номиналов.
5. При покупке на сумму меньше номинала сертификата чек будет закрыт на сумму покупки с видом оплаты «Сертификат». При покупке на сумму, равную сертификату, чек будет закрыт по номиналу сертификата. При покупке на сумму больше номинала сертификата, будет зарегистрирована оплата на сумму сертификата, а остальное надо будет доплатить наличными или по безналу.
6. Сертификат у покупателя изымается.
7. Нигде не контролируется, что сертификат уже был отоварен. Поэтому изымать сертификат надо обязательно.

Последовательность действий:

1. Создаем сценарий с моментом действия «Ввод платежа».

Код
function inArray(data, array) {
    for (var i = 0; i < array.length; i++) {
        if (data == array[i]) return true;
    }
    return false;
}

function BeforeAct(AO, RO, E, O) {
    var certificateSumm = 0;
    var groupCode = [1, 2, 3]; // Коды групп карт, которые являются сертификатами
    var certificateValue = [5000, 5000, 6000]; // Номиналы сертификатов. К массиву обращаться по [код группы - 1]. В соответствующей ячейке будет сумма.

    // Проверим, что вводится оплата по сертификату, в нашем случае это вид оплаты с кодом 2
    if (O.Code == 2) {
        // Вычислим сумму номиналов всех сертификатов
        for (RO.Card.Index = 1; RO.Card.Index <= RO.Card.Count; RO.Card.Index++) {
            // Проверяем, является ли введенная карта сертификатом (по коду группы карт)
            if (inArray(RO.Card.GroupCode, groupCode)) {
                certificateSumm += certificateValue[RO.Card.GroupCode - 1];
            }
        }
        // Если сумма сертификатов равно 0, то отменяем оплату по сертификату
        if (certificateSumm == 0) {
            AO.ShowError("Сертификат не введен!");
        }
        // Если сумма чека больше или равна сумме сертификатов, то закрываем суммой сертификатов.
        // Если сумма чека меньше, то закрываем суммой чека.
        if (RO.SummWD >= certificateSumm) {
            RO.AddPayment(2, certificateSumm);
        } else {
            RO.AddPayment(2, RO.SummWD)
        }
        AO.Cancel()
    }
}

function AfterAct(AO, RO, E, O)
{
}

function FuncAct(AO, RO)
{
}

function NoAction(AO, RO, POS)
{
}


2. Создаем объект скидок, выбираем в «Оплата» «Сертификатом» в действии «Сценарий» - наш созданный сценарий.
3. Создаем группу карт с параметром «Авторегистрация карт», ввод «Ридером», указываем минимальный и максимальный префикс.
4. Код созданной группы будет проверяться в сценарии. По нему мы будем определять, что карта является сертификатом. В сценарии есть массив groupCode, в который надо внести все коды групп карт данных сертификатов.
5. «В Системных справочниках» в «Видах оплаты» создаем вид оплаты «Сертификатом», «Тип оплаты в ККМ» - 1, «Операция» - Нет. Сдача не выдается, денежный ящик не меняется. Код вида оплаты проверяется в сценарии тут: if (O.Code == 2). В данном случае код вида оплаты «Сертификатом» - 2.

PS. Спасибо Павлу Сусину за примеры.
POUL
Глубокоуважаемые коллеги!!!
Убедительная просьба обратить ваше драгоценное внимание на название темы.
Выкладывайте, пожалуйста, сюда примеры работы с внутренним программированием во Фронтоле.
Для решения ваших личных в этой области проблем, остается почти весь остальной форум!
Спасибо за понимание.
Владимир Шалаев
Существует группа карт "Накопительные карты", имеющая свой код Х.
При любой покупке, на карту добавляется сумма покупки. При достижении определенной суммы, выдается определенная скидка.
Задача: написать скрипт, который при возврате товара, вычитает цену товара из накоплений карты.
момент действия: Закрытие документа.
Функция может быть как BeforeAct, так и AfterAct.

/*Скрипт при каждом закрытии документа определяет его тип.
Если тип документа "ВОЗВРАТ", то скрипт проверяет наличие
накопительных карт в документе. Если накопительная карта найдена,
то из ее суммы накоплений вычитается сумма возврата (с учетом скидки).*/
Код
function BeforeAct(AO, RO, E, O)
{

   if(RO.ReceiptType == "ВОЗВРАТ")
   {//Если название операции "ВОЗВРАТ", то обрабатываем этот случай
        for(RO.Card.Index = 1; RO.Card.Index <= RO.Card.Count; RO.Card.Index++)
        {//Запускаем цикл по всем картам, имеющимся в документе
              if((RO.Card.GroupCode==X)) //где X - код группы накопительных карт
              {//Находим счетчик накопительных карт. Код группы таких счетчиков - X
                   for(RO.Card.Counter.Index = 1; RO.Card.Counter.Index <= RO.Card.Counter.Count; RO.Card.Counter.Index++)
                   { //Запускаем цикл по всем счетчикам карты
                         if(RO.Card.Counter.TypeName == "Накопления по картам")
                         {
                         RO.Card.Counter.AddValue(-RO.SummWD);
                         } //Окончание условия обработки счетчика "Накопления по картам"

                   } //Окончание цикла перебора всех счетчиков карты

              } //Окончание условия проверки кода группы карт (нам нужен код группы 509)

        } //Окончание цикла перебора всех карт данного документа

   } //Окончание условия обработки типа документа "ВОЗВРАТ"

} //Конец функции

function AfterAct(AO, RO, E, O)
{}
function FuncAct(AO, RO)
{}
function NoAction(AO, RO, POS)
{}
POUL
Такие вещи надо писать в AfterAct
Потому что если это будет в таком виде, возможна следующая ситуация:
Проигрался BeforAct, пошла печать чека, ФР вернул ошибку, кассир жмет закрыть чек еще раз, опять проигрывается BeforAct и так далее со всеми вытекающими последствиями.
Владимир Шалаев
Цитата(POUL @ 14.11.2012, 14:35) *
Такие вещи надо писать в AfterAct
Потому что если это будет в таком виде, возможна следующая ситуация:
Проигрался BeforAct, пошла печать чека, ФР вернул ошибку, кассир жмет закрыть чек еще раз, опять проигрывается BeforAct и так далее со всеми вытекающими последствиями.

Спасибо! Это ценное замечание!!
POUL
Ваш Кэп.
Лазарев Максим Викторович
Скрипт, блокирующий продажу алкоголя с 22.00 до 10.00 часов

Данный скрипт вытаскивает первые n символов из названия товара в позиции и сравнивает с заданными значениями в скрипте.
Скрипт писался специально, т.к. товарный справочник на кассе без классификатора (всё в куче, особенность товароучетки)
Вы сами можете "допилить" данный скрипт под свои наименования товаров.

Код
unction BeforeAct(AO, RO, E, O, CO, POS)
{
var now = new Date();
var hour = now.getHours();
var s = O.Ware.Name;
var vin = s.substr(0, 3); //Вино
var vod = s.substr(0, 5); //Водка
var kon = s.substr(0, 4); //Коньяк
var piv = s.substr(0, 3); //Пиво
var nas = s.substr(0, 4); //Настойка
var bal = s.substr(0, 4); //Бальзам
var vis = s.substr(0, 3); //Виски
var lik = s.substr(0, 3); //Ликер
var rom = s.substr(0, 3); //Ром
var tek = s.substr(0, 3); //Текила
var brd = s.substr(0, 3); //Бренди
var kok = s.substr(0, 4); //Коктейль
var djn = s.substr(0, 4); //ДжинТоник
var shp = s.substr(0, 5); //Шампанское
var por = s.substr(0, 3); //Портвейн
var ver = s.substr(0, 5); //Вермут
var bo = s.substr(0, 15); //Балтика 0 (продавать можно)
var so = s.substr(0, 28); //Сибирская корона 0 (продавать можно)
var jag1 = s.substr(0, 5); //Ягуар
var jag2 = s.substr(0, 6); //Ягуар


if ((vin == "ВИН" || vod == "ВОДКА" || kon == "КОН " || piv == "ПИВ" || nas == "НАСТ" ||
  bal == "БАЛЬ" || vis == "ВИС" || lik == "ЛИК" || rom  == "РОМ" || tek == "ТЕК" || brd == "БРЕ" ||
  kok == "КОКТ" || djn == "ДЖИН" || shp == "ШАМПА" || por == "ПОР" || ver == "ВЕРМУ" || jag1 == "ЭНЕР " || jag2 == "ЭНЕРГ ") &&
  (bo != "ПИВО БАЛТИКА їО") && (so != "ПИВО Сибирская Корона БЕЗАЛК") && (hour >= 22 || hour < 10))
   AO.ShowError("Нельзя продавать алкоголь с 22.00 до 10.00!!!");
}

function AfterAct(AO, RO, E, O, CO)
{
}

function FuncAct(AO, RO, CO)
{
}

function NoAction(AO, RO, POS, CO, UserParam)
{
}
mozer
Скрипт организует скидку 20% на каждую 2-ю позицию из классификатора. Скидка применяется к позициям по возрастанию цены, то есть сначала идет скидка на дешёвый товар.
Необходимые условия:
1. Номенклатура дожна принадлежать только 1 классификатору
2. Создать условие по классификатору, в качестве ставки указать ставку которая вычисляет скидку по данному скрипту. Ставка СУММОВАЯ, НЕ ПРОЦЕНТНАЯ
Условий в пункте 2 может быть сколько угодно, тогда скрипт вычислит скидку по каждому классификатору отдельно.
3. Скрипт с моментом действия НЕТ.
Код
function BeforeAct(AO, RO, E, O)
{
}

function AfterAct(AO, RO, E, O)
{
}

function FuncAct(AO, RO)
{
}

//Функция сравнения для сортировки массива позиций
//Умышлено сортируем по возрастанию цены позиции
function Compare(A,B)
{
    if (A.Price < B.Price)
    {
        return -1;
    }
    if (A.Price > B.Price)
    {
        return 1;
    }
    return 0;
}

//Объект позиция. Содержит свойства:
//Идентификатор товара
//Цена товара без скидок
function MyPosition(ID,Price)
{
    this.ID = ID;
    this.Price = Price;
}
//Функция собирает массив позиций
//принадлежащих к одному класификатору.
//Сортирует массив в порядке возрастания цены.
//позиция попадает в массив столько раз, сколько товара взял покупатель
function collectArray(RO,POS)
{
    arrayPosition = new Array;
    //Соберем массив строк принадлежащих одному класификатору
    POS.Classifier.Index = 1;
    for(RO.Pos.Index = 1; RO.Pos.Index <= RO.Pos.Count; RO.Pos.Index++)
    {
        //Если позиция сторнирована или не принадлежит классификаторам, пропустим ее.
        if ((RO.Pos.Storno == 1)||RO.Pos.Classifier.Count == 0)
        {
            continue;
        }
        //Установливаем на первый классификатор
        RO.Pos.Classifier.Index = 1;
        if (RO.Pos.Classifier.Code == POS.Classifier.Code)
        {

            for (var IndexCount = 1; IndexCount <= RO.Pos.Quantity; IndexCount++)
            {
                MyPos = new MyPosition(RO.Pos.PosID,RO.Pos.Price);
                arrayPosition.push(MyPos);
            }
        }
    }
    //Сортируем массив в порядке возрастания цены
    arrayPosition.sort(Compare);
    //обрабатываем массив,для определения скидок по позициям.
    //Найдем количество позиций со скидкой. Каждый второй товар со скидкой.
    CountDiscounWare = arrayPosition.length / 2;
    arrayDiscounPosition = new Array;
    for(var IndexDiscount = 1; IndexDiscount <= CountDiscounWare; IndexDiscount++)
    {
        arrayDiscounPosition.push(arrayPosition.shift());
    }
    return arrayDiscounPosition;

}

//Основная функция ее подставляем в ставку
function MyAction(AO, RO, POS)
{
    var Discount = 0;
    //Если позиция не относится ни к одному класссификатору, тогда и скидки на нее нет.
    if (POS.Classifier.Count == 0)
    {
        return Discount;
    }
    //Сформируем массив скидок
    var arrayDiscounPosition = collectArray(RO,POS);
    //Обрабатываем полученый массив. В массиве может быть не одна текущая позиция, если количество больше 1
    for (var index = 0; index < arrayDiscounPosition.length; index++)
    {
        if ((arrayDiscounPosition[index].ID == POS.PosID))
        {
            Discount = Discount + arrayDiscounPosition[index].Price*0.2;
        }
    }
    return Discount;
}
Вованыч
Цитата(mozer @ 7.2.2013, 5:20) *
Скрипт организует скидку 20% на каждую 2-ю позицию из классификатора. Скидка применяется к позициям по возрастанию цены, то есть сначала идет скидка на дешёвый товар.
Необходимые условия:
1. Номенклатура дожна принадлежать только 1 классификатору
2. Создать условие по классификатору, в качестве ставки указать ставку которая вычисляет скидку по данному скрипту. Ставка СУММОВАЯ, НЕ ПРОЦЕНТНАЯ
Условий в пункте 2 может быть сколько угодно, тогда скрипт вычислит скидку по каждому классификатору отдельно.
3. Скрипт с моментом действия НЕТ.
Код
function BeforeAct(AO, RO, E, O)
{
}

function AfterAct(AO, RO, E, O)
{
}

function FuncAct(AO, RO)
{
}

//Функция сравнения для сортировки массива позиций
//Умышлено сортируем по возрастанию цены позиции
function Compare(A,B)
{
    if (A.Price < B.Price)
    {
        return -1;
    }
    if (A.Price > B.Price)
    {
        return 1;
    }
    return 0;
}

//Объект позиция. Содержит свойства:
//Идентификатор товара
//Цена товара без скидок
function MyPosition(ID,Price)
{
    this.ID = ID;
    this.Price = Price;
}
//Функция собирает массив позиций
//принадлежащих к одному класификатору.
//Сортирует массив в порядке возрастания цены.
//позиция попадает в массив столько раз, сколько товара взял покупатель
function collectArray(RO,POS)
{
    arrayPosition = new Array;
    //Соберем массив строк принадлежащих одному класификатору
    POS.Classifier.Index = 1;
    for(RO.Pos.Index = 1; RO.Pos.Index <= RO.Pos.Count; RO.Pos.Index++)
    {
        //Если позиция сторнирована или не принадлежит классификаторам, пропустим ее.
        if ((RO.Pos.Storno == 1)||RO.Pos.Classifier.Count == 0)
        {
            continue;
        }
        //Установливаем на первый классификатор
        RO.Pos.Classifier.Index = 1;
        if (RO.Pos.Classifier.Code == POS.Classifier.Code)
        {

            for (var IndexCount = 1; IndexCount <= RO.Pos.Quantity; IndexCount++)
            {
                MyPos = new MyPosition(RO.Pos.PosID,RO.Pos.Price);
                arrayPosition.push(MyPos);
            }
        }
    }
    //Сортируем массив в порядке возрастания цены
    arrayPosition.sort(Compare);
    //обрабатываем массив,для определения скидок по позициям.
    //Найдем количество позиций со скидкой. Каждый второй товар со скидкой.
    CountDiscounWare = arrayPosition.length / 2;
    arrayDiscounPosition = new Array;
    for(var IndexDiscount = 1; IndexDiscount <= CountDiscounWare; IndexDiscount++)
    {
        arrayDiscounPosition.push(arrayPosition.shift());
    }
    return arrayDiscounPosition;

}

//Основная функция ее подставляем в ставку
function MyAction(AO, RO, POS)
{
    var Discount = 0;
    //Если позиция не относится ни к одному класссификатору, тогда и скидки на нее нет.
    if (POS.Classifier.Count == 0)
    {
        return Discount;
    }
    //Сформируем массив скидок
    var arrayDiscounPosition = collectArray(RO,POS);
    //Обрабатываем полученый массив. В массиве может быть не одна текущая позиция, если количество больше 1
    for (var index = 0; index < arrayDiscounPosition.length; index++)
    {
        if ((arrayDiscounPosition[index].ID == POS.PosID))
        {
            Discount = Discount + arrayDiscounPosition[index].Price*0.2;
        }
    }
    return Discount;
}

Очень нужный скриптик.., но почему то у меня фронтол вылетает если в чеке более 7 товаров забить принадлежащих одному классификатору.
АТОЛ: Средних Владимир
Цитата(Вованыч @ 11.12.2013, 20:02) *
Очень нужный скриптик.., но почему то у меня фронтол вылетает если в чеке более 7 товаров забить принадлежащих одному классификатору.

Версия фронтола, которая "вылетает"?
Вованыч
Цитата(АТОЛ: Средних Владимир @ 12.12.2013, 12:02) *
Версия фронтола, которая "вылетает"?

Начинал на 4.9.13
обновился до 4.9.14 ситуация та же.
Ошибку описывал в отдельной теме. Ошибка чтения памяти.
Патч ставил с форума, ситуация та же.
ДмитрийН
Подскажите пожалуйста, а как написать скрипт чтобы в определенное время выскакивало сообщение?
АТОЛ: Царюков Роман
Цитата(ДмитрийН @ 23.1.2014, 13:23) *
Подскажите пожалуйста, а как написать скрипт чтобы в определенное время выскакивало сообщение?

http://forum.atol.ru/index.php?showtopic=6...st&p=163789
POUL
Во Фронтоле начиная с релиза, по-моему 4.9.7 (могу ошибаться) доступно чтение данных из базы путем SQL запросов без использования внешних провайдеров.
Пример использования:

Код
    QueryCode = "";
    QueryName = "";
    Query = CO.NewDBQuery;
    Query.SQL = "SELECT CODE, NAME FROM SPRT WHERE PARENTID IN (SELECT ID FROM SPRT WHERE ISWARE = 0 AND NAME = "Контрацепция") ORDER BY 1";
    Query.Open();
    if (Query.FieldByName("CODE") != null)
    {
     do
     {
      QueryCode = QueryCode + String (Query.FieldByName("CODE")) + "\n";
      QueryName = QueryName + String (Query.FieldByName("NAME")) + "\n";
      n = Query.RecordCount;
      Query.Next();
     }
     while (n != Query.RecordCount)
     Query.Close();
    }
    if (QueryCode == "" || QueryName == "")
    {
     Query.Close();
     AO.ShowError ("Результат запроса пуст!");
    }
    QueryCode = QueryCode.substring (0, QueryCode.length - 1);
    QueryName = QueryName.substring (0, QueryName.length - 1);

    SelectedSol = Number (AO.SelectString ("Выберите товар:", QueryName, QueryCode));


Повторюсь. Доступно только чтение данных.
Romeo
Цитата(Лазарев Максим Викторович @ 25.1.2013, 14:18) *
Скрипт, блокирующий продажу алкоголя с 22.00 до 10.00 часов

Данный скрипт вытаскивает первые n символов из названия товара в позиции и сравнивает с заданными значениями в скрипте.
Скрипт писался специально, т.к. товарный справочник на кассе без классификатора (всё в куче, особенность товароучетки)
Вы сами можете "допилить" данный скрипт под свои наименования товаров.

CODE
unction BeforeAct(AO, RO, E, O, CO, POS)
{
var now = new Date();
var hour = now.getHours();
var s = O.Ware.Name;
var vin = s.substr(0, 3); //Вино
var vod = s.substr(0, 5); //Водка
var kon = s.substr(0, 4); //Коньяк
var piv = s.substr(0, 3); //Пиво
var nas = s.substr(0, 4); //Настойка
var bal = s.substr(0, 4); //Бальзам
var vis = s.substr(0, 3); //Виски
var lik = s.substr(0, 3); //Ликер
var rom = s.substr(0, 3); //Ром
var tek = s.substr(0, 3); //Текила
var brd = s.substr(0, 3); //Бренди
var kok = s.substr(0, 4); //Коктейль
var djn = s.substr(0, 4); //ДжинТоник
var shp = s.substr(0, 5); //Шампанское
var por = s.substr(0, 3); //Портвейн
var ver = s.substr(0, 5); //Вермут
var bo = s.substr(0, 15); //Балтика 0 (продавать можно)
var so = s.substr(0, 28); //Сибирская корона 0 (продавать можно)
var jag1 = s.substr(0, 5); //Ягуар
var jag2 = s.substr(0, 6); //Ягуар


if ((vin == "ВИН" || vod == "ВОДКА" || kon == "КОН " || piv == "ПИВ" || nas == "НАСТ" ||
bal == "БАЛЬ" || vis == "ВИС" || lik == "ЛИК" || rom == "РОМ" || tek == "ТЕК" || brd == "БРЕ" ||
kok == "КОКТ" || djn == "ДЖИН" || shp == "ШАМПА" || por == "ПОР" || ver == "ВЕРМУ" || jag1 == "ЭНЕР " || jag2 == "ЭНЕРГ ") &&
(bo != "ПИВО БАЛТИКА їО") && (so != "ПИВО Сибирская Корона БЕЗАЛК") && (hour >= 22 || hour < 10))
AO.ShowError("Нельзя продавать алкоголь с 22.00 до 10.00!!!");
}

function AfterAct(AO, RO, E, O, CO)
{
}

function FuncAct(AO, RO, CO)
{
}

function NoAction(AO, RO, POS, CO, UserParam)
{
}


По наименованию ??? blink.gif
Странно может получиться, особенно в случаях:
vin == "ВИН" - Виноград
kon == "КОН " - Конфеты
vis == "ВИС" - Вискас
por == "ПОР" - Порошок стиральный
... и прочие rolleyes.gif rolleyes.gif rolleyes.gif
АТОЛ: Царюков Роман
а с чего Вы взяли, что у них есть такие товары?
скрипт писали под себя, поэтому я думаю автор скрипта уверен в своем справочнике товаров
АТОЛ: Царюков Роман
Курс доллара. Пример работы с XML
АТОЛ: Царюков Роман
Научим фронтол разговаривать!!!
АТОЛ: Царюков Роман
Информеры Яндекс
еще один пример с XML
Волгоград.Инфософт
Задача:
Перед печатью картинки на ФР проверить принадлежность к формату bmp, ширину и высоту картинки в пикселях а так же количество бит цвета на пиксель.

Решаемая проблема:
Фискальные регистраторы умеют печатать только монохромные (один бит цвета на пиксель) картинки в формате bmp. Размер картинки может быть слишком широк для чековой ленты и слишком длинен для приемлемого времени печати. Проверка параметров файла, позволит принять решение о печати.

Пример получаемой информации:
Нажмите для просмотра прикрепленного файла

Пример вызова:

Код
function FuncAct(AO, RO, CO) {
    
    // конструктор объекта
    // параметр - полный путь к файлу картинки - строка
    // var bytes0 = new propertyBMPfile("d:\\picture\\0.bmp");
    
    // DepthColor = bytes0.nDepthColor; // получение свойства "глубина цвета" - число
    // Width = bytes0.nWidth;           // получение свойства "ширина растра" - число
    // Heigth = bytes0.nHeigth;         // получение свойства "высота растра" - число
    // Path = bytes0.fullPathFile;      // получение свойства "полный путь к картинке" - строка
    
    var bytes0 = new propertyBMPfile("d:\\picture\\0.bmp");
    AO.ShowMessage("глубина цвета " + bytes0.nDepthColor+"\n" +
        "ширина растра " + bytes0.nWidth+"\n" +
        "высота растра " + bytes0.nHeigth);
    
    var bytes1 = new propertyBMPfile("d:\\picture\\1.bmp");
    AO.ShowMessage("глубина цвета " + bytes1.nDepthColor+"\n" +
        "ширина растра " + bytes1.nWidth+"\n" +
        "высота растра " + bytes1.nHeigth);

    // !такой картинки в папке нет! Все свойства будут равны 0
    var bytes5 = new propertyBMPfile("d:\\picture\\5.bmp");
    AO.ShowMessage("глубина цвета " + bytes5.nDepthColor+"\n" +
        "ширина растра " + bytes5.nWidth+"\n" +
        "высота растра " + bytes5.nHeigth);
}


Файл класса:

Нажмите для просмотра прикрепленного файла
maxdale
есть справочные/обучающие материалы скриптам для Frontol 5 ?
АТОЛ: Царюков Роман
Цитата(maxdale @ 19.7.2016, 12:25) *
есть справочные/обучающие материалы скриптам для Frontol 5 ?

руководство интегратора
Волгоград.Инфософт
Функция, возвращающая путь к БД Frontol

Описание:
возвращает строку, которая содержит полный путь к базе данных
путь к базе читается из файла Frontol.ini
если не удалось получить путь, то возвращается пустая сторка


Пример вызова:

cPath = GetPathDBFrontol5(); //функция вернёт: "localhost:E:\BASE\POSBASE\FT_5_TRADE\"

Нажмите для просмотра прикрепленного файла
АТОЛ: Царюков Роман
в каком каталоге вы ищите файл Frontol.ini ?
для каких версий фронтол 5 будет работать данный сценарий?
POUL
del
Волгоград.Инфософт
Цитата(АТОЛ: Царюков Роман @ 13.9.2016, 13:08) *
в каком каталоге вы ищите файл Frontol.ini ?
для каких версий фронтол 5 будет работать данный сценарий?


Да, я понял вопрос. Представленная версия ищет ini файл в папке bin.
Постараюсь в ближайшие дени выпустить исправленную версию функции.
Волгоград.Инфософт
Цитата(АТОЛ: Царюков Роман @ 13.9.2016, 13:08) *
для каких версий фронтол 5 будет работать данный сценарий?


Уважаемые разработчики, расширьте пожалуйста класс Frontol свойством currentVersion и currentVariant (вариант поставки Frontol), тогда в скриптах можно будет проверять контекст исполнения и не напороть ошибок из за отличий в версиях.
АТОЛ: Царюков Роман
Цитата(Волгоград.Инфософт @ 13.9.2016, 14:10) *
Уважаемые разработчики, расширьте пожалуйста класс Frontol свойством currentVersion и currentVariant (вариант поставки Frontol), тогда в скриптах можно будет проверять контекст исполнения и не напороть ошибок из за отличий в версиях.

пока разработчики будут расширять этот функционал - дергайте инфу напрямую из БД
Волгоград.Инфософт
Функция GetPathDBFrontol5(cPathVariant) - получение пути к БД FronTol5
(это доработанная версия функции из сообщения http://forum.atol.ru/index.php?s=&show...t&p=212558)

функция GetPathDBFrontol5(cPathVariant) корректно работает для FronTol5 до и после версии 5.9.0

Описание:
Функция GetPathDBFrontol5(cPathVariant) - путь к базе данных Frontol5
возвращает строку, содержащую путь к БД Frontol или пустую строку, в случае ошибки
аргумент функции cPathVariant - строковой литерал со значением:
"OnlyPath" - по умолчанию - функция возвращает только путь к БД (E:\BASE\POSBASE\FT_5_TRADE\)
"HostAndPath" - функция возвращает хост и путь к БД (localhost:E:\BASE\POSBASE\FT_5_TRADE\)

Пример использования:
по умолчанию
Код
cPath = GetPathDBFrontol5(); // возвращает: E:\BASE\POSBASE\FT_5_TRADE\

с аргументом "OnlyPath"
Код
cPath = GetPathDBFrontol5("OnlyPath"); // возвращает: E:\BASE\POSBASE\FT_5_TRADE\

с аргументом "HostAndPath"
Код
cPath = GetPathDBFrontol5("HostAndPath"); // возвращает: localhost:E:\BASE\POSBASE\FT_5_TRADE\


Нажмите для просмотра прикрепленного файла
Волгоград.Инфософт
коллеги, оформил полезные функции для Frontol 5 в виде репозитория на GitHub:
https://github.com/infosoft-v/frontol5lib

для каждой функции написана краткая инструкция:
https://github.com/infosoft-v/frontol5lib/wiki

планирую, по мере появления универсальных функций в проектах, пополнять библиотеку.

Коллеги, с удовольствием добавлю ваши полезные универсальные функции для Frontol 5 в библиотеку. Автора и ссылку на источник укажу обязательно.
POUL
если не сложно, выложите пожалуйста в виде программнго кода, а не в виде ссылок
Волгоград.Инфософт
коллеги, позволю себе опубликовать тут краткую инструкцию по использованию GitHub и в частности получение текста функций из библиотеки

  1. по ссылке https://github.com/infosoft-v/frontol5lib можно попасть в библиотеку функций, где можно получить текст нужной функции или ознакомиться с документацией по использованию функций
    Нажмите для просмотра прикрепленного файла
  2. щелкнув на название функции, например getEAN13.js, можно перейти к тексту этой функции. Текст можно скопировать и использовать в своих проектах
    Нажмите для просмотра прикрепленного файла
  3. щелкнув на слове Wiki можно перейти к описанию функций и примерам использования
    Нажмите для просмотра прикрепленного файла
zenik
Цитата(Волгоград.Инфософт @ 20.9.2016, 14:26) *
можно попасть в библиотеку функций, где можно получить текст нужной функции или ознакомиться с документацией по использованию функций

Годнота... Я тоже подумал, что будет "качать". А так супер, жаль что функция пока маловато smile.gif
Волгоград.Инфософт
добавлена функция формирования строки жирным шрифтом для ККМ

функция getBoldString(cString) - получить строку, которую ККМ выведет жирным (bold) шрифтом

параметры:
cString - строка. Строка текста, которую необходимо преобразовать в в строку, которую ККМ выведет жирным шрифтом

Пример использования: cBoldString = getBoldString("ПРОДАЖА"); // возвращается строка преобразованная в шрифт bold "\tП\tР\tО\tД\tА\tЖ\tА"

эта и другие полезные функции на GitHub https://github.com/infosoft-v/frontol5lib
Евдокимов Сергей
Сценарий для 4 Фронтола. Он делает запрограммированную скидку в момент, когда продавец выбрал вид оплаты "Банковская карта"
Так же для этого сценарий нужно задать горячую клавишу на f5, которая будет запускать FuncAct этого сценария.

Код
var paymentCode = 2; // Код вида оплаты
var keyMacros = "{F5}"; //Клавиша для запуска макроса

function BeforeAct(AO, RO, E, O, CO) {
    if (E == 6) {
        if (O.Code == paymentCode) {
            runMacros(AO, RO, O);
            AO.Cancel();
        }
    }
}

function AfterAct(AO, RO, E, O, CO) {}

//Сценарий для макроса
function FuncAct(AO, RO, CO) {
    receiptSum = 0;
    for (RO.Pos.Index = 1; RO.Pos.Index <= RO.Pos.Count; RO.Pos.Index++) {
        if (RO.Pos.Storno == 0) {
            //Расчет скидки
            RO.Pos.SetPrice(RO.Pos.Ware.Price - (RO.Pos.Ware.Price / 1.13 * 0.01));
            receiptSum = receiptSum + RO.Pos.SummWD;
        }
    }
    //Добавляем оплату
    RO.AddPayment(paymentCode, receiptSum);

}

function NoAction(AO, RO, POS, CO) {}

//Нажатие кнопки
function runMacros(AO, RO, O) {
    var WShell = new ActiveXObject("WScript.Shell");
    WShell.SendKeys(keyMacros);
}
Волгоград.Инфософт
пополнил библиотеку полезных функций для FronTol5 двумя модулями:
Код
propertyBMPfile(cFullPathFile) - доступ к различным свойствам BMP файла
userVar - обёртка, для более удобной работы с пользовательскими переменными


библиотека доступна по адресу библиотека полезных функций на GitHub
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Русская версия IP.Board © 2001-2022 IPS, Inc.