Sync Filter examples with child entities

From Resco's Wiki
Jump to navigation Jump to search
Sync Filter examples

Resco platform respects some well-known child-parent relations out of the box (current as of release v13.1):

Child Parent
invoicedetail invoice
quotedetail quote
salesorderdetail salesorder
opportunityproduct opportunity
uom uomschedule
productpricelevel pricelevel
discount discounttype
contractdetail contract
salesliteratureitem salesliterature
queueitem queue
activitymimeattachment email
dealline deal
productsubstitute product
productassociation product
fs_workorderproduct fs_workorder
resco_question resco_questionnaire
resco_questiongroup resco_questionnaire
sf_opportunitylineitem sf_opportunity
sf_quotelineitem sf_quote
sf_orderitem sf_order
sf_workorderlineitem sf_workorder
sf_pricebookentry sf_pricebook2

Valid child-parent relation requires that the child entity properties encompass also the lookup to the parent. Even for the hardcoded relations, if the customization does not contain this lookup, child-parent relation is ignored.

In addition to the built-in child-parent relationships, users can define custom child-parent relations. To do so:

  1. Edit an app project in Woodford.
  2. Select the child entity.
  3. Select lookup property that should point to the parent.
  4. On the Properties pane, enable Mark as Parent Pointer.
  5. Make sure that the lookup targets allow a single entity - our parent entity.
    This easily overlooked decision has important consequences: If a child entity allows multiple targets, then SyncEngine does not automatically adjust child sync filters as they would be potentially too complex. Instead, a user-defined child filter is taken. And if the user does not define any sync filter at all, SyncEngine will download all child records - even those whose parent record was not downloaded. (Potential problem.) Among well-known child-parent relations, this problem can happen only for activitymimeattachment entity, which allows 2 parents - email and template (email template). If you allow the email template to contain attachments, SyncEngine will not adjust your activitymimeattachment sync filter.

The two entities related as child-parent are not independent. There is always one parent record and a set of N child records. (Example: quote with its quotedetails.) It is logical to expect that these (N+1) records are treated as one unit in many respects:

  • When we delete a quote, we expect that its quotedetails get deleted as well.
  • When we download a quote, we expect that its quotedetails get downloaded as well. On the other hand, we do not want quotedetail records without its parent record.

SyncEngine implements the second requirement by adjusting user-defined child sync filters. (Parent sync filter is unchanged.) The steps:

  1. Eventual user-defined links in child sync filter are removed.
  2. An inner link to parent entity is added together with its filter as defined in parent sync filter.
  3. Eventual user-defined filter in child sync filter is preserved.

Woodford user interface does not allow you to set up sync filters for child entities listed above among well-known child-parent relationships. However, you still can define sync filters by direct manipulation of SyncFilter.xml file.

Quote and quotedetails

If we download 24 months old quotes (sync filter for parent entity), but do not specify any sync filter for quotedetails...

<fetch version="1.0">
	<entity name="quote">
		<filter type="and">
			<condition attribute="modifiedon" operator="last-x-months" value="24"/>
		</filter>
	</entity>
</fetch>

... then the SyncEngine will automatically generate this sync filter that downloads quotedetail records just for above quotes:

<fetch version="1.0" aggregate="false">
	<entity name="quotedetail">
		<link-entity name="quote" from="quoteid" to="quoteid">
			<filter type="and">
				<condition attribute="modifiedon" operator="last-x-months" value="24"/>
			</filter>
		</link-entity>
	</entity>
</fetch>

The next example includes the same entities, but the parent filter is more complex.

<fetch version="1.0">
	<entity name="quote">
		<filter type="and">
			<condition value="120" operator="last-x-days" attribute="createdon"/>
		</filter>
		<link-entity name="account" link-type="inner" to="ext_clienteareadeventa" from="accountid" alias="L0">
			<filter type="and">
				<condition value="0" operator="eq" attribute="statecode"/>
			</filter>
		</link-entity>
	</entity>
</fetch>

Again, the child filter is derived from the parent filter.

<fetch version="1.0" aggregate="false">
	<entity name="quotedetail">
		<link-entity name="quote" from="quoteid" to="quoteid">
			<filter type="and">
				<condition attribute="createdon" operator="last-x-days" value="120" />
			</filter>
			<link-entity name="account" from="accountid" to="ext_clienteareadeventa" link-type="inner" alias="L0">
				<filter type="and">
					<condition attribute="statecode" operator="eq" value="0" />
				</filter>
			</link-entity>
		</link-entity>
	</entity>
</fetch>

Example of incompatible filters

Let's see what happens if the user defined incompatible filters for child and parent entities: 1 month old emails, but 3 months old attachments with max size 1 MB.

<fetch version="1.0">
	<entity name="email">
		<filter type="and">
			<condition attribute="modifiedon" operator="last-x-months" value="1"/>
		</filter>
	</entity>
</fetch>
<fetch version="1.0">
	<entity name="activitymimeattachment">
		<filter type="and">
			<condition attribute="filesize" operator="lt" value="1048576"/>
		</filter>
		<link-entity name="email" from="activityid" to="objectid">
			<filter type="and">
				<condition attribute="modifiedon" operator="last-x-months" value="3"/>
			</filter>
		</link-entity>
	</entity>
</fetch>

SyncEngine will adapt the child filter (File size condition is preserved, inner link is replaced) so that the really used sync filter is:

<fetch version="1.0" aggregate="false">
	<entity name="activitymimeattachment">
		<filter type="and">
			<condition attribute="filesize" operator="lt" value="1048576" />
		</filter>
		<link-entity name="email" from="activityid" to="objectid">
			<filter type="and">
				<condition attribute="modifiedon" operator="last-x-months" value="1" />
			</filter>
		</link-entity>
	</entity>
</fetch>

Complex sync filter for activitymimeattachment

This example of a complex sync filter for the activitymimeattachment entity specifies attachments of recent emails in which the current user participated.

The fetch is copied from a real customer and includes a logical problem. As we explained above, the attachment's inner link will be overwritten by the simpler link derived from the email sync filter. Customer should move the complex attachment logic to the email sync filter.

<fetch version="1.0">
	<entity name="activitymimeattachment">
		<link-entity name="email" link-type="inner" to="objectid" from="activityid" alias="L0">
			<filter type="and">
				<condition value="60" attribute="modifiedon" operator="last-x-days" />
			</filter>
			<link-entity name="activityparty" link-type="inner" to="activityid" from="activityid" alias="L1">
				<filter type="and">
					<condition attribute="participationtypemask" operator="in">
						<value>1</value>
						<value>2</value>
						<value>3</value>
						<value>4</value>
						<value>8</value>
						<value>9</value>
					</condition>
					<condition attribute="partyid" operator="eq-userid" />
				</filter>
			</link-entity>
		</link-entity>
	</entity>
</fetch>>
<fetch version="1.0">
	<entity name="email">
		<filter type="and">
			<condition operator="last-x-days" attribute="modifiedon" value="60"/>
			<condition operator="ne" attribute="statecode" value="2"/>
		</filter>
	</entity>
</fetch>