I want every user, that registers on my Magento instance, to upload a certificate that shows me that he registered a business.
I already added the fields in the template. But how can I fetch the file and save the filename / contents in the customer record?
Is there a way to extend the functionality in the Controllers?
This is actually even easier:
Just make sure you set these parameters on your config.xml:
'attributes' => array(
'prooffile' => array(
'type' => 'text',
'input' => 'file',
'label' => 'Proof file',
'visible' => true,
'required' => false,
'position' => 100,
"user_defined" => false,
),
This adds a nice editor in your admin backend.
The way I did this:
I added the file field to the registration form:
<li class="fields">
<div class="field">
<div class="input-box">
<label for="prooffile"><?php echo $this->__('Proof of business registration') ?><span class="required">*</span></label><br />
<input type="file" name="prooffile" id="prooffile" title="<?php echo $this->__('Proof of business registration') ?>" class="required-entry input-text" />
</div>
</div>
</li>
Also, make sure that you set the form enctype to "multipart/form-data".
After that, I created a class that subscribes to the "user-register-success" Event. Magento has a very solid Event/Observer mechanism built in.
To do this, you have to have a custom module. In the modules etc/config.xml, add these lines for the event listener:
<events>
<customer_register_success> <!-- The name of the Event -->
<observers>
<customfields> <!-- Your module name -->
<type>singleton</type>
<class>customfields/observer</class> <!-- The class name, that holds your callback function -->
<method>handle_file_upload</method>
</customfields>
</observers>
</customer_register_success>
</events>
This registers an event handler for the event customer_register_success. Make sure that you create a file Observer.php in your modules Model folder:
Model/Observer.php:
<?php
class Komola_Customfields_Model_Observer
{
public function __construct()
{
}
public function handle_file_upload($observer)
{
$customer = $observer->getCustomer();
if (isset($_FILES['prooffile']['name']) && $_FILES['prooffile']['name'] != "") {
$uploader = new Varien_File_Uploader("prooffile");
$uploader->setAllowedExtensions(array('jpg', 'jpeg', 'gif', 'png', 'pdf'));
$uploader->setAllowRenameFiles(false);
$uploader->setFilesDispersion(false);
$path = Mage::getBaseDir("media") . DS . "customer" . DS;
$logoName = $customer->getId() . "." . pathinfo($_FILES['prooffile']['name'], PATHINFO_EXTENSION);
$uploader->save($path, $logoName);
$customer->setProoffile($logoName);
$customer->save();
}
}
}
This takes the uploaded file, and saves the file in the folder media/customer (make sure to create this folder and to make it writable!). It also saves the file name in a custom customer attribute.
In the module installer file, create the attribute like this, and it will appear in the customer backend.
An extra part is needed for newer version of Magento (not sure from when exactly, but it is true as of Magento Community Edition 1.6 and up).
The "used_in_forms" key cannot be in the array passed to the addAttribute call directly (won't work). It probably contain the names of the forms from which the customer model will accept the values and not ignore them when being saved.
Known values are at this question's answers: Can no longer add registration fields in Magento 1.4.2.0 (The answer by Folker Schellenberg)
I think it is the name of the controller and action that rendered the form. This name is also the main layout handle name of the page (eg: customer_account_edit).
It should be noted that the customer form in the front-end is HTML-based. It doesn't dynamically render inputs from the attributes like the backend forms. This means that if these attributes should be input by the user, the template needs to be amended to contain the proper input tags as well (and the proper value added in the used_in_forms array).
$attributeCode = "uploaded_file";
$attributeLabel = "Uploaded file";
$installer->addAttribute('customer', $attributeCode, array(
'type' => 'text',
'input' => 'file',
'label' => $attributeLabel,
'global' => true,
'visible' => true,
'required' => false,
'user_defined' => false
));
// For newer versions of Magento, otherwise won't show up.
$eavConfig = Mage::getSingleton('eav/config');
$attribute = $eavConfig->getAttribute('customer', $attributeCode);
$attribute->setData('used_in_forms', array('customer_account_create', 'adminhtml_customer'));
$attribute->setData('sort_order', 200);
$attribute->save();
Another possible type is 'image' which renders exactly as 'file' except it shows the image in a preview box (a small one). Maybe good for customer photo ?
Also, noteworthy is that is this specific for the customer form (the class that handles this type of attribute is: Mage_Adminhtml_Block_Customer_Form_Element_File and Mage_Adminhtml_Block_Customer_Form_Element_Image), so this won't work in a product attribute without custom work.
Hope this helps !
Related
Is it possible to add a custom button that downloads pdf ?
ive tried doing it but i only get create button from this example: Link here
'searchInputs' => array(
1 => 'payment_date',
2 => 'payment_stage',
3 => 'or_no',
),
'create' =>
array(
'formBase' => 'PrintPayment.php',
'formBaseClass' => 'PrintPayment',
'getFormBodyParams' => array('', '', 'PrintPaymentSave'),
'createButton' => $mod_strings['LNK_NEW_PAYMENT']
),
is there any other way to add a download functionality ?
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('include/SugarObjects/forms/FormBase.php');
class PrintPayment extends FormBase {
var $moduleName = 'PrintPayment';
var $objectName = 'PrintPayment';
function handleSave($prefix, $redirect=true, $useRequired=false){
require_once('include/formbase.php');
$focus = new PrintPayment();
$focus = populateFromPost($prefix, $focus);
$focus->save();
}
}
is there any experts who knows this ? thanks in advance.
First you need to go to dropdown editor in admin panel and find "pdf_template_type_dom".
It's list responsible for modules available in PDF - templates module.
After adding module of your choice to the list you might need to rebuild the app.
After you add module, create a some template for it.
Afterwards you need to modify your viewdefs in your module to add the button allowing for PDF print. Here is custom code for the button:
array ( 'customCode' => '<input type="button" class="button" onClick="showPopup(\'pdf\');" value="PDF">'
Add the button somewhere and voila.
I tested in DetailView for my custom modules but the principle should be the same.
In my project, I added a new field location in "product reviews" of admin panel going through the following steps as explained in many blogs.
Created a new field in database table review_detail as location.
Added the following code in app/code/code/Mage/Adminhtml/Block/Review/Edit/Form.php
$fieldset->addField('location', 'text', array(
'name' => 'location',
'label' => Mage::helper('adminhtml')->__('Location'),
'required' => false
)
);
Just above:
$fieldset->addField('nickname', 'text', array(
'label' => Mage::helper('review')->__('Nickname'),
'required' => true,
'name' => 'nickname'
));
.Added the following code in app/code/core/Mage/Review/Model/Resource/Review.php
$detail = array(
'title' => $object->getTitle(),
'detail' => $object->getDetail(),
'nickname' => $object->getNickname(),
'location' => $object->getLocation() /* added */
);
Added "location" in below function array. In the file: app/code/core/Mage/Review/Model/Resource/Review/Collection.php
protected function _initSelect()
{
parent::_initSelect();
$this->getSelect()
->join(array('detail' => $this->_reviewDetailTable),
'main_table.review_id = detail.review_id',
array('detail_id', 'title', 'detail', 'nickname', 'customer_id','location'));
return $this;
}
Added the following in {$mytheme}/template/review/form.phtml:
<li>
<label for="location_field" class="required"><em>*</em><?php echo $this->__('Location') ?></label>
<div class="input-box">
<input type="text" name="nickname" id="location_field" class="input-text required-entry" value="<?php echo $this->htmlEscape($data->getLocation()) ?>" />
</div>
</li>
My problem is that though I can see a new field in admin panel, whenever I submit a review form it is not being submitted/stored in database.
I even re-indexed and cleared the cache.
What should I change more to make it work properly?
Please help... I am on magento 1.8.
PS: I know core files should not be changed. I will override this to new module once I have success in this issue.
I did follow exact steps explained in quetion. And find it working properly.
Only issue I faced was that in {$mytheme}/template/review/form.phtml
You have defined name="nickname" for location field instead of name="location"
Correct this and if you still face same issue than then check if Module Classes as being overridden.
Have a look at the html code created in the browser. Check for:
is your field included within -tags?
is the action type and target set correctly?
with a browser console of your choice (e.g. chrome F12) ensure that fields are correctly set and the form is really sent.
Try this, take db backup first. Delete entry of table from core_resource table and load the site.. In short try to recreate the db table with your column 'location'. I don't know ,what is wrong with setters when we add new field in varien forms they didn't work properly.
I hope this will work.
Does anyone know how can I add a custom product attribute with a widget renderer?
You can see this in Promo rules if you select SKU you'll got an Ajax popup with product selection.
so how would I go about it?
in :
$installer->addAttribute(Mage_Catalog_Model_Product::ENTITY...
In other words, how can I use a widget to select custom attribute values?
EDIT:
The scenario is as follows:
I would like to create a product attribute that will, upon a button click, open a product selection widget.
After the selection, the selected SKU's will go in in a comma delimited format.
This behavior can be seen in the catalog and shopping cart price rules.
If you filter the rule by SKU (SKU attribute must be enabled to "apply to rules"), you'll get a field and a button that will open the product selection widget.
Here is some thoughts that should get you going on the right track:
First, in a setup script, create your entity:
$installer->addAttribute('catalog_product', 'frontend_display', array(
'label' => 'Display Test',
'type' => 'varchar',
'frontend_model' => 'Test_Module/Entity_Attribute_Frontend_CsvExport',
'input' => 'select',
'required' => 0,
'user_defined' => false,
'group' => 'General'
));
Make sure to set the frontend_model to the model that you are going to use. The frontend model affects the display of the attribute (both in the frontend and the adminhtml sections).
Next, create yourself the class, and override one or both of the following functions:
public function getInputType()
{
return parent::getInputType();
}
public function getInputRendererClass()
{
return "Test_Module_Block_Adminhtml_Entity_Renderer_CsvExport";
}
The first (getInputType()) is used to change the input type to a baked in input type (see Varien_Data_Form_Element_* for the options). However, to set your own renderer class, use the latter function - getInputRendererClass(). That is what I am going to demonstrate below:
public function getElementHtml()
{
return Mage::app()->getLayout()->createBlock('Test_Module/Adminhtml_ExportCsv', 'export')->toHtml();
}
Here, to clean things up, I am instantiating another block, as the element itself doesn't have the extra functions to display buttons and the like.
Then finally, create this file:
class Test_Module_Block_Adminhtml_ExportCsv extends Mage_Adminhtml_Block_Widget
{
protected function _prepareLayout()
{
$button = $this->getLayout()->createBlock('adminhtml/widget_button')
->setData(array(
'label' => $this->__('Generate CSV'),
'onclick' => '',
'class' => 'ajax',
));
$this->setChild('generate', $button);
}
protected function _toHtml()
{
return $this->getChildHtml();
}
}
This doesn't cover the AJAX part, but will get you very close to getting the rest to work.
I need to extend the Magento shopping cart to include an extra step for a store locator. I understand that I need to overwrite the core OnePage controller (Mage_Checkout_OnepageController) and blocks (Mage_Checkout_Block_Onepage) but what needs to be done with regards to keeping track of the extra information (e.g. user's selected options from my custom step).
There are a number of steps required here to get the whole solution.
Firstly, create a new module. Use the ModuleCreator if you wish.
Then, write a setup script in your module to add the new fields to Magento's attribute structure, e.g. :
$setup = new Mage_Sales_Model_Mysql4_Setup('core_setup');
$setup->startSetup();
$setup->addAttribute('quote', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));
$setup->addAttribute('order', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));
$setup->addAttribute('invoice', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));
$setup->addAttribute('creditmemo', 'my_attribute', array('type' => 'varchar', 'visible' => false, 'required' => false));
Note the use of the Mage_Sales_Model_Mysql4_Setup to add the fields to the relevant sales_flat_quote and sales_flat_order tables.
Now, insert the following values in your module's config.xml file:
<global>
<fieldsets>
<sales_convert_quote>
<my_attribute>
<to_order>*</to_order>
</my_attribute>
</sales_convert_quote>
<sales_convert_order>
<my_attribute>
<to_cm>*</to_cm>
<to_invoice>*</to_invoice>
</my_attribute>
</sales_convert_order>
</fieldsets>
That will instruct Magento to copy the values of your custom field from quote to order to invoice and credit_memo, etc.
Then in your custom block/controller code, you will be able to use Magento's magic getters and setters to persist the values.
$oQuote = Mage::getSingleton('checkout/session')->getQuote();
$oQuote->setMyAttribute('some_value');
$oQuote->save();
You should see the new column and value saved in sales_flat_quote. Then once the customer completes checkout, the same value should be saved in sales_flat_order.
Note that the above code can be extended to work for quote_item and order_item by just changing quote to quote_item etc, however, if you wish to save attribute values that have been set on your products, then some extra work is required.
Insert a new block of XML into your config.xml (again inside the global node):
<sales>
<quote>
<item>
<product_attributes>
<my_attribute />
</product_attributes>
</item>
</quote>
</sales>
Where my_attribute is the attribute code on the product model. That will make the my_attribute available on the linked product, so you can access it via
$oQuoteItem->getProduct()->getMyAttribute()
without needing to perform a full Mage::getModel('catalog/product')->load($oQuoteItem->getProductId()). This is much more efficient.
Then, you will need an observer to copy the values from the product object to the quote_item object. So, declare your observer in the config.xml:
<events>
<sales_quote_item_set_product>
<observers>
<quoteitem_set_custom_data>
<type>singleton</type>
<class>mymodule/observer</class>
<method>setCustomDataOnQuoteItem</method>
</quoteitem_set_custom_data>
</observers>
</sales_quote_item_set_product>
<events>
and write code in your observer class like this:
public function setCustomDataOnQuoteItem($oObserver){
$oProduct = $oObserver->getProduct();
$oQuoteItem = $oObserver->getQuoteItem();
foreach(array('my_attribute') as $vAttributeCode){
$oQuoteItem->setData($vAttributeCode,$oProduct->getData($vAttributeCode));
}
}
Here is a complete working module.. its (almost) the same as the above code of Johnatan.
You will find it here:
https://bitbucket.org/vovsky/adding-custom-product-attribute-to-quote-and-order-items-in/
And full explanation of every step here: http://www.atwix.com/magento/custom-product-attribute-quote-order-item/
In the magento system, I added the columns subscriber_firstname and subscriber_lastname to the newsletter_subscriber db table.
In the admin area of magento, I want the Newsletter>Newsletter Subscribers grid table to show:
customer first name if it exists, otherwise show newsletter_subscriber.subscriber_firstname if it exists, otherwise show nothing
customer last name if it exists, otherwise show newsletter_subscriber.subscriber_lastname if it exists, otherwise show nothing
Which magento files do I need to edit to make this work? How do I go about editing the files to make this work?
app/code/core/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php
You'll want to condition this based off if subscriber_firstname or subscriber_lastname have values or not:
$this->addColumn('subscribername', array(
'header' => Mage::helper('newsletter')->__('Subscriber First Name'),
'index' => 'subscriber_firstname',
'default' => '----'
));
Also, make sure to make a copy of the core files and NOT edit them directly!
the quick and easy solution is to create a column render and select the correct field based on the subscriber type e.g.
app/code/local/Mage/Adminhtml/Block/Newsletter/Subscriber/Renderer/FirstName.php
class Mage_Adminhtml_Block_Newsletter_Subscriber_Renderer_FirstName extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract {
public function render(Varien_Object $row) {
$value = '';
if ($row->getData('type') == 2) {
$value = $row->getData('customer_firstname');
}
else {
$value = $row->getData('subscriber_firstname');
}
return $value;
}
}
then add your render to a local copy of the subscriber grid class
app/code/local/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php
$this->addColumn('firstname', array(
'header' => Mage::helper('newsletter')->__('First Name'),
'index' => 'customer_firstname',
'default' => '----',
'renderer' => 'Mage_Adminhtml_Block_Newsletter_Subscriber_Renderer_FirstName'
));
Note. the search and sort will not work on the subscriber name fields, to get this working you will need to extend app/code/core/Mage/Newsletter/Model/Mysql4/Subscriber/Collection.php