1. Algemeen

Met behulp van de cloudplan webservice kunt u gegevens uit cloudplan ophalen en wegschrijven. De webservice wisselt gegevens uit via SOAP en XML. Hierbij valt te denken aan o.a.:

  • projectgegevens
  • personeelgegevens
  • klantgegevens
  • planning

Wat u precies kunt aanroepen van de webservice is te zien op de overzichtspagina van de webservice, beschikbaar op https://api.cloudplan.nl/v1/.
Hier zijn ook de WSDL's  te vinden die u nodig heeft als u bijvoorbeeld wilt experimenteren met bijvoorbeeld SoapUI.  

Iedere service heeft zijn eigen WSDL. Voor de authenticatieservice is dit bijvoorbeeld https://api.cloudplan.nl/v1/authentication?wsdl
SoapUI kan automatisch voorbeeldrequests voor u genereren aan de hand van de WSDL, en kunt u op eenvoudige wijze experimenteren.
De open source versie is gratis en beschikbaar op 
https://www.soapui.org/open-source.html

2. Ophalen, toevoegen, wijzigen en verwijderen van gegevens

Voor het gebruik van de cloudplan webservice dient u eerst in te loggen waarna u een authenticatietoken teruggestuurd krijgt.  Voor elke request die u vervolgens doet dient u het verkregen authenticatietoken mee te sturen.
De verkregen token kan voor meerdere requests worden gebruikt.
Het proces is hieronder schematisch weergegeven. 

Gegevens in Cloudplan toevoegen en wijzigen kunt u doen mbv een 'push...' , ophalen met een 'get..' en verwijderen met 'delete...'.  Zie ook de overzichtspagina voor de beschikbare webmethods.

3. Matchers

In de XML die u naar de webservice stuurt zult u gebruik maken van matchers. Deze matchers bepalen welke gegevens opgehaald, gewijzigd of verwijderd moeten worden in cloudplan (get, push, delete).  Dat kunnen 1 of meerdere records zijn.  In het voorbeeld hieronder worden twee projecten opgehaald met projectnummers PROJ-01 en PROJ-02.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:api="https://api.cloudplan.nl/">
   <soapenv:Header/>
   <soapenv:Body>
      <api:getProjects>
         <authentication>
            <token>F42A1BA2F83074526E7E18238FA2D5C0</token>
         </authentication>
         <projectMatcher allowMultiple="false">
            <number>PROJ-01</number>
         </projectMatcher>
         <projectMatcher allowMultiple="false">
            <number>PROJ-02</number>
         </projectMatcher>
      </api:getProjects>
   </soapenv:Body>
</soapenv:Envelope>

Per matcher krijgt u vervolgens ook het resultaat terug.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:getProjectsResponse xmlns:ns2="https://api.cloudplan.nl/">
         <return>
            <authenticationTokenExpiration>0</authenticationTokenExpiration>
            <matcherResults>
               <matcherResult>
                  <matcher xsi:type="ns2:projectMatcher" allowMultiple="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                     <number>PROJ-01</number>
                  </matcher>
                  <entities>
                     <entity xsi:type="ns2:project" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                        <id>23</id>
                        <number>PROJ-01</number>
                        <description>Example-Project1</description>
                        <department>
                           <id>0</id>
                        </department>
                        <projectType>
                           <id>0</id>
                        </projectType>
                        <customer>
                           <id>0</id>
                        </customer>
                        <customerAddress>
                           <id>0</id>
                        </customerAddress>
                        <postalCode/>
                        <color>#ffffff</color>
                        <index>0</index>
                        <start>2019-01-01</start>
                        <end>2025-12-31</end>
                        <budget>0.0</budget>
                        <backgroundColor>#999999</backgroundColor>
                        <manager>
                           <id>0</id>
                        </manager>
                        <contact/>
                        <status>
                           <id>0</id>
                        </status>
                        <textField1/>
                        <textField2/>
                        <comments>Multi-yearproject</comments>
                        <hidden>false</hidden>
                     </entity>
                  </entities>
               </matcherResult>
               <matcherResult>
                  <matcher xsi:type="ns2:projectMatcher" allowMultiple="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                     <number>PROJ-02</number>
                  </matcher>
                  <entities>
                     <entity xsi:type="ns2:project" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                        <id>32</id>
                        <number>PROJ-02</number>
                        <description>Example-Project02</description>
                        <department>
                           <id>0</id>
                        </department>
                        <projectType>
                           <id>0</id>
                        </projectType>
                        <customer>
                           <id>0</id>
                        </customer>
                        <customerAddress>
                           <id>0</id>
                        </customerAddress>
                        <postalCode/>
                        <color>#ffffff</color>
                        <index>0</index>
                        <start>2020-01-19</start>
                        <end/>
                        <budget>0.0</budget>
                        <backgroundColor>#999999</backgroundColor>
                        <manager>
                           <id>0</id>
                        </manager>
                        <contact/>
                        <status>
                           <id>0</id>
                        </status>
                        <textField1/>
                        <textField2/>
                        <comments/>
                        <hidden>false</hidden>
                     </entity>
                  </entities>
               </matcherResult>
            </matcherResults>
         </return>
      </ns2:getProjectsResponse>
   </soap:Body>
</soap:Envelope>

Zoals u kunt zien bevat de teruggestuurde data geen geneste gegevens, zoals een afdelingsnaam. In plaats daarvan bevat het alleen het id, zoals hier het (cloudplan) id van de afdeling
Als u deze data ook wenst zult
u die apart moeten ophalen via de webservice. (Zie voorbeeld exportProject2.ps1).

Het volgende voorbeeld laat zien dat een enkele matcher ook meerdere resultaten kan opleveren, en dat binnen een matcher soms ook andere matchers gebruikt kunnen worden. Hieronder wordt alle planning opgehaald voor een klant met klantnummer 'KLANT-01' in september 2019:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:api="https://api.cloudplan.nl/">
   <soapenv:Header/>
   <soapenv:Body>
      <api:getPlanning>
         <authentication>
            <token>F42A1BA2F83074526E7E18238FA2D5C0</token>
         </authentication>
         <planningMatcher allowMultiple="true">
            <customerMatcher allowMultiple="false">
               <number>KLANT-01</number>
            </customerMatcher>

            <!-- Overlap met september 2019 -->
            <start operator="BEFORE_OR_EQUAL_DATE">
            	 <dateTime>2019-09-30</dateTime>
            </start>
            <end operator="AFTER_OR_EQUAL_DATE">
            	 <dateTime>2019-09-01</dateTime>
            </end>            
         </planningMatcher>
      </api:getPlanning>
   </soapenv:Body>
</soapenv:Envelope>


Gebruik het 'nummer' veld in cloudplan om 
hierin uw eigen (unieke) referentie op te slaan (zoals projectnummer/personeelsnummer/afdelingsnummer/etc) , zodat uw de gegevens later ook weer makkelijk kunt terugvinden. De meeste matchers staan toe dat u zoekt op het nummer veld.

Elke matcher heeft een attribuut allowMultiple met een default voor 'false'. Gebruik "false" als u een enkel resultaat verwacht.  Dit is vooral nuttig als u gegevens wijzigt/verwijderd in een push/delete en verwacht dat slechts een enkel record wordt aangepast/verwijderd. Als deze is ingesteld op false, maar de matcher levert wel meerdere resultaten op, dan zal er niets worden gewijzigd en een foutmelding worden teruggestuurd. 

Toevoegen / wijzigen gegevens

Hieronder een voorbeeld voor het toevoegen of wijzigen van gegevens in cloudplan.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:api="https://api.cloudplan.nl/">
   <soapenv:Header/>
   <soapenv:Body>
      <api:pushResources>
         <authentication>
            <token>F42A1BA2F83074526E7E18238FA2D5C0</token>
         </authentication>
         <resource>
            <resourceMatcher allowMultiple="false" validationPolicy="FAIL">
               <number>001</number>
            </resourceMatcher>
            <resourceValues>
               <number>001</number>
               <name>Jan L</name>
               <department allowMultiple="false">
                  <number>AFD-01</number>
               </department>
               <email>test@test.test</email>
               <availability>40</availability>
            </resourceValues>
         </resource>
      </api:pushResources>
   </soapenv:Body>
</soapenv:Envelope>

Het bovenstaande voorbeeld kan tot meerdere resultaten leiden:

  • Als er geen persoon bestaat met personeelsnummer 001 dan zal de persoon worden toegevoegd

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body>
          <ns2:pushResourcesResponse xmlns:ns2="https://api.cloudplan.nl/">
             <return>
                <authenticationTokenExpiration>0</authenticationTokenExpiration>
                <MatcherResults>
                   <MatcherResult>
                      <matcher xsi:type="ns2:resourceMatcher" allowMultiple="false" validationPolicy="FAIL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                         <number>001</number>
                      </matcher>
                      <InsertedIds>
                         <InsertedId>250</InsertedId>
                      </InsertedIds>
                      <UpdatedIds/>
                   </MatcherResult>
                </MatcherResults>
             </return>
          </ns2:pushResourcesResponse>
       </soap:Body>
    </soap:Envelope>
  • Als er al een persoon bestaat met personeelsnummer 001 zullen zijn gegevens worden bijgewerkt 

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body>
          <ns2:pushResourcesResponse xmlns:ns2="https://api.cloudplan.nl/">
             <return>
                <authenticationTokenExpiration>0</authenticationTokenExpiration>
                <MatcherResults>
                   <MatcherResult>
                      <matcher xsi:type="ns2:resourceMatcher" allowMultiple="false" validationPolicy="FAIL" select="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                         <number>001</number>
                      </matcher>
                      <InsertedIds/>
                      <UpdatedIds>
                         <UpdatedId>250</UpdatedId>
                      </UpdatedIds>
                   </MatcherResult>
                </MatcherResults>
             </return>
          </ns2:pushResourcesResponse>
       </soap:Body>
    </soap:Envelope>
  • Als er meerdere personen bestaan in cloudplan met personeelsnummer 001 dan zal cloudplan een error terugsturen (vanwege allowMultiple="false").
    (Indien allowMultiple=true, dan worden alle gevonden personen met personeelsnummer 001 bijgewerkt met de nieuwe waarden!)

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body>
          <ns2:pushResourcesResponse xmlns:ns2="https://api.cloudplan.nl/">
             <return>
                <authenticationTokenExpiration>0</authenticationTokenExpiration>
                <MatcherResults>
                   <MatcherResult>
                      <matcher xsi:type="ns2:resourceMatcher" validationPolicy="FAIL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                         <number>001</number>
                      </matcher>
                      <Errors>
                         <Error>Multiple results found for this matcher.</Error>
                      </Errors>
                   </MatcherResult>
                </MatcherResults>
             </return>
          </ns2:pushResourcesResponse>
       </soap:Body>
    </soap:Envelope>
  • Als het toevoegen of wijzigen van gegevens om welke reden dan ook niet mag van cloudplan (door een validatie), dan zal cloudplan een error terugsturen.  Als de <name> was leeggelaten in bovenstaand voorbeeld, dan zou dit de output zijn

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body>
          <ns2:pushResourcesResponse xmlns:ns2="https://api.cloudplan.nl/">
             <return>
                <authenticationTokenExpiration>0</authenticationTokenExpiration>
                <MatcherResults>
                   <MatcherResult>
                      <matcher xsi:type="ns2:resourceMatcher" allowMultiple="true" validationPolicy="FAIL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                         <number>002</number>
                      </matcher>
                      <Errors>
                         <Error entityId="0">Name is empty!</Error>
                      </Errors>
                   </MatcherResult>
                </MatcherResults>
             </return>
          </ns2:pushResourcesResponse>
       </soap:Body>
    </soap:Envelope>



Validation policy

Cloudplan zit vol met validaties.  Zo mag de naam van een persoon bijvoorbeeld niet leeggelaten worden en mag de einddatum van planning niet voor de startdatum liggen. 
De validationPolicy wordt relevant als je meerdere records tegelijk bijwerkt / verwijdert met een enkele matcher, maar waarvan van enkele niet mogen vanwege een validatie. De validationPolicy bepaalt of cloudplan in dat geval helemaal niets moet doen (FAIL), of wel door moet gaan met het gedeelte waarbij de validatie wel goed gaat (SKIP).


Matchen van datum

Een datum matcher bestaat uit een operator en een datum. Als er een datetime type gevraagd wordt, maar er is alleen een datum opgegeven, dan wordt de tijd op 00:00:00 gezet. De mogelijke operatoren zijn:

  • EQUALS_TIME
  • EQUALS_DATE
  • AFTER_OR_EQUAL_TIME
  • AFTER_OR_EQUAL_DATE
  • AFTER_TIME
  • AFTER_DATE
  • BEFORE_OR_EQUAL_TIME
  • BEFORE_OR_EQUAL_DATE
  • BEFORE_TIME
  • BEFORE_DATE

5. Foutafhandeling

Bij het gebruik van de cloudplan webservice kunt u met onderstaande situaties te maken krijgen. Als u de communicatie met de webservice wilt automatiseren, is het belangrijk dat al deze situaties goed worden afgehandeld in uw programma.

  • Een socket timeout als de webserver om welke reden dan ook niet reageert
  • Een HTTP 404 error (Page not found), als de webservice bv tijdelijk offline is voor onderhoud
  • Een HTTP 500 error (Internal Server Error). Dit kan een hoop oorzaken hebben. Dit kan bijvoorbeeld voorkomen als er op de server een fout optreedt bij het verwerken van de opgestuurde gegevens.
  • Soap faults (bijvoorbeeld als er syntax fouten zitten in de opgestuurde XML):

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    	<soap:Body>
    		<soap:Fault>
    			<faultcode>soap:Client</faultcode>
    			<faultstring>Unmarshalling Error: Unexpected close tag &lt;/usernaem>; expected &lt;/username>.
     at [row,col {unknown-source}]: [6,35]</faultstring>
    		</soap:Fault>
    	</soap:Body>
    </soap:Envelope>
  • <error> blok in de response, bijvoorbeeld als de authenticatie token verlopen

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    	<soap:Body>
    		<ns2:getResourcesResponse xmlns:ns2="https://api.cloudplan.nl/">
    			<return>
    				<authenticationTokenExpiration>0</authenticationTokenExpiration>
    				<error>
    					<message>The current session is not authenticated</message>
    				</error>
    			</return>
    		</ns2:getResourcesResponse>
    	</soap:Body>
    </soap:Envelope>
  • of als een loginpoging is mislukt

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    	<soap:Body>
    		<ns2:loginResponse xmlns:ns2="https://api.cloudplan.nl/">
    			<return>
    				<authenticationTokenExpiration>0</authenticationTokenExpiration>
    				<error>AUTHENTICATION_FAILED</error>
    				<accountLocked_RemainingTimeout>0</accountLocked_RemainingTimeout>
    			</return>
    		</ns2:loginResponse>
    	</soap:Body>
    </soap:Envelope>
  • Of als het toevoegen van gegevens mislukt, bijvoorbeeld als je niet genoeg gegevens aanlevert voor bij het opslaan (Push) van een resource.

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    	<soap:Body>
    		<ns2:pushResourcesResponse xmlns:ns2="https://api.cloudplan.nl/">
    			<return>
    				<authenticationTokenExpiration>0</authenticationTokenExpiration>
    				<MatcherResults>
    					<MatcherResult>
    						<matcher xsi:type="ns2:resourceMatcher" allowMultiple="false" validationPolicy="SKIP" select="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    							<number>9999</number>
    						</matcher>
    						<InsertedIds/>
    						<UpdatedIds/>
    						<Errors>
    							<Error entityId="0">Name is empty!</Error>
    						</Errors>
    					</MatcherResult>
    				</MatcherResults>
    			</return>
    		</ns2:pushResourcesResponse>
    	</soap:Body>
    </soap:Envelope>

    De validaties die bepalen of gegevens wel/niet verwijderd of opgeslagen mogen worden, kunnen door planning.nl nog worden bijgesteld indien noodzakelijk.  Hierdoor is het belangrijk dat u de output van '<errors>' niet negeert!