* Fertigstellung Buchungsformular (#1321) (SternTours-CRM-API-Anbindung, Mailversand, Validierung, Dynamische Preisberechnung, Persistierung von Buchungsinformationen)
* Fehler bei der Preisberechnung behoben * Farbschema geändert (Kevin Adametz) git-svn-id: http://78.47.251.156/svn/dev/sterntours-3@3289 f459cee4-fb09-11de-96c3-f9c5f16c3c76
This commit is contained in:
parent
dde3b91724
commit
3a28866cd2
36 changed files with 2200 additions and 268 deletions
365
trunk/src/AppBundle/Export/SternToursCrmBookingExporter.php
Normal file
365
trunk/src/AppBundle/Export/SternToursCrmBookingExporter.php
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Ulrich Hecht <ulrich.hecht@hecht-software.de>
|
||||
* @date 02/13/2017
|
||||
*/
|
||||
|
||||
namespace AppBundle\Export;
|
||||
|
||||
|
||||
use AppBundle\Entity\BookingRequest;
|
||||
use AppBundle\Entity\TravelDate;
|
||||
use AppBundle\Entity\Traveler;
|
||||
use AppBundle\Util;
|
||||
use Monolog\Logger;
|
||||
|
||||
class SternToursCrmBookingExporter
|
||||
{
|
||||
const API_URL = 'http://www.cms.stern-tours.net/api';
|
||||
const API_KEY = 'f6077389c9ce710e554763a5de02c8ec';
|
||||
const API_USER_ID = 15; // 'apiuser'
|
||||
const WEBSITE_ID = 1; // 'sterntours.de'
|
||||
|
||||
private $logger;
|
||||
|
||||
public function __construct(Logger $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function process(BookingRequest $bookingRequest, TravelDate $travelDate, $bookingPriceInfo)
|
||||
{
|
||||
$tp = $travelDate->getTravelProgram();
|
||||
$startDateStr = $travelDate->getStart()->format('Y-m-d');
|
||||
$lead = $this->createLead($bookingRequest, $travelDate);
|
||||
if ($lead === null)
|
||||
{
|
||||
$this->warn('Failed creating lead in CRM', $bookingRequest, $travelDate, Logger::ERROR);
|
||||
return false;
|
||||
}
|
||||
$bookingUrl = $this->createBooking($bookingRequest, $travelDate, $bookingPriceInfo, $lead['customer_id'],
|
||||
$lead['id']);
|
||||
if ($bookingUrl === false)
|
||||
{
|
||||
$this->warn('Failed creating booking in CRM', $bookingRequest, $travelDate, Logger::ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 1; $i < $bookingRequest->getTravelerCount(); ++$i)
|
||||
{
|
||||
if (!$this->createTraveler($bookingUrl, $bookingRequest->getTravelers()[$i]))
|
||||
{
|
||||
$this->warn('Failed creating traveler with index '. $i .' in CRM.', $bookingRequest, $travelDate);
|
||||
}
|
||||
}
|
||||
|
||||
if ($tp->getIsMediated())
|
||||
{
|
||||
$serviceItemDefaults = [
|
||||
'travel_company_id' => $tp->getOrganizer()->getCmsId(),
|
||||
'travel_date' => $startDateStr,
|
||||
'commission' => 0,
|
||||
];
|
||||
|
||||
foreach ($bookingPriceInfo['rooms'] as $room)
|
||||
{
|
||||
$this->createServiceItem($bookingUrl, $serviceItemDefaults + [
|
||||
'service_price' => $room['price_total'],
|
||||
'name' => $room['name'],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->createServiceItem($bookingUrl, $serviceItemDefaults + [
|
||||
'service_price' => $bookingRequest->getTravelerCount() * $bookingPriceInfo['departure']->getExtraCharge(),
|
||||
'name' => $bookingRequest->getTravelerCount() .' x '. $bookingPriceInfo['departure']->getName()
|
||||
]);
|
||||
|
||||
foreach ($bookingRequest->getTravelOptions() as $option)
|
||||
{
|
||||
$this->createServiceItem($bookingUrl, $serviceItemDefaults + [
|
||||
'service_price' => $option->getPrice() * $bookingRequest->getTravelerCount(),
|
||||
'name' => $bookingRequest->getTravelerCount() .' x '. $option->getName()
|
||||
]);
|
||||
}
|
||||
|
||||
// Actually: extra_category
|
||||
foreach ($bookingPriceInfo['classOptions'] as $classOption)
|
||||
{
|
||||
$this->createServiceItem($bookingUrl, $serviceItemDefaults + [
|
||||
'service_price' => $classOption['count'] * $classOption['price'],
|
||||
'name' => $classOption['count'] .' x '. $classOption['name']
|
||||
]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$viewPosition = 100;
|
||||
$viewPositionPrice = 50;
|
||||
$endDateStr = $travelDate->getEnd()->format('Y-m-d');
|
||||
|
||||
$arrangementDefaults = [
|
||||
'state' => (new \DateTime())->format('Y-m-d'),
|
||||
'in_pdf' => 1
|
||||
];
|
||||
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 4, // Flug
|
||||
'type_s' => 'Flug',
|
||||
'begin' => $startDateStr,
|
||||
'view_position' => --$viewPosition,
|
||||
'data_s' => ['Hinflug' => 'von '. $bookingPriceInfo['departure']->getName()],
|
||||
]);
|
||||
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 26, // Preisinformation
|
||||
'type_s' => 'Preisinformation',
|
||||
'view_position' => --$viewPositionPrice,
|
||||
'data_s' => [
|
||||
'Name' => 'Abfahrts-/Abflugort '. $bookingPriceInfo['departure']->getName(),
|
||||
'Preis' => $bookingPriceInfo['departure']->getExtraCharge(),
|
||||
'Teilnehmer' => $bookingRequest->getTravelerCount(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 24, // Rundreise
|
||||
'type_s' => 'Rundreise', // Rundreise
|
||||
'begin' => $startDateStr,
|
||||
'end' => $endDateStr,
|
||||
'view_position' => --$viewPosition,
|
||||
'data_s' => ['Name' => $tp->getTitle() .' ('. $travelDate->getName() .')'],
|
||||
]);
|
||||
|
||||
$roomStrs = [];
|
||||
foreach ($bookingPriceInfo['rooms'] as $room)
|
||||
{
|
||||
$roomStrs[] = '1x '. $room['name'];
|
||||
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 26, // Preisinformation
|
||||
'type_s' => 'Preisinformation',
|
||||
'view_position' => --$viewPositionPrice,
|
||||
'data_s' => [
|
||||
'Name' => 'pro Person im \''. $room['name'] .'\'',
|
||||
'Preis' => $room['price'],
|
||||
'Teilnehmer' => $room['adults'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 5, // Hotel
|
||||
'type_s' => 'Hotel',
|
||||
'begin' => $startDateStr,
|
||||
'end' => $endDateStr,
|
||||
'view_position' => --$viewPosition,
|
||||
'data_s' => ['Zimmer' => implode(', ', $roomStrs)],
|
||||
]);
|
||||
|
||||
// Actually: extra_category
|
||||
foreach ($bookingPriceInfo['classOptions'] as $classOption)
|
||||
{
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 26, // Preisinformation
|
||||
'type_s' => 'Preisinformation',
|
||||
'view_position' => --$viewPositionPrice,
|
||||
'data_s' => [
|
||||
'Name' => $classOption['name'],
|
||||
'Preis' => $classOption['price'],
|
||||
'Teilnehmer' => $classOption['count'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 4, // Flug
|
||||
'type_s' => 'Flug',
|
||||
'begin' => $endDateStr,
|
||||
'view_position' => --$viewPosition,
|
||||
'data_s' => ['Rückflug' => $bookingRequest->getDeparture()->getName()],
|
||||
]);
|
||||
|
||||
foreach ($bookingRequest->getTravelOptions() as $option)
|
||||
{
|
||||
$this->createArrangement($bookingUrl, $arrangementDefaults + [
|
||||
'type_id' => 26, // Preisinformation
|
||||
'type_s' => 'Preisinformation',
|
||||
'view_position' => --$viewPositionPrice,
|
||||
'data_s' => [
|
||||
'Name' => $option->getName(),
|
||||
'Preis' => $option->getPrice(),
|
||||
'Teilnehmer' => $bookingRequest->getTravelerCount(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($bookingPriceInfo['insurances'] as $insuranceInfo)
|
||||
{
|
||||
$this->createServiceItem($bookingUrl, [
|
||||
'travel_company_id' => 30,
|
||||
'service_price' => $insuranceInfo['count'] * $insuranceInfo['insurancePriceValue'],
|
||||
'name' => $insuranceInfo['count'] . 'x ' . $insuranceInfo['insurance']->getName() . ' ('.
|
||||
$insuranceInfo['insurancePrice']->getCode() . ')',
|
||||
'commission' => round(($insuranceInfo['count'] * $insuranceInfo['insurancePriceValue']) * 20 / 100, 2),
|
||||
'travel_date' => $startDateStr,
|
||||
]);
|
||||
}
|
||||
|
||||
return $bookingUrl;
|
||||
}
|
||||
|
||||
private function createLead(BookingRequest $bookingRequest, TravelDate $travelDate)
|
||||
{
|
||||
$resp = $this->httpPost('lead', ['lead' => [
|
||||
'customerForm' => [
|
||||
'salutation_id' => $bookingRequest->getSalutation(),
|
||||
'name' => $bookingRequest->getLastName(),
|
||||
'firstname' => $bookingRequest->getFirstName(),
|
||||
'street' => $bookingRequest->getStreetAddress(),
|
||||
'zip' => $bookingRequest->getZipCode(),
|
||||
'city' => $bookingRequest->getCity(),
|
||||
'country_id' => $bookingRequest->getNation(),
|
||||
'phone' => $bookingRequest->getPhone(),
|
||||
'fax' => $bookingRequest->getFax(),
|
||||
'email' => $bookingRequest->getEmail()
|
||||
],
|
||||
'request_date' => (new \DateTime())->format('Y-m-d'),
|
||||
'sf_guard_user_id' => self::API_USER_ID,
|
||||
'status_id' => 7, // 'gebucht'
|
||||
'travelperiod_start' => $travelDate->getStart()->format('Y-m-d'),
|
||||
'travelperiod_end' => $travelDate->getEnd()->format('Y-m-d'),
|
||||
//'travelcategory_id'
|
||||
'is_closed' => 1,
|
||||
'website_id' => self::WEBSITE_ID,
|
||||
'initialcontacttype_id' => 14,
|
||||
// 'travelperiod_length
|
||||
'remarks' => $bookingRequest->getNotes()
|
||||
]]);
|
||||
|
||||
if ($resp['success'])
|
||||
{
|
||||
$ret = $this->httpGet($resp['location']);
|
||||
if ($ret == null)
|
||||
{
|
||||
$this->warn('Failed retrieving newly created lead object', $bookingRequest, $travelDate);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function createBooking(BookingRequest $bookingRequest, TravelDate $travelDate, $bookingPriceInfo,
|
||||
$customerId, $leadId)
|
||||
{
|
||||
$tp = $travelDate->getTravelProgram();
|
||||
$resp = $this->httpPost('booking', ['booking' => [
|
||||
'booking_date' => (new \DateTime())->format('Y-m-d'),
|
||||
'customer_id' => $customerId,
|
||||
'lead_id' => $leadId,
|
||||
'travel_country_id' => $tp->getTravelCountry(),
|
||||
'travel_category_id' => $tp->getTravelCategory(),
|
||||
'travelagenda_id' => $tp->getTravelAgenda(),
|
||||
'sf_guard_user_id' => self::API_USER_ID,
|
||||
'branch_id' => 4,
|
||||
'website_id' => self::WEBSITE_ID,
|
||||
'title' => $tp->getTitle(),
|
||||
'start_date' => $travelDate->getStart()->format('Y-m-d'),
|
||||
'end_date' => $travelDate->getEnd()->format('Y-m-d'),
|
||||
'pax' => $bookingRequest->getTravelerCount(),
|
||||
'travel_number' => $travelDate->getName(),
|
||||
'price' => $bookingPriceInfo['totalWithoutInsurance'],
|
||||
|
||||
'participant_salutation_id' => $bookingRequest->getTravelers()[0]->getSex(),
|
||||
'participant_name' => $bookingRequest->getTravelers()[0]->getLastName(),
|
||||
'participant_firstname' => $bookingRequest->getTravelers()[0]->getFirstName(),
|
||||
'participant_birthdate' => $bookingRequest->getTravelers()[0]->getBirthDate()->format('Y-m-d'),
|
||||
]]);
|
||||
|
||||
if (!$resp['success'])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return $resp['location'];
|
||||
}
|
||||
|
||||
private function createTraveler($bookingUrl, Traveler $traveler)
|
||||
{
|
||||
$resp = $this->httpPost($bookingUrl .'/participant.json', ['participant' => [
|
||||
'participant_salutation_id' => $traveler->getSex(),
|
||||
'participant_name' => $traveler->getLastName(),
|
||||
'participant_firstname' => $traveler->getFirstName(),
|
||||
'participant_birthdate' => $traveler->getBirthDate()->format('Y-m-d'),
|
||||
]], true);
|
||||
return $resp['success'];
|
||||
}
|
||||
|
||||
private function createServiceItem($bookingUrl, $serviceItemData)
|
||||
{
|
||||
$resp = $this->httpPost($bookingUrl .'/serviceitem.json', ['booking_service_item' => $serviceItemData], true);
|
||||
if (!$resp['success'])
|
||||
{
|
||||
$this->warn('Failed creating service item '. $serviceItemData['name'] .' for booking '. $bookingUrl);
|
||||
}
|
||||
return $resp['success'];
|
||||
}
|
||||
|
||||
private function createArrangement($bookingUrl, $arrangementData)
|
||||
{
|
||||
if (isset($arrangementData['data_s']) && is_array($arrangementData['data_s']))
|
||||
{
|
||||
$tmp = [];
|
||||
foreach ($arrangementData['data_s'] as $k => $v)
|
||||
{
|
||||
$tmp[] .= $k .': '. $v;
|
||||
}
|
||||
$arrangementData['data_s'] = implode("\n", $tmp);
|
||||
}
|
||||
$resp = $this->httpPost($bookingUrl .'/arrangement.json', ['arrangement' => $arrangementData], true);
|
||||
if (!$resp['success'])
|
||||
{
|
||||
$this->warn('Failed creating arrangement item '. $arrangementData['type_s'] .' for booking '. $bookingUrl);
|
||||
}
|
||||
return $resp['success'];
|
||||
}
|
||||
|
||||
private function httpGet($url)
|
||||
{
|
||||
$resp = Util::httpGet($url, ['X-ApiKey: '. self::API_KEY]);
|
||||
$ret = json_decode($resp['content'], true);
|
||||
if ($ret === null)
|
||||
{
|
||||
$this->warn('Invalid server response: '. $resp['content']);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function httpPost($context, $postData = [], $isContextFullUrl = false)
|
||||
{
|
||||
$url = $isContextFullUrl ? $context : self::API_URL.'/'. $context .'.json';
|
||||
$resp = Util::httpPost($url, $postData, ['X-ApiKey: '. self::API_KEY], true);
|
||||
return [
|
||||
'content' => json_decode($resp['content']),
|
||||
'location' => isset($resp['response_headers']['location'])
|
||||
? $resp['response_headers']['location']
|
||||
: null,
|
||||
'success' => $resp['success'] && ($resp['status_code'] == 201)
|
||||
];
|
||||
}
|
||||
|
||||
private function warn($msg, BookingRequest $bookingRequest = null, TravelDate $travelDate = null,
|
||||
$level = Logger::WARNING)
|
||||
{
|
||||
$this->logger->log($level, 'SternToursCrmBookingExporter: '. $msg);
|
||||
$this->logger->log($level, '*** Date: '. (new \DateTime())->format('d.m.Y'));
|
||||
if ($travelDate !== null)
|
||||
{
|
||||
$this->logger->log($level, '*** Travel date: '. $travelDate->getName() .'('. $travelDate->getStart()->format('d.m.Y') .
|
||||
' - '. $travelDate->getEnd()->format('d.m.Y') .')');
|
||||
//$this->logger->warn('*** Travel program ID: '. $travelDate->)
|
||||
}
|
||||
if ($bookingRequest !== null)
|
||||
{
|
||||
$this->logger->log($level, '*** User name: '. $bookingRequest->getFirstName() .' '. $bookingRequest->getLastName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue