diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5826402 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/vendor +composer.phar +composer.lock +.DS_Store diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2774819 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - hhvm + +before_script: + - composer self-update + - composer install --prefer-source --no-interaction --dev + +script: phpunit diff --git a/README.md b/README.md new file mode 100644 index 0000000..4f79e9e --- /dev/null +++ b/README.md @@ -0,0 +1,271 @@ +# Unofficial Acumulus PHP SDK +Official Acumulus documentation: https://apidoc.sielsystems.nl/ + +This package uses [Guzzle](https://github.com/guzzle/guzzle) to make the cUrl requests to Acumulus. Because of its dependency to Guzzle, this package requires PHP >= 5.4 to function. +## Installation +### Via composer +Add the package to your composer.json file +``` + "require": { + "siegerhansma/acumulus": "~1.0" + }, +``` + +## Configuration +All of the provider classes take a config array as parameter. +``` + $config['contractcode'] = 123456; + $config['username'] = "xxxxxxxxx"; + $config['password'] = "xxxxxxxxx"; +``` +You could put these variables in a specific config file. + +## Usage +Every class and function is fully documented in the [online documentation](http://www.trixoict.nl/acumulus/namespaces/Siegerhansma.AcumulusPhp.html). +### Request +The calls in the API can be called via specific classes corresponding to the categories on the official API docs. +To start, create a new instance of the provider class you need. +``` + $client = new \Siegerhansma\AcumulusPhp\Providers\ContactsProvider($config); +``` +After that, all the calls in that class will be available via the $client variable. +``` + $client->getContactDetails(14036242)->sendRequest(); +``` +When the method is called, you can chain the sendRequest method to that. This method actually sends the request to the Acumulus API. The same principle stands for the other provider classes. + +### Response +The sendRequest method returns the response given by Acumulus. The response is being cast to an array for multiple records or an instance of the model for a single record. + +In the example below is the response of the getAvailableContacts method on the ContactsProvider. +#### Example response +``` +array(3) { + [0] => + class Siegerhansma\AcumulusPhp\Models\Contact#68 (27) { + protected $contactid => + string(7) "1234567" + protected $contactname1 => + string(13) "Contactname 1" + protected $contactname2 => + NULL + protected $contacttypeid => + string(1) "3" + protected $contacttypename => + string(7) "Relatie" + protected $contactperson => + NULL + protected $contactsalutation => + NULL + protected $contactaddress1 => + string(9) "Address 1" + protected $contactaddress2 => + NULL + protected $contactpostalcode => + NULL + protected $contactcity => + string(10) "Leeuwarden" + protected $contactcountryid => + NULL + protected $contactcountrycode => + NULL + protected $contactcountryname => + NULL + protected $contacttelephone => + NULL + protected $contactfax => + NULL + protected $contactemail => + NULL + protected $contactwebsite => + NULL + protected $contactbankaccountnumber => + NULL + protected $contactiban => + NULL + protected $contactbic => + NULL + protected $contactmark => + NULL + protected $contactvatnumber => + NULL + protected $contactvatstandard => + NULL + protected $contacttemplateid => + NULL + protected $contactnotes => + NULL + protected $contactstatus => + NULL + } + [1] => + class Siegerhansma\AcumulusPhp\Models\Contact#91 (27) { + protected $contactid => + string(7) "3216549" + protected $contactname1 => + string(13) "Contactname 2" + protected $contactname2 => + NULL + protected $contacttypeid => + string(1) "3" + protected $contacttypename => + string(7) "Relatie" + protected $contactperson => + NULL + protected $contactsalutation => + NULL + protected $contactaddress1 => + string(9) "Address 2" + protected $contactaddress2 => + NULL + protected $contactpostalcode => + NULL + protected $contactcity => + string(8) "Drachten" + protected $contactcountryid => + NULL + protected $contactcountrycode => + NULL + protected $contactcountryname => + NULL + protected $contacttelephone => + NULL + protected $contactfax => + NULL + protected $contactemail => + NULL + protected $contactwebsite => + NULL + protected $contactbankaccountnumber => + NULL + protected $contactiban => + NULL + protected $contactbic => + NULL + protected $contactmark => + NULL + protected $contactvatnumber => + NULL + protected $contactvatstandard => + NULL + protected $contacttemplateid => + NULL + protected $contactnotes => + NULL + protected $contactstatus => + NULL + } + [2] => + class Siegerhansma\AcumulusPhp\Models\Contact#69 (27) { + protected $contactid => + string(5) "00001" + protected $contactname1 => + string(13) "Contactname 3" + protected $contactname2 => + NULL + protected $contacttypeid => + string(1) "3" + protected $contacttypename => + string(7) "Relatie" + protected $contactperson => + NULL + protected $contactsalutation => + NULL + protected $contactaddress1 => + string(9) "Address 3" + protected $contactaddress2 => + NULL + protected $contactpostalcode => + NULL + protected $contactcity => + NULL + protected $contactcountryid => + NULL + protected $contactcountrycode => + string(2) "NL" + protected $contactcountryname => + NULL + protected $contacttelephone => + NULL + protected $contactfax => + NULL + protected $contactemail => + NULL + protected $contactwebsite => + NULL + protected $contactbankaccountnumber => + NULL + protected $contactiban => + NULL + protected $contactbic => + NULL + protected $contactmark => + NULL + protected $contactvatnumber => + NULL + protected $contactvatstandard => + NULL + protected $contacttemplateid => + NULL + protected $contactnotes => + NULL + protected $contactstatus => + NULL + } +} +``` + +### Models +For the responses you get from Acumulus, there are several models being used. There models are integral copies of the responses and have their own getters and setters. For a list of all the models and the methods that you can use on them, check out the API documentation [here](http://trixoict.nl/acumulus/namespaces/Siegerhansma.AcumulusPhp.Models.html) +### Adding an invoice +By far the most difficult task this package does is adding an invoice to Acumulus. I've tried to create this as easy as possible, but the call being made is pretty complex. +One thing to note is that Acumulus looks at the customer emailadress as being the unique identifier of a customer. So if a customer doesn't have an email yet, this package will automatically create a unique emailaddress for that customer to prevent creating multiple customers. +However, before you make this call it's recommended that you make sure that the customer has an email. +To (hopefully) make this a little bit easier for you, I made an InvoiceBuilder class. Here's an example of how to use this. +``` + + // Instantiate a new InvoiceBuilder object + $invoiceBuilder = new InvoiceBuilder; + + // Create a new contact by instantiating a new Contact model or get it from the API + $builder = new \Siegerhansma\AcumulusPhp\ContactsProvider($config); + $contact = $builder->getContactDetails(123456)->sendRequest(); + + // Set the customer by passing in the Contact model + $invoiceBuilder->setCustomer($contact); + + // Instantiate a new Invoice model and set Invoice specific settings + $invoice = new Invoice; + $invoice + ->setTemplate('Standaard'); + + // Pass in the Invoice model + $invoiceBuilder->setInvoiceData($invoice); + + // Create a new InvoiceLine object and set the fields + // Use this in a loop for multiple lines + $invoiceLine = new InvoiceLine; + $invoiceLine + ->setItemnumber(102) + ->setProduct("Awesome product") + ->setUnitprice(19.95) + ->setQuantity(3); + $invoiceBuilder->addLine($invoiceLine); + + // Pass the InvoiceBuilder into the addInvoice method on the InvoicesProvider and call the build method on it + $invoiceSender = new \Siegerhansma\AcumulusPhp\InvoicesProvider($config); + $response = $invoiceSender->addInvoice($invoiceBuilder->build())->sendRequest(); +``` + +In the response from Acumulus you will get an array with the following fields: +* invoicenumber +* token +* entryid + +## TODO +A lot still to do, here's what: +* Write more tests +* Make documentation +* Support [Picklists](https://apidoc.sielsystems.nl/acumulus-api/picklists) + +If you have any questions, feedback or if you encounter a bug, please leave an issue or a pull request. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a17f7e8 --- /dev/null +++ b/composer.json @@ -0,0 +1,26 @@ +{ + "name": "nexttalent/acumulus", + "description": "PHP wrapper for the Acumulus API", + "authors": [ + { + "name": "Michiel Thalen", + "email": "michiel@nexttalent.nl" + } + ], + "require": { + "php": ">=5.4.0", + + "guzzlehttp/guzzle": "4.1.*" + }, + "require-dev": { + "phpunit/phpunit": "4.1.*", + "mockery/mockery": "0.9.*", + "evert/phpdoc-md" : "0.0.*" + }, + "autoload": { + "psr-0": { + "NextTalent\\AcumulusPhp": "src/" + } + }, + "minimum-stability": "stable" +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..3347b75 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,18 @@ + + + + + ./tests/ + + + diff --git a/src/NextTalent/.idea/.name b/src/NextTalent/.idea/.name new file mode 100644 index 0000000..d1f77da --- /dev/null +++ b/src/NextTalent/.idea/.name @@ -0,0 +1 @@ +NextTalent \ No newline at end of file diff --git a/src/NextTalent/.idea/NextTalent.iml b/src/NextTalent/.idea/NextTalent.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/src/NextTalent/.idea/NextTalent.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/NextTalent/.idea/encodings.xml b/src/NextTalent/.idea/encodings.xml new file mode 100644 index 0000000..d821048 --- /dev/null +++ b/src/NextTalent/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/NextTalent/.idea/misc.xml b/src/NextTalent/.idea/misc.xml new file mode 100644 index 0000000..8662aa9 --- /dev/null +++ b/src/NextTalent/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/NextTalent/.idea/modules.xml b/src/NextTalent/.idea/modules.xml new file mode 100644 index 0000000..f3d7de9 --- /dev/null +++ b/src/NextTalent/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/NextTalent/.idea/scopes/scope_settings.xml b/src/NextTalent/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..922003b --- /dev/null +++ b/src/NextTalent/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/src/NextTalent/.idea/vcs.xml b/src/NextTalent/.idea/vcs.xml new file mode 100644 index 0000000..6564d52 --- /dev/null +++ b/src/NextTalent/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/NextTalent/.idea/workspace.xml b/src/NextTalent/.idea/workspace.xml new file mode 100644 index 0000000..dbce8bb --- /dev/null +++ b/src/NextTalent/.idea/workspace.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1427208051691 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/NextTalent/AcumulusPhp/AcumulusConnector.php b/src/NextTalent/AcumulusPhp/AcumulusConnector.php new file mode 100644 index 0000000..6575553 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/AcumulusConnector.php @@ -0,0 +1,96 @@ +client = new GuzzleHttp\Client(['base_url' => $this->apiUrl]); + $this->xml = new XmlBuilder; + $this->config = $config; + } + + /** + * @param bool $returnApiCall + * @return array|mixed|null + * @throws ConfigNotAnArrayException + * @throws NoConfigSuppliedException + * @throws NoXmlPayloadSuppliedException + */ + public function sendRequest($returnApiCall = false) + { + // Some functions need to return the URL instead of send the request. + if (preg_match('/invoice_get_pdf/', $this->apiCall)) { + return $this->apiUrl . $this->apiCall; + } + + if (empty($this->config)) { + throw new NoConfigSuppliedException("There is no config supplied."); + } + + if (empty($this->xmlPayload) and !is_null($this->xmlPayload)) { + throw new NoXmlPayloadSuppliedException("There is no payload."); + } + + $request = $this->client->post( + $this->apiCall, + [ + 'body' => [ + 'xmlstring' => $this->xml->buildXML($this->xmlPayload, $this->config) + ] + ]); + + return $this->parseResponse($request); + } + + /** + * @param $response + * @return array|mixed|null + * @throws AcumulusException + */ + private function parseResponse($response) + { + $parser = new ResponseParser($response); + + return $parser->parse(); + } +} diff --git a/src/NextTalent/AcumulusPhp/Exceptions/AcumulusException.php b/src/NextTalent/AcumulusPhp/Exceptions/AcumulusException.php new file mode 100644 index 0000000..3c694e8 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Exceptions/AcumulusException.php @@ -0,0 +1,7 @@ +invoice = new Invoice; + } + + /** + * @param InvoiceLine $invoiceLine + * @return $this + */ + public function addLine(InvoiceLine $invoiceLine) + { + $this->invoiceLines[] = $invoiceLine; + + return $this; + } + + /** + * @param Contact $customer + * @param bool $overwriteIfExists + * @return $this + * @throws \Exception + */ + public function setCustomer(Contact $customer, $overwriteIfExists = false) + { + if (!$customer instanceof Contact) { + throw new ValidationErrorException("Customer should be a contact model"); + } + + $this->customer = $customer; + $this->overwriteCustomer = $overwriteIfExists; + + return $this; + } + + /** + * @param Invoice $invoice + * @return $this + * @throws \Exception + */ + public function setInvoiceData(Invoice $invoice) + { + if (!$invoice instanceof Invoice) { + throw new ValidationErrorException("Invoice should be an invoice model"); + } + + $this->invoice = $invoice; + + return $this; + } + + /** + * @return string + * @throws \Exception + */ + public function build() + { + $customer = new \SimpleXMLElement(''); + + $customer->addChild('type', $this->customer->getContacttype()); + $customer->addChild('companyname1', $this->customer->getContactname1()); + $customer->addChild('companyname2', $this->customer->getContactname2()); + $customer->addChild('fullname', $this->customer->getContactperson()); + $customer->addChild('salutation', $this->customer->getContactsalutation()); + $customer->addChild('address1', $this->customer->getContactaddress1()); + $customer->addChild('address2', $this->customer->getContactaddress2()); + $customer->addChild('postalcode', $this->customer->getContactpostalcode()); + $customer->addChild('countrycode', $this->customer->getContactcountrycode()); + $customer->addChild('vatnumber', $this->customer->getContactvatnumber()); + $customer->addChild('telephone', $this->customer->getContacttelephone()); + $customer->addChild('fax', $this->customer->getContactfax()); + $customer->addChild('email', $this->customer->getContactemail()); + $customer->addChild('bankaccountnumber', $this->customer->getContactiban()); + $customer->addChild('mark', $this->customer->getContactmark()); + + $invoice = $customer->addChild('invoice'); + $invoice->addChild('concept', $this->invoice->getConcept()); + $invoice->addChild('number', $this->invoice->getNumber()); + $invoice->addChild('vattype', $this->invoice->getVattype()); + $invoice->addChild('issuedate', $this->invoice->getIssuedate()); + $invoice->addChild('costcenter', $this->invoice->getCostcenter()); + $invoice->addChild('accountnumber', $this->invoice->getAccountnumber()); + $invoice->addChild('paymentstatus', $this->invoice->getPaymentstatus()); + $invoice->addChild('paymentdate', $this->invoice->getPaymentdate()); + $invoice->addChild('description', $this->invoice->getDescription()); + $invoice->addChild('template', $this->invoice->getConcept()); + + if (count($this->invoiceLines) == 0) { + throw new ValidationErrorException("You need to have invoicelines for your invoice"); + } + foreach ($this->invoiceLines as $invoiceLine) { + $line = $invoice->addChild('line'); + $line->addChild('itemnumber', $invoiceLine->getItemnumber()); + $line->addChild('product', $invoiceLine->getProduct()); + $line->addChild('unitprice', $invoiceLine->getUnitprice()); + $line->addChild('vatrate', $invoiceLine->getVatrate()); + $line->addChild('quantity', $invoiceLine->getQuantity()); + $line->addChild('costprice', $invoiceLine->getCostprice()); + } + if (!is_null($this->invoice->getEmailto())) { + $emailaspdf = $invoice->addChild('emailaspdf'); + $emailaspdf->addChild('emailto', $this->invoice->getEmailto()); + $emailaspdf->addChild('emailbcc', $this->invoice->getEmailbcc()); + $emailaspdf->addChild('emailfrom', $this->invoice->getEmailfrom()); + $emailaspdf->addChild('subject', $this->invoice->getSubject()); + $emailaspdf->addChild('message', $this->invoice->getMessage()); + $emailaspdf->addChild('confirmreading', $this->invoice->getConfirmreading()); + } + + $xml = $customer->asXML(); + + // XML output starts with an xml version declaration, this cuts that off. + // Pretty hacky, but it works. + // TODO: Think of something a better solution + return substr($xml, 21); + + } + +} diff --git a/src/NextTalent/AcumulusPhp/Models/Contact.php b/src/NextTalent/AcumulusPhp/Models/Contact.php new file mode 100644 index 0000000..1af76a7 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Models/Contact.php @@ -0,0 +1,457 @@ +contactid; + } + + /** + * @param mixed $contactid + */ + public function setContactid($contactid) { + $this->contactid = $contactid; + } + + /** + * @return mixed + */ + public function getContactyourid() { + return $this->contactyourid; + } + + /** + * @param mixed $contactyourid + */ + public function setContactyourid($contactyourid) { + $this->contactyourid = $contactyourid; + } + + /** + * @return mixed + */ + public function getContactemail() { + return $this->contactemail; + } + + /** + * @param mixed $contactemail + */ + public function setContactemail($contactemail) { + $this->contactemail = $contactemail; + } + + /** + * @return mixed + */ + public function getContacttype() { + return $this->contacttype; + } + + /** + * @param mixed $contacttype + */ + public function setContacttype($contacttype) { + $this->contacttype = $contacttype; + } + + /** + * @return mixed + */ + public function getOverwriteifexists() { + return $this->overwriteifexists; + } + + /** + * @param mixed $overwriteifexists + */ + public function setOverwriteifexists($overwriteifexists) { + $this->overwriteifexists = $overwriteifexists; + } + + /** + * @return mixed + */ + public function getContactname1() { + return $this->contactname1; + } + + /** + * @param mixed $contactname1 + */ + public function setContactname1($contactname1) { + $this->contactname1 = $contactname1; + } + + /** + * @return mixed + */ + public function getContactname2() { + return $this->contactname2; + } + + /** + * @param mixed $contactname2 + */ + public function setContactname2($contactname2) { + $this->contactname2 = $contactname2; + } + + /** + * @return mixed + */ + public function getContactperson() { + return $this->contactperson; + } + + /** + * @param mixed $contactperson + */ + public function setContactperson($contactperson) { + $this->contactperson = $contactperson; + } + + /** + * @return mixed + */ + public function getContactsalutation() { + return $this->contactsalutation; + } + + /** + * @param mixed $contactsalutation + */ + public function setContactsalutation($contactsalutation) { + $this->contactsalutation = $contactsalutation; + } + + /** + * @return mixed + */ + public function getContactaddress1() { + return $this->contactaddress1; + } + + /** + * @param mixed $contactaddress1 + */ + public function setContactaddress1($contactaddress1) { + $this->contactaddress1 = $contactaddress1; + } + + /** + * @return mixed + */ + public function getContactaddress2() { + return $this->contactaddress2; + } + + /** + * @param mixed $contactaddress2 + */ + public function setContactaddress2($contactaddress2) { + $this->contactaddress2 = $contactaddress2; + } + + /** + * @return mixed + */ + public function getContactpostalcode() { + return $this->contactpostalcode; + } + + /** + * @param mixed $contactpostalcode + */ + public function setContactpostalcode($contactpostalcode) { + $this->contactpostalcode = $contactpostalcode; + } + + /** + * @return mixed + */ + public function getContactcity() { + return $this->contactcity; + } + + /** + * @param mixed $contactcity + */ + public function setContactcity($contactcity) { + $this->contactcity = $contactcity; + } + + /** + * @return mixed + */ + public function getContactlocationcode() { + return $this->contactlocationcode; + } + + /** + * @param mixed $contactlocationcode + */ + public function setContactlocationcode($contactlocationcode) { + $this->contactlocationcode = $contactlocationcode; + } + + /** + * @return mixed + */ + public function getContactcountrycode() { + return $this->contactcountrycode; + } + + /** + * @param mixed $contactcountrycode + */ + public function setContactcountrycode($contactcountrycode) { + $this->contactcountrycode = $contactcountrycode; + } + + /** + * @return mixed + */ + public function getContactcountry() { + return $this->contactcountry; + } + + /** + * @param mixed $contactcountry + */ + public function setContactcountry($contactcountry) { + $this->contactcountry = $contactcountry; + } + + /** + * @return mixed + */ + public function getContactvatnumber() { + return $this->contactvatnumber; + } + + /** + * @param mixed $contactvatnumber + */ + public function setContactvatnumber($contactvatnumber) { + $this->contactvatnumber = $contactvatnumber; + } + + /** + * @return mixed + */ + public function getContactvatratebase() { + return $this->contactvatratebase; + } + + /** + * @param mixed $contactvatratebase + */ + public function setContactvatratebase($contactvatratebase) { + $this->contactvatratebase = $contactvatratebase; + } + + /** + * @return mixed + */ + public function getContacttelephone() { + return $this->contacttelephone; + } + + /** + * @param mixed $contacttelephone + */ + public function setContacttelephone($contacttelephone) { + $this->contacttelephone = $contacttelephone; + } + + /** + * @return mixed + */ + public function getContactfax() { + return $this->contactfax; + } + + /** + * @param mixed $contactfax + */ + public function setContactfax($contactfax) { + $this->contactfax = $contactfax; + } + + /** + * @return mixed + */ + public function getContactmark() { + return $this->contactmark; + } + + /** + * @param mixed $contactmark + */ + public function setContactmark($contactmark) { + $this->contactmark = $contactmark; + } + + /** + * @return mixed + */ + public function getContactinvoicetemplateid() { + return $this->contactinvoicetemplateid; + } + + /** + * @param mixed $contactinvoicetemplateid + */ + public function setContactinvoicetemplateid($contactinvoicetemplateid) { + $this->contactinvoicetemplateid = $contactinvoicetemplateid; + } + + /** + * @return mixed + */ + public function getContactstatus() { + return $this->contactstatus; + } + + /** + * @param mixed $contactstatus + */ + public function setContactstatus($contactstatus) { + $this->contactstatus = $contactstatus; + } + + /** + * @return mixed + */ + public function getContactiban() { + return $this->contactiban; + } + + /** + * @param mixed $contactiban + */ + public function setContactiban($contactiban) { + $this->contactiban = $contactiban; + } + + /** + * @return mixed + */ + public function getContactbic() { + return $this->contactbic; + } + + /** + * @param mixed $contactbic + */ + public function setContactbic($contactbic) { + $this->contactbic = $contactbic; + } + + /** + * @return mixed + */ + public function getContactsepamandatenr() { + return $this->contactsepamandatenr; + } + + /** + * @param mixed $contactsepamandatenr + */ + public function setContactsepamandatenr($contactsepamandatenr) { + $this->contactsepamandatenr = $contactsepamandatenr; + } + + /** + * @return mixed + */ + public function getContactsepamandatedate() { + return $this->contactsepamandatedate; + } + + /** + * @param mixed $contactsepamandatedate + */ + public function setContactsepamandatedate($contactsepamandatedate) { + $this->contactsepamandatedate = $contactsepamandatedate; + } + + /** + * @return mixed + */ + public function getContactsepaincassostatus() { + return $this->contactsepaincassostatus; + } + + /** + * @param mixed $contactsepaincassostatus + */ + public function setContactsepaincassostatus($contactsepaincassostatus) { + $this->contactsepaincassostatus = $contactsepaincassostatus; + } + + /** + * @return mixed + */ + public function getContactinvoicenotes() { + return $this->contactinvoicenotes; + } + + /** + * @param mixed $contactinvoicenotes + */ + public function setContactinvoicenotes($contactinvoicenotes) { + $this->contactinvoicenotes = $contactinvoicenotes; + } + + /** + * @return mixed + */ + public function getContactabout() { + return $this->contactabout; + } + + /** + * @param mixed $contactabout + */ + public function setContactabout($contactabout) { + $this->contactabout = $contactabout; + } + protected $contactsalutation; + protected $contactaddress1; + protected $contactaddress2; + protected $contactpostalcode; + protected $contactcity; + protected $contactlocationcode; + protected $contactcountrycode; + protected $contactcountry; + protected $contactvatnumber; + protected $contactvatratebase; + protected $contacttelephone; + protected $contactfax; + protected $contactmark; + protected $contactinvoicetemplateid; + protected $contactstatus; + protected $contactiban; + protected $contactbic; + protected $contactsepamandatenr; + protected $contactsepamandatedate; + protected $contactsepaincassostatus; + protected $contactinvoicenotes; + protected $contactabout; +} diff --git a/src/NextTalent/AcumulusPhp/Models/Entry.php b/src/NextTalent/AcumulusPhp/Models/Entry.php new file mode 100644 index 0000000..b4e85f9 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Models/Entry.php @@ -0,0 +1,452 @@ +foreignvat; + } + + /** + * @param mixed $foreignvat + */ + public function setForeignvat($foreignvat) { + $this->foreignvat = $foreignvat; + } + + /** + * @return mixed + */ + public function getInvoicelayoutid() { + return $this->invoicelayoutid; + } + + /** + * @param mixed $invoicelayoutid + */ + public function setInvoicelayoutid($invoicelayoutid) { + $this->invoicelayoutid = $invoicelayoutid; + } + + + /** + * @return mixed + */ + public function getPaymentstatus() + { + return $this->paymentstatus; + } + + /** + * @param mixed $paymentstatus + */ + public function setPaymentstatus($paymentstatus) + { + $this->paymentstatus = $paymentstatus; + } + + /** + * @return mixed + */ + public function getPaymenttermdays() + { + return $this->paymenttermdays; + } + + /** + * @param mixed $paymenttermdays + */ + public function setPaymenttermdays($paymenttermdays) + { + $this->paymenttermdays = $paymenttermdays; + } + + /** + * @return mixed + */ + public function getAccountid() + { + return $this->accountid; + } + + /** + * @param mixed $accountid + */ + public function setAccountid($accountid) + { + $this->accountid = $accountid; + } + + /** + * @return mixed + */ + public function getContactid() + { + return $this->contactid; + } + + /** + * @param mixed $contactid + */ + public function setContactid($contactid) + { + $this->contactid = $contactid; + } + + /** + * @return mixed + */ + public function getCostcenterid() + { + return $this->costcenterid; + } + + /** + * @param mixed $costcenterid + */ + public function setCostcenterid($costcenterid) + { + $this->costcenterid = $costcenterid; + } + + /** + * @return mixed + */ + public function getCosttypeid() + { + return $this->costtypeid; + } + + /** + * @param mixed $costtypeid + */ + public function setCosttypeid($costtypeid) + { + $this->costtypeid = $costtypeid; + } + + /** + * @return mixed + */ + public function getDeleted() + { + return $this->deleted; + } + + /** + * @param mixed $deleted + */ + public function setDeleted($deleted) + { + $this->deleted = $deleted; + } + + /** + * @return mixed + */ + public function getEntrydate() + { + return $this->entrydate; + } + + /** + * @param mixed $entrydate + */ + public function setEntrydate($entrydate) + { + $this->entrydate = $entrydate; + } + + /** + * @return mixed + */ + public function getEntrydescription() + { + return $this->entrydescription; + } + + /** + * @param mixed $entrydescription + */ + public function setEntrydescription($entrydescription) + { + $this->entrydescription = $entrydescription; + } + + /** + * @return mixed + */ + public function getEntryid() + { + return $this->entryid; + } + + /** + * @param mixed $entryid + */ + public function setEntryid($entryid) + { + $this->entryid = $entryid; + } + + /** + * @return mixed + */ + public function getEntrynote() + { + return $this->entrynote; + } + + /** + * @param mixed $entrynote + */ + public function setEntrynote($entrynote) + { + $this->entrynote = $entrynote; + } + + /** + * @return mixed + */ + public function getEntrytype() + { + return $this->entrytype; + } + + /** + * @param mixed $entrytype + */ + public function setEntrytype($entrytype) + { + $this->entrytype = $entrytype; + } + + /** + * @return mixed + */ + public function getFiscaltype() + { + return $this->fiscaltype; + } + + /** + * @param mixed $fiscaltype + */ + public function setFiscaltype($fiscaltype) + { + $this->fiscaltype = $fiscaltype; + } + + /** + * @return mixed + */ + public function getForeigneu() + { + return $this->foreigneu; + } + + /** + * @param mixed $foreigneu + */ + public function setForeigneu($foreigneu) + { + $this->foreigneu = $foreigneu; + } + + /** + * @return mixed + */ + public function getForeignnoneu() + { + return $this->foreignnoneu; + } + + /** + * @param mixed $foreignnoneu + */ + public function setForeignnoneu($foreignnoneu) + { + $this->foreignnoneu = $foreignnoneu; + } + + /** + * @return mixed + */ + public function getInvoicelayout() + { + return $this->invoicelayout; + } + + /** + * @param mixed $invoicelayout + */ + public function setInvoicelayout($invoicelayout) + { + $this->invoicelayout = $invoicelayout; + } + + /** + * @return mixed + */ + public function getInvoicenote() + { + return $this->invoicenote; + } + + /** + * @param mixed $invoicenote + */ + public function setInvoicenote($invoicenote) + { + $this->invoicenote = $invoicenote; + } + + /** + * @return mixed + */ + public function getInvoicenumber() + { + return $this->invoicenumber; + } + + /** + * @param mixed $invoicenumber + */ + public function setInvoicenumber($invoicenumber) + { + $this->invoicenumber = $invoicenumber; + } + + /** + * @return mixed + */ + public function getMarginscheme() + { + return $this->marginscheme; + } + + /** + * @param mixed $marginscheme + */ + public function setMarginscheme($marginscheme) + { + $this->marginscheme = $marginscheme; + } + + /** + * @return mixed + */ + public function getPaymentterm() + { + return $this->paymenttermdays; + } + + /** + * @param mixed $paymenttermdays + */ + public function setPaymentterm($paymenttermdays) + { + $this->paymenttermdays = $paymenttermdays; + } + + /** + * @return mixed + */ + public function getToken() + { + return $this->token; + } + + /** + * @param mixed $token + */ + public function setToken($token) + { + $this->token = $token; + } + + /** + * @return mixed + */ + public function getTotalvalue() + { + return $this->totalvalue; + } + + /** + * @param mixed $totalvalue + */ + public function setTotalvalue($totalvalue) + { + $this->totalvalue = $totalvalue; + } + + /** + * @return mixed + */ + public function getTotalvalueexclvat() + { + return $this->totalvalueexclvat; + } + + /** + * @param mixed $totalvalueexclvat + */ + public function setTotalvalueexclvat($totalvalueexclvat) + { + $this->totalvalueexclvat = $totalvalueexclvat; + } + + /** + * @return mixed + */ + public function getVatreversecharge() + { + return $this->vatreversecharge; + } + + /** + * @param mixed $vatreversecharge + */ + public function setVatreversecharge($vatreversecharge) + { + $this->vatreversecharge = $vatreversecharge; + } + +} diff --git a/src/NextTalent/AcumulusPhp/Models/Invoice.php b/src/NextTalent/AcumulusPhp/Models/Invoice.php new file mode 100644 index 0000000..7b5433b --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Models/Invoice.php @@ -0,0 +1,329 @@ +accountnumber; + } + + /** + * @param mixed $accountnumber + */ + public function setAccountnumber($accountnumber) + { + $this->accountnumber = $accountnumber; + + return $this; + } + + /** + * @return mixed + */ + public function getConcept() + { + return $this->concept; + } + + /** + * @param mixed $concept + */ + public function setConcept($concept) + { + $this->concept = $concept; + + return $this; + } + + /** + * @return mixed + */ + public function getConfirmreading() + { + return $this->confirmreading; + } + + /** + * @param mixed $confirmreading + */ + public function setConfirmreading($confirmreading) + { + $this->confirmreading = $confirmreading; + + return $this; + } + + /** + * @return mixed + */ + public function getContact() + { + return $this->contact; + } + + /** + * @param mixed $contact + */ + public function setContact($contact) + { + $this->contact = $contact; + + return $this; + } + + /** + * @return mixed + */ + public function getCostcenter() + { + return $this->costcenter; + } + + /** + * @param mixed $costcenter + */ + public function setCostcenter($costcenter) + { + $this->costcenter = $costcenter; + + return $this; + } + + /** + * @return mixed + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param mixed $description + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return mixed + */ + public function getEmailbcc() + { + return $this->emailbcc; + } + + /** + * @param mixed $emailbcc + */ + public function setEmailbcc($emailbcc) + { + $this->emailbcc = $emailbcc; + + return $this; + } + + /** + * @return mixed + */ + public function getEmailfrom() + { + return $this->emailfrom; + } + + /** + * @param mixed $emailfrom + */ + public function setEmailfrom($emailfrom) + { + $this->emailfrom = $emailfrom; + + return $this; + } + + /** + * @return mixed + */ + public function getEmailto() + { + return $this->emailto; + } + + /** + * @param mixed $emailto + */ + public function setEmailto($emailto) + { + $this->emailto = $emailto; + + return $this; + } + + /** + * @return mixed + */ + public function getIssuedate() + { + return $this->issuedate; + } + + /** + * @param mixed $issuedate + */ + public function setIssuedate($issuedate) + { + $this->issuedate = $issuedate; + + return $this; + } + + /** + * @return mixed + */ + public function getMessage() + { + return $this->message; + } + + /** + * @param mixed $message + */ + public function setMessage($message) + { + $this->message = $message; + + return $this; + } + + /** + * @return mixed + */ + public function getNumber() + { + return $this->number; + } + + /** + * @param mixed $number + */ + public function setNumber($number) + { + $this->number = $number; + + return $this; + } + + /** + * @return mixed + */ + public function getPaymentdate() + { + return $this->paymentdate; + } + + /** + * @param mixed $paymentdate + */ + public function setPaymentdate($paymentdate) + { + $this->paymentdate = $paymentdate; + + return $this; + } + + /** + * @return mixed + */ + public function getPaymentstatus() + { + return $this->paymentstatus; + } + + /** + * @param mixed $paymentstatus + */ + public function setPaymentstatus($paymentstatus) + { + $this->paymentstatus = $paymentstatus; + + return $this; + } + + /** + * @return mixed + */ + public function getSubject() + { + return $this->subject; + } + + /** + * @param mixed $subject + */ + public function setSubject($subject) + { + $this->subject = $subject; + + return $this; + } + + /** + * @return mixed + */ + public function getTemplate() + { + return $this->template; + } + + /** + * @param mixed $template + */ + public function setTemplate($template) + { + $this->template = $template; + + return $this; + } + + /** + * @return mixed + */ + public function getVattype() + { + return $this->vattype; + } + + /** + * @param mixed $vattype + */ + public function setVattype($vattype) + { + $this->vattype = $vattype; + + return $this; + } + +} diff --git a/src/NextTalent/AcumulusPhp/Models/InvoiceLine.php b/src/NextTalent/AcumulusPhp/Models/InvoiceLine.php new file mode 100644 index 0000000..514cb0a --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Models/InvoiceLine.php @@ -0,0 +1,127 @@ +costprice; + } + + /** + * @param mixed $costprice + */ + public function setCostprice($costprice) + { + $this->costprice = $costprice; + + return $this; + } + + /** + * @return mixed + */ + public function getItemnumber() + { + return $this->itemnumber; + } + + /** + * @param mixed $itemnumber + */ + public function setItemnumber($itemnumber) + { + $this->itemnumber = $itemnumber; + + return $this; + } + + /** + * @return mixed + */ + public function getProduct() + { + return $this->product; + } + + /** + * @param mixed $product + */ + public function setProduct($product) + { + $this->product = $product; + + return $this; + } + + /** + * @return mixed + */ + public function getQuantity() + { + return $this->quantity; + } + + /** + * @param mixed $quantity + */ + public function setQuantity($quantity) + { + $this->quantity = $quantity; + + return $this; + } + + /** + * @return mixed + */ + public function getUnitprice() + { + return $this->unitprice; + } + + /** + * @param mixed $unitprice + */ + public function setUnitprice($unitprice) + { + $this->unitprice = $unitprice; + + return $this; + } + + /** + * @return mixed + */ + public function getVatrate() + { + return $this->vatrate; + } + + /** + * @param mixed $vatrate + */ + public function setVatrate($vatrate) + { + $this->vatrate = $vatrate; + + return $this; + } + +} diff --git a/src/NextTalent/AcumulusPhp/Models/Model.php b/src/NextTalent/AcumulusPhp/Models/Model.php new file mode 100644 index 0000000..d804fb0 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Models/Model.php @@ -0,0 +1,13 @@ +contact = $contact; + } + + /** + * @return null + */ + public function parse() + { + if (empty($this->contact)) { + return null; + } + $model = new Contact(); + + return $this->buildModel($this->contact, $model); + } +} diff --git a/src/NextTalent/AcumulusPhp/Parsers/ContactsParser.php b/src/NextTalent/AcumulusPhp/Parsers/ContactsParser.php new file mode 100644 index 0000000..70e625e --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Parsers/ContactsParser.php @@ -0,0 +1,67 @@ +contacts = $contacts; + } + + /** + * @return array + */ + public function parse() + { + if (empty($this->contacts)) { + return null; + } + + // When filter is used, one result comes back in the form of an array + if (array_key_exists("contactid", $this->contacts)) { + return $this->parseContact($this->contacts); + } + + foreach ($this->contacts as $contact) { + $models[] = $this->parseContact($contact); + } + + return $models; + + } + + /** + * @param $contact + * @param $models + * @return array + */ + public function parseContact($contact) + { + $model = new Contact(); + + // Sometimes a response comes back as contactname instead of + // contactname1. Fixing it here before model is created. + if (array_key_exists('contactname', $contact)) { + $contact['contactname1'] = $contact['contactname']; + unset($contact['contactname']); + } + + return $this->buildModel($contact, $model); + + } + +} diff --git a/src/NextTalent/AcumulusPhp/Parsers/EntryParser.php b/src/NextTalent/AcumulusPhp/Parsers/EntryParser.php new file mode 100644 index 0000000..66d2ad2 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Parsers/EntryParser.php @@ -0,0 +1,28 @@ +entry = $entry; + } + + /** + * @return mixed + */ + public function parse() + { + $model = new Entry; + + return $this->buildModel($this->entry, $model); + } +} diff --git a/src/NextTalent/AcumulusPhp/Parsers/InvoiceParser.php b/src/NextTalent/AcumulusPhp/Parsers/InvoiceParser.php new file mode 100644 index 0000000..9ac1787 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Parsers/InvoiceParser.php @@ -0,0 +1,27 @@ +invoice = $invoice; + } + + /** + * Returns array with keys 'invoicenumber', 'token' and 'entryid' + * @return mixed + */ + public function parse() + { + return $this->invoice; + } +} diff --git a/src/NextTalent/AcumulusPhp/Parsers/Parser.php b/src/NextTalent/AcumulusPhp/Parsers/Parser.php new file mode 100644 index 0000000..3374783 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Parsers/Parser.php @@ -0,0 +1,38 @@ + $value) { + + if (empty($value)) { + $value = null; + } + + $fieldName = 'set' . ucfirst($name); + // Call the function by the array key name + $model->$fieldName($value); + + } + + return $model; + } + +} diff --git a/src/NextTalent/AcumulusPhp/Parsers/ParserInterface.php b/src/NextTalent/AcumulusPhp/Parsers/ParserInterface.php new file mode 100644 index 0000000..08c3ed0 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Parsers/ParserInterface.php @@ -0,0 +1,16 @@ +apiCall = 'contacts/contact_get.php'; + $this->xmlPayload = sprintf('%d', $contact_id); + + return $this; + } + + /** + * Submit a contact identifier and obtain a list of invoices (if any) received from this particular contact. + * @link https://apidoc.sielsystems.nl/content/contact-list-incoming-invoices + * @param $contact_id + * @return $this + */ + public function getIncomingInvoices($contact_id) + { + $this->apiCall = 'contacts/contact_invoices_incoming.php'; + $this->xmlPayload = sprintf('%d', $contact_id); + + return $this; + } + + /** + * Submit a contact identifier and obtain a list of invoices (if any) send to this particular contact. + * @link https://apidoc.sielsystems.nl/content/contact-list-outgoing-invoices + * @param $contact_id + * @return $this + */ + public function getOutgoingInvoices($contact_id) + { + $this->apiCall = 'contacts/contact_invoices_outgoing.php'; + $this->xmlPayload = sprintf('%d', $contact_id); + + return $this; + } + + /** + * This API-call allows you to query your contacts. It has a few nice features including an option to provide a term to search for and a selection count and offset to receive only a limited amount of matches. + * @link https://apidoc.sielsystems.nl/content/contacts-list-contacts + * @param $options + * @return $this + * @throws Exception + */ + public function getAvailableContacts($options) + { + if (!is_array($options)) { + throw new NotAnArrayException("Options should be an array"); + } + + $this->xmlPayload = null; + + if (isset($options['filter'])) { + $this->xmlPayload .= sprintf('%s', $options['filter']); + } + if (isset($options['offset'])) { + $this->xmlPayload .= sprintf('%d', $options['offset']); + } + if (isset($options['rowcount'])) { + $this->xmlPayload .= sprintf('%d', $options['rowcount']); + } + if (isset($options['contacttype'])) { + $this->xmlPayload .= sprintf('%d', $options['contacttype']); + } + + $this->apiCall = 'contacts/contacts_list.php'; + + return $this; + + } +} diff --git a/src/NextTalent/AcumulusPhp/Providers/ContactsProvider.php b/src/NextTalent/AcumulusPhp/Providers/ContactsProvider.php new file mode 100644 index 0000000..9545b40 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Providers/ContactsProvider.php @@ -0,0 +1,88 @@ +apiCall = 'contacts/contact_get.php'; + $this->xmlPayload = sprintf('%d', $contact_id); + + return $this; + } + + /** + * Submit a contact identifier and obtain a list of invoices (if any) received from this particular contact. + * @link https://apidoc.sielsystems.nl/content/contact-list-incoming-invoices + * @param $contact_id + * @return $this + */ + public function getIncomingInvoices($contact_id) + { + $this->apiCall = 'contacts/contact_invoices_incoming.php'; + $this->xmlPayload = sprintf('%d', $contact_id); + + return $this; + } + + /** + * Submit a contact identifier and obtain a list of invoices (if any) send to this particular contact. + * @link https://apidoc.sielsystems.nl/content/contact-list-outgoing-invoices + * @param $contact_id + * @return $this + */ + public function getOutgoingInvoices($contact_id) + { + $this->apiCall = 'contacts/contact_invoices_outgoing.php'; + $this->xmlPayload = sprintf('%d', $contact_id); + + return $this; + } + + /** + * This API-call allows you to query your contacts. It has a few nice features including an option to provide a term to search for and a selection count and offset to receive only a limited amount of matches. + * @link https://apidoc.sielsystems.nl/content/contacts-list-contacts + * @param $options + * @return $this + * @throws Exception + */ + public function getAvailableContacts($options) + { + if (!is_array($options)) { + throw new NotAnArrayException("Options should be an array"); + } + + $this->xmlPayload = null; + + if (isset($options['filter'])) { + $this->xmlPayload .= sprintf('%s', $options['filter']); + } + if (isset($options['offset'])) { + $this->xmlPayload .= sprintf('%d', $options['offset']); + } + if (isset($options['rowcount'])) { + $this->xmlPayload .= sprintf('%d', $options['rowcount']); + } + if (isset($options['contacttype'])) { + $this->xmlPayload .= sprintf('%d', $options['contacttype']); + } + + $this->apiCall = 'contacts/contacts_list.php'; + + return $this; + + } +} diff --git a/src/NextTalent/AcumulusPhp/Providers/Entries.php b/src/NextTalent/AcumulusPhp/Providers/Entries.php new file mode 100644 index 0000000..2e1dffa --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Providers/Entries.php @@ -0,0 +1,21 @@ +apiCall = 'entry/entry_info.php'; + $this->xmlPayload = sprintf('%d', $entry_id); + + return $this; + } +} diff --git a/src/NextTalent/AcumulusPhp/Providers/EntriesProvider.php b/src/NextTalent/AcumulusPhp/Providers/EntriesProvider.php new file mode 100644 index 0000000..e0c95ce --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Providers/EntriesProvider.php @@ -0,0 +1,23 @@ +apiCall = 'entry/entry_info.php'; + $this->xmlPayload = sprintf('%d', $entry_id); + + return $this; + } +} diff --git a/src/NextTalent/AcumulusPhp/Providers/Invoices.php b/src/NextTalent/AcumulusPhp/Providers/Invoices.php new file mode 100644 index 0000000..45df666 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Providers/Invoices.php @@ -0,0 +1,74 @@ +build() method to this function. + * https://apidoc.sielsystems.nl/content/invoice-add + * @param $invoiceBuilder + * @return $this + */ + public function addInvoice($invoiceBuilder) + { + $this->apiCall = 'invoices/invoice_add.php'; + $this->xmlPayload = $invoiceBuilder; + + return $this; + } + + /** + * Gets the next invoice number and returns it as a string + * @link https://apidoc.sielsystems.nl/content/invoice-get-next-invoice-number + * @return $this + */ + public function getNextInvoiceNumber() + { + $this->apiCall = 'invoices/invoice_get_next_number.php'; + $this->xmlPayload = null; + + return $this; + } + + /** + * Get the URL to a PDF invoice based on a token + * https://apidoc.sielsystems.nl/content/invoice-get-pdf-invoice + * @param $token + * @return $this + */ + public function getPdfInvoice($token) + { + $this->apiCall = 'invoices/invoice_get_pdf.php?token=' . $token; + $this->xmlPayload = null; + + return $this; + } + + public function getPaymentStatus($token) + { + $this->apiCall = 'invoices/invoice_paymentstatus_get.php'; + $this->xmlPayload = sprintf('%s', $token); + + return $this; + } + + public function setPaymentStatus($token, $paymentstatus = 1, $paymentdate) + { + // Validate paymentdate before sending it off + $datetime = \DateTime::createFromFormat("Y-m-d", $paymentdate); + if (!$datetime and $datetime->format('Y-m-d') !== $paymentdate) { + throw new ValidationErrorException("Paymentdate should be in YYYY-MM-DD format"); + } + + $this->apiCall = 'invoices/invoice_paymentstatus_set.php'; + $this->xmlPayload .= sprintf('%s', $token); + $this->xmlPayload .= sprintf('%d', $paymentstatus); + $this->xmlPayload .= sprintf('%s', $paymentdate); + + return $this; + } + +} diff --git a/src/NextTalent/AcumulusPhp/Providers/InvoicesProvider.php b/src/NextTalent/AcumulusPhp/Providers/InvoicesProvider.php new file mode 100644 index 0000000..a9e9ac0 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Providers/InvoicesProvider.php @@ -0,0 +1,76 @@ +build() method to this function. + * https://apidoc.sielsystems.nl/content/invoice-add + * @param $invoiceBuilder + * @return $this + */ + public function addInvoice(InvoiceBuilder $invoiceBuilder) + { + $this->apiCall = 'invoices/invoice_add.php'; + $this->xmlPayload = $invoiceBuilder->build(); + + return $this; + } + + /** + * Gets the next invoice number and returns it as a string + * @link https://apidoc.sielsystems.nl/content/invoice-get-next-invoice-number + * @return $this + */ + public function getNextInvoiceNumber() + { + $this->apiCall = 'invoices/invoice_get_next_number.php'; + $this->xmlPayload = null; + + return $this; + } + + /** + * Get the URL to a PDF invoice based on a token + * https://apidoc.sielsystems.nl/content/invoice-get-pdf-invoice + * @param $token + * @return $this + */ + public function getPdfInvoice($token) + { + $this->apiCall = 'invoices/invoice_get_pdf.php?token=' . $token; + $this->xmlPayload = null; + + return $this; + } + + public function getPaymentStatus($token) + { + $this->apiCall = 'invoices/invoice_paymentstatus_get.php'; + $this->xmlPayload = sprintf('%s', $token); + + return $this; + } + + public function setPaymentStatus($token, $paymentstatus = 1, $paymentdate) + { + // Validate paymentdate before sending it off + $datetime = \DateTime::createFromFormat("Y-m-d", $paymentdate); + if (!$datetime and $datetime->format('Y-m-d') !== $paymentdate) { + throw new ValidationErrorException("Paymentdate should be in YYYY-MM-DD format"); + } + + $this->apiCall = 'invoices/invoice_paymentstatus_set.php'; + $this->xmlPayload .= sprintf('%s', $token); + $this->xmlPayload .= sprintf('%d', $paymentstatus); + $this->xmlPayload .= sprintf('%s', $paymentdate); + + return $this; + } + +} diff --git a/src/NextTalent/AcumulusPhp/Providers/Picklists.php b/src/NextTalent/AcumulusPhp/Providers/Picklists.php new file mode 100644 index 0000000..26e1eee --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Providers/Picklists.php @@ -0,0 +1,20 @@ +apiCall = 'picklists/picklist_accounts.php'; + $this->xmlPayload = null; + + return $this; + } + +} diff --git a/src/NextTalent/AcumulusPhp/Providers/PicklistsProvider.php b/src/NextTalent/AcumulusPhp/Providers/PicklistsProvider.php new file mode 100644 index 0000000..8a9ee59 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/Providers/PicklistsProvider.php @@ -0,0 +1,21 @@ +apiCall = 'picklists/picklist_accounts.php'; + $this->xmlPayload = null; + + return $this; + } + +} diff --git a/src/NextTalent/AcumulusPhp/ResponseParser.php b/src/NextTalent/AcumulusPhp/ResponseParser.php new file mode 100644 index 0000000..ecfc609 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/ResponseParser.php @@ -0,0 +1,73 @@ +request = $request; + } + + /** + * Parses the response and sends it to the appropriate response class + * @return array|mixed|null + * @throws AcumulusException + */ + public function parse() + { + // Get the response body and parse it as Json + $response = $this->request->json(); + + if (!is_array($response)) { + return $response; + } + + // Handle errors returned by Acumulus + if ($response['status'] == 1) { + throw new AcumulusException($response['errors']['error']['message']); + } elseif ($response['status'] > 1) { + throw new AcumulusException($response['warnings']['warning']['message']); + } + + // Get the key from the first element from the response + switch (key($response)) { + case 'contacts': + $contacts = new ContactsParser(array_shift($response)['contact']); + + return $contacts->parse(); + case 'contact': + $contact = new ContactParser(array_shift($response)); + + return $contact->parse(); + case 'entry': + $entry = new EntryParser(array_shift($response)); + + return $entry->parse(); + case 'invoice': + $invoice = new InvoiceParser(array_shift($response)); + + return $invoice->parse(); + } + return $response; + } +} diff --git a/src/NextTalent/AcumulusPhp/XmlBuilder.php b/src/NextTalent/AcumulusPhp/XmlBuilder.php new file mode 100644 index 0000000..536b281 --- /dev/null +++ b/src/NextTalent/AcumulusPhp/XmlBuilder.php @@ -0,0 +1,53 @@ +'; + $xml .= ''; + $xml .= 'json'; + $xml .= ''; + $xml .= sprintf('%d', $config['contractcode']); + $xml .= sprintf('%s', $config['username']); + $xml .= sprintf('%s', $config['password']); + + if (isset($config['email'])) { + $xml .= sprintf('%s', $config['email']); + $xml .= sprintf('%s', $config['email']); + } + + $xml .= ''; + + $xml .= $xmlPayload; + + $xml .= ''; + + return $xml; + } + +} diff --git a/tests/.gitkeep b/tests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/AcumulusConnectorTest.php b/tests/AcumulusConnectorTest.php new file mode 100644 index 0000000..d3d56df --- /dev/null +++ b/tests/AcumulusConnectorTest.php @@ -0,0 +1,54 @@ + 123456, + 'username' => 'xxxxxxxxxxxxxxxxxxxx', + 'password' => 'xxxxxxxxxxxxxxxxxxxxxx' + ]; + + $contact = new \Siegerhansma\AcumulusPhp\Providers\ContactsProvider($config); + $contact->getAvailableContacts([])->sendRequest(); + } + + /** @test + * @expectedException Siegerhansma\AcumulusPhp\Exceptions\NoConfigSuppliedException + */ + public function it_should_fail_when_there_is_no_config() + { + $contact = new \Siegerhansma\AcumulusPhp\Providers\ContactsProvider([]); + $contact->getAvailableContacts([])->sendRequest(); + } + + /** + * @test + * @expectedException Siegerhansma\AcumulusPhp\Exceptions\NoXmlPayloadSuppliedException + */ + public function it_should_fail_when_there_is_no_payload() + { + $config = [ + 'contractcode' => 123456, + 'username' => 'xxxxxxxxxxxxxxxxxxxx', + 'password' => 'xxxxxxxxxxxxxxxxxxxxxx' + ]; + + $invoice = ''; + + $invoices = new \Siegerhansma\AcumulusPhp\Providers\InvoicesProvider($config); + $invoices->addInvoice($invoice)->sendRequest(); + + } + +} diff --git a/tests/ResponseParserTest.php b/tests/ResponseParserTest.php new file mode 100644 index 0000000..be7b911 --- /dev/null +++ b/tests/ResponseParserTest.php @@ -0,0 +1,124 @@ +shouldReceive('json') + ->once() + ->andReturn('this is a string') + ->getMock(); + + $parser = new \Siegerhansma\AcumulusPhp\ResponseParser($mock); + + $this->assertEquals('this is a string', $parser->parse()); + } + + /** + * @test + * + * @expectedException Siegerhansma\AcumulusPhp\Exceptions\AcumulusException + */ + public function it_throws_an_exception_when_error_from_acumulus() + { + $response = '{ + "errors": { + "count_errors": "0" + }, + "warnings": { + "warning": { + "code": "502", + "codetag": "EMPTYG5FG", + "message": "Warning - No data - We tried but based on you request we could not find any available contact data." + }, + "count_warnings": "1" + }, + "status": "2" +}'; + + $mock = Mockery::mock('GuzzleHttp\Message\Response') + ->shouldReceive('json') + ->once() + ->andReturn(json_decode($response, true)) + ->getMock(); + $parser = new \Siegerhansma\AcumulusPhp\ResponseParser($mock); + $parser->parse(); + } + + /** @test */ + public function it_should_pick_the_right_model() + { + $response = array( + 'contacts' => array( + 'contact' => array( + 'contactid' => 'value' + ), + 'contact' => array( + 'contactid' => 'another value' + ) + ), + 'status' => 0 + ); + $mock = Mockery::mock('GuzzleHttp\Message\Response') + ->shouldReceive('json') + ->once() + ->andReturn($response) + ->getMock(); + + $parser = new \Siegerhansma\AcumulusPhp\ResponseParser($mock); + $parseClass = $parser->parse(); + + $this->assertInstanceOf('Siegerhansma\AcumulusPhp\Models\Contact', $parseClass); + } + + /** @test */ + public function it_should_return_an_array_of_contacts() + { + $response = file_get_contents(__DIR__ . '/stubs/contacts.txt'); + + $mock = Mockery::mock('GuzzleHttp\Message\Response') + ->shouldReceive('json') + ->once() + ->andReturn(json_decode($response, true)) + ->getMock(); + + $parser = new \Siegerhansma\AcumulusPhp\ResponseParser($mock); + $parsedArray = $parser->parse(); + + $this->assertCount(3, $parsedArray); + } + + /** @test */ + public function it_should_return_a_single_contact() + { + $response = file_get_contents(__DIR__ . '/stubs/contact.txt'); + + $mock = Mockery::mock('GuzzleHttp\Message\Response') + ->shouldReceive('json') + ->once() + ->andReturn(json_decode($response, true)) + ->getMock(); + + $parser = new \Siegerhansma\AcumulusPhp\ResponseParser($mock); + $parsedArray = $parser->parse(); + + $this->assertInstanceOf('Siegerhansma\AcumulusPhp\Models\Contact', $parsedArray); + $this->assertEquals("123456", $parsedArray->getContactid()); + $this->assertEquals("joe@example.com", $parsedArray->getContactemail()); + $this->assertEquals("Address 1", $parsedArray->getContactaddress1()); + } + + /** @test */ + public function it_should_return_null_when_there_is_no_contact() + { + // TODO + } + +} diff --git a/tests/stubs/contact.txt b/tests/stubs/contact.txt new file mode 100644 index 0000000..ac29bc2 --- /dev/null +++ b/tests/stubs/contact.txt @@ -0,0 +1,38 @@ +{ + "contact": { + "contactid": "123456", + "contactname1": "Company name", + "contactname2": {}, + "contacttypeid": "3", + "contacttypename": "Relatie", + "contactperson": {}, + "contactsalutation": {}, + "contactaddress1": "Address 1", + "contactaddress2": {}, + "contactpostalcode": "1234AB", + "contactcity": "Leeuwarden", + "contactcountryid": "0", + "contactcountrycode": {}, + "contactcountryname": {}, + "contacttelephone": {}, + "contactfax": {}, + "contactemail": "joe@example.com", + "contactwebsite": {}, + "contactbankaccountnumber": {}, + "contactiban": {}, + "contactbic": {}, + "contactmark": {}, + "contactvatnumber": {}, + "contactvatstandard": "21.00", + "contacttemplateid": "0", + "contactnotes": {}, + "contactstatus": "1" + }, + "errors": { + "count_errors": "0" + }, + "warnings": { + "count_warnings": "0" + }, + "status": "0" +} \ No newline at end of file diff --git a/tests/stubs/contacts.txt b/tests/stubs/contacts.txt new file mode 100644 index 0000000..974a5e5 --- /dev/null +++ b/tests/stubs/contacts.txt @@ -0,0 +1,57 @@ +{ + + "contacts":{ + "contact":[ + { + "contactid":"1234567", + "contactname":"Contactname 1", + "contacttypeid":"3", + "contacttypename":"Relatie", + "contactperson":{ + }, + "contactaddress1":"Address 1", + "contactaddress2":{}, + "contactcity":"Leeuwarden", + "contactcountrycode":{} + }, + { + "contactid":"3216549", + "contactname":"Contactname 2", + "contacttypeid":"3", + "contacttypename":"Relatie", + "contactperson":{ + }, + "contactaddress1":"Address 2", + "contactaddress2":{ + }, + "contactcity":"Drachten", + "contactcountrycode":{ + } + }, + { + "contactid":"00001", + "contactname":"Contactname 3", + "contacttypeid":"3", + "contacttypename":"Relatie", + "contactperson":{ + }, + "contactaddress1":"Address 3", + "contactaddress2":{ + }, + "contactcity":{ + }, + "contactcountrycode":"NL" + } + + + ] + }, + "errors":{ + "count_errors":"0" + }, + "warnings":{ + "count_warnings":"0" + }, + "status":"0" + +} \ No newline at end of file