Вход | Регистрация
    1  2  3  4  5  6

Конкретные вопросы по lsFusion. Часть 2.

Конкретные вопросы по lsFusion. Часть 2.
Я
   CrushBy
 
14.10.19 - 21:08
В этой ветке только вопросы по lsFusion, без оценок и срача, что в сторону lsFusion, что в сторону 1С.

Для сравнения и троллинга есть отдельная ветка : OFF: lsFusion vs 1C. Раунд 3
 
 
   Ещё1
 
501 - 29.10.19 - 13:27
Правильное решение получения объекта по внутреннему идентификатору:
order() <- GROUP MAX Order o IF o IS Order AND LONG(o) == impID();
   Bro
 
502 - 29.10.19 - 14:06
(501) Да есть этот фокус, с тем что указание класса, это еще не означает IS. Хотя строго говоря в данном случаем можно класс не указывать и просто писать GROUP MAX o IF o IS Order AND LONG(o) = impID();
   Ещё1
 
503 - 29.10.19 - 14:16
(502) Ага, untyped implicit parameter declaration. С другой стороны, если lsFusion может вывести тип и параметры переменной из записи запроса, то почему нет.
   Bro
 
504 - 29.10.19 - 14:39
(503) Это не warning. Это подсветка чтобы случайно новые параметры не заводили. lsFusion выводит классы параметры и значений свойств и при неявной ситуации. Просто обычно не рекомендуется не указывать классы параметров, если идет обращение к другим свойством, потому как ambigious рискуете получить, когда появится еще одно свойство с таким именем.
   Bro
 
505 - 29.10.19 - 14:40
* при неявной типизации
   Ещё1
 
506 - 29.10.19 - 16:24
(504) Так а в случае ambigious будет предупреждение? Если да - то не проблема.
   Ещё1
 
507 - 29.10.19 - 16:36
Обновляется ли форма в lsFusion автоматически при изменениях в базе? На примере: в web-клиенте открыта форма со списком заказов, на сервере приложений фоновая задача отрабатывает пришедший от 1С пакет, который обновляет статус заказов. Но у пользователя в Web-клиенте статусы сами не обновляются, надо жать formRefresh. Это так задумано, или недоработка (моя или платформы)?
   Злопчинский
 
508 - 29.10.19 - 16:40
(507) имхо это проблематично.
обновлений в базе столько может быть, что ядро должно постоянно диспетчеризировать и рассылать "уведомления" об обновлении. или клиент (с таймаутом? - это херня полная)
   Bro
 
509 - 29.10.19 - 16:52
(507) Да проблематично, по сути надо следить как-то за видимым окном и что именно в нем произошли изменения. Оверхед будет очень большой скорее всего в таком случае.

Для реализации таких вещей обычно AUTOREFRESH используют:
https://documentation.lsfusion.org/pages/viewpage.action?pageId=3670145
   Ещё1
 
510 - 29.10.19 - 17:26
(509) AUTOREFRESH отлично, полностью устраивает.
   Злопчинский
 
511 - 29.10.19 - 17:34
(509) при авторефреше - сохранится набитое в текстовых поляпрочих полях которые не изменялись другой тсороной? курсор в поле вврда текста останетяс на той же строке?
   Bro
 
512 - 29.10.19 - 17:47
(511) Естественно.
   Ещё1
 
513 - 29.10.19 - 20:48
Зря вы сделали логины пользователей чувствительными к регистру. Он должен иметь возможность ввести Vasya, vasya или VASYA (Caps Lock "случайно" включился), и система его примет. Меньше разгневанных звонков в службу поддержки. Вот пробелы в начале и конце логина отбрасываете - это правильно.
   Ещё1
 
514 - 30.10.19 - 11:37
Такой код:
NEW ur = UserRole {
  sid(ur) <- 'admin';
  //...
  mainRole(customUser('admin')) <- ur;
}
Он компилируется, но в IDEA подчёркивает красным customUser('admin') и пишет Ambiguous reference: mainRole(?) and mainRole(?) match.
Я уточняю тип параметра:
mainRole(customUser('admin') AS CustomUser) <- ur;
Но подчёркивание остаётся. Пробовал приведение к типу:
mainRole(CustomUser(customUser('admin'))) <- ur;
Но так не компилируется.
Как избавиться от этого предупреждения? Можно и так оставить, но я люблю когда код чистый, без предупреждений компилятора.
   _DAle_
 
515 - 30.10.19 - 12:08
(514) Подскажите, пожалуйста, если нажать ctrl+b на mainRole в исходном коде, то показываются ссылки на исходные файлы в двух разных .jar файлах, один из которых *sources.jar?
   Ещё1
 
516 - 30.10.19 - 14:15
   _DAle_
 
517 - 30.10.19 - 14:40
(516) Избавиться всегда можно с помощью явного указания сигнатуры, в данном случае mainRole[User], но ситуация ненормальная, нужно смотреть.
   Ещё1
 
518 - 30.10.19 - 14:45
Подстановка mainRole[CustomUser](customUser('admin')) <- ur; не убирает подчёркивание.
   Ещё1
 
519 - 30.10.19 - 14:49
https://paste.pics/81cbf7cc50a7b6a2939a2b7dc5e949b5
Меня смущают "?" в предупреждении об ошибке. Такое ощущение что плагин не видит истинных типов параметров в определениях mainRole.
   _DAle_
 
520 - 30.10.19 - 15:15
(518) Да, но я не зря написал, mainRole[User], вы же в DATA свойство хотите записать.
(519) Да, похоже, почему-то не видит, надо разбираться. Могу пока посоветовать вызвать File | Invalidate caches / restart, пускай индексы перестроит для начала.
   _DAle_
 
521 - 30.10.19 - 15:33
(520) Воспроизвел баг, проявляется, когда системные модули, в том числе и Security.lsf, находятся внутри jar файла, как, видимо, и у вас сейчас. Будем разбираться.
   Злопчинский
 
522 - 31.10.19 - 00:24
Где по типовой методе в фузине предполагается хранить картинки товаров (для веба и для десктопа).
Как от рисовать хранимую картинку на форме? Типа идём по товарам по списку - меняется картинка.
   _DAle_
 
523 - 31.10.19 - 12:24
(522) Я, конечно, не очень знаю типовые подходы. Но в исходниках вижу, например, вот такое применение:

image 'Изображение' = DATA IMAGEFILE (Article, Color);

То есть изображения хранятся в базе. Реализуется это с помощью свойства, которое возвращает объект класса IMAGEFILE. В данном случае выбор картинки зависит от артикула и цвета. Потом нужно будет добавить это свойство на форму, обычно в отдельную панель.
   Bro
 
524 - 31.10.19 - 12:30
(522)
image = DATA IMAGEFILE (Sku);
FORM skus
    OBJECTS s=Sku
    PROPERTIES (s) image PANEL
;

Когда будете ходить по товарам картинка будет сама обновляться.  Хранятся прямо в базе.
   Ник080808
 
525 - 31.10.19 - 12:33
(524) если нужно прикреплять несколько картинок к товару? к строке документа?
   CrushBy
 
526 - 31.10.19 - 12:43
(525) Несколько картинок :
CLASS Image;
sku = DATA Sku (Image) NONULL DELETE;
file = DATA IMAGEFILE (Image);

Прикрепление к строке документа :
image = DATA IMAGEFILE (DocumentLine);
   Ник080808
 
527 - 31.10.19 - 12:47
(526) по какому ключу связывается картинка и строка? по номеру строки?
   CrushBy
 
528 - 31.10.19 - 12:52
(527) Смотрите, IMAGEFILE - это просто примитивный тип. Вроде строки. В базе данных она хранится как byte array (то есть просто бинарным файлом). Соответственно просто в строке появляется новое поле. Как правило, мы складываем их в отдельную таблицу, чтобы не раздувать основную таблицу со строками :

TABLE documentLineImage(DocumentLine);
image = DATA IMAGEFILE (DocumentLine) TABLE documentLineImage;
   Ещё1
 
529 - 31.10.19 - 13:15
Непонятно, как показать в карточке товара все его картинки. Например, автомобиль, снятый с разных ракурсов. Тут можно разную логику придумать, например по-умолчанию выводится 1-я прикреплённая картинка. Щёлкая по картинке - открывается новое окно с галереей картинок по товару.
   Bro
 
530 - 31.10.19 - 15:02
(529) Можно либо в таблице сделать и увеличить размер ряда, либо что логичнее объектами-в-колонки:

image = DATA IMAGEFILE (Car, LONG);
FORM carWithPhotos
    OBJECTS c=Car, l=LONG
    FILTERS image(c, l) // фильтруем только номера с картинками
    PROPERTIES image(c,l) COLUMNS (l) HEADER 'Фото ' + l
;
По идее должно сработать
 
 Рекламное место пустует
   Ещё1
 
531 - 31.10.19 - 15:08
(530) Т.е. в таблицы можно не только текст выводить, но и картинки?
   Злопчинский
 
532 - 31.10.19 - 16:34
(470) я согласен, но настройки интерфейса - зачем на них разработчика тащить. если у меня на ноуте по вертикали 800 пикселей экран - мне бы верхнее меню вообще значки убоать и оставить только текст.
.
аналогично - левая панель перечень справочников\документов - хорошо бы разные пиктограммы иметь и убрать текстт - я по горизонтали сэкономлю...
   Злопчинский
 
533 - 31.10.19 - 16:37
(531) не, в таблицы картинкт колонками выводить это в отчет хорошо. а на экране - как показать ленту картинок для текущей строки таблицы\списка?понятно что в ленте может быть переменное колво картинок для разных строк списка.
   Bro
 
534 - 31.10.19 - 16:38
(531) ну все можно везде выводить. Строго говоря, с точки зрения реализации свойство в панели это таблица из одного ряда, одной колонки, без заголовка. Вопрос что у разных типов разные рендереры. У картинок это отображение картинки.
   Bro
 
535 - 31.10.19 - 16:39
(533) для этого объекты-в-колонки использовать. То есть по сути кросс-таблицы, просто в панели эта таблица из одного ряда.
   Ещё1
 
536 - 01.11.19 - 01:42
Воспользовался предложением CrushBy в соседней ветке ( OFF: lsFusion vs 1C. Раунд 7 (37) ) и переделал обновление справочника товаров, как приведено в примере №3 https://documentation.lsfusion.org/pages/viewpage.action?pageId=46367614
И сравнил по скорости с первоначальным решением "в лоб". В качестве теста делал 3 загрузки каталога: сначала 1-ю половину, потом 2-ю, а потом целый каталог товаров.
Действительно, загрузка ускорилась практически ровно в 2 раза.
   CrushBy
 
537 - 02.11.19 - 11:17
К сожалению, оптимизация получилась не полной. В общем случае FOR может скомпилироваться в один SQL запрос (а не выполняться на сервере приложений), если в нем нет IF'ов, других FOR'ов и строки записи внутри его не зависят друг от друга. У Вас же получается, что внутри пробега создаются группы, производители и прочие. Для оптимизации нужно вынести создание справочников за пределы FOR'а.

Например, с импортом групп снаружи FOR будет другой цикл по созданию несуществующих групп :
FOR [GROUP MAX INTEGER i BY groupName(i)](ISTRING[100] name) AND NOT groupByName(name) NEW g = Group DO {
    name(g) <- name;
}

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

Потом уже при заполнении свойств sku там останется только
group(u) <- groupByName(groupName(i));

так как все группы уже созданы в предыдущем FOR'е.

Это все приведет к тому, что все пойдет одним запросом и импорт должен ускориться во много раз.
   Bro
 
538 - 02.11.19 - 12:23
(537) IF'и и FOR'ы тоже отлично компилируются в "один запрос" (ELSE'ы только пока не компилируются). Главное чтобы зависимостей читающих свойств от свойств в которые пишется не было. Хотя там можно INLINE в FOR поставить и тогда :

FOR f(a) INLINE DO
   g(a) <- h(g(a));

Скомпилируется в WHERE (то есть один запрос):
g(a) <- h(g(a)) WHERE f(a);
принудительно. Но нужно понимать, что при этом может поменяться логика (собственно поэтому платформа этого и не делает).

INLINE пока единственная (или одна из 2-3) опция которая не описана в документации, так как для этого нужно подробнее описывать как все работает. Это мы конечно тоже сделаем, но чуть позже.
   Ещё1
 
539 - 02.11.19 - 18:10
Я собирался вынести обновление вспомогательных справочников отдельно. Но почему-то показалось, что несколько пробегов типа FOR groupName(INTEGER i) ... по загруженным данным будут хуже 1 пробега FOR id(SKU u) == skuID(INTEGER i), пусть с проверками внутри. А надо было проверить, разница очень заметная. Если до изменений тест пробегался за 16145 мс и 14379 мс (1-я и последующие итерации), то после выноса обновлений справочников - 2688 мс и 1743 мс соответственно. Выигрыш в 6-8 раз. Получается импорт стал быстрее в 12-16 раз по сравнению с решением "в лоб".

Может, немного сбил синтаксис локальных свойств, что вместо
groupName = DATA LOCAL ISTRING[100] (INTEGER);
нужно писать
LOCAL groupName = ISTRING[100] (INTEGER);

Я протестировал сейчас 4 варианта: с циклами типа FOR groupName(INTEGER i)..., циклы FOR [GROUP MAX INTEGER i BY groupName(i)](name), и те же циклы с добавлением INLINE. По скорости они все примерно одинаковы. Может только FOR groupName(INTEGER i)... без INLINE чуть медленнее, но нужны значительно большие тестовые справочники, чтобы утверждать точно.

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

Небольшое наблюдение. В операторе
[GROUP MAX INTEGER i BY groupName(i)](ISTRING[100] name)
Я бы предпочёл не указывать тип параметра ISTRING[100]. И я вижу, язык это позволяет. Причина: при изменении размерности или типа исходного свойства (например на STRING[200]) при явном указании типа в (ISTRING[100] name) придётся вручную отыскать все такие использования и откорректировать.
   tty12
 
540 - 02.11.19 - 18:46
(538) (537)
Может уже спрашивали, но я ответа не видел... И все с начала читать лень.
Конкретный, простой вопрос. Вы зарубу (задачи в ней) сделали? На котрую Вы подписались! Где решение? Под ТЗ решение, а не под оду... У вас есть ответ?

PS: Я вижу один и тот же ответ -
1. "Три сточки дописать." - это всегда!!!
2. "Джун косячит..." - хотя Краш клялся за ним следить, "как за собой" - его цитата.
3. "Краш оду пишет..." - нахер она кому нужна тут???? Речь не про оду...
4. А надо ли продолжать?

Фузинаторы - Вы дурачки?
   CrushBy
 
541 - 03.11.19 - 13:45
(539) Я тут немного понял вот что, делать вот так вроде как нельзя :
FOR groupName(INTEGER i) AND NOT groupByName(groupName(i)) NEW g = Group DO {
name(g) <- groupName(i)
}

Поскольку, если это не будет скомпилировано в один запрос, то сначала вычисляется выражение, а затем идет по нему итерирование уже на сервере приложений. Так как таблица денормализованна, то создастся несколько групп с одинаковым именем и сохранение не пройдет по CONSTRAINT. Поэтому в моем примере шел GROUP MAX.
В целом важно понимать, что нужно стремиться, чтобы все компилировалось в SQL запрос, так как выполнение на сервере БД значительно быстрее чем round trip между сервером приложений и сервером БД.

[Может, немного сбил синтаксис локальных свойств, что вместо
groupName = DATA LOCAL ISTRING[100] (INTEGER);
нужно писать
LOCAL groupName = ISTRING[100] (INTEGER);]
Эти два объявления с точки зрения выполнения идентичны. Разница в том, что второе объявление видно только в пределах действия, а первое - в пределах модуля и зависимых от него модулей.

[С INLINE мне не совсем понятно. Есть ли небольшое ускорение, или и без INLINE компилятор нормально справился в данном случае.]
Итерирование на большом объеме в любом случае медленнее, если с INLINE они одинаковы, то или INLINE не сработал и запрос не скомпилировался, или наоборот, исходный скомпилировался. Вообще, с точки зрения выполнения это хорошо видно по "бегунку" в GUI. При итерировании будет идти бегунок, когда выполняется SQL запрос, то никакого бегунка быть не может, так как SQL запрос не возвращает данные о статусе своего выполнения в данный момент.

[Я бы предпочёл не указывать тип параметра ISTRING[100]].
Да, там можно не указывать. Платформа должна в таком случае вывести тип сама (если получится).
   Salimbek
 
542 - 08.11.19 - 16:58
Тут Конкретные вопросы по lsFusion
Это:
// можно сделать хитрее, i2 закинуть в колонки выдаст матрицу 10x10 в ней будут значения

REQUIRE Utils; // Моя добавка, т.к. iterate в utils

FORM a
    OBJECTS i1=LONG
    PROPERTIES VALUE(i1)

    OBJECTS i2=LONG
    PROPERTIES a(i1,i2) COLUMNS (i2) HEADER (i2)
    FILTERS iterate(i1,1,10), iterate(i2,1,10)
;

run() {
    a(1,2) <- 5;
    a(4,2) <- 7;
    a(1,3) <- 9;

    SHOW a;
}


Пробую выполнить код на lsfusion.org/try - открывается пустое приложение, SHOW a не срабатывает?

Ну ок, запускаю IDEA, копирую туда этот код, в ответ: ERROR StartLogger - Exception while starting logics instance: [error]:    Main:11:5 single parameter is forbidden in this context
Subsequent errors (if any) could not be found.

Как я понял - это оно на HEADER (i2) ругается, но как и где поправить?
   Ёпрст
 
543 - 08.11.19 - 18:12
(542) тестиь платформу ? Я чегой-то подзабил, хотя и развернул и демку с ерп даже запустил, лень
   Bro
 
544 - 08.11.19 - 18:32
(542) Вообще сейчас не у компьютера, но по идее можно написать HEADER (i2+1-1) :) То есть ей не нравится в этом месте параметр, там да косяк был в этом месте. На самом деле в 2.1 это уже пофикшено ЕМНИП и даже уже релиз ее был. На сайте ссылки новые на нее не добавили. Хотя на download.lsfusion.org уже есть.
   CrushBy
 
545 - 08.11.19 - 18:51
(542) Если речь идет о запуске в Try, то вот модифицированный код, который работает :
REQUIRE Utils; // Моя добавка, т.к. iterate в utils

a = DATA LONG (LONG, LONG);

FORM a
    OBJECTS i1=LONG
    FILTERS iterate(i1,1,10)

    OBJECTS i2=LONG
    PROPERTIES a(i1,i2) COLUMNS (i1) HEADER (i1)
    FILTERS iterate(i2,1,10)
;

NAVIGATOR {
    NEW a;
}
   Bro
 
546 - 08.11.19 - 19:13
(542) а понял теперь. На Try уже свежая версия 3.beta.0 (поэтому на HEADERS (i2) не ругается), а в инсталляторе вы 2.0 ставили где да была такая проблема.

А не запускается потому как run() в режиме платформы ничего не значит, это вы просто объявили действие с именем run. Оно играет роль в режиме СУБД (а точнее оператора EVAL или HTTP вызова eval например, который и выполняет EVAL) - там выполняется именно действие с именем run.
https://documentation.lsfusion.org/pages/viewpage.action?pageId=4915350
https://documentation.lsfusion.org/pages/viewpage.action?pageId=51216539
   Salimbek
 
547 - 12.11.19 - 14:52
(546) И как обновиться с 2.0 до "3.beta.0" или чего там у вас самое новое?
   Bro
 
548 - 12.11.19 - 15:13
(547) Последние snapshot версии вот тут (файлы с постфиксом assembly, это jar файлы все-в-одном вместе с зависимостимя ):
Сервер:
https://repo.lsfusion.org/nexus/service/rest/repository/browse/public/lsfusion/platform/server/3.beta.0-SNAPSHOT/
Десктоп-клиент:
https://repo.lsfusion.org/nexus/service/rest/repository/browse/public/lsfusion/platform/desktop-client/3.beta.0-SNAPSHOT/
Веб-клиент:
https://repo.lsfusion.org/nexus/service/rest/repository/browse/public/lsfusion/platform/web-client/3.beta.0-SNAPSHOT/

Инструкции тут в разделе Обновление:
https://documentation.lsfusion.org/pages/viewpage.action?pageId=57738078

Пока 3.beta.0 не выпускали, но в ближайшее время выпустим, тогда просто в download.lsfusion.org появится.
  1  2  3  4  5  6

Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.