├── src ├── RequestInterface.php ├── Response │ ├── ResponseInterface.php │ ├── Exception │ │ ├── InvalidZipFileException.php │ │ └── InvalidZipResponseException.php │ ├── ResponseFactory.php │ ├── ZipResponse.php │ └── CsvResponse.php ├── Exception │ ├── RequestErrorException.php │ ├── InvalidTypeIdentifierException.php │ └── InvalidResponseMimeTypeException.php ├── Client │ ├── Exception │ │ └── RequestFailedException.php │ ├── ClientInterface.php │ ├── AbstractClient.php │ └── Curl.php ├── Type │ ├── Exception │ │ └── InvalidFieldNameException.php │ ├── TypeInterface.php │ ├── Validator │ │ ├── ValidatorInterface.php │ │ ├── TimeInterval.php │ │ ├── DateOrEmpty.php │ │ └── Date.php │ ├── TermsOfPaymentGet.php │ ├── AddressGroupsGet.php │ ├── ProductGroupsGet.php │ ├── ProjectStaffGet.php │ ├── EmployeeGet.php │ ├── AddressGroups.php │ ├── PriceGroupsGet.php │ ├── Login.php │ ├── NewObject.php │ ├── AccountBalance.php │ ├── TrackingNumber.php │ ├── Message.php │ ├── Batch.php │ ├── ProductPriceGet.php │ ├── BankStatementGet.php │ ├── ProjectStaff.php │ ├── InvoicePaymentGet.php │ ├── ProductGroup.php │ ├── PriceGroup.php │ ├── StockAvailable.php │ ├── BatchGet.php │ ├── OpenItemsGet.php │ ├── ProductPrice.php │ ├── VendorGet.php │ ├── BillOfMaterialGet.php │ ├── ProductPriceChange.php │ ├── VoucherGet.php │ ├── AccountBalanceGet.php │ ├── Stock.php │ ├── InvoicePayment.php │ ├── SendShipmentNotification.php │ ├── ProductionOrderGet.php │ ├── PaymentConfirmation.php │ ├── TermsOfPayment.php │ ├── Voucher.php │ ├── PurchaseOrderGet.php │ ├── ShipmentConfirm.php │ ├── StockGet.php │ ├── CustomerGet.php │ ├── InvoiceOutputSet.php │ ├── ProductGet.php │ ├── StockAvailableGet.php │ ├── StockChangeGet.php │ ├── SupplierInvoice.php │ ├── SubscriptionGet.php │ ├── DeliveryGet.php │ ├── BillOfMaterial.php │ ├── MemberGet.php │ ├── AccountDocumentGet.php │ ├── SupplierAgreement.php │ ├── OpenItem.php │ ├── DifferentShippingAddress.php │ ├── SalesOrderGet.php │ ├── Employee.php │ ├── InvoiceGet.php │ ├── ApiNotification.php │ ├── ProductionOrder.php │ ├── ShipmentOrdersGet.php │ ├── InvoiceOutput.php │ ├── AccountDocument.php │ ├── Subscription.php │ ├── Quotation.php │ ├── Supplier.php │ ├── StockChange.php │ ├── Revenue.php │ ├── Address.php │ ├── Member.php │ ├── AbstractType.php │ ├── Customer.php │ ├── SupplierCredit.php │ ├── Delivery.php │ ├── PurchaseOrder.php │ └── Product.php ├── Filter │ ├── FilterInterface.php │ ├── AbstractFilter.php │ ├── Windows1252ToUtf8.php │ └── Utf8ToWindows1252.php ├── Csv │ ├── FormatInterface.php │ ├── Parser.php │ └── Generator.php ├── AbstractRequest.php ├── Request.php ├── MultiRequest.php ├── CollmexField │ ├── Money.php │ └── Date.php ├── CollmexServiceProvider.php └── TypeFactory.php ├── phpstan.neon ├── config └── collmex.php ├── rector.php ├── LICENSE ├── composer.json └── docs └── collmex.adoc /src/RequestInterface.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class InvalidFieldNameException extends \RuntimeException 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /config/collmex.php: -------------------------------------------------------------------------------- 1 | env('COLLMEX_USER', ''), 12 | 'password' => env('COLLMEX_PASSWORD', ''), 13 | 'customer' => env('COLLMEX_CUSTOMER_ID', ''), 14 | ]; 15 | -------------------------------------------------------------------------------- /src/Client/ClientInterface.php: -------------------------------------------------------------------------------- 1 | |string> $data 13 | */ 14 | public function filterArray(array $data): array; 15 | } 16 | -------------------------------------------------------------------------------- /src/Response/Exception/InvalidZipResponseException.php: -------------------------------------------------------------------------------- 1 | withPaths([ 9 | __DIR__ . '/config', 10 | __DIR__ . '/src', 11 | __DIR__ . '/tests', 12 | ]) 13 | // uncomment to reach your current PHP version 14 | // ->withPhpSets() 15 | ->withTypeCoverageLevel(0) 16 | ->withDeadCodeLevel(0) 17 | ->withCodeQualityLevel(0); 18 | -------------------------------------------------------------------------------- /src/Type/TypeInterface.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface TypeInterface 13 | { 14 | /** 15 | * Formally validates the type data in $data attribute. 16 | * 17 | * @return bool Validation success 18 | */ 19 | public function validate(): bool; 20 | } 21 | -------------------------------------------------------------------------------- /src/AbstractRequest.php: -------------------------------------------------------------------------------- 1 | responseParser = new Parser(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Type/Validator/ValidatorInterface.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface ValidatorInterface 13 | { 14 | /** 15 | * Validates a value. 16 | * 17 | * @param mixed $value 18 | * @param array $options 19 | * 20 | * @return bool Validation success 21 | */ 22 | public function validate($value, array $options = []): bool; 23 | } 24 | -------------------------------------------------------------------------------- /src/Filter/AbstractFilter.php: -------------------------------------------------------------------------------- 1 | $value) { 13 | if (is_array($value)) { 14 | $data[$key] = $this->filterArray($value); 15 | continue; 16 | } 17 | $data[$key] = $this->filterString($value); 18 | } 19 | 20 | return $data; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Filter/Windows1252ToUtf8.php: -------------------------------------------------------------------------------- 1 | 'TERMS_OF_PAYMENT_GET', 17 | ]; 18 | 19 | /** 20 | * Formally validates the type data in $data attribute. 21 | * 22 | * @return bool Validation success 23 | */ 24 | #[\Override] 25 | public function validate(): bool 26 | { 27 | return true; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Type/AddressGroupsGet.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * @property string $type_identifier 11 | */ 12 | class AddressGroupsGet extends AbstractType implements TypeInterface 13 | { 14 | /** 15 | * @var array 16 | */ 17 | protected $template = [ 18 | 'type_identifier' => 'ADDRESS_GROUPS_GET', 19 | ]; 20 | 21 | /** 22 | * Formally validates the type data in $data attribute. 23 | * 24 | * @return bool Validation success 25 | */ 26 | #[\Override] 27 | public function validate(): bool 28 | { 29 | return true; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Type/Validator/TimeInterval.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class TimeInterval implements ValidatorInterface 13 | { 14 | /** 15 | * Validates a date value. 16 | * 17 | * Collmex date representation: `YYYYMMDD` 18 | * 19 | * @param mixed $value 20 | * @param array $options 21 | * 22 | * @return bool Validation success 23 | */ 24 | #[\Override] 25 | public function validate($value, array $options = []): bool 26 | { 27 | return is_int($value) && $value >= 0 && $value <= 7; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Filter/Utf8ToWindows1252.php: -------------------------------------------------------------------------------- 1 | 11 | * @author Timo Paul 12 | * 13 | * @property $type_identifier 14 | */ 15 | class ProductGroupsGet extends AbstractType implements TypeInterface 16 | { 17 | /** 18 | * @var array 19 | */ 20 | protected $template = [ 21 | 'type_identifier' => 'PRODUCT_GROUPS_GET', 22 | ]; 23 | 24 | /** 25 | * Formally validates the type data in $data attribute. 26 | * 27 | * @return bool Validation success 28 | */ 29 | #[\Override] 30 | public function validate(): bool 31 | { 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Type/Validator/DateOrEmpty.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class DateOrEmpty extends Date implements ValidatorInterface 13 | { 14 | /** 15 | * Validates a date value. 16 | * 17 | * Collmex date representation: `YYYYMMDD` 18 | * 19 | * @param mixed $value 20 | * @param array $options 21 | * 22 | * @return bool Validation success 23 | */ 24 | #[\Override] 25 | public function validate($value, array $options = []): bool 26 | { 27 | if (empty($value)) { 28 | return true; 29 | } 30 | 31 | return parent::validate($value, $options); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Type/ProjectStaffGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property string $type_identifier 13 | * @property int $project_id 14 | */ 15 | class ProjectStaffGet extends AbstractType implements TypeInterface 16 | { 17 | /** 18 | * @var array 19 | */ 20 | protected $template = [ 21 | 'type_identifier' => 'PROJECT_STAFF_GET', 22 | 'project_id' => null, 23 | ]; 24 | 25 | /** 26 | * Formally validates the type data in $data attribute. 27 | * 28 | * @return bool Validation success 29 | */ 30 | #[\Override] 31 | public function validate(): bool 32 | { 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Type/EmployeeGet.php: -------------------------------------------------------------------------------- 1 | 'EMPLOYEE_GET', 20 | 'employee_id' => null, 21 | 'client_id' => null, 22 | 'text' => null, 23 | ]; 24 | 25 | /** 26 | * Formally validates the type data in $data attribute. 27 | * 28 | * @return bool Validation success 29 | */ 30 | #[\Override] 31 | public function validate(): bool 32 | { 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Type/AddressGroups.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * @property string $type_identifier 11 | * @property string $address_group_id 12 | * @property string $description 13 | */ 14 | class AddressGroups extends AbstractType implements TypeInterface 15 | { 16 | /** 17 | * @var array 18 | */ 19 | protected $template = [ 20 | 'type_identifier' => 'ADRGRP', 21 | 'address_group_id' => null, 22 | 'description' => null, 23 | ]; 24 | 25 | /** 26 | * Formally validates the type data in $data attribute. 27 | * 28 | * @return bool Validation success 29 | */ 30 | #[\Override] 31 | public function validate(): bool 32 | { 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Type/PriceGroupsGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | */ 16 | class PriceGroupsGet extends AbstractType implements TypeInterface 17 | { 18 | /** 19 | * @var array 20 | */ 21 | protected $template = [ 22 | 'type_identifier' => 'PRICE_GROUPS_GET', 23 | 'client_id' => null, 24 | ]; 25 | 26 | /** 27 | * Formally validates the type data in $data attribute. 28 | * 29 | * @return bool Validation success 30 | */ 31 | #[\Override] 32 | public function validate(): bool 33 | { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Type/Login.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $user 14 | * @property $password 15 | */ 16 | class Login extends AbstractType implements TypeInterface 17 | { 18 | /** 19 | * @var array 20 | */ 21 | protected $template = [ 22 | 'type_identifier' => 'LOGIN', 23 | 'user' => null, 24 | 'password' => null, 25 | ]; 26 | 27 | /** 28 | * Formally validates the type data in $data attribute. 29 | * 30 | * @return bool Validation success 31 | */ 32 | #[\Override] 33 | public function validate(): bool 34 | { 35 | return !empty($this->data['user']) && !empty($this->data['password']); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Request.php: -------------------------------------------------------------------------------- 1 | client->request($body); 23 | 24 | $responseType = new ResponseFactory($response, $this->responseParser); 25 | 26 | return $responseType->getResponseInstance(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Type/NewObject.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $new_id 14 | * @property $temporary_id 15 | * @property $line 16 | */ 17 | class NewObject extends AbstractType implements TypeInterface 18 | { 19 | /** 20 | * @var array 21 | */ 22 | protected $template = [ 23 | 'type_identifier' => 'NEW_OBJECT_ID', 24 | 'new_id' => null, 25 | 'temporary_id' => null, 26 | 'line' => null, 27 | ]; 28 | 29 | /** 30 | * Formally validates the type data in $data attribute. 31 | * 32 | * @return bool Validation success 33 | */ 34 | #[\Override] 35 | public function validate(): bool 36 | { 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Type/AccountBalance.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $account_id 14 | * @property $account_name 15 | * @property $balance 16 | */ 17 | class AccountBalance extends AbstractType implements TypeInterface 18 | { 19 | /** 20 | * @var array 21 | */ 22 | protected $template = [ 23 | 'type_identifier' => 'ACC_BAL', 24 | 'account_id' => null, 25 | 'account_name' => null, 26 | 'balance' => null, 27 | ]; 28 | 29 | /** 30 | * Formally validates the type data in $data attribute. 31 | * 32 | * @return bool Validation success 33 | */ 34 | #[\Override] 35 | public function validate(): bool 36 | { 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Type/TrackingNumber.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $delivery_id 15 | * @property $tracking_code 16 | */ 17 | class TrackingNumber extends AbstractType implements TypeInterface 18 | { 19 | /** 20 | * @var array 21 | */ 22 | protected $template = [ 23 | 'type_identifier' => 'TRACKING_NUMBER', 24 | 'delivery_id' => null, 25 | 'tracking_code' => null, 26 | ]; 27 | 28 | /** 29 | * Formally validates the type data in $data attribute. 30 | * 31 | * @return bool Validation success 32 | */ 33 | #[\Override] 34 | public function validate(): bool 35 | { 36 | return true; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Type/Message.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $message_type 14 | * @property $message_id 15 | * @property $message_text 16 | * @property $line 17 | */ 18 | class Message extends AbstractType implements TypeInterface 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected $template = [ 24 | 'type_identifier' => 'MESSAGE', 25 | 'message_type' => null, 26 | 'message_id' => null, 27 | 'message_text' => null, 28 | 'line' => null, 29 | ]; 30 | 31 | /** 32 | * Formally validates the type data in $data attribute. 33 | * 34 | * @return bool Validation success 35 | */ 36 | #[\Override] 37 | public function validate(): bool 38 | { 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Type/Batch.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * @property string $type_identifier 11 | * @property string $client_id 12 | * @property string $batch_number 13 | * @property string $product_id 14 | * @property string $description 15 | */ 16 | class Batch extends AbstractType implements TypeInterface 17 | { 18 | /** 19 | * @var array 20 | */ 21 | protected $template = [ 22 | 'type_identifier' => 'CMXBTC', 23 | 'client_id' => null, 24 | 'batch_number' => null, 25 | 'product_id' => null, 26 | // 5 27 | 'description' => null, 28 | ]; 29 | 30 | /** 31 | * Formally validates the type data in $data attribute. 32 | * 33 | * @return bool Validation success 34 | */ 35 | #[\Override] 36 | public function validate(): bool 37 | { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Type/ProductPriceGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $product_id 16 | * @property $inactive 17 | */ 18 | class ProductPriceGet extends AbstractType implements TypeInterface 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected $template = [ 24 | 'type_identifier' => 'PRODUCT_PRICE_GET', 25 | 'client_id' => null, 26 | 'product_id' => null, 27 | 'inactive' => null, 28 | ]; 29 | 30 | /** 31 | * Formally validates the type data in $data attribute. 32 | * 33 | * @return bool Validation success 34 | */ 35 | #[\Override] 36 | public function validate(): bool 37 | { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Type/BankStatementGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property mixed $type_identifier 13 | * @property mixed $client_id 14 | * @property mixed $invoice_id 15 | * @property mixed $new_payments_only 16 | * @property mixed $system_name 17 | */ 18 | class BankStatementGet extends AbstractType implements TypeInterface 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected $template = [ 24 | 'type_identifier' => 'BANK_STATEMENT_GET_FROM_BANK', 25 | 'client_id' => null, 26 | 'iban' => null, 27 | 'pin' => null, 28 | ]; 29 | 30 | /** 31 | * Formally validates the type data in $data attribute. 32 | * 33 | * @return bool Validation success 34 | */ 35 | #[\Override] 36 | public function validate(): bool 37 | { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Type/ProjectStaff.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property string $type_identifier 13 | * @property int $project_id 14 | * @property int $staff_id 15 | * @property int $staff_company_id 16 | * @property string $name 17 | */ 18 | class ProjectStaff extends AbstractType implements TypeInterface 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected $template = [ 24 | 'type_identifier' => 'PROJECT_STAFF', 25 | 'project_id' => null, 26 | 'staff_id' => null, 27 | 'staff_company_id' => null, 28 | 'name' => null, 29 | ]; 30 | 31 | /** 32 | * Formally validates the type data in $data attribute. 33 | * 34 | * @return bool Validation success 35 | */ 36 | #[\Override] 37 | public function validate(): bool 38 | { 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Type/InvoicePaymentGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property mixed $type_identifier 13 | * @property mixed $client_id 14 | * @property mixed $invoice_id 15 | * @property mixed $new_payments_only 16 | * @property mixed $system_name 17 | */ 18 | class InvoicePaymentGet extends AbstractType implements TypeInterface 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected $template = [ 24 | 'type_identifier' => 'INVOICE_PAYMENT_GET', 25 | 'client_id' => null, 26 | 'invoice_id' => null, 27 | 'new_payments_only' => null, 28 | 'system_name' => null, 29 | ]; 30 | 31 | /** 32 | * Formally validates the type data in $data attribute. 33 | * 34 | * @return bool Validation success 35 | */ 36 | #[\Override] 37 | public function validate(): bool 38 | { 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Type/ProductGroup.php: -------------------------------------------------------------------------------- 1 | 11 | * @author Timo Paul 12 | * 13 | * @property $type_identifier 14 | * @property $product_group_id 15 | * @property $title 16 | * @property $parent 17 | */ 18 | class ProductGroup extends AbstractType implements TypeInterface 19 | { 20 | /** 21 | * Type data template. 22 | * 23 | * @var array 24 | */ 25 | protected $template = [ 26 | // 1 27 | 'type_identifier' => 'PRDGRP', 28 | 'product_group_id' => null, 29 | 'title' => null, 30 | 'parent' => null, 31 | ]; 32 | 33 | /** 34 | * Formally validates the type data in $data attribute. 35 | * 36 | * @return bool Validation success 37 | */ 38 | #[\Override] 39 | public function validate(): bool 40 | { 41 | // TODO: Implement validate() method. 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Type/PriceGroup.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $price_group_id 16 | * @property $name 17 | * @property $gross 18 | * @property $currency 19 | */ 20 | class PriceGroup extends AbstractType implements TypeInterface 21 | { 22 | /** 23 | * @var array 24 | */ 25 | protected $template = [ 26 | 'type_identifier' => 'PRICE_GROUP', 27 | 'client_id' => null, 28 | 'price_group_id' => null, 29 | 'name' => null, 30 | 'gross' => null, 31 | 'currency' => null, 32 | ]; 33 | 34 | /** 35 | * Formally validates the type data in $data attribute. 36 | * 37 | * @return bool Validation success 38 | */ 39 | #[\Override] 40 | public function validate(): bool 41 | { 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Type/StockAvailable.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $product_id 15 | * @property $client_id 16 | * @property $stock 17 | * @property $unit 18 | * @property $reorder_time 19 | */ 20 | class StockAvailable extends AbstractType implements TypeInterface 21 | { 22 | /** 23 | * @var array 24 | */ 25 | protected $template = [ 26 | 'type_identifier' => 'STOCK_AVAILABLE', 27 | 'product_id' => null, 28 | 'client_id' => null, 29 | 'stock' => null, 30 | 'unit' => null, 31 | 'reorder_time' => null, 32 | ]; 33 | 34 | /** 35 | * Formally validates the type data in $data attribute. 36 | * 37 | * @return bool Validation success 38 | */ 39 | #[\Override] 40 | public function validate(): bool 41 | { 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Marcus Jaschen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/Type/BatchGet.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * @property string $type_identifier 11 | * @property string $client_id 12 | * @property string $batch_number 13 | * @property string $product_id 14 | * @property string $free_text 15 | * @property string $changed_only 16 | * @property string $system_name 17 | */ 18 | class BatchGet extends AbstractType implements TypeInterface 19 | { 20 | /** 21 | * @var array 22 | */ 23 | protected $template = [ 24 | 'type_identifier' => 'BATCH_GET', 25 | 'client_id' => null, 26 | 'batch_number' => null, 27 | 'product_id' => null, 28 | // 5 29 | 'search_description' => null, 30 | 'changed_only' => null, 31 | 'system_name' => null, 32 | ]; 33 | 34 | /** 35 | * Formally validates the type data in $data attribute. 36 | * 37 | * @return bool Validation success 38 | */ 39 | #[\Override] 40 | public function validate(): bool 41 | { 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Client/AbstractClient.php: -------------------------------------------------------------------------------- 1 | exchangeUrl = sprintf(static::EXCHANGE_URL, $customer); 19 | } 20 | 21 | protected function convertEncodingForCollmex(string $text): string 22 | { 23 | $filter = new Utf8ToWindows1252(); 24 | 25 | return $filter->filterString($text); 26 | } 27 | 28 | /** 29 | * Creates the first line of the request body - it contains the 30 | * authentication credentials. 31 | */ 32 | protected function getLoginLine(): string 33 | { 34 | $csvGenerator = new Generator(); 35 | 36 | return $csvGenerator->generate(['LOGIN', $this->user, $this->password]); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Type/OpenItemsGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $open_items 16 | * @property $customer_id 17 | * @property $supplier_id 18 | * @property $agent_id 19 | */ 20 | class OpenItemsGet extends AbstractType implements TypeInterface 21 | { 22 | /** 23 | * @var array 24 | */ 25 | protected $template = [ 26 | 'type_identifier' => 'OPEN_ITEMS_GET', 27 | 'client_id' => null, 28 | // if empty or 0 => customer, if 1 => supplier 29 | 'open_items' => null, 30 | 'customer_id' => null, 31 | 'supplier_id' => null, 32 | 'agent_id' => null, 33 | ]; 34 | 35 | /** 36 | * Formally validates the type data in $data attribute. 37 | * 38 | * @return bool Validation success 39 | */ 40 | #[\Override] 41 | public function validate(): bool 42 | { 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Type/ProductPrice.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $product_id 15 | * @property $client_id 16 | * @property $price_group_id 17 | * @property $valid_from 18 | * @property $valid_to 19 | * @property $price 20 | */ 21 | class ProductPrice extends AbstractType implements TypeInterface 22 | { 23 | /** 24 | * Type data template. 25 | * 26 | * @var array 27 | */ 28 | protected $template = [ 29 | 'type_identifier' => 'CMXPRI', 30 | 'product_id' => null, 31 | 'client_id' => null, 32 | 'price_group_id' => null, 33 | 'valid_from' => null, 34 | 'valid_to' => null, 35 | 'price' => null, 36 | ]; 37 | 38 | /** 39 | * Formally validates the type data in $data attribute. 40 | * 41 | * @return bool Validation success 42 | */ 43 | #[\Override] 44 | public function validate(): bool 45 | { 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Type/VendorGet.php: -------------------------------------------------------------------------------- 1 | 'VENDOR_GET', 28 | 'vendor_id' => null, 29 | 'client_id' => null, 30 | 'text' => null, 31 | 'follow_up' => null, 32 | 'zipcode' => null, 33 | 'changed_only' => null, 34 | 'system_name' => null, 35 | ]; 36 | 37 | /** 38 | * Formally validates the type data in $data attribute. 39 | * 40 | * @return bool Validation success 41 | */ 42 | #[\Override] 43 | public function validate(): bool 44 | { 45 | return true; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Type/BillOfMaterialGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $product_id 16 | * @property $assignment 17 | * @property $component_product_id 18 | * @property $changed_only 19 | * @property $system_name 20 | */ 21 | class BillOfMaterialGet extends AbstractType implements TypeInterface 22 | { 23 | /** 24 | * @var array 25 | */ 26 | protected $template = [ 27 | 'type_identifier' => 'BILL_OF_MATERIAL_GET', 28 | 'client_id' => null, 29 | 'product_id' => null, 30 | 'assignment' => null, 31 | 'component_product_id' => null, 32 | 'changed_only' => null, 33 | 'system_name' => null, 34 | ]; 35 | 36 | /** 37 | * Formally validates the type data in $data attribute. 38 | * 39 | * @return bool Validation success 40 | */ 41 | #[\Override] 42 | public function validate(): bool 43 | { 44 | return true; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Type/ProductPriceChange.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $product_id 15 | * @property $client_id 16 | * @property $price_group_id 17 | * @property $valid_from 18 | * @property $valid_to 19 | * @property $price 20 | */ 21 | class ProductPriceChange extends AbstractType implements TypeInterface 22 | { 23 | /** 24 | * Type data template. 25 | * 26 | * @var array 27 | */ 28 | protected $template = [ 29 | 'type_identifier' => 'CMXPRI_CHANGE', 30 | 'product_id' => null, 31 | 'client_id' => null, 32 | 'price_group_id' => null, 33 | 'valid_from' => null, 34 | 'valid_to' => null, 35 | 'price' => null, 36 | ]; 37 | 38 | /** 39 | * Formally validates the type data in $data attribute. 40 | * 41 | * @return bool Validation success 42 | */ 43 | #[\Override] 44 | public function validate(): bool 45 | { 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Type/VoucherGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $voucher_id 14 | * @property $client_id 15 | * @property $customer_id 16 | * @property $agent_id 17 | * @property $voucher_desc 18 | * @property $show_expired 19 | * @property $changed_only 20 | * @property $system_name 21 | */ 22 | class VoucherGet extends AbstractType implements TypeInterface 23 | { 24 | /** 25 | * @var array 26 | */ 27 | protected $template = [ 28 | 'type_identifier' => 'VOUCHER_GET', 29 | 'voucher_id' => null, 30 | 'client_id' => null, 31 | 'customer_id' => null, 32 | 'agent_id' => null, 33 | 'voucher_desc' => null, 34 | 'show_expired' => null, 35 | 'changed_only' => null, 36 | 'system_name' => null, 37 | ]; 38 | 39 | /** 40 | * Formally validates the type data in $data attribute. 41 | * 42 | * @return bool Validation success 43 | */ 44 | #[\Override] 45 | public function validate(): bool 46 | { 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Type/AccountBalanceGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $client_id 14 | * @property $business_year 15 | * @property $date_to 16 | * @property $account_id 17 | * @property $account_group_id 18 | * @property $customer_id 19 | * @property $supplier_id 20 | * @property $cost_center 21 | */ 22 | class AccountBalanceGet extends AbstractType implements TypeInterface 23 | { 24 | /** 25 | * @var array 26 | */ 27 | protected $template = [ 28 | 'type_identifier' => 'ACCBAL_GET', 29 | 'client_id' => null, 30 | 'business_year' => null, 31 | 'date_to' => null, 32 | 'account_id' => null, 33 | 'account_group_id' => null, 34 | 'customer_id' => null, 35 | 'supplier_id' => null, 36 | 'cost_center' => null, 37 | ]; 38 | 39 | /** 40 | * Formally validates the type data in $data attribute. 41 | * 42 | * @return bool Validation success 43 | */ 44 | #[\Override] 45 | public function validate(): bool 46 | { 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Type/Stock.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $product_id 15 | * @property $client_id 16 | * @property $stock 17 | * @property $type 18 | * @property $batch_number 19 | * @property $value 20 | * @property $batch_description 21 | * @property $product_description 22 | */ 23 | class Stock extends AbstractType implements TypeInterface 24 | { 25 | /** 26 | * @var array 27 | */ 28 | protected $template = [ 29 | 'type_identifier' => 'CMXSTK', 30 | 'product_id' => null, 31 | 'client_id' => null, 32 | 'stock' => null, 33 | 'type' => null, 34 | 'batch_number' => null, 35 | 'value' => null, 36 | 'batch_description' => null, 37 | 'product_description' => null, 38 | ]; 39 | 40 | /** 41 | * Formally validates the type data in $data attribute. 42 | * 43 | * @return bool Validation success 44 | */ 45 | #[\Override] 46 | public function validate(): bool 47 | { 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Type/Validator/Date.php: -------------------------------------------------------------------------------- 1 | createDateInstance($value); 24 | } catch (\InvalidArgumentException) { 25 | return false; 26 | } 27 | 28 | return (int)$date->format('Y') > 1900 && (int)$date->format('Y') < 2100; 29 | } 30 | 31 | private function createDateInstance($value): \DateTime 32 | { 33 | if (strlen((string)$value) === 8) { 34 | return \DateTime::createFromFormat('Ymd', $value); 35 | } 36 | 37 | if (strlen((string)$value) === 10) { 38 | return \DateTime::createFromFormat('d.m.Y', $value); 39 | } 40 | 41 | throw new \InvalidArgumentException('Invalid date format: ' . $value, 3_203_218_841); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Type/InvoicePayment.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property mixed $type_identifier 13 | * @property mixed $invoice_id 14 | * @property mixed $date 15 | * @property mixed $amount_paid 16 | * @property mixed $amount_reduced 17 | * @property mixed $business_year 18 | * @property mixed $entry_id 19 | * @property mixed $entry_pos 20 | * @property mixed $system_name 21 | */ 22 | class InvoicePayment extends AbstractType implements TypeInterface 23 | { 24 | /** 25 | * @var array 26 | */ 27 | protected $template = [ 28 | 'type_identifier' => 'INVOICE_PAYMENT', 29 | 'invoice_id' => null, 30 | 'date' => null, 31 | 'amount_paid' => null, 32 | 'amount_reduced' => null, 33 | 'business_year' => null, 34 | 'entry_id' => null, 35 | 'entry_pos' => null, 36 | 'system_name' => null, 37 | ]; 38 | 39 | /** 40 | * Formally validates the type data in $data attribute. 41 | * 42 | * @return bool Validation success 43 | */ 44 | #[\Override] 45 | public function validate(): bool 46 | { 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Type/SendShipmentNotification.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property string $type_identifier 14 | * @property int $delivery_id 15 | * @property int $client_id 16 | * @property int $customer_id 17 | * @property int $mode_of_shipment 18 | * @property int $sent_to_shipment_company 19 | * @property string $tracking_code 20 | * @property string $delivery_date_from 21 | */ 22 | class SendShipmentNotification extends AbstractType implements TypeInterface 23 | { 24 | /** 25 | * @var array 26 | */ 27 | protected $template = [ 28 | 'type_identifier' => 'SHIPMENT_NOTIFICATION_SEND', 29 | 'delivery_id' => null, 30 | 'client_id' => null, 31 | 'customer_id' => null, 32 | 'mode_of_shipment' => null, 33 | 'sent_to_shipment_company' => null, 34 | 'use_tracking_code' => null, 35 | 'delivery_date_from' => null, 36 | ]; 37 | 38 | /** 39 | * Formally validates the type data in $data attribute. 40 | * 41 | * @return bool Validation success 42 | */ 43 | #[\Override] 44 | public function validate(): bool 45 | { 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Type/ProductionOrderGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $production_order_id 15 | * @property $client_id 16 | * @property $product_id_produced 17 | * @property $product_id_component 18 | * @property $open 19 | * @property $production_order_date 20 | * @property $changed_only 21 | * @property $system_name 22 | */ 23 | class ProductionOrderGet extends AbstractType implements TypeInterface 24 | { 25 | /** 26 | * @var array 27 | */ 28 | protected $template = [ 29 | 'type_identifier' => 'PRODUCTION_ORDER_GET', 30 | 'production_order_id' => null, 31 | 'client_id' => null, 32 | 'product_id_produced' => null, 33 | 'product_id_component' => null, 34 | 'open' => null, 35 | 'production_order_date' => null, 36 | 'changed_only' => null, 37 | 'system_name' => null, 38 | ]; 39 | 40 | /** 41 | * Formally validates the type data in $data attribute. 42 | * 43 | * @return bool Validation success 44 | */ 45 | #[\Override] 46 | public function validate(): bool 47 | { 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Type/PaymentConfirmation.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $order_id 15 | * @property $date_of_payment 16 | * @property $amount 17 | * @property $fee 18 | * @property $currency 19 | * @property $paypal_email 20 | * @property $paypal_transactionnumber 21 | * @property $cost_center 22 | * @property $account_id 23 | */ 24 | class PaymentConfirmation extends AbstractType implements TypeInterface 25 | { 26 | /** 27 | * @var array 28 | */ 29 | protected $template = [ 30 | 'type_identifier' => 'PAYMENT_CONFIRMATION', 31 | 'order_id' => null, 32 | 'date_of_payment' => null, 33 | 'amount' => null, 34 | 'fee' => null, 35 | 'currency' => null, 36 | 'paypal_email' => null, 37 | 'paypal_transactionnumber' => null, 38 | 'cost_center' => null, 39 | 'account_id' => null, 40 | ]; 41 | 42 | /** 43 | * Formally validates the type data in $data attribute. 44 | * 45 | * @return bool Validation success 46 | */ 47 | #[\Override] 48 | public function validate(): bool 49 | { 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Type/TermsOfPayment.php: -------------------------------------------------------------------------------- 1 | 'CMXTOP', 26 | 'terms_of_payment_id' => null, 27 | 'description' => null, 28 | 'terms_of_payment' => null, 29 | // 5 30 | 'inactive' => null, 31 | 'payment_period_first' => null, 32 | 'payment_period_first_discount' => null, 33 | 'payment_period_second' => null, 34 | 'payment_period_second_discount' => null, 35 | // 10 36 | 'payment_period_third' => null, 37 | ]; 38 | 39 | /** 40 | * Formally validates the type data in $data attribute. 41 | * 42 | * @return bool Validation success 43 | */ 44 | #[\Override] 45 | public function validate(): bool 46 | { 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Type/Voucher.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $voucher_id 14 | * @property $client_id 15 | * @property $usage 16 | * @property $valid_from 17 | * @property $valid_to 18 | * @property $discount_percentage 19 | * @property $discount_total 20 | * @property $voucher_desc 21 | * @property $agent_id 22 | * @property $min_order_value 23 | * @property $currency 24 | */ 25 | class Voucher extends AbstractType implements TypeInterface 26 | { 27 | /** 28 | * @var array 29 | */ 30 | protected $template = [ 31 | 'type_identifier' => 'VOUCHER', 32 | 'voucher_id' => null, 33 | 'client_id' => null, 34 | 'usage' => null, 35 | 'valid_from' => null, 36 | 'valid_to' => null, 37 | 'discount_percentage' => null, 38 | 'discount_total' => null, 39 | 'voucher_desc' => null, 40 | 'agent_id' => null, 41 | 'min_order_value' => null, 42 | 'currency' => null, 43 | ]; 44 | 45 | /** 46 | * Formally validates the type data in $data attribute. 47 | * 48 | * @return bool Validation success 49 | */ 50 | #[\Override] 51 | public function validate(): bool 52 | { 53 | return true; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Type/PurchaseOrderGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $purchase_order_id 15 | * @property $client_id 16 | * @property $supplier_id 17 | * @property $product_id 18 | * @property $sent_only 19 | * @property $return_format 20 | * @property $changed_only 21 | * @property $system_name 22 | * @property $do_not_use_letter 23 | */ 24 | class PurchaseOrderGet extends AbstractType implements TypeInterface 25 | { 26 | /** 27 | * @var array 28 | */ 29 | protected $template = [ 30 | 'type_identifier' => 'PURCHASE_ORDER_GET', 31 | 'purchase_order_id' => null, 32 | 'client_id' => null, 33 | 'supplier_id' => null, 34 | 'product_id' => null, 35 | 'sent_only' => null, 36 | 'return_format' => null, 37 | 'changed_only' => null, 38 | 'system_name' => null, 39 | 'do_not_use_letter' => null, 40 | ]; 41 | 42 | /** 43 | * Formally validates the type data in $data attribute. 44 | * 45 | * @return bool Validation success 46 | */ 47 | #[\Override] 48 | public function validate(): bool 49 | { 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Type/ShipmentConfirm.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property string $type_identifier 14 | * @property int $delivery_id 15 | * @property int $client_id 16 | * @property int $customer_id 17 | * @property int $mode_of_shipment 18 | * @property int $sent_to_shipment_company 19 | * @property string $tracking_code 20 | * @property string $delivery_date_from 21 | * @property string $not_confirmed 22 | */ 23 | class ShipmentConfirm extends AbstractType implements TypeInterface 24 | { 25 | /** 26 | * @var array 27 | */ 28 | protected $template = [ 29 | 'type_identifier' => 'SHIPMENT_CONFIRM', 30 | 'delivery_id' => null, 31 | 'client_id' => null, 32 | 'customer_id' => null, 33 | 'mode_of_shipment' => null, 34 | 'sent_to_shipment_company' => null, 35 | 'use_tracking_code' => null, 36 | 'delivery_date_from' => null, 37 | 'not_confirmed' => null, 38 | ]; 39 | 40 | /** 41 | * Formally validates the type data in $data attribute. 42 | * 43 | * @return bool Validation success 44 | */ 45 | #[\Override] 46 | public function validate(): bool 47 | { 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Type/StockGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $product_id 16 | * @property $product_group 17 | * @property string $text 18 | * @property int $type 19 | * @property int $changed_only 20 | * @property string $system_name 21 | * @property string $date_effective 22 | */ 23 | class StockGet extends AbstractType implements TypeInterface 24 | { 25 | final public const TYPE_FREI = 0; 26 | final public const TYPE_GESPERRT = 1; 27 | final public const TYPE_FBA_BESTAND = 2; 28 | 29 | /** 30 | * @var array 31 | */ 32 | protected $template = [ 33 | 'type_identifier' => 'STOCK_GET', 34 | 'client_id' => null, 35 | 'product_id' => null, 36 | 'product_group' => null, 37 | 'text' => null, 38 | 'type' => null, 39 | 'changed_only' => null, 40 | 'system_name' => null, 41 | 'date_effective' => null, 42 | ]; 43 | 44 | /** 45 | * Formally validates the type data in $data attribute. 46 | * 47 | * @return bool Validation success 48 | */ 49 | #[\Override] 50 | public function validate(): bool 51 | { 52 | return true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Type/CustomerGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $customer_id 14 | * @property $client_id 15 | * @property $query 16 | * @property $follow 17 | * @property $zipcode 18 | * @property $address_group_id 19 | * @property $price_group_id 20 | * @property $discount_id 21 | * @property $agent_id 22 | * @property $changed_only 23 | * @property $system_name 24 | * @property $inactive 25 | */ 26 | class CustomerGet extends AbstractType implements TypeInterface 27 | { 28 | /** 29 | * @var array 30 | */ 31 | protected $template = [ 32 | 'type_identifier' => 'CUSTOMER_GET', 33 | 'customer_id' => null, 34 | 'client_id' => null, 35 | 'query' => null, 36 | 'follow-up' => null, 37 | 'zipcode' => null, 38 | 'address_group_id' => null, 39 | 'price_group_id' => null, 40 | 'discount_id' => null, 41 | 'agent_id' => null, 42 | 'changed_only' => null, 43 | 'system_name' => null, 44 | 'inactive' => null, 45 | ]; 46 | 47 | /** 48 | * Formally validates the type data in $data attribute. 49 | * 50 | * @return bool Validation success 51 | */ 52 | #[\Override] 53 | public function validate(): bool 54 | { 55 | return true; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Type/InvoiceOutputSet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property string $type_identifier 13 | * @property string $invoice_id 14 | * @property int $output_medium 15 | */ 16 | class InvoiceOutputSet extends AbstractType implements TypeInterface 17 | { 18 | /** 19 | * @var int 20 | */ 21 | final public const OUTPUT_MEDIUM_PRINT = 0; 22 | /** 23 | * @var int 24 | */ 25 | final public const OUTPUT_MEDIUM_EMAIL = 1; 26 | /** 27 | * @var int 28 | */ 29 | final public const OUTPUT_MEDIUM_FAX = 2; 30 | /** 31 | * @var int 32 | */ 33 | final public const OUTPUT_MEDIUM_MAIL = 3; 34 | /** 35 | * @var int 36 | */ 37 | final public const OUTPUT_MEDIUM_EMAIL_SIGNED = 4; 38 | /** 39 | * @var int 40 | */ 41 | final public const OUTPUT_MEDIUM_NO_OUTPUT = 100; 42 | 43 | /** 44 | * @var array 45 | */ 46 | protected $template = [ 47 | 'type_identifier' => 'INVOICE_OUTPUT_SET', 48 | 'invoice_id' => null, 49 | 'output_medium' => null, 50 | ]; 51 | 52 | /** 53 | * Formally validates the type data in $data attribute. 54 | * 55 | * @return bool Validation success 56 | */ 57 | #[\Override] 58 | public function validate(): bool 59 | { 60 | return true; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Type/ProductGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author Marcus Jaschen 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $product_id 16 | * @property $product_group 17 | * @property $price_group 18 | * @property $changed_only 19 | * @property $system_name 20 | * @property $website_id 21 | * @property $with_price_only 22 | */ 23 | class ProductGet extends AbstractType implements TypeInterface 24 | { 25 | /** 26 | * @var int 27 | */ 28 | final public const ONLY_WITH_PRICE = 1; 29 | /** 30 | * @var int 31 | */ 32 | final public const NOTONLY_WITH_PRICE = 0; 33 | 34 | /** 35 | * @var array 36 | */ 37 | protected $template = [ 38 | 'type_identifier' => 'PRODUCT_GET', 39 | 'client_id' => null, 40 | 'product_id' => null, 41 | 'product_group' => null, 42 | 'price_group' => null, 43 | 'changed_only' => null, 44 | 'system_name' => null, 45 | 'website_id' => null, 46 | 'with_price_only' => null, 47 | ]; 48 | 49 | /** 50 | * Formally validates the type data in $data attribute. 51 | * 52 | * @return bool Validation success 53 | */ 54 | #[\Override] 55 | public function validate(): bool 56 | { 57 | return true; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Type/StockAvailableGet.php: -------------------------------------------------------------------------------- 1 | 21 | * @author René Galle 22 | * 23 | * @property $type_identifier 24 | * @property $client_id 25 | * @property $product_id 26 | * @property $changed_only 27 | * @property $system_name 28 | */ 29 | class StockAvailableGet extends AbstractType implements TypeInterface 30 | { 31 | /** 32 | * @var array 33 | */ 34 | protected $template = [ 35 | 'type_identifier' => 'STOCK_AVAILABLE_GET', 36 | 'client_id' => null, 37 | 'product_id' => null, 38 | 'changed_only' => null, 39 | 'system_name' => null, 40 | ]; 41 | 42 | /** 43 | * Formally validates the type data in $data attribute. 44 | * 45 | * @return bool Validation success 46 | */ 47 | #[\Override] 48 | public function validate(): bool 49 | { 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Type/StockChangeGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $product_id 16 | * @property $date_from 17 | * @property $date_to 18 | * @property $customer_id 19 | * @property $supplier_id 20 | * @property $include_canceled 21 | * @property $changed_only 22 | * @property $system_name 23 | */ 24 | class StockChangeGet extends AbstractType implements TypeInterface 25 | { 26 | /** 27 | * @var array 28 | */ 29 | protected $template = [ 30 | // 1 31 | 'type_identifier' => 'STOCK_CHANGE_GET', 32 | 'client_id' => null, 33 | 'product_id' => null, 34 | 'date_from' => null, 35 | // 5 36 | 'date_to' => null, 37 | 'customer_id' => null, 38 | 'supplier_id' => null, 39 | 'include_canceled' => null, 40 | 'changed_only' => null, 41 | // 10 42 | 'system_name' => null, 43 | 'purchase_order_id' => null, 44 | 'delivery_id' => null, 45 | 'invoice_id' => null, 46 | 'production_order_id' => null, 47 | ]; 48 | 49 | /** 50 | * Formally validates the type data in $data attribute. 51 | * 52 | * @return bool Validation success 53 | */ 54 | #[\Override] 55 | public function validate(): bool 56 | { 57 | return true; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Type/SupplierInvoice.php: -------------------------------------------------------------------------------- 1 | 'CMXLRN', 23 | 'supplier_id' => null, 24 | 'client_id' => null, 25 | 'invoice_date' => null, 26 | // 5 27 | 'invoice_id' => null, 28 | 'amount_netto_with_default_tax' => null, 29 | 'amount_default_tax' => null, 30 | 'amount_netto_with_reduced_tax' => null, 31 | 'amount_reduced_tax' => null, 32 | // 10 33 | 'revenue_misc_account' => null, 34 | 'revenue_misc_amount' => null, 35 | 'currency' => null, 36 | 'contra_account' => null, 37 | 'credit_memo' => null, 38 | // 15 39 | 'receipt_text' => null, 40 | 'terms_of_payment' => null, 41 | 'account_default_tax' => null, 42 | 'account_reduced_tax' => null, 43 | 'cancelation' => null, 44 | // 20 45 | 'cost_center' => null, 46 | ]; 47 | 48 | /** 49 | * Formally validates the type data in $data attribute. 50 | * 51 | * @return bool Validation success 52 | */ 53 | #[\Override] 54 | public function validate(): bool 55 | { 56 | return true; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Type/SubscriptionGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author Jesus Ortiz 12 | * 13 | * @property $type_identifier 14 | * @property $customer_id 15 | * @property $client_id 16 | * @property $product_id 17 | * @property $next_invoice_from 18 | * @property $next_invoice_to 19 | * @property $currently_valid_only 20 | * @property $changed_only 21 | * @property $system_name 22 | */ 23 | class SubscriptionGet extends AbstractType implements TypeInterface 24 | { 25 | /** 26 | * @var int 27 | */ 28 | final public const FILTER_ALL = 0; 29 | /** 30 | * @var int 31 | */ 32 | final public const FILTER_CURRENTLY_VALID = 1; 33 | /** 34 | * @var int 35 | */ 36 | final public const FILTER_CHANGED_ONLY = 1; 37 | 38 | /** 39 | * Type data template. 40 | * 41 | * @var array 42 | */ 43 | protected $template = [ 44 | 'type_identifier' => 'ABO_GET', 45 | 'customer_id' => null, 46 | 'client_id' => null, 47 | 'product_id' => null, 48 | 'next_invoice_from' => null, 49 | 'next_invoice_to' => null, 50 | 'currently_valid_only' => null, 51 | 'changed_only' => null, 52 | 'system_name' => null, 53 | ]; 54 | 55 | /** 56 | * Formally validates the type data in $data attribute. 57 | * 58 | * @return bool Validation success 59 | */ 60 | #[\Override] 61 | public function validate(): bool 62 | { 63 | return true; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Type/DeliveryGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $delivery_id 15 | * @property $client_id 16 | * @property $customer_id 17 | * @property $delivery_date_from 18 | * @property $delivery_date_to 19 | * @property $issued_only 20 | * @property $returned_format 21 | * @property $changed_only 22 | * @property $system_name 23 | * @property $no_writing_paper 24 | * @property $order_id 25 | * @property $shipment_type 26 | * @property $mark_as_issued 27 | */ 28 | class DeliveryGet extends AbstractType implements TypeInterface 29 | { 30 | /** 31 | * @var array 32 | */ 33 | protected $template = [ 34 | 'type_identifier' => 'DELIVERY_GET', 35 | 'delivery_id' => null, 36 | 'client_id' => null, 37 | 'customer_id' => null, 38 | 'delivery_date_from' => null, 39 | 'delivery_date_to' => null, 40 | 'issued_only' => null, 41 | 'returned_format' => null, 42 | 'changed_only' => null, 43 | 'system_name' => null, 44 | 'no_writing_paper' => null, 45 | 'order_id' => null, 46 | 'shipment_type' => null, 47 | 'mark_as_issued' => null, 48 | ]; 49 | 50 | /** 51 | * Formally validates the type data in $data attribute. 52 | * 53 | * @return bool Validation success 54 | */ 55 | #[\Override] 56 | public function validate(): bool 57 | { 58 | return true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Type/BillOfMaterial.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $product_id 15 | * @property $client_id 16 | * @property $version 17 | * @property $assignment 18 | * @property $valid_from 19 | * @property $text 20 | * @property $reserved_1 21 | * @property $reserved_2 22 | * @property $reserved_3 23 | * @property $reserved_4 24 | * @property $reserved_5 25 | * @property $position 26 | * @property $component_product_id 27 | * @property $quantity 28 | * @property $allocation_base 29 | */ 30 | class BillOfMaterial extends AbstractType implements TypeInterface 31 | { 32 | /** 33 | * @var array 34 | */ 35 | protected $template = [ 36 | 'type_identifier' => 'CMXBOM', 37 | 'product_id' => null, 38 | 'client_id' => null, 39 | 'version' => null, 40 | 'assignment' => null, 41 | 'valid_from' => null, 42 | 'text' => null, 43 | 'reserved_1' => null, 44 | 'reserved_2' => null, 45 | 'reserved_3' => null, 46 | 'reserved_4' => null, 47 | 'reserved_5' => null, 48 | 'position' => null, 49 | 'component_product_id' => null, 50 | 'quantity' => null, 51 | 'allocation_base' => null, 52 | ]; 53 | 54 | /** 55 | * Formally validates the type data in $data attribute. 56 | * 57 | * @return bool Validation success 58 | */ 59 | #[\Override] 60 | public function validate(): bool 61 | { 62 | return true; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Type/MemberGet.php: -------------------------------------------------------------------------------- 1 | 'MEMBER_GET', 37 | 'customer_id' => null, 38 | 'client_id' => null, 39 | 'query' => null, 40 | // 5 41 | 'zipcode' => null, 42 | 'address_group_id' => null, 43 | 'exited_too' => null, 44 | 'changed_only' => null, 45 | 'system_name' => null, 46 | // 10 47 | 'reporting_date' => null, 48 | 'entrance_date_from' => null, 49 | 'entrance_date_to' => null, 50 | 'exit_date_from' => null, 51 | 'exit_date_to' => null, 52 | // 15 53 | 'birthday_from' => null, 54 | 'birthday_to' => null, 55 | ]; 56 | 57 | /** 58 | * Formally validates the type data in $data attribute. 59 | * 60 | * @return bool Validation success 61 | */ 62 | #[\Override] 63 | public function validate(): bool 64 | { 65 | return true; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Type/AccountDocumentGet.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * @property string $type_identifier 11 | * @property string $client_id 12 | * @property string $business_year 13 | * @property string $entry_id 14 | * @property string $account_id 15 | * @property string $cost_center 16 | * @property string $customer_id 17 | * @property string $supplier_id 18 | * @property string $equipment_id 19 | * @property string $invoice_id 20 | * @property string $travel_id 21 | * @property string $text 22 | * @property string $receipt_date_from 23 | * @property string $receipt_date_to 24 | * @property string $include_canceled 25 | * @property string $changed_only 26 | * @property string $system_name 27 | */ 28 | class AccountDocumentGet extends AbstractType implements TypeInterface 29 | { 30 | /** 31 | * @var array 32 | */ 33 | protected $template = [ 34 | 'type_identifier' => 'ACCDOC_GET', 35 | 'client_id' => null, 36 | 'business_year' => null, 37 | 'entry_id' => null, 38 | // 5 39 | 'account_id' => null, 40 | 'cost_center' => null, 41 | 'customer_id' => null, 42 | 'supplier_id' => null, 43 | 'equipment_id' => null, 44 | // 10 45 | 'invoice_id' => null, 46 | 'travel_id' => null, 47 | 'text' => null, 48 | 'receipt_date_from' => null, 49 | 'receipt_date_to' => null, 50 | // 15 51 | 'include_canceled' => null, 52 | 'changed_only' => null, 53 | 'system_name' => null, 54 | ]; 55 | 56 | /** 57 | * Formally validates the type data in $data attribute. 58 | * 59 | * @return bool Validation success 60 | */ 61 | #[\Override] 62 | public function validate(): bool 63 | { 64 | return true; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/MultiRequest.php: -------------------------------------------------------------------------------- 1 | types[] = $type; 21 | 22 | return $this; 23 | } 24 | 25 | /** 26 | * Adds multiple types for the request. 27 | * 28 | * @param TypeInterface[] $types 29 | */ 30 | public function push(array $types): self 31 | { 32 | foreach ($types as $type) { 33 | $this->add($type); 34 | } 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * @throws RequestErrorException 41 | */ 42 | private function buildRequestBody(): string 43 | { 44 | if (count($this->types) === 0) { 45 | throw new RequestErrorException('Request data empty', 7_294_275_601); 46 | } 47 | 48 | return implode( 49 | PHP_EOL, 50 | array_map( 51 | static fn($type): string => $type->getCsv(), 52 | $this->types 53 | ) 54 | ); 55 | } 56 | 57 | /** 58 | * @throws InvalidResponseMimeTypeException 59 | * @throws RequestFailedException 60 | * @throws RequestErrorException 61 | */ 62 | public function send(): ResponseInterface 63 | { 64 | $response = $this->client->request($this->buildRequestBody()); 65 | 66 | $responseType = new ResponseFactory($response, $this->responseParser); 67 | 68 | return $responseType->getResponseInstance(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Response/ResponseFactory.php: -------------------------------------------------------------------------------- 1 | getResponseMimeType(); 27 | } catch (\Exception $exception) { 28 | throw new InvalidResponseMimeTypeException('Cannot determine MIME type for response', 0, $exception); 29 | } 30 | 31 | if ($mimeType === 'application/zip') { 32 | return new ZipResponse($this->responseParser, $this->responseBody); 33 | } 34 | 35 | return new CsvResponse($this->responseParser, $this->responseBody); 36 | } 37 | 38 | /** 39 | * Determines MIME type of response body. 40 | * 41 | * @throws FileNotFoundException 42 | * @throws \RuntimeException 43 | */ 44 | protected function getResponseMimeType(): string|null 45 | { 46 | $tmpFilename = tempnam(sys_get_temp_dir(), 'collmexphp_'); 47 | 48 | if ($tmpFilename === false) { 49 | throw new \RuntimeException('Cannot create a tmp file for MIME type detection', 5276268253); 50 | } 51 | 52 | file_put_contents($tmpFilename, $this->responseBody); 53 | 54 | $file = new File($tmpFilename); 55 | $mimeType = $file->getMimeType(); 56 | 57 | unlink($tmpFilename); 58 | 59 | return $mimeType; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/CollmexField/Money.php: -------------------------------------------------------------------------------- 1 | 4) { 29 | throw new \InvalidArgumentException('Invalid round mode provided: ' . $roundMode . ' (allowed: 1..4)'); 30 | } 31 | 32 | return number_format(round($amount, 2, $roundMode), 2, ',', ''); 33 | } 34 | 35 | /** 36 | * Formats a money value given as cents (integer type) to Collmex format. 37 | * 38 | * Examples with default round mode: 39 | * 40 | * value given: 1999 41 | * Collmex format: 19,99 42 | * 43 | * value given: 85 44 | * Collmex format: 0,85 45 | */ 46 | public static function fromCents(int $cents): string 47 | { 48 | return number_format(round($cents / 100, 2), 2, ',', ''); 49 | } 50 | 51 | /** 52 | * Formats a money value given as \Money\Money to Collmex format. 53 | * 54 | * Examples with default round mode: 55 | * 56 | * value given: new \Money\Money(1999, new \Money\Currency('EUR')) 57 | * Collmex format: 19,99 58 | * 59 | * value given: new \Money\Money(85, new \Money\Currency('EUR')) 60 | * Collmex format: 0,85 61 | * 62 | * @see https://www.moneyphp.org/en/stable/ 63 | */ 64 | public static function fromMoney(\Money\Money $money): string 65 | { 66 | return self::fromCents((int)$money->getAmount()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Csv/Parser.php: -------------------------------------------------------------------------------- 1 | initCurl(); 23 | 24 | $requestBody = $this->buildRequestBody($body); 25 | 26 | curl_setopt( 27 | $this->curl, 28 | CURLOPT_POSTFIELDS, 29 | $this->convertEncodingForCollmex($requestBody) 30 | ); 31 | 32 | $response = curl_exec($this->curl); 33 | 34 | if ($response === false) { 35 | throw new RequestFailedException( 36 | 'Curl request failed: ' . curl_error($this->curl) . ' (' . curl_errno($this->curl) . ' )' 37 | ); 38 | } 39 | 40 | return (string)$response; 41 | } 42 | 43 | /** 44 | * @throws \RuntimeException 45 | */ 46 | protected function initCurl(): void 47 | { 48 | $curlHandle = curl_init($this->exchangeUrl); 49 | 50 | if ($curlHandle === false) { 51 | throw new \RuntimeException('Cannot create a curl handle', 9007569411); 52 | } 53 | 54 | $this->curl = $curlHandle; 55 | 56 | curl_setopt($this->curl, CURLOPT_POST, true); 57 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, ['Content-Type: text/csv']); 58 | curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, true); 59 | curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); 60 | } 61 | 62 | /** 63 | * Prepend the login credentials to the request body. 64 | */ 65 | protected function buildRequestBody(string $body): string 66 | { 67 | return $this->getLoginLine() . $body; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Type/SupplierAgreement.php: -------------------------------------------------------------------------------- 1 | 'CMXVAG', 40 | 'client_id' => null, 41 | 'supplier_id' => null, 42 | 'supplier_name' => null, 43 | // 5 44 | 'product_id' => null, 45 | 'product_description' => null, 46 | 'quantity_unit' => null, 47 | 'product_id_supplier' => null, 48 | 'description' => null, 49 | // 10 50 | 'packaging_unit' => null, 51 | 'tax_rate' => null, 52 | 'priority' => null, 53 | 'reserved_1' => null, 54 | 'reserved_2' => null, 55 | // 15 56 | 'reserved_3' => null, 57 | 'reserved_4' => null, 58 | 'reserved_5' => null, 59 | 'position' => null, 60 | 'valid_from' => null, 61 | // 20 62 | 'valid_to' => null, 63 | 'delivery_time' => null, 64 | 'price' => null, 65 | 'currency' => null, 66 | 'price_quantity' => null, 67 | ]; 68 | 69 | #[\Override] 70 | public function validate(): bool 71 | { 72 | return true; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Type/OpenItem.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $client_id 15 | * @property $business_year 16 | * @property $accounting_id 17 | * @property $position_number 18 | * @property $customer_id 19 | * @property $customer_name 20 | * @property $supplier_id 21 | * @property $supplier_name 22 | * @property $invoice_id 23 | * @property $receipt_date 24 | * @property $payment_conditions 25 | * @property $due_date 26 | * @property $delay 27 | * @property $dunning_level 28 | * @property $dunning_date 29 | * @property $dunning_charge 30 | * @property $amount 31 | * @property $payed 32 | * @property $open 33 | */ 34 | class OpenItem extends AbstractType implements TypeInterface 35 | { 36 | /** 37 | * @var array 38 | */ 39 | protected $template = [ 40 | // 1 41 | 'type_identifier' => 'OPEN_ITEM', 42 | 'client_id' => null, 43 | 'business_year' => null, 44 | 'accounting_id' => null, 45 | // 5 46 | 'position_number' => null, 47 | 'customer_id' => null, 48 | 'customer_name' => null, 49 | 'supplier_id' => null, 50 | 'supplier_name' => null, 51 | // 10 52 | 'invoice_id' => null, 53 | 'receipt_date' => null, 54 | 'payment_conditions' => null, 55 | 'due_date' => null, 56 | 'delay' => null, 57 | // 15 58 | 'dunning_level' => null, 59 | 'dunning_date' => null, 60 | 'dunning_charge' => null, 61 | 'amount' => null, 62 | 'payed' => null, 63 | // 20 64 | 'open' => null, 65 | ]; 66 | 67 | /** 68 | * Formally validates the type data in $data attribute. 69 | * 70 | * @return bool Validation success 71 | */ 72 | #[\Override] 73 | public function validate(): bool 74 | { 75 | return true; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Type/DifferentShippingAddress.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $customer_id 15 | * @property $client_id 16 | * @property $document_type 17 | * @property $output_medium 18 | * @property $salutation 19 | * @property $title 20 | * @property $firstname 21 | * @property $lastname 22 | * @property $company 23 | * @property $department 24 | * @property $street 25 | * @property $zipcode 26 | * @property $city 27 | * @property $country 28 | * @property $phone 29 | * @property $phone2 30 | * @property $fax 31 | * @property $skype_voip 32 | * @property $email 33 | * @property $annotation 34 | * @property $url 35 | * @property $no_mailings 36 | * @property $address_group 37 | */ 38 | class DifferentShippingAddress extends AbstractType implements TypeInterface 39 | { 40 | /** 41 | * @var array 42 | */ 43 | protected $template = [ 44 | 'type_identifier' => 'CMXEPF', 45 | 'customer_id' => null, 46 | 'client_id' => null, 47 | 'document_type' => null, 48 | 'output_medium' => null, 49 | 'salutation' => null, 50 | 'title' => null, 51 | 'firstname' => null, 52 | 'lastname' => null, 53 | 'company' => null, 54 | 'department' => null, 55 | 'street' => null, 56 | 'zipcode' => null, 57 | 'city' => null, 58 | 'country' => null, 59 | 'phone' => null, 60 | 'phone2' => null, 61 | 'fax' => null, 62 | 'skype_voip' => null, 63 | 'email' => null, 64 | 'annotation' => null, 65 | 'url' => null, 66 | 'no_mailings' => null, 67 | 'address_group' => null, 68 | ]; 69 | 70 | /** 71 | * Formally validates the type data in $data attribute. 72 | * 73 | * @return bool Validation success 74 | */ 75 | #[\Override] 76 | public function validate(): bool 77 | { 78 | return true; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Type/SalesOrderGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $order_id 14 | * @property $client_id 15 | * @property $customer_id 16 | * @property $order_date_start 17 | * @property $order_date_end 18 | * @property $customer_order_id 19 | * @property $format 20 | * @property $changed_only 21 | * @property $system_name 22 | * @property $only_created_by_system 23 | * @property $letter_paper 24 | */ 25 | class SalesOrderGet extends AbstractType implements TypeInterface 26 | { 27 | /** 28 | * @var int 29 | */ 30 | final public const FORMAT_CSV = 0; 31 | /** 32 | * @var int 33 | */ 34 | final public const FORMAT_ZIP = 1; 35 | 36 | /** 37 | * useable for 'changed_only' and 'only_created_by_system'. 38 | * 39 | * @var int 40 | */ 41 | final public const FILTER_ON = 1; 42 | /** 43 | * useable for 'changed_only' and 'only_created_by_system'. 44 | * 45 | * @var int 46 | */ 47 | final public const FILTER_OFF = 0; 48 | 49 | /** 50 | * @var int 51 | */ 52 | final public const WITH_LETTER_PAPER = 0; 53 | /** 54 | * @var int 55 | */ 56 | final public const NO_LETTER_PAPER = 1; 57 | 58 | /** 59 | * @var array 60 | */ 61 | protected $template = [ 62 | 'type_identifier' => 'SALES_ORDER_GET', 63 | 'order_id' => null, 64 | 'client_id' => null, 65 | 'customer_id' => null, 66 | 'order_date_start' => null, 67 | 'order_date_end' => null, 68 | 'customer_order_id' => null, 69 | 'format' => null, 70 | 'changed_only' => null, 71 | // 10 72 | 'system_name' => null, 73 | 'only_created_by_system' => null, 74 | 'letter_paper' => null, 75 | ]; 76 | 77 | /** 78 | * Formally validates the type data in $data attribute. 79 | * 80 | * @return bool Validation success 81 | */ 82 | #[\Override] 83 | public function validate(): bool 84 | { 85 | return true; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Type/Employee.php: -------------------------------------------------------------------------------- 1 | 'EMPLOYEE', 42 | 'employee_id' => null, 43 | 'client_id' => null, 44 | 'salutation' => null, 45 | // 5 46 | 'firstname' => null, 47 | 'lastname' => null, 48 | 'street' => null, 49 | 'zipcode' => null, 50 | 'city' => null, 51 | // 10 52 | 'country' => null, 53 | 'phone' => null, 54 | 'phone2' => null, 55 | 'email' => null, 56 | 'note' => null, 57 | // 15 58 | 'bank_iban' => null, 59 | 'bank_bic' => null, 60 | 'bank_name' => null, 61 | 'bank_account' => null, 62 | 'bank_code' => null, 63 | // 20 64 | 'bank_account_owner' => null, 65 | 'type' => null, 66 | 'joined_at' => null, 67 | 'left_at' => null, 68 | ]; 69 | 70 | /** 71 | * Formally validates the type data in $data attribute. 72 | * 73 | * @return bool Validation success 74 | */ 75 | #[\Override] 76 | public function validate(): bool 77 | { 78 | return true; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Type/InvoiceGet.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property mixed $type_identifier 13 | * @property mixed $invoice_id 14 | * @property mixed $client_id 15 | * @property mixed $customer_id 16 | * @property mixed $invoice_date_from 17 | * @property mixed $invoice_date_to 18 | * @property mixed $sent_only 19 | * @property mixed $format 20 | * @property mixed $changed_only 21 | * @property mixed $system_name 22 | * @property mixed $created_by_system_only 23 | * @property mixed $stationary_exclude 24 | * @property mixed $output_required 25 | * @property mixed $order_id 26 | * @property mixed $product_id 27 | */ 28 | class InvoiceGet extends AbstractType implements TypeInterface 29 | { 30 | /** 31 | * @var int 32 | */ 33 | final public const FORMAT_CSV = 0; 34 | /** 35 | * @var int 36 | */ 37 | final public const FORMAT_ZIP = 1; 38 | /** 39 | * @var int 40 | */ 41 | final public const FORMAT_ZIP_XML_ONLY = 2; 42 | /** 43 | * @var int 44 | */ 45 | final public const FORMAT_ZIP_XML_AND_PDF = 3; 46 | 47 | /** 48 | * @var int 49 | */ 50 | final public const STATIONARY_INCLUDE = 0; 51 | /** 52 | * @var int 53 | */ 54 | final public const STATIONARY_EXCLUDE = 1; 55 | 56 | /** 57 | * @var array 58 | */ 59 | protected $template = [ 60 | 'type_identifier' => 'INVOICE_GET', 61 | 'invoice_id' => null, 62 | 'client_id' => null, 63 | 'customer_id' => null, 64 | 'invoice_date_from' => null, 65 | 'invoice_date_to' => null, 66 | 'sent_only' => null, 67 | 'format' => null, 68 | 'changed_only' => null, 69 | 'system_name' => null, 70 | 'created_by_system_only' => null, 71 | 'stationary_exclude' => null, 72 | 'output_required' => null, 73 | 'order_id' => null, 74 | 'product_id' => null, 75 | ]; 76 | 77 | /** 78 | * Formally validates the type data in $data attribute. 79 | * 80 | * @return bool Validation success 81 | */ 82 | #[\Override] 83 | public function validate(): bool 84 | { 85 | return true; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Type/ApiNotification.php: -------------------------------------------------------------------------------- 1 | 'API_NOTIFICATION', 85 | 'system_name' => null, 86 | 'event' => null, 87 | 'url' => null, 88 | // 5 89 | 'inactive' => null, 90 | ]; 91 | 92 | /** 93 | * Formally validates the type data in $data attribute. 94 | * 95 | * @return bool Validation success 96 | */ 97 | #[\Override] 98 | public function validate(): bool 99 | { 100 | return true; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Type/ProductionOrder.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $production_order_id 15 | * @property $component_number 16 | * @property $client_id 17 | * @property $product_id_produced 18 | * @property $quantity_produced 19 | * @property $production_date_from 20 | * @property $production_date_to 21 | * @property $production_duration 22 | * @property $approved 23 | * @property $finished 24 | * @property $header_text 25 | * @property $bill_of_material_version 26 | * @property $reserved_01 27 | * @property $reserved_02 28 | * @property $reserved_03 29 | * @property $reserved_04 30 | * @property $product_id_component 31 | * @property $quantity_component 32 | * @property $due_date_component 33 | * @property $bill_of_material_position 34 | */ 35 | class ProductionOrder extends AbstractType implements TypeInterface 36 | { 37 | /** 38 | * Note: the field `bill_of_meterial_version` is misspelled. It will be fixed 39 | * in the next major release (as it's breaking backwards compatibility). 40 | * A pull request is already pending: https://github.com/mjaschen/collmex/pull/195. 41 | * 42 | * @var array 43 | */ 44 | protected $template = [ 45 | 'type_identifier' => 'PRODUCTION_ORDER', 46 | 'production_order_id' => null, 47 | 'component_number' => null, 48 | 'client_id' => null, 49 | 'product_id_produced' => null, 50 | 'quantity_produced' => null, 51 | 'production_date_from' => null, 52 | 'production_date_to' => null, 53 | 'production_duration' => null, 54 | 'approved' => null, 55 | 'finished' => null, 56 | 'header_text' => null, 57 | 'bill_of_material_version' => null, 58 | 'reserved_01' => null, 59 | 'reserved_02' => null, 60 | 'reserved_03' => null, 61 | 'reserved_04' => null, 62 | 'product_id_component' => null, 63 | 'quantity_component' => null, 64 | 'due_date_component' => null, 65 | 'bill_of_material_position' => null, 66 | ]; 67 | 68 | /** 69 | * Formally validates the type data in $data attribute. 70 | * 71 | * @return bool Validation success 72 | */ 73 | #[\Override] 74 | public function validate(): bool 75 | { 76 | return true; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Type/ShipmentOrdersGet.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $delivery_id 15 | * @property $client_id 16 | * @property $customer_id 17 | * @property $shipment_handover_id 18 | * @property $shipment_type 19 | * @property $handover_required 20 | * @property $delivery_date_from 21 | * @property $delivery_date_to 22 | * @property $shipment_date 23 | */ 24 | class ShipmentOrdersGet extends AbstractType implements TypeInterface 25 | { 26 | /** 27 | * @var int 28 | */ 29 | final public const SHIPMENT_HANDOVER_ID_UNIVERSAL_CSV = 1; 30 | /** 31 | * @var int 32 | */ 33 | final public const SHIPMENT_HANDOVER_ID_DHL_ONLINE_FRANKING = 2; 34 | /** 35 | * @var int 36 | */ 37 | final public const SHIPMENT_HANDOVER_ID_DHL_INTRASHIP = 3; 38 | /** 39 | * @var int 40 | */ 41 | final public const SHIPMENT_HANDOVER_ID_FULFILLMENT_SERVICE_PROVIDER = 4; 42 | /** 43 | * @var int 44 | */ 45 | final public const SHIPMENT_HANDOVER_ID_YOUR_GLS = 5; 46 | /** 47 | * @var int 48 | */ 49 | final public const SHIPMENT_HANDOVER_ID_HERMES = 6; 50 | /** 51 | * @var int 52 | */ 53 | final public const SHIPMENT_HANDOVER_ID_AMAZON_FBA = 7; 54 | /** 55 | * @var int 56 | */ 57 | final public const SHIPMENT_HANDOVER_ID_GERMAN_POST_INTERNET_STAMP = 8; 58 | /** 59 | * @var int 60 | */ 61 | final public const SHIPMENT_HANDOVER_ID_MY_DPD_BUSINESS = 9; 62 | /** 63 | * @var int 64 | */ 65 | final public const SHIPMENT_HANDOVER_ID_DHL_BUSINESS_CLIENT_PORTAL = 10; 66 | 67 | /** 68 | * @var array 69 | */ 70 | protected $template = [ 71 | 'type_identifier' => 'SHIPMENT_ORDERS_GET', 72 | 'delivery_id' => null, 73 | 'client_id' => null, 74 | 'customer_id' => null, 75 | 'shipment_handover_id' => null, 76 | 'shipment_type' => null, 77 | 'handover_required' => null, 78 | 'delivery_date_from' => null, 79 | 'delivery_date_to' => null, 80 | 'shipment_date' => null, 81 | ]; 82 | 83 | /** 84 | * Formally validates the type data in $data attribute. 85 | * 86 | * @return bool Validation success 87 | */ 88 | #[\Override] 89 | public function validate(): bool 90 | { 91 | return true; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/CollmexServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes( 24 | [ 25 | // @phpstan-ignore-next-line 26 | __DIR__ . '/../config/collmex.php' => config_path('collmex.php'), 27 | ], 28 | 'config' 29 | ); 30 | } 31 | 32 | public function register(): void 33 | { 34 | $this->mergeConfigFrom(__DIR__ . '/../config/collmex.php', 'collmex'); 35 | 36 | $this->registerClient(); 37 | $this->registerRequest(); 38 | $this->registerMultiRequest(); 39 | } 40 | 41 | protected function registerClient(): void 42 | { 43 | $this->app->singleton( 44 | 'collmex.client', 45 | static fn() => new CurlClient( 46 | // @phpstan-ignore-next-line 47 | config('collmex.user'), 48 | // @phpstan-ignore-next-line 49 | config('collmex.password'), 50 | // @phpstan-ignore-next-line 51 | config('collmex.customer'), 52 | ) 53 | ); 54 | 55 | $this->app->singleton(ClientInterface::class, 'collmex.client'); 56 | } 57 | 58 | protected function registerRequest(): void 59 | { 60 | $this->app->singleton( 61 | 'collmex.request', 62 | static fn($app) => new Request($app->make(ClientInterface::class)) 63 | ); 64 | 65 | $this->app->singleton(Request::class, 'collmex.request'); 66 | } 67 | 68 | protected function registerMultiRequest(): void 69 | { 70 | $this->app->singleton( 71 | 'collmex.multirequest', 72 | static fn($app) => new MultiRequest($app->make(ClientInterface::class)) 73 | ); 74 | 75 | $this->app->singleton(MultiRequest::class, 'collmex.multirequest'); 76 | } 77 | 78 | /** 79 | * @return string[] 80 | */ 81 | public function provides(): array 82 | { 83 | return [ 84 | 'collmex.client', 85 | 'collmex.request', 86 | 'collmex.multirequest', 87 | ClientInterface::class, 88 | Request::class, 89 | MultiRequest::class, 90 | ]; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/CollmexField/Date.php: -------------------------------------------------------------------------------- 1 | format('Ymd'); 19 | } 20 | 21 | /** 22 | * Converts Collmex date format to \DateTime 23 | * 24 | * @see https://www.collmex.de/c.cmx?1005,1,help,daten_importieren_datentypen_felder 25 | * 26 | * @throws InvalidArgumentException 27 | */ 28 | public static function toDateTime(string $value, ?DateTimeZone $timeZone = null): DateTime 29 | { 30 | if ($timeZone === null) { 31 | // Europe/Berlin is probably a sane choice here as Collmex targets german customers ... 32 | $timeZone = new DateTimeZone('Europe/Berlin'); 33 | } 34 | 35 | // ISO format YYYYMMDD 36 | if (preg_match('/^(\d{8})$/', $value) === 1) { 37 | return self::createDateTimeFromIsoFormat($value, $timeZone); 38 | } 39 | 40 | // German format DD.MM.YYYY 41 | if (preg_match('/^(\d{2}\.\d{2}\.\d{4})$/', $value) === 1) { 42 | return self::createDateTimeFromGermanFormat($value, $timeZone); 43 | } 44 | 45 | throw new InvalidArgumentException('Invalid date value: ' . $value, 3_746_303_620); 46 | } 47 | 48 | private static function createDateTimeFromIsoFormat(string $value, DateTimeZone $timeZone): DateTime 49 | { 50 | try { 51 | return new DateTime( 52 | substr($value, 0, 4) . '-' 53 | . substr($value, 4, 2) . '-' 54 | . substr($value, 6), 55 | $timeZone 56 | ); 57 | } catch (\Exception $exception) { 58 | throw new InvalidArgumentException( 59 | 'Cannot create DateTime object - invalid date string: ' . $value, 60 | 3_667_838_412, 61 | $exception 62 | ); 63 | } 64 | } 65 | 66 | public static function createDateTimeFromGermanFormat(string $value, ?DateTimeZone $timeZone): DateTime 67 | { 68 | try { 69 | return new DateTime( 70 | substr($value, 6) . '-' 71 | . substr($value, 3, 2) . '-' 72 | . substr($value, 0, 2), 73 | $timeZone 74 | ); 75 | } catch (\Exception $exception) { 76 | throw new InvalidArgumentException( 77 | 'Cannot create DateTime object - invalid date string: ' . $value, 78 | 2_033_421_948, 79 | $exception 80 | ); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Type/InvoiceOutput.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $client_id 14 | * @property $invoice_id 15 | * @property $output_medium 16 | * @property $output_required 17 | * @property $customer_id 18 | * @property $invoice_date_begin 19 | * @property $invoice_date_end 20 | * @property $max_invoices_amount 21 | * @property $also_deleted 22 | * @property $dont_book 23 | */ 24 | class InvoiceOutput extends AbstractType implements TypeInterface 25 | { 26 | /** 27 | * @var int 28 | */ 29 | final public const OUTPUT_MEDIUM_PRINT = 0; 30 | 31 | /** 32 | * @var int 33 | */ 34 | final public const OUTPUT_MEDIUM_EMAIL = 1; 35 | 36 | /** 37 | * @var int 38 | */ 39 | final public const OUTPUT_MEDIUM_FAX = 2; 40 | 41 | /** 42 | * @var int 43 | */ 44 | final public const OUTPUT_MEDIUM_MAIL = 3; 45 | 46 | /** 47 | * @var int 48 | */ 49 | final public const OUTPUT_MEDIUM_EMAIL_SIGNED = 4; 50 | 51 | /** 52 | * @var int 53 | */ 54 | final public const OUTPUT_MEDIUM_NO_OUTPUT = 100; 55 | 56 | /** 57 | * @var int 58 | */ 59 | final public const ALSO_DELETED_NO_DELETED = 0; 60 | 61 | /** 62 | * @var int 63 | */ 64 | final public const ALSO_DELETED_DELETED = 1; 65 | 66 | /** 67 | * @var int 68 | */ 69 | final public const DONT_BOOK_BOOK = 0; 70 | 71 | /** 72 | * @var int 73 | */ 74 | final public const DONT_BOOK_NO_BOOK = 1; 75 | 76 | /** 77 | * @var int 78 | */ 79 | final public const OUTPUT_REQUIRED_REQUIRED = 1; 80 | 81 | /** 82 | * @var int 83 | */ 84 | final public const OUTPUT_REQUIRED_NOT_REQUIRED = 0; 85 | 86 | /** 87 | * @var array 88 | */ 89 | protected $template = [ 90 | // 1 91 | 'type_identifier' => 'INVOICE_OUTPUT', 92 | 'client_id' => null, 93 | 'invoice_id' => null, 94 | 'output_medium' => null, 95 | // 5 96 | 'output_required' => null, 97 | 'customer_id' => null, 98 | 'invoice_date_begin' => null, 99 | 'invoice_date_end' => null, 100 | 'max_invoices_amount' => null, 101 | // 10 102 | 'also_deleted' => null, 103 | 'dont_book' => null, 104 | ]; 105 | 106 | /** 107 | * Formally validates the type data in $data attribute. 108 | * 109 | * @return bool Validation success 110 | */ 111 | #[\Override] 112 | public function validate(): bool 113 | { 114 | return true; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Type/AccountDocument.php: -------------------------------------------------------------------------------- 1 | 9 | * 10 | * @property string $type_identifier 11 | * @property string $client_id 12 | * @property string $business_year 13 | * @property string $entry_id 14 | * @property string $document_date 15 | * @property string $booked_on 16 | * @property string $entry_description 17 | * @property string $position 18 | * @property string $account_id 19 | * @property string $account_name 20 | * @property string $debit_or_credit 21 | * @property string $amount 22 | * @property string $customer_id 23 | * @property string $customer_name 24 | * @property string $supplier_id 25 | * @property string $supplier_name 26 | * @property string $equipment_id 27 | * @property string $equipment_name 28 | * @property string $canceled_entry_id 29 | * @property string $cost_centre 30 | * @property string $invoice_id 31 | * @property string $order_id 32 | * @property string $travel_id 33 | * @property string $assigned_id 34 | * @property string $assigned_business_year 35 | * @property string $assigned_position 36 | * @property string $document_id 37 | * @property string $receipt_date 38 | * @property string $entry_date 39 | * @property string $internal_memo 40 | */ 41 | class AccountDocument extends AbstractType implements TypeInterface 42 | { 43 | /** 44 | * @var array 45 | */ 46 | protected $template = [ 47 | 'type_identifier' => 'ACCDOC', 48 | 'client_id' => null, 49 | 'business_year' => null, 50 | 'entry_id' => null, 51 | // 5 52 | 'document_date' => null, 53 | 'booked_on' => null, 54 | 'entry_description' => null, 55 | 'position' => null, 56 | 'account_id' => null, 57 | // 10 58 | 'account_name' => null, 59 | 'debit_or_credit' => null, 60 | 'amount' => null, 61 | 'customer_id' => null, 62 | 'customer_name' => null, 63 | // 15 64 | 'supplier_id' => null, 65 | 'supplier_name' => null, 66 | 'equipment_id' => null, 67 | 'equipment_name' => null, 68 | 'canceled_entry_id' => null, 69 | // 20 70 | 'cost_centre' => null, 71 | 'invoice_id' => null, 72 | 'order_id' => null, 73 | 'travel_id' => null, 74 | 'assigned_id' => null, 75 | // 25 76 | 'assigned_business_year' => null, 77 | 'assigned_position' => null, 78 | 'document_id' => null, 79 | 'receipt_date' => null, 80 | 'entry_date' => null, 81 | // 30 82 | 'internal_memo' => null, 83 | ]; 84 | 85 | /** 86 | * Formally validates the type data in $data attribute. 87 | * 88 | * @return bool Validation success 89 | */ 90 | #[\Override] 91 | public function validate(): bool 92 | { 93 | return true; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Type/Subscription.php: -------------------------------------------------------------------------------- 1 | 14 | * 15 | * @property $type_identifier 16 | * @property $customer_id 17 | * @property $client_id 18 | * @property $valid_from 19 | * @property $valid_to 20 | * @property $product_id 21 | * @property $product_description 22 | * @property $price 23 | * @property $interval 24 | * @property $next_invoice 25 | */ 26 | class Subscription extends AbstractType implements TypeInterface 27 | { 28 | /** 29 | * @var int 30 | */ 31 | final public const INTERVAL_YEAR = 0; 32 | /** 33 | * @var int 34 | */ 35 | final public const INTERVAL_HALF_YEAR = 1; 36 | /** 37 | * @var int 38 | */ 39 | final public const INTERVAL_QUARTER = 2; 40 | /** 41 | * @var int 42 | */ 43 | final public const INTERVAL_MONTH = 3; 44 | /** 45 | * @var int 46 | */ 47 | final public const INTERVAL_YEAR_PREPAID = 4; 48 | /** 49 | * @var int 50 | */ 51 | final public const INTERVAL_HALF_YEAR_PREPAID = 5; 52 | /** 53 | * @var int 54 | */ 55 | final public const INTERVAL_QUARTER_PREPAID = 6; 56 | /** 57 | * @var int 58 | */ 59 | final public const INTERVAL_MONTH_PREPAID = 7; 60 | 61 | /** 62 | * Type data template. 63 | * 64 | * @var array 65 | */ 66 | protected $template = [ 67 | 'type_identifier' => 'CMXABO', 68 | 'customer_id' => null, 69 | 'client_id' => null, 70 | 'valid_from' => null, 71 | 'valid_to' => null, 72 | 'product_id' => null, 73 | 'product_description' => null, 74 | 'price' => null, 75 | 'interval' => null, 76 | 'next_invoice' => null, 77 | ]; 78 | 79 | /** 80 | * Formally validates the type data in $data attribute. 81 | * 82 | * @return bool Validation success 83 | */ 84 | #[\Override] 85 | public function validate(): bool 86 | { 87 | $dateOrEmptyValidator = new DateOrEmptyValidator(); 88 | 89 | if (!$dateOrEmptyValidator->validate($this->data['valid_from'])) { 90 | $this->validationErrors['valid_from'] = true; 91 | } 92 | if (!$dateOrEmptyValidator->validate($this->data['valid_to'])) { 93 | $this->validationErrors['valid_to'] = true; 94 | } 95 | 96 | $intervalValidator = new TimeIntervalValidator(); 97 | 98 | if (!$intervalValidator->validate($this->data['interval'])) { 99 | $this->validationErrors['interval'] = true; 100 | } 101 | 102 | return null === $this->validationErrors; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mjaschen/collmex", 3 | "description": "Collmex PHP SDK", 4 | "license": "MIT", 5 | "keywords": [ 6 | "collmex", 7 | "api" 8 | ], 9 | "authors": [ 10 | { 11 | "name": "Marcus Jaschen", 12 | "email": "mail@marcusjaschen.de", 13 | "homepage": "https://marcusjaschen.de/", 14 | "role": "maintainer and developer" 15 | }, 16 | { 17 | "name": "Oliver Klee", 18 | "email": "typo3-coding@oliverklee.de", 19 | "homepage": "https://www.oliverklee.de/", 20 | "role": "developer" 21 | } 22 | ], 23 | "support": { 24 | "issues": "https://github.com/mjaschen/collmex/issues", 25 | "source": "https://github.com/mjaschen/collmex" 26 | }, 27 | "require": { 28 | "php": "^8.1", 29 | "ext-curl": "*", 30 | "ext-fileinfo": "*", 31 | "ext-json": "*", 32 | "ext-zip": "*", 33 | "symfony/finder": "^5.4 || ^6.4 || ^7.0", 34 | "symfony/http-foundation": "^5.4 || ^6.4 || ^7.0", 35 | "symfony/mime": "^5.4 || ^6.4 || ^7.0", 36 | "symfony/string": "^5.4 || ^6.4 || ^7.0" 37 | }, 38 | "require-dev": { 39 | "dereuromark/composer-prefer-lowest": "^0.1.10", 40 | "ergebnis/composer-normalize": "^2.0", 41 | "friendsofphp/php-cs-fixer": "^3.0", 42 | "mockery/mockery": "^1.6.11", 43 | "moneyphp/money": "^4.0", 44 | "phpunit/phpunit": "^10.5", 45 | "rector/rector": "^2.0", 46 | "squizlabs/php_codesniffer": "^4.0", 47 | "phpstan/phpstan": "^2.0", 48 | "illuminate/support": "^10.0" 49 | }, 50 | "prefer-stable": true, 51 | "autoload": { 52 | "psr-4": { 53 | "MarcusJaschen\\Collmex\\": "src/" 54 | } 55 | }, 56 | "autoload-dev": { 57 | "psr-4": { 58 | "MarcusJaschen\\Collmex\\Tests\\": "tests/" 59 | } 60 | }, 61 | "config": { 62 | "allow-plugins": { 63 | "ergebnis/composer-normalize": true 64 | }, 65 | "preferred-install": { 66 | "*": "dist" 67 | } 68 | }, 69 | "extra": { 70 | "laravel": { 71 | "providers": [ 72 | "MarcusJaschen\\Collmex\\CollmexServiceProvider" 73 | ] 74 | } 75 | }, 76 | "scripts": { 77 | "ci": [ 78 | "@ci:static", 79 | "@ci:dynamic" 80 | ], 81 | "ci:dynamic": [ 82 | "@ci:tests" 83 | ], 84 | "ci:lint": "find config src tests -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l", 85 | "ci:phpstan": "./vendor/bin/phpstan analyse --configuration=phpstan.neon --memory-limit=1G", 86 | "ci:sniff": "./vendor/bin/phpcs config/ src/ tests/", 87 | "ci:static": [ 88 | "@ci:lint", 89 | "@ci:sniff", 90 | "@ci:phpstan" 91 | ], 92 | "ci:tests": "./vendor/bin/phpunit tests/", 93 | "fix:php-cs": "./vendor/bin/php-cs-fixer fix" 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Csv/Generator.php: -------------------------------------------------------------------------------- 1 | generateFromSingleLine($data); 23 | } 24 | 25 | return $this->generateFromMultipleLines($data); 26 | } 27 | 28 | public function generateFromSingleLine(array $line): string 29 | { 30 | return $this->createCsvString( 31 | /** @param resource $fileHandle */ 32 | function ($fileHandle) use ($line): void { 33 | fputcsv( 34 | $fileHandle, 35 | $this->insertSpecialPlaceholder($line), 36 | FormatInterface::DELIMITER, 37 | FormatInterface::ENCLOSURE, 38 | '', 39 | ); 40 | } 41 | ); 42 | } 43 | 44 | public function generateFromMultipleLines(array $lines): string 45 | { 46 | return $this->createCsvString( 47 | /** @param resource $fileHandle */ 48 | function ($fileHandle) use ($lines): void { 49 | foreach ($lines as $line) { 50 | fputcsv( 51 | $fileHandle, 52 | $this->insertSpecialPlaceholder($line), 53 | FormatInterface::DELIMITER, 54 | FormatInterface::ENCLOSURE, 55 | '', 56 | ); 57 | } 58 | } 59 | ); 60 | } 61 | 62 | /** 63 | * @throws \RuntimeException 64 | */ 65 | private function createCsvString(callable $csvCreator): string 66 | { 67 | $fileHandle = fopen('php://temp', 'wb'); 68 | 69 | if (!$fileHandle) { 70 | throw new RuntimeException('Cannot open temp file handle (php://temp)', 5_529_946_737); 71 | } 72 | 73 | $csvCreator($fileHandle); 74 | 75 | rewind($fileHandle); 76 | $csv = stream_get_contents($fileHandle); 77 | fclose($fileHandle); 78 | 79 | if ($csv === false) { 80 | throw new \RuntimeException('Cannot get stream contents (php://temp)', 5693338927); 81 | } 82 | 83 | // remove the temporary placeholder from the final CSV string 84 | return str_replace(self::PLACEHOLDER_FPUTCSV_BUG, '', $csv); 85 | } 86 | 87 | private function insertSpecialPlaceholder(array $csvLine): array 88 | { 89 | return array_map( 90 | /** @psalm-suppress MissingClosureParamType */ 91 | static function ($item) { 92 | if (!is_string($item)) { 93 | return $item; 94 | } 95 | 96 | return preg_replace('/(\\\\+)"/m', '$1' . self::PLACEHOLDER_FPUTCSV_BUG . '"', $item); 97 | }, 98 | $csvLine 99 | ); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Type/Quotation.php: -------------------------------------------------------------------------------- 1 | 'CMXQTN', 11 | 'quotation_id' => null, 12 | 'position' => null, 13 | 'quotation_type' => null, 14 | // 5 15 | 'client_id' => null, 16 | 'customer_id', 17 | 'customer_salutation', 18 | 'customer_title', 19 | 'customer_firstname', 20 | // 10 21 | 'customer_lastname', 22 | 'customer_company', 23 | 'customer_department', 24 | 'customer_street', 25 | 'customer_zipcode', 26 | // 15 27 | 'customer_city', 28 | 'customer_country', 29 | 'customer_phone', 30 | 'customer_phone_2', 31 | 'customer_fax', 32 | // 20 33 | 'customer_email', 34 | 'customer_bank_account', 35 | 'customer_bank_code', 36 | 'customer_bank_account_owner', 37 | 'customer_bank_iban', 38 | // 25 39 | 'customer_bank_bic', 40 | 'customer_bank_name', 41 | 'customer_vat_id', 42 | 'customer_private_person', 43 | 'quotation_date', 44 | // 30 45 | 'price_date', 46 | 'terms_of_payment', 47 | 'currency', 48 | 'price_group', 49 | 'discount_id', 50 | // 35 51 | 'discount_final', 52 | 'discount_reason', 53 | 'confirmation_text', 54 | 'final_text', 55 | 'internal_memo', 56 | // 40 57 | 'deleted', 58 | 'declined_date', 59 | 'language', 60 | 'employee_id', 61 | 'agent_id', 62 | // 45 63 | 'discount_final_2', 64 | 'discount_final_2_reason', 65 | 'status', 66 | 'quotation_limit_date', 67 | 'shipping_type', 68 | // 50 69 | 'shipping_costs', 70 | 'cod_costs', 71 | 'delivery_date', 72 | 'delivery_conditions', 73 | 'delivery_conditions_additional', 74 | // 55 75 | 'delivery_salutation', 76 | 'delivery_title', 77 | 'delivery_firstname', 78 | 'delivery_lastname', 79 | 'delivery_company', 80 | // 60 81 | 'delivery_department', 82 | 'delivery_street', 83 | 'delivery_zipcode', 84 | 'delivery_city', 85 | 'delivery_country', 86 | // 65 87 | 'delivery_phone', 88 | 'delivery_phone_2', 89 | 'delivery_fax', 90 | 'delivery_email', 91 | 'position_type', 92 | // 70 93 | 'product_id', 94 | 'product_description', 95 | 'quantity_unit', 96 | 'quantity', 97 | 'price', 98 | // 75 99 | 'price_quantity', 100 | 'position_discount', 101 | 'position_value', 102 | 'product_type', 103 | 'tax_rate', 104 | // 80 105 | 'foreign_tax', 106 | 'revenue_type', 107 | 'sum_over_positions', 108 | 'revenue', 109 | 'costs', 110 | // 85 111 | 'gross_profit', 112 | 'margin', 113 | 'costs_manual', 114 | ]; 115 | 116 | #[\Override] 117 | public function validate(): bool 118 | { 119 | return true; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/Response/ZipResponse.php: -------------------------------------------------------------------------------- 1 | extractFiles(); 23 | } 24 | 25 | /** 26 | * Returns an iterator of files matching the given file extension filter. 27 | * 28 | * @throws \InvalidArgumentException 29 | */ 30 | public function getFilesByType(string $type = 'pdf'): Finder 31 | { 32 | $finder = new Finder(); 33 | 34 | return $finder 35 | ->files() 36 | ->name('*.' . $type) 37 | ->depth(0) 38 | ->in($this->extractDirectory); 39 | } 40 | 41 | /** 42 | * Returns the CsvResponse instance for the (first) included CSV file. 43 | * 44 | * @throws InvalidZipResponseException 45 | * @throws \RuntimeException 46 | */ 47 | public function getCsvResponse(): CsvResponse 48 | { 49 | $iterator = $this->getFilesByType('csv'); 50 | 51 | foreach ($iterator as $file) { 52 | $csv = file_get_contents($file->getPathName()); 53 | 54 | if ($csv === false) { 55 | throw new \RuntimeException('Failed to read csv file: ' . $file->getPathName(), 1493429078); 56 | } 57 | 58 | return new CsvResponse($this->responseParser, $csv); 59 | } 60 | 61 | throw new InvalidZipResponseException('Zip Response doesn\'t contain the required CSV segment', 1567429445); 62 | } 63 | 64 | /** 65 | * @throws InvalidZipFileException 66 | * @throws \RuntimeException 67 | */ 68 | private function extractFiles(): void 69 | { 70 | $tmpFilename = tempnam(sys_get_temp_dir(), 'collmexphp_'); 71 | 72 | if ($tmpFilename === false) { 73 | throw new \RuntimeException('Failed to create temporary file for extracting Zip response', 9058757607); 74 | } 75 | 76 | file_put_contents($tmpFilename, $this->responseBody); 77 | 78 | $this->extractDirectory = dirname($tmpFilename) . DIRECTORY_SEPARATOR 79 | . 'collmexphp_extracted_' . basename($tmpFilename); 80 | 81 | $this->ensureExtractDirectoryExists(); 82 | 83 | if ($this->responseBody === '') { 84 | return; 85 | } 86 | 87 | $zip = new \ZipArchive(); 88 | 89 | if ($zip->open($tmpFilename) !== true) { 90 | throw new InvalidZipFileException('Cannot open ZIP archive: ' . $tmpFilename); 91 | } 92 | 93 | $zip->extractTo($this->extractDirectory); 94 | $zip->close(); 95 | } 96 | 97 | /** 98 | * @throws \RuntimeException 99 | */ 100 | private function ensureExtractDirectoryExists(): void 101 | { 102 | if (!mkdir($this->extractDirectory) && !is_dir($this->extractDirectory)) { 103 | throw new \RuntimeException( 104 | sprintf('Directory "%s" was not created', $this->extractDirectory), 105 | 1_631_246_675 106 | ); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Type/Supplier.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $supplier_id 14 | * @property $client_id 15 | * @property $salutation 16 | * @property $title 17 | * @property $firstname 18 | * @property $lastname 19 | * @property $company 20 | * @property $department 21 | * @property $street 22 | * @property $zipcode 23 | * @property $city 24 | * @property $annotation 25 | * @property $inactive 26 | * @property $country 27 | * @property $phone 28 | * @property $fax 29 | * @property $email 30 | * @property $bank_account 31 | * @property $bank_code 32 | * @property $iban 33 | * @property $bic 34 | * @property $bank_name 35 | * @property $tax_id 36 | * @property $vat_id 37 | * @property $terms_of_payment 38 | * @property $delivery_conditions 39 | * @property $delivery_conditions_additional 40 | * @property $output_medium 41 | * @property $bank_account_owner 42 | * @property $address_group_id 43 | * @property $supplier_customer_number 44 | * @property $currency 45 | * @property $phone_2 46 | * @property $output_language 47 | * @property $expense_account 48 | * @property $input_tax 49 | * @property $receipt_text 50 | * @property $cost_center 51 | * @property $private_person 52 | * @property $url 53 | */ 54 | class Supplier extends AbstractType implements TypeInterface 55 | { 56 | final public const INACTIVE_STATE_ACTIVE = 0; 57 | final public const INACTIVE_STATE_INACTIVE = 1; 58 | final public const INACTIVE_STATE_DELETE = 2; 59 | final public const INACTIVE_STATE_DELETE_IF_UNUSED = 3; 60 | 61 | final public const LANGUAGE_GERMAN = 0; 62 | final public const LANGUAGE_ENGLISH = 1; 63 | 64 | /** 65 | * Type data template. 66 | * 67 | * @var array 68 | */ 69 | protected $template = [ 70 | 'type_identifier' => 'CMXLIF', 71 | 'supplier_id' => null, 72 | 'client_id' => null, 73 | 'salutation' => null, 74 | // 5 75 | 'title' => null, 76 | 'firstname' => null, 77 | 'lastname' => null, 78 | 'company' => null, 79 | 'department' => null, 80 | // 10 81 | 'street' => null, 82 | 'zipcode' => null, 83 | 'city' => null, 84 | 'annotation' => null, 85 | 'inactive' => null, 86 | // 15 87 | 'country' => null, 88 | 'phone' => null, 89 | 'fax' => null, 90 | 'email' => null, 91 | 'bank_account' => null, 92 | // 20 93 | 'bank_code' => null, 94 | 'iban' => null, 95 | 'bic' => null, 96 | 'bank_name' => null, 97 | 'tax_id' => null, 98 | // 25 99 | 'vat_id' => null, 100 | 'terms_of_payment' => null, 101 | 'delivery_conditions' => null, 102 | 'delivery_conditions_additional' => null, 103 | 'output_medium' => null, 104 | // 30 105 | 'bank_account_owner' => null, 106 | 'address_group_id' => null, 107 | 'supplier_customer_number' => null, 108 | 'currency' => null, 109 | 'phone_2' => null, 110 | // 35 111 | 'output_language' => null, 112 | 'expense_account' => null, 113 | 'input_tax' => null, 114 | 'receipt_text' => null, 115 | 'cost_center' => null, 116 | // 40 117 | 'private_person' => null, 118 | 'url' => null, 119 | ]; 120 | 121 | /** 122 | * Formally validates the type data in $data attribute. 123 | * 124 | * @return bool Validation success 125 | */ 126 | #[\Override] 127 | public function validate(): bool 128 | { 129 | return true; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/Type/StockChange.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $stock_change_id 15 | * @property $stock_change_position 16 | * @property $product_id 17 | * @property $stock_change_type 18 | * @property $quantity 19 | * @property $destination_location_id 20 | * @property $destination_stock_type 21 | * @property $destination_batch 22 | * @property $destination_batch_labeling 23 | * @property $reserved_1 24 | * @property $reserved_2 25 | * @property $source_location_id 26 | * @property $source_stock_type 27 | * @property $source_batch 28 | * @property $reserved_3 29 | * @property $reserved_4 30 | * @property $reserved_5 31 | * @property $supplier_order_id 32 | * @property $supplier_order_position 33 | * @property $delivery_id 34 | * @property $delivery_position 35 | * @property $production_order_id 36 | * @property $production_order_position 37 | * @property $invoice_id 38 | * @property $invoice_position 39 | * @property $cancel_stock_change_id 40 | * @property $cancel_stock_change_pos 41 | * @property $notice 42 | * @property $booked_date 43 | * @property $booked_time 44 | */ 45 | class StockChange extends AbstractType implements TypeInterface 46 | { 47 | /** 48 | * @var int 49 | */ 50 | final public const STOCK_CHANGE_TYPE_WITHDRAWAL = 0; 51 | /** 52 | * @var int 53 | */ 54 | final public const STOCK_CHANGE_TYPE_INPUT = 1; 55 | /** 56 | * @var int 57 | */ 58 | final public const STOCK_CHANGE_TYPE_TRANSFER = 2; 59 | /** 60 | * @var int 61 | */ 62 | final public const STOCK_CHANGE_TYPE_INVENTORY = 3; 63 | 64 | /** 65 | * @var int 66 | */ 67 | final public const DESTINATION_STOCK_TYPE_FREE = 0; 68 | /** 69 | * @var int 70 | */ 71 | final public const DESTINATION_STOCK_TYPE_LOCKED = 1; 72 | 73 | /** 74 | * @var array 75 | */ 76 | protected $template = [ 77 | // 1 78 | 'type_identifier' => 'STOCK_CHANGE', 79 | 'stock_change_id' => null, 80 | 'stock_change_position' => null, 81 | 'product_id' => null, 82 | // 5 83 | 'stock_change_type' => null, 84 | 'quantity' => null, 85 | // 7-12: only STOCK_CHANGE_TYPE_INPUT, STOCK_CHANGE_TYPE_TRANSFER, STOCK_CHANGE_TYPE_INVENTORY 86 | 'destination_location_id' => null, 87 | 'destination_stock_type' => null, 88 | 'destination_batch' => null, 89 | // 10 90 | 'destination_batch_labeling' => null, 91 | 'reserved_1' => null, 92 | 'reserved_2' => null, 93 | // 13-18: only STOCK_CHANGE_TYPE_WITHDRAWAL, STOCK_CHANGE_TYPE_TRANSFER 94 | 'source_location_id' => null, 95 | 'source_stock_type' => null, 96 | // 15 97 | 'source_batch' => null, 98 | 'reserved_3' => null, 99 | 'reserved_4' => null, 100 | 'reserved_5' => null, 101 | 'purchase_order_id' => null, 102 | // 20 103 | 'purchase_order_position' => null, 104 | 'delivery_id' => null, 105 | 'delivery_position' => null, 106 | 'production_order_id' => null, 107 | 'production_order_position' => null, 108 | // 25 109 | 'invoice_id' => null, 110 | 'invoice_position' => null, 111 | 'cancel_stock_change_id' => null, 112 | 'cancel_stock_change_pos' => null, 113 | 'notice' => null, 114 | // 30 115 | 'booked_date' => null, 116 | 'booked_time' => null, 117 | ]; 118 | 119 | /** 120 | * Formally validates the type data in $data attribute. 121 | * 122 | * @return bool Validation success 123 | */ 124 | #[\Override] 125 | public function validate(): bool 126 | { 127 | return true; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/Type/Revenue.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $customer_id 14 | * @property $client_id 15 | * @property $invoice_date 16 | * @property $invoice_id 17 | * @property $amount_netto_with_default_tax 18 | * @property $amount_default_tax 19 | * @property $amount_netto_with_reduced_tax 20 | * @property $amount_reduced_tax 21 | * @property $amount_inner_community_revenue 22 | * @property $amount_export 23 | * @property $account_taxfree_revenue 24 | * @property $amount_taxfree_revenue 25 | * @property $currency 26 | * @property $contra_account 27 | * @property $invoice_type 28 | * @property $receipt_text 29 | * @property $terms_of_payment 30 | * @property $account_default_tax 31 | * @property $account_reduced_tax 32 | * @property $reserved_1 33 | * @property $reserved_2 34 | * @property $cancelation 35 | * @property $closing_invoice 36 | * @property $revenue_type 37 | * @property $system_name 38 | * @property $compensation_invoice_id 39 | * @property $cost_center 40 | */ 41 | class Revenue extends AbstractType implements TypeInterface 42 | { 43 | /** 44 | * @var int 45 | */ 46 | final public const INVOICE_TYPE_STANDARD = 0; 47 | /** 48 | * @var int 49 | */ 50 | final public const INVOICE_TYPE_CREDIT_MEMO = 1; 51 | /** 52 | * @var int 53 | */ 54 | final public const INVOICE_TYPE_DOWN_PAYMENT = 2; 55 | 56 | /** 57 | * @var null 58 | */ 59 | final public const CANCELATION_TYPE_NO_CANCELATION = null; 60 | /** 61 | * @var int 62 | */ 63 | final public const CANCELATION_TYPE_CANCELATION = 1; 64 | 65 | /** 66 | * @var int 67 | */ 68 | final public const REVENUE_TYPE_EXPORT = 10; 69 | /** 70 | * @var int 71 | */ 72 | final public const REVENUE_TYPE_INNER_COMMUNITY = 11; 73 | /** 74 | * @var int 75 | */ 76 | final public const REVENUE_TYPE_NO_TAX_EU = 12; 77 | /** 78 | * @var int 79 | */ 80 | final public const REVENUE_TYPE_NO_TAX = 13; 81 | /** 82 | * @var int 83 | */ 84 | final public const REVENUE_TYPE_TAX = 14; 85 | /** 86 | * @var int 87 | */ 88 | final public const REVENUE_TYPE_NO_TAX_3RD_PARTY_COUNTRY = 15; 89 | 90 | /** 91 | * @var array 92 | */ 93 | protected $template = [ 94 | 'type_identifier' => 'CMXUMS', 95 | 'customer_id' => null, 96 | 'client_id' => null, 97 | 'invoice_date' => null, 98 | // 5 99 | 'invoice_id' => null, 100 | 'amount_netto_with_default_tax' => null, 101 | 'amount_default_tax' => null, 102 | 'amount_netto_with_reduced_tax' => null, 103 | 'amount_reduced_tax' => null, 104 | // 10 105 | 'amount_inner_community_revenue' => null, 106 | 'amount_export' => null, 107 | 'account_taxfree_revenue' => null, 108 | 'amount_taxfree_revenue' => null, 109 | 'currency' => null, 110 | // 15 111 | 'contra_account' => null, 112 | 'invoice_type' => null, 113 | 'receipt_text' => null, 114 | 'terms_of_payment' => null, 115 | 'account_default_tax' => null, 116 | // 20 117 | 'account_reduced_tax' => null, 118 | 'reserved_1' => null, 119 | 'reserved_2' => null, 120 | 'cancelation' => null, 121 | 'closing_invoice' => null, 122 | // 25 123 | 'revenue_type' => null, 124 | 'system_name' => null, 125 | 'compensation_invoice_id' => null, 126 | // 28 127 | 'cost_center' => null, 128 | ]; 129 | 130 | /** 131 | * Formally validates the type data in $data attribute. 132 | * 133 | * @return bool Validation success 134 | */ 135 | #[\Override] 136 | public function validate(): bool 137 | { 138 | return true; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/Type/Address.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $address_number 14 | * @property $address_type 15 | * @property $salutation 16 | * @property $title 17 | * @property $first_name 18 | * @property $name 19 | * @property $company 20 | * @property $department 21 | * @property $street 22 | * @property $zipcode 23 | * @property $city 24 | * @property $note 25 | * @property $inactive 26 | * @property $country 27 | * @property $phone 28 | * @property $fax 29 | * @property $email 30 | * @property $bank_account 31 | * @property $bank_code 32 | * @property $bank_iban 33 | * @property $bank_bic 34 | * @property $bank_name 35 | * @property $tax_number 36 | * @property $vat_id 37 | * @property $no_mailings 38 | * @property $phone_2 39 | * @property $skype_voip 40 | * @property $url 41 | * @property $bank_account_owner 42 | * @property $resubmission 43 | * @property $address_group 44 | * @property $mediator 45 | * @property $mediator_company_number 46 | * @property $direct_debit_mandate_reference 47 | * @property $date_signature 48 | * @property $date_resubmission 49 | * @property $contact_person_address_number 50 | */ 51 | class Address extends AbstractType implements TypeInterface 52 | { 53 | /** 54 | * @var int 55 | */ 56 | final public const ADDRESS_TYPE_CUSTOMER_SUPPLIER_MEMBER = 0; 57 | 58 | /** 59 | * @var int 60 | */ 61 | final public const ADDRESS_TYPE_ADDRESS_MANAGEMENT = 3; 62 | 63 | /** 64 | * @var int 65 | */ 66 | final public const ADDRESS_TYPE_CONTACT = 4; 67 | 68 | /** 69 | * @var int 70 | */ 71 | final public const INACTIVE_ACTIVE = 0; 72 | 73 | /** 74 | * @var int 75 | */ 76 | final public const INACTIVE_INACTIVE = 1; 77 | 78 | /** 79 | * @var int 80 | */ 81 | final public const INACTIVE_DELETE = 2; 82 | 83 | /** 84 | * @var int 85 | */ 86 | final public const INACTIVE_DELETE_UNUSED = 3; 87 | 88 | /** 89 | * @var int 90 | */ 91 | final public const NO_MAILING_NOT_SET = 0; 92 | 93 | /** 94 | * @var int 95 | */ 96 | final public const NO_MAILING_NO_MAILING = 1; 97 | 98 | /** 99 | * Type data template. 100 | * 101 | * @var array 102 | */ 103 | protected $template = [ 104 | 'type_identifier' => 'CMXADR', 105 | 'address_number' => null, 106 | 'address_type' => null, 107 | 'salutation' => null, 108 | // 5 109 | 'title' => null, 110 | 'first_name' => null, 111 | 'name' => null, 112 | 'company' => null, 113 | 'department' => null, 114 | // 10 115 | 'street' => null, 116 | 'zipcode' => null, 117 | 'city' => null, 118 | 'note' => null, 119 | 'inactive' => null, 120 | // 15 121 | 'country' => null, 122 | 'phone' => null, 123 | 'fax' => null, 124 | 'email' => null, 125 | 'bank_account' => null, 126 | // 20 127 | 'bank_code' => null, 128 | 'bank_iban' => null, 129 | 'bank_bic' => null, 130 | 'bank_name' => null, 131 | 'tax_number' => null, 132 | // 25 133 | 'vat_id' => null, 134 | 'no_mailings' => null, 135 | 'phone_2' => null, 136 | 'skype_voip' => null, 137 | 'url' => null, 138 | // 30 139 | 'bank_account_owner' => null, 140 | 'resubmission' => null, 141 | 'address_group' => null, 142 | 'mediator' => null, 143 | 'mediator_company_number' => null, 144 | // 35 145 | 'direct_debit_mandate_reference' => null, 146 | 'date_signature' => null, 147 | 'date_resubmission' => null, 148 | 'contact_person_address_number' => null, 149 | ]; 150 | 151 | /** 152 | * Formally validates the type data in $data attribute. 153 | * 154 | * @return bool Validation success 155 | */ 156 | #[\Override] 157 | public function validate(): bool 158 | { 159 | return true; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/Type/Member.php: -------------------------------------------------------------------------------- 1 | 'CMXMGD', 114 | 'customer_id' => null, 115 | 'salutation' => null, 116 | 'title' => null, 117 | // 5 118 | 'firstname' => null, 119 | 'lastname' => null, 120 | 'company' => null, 121 | 'department' => null, 122 | 'street' => null, 123 | // 10 124 | 'zipcode' => null, 125 | 'city' => null, 126 | 'delete' => null, 127 | 'url' => null, 128 | 'country' => null, 129 | // 15 130 | 'phone' => null, 131 | 'fax' => null, 132 | 'email' => null, 133 | 'bank_account' => null, 134 | 'bank_code' => null, 135 | // 20 136 | 'iban' => null, 137 | 'bic' => null, 138 | 'bank_name' => null, 139 | 'mandate_reference' => null, 140 | 'mandate_reference_sign_date' => null, 141 | // 25 142 | 'birthday' => null, 143 | 'entrance_date' => null, 144 | 'exit_date' => null, 145 | 'annotation' => null, 146 | 'phone2' => null, 147 | // 30 148 | 'skype' => null, 149 | 'bankaccount_owner' => null, 150 | 'printout_medium' => null, 151 | 'address_group' => null, 152 | 'payment_agreement' => null, 153 | // 35 154 | 'payment_via' => null, 155 | 'printout_language' => null, 156 | 'cost_center' => null, 157 | 'no_mailings' => null, 158 | ]; 159 | 160 | /** 161 | * Formally validates the type data in $data attribute. 162 | * 163 | * @return bool Validation success 164 | */ 165 | #[\Override] 166 | public function validate(): bool 167 | { 168 | return true; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/TypeFactory.php: -------------------------------------------------------------------------------- 1 | Login::class, 53 | 'MESSAGE' => Message::class, 54 | 'NEW_OBJECT_ID' => NewObject::class, 55 | // regular types 56 | 'ACC_BAL' => AccountBalance::class, 57 | 'ACCDOC' => AccountDocument::class, 58 | 'ADRGRP' => AddressGroups::class, 59 | 'CMXABO' => Subscription::class, 60 | 'CMXADR' => Address::class, 61 | 'CMXBOM' => BillOfMaterial::class, 62 | 'CMXBTC' => Batch::class, 63 | 'CMXDLV' => Delivery::class, 64 | 'EMPLOYEE' => Employee::class, 65 | 'CMXEPF' => DifferentShippingAddress::class, 66 | 'CMXINV' => Invoice::class, 67 | 'CMXKND' => Customer::class, 68 | 'CMXLIF' => Supplier::class, 69 | 'CMXMGD' => Member::class, 70 | 'CMXORD-2' => CustomerOrder::class, 71 | 'CMXPOD' => PurchaseOrder::class, 72 | 'CMXPRD' => Product::class, 73 | 'CMXPRI' => ProductPrice::class, 74 | 'CMXSBI' => SupplierCredit::class, 75 | 'CMXSTK' => Stock::class, 76 | 'CMXTOP' => TermsOfPayment::class, 77 | 'CMXUMS' => Revenue::class, 78 | 'INVOICE_OUTPUT' => InvoiceOutput::class, 79 | 'INVOICE_PAYMENT' => InvoicePayment::class, 80 | 'OPEN_ITEM' => OpenItem::class, 81 | 'PRDGRP' => ProductGroup::class, 82 | 'PRICE_GROUP' => PriceGroup::class, 83 | 'PRODUCTION_ORDER' => ProductionOrder::class, 84 | 'PROJECT_STAFF' => ProjectStaff::class, 85 | 'STOCK_AVAILABLE' => StockAvailable::class, 86 | 'STOCK_CHANGE' => StockChange::class, 87 | 'TRACKING_NUMBER' => TrackingNumber::class, 88 | 'VOUCHER' => Voucher::class, 89 | ]; 90 | 91 | /** 92 | * @param array $data 93 | * @throws InvalidTypeIdentifierException 94 | */ 95 | public function getType(array $data): Type\AbstractType 96 | { 97 | $recordTypeIdentifier = $data[0] ?? null; 98 | 99 | if (!isset(self::RECORD_TYPE_CLASS_MAP[$recordTypeIdentifier])) { 100 | throw new InvalidTypeIdentifierException( 101 | 'Invalid/Unsupported Record Type Identifier: ' . $recordTypeIdentifier, 102 | 8_186_126_281 103 | ); 104 | } 105 | 106 | $class = self::RECORD_TYPE_CLASS_MAP[$recordTypeIdentifier]; 107 | 108 | if (class_exists($class)) { 109 | return new $class($data); 110 | } 111 | 112 | throw new InvalidTypeIdentifierException('Undefined Class: ' . $class, 4_512_716_533); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Response/CsvResponse.php: -------------------------------------------------------------------------------- 1 | |string> 19 | */ 20 | protected array $data; 21 | 22 | /** 23 | * @var AbstractType[]|null 24 | */ 25 | protected array|null $records = null; 26 | 27 | protected string|null $errorCode = null; 28 | 29 | protected string|null $errorMessage = null; 30 | 31 | /** 32 | * Line of request CSV where the error occurred. 33 | */ 34 | protected int|null $errorLine = null; 35 | 36 | public function __construct(protected Parser $parser, protected string $responseRaw) 37 | { 38 | $this->data = $this->convertEncodingFromCollmex( 39 | $this->parser->parse($responseRaw) 40 | ); 41 | } 42 | 43 | /** 44 | * Checks if the API request returned an error. 45 | */ 46 | public function isError(): bool 47 | { 48 | foreach ($this->data as $data) { 49 | if (!is_array($data)) { 50 | continue; 51 | } 52 | if (!$this->isErrorLine($data)) { 53 | continue; 54 | } 55 | 56 | $this->errorCode = $data[2]; 57 | $this->errorMessage = $data[3]; 58 | 59 | if (isset($data[4])) { 60 | $this->errorLine = (int)$data[4]; 61 | } 62 | 63 | return true; 64 | } 65 | 66 | return false; 67 | } 68 | 69 | public function getErrorMessage(): string|null 70 | { 71 | return $this->errorMessage; 72 | } 73 | 74 | public function getErrorCode(): string|null 75 | { 76 | return $this->errorCode; 77 | } 78 | 79 | public function getErrorLine(): int|null 80 | { 81 | return $this->errorLine; 82 | } 83 | 84 | /** 85 | * Returns the unparsed contents of the Collmex response (CSV string). 86 | */ 87 | public function getResponseRaw(): string 88 | { 89 | return $this->responseRaw; 90 | } 91 | 92 | /** 93 | * Returns an array of all response records as Type objects. 94 | * 95 | * @return AbstractType[]|null 96 | * 97 | * @throws InvalidTypeIdentifierException 98 | */ 99 | public function getRecords(): array|null 100 | { 101 | if ($this->isError()) { 102 | return null; 103 | } 104 | 105 | if (empty($this->data)) { 106 | return null; 107 | } 108 | 109 | if ($this->records === null) { 110 | $this->createTypeRecords(); 111 | } 112 | 113 | return $this->records; 114 | } 115 | 116 | /** 117 | * Returns the Type object of the first record (or null if response 118 | * contains no records). 119 | * 120 | * @return AbstractType|null 121 | * 122 | * @throws InvalidTypeIdentifierException 123 | */ 124 | public function getFirstRecord(): AbstractType|null 125 | { 126 | $records = $this->getRecords(); 127 | 128 | if (empty($records)) { 129 | return null; 130 | } 131 | 132 | return $records[0]; 133 | } 134 | 135 | /** 136 | * Populates the $records attribute with Type objects, created 137 | * from $data attribute. 138 | * 139 | * @throws InvalidTypeIdentifierException 140 | */ 141 | private function createTypeRecords(): void 142 | { 143 | $typeFactory = new TypeFactory(); 144 | 145 | foreach ($this->data as $data) { 146 | $this->records[] = $typeFactory->getType($data); 147 | } 148 | } 149 | 150 | /** 151 | * Converts response from Collmex API to UTF-8. 152 | * 153 | * @param array|string> $data 154 | * 155 | * @return string[] 156 | */ 157 | private function convertEncodingFromCollmex(array $data): array 158 | { 159 | $filter = new Windows1252ToUtf8(); 160 | 161 | return $filter->filterArray($data); 162 | } 163 | 164 | private function isErrorLine(array $lineData): bool 165 | { 166 | return $lineData[0] === 'MESSAGE' && $lineData[1] === 'E'; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/Type/AbstractType.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | abstract class AbstractType implements JsonSerializable 17 | { 18 | /** 19 | * All data fields for the type, ordered. 20 | * 21 | * @var array 22 | */ 23 | protected $template; 24 | 25 | /** 26 | * The type data fields (ordered). 27 | * 28 | * @var array 29 | */ 30 | protected $data; 31 | 32 | /** 33 | * @var bool[]|null 34 | */ 35 | protected $validationErrors; 36 | 37 | /** 38 | * @var Generator 39 | */ 40 | protected $csvGenerator; 41 | 42 | /** 43 | * @param array $data type data 44 | * 45 | * @throws InvalidFieldNameException 46 | */ 47 | public function __construct(array $data) 48 | { 49 | $this->csvGenerator = new Generator(); 50 | 51 | $this->populateData($data); 52 | } 53 | 54 | /** 55 | * Builds the CSV representation of the Collmex type. 56 | * 57 | * @return string CSV lines 58 | */ 59 | public function getCsv(): string 60 | { 61 | return $this->csvGenerator->generate([$this->data]); 62 | } 63 | 64 | /** 65 | * Returns the complete data array. 66 | * 67 | * @return array 68 | */ 69 | public function getData(): array 70 | { 71 | return $this->toArray(); 72 | } 73 | 74 | /** 75 | * @return array 76 | */ 77 | public function toArray(): array 78 | { 79 | return $this->data; 80 | } 81 | 82 | /** 83 | * @return string 84 | */ 85 | public function getJson(): string 86 | { 87 | return $this->toJson(); 88 | } 89 | 90 | /** 91 | * Returns the complete data as JSON. 92 | * 93 | * @return string 94 | */ 95 | public function toJson(): string 96 | { 97 | return json_encode($this->data, JSON_THROW_ON_ERROR); 98 | } 99 | 100 | /** 101 | * @return array 102 | */ 103 | #[\Override] 104 | public function jsonSerialize(): array 105 | { 106 | return $this->data; 107 | } 108 | 109 | /** 110 | * Read record field. 111 | * 112 | * @param string $name The field name 113 | * 114 | * @return mixed 115 | * 116 | * @throws InvalidFieldNameException 117 | */ 118 | public function __get(string $name) 119 | { 120 | if (isset($this->data[$name])) { 121 | return $this->data[$name]; 122 | } 123 | 124 | throw new InvalidFieldNameException( 125 | 'Cannot read field value; field "' . $name . '" does not exist in class ' . static::class 126 | ); 127 | } 128 | 129 | /** 130 | * @param string $name The field name 131 | * @param mixed $value The new field value 132 | * 133 | * @return void 134 | * 135 | * @throws InvalidFieldNameException 136 | */ 137 | public function __set(string $name, mixed $value): void 138 | { 139 | if ($name === 'type_identifier') { 140 | throw new InvalidFieldNameException('Cannot overwrite type identifier'); 141 | } 142 | 143 | if (array_key_exists($name, $this->template)) { 144 | $this->data[$name] = $value; 145 | 146 | return; 147 | } 148 | 149 | throw new InvalidFieldNameException( 150 | 'Cannot set field value; field "' . $name . '" does not exist in class ' . static::class 151 | ); 152 | } 153 | 154 | /** 155 | * @param string $name The field name 156 | * 157 | * @return bool 158 | */ 159 | public function __isset(string $name): bool 160 | { 161 | return isset($this->data[$name]); 162 | } 163 | 164 | /** 165 | * Populates the $data attribute with the given array. 166 | * 167 | * @param array $data if the array is indexed by numeric keys (first key 168 | * is checked), we'll merge the data by index order. 169 | * 170 | * @return void 171 | * 172 | * @throws InvalidFieldNameException 173 | */ 174 | protected function populateData(array $data): void 175 | { 176 | if (!isset($data[0])) { 177 | $this->assertValidFieldNames($data); 178 | $this->data = array_merge($this->template, $data); 179 | 180 | return; 181 | } 182 | 183 | $index = 0; 184 | 185 | foreach ($this->template as $key => $value) { 186 | if (isset($data[$index])) { 187 | $this->data[$key] = $data[$index]; 188 | } 189 | $index++; 190 | } 191 | } 192 | 193 | /** 194 | * Checks if all provided field names are valid: each given field name 195 | * must exist in $this->template. 196 | * 197 | * 198 | * @return void 199 | * @throws InvalidFieldNameException 200 | */ 201 | private function assertValidFieldNames(array $data): void 202 | { 203 | $fieldNamesDiff = array_diff_key($data, $this->template); 204 | 205 | if (count($fieldNamesDiff) !== 0) { 206 | throw new InvalidFieldNameException( 207 | 'Cannot populate data: invalid field name(s) detected: ' . implode(', ', array_keys($fieldNamesDiff)) 208 | ); 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/Type/Customer.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $customer_id 14 | * @property $client_id 15 | * @property $salutation 16 | * @property $title 17 | * @property $firstname 18 | * @property $lastname 19 | * @property $company 20 | * @property $department 21 | * @property $street 22 | * @property $zipcode 23 | * @property $city 24 | * @property $annotation 25 | * @property $inactive 26 | * @property $country 27 | * @property $phone 28 | * @property $fax 29 | * @property $email 30 | * @property $bank_account 31 | * @property $bank_code 32 | * @property $iban 33 | * @property $bic 34 | * @property $bank_name 35 | * @property $reserved_1 36 | * @property $vat_id 37 | * @property $terms_of_payment 38 | * @property $discount_id 39 | * @property $delivery_conditions 40 | * @property $delivery_conditions_additional 41 | * @property $output_medium 42 | * @property $bank_account_owner 43 | * @property $address_group_id 44 | * @property $ebay_account_name 45 | * @property $price_group_id 46 | * @property $currency 47 | * @property $agent_id 48 | * @property $cost_center 49 | * @property $follow_up_date 50 | * @property $delivery_block 51 | * @property $construction_service_provider 52 | * @property $customer_supplier_number 53 | * @property $output_language 54 | * @property $email_cc 55 | * @property $phone_2 56 | * @property $mandate_reference 57 | * @property $mandate_reference_sign_date 58 | * @property $dunning_block 59 | * @property $no_mailings 60 | * @property $private_person 61 | * @property $url 62 | * @property $partial_delivery_allowed 63 | * @property $partial_invoice_allowed 64 | * @property $created_at 65 | */ 66 | class Customer extends AbstractType implements TypeInterface 67 | { 68 | /** 69 | * @var int 70 | */ 71 | final public const STATUS_ACTIVE = 0; 72 | /** 73 | * @var int 74 | */ 75 | final public const STATUS_INACTIVE = 1; 76 | 77 | /** 78 | * @var int 79 | */ 80 | final public const OUTPUT_MEDIUM_PRINT = 0; 81 | /** 82 | * @var int 83 | */ 84 | final public const OUTPUT_MEDIUM_EMAIL = 1; 85 | /** 86 | * @var int 87 | */ 88 | final public const OUTPUT_MEDIUM_FAX = 2; 89 | /** 90 | * @var int 91 | */ 92 | final public const OUTPUT_MEDIUM_MAIL = 3; 93 | 94 | /** 95 | * @var int 96 | */ 97 | final public const NO_DELIVERY_BLOCK = 0; 98 | /** 99 | * @var int 100 | */ 101 | final public const DELIVERY_BLOCK = 1; 102 | 103 | /** 104 | * @var int 105 | */ 106 | final public const NO_CONSTRUCTION_SERVICE_PROVIDER = 0; 107 | /** 108 | * @var int 109 | */ 110 | final public const CONSTRUCTION_SERVICE_PROVIDER = 1; 111 | 112 | /** 113 | * @var int 114 | */ 115 | final public const LANGUAGE_GERMAN = 0; 116 | /** 117 | * @var int 118 | */ 119 | final public const LANGUAGE_ENGLISH = 1; 120 | 121 | /** 122 | * Type data template. 123 | * 124 | * @var array 125 | */ 126 | protected $template = [ 127 | // 1 128 | 'type_identifier' => 'CMXKND', 129 | 'customer_id' => null, 130 | 'client_id' => null, 131 | 'salutation' => null, 132 | // 5 133 | 'title' => null, 134 | 'firstname' => null, 135 | 'lastname' => null, 136 | 'company' => null, 137 | 'department' => null, 138 | // 10 139 | 'street' => null, 140 | 'zipcode' => null, 141 | 'city' => null, 142 | 'annotation' => null, 143 | 'inactive' => null, 144 | // 15 145 | 'country' => null, 146 | 'phone' => null, 147 | 'fax' => null, 148 | 'email' => null, 149 | 'bank_account' => null, 150 | // 20 151 | 'bank_code' => null, 152 | 'iban' => null, 153 | 'bic' => null, 154 | 'bank_name' => null, 155 | 'reserved_1' => null, 156 | // 25 157 | 'vat_id' => null, 158 | 'terms_of_payment' => null, 159 | 'discount_id' => null, 160 | 'delivery_conditions' => null, 161 | 'delivery_conditions_additional' => null, 162 | // 30 163 | 'output_medium' => null, 164 | 'bank_account_owner' => null, 165 | 'address_group_id' => null, 166 | 'ebay_account_name' => null, 167 | 'price_group_id' => null, 168 | // 35 169 | 'currency' => null, 170 | 'agent_id' => null, 171 | 'cost_center' => null, 172 | 'follow_up_date' => null, 173 | 'delivery_block' => null, 174 | // 40 175 | 'construction_service_provider' => null, 176 | 'customer_supplier_number' => null, 177 | 'output_language' => null, 178 | 'email_cc' => null, 179 | 'phone_2' => null, 180 | // 45 181 | 'mandate_reference' => null, 182 | 'mandate_reference_sign_date' => null, 183 | 'dunning_block' => null, 184 | 'no_mailings' => null, 185 | 'private_person' => null, 186 | // 50 187 | 'url' => null, 188 | 'partial_delivery_allowed' => null, 189 | 'partial_invoice_allowed' => null, 190 | 'created_at' => null, 191 | ]; 192 | 193 | /** 194 | * Formally validates the type data in $data attribute. 195 | * 196 | * @return bool Validation success 197 | */ 198 | #[\Override] 199 | public function validate(): bool 200 | { 201 | return true; 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/Type/SupplierCredit.php: -------------------------------------------------------------------------------- 1 | 11 | * 12 | * @property $type_identifier 13 | * @property $credit_id 14 | * @property $position 15 | * @property $credit_type 16 | * @property $client_id 17 | * @property $supplier_id 18 | * @property $supplier_salutation 19 | * @property $supplier_title 20 | * @property $supplier_firstname 21 | * @property $supplier_lastname 22 | * @property $supplier_company 23 | * @property $supplier_department 24 | * @property $supplier_street 25 | * @property $supplier_zipcode 26 | * @property $supplier_city 27 | * @property $supplier_country 28 | * @property $supplier_phone 29 | * @property $supplier_phone_2 30 | * @property $supplier_fax 31 | * @property $supplier_email 32 | * @property $supplier_bank_account 33 | * @property $supplier_bank_code 34 | * @property $supplier_bank_account_owner 35 | * @property $supplier_bank_iban 36 | * @property $supplier_bank_bic 37 | * @property $supplier_bank_name 38 | * @property $supplier_vat_id 39 | * @property $supplier_tax_id 40 | * @property $supplier_private 41 | * @property $credit_date 42 | * @property $terms_of_payment 43 | * @property $currency 44 | * @property $credit_text 45 | * @property $final_text 46 | * @property $internal_memo 47 | * @property $deleted 48 | * @property $language 49 | * @property $employee_id 50 | * @property $status 51 | * @property $reserved_1 52 | * @property $reserved_2 53 | * @property $reserved_3 54 | * @property $position_type 55 | * @property $product_id 56 | * @property $product_id_supplier 57 | * @property $product_description 58 | * @property $quantity_unit 59 | * @property $quantity 60 | * @property $price 61 | * @property $price_quantity 62 | * @property $position_value 63 | * @property $tax_rate 64 | */ 65 | class SupplierCredit extends AbstractType implements TypeInterface 66 | { 67 | /** 68 | * @var int 69 | */ 70 | final public const NOT_DELETED = 0; 71 | /** 72 | * @var int 73 | */ 74 | final public const DELETED = 1; 75 | 76 | /** 77 | * @var int 78 | */ 79 | final public const LANGUAGE_GERMAN = 0; 80 | /** 81 | * @var int 82 | */ 83 | final public const LANGUAGE_ENGLISH = 1; 84 | 85 | /** 86 | * @var int 87 | */ 88 | final public const STATUS_NEW = 0; 89 | /** 90 | * @var int 91 | */ 92 | final public const STATUS_OPEN = 10; 93 | /** 94 | * @var int 95 | */ 96 | final public const STATUS_PARTIALLY_SHIPPED = 20; 97 | /** 98 | * @var int 99 | */ 100 | final public const STATUS_DONE = 30; 101 | /** 102 | * @var int 103 | */ 104 | final public const STATUS_DELETED = 40; 105 | 106 | /** 107 | * @var int 108 | */ 109 | final public const POSITION_NORMAL = 0; 110 | /** 111 | * @var int 112 | */ 113 | final public const POSITION_TEXT = 2; 114 | 115 | /** 116 | * @var int 117 | */ 118 | final public const TAX_RATE_FULL = 0; 119 | /** 120 | * @var int 121 | */ 122 | final public const TAX_RATE_REDUCED = 1; 123 | /** 124 | * @var int 125 | */ 126 | final public const TAX_RATE_TAXFREE = 2; 127 | 128 | /** 129 | * @var array 130 | */ 131 | protected $template = [ 132 | 'type_identifier' => 'CMXSBI', 133 | 'credit_id' => null, 134 | 'position' => null, 135 | 'credit_type' => null, 136 | // 5 137 | 'client_id' => null, 138 | 'supplier_id' => null, 139 | 'supplier_salutation' => null, 140 | 'supplier_title' => null, 141 | 'supplier_firstname' => null, 142 | // 10 143 | 'supplier_lastname' => null, 144 | 'supplier_company' => null, 145 | 'supplier_department' => null, 146 | 'supplier_street' => null, 147 | 'supplier_zipcode' => null, 148 | // 15 149 | 'supplier_city' => null, 150 | 'supplier_country' => null, 151 | 'supplier_phone' => null, 152 | 'supplier_phone_2' => null, 153 | 'supplier_fax' => null, 154 | // 20 155 | 'supplier_email' => null, 156 | 'supplier_bank_account' => null, 157 | 'supplier_bank_code' => null, 158 | 'supplier_bank_account_owner' => null, 159 | 'supplier_bank_iban' => null, 160 | // 25 161 | 'supplier_bank_bic' => null, 162 | 'supplier_bank_name' => null, 163 | 'supplier_vat_id' => null, 164 | 'supplier_tax_id' => null, 165 | 'supplier_private_person' => null, 166 | // 30 167 | 'credit_date' => null, 168 | 'terms_of_payment' => null, 169 | 'currency' => null, 170 | 'credit_text' => null, 171 | 'final_text' => null, 172 | // 35 173 | 'internal_memo' => null, 174 | 'deleted' => null, 175 | 'language' => null, 176 | 'employee_id' => null, 177 | 'status' => null, 178 | // 40 179 | 'reserved_1' => null, 180 | 'reserved_2' => null, 181 | 'reserved_3' => null, 182 | 'position_type' => null, 183 | 'product_id' => null, 184 | // 45 185 | 'product_id_supplier' => null, 186 | 'product_description' => null, 187 | 'quantity_unit' => null, 188 | 'quantity' => null, 189 | 'price' => null, 190 | // 50 191 | 'price_quantity' => null, 192 | 'position_value' => null, 193 | 'tax_rate' => null, 194 | ]; 195 | 196 | /** 197 | * Formally validates the type data in $data attribute. 198 | * 199 | * @return bool Validation success 200 | */ 201 | #[\Override] 202 | public function validate(): bool 203 | { 204 | return true; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/Type/Delivery.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $delivery_id 15 | * @property $position 16 | * @property $kind_of_delivery 17 | * @property $client_id 18 | * @property $customer_id 19 | * @property $order_id 20 | * @property $customer_salutation 21 | * @property $customer_title 22 | * @property $customer_firstname 23 | * @property $customer_lastname 24 | * @property $customer_company 25 | * @property $customer_department 26 | * @property $customer_street 27 | * @property $customer_zip 28 | * @property $customer_city 29 | * @property $customer_country 30 | * @property $customer_tel 31 | * @property $customer_tel2 32 | * @property $customer_telefax 33 | * @property $customer_email 34 | * @property $customer_account_number 35 | * @property $customer_bank_routing_number 36 | * @property $customer_different_dipositor 37 | * @property $customer_IBAN 38 | * @property $customer_BIC 39 | * @property $customer_bank 40 | * @property $customer_business_tax_id 41 | * @property $customer_private_person 42 | * @property $order_id_at_customer 43 | * @property $delivery_date 44 | * @property $delivery_note 45 | * @property $closing_note 46 | * @property $internal_note 47 | * @property $deleted 48 | * @property $completed 49 | * @property $status 50 | * @property $lang 51 | * @property $issuer_id 52 | * @property $weight 53 | * @property $amount_to_be_collected 54 | * @property $currency 55 | * @property $tracking_code 56 | * @property $mode_of_shipment 57 | * @property $delivery_specifications 58 | * @property $delivery_additions 59 | * @property $delivery_address_salutation 60 | * @property $delivery_address_title 61 | * @property $delivery_address_firstname 62 | * @property $delivery_address_lastname 63 | * @property $delivery_address_company 64 | * @property $delivery_address_department 65 | * @property $delivery_address_street 66 | * @property $delivery_address_zip 67 | * @property $delivery_address_city 68 | * @property $delivery_address_country 69 | * @property $delivery_address_tel 70 | * @property $delivery_address_tel2 71 | * @property $delivery_address_telefax 72 | * @property $delivery_address_email 73 | * @property $position_type 74 | * @property $product_id 75 | * @property $product_description 76 | * @property $unit 77 | * @property $quantity 78 | * @property $customer_order_position 79 | * @property $ean 80 | * @property $handover_required 81 | * @property $last_handover 82 | */ 83 | class Delivery extends AbstractType implements TypeInterface 84 | { 85 | /** 86 | * @var array 87 | */ 88 | protected $template = [ 89 | // 1 90 | 'type_identifier' => 'CMXDLV', 91 | 'delivery_id' => null, 92 | 'position' => null, 93 | // reserved 94 | 'kind_of_delivery' => null, 95 | // 5 96 | 'client_id' => null, 97 | 'customer_id' => null, 98 | 'order_id' => null, 99 | 'customer_salutation' => null, 100 | 'customer_title' => null, 101 | // 10 102 | 'customer_firstname' => null, 103 | 'customer_lastname' => null, 104 | 'customer_company' => null, 105 | 'customer_department' => null, 106 | 'customer_street' => null, 107 | // 15 108 | 'customer_zip' => null, 109 | 'customer_city' => null, 110 | 'customer_country' => null, 111 | 'customer_tel' => null, 112 | 'customer_tel2' => null, 113 | // 20 114 | 'customer_telefax' => null, 115 | 'customer_email' => null, 116 | 'customer_account_number' => null, 117 | 'customer_bank_routing_number' => null, 118 | 'customer_different_dipositor' => null, 119 | // 25 120 | 'customer_IBAN' => null, 121 | 'customer_BIC' => null, 122 | 'customer_bank' => null, 123 | 'customer_business_tax_id' => null, 124 | 'customer_private_person' => null, 125 | // 30 126 | 'order_id_at_customer' => null, 127 | 'delivery_date' => null, 128 | 'delivery_note' => '(NULL)', 129 | 'closing_note' => '(NULL)', 130 | 'internal_note' => null, 131 | // 35 132 | 'deleted' => null, 133 | 'completed' => null, 134 | 'status' => null, 135 | 'lang' => null, 136 | 'issuer_id' => null, 137 | // 40 138 | 'weight' => null, 139 | 'amount_to_be_collected' => null, 140 | 'currency' => null, 141 | 'tracking_code' => null, 142 | 'mode_of_shipment' => null, 143 | // 45 144 | 'delivery_specifications' => null, 145 | 'delivery_additions' => null, 146 | 'delivery_address_salutation' => null, 147 | 'delivery_address_title' => null, 148 | 'delivery_address_firstname' => null, 149 | // 50 150 | 'delivery_address_lastname' => null, 151 | 'delivery_address_company' => null, 152 | 'delivery_address_department' => null, 153 | 'delivery_address_street' => null, 154 | 'delivery_address_zip' => null, 155 | // 55 156 | 'delivery_address_city' => null, 157 | 'delivery_address_country' => null, 158 | 'delivery_address_tel' => null, 159 | 'delivery_address_tel2' => null, 160 | 'delivery_address_telefax' => null, 161 | // 60 162 | 'delivery_address_email' => null, 163 | 'position_type' => null, 164 | 'product_id' => null, 165 | 'product_description' => null, 166 | 'unit' => null, 167 | // 65 168 | 'quantity' => null, 169 | 'customer_order_position' => null, 170 | 'ean' => null, 171 | 'handover_required' => null, 172 | 'last_handover' => null, 173 | // 70 174 | 'batches' => null, 175 | 'batches_descriptions' => null, 176 | 'commodity_code' => null, 177 | ]; 178 | 179 | /** 180 | * Formally validates the type data in $data attribute. 181 | * 182 | * @return bool Validation success 183 | */ 184 | #[\Override] 185 | public function validate(): bool 186 | { 187 | return true; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/Type/PurchaseOrder.php: -------------------------------------------------------------------------------- 1 | 11 | * @author René Galle 12 | * 13 | * @property $type_identifier 14 | * @property $purchase_order_id 15 | * @property $position 16 | * @property $kind_of_purchase_order 17 | * @property $client_id 18 | * @property $supplier_id 19 | * @property $supplier_salutation 20 | * @property $supplier_title 21 | * @property $supplier_firstname 22 | * @property $supplier_lastname 23 | * @property $supplier_company 24 | * @property $supplier_department 25 | * @property $supplier_street 26 | * @property $supplier_zip 27 | * @property $supplier_city 28 | * @property $supplier_country 29 | * @property $supplier_tel 30 | * @property $supplier_tel2 31 | * @property $supplier_telefax 32 | * @property $supplier_email 33 | * @property $supplier_account_number 34 | * @property $supplier_bank_routing_number 35 | * @property $supplier_different_dipositor 36 | * @property $supplier_IBAN 37 | * @property $supplier_BIC 38 | * @property $supplier_bank 39 | * @property $supplier_business_tax_id 40 | * @property $supplier_tax_id 41 | * @property $supplier_private_person 42 | * @property $purchase_order_date 43 | * @property $payment_conditions 44 | * @property $currency 45 | * @property $purchase_order_note 46 | * @property $closing_note 47 | * @property $internal_note 48 | * @property $deleted 49 | * @property $completed 50 | * @property $lang 51 | * @property $issuer_id 52 | * @property $delivery_conditions 53 | * @property $delivery_additions 54 | * @property $delivery_address_salutation 55 | * @property $delivery_address_title 56 | * @property $delivery_address_firstname 57 | * @property $delivery_address_lastname 58 | * @property $delivery_address_company 59 | * @property $delivery_address_department 60 | * @property $delivery_address_street 61 | * @property $delivery_address_zip 62 | * @property $delivery_address_city 63 | * @property $delivery_address_country 64 | * @property $delivery_address_tel 65 | * @property $delivery_address_tel2 66 | * @property $delivery_address_telefax 67 | * @property $delivery_address_email 68 | * @property $status 69 | * @property $sales_order_id 70 | * @property $reserved_1 71 | * @property $reserved_2 72 | * @property $position_type 73 | * @property $product_id 74 | * @property $product_id_of_supplier 75 | * @property $product_description 76 | * @property $unit 77 | * @property $quantity 78 | * @property $delivery_date 79 | * @property $unit_price 80 | * @property $price_quantity 81 | * @property $packaging_unit 82 | * @property $delivery_time 83 | * @property $position_value 84 | * @property $purchase_order_position 85 | */ 86 | class PurchaseOrder extends AbstractType implements TypeInterface 87 | { 88 | /** 89 | * @var array 90 | */ 91 | protected $template = [ 92 | // 1 93 | 'type_identifier' => 'CMXPOD', 94 | 'purchase_order_id' => null, 95 | 'position' => null, 96 | // reserved 97 | 'kind_of_purchase_order' => null, 98 | // 5 99 | 'client_id' => null, 100 | 'supplier_id' => null, 101 | 'supplier_salutation' => null, 102 | 'supplier_title' => null, 103 | 'supplier_firstname' => null, 104 | // 10 105 | 'supplier_lastname' => null, 106 | 'supplier_company' => null, 107 | 'supplier_department' => null, 108 | 'supplier_street' => null, 109 | 'supplier_zip' => null, 110 | // 15 111 | 'supplier_city' => null, 112 | 'supplier_country' => null, 113 | 'supplier_tel' => null, 114 | 'supplier_tel2' => null, 115 | 'supplier_telefax' => null, 116 | // 20 117 | 'supplier_email' => null, 118 | 'supplier_account_number' => null, 119 | 'supplier_bank_routing_number' => null, 120 | 'supplier_different_dipositor' => null, 121 | 'supplier_IBAN' => null, 122 | // 25 123 | 'supplier_BIC' => null, 124 | 'supplier_bank' => null, 125 | 'supplier_business_tax_id' => null, 126 | 'supplier_tax_id' => null, 127 | 'supplier_private_person' => null, 128 | // 30 129 | 'purchase_order_date' => null, 130 | 'payment_conditions' => null, 131 | 'currency' => null, 132 | 'purchase_order_note' => null, 133 | 'closing_note' => null, 134 | // 35 135 | 'internal_note' => null, 136 | 'deleted' => null, 137 | 'completed' => null, 138 | 'lang' => null, 139 | 'issuer_id' => null, 140 | // 40 141 | 'delivery_conditions' => null, 142 | 'delivery_additions' => null, 143 | 'delivery_address_salutation' => null, 144 | 'delivery_address_title' => null, 145 | 'delivery_address_firstname' => null, 146 | // 45 147 | 'delivery_address_lastname' => null, 148 | 'delivery_address_company' => null, 149 | 'delivery_address_department' => null, 150 | 'delivery_address_street' => null, 151 | 'delivery_address_zip' => null, 152 | // 50 153 | 'delivery_address_city' => null, 154 | 'delivery_address_country' => null, 155 | 'delivery_address_tel' => null, 156 | 'delivery_address_tel2' => null, 157 | 'delivery_address_telefax' => null, 158 | // 55 159 | 'delivery_address_email' => null, 160 | 'status' => null, 161 | 'sales_order_id' => null, 162 | // reserved 163 | 'reserved_1' => null, 164 | // reserved 165 | 'reserved_2' => null, 166 | // 60 167 | 'position_type' => null, 168 | 'product_id' => null, 169 | 'product_id_of_supplier' => null, 170 | 'product_description' => null, 171 | 'unit' => null, 172 | // 65 173 | 'quantity' => null, 174 | 'delivery_date' => null, 175 | 'unit_price' => null, 176 | 'price_quantity' => null, 177 | 'packaging_unit' => null, 178 | // 70 179 | 'delivery_time' => null, 180 | 'position_value' => null, 181 | // 72 182 | 'purchase_order_position' => null, 183 | ]; 184 | 185 | /** 186 | * Formally validates the type data in $data attribute. 187 | * 188 | * @return bool Validation success 189 | */ 190 | #[\Override] 191 | public function validate(): bool 192 | { 193 | return true; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /docs/collmex.adoc: -------------------------------------------------------------------------------- 1 | = Collmex PHP SDK 2 | Marcus Jaschen 3 | v0.6.2, 2016-03-22 4 | :toc: left 5 | :toclevels: 3 6 | :source-highlighter: coderay 7 | :icons: font 8 | :stem: latexmath 9 | 10 | == Introduction 11 | 12 | This library provides a wrapper for the Collmex API. Collmex is an online 13 | accounting service which provides an API. 14 | 15 | This library is not complete yet, some record types (and maybe some 16 | features) are missing. 17 | 18 | Please create a Pull Request if you've implemented a new type/feature 19 | or create https://github.com/mjaschen/collmex/issues[Issues] for 20 | bugs/feature requests. 21 | 22 | There is (or least should be …) a *Type* class for every Collmex 23 | record type ("Satzart"). Currently only the base types (`MESSAGE`, 24 | `LOGIN`, `NEW_OBJECT_ID`) and a few normal record types (e. g. `CMXKND`, 25 | `CMXINV`, `CMXABO`, `CMXUMS`) are implemented. 26 | 27 | == Requirements 28 | 29 | The Collmex PHP SDK requires PHP 5.5.9. If you're still using older 30 | PHP versions, you can install the 0.4 branch for PHP 5.4 compatibility 31 | or the 0.3 branch for PHP 5.3 compatibility. New features will only go 32 | into the current branch. Bug fixes _may_ be merged back into the old 33 | branches, but don't pin me down on that. 34 | 35 | == Installation 36 | 37 | Using Composer, just add it to your `composer.json` by running: 38 | 39 | ``` 40 | php composer.phar require mjaschen/collmex 41 | ``` 42 | 43 | == Examples 44 | 45 | === Load data from Collmex 46 | 47 | Let's dive in with an example, as this is the easiest way to understand 48 | how the Collmex PHP SDK works. The follwing code loads a customer record 49 | from the Collmex API: 50 | 51 | [source,php] 52 | ---- 53 | 61 | 62 | // create request object 63 | $collmexRequest = new Request($collmexClient); <2> 64 | 65 | // create a record type; we're querying the API for customer with ID=12345 66 | $getCustomerType = new CustomerGet(['customer_id' => '12345']); <3> 67 | 68 | // send HTTP request and get response object 69 | $collmexResponse = $collmexRequest->send($getCustomerType->getCsv()); <4> 70 | 71 | if ($collmexResponse->isError()) { <5> 72 | echo "Collmex error: " . $collmexResponse->getErrorMessage() 73 | . "; Code=" . $collmexResponse->getErrorCode() . PHP_EOL; 74 | } else { 75 | // contains one Customer object and the Message object(s) 76 | $records = $collmexResponse->getRecords(); <6> 77 | 78 | foreach ($records as $record) { 79 | var_dump($record->getData()); <7> 80 | } 81 | } 82 | ---- 83 | 84 | <1> The HTTP layer is handled by a `Client` instance; currently we provide 85 | an implementation which uses PHP's `curl` functions. The `Client` expects 86 | _Login Handle_, _Password_, and the _Customer ID_ as constructor arguments. 87 | <2> The `Request` class gets a `Client` as constructor argument 88 | <3> The Collmex API expects and sends so called _Types_ (german: _Satzart_); 89 | in this example we create a _Type_ which queries Collmex for a customer record 90 | <4> the `send()` method of the `Request` instance sends a HTTP request to 91 | the Collmex API and returns an instance of the `Response` class 92 | <5> the `Response` has a method which checks if Collmex answered with 93 | an error 94 | <6> here we extract all records from the response, they are returned as an 95 | array of `Type` instances 96 | <7> the `getData()` method returns an array with all record fields 97 | 98 | === Create a new Collmex customer record 99 | 100 | Create a new Collmex *Customer* record and get the Collmex Customer-ID from the 101 | response data: 102 | 103 | [source,php] 104 | ---- 105 | "2", 121 | 'salutation' => "Herr", 122 | 'firstname' => "Charly", 123 | 'lastname' => "Cash", 124 | 'street' => "Hauptstraße 12", 125 | 'zipcode' => "12222", 126 | 'city' => "Berlin", 127 | 'inactive' => Customer::STATUS_ACTIVE, 128 | 'country' => "DE", 129 | 'phone' => "+49300000000", 130 | 'email' => "cash@example.org", 131 | 'output_medium' => Customer::OUTPUT_MEDIUM_EMAIL, 132 | ) 133 | ); 134 | 135 | // send HTTP request and get response object 136 | $collmexResponse = $collmexRequest->send($customer->getCsv()); 137 | 138 | if ($collmexResponse->isError()) { 139 | echo "Collmex error: " . $collmexResponse->getErrorMessage() . "; Code=" . $collmexResponse->getErrorCode() . PHP_EOL; 140 | } else { 141 | $newObject = $collmexResponse->getFirstRecord(); 142 | echo "New Collmex customer ID=" . $newObject->new_id . PHP_EOL; 143 | 144 | $records = $collmexResponse->getRecords(); 145 | 146 | foreach ($records as $record) { 147 | var_dump($record->getData()); // contains one NewObject object and the Message object(s) 148 | } 149 | } 150 | ---- 151 | 152 | === Transmit a Collmex customer order with multiple items 153 | 154 | [source,php] 155 | ---- 156 | '2', 179 | 'order_id' => $orderId, 180 | 'position' => null, 181 | 'order_type' => null, 182 | ... 183 | 'product_id' => '12345', 184 | ... 185 | ] 186 | ); 187 | 188 | $customerOrderItem2 = clone $customerOrderItem1; 189 | $customerOrderItem2->product_id = '23456'; 190 | 191 | $csv = $customerOrderItem1->getCsv() . $customerOrderItem2->getCsv(); 192 | 193 | // send HTTP request and get response object 194 | $collmexResponse = $collmexRequest->send($csv); 195 | 196 | if ($collmexResponse->isError()) { 197 | echo 'Collmex error: ' . $collmexResponse->getErrorMessage() . '; Code=' . $collmexResponse->getErrorCode() . PHP_EOL; 198 | } else { 199 | $newObject = $collmexResponse->getFirstRecord(); 200 | echo 'New Collmex customer ID=' . $newObject->new_id . PHP_EOL; 201 | 202 | $records = $collmexResponse->getRecords(); 203 | 204 | foreach ($records as $record) { 205 | // contains one NewObject object and the Message object(s) 206 | var_dump($record->getData()); 207 | } 208 | } 209 | ---- 210 | -------------------------------------------------------------------------------- /src/Type/Product.php: -------------------------------------------------------------------------------- 1 | 11 | * @author Marcus Jaschen 12 | * 13 | * @property $type_identifier 14 | * @property $product_id 15 | * @property $product_description 16 | * @property $product_description_eng 17 | * @property $quantity_unit 18 | * @property $product_group 19 | * @property $client_id 20 | * @property $tax_rate 21 | * @property $weight 22 | * @property $weight_unit 23 | * @property $price_quantity 24 | * @property $product_type 25 | * @property $inactive 26 | * @property $price_group 27 | * @property $price 28 | * @property $ean 29 | * @property $manufacturer 30 | * @property $shipping_group 31 | * @property $minimum_quantity 32 | * @property $quantity 33 | * @property $lot_mandatory 34 | * @property $procurement 35 | * @property $production_time 36 | * @property $labor_costs 37 | * @property $labor_costs_reference_amount 38 | * @property $annotation 39 | * @property $costing 40 | * @property $costs 41 | * @property $reference_amount_cost 42 | * @property $purchase_supplier 43 | * @property $purchase_tax_rate 44 | * @property $product_number_supplier 45 | * @property $purchase_quantity_per_package 46 | * @property $purchase_description 47 | * @property $purchase_price 48 | * @property $purchase_price_quantity 49 | * @property $purchase_delivery_time 50 | * @property $purchase_currency 51 | * @property $reserved01 52 | * @property $reserved02 53 | * @property $website_id 54 | * @property $shop_short_text 55 | * @property $shop_long_text 56 | * @property $text_type 57 | * @property $filename 58 | * @property $keywords 59 | * @property $title 60 | * @property $template_id 61 | * @property $image_url 62 | * @property $base_price_quantity_product 63 | * @property $base_price_quantity_base_unit 64 | * @property $base_unit 65 | * @property $requested_price 66 | * @property $inactive_alt 67 | * @property $shop_category_ids 68 | * @property $reserved03 69 | * @property $reserved04 70 | * @property $reserved05 71 | * @property $product_number_manufacturer 72 | * @property $delivery_relevant 73 | * @property $amazon_asin 74 | * @property $ebay_item_number 75 | * @property $direct_delivery 76 | * @property $hs_code 77 | * @property $storage_bin 78 | * @property $no_stock_management 79 | * @property $country_of_origin 80 | */ 81 | class Product extends AbstractType implements TypeInterface 82 | { 83 | /** 84 | * @var int 85 | */ 86 | final public const TAX_RATE_FULL = 0; 87 | /** 88 | * @var int 89 | */ 90 | final public const TAX_RATE_REDUCED = 1; 91 | /** 92 | * @var int 93 | */ 94 | final public const TAX_RATE_TAXFREE = 2; 95 | 96 | /** 97 | * @var int 98 | */ 99 | final public const BUY_TAX_RATE_FULL = 0; 100 | /** 101 | * @var int 102 | */ 103 | final public const BUY_TAX_RATE_REDUCED = 1; 104 | /** 105 | * @var int 106 | */ 107 | final public const BUY_TAX_RATE_TAXFREE = 2; 108 | 109 | /** 110 | * @var int 111 | */ 112 | final public const PRODUCT_TYPE_GOODS = 0; 113 | /** 114 | * @var int 115 | */ 116 | final public const PRODUCT_TYPE_SERVICE = 1; 117 | /** 118 | * @var int 119 | */ 120 | final public const PRODUCT_TYPE_MEMBERSHIP_FEE = 2; 121 | /** 122 | * @var int 123 | */ 124 | final public const PRODUCT_TYPE_CONSTRUCTION_SERVICE = 3; 125 | /** 126 | * @var int 127 | */ 128 | final public const PRODUCT_TYPE_GOODS_CUSTOMER_TAX = 4; 129 | 130 | /** 131 | * @var int 132 | */ 133 | final public const INACTIVE_PRODUCT_ACTIVE = 0; 134 | /** 135 | * @var int 136 | */ 137 | final public const INACTIVE_PRODUCT_INACTIVE = 1; 138 | /** 139 | * @var int 140 | */ 141 | final public const INACTIVE_PRODUCT_DELETE = 2; 142 | /** 143 | * @var int 144 | */ 145 | final public const INACTIVE_PRODUCT_DELETE_IF_INACTIVE = 3; 146 | 147 | /** 148 | * @var int 149 | */ 150 | final public const LOT_MANDATORY = 0; 151 | 152 | /** 153 | * @var int 154 | */ 155 | final public const TEXT_PLAIN = 0; 156 | /** 157 | * @var int 158 | */ 159 | final public const TEXT_HTML = 1; 160 | 161 | /** 162 | * @var int 163 | */ 164 | final public const PROCUREMENT_SHOPPING = 0; 165 | /** 166 | * @var int 167 | */ 168 | final public const PROCUREMENT_PRODUCTION = 10; 169 | 170 | /** 171 | * @var int 172 | */ 173 | final public const LABOR_COSTS_REFERENCE_AMOUNT = 1; 174 | 175 | /** 176 | * @var int 177 | */ 178 | final public const COSTING_AUTOMATIC = 0; 179 | /** 180 | * @var int 181 | */ 182 | final public const COSTING_MANUAL = 0; 183 | 184 | /** 185 | * @var int 186 | */ 187 | final public const BASIC_UNIT_NO_UNIT = 0; 188 | /** 189 | * @var int 190 | */ 191 | final public const BASIC_UNIT_KILOGRAM = 1; 192 | /** 193 | * @var int 194 | */ 195 | final public const BASIC_UNIT_LITER = 2; 196 | /** 197 | * @var int 198 | */ 199 | final public const BASIC_UNIT_CUBIC_METER = 3; 200 | /** 201 | * @var int 202 | */ 203 | final public const BASIC_UNIT_METER = 4; 204 | /** 205 | * @var int 206 | */ 207 | final public const BASIC_UNIT_SQUARE_METER = 5; 208 | /** 209 | * @var int 210 | */ 211 | final public const BASIC_UNIT_PIECE = 6; 212 | 213 | /** 214 | * @var int 215 | */ 216 | final public const DELIVERY_RELEVANCE_NO = 0; 217 | /** 218 | * @var int 219 | */ 220 | final public const DELIVERY_RELEVANCE_YES = 1; 221 | 222 | /** 223 | * @var int 224 | */ 225 | final public const DIRECT_DELIVERY_NO = 0; 226 | /** 227 | * @var int 228 | */ 229 | final public const DIRECT_DELIVERY_YES = 1; 230 | 231 | /** 232 | * @var int 233 | */ 234 | final public const STOCK_MANAGEMENT_YES = 0; 235 | 236 | /** 237 | * @var int 238 | */ 239 | final public const STOCK_MANAGEMENT_NO = 1; 240 | 241 | /** 242 | * Type data template. 243 | * 244 | * @var array 245 | */ 246 | protected $template = [ 247 | // 1 248 | 'type_identifier' => 'CMXPRD', 249 | 'product_id' => null, 250 | 'product_description' => null, 251 | 'product_description_eng' => null, 252 | 'quantity_unit' => null, 253 | 'product_group' => null, 254 | 'client_id' => null, 255 | 'tax_rate' => null, 256 | 'weight' => null, 257 | // 10 258 | 'weight_unit' => null, 259 | 'price_quantity' => null, 260 | 'product_type' => null, 261 | 'inactive' => null, 262 | 'price_group' => null, 263 | 'price' => null, 264 | 'ean' => null, 265 | 'manufacturer' => null, 266 | 'shipping_group' => null, 267 | 'minimum_quantity' => null, 268 | // 20 269 | 'quantity' => null, 270 | 'lot_mandatory' => null, 271 | 'procurement' => null, 272 | 'production_time' => null, 273 | 'labor_costs' => null, 274 | 'labor_costs_reference_amount' => null, 275 | 'annotation' => null, 276 | 'costing' => null, 277 | 'costs' => null, 278 | 'reference_amount_cost' => null, 279 | // 30 280 | 'purchase_supplier' => null, 281 | 'purchase_tax_rate' => null, 282 | 'product_number_supplier' => null, 283 | 'purchase_quantity_per_package' => null, 284 | 'purchase_description' => null, 285 | 'purchase_price' => null, 286 | 'purchase_price_quantity' => null, 287 | 'purchase_delivery_time' => null, 288 | 'purchase_currency' => null, 289 | 'reserved01' => null, 290 | // 40 291 | 'reserved02' => null, 292 | 'website_id' => null, 293 | 'shop_short_text' => null, 294 | 'shop_long_text' => null, 295 | 'text_type' => null, 296 | 'filename' => null, 297 | 'keywords' => null, 298 | 'title' => null, 299 | 'template_id' => null, 300 | 'image_url' => null, 301 | // 50 302 | 'base_price_quantity_product' => null, 303 | 'base_price_quantity_base_unit' => null, 304 | 'base_unit' => null, 305 | 'requested_price' => null, 306 | 'inactive_alt' => null, 307 | 'shop_category_ids' => null, 308 | 'reserved03' => null, 309 | 'reserved04' => null, 310 | 'reserved05' => null, 311 | 'product_number_manufacturer' => null, 312 | // 60 313 | 'delivery_relevant' => null, 314 | 'amazon_asin' => null, 315 | 'ebay_item_number' => null, 316 | 'direct_delivery' => null, 317 | 'hs_code' => null, 318 | // 65 319 | 'storage_bin' => null, 320 | 'no_stock_management' => null, 321 | 'country_of_origin' => null, 322 | ]; 323 | 324 | /** 325 | * Formally validates the type data in $data attribute. 326 | * 327 | * @return bool Validation success 328 | */ 329 | #[\Override] 330 | public function validate(): bool 331 | { 332 | return true; 333 | } 334 | } 335 | --------------------------------------------------------------------------------