Page 2 of 3

Re: Extend Stock to Save a new Value

Posted: 06 Apr 2018, 14:12
by tenkraD
Hi all and hi Administrator,

after i installed the newest aimeos 18.1.1 typo 3 extension i got a problem with my template.
I see you use vue.js now, so i edited my template.

I changed the template files name from default to standard and I added the new key and copied the form line but i cant see the data ordertime in in data items stockdata. I just get a blank form and this error message, maybe someone knows some help that would be awesome.

Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/admin/jqadm/templates/product/item-stock-standard.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', [] );

//$keys = ['stock.id', 'stock.siteid', 'stock.typeid', 'stock.stocklevel', 'stock.dateback'];
/** New Stock Var Ordertime - AZ **/
$keys = ['stock.id', 'stock.siteid', 'stock.typeid', 'stock.stocklevel', 'stock.dateback', 'stock.ordertime'];
/** New Stock Var Ordertime - AZ **/

?>
<div id="stock" class="item-stock content-block tab-pane fade" role="tabpanel" aria-labelledby="stock">

	<table class="stock-list table table-default"
		data-items="<?= $enc->attr( json_encode( $this->get( 'stockData', [] ) ) ); ?>"
		data-keys="<?= $enc->attr( json_encode( $keys ) ) ?>"
		data-prefix="stock."
		data-siteid="<?= $this->site()->siteid() ?>"
		data-numtypes="<?= count( $stockTypes ) ?>" >

		<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', '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="actions">
					<div v-if="(items['stock.id'] || []).length < numtypes" class="btn act-add fa" tabindex="<?= $this->get( 'tabindex' ); ?>"
						title="<?= $enc->attr( $this->translate( 'admin', 'Insert new entry (Ctrl+I)') ); ?>"
						v-on:click="addItem()">
					</div>
				</th>
			</tr>
		</thead>
		<tbody>

			<tr v-for="(id, idx) in items['stock.id']" v-bind:key="idx" class="stock-row">
				<?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', '' ) ) ); ?>"
							v-bind:readonly="checkSite('stock.siteid', idx)"
							v-model="items['stock.typeid'][idx]" >

							<option value="" disable>
								<?= $enc->html( $this->translate( 'admin', 'Please select' ) ); ?>
							</option>

							<?php foreach( $stockTypes as $typeId => $typeItem ) : ?>
								<option value="<?= $enc->attr( $typeId ); ?>" v-bind:selected="items['stock.typeid'][idx] == '<?= $enc->attr( $typeId ) ?>'">
									<?= $enc->html( $typeItem->getLabel() ) ?>
								</option>
							<?php endforeach; ?>
						</select>
					</td>
				<?php else : ?>
					<input class="item-typeid" type="hidden"
						name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>"
						value="<?= $enc->attr( key( $stockTypes ) ); ?>" />
				<?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', '' ) ) ); ?>"
						v-bind:readonly="checkSite('stock.siteid', idx)"
						v-model="items['stock.stocklevel'][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', '' ) ) ); ?>"
						placeholder="<?= $enc->attr( $this->translate( 'admin', 'YYYY-MM-DD hh:mm:ss (optional)' ) ); ?>"
						v-bind:readonly="checkSite('stock.siteid', idx)"
						v-model="items['stock.dateback'][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', '' ) ) ); ?>"
						placeholder="<?= $enc->attr( $this->translate( 'admin', 'Order Time' ) ); ?>"
						v-bind:readonly="checkSite('stock.siteid', idx)"
						v-model="items['stock.ordertime'][idx]" />

				</td>

				
				<td class="actions">
					<input class="item-id" type="hidden" v-model="items['stock.id'][idx]"
						name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.id', '' ) ) ); ?>" />

					<div v-if="!checkSite('stock.siteid', idx)" class="btn act-delete fa" tabindex="<?= $this->get( 'tabindex' ); ?>"
						title="<?= $enc->attr( $this->translate( 'admin', 'Delete this entry') ); ?>"
						v-on:click.stop="removeItem(idx)">
					</div>
				</td>
			</tr>

		</tbody>
	</table>

	<?= $this->get( 'stockBody' ); ?>

</div>
Error message:

Code: Select all

VM4115 vue.min.js:6 TypeError: Cannot read property '0' of undefined
    at eval (eval at wi (VM4067 vue.min.js:6), <anonymous>:2:2534)
    at Ot.et [as _l] (VM4067 vue.min.js:6)
    at Ot.eval (eval at wi (VM4067 vue.min.js:6), <anonymous>:2:949)
    at Ot.e._render (VM4067 vue.min.js:6)
    at Ot.r (VM4067 vue.min.js:6)
    at Uo.get (VM4067 vue.min.js:6)
    at new Uo (VM4067 vue.min.js:6)
    at Se (VM4067 vue.min.js:6)
    at Ot.$mount (VM4067 vue.min.js:6)
    at Ot.$mount (VM4067 vue.min.js:6)
Do you know what im doing wrong?
Thanks in advance

Re: Extend Stock to Save a new Value

Posted: 06 Apr 2018, 17:37
by nos3
Vue.JS error messages are no help in general if there's something in the template but your template file seems to be OK.

If "stock.ordertime" isn't available in the JSON of the "data-items" attribute, there's something wrong before, maybe your item doesn't return it in toArray() which might be caused by your item class isn't used that may be due to your manager isn't configured or something like that.

Re: Extend Stock to Save a new Value

Posted: 06 Apr 2018, 23:35
by tenkraD
thanks nos3, strange the manager and item worked before i update the aimeos. i will do some testing and debug on sunnday.

bye tenkraD

Re: Extend Stock to Save a new Value

Posted: 10 Apr 2018, 17:19
by tenkraD
Hi all hi Administrator,

what can i do if the new value isnt avaible in save function of the manager.
Getter Function of Item Class works, but the setter sems not.
In manager Class on saveItem() Function i call $stmt->bind( 1, $item->getOrderTime() ); and getOrderTime gets me always the old value back.

Thank You

Re: Extend Stock to Save a new Value

Posted: 11 Apr 2018, 07:37
by aimeos
I think, your new value isn't set in the item there:
https://github.com/aimeos/ai-admin-jqad ... d.php#L307

Re: Extend Stock to Save a new Value

Posted: 11 Apr 2018, 10:43
by tenkraD
I dont get it, it doesn't work.

I forget to post it but i had edited this file but with no result.
I created it under
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/admin/jqadm/src/Admin/JQAdm/Product/Stock/Standard.php

Code: Select all

	/**
	 * Creates new and updates existing items using the data array
	 *
	 * @param \Aimeos\MShop\Product\Item\Iface $item Product item object without referenced domain items
	 * @param string[] $data Data array
	 */
	protected function fromArray( \Aimeos\MShop\Product\Item\Iface $item, array $data )
	{
		.....

		foreach( $list as $idx => $id )
		{
			if( !isset( $stockItems[$id] ) ) {
				$stockItem = $manager->createItem();
			} else {
				$stockItem = $stockItems[$id];
			}

			$stockItem->setProductCode( $item->getCode() );
			$stockItem->setTypeId( $this->getValue( $data, 'stock.typeid/' . $idx ) );
			$stockItem->setStocklevel( $this->getValue( $data, 'stock.stocklevel/' . $idx ) );
			$stockItem->setDateBack( $this->getValue( $data, 'stock.dateback/' . $idx ) );
			
			// Get new value and set Order Time
			$stockItem->setOrderTime( $this->getValue( $data, 'stock.ordertime/' . $idx ) );

			$manager->saveItem( $stockItem, false );
		}
	}
Do i have to register the file "myext/mhaimeos/admin/jqadm/src/Admin/JQAdm/Product/Stock/Standard.php" somewhere?

Thank ya admin

Re: Extend Stock to Save a new Value

Posted: 11 Apr 2018, 17:46
by nos3
You can't name your class "Standard" like the default one. You have to give it a different name and configure it using
https://aimeos.org/docs/Configuration/C ... stock/name

Re: Extend Stock to Save a new Value

Posted: 11 Apr 2018, 19:19
by tenkraD
Nos3 ure great, that was it!

Thanks all helpers, its now working fine.



------------------------------- Working Solution of Extending Stock -----------------------------------------------

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...

-------------------------------------------------------------------------------------------------------------


I created an Typo3 2018.x extension named "mhaimeos" with aimeos extensionbuilder https://aimeos.org/developer/extensions/.

Extend Stock Schema
Documentation: https://aimeos.org/docs/Developers/Libr ... ing_tables
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/lib/custom/setup/default/schema/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;
		},
	),
);
Extend Stock Item
Documentation: https://aimeos.org/docs/Developers/Libr ... tems#Items
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
 * @copyright A. Zumstein
 * @package MShop
 * @subpackage Stock
 */

namespace Aimeos\MShop\Stock\Item;
 
class Mystandard 
	extends \Aimeos\MShop\Stock\Item\Standard
	implements \Aimeos\MShop\Stock\Item\Myiface
	//implements Myiface
{
    private $values;
 
    public function __construct( array $values )
    {
        //parent::__construct( 'stock.', $values );
    	parent::__construct( $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;
    }
}
The Items Iface, but this is propably not needed. Dont tested it without it.
Extend Stock Item Iface
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;


/**
 * Extends Default stock item interface.
 *
 * @package MShop
 * @subpackage Stock
 */
interface Myiface extends \Aimeos\MShop\Stock\Item\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 );

}
Extend Stock Manager
Documentation: https://aimeos.org/docs/Developers/Libr ... s#Managers
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
 * @copyright A. Zumstein
 * @package MShop
 * @subpackage Stock
 */

namespace Aimeos\MShop\Stock\Manager;
 
class Mystandard 
	extends \Aimeos\MShop\Stock\Manager\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 = '\\Aimeos\\MShop\\Stock\\Item\\Myiface';
        //$iface = '\\Mhaimeos\\MShop\\Stock\\Item\\Iface';
    	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;
    		//throw new \Aimeos\MShop\Stock\Exception( sprintf( 'Item isnt modified' ) );
    		 
    	}    	 
    	$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';
    			//throw new \Aimeos\MShop\Stock\Exception( sprintf( 'try 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';
    			//throw new \Aimeos\MShop\Stock\Exception( sprintf( 'try update' ) );
    		}
    	
    		//throw new \Aimeos\MShop\Stock\Exception( sprintf( 'Item is "%s"', $item->getOrderTime() ) );
    		$stmt = $this->getCachedStatement( $conn, $path );
    	
    		//  GET the Order Time
    		$stmt->bind( 1, $item->getOrderTime() );
    		
    		
    		$stmt->bind( 2, $item->getProductCode() );
    		$stmt->bind( 3, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
    		$stmt->bind( 4, $item->getStocklevel(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
    		$stmt->bind( 5, $item->getDateBack() );

    		
    		$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 \Aimeos\MShop\Stock\Item\Mystandard( $values );
    }
}

Config for Manager and Item
Documentation: https://aimeos.org/docs/Developers/Libr ... figuration
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/config/mshop.php

Code: Select all

<?php

/**
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
* @copyright Aimeos (aimeos.org), 2015-2017
*/


return [
		'stock' => [
				'manager' => [
						'name' => 'Mystandard',						
						'standard' => [
								'insert' => [
										'ansi' => '
											INSERT INTO "mshop_stock" (
												 "ordertime", "productcode", "typeid", "stocklevel", "backdate",
												"mtime", "editor", "siteid", "ctime"
											) VALUES (
												?, ?, ?, ?, ?, ?, ?, ?, ?
											)
										'
								],
								'update' => [
										'ansi' => '
											UPDATE "mshop_stock"
											SET "ordertime" = ?, "productcode" = ?, "typeid" = ?, "stocklevel" = ?,
												"backdate" = ?, "mtime" = ?, "editor" = ?
											WHERE "siteid" = ? AND "id" = ?
										'
								],
								'search' => [
										'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
										'
								],
						],
				],
		],
];
Backend Product Stock Template
Path:Canonical Path /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/admin/jqadm/templates/product/item-stock-ordertime.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', [] );

//$keys = ['stock.id', 'stock.siteid', 'stock.typeid', 'stock.stocklevel', 'stock.dateback'];
/** New Stock Var Ordertime - AZ **/
$keys = ['stock.id', 'stock.siteid', 'stock.typeid', 'stock.stocklevel', 'stock.dateback', 'stock.ordertime'];
/** New Stock Var Ordertime - AZ **/

?>
<div id="stock" class="item-stock content-block tab-pane fade" role="tabpanel" aria-labelledby="stock">

	<table class="stock-list table table-default"
		data-items="<?= $enc->attr( json_encode( $this->get( 'stockData', [] ) ) ); ?>"
		data-keys="<?= $enc->attr( json_encode( $keys ) ) ?>"
		data-prefix="stock."
		data-siteid="<?= $this->site()->siteid() ?>"
		data-numtypes="<?= count( $stockTypes ) ?>" >

		<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', '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="actions">
					<div v-if="(items['stock.id'] || []).length < numtypes" class="btn act-add fa" tabindex="<?= $this->get( 'tabindex' ); ?>"
						title="<?= $enc->attr( $this->translate( 'admin', 'Insert new entry (Ctrl+I)') ); ?>"
						v-on:click="addItem()">
					</div>
				</th>
			</tr>
		</thead>
		<tbody>

			<tr v-for="(id, idx) in items['stock.id']" v-bind:key="idx" class="stock-row">
				<?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', '' ) ) ); ?>"
							v-bind:readonly="checkSite('stock.siteid', idx)"
							v-model="items['stock.typeid'][idx]" >

							<option value="" disable>
								<?= $enc->html( $this->translate( 'admin', 'Please select' ) ); ?>
							</option>

							<?php foreach( $stockTypes as $typeId => $typeItem ) : ?>
								<option value="<?= $enc->attr( $typeId ); ?>" v-bind:selected="items['stock.typeid'][idx] == '<?= $enc->attr( $typeId ) ?>'">
									<?= $enc->html( $typeItem->getLabel() ) ?>
								</option>
							<?php endforeach; ?>
						</select>
					</td>
				<?php else : ?>
					<input class="item-typeid" type="hidden"
						name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.typeid', '' ) ) ); ?>"
						value="<?= $enc->attr( key( $stockTypes ) ); ?>" />
				<?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', '' ) ) ); ?>"
						v-bind:readonly="checkSite('stock.siteid', idx)"
						v-model="items['stock.stocklevel'][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', '' ) ) ); ?>"
						placeholder="<?= $enc->attr( $this->translate( 'admin', 'YYYY-MM-DD hh:mm:ss (optional)' ) ); ?>"
						v-bind:readonly="checkSite('stock.siteid', idx)"
						v-model="items['stock.dateback'][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', '' ) ) ); ?>"
						placeholder="<?= $enc->attr( $this->translate( 'admin', 'Order Time' ) ); ?>"
						v-bind:readonly="checkSite('stock.siteid', idx)"
						v-model="items['stock.ordertime'][idx]" />

				</td>

				
				<td class="actions">
					<input class="item-id" type="hidden" v-model="items['stock.id'][idx]"
						name="<?= $enc->attr( $this->formparam( array( 'stock', 'stock.id', '' ) ) ); ?>" />

					<div v-if="!checkSite('stock.siteid', idx)" class="btn act-delete fa" tabindex="<?= $this->get( 'tabindex' ); ?>"
						title="<?= $enc->attr( $this->translate( 'admin', 'Delete this entry') ); ?>"
						v-on:click.stop="removeItem(idx)">
					</div>
				</td>
			</tr>

		</tbody>
	</table>

	<?= $this->get( 'stockBody' ); ?>

</div>

Product stock JQAdm client
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/admin/jqadm/src/Admin/JQAdm/Product/Stock/Mystandard.php

Code: Select all

<?php

/**
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
 * @copyright Aimeos (aimeos.org), 2015-2017
 * @package Admin
 * @subpackage JQAdm
 */


namespace Aimeos\Admin\JQAdm\Product\Stock;

sprintf( 'stock' ); // for translation


/**
 * Default implementation of product stock JQAdm client.
 *
 * @package Admin
 * @subpackage JQAdm
 */
class Mystandard
	extends \Aimeos\Admin\JQAdm\Product\Stock\Standard
{

	/**
	 * Creates new and updates existing items using the data array
	 *
	 * @param \Aimeos\MShop\Product\Item\Iface $item Product item object without referenced domain items
	 * @param string[] $data Data array
	 */
	protected function fromArray( \Aimeos\MShop\Product\Item\Iface $item, array $data )
	{
		$manager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'stock' );

		$search = $manager->createSearch();
		$search->setConditions( $search->compare( '==', 'stock.productcode', $item->getCode() ) );
		$stockItems = $manager->searchitems( $search );

		$list = (array) $this->getValue( $data, 'stock.id', [] );

		$manager->deleteItems( array_diff( array_keys( $stockItems ), $list ) );

		foreach( $list as $idx => $id )
		{
			if( !isset( $stockItems[$id] ) ) {
				$stockItem = $manager->createItem();
			} else {
				$stockItem = $stockItems[$id];
			}

			$stockItem->setProductCode( $item->getCode() );
			$stockItem->setTypeId( $this->getValue( $data, 'stock.typeid/' . $idx ) );
			$stockItem->setStocklevel( $this->getValue( $data, 'stock.stocklevel/' . $idx ) );
			$stockItem->setDateBack( $this->getValue( $data, 'stock.dateback/' . $idx ) );
			$stockItem->setOrderTime( $this->getValue( $data, 'stock.ordertime/' . $idx ) );
			$manager->saveItem( $stockItem, false );
		}
	}
	/**
	 * Returns the rendered template including the view data
	 *
	 * @param \Aimeos\MW\View\Iface $view View object with data assigned
	 * @return string HTML output
	 */
	protected function render( \Aimeos\MW\View\Iface $view )
	{
		/** admin/jqadm/product/stock/template-item
		 * Relative path to the HTML body template of the stock subpart for products.
		 *
		 * The template file contains the HTML code and processing instructions
		 * to generate the result shown in the body of the frontend. The
		 * configuration string is the path to the template file relative
		 * to the templates directory (usually in admin/jqadm/templates).
		 *
		 * You can overwrite the template file configuration in extensions and
		 * provide alternative templates. These alternative templates should be
		 * named like the default one but with the string "default" replaced by
		 * an unique name. You may use the name of your project for this. If
		 * you've implemented an alternative client class as well, "default"
		 * should be replaced by the name of the new class.
		 *
		 * @param string Relative path to the template creating the HTML code
		 * @since 2016.04
		 * @category Developer
		 */
		$tplconf = 'admin/jqadm/product/stock/template-item';
		$default = 'product/item-stock-ordertime.php';
	
		return $view->render( $view->config( $tplconf, $default ) );
	}
}
Configuration for the Jqadmin Client Mystandard
Documentation: https://aimeos.org/docs/Configuration/C ... stock/name
Path: /typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/config/admin.php

Code: Select all

<?php

return [
	'jqadm' => [
	   'product' => [
	       'stock' => [
	           'name' => 'Mystandard'
           ]
	   ]
	],
	'jsonadm' => [
	],
];

Many Thanks for all the Help
Typo3 7.6.x / Aimeos 18.x / PHP 7.1

Re: Extend Stock (Solved)

Posted: 12 Apr 2018, 11:25
by aimeos
You should (!) only add the configuration and code you overwrite and remove the things that are the same as in the core. Especially in the configuration file (SQL statements that are the same as in the core file) and in the admin client (which should contain only the overwritten method and nothing else).

The setting for configuring your new admin client class is in general

Code: Select all

admin/jqadm/product/stock/name = Mystandard
and documentation can be found here:
https://aimeos.org/docs/Configuration/C ... stock/name

Re: Extend Stock (Solved)

Posted: 12 Apr 2018, 19:50
by tenkraD
aimeos wrote:You should (!) only add the configuration and code you overwrite and remove the things that are the same as in the core. Especially in the configuration file (SQL statements that are the same as in the core file) and in the admin client (which should contain only the overwritten method and nothing else).

The setting for configuring your new admin client class is in general

Code: Select all

admin/jqadm/product/stock/name = Mystandard
and documentation can be found here:
https://aimeos.org/docs/Configuration/C ... stock/name
Accepted i updated the post above.
Just adding code i overwrite is not working for the file
/typo3conf/ext/mhaimeos/Resources/Private/Extensions/mhaimeos/admin/jqadm/src/Admin/JQAdm/Product/Stock/Mystandard.php. Why?

Thanks admin