Extend Stock (Solved)
Forum rules
Always add your TYPO3, Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
Always add your TYPO3, Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
Extend Stock (Solved)
Working Solution on the End Goto post6012.html#p6012
---------------------------------------------------------------------
Hello Guys,
i would like to extend the stock of products with a optional field order time.
the order time is a string, and describes how long it takes for us to reorder if the product is selled out - 1 weeks/ 1 month / a few days...
-------------------------------------------------------------------------------------------------------------
1. My Problem is i cant save the values in db and dont know what im doing wrong. Also i dont get any error response, im a bit lost.
It would be great if you can help me.
I created an extension named "mhaimeos" with our extensionbuilder.
Then i extended the stock shema, this is working good.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/config/stock.php
After that i created the Item
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Item/Mystandard.php
I created the manager
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Manager/Mystandard.php
I created the Config
Its a copy from the existing one. I just change the name, the insert and update.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/config/stock.php
I edited the template
Path: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-jqadm/admin/jqadm/templates/product/item-stock-default.php
-----------------------------------------------------------------------------------------------------
2. And my second Question is do i have to change the iface for order with my new function getOrderTime and setOrderTime and if yes where do i have to register the iface? I tryed it in the save function of my manager.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Item/Myiface.php
----------------------------------------------------------------------------------------------------
3. Third Question, are my namespaces correct?
----------------------------------------------------------------------------------------------------
4. And my last question is how do i change the templates for the extadmin, is there anything documented?
I tryed to change the ItemUI.js and ListUI.js but got this error
ext-all.js:21 Uncaught TypeError: g is not a constructor
at constructor.setConfig (ext-all.js:21)
at new constructor (ext-all.js:21)
at S.initComponent (ext-all.js:21)
at S.Ext.Component [as constructor] (ext-all.js:21)
at S [as constructor] (ext-base.js:21)
at S [as constructor] (ext-base.js:21)
at S [as constructor] (ext-base.js:21)
at new S (ext-base.js:21)
at S.initComponent (index.php?M=web_AimeosTxAimeosAdmin&moduleToken=60ae9e4e8faae802e56a6d72d2902be966dd9fed&tx_aimeos_web_aimeostxaimeosadmin[action]=file&tx_aimeos_web_aimeostxaimeosadmin[controller]=Extadm:3347)
at S.initComponent (index.php?M=web_AimeosTxAimeosAdmin&moduleToken=60ae9e4e8faae802e56a6d72d2902be966dd9fed&tx_aimeos_web_aimeostxaimeosadmin[action]=file&tx_aimeos_web_aimeostxaimeosadmin[controller]=Extadm:9500)
Path: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-extadm/admin/extjs/src/panel/product/stock/ItemUi.js
Path: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-extadm/admin/extjs/src/panel/product/stock/ListUi.js
Many Thanks and sorry for the long post
Typo3 7.6.x / Aimeos 17.10.0
---------------------------------------------------------------------
Hello Guys,
i would like to extend the stock of products with a optional field order time.
the order time is a string, and describes how long it takes for us to reorder if the product is selled out - 1 weeks/ 1 month / a few days...
-------------------------------------------------------------------------------------------------------------
1. My Problem is i cant save the values in db and dont know what im doing wrong. Also i dont get any error response, im a bit lost.
It would be great if you can help me.
I created an extension named "mhaimeos" with our extensionbuilder.
Then i extended the stock shema, this is working good.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/config/stock.php
Code: Select all
<?php
/**
* @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
*
* Extend Database Table mshop_stock in /typo3conf/ext/aimeos/Resources/Libraries/aimeos/aimeos-core/lib/mshoplib/setup/default/schema/stock.php
*
* https://aimeos.org/docs/Developers/Library/Setup_tasks/Schema_update#Modify_existing_tables
*/
return array(
'table' => array(
'mshop_stock' => function ( \Doctrine\DBAL\Schema\Schema $schema ) {
$table = $schema->getTable( 'mshop_stock' );
$table->addColumn( 'ordertime', 'string', array( 'length' => 32 ) );
$table->addIndex( array( 'siteid', 'ordertime' ), 'idx_mssto_sid_ordertime' );
return $schema;
},
),
);
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Item/Mystandard.php
Code: Select all
<?php
/**
* @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
* @package MShop
* @subpackage Stock
*/
namespace Aimeos\MShop\Stock\Item;
//namespace Mhaimeos\MShop\Stock\Item;
class Mystandard extends Standard
{
private $values;
public function __construct( array $values )
{
parent::__construct( 'stock.', $values );
$this->values = $values;
}
/**
* Returns ordertime for the product stock
*
* @return string|null stock ordertime of the product
*/
public function getOrderTime()
{
if( isset( $this->values['stock.ordertime'] ) ) {
return (string) $this->values['stock.ordertime'];
}
return '';
}
public function setOrderTime( $ordertime )
{
if( (string) $ordertime !== $this->getOrderTime() )
{
$this->values['stock.ordertime'] = (string) $ordertime;
$this->setModified();
}
return $this;
}
public function fromArray( array $list )
{
$unknown = [];
$list = parent::fromArray( $list );
foreach( $list as $key => $value )
{
switch( $key )
{
case 'stock.ordertime': $this->setOrderTime( $value ); break;
default: $unknown[$key] = $value;
}
}
return $unknown;
}
public function toArray( $private = false )
{
$list = parent::toArray( $private );
if( $private === true ) {
$list['stock.ordertime'] = $this->getOrderTime();
}
return $list;
}
}
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Manager/Mystandard.php
Code: Select all
<?php
/**
* @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
* @package MShop
* @subpackage Stock
*/
namespace Aimeos\MShop\Stock\Manager;
//namespace Mhaimeos\MShop\Stock\Manager;
class Mystandard extends Standard
{
private $searchConfig = array(
'stock.ordertime'=> array(
'code'=>'stock.ordertime',
'internalcode'=>'msto."ordertime"',
'label'=>'Product Ordertime',
'type'=> 'string', // integer, float, etc.
'internaltype'=> \Aimeos\MW\DB\Statement\Base::PARAM_STR, // _INT, _FLOAT, etc.
),
);
public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
{
// a modified copy of the code from the parent class
// extended by a bind() call and updated bind positions (first parameter)
$iface = '\\Mhaimeos\\MShop\\Stock\\Item\\Myiface';
if( !( $item instanceof $iface ) ) {
throw new \Aimeos\MShop\Stock\Exception( sprintf( 'Object is not of required type "%1$s"', $iface ) );
}
if( !$item->isModified() ) {
return $item;
}
$context = $this->getContext();
$dbm = $context->getDatabaseManager();
$dbname = $this->getResourceName();
$conn = $dbm->acquire( $dbname );
try
{
$id = $item->getId();
$date = date( 'Y-m-d H:i:s' );
if( $id === null )
{
/** mshop/stock/manager/standard/insert/mysql
* Inserts a new product stock record into the database table
*
* @see mshop/stock/manager/standard/insert/ansi
*/
/** mshop/stock/manager/standard/insert/ansi
* Inserts a new product stock record into the database table
*
* Items with no ID yet (i.e. the ID is NULL) will be created in
* the database and the newly created ID retrieved afterwards
* using the "newid" SQL statement.
*
* The SQL statement must be a string suitable for being used as
* prepared statement. It must include question marks for binding
* the values from the product stock item to the statement before they are
* sent to the database server. The number of question marks must
* be the same as the number of columns listed in the INSERT
* statement. The order of the columns must correspond to the
* order in the saveItems() method, so the correct values are
* bound to the columns.
*
* The SQL statement should conform to the ANSI standard to be
* compatible with most relational database systems. This also
* includes using double quotes for table and column names.
*
* @param string SQL statement for inserting records
* @since 2017.01
* @category Developer
* @see mshop/stock/manager/standard/update/ansi
* @see mshop/stock/manager/standard/newid/ansi
* @see mshop/stock/manager/standard/delete/ansi
* @see mshop/stock/manager/standard/search/ansi
* @see mshop/stock/manager/standard/count/ansi
* @see mshop/stock/manager/standard/stocklevel
*/
$path = 'mshop/stock/manager/standard/insert';
// $path = 'mshop/stock/manager/mystandard/insert';
}
else
{
/** mshop/stock/manager/standard/update/mysql
* Updates an existing product stock record in the database
*
* @see mshop/stock/manager/standard/update/ansi
*/
/** mshop/stock/manager/standard/update/ansi
* Updates an existing product stock record in the database
*
* Items which already have an ID (i.e. the ID is not NULL) will
* be updated in the database.
*
* The SQL statement must be a string suitable for being used as
* prepared statement. It must include question marks for binding
* the values from the product stock item to the statement before they are
* sent to the database server. The order of the columns must
* correspond to the order in the saveItems() method, so the
* correct values are bound to the columns.
*
* The SQL statement should conform to the ANSI standard to be
* compatible with most relational database systems. This also
* includes using double quotes for table and column names.
*
* @param string SQL statement for updating records
* @since 2017.01
* @category Developer
* @see mshop/stock/manager/standard/insert/ansi
* @see mshop/stock/manager/standard/newid/ansi
* @see mshop/stock/manager/standard/delete/ansi
* @see mshop/stock/manager/standard/search/ansi
* @see mshop/stock/manager/standard/count/ansi
* @see mshop/stock/manager/standard/stocklevel
*/
$path = 'mshop/stock/manager/standard/update';
// $path = 'mshop/stock/manager/mystandard/update';
}
$stmt = $this->getCachedStatement( $conn, $path );
$stmt->bind( 1, $item->getProductCode() );
$stmt->bind( 2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
$stmt->bind( 3, $item->getStocklevel(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
$stmt->bind( 4, $item->getDateBack() );
// GET the Order Time
$stmt->bind( 5, $item->getOrderTime() );
$stmt->bind( 6, $date ); //mtime
$stmt->bind( 7, $context->getEditor() );
$stmt->bind( 8, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
if( $id !== null ) {
$stmt->bind( 9, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
$item->setId( $id ); // modified false
} else {
$stmt->bind( 9, $date ); //ctime
}
$stmt->execute()->finish();
if( $id === null && $fetch === true )
{
/** mshop/stock/manager/standard/newid/mysql
* Retrieves the ID generated by the database when inserting a new record
*
* @see mshop/stock/manager/standard/newid/ansi
*/
/** mshop/stock/manager/standard/newid/ansi
* Retrieves the ID generated by the database when inserting a new record
*
* As soon as a new record is inserted into the database table,
* the database server generates a new and unique identifier for
* that record. This ID can be used for retrieving, updating and
* deleting that specific record from the table again.
*
* For MySQL:
* SELECT LAST_INSERT_ID()
* For PostgreSQL:
* SELECT currval('seq_msto_id')
* For SQL Server:
* SELECT SCOPE_IDENTITY()
* For Oracle:
* SELECT "seq_msto_id".CURRVAL FROM DUAL
*
* There's no way to retrive the new ID by a SQL statements that
* fits for most database servers as they implement their own
* specific way.
*
* @param string SQL statement for retrieving the last inserted record ID
* @since 2017.01
* @category Developer
* @see mshop/stock/manager/standard/insert/ansi
* @see mshop/stock/manager/standard/update/ansi
* @see mshop/stock/manager/standard/delete/ansi
* @see mshop/stock/manager/standard/search/ansi
* @see mshop/stock/manager/standard/count/ansi
* @see mshop/stock/manager/standard/stocklevel
*/
$path = 'mshop/stock/manager/standard/newid';
$item->setId( $this->newId( $conn, $path ) );
}
$dbm->release( $conn, $dbname );
}
catch( \Exception $e )
{
$dbm->release( $conn, $dbname );
throw $e;
}
return $item;
}
public function getSearchAttributes( $withsub = true )
{
$list = parent::getSearchAttributes( $withsub );
foreach( $this->searchConfig as $key => $fields ) {
$list[$key] = new \Aimeos\MW\Criteria\Attribute\Standard( $fields );
}
return $list;
}
protected function createItemBase( array $values = [] /* , ... */ )
{
return new \Mhaimeos\MShop\Stock\Item\Standard( $values /* , ... */ );
}
}
I created the Config
Its a copy from the existing one. I just change the name, the insert and update.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/config/stock.php
Code: Select all
<?php
/**
* @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
* @copyright Aimeos (aimeos.org), 2015-2017
*/
return array(
'manager' => array(
'name' => 'Mystandard',
'type' => array(
'standard' => array(
'delete' => array(
'ansi' => '
DELETE FROM "mshop_stock_type"
WHERE :cond AND siteid = ?
'
),
'insert' => array(
'ansi' => '
INSERT INTO "mshop_stock_type" (
"code", "domain", "label", "status",
"mtime", "editor", "siteid", "ctime"
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?
)
'
),
'update' => array(
'ansi' => '
UPDATE "mshop_stock_type"
SET "code" = ?, "domain" = ?, "label" = ?,
"status" = ?, "mtime" = ?, "editor" = ?
WHERE "siteid" = ? AND "id" = ?
'
),
'search' => array(
'ansi' => '
SELECT mstoty."id" AS "stock.type.id", mstoty."siteid" AS "stock.type.siteid",
mstoty."code" AS "stock.type.code", mstoty."domain" AS "stock.type.domain",
mstoty."label" AS "stock.type.label", mstoty."status" AS "stock.type.status",
mstoty."mtime" AS "stock.type.mtime", mstoty."editor" AS "stock.type.editor",
mstoty."ctime" AS "stock.type.ctime"
FROM "mshop_stock_type" mstoty
:joins
WHERE :cond
GROUP BY mstoty."id", mstoty."siteid", mstoty."code", mstoty."domain",
mstoty."label", mstoty."status", mstoty."mtime", mstoty."editor",
mstoty."ctime" /*-columns*/ , :columns /*columns-*/
/*-orderby*/ ORDER BY :order /*orderby-*/
LIMIT :size OFFSET :start
'
),
'count' => array(
'ansi' => '
SELECT COUNT(*) AS "count"
FROM (
SELECT DISTINCT mstoty."id"
FROM "mshop_stock_type" mstoty
:joins
WHERE :cond
LIMIT 10000 OFFSET 0
) AS list
'
),
'newid' => array(
'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
'mysql' => 'SELECT LAST_INSERT_ID()',
'oracle' => 'SELECT mshop_stock_type_seq.CURRVAL FROM DUAL',
'pgsql' => 'SELECT lastval()',
'sqlite' => 'SELECT last_insert_rowid()',
'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
'sqlanywhere' => 'SELECT @@IDENTITY',
),
),
),
'standard' => array(
'delete' => array(
'ansi' => '
DELETE FROM "mshop_stock"
WHERE :cond AND siteid = ?
'
),
'insert' => array(
'ansi' => '
INSERT INTO "mshop_stock" (
"productcode", "typeid", "stocklevel", "backdate", "ordertime"
"mtime", "editor", "siteid", "ctime"
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?
)
'
),
'update' => array(
'ansi' => '
UPDATE "mshop_stock"
SET "productcode" = ?, "typeid" = ?, "stocklevel" = ?,
"backdate" = ?, "ordertime" = ?, "mtime" = ?, "editor" = ?
WHERE "siteid" = ? AND "id" = ?
'
),
'search' => array(
'ansi' => '
SELECT msto."id" AS "stock.id", msto."productcode" AS "stock.productcode",
msto."siteid" AS "stock.siteid", msto."typeid" AS "stock.typeid",
msto."stocklevel" AS "stock.stocklevel", msto."backdate" AS "stock.backdate",
msto."ordertime" AS "stock.ordertime",
msto."mtime" AS "stock.mtime", msto."editor" AS "stock.editor",
msto."ctime" AS "stock.ctime"
FROM "mshop_stock" AS msto
:joins
WHERE :cond
GROUP BY msto."id", msto."productcode", msto."siteid", msto."typeid",
msto."stocklevel", msto."backdate", msto."ordertime", msto."mtime", msto."editor",
msto."ctime" /*-columns*/ , :columns /*columns-*/
/*-orderby*/ ORDER BY :order /*orderby-*/
LIMIT :size OFFSET :start
'
),
'count' => array(
'ansi' => '
SELECT COUNT(*) AS "count"
FROM (
SELECT DISTINCT msto."id"
FROM "mshop_stock" AS msto
:joins
WHERE :cond
LIMIT 10000 OFFSET 0
) AS list
'
),
'stocklevel' => array(
'ansi' => '
UPDATE "mshop_stock"
SET "stocklevel" = "stocklevel" + ?, "mtime" = ?, "editor" = ?
WHERE :cond
'
),
'newid' => array(
'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
'mysql' => 'SELECT LAST_INSERT_ID()',
'oracle' => 'SELECT mshop_stock_seq.CURRVAL FROM DUAL',
'pgsql' => 'SELECT lastval()',
'sqlite' => 'SELECT last_insert_rowid()',
'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
'sqlanywhere' => 'SELECT @@IDENTITY',
),
),
),
);
Path: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-jqadm/admin/jqadm/templates/product/item-stock-default.php
Code: Select all
<?php
/**
* @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
* @copyright Aimeos (aimeos.org), 2015-2017
*/
$enc = $this->encoder();
$stockTypes = $this->get( 'stockTypes', [] );
?>
<div id="stock" class="item-stock content-block tab-pane fade" role="tabpanel" aria-labelledby="stock">
<table class="stock-list table table-default">
<thead>
<tr>
<?php if( count( $stockTypes ) > 1 ) : ?>
<th class="stock-type">
<span class="help"><?= $enc->html( $this->translate( 'admin', 'Type' ) ); ?></span>
<div class="form-text text-muted help-text">
<?= $enc->html( $this->translate( 'admin', 'Warehouse or local store if your articles are available at several locations' ) ); ?>
</div>
</th>
<?php endif; ?>
<th class="stock-stocklevel">
<span class="help"><?= $enc->html( $this->translate( 'admin', 'Stock level' ) ); ?></span>
<div class="form-text text-muted help-text">
<?= $enc->html( $this->translate( 'admin', 'Number of articles currently in stock, leave empty for an unlimited quantity' ) ); ?>
</div>
</th>
<th class="stock-databack">
<span class="help"><?= $enc->html( $this->translate( 'admin', 'Back in stock' ) ); ?></span>
<div class="form-text text-muted help-text">
<?= $enc->html( $this->translate( 'admin', 'Shown if the article reached a stock level of zero' ) ); ?>
</div>
</th>
<th class="stock-ordertime">
<span class="help"><?= $enc->html( $this->translate( 'admin', 'Stock Item Order Time' ) ); ?></span>
<div class="form-text text-muted help-text">
<?= $enc->html( $this->translate( 'admin', 'Shown if the article reached a stock level of zero' ) ); ?>
</div>
</th>
<th class="actions">
<div class="btn act-add fa" tabindex="<?= $this->get( 'tabindex' ); ?>"
title="<?= $enc->attr( $this->translate( 'admin', 'Insert new entry (Ctrl+I)') ); ?>">
</div>
</th>
</tr>
</thead>
<tbody>
<?php foreach( $this->get( 'stockData/stock.id', [] ) as $idx => $id ) : ?>
<tr class="<?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?>">
<?php if( count( $stockTypes ) > 1 ) : ?>
<td class="stock-type mandatory">
<select class="form-control custom-select item-typeid" required="required" tabindex="<?= $this->get( 'tabindex' ); ?>"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>"
<?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> >
<option value="">
<?= $enc->html( $this->translate( 'admin', 'Please select' ) ); ?>
</option>
<?php foreach( $this->get( 'stockTypes', [] ) as $typeId => $typeItem ) : ?>
<?php if( $typeId == $this->get( 'stockData/stock.typeid/' . $idx ) ) : ?>
<option value="<?= $enc->attr( $typeId ); ?>" selected="selected"><?= $enc->html( $typeItem->getLabel() ) ?></option>
<?php else : ?>
<option value="<?= $enc->attr( $typeId ); ?>"><?= $enc->html( $typeItem->getLabel() ) ?></option>
<?php endif; ?>
<?php endforeach; ?>
</select>
</td>
<?php else : $stockType = reset( $stockTypes ); ?>
<input class="item-typeid" type="hidden"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>"
value="<?= $enc->attr( $stockType ? $stockType->getId() : '' ); ?>" />
<?php endif; ?>
<td class="stock-stocklevel optional">
<input class="form-control item-stocklevel" type="number" step="1" min="0" tabindex="<?= $this->get( 'tabindex' ); ?>"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.stocklevel', '' ) ) ); ?>"
value="<?= $enc->attr( $this->get( 'stockData/stock.stocklevel/' . $idx ) ); ?>"
<?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> />
</td>
<td class="stock-databack optional">
<input class="form-control item-dateback" type="datetime-local" tabindex="<?= $this->get( 'tabindex' ); ?>"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.dateback', '' ) ) ); ?>"
value="<?= $enc->attr( $this->get( 'stockData/stock.dateback/' . $idx ) ); ?>"
placeholder="<?= $enc->attr( $this->translate( 'admin', 'YYYY-MM-DD hh:mm:ss (optional)' ) ); ?>"
<?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> />
</td>
<td class="stock-ordertime optional">
<input class="form-control item-ordertime" type="string" tabindex="<?= $this->get( 'tabindex' ); ?>"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.ordertime', '' ) ) ); ?>"
value="<?= $enc->attr( $this->get( 'stockData/stock.ordertime/' . $idx ) ); ?>"
placeholder="<?= $enc->attr( $this->translate( 'admin', 'Order Time' ) ); ?>"
<?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> />
</td>
<td class="actions">
<input class="item-id" type="hidden" value="<?= $enc->attr( $id ); ?>"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.id', '' ) ) ); ?>" />
<?php if( !$this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ) ) : ?>
<div class="btn act-delete fa" tabindex="<?= $this->get( 'tabindex' ); ?>"
title="<?= $enc->attr( $this->translate( 'admin', 'Delete this entry') ); ?>">
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<tr class="prototype">
<?php if( count( $stockTypes ) > 1 ) : ?>
<td class="stock-type">
<select class="form-control custom-select item-typeid" required="required" tabindex="<?= $this->get( 'tabindex' ); ?>" disabled="disabled"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>">
<option value="">
<?= $enc->attr( $this->translate( 'admin', 'Please select' ) ); ?>
</option>
<?php foreach( $stockTypes as $typeId => $typeItem ) : ?>
<option value="<?= $enc->attr( $typeId ); ?>"><?= $enc->html( $typeItem->getLabel() ) ?></option>
<?php endforeach; ?>
</select>
</td>
<?php else : $stockType = reset( $stockTypes ); ?>
<input class="item-typeid" type="hidden"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>"
value="<?= $enc->attr( $stockType ? $stockType->getId() : '' ); ?>" />
<?php endif; ?>
<td class="stock-stocklevel optional">
<input class="form-control item-stocklevel" type="number" step="1" min="0" tabindex="<?= $this->get( 'tabindex' ); ?>" disabled="disabled"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.stocklevel', '' ) ) ); ?>" />
</td>
<td class="stock-databack optional">
<input class="form-control item-dateback" type="datetime-local" tabindex="<?= $this->get( 'tabindex' ); ?>" disabled="disabled"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.dateback', '' ) ) ); ?>"
placeholder="<?= $enc->attr( $this->translate( 'admin', 'YYYY-MM-DD hh:mm:ss (optional)' ) ); ?>" />
</td>
<td class="stock-ordertime optional">
<input class="form-control item-orderdate" type="string" tabindex="<?= $this->get( 'tabindex' ); ?>"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.ordertime', '' ) ) ); ?>"
placeholder="<?= $enc->attr( $this->translate( 'admin', 'Order Time' ) ); ?>"
</td>
<td class="actions">
<input class="item-id" type="hidden" value="" disabled="disabled"
name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.id', '' ) ) ); ?>" />
<div class="btn act-delete fa" tabindex="<?= $this->get( 'tabindex' ); ?>"
title="<?= $enc->attr( $this->translate( 'admin', 'Delete this entry') ); ?>">
</div>
</td>
</tr>
</tbody>
</table>
<?= $this->get( 'stockBody' ); ?>
</div>
2. And my second Question is do i have to change the iface for order with my new function getOrderTime and setOrderTime and if yes where do i have to register the iface? I tryed it in the save function of my manager.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Item/Myiface.php
Code: Select all
<?php
/**
* @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
* @copyright Metaways Infosystems GmbH, 2011
* @copyright Aimeos (aimeos.org), 2015-2017
* @package MShop
* @subpackage Stock
*/
namespace Aimeos\MShop\Stock\Item;
//namespace Mhaimeos\MShop\Stock\Item;
/**
* Extends Default stock item interface.
*
* @package MShop
* @subpackage Stock
*/
interface Myiface extends Iface
{
/**
* Returns the ordertime of the stock item.
*
* @return string Order Time
*/
public function getOrderTime();
/**
* Sets a new Ordertime of the stock item.
*
* @param string $ordertime
* @return \Aimeos\MShop\Stock\Item\Iface Stock item for chaining method calls
*/
public function setOrderTime( $ordertime );
}
3. Third Question, are my namespaces correct?
----------------------------------------------------------------------------------------------------
4. And my last question is how do i change the templates for the extadmin, is there anything documented?
I tryed to change the ItemUI.js and ListUI.js but got this error
ext-all.js:21 Uncaught TypeError: g is not a constructor
at constructor.setConfig (ext-all.js:21)
at new constructor (ext-all.js:21)
at S.initComponent (ext-all.js:21)
at S.Ext.Component [as constructor] (ext-all.js:21)
at S [as constructor] (ext-base.js:21)
at S [as constructor] (ext-base.js:21)
at S [as constructor] (ext-base.js:21)
at new S (ext-base.js:21)
at S.initComponent (index.php?M=web_AimeosTxAimeosAdmin&moduleToken=60ae9e4e8faae802e56a6d72d2902be966dd9fed&tx_aimeos_web_aimeostxaimeosadmin[action]=file&tx_aimeos_web_aimeostxaimeosadmin[controller]=Extadm:3347)
at S.initComponent (index.php?M=web_AimeosTxAimeosAdmin&moduleToken=60ae9e4e8faae802e56a6d72d2902be966dd9fed&tx_aimeos_web_aimeostxaimeosadmin[action]=file&tx_aimeos_web_aimeostxaimeosadmin[controller]=Extadm:9500)
Path: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-extadm/admin/extjs/src/panel/product/stock/ItemUi.js
Code: Select all
/*!
* Copyright (c) Metaways Infosystems GmbH, 2011
* LGPLv3, http://opensource.org/licenses/LGPL-3.0
*/
Ext.ns('MShop.panel.product.stock');
/**
* Concrete ItemUi
*
* @extends Mshop.panel.AbstractListItemUi
*/
MShop.panel.product.stock.ItemUi = Ext.extend(MShop.panel.AbstractItemUi, {
siteidProperty : 'stock.siteid',
initComponent : function() {
this.title = MShop.I18n.dt('admin', 'Product stock');
MShop.panel.AbstractItemUi.prototype.setSiteCheck(this);
this.items = [{
xtype : 'tabpanel',
activeTab : 0,
border : false,
itemId : 'MShop.panel.product.stock.ItemUi',
plugins : ['ux.itemregistry'],
items : [{
xtype : 'panel',
title : MShop.I18n.dt('admin', 'Basic'),
border : false,
layout : 'hbox',
layoutConfig : {
align : 'stretch'
},
itemId : 'MShop.panel.product.stock.ItemUi.BasicPanel',
plugins : ['ux.itemregistry'],
defaults : {
bodyCssClass : this.readOnlyClass
},
items : [{
xtype : 'form',
title : MShop.I18n.dt('admin', 'Details'),
flex : 1,
ref : '../../mainForm',
autoScroll : true,
items : [{
xtype : 'fieldset',
style : 'padding-right: 25px;',
border : false,
labelAlign : 'top',
defaults : {
readOnly : this.fieldsReadOnly,
anchor : '100%'
},
items : [{
xtype : 'hidden',
name : 'stock.productcode'
}, {
xtype : 'displayfield',
fieldLabel : MShop.I18n.dt('admin', 'ID'),
name : 'stock.id'
}, {
xtype : 'combo',
fieldLabel : MShop.I18n.dt('admin', 'Type'),
name : 'stock.typeid',
mode : 'local',
store : MShop.GlobalStoreMgr.get('Stock_Type', this.domain),
displayField : 'stock.type.label',
valueField : 'stock.type.id',
forceSelection : true,
triggerAction : 'all',
typeAhead : true,
listeners : {
'render' : {
fn : function() {
var record, index = this.store.find('stock.type.code', 'default');
if((record = this.store.getAt(index))) {
this.setValue(record.id);
}
}
}
}
}, {
xtype : 'numberfield',
fieldLabel : MShop.I18n.dt('admin', 'Stock level'),
name : 'stock.stocklevel',
emptyText : MShop.I18n.dt('admin', 'Quantity or empty if unlimited (optional)')
}, {
xtype : 'datefield',
fieldLabel : MShop.I18n.dt('admin', 'Back in stock'),
name : 'stock.dateback',
format : 'Y-m-d H:i:s',
emptyText : MShop.I18n.dt('admin', 'YYYY-MM-DD hh:mm:ss (optional)')
}, {
xtype : 'ordertime',
fieldLabel : MShop.I18n.dt('admin', 'Stock Order Time'),
name : 'stock.ordertime',
emptyText : MShop.I18n.dt('admin', 'Stock Order Time')
}, {
xtype : 'displayfield',
fieldLabel : MShop.I18n.dt('admin', 'Created'),
name : 'stock.ctime'
}, {
xtype : 'displayfield',
fieldLabel : MShop.I18n.dt('admin', 'Last modified'),
name : 'stock.mtime'
}, {
xtype : 'displayfield',
fieldLabel : MShop.I18n.dt('admin', 'Editor'),
name : 'stock.editor'
}]
}]
}]
}]
}];
MShop.panel.product.stock.ItemUi.superclass.initComponent.call(this);
},
onSaveItem : function() {
// validate data
if(!this.mainForm.getForm().isValid() && this.fireEvent('validate', this) !== false) {
Ext.Msg.alert(MShop.I18n.dt('admin', 'Invalid data'), MShop.I18n.dt('admin',
'Please recheck your data'));
return;
}
this.saveMask.show();
this.isSaveing = true;
// force record to be saved!
this.record.dirty = true;
if(this.fireEvent('beforesave', this, this.record) === false) {
this.isSaveing = false;
this.saveMask.hide();
}
this.mainForm.getForm().updateRecord(this.record);
this.record.data['stock.productcode'] = this.listUI.itemUi.record.data['product.code'];
if(this.action == 'add' || this.action == 'copy') {
this.store.add(this.record);
}
// store async action is triggered. {@see onStoreWrite/onStoreException}
if(!this.store.autoSave) {
this.onAfterSave();
}
},
onStoreException : function() {
this.store.remove(this.record);
MShop.panel.product.stock.ItemUi.superclass.onStoreException.apply(this, arguments);
}
});
Ext.reg('MShop.panel.product.stock.itemui', MShop.panel.product.stock.ItemUi);
Code: Select all
/*!
* LGPLv3, http://opensource.org/licenses/LGPL-3.0
* Copyright (c) Metaways Infosystems GmbH, 2011
* Copyright (c) Aimeos (aimeos.org), 2015-2017
*/
Ext.ns('MShop.panel.product.stock');
MShop.panel.product.stock.ListUi = Ext.extend(MShop.panel.AbstractListUi, {
recordName : 'Stock',
idProperty : 'stock.id',
siteidProperty : 'stock.siteid',
itemUiXType : 'MShop.panel.product.stock.itemui',
autoExpandColumn : 'product-stock-stocktype',
filterConfig : {
filters : [{
dataIndex : 'stock.type.label',
operator : '=~',
value : ''
}]
},
initComponent : function() {
this.title = MShop.I18n.dt('admin', 'Stock');
MShop.panel.AbstractListUi.prototype.initActions.call(this);
MShop.panel.AbstractListUi.prototype.initToolbar.call(this);
MShop.panel.product.stock.ListUi.superclass.initComponent.call(this);
},
afterRender : function() {
this.itemUi = this.findParentBy(function(c) {
return c.isXType(MShop.panel.AbstractItemUi, false);
});
MShop.panel.product.stock.ListUi.superclass.afterRender.apply(this, arguments);
},
onBeforeLoad : function(store, options) {
this.setSiteParam(store);
if(this.domain) {
this.setDomainFilter(store, options);
}
options.params = options.params || {};
options.params.condition = {
'&&' : [{
'==' : {
'stock.productcode' : this.itemUi.record ? this.itemUi.record.data['product.code'] : ''
}
}]
};
},
getColumns : function() {
this.typeStore = MShop.GlobalStoreMgr.get('Stock_Type');
return [
{
xtype : 'gridcolumn',
dataIndex : 'stock.id',
header : MShop.I18n.dt('admin', 'ID'),
sortable : true,
width : 50,
hidden : true
},
{
xtype : 'gridcolumn',
dataIndex : 'stock.productcode',
header : MShop.I18n.dt('admin', 'Product code'),
width : 50,
hidden : true
},
{
xtype : 'gridcolumn',
dataIndex : 'stock.typeid',
header : MShop.I18n.dt('admin', 'Type'),
align : 'center',
id : 'product-stock-stocktype',
renderer : this.typeColumnRenderer.createDelegate(this, [
this.typeStore,
"stock.type.label"], true)
},
{
xtype : 'gridcolumn',
dataIndex : 'stock.stocklevel',
header : MShop.I18n.dt('admin', 'Stock level'),
sortable : true,
align : 'center',
width : 80
},
{
xtype : 'datecolumn',
dataIndex : 'stock.dateback',
header : MShop.I18n.dt('admin', 'Date back'),
format : 'Y-m-d H:i:s',
sortable : true,
width : 130
},
{
xtype : 'ordertime',
dataIndex : 'stock.ordertime',
header : MShop.I18n.dt('admin', 'Order Time'),
sortable : true,
width : 130
},
{
xtype : 'datecolumn',
dataIndex : 'stock.ctime',
header : MShop.I18n.dt('admin', 'Created'),
format : 'Y-m-d H:i:s',
sortable : true,
width : 130,
editable : false,
hidden : true
},
{
xtype : 'datecolumn',
dataIndex : 'stock.mtime',
header : MShop.I18n.dt('admin', 'Last modified'),
format : 'Y-m-d H:i:s',
sortable : true,
width : 130,
editable : false,
hidden : true
},
{
xtype : 'gridcolumn',
dataIndex : 'stock.editor',
header : MShop.I18n.dt('admin', 'Editor'),
sortable : true,
width : 130,
editable : false,
hidden : true
}];
}
});
Ext.reg('MShop.panel.product.stock.listui', MShop.panel.product.stock.ListUi);
Ext.ux.ItemRegistry.registerItem('MShop.panel.product.ItemUi', 'MShop.panel.product.stock.listui', MShop.panel.product.stock.ListUi, 2);
Many Thanks and sorry for the long post
Typo3 7.6.x / Aimeos 17.10.0
Last edited by tenkraD on 11 Apr 2018, 20:36, edited 3 times in total.
Re: Extend Stock to Save a new Value
The namespace/class name of your item in createItemBase() (manager class) is wrong. It must be \Aimeos\MShop\Stock\Item\MyStandard. The rest seems to be OK.
If you don't have a clue, add some debug output to see which code is executed.
Regarding the ExtJS interface: Forget about it!
In 2017.x it's deprecated and in the 2018.x version it's already removed.
If you don't have a clue, add some debug output to see which code is executed.
Regarding the ExtJS interface: Forget about it!
In 2017.x it's deprecated and in the 2018.x version it's already removed.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, give us a star
If you like Aimeos, give us a star
Re: Extend Stock to Save a new Value
-----tenkraD wrote:Hello Guys,
i would like to extend the stock of products with a optional field order time.
the order time is a string, and describes how long it takes for us to reorder if the product is selled out - 1 weeks/ 1 month / a few days...
-------------------------------------------------------------------------------------------------------------
1. My Problem is i cant save the values in db and dont know what im doing wrong. Also i dont get any error response, im a bit lost.
It would be great if you can help me.
I created an extension named "mhaimeos" with our extensionbuilder.
Then i extended the stock shema, this is working good.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/config/stock.phpAfter that i created the ItemCode: Select all
<?php /** * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 * * Extend Database Table mshop_stock in /typo3conf/ext/aimeos/Resources/Libraries/aimeos/aimeos-core/lib/mshoplib/setup/default/schema/stock.php * * https://aimeos.org/docs/Developers/Library/Setup_tasks/Schema_update#Modify_existing_tables */ return array( 'table' => array( 'mshop_stock' => function ( \Doctrine\DBAL\Schema\Schema $schema ) { $table = $schema->getTable( 'mshop_stock' ); $table->addColumn( 'ordertime', 'string', array( 'length' => 32 ) ); $table->addIndex( array( 'siteid', 'ordertime' ), 'idx_mssto_sid_ordertime' ); return $schema; }, ), );
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Item/Mystandard.phpI created the managerCode: Select all
<?php /** * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 * @package MShop * @subpackage Stock */ namespace Aimeos\MShop\Stock\Item; //namespace Mhaimeos\MShop\Stock\Item; class Mystandard extends Standard { private $values; public function __construct( array $values ) { parent::__construct( 'stock.', $values ); $this->values = $values; } /** * Returns ordertime for the product stock * * @return string|null stock ordertime of the product */ public function getOrderTime() { if( isset( $this->values['stock.ordertime'] ) ) { return (string) $this->values['stock.ordertime']; } return ''; } public function setOrderTime( $ordertime ) { if( (string) $ordertime !== $this->getOrderTime() ) { $this->values['stock.ordertime'] = (string) $ordertime; $this->setModified(); } return $this; } public function fromArray( array $list ) { $unknown = []; $list = parent::fromArray( $list ); foreach( $list as $key => $value ) { switch( $key ) { case 'stock.ordertime': $this->setOrderTime( $value ); break; default: $unknown[$key] = $value; } } return $unknown; } public function toArray( $private = false ) { $list = parent::toArray( $private ); if( $private === true ) { $list['stock.ordertime'] = $this->getOrderTime(); } return $list; } }
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Manager/Mystandard.phpCode: Select all
<?php /** * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 * @package MShop * @subpackage Stock */ namespace Aimeos\MShop\Stock\Manager; //namespace Mhaimeos\MShop\Stock\Manager; class Mystandard extends Standard { private $searchConfig = array( 'stock.ordertime'=> array( 'code'=>'stock.ordertime', 'internalcode'=>'msto."ordertime"', 'label'=>'Product Ordertime', 'type'=> 'string', // integer, float, etc. 'internaltype'=> \Aimeos\MW\DB\Statement\Base::PARAM_STR, // _INT, _FLOAT, etc. ), ); public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true ) { // a modified copy of the code from the parent class // extended by a bind() call and updated bind positions (first parameter) $iface = '\\Mhaimeos\\MShop\\Stock\\Item\\Myiface'; if( !( $item instanceof $iface ) ) { throw new \Aimeos\MShop\Stock\Exception( sprintf( 'Object is not of required type "%1$s"', $iface ) ); } if( !$item->isModified() ) { return $item; } $context = $this->getContext(); $dbm = $context->getDatabaseManager(); $dbname = $this->getResourceName(); $conn = $dbm->acquire( $dbname ); try { $id = $item->getId(); $date = date( 'Y-m-d H:i:s' ); if( $id === null ) { /** mshop/stock/manager/standard/insert/mysql * Inserts a new product stock record into the database table * * @see mshop/stock/manager/standard/insert/ansi */ /** mshop/stock/manager/standard/insert/ansi * Inserts a new product stock record into the database table * * Items with no ID yet (i.e. the ID is NULL) will be created in * the database and the newly created ID retrieved afterwards * using the "newid" SQL statement. * * The SQL statement must be a string suitable for being used as * prepared statement. It must include question marks for binding * the values from the product stock item to the statement before they are * sent to the database server. The number of question marks must * be the same as the number of columns listed in the INSERT * statement. The order of the columns must correspond to the * order in the saveItems() method, so the correct values are * bound to the columns. * * The SQL statement should conform to the ANSI standard to be * compatible with most relational database systems. This also * includes using double quotes for table and column names. * * @param string SQL statement for inserting records * @since 2017.01 * @category Developer * @see mshop/stock/manager/standard/update/ansi * @see mshop/stock/manager/standard/newid/ansi * @see mshop/stock/manager/standard/delete/ansi * @see mshop/stock/manager/standard/search/ansi * @see mshop/stock/manager/standard/count/ansi * @see mshop/stock/manager/standard/stocklevel */ $path = 'mshop/stock/manager/standard/insert'; // $path = 'mshop/stock/manager/mystandard/insert'; } else { /** mshop/stock/manager/standard/update/mysql * Updates an existing product stock record in the database * * @see mshop/stock/manager/standard/update/ansi */ /** mshop/stock/manager/standard/update/ansi * Updates an existing product stock record in the database * * Items which already have an ID (i.e. the ID is not NULL) will * be updated in the database. * * The SQL statement must be a string suitable for being used as * prepared statement. It must include question marks for binding * the values from the product stock item to the statement before they are * sent to the database server. The order of the columns must * correspond to the order in the saveItems() method, so the * correct values are bound to the columns. * * The SQL statement should conform to the ANSI standard to be * compatible with most relational database systems. This also * includes using double quotes for table and column names. * * @param string SQL statement for updating records * @since 2017.01 * @category Developer * @see mshop/stock/manager/standard/insert/ansi * @see mshop/stock/manager/standard/newid/ansi * @see mshop/stock/manager/standard/delete/ansi * @see mshop/stock/manager/standard/search/ansi * @see mshop/stock/manager/standard/count/ansi * @see mshop/stock/manager/standard/stocklevel */ $path = 'mshop/stock/manager/standard/update'; // $path = 'mshop/stock/manager/mystandard/update'; } $stmt = $this->getCachedStatement( $conn, $path ); $stmt->bind( 1, $item->getProductCode() ); $stmt->bind( 2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT ); $stmt->bind( 3, $item->getStocklevel(), \Aimeos\MW\DB\Statement\Base::PARAM_INT ); $stmt->bind( 4, $item->getDateBack() ); // GET the Order Time $stmt->bind( 5, $item->getOrderTime() ); $stmt->bind( 6, $date ); //mtime $stmt->bind( 7, $context->getEditor() ); $stmt->bind( 8, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT ); if( $id !== null ) { $stmt->bind( 9, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT ); $item->setId( $id ); // modified false } else { $stmt->bind( 9, $date ); //ctime } $stmt->execute()->finish(); if( $id === null && $fetch === true ) { /** mshop/stock/manager/standard/newid/mysql * Retrieves the ID generated by the database when inserting a new record * * @see mshop/stock/manager/standard/newid/ansi */ /** mshop/stock/manager/standard/newid/ansi * Retrieves the ID generated by the database when inserting a new record * * As soon as a new record is inserted into the database table, * the database server generates a new and unique identifier for * that record. This ID can be used for retrieving, updating and * deleting that specific record from the table again. * * For MySQL: * SELECT LAST_INSERT_ID() * For PostgreSQL: * SELECT currval('seq_msto_id') * For SQL Server: * SELECT SCOPE_IDENTITY() * For Oracle: * SELECT "seq_msto_id".CURRVAL FROM DUAL * * There's no way to retrive the new ID by a SQL statements that * fits for most database servers as they implement their own * specific way. * * @param string SQL statement for retrieving the last inserted record ID * @since 2017.01 * @category Developer * @see mshop/stock/manager/standard/insert/ansi * @see mshop/stock/manager/standard/update/ansi * @see mshop/stock/manager/standard/delete/ansi * @see mshop/stock/manager/standard/search/ansi * @see mshop/stock/manager/standard/count/ansi * @see mshop/stock/manager/standard/stocklevel */ $path = 'mshop/stock/manager/standard/newid'; $item->setId( $this->newId( $conn, $path ) ); } $dbm->release( $conn, $dbname ); } catch( \Exception $e ) { $dbm->release( $conn, $dbname ); throw $e; } return $item; } public function getSearchAttributes( $withsub = true ) { $list = parent::getSearchAttributes( $withsub ); foreach( $this->searchConfig as $key => $fields ) { $list[$key] = new \Aimeos\MW\Criteria\Attribute\Standard( $fields ); } return $list; } protected function createItemBase( array $values = [] /* , ... */ ) { return new \Mhaimeos\MShop\Stock\Item\Standard( $values /* , ... */ ); } }
I created the Config
Its a copy from the existing one. I just change the name, the insert and update.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/config/stock.phpI edited the templateCode: Select all
<?php /** * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 * @copyright Aimeos (aimeos.org), 2015-2017 */ return array( 'manager' => array( 'name' => 'Mystandard', 'type' => array( 'standard' => array( 'delete' => array( 'ansi' => ' DELETE FROM "mshop_stock_type" WHERE :cond AND siteid = ? ' ), 'insert' => array( 'ansi' => ' INSERT INTO "mshop_stock_type" ( "code", "domain", "label", "status", "mtime", "editor", "siteid", "ctime" ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ? ) ' ), 'update' => array( 'ansi' => ' UPDATE "mshop_stock_type" SET "code" = ?, "domain" = ?, "label" = ?, "status" = ?, "mtime" = ?, "editor" = ? WHERE "siteid" = ? AND "id" = ? ' ), 'search' => array( 'ansi' => ' SELECT mstoty."id" AS "stock.type.id", mstoty."siteid" AS "stock.type.siteid", mstoty."code" AS "stock.type.code", mstoty."domain" AS "stock.type.domain", mstoty."label" AS "stock.type.label", mstoty."status" AS "stock.type.status", mstoty."mtime" AS "stock.type.mtime", mstoty."editor" AS "stock.type.editor", mstoty."ctime" AS "stock.type.ctime" FROM "mshop_stock_type" mstoty :joins WHERE :cond GROUP BY mstoty."id", mstoty."siteid", mstoty."code", mstoty."domain", mstoty."label", mstoty."status", mstoty."mtime", mstoty."editor", mstoty."ctime" /*-columns*/ , :columns /*columns-*/ /*-orderby*/ ORDER BY :order /*orderby-*/ LIMIT :size OFFSET :start ' ), 'count' => array( 'ansi' => ' SELECT COUNT(*) AS "count" FROM ( SELECT DISTINCT mstoty."id" FROM "mshop_stock_type" mstoty :joins WHERE :cond LIMIT 10000 OFFSET 0 ) AS list ' ), 'newid' => array( 'db2' => 'SELECT IDENTITY_VAL_LOCAL()', 'mysql' => 'SELECT LAST_INSERT_ID()', 'oracle' => 'SELECT mshop_stock_type_seq.CURRVAL FROM DUAL', 'pgsql' => 'SELECT lastval()', 'sqlite' => 'SELECT last_insert_rowid()', 'sqlsrv' => 'SELECT SCOPE_IDENTITY()', 'sqlanywhere' => 'SELECT @@IDENTITY', ), ), ), 'standard' => array( 'delete' => array( 'ansi' => ' DELETE FROM "mshop_stock" WHERE :cond AND siteid = ? ' ), 'insert' => array( 'ansi' => ' INSERT INTO "mshop_stock" ( "productcode", "typeid", "stocklevel", "backdate", "ordertime" "mtime", "editor", "siteid", "ctime" ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? ) ' ), 'update' => array( 'ansi' => ' UPDATE "mshop_stock" SET "productcode" = ?, "typeid" = ?, "stocklevel" = ?, "backdate" = ?, "ordertime" = ?, "mtime" = ?, "editor" = ? WHERE "siteid" = ? AND "id" = ? ' ), 'search' => array( 'ansi' => ' SELECT msto."id" AS "stock.id", msto."productcode" AS "stock.productcode", msto."siteid" AS "stock.siteid", msto."typeid" AS "stock.typeid", msto."stocklevel" AS "stock.stocklevel", msto."backdate" AS "stock.backdate", msto."ordertime" AS "stock.ordertime", msto."mtime" AS "stock.mtime", msto."editor" AS "stock.editor", msto."ctime" AS "stock.ctime" FROM "mshop_stock" AS msto :joins WHERE :cond GROUP BY msto."id", msto."productcode", msto."siteid", msto."typeid", msto."stocklevel", msto."backdate", msto."ordertime", msto."mtime", msto."editor", msto."ctime" /*-columns*/ , :columns /*columns-*/ /*-orderby*/ ORDER BY :order /*orderby-*/ LIMIT :size OFFSET :start ' ), 'count' => array( 'ansi' => ' SELECT COUNT(*) AS "count" FROM ( SELECT DISTINCT msto."id" FROM "mshop_stock" AS msto :joins WHERE :cond LIMIT 10000 OFFSET 0 ) AS list ' ), 'stocklevel' => array( 'ansi' => ' UPDATE "mshop_stock" SET "stocklevel" = "stocklevel" + ?, "mtime" = ?, "editor" = ? WHERE :cond ' ), 'newid' => array( 'db2' => 'SELECT IDENTITY_VAL_LOCAL()', 'mysql' => 'SELECT LAST_INSERT_ID()', 'oracle' => 'SELECT mshop_stock_seq.CURRVAL FROM DUAL', 'pgsql' => 'SELECT lastval()', 'sqlite' => 'SELECT last_insert_rowid()', 'sqlsrv' => 'SELECT SCOPE_IDENTITY()', 'sqlanywhere' => 'SELECT @@IDENTITY', ), ), ), );
Path: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-jqadm/admin/jqadm/templates/product/item-stock-default.php-----------------------------------------------------------------------------------------------------Code: Select all
<?php /** * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 * @copyright Aimeos (aimeos.org), 2015-2017 */ $enc = $this->encoder(); $stockTypes = $this->get( 'stockTypes', [] ); ?> <div id="stock" class="item-stock content-block tab-pane fade" role="tabpanel" aria-labelledby="stock"> <table class="stock-list table table-default"> <thead> <tr> <?php if( count( $stockTypes ) > 1 ) : ?> <th class="stock-type"> <span class="help"><?= $enc->html( $this->translate( 'admin', 'Type' ) ); ?></span> <div class="form-text text-muted help-text"> <?= $enc->html( $this->translate( 'admin', 'Warehouse or local store if your articles are available at several locations' ) ); ?> </div> </th> <?php endif; ?> <th class="stock-stocklevel"> <span class="help"><?= $enc->html( $this->translate( 'admin', 'Stock level' ) ); ?></span> <div class="form-text text-muted help-text"> <?= $enc->html( $this->translate( 'admin', 'Number of articles currently in stock, leave empty for an unlimited quantity' ) ); ?> </div> </th> <th class="stock-databack"> <span class="help"><?= $enc->html( $this->translate( 'admin', 'Back in stock' ) ); ?></span> <div class="form-text text-muted help-text"> <?= $enc->html( $this->translate( 'admin', 'Shown if the article reached a stock level of zero' ) ); ?> </div> </th> <th class="stock-ordertime"> <span class="help"><?= $enc->html( $this->translate( 'admin', 'Stock Item Order Time' ) ); ?></span> <div class="form-text text-muted help-text"> <?= $enc->html( $this->translate( 'admin', 'Shown if the article reached a stock level of zero' ) ); ?> </div> </th> <th class="actions"> <div class="btn act-add fa" tabindex="<?= $this->get( 'tabindex' ); ?>" title="<?= $enc->attr( $this->translate( 'admin', 'Insert new entry (Ctrl+I)') ); ?>"> </div> </th> </tr> </thead> <tbody> <?php foreach( $this->get( 'stockData/stock.id', [] ) as $idx => $id ) : ?> <tr class="<?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?>"> <?php if( count( $stockTypes ) > 1 ) : ?> <td class="stock-type mandatory"> <select class="form-control custom-select item-typeid" required="required" tabindex="<?= $this->get( 'tabindex' ); ?>" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>" <?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> > <option value=""> <?= $enc->html( $this->translate( 'admin', 'Please select' ) ); ?> </option> <?php foreach( $this->get( 'stockTypes', [] ) as $typeId => $typeItem ) : ?> <?php if( $typeId == $this->get( 'stockData/stock.typeid/' . $idx ) ) : ?> <option value="<?= $enc->attr( $typeId ); ?>" selected="selected"><?= $enc->html( $typeItem->getLabel() ) ?></option> <?php else : ?> <option value="<?= $enc->attr( $typeId ); ?>"><?= $enc->html( $typeItem->getLabel() ) ?></option> <?php endif; ?> <?php endforeach; ?> </select> </td> <?php else : $stockType = reset( $stockTypes ); ?> <input class="item-typeid" type="hidden" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>" value="<?= $enc->attr( $stockType ? $stockType->getId() : '' ); ?>" /> <?php endif; ?> <td class="stock-stocklevel optional"> <input class="form-control item-stocklevel" type="number" step="1" min="0" tabindex="<?= $this->get( 'tabindex' ); ?>" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.stocklevel', '' ) ) ); ?>" value="<?= $enc->attr( $this->get( 'stockData/stock.stocklevel/' . $idx ) ); ?>" <?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> /> </td> <td class="stock-databack optional"> <input class="form-control item-dateback" type="datetime-local" tabindex="<?= $this->get( 'tabindex' ); ?>" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.dateback', '' ) ) ); ?>" value="<?= $enc->attr( $this->get( 'stockData/stock.dateback/' . $idx ) ); ?>" placeholder="<?= $enc->attr( $this->translate( 'admin', 'YYYY-MM-DD hh:mm:ss (optional)' ) ); ?>" <?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> /> </td> <td class="stock-ordertime optional"> <input class="form-control item-ordertime" type="string" tabindex="<?= $this->get( 'tabindex' ); ?>" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.ordertime', '' ) ) ); ?>" value="<?= $enc->attr( $this->get( 'stockData/stock.ordertime/' . $idx ) ); ?>" placeholder="<?= $enc->attr( $this->translate( 'admin', 'Order Time' ) ); ?>" <?= $this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ); ?> /> </td> <td class="actions"> <input class="item-id" type="hidden" value="<?= $enc->attr( $id ); ?>" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.id', '' ) ) ); ?>" /> <?php if( !$this->site()->readonly( $this->get( 'stockData/stock.siteid/' . $idx ) ) ) : ?> <div class="btn act-delete fa" tabindex="<?= $this->get( 'tabindex' ); ?>" title="<?= $enc->attr( $this->translate( 'admin', 'Delete this entry') ); ?>"> </div> <?php endif; ?> </td> </tr> <?php endforeach; ?> <tr class="prototype"> <?php if( count( $stockTypes ) > 1 ) : ?> <td class="stock-type"> <select class="form-control custom-select item-typeid" required="required" tabindex="<?= $this->get( 'tabindex' ); ?>" disabled="disabled" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>"> <option value=""> <?= $enc->attr( $this->translate( 'admin', 'Please select' ) ); ?> </option> <?php foreach( $stockTypes as $typeId => $typeItem ) : ?> <option value="<?= $enc->attr( $typeId ); ?>"><?= $enc->html( $typeItem->getLabel() ) ?></option> <?php endforeach; ?> </select> </td> <?php else : $stockType = reset( $stockTypes ); ?> <input class="item-typeid" type="hidden" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>" value="<?= $enc->attr( $stockType ? $stockType->getId() : '' ); ?>" /> <?php endif; ?> <td class="stock-stocklevel optional"> <input class="form-control item-stocklevel" type="number" step="1" min="0" tabindex="<?= $this->get( 'tabindex' ); ?>" disabled="disabled" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.stocklevel', '' ) ) ); ?>" /> </td> <td class="stock-databack optional"> <input class="form-control item-dateback" type="datetime-local" tabindex="<?= $this->get( 'tabindex' ); ?>" disabled="disabled" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.dateback', '' ) ) ); ?>" placeholder="<?= $enc->attr( $this->translate( 'admin', 'YYYY-MM-DD hh:mm:ss (optional)' ) ); ?>" /> </td> <td class="stock-ordertime optional"> <input class="form-control item-orderdate" type="string" tabindex="<?= $this->get( 'tabindex' ); ?>" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.ordertime', '' ) ) ); ?>" placeholder="<?= $enc->attr( $this->translate( 'admin', 'Order Time' ) ); ?>" </td> <td class="actions"> <input class="item-id" type="hidden" value="" disabled="disabled" name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.id', '' ) ) ); ?>" /> <div class="btn act-delete fa" tabindex="<?= $this->get( 'tabindex' ); ?>" title="<?= $enc->attr( $this->translate( 'admin', 'Delete this entry') ); ?>"> </div> </td> </tr> </tbody> </table> <?= $this->get( 'stockBody' ); ?> </div>
2. And my second Question is do i have to change the iface for order with my new function getOrderTime and setOrderTime and if yes where do i have to register the iface? I tryed it in the save function of my manager.
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/src/MShop/Stock/Item/Myiface.php----------------------------------------------------------------------------------------------------Code: Select all
<?php /** * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 * @copyright Metaways Infosystems GmbH, 2011 * @copyright Aimeos (aimeos.org), 2015-2017 * @package MShop * @subpackage Stock */ namespace Aimeos\MShop\Stock\Item; //namespace Mhaimeos\MShop\Stock\Item; /** * Extends Default stock item interface. * * @package MShop * @subpackage Stock */ interface Myiface extends Iface { /** * Returns the ordertime of the stock item. * * @return string Order Time */ public function getOrderTime(); /** * Sets a new Ordertime of the stock item. * * @param string $ordertime * @return \Aimeos\MShop\Stock\Item\Iface Stock item for chaining method calls */ public function setOrderTime( $ordertime ); }
3. Third Question, are my namespaces correct?
----------------------------------------------------------------------------------------------------
4. And my last question is how do i change the templates for the extadmin, is there anything documented?
I tryed to change the ItemUI.js and ListUI.js but got this error
ext-all.js:21 Uncaught TypeError: g is not a constructor
at constructor.setConfig (ext-all.js:21)
at new constructor (ext-all.js:21)
at S.initComponent (ext-all.js:21)
at S.Ext.Component [as constructor] (ext-all.js:21)
at S [as constructor] (ext-base.js:21)
at S [as constructor] (ext-base.js:21)
at S [as constructor] (ext-base.js:21)
at new S (ext-base.js:21)
at S.initComponent (index.php?M=web_AimeosTxAimeosAdmin&moduleToken=60ae9e4e8faae802e56a6d72d2902be966dd9fed&tx_aimeos_web_aimeostxaimeosadmin[action]=file&tx_aimeos_web_aimeostxaimeosadmin[controller]=Extadm:3347)
at S.initComponent (index.php?M=web_AimeosTxAimeosAdmin&moduleToken=60ae9e4e8faae802e56a6d72d2902be966dd9fed&tx_aimeos_web_aimeostxaimeosadmin[action]=file&tx_aimeos_web_aimeostxaimeosadmin[controller]=Extadm:9500)
Path: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-extadm/admin/extjs/src/panel/product/stock/ItemUi.jsPath: /typo3conf/ext/aimeos/Resources/Private/Extensions/ai-admin-extadm/admin/extjs/src/panel/product/stock/ListUi.jsCode: Select all
/*! * Copyright (c) Metaways Infosystems GmbH, 2011 * LGPLv3, http://opensource.org/licenses/LGPL-3.0 */ Ext.ns('MShop.panel.product.stock'); /** * Concrete ItemUi * * @extends Mshop.panel.AbstractListItemUi */ MShop.panel.product.stock.ItemUi = Ext.extend(MShop.panel.AbstractItemUi, { siteidProperty : 'stock.siteid', initComponent : function() { this.title = MShop.I18n.dt('admin', 'Product stock'); MShop.panel.AbstractItemUi.prototype.setSiteCheck(this); this.items = [{ xtype : 'tabpanel', activeTab : 0, border : false, itemId : 'MShop.panel.product.stock.ItemUi', plugins : ['ux.itemregistry'], items : [{ xtype : 'panel', title : MShop.I18n.dt('admin', 'Basic'), border : false, layout : 'hbox', layoutConfig : { align : 'stretch' }, itemId : 'MShop.panel.product.stock.ItemUi.BasicPanel', plugins : ['ux.itemregistry'], defaults : { bodyCssClass : this.readOnlyClass }, items : [{ xtype : 'form', title : MShop.I18n.dt('admin', 'Details'), flex : 1, ref : '../../mainForm', autoScroll : true, items : [{ xtype : 'fieldset', style : 'padding-right: 25px;', border : false, labelAlign : 'top', defaults : { readOnly : this.fieldsReadOnly, anchor : '100%' }, items : [{ xtype : 'hidden', name : 'stock.productcode' }, { xtype : 'displayfield', fieldLabel : MShop.I18n.dt('admin', 'ID'), name : 'stock.id' }, { xtype : 'combo', fieldLabel : MShop.I18n.dt('admin', 'Type'), name : 'stock.typeid', mode : 'local', store : MShop.GlobalStoreMgr.get('Stock_Type', this.domain), displayField : 'stock.type.label', valueField : 'stock.type.id', forceSelection : true, triggerAction : 'all', typeAhead : true, listeners : { 'render' : { fn : function() { var record, index = this.store.find('stock.type.code', 'default'); if((record = this.store.getAt(index))) { this.setValue(record.id); } } } } }, { xtype : 'numberfield', fieldLabel : MShop.I18n.dt('admin', 'Stock level'), name : 'stock.stocklevel', emptyText : MShop.I18n.dt('admin', 'Quantity or empty if unlimited (optional)') }, { xtype : 'datefield', fieldLabel : MShop.I18n.dt('admin', 'Back in stock'), name : 'stock.dateback', format : 'Y-m-d H:i:s', emptyText : MShop.I18n.dt('admin', 'YYYY-MM-DD hh:mm:ss (optional)') }, { xtype : 'ordertime', fieldLabel : MShop.I18n.dt('admin', 'Stock Order Time'), name : 'stock.ordertime', emptyText : MShop.I18n.dt('admin', 'Stock Order Time') }, { xtype : 'displayfield', fieldLabel : MShop.I18n.dt('admin', 'Created'), name : 'stock.ctime' }, { xtype : 'displayfield', fieldLabel : MShop.I18n.dt('admin', 'Last modified'), name : 'stock.mtime' }, { xtype : 'displayfield', fieldLabel : MShop.I18n.dt('admin', 'Editor'), name : 'stock.editor' }] }] }] }] }]; MShop.panel.product.stock.ItemUi.superclass.initComponent.call(this); }, onSaveItem : function() { // validate data if(!this.mainForm.getForm().isValid() && this.fireEvent('validate', this) !== false) { Ext.Msg.alert(MShop.I18n.dt('admin', 'Invalid data'), MShop.I18n.dt('admin', 'Please recheck your data')); return; } this.saveMask.show(); this.isSaveing = true; // force record to be saved! this.record.dirty = true; if(this.fireEvent('beforesave', this, this.record) === false) { this.isSaveing = false; this.saveMask.hide(); } this.mainForm.getForm().updateRecord(this.record); this.record.data['stock.productcode'] = this.listUI.itemUi.record.data['product.code']; if(this.action == 'add' || this.action == 'copy') { this.store.add(this.record); } // store async action is triggered. {@see onStoreWrite/onStoreException} if(!this.store.autoSave) { this.onAfterSave(); } }, onStoreException : function() { this.store.remove(this.record); MShop.panel.product.stock.ItemUi.superclass.onStoreException.apply(this, arguments); } }); Ext.reg('MShop.panel.product.stock.itemui', MShop.panel.product.stock.ItemUi);
Code: Select all
/*! * LGPLv3, http://opensource.org/licenses/LGPL-3.0 * Copyright (c) Metaways Infosystems GmbH, 2011 * Copyright (c) Aimeos (aimeos.org), 2015-2017 */ Ext.ns('MShop.panel.product.stock'); MShop.panel.product.stock.ListUi = Ext.extend(MShop.panel.AbstractListUi, { recordName : 'Stock', idProperty : 'stock.id', siteidProperty : 'stock.siteid', itemUiXType : 'MShop.panel.product.stock.itemui', autoExpandColumn : 'product-stock-stocktype', filterConfig : { filters : [{ dataIndex : 'stock.type.label', operator : '=~', value : '' }] }, initComponent : function() { this.title = MShop.I18n.dt('admin', 'Stock'); MShop.panel.AbstractListUi.prototype.initActions.call(this); MShop.panel.AbstractListUi.prototype.initToolbar.call(this); MShop.panel.product.stock.ListUi.superclass.initComponent.call(this); }, afterRender : function() { this.itemUi = this.findParentBy(function(c) { return c.isXType(MShop.panel.AbstractItemUi, false); }); MShop.panel.product.stock.ListUi.superclass.afterRender.apply(this, arguments); }, onBeforeLoad : function(store, options) { this.setSiteParam(store); if(this.domain) { this.setDomainFilter(store, options); } options.params = options.params || {}; options.params.condition = { '&&' : [{ '==' : { 'stock.productcode' : this.itemUi.record ? this.itemUi.record.data['product.code'] : '' } }] }; }, getColumns : function() { this.typeStore = MShop.GlobalStoreMgr.get('Stock_Type'); return [ { xtype : 'gridcolumn', dataIndex : 'stock.id', header : MShop.I18n.dt('admin', 'ID'), sortable : true, width : 50, hidden : true }, { xtype : 'gridcolumn', dataIndex : 'stock.productcode', header : MShop.I18n.dt('admin', 'Product code'), width : 50, hidden : true }, { xtype : 'gridcolumn', dataIndex : 'stock.typeid', header : MShop.I18n.dt('admin', 'Type'), align : 'center', id : 'product-stock-stocktype', renderer : this.typeColumnRenderer.createDelegate(this, [ this.typeStore, "stock.type.label"], true) }, { xtype : 'gridcolumn', dataIndex : 'stock.stocklevel', header : MShop.I18n.dt('admin', 'Stock level'), sortable : true, align : 'center', width : 80 }, { xtype : 'datecolumn', dataIndex : 'stock.dateback', header : MShop.I18n.dt('admin', 'Date back'), format : 'Y-m-d H:i:s', sortable : true, width : 130 }, { xtype : 'ordertime', dataIndex : 'stock.ordertime', header : MShop.I18n.dt('admin', 'Order Time'), sortable : true, width : 130 }, { xtype : 'datecolumn', dataIndex : 'stock.ctime', header : MShop.I18n.dt('admin', 'Created'), format : 'Y-m-d H:i:s', sortable : true, width : 130, editable : false, hidden : true }, { xtype : 'datecolumn', dataIndex : 'stock.mtime', header : MShop.I18n.dt('admin', 'Last modified'), format : 'Y-m-d H:i:s', sortable : true, width : 130, editable : false, hidden : true }, { xtype : 'gridcolumn', dataIndex : 'stock.editor', header : MShop.I18n.dt('admin', 'Editor'), sortable : true, width : 130, editable : false, hidden : true }]; } }); Ext.reg('MShop.panel.product.stock.listui', MShop.panel.product.stock.ListUi); Ext.ux.ItemRegistry.registerItem('MShop.panel.product.ItemUi', 'MShop.panel.product.stock.listui', MShop.panel.product.stock.ListUi, 2);
Many Thanks and sorry for the long post
Typo3 7.6.x / Aimeos 17.10.0
Have you fixed your problem? I am facing an issue and have been struggling to fix it. Can you help me? I want to add a new field in Product form on Admin side.
Thanks!
Re: Extend Stock to Save a new Value
was in hollidays and not here sorry. ya, its working now. where do u have problems
Re: Extend Stock to Save a new Value
I have rewritten my code 3 times and now the situation is this... I am able to display value in my extra field but it is not saving in the DB and there are no errors . Please, look at my code and guide me!tenkraD wrote:was in hollidays and not here sorry. ya, its working now. where do u have problems
./ext/myextension/lib/custom/setup/default/schema/product.php
Code: Select all
return array(
'table' => array(
'mshop_product' => function ( \Doctrine\DBAL\Schema\Schema $schema ) {
// $table = $schema->createTable( 'mshop_price' );
$table = $schema->getTable( 'mshop_product' );
$table->addColumn( 'oldcode', 'string', array( 'length' => 32 ) );
$table->addIndex( array( 'siteid', 'oldcode' ), 'idx_msproty_sid_oldcode' );
return $schema;
}
)
);
Code: Select all
namespace Aimeos\MShop\Product\Item;
class Myproject extends Standard
{
private $myvalues;
public function __construct(array $values)
{
parent::__construct($values);
$this->myvalues = $values;
}
public function getOldCode()
{
if( isset( $this->myvalues['product.oldcode'] ) ) {
return (string) $this->myvalues['product.oldcode'];
}
return '';
}
public function setOldCode( $oldcode )
{
if ((string) $oldcode !== $this->getOldCode()) {
// exit("<br />616");
$this->myvalues['product.oldcode'] = (string) $oldcode;
$this->setModified();
}
return $this;
}
public function fromArray(array $list)
{
$unknown = [];
$list = parent::fromArray($list);
foreach ($list as $key => $value) {
switch ($key) {
case 'product.oldcode':
$this->setOldCode($value);
break;
default:
$unknown[$key] = $value;
}
}
// exit("<br />617");
return $unknown;
}
public function toArray( $private = false )
{
$list = parent::toArray( $private );
if( $private === true ) {
$list['product.oldcode'] = $this->getOldCode();
}
return $list;
}
}
Code: Select all
namespace Aimeos\MShop\Product\Manager;
class Myproject extends Standard
{
private $searchConfig = array(
'product.oldcode'=> array(
'code'=>'product.oldcode',
'internalcode'=>'mpro."oldcode"',
'label'=>'Product oldcode',
'type'=> 'string', // integer, float, etc.
'internaltype'=> \Aimeos\MW\DB\Statement\Base::PARAM_STR, // _INT, _FLOAT, etc.
),
);
public function saveItem(\Aimeos\MShop\Common\Item\Iface $item, $fetch = true)
{
$iface = '\\Aimeos\\MShop\\Product\\Item\\Iface';
if (! ($item instanceof $iface)) {
throw new \Aimeos\MShop\Product\Exception(sprintf('Object is not of required type "%1$s"', $iface));
}
if (!$item->isModified()) {
return $item;
}
$context = $this->getContext();
$dbm = $context->getDatabaseManager();
$dbname = $this->getResourceName();
$conn = $dbm->acquire( $dbname );
try {
$id = $item->getId();
$date = date('Y-m-d H:i:s');
if ($id === null) {
$path = 'mshop/product/manager/standard/insert';
} else {
$path = 'mshop/product/manager/standard/update';
}
$stmt = $this->getCachedStatement($conn, $path);
$stmt->bind(1, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
$stmt->bind(2, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
$stmt->bind(3, $item->getCode());
$stmt->bind(4, $item->getLabel());
$stmt->bind(5, json_encode($item->getConfig()));
$stmt->bind(6, $item->getDateStart());
$stmt->bind(7, $item->getDateEnd());
$stmt->bind(8, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
$stmt->bind(9, $date); // mtime
$stmt->bind(10, $context->getEditor());
$stmt->bind(11, $item->getTarget());
$stmt->bind(12, $item->getOldCode());
if( $id !== null ) {
$stmt->bind( 13, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
$item->setId( $id ); //so item is no longer modified
} else {
$stmt->bind( 13, $date ); // ctime
}
$stmt->execute()->finish();
if( $id === null && $fetch === true )
{
$path = 'mshop/product/manager/standard/newid';
$item->setId( $this->newId( $conn, $path ) );
}
$dbm->release( $conn, $dbname );
} catch (\Exception $e) {
$dbm->release( $conn, $dbname );
throw $e;
}
return $item;
}
public function getSearchAttributes( $withsub = true )
{
$list = parent::getSearchAttributes( $withsub );
foreach( $this->searchConfig as $key => $fields ) {
$list[$key] = new \Aimeos\MW\Criteria\Attribute\Standard( $fields );
}
return $list;
}
protected function createItemBase(array $values = [], array $listitems = [],
array $refItems = [], array $propertyItems = [])
{
return new \Aimeos\MShop\Product\Item\Myproject($values, $listitems, $refItems, $propertyItems);
}
}
./ext/myextension/lib/custom/config/mshop.php
Code: Select all
return [
'product' => [
'manager' => [
'name' => 'Myproject',
'standard' => [
'insert' => array(
'ansi' => '
INSERT INTO "mshop_product" (
"typeid", "siteid", "code", "label", "config", "start", "end",
"status", "mtime", "editor", "target", "ctime", "oldcode"
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
)
'
),
'update' => array(
'ansi' => '
UPDATE "mshop_product"
SET "typeid" = ?, "code" = ?, "label" = ?, "status" = ?,
"start" = ?, "end" = ?, "config" = ?, "mtime" = ?, "editor" = ?, "target" = ?, "oldcode" = ?
WHERE "siteid" = ? AND "id" = ?
'
),
'search' => array(
'ansi' => '
SELECT mpro."id" AS "product.id", mpro."siteid" AS "product.siteid",
mpro."typeid" AS "product.typeid", mpro."code" AS "product.code",
mpro."label" AS "product.label", mpro."config" AS "product.config",
mpro."start" AS "product.datestart", mpro."end" AS "product.dateend",
mpro."status" AS "product.status", mpro."ctime" AS "product.ctime",
mpro."mtime" AS "product.mtime", mpro."editor" AS "product.editor",
mpro."target" AS "product.target",
mpro."oldcode" AS "product.oldcode"
FROM "mshop_product" AS mpro
:joins
WHERE :cond
GROUP BY mpro."id", mpro."siteid", mpro."typeid", mpro."code",
mpro."label", mpro."config", mpro."start", mpro."end",
mpro."status", mpro."ctime", mpro."mtime", mpro."editor",
mpro."target", mpro."oldcode"
/*-columns*/ , :columns /*columns-*/
/*-orderby*/ ORDER BY :order /*orderby-*/
LIMIT :size OFFSET :start
'
),
'count' => array(
'ansi' => '
SELECT COUNT(*) AS "count"
FROM (
SELECT DISTINCT mpro."id"
FROM "mshop_product" AS mpro
:joins
WHERE :cond
LIMIT 10000 OFFSET 0
) AS list
'
),
'newid' => array(
'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
'mysql' => 'SELECT LAST_INSERT_ID()',
'oracle' => 'SELECT mshop_product_seq.CURRVAL FROM DUAL',
'pgsql' => 'SELECT lastval()',
'sqlite' => 'SELECT last_insert_rowid()',
'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
'sqlanywhere' => 'SELECT @@IDENTITY',
),
],
],
],
];
Thanks!
Re: Extend Stock to Save a new Value
Looks good but i see 2 differences,
1. I created my extension with the extensionbuilder https://aimeos.org/developer/extensions/ and got another directory structur as you. In the extensionbuilder i have select "Typo3 2018.x Extension" because im using the 2018 Aimeos Extension in Typo3. Perhaps this is making u some problems, dont really know.
2. I extended the standard Iface that my new functions from Item.php in Manager.php can be used.
Create src/MShop/Product/Item/Myiface.php
2b. In Manager in the saveItem function use ure new Iface "Myiface"
src/MShop/Product/Manager/Myproject.php
1. I created my extension with the extensionbuilder https://aimeos.org/developer/extensions/ and got another directory structur as you. In the extensionbuilder i have select "Typo3 2018.x Extension" because im using the 2018 Aimeos Extension in Typo3. Perhaps this is making u some problems, dont really know.
2. I extended the standard Iface that my new functions from Item.php in Manager.php can be used.
Create src/MShop/Product/Item/Myiface.php
Code: Select all
<?php
interface Myiface extends Iface
{
public function getOldCode();
public function setOldCode( $oldcode );
}
src/MShop/Product/Manager/Myproject.php
Code: Select all
public function saveItem(\Aimeos\MShop\Common\Item\Iface $item, $fetch = true)
{
$iface = '\\myextension\\lib\\custom\\src\\MShop\\Product\\Item\\Myiface';
.......
.......
}
Last edited by tenkraD on 03 Apr 2018, 12:03, edited 2 times in total.
Re: Extend Stock to Save a new Value
Thanks to Almighty Allah, I have solved my issue. Complete solution can be found on following link: post5939.html#p5939
Thanks!
Thanks!
Re: Extend Stock to Save a new Value
Yes, it was nice for moments until I see that it has somehow stopped saving some other data for product. For example, it is not saving Product images. I wonder what is the connection? I guess I have to extend those classes also, which is too dumb.tenkraD wrote:Nice
Can you guide me with this?
Thanks!
Re: Extend Stock to Save a new Value
Im a bit in hurry and have not much time to look at ure code. But the master jedi alias "Administrator" surely knows some help.
I saw just one thing: In ure manager in createItemBase change $listitems to $listItems.
Cya and good luck
I saw just one thing: In ure manager in createItemBase change $listitems to $listItems.
Cya and good luck