From e0a7b3db027414c0114e270a2382bb62a27ee589 Mon Sep 17 00:00:00 2001 From: Jonas Dambacher Date: Fri, 27 May 2016 17:25:25 +0200 Subject: [PATCH] Working version 1.0.0 --- .gitignore | 1 + .gitlab-ci.yml | 22 ++ CoffeeBikeCollmexBundle.php | 9 + .../CoffeeBikeCollmexExtension.php | 28 +++ DependencyInjection/Configuration.php | 29 +++ Models/Invoice.php | 158 +++++++++++++ Models/Product.php | 129 +++++++++++ Models/ProductGroup.php | 41 ++++ Models/Request.php | 35 +++ Models/Response.php | 44 ++++ Models/ResponseMessage.php | 104 +++++++++ README.md | 51 +++++ Resources/config/services.xml | 16 ++ Services/CollmexManager.php | 214 ++++++++++++++++++ Tests/CollmexManagerTest.php | 152 +++++++++++++ composer.json | 34 +++ phpunit.xml.dist | 40 ++++ 17 files changed, 1107 insertions(+) create mode 100644 .gitlab-ci.yml create mode 100644 CoffeeBikeCollmexBundle.php create mode 100644 DependencyInjection/CoffeeBikeCollmexExtension.php create mode 100644 DependencyInjection/Configuration.php create mode 100644 Models/Invoice.php create mode 100644 Models/Product.php create mode 100644 Models/ProductGroup.php create mode 100644 Models/Request.php create mode 100644 Models/Response.php create mode 100644 Models/ResponseMessage.php create mode 100644 README.md create mode 100644 Resources/config/services.xml create mode 100644 Services/CollmexManager.php create mode 100644 Tests/CollmexManagerTest.php create mode 100644 composer.json create mode 100644 phpunit.xml.dist diff --git a/.gitignore b/.gitignore index 444374d..eece136 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ /bin/* !bin/console !bin/symfony_requirements +/composer.lock /vendor/ # Assets and user uploads diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..a99d34a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,22 @@ +before_script: + +stages: + - test + +test: + stage: test + script: + - export ENV=Development + - rm -r /var/www + - ln -s /builds/efis/collmexBundle /var/www + - cd /var/www + - wget http://getcomposer.org/composer.phar -O composer.phar + - php -dmemory_limit=2G composer.phar install --optimize-autoloader + - php app/console assetic:dump --env=dev + - php app/console cache:clear --env=dev + - php app/console assets:install web --symlink + - chown -R www-data:root /var/www + - ./bin/phpunit -c app --coverage-text --colors=never + allow_failure: false + tags: + - docker-runner \ No newline at end of file diff --git a/CoffeeBikeCollmexBundle.php b/CoffeeBikeCollmexBundle.php new file mode 100644 index 0000000..8ff0840 --- /dev/null +++ b/CoffeeBikeCollmexBundle.php @@ -0,0 +1,9 @@ +processConfiguration($configuration, $configs); + + $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.xml'); + } +} diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php new file mode 100644 index 0000000..37fd69d --- /dev/null +++ b/DependencyInjection/Configuration.php @@ -0,0 +1,29 @@ +root('coffee_bike_collmex'); + + // Here you should define the parameters that are allowed to + // configure your bundle. See the documentation linked above for + // more information on that topic. + + return $treeBuilder; + } +} diff --git a/Models/Invoice.php b/Models/Invoice.php new file mode 100644 index 0000000..a8bb081 --- /dev/null +++ b/Models/Invoice.php @@ -0,0 +1,158 @@ + 'CMXINV', + 'invoice_id' => null, + 'position' => null, + 'invoice_type' => null, + 'client_id' => null, + 'order_id' => null, + 'customer_id' => null, + 'customer_salutation' => null, + 'customer_title' => null, + 'customer_forename' => null, + 'customer_lastname' => null, + 'customer_firm' => null, + 'customer_department' => null, + 'customer_street' => null, + 'customer_zipcode' => null, + 'customer_city' => null, + 'customer_country' => null, + 'customer_phone' => null, + 'customer_phone_2' => null, + 'customer_fax' => null, + 'customer_email' => null, + 'customer_bank_account' => null, + 'customer_bank_code' => null, + 'customer_bank_account_owner' => null, + 'customer_bank_iban' => null, + 'customer_bank_bic' => null, + 'customer_bank_name' => null, + 'customer_vat_id' => null, + 'reserved' => null, + 'invoice_date' => null, + 'price_date' => null, + 'terms_of_payment' => null, + 'currency' => null, + 'price_group' => null, + 'discount_id' => null, + 'discount_final' => null, + 'discount_reason' => null, + 'invoice_text' => null, + 'final_text' => null, + 'annotation' => null, + 'deleted' => null, + 'language' => null, + 'employee_id' => null, + 'agent_id' => null, + 'system_name' => null, + 'status' => null, + 'discount_final_2' => null, + 'discount_final_2_reason' => null, + 'shipping_id' => null, + 'shipping_costs' => null, + 'cod_costs' => null, + 'time_of_delivery' => null, + 'delivery_conditions' => null, + 'delivery_conditions_additional' => null, + 'delivery_salutation' => null, + 'delivery_title' => null, + 'delivery_forename' => null, + 'delivery_lastname' => null, + 'delivery_firm' => null, + 'delivery_department' => null, + 'delivery_street' => null, + 'delivery_zipcode' => null, + 'delivery_city' => null, + 'delivery_country' => null, + 'delivery_phone' => null, + 'delivery_phone_2' => null, + 'delivery_fax' => null, + 'delivery_email' => null, + 'position_type' => null, + 'product_id' => null, + 'product_description' => null, + 'quantity_unit' => null, + 'quantity' => null, + 'price' => null, + 'price_quantity' => null, + 'position_discount' => null, + 'position_value' => null, + 'product_type' => null, + 'tax_rate' => null, + 'foreign_tax' => null, + 'customer_order_position' => null, + 'revenue_type' => null, + 'sum_over_positions' => null, + 'revenue' => null, + 'costs' => null, + 'gross_profit' => null, + 'margin' => null, + 'costs_manual' => null, + ); + + /** + * Formally validates the type data in $data attribute. + * + * @return bool Validation success + */ + public function validate() + { + // TODO: Implement validate() method. + } + + public function setInvoiceData($aTemplate) + { + $i = 0; + foreach ($this->template as $key => $value) { + $this->template[$key] = $aTemplate[$i]; + $i++; + + } + } + + public function getData() + { + return $this->template; + } +} \ No newline at end of file diff --git a/Models/Product.php b/Models/Product.php new file mode 100644 index 0000000..bd151ed --- /dev/null +++ b/Models/Product.php @@ -0,0 +1,129 @@ + 'CMXPRD', + 'product_id' => null, + 'product_name' => null, + 'product_name_en' => null, + 'base_unit_measure' => null, + 'product_group' => null, + 'company' => null, + 'tax_classification' => null, + 'weight' => null, + 'weight_base_unit' => null, + 'price_quotation' => null, + 'product_type' => null, + 'inactive' => null, + 'price_group' => null, + 'retail_price' => null, + 'ean' => null, + 'manufacturer' => null, + 'shipping_group' => null, + 'minimum_stock ' => null, + 'order_volume' => null, + 'batch_management_requirement' => null, + 'procurement' => null, + 'production_time' => null, + 'wage_costs' => null, + 'wage_costs_reference_amount' => null, + 'remark' => null, + 'cost_determination' => null, + 'cost' => null, + 'cost_reference_amount' => null, + 'supplier' => null, + 'supplier_tax_classification' => null, + 'supplier_product_id' => null, + 'supplier_package_unit' => null, + 'supplier_designation' => null, + 'supplier_price' => null, + 'supplier_price_amount' => null, + 'supplier_delivery_time' => null, + 'supplier_currency' => null, + 'reserved1' => null, + 'reserved2' => null, + 'website_no' => null, + 'shop_shorttext' => null, + 'shop_fulltext' => null, + 'text_html' => null, + 'filename' => null, + 'keywords' => null, + 'title' => null, + 'different_template' => null, + 'picture_url' => null, + 'basic_price_amount_1' => null, + 'basic_price_amount_2' => null, + 'basic_unit' => null, + 'requested_price' => null, + 'inactive_product' => null, + 'shop_category' => null, + 'reserved3' => null, + 'reserved4' => null, + 'reserved5' => null, + 'manufacturer_product_id' => null, + 'delivery_relevance' => null, + 'amazon_asin' => null, + 'ebay_article_id' => null, + 'direct_delivery' => null, + 'goods_number' => null, + ); + + protected $extraInfo; + + + public function setData($aTemplate) + { + $i = 0; + foreach ($this->template as $key => $value) { + $this->template[$key] = $aTemplate[$i]; + $i++; + } + + $this->parseRemark(); + } + + public function getData() + { + return $this->template; + } + + public function setField($key, $value) + { + $this->template[$key] = $value; + + if ($key == 'remark') { + $this->parseRemark(); + } + } + + public function getField($key) + { + return $this->template[$key]; + } + + public function getExtraInfo() + { + return $this->extraInfo; + } + + public function parseRemark() + { + $remark = $this->getField('remark'); + $key = null; + $value = null; + + preg_match_all("/(\[)(.*?)(\])/", $remark, $aMatches); + + foreach ($aMatches[2] as $match) { + $parameters = explode('=', $match); + $key = $parameters[0]; + $value = $parameters[1]; + } + + $this->extraInfo[$key] = $value; + } +} \ No newline at end of file diff --git a/Models/ProductGroup.php b/Models/ProductGroup.php new file mode 100644 index 0000000..ff341d0 --- /dev/null +++ b/Models/ProductGroup.php @@ -0,0 +1,41 @@ + 'PRDGRP', + 'productgroup_id' => null, + 'name' => null, + 'is_subgroup_from_id' => null, + + ); + + + public function setData($aTemplate) + { + $i = 0; + foreach ($this->template as $key => $value) { + $this->template[$key] = $aTemplate[$i]; + $i++; + } + } + + public function getData($key) + { + return $this->template[$key]; + } + + public function setField($key, $value) + { + $this->template[$key] = $value; + } + + public function getField($key) + { + return $this->template[$key]; + } + +} \ No newline at end of file diff --git a/Models/Request.php b/Models/Request.php new file mode 100644 index 0000000..64b8d13 --- /dev/null +++ b/Models/Request.php @@ -0,0 +1,35 @@ + + */ + +namespace CoffeeBike\CollmexBundle\Models; + + +class Request +{ + private $data; + + public function __construct($data) + { + $this->data = $data; + } + + public function setData($data) + { + $this->data = $data; + } + + public function getData() + { + return $this->data; + } + +} \ No newline at end of file diff --git a/Models/Response.php b/Models/Response.php new file mode 100644 index 0000000..4f03ba7 --- /dev/null +++ b/Models/Response.php @@ -0,0 +1,44 @@ +setData($aData); + + $this->objects[] = $object; + } + + public function getObjects() + { + return $this->objects; + } + + public function addMessage($message) + { + $this->messages[] = $message; + } + + public function getMessages() + { + return $this->messages; + } +} \ No newline at end of file diff --git a/Models/ResponseMessage.php b/Models/ResponseMessage.php new file mode 100644 index 0000000..6a5d1fd --- /dev/null +++ b/Models/ResponseMessage.php @@ -0,0 +1,104 @@ + + */ + +namespace CoffeeBike\CollmexBundle\Models; + + +class ResponseMessage +{ + private $typeIdentifier; + private $status; + private $code; + private $text; + private $line; + + + /** + * @return mixed + */ + public function getTypeIdentifier() + { + return $this->typeIdentifier; + } + + /** + * @param mixed $typeIdentifier + */ + public function setTypeIdentifier($typeIdentifier) + { + $this->typeIdentifier = $typeIdentifier; + } + + /** + * @return mixed + */ + public function getStatus() + { + return $this->status; + } + + /** + * @param mixed $status + */ + public function setStatus($status) + { + $this->status = $status; + } + + /** + * @return mixed + */ + public function getCode() + { + return $this->code; + } + + /** + * @param mixed $code + */ + public function setCode($code) + { + $this->code = $code; + } + + /** + * @return mixed + */ + public function getText() + { + return $this->text; + } + + /** + * @param mixed $text + */ + public function setText($text) + { + $this->text = $text; + } + + /** + * @return mixed + */ + public function getLine() + { + return $this->line; + } + + /** + * @param mixed $line + */ + public function setLine($line) + { + $this->line = $line; + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1ab414 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# [WIP] CollmexBundle +This is a Symfony Bundle for the Collmex API. + +**Notice**: This bundle is still work in progress! + +**Please open an issue or a PR if you want to contribute to the project.** Take a look at the [**Contribution** page](https://github.com/coffee-bike/CoffeeBikeCollmexBundle/wiki/Contribution) + +Installation +============ + +Step 1: Download the Bundle +--------------------------- + +Open a command console, enter your project directory and execute the +following command to download the latest stable version of this bundle: + +```bash +$ composer require coffeebike/collmex-bundle +``` + +This command requires you to have Composer installed globally, as explained +in the [installation chapter](https://getcomposer.org/doc/00-intro.md) +of the Composer documentation. + +Step 2: Enable the Bundle +------------------------- + +Then, enable the bundle by adding it to the list of registered bundles +in the `app/AppKernel.php` file of your project: + +```php + + + + + + diff --git a/Services/CollmexManager.php b/Services/CollmexManager.php new file mode 100644 index 0000000..d5694c6 --- /dev/null +++ b/Services/CollmexManager.php @@ -0,0 +1,214 @@ + null, + "password" => null, + "customerId" => null, + ); + + + public function __construct($user, $password, $customerId) + { + $this->credentials['user'] = $user; + $this->credentials['password'] = $password; + $this->credentials['customerId'] = $customerId; + } + + public function send(Request $request) + { + $curl = cURL_init( + "https://www.collmex.de/cgi-bin/cgi.exe?" . $this->credentials['customerId'] . ",0,data_exchange" + ); + cURL_setopt($curl, CURLOPT_POST, 1); + cURL_setopt($curl, CURLOPT_POSTFIELDS, $this->prepareData($request)); + cURL_setopt($curl, CURLOPT_HTTPHEADER, Array("Content-Type: text/csv")); + cURL_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + cURL_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + $message = curl_exec($curl); //returns true or false + cURL_close($curl); + + $message = utf8_encode($message); + + // TODO: Better handling of csv file! + $tmpHandle = tmpfile(); + fwrite($tmpHandle, $message); + rewind($tmpHandle); + $responseObjects = array(); + $responseMessages = array(); + while ($line = fgetcsv($tmpHandle, 0, ';', '"')) { + if ($line[0] == "MESSAGE") { + $responseMessages[] = $line; + } else { + $responseObjects[] = $line; + } + + } + + fclose($tmpHandle); + + try { + $response = new Response(); + + foreach ($responseMessages as $responseMessage) { + $message = new ResponseMessage(); + + $message->setTypeIdentifier($responseMessage[0]); + $message->setStatus($responseMessage[1]); + $message->setCode($responseMessage[2]); + $message->setText($responseMessage[3]); + + if (array_key_exists(4, $responseMessage)) { + $message->setLine($responseMessage[4]); + } + + $response->addMessage($message); + } + + foreach ($responseObjects as $object) { + $response->addObject($object); + } + + return $response; + } catch (\Exception $e) { + echo $e->getMessage(); + + return false; + } + } + + public function prepareData($data) + { + $strCSV = "LOGIN;" . $this->credentials['user'] . ";" . $this->credentials['password'] . "\n"; + + // TODO: Remove duplicated code! + if (is_array($data)) { + foreach ($data as $obj) { + foreach ($obj->getData() as $field) { + $strCSV .= $field . ";"; + } + $strCSV .= "\n"; + } + } else { + foreach ($data->getData() as $field) { + $strCSV .= $field . ";"; + } + $strCSV .= "\n"; + } + + $strCSV = substr($strCSV, 0, -2); // Delete \n from CSV + + return utf8_decode($strCSV); + } + + public function getProduct($prodNo, $prodGroup = null, $priceGroup = null, $onlyModified = 0, $shopId = null, $onlyWithPrice = 0, $companyId = 1) + { + $request = new Request([ + 'PRODUCT_GET', + $companyId, + $prodNo, + $prodGroup, + $priceGroup, + $onlyModified, + 'eFIS', + $shopId, + $onlyWithPrice, + ]); + + $response = $this->send($request); + + return $response->getObjects()[0]; + } + + public function getProductGroups() + { + $request = new Request([ + 'PRODUCT_GROUPS_GET', + ]); + + $response = $this->send($request); + + return $response->getObjects(); + } + + public function getProducts($prodGroup = null, $priceGroup = null, $onlyModified = 0, $shopId = null, $onlyWithPrice = 0, $companyId = 1) + { + $request = new Request([ + 'PRODUCT_GET', + $companyId, + '', + $prodGroup, + $priceGroup, + $onlyModified, + 'eFIS', + $shopId, + $onlyWithPrice, + ]); + + $response = $this->send($request); + + return $response->getObjects(); + } + + public function getInvoice($invoiceNo, $customerNo, $from = null, $to = null, $onlyIssued = 0, $onlyModified = 0, $onlyCreatedWithThisAPI = 0, $companyId = 1) + { + $request = new Request([ + 'INVOICE_GET', + $invoiceNo, + $companyId, + $customerNo, + $from, + $to, + $onlyIssued, + 0, + $onlyModified, + 'eFIS', + $onlyCreatedWithThisAPI, + 0, + ]); + + $response = $this->send($request); + + return $response->getObjects()[0]; + } + + public function getInvoices($customerNo, $from = null, $to = null, $onlyIssued = 0, $onlyModified = 0, $onlyCreatedWithThisAPI = 0, $companyId = 1) + { + $request = new Request([ + 'INVOICE_GET', + '', + $companyId, + $customerNo, + $from, + $to, + $onlyIssued, + 0, + $onlyModified, + 'eFIS', + $onlyCreatedWithThisAPI, + 0, + ]); + + $response = $this->send($request); + + return $response->getObjects(); + } + + + + +} \ No newline at end of file diff --git a/Tests/CollmexManagerTest.php b/Tests/CollmexManagerTest.php new file mode 100644 index 0000000..d057d44 --- /dev/null +++ b/Tests/CollmexManagerTest.php @@ -0,0 +1,152 @@ +cm = new CollmexManager('USER', 'PASSWORD', 'CUSTOMERID'); + } + + public function testPrepareData() + { + $request = new Request([ + 'PRODUCT_GET', + '1', + '1000', + ]); + + $data = $this->cm->prepareData($request); + + $this->assertContains('PRODUCT_GET;1;1000', $data); + } + + public function testRequest() + { + $request = new Request([ + 'PRODUCT_GET', + '1', + '1000', + ]); + + $this->cm->send($request); + } + + public function testResponseMessages() + { + $request = new Request([ + 'PRODUCT_GET', + '1', + '1000', + ]); + + $response = $this->cm->send($request); + + $this->assertCount(2, $response->getMessages()); + } + + public function testResponseObjects() + { + $request = new Request([ + 'PRODUCT_GET', + '1', + '1000', + ]); + + $response = $this->cm->send($request); + + $this->assertCount(1, $response->getObjects()); + } + + public function testGetProduct() + { + $product = $this->cm->getProduct(1000); + + $this->assertTrue($product instanceof Product); + $this->assertEquals('Coffee-Bike', $product->getField('product_name')); + } + + /* + public function testGetInvoice() + { + $testData = array( + 'set_type' => 'INVOICE_GET', + 'invoice_id' => null, + 'client_id' => null, + 'customer_id' => 10623, + 'invoice_date_begin' => null, + 'invoice_date_end' => null, + 'only_sent' => null, + 'format' => null, + 'only_changed' => null, + 'system_name' => null, + 'system_generated' => null, + 'no_stationery' => null, + ); + + + $invoice = $this->cm->getInvoice($testData); + print_r($invoice); + } + + public function testProduct() + { + $product = $this->cm->getProducts(); + + } + + public function testRequest() + { + $testType = new TestType(); + $testType->template = array( + 'CUSTOMER_GET', + '9999', + '1', + ); + + // CollmexResult object + $result = $this->cm->sendRequest([$testType]); + + $this->assertEquals('MESSAGE', $result->get('type_identifier')); + $this->assertEquals('S', $result->get('status')); + $this->assertNotNull($result->get('code')); + $this->assertNotNull($result->get('text')); + // $this->assertTrue($result->get('line')); + + //$this->assertEquals('Allgemeiner Geschäftspartner', $result->getResponse()[0]->get('name')); + } + + /* + public function testCreateInvoice() + { + $invoice['marketing'] = new Invoice(); + $invoice['marketing']->setInvoiceData(array( + 'invoice_id' => -1, + 'position' => null, + 'client_id' => 1, + 'customer_id' => 9999, //$sm->getCollmexId($monthlyReport->getStore()->getCompany()), + 'invoice_type' => 0, + 'invoice_text' => 'Test ÄÜÖß', //TODO: Invoice text + 'language' => 0, // TODO: Language + 'employee_id' => null, + 'system_name' => 'eFIS', + 'status' => 10, + 'position_type' => 0, + 'product_id' => 1, //$monthlyReport->getStore()->getCompany()->getCountry()->getProdNoMarketing(), + 'quantity' => 1, + 'foreign_tax' => 0, + )); + + $result = $this->cm->sendRequest($invoice); + } + */ + +} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c796a4c --- /dev/null +++ b/composer.json @@ -0,0 +1,34 @@ +{ + "name": "coffeebike/collmex-bundle", + "license": "GPL-3.0", + "type": "symfony-bundle", + "description": "Symfony Bundle for the Collmex API", + "homepage": "https://coffee-bike.com", + "authors": [ + { + "name": "Jonas Dambacher", + "email": "jonas.dambacher@coffee-bike.com" + }, + { + "name": "Jannik Kroeger", + "email": "jannik.kroeger@coffee-bike.com" + } + + ], + "autoload": { + "psr-4": { "CoffeeBike\\CollmexBundle\\": "" } + }, + "require": { + "php": ">=5.5.9", + "symfony/framework-bundle": "~2.3|~3.0" + }, + "require-dev": { + "symfony/console": "~2.3|~3.0", + "symfony/phpunit-bridge": "~2.7|~3.0" + }, + "config": { + "platform": { + "php": "5.5.9" + } + } +} \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..8b74c10 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,40 @@ + + + + + + + + + ./Tests/ + + + + + + + ./ + + ./Tests/ + ./Resources/ + ./DependencyInjection/ + ./vendor/ + + + + + \ No newline at end of file