Show custom query data in Magento 2 admin grid - grid

I have created a custom module which stores some data related to the product in a custom collection.
Now to show it as a report in the Magento 2 admin, I need to create a custom query to join it with the customer and product tables and do some aggregate functionality such as count grouped by the product.
Is there a way we can do that using custom SQL query and pass the whole result in the grid and it takes the relevant column names and shows it in the grid?
<?xml version="1.0"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">bargain_offer_listing.bargain_offer_listing_data_source</item>
<item name="deps" xsi:type="string">bargain_offer_listing.bargain_offer_listing_data_source</item>
<item name="spinner" xsi:type="string">bargain_offer_listing_columns</item>
</item>
</argument>
<listingToolbar name="listing_top">
<bookmark name="bookmarks"/>
<columnsControls name="columns_controls"/>
<filterSearch name="fulltext"/>
<filters name="listing_filters"/>
<paging name="listing_paging"/>
</listingToolbar>
<dataSource name="bargain_offer_listing_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">MyModule\Bargain\Ui\DataProvider\OfferListingProvider
</argument>
<argument name="name" xsi:type="string">bargain_offer_listing_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">entity_id</argument>
<argument name="requestFieldName" xsi:type="string">entity_id</argument>
<argument name="data" xsi:type="array">
<item name="update_url" xsi:type="url" path="mui/index/render"/>
<item name="storageConfig" xsi:type="array">
<item name="indexField" xsi:type="string">entity_id</item>
</item>
</argument>
</argument>
</dataSource>
<columns name="bargain_offer_listing_columns">
<column name="entity_id">
<settings>
<filter>textRange</filter>
<label translate="true">ID</label>
</settings>
</column>
<column name="product_sku">
<settings>
<filter>text</filter>
<label translate="true">Product Sku</label>
</settings>
</column>
<column name="product_name">
<settings>
<filter>text</filter>
<bodyTmpl>ui/grid/cells/text</bodyTmpl>
<label translate="true">Product Name</label>
</settings>
</column>
<column name="number_of_buyers">
<settings>
<filter>text</filter>
<label translate="true">No of buyers</label>
</settings>
</column>
<column name="times_bought">
<settings>
<filter>text</filter>
<label translate="true">Times Bought</label>
</settings>
</column>
</columns>
</listing>
This is my data provider class
use Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider;
class OfferListingProvider extends DataProvider
{
}
But I do not know how to utilize this. Any suggestions or guides is appreciated.

Related

How can fetch data from shipping to custom field in sales order grid page

I added custom column to sales order page contain the fields: Ordernumber, First name, Last name, streetname, housenumber, additional housenumber, emailaddress, postcode and landcode. But I'm unable to fetch the value of all fields.
Below is what I have tried my level best. Any help will be appreciated.
/Ahmad/OrderGrid/view/adminhtml/ui_component/sales_order_grid.xml
<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<container name="listing_top">
<filters name="listing_filters">
<filterInput name="order_items">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="dataScope" xsi:type="string">order_items</item>
<item name="label" xsi:type="string" translate="true">Order items</item>
</item>
</argument>
</filterInput>
</filters>
</container>
<columns name="sales_order_columns">
<column name="order_items">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Order Items</item>
</item>
</argument>
</column>
<column name="first_name">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">First Name</item>
</item>
</argument>
</column>
<column name="last_name">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Last Name</item>
</item>
</argument>
</column>
<column name="street_name">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Street Name</item>
</item>
</argument>
</column>
<column name="house_number">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">House Number</item>
</item>
</argument>
</column>
<column name="additional _housenumber">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Additional Housenumber</item>
</item>
</argument>
</column>
<column name="emailaddress">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Email Address</item>
</item>
</argument>
</column>
<column name="postcode">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Post Code</item>
</item>
</argument>
</column>
<column name="landcode">
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item>
</item>
<item name="config" xsi:type="array">
<item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item>
<item name="dataType" xsi:type="string">text</item>
<item name="align" xsi:type="string">left</item>
<item name="sortable" xsi:type="boolean">false</item>
<item name="label" xsi:type="string" translate="true">Land Code</item>
</item>
</argument>
</column>
</columns>
</listing>
Ahmad/OrderGrid/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
<arguments>
<argument name="collections" xsi:type="array">
<item name="sales_order_grid_data_source" xsi:type="string">Ahmad\OrderGrid\Model\ResourceModel\Order\Grid\Collection</item>
</argument>
</arguments>
</type>
<virtualType name="Ahmad\OrderGrid\Model\ResourceModel\Order\Grid\Collection">
<arguments>
<argument name="mainTable" xsi:type="string">sales_order_grid</argument>
<argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order</argument>
</arguments>
</virtualType>
</config>
Ahmad/OrderGrid/Model/ResourceModel/Order/Grid/Collection.php
<?php
namespace Ahmad\OrderGrid\Model\ResourceModel\Order\Grid;
use Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult;
/**
* Class Collection
* #package Ahmad\OrderGrid\Model\ResourceModel\Order\Grid
*/
class Collection extends SearchResult
{
/**
* Initialize the select statement.
*
* #return $this
*/
protected function _initSelect()
{
parent::_initSelect();
// Add the sales_order_item model to this collection
$this->join(
[$this->getTable('sales_order_item')],
"main_table.entity_id = {$this->getTable('sales_order_item')}.order_id",
[]
);
// Group by the order id, which is initially what this grid is id'd by
$this->getSelect()->group('main_table.entity_id');
return $this;
}
/**
* Add field to filter.
*
* #param string|array $field
* #param string|int|array|null $condition
* #return SearchResult
*/
public function addFieldToFilter($field, $condition = null)
{
if ($field === 'products' && !$this->getFlag('product_filter_added')) {
// Add the sales/order_item model to this collection
$this->getSelect()->join(
[$this->getTable('sales_order_item')],
"main_table.entity_id = {$this->getTable('sales_order_item')}.order_id",
[]
);
// Group by the order id, which is initially what this grid is id'd by
$this->getSelect()->group('main_table.entity_id');
// On the products field, let's add the sku and name as filterable fields
$this->addFieldToFilter([
"{$this->getTable('sales_order_item')}.sku",
"{$this->getTable('sales_order_item')}.name",
], [
$condition,
$condition,
]);
$this->setFlag('product_filter_added', 1);
}
return parent::addFieldToFilter($field, $condition);
}
/**
* Perform operations after collection load.
*
* #return SearchResult
*/
protected function _afterLoad()
{
$items = $this->getColumnValues('entity_id');
if (count($items)) {
$connection = $this->getConnection();
// Build out item sql to add products to the order data
$select = $connection->select()
->from([
'sales_order_item' => $this->getTable('sales_order_item'),
], [
'order_id',
'product_skus' => new \Zend_Db_Expr('GROUP_CONCAT(`sales_order_item`.sku SEPARATOR "|")'),
'product_names' => new \Zend_Db_Expr('GROUP_CONCAT(`sales_order_item`.name SEPARATOR "|")'),
'product_qtys' => new \Zend_Db_Expr('GROUP_CONCAT(`sales_order_item`.qty_ordered SEPARATOR "|")'),
])
->where('order_id IN (?)', $items)
->where('parent_item_id IS NULL') // Eliminate configurable products, otherwise two products show
->group('order_id');
$itemCollection = $connection->fetchAll($select);
// Loop through this sql an add items to related orders
foreach ($itemCollection as $item) {
$row = $this->getItemById($item['order_id']);
$productSkus = explode('|', $item['product_skus']);
$productQtys = explode('|', $item['product_qtys']);
$productNames = explode('|', $item['product_names']);
$html = '';
foreach ($productSkus as $index => $sku) {
$html .= sprintf('<div>%d x [%s] %s </div>', $productQtys[$index], $sku, $productNames[$index]);
}
$row->setOrderItems($html);
}
}
return parent::_afterLoad();
}
/**
* Get the record count.
*
* #return int
*/
public function getSize()
{
if ($this->_totalRecords === null) {
$sql = $this->getSelectCountSql();
$this->_totalRecords = count($this->getConnection()->fetchAll($sql, $this->_bindParams));
}
return (int) $this->_totalRecords;
}
}
enter image description here

Magento2 Newsletter Grid custom column filter not working

I have added new column in newsletter grid in Magento2.2.5 with override newsletter_subscriber_block.xml in my custom module, but somehow filter is not working for new column. Please find below code of newsletter grid i have override in my custom module..
<referenceBlock name="adminhtml.newslettrer.subscriber.grid.columnSet">
<block class="Magento\Backend\Block\Widget\Grid\Column">
<arguments>
<argument name="header" xsi:type="string" translate="true">Urgency</argument>
<argument name="index" xsi:type="string">urgency</argument>
<argument name="type" xsi:type="string">options</argument>
<argument name="options" xsi:type="array">
<item name="withinweek" xsi:type="array">
<item name="value" xsi:type="string">1</item>
<item name="label" xsi:type="string" translate="true">With in 3 Weeks</item>
</item>
<item name="afterweek" xsi:type="array">
<item name="value" xsi:type="string">0</item>
<item name="label" xsi:type="string" translate="true">After 3 Weeks</item>
</item>
</argument>
<argument name="header_css_class" xsi:type="string">col-urgency</argument>
<argument name="column_css_class" xsi:type="string">col-urgency</argument>
</arguments>
</block>
</referenceBlock>

After added new custom column in magento 2 filter not working for date sorting

I have added new column in sales order for coupon code. after added this column sorting working fine but when i am filtering for last day order it is showing something went wrong.
the ajax issue is in 'mui/index/render'
app\code\Vicomage\CustomCoupon\etc\di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
<arguments>
<argument name="collections" xsi:type="array">
<item name="sales_order_grid_data_source" xsi:type="string">Vicomage\CustomCoupon\Model\ResourceModel\Order\Grid\Collection</item>
</argument>
</arguments>
</type>
</config>
app\code\Vicomage\CustomCoupon\etc\module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vicomage_CustomCoupon" setup_version="2.0.0">
</module>
</config>
app\code\Vicomage\CustomCoupon\Model\ResourceModel\Order\Grid\Collection.php
<?php
namespace Vicomage\CustomCoupon\Model\ResourceModel\Order\Grid;
use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as OriginalCollection;
class Collection extends OriginalCollection{
protected function _renderFiltersBefore()
{
$joinTable = $this->getTable('sales_order');
$this->getSelect()->joinLeft($joinTable, 'main_table.entity_id = sales_order.entity_id', ['coupon_code']);
parent::_renderFiltersBefore();
}
}
app\code\Vicomage\CustomCoupon\view\adminhtml\ui_component\sales_order_grid.xml
<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<columns name="sales_order_columns">
<column name="coupon_code">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="filter" xsi:type="string">text</item>
<item name="label" xsi:type="string" translate="true">Coupon Code</item>
</item>
</argument>
</column>
</columns>
</listing>
add below lines of code before parent::_renderFiltersBefore() in your file app\code\Vicomage\CustomCoupon\Model\ResourceModel\Order\Grid\Collection.php
$this->getSelect()->group('main_table.entity_id');
$this->getSelect()->group('main_table.store_id');
let me know if you still facing same issue.

ASCX Web Controls are not stored in Database

Recently we have upgraded to Tridion 2011 SP1 from Tridion 5.3.
In our existing implementation we have various Dynamic Component Templates. For few CTs output format is ASCX Web Control for few CTs output format is HTML Fragment.
After publishing we came across
1) ASCX WebControls are NOT stored to Storage Database (SQLServer). In Tridion 5.3 they were.
2) HTML Fragments are getting stored in database.
In our implementation binary files, page, embedded component templates are stored on file system and Dynamic component templates are stored in SQL Sever database.
We think we have missed something in our cd_storage_config. Please find attached config file.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration Version="6.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schemas/cd_storage_conf.xsd">
<Global>
<ObjectCache Enabled="false">
<Policy Type="LRU" Class="com.tridion.cache.LRUPolicy">
<Param Name="MemSize" Value="16mb"/>
</Policy>
<Features>
<Feature Type="DependencyTracker" Class="com.tridion.cache.DependencyTracker"/>
</Features>
</ObjectCache>
<Storages>
<Storage Type="persistence" Id="sqlserver" dialect="MSSQL" Class="com.tridion.storage.persistence.JPADAOFactory">
<Pool Type="jdbc" Size="5" MonitorInterval="60" IdleTimeout="120" CheckoutTimeout="120" />
<DataSource Class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
<Property Name="serverName" Value="local" />
<Property Name="portNumber" Value="1433" />
<Property Name="databaseName" Value="TridionBroker" />
<Property Name="user" Value="TridionBrokerUser" />
<Property Name="password" Value="mypass" />
</DataSource>
</Storage>
<Storage Type="filesystem" Class="com.tridion.storage.filesystem.FSDAOFactory" Id="defaultFile" defaultFilesystem="false">
<Root Path="d:\Inetpub\MyPortal" />
</Storage>
<Storage Type="filesystem" Class="com.tridion.storage.filesystem.FSDAOFactory" Id="defaultDataFile" defaultFilesystem="true" defaultStorage="true">
<Root Path="d:\Inetpub\MyPortal\data" />
</Storage>
<SearchFilter Name="SearchFilter" Class="com.tridion.broker.components.meta.MsSqlSearchFilterHome" defaultStorageId="sqlserver"/>
</Storages>
</Global>
<ItemTypes defaultStorageId="defaultDataFile" cached="false">
<Item typeMapping="Query" storageId="sqlserver"/>
<Item typeMapping="Page" cached="false" storageId="defaultFile"/>
<Item typeMapping="Binary" cached="false" storageId="defaultFile"/>
<Item typeMapping="ComponentPresentation" itemExtension=".Jsp" storageId="sqlserver"/>
<Item typeMapping="ComponentPresentation" itemExtension=".Asp" storageId="sqlserver"/>
<Item typeMapping="ComponentPresentation" itemExtension=".Xml" storageId="sqlserver"/>
<Item typeMapping="ComponentPresentation" itemExtension=".Txt" storageId="sqlserver"/>
<Item typeMapping="Metadata" cached="true" storageId="sqlserver"/>
<Item typeMapping="XSLT" cached="true" storageId="sqlserver"/>
</ItemTypes>
<License Location="d:\Tridion\config\cd_licenses.xml"/>
You don't have any ascx binding in your storage config. In 5.3, it used to be Asp binding.
Change the following:
<Item typeMapping="ComponentPresentation" itemExtension=".Asp" storageId="sqlserver"/>
To:
<Item typeMapping="ComponentPresentation" itemExtension=".ascx" storageId="sqlserver"/>
Also, in tridion 2011 you don't need to specify mapping for each type (like txt, jsp etc..) if you want all to be stored in db.
You can simply do this:
<Item typeMapping="ComponentPresentation" storageId="sqlserver"/>

Dynamic Component Template no longer going to broker db

I have made an adjustment to my blueprinting structure, so that what was previously a publishable web publication has now been turned into a non publishable web publication at a parent level. A new child web publication has been created to take it's place.
As such, this has created a new publication ID. I've updated all configurations with this new ID, and been able to successfully publish content to the presentation servers on the file system. Dynamic component presentations are also being published into the broker database using the new ID.
However, recently one of my dynamic component templates has stopped publishing to the broker. It publishes to the file system, but no record of the component appears in the LINK_INFO table of the broker. This means dynamic linking for content using this template is failing on the website.
Could anyone possible tell me if they know why this is occurring?
UPDATE 2: Found something interesting.....dynamic linking is actually working but only for some component templates. I discovered this by using the ComponentLink.GetLink(string) method to see if it would return a link...for some content types it does, but for others which previously had links, it now doesn't, even after republishing these templates :s
UPDATE: cd_storage.xml
<Configuration Version="6.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="schemas/cd_storage_conf.xsd">
<Global>
<ObjectCache Enabled="false">
<Policy Type="LRU" Class="com.tridion.cache.LRUPolicy">
<Param Name="MemSize" Value="16mb"/>
</Policy>
<Features>
<Feature Type="DependencyTracker" Class="com.tridion.cache.DependencyTracker"/>
</Features>
</ObjectCache>
<Storages>
<StorageBindings>
<Bundle src="AudienceManagerDAOBundle.xml" />
</StorageBindings>
<Storage Type="persistence" Id="defaultdb" dialect="MSSQL"
Class="com.tridion.storage.persistence.JPADAOFactory">
<Pool Type="jdbc" Size="5" MonitorInterval="60" IdleTimeout="120"
CheckoutTimeout="120" />
<DataSource Class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
<Property Name="serverName" Value="lon1udb01.int.rroom.net" />
<Property Name="portNumber" Value="1433" />
<Property Name="databaseName" Value="uat_mal_Tridion_Broker_2" />
<Property Name="user" Value="uat_mal" />
<Property Name="password" Value="mj][zdvd=h" />
</DataSource>
</Storage>
<Storage Type="persistence" Id="profiledb" dialect="MSSQL"
Class="com.tridion.storage.persistence.JPADAOFactory"
defaultStorage="false">
<Pool Type="jdbc" Size="5" MonitorInterval="60" IdleTimeout="120"
CheckoutTimeout="120" />
<DataSource Class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
<Property Name="serverName" Value="lon1udb01.int.rroom.net" />
<Property Name="portNumber" Value="1433" />
<Property Name="databaseName" Value="uat_mal_Tridion_submgmt" />
<Property Name="user" Value="uat_mal" />
<Property Name="password" Value="mj][zdvd=h" />
</DataSource>
</Storage>
<Storage Type="persistence" Id="trackingdb" dialect="MSSQL"
Class="com.tridion.storage.persistence.JPADAOFactory"
defaultStorage="false">
<Pool Type="jdbc" Size="5" MonitorInterval="60" IdleTimeout="120"
CheckoutTimeout="120" />
<DataSource Class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
<Property Name="serverName" Value="lon1udb01.int.rroom.net" />
<Property Name="portNumber" Value="1433" />
<Property Name="databaseName" Value="uat_mal_Tridion_tracking" />
<Property Name="user" Value="uat_mal" />
<Property Name="password" Value="mj][zdvd=h" />
</DataSource>
</Storage>
<Storage Type="filesystem" Id="defaultFile"
Class="com.tridion.storage.filesystem.FSDAOFactory"
defaultFilesystem="false"
defaultStorage="false">
<Root Path="c:\websites\live" />
</Storage>
<Storage Type="filesystem" Id="defaultFileAssets"
Class="com.tridion.storage.filesystem.FSDAOFactory"
defaultFilesystem="false"
defaultStorage="true">
<Root Path="c:\websites\live\malvern.com.en\Assets" />
</Storage>
<Storage Type="filesystem" Class="com.tridion.storage.filesystem.FSDAOFactory"
Id="malenctrls" defaultFilesystem="false" defaultStorage="false">
<Root Path="c:\websites\live\malvern.com.en\usercontrols" />
</Storage>
<Storage Type="filesystem" Class="com.tridion.storage.filesystem.FSDAOFactory"
Id="malcnctrls" defaultFilesystem="false" defaultStorage="false">
<Root Path="c:\websites\live\malvern.com.cn\usercontrols" />
</Storage>
<SearchFilter Name="SearchFilter"
Class="com.tridion.broker.components.meta.MsSqlSearchFilterHome"
defaultStorageId="defaultdb"/>
</Storages>
<Transaction Timeout="60000" MonitorInterval="5000"/>
</Global>
<ItemTypes defaultStorageId="defaultdb" cached="false">
<Item storageId="profiledb" typeMapping="AudienceManagerProfile" cached="false"/>
<Item storageId="trackingdb" typeMapping="AudienceManagerTracking" cached="false" />
<!-- GLOBAL MASTER -->
<Publication Id="22" defaultStorageId="defaultdb" cached="false">
<Item storageId="defaultFile" typeMapping="Page" cached="false" />
<Item storageId="defaultFile" typeMapping="Binary" cached="false" />
<Item storageId="malenctrls" typeMapping="ComponentPresentation"
itemExtension=".ascx" cached="false" />
</Publication>
<!-- CHINESE WEB -->
<Publication Id="15" defaultStorageId="defaultdb" cached="false">
<Item storageId="defaultFile" typeMapping="Page" cached="false" />
<Item storageId="defaultFile" typeMapping="Binary" cached="false" />
<Item storageId="malcnctrls" typeMapping="ComponentPresentation"
itemExtension=".ascx" cached="false" />
</Publication>
</ItemTypes>
<License Location="c:/tridion/config/cd_licenses.xml"/>
You have
<Storage Type="filesystem" Id="defaultFileAssets"
Class="com.tridion.storage.filesystem.FSDAOFactory" defaultFilesystem="false"
defaultStorage="true">
and no TypeMappings definition anywhere in your cd_storage_conf.xml. This makes the "defaultFileAssets" the storage location of choice for the deployer.
I would normally expect something like this
<ItemTypes defaultStorageId="defaultdb" cached="false">
<Item typeMapping="Page" cached="false" storageId="defaultFile"/>
<Item typeMapping="Binary" storageId="defaultFile" cached="false"/>
</ItemTypes>
in your Configuration node.
It would also be very helpful to ensure that the configuration you have posted is actually being used; you can view this in the logfiles generated by Tridion (with debug logging enables) as it logs which config file it is using; there has been more than one occasion where I was puzzled with issues simply because I was looking at the wrong configuration file...
I've removed a lot of unhelpful comments from the storage configuration in the question. Now it's easy to see that as Quirijn suspected, there are publication-specific configurations in play. If your web publication id was previously 15 or 22, and this has changed, that would explain your problem.
I think the issue may be being caused by an expired cd_licence file but i can't confirm it, have asked SDL support to tell me if it's so

Resources