Basic DHL implementation, Refactor redundant code

This commit is contained in:
Andreas Palm 2022-11-14 22:29:42 +01:00
parent d676a1b09a
commit 8ad45ed723
44 changed files with 1051 additions and 4196 deletions

View File

@ -0,0 +1,14 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Bank
{
public string $accountOwner;
public string $bankName;
public string $iban;
public string $note1;
public string $note2;
public ?string $bic;
public ?string $accountreference;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Communication
{
public ?string $phone;
public ?string $email;
public ?string $contactPerson;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Contact
{
public ?Communication $Communication;
public ?NativeAddress $Address;
public ?Name $Name;
}

View File

@ -0,0 +1,18 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Country
{
public ?string $country;
public string $countryISOCode;
public ?string $state;
public static function Create(string $isoCode, ?string $state = null):Country {
$obj = new Country();
$obj->countryISOCode = $isoCode;
$obj->state = $state;
return $obj;
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class CreateShipmentOrderRequest
{
public Version $Version;
public ShipmentOrder $ShipmentOrder;
public ?string $labelResponseType;
public ?string $groupProfileName;
public ?string $labelFormat;
public ?string $labelFormatRetoure;
public ?string $combinedPrinting;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class CreateShipmentOrderResponse
{
public Version $Version;
public Statusinformation $Status;
public ?CreationState $CreationState;
}

View File

@ -0,0 +1,11 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class CreationState
{
public string $sequenceNumber;
public ?string $shipmentNumber;
public ?string $returnShipmentNumber;
public LabelData $LabelData;
}

View File

@ -0,0 +1,14 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Customer
{
public Name $Name;
public ?string $vatID;
public string $EKP;
public NativeAddress $Address;
public Contact $Contact;
public ?Bank $Bank;
public ?string $note;
}

View File

@ -0,0 +1,9 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class DeleteShipmentOrderRequest
{
public Version $Version;
public string $shipmentNumber;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class DeleteShipmentOrderResponse
{
public Version $Version;
public Statusinformation $Status;
public ?DeletionState $DeletionState;
}

View File

@ -0,0 +1,9 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class DeletionState
{
public string $shipmentNumber;
public Statusinformation $Status;
}

View File

@ -0,0 +1,12 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class DeliveryAddress
{
public ?NativeAddress $NativeAddress;
public ?Postfiliale $PostOffice;
public ?PackStation $PackStation;
public ?string $streetNameCode;
public ?string $streetNumberCode;
}

View File

@ -0,0 +1,11 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Dimension
{
public int $length;
public int $width;
public int $height;
public ?string $unit;
}

View File

@ -0,0 +1,13 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class ExportDocPosition
{
public string $description;
public string $countryCodeOrigin;
public string $customsTariffNumber;
public int $amount;
public float $netWeightInKG;
public float $customsValue;
}

View File

@ -0,0 +1,34 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class ExportDocument
{
const TYPE_PRESENT = 'PRESENT';
const TYPE_DOCUMENT = 'DOCUMENT';
const TYPE_COMMERCIAL_GOODS = 'COMMERCIAL_GOODS';
const TYPE_COMMERCIAL_SAMPLE = 'COMMERCIAL_SAMPLE';
const TYPE_RETURN_OF_GOODS= 'RETURN_OF_GOODS';
const TYPE_OTHER = 'OTHER';
const TERMS_DDP = 'DDP';
const TERMS_DXV = 'DXV';
const TERMS_DAP = 'DAP';
const TERMS_DDX = 'DDX';
const TERMS_CPT = 'CPT';
public ?string $invoiceNumber;
public string $exportType;
public ?string $exportTypeDescription;
public ?string $termsOfTrade;
public string $placeOfCommital;
public ?float $additionalFee;
public ?string $customsCurrency;
public ?string $permitNumber;
public ?string $attestationNumber;
public ?string $addresseesCustomsReference;
public ?string $sendersCustomsReference;
public ?bool $WithElectronicExportNtfctn;
/** @var ExportDocPosition[] $ExportDocPosition */
public array $ExportDocPosition;
}

View File

@ -0,0 +1,17 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class LabelData
{
public Statusinformation $Status;
public ?string $shipmentNumber;
public ?string $labelUrl;
public ?string $labelData;
public ?string $returnLabelUrl;
public ?string $returnLabelData;
public ?string $exportLabelUrl;
public ?string $exportLabelData;
public ?string $codLabelUrl;
public ?string $codLabelData;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Name
{
public string $name1;
public ?string $name2;
public ?string $name3;
}

View File

@ -0,0 +1,19 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class NativeAddress
{
public string $streetName;
public ?string $streetNumber;
/**
* @var string[]
*/
public array $addressAddition;
public ?string $dispatchingInformation;
public string $zip;
public string $city;
public ?string $province;
public ?Country $Origin;
}

View File

@ -0,0 +1,12 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class NativeAddressNew
{
public string $streetName;
public ?string $streetNumber;
public string $zip;
public string $city;
public ?Country $Origin;
}

View File

@ -0,0 +1,13 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class PackStation
{
public string $postNumber;
public string $packstationNumber;
public string $zip;
public string $city;
public ?string $province;
public ?Country $Origin;
}

View File

@ -0,0 +1,12 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Postfiliale
{
public string $postfilialeNumber;
public string $postNumber;
public string $zip;
public string $city;
public ?Country $Origin;
}

View File

@ -0,0 +1,12 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Receiver
{
public string $name1;
public ?NativeAddress $Address;
public ?PackStation $Packstation;
public ?Postfiliale $Postfiliale;
public ?Communication $Communication;
}

View File

@ -0,0 +1,22 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Shipment
{
public ShipmentDetails $ShipmentDetails;
public Shipper $Shipper;
public string $ShipperReference;
public Receiver $Receiver;
public ?Shipper $ReturnReceiver;
public ?ExportDocument $ExportDocument;
public ?string $feederSystem;
public function __construct()
{
$this->ShipmentDetails = new ShipmentDetails();
$this->Shipper = new Shipper();
$this->ShipperReference = '';
$this->Receiver = new Receiver();
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
use DateTimeImmutable;
class ShipmentDetails
{
public string $product;
public string $accountNumber;
public string $customerReference;
private string $shipmentDate;
public string $costCentre;
public string $returnShipmentAccountNumber;
public string $returnShipmentReference;
public ShipmentItem $ShipmentItem;
public ShipmentService $Service;
public ShipmentNotification $Notification;
public Bank $BankData;
public function SetShipmentDate(DateTimeImmutable $date): void {
$this->shipmentDate = $date->format('Y-m-d');
}
public function GetShipmentDate(): DateTimeImmutable {
return DateTimeImmutable::createFromFormat('Y-m-d', $this->shipmentDate);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class ShipmentItem
{
public float $weightInKG;
public ?int $lengthInCM;
public ?int $widthInCM;
public ?int $heightInCM;
}

View File

@ -0,0 +1,9 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class ShipmentNotification
{
public string $recipientEmailAddress;
public ?string $templateId;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class ShipmentOrder
{
public string $sequenceNumber;
public Shipment $Shipment;
public ?Serviceconfiguration $PrintOnlyIfCodeable;
}

View File

@ -0,0 +1,7 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class ShipmentService
{
}

View File

@ -0,0 +1,16 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Shipper
{
public Name $Name;
public NativeAddressNew $Address;
public ?Communication $Communication;
public function __construct()
{
$this->Name = new Name();
$this->Address = new NativeAddressNew();
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Status
{
public string $statuscode;
public string $statusDescription;
}

View File

@ -0,0 +1,9 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class StatusElement
{
public string $statusElement;
public string $statusMessage;
}

View File

@ -0,0 +1,13 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Statusinformation
{
public int $statusCode;
public string $statusText;
public array|string $statusMessage;
public string $statusType;
public StatusElement $errorMessage;
public StatusElement $warningMessage;
}

View File

@ -0,0 +1,10 @@
<?php
namespace Xentral\Carrier\Dhl\Data;
class Version
{
public string $majorRelease;
public string $minorRelease;
public ?string $build;
}

View File

@ -0,0 +1,70 @@
<?php
namespace Xentral\Carrier\Dhl;
use SoapClient;
use SoapHeader;
use Xentral\Carrier\Dhl\Data\CreateShipmentOrderRequest;
use Xentral\Carrier\Dhl\Data\CreateShipmentOrderResponse;
use Xentral\Carrier\Dhl\Data\CreationState;
use Xentral\Carrier\Dhl\Data\LabelData;
use Xentral\Carrier\Dhl\Data\Shipment;
use Xentral\Carrier\Dhl\Data\ShipmentOrder;
use Xentral\Carrier\Dhl\Data\Statusinformation;
use Xentral\Carrier\Dhl\Data\Version;
class DhlApi
{
private SoapClient $soapClient;
private const SANDBOX_URL = 'https://cig.dhl.de/services/sandbox/soap';
private const PRODUCTION_URL = 'https://cig.dhl.de/services/production/soap';
private const NAMESPACE_CIS = 'http://dhl.de/webservice/cisbase';
public function __construct(string $user, string $signature)
{
$this->soapClient = new SoapClient(__DIR__ . '/Wsdl/geschaeftskundenversand-api-3.4.0.wsdl', [
'login' => 'ewsp',
'password' => 'rZ*twrzJ5@wr&$',
'location' => self::SANDBOX_URL,
'trace' => 1,
'connection_timeout' => 30,
'classmap' => [
'CreateShipmentOrderResponse' => CreateShipmentOrderResponse::class,
'CreationState' => CreationState::class,
'LabelData' => LabelData::class,
'Statusinformation' => Statusinformation::class,
'Version' => Version::class,
]
]);
$authHeader = new SoapHeader(self::NAMESPACE_CIS, 'Authentification', [
'user' => $user,
'signature' => $signature
]);
$this->soapClient->__setSoapHeaders($authHeader);
}
public function CreateShipment(Shipment $shipment): CreateShipmentOrderResponse|string
{
$request = new CreateShipmentOrderRequest();
$request->Version = $this->getVersion();
$request->ShipmentOrder = new ShipmentOrder();
$request->ShipmentOrder->Shipment = $shipment;
$request->ShipmentOrder->sequenceNumber = '1';
$request->labelResponseType = "B64";
try {
$response = $this->soapClient->createShipmentOrder($request);
return $response;
} catch (\SoapFault $e) {
return $e->getMessage();
}
}
private function getVersion() {
$version = new Version();
$version->majorRelease = '3';
$version->minorRelease = '4';
return $version;
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace Xentral\Modules\ShippingMethod\Model;
class CreateShipmentResult
{
public bool $Success = false;
public array $Errors = [];
public ?string $Label;
public ?string $ExportDocuments;
public ?string $TrackingNumber;
public ?string $TrackingUrl;
}

View File

@ -0,0 +1,13 @@
<?php
namespace Xentral\Modules\ShippingMethod\Model;
class CustomsInfo
{
const CUSTOMS_TYPE_GIFT = 0;
const CUSTOMS_TYPE_DOCUMENTS = 1;
const CUSTOMS_TYPE_GOODS = 2;
const CUSTOMS_TYPE_SAMPLE = 3;
const CUSTOMS_TYPE_RETURN = 4;
}

View File

@ -0,0 +1,57 @@
<?php
namespace Xentral\Modules\ShippingMethod\Model;
class Product
{
const SERVICE_COD = 'cod';
const SERVICE_PREMIUM = 'premium';
public string $Id;
public string $Name;
public float $LengthMin = 0;
public float $LengthMax = 500;
public float $WidthMin = 0;
public float $WidthMax = 500;
public float $HeightMin = 0;
public float $HeightMax = 500;
public float $WeightMin = 0;
public float $WeightMax = 100;
public array $AvailableServices = [];
public static function Create(string $id, string $name):Product {
$obj = new Product();
$obj->Id = $id;
$obj->Name = $name;
return $obj;
}
public function WithLength(float $min, float $max): Product {
$this->LengthMin = $min;
$this->LengthMax = $max;
return $this;
}
public function WithWidth(float $min, float $max): Product {
$this->WidthMin = $min;
$this->WidthMax = $max;
return $this;
}
public function WithHeight(float $min, float $max): Product {
$this->HeightMin = $min;
$this->HeightMax = $max;
return $this;
}
public function WithWeight(float $min, float $max): Product {
$this->WeightMin = $min;
$this->WeightMax = $max;
return $this;
}
public function WithServices(array $services): Product {
$this->AvailableServices = $services;
return $this;
}
}

View File

@ -1,5 +1,11 @@
<?php
abstract class Versanddienstleister {
<?php
use Xentral\Modules\ShippingMethod\Model\CreateShipmentResult;
use Xentral\Modules\ShippingMethod\Model\CustomsInfo;
use Xentral\Modules\ShippingMethod\Model\Product;
abstract class Versanddienstleister
{
protected int $id;
protected Application $app;
protected string $type;
@ -26,91 +32,83 @@ abstract class Versanddienstleister {
$this->settings = json_decode($row['einstellungen_json']);
}
public function isEtikettenDrucker(): bool {
public function isEtikettenDrucker(): bool
{
return false;
}
public function GetAdressdaten($id, $sid)
public abstract function GetName(): string;
public function GetAdressdaten($id, $sid): array
{
$auftragId = $lieferscheinId = $rechnungId = $versandId = 0;
if($sid==='rechnung')
if ($sid === 'rechnung')
$rechnungId = $id;
if($sid==='lieferschein') {
if ($sid === 'lieferschein') {
$lieferscheinId = $id;
$auftragId = $this->app->DB->Select("SELECT auftragid FROM lieferschein WHERE id=$lieferscheinId LIMIT 1");
$rechnungId = $this->app->DB->Select("SELECT id FROM rechnung WHERE lieferschein = '$lieferscheinId' LIMIT 1");
if($rechnungId <= 0)
if ($rechnungId <= 0)
$rechnungId = $this->app->DB->Select("SELECT rechnungid FROM lieferschein WHERE id='$lieferscheinId' LIMIT 1");
}
if($sid==='versand')
{
if ($sid === 'versand') {
$versandId = $id;
$lieferscheinId = $this->app->DB->Select("SELECT lieferschein FROM versand WHERE id='$versandId' LIMIT 1");
$rechnungId = $this->app->DB->Select("SELECT rechnung FROM versand WHERE id='$versandId' LIMIT 1");
$rechnungId = $this->app->DB->Select("SELECT rechnung FROM versand WHERE id='$versandId' LIMIT 1");
$sid = 'lieferschein';
}
if ($auftragId <= 0 && $rechnungId > 0)
$auftragId = $this->app->DB->Select("SELECT auftragid FROM rechnung WHERE id=$rechnungId LIMIT 1");
if($sid==='rechnung' || $sid==='lieferschein' || $sid==='adresse')
{
if ($sid === 'rechnung' || $sid === 'lieferschein' || $sid === 'adresse') {
$docArr = $this->app->DB->SelectRow("SELECT * FROM `$sid` WHERE id = $id LIMIT 1");
$ret['addressId'] = $docArr['adresse'];
$ret['auftragId'] = $auftragId;
$ret['rechnungId'] = $rechnungId;
$ret['lieferscheinId'] = $lieferscheinId;
$addressfields = ['name', 'adresszusatz', 'abteilung', 'ansprechpartner', 'unterabteilung', 'ort', 'plz',
'strasse', 'land', 'telefon', 'email'];
$ret = array_filter($docArr, fn($key)=>in_array($key, $addressfields), ARRAY_FILTER_USE_KEY);
'strasse', 'land'];
$ret['original'] = array_filter($docArr, fn($key) => in_array($key, $addressfields), ARRAY_FILTER_USE_KEY);
$name2 = trim($docArr['adresszusatz']);
$abt = 0;
if($name2==='')
{
$name2 = trim($docArr['abteilung']);
$abt=1;
}
$name3 = trim($docArr['ansprechpartner']);
if($name3==='' && $abt!==1){
$name3 = trim($docArr['abteilung']);
}
$ret['name'] = empty(trim($docArr['ansprechpartner'])) ? trim($docArr['name']) : trim($docArr['ansprechpartner']);
$ret['companyname'] = !empty(trim($docArr['ansprechpartner'])) ? trim($docArr['name']) : '';
$ret['address2'] = join(';', array_filter([
$docArr['abteilung'],
$docArr['unterabteilung'],
$docArr['adresszusatz']
], fn(string $item) => !empty(trim($item))));
//unterabteilung versuchen einzublenden
if($name2==='') {
$name2 = trim($docArr['unterabteilung']);
} else if ($name3==='') {
$name3 = trim($docArr['unterabteilung']);
}
if($name3!=='' && $name2==='') {
$name2=$name3;
$name3='';
}
$ret['name2'] = $name2;
$ret['name3'] = $name3;
$ret['city'] = $docArr['ort'];
$ret['zip'] = $docArr['plz'];
$ret['country'] = $docArr['land'];
$ret['phone'] = $docArr['telefon'];
$ret['email'] = $docArr['email'];
$strasse = trim($docArr['strasse']);
$ret['streetwithnumber'] = $strasse;
$hausnummer = trim($this->app->erp->ExtractStreetnumber($strasse));
$strasse = trim(str_replace($hausnummer,'',$strasse));
$strasse = str_replace('.','',$strasse);
$strasse = trim(str_replace($hausnummer, '', $strasse));
$strasse = str_replace('.', '', $strasse);
if($strasse=='')
{
if ($strasse == '') {
$strasse = trim($hausnummer);
$hausnummer = '';
}
$ret['strasse'] = $strasse;
$ret['hausnummer'] = $hausnummer;
$ret['street'] = $strasse;
$ret['streetnumber'] = $hausnummer;
}
// wenn rechnung im spiel entweder durch versand oder direkt rechnung
if($rechnungId >0)
{
$invoice_data = $this->app->DB->SelectRow("SELECT zahlungsweise, soll, belegnr FROM rechnung WHERE id='$rechnungId' LIMIT 1");
if ($rechnungId > 0) {
$invoice_data = $this->app->DB->SelectRow("SELECT zahlungsweise, soll, belegnr FROM rechnung WHERE id='$rechnungId' LIMIT 1");
$ret['zahlungsweise'] = $invoice_data['zahlungsweise'];
$ret['betrag'] = $invoice_data['soll'];
$ret['invoice_number'] = $invoice_data['belegnr'];
if($invoice_data['zahlungsweise']==='nachnahme'){
if ($invoice_data['zahlungsweise'] === 'nachnahme') {
$ret['nachnahme'] = true;
}
}
@ -118,10 +116,10 @@ abstract class Versanddienstleister {
$sql = "SELECT
lp.bezeichnung,
lp.menge,
coalesce(nullif(lp.zolltarifnummer, ''), nullif(rp.zolltarifnummer, ''), nullif(a.zolltarifnummer, '')) zolltarifnummer,
coalesce(nullif(lp.herkunftsland, ''), nullif(rp.herkunftsland, ''), nullif(a.herkunftsland, '')) herkunftsland,
coalesce(nullif(lp.zolleinzelwert, '0'), rp.preis *(1-rp.rabatt/100)) zolleinzelwert,
coalesce(nullif(lp.zolleinzelgewicht, 0), a.gewicht) zolleinzelgewicht,
coalesce(nullif(lp.zolltarifnummer, ''), nullif(rp.zolltarifnummer, ''), nullif(a.zolltarifnummer, '')) as zolltarifnummer,
coalesce(nullif(lp.herkunftsland, ''), nullif(rp.herkunftsland, ''), nullif(a.herkunftsland, '')) as herkunftsland,
coalesce(nullif(lp.zolleinzelwert, '0'), rp.preis *(1-rp.rabatt/100)) as zolleinzelwert,
coalesce(nullif(lp.zolleinzelgewicht, 0), a.gewicht) as zolleinzelgewicht,
lp.zollwaehrung
FROM lieferschein_position lp
JOIN artikel a on lp.artikel = a.id
@ -131,10 +129,9 @@ abstract class Versanddienstleister {
ORDER BY lp.sort";
$ret['positions'] = $this->app->DB->SelectArr($sql);
if($sid==="lieferschein"){
if ($sid === "lieferschein") {
$standardkg = $this->app->erp->VersandartMindestgewicht($lieferscheinId);
}
else{
} else {
$standardkg = $this->app->erp->VersandartMindestgewicht();
}
$ret['weight'] = $standardkg;
@ -155,7 +152,8 @@ abstract class Versanddienstleister {
*
* @return array
*/
public function AdditionalSettings(): array {
public function AdditionalSettings(): array
{
return [];
}
@ -168,73 +166,60 @@ abstract class Versanddienstleister {
public function RenderAdditionalSettings(string $target, array $form): void
{
$fields = $this->AdditionalSettings();
if($this->app->Secure->GetPOST('speichern'))
{
$json = $this->app->DB->Select("SELECT einstellungen_json FROM versandarten WHERE id = '".$this->id."' LIMIT 1");
$modul = $this->app->DB->Select("SELECT modul FROM versandarten WHERE id = '".$this->id."' LIMIT 1");
if(!empty($json))
{
if ($this->app->Secure->GetPOST('speichern')) {
$json = $this->app->DB->Select("SELECT einstellungen_json FROM versandarten WHERE id = '" . $this->id . "' LIMIT 1");
$modul = $this->app->DB->Select("SELECT modul FROM versandarten WHERE id = '" . $this->id . "' LIMIT 1");
if (!empty($json)) {
$json = @json_decode($json, true);
}else{
} else {
$json = array();
foreach($fields as $name => $val)
{
if(isset($val['default']))
{
foreach ($fields as $name => $val) {
if (isset($val['default'])) {
$json[$name] = $val['default'];
}
}
}
if(empty($json))
{
if (empty($json)) {
$json = null;
}
foreach($fields as $name => $val)
{
foreach ($fields as $name => $val) {
if($modul === $this->app->Secure->GetPOST('modul_name'))
{
$json[$name] = $this->app->Secure->GetPOST($name, '','', 1);
if ($modul === $this->app->Secure->GetPOST('modul_name')) {
$json[$name] = $this->app->Secure->GetPOST($name, '', '', 1);
}
if(isset($val['replace']))
{
switch($val['replace'])
{
if (isset($val['replace'])) {
switch ($val['replace']) {
case 'lieferantennummer':
$json[$name] = $this->app->erp->ReplaceLieferantennummer(1,$json[$name],1);
break;
$json[$name] = $this->app->erp->ReplaceLieferantennummer(1, $json[$name], 1);
break;
}
}
}
$json_str = $this->app->DB->real_escape_string(json_encode($json));
$this->app->DB->Update("UPDATE versandarten SET einstellungen_json = '$json_str' WHERE id = '".$this->id."' LIMIT 1");
$this->app->DB->Update("UPDATE versandarten SET einstellungen_json = '$json_str' WHERE id = '" . $this->id . "' LIMIT 1");
}
$html = '';
foreach($fields as $name => $val) // set missing default values
foreach ($fields as $name => $val) // set missing default values
{
if(isset($val['default']) && !isset($form[$name]))
{
if (isset($val['default']) && !isset($form[$name])) {
$form[$name] = $val['default'];
}
}
foreach($fields as $name => $val)
{
if(isset($val['heading']))
$html .= '<tr><td colspan="2"><b>'.html_entity_decode($val['heading']).'</b></td></tr>';
foreach ($fields as $name => $val) {
if (isset($val['heading']))
$html .= '<tr><td colspan="2"><b>' . html_entity_decode($val['heading']) . '</b></td></tr>';
$html .= '<tr><td>'.($val['bezeichnung'] ?? $name).'</td><td>';
if(isset($val['replace']))
{
switch($val['replace'])
{
$html .= '<tr><td>' . ($val['bezeichnung'] ?? $name) . '</td><td>';
if (isset($val['replace'])) {
switch ($val['replace']) {
case 'lieferantennummer':
$form[$name] = $this->app->erp->ReplaceLieferantennummer(0,$form[$name],0);
$form[$name] = $this->app->erp->ReplaceLieferantennummer(0, $form[$name], 0);
$this->app->YUI->AutoComplete($name, 'lieferant', 1);
break;
case 'shop':
$form[$name] .= ($form[$name]?' '.$this->app->DB->Select("SELECT bezeichnung FROM shopexport WHERE id = '".(int)$form[$name]."'"):'');
$form[$name] .= ($form[$name] ? ' ' . $this->app->DB->Select("SELECT bezeichnung FROM shopexport WHERE id = '" . (int)$form[$name] . "'") : '');
$this->app->YUI->AutoComplete($name, 'shopnameid');
break;
case 'etiketten':
@ -242,41 +227,38 @@ abstract class Versanddienstleister {
break;
}
}
switch($val['typ'] ?? 'text')
{
switch ($val['typ'] ?? 'text') {
case 'textarea':
$html .= '<textarea name="'.$name.'" id="'.$name.'">'.($form[$name] ?? '').'</textarea>';
$html .= '<textarea name="' . $name . '" id="' . $name . '">' . ($form[$name] ?? '') . '</textarea>';
break;
case 'checkbox':
$html .= '<input type="checkbox" name="'.$name.'" id="'.$name.'" value="1" '.($form[$name] ?? false ? ' checked="checked" ':'').' />';
$html .= '<input type="checkbox" name="' . $name . '" id="' . $name . '" value="1" ' . ($form[$name] ?? false ? ' checked="checked" ' : '') . ' />';
break;
case 'select':
$html .= $this->app->Tpl->addSelect('return', $name, $name, $val['optionen'], $form[$name]);
break;
case 'submit':
if(isset($val['text']))
$html .= '<form method="POST"><input type="submit" name="'.$name.'" value="'.$val['text'].'"></form>';
if (isset($val['text']))
$html .= '<form method="POST"><input type="submit" name="' . $name . '" value="' . $val['text'] . '"></form>';
break;
case 'custom':
if(isset($val['function']))
{
if (isset($val['function'])) {
$tmpfunction = $val['function'];
if(method_exists($this, $tmpfunction))
{
if (method_exists($this, $tmpfunction)) {
$html .= $this->$tmpfunction();
}
}
break;
default:
$html .= '<input type="text"'
.(!empty($val['size'])?' size="'.$val['size'].'"':'')
.(!empty($val['placeholder'])?' placeholder="'.$val['placeholder'].'"':'')
.' name="'.$name.'" id="'.$name.'" value="'.(isset($form[$name])?htmlspecialchars($form[$name]):'').'" />';
break;
. (!empty($val['size']) ? ' size="' . $val['size'] . '"' : '')
. (!empty($val['placeholder']) ? ' placeholder="' . $val['placeholder'] . '"' : '')
. ' name="' . $name . '" id="' . $name . '" value="' . (isset($form[$name]) ? htmlspecialchars($form[$name]) : '') . '" />';
break;
}
if(isset($val['info']) && $val['info'])
$html .= ' <i>'.$val['info'].'</i>';
if (isset($val['info']) && $val['info'])
$html .= ' <i>' . $val['info'] . '</i>';
$html .= '</td></tr>';
}
$this->app->Tpl->Add($target, $html);
@ -290,21 +272,20 @@ abstract class Versanddienstleister {
*/
public function ValidateSettings(array &$form): array
{
return [];
return [];
}
/**
* @param string $tracking
* @param int $versand
* @param int $lieferschein
* @param int $versand
* @param int $lieferschein
*/
public function SetTracking($tracking,$versand=0,$lieferschein=0, $trackingLink = '')
public function SetTracking($tracking, $versand = 0, $lieferschein = 0, $trackingLink = '')
{
//if($versand > 0) $this->app->DB->Update("UPDATE versand SET tracking=CONCAT(tracking,if(tracking!='',';',''),'".$tracking."') WHERE id='$versand' LIMIT 1");
$this->app->User->SetParameter('versand_lasttracking',$tracking);
$this->app->User->SetParameter('versand_lasttracking_link',$trackingLink);
$this->app->User->SetParameter('versand_lasttracking', $tracking);
$this->app->User->SetParameter('versand_lasttracking_link', $trackingLink);
$this->app->User->SetParameter('versand_lasttracking_versand', $versand);
$this->app->User->SetParameter('versand_lasttracking_lieferschein', $lieferschein);
}
@ -314,17 +295,17 @@ abstract class Versanddienstleister {
*/
public function deleteTrackingFromUserdata($tracking)
{
if(empty($tracking)) {
if (empty($tracking)) {
return;
}
$trackingUser = !empty($this->app->User) && method_exists($this->app->User,'GetParameter')?
$this->app->User->GetParameter('versand_lasttracking'):'';
if(empty($trackingUser) || $trackingUser !== $tracking) {
$trackingUser = !empty($this->app->User) && method_exists($this->app->User, 'GetParameter') ?
$this->app->User->GetParameter('versand_lasttracking') : '';
if (empty($trackingUser) || $trackingUser !== $tracking) {
return;
}
$this->app->User->SetParameter('versand_lasttracking','');
$this->app->User->SetParameter('versand_lasttracking_link','');
$this->app->User->SetParameter('versand_lasttracking', '');
$this->app->User->SetParameter('versand_lasttracking_link', '');
$this->app->User->SetParameter('versand_lasttracking_versand', '');
$this->app->User->SetParameter('versand_lasttracking_lieferschein', '');
}
@ -341,21 +322,84 @@ abstract class Versanddienstleister {
/**
* @param string $tracking
* @param int $notsend
* @param int $notsend
* @param string $link
* @param string $rawlink
*
* @return bool
*/
public function Trackinglink($tracking, &$notsend, &$link, &$rawlink) {
public function Trackinglink($tracking, &$notsend, &$link, &$rawlink)
{
$notsend = 0;
$rawlink = '';
$link = '';
return true;
}
public function Paketmarke(string $target, string $docType, int $docId): void {
public function Paketmarke(string $target, string $docType, int $docId): void
{
$address = $this->GetAdressdaten($docId, $docType);
if (isset($_SERVER['HTTP_CONTENT_TYPE']) && ($_SERVER['HTTP_CONTENT_TYPE'] === 'application/json')) {
$json = json_decode(file_get_contents('php://input'));
$ret = [];
if ($json->submit == 'print') {
$result = $this->CreateShipment($json, $address);
if ($result->Success) {
$sql = "INSERT INTO versand
(adresse, lieferschein, versandunternehmen, gewicht, tracking, tracking_link, anzahlpakete)
VALUES
({$address['addressId']}, {$address['lieferscheinId']}, '$this->type',
'$json->weight', '$result->TrackingNumber', '$result->TrackingUrl', 1)";
print_r($sql);
$this->app->DB->Insert($sql);
$filename = $this->app->erp->GetTMP() . join('_', [$this->type, 'Label', $result->TrackingNumber]) . '.pdf';
file_put_contents($filename, $result->Label);
$this->app->printer->Drucken($this->labelPrinterId, $filename);
if (isset($result->ExportDocuments)) {
$filename = $this->app->erp->GetTMP() . join('_', [$this->type, 'ExportDoc', $result->TrackingNumber]) . '.pdf';
file_put_contents($filename, $result->ExportDocuments);
$this->app->printer->Drucken($this->documentPrinterId, $filename);
}
$ret['messages'][] = ['class' => 'info', 'text' => "Paketmarke wurde erfolgreich erstellt: $result->TrackingNumber"];
} else {
$ret['messages'] = array_map(fn(string $item) => ['class' => 'error', 'text' => $item], array_unique($result->Errors));
}
}
header('Content-Type: application/json');
echo json_encode($ret);
$this->app->ExitXentral();
}
$address['sendungsart'] = CustomsInfo::CUSTOMS_TYPE_GOODS;
$products = $this->GetShippingProducts();
$products = array_combine(array_column($products, 'Id'), $products);
$address['product'] = $products[0]->Id ?? '';
$json['form'] = $address;
$json['countries'] = $this->app->erp->GetSelectLaenderliste();
$json['products'] = $products;
$json['customs_shipment_types'] = [
CustomsInfo::CUSTOMS_TYPE_GIFT => 'Geschenk',
CustomsInfo::CUSTOMS_TYPE_DOCUMENTS => 'Dokumente',
CustomsInfo::CUSTOMS_TYPE_GOODS => 'Handelswaren',
CustomsInfo::CUSTOMS_TYPE_SAMPLE => 'Erprobungswaren',
CustomsInfo::CUSTOMS_TYPE_RETURN => 'Rücksendung'
];
$json['messages'] = [];
$json['form']['services'] = [
Product::SERVICE_PREMIUM => false
];
$this->app->Tpl->Set('JSON', json_encode($json));
$this->app->Tpl->Set('CARRIERNAME', $this->GetName());
$this->app->Tpl->Parse($target, 'createshipment.tpl');
}
public abstract function CreateShipment(object $json, array $address): CreateShipmentResult;
/**
* @return Product[]
*/
public abstract function GetShippingProducts(): array;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,57 +1,57 @@
<div class="container-fluid" id="sendcloudapp">
<div class="container-fluid" id="createshipmentapp">
<form action="" method="post" v-on:submit.prevent="submit">
<div class="row">
<div v-for="msg in messages" :class="msg.class">{{msg.text}}</div>
<div>
<h1>{|Paketmarken Drucker f&uuml;r|} SendCloud</h1>
<h1>{|Paketmarken Drucker f&uuml;r|} [CARRIERNAME]</h1>
</div>
<div class="col-md-4">
<h2>{|Empf&auml;nger|}</h2>
<table>
<tr>
<td>{|Name|}:</td>
<td><input type="text" size="36" v-model="form.l_name"></td>
<td><input type="text" size="36" v-model.trim="form.name"></td>
</tr>
<tr>
<td>{|Firmenname|}:</td>
<td><input type="text" size="36" v-model="form.l_companyname"></td>
<td><input type="text" size="36" v-model.trim="form.companyname"></td>
</tr>
<tr>
<td>{|Strasse/Hausnummer|}:</td>
<td>
<input type="text" size="30" v-model="form.strasse">
<input type="text" size="5" v-model="form.hausnummer">
<input type="text" size="30" v-model.trim="form.street">
<input type="text" size="5" v-model.trim="form.streetnumber">
</td>
</tr>
<tr>
<td>{|Adresszeile 2|}:</td>
<td><input type="text" size="36" v-model="form.l_address2"></td>
<td><input type="text" size="36" v-model.trim="form.address2"></td>
</tr>
<tr>
<td>{|PLZ/Ort|}:</td>
<td><input type="text" size="5" v-model="form.plz">
<input type="text" size="30" v-model="form.ort">
<td><input type="text" size="5" v-model.trim="form.zip">
<input type="text" size="30" v-model.trim="form.city">
</td>
</tr>
<tr>
<td>{|Bundesland|}:</td>
<td><input type="text" size="36" v-model="form.bundesland"></td>
<td><input type="text" size="36" v-model.trim="form.state"></td>
</tr>
<tr>
<td>{|Land|}:</td>
<td>
<select v-model="form.land">
<select v-model="form.country" required>
<option v-for="(value, key) in countries" :value="key">{{value}}</option>
</select>
</td>
</tr>
<tr>
<td>{|E-Mail|}:</td>
<td><input type="text" size="36" v-model="form.email"></td>
<td><input type="text" size="36" v-model.trim="form.email"></td>
</tr>
<tr>
<td>{|Telefon|}:</td>
<td><input type="text" size="36" v-model="form.telefon"></td>
<td><input type="text" size="36" v-model.trim="form.phone"></td>
</tr>
</table>
@ -61,39 +61,39 @@
<table>
<tr>
<td>{|Name|}</td>
<td>{{form.name}}</td>
<td>{{form.original.name}}</td>
</tr>
<tr>
<td>{|Ansprechpartner|}</td>
<td>{{form.ansprechpartner}}</td>
<td>{{form.original.ansprechpartner}}</td>
</tr>
<tr>
<td>{|Abteilung|}</td>
<td>{{form.abteilung}}</td>
<td>{{form.original.abteilung}}</td>
</tr>
<tr>
<td>{|Unterabteilung|}</td>
<td>{{form.unterabteilung}}</td>
<td>{{form.original.unterabteilung}}</td>
</tr>
<tr>
<td>{|Adresszusatz|}</td>
<td>{{form.adresszusatz}}</td>
<td>{{form.original.adresszusatz}}</td>
</tr>
<tr>
<td>{|Strasse|}</td>
<td>{{form.streetwithnumber}}</td>
<td>{{form.original.strasse}}</td>
</tr>
<tr>
<td>{|PLZ/Ort|}</td>
<td>{{form.plz}} {{form.ort}}</td>
<td>{{form.original.plz}} {{form.original.ort}}</td>
</tr>
<tr>
<td>{|Bundesland|}</td>
<td>{{form.bundesland}}</td>
<td>{{form.original.bundesland}}</td>
</tr>
<tr>
<td>{|Land|}</td>
<td>{{form.land}}</td>
<td>{{form.original.land}}</td>
</tr>
</table>
</div>
@ -102,28 +102,32 @@
<table>
<tr>
<td>{|Gewicht (in kg)|}:</td>
<td><input type="text" v-model="form.weight"></td>
<td><input type="text" v-model.number="form.weight"></td>
</tr>
<tr>
<td>{|H&ouml;he (in cm)|}:</td>
<td><input type="text" size="10" v-model="form.height"></td>
<td><input type="text" size="10" v-model.number="form.height"></td>
</tr>
<tr>
<td>{|Breite (in cm)|}:</td>
<td><input type="text" size="10" v-model="form.width"></td>
<td><input type="text" size="10" v-model.number="form.width"></td>
</tr>
<tr>
<td>{|L&auml;nge (in cm)|}:</td>
<td><input type="text" size="10" v-model="form.length"></td>
<td><input type="text" size="10" v-model.number="form.length"></td>
</tr>
<tr>
<td>{|Produkt|}:</td>
<td>
<select v-model="form.method">
<option v-for="(value, key, index) in methods" :value="key">{{value}}</option>
<select v-model="form.product">
<option v-for="prod in products" :value="prod.Id">{{prod.Name}}</option>
</select>
</td>
</tr>
<tr v-if="serviceAvailable('premium')">
<td>{|Premium|}:</td>
<td><input type="checkbox" v-model="form.services.premium"></td>
</tr>
</table>
</div>
<div class="clearfix"></div>
@ -161,25 +165,23 @@
<th>{|Herkunftsland|}</th>
<th>{|Einzelwert|}</th>
<th>{|Einzelgewicht|}</th>
<th>{|Währung|}</th>
<th>{|Gesamtwert|}</th>
<th>{|Gesamtgewicht|}</th>
<th><a v-on:click="addPosition"><img src="themes/new/images/add.png"></a></</th>
</tr>
<tr v-for="(pos, index) in form.positions">
<td><input type="text" v-model="pos.bezeichnung" required></td>
<td><input type="text" v-model="pos.menge" required></td>
<td><input type="text" v-model="pos.zolltarifnummer" required></td>
<td><input type="text" v-model="pos.herkunftsland" required></td>
<td><input type="text" v-model="pos.zolleinzelwert" required></td>
<td><input type="text" v-model="pos.zolleinzelgewicht" required></td>
<td><input type="text" v-model="pos.zollwaehrung" required></td>
<td><input type="text" v-model.trim="pos.bezeichnung" required></td>
<td><input type="text" v-model.number="pos.menge" required></td>
<td><input type="text" v-model.trim="pos.zolltarifnummer" required></td>
<td><input type="text" v-model.trim="pos.herkunftsland" required></td>
<td><input type="text" v-model.number="pos.zolleinzelwert" required></td>
<td><input type="text" v-model.number="pos.zolleinzelgewicht" required></td>
<td>{{Number(pos.menge*pos.zolleinzelwert || 0).toFixed(2)}}</td>
<td>{{Number(pos.menge*pos.zolleinzelgewicht || 0).toFixed(3)}}</td>
<td><a v-on:click="deletePosition(index)"><img src="themes/new/images/delete.svg"></a></td>
</tr>
<tr>
<td colspan="7"></td>
<td colspan="6"></td>
<td>{{total_value.toFixed(2)}}</td>
<td>{{total_weight.toFixed(3)}}</td>
</tr>
@ -187,33 +189,27 @@
</div>
<div>
<input class="btnGreen" type="submit" value="{|Paketmarke drucken|}" name="drucken">&nbsp;
<input type="button" value="{|Andere Versandart auswählen|}" name="anders">&nbsp;
<!--<input type="button" value="{|Andere Versandart auswählen|}" name="anders">&nbsp;-->
</div>
</div>
</form>
</div>
<script type="text/javascript">
const sendcloudApp = new Vue({
el: '#sendcloudapp',
data: {
form: [JSON],
countries: [JSON_COUNTRIES],
methods: [JSON_METHODS],
customs_shipment_types: [JSON_CUSTOMS_SHIPMENT_TYPES],
messages: []
},
const createshipmentapp = new Vue({
el: '#createshipmentapp',
data: [JSON],
computed: {
total_value() {
let sum = 0;
for(const pos of this.form.positions) {
sum += pos.menge * pos.zolleinzelwert;
sum += (pos.menge * pos.zolleinzelwert) || 0;
}
return sum;
},
total_weight() {
let sum = 0;
for(const pos of this.form.positions) {
sum += pos.menge * pos.zolleinzelgewicht;
sum += (pos.menge * pos.zolleinzelgewicht) || 0;
}
return sum;
}
@ -235,6 +231,11 @@
},
deletePosition: function(index) {
this.form.positions.splice(index, 1);
},
serviceAvailable: function(service) {
if (!this.products.hasOwnProperty(this.form.product))
return false;
return this.products[this.form.product].AvailableServices.indexOf(service) >= 0;
}
}
})

View File

@ -0,0 +1,169 @@
<?php
/**
*
*/
use Xentral\Carrier\Dhl\Data\Communication;
use Xentral\Carrier\Dhl\Data\Country;
use Xentral\Carrier\Dhl\Data\CreateShipmentOrderResponse;
use Xentral\Carrier\Dhl\Data\NativeAddress;
use Xentral\Carrier\Dhl\Data\Shipment;
use Xentral\Carrier\Dhl\Data\ShipmentItem;
use Xentral\Carrier\Dhl\DhlApi;
use Xentral\Modules\ShippingMethod\Model\CreateShipmentResult;
use Xentral\Modules\ShippingMethod\Model\Product;
require_once(dirname(__DIR__).'/class.versanddienstleister.php');
class Versandart_dhl extends Versanddienstleister{
public function GetName():string
{
return 'DHL';
}
public function AdditionalSettings(): array
{
return [
'user' => array('typ' => 'text', 'bezeichnung' => 'Benutzer:', 'info' => 'geschaeftskunden_api (Versenden/Intraship-Benutzername)'),
'signature' => array('typ' => 'text', 'bezeichnung' => 'Signature:', 'info' => 'Dhl_ep_test1 (Versenden/IntrashipPasswort)'),
'ekp' => array('typ' => 'text', 'bezeichnung' => 'EKP', 'info' => '5000000000 (gültige DHL Kundennummer)'),
'accountnumber' => array('typ' => 'text', 'bezeichnung' => 'Abrechnungsnummer Paket:'),
'accountnumber_int' => array('typ' => 'text', 'bezeichnung' => 'Abrechnungsnummer Paket International:'),
'accountnumber_euro' => array('typ' => 'text', 'bezeichnung' => 'Abrechnungsnummer Europaket:'),
'accountnumber_connect' => array('typ' => 'text', 'bezeichnung' => 'Abrechnungsnummer Paket Connect:'),
'accountnumber_wp' => array('typ' => 'text', 'bezeichnung' => 'Abrechnungsnummer Warenpost:'),
'accountnumber_wpint' => array('typ' => 'text', 'bezeichnung' => 'Abrechnungsnummer Warenpost International:'),
// 'intraship_retourenaccount' => array('typ' => 'text', 'bezeichnung' => 'Retouren Account:', 'info' => '14 Stellige DHL-Retoure Abrechnungsnummer'),
// 'intraship_retourenlabel' => array('typ' => 'checkbox', 'bezeichnung' => 'Vorauswahl Retourenlabel:', 'info' => 'Druckt Retourenlabel mit'),
'sender_name1' => array('typ' => 'text', 'bezeichnung' => 'Versender Firma:'),
'sender_street' => array('typ' => 'text', 'bezeichnung' => 'Versender Strasse:'),
'sender_streetnumber' => array('typ' => 'text', 'bezeichnung' => 'Versender Strasse Nr.:'),
'sender_zip' => array('typ' => 'text', 'bezeichnung' => 'Versender PLZ:'),
'sender_city' => array('typ' => 'text', 'bezeichnung' => 'Versender Stadt:'),
'sender_country' => array('typ' => 'text', 'bezeichnung' => 'Versender ISO Code:', 'info' => 'DE'),
'sender_email' => array('typ' => 'text', 'bezeichnung' => 'Versender E-Mail:'),
'sender_phone' => array('typ' => 'text', 'bezeichnung' => 'Versender Telefon:'),
'sender_web' => array('typ' => 'text', 'bezeichnung' => 'Versender Web:'),
'sender_contact_person' => array('typ' => 'text', 'bezeichnung' => 'Versender Ansprechpartner:'),
'cod_account_owner' => array('typ' => 'text', 'bezeichnung' => 'Nachnahme Kontoinhaber:'),
'cod_bank_name' => array('typ' => 'text', 'bezeichnung' => 'Nachnahme Bank Name:'),
'cod_account_iban' => array('typ' => 'text', 'bezeichnung' => 'Nachnahme IBAN:'),
'cod_account_bic' => array('typ' => 'text', 'bezeichnung' => 'Nachnahme BIC:'),
'cod_extra_fee' => array('typ' => 'text', 'bezeichnung' => 'Nachnahme Gebühr:', 'info' => 'z.B. 2,00 wird auf Rechnungsbetrag addiert, da DHL dies als extra Gebühr für sich behält'),
'weight' => array('typ' => 'text', 'bezeichnung' => 'Standard Gewicht:', 'info' => 'in KG'),
'length' => array('typ' => 'text', 'bezeichnung' => 'Standard Länge:', 'info' => 'in cm'),
'width' => array('typ' => 'text', 'bezeichnung' => 'Standard Breite:', 'info' => 'in cm'),
'height' => array('typ' => 'text', 'bezeichnung' => 'Standard Höhe:', 'info' => 'in cm'),
'product' => array('typ' => 'text', 'bezeichnung' => 'Standard Produkt:', 'info' => 'z.B. in DE: V01PAK oder AT: V86PARCEL'),
'use_premium' => array('typ' => 'checkbox', 'bezeichnung' => 'Premiumversand verwenden:'),
/*
'intraship_vorausverfuegung' => array('typ' => 'select', 'bezeichnung' => 'Vorausverf&uuml;gung: ', 'optionen' => array('-' => 'keine Vorausverf&uuml;gung', 'IMMEDIATE' => 'Sofortige R&uuml;cksendung an den Absender', 'AFTER_DEADLINE' => 'R&uuml;cksenden an den Absender nach Ablauf der Frist', 'ABANDONMENT' => 'Preisgabe des Pakets durch den Absender (entgeltfrei)')),
'sperrgut' => array('typ' => 'checkbox', 'bezeichnung' => 'Sperrgut:'),
'keineversicherung' => array('typ' => 'checkbox', 'bezeichnung' => 'Extra Versicherung ausschalten:', 'info' => 'Option muss von Hand im Paketmarkendialog gesetzt werden.'),
'leitcodierung' => array('typ' => 'checkbox', 'bezeichnung' => 'Leitcodierung aktivieren:'),
'use_shipping_article_from_order_on_export' => ['typ' => 'checkbox', 'bezeichnung' => 'Bei Export Porto aus Auftrag senden:'],
'autotracking' => array('typ' => 'checkbox', 'bezeichnung' => 'Tracking übernehmen:'),
'log' => array('typ' => 'checkbox', 'bezeichnung' => 'Logging')*/
];
}
public function CreateShipment(object $json, array $address): CreateShipmentResult
{
$shipment = new Shipment();
$shipment->ShipmentDetails->product = $json->product;
$shipment->ShipmentDetails->accountNumber = '22222222220101';
$shipment->ShipmentDetails->SetShipmentDate(new DateTimeImmutable('today'));
$shipment->ShipmentDetails->ShipmentItem = new ShipmentItem();
$shipment->ShipmentDetails->ShipmentItem->weightInKG = $json->weight ?? 0;
$shipment->ShipmentDetails->ShipmentItem->lengthInCM = $json->length;
$shipment->ShipmentDetails->ShipmentItem->widthInCM = $json->width;
$shipment->ShipmentDetails->ShipmentItem->heightInCM = $json->height;
$shipment->Shipper->Name->name1 = $this->settings->sender_name1 ?? '';
$shipment->Shipper->Address->streetName = $this->settings->sender_street ?? '';
$shipment->Shipper->Address->streetNumber = $this->settings->sender_streetnumber;
$shipment->Shipper->Address->zip = $this->settings->sender_zip ?? '';
$shipment->Shipper->Address->city = $this->settings->sender_city ?? '';
$shipment->Shipper->Address->Origin = Country::Create($this->settings->sender_country ?? 'DE');
$shipment->Shipper->Communication = new Communication();
$shipment->Shipper->Communication->phone = $this->settings->sender_phone;
$shipment->Shipper->Communication->email = $this->settings->sender_email;
$shipment->Shipper->Communication->contactPerson = $this->settings->sender_contact_person;
$shipment->Receiver->name1 = $json->name;
$shipment->Receiver->Address = new NativeAddress();
$shipment->Receiver->Address->streetName = $json->street ?? '';
$shipment->Receiver->Address->streetNumber = $json->streetnumber ?? '';
$shipment->Receiver->Address->city = $json->city ?? '';
$shipment->Receiver->Address->zip = $json->zip ?? '';
$shipment->Receiver->Address->Origin = Country::Create($json->country ?? 'DE', $json->state);
$shipment->Receiver->Communication = new Communication();
$shipment->Receiver->Communication->email = $json->email;
$shipment->Receiver->Communication->phone = $json->phone;
$api = new DhlApi($this->settings->user, $this->settings->signature);
$ret = new CreateShipmentResult();
$result = $api->CreateShipment($shipment);
if (!$result instanceof CreateShipmentOrderResponse) {
$ret->Errors[] = $result;
return $ret;
}
if ($result->Status->statusCode === 0) {
$ret->Success = true;
$ret->TrackingNumber = $result->CreationState->shipmentNumber;
$ret->TrackingUrl = sprintf('https://www.dhl.de/de/privatkunden/pakete-empfangen/verfolgen.html?piececode=%s', $ret->TrackingNumber);
if (isset($result->CreationState->LabelData->labelData))
$ret->Label = base64_decode($result->CreationState->LabelData->labelData);
if (isset($result->CreationState->LabelData->exportLabelData))
$ret->ExportDocuments = base64_decode($result->CreationState->LabelData->exportLabelData);
} else {
if (is_array($result->CreationState->LabelData->Status->statusMessage))
$ret->Errors = $result->CreationState->LabelData->Status->statusMessage;
else
$ret->Errors[] = $result->CreationState->LabelData->Status->statusMessage;
}
return $ret;
}
public function GetShippingProducts(): array
{
$result = [];
$result[] = Product::Create('V01PAK', 'DHL Paket')
->WithLength(15, 120)
->WithWidth(11, 60)
->WithHeight(1, 60)
->WithWeight(0.01, 31.5);
$result[] = Product::Create('V53WPAK', 'DHL Paket International')
->WithLength(15, 120)
->WithWidth(11, 60)
->WithHeight(1, 60)
->WithWeight(0.01, 31.5)
->WithServices([Product::SERVICE_PREMIUM]);
$result[] = Product::Create('V54EPAK', 'DHL Europaket')
->WithLength(15, 120)
->WithWidth(11, 60)
->WithHeight(3.5, 60)
->WithWeight(0.01, 31.5);
$result[] = Product::Create('V55PAK', 'DHL Paket Connect')
->WithLength(15, 120)
->WithWidth(11, 60)
->WithHeight(3.5, 60)
->WithWeight(0.01, 31.5);
$result[] = Product::Create('V62WP', 'DHL Warenpost')
->WithLength(10, 35)
->WithWidth(7, 25)
->WithHeight(0.1, 5)
->WithWeight(0.01, 1);
$result[] = Product::Create('V66WPI', 'DHL Warenpost International')
->WithLength(10, 35)
->WithWidth(7, 25)
->WithHeight(0.1, 10)
->WithWeight(0.01, 1)
->WithServices([Product::SERVICE_PREMIUM]);
return $result;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,8 @@ use Xentral\Carrier\SendCloud\Data\SenderAddress;
use Xentral\Carrier\SendCloud\Data\ShippingProduct;
use Xentral\Carrier\SendCloud\Data\ShippingMethod;
use Xentral\Carrier\SendCloud\SendcloudApiException;
use Xentral\Modules\ShippingMethod\Model\CreateShipmentResult;
use Xentral\Modules\ShippingMethod\Model\Product;
require_once dirname(__DIR__) . '/class.versanddienstleister.php';
@ -25,6 +27,11 @@ class Versandart_sendcloud extends Versanddienstleister
$this->api = new SendCloudApi($this->settings->public_key, $this->settings->private_key);
}
public function GetName(): string
{
return "SendCloud";
}
protected function FetchOptionsFromApi()
{
if (isset($this->options))
@ -49,13 +56,6 @@ class Versandart_sendcloud extends Versanddienstleister
$this->options['products'][0] = '';
$this->options['selectedProduct'] = $shippingProducts[$this->settings->shipping_product] ?? [];
natcasesort($this->options['products']);
$this->options['customs_shipment_types'] = [
0 => 'Geschenk',
1 => 'Dokumente',
2 => 'Kommerzielle Waren',
3 => 'Erprobungswaren',
4 => 'Rücksendung'
];
}
public function AdditionalSettings(): array
@ -66,102 +66,77 @@ class Versandart_sendcloud extends Versanddienstleister
'private_key' => ['typ' => 'text', 'bezeichnung' => 'API Private Key:'],
'sender_address' => ['typ' => 'select', 'bezeichnung' => 'Absender-Adresse:', 'optionen' => $this->options['senders']],
'shipping_product' => ['typ' => 'select', 'bezeichnung' => 'Versand-Produkt:', 'optionen' => $this->options['products']],
'default_customs_shipment_type' => ['typ' => 'select', 'bezeichnung' => 'Sendungsart:', 'optionen' => $this->options['customs_shipment_types']],
];
}
public function Paketmarke(string $target, string $docType, int $docId): void
public function CreateShipment(object $json, array $address): CreateShipmentResult
{
$address = $this->GetAdressdaten($docId, $docType);
if (isset($_SERVER['HTTP_CONTENT_TYPE']) && ($_SERVER['HTTP_CONTENT_TYPE'] === 'application/json')) {
$json = json_decode(file_get_contents('php://input'));
$response = [];
if ($json->submit == 'print') {
header('Content-Type: application/json');
$parcel = new ParcelCreation();
$parcel->SenderAddressId = $this->settings->sender_address;
$parcel->ShippingMethodId = $json->method;
$parcel->Name = $json->l_name;
$parcel->CompanyName = $json->l_companyname;
$parcel->Country = $json->land;
$parcel->PostalCode = $json->plz;
$parcel->City = $json->ort;
$parcel->Address = $json->strasse;
$parcel->Address2 = $json->l_address2;
$parcel->HouseNumber = $json->hausnummer;
$parcel->EMail = $json->email;
$parcel->Telephone = $json->telefon;
$parcel->CountryState = $json->bundesland;
$parcel->CustomsInvoiceNr = $json->invoice_number;
$parcel->CustomsShipmentType = $json->sendungsart;
$parcel->TotalInsuredValue = $json->total_insured_value;
$parcel->OrderNumber = $json->order_number;
foreach ($json->positions as $pos) {
$item = new ParcelItem();
$item->HsCode = $pos->zolltarifnummer;
$item->Description = $pos->bezeichnung;
$item->Quantity = $pos->menge;
$item->OriginCountry = $pos->herkunftsland;
$item->Price = $pos->zolleinzelwert;
$item->Weight = $pos->zolleinzelgewicht * 1000;
$parcel->ParcelItems[] = $item;
}
$parcel->Weight = floatval($json->weight) * 1000;
try {
$result = $this->api->CreateParcel($parcel);
if ($result instanceof ParcelResponse) {
$sql = "INSERT INTO versand
(adresse, lieferschein, versandunternehmen, gewicht, tracking, tracking_link, anzahlpakete)
VALUES
({$address['addressId']}, {$address['lieferscheinId']}, '$this->type',
'$json->weight', '$result->TrackingNumber', '$result->TrackingUrl', 1)";
$this->app->DB->Insert($sql);
$response['messages'][] = ['class' => 'info', 'text' => "Paketmarke wurde erfolgreich erstellt: $result->TrackingNumber"];
$doc = $result->GetDocumentByType(Document::TYPE_LABEL);
$filename = $this->app->erp->GetTMP() . join('_', ['Sendcloud', $doc->Type, $doc->Size, $result->TrackingNumber]) . '.pdf';
file_put_contents($filename, $this->api->DownloadDocument($doc));
$this->app->printer->Drucken($this->labelPrinterId, $filename);
$doc = $result->GetDocumentByType(Document::TYPE_CN23);
$filename = $this->app->erp->GetTMP() . join('_', ['Sendcloud', $doc->Type, $doc->Size, $result->TrackingNumber]) . '.pdf';
file_put_contents($filename, $this->api->DownloadDocument($doc));
$this->app->printer->Drucken($this->documentPrinterId, $filename);
} else {
$response['messages'][] = ['class' => 'error', 'text' => $result];
}
echo json_encode($response);
} catch (SendcloudApiException $e) {
$this->app->Tpl->addMessage('error', $e->getMessage());
}
$this->app->ExitXentral();
}
$parcel = new ParcelCreation();
$parcel->SenderAddressId = $this->settings->sender_address;
$parcel->ShippingMethodId = $json->product;
$parcel->Name = $json->name;
$parcel->CompanyName = $json->companyname;
$parcel->Country = $json->country;
$parcel->PostalCode = $json->zip;
$parcel->City = $json->city;
$parcel->Address = $json->street;
$parcel->Address2 = $json->address2;
$parcel->HouseNumber = $json->streetnumber;
$parcel->EMail = $json->email;
$parcel->Telephone = $json->phone;
$parcel->CountryState = $json->state;
$parcel->CustomsInvoiceNr = $json->invoice_number;
$parcel->CustomsShipmentType = $json->shipment_type;
$parcel->TotalInsuredValue = $json->total_insured_value;
$parcel->OrderNumber = $json->order_number;
foreach ($json->positions as $pos) {
$item = new ParcelItem();
$item->HsCode = $pos->zolltarifnummer;
$item->Description = $pos->bezeichnung;
$item->Quantity = $pos->menge;
$item->OriginCountry = $pos->herkunftsland;
$item->Price = $pos->zolleinzelwert;
$item->Weight = $pos->zolleinzelgewicht * 1000;
$parcel->ParcelItems[] = $item;
}
$parcel->Weight = floatval($json->weight) * 1000;
$ret = new CreateShipmentResult();
try {
$result = $this->api->CreateParcel($parcel);
if ($result instanceof ParcelResponse) {
$ret->Success = true;
$ret->TrackingNumber = $result->TrackingNumber;
$ret->TrackingUrl = $result->TrackingUrl;
$address['l_name'] = empty(trim($address['ansprechpartner'])) ? trim($address['name']) : trim($address['ansprechpartner']);
$address['l_companyname'] = !empty(trim($address['ansprechpartner'])) ? trim($address['name']) : '';
$address['l_address2'] = join(';', array_filter([
$address['abteilung'],
$address['unterabteilung'],
$address['adresszusatz']
], fn(string $item) => !empty(trim($item))));
$doc = $result->GetDocumentByType(Document::TYPE_LABEL);
$ret->Label = $this->api->DownloadDocument($doc);
$doc = $result->GetDocumentByType(Document::TYPE_CN23);
$ret->ExportDocuments = $this->api->DownloadDocument($doc);
} else {
$ret->Errors[] = $result;
}
} catch (SendcloudApiException $e) {
$ret->Errors[] = $e->getMessage();
}
return $ret;
}
public function GetShippingProducts(): array
{
$this->FetchOptionsFromApi();
/** @var ShippingProduct $product */
$product = $this->options['selectedProduct'];
$methods = [];
$result = [];
/** @var ShippingMethod $item */
foreach ($product->ShippingMethods as $item)
$methods[$item->Id] = $item->Name;
$address['method'] = array_key_first($methods);
$address['sendungsart'] = $this->settings->default_customs_shipment_type;
$this->app->Tpl->Set('JSON', json_encode($address));
$this->app->Tpl->Set('JSON_COUNTRIES', json_encode($this->app->erp->GetSelectLaenderliste()));
$this->app->Tpl->Set('JSON_METHODS', json_encode($methods));
$this->app->Tpl->Set('JSON_CUSTOMS_SHIPMENT_TYPES', json_encode($this->options['customs_shipment_types']));
$this->app->Tpl->Parse($target, 'versandarten_sendcloud.tpl');
foreach ($product->ShippingMethods as $item) {
$p = new Product();
$p->Id = $item->Id;
$p->Name = $item->Name;
$result[] = $p;
}
return $result;
}
}

View File

@ -66,7 +66,6 @@ function xentral_autoloader($class) {
'ICS'=>__DIR__.'/www/plugins/class.ics.php',
'USTID'=>__DIR__.'/www/lib/class.ustid.php',
'phpprint'=>__DIR__.'/www/plugins/php-print.php',
'DHLBusinessShipment'=>__DIR__.'/www/lib/class.intraship.php',
'Navigation'=>__DIR__.'/www/lib/class.navigation_edit.php',
'GoShipment'=>__DIR__.'/www/lib/class.go.php',
'UPSShipment'=>__DIR__.'/www/lib/class.ups.php',