* Behoben: Falsche CRM-URL in Buchungs-Service-E-Mail

* Kontaktformular

git-svn-id: http://78.47.251.156/svn/dev/sterntours-3@3300 f459cee4-fb09-11de-96c3-f9c5f16c3c76
This commit is contained in:
uli 2017-02-21 16:54:37 +00:00
parent ff9c159297
commit 353b758bcd
12 changed files with 741 additions and 34 deletions

View file

@ -94,6 +94,7 @@ class BookingController extends Controller
$em->flush();
$crmBookingUrl = $this->get('app.booking_exporter')->process($bookingRequest, $travelDate, $bookingPriceInfo);
$crmBookingUrl = preg_replace('/\\/api/', '', $crmBookingUrl) .'/edit';
$this->get('mailer')->send(\Swift_Message::newInstance()
->setSubject('Ihr Buchungsauftrag bei STERN TOURS')
@ -118,7 +119,7 @@ class BookingController extends Controller
->setBody(
$this->renderView('default/email/bookingServiceEmail.txt.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'crm_url' => $crmBookingUrl .'/edit',
'crm_url' => $crmBookingUrl,
'travel_program_url' => Util::getBaseUrl() . $travelProgramPage->getUrlPath(),
'booking_request' => $bookingRequest,
'booking_price_info' => $bookingPriceInfo,

View file

@ -3,8 +3,10 @@
namespace AppBundle\Controller;
use AppBundle\Entity\BreadcrumbEntry;
use AppBundle\Entity\ContactRequest;
use AppBundle\Entity\Page;
use AppBundle\Entity\TravelProgram;
use AppBundle\Form\ContactRequestType;
use AppBundle\Form\SearchRequestType;
use AppBundle\Form\TtSearchRequestType;
use AppBundle\Util;
@ -224,6 +226,62 @@ class DefaultController extends Controller
]);
}
/**
* @Route("/kontakt")
*/
public function contactAction(Request $request)
{
$form = $this->createForm(ContactRequestType::class);
$breadcrumbEntries = [new BreadcrumbEntry('Kontaktformular')];
if ($request->getMethod() == 'POST')
{
$form->handleRequest($request);
if ($form->isValid())
{
/** @var ContactRequest $contactRequest */
$contactRequest = $form->getData();
$crmLeadUrl = $this->get('app.contact_exporter')->process($contactRequest);
if ($crmLeadUrl)
{
$crmLeadUrl = preg_replace('/\\/api\\/lead/', '/leads', $crmLeadUrl) .'/edit';
}
else
{
$crmLeadUrl = '[Übertragung zum CRM fehlgeschlagung]';
}
$this->get('mailer')->send(\Swift_Message::newInstance()
->setSubject('Kontaktformular (stern-tours.de)')
->setFrom('stern@stern-tours.de', 'STERN TOURS')
->setTo('ulrich.hecht@hecht-software.de')
->setBody(
$this->renderView('default/email/contactServiceEmail.txt.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'crm_url' => $crmLeadUrl,
'contact_request' => $contactRequest,
]),
'text/plain', 'utf-8'
)
);
// #TODO This will lead to multiple submissions. Redirect instead!
return $this->render('default/pages/contactConfirmation.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'breadcrumb_entries' => $breadcrumbEntries,
]);
}
}
return $this->render('default/pages/contact.html.twig', [
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..').DIRECTORY_SEPARATOR,
'breadcrumb_entries' => $breadcrumbEntries,
'contact_form' => $form->createView(),
]);
}
public function headerAction()
{
$qb = $this->getEntityManager()->createQueryBuilder();

View file

@ -0,0 +1,361 @@
<?php
/**
* @author Ulrich Hecht <ulrich.hecht@hecht-software.de>
* @date 02/21/2017
*/
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
class ContactRequest
{
const MR = 1;
const MRS = 2;
/** @var int|null $salutation */
private $salutation;
/** @var string|null $firstName */
private $firstName;
/** @var string|null $lastName */
private $lastName;
/** @var string|null $streetAddress */
private $streetAddress;
/** @var string|null $zipCode */
private $zipCode;
/** @var string|null $city */
private $city;
/** @var int|null $nation */
private $nation;
/** @var string|null $phone */
private $phone;
/** @var string|null $mobilePhone */
private $mobilePhone;
/** @var string|null $email */
private $email;
/**
* @var string|null $travelerCount */
private $travelerCount;
/** @var string|null $notes */
private $notes;
/** @var string|null $departure0 */
private $departure0;
/** @var string|null $departure1 */
private $departure1;
/** @var string|null $departure2 */
private $departure2;
/** @var \DateTime|null $start */
private $start;
/** @var \DateTime|null $end */
private $end;
/**
* @var int|null $duration
* @Assert\Type(type="integer", message="Bitte geben Sie eine gültige Ganzzahl für die Dauer in Tagen ein")
*/
private $duration;
/**
* @return int|null
*/
public function getSalutation()
{
return $this->salutation;
}
/**
* @param int|null $salutation
*/
public function setSalutation($salutation)
{
$this->salutation = $salutation;
}
/**
* @return null|string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* @param null|string $firstName
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
}
/**
* @return null|string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* @param null|string $lastName
*/
public function setLastName($lastName)
{
$this->lastName = $lastName;
}
/**
* @return null|string
*/
public function getStreetAddress()
{
return $this->streetAddress;
}
/**
* @param null|string $streetAddress
*/
public function setStreetAddress($streetAddress)
{
$this->streetAddress = $streetAddress;
}
/**
* @return null|string
*/
public function getZipCode()
{
return $this->zipCode;
}
/**
* @param null|string $zipCode
*/
public function setZipCode($zipCode)
{
$this->zipCode = $zipCode;
}
/**
* @return null|string
*/
public function getCity()
{
return $this->city;
}
/**
* @param null|string $city
*/
public function setCity($city)
{
$this->city = $city;
}
/**
* @return int|null
*/
public function getNation()
{
return $this->nation;
}
/**
* @param int|null $nation
*/
public function setNation($nation)
{
$this->nation = $nation;
}
/**
* @return null|string
*/
public function getPhone()
{
return $this->phone;
}
/**
* @param null|string $phone
*/
public function setPhone($phone)
{
$this->phone = $phone;
}
/**
* @return null|string
*/
public function getMobilePhone()
{
return $this->mobilePhone;
}
/**
* @param null|string $mobilePhone
*/
public function setMobilePhone($mobilePhone)
{
$this->mobilePhone = $mobilePhone;
}
/**
* @return null|string
*/
public function getEmail()
{
return $this->email;
}
/**
* @param null|string $email
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* @return null|string
*/
public function getTravelerCount()
{
return $this->travelerCount;
}
/**
* @param null|string $travelerCount
*/
public function setTravelerCount($travelerCount)
{
$this->travelerCount = $travelerCount;
}
/**
* @return null|string
*/
public function getNotes()
{
return $this->notes;
}
/**
* @param null|string $notes
*/
public function setNotes($notes)
{
$this->notes = $notes;
}
/**
* @return null|string
*/
public function getDeparture0()
{
return $this->departure0;
}
/**
* @param null|string $departure0
*/
public function setDeparture0($departure0)
{
$this->departure0 = $departure0;
}
/**
* @return null|string
*/
public function getDeparture1()
{
return $this->departure1;
}
/**
* @param null|string $departure1
*/
public function setDeparture1($departure1)
{
$this->departure1 = $departure1;
}
/**
* @return null|string
*/
public function getDeparture2()
{
return $this->departure2;
}
/**
* @param null|string $departure2
*/
public function setDeparture2($departure2)
{
$this->departure2 = $departure2;
}
/**
* @return \DateTime|null
*/
public function getStart()
{
return $this->start;
}
/**
* @param \DateTime|null $start
*/
public function setStart($start)
{
$this->start = $start;
}
/**
* @return \DateTime|null
*/
public function getEnd()
{
return $this->end;
}
/**
* @param \DateTime|null $end
*/
public function setEnd($end)
{
$this->end = $end;
}
/**
* @return int|null
*/
public function getDuration()
{
return $this->duration;
}
/**
* @param int|null $duration
*/
public function setDuration($duration)
{
$this->duration = $duration;
}
}

View file

@ -13,18 +13,12 @@ use AppBundle\Entity\Traveler;
use AppBundle\Util;
use Monolog\Logger;
class SternToursCrmBookingExporter
class BookingSternToursCrmExporter extends SternToursCrmExporter
{
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;
parent::__construct($logger);
}
public function process(BookingRequest $bookingRequest, TravelDate $travelDate, $bookingPriceInfo)
@ -322,30 +316,6 @@ class SternToursCrmBookingExporter
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)
{

View file

@ -0,0 +1,61 @@
<?php
/**
* @author Ulrich Hecht <ulrich.hecht@hecht-software.de>
* @date 02/21/2017
*/
namespace AppBundle\Export;
use AppBundle\Entity\ContactRequest;
use Monolog\Logger;
class ContactSternToursCrmExporter extends SternToursCrmExporter
{
public function __construct(Logger $logger)
{
parent::__construct($logger);
}
public function process(ContactRequest $contactRequest)
{
$data = ['lead' => [
'customerForm' => [
'salutation_id' => $contactRequest->getSalutation(),
'name' => $contactRequest->getLastName(),
'firstname' => $contactRequest->getFirstName(),
'street' => $contactRequest->getStreetAddress(),
'zip' => $contactRequest->getZipCode(),
'city' => $contactRequest->getCity(),
'country_id' => $contactRequest->getNation(),
'phone' => $contactRequest->getPhone(),
'phonemobile' => $contactRequest->getMobilePhone(),
'email' => $contactRequest->getEmail()
],
'request_date' => (new \DateTime())->format('Y-m-d'),
'sf_guard_user_id' => self::API_USER_ID,
'status_id' => 10, // 'Angebot erstellen'
'travelperiod_start' => $contactRequest->getStart(),
'travelperiod_end' => $contactRequest->getEnd(),
//'travelcategory_id'
'is_closed' => 0,
'website_id' => self::WEBSITE_ID,
'initialcontacttype_id' => 1,
'travelperiod_length' => $contactRequest->getDuration(),
'remarks' => $contactRequest->getNotes(),
'pax' => $contactRequest->getTravelerCount(),
]];
$resp = $this->httpPost('lead', $data);
if (!$resp['success'])
{
$this->logger->error(get_class($this). ': Failed submitting contact request to CRM');
$this->logger->error('*** Submitted data: '. json_encode($data));
$this->logger->error('*** Server response: '. $resp['content']);
}
return $resp['location'] ?? null;
}
}

View file

@ -0,0 +1,51 @@
<?php
/**
* @author Ulrich Hecht <ulrich.hecht@hecht-software.de>
* @date 02/21/2017
*/
namespace AppBundle\Export;
use AppBundle\Util;
use Monolog\Logger;
abstract class SternToursCrmExporter
{
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'
protected $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
protected final function httpGet($url)
{
$resp = Util::httpGet($url, ['X-ApiKey: '. self::API_KEY]);
$ret = json_decode($resp['content'], true);
if ($ret === null)
{
$this->logger->warn(get_class($this) .': Invalid server response: '. $resp['content']);
$this->logger->warn('*** Date: '. (new \DateTime())->format('d.m.Y'));
}
return $ret;
}
protected final 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)
];
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @author Ulrich Hecht <ulrich.hecht@hecht-software.de>
* @date 02/21/2017
*/
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\NotNull;
class ContactRequestType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\ContactRequest',
]);
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$travelerCountChoices = [];
for ($i = 1; $i <= 20; ++$i)
{
$travelerCountChoices[$i] = $i;
}
$builder
->add('salutation', ChoiceType::class, [
'placeholder' => 'Anrede (Bitte wählen) *',
'choices' => BookingRequestType::$SALUTATION_CHOICES,
'constraints' => [
new NotNull(),
new Choice(['choices' => BookingRequestType::$SALUTATION_CHOICES])
]
])
->add('firstName', TextType::class, ['required' => true])
->add('lastName', TextType::class, ['required' => true])
->add('streetAddress')
->add('zipCode')
->add('city')
->add('nation', ChoiceType::class, [
'placeholder' => 'Land (Bitte wählen)',
'choices' => BookingRequestType::$NATION_CHOICES,
'constraints' => [
new NotNull(),
new Choice(['choices' => BookingRequestType::$NATION_CHOICES])
],
'data' => BookingRequestType::$NATION_CHOICES['Deutschland'],
])
->add('phone', TextType::class, ['required' => true])
->add('mobilePhone')
->add('email', EmailType::class, ['required' => true])
->add('travelerCount', ChoiceType::class, [
'placeholder' => 'Anzahl der Reisenden (Bitte wählen)',
'choices' => $travelerCountChoices,
'constraints' => [
new Choice(['choices' => $travelerCountChoices])]
])
->add('notes', TextareaType::class, ['required' => false])
->add('departure0')
->add('departure1')
->add('departure2')
->add('start', StDateType::class, ['required' => false])
->add('end', StDateType::class, ['required' => false])
->add('duration')
;
}
}