Have you ever asked yourself how to mass-create a set of related records? Welcome to the presentation of the Many-to-Many editor for mass creation of related records in Evolutivo Framework.
The application doesn't manage many-to-many relations very well. When you have one, we recommend creating a "bridge" module that relates records from each of the two modules. This is very easy using native relation fields and also a very helpful way of establishing the relation because, usually, we have information that needs to be saved in the relation itself, so the module is perfect. For example, the Product Component module has two related fields to the product module which represent the relation between the two products and it also has fields like units, validity, and type of relation. The same happens in campaigns with contacts, where we have many contacts inside a campaign and a campaign has many contacts. On the relation we must hold the activities done in each campaign for each client and their status.
So, the solution is perfect for what we need, and Evolutivo has all the tools you need to represent the relationship. The issue with this approach is that it is not user-friendly. Establishing the relation between records is a tedious task that requires many clicks and moving around, so we created an extension to help make the process easier: the Many-to-Many editor.
Survey - Questions relation
Another example of a Many-to-Many relation in the application is between a survey and survey questions. A survey has many questions and a question can be part of many surveys. The relation is held in the Survey Path module which represents the flow of questions and some other additional information for each question in that particular survey.
Let's see how we can configure the Many-to-Many editor to help us manage this relation.
Accessing the Editor
There are two ways of showing the extension/widget. One as a block, the normal way of showing a widget and the other as a "stand-alone" functionality more oriented to be included in a menu option or a related tab inside a module.
For the block widget, we use the business action:
block://m2meditorWidget:modules/Widgets/M2MEditor/M2MEditor.php:record=$RECORD$&mapname=mapname
For the stand-alone version, we type into the browser the URL:
index.php?module=Widgets&action=WidgetsAjax&actionname=m2mactions&method=getEditorLayout&mapname=SurveyPathM2MEditor&record=0&standalone=1
That looks something like this:
Configuration Maps
Map with all surveys and all questions, for complete relation editing in full screen or related tab.
<map>
<module>cbSurveyPath</module>
<leftmodule>cbSurvey</leftmodule>
<leftfield>cbsurveyname</leftfield>
<rightmodule>cbSurveyQuestion</rightmodule>
<gridmap>MassGridSurveyPath</gridmap>
</map>
Map with filtered surveys and all questions, for inline survey editing.
<map>
<module>cbSurveyPath</module>
<leftmodule>cbSurvey</leftmodule>
<leftfield>cbsurveyname</leftfield>
<leftfilter>[{"fieldname":"id","operation":"is","value":"$RECORD$","valuetype":"rawtext","joincondition":"and","groupid":"0"}]</leftfilter>
<rightmodule>cbSurveyQuestion</rightmodule>
<gridmap>MassGridSurveyPath</gridmap>
</map>
Map with filtered surveys and questions. Not very useful, but an example
<map>
<module>cbSurveyPath</module>
<leftmodule>cbSurvey</leftmodule>
<leftfield>cbsurveyname</leftfield>
<leftfilter>[{"fieldname":"id","operation":"is","value":"$RECORD$","valuetype":"rawtext","joincondition":"and","groupid":"0"}]</leftfilter>
<rightmodule>cbSurveyQuestion</rightmodule>
<rightfilter>[{"fieldname":"$(cbsurvey : (cbSurvey) id) ","operation":"is","value":"$RECORD$","valuetype":"rawtext","joincondition":"and","groupid":"0"}]</rightfilter>
<gridmap>MassGridSurveyPath</gridmap>
</map>
For the three examples, the Grid map being used is:
<map>
<module>cbSurveyPath</module>
<parentmodule>cbSurvey</parentmodule>
<relatedfield>surveyid</relatedfield>
<enablePaste>1</enablePaste>
<showFullText>1</showFullText>
<props>
<height>20px</height>
<widths>
<width>
<value>100px</value>
<field>description</field>
</width>
</widths>
<whitespace>unset</whitespace>
<dvreload>0</dvreload>
<forcesave>1</forcesave>
<forceheader>1</forceheader>
</props>
<fields>
<field>
<name>surveypathname</name>
</field>
<field>
<name>surveyid</name>
<autocomplete>1</autocomplete>
</field>
<field>
<name>questionid</name>
<autocomplete>1</autocomplete>
</field>
<field>
<name>sequence</name>
</field>
<field>
<name>yes_points</name>
</field>
<field>
<name>no_points</name>
</field>
<field>
<name>question</name>
</field>
<field>
<name>pathyes</name>
<autocomplete>1</autocomplete>
</field>
<field>
<name>pathno</name>
<autocomplete>1</autocomplete>
</field>
</fields>
</map>
Functionality
The idea is that the extension presents two lists of records, one from each module in the relation. These lists may be filtered based on the conditions in the map but the extension will also present a list of the filters active in the module so that we can quickly filter the records. Then we select records from both lists and either create (add) or delete the relation. These buttons will effectively mass create or mass delete records in the "bridge" module. The records that exist in the module are presented in the grid below where we can inline edit the values.
Enjoy!