edit order form

This commit is contained in:
Etienne Roudeix
2013-09-26 13:07:51 +02:00
parent 5e0f9cedf5
commit 34ef5cf524
7 changed files with 451 additions and 44 deletions

View File

@@ -26,6 +26,7 @@ namespace Thelia\Action;
use Propel\Runtime\ActiveQuery\ModelCriteria;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Thelia\Core\Event\OrderAddressEvent;
use Thelia\Core\Event\OrderEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Exception\OrderException;
@@ -313,6 +314,30 @@ class Order extends BaseAction implements EventSubscriberInterface
$event->setOrder($order);
}
/**
* @param OrderAddressEvent $event
*/
public function updateAddress(OrderAddressEvent $event)
{
$orderAddress = $event->getOrderAddress();
$orderAddress
->setCustomerTitleId($event->getTitle())
->setCompany($event->getCompany())
->setFirstname($event->getFirstname())
->setLastname($event->getLastname())
->setAddress1($event->getAddress1())
->setAddress2($event->getAddress2())
->setAddress3($event->getAddress3())
->setZipcode($event->getZipcode())
->setCity($event->getCity())
->setPhone($event->getPhone())
;
$orderAddress->save();
$event->setOrderAddress($orderAddress);
}
/**
* Returns an array of event names this subscriber wants to listen to.
*
@@ -344,6 +369,7 @@ class Order extends BaseAction implements EventSubscriberInterface
TheliaEvents::ORDER_BEFORE_PAYMENT => array("sendOrderEmail", 128),
TheliaEvents::ORDER_UPDATE_STATUS => array("updateStatus", 128),
TheliaEvents::ORDER_UPDATE_DELIVERY_REF => array("updateDeliveryRef", 128),
TheliaEvents::ORDER_UPDATE_ADDRESS => array("updateAddress", 128),
);
}

View File

@@ -82,6 +82,10 @@
<default key="_controller">Thelia\Controller\Admin\OrderController::updateDeliveryRef</default>
</route>
<route id="admin.order.update.address" path="/admin/order/update/{order_id}/address">
<default key="_controller">Thelia\Controller\Admin\OrderController::updateAddress</default>
</route>
<!-- end order management -->
<!-- Categories management -->

View File

@@ -23,9 +23,12 @@
namespace Thelia\Controller\Admin;
use Thelia\Core\Event\OrderAddressEvent;
use Thelia\Core\Event\OrderEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Translation\Translator;
use Thelia\Form\OrderUpdateAddress;
use Thelia\Model\Base\OrderAddressQuery;
use Thelia\Model\OrderQuery;
use Thelia\Model\OrderStatusQuery;
use Thelia\Tools\URL;
@@ -136,4 +139,60 @@ class OrderController extends BaseAdminController
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", $params)));
}
public function updateAddress($order_id)
{
if (null !== $response = $this->checkAuth("admin.order.update")) return $response;
$message = null;
$orderUpdateAddress = new OrderUpdateAddress($this->getRequest());
try {
$order = OrderQuery::create()->findPk($order_id);
if(null === $order) {
throw new \InvalidArgumentException("The order you want to update does not exist");
}
$form = $this->validateForm($orderUpdateAddress, "post");
$orderAddress = OrderAddressQuery::create()->findPk($form->get("id")->getData());
if($orderAddress->getId() !== $order->getInvoiceOrderAddressId() && $orderAddress->getId() !== $order->getDeliveryOrderAddressId()) {
throw new \InvalidArgumentException("The order address you want to update does not belong to the current order not exist");
}
$event = new OrderAddressEvent(
$form->get("title")->getData(),
$form->get("firstname")->getData(),
$form->get("lastname")->getData(),
$form->get("address1")->getData(),
$form->get("address2")->getData(),
$form->get("address3")->getData(),
$form->get("zipcode")->getData(),
$form->get("city")->getData(),
$form->get("country")->getData(),
$form->get("phone")->getData(),
$form->get("company")->getData()
);
$event->setOrderAddress($orderAddress);
$event->setOrder($order);
$this->dispatch(TheliaEvents::ORDER_UPDATE_ADDRESS, $event);
} catch(\Exception $e) {
$message = $e->getMessage();
}
$params = array();
if ($message) {
$params["update_status_error_message"] = $message;
}
$params["order_id"] = $order_id;
$params["tab"] = $this->getRequest()->get("tab", 'bill');
$this->redirect(URL::getInstance()->absoluteUrl($this->getRoute("admin.order.update.view", $params)));
}
}

View File

@@ -0,0 +1,230 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Event;
use Thelia\Model\Order;
use Thelia\Model\OrderAddress;
class OrderAddressEvent extends ActionEvent
{
/**
* @var int title id
*/
protected $title;
/**
* @var string|null company name
*/
protected $company;
/**
* @var string first name
*/
protected $firstname;
/**
* @var string last name
*/
protected $lastname;
/**
* @var string address
*/
protected $address1;
/**
* @var string address line 2
*/
protected $address2;
/**
* @var string address line 3
*/
protected $address3;
/**
* @var string zipcode
*/
protected $zipcode;
/**
* @var string city
*/
protected $city;
/**
* @var int country id
*/
protected $country;
/**
* @var string phone
*/
protected $phone;
/**
* @var \Thelia\Model\OrderAddress
*/
protected $orderAddress;
/**
* @var \Thelia\Model\Order
*/
protected $order;
public function __construct($title, $firstname, $lastname, $address1, $address2, $address3, $zipcode, $city, $country, $phone, $company)
{
$this->address1 = $address1;
$this->address2 = $address2;
$this->address3 = $address3;
$this->city = $city;
$this->company = $company;
$this->country = $country;
$this->firstname = $firstname;
$this->lastname = $lastname;
$this->phone = $phone;
$this->title = $title;
$this->zipcode = $zipcode;
}
/**
* @return string
*/
public function getAddress1()
{
return $this->address1;
}
/**
* @return string
*/
public function getAddress2()
{
return $this->address2;
}
/**
* @return string
*/
public function getAddress3()
{
return $this->address3;
}
/**
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* @return null|string
*/
public function getCompany()
{
return $this->company;
}
/**
* @return int
*/
public function getCountry()
{
return $this->country;
}
/**
* @return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* @return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* @return string
*/
public function getPhone()
{
return $this->phone;
}
/**
* @return int
*/
public function getTitle()
{
return $this->title;
}
/**
* @return string
*/
public function getZipcode()
{
return $this->zipcode;
}
/**
* @param \Thelia\Model\OrderAddress $orderAddress
*/
public function setOrderAddress(OrderAddress $orderAddress)
{
$this->orderAddress = $orderAddress;
}
/**
* @param \Thelia\Model\Order $order
*/
public function setOrder(Order $order)
{
$this->order = $order;
}
/**
* @return \Thelia\Model\OrderAddress
*/
public function getOrderAddress()
{
return $this->orderAddress;
}
/**
* @return \Thelia\Model\Order
*/
public function getOrder()
{
return $this->order;
}
}

View File

@@ -303,6 +303,7 @@ final class TheliaEvents
const ORDER_UPDATE_STATUS = "action.order.updateStatus";
const ORDER_UPDATE_DELIVERY_REF = "action.order.updateDeliveryRef";
const ORDER_UPDATE_ADDRESS = "action.order.updateAddress";
const ORDER_PRODUCT_BEFORE_CREATE = "action.orderProduct.beforeCreate";
const ORDER_PRODUCT_AFTER_CREATE = "action.orderProduct.afterCreate";

View File

@@ -22,8 +22,13 @@
/*************************************************************************************/
namespace Thelia\Form;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\ExecutionContextInterface;
use Thelia\Core\Translation\Translator;
use Thelia\Model\CountryQuery;
use Thelia\Model\CustomerTitleQuery;
use Thelia\Model\OrderAddressQuery;
/**
* Class AddressUpdateForm
@@ -35,9 +40,25 @@ class OrderUpdateAddress extends BaseForm
protected function buildForm()
{
$this->formBuilder
->add("id", "integer", array(
"constraints" => array(
new NotBlank(),
new Callback(array(
"methods" => array(
array($this, "verifyId")
)
))
),
"required" => true
))
->add("title", "text", array(
"constraints" => array(
new NotBlank()
new NotBlank(),
new Callback(array(
"methods" => array(
array($this, "verifyTitle")
)
))
),
"label" => Translator::getInstance()->trans("Title"),
"label_attr" => array(
@@ -103,7 +124,12 @@ class OrderUpdateAddress extends BaseForm
))
->add("country", "text", array(
"constraints" => array(
new NotBlank()
new NotBlank(),
new Callback(array(
"methods" => array(
array($this, "verifyCountry")
)
))
),
"label" => Translator::getInstance()->trans("Country"),
"label_attr" => array(
@@ -133,4 +159,34 @@ class OrderUpdateAddress extends BaseForm
{
return "thelia_order_address_update";
}
public function verifyId($value, ExecutionContextInterface $context)
{
$address = OrderAddressQuery::create()
->findPk($value);
if(null === $address) {
$context->addViolation("Order address ID not found");
}
}
public function verifyTitle($value, ExecutionContextInterface $context)
{
$address = CustomerTitleQuery::create()
->findPk($value);
if(null === $address) {
$context->addViolation("Title ID not found");
}
}
public function verifyCountry($value, ExecutionContextInterface $context)
{
$address = CountryQuery::create()
->findPk($value);
if(null === $address) {
$context->addViolation("Country ID not found");
}
}
}

View File

@@ -196,7 +196,7 @@
<a class="btn btn-default btn-primary" title="{intl l='Download invoice as PDF'}" href="#">
<span class="glyphicon glyphicon-cloud-download"></span> {intl l='PDF | Invoice'}
</a>
<a class="btn btn-default btn-primary" title="{intl l='Edit invoice address'}" href="#edit_address_dialog" data-toggle="modal">
<a class="btn btn-default btn-primary js-update-order-address" data-address-id="{$INVOICE_ADDRESS}" title="{intl l='Edit invoice address'}" href="#edit_order_address_dialog" data-toggle="modal">
<span class="glyphicon glyphicon-edit"></span>
</a>
</div>
@@ -212,47 +212,47 @@
</tr>
{loop type="order_address" name="order-invoice-address" id=$INVOICE_ADDRESS}
<tr>
<tr data-field-class="js-title" data-value="{$TITLE}">
<th>{intl l="Title"}</th>
<td>{loop type="title" name="order-invoice-address-title" id=$TITLE}{$LONG}{/loop}</td>
</tr>
<tr>
<tr data-field-class="js-company">
<th>{intl l="Company"}</th>
<td>{$COMPANY}</td>
</tr>
<tr>
<tr data-field-class="js-firstname">
<th>{intl l="Firstname"}</th>
<td>{$FIRSTNAME}</td>
</tr>
<tr>
<tr data-field-class="js-lastname">
<th>{intl l="Lastname"}</th>
<td>{$LASTNAME}</td>
</tr>
<tr>
<tr data-field-class="js-address1">
<th>{intl l="Street address"}</th>
<td>{$ADDRESS1}</td>
</tr>
<tr>
<tr data-field-class="js-address2">
<th>{intl l="Additional address"}</th>
<td>{$ADDRESS2}</td>
</tr>
<tr>
<tr data-field-class="js-address3">
<th>{intl l="Additional address"}</th>
<td>{$ADDRESS3}</td>
</tr>
<tr>
<tr data-field-class="js-zipcode">
<th>{intl l="Zip code"}</th>
<td>{$ZIPCODE}</td>
</tr>
<tr>
<tr data-field-class="js-city">
<th>{intl l="City"}</th>
<td>{$CITY}</td>
</tr>
<tr>
<tr data-field-class="js-country" data-value="{$COUNTRY}">
<th>{intl l="Country"}</th>
<td>{loop type="country" name="order-invoice-address-country" id=$COUNTRY}{$TITLE}{/loop}</td>
</tr>
<tr>
<tr data-field-class="js-phone">
<th>{intl l="Phone"}</th>
<td>{$PHONE}</td>
</tr>
@@ -271,54 +271,54 @@
<a class="btn btn-default btn-primary" title="{intl l='Download purchase order as PDF'}" href="#">
<span class="glyphicon glyphicon-cloud-download"></span> {intl l='PDF | Purchase order'}
</a>
<a class="btn btn-default btn-primary" title="{intl l='Edit delivery address'}" href="#edit_address_dialog" data-toggle="modal">
<a class="btn btn-default btn-primary js-update-order-address" data-address-id="{$DELIVERY_ADDRESS}" title="{intl l='Edit delivery address'}" href="#edit_order_address_dialog" data-toggle="modal">
<span class="glyphicon glyphicon-edit"></span>
</a>
</div>
</caption>
<tbody>
{loop type="order_address" name="order-delivery-address" id=$DELIVERY_ADDRESS}
<tr>
<tr data-field-class="js-title" data-value="{$TITLE}">
<th>{intl l="Title"}</th>
<td>{loop type="title" name="order-delivery-address-title" id=$TITLE}{$LONG}{/loop}</td>
</tr>
<tr>
<tr data-field-class="js-company">
<th>{intl l="Company"}</th>
<td>{$COMPANY}</td>
</tr>
<tr>
<tr data-field-class="js-firstname">
<th>{intl l="Firstname"}</th>
<td>{$FIRSTNAME}</td>
</tr>
<tr>
<tr data-field-class="js-lastname">
<th>{intl l="Lastname"}</th>
<td>{$LASTNAME}</td>
</tr>
<tr>
<tr data-field-class="js-address1">
<th>{intl l="Street address"}</th>
<td>{$ADDRESS1}</td>
</tr>
<tr>
<tr data-field-class="js-address2">
<th>{intl l="Additional address"}</th>
<td>{$ADDRESS2}</td>
</tr>
<tr>
<tr data-field-class="js-address3">
<th>{intl l="Additional address"}</th>
<td>{$ADDRESS3}</td>
</tr>
<tr>
<tr data-field-class="js-zipcode">
<th>{intl l="Zip code"}</th>
<td>{$ZIPCODE}</td>
</tr>
<tr>
<tr data-field-class="js-city">
<th>{intl l="City"}</th>
<td>{$CITY}</td>
</tr>
<tr>
<tr data-field-class="js-country" data-value="{$COUNTRY}">
<th>{intl l="Country"}</th>
<td>{loop type="country" name="order-delivery-address-country" id=$COUNTRY}{$TITLE}{/loop}</td>
</tr>
<tr>
<tr data-field-class="js-phone">
<th>{intl l="Phone"}</th>
<td>{$PHONE}</td>
</tr>
@@ -355,22 +355,26 @@
{form name="thelia.order.update.address"}
{* Capture the dialog body, to pass it to the generic dialog *}
{capture "edit_address_dialog"}
{capture "edit_order_address_dialog"}
{form_hidden_fields form=$form}
{form_field form=$form field='id'}
<input type="hidden" id="{$label_attr.for}" name="{$name}" class="js-order-address-id" value="{$value}">
{/form_field}
{form_field form=$form field='company'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Company'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-company" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Company'}">
</div>
{/form_field}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control">
<select name="{$name}" id="{$label_attr.for}" class="form-control js-title">
{loop type="title" name="title1"}
<option value='{$ID}'>{$LONG}</option>
{/loop}
@@ -381,32 +385,32 @@
{form_field form=$form field='firstname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Firstname'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-firstname" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Firstname'}">
</div>
{/form_field}
{form_field form=$form field='lastname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Lastname'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-lastname" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Lastname'}">
</div>
{/form_field}
{form_field form=$form field='address1'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Address'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-address1" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Address'}">
</div>
<div class="form-group">
{form_field form=$form field='address2'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Additional address'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-address2" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
<div class="form-group">
{form_field form=$form field='address3'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Additional address'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-address3" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
{/form_field}
@@ -414,43 +418,51 @@
{form_field form=$form field='zipcode'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Zip code'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-zipcode" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Zip code'}">
</div>
{/form_field}
{form_field form=$form field='city'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l=$label}" placeholder="{intl l='City'}">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-city" value="{$value}" title="{intl l=$label}" placeholder="{intl l='City'}">
</div>
{/form_field}
{form_field form=$form field='country'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control">
<select name="{$name}" id="{$label_attr.for}" class="form-control js-country">
{loop type="country" name="country1"}
<option value="{$ID}">{$TITLE}</option>
{/loop}
</select>
</div>
{/form_field}
{/form_field}
{form_field form=$form field='phone'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l=$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control js-phone" value="{$value}" title="{intl l=$label}" placeholder="{intl l='Phone'}">
</div>
{/form_field}
{/capture}
{include
file = "includes/generic-create-dialog.html"
dialog_id = "edit_address_dialog"
dialog_title = {intl l="Edit an address"}
dialog_body = {$smarty.capture.edit_address_dialog nofilter}
dialog_id = "edit_order_address_dialog"
dialog_title = {intl l="Edit order address"}
dialog_body = {$smarty.capture.edit_order_address_dialog nofilter}
dialog_ok_label = {intl l="Edit this address"}
dialog_ok_label = {intl l="Confirm changes"}
dialog_cancel_label = {intl l="Cancel"}
form_action = {url path='/admin/address/update'}
form_action = {url path="/admin/order/update/$order_id/address"}
form_enctype = {form_enctype form=$form}
form_error_message = $form_error_message
form_id = 'updateOrderAddressForm'
}
{/form}
@@ -475,6 +487,25 @@
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
$(".js-current-tab").val($(e.target).data("tab-name"));
});
$(".js-update-order-address").click(function(){
$(".js-order-address-id").val(
$(this).data("address-id")
);
$(this).parents('table').find('tr').each(function(k, v) {
if(!$(v).data('field-class')) {
return true;
}
if($(v).data('value')) {
var fieldValue = $(v).data('value');
} else {
var fieldValue = $(v).children('td').text();
}
$('.' + $(v).data('field-class')).val(fieldValue);
});
});
</script>
{/block}