
La deuxième partie de la trilogie du langage et de la plateforme lsFusion. La première partie se trouve
ici .
Il se concentrera sur la logique des représentations, à savoir sur tout ce qui concerne la combinaison des données et leur affichage à l'utilisateur ou à d'autres systèmes d'information.
Il est clair que beaucoup ne sont peut-être pas aussi intéressés à regarder la présentation du combattant, et ils aimeraient voir un vrai combat, si possible avec du sang (et ce le sera, car la discussion des articles précédents a aidé à mieux comprendre les endroits non protégés des concurrents potentiels et où les battre) . Mais il y a deux choses à considérer:
a) c'est Habr. C'est-à-dire, une ressource technique, ils n'aiment pas les belles images et les slogans publicitaires ici - pour dire quelque chose, vous avez besoin de détails sur la façon dont vous allez y parvenir.
b) c'est un marché pour le développement de systèmes d'information, et il est très similaire au marché des produits amaigrissants. Ici, tout le monde dit que nous avons un service rapide et facile. Mais en ce qui concerne les détails, dans lesquels, comme vous le savez, le diable se trouve, soit les CRUD les plus simples sont utilisés comme exemples, soit ils ont recours à diverses astuces: ils affichent quelques extraits de code et masquent la partie principale avec les mots «cela n'a pas d'importance "," Fait en quelques minutes "et tout le reste.
En fait, c’est pourquoi nous avions deux options: soit commencer par les avantages et les risques d’obtenir des reproches pour le marketing de conneries, soit commencer par une description technique et les questions «pourquoi avons-nous besoin d’une autre langue». Théoriquement, bien sûr, tout cela pourrait être fait en un seul article, mais un tel article serait difficile non seulement à lire, mais même juste à faire défiler. En conséquence, nous avons choisi la deuxième option, bien que s'il est toujours important pour quelqu'un de se renseigner sur les raisons de l'apparence et des avantages de la langue en ce moment (et non dans de futurs articles), bienvenue sur le
site . Il ne comprend que trois pages: quoi, comment et pourquoi pas, et donne, à mon avis, suffisamment d'informations pour répondre à toutes ces questions. De plus, vous pouvez également essayer la plate-forme en
ligne là -
bas ,
y compris pour vous assurer qu'il n'y a pas de «piano dans les buissons», et le code des exemples de cet article est vraiment tout le code nécessaire pour exécuter l'application.
Mais assez digressions lyriques, nous revenons à la
présentation de la description
combattante de la logique des représentations.
Comme la logique de domaine (premier article), tous les concepts de logique de présentation dans lsFusion forment une pile:

et c'est dans l'ordre de cette pile que je vais en parler.
Formulaires
Un formulaire est le concept le plus important (et en fait pratiquement le seul) dans la logique de présentation, qui est responsable de tout - à la fois pour l'interaction avec l'utilisateur et pour l'impression, l'exportation et l'importation de données.
Le formulaire peut logiquement être divisé en deux parties:
- La structure du formulaire détermine quelles données le formulaire affiche.
- La présentation du formulaire détermine comment il affiche ces données.
Structure de forme
Nous commençons, naturellement, par la structure de la forme.
Les objets
Lors de la création d'un formulaire, vous devez d'abord déterminer les objets qu'il affichera. Il convient de noter qu'il peut y avoir une légère confusion terminologique entre les objets du formulaire et les objets affichés dans ces objets de formulaire. Par conséquent, à l'avenir, si cela n'est pas évident dans le contexte, nous utiliserons les termes «objets de formulaire» (pour le premier cas) et «objets dans la base de données» (pour le second).
Pour chaque objet de formulaire, vous devez définir sa classe. Cette classe peut être primitive (intégrée) ou objet (personnalisée).
Conformément à l'ordre d'ajout d'objets au formulaire, une liste ordonnée d'objets est formée. Par conséquent, le dernier objet d'un certain ensemble d'objets sera appelé un objet de cet ensemble avec le numéro de série maximal dans cette liste (c'est-à-dire le plus récent).
Chaque objet du formulaire à un moment donné a une valeur actuelle. Son changement se produit en fonction de la présentation, soit du fait des actions correspondantes de l'utilisateur dans la présentation interactive, soit "virtuellement" dans le processus de lecture des données dans une représentation statique.
Propriétés et actions
Après avoir défini les objets sur le formulaire, vous pouvez ajouter des propriétés et des actions, en les remplaçant par les objets décrits ci-dessus comme entrée dans les arguments.
Notez que l'ajout d'actions n'est pertinent que pour la présentation interactive; elles sont ignorées dans les rapports et les exportations. De plus, étant donné que le comportement des propriétés et des actions du point de vue de leur affichage sur le formulaire est exactement le même, à l'avenir, nous n'utiliserons que le terme propriété (pour les actions, le comportement est absolument similaire).
Objet d'affichage
Chaque propriété est affichée dans exactement un objet sur le formulaire (nous l'appellerons l'objet d'affichage de cette propriété). Par défaut, l'objet d'affichage est un objet, ce dernier pour l'ensemble d'objets qui sont passés à l'entrée de cette propriété. Par exemple, si nous avons une forme de soldes courants avec deux objets - un entrepôt et des marchandises et trois propriétés - les noms de l'entrepôt et des marchandises et le solde des marchandises dans l'entrepôt:
Ensuite, pour le nom de l'entrepôt, l'objet d'affichage sera s (entrepôt), et pour le nom des marchandises et le solde, i (marchandises).
Cependant, si nécessaire, le développeur peut spécifier explicitement l'objet d'affichage (c'est-à-dire, par exemple, dans une vue interactive, afficher la propriété avec le reste dans le tableau des entrepôts, pas des marchandises).
Filtres et tri
Pour chaque formulaire, le développeur peut définir des filtres et des commandes qui limiteront la liste des objets disponibles pour la visualisation / sélection sur le formulaire, ainsi que l'ordre dans lequel ils sont affichés.
Pour définir un filtre, vous devez spécifier une propriété qui sera utilisée comme critère de filtre. Le filtre sera appliqué à la table de cet objet, qui est le dernier pour l'ensemble d'objets transmis à l'entrée de cette propriété (c'est-à-dire, de la même manière qu'avec la définition de l'objet d'affichage de propriété). Dans ce cas, seuls les ensembles d'objets (séries) seront affichés pour lesquels les valeurs de propriété ne sont pas NULL. Par exemple, si nous ajoutons le filtre currentBalance (s, i) OU isActive (i) au formulaire ci-dessus:
Capture d'écran du formulaire lors de l'affichage des produits, seuls les produits en équilibre ou marqués comme actifs seront affichés.
Les tris sont définis comme une liste de propriétés sur le formulaire dans lequel les objets doivent être affichés. Sinon, tout est similaire aux filtres.
Groupes d'objets
La plateforme a également la possibilité de combiner des objets en un
groupe d'objets . Dans ce cas, le «produit cartésien» de ces objets sera affiché dans les tableaux / listes (c'est-à-dire pour deux objets - toutes les paires, trois objets - les triplets, etc.).
Capture d'écran du formulaire Par conséquent, presque partout, avant et après, au lieu d'objets uniques du formulaire, vous pouvez utiliser des groupes d'objets.
En fait, c'est ce qui a été fait dans la documentation: le terme plus général «groupe d'objets» est utilisé partout, mais pour ne pas compliquer les choses dans cet article (et les groupes d'objets composés de plusieurs objets sont utilisés beaucoup moins souvent), il a été décidé d'oublier et de compter sur les groupes d'objets, qu'un groupe d'objets se compose toujours d'un seul objet et, par conséquent, utilise partout le terme «objet» au lieu du «groupe d'objets» et «ensemble d'objets» plus complexe.
Groupes de propriétés
Les propriétés du formulaire, comme les objets, peuvent également être combinées en groupes, qui, à leur tour, sont utilisés dans les représentations interactives (conception par défaut) et hiérarchiques du formulaire (à leur sujet un peu plus tard). Par défaut, la liaison d'une propriété à un groupe est globale (c'est-à-dire qu'elle est définie pour une propriété pour tous les formulaires à la fois), mais si nécessaire, pour les formulaires individuels, cette liaison peut être redéfinie.
Objets de colonne
Par défaut, une propriété est affichée exactement une fois dans son objet d'affichage. Dans ce cas, comme les valeurs des objets autres que l'objet d'affichage de cette propriété (nous les appelons supérieur), leurs valeurs actuelles sont utilisées. Cependant, la plate-forme a également la possibilité d'afficher une propriété plusieurs fois afin que les valeurs de certains objets supérieurs ne soient pas utilisées par leurs valeurs actuelles, mais tous les objets de la base de données qui conviennent aux filtres. Avec ce mappage de propriétés, une sorte de «matrice» est formée - (objet d'affichage) x (objets supérieurs). En conséquence, afin de créer une telle matrice, lors de l'ajout d'une propriété au formulaire, il est nécessaire d'indiquer quels objets supérieurs doivent être utilisés pour créer des colonnes (nous appellerons ces objets objets-en-colonnes).
Capture d'écran du formulaire Donc, avec ce que le formulaire affiche, plus ou moins compris, passons à la façon dont il peut le faire.
Soumissions de formulaires
Il y a trois soumissions de formulaires:

Voir les captures d'écranInteractif:

Imprimé:

Structuré:

- Interactif. Une vue avec laquelle l'utilisateur peut interagir consiste à modifier les données et les objets actuels en déclenchant divers événements. En fait, cette représentation est généralement appelée un formulaire.
- Imprimé. Il est généralement appelé un rapport - en téléchargeant toutes les données du formulaire et en les présentant sous forme graphique. Y compris avec la possibilité de les imprimer (d'où il tire son nom).
- Structuré - représentation du formulaire dans différents formats structurés (JSON, XML, DBF, etc.). Généralement utilisé pour une intégration plus poussée avec d'autres systèmes.
Les représentations interactives et imprimées sont graphiques, c'est-à-dire qu'elles affichent les données reçues dans un espace bidimensionnel: le papier ou l'écran de l'appareil. En conséquence, chacune de ces représentations a une conception qui, en fonction de la représentation particulière, peut être définie à l'aide de mécanismes appropriés (à leur sujet un peu plus tard).
La présentation imprimée et structurée est statique, c'est-à-dire qu'ils lisent toutes les données au moment de l'ouverture du formulaire (par opposition à la présentation interactive, qui lit les données si nécessaire).
La description des performances commencera peut-être par la plus difficile - la présentation interactive.
Présentation interactive
Dans une vue interactive, les objets de formulaire sont affichés sous forme de tableau. Les lignes de ce tableau correspondent aux objets de la base de données qui satisfont aux filtres spécifiés, les colonnes, à leur tour, correspondent aux propriétés.
Toutefois, si nécessaire, la propriété peut être affichée non pas comme une colonne de tableau, c'est-à-dire pour toutes ses lignes, mais comme un champ distinct sur le formulaire, c'est-à-dire uniquement pour la valeur actuelle de l'objet de formulaire. Par exemple:
Capture d'écran du formulaire La modification de la valeur actuelle d'un objet de formulaire se produit soit à la suite d'un changement de ligne actuelle de la table par un utilisateur, soit à la suite de l'exécution d'une action créée à l'aide d'un opérateur de recherche spécial (SEEK).
Notez que la façon dont une propriété est affichée dans un panneau ou une table, en règle générale, n'est pas définie séparément pour chaque propriété, mais dans son ensemble pour un objet de formulaire. Par conséquent, si l'objet de formulaire est marqué comme PANEL, toutes ses propriétés sont affichées dans le panneau (c'est-à-dire pour la valeur actuelle), sinon (par défaut) toutes ses propriétés sont affichées dans le tableau. Les propriétés sans paramètres et actions par défaut sont affichées dans le panneau.
Toutes les tables de la vue interactive sont dynamiques par défaut, c'est-à-dire que seul un nombre limité d'objets dans la base de données sont lus et les autres sont lus lorsque l'objet actuel dans la table change. Dans ce cas, le nombre d'objets affichés peut être déterminé automatiquement en fonction de la hauteur de la partie visible de la table ou défini explicitement par le développeur lors de la création du formulaire.
En outre, le formulaire dans la présentation interactive est complètement réactif, c'est-à-dire qu'il met automatiquement à jour toutes les données du formulaire lorsque des données qui les affectent changent (telles que React, uniquement dans le cas général). De plus, tout cela ne se fait pas par recalcul complet (comme dans le même React), mais de manière incrémentielle, de plus, sur le serveur SQL.
En général, c'est drôle quand, en comparant avec d'autres technologies, vous essayez d'inclure les trois principales exigences dans la tâche, les gens se font souvent des yeux ronds, comme si on leur demandait de lancer une personne dans l'espace. Bien que le non-respect de la deuxième exigence par tout utilisateur normal soit classé comme un bug, et la première et la troisième exigence sont que le formulaire développé fonctionne normalement lorsqu'au moins un peu de données apparaissent dans la base de données (plusieurs dizaines de milliers d'enregistrements, par exemple).
La présentation interactive est prise en charge à la fois en mode client Web (c'est-à-dire les applications Web dans un navigateur) et en mode client de bureau (applications Java). Le client de bureau, comme tout client natif, a une réactivité légèrement meilleure de l'interface, mais surtout, il vous permet de travailler avec du matériel et d'effectuer d'autres opérations qui ne sont pas disponibles dans le navigateur (principalement en raison de problèmes de sécurité).
Arbres d'objets
En plus des tableaux, la plateforme vous permet également d'organiser l'affichage des objets sous forme d'arbres, à la fois plats ("imbriqués" dans les autres tableaux) et récursifs (par exemple, les objets "imbriqués" dans la base de données).
Les arbres plats, en fait, sont une généralisation des tables, lorsque plusieurs tables sont "combinées" en une seule table à la fois:
Capture d'écran du formulaire Il s'agit d'un mécanisme relativement complexe et rarement utilisé dans la pratique, nous n'y reviendrons donc pas en détail.
Mais les arbres récursifs, au contraire, sont utilisés assez souvent (par exemple, pour implémenter des classificateurs). Pour afficher un objet de formulaire sous la forme d'un tel arbre, il est nécessaire de définir un filtre supplémentaire pour lui - une propriété dont la valeur pour les objets inférieurs doit être égale à l'objet supérieur. Initialement, l'objet supérieur est considéré comme NULL.
Capture d'écran du formulaire Gestion du formulaire utilisateur
Pour assurer une meilleure ergonomie du système (notamment pour ne pas créer de formulaires pour tout le monde), une partie des opérations de mise en place de la présentation interactive du formulaire peut être effectuée par les utilisateurs eux-mêmes. Par exemple, ces opérations sont les suivantes:
- mise en place de tableaux (colonnes visibles, ordre, polices, etc.),
- créer des filtres et des tris personnalisés,
- regrouper les données par valeurs de colonne,
- imprimez un tableau et téléchargez-le dans Excel.
En outre, le développeur peut créer les soi-disant groupes de filtres, que l'utilisateur peut activer / désactiver indépendamment. Par exemple:
Ce ne sont pas toutes les possibilités de personnalisation du système par l'utilisateur, mais nous reviendrons sur les autres possibilités dans le troisième article, car la plupart d'entre elles n'ont toujours pas de relation directe avec la logique de présentation.
Notez que la fonctionnalité décrite ci-dessus se réfère plus probablement à la fonctionnalité des plates-formes ERP, qui est déjà complètement discordante avec le titre de l'article. D'autre part, comme mentionné dans le premier article, à l'avenir, le langage / la plate-forme prétend remplacer, y compris cette classe de plates-formes, il serait donc faux de ne pas mentionner du tout ces fonctionnalités.
Opérateurs d'objets
L'un des scénarios les plus courants d'utilisation d'un formulaire consiste à ajouter / supprimer un objet, ainsi qu'à le modifier dans un nouveau formulaire. Pour implémenter de tels scénarios, la plateforme dispose d'un ensemble prédéfini d'opérateurs qui vous permettent de créer les actions nécessaires en un mot directement dans l'opérateur de création de formulaire:
- NOUVEAU - créer un objet
- EDIT - modification d'un objet
- NEWEDIT - création et modification d'un objet
- DELETE - supprimer un objet
De plus, comme il est très souvent nécessaire d'effectuer ces actions dans une nouvelle session (si vous devez séparer les actions de création d'objets des actions sur le formulaire à partir duquel ces objets sont créés), la plateforme prend en charge le sucre syntaxique correspondant - les options NEWSESSION et NESTEDSESSION, qui fonctionnent de manière similaire aux opérateurs du même nom créer des actions, mais, comme les opérateurs eux-mêmes travaillant avec des objets, il n'est pas nécessaire que le développeur crée et nomme de nouvelles actions. Par exemple:
Par défaut, lors de la modification d'un objet, le formulaire de modification est appelé, qui est automatiquement généré pour la classe de l'objet de formulaire transmis. Cependant, il est souvent nécessaire de redéfinir ce formulaire (par exemple, ajouter des informations supplémentaires, changer la conception, etc.) Pour ce faire, il suffit de créer le formulaire d'édition nécessaire et d'indiquer qu'il s'agit du formulaire par défaut pour éditer les objets d'une classe donnée:
De même, les formulaires de sélection des objets d'une classe donnée sont redéfinis.
Conception de forme
Comme avec la plupart des interfaces graphiques existantes, la conception d'une présentation interactive d'un formulaire est une hiérarchie dont les nœuds sont des composants. À leur tour, les composants peuvent être:
- conteneurs - composants qui contiennent d'autres composants.
- composants de base - représentations graphiques des éléments de base: tableaux, panneaux de propriétés, groupes de filtres, etc.
Le mécanisme d'organisation des composants à l'intérieur des conteneurs répète essentiellement la
disposition de boîte flexible CSS (et est implémenté dans le client Web avec lui), nous ne nous attarderons donc pas sur ce mécanisme en détail.
Notez que la conception du formulaire n'est généralement pas créée à partir de zéro (car elle prend beaucoup de temps). En règle générale, une conception de formulaire est automatiquement créée en fonction de la structure du formulaire, puis le développeur ne le modifie que légèrement: par exemple, ajoute un nouveau conteneur et lui transfère des composants existants:
Exemple de conception de formulaire par défautLa hiérarchie des conteneurs et des composants dans la conception par défaut ressemblera à ceci:

Capture d'écran du formulaire Form Design 2.0 (React)
En regardant les représentations interactives des formulaires dans les captures d'écran ci-dessus (ou, par exemple, dans une démo en ligne), vous pouvez voir que la conception actuelle du formulaire dans l'interface utilisateur est, disons, assez ascétique. Bien entendu, cela n'a jamais été un problème particulier pour les systèmes d'information, où les principaux utilisateurs sont des employés ou des partenaires de l'entreprise propriétaire de ces systèmes d'information. De plus, malgré l'ascétisme, le mécanisme actuel de conception de formulaire vous permet d'implémenter des cas très difficiles, par exemple POS:
Capture d'écran du formulaire Mais s'il s'agit, par exemple, du SaaS B2B ou même du B2C (par exemple, certains services bancaires par Internet), des questions commencent immédiatement à apparaître sur la façon de rendre le design plus ergonomique.
Au stade actuel, pour résoudre ce problème, une
bibliothèque javascript spéciale
a été développée, dont la tâche principale est de créer et de mettre à jour un objet js spécial contenant des données de formulaire. En conséquence, cet objet peut être utilisé comme état pour le composant React et ainsi créer toute conception et toute interactivité supplémentaire de la forme en cours de développement. Par exemple:
Exemple de formulaire React (sur codesandbox)Ou un exemple plus complexe - avec des listes déroulantes et en utilisant l'API REST (ou plutôt sans état) pour cela:
Exemple de formulaire React avec listes déroulantes (sur codesandbox)Certes, le problème avec cette approche est que les formulaires des exemples ci-dessus ne seront pas intégrés dans l'interface générale de la plateforme ou dans le flux général de contrôle des actions. Par conséquent, l'une des tâches les plus immédiates dans le développement de la plateforme est la traduction du mécanisme de conception de formulaire dans le schéma utilisé dans la conception du rapport (présentation imprimée):
- La plate-forme génère automatiquement une conception React basée sur la structure du formulaire comme dans l'exemple ci-dessus.
- Si nécessaire, le développeur peut l'enregistrer et le modifier à sa guise. Par conséquent, la plate-forme utilisera cette conception modifiée lors de l'ouverture du formulaire.
De plus, cette approche permettra de générer des formulaires React Native, et ainsi de créer des applications mobiles natives. Bien que ce problème (avec les applications mobiles natives), nous n'ayons pas encore travaillé très profondément.
Certes, nous notons que l'ancien mécanisme de conception sera également pris en charge, car, pour les mêmes applications métier, il remplit parfaitement sa fonction.
Événements de formulaire
Les événements de formulaire sont le deuxième mécanisme clé après les événements de domaine, qui est chargé de déterminer quand effectuer des actions.
La plate-forme a tout un ensemble de divers événements de formulaire qui surviennent à la suite de certaines actions de l'utilisateur, mais dans cet article, nous n'envisagerons qu'un seul, le plus souvent utilisé - l'événement CHANGE. Cet événement se produit lorsque l'utilisateur a lancé un appel de modification / action de propriété, par exemple, en appuyant sur une touche non système du clavier, en se trouvant dans le champ de la propriété en cours de modification ou en cliquant sur ce champ avec la souris.
En ce qui concerne les événements du domaine, pour les événements du formulaire, vous pouvez spécifier le traitement - l'action qui sera effectuée lorsque l'événement spécifié se produit. Notez que la plupart des événements du formulaire ont déjà un traitement par défaut qui implémente le comportement le plus attendu par l'utilisateur (par exemple, avec l'événement CHANGE susmentionné, demandez l'entrée de l'utilisateur et modifiez la propriété à la valeur entrée). Cependant, dans la pratique, des situations surviennent parfois lorsque, pour un événement de formulaire, il est nécessaire de spécifier un traitement spécifique, par exemple:
, – , ( , , , paste , ). . .
, , , , , , , , INPUT.
, , , , , , . Par exemple:
, , :
, INPUT – . (ASK):
(DIALOG) , , , , .
.
, . , , . , «» . , A B, A B, A A, B (A, B) B, A B ( «» ).
, , :
Par exemple:

, , , , .
LGPL – JasperReports.
, JasperReports , . , :
- «» ( , O1, O2, O3,… On, O2 – O1, O3 – O2 ..) ;
- , .
«» , SUBREPORT ( , -):

:
JasperReports (, lsFusion). , . , JasperSoft Studio.
, lsFusion- IDEA, Eclipse, ( Eclipse JasperReports ). IDEA , language injection, jrxml-, , , , , , . , , Eclipse GrammarKit autocomplete (, ), stub-, lazy chameleon- ( ), , . .
() :
- (XML, JSON) – , () -.
- (DBF, CSV, XLS) – - . parent, «» -.
, (- ), , , ( ). . , .
– XML, JSON. , , JSON ( XML ).
/ JSON , : JSON-, – , – . :
JSON/ , / :
, / :
JSON ::= { JSON , / } JSON , / ::= JSON 1 | JSON 1 | JSON 1 JSON 2 | JSON 2 | JSON 2 ... JSON M | JSON M | JSON M JSON ::= " " : JSON ::= " " : { JSON , / } JSON ::= " " : [ { JSON , / 1 }, { JSON , / 2 }, ... { JSON , / N }, ]
:
{ "s": [ { "date": "21.02.19", "sd": [ { "money": { "item": " 3", "quantity": 1, "price": 5, "index": 1 } } ], "stock": " 2", "customer": " 2" }, { "date": "15.03.19", "sd": [ { "money": { "item": " 1", "quantity": 1, "price": 5, "index": 1 } }, { "money": { "item": " 2", "quantity": 1, "price": 10, "index": 2 } }, { "money": { "item": " 3", "quantity": 1, "price": 15, "index": 3 } }, { "money": { "item": " 4", "quantity": 1, "price": 20, "index": 4 } }, { "money": { "item": "Milk", "quantity": 1, "price": 50, "index": 5 } } ], "stock": " 1", "customer": " 3" }, { "date": "04.03.19", "sd": [ { "money": { "item": " 1", "quantity": 2, "price": 4, "index": 1 } }, { "money": { "item": " 2", "quantity": 3, "price": 4, "index": 2 } }, { "money": { "item": " 1", "quantity": 2, "price": 5, "index": 3 } } ], "stock": " 1", "customer": " 2" }, { "date": "04.03.19", "sd": [ { "money": { "item": " 1", "quantity": 3, "price": 1, "index": 1 } }, { "money": { "item": " 2", "quantity": 2, "price": 1, "index": 2 } } ], "stock": " 1", "customer": " 2" }, { "date": "14.03.19", "sd": [ { "money": { "item": " 2", "quantity": 1, "price": 2, "index": 1 } } ], "stock": " 1", "customer": " 2" }, { "date": "17.04.19", "sd": [ { "money": { "item": " 2", "quantity": 5, "price": 6, "index": 1 } }, { "money": { "item": " 1", "quantity": 2, "price": 6, "index": 2 } } ], "stock": " 1", "customer": " 1" }, { "date": "21.02.19", "sd": [ { "money": { "item": " 3", "quantity": 1, "price": 22, "index": 1 } } ], "stock": " 2", "customer": " 1" }, { "date": "21.02.19", "sd": [ { "money": { "item": " 3", "quantity": 1, "price": 22, "index": 1 } } ], "stock": " 2", "customer": " 1" }, { "date": "20.02.19", "sd": [ { "money": { "item": " 3", "quantity": 1, "price": 22, "index": 1 } } ], "stock": " 2", "customer": " 1" } ] }
, JSON JSON-. , , IDE JSON , – JSON. , ( , , JSON- ), . / JSON .
, :
, , , ( ). , , , / :
, SELECT SQL. , , , ( , ).
, , , – .
, , , :
– ( ) . .
(SHOW, DIALOG)
:
- (WAIT) – , , , , .
- (NOWAIT) – .
.
, :
- (FLOAT) – .
- (DOCKED) – System.forms.
, – .
, , (DIALOG). (, , ), , , .
, , (INPUT), ( ), , , ( ), , , ( ).
(PRINT)
( ) , JasperReports : DOC, DOCX, XLS, XLSX, PDF, HTML, RTF , JasperReports. , , , , ( , ).
, - (PREVIEW), , / . , , .
(EXPORT, IMPORT)
, , , : XML, JSON, DBF, CSV, XLS, XLSX. .
, , , – . () , () , .
– , , « », :
- .
- ( , , , , , TRUE f(a) = b – f(a) b)
TRUE ( , , 0 , .., , , ).
Navigateur
, , . , , , . . ( ), .
- , ( ). , , ( ). .
. , — .
– , . , , . , , .

.

100x100 . , , . , «» . , ( ). , . , .
. , - , , .
:
- , – , , .
- – forms, log, status, root, toolbar, tree, (, root, , )
, – , , , , , ERP-. , , « », : ? Vraiment? ? , -, lsFusion language-based ( SQL ABAP), library-based ( Java 1C) / . , , – domain-specific , . -, , , , . : , , , . , , , ( ).
. – , :
, :
- . «» : , , / . , , , , , , .
- . control flow . , – .
- SQL ( ORM). , , , .
Conclusion
, , (, , , , tutorial, , , ). , , ( ) «», , lsFusion.
, , – . , . , , « . .», , ( - ).
. : « ». , . , , lsFusion SQL-. , , , – , - , . , SQL- (
). , . , , ( , ), , , . «?», « ...?» «?».
UPD:
.