@prefix sioc: <http://rdfs.org/sioc/ns#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix content: <http://purl.org/rss/1.0/modules/content/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<https://lhero.org/?post_type=lh-portfolio-doc&#038;p=147701>
  a sioc:Post ;
  dc:title "Data model" ;
  dcterms:identifier 147701 ;
  dc:modified "2026-09-18T17:08:52Z"^^xsd:dateTime ;
  dc:created "2026-09-17T23:23:54Z"^^xsd:dateTime ;
  sioc:link <https://lhero.org/portfolio/lh-crm/data-model/> ;
  sioc:has_creator <https://lhero.org/author/1/#account> ;
  sioc:has_container <https://lhero.org/#posts> ;
  content:encoded """<ul class="lh_portfolio-meta"><li><strong>Part of:</strong> <a href="https://lhero.org/portfolio/lh-crm/">LH Customer Relationship Management</a></li></ul>
<p class="wp-block-paragraph">LH CRM creates no custom database tables. All data lives in each site&#8217;s standard <code>posts</code>, <code>postmeta</code>, <code>terms</code> and <code>term_relationships</code> tables, plus BuddyPress&#8217;s own tables. Uninstalling the plugin deletes nothing: <code>uninstall.php</code> only contains a commented-out purge.</p>



<h2 class="wp-block-heading">Post types</h2>



<figure class="wp-block-table"><table><thead><tr><th>Post type</th><th>Purpose</th><th>Visibility</th></tr></thead><tbody><tr><td><code>lh-crm-form</code></td><td>Contact form configuration</td><td>Not public; admin UI and REST</td></tr><tr><td><code>lh_crm_enquiry_post</code></td><td>One enquiry per submission</td><td>Registered public with rewrite slug <code>enquiry</code> and archive <code>enquiries</code>, but its statuses are only public to users with <code>edit_others_posts</code>. Excluded from sitemaps and several LH SEO and listing plugins.</td></tr><tr><td><code>lh_frpt-post_type</code></td><td>Form Response templates (bundled library)</td><td>Public; REST</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">An enquiry post stores the enquirer as <code>post_author</code>, its form as <code>post_parent</code>, the message as <code>post_content</code> (tag-stripped copy in <code>post_excerpt</code>), and an HTML-stripped &#8220;X enquired via Page on Site&#8221; string as <code>post_title</code>. Its <code>post_name</code> is set to its own ID.</p>



<h2 class="wp-block-heading">Enquiry statuses</h2>



<figure class="wp-block-table"><table><thead><tr><th>Status</th><th>Label</th></tr></thead><tbody><tr><td><code>lh_crm-new_enq</code></td><td>New (every enquiry starts here)</td></tr><tr><td><code>lh_crm-prog_enq</code></td><td>In Progress</td></tr><tr><td><code>lh_crm-pending_enq</code></td><td>Pending</td></tr><tr><td><code>lh_crm-res_enq</code></td><td>Resolved</td></tr><tr><td><code>lh_crm-clos_enq</code></td><td>Closed</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A New enquiry dated in the future is switched to core <code>future</code> status and returned to New by cron when its date arrives (see Cron jobs).</p>



<h2 class="wp-block-heading">Contact form meta</h2>



<figure class="wp-block-table"><table><thead><tr><th>Meta key</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>_lh_crm-fe_full_name-hide</code></td><td>string</td><td><code>1</code> hides the name field</td></tr><tr><td><code>_lh_crm-fe_message-hide</code></td><td>string</td><td><code>1</code> hides the message field</td></tr><tr><td><code>_lh_crm-form_submit_button</code></td><td>string</td><td>Submit button label</td></tr><tr><td><code>_lh_crm-field_group</code></td><td>integer</td><td>BuddyPress xProfile field group ID</td></tr><tr><td><code>_lh_crm-default_category</code></td><td>integer</td><td>Default <code>lh_crm-category</code> term ID</td></tr><tr><td><code>_lh_crm-recipient_id</code></td><td>integer</td><td>User who owns the form&#8217;s enquiries (required to publish)</td></tr><tr><td><code>_lh_crm-group_id</code></td><td>integer</td><td>BuddyPress group ID</td></tr><tr><td><code>_lh_crm-group_action</code></td><td>string</td><td><code>add_to_group</code>, <code>email_invite</code> or <code>silent_invite</code></td></tr><tr><td><code>_lh_crm-bp_notification_recipients</code></td><td>array</td><td>User IDs for BuddyPress notifications</td></tr><tr><td><code>_lh_crm-notification_id</code></td><td>integer</td><td><code>bp-email</code> post used as the auto-reply</td></tr><tr><td><code>_lh_crm-response_id</code></td><td>integer</td><td>Form Response post shown after submission</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Enquiry meta</h2>



<figure class="wp-block-table"><table><thead><tr><th>Meta key</th><th>Description</th></tr></thead><tbody><tr><td><code>_lh_crm-reference</code></td><td>Random reference generated in the browser; a resubmission with the same reference returns the existing enquiry</td></tr><tr><td><code>_lh_crm-page_id</code></td><td>Page the form was submitted from</td></tr><tr><td><code>_lh_crm-referrer</code></td><td>Browser referrer at submission time</td></tr><tr><td><code>_lh_crm-enquiry_notes</code></td><td>Staff notes (exposed in REST, edit context only)</td></tr><tr><td><code>_lh_crm-status-{status}-at</code></td><td>UTC time of the most recent move into each status. <code>{status}</code> is the full status name, so the real keys look like <code>_lh_crm-status-lh_crm-new_enq-at</code>.</td></tr><tr><td><code>_lh_post_user_agent-user_agent</code></td><td>Browser user agent at submission (bundled library, max 1000 characters)</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Taxonomies</h2>



<ul class="wp-block-list"><li><code>lh_crm-category</code>: hierarchical enquiry category, one term per enquiry in the admin UI. It is registered with <code>show_ui</code> off, so there is no wp-admin screen for managing its terms; they are available through REST.</li><li><code>lh_post_ip_tax-ip</code> (bundled library): the submitter&#8217;s IP address as a term (dots become hyphens in the slug). Terms can only be managed by users with <code>update_plugins</code>.</li></ul>



<h2 class="wp-block-heading">Users and BuddyPress data</h2>



<ul class="wp-block-list"><li>Every enquirer is a WordPress user, matched or created by email. Submitted profile fields are saved as xProfile data on that user.</li><li>Group actions create normal BuddyPress memberships or invitations.</li><li>BuddyPress notifications use component <code>blogs</code>, action <code>lh_crm-bp_notification-action</code>, with the site ID as <code>item_id</code> and the enquiry ID as <code>secondary_item_id</code>.</li><li>LH CRM does not create BuddyPress activity items. The <code>lh_crm-enquiry</code> activity type is legacy, and no items of that type remain on the network. Until 1.5.15 an activity class still filtered every BuddyPress activity query for it; that class was removed. <code>LH_Crm_plugin::return_activity_type()</code> still returns the type name.</li><li>The initial cron run grants an <code>edit_enquiries</code> capability to every role with <code>edit_others_pages</code>. Nothing currently checks that capability.</li></ul>



<h2 class="wp-block-heading">Relationship triples (removed in 1.5.8)</h2>



<p class="wp-block-paragraph">Until 1.5.8, each enquiry was also written to the LH Relationships triple store as <code>as:actor</code> (the enquirer), <code>as:target</code> (the form), <code>as:to</code> (the form&#8217;s recipient) and <code>schema:about</code> (the page it was sent from), all with source <code>lh_crm</code>. Nothing read them, and an hourly resync kept re-inserting the same triples, so the integration was removed. Rows written before 1.5.8 remain in the triple store until they are cleaned up separately.</p>
"""^^rdf:XMLLiteral ;
  sioc:content """Part of: LH Customer Relationship Management
LH CRM creates no custom database tables. All data lives in each site&#8217;s standard posts, postmeta, terms and term_relationships tables, plus BuddyPress&#8217;s own tables. Uninstalling the plugin deletes nothing: uninstall.php only contains a commented-out purge.



Post types



Post typePurposeVisibilitylh-crm-formContact form configurationNot public; admin UI and RESTlh_crm_enquiry_postOne enquiry per submissionRegistered public with rewrite slug enquiry and archive enquiries, but its statuses are only public to users with edit_others_posts. Excluded from sitemaps and several LH SEO and listing plugins.lh_frpt-post_typeForm Response templates (bundled library)Public; REST



An enquiry post stores the enquirer as post_author, its form as post_parent, the message as post_content (tag-stripped copy in post_excerpt), and an HTML-stripped &#8220;X enquired via Page on Site&#8221; string as post_title. Its post_name is set to its own ID.



Enquiry statuses



StatusLabellh_crm-new_enqNew (every enquiry starts here)lh_crm-prog_enqIn Progresslh_crm-pending_enqPendinglh_crm-res_enqResolvedlh_crm-clos_enqClosed



A New enquiry dated in the future is switched to core future status and returned to New by cron when its date arrives (see Cron jobs).



Contact form meta



Meta keyTypeDescription_lh_crm-fe_full_name-hidestring1 hides the name field_lh_crm-fe_message-hidestring1 hides the message field_lh_crm-form_submit_buttonstringSubmit button label_lh_crm-field_groupintegerBuddyPress xProfile field group ID_lh_crm-default_categoryintegerDefault lh_crm-category term ID_lh_crm-recipient_idintegerUser who owns the form&#8217;s enquiries (required to publish)_lh_crm-group_idintegerBuddyPress group ID_lh_crm-group_actionstringadd_to_group, email_invite or silent_invite_lh_crm-bp_notification_recipientsarrayUser IDs for BuddyPress notifications_lh_crm-notification_idintegerbp-email post used as the auto-reply_lh_crm-response_idintegerForm Response post shown after submission



Enquiry meta



Meta keyDescription_lh_crm-referenceRandom reference generated in the browser; a resubmission with the same reference returns the existing enquiry_lh_crm-page_idPage the form was submitted from_lh_crm-referrerBrowser referrer at submission time_lh_crm-enquiry_notesStaff notes (exposed in REST, edit context only)_lh_crm-status-{status}-atUTC time of the most recent move into each status. {status} is the full status name, so the real keys look like _lh_crm-status-lh_crm-new_enq-at._lh_post_user_agent-user_agentBrowser user agent at submission (bundled library, max 1000 characters)



Taxonomies



lh_crm-category: hierarchical enquiry category, one term per enquiry in the admin UI. It is registered with show_ui off, so there is no wp-admin screen for managing its terms; they are available through REST.lh_post_ip_tax-ip (bundled library): the submitter&#8217;s IP address as a term (dots become hyphens in the slug). Terms can only be managed by users with update_plugins.



Users and BuddyPress data



Every enquirer is a WordPress user, matched or created by email. Submitted profile fields are saved as xProfile data on that user.Group actions create normal BuddyPress memberships or invitations.BuddyPress notifications use component blogs, action lh_crm-bp_notification-action, with the site ID as item_id and the enquiry ID as secondary_item_id.LH CRM does not create BuddyPress activity items. The lh_crm-enquiry activity type is legacy, and no items of that type remain on the network. Until 1.5.15 an activity class still filtered every BuddyPress activity query for it; that class was removed. LH_Crm_plugin::return_activity_type() still returns the type name.The initial cron run grants an edit_enquiries capability to every role with edit_others_pages. Nothing currently checks that capability.



Relationship triples (removed in 1.5.8)



Until 1.5.8, each enquiry was also written to the LH Relationships triple store as as:actor (the enquirer), as:target (the form), as:to (the form&#8217;s recipient) and schema:about (the page it was sent from), all with source lh_crm. Nothing read them, and an hourly resync kept re-inserting the same triples, so the integration was removed. Rows written before 1.5.8 remain in the triple store until they are cleaned up separately.
""" ;
  sioc:topic <https://lhero.org/?taxonomy=author&term=cap-1> .

<https://lhero.org/author/1/#account> rdfs:seeAlso <https://lhero.org/author/1/?feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=author&term=cap-1> rdfs:seeAlso <https://lhero.org/?taxonomy=author&term=cap-1&feed=lhrdf&format=turtle> .
