Overview

IDL : Evergreen DNA

XML file which describes the structure of Evergreen classes.

IDL Classes

IDL Sample

<class
  id="aou"
  controller="open-ils.cstore open-ils.pcrud"
  oils_obj:fieldmapper="actor::org_unit"
  oils_persist:tablename="actor.org_unit"
  reporter:label="Organizational Unit"
  oils_persist:field_safe="true">

  <fields oils_persist:primary="id"
    oils_persist:sequence="actor.org_unit_id_seq">
    <field reporter:label="ID" name="id" reporter:datatype="id"/>
    <field reporter:label="Name" name="name"
      reporter:datatype="text" oils_persist:i18n="true"/>
    <field reporter:label="Organizational Unit Type"
      name="ou_type" reporter:datatype="link"/>
  </fields>
  <links>
    <link field="ou_type" reltype="has_a" key="id" map="" class="aout"/>
  </links>
</class>

IDL Virtual SQL-driven Class

<class id="ahopl" controller="open-ils.cstore open-ils.pcrud"
    oils_obj:fieldmapper="action::hold_on_pull_list"
    reporter:label="Hold On Pull List" oils_persist:readonly="true">

    <oils_persist:source_definition><![CDATA[
    SELECT ahr.*,
        COALESCE(acplo.position, acpl_ordered.fallback_position) AS
            copy_location_order_position, au.alias
        ...
    ]]></oils_persist:source_definition>

    <fields oils_persist:primary="id">
        <field reporter:label="Status"
            name="status" oils_persist:virtual="true" />
        <field reporter:label="Transit"
            name="transit" oils_persist:virtual="true" />

Scripting (Dojo)

var org = new fieldmapper.aou();
org.name('foo');

var class_label = fieldmapper.IDL.fmclasses.aou.label;

dojo.forEach(fieldmapper.IDL.classes.aou.fields,
    function(field) {
        console.log(field.name + ' ' + field.type + ' ' + field.label);
    }
);

Scripting (Angular)

var org = new egCore.idl.aou();
org.name('foo');

var class_label = egCore.idl.classes.aou.label;

angular.forEach(egCore.idl.classes.aou.fields,
    function(field) {
        console.log(field.name + ' ' + field.type + ' ' + field.label);
    }
);

Perl

use OpenILS::Utils::Fieldmapper;
my $org = new Fieldmapper::actor::org_unit();
$org->name($name);

Accessing the IDL

PCRUD

srfsh# request open-ils.pcrud open-ils.pcrud.retrieve.aou "<auth>", 1

PCRUD IDL Configuration

  1. Classes
  2. Actions
  3. Permissions
  4. Context org unit

PCRUD IDL Example

<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
    <actions>
        <create permission="CREATE_NON_CAT_TYPE"
            context_field="owning_lib"/>
        <retrieve/>
        <update permission="CREATE_NON_CAT_TYPE"
            context_field="owning_lib"/>
        <delete permission="CREATE_NON_CAT_TYPE"
            context_field="owning_lib"/>
    </actions>
</permacrud>

PCRUD Permission Links and Jumps

<!-- fund_debit -->
<retrieve permission="ADMIN_ACQ_FUND">
    <context link="fund" field="org"/>
</retrieve>
<!-- edi_message -->
<retrieve permission="ADMIN_PROVIDER MANAGE_PROVIDER VIEW_PROVIDER">
    <context link="account" jump="provider" field="owner"/>
</retrieve>

PCRUD-related IDL Attributes

<class id="vmp" controller="open-ils.cstore open-ils.pcrud" ...
<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1"
    ignore_object_perms="true">
<create permission="ADMIN_FLOAT_GROUPS" global_required="true"/>

PCRUD API

srfsh# request open-ils.pcrud open-ils.pcrud.retrieve.aou "<auth>", 1

srfsh# request open-ils.pcrud open-ils.pcrud.search.aou
    "<auth>", {"ou_type":2,"id":{">":2}}

srfsh# request open-ils.pcrud open-ils.pcrud.create.aou
    "<auth>", {"__c":"aou","__p":[null,"11","12","7","12",...]}

srfsh# request open-ils.pcrud open-ils.pcrud.update.aou
    "<auth>", {"__c":"aou","__p":[null,"11","12","7","12",...]}

srfsh# request open-ils.pcrud open-ils.pcrud.delete.aou
    "<auth>", {"__c":"aou","__p":[null,"11","12","7","12",...]}

PCRUD API: Transactions and Save Points

Require OpenSRF CONNECT.

Fleshing, Sorting, Limiting

srfsh# request open-ils.pcrud open-ils.pcrud.retrieve.au "<auth>", 1,
    {"flesh":2,"flesh_fields":{"au":["home_ou"],"aou":["ou_type"]}}
srfsh# request open-ils.pcrud open-ils.pcrud.search.aou "<auth>",
    {"id":{"!=":null}}, {"order_by":{"aou":"name desc"}, "limit":3}
srfsh# request open-ils.pcrud open-ils.pcrud.search.aou "<auth>",
    {"id":{"!=":null}},
    {"order_by":[
        {"class" : "aou", "field" : "parent_ou"},
        {"class" : "aou", "field" : "name", "direction" : "desc"}
    ]}

Selecting

srfsh# request open-ils.pcrud open-ils.pcrud.retrieve.bre "<auth>", 1,
    {"select":{"bre":[
    "id","create_date","editor","tcn_value","fingerprint"]}}

Received Data: {
  "__c":"bre",
  "__p":[
    null,
    null,
    null,
    "2015-04-24T11:26:11-0400",
    null,
    null,
    null,
    1,
    "lacanzoneitalianadelnovecentobaldazzi",
    1,
    null,
    null,
    null,
    null,
    null,
    "1"
  ]
}

ANONYMOUS PCRUD

<class id="aou" ... oils_persist:field_safe="true">
srfsh# request open-ils.pcrud open-ils.pcrud.retrieve.aou "ANONYMOUS", 1

PCRUD JavaScript Interface (Dojo)

var pcrud = new openils.PermaCrud();

pcrud.retrieve('aou', 1, {oncomplete : function(org) { ... }});
pcrud.update(some_org, {oncomplete : function(resp) { ... }});

pcrud.search('aou', {parent_ou : 1}, {
    oncomplete : function() {...},
    onerror    : function() {...},
    onresponse : function(r) { // streams in XUL client only
        var org = openils.Util.readResponse(r);
        console.log('one org unit: ' + org);
    }
});

A Quick Note on Promises

PCRUD JavaScript Interface (Angular)

egCore.pcrud.retrieve('aou', 1).then(function(org) { ... });
egCore.pcrud.update(some_org).then(function(resp) { ... });

egCore.pcrud.search('aou', {parent_ou : 1})
.then(
    function() {...},   // oncomplete
    function() {...},   // onerror
    function(one_org) { // onresponse -- streams universally supported
        console.log('one org unit: ' + one_org);
    }
});

When Not To Use PCRUD

Fielder

srfsh# request open-ils.fielder
    open-ils.fielder.aou {"query":{"id":{"!=":null}}}

Received Data: {
    "shortname":"SL1",
    "holds_address":null,
    "fiscal_calendar":1,
    "parent_ou":4,
    "opac_visible":"t",
    "ou_type":4,
    "billing_address":null,
    "phone":null,
    "mailing_address":null,
    "email":null,
    "id":8,
    "name":"Example Sub-library 1",
    "ill_address":null
  }
...

Flat Fielder

open-ils.fielder
open-ils.fielder.flattened_search
<auth>, "mbt", {
    "summary.balance_owed":"summary.balance_owed",
    "summary.last_billing_type":"summary.last_billing_type",
    "xact_start":"xact_start",
    "record_id":"circulation.target_copy.call_number.record.id",
    "copy_id":"circulation.target_copy.id",
    "title":"circulation.target_copy.call_number.record.simple_record.title",
    ...
}, {
    "usr":"201",
    "xact_finish":null,
    "summary.balance_owed":{"<>":0}
}, {
    "sort":["xact_start"],
    "limit":25,
    "offset":0
}

Flat Fielder Response

{
  "summary.last_billing_type":"Overdue materials",
  "record_id":58,
  "copy_barcode":"CONC70000393",
  "summary.total_owed":"1.40",
  "summary.balance_owed":"1.40",
  "copy_id":358,
  "id":348,
  "summary.total_paid":"0.0",
  "title":"concerto for violin and orchestra no 2 in d major, k 211",
  "xact_start":"2015-04-10T11:26:11-0400"
}

Fielder Notes and Limitations

Questions / Comments