昨年12月、プロトタイプ作成プラットフォームを使用したハッカソンに参加しました。 割り当てられた2日間は、オンラインキャッシャーとそのクラウドエコシステムに対処するためにゼロから始め、サービスのプロトタイプを作成しました-マーケットプレイス。 予想どおり、私たちは80%の時間をなじみのないデバイスと統合し、残りの20%は多くの楽しみを持ち、残りを行いました。
正直なところ、この曇りの世界への参入のしやすさ、その規模(最初はほぼ16万人のユーザー)、機能、そして...穴に驚きました。 その結果、すべてが私たちのためにうまくいき、組織会社は、彼らの声明によると、市場のプロジェクトを開始しようとしています。
この記事では、2〜3時間でWebサービスがどのように統合され、クラウドベースのキャッシュデスクと統合され、フォーカスグループの顧客への実行に適しているかを示します。 プロジェクト自体は、githubおよびオンラインバージョンのソースの形式でレビューおよび複製することができます。

ハッカソンに来たのは、営業時間がないだけでなく、一般的に漠然とそれが何であるかを想像していました。 知っていて、ここで私たちに署名した唯一の人は、開発に関与していません。 そのため、すべてを非常に迅速に行う必要がありました-TKはプラットフォームですぐに書き込み、その作業をデバッグしました。
この場合のマーケットプレイスは、必要に応じて、つまり商品が終了したときに、売り手(オンラインキャッシュデスクの所有者)に商品を配送するためのシステムです。
ハッカソンの目標は、クラウドサービスストアで利用できるアプリケーションを作成し、クライアントに役立ついくつかの機能を実行することでした。 アプリケーションの主なタスクは、ユーザーをサービスに登録し、マーケットプレイスの個人アカウントにすばやくアクセスできるようにすることです。 モバイルアプリケーションでは、MarketplaceもWebビューの形式で機能しますが、もちろん、さまざまなモバイルプラットフォーム用のサービスのデバッグは開始しませんでした。
統合部分は非常に単純に見えます。登録されたクライアントは、サービスがクラウドに接続するトークンを受け取り、JSON形式で店舗、製品、キャッシュデスク、従業員に関する情報を要求します。 次に、データをデータベースと同期し、プラットフォームのコアがすでに行っている外の世界で作業する準備ができています。
プラットフォームタイプエディターでの彼のデータのスキームは、次の図のようになります。これがTKの始まりです。
タイプエディタでは、オブジェクトの階層が単純なルールに従って表示されることを思い出してください。オブジェクトのすべての詳細は親の右側に配置され、広がっています。
ただし、データスキームはシステムのユーザーから隠されており、変更できるのは管理者だけです。
クラウドサービスストアにアプリケーションをインストールすると、クライアントは自分の個人アカウントにアクセスし、そこで自分のすべての店舗、製品、ユーザー、および端末に関する情報を確認できます。 これが、ハッカソンの2日目の朝にデザイナーが設計したCloud Syncワークステーションの外観です。
クラウドデータ構造を繰り返し、[同期]メニューでサービスのデータが更新されます。店舗、商品、その他のオブジェクトが作成され、価格が更新されます。 上の図に示されている同期ページjavascript'omは、クラウドおよびサービスベースからJSONで受信したすべてのオブジェクトを描画します。
同期ページのコード自体は、興味がある場合はgithubで入手できます。 むき出しのjavascriptで作成されており、7キロバイトのコードがあり、確かに削減できますが、ハッカソンにとっては重要ではありませんでした。
このフォームのインターフェイスは、データを収集して同期フォームとメニューを作成する3つのサービスレポートに基づいて構築されています。 ユーザーに直接表示されるいくつかのレポートもあり、それらはすべてインタラクティブです。
レポートは、さまざまなデータスキーマテーブルのフィールドのセットです。 プラットフォームのカーネルはこれらすべてのフィールドを選択し、必要なテーブルをSQLに似たクエリに個別にリンクし、フィルター、グループ化、並べ替え、その他のSQL機能を適用します。 テーブル自体のリンクは「舞台裏」のままであり、ユーザーは必要なフィールドとクエリパラメーターのセットのみを設定します。
プラットフォームの基本インターフェースのレポートのリストは次のとおりです。
ユーザーが選択したレポートフィールドは、レポート列のサブテーブルにあり、記事の下の非表示テキストで詳細に説明されています。
プレフィックスintでサービスレポートを呼び出しました。 ユーザーレポートの名前はロシア語であり、ユーザーアクセスは、ロールで指定されたレポート名のマスクによって制限されます(興味がある場合は、すべての詳細も非表示テキストで説明されます)。
intMyShopレポートとintMySuppレポートは、それぞれユーザーに関連付けられたストアコードとサプライヤコードを返します。 たとえば、内部のintMyShopは次のようになります。
このレポートのリクエストを実行するとき、プラットフォームエンジンは、レポートを起動したユーザーのID([USER_ID]および[USER]-IDおよびユーザー名、ランタイムパラメーター)と等しいユーザーへのすべてのリンクをデータベースから選択します。 対応するストアも選択されます。 ここで使用されるabn_ID関数は、識別子が参照として使用されるため、名前ではなくオブジェクトIDを返します。 さらに、数値IDの比較は、シンボリックオブジェクト名よりも高速です。
レポートは、注文を作成するときにフォームフィールドをオートコンプリートするために使用できる値を返します。 タイプエディタで、[ショップ]フィールドのデフォルト値としてこのレポートを指定します。
したがって、注文を作成すると、現在の日付、ステータスコード「新規」(737)、およびユーザーが接続されているストアコードがすぐにそれに置き換えられます。
サービスディクショナリでは、ステータスディレクトリを確認できます。このディレクトリでは、注文に挿入されてそのステータスを示すコード(システムID)を見つけることができます。

intProdsレポートは、ユーザーがリンクされているストアの製品に関する情報を収集します。 次に、テンプレートで使用される名前が付けられたレポート列を示します。
レポートによって返されるレコードセットは次のようになります。
このレポートは、次のコードフラグメントのjavascript配列に入力するために、同期の形式で使用されます。
<script> var s=new Array(), p=new Array(); <!-- Begin:intShops -->s['{uid}'] = {i:{id}, n:'{n}'}; <!-- End:intShops --> <!-- Begin:intProds -->p['{uid}'] = {i:{id}, s:'{sid}', n:'{tname}', stock:'0{stock}',min:'0{min}',ask:'0{ask}',costPrice:'{price}'}; <!-- End:intProds --> </script>
構造<!-Begin:intProds-> ... <!-End:intProds-> intProdsレポートを呼び出し、その結果の列を使用して挿入ポイント{uid}、{id}、{sid}を埋めるようにパーサーに指示します。このデザイン内のその他。 挿入ポイント内のコードスニペットは、レポートによって返されるレコードの数だけ繰り返されます。
このコードを処理すると、パーサーはデータを埋めて、次のようなjavascript実行可能ファイルを取得します。
<script> var s=new Array(), p=new Array(); s['20171202-0534-4070-8033-06A9159C64BE'] = {i:529, n:' '}; s['20171204-C914-409F-8028-405CA94D6FE4'] = {i:1178, n:' '}; p['70b263e5-252f-4a77-949e-22f4ed7dedab'] = {i:547, s:'20171202-0534-4070-8033-06A9159C64BE', n:' 100/50 .', stock:'05',min:'07',ask:'020',costPrice:'48'}; p['2e3a61d4-f465-4ec9-ad86-a84e53b4402a'] = {i:549, s:'20171202-0534-4070-8033-06A9159C64BE', n:' 1950 3-5 4', stock:'050',min:'0103',ask:'0100',costPrice:'42'}; p['581c8f9b-6a19-42bc-9a36-169e792165bc'] = {i:551, s:'20171202-0534-4070-8033-06A9159C64BE', n:' ', stock:'050',min:'040',ask:'01000',costPrice:'8'}; p['11e59bcf-ea73-4fbd-adb2-955fd3452749'] = {i:553, s:'20171202-0534-4070-8033-06A9159C64BE', n:' ', stock:'015',min:'040',ask:'00',costPrice:'125'}; p['7a631129-05c0-4cf3-a9d7-dfbd56d31e68'] = {i:555, s:'20171202-0534-4070-8033-06A9159C64BE', n:'Draje', stock:'050',min:'0100',ask:'01000',costPrice:'44'}; </script>
さらに、これらの配列は、クラウドで同期テーブルをレンダリングするために使用されます。
サービスには、販売者、ユーザー、サプライヤー、物流会社の3つのユーザーロールがあります。 これは、ユーザーが辞書でどのように見えるかです:
ユーザーの役割には、ユーザーに表示されるメニュー(レポートへのリンク形式のアイテムのセット)が与えられます。
各ロールには、要約レポートに表示できるアクセスのセットもあります。
ロールには、オブジェクトのセット、可視性を制限するためのマスク、およびアクセスレベル(禁止、読み取り、書き込み)が指定されます。
このレポートは、ユーザーロールにレポートへの読み取りアクセス権があることを示しています。さらに、アクセスはレポート名のマスクによって制限されています。 したがって、誰もが自分のレポートのみを見ることができます。
また、ユーザーロールを持つユーザーを作成できるRegサービスユーザーもいます(そして、彼女のみ-ロールディレクトリへのアクセスはマスクによって制限されます)。 マスク「!%」は「空の」ユーザー名を設定するため、ユーザーを表示できません。 このユーザーは、サイトの登録フォームで使用されます。このフォームは、captchaをチェックしてフィールドを検証した後、ユーザー作成フォームの送信をシミュレートするサービスにPOSTリクエストを送信することにより、新しいユーザーを記録できます。
アクセスレポートのソースは非常に簡単です。
配達は、商品の供給者と配達の主催者の両方に関連して、競争的に行われます。 他の人の作業や不必要な作業を誰かに強制しないように、作業のスキームが考えられました。すべての情報はすでにクラウドにあり、市場参加者が利用できます。
- 売り手は一度最小残高を示し、それに達すると、選択するオファーを受け取ります。
- サプライヤは、需要があるすべての商品を確認し、その価格と在庫量を示します。
- 物流会社は、考えられるすべての配送ルートを確認し、注文を配送します。
売主
プロジェクトの目的のために、売り手は商品にプロパティを追加できます。最小残高と最小注文は、サプライヤの注文をすばやく作成するのに役立ちます。
必要な値を指定すると、それらは製品を参照して保存されます。
ボタンをクリックすると、JavaScriptが呼び出され、GETリクエストと非同期にデータが保存されます
// Save the parameters for this Product function saveDiv(d){ save = new XMLHttpRequest(); save.open('GET' ,'index.php?db={_global_.z}&a=edit_obj&next_act=nul&do=save_val&id='+p[d].i +'&t216='+document.getElementById('s'+d).value +'&t217='+document.getElementById('m'+d).value +'&t716='+document.getElementById('a'+d).value ,true); save.send(); save.onload=function(e) { save.abort(); // Light the "Saved Ok" icon document.getElementById('b'+d).style.display='inline'; } }
このリクエストは、フォームの送信をエミュレートします。まるでユーザーが基本インターフェースのストアでこのアイテムを見つけ、編集して保存をクリックしたかのように:
プラットフォームパーサーによって自動的に生成されたフォームのhtmlコードから必要なすべてのフィールドを引き出し、ユーザーが理解できるコンパクトなフォームにそれらを描画しました。
<FORM method="post" action="index.php?db=evo&a=edit_obj" ENCTYPE="multipart/form-data" ONSUBMIT="savebtn.disabled=true; return true;"> <TABLE > <TR> <TD>553 <B> ():</B> <input type="hidden" name="do" value="save_val"> <input type="hidden" name="typ" value="211"> <input type="hidden" name="id" value="553"> </TD> </TR> <TR> <TD><input type="text" name="t211" value="11e59bcf-ea73-4fbd-adb2-955fd3452749" autofocus class="form-control"> <div style="height:5px; "></div> </TD> </TR> <TR> <TD> <div style="height:3px; "></div> <TABLE class="table table-condensed"> <TR> <TD style=" max-width:400px; " ALIGN="right"> : </TD> <TD> <nobr><select name="t213" class="form-control"> <option> </option> <option value="1139">""-</option> <option value="532">Draje</option> <option value="536"> 100/50 .</option> <option value="535" SELECTED> </option> <option value="980"> / SH619/</option> <option value="1170"> 3 </option> <option value="533"> 1950 3-5 4</option> <option value="539"> / . " " 0,25.</option> <option value="534"> </option> <option value="537"> . BEATY YOUNG 15</option> <option value="538"> 1,2 </option> </select> </nobr> </TD> </TR> <TR> <TD style=" max-width:400px; " ALIGN="right"> : </TD> <TD> <input class="form-control" type="text" name="t216" size="10" value="15" > </TD> </TR> <TR> <TD style=" max-width:400px; " ALIGN="right"> : </TD> <TD> <input class="form-control" type="text" name="t217" size="10" value="40" > </TD> </TR> <TR> <TD style=" max-width:400px; " ALIGN="right"> : </TD> <TD> <input class="form-control" type="text" name="t716" size="10" value="0" > </TD> </TR> <TR> <TD style=" max-width:400px; " ALIGN="right"> : </TD> <TD> <input class="form-control" type="text" name="t1025" size="10" value="125" > </TD> </TR> </TABLE> </TD> </TR> <TR> <TD colspan="2"> <input type="submit" name="savebtn" class="btn btn-primary" value=""> <input type="submit" name="copybtn" class="btn btn-default" value=""> </TD> </TR> </TABLE> </FORM>
*フォームコードから削除された化粧品およびその他のマイナー情報の一部
サービスは、クラウドサービスのバーコードで識別される製品名を使用します。
クラウドで非常に成功したアプローチが適用されていることは注目に値します-すべての人に人気のある製品名の単一ディレクトリを使用して-これにより、名前の競合が最小限に抑えられます。 最も使用されるオプションは、ユーザーに「課される」ものです。
命名法コードを使用するいくつかの機能により、これらのコードは商品の人間の名前と一緒に保存されますが、1つの商品は異なるコードで記述できます。 そのため、製品ディレクトリは基本的なインターフェイスで表示されます。
製品は独立したディレクトリに存在しますが、名前が使用されているアイテムは、ユーザーが保存したパラメーターとともに特定のストアに関連付けられています。
仕入先
サプライヤは、すべてのユーザーがクラウドで使用している製品を確認し、名前とバーコードでフィルタリングできます。
製品には、検索対象のバーコードが複数ある場合がありますが、表にはそのうちの1つだけがリストされています。
%7777で終わるバーコードを探しています(たとえば、Red Bull製品にはいくつかの異なるコードがあります)。
レポートでは、製品ごとに1つのバーコードのみが選択されます。最後のバーコードは、アルファベット順に並べ替えた場合です。 バーコードによるフィルターを適用すると、適切なコードを持つ製品のみが表示されます。
ここでは、「ボタン」htmlコードも収集します。レポートに描画され、「Offer」オブジェクト(タイプ591)を作成するアクションを開始し、必要な「Product」(タイプ593)を入力するFormulaフィールドを参照してください。
このハッカソンは、プラットフォームのコアにCNCを実装する前に実行されたため、相対アドレスは次のようになりました
index.php?db=evo&id=591&a=edit_obj&do=new_obj&t593=prod
同じアドレスは次のようになります。
evo/new_obj/591?t593=prod
人を見るのがもっと楽しいです
さらに、サプライヤは、他のサプライヤ間の競争に参加するために、自分が示した価格で一定量の商品を供給するための提案を作成できます。 提案編集フォームはプラットフォームの基本的なインターフェースであり、ここでは余分なものは必要ありません。
オファーを作成日として保存します。
オファーには、システムID = 1238、2017年12月3日の値、および詳細があり、その一部は自動的に入力されます。
サプライヤのすべてのオファーのリスト([マイオファー]メニュー)を使用すると、オファーを選択および編集したり、無関係なオファーを削除したりできます。 これを行うには、レポートをインタラクティブにし、レポートからオブジェクトにすばやく移動できるようにします。この場合、「日付」値をクリックします。
6列目はレポートデータをフィルターします。現在のユーザーが属するサプライヤーによって生成されたオファーのみがレポートデータに含まれます。 データベースへのクエリは、おおよそ次のように機能します。
- コンテキストパラメータ[USER_ID]の値-許可されたユーザーの識別子-は、システムユーザーの識別子(ID)と比較されます。
- ユーザーIDで見つかったものにはサプライヤへのリンクがあり、それによりデータベースで後者が見つかります
- 次に、現在のユーザーがレポートに表示するこのサプライヤーのすべてのオファーが選択されます
クエリは、インデックス統計に従って、最初に最小のオブジェクトを選択するため、指定された順序で実行される可能性があります。
なぜそれがそのように機能するのですか?
データモデルを作成する場合、プラットフォームではすべてのデータベースでインデックスが作成されるため、インデックスフィールドを指定する必要はありません(許可されません)。
クエリオプティマイザーはプログラマーの汚い仕事をします-管理者が構造を分析し、必要なすべてのインデックスを手動で作成したかのように、データテーブルの最適でないスキャンを排除します。 これは通常、必要に応じて処理される日常的なタスクですが、これに真剣に対処しないと、データベースは非生産的にサーバーリソースを消費します。 時には非常に非生産的です。
売り手は、自分に適したサプライヤのすべてのオファーを見ることができます。商品、サプライヤの価格、利用可能な商品の数量、作成済みの注文に関する情報、最新の購入価格です。
データベースへのこのクエリは、関連性によってソートされたサプライヤのオファーを表示します。8番目の列では、最小残高のフィルファクターが昇順でソートされます。 このレポートは、10列目の商品注文用のハイパーリンクも生成します。 また、レポートでは、このプロポーザルの注文済みの商品の量と最新の購入価格を確認できます。
ここでは、2回のクリックですぐに注文できます。 クリックには番号1と2が付けられ、すべてのフォームフィールドにはすでに自動的に入力されています。
配送および配達フィールド(これらは時間のある日付です)は、物流会社が記入するため編集できません。
次に、注文のステータスと配達予定時間を監視します。
サプライヤは、関連する注文と出荷予定日も確認し、出荷の準備と購入の計画を立てることができます。
物流会社
このプロセスの3番目の参加者は、物流会社です。 彼の主な職場は注文のリストです。
レポートは非常にシンプルです。4つの異なるテーブルから列が選択され、フィルターが適用されます。注文ステータスは「Closed」であってはなりません。
彼はすべての注文を確認し、それらを処理して配信できます。 レポートはインタラクティブであるため、レポートから直接注文を処理することができます。
ロジスティクスは非常に複雑になる可能性がありますが、これまでのところ、注文のステータスと商品の発送と配送の日付の変更のみが確認されています。
この段階のロジスティクス担当者には、会社またはユーザーによるフィルターはありません。実行には、2つまたは3つのディスパッチャを持つ唯一の会社が使用されます。
完了した注文は販売者の注文のリストから自動的に削除されますが、注文ステータス:%(すべてのステータス)によるフィルターを介して注文履歴で利用できます。
これにより、パイロット顧客向けのサービスの全サイクルが完了します。
ご覧のとおり、このプロジェクト(スタートアップ!)を作成するためのプロトタイプ作成プラットフォームとテキストエディター以外は必要ありませんでした。 ORMを使用して多くの時間を節約しました。これは、CRM、コンストラクター、またはお気に入りの開発プラットフォームで最初から同じことをしようとしているかどうかを確認できます。 すべての開発手順は、非表示のテキストで上に配置され、実際、目の前で実行されます。 これらはすべて非常にアクセスしやすく、データスキーマとクエリを操作するのに特別な知識を必要としないと思われます。
スタートアップの開発に伴う機能の拡張(データモデルの複雑さ、詳細、レポート、分析セクション、既存のロール、および対応する制限の追加)は、このプロトタイプをスケッチしたのと同じくらい迅速にタイプエディターとレポートで行われます。