How to configure and adapt Aimeos based shops as developer
Forum rules: Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
#5991 by aimeos
09 Apr 2018, 08:08
Also looks OK. Now you have to debug the files mentioned, especially the Factory.php. Tried to reconfigure the price manager myself and it worked like expected.
#5995 by mohal_04
09 Apr 2018, 09:56
aimeos wrote:Also looks OK. Now you have to debug the files mentioned, especially the Factory.php. Tried to reconfigure the price manager myself and it worked like expected.


Hi,

Thanks for the tips! Debugging inside Factory.php and PHPArray.php, I am able to see that my Manager is being loaded, which is a good thing. At least, it has been recognized.

But the Million Dollar question still there. If manager is being loaded then why is it not working. :'(

Any more places I can debug?

Thanks!
#5996 by mohal_04
09 Apr 2018, 12:43
aimeos wrote:Also looks OK. Now you have to debug the files mentioned, especially the Factory.php. Tried to reconfigure the price manager myself and it worked like expected.


Laravel: 5.6
Aimeos: 2017.10


Hello,

Thanks for being available and replying to my questions.

The so far progress is this that value of new custom field is retrieving from DB but it is not saving in the DB. Can you look at my code once again and see what am I doing wrong. I think there is something wrong in insert and update queries...

./ext/myextension/lib/custom/src/MShop/Price/Item/Custompricefields.php
Code: Select allnamespace Aimeos\MShop\Price\Item;
 
class Custompricefields extends Standard
{
    private $myvalues;
 
    public function __construct(array $values, array $listItems, array $refItems)
    {
        parent::__construct($values, $listItems, $refItems);
        $this->myvalues = $values;
    }
 
    public function getMinimumAdvertisedPrice()
    {
        if (isset($this->myvalues['price.minimumadvertisedprice'])) {
            return (string) $this->myvalues['price.minimumadvertisedprice'];
        }
        return '';
    }
 
    public function setMinimumAdvertisedPrice($minimumadvertisedprice)
    {
        if ((string) $minimumadvertisedprice !== $this->getMinimumAdvertisedPrice()) {
            $this->myvalues['price.minimumadvertisedprice'] = (string) $minimumadvertisedprice;
            $this->setModified();
        }
        return $this;
    }
 
    public function fromArray(array $list)
    {
        $unknown = [];
        $list = parent::fromArray($list);

        foreach ($list as $key => $value) {
            switch ($key) {
                case 'price.minimumadvertisedprice':
                    $this->setMinimumAdvertisedPrice($value);
                    break;
                default:
                    $unknown[$key] = $value;
            }
        }
        return $unknown;
    }
 
    public function toArray($private = false)
    {
        $list = parent::toArray($private);
        if ($private === true) {
            $list['price.minimumadvertisedprice'] = $this->getMinimumAdvertisedPrice();
        }
        return $list;
    }
}


./ext/myextension/lib/custom/src/MShop/Price/Manager/Custompricefields.php
Code: Select allnamespace Aimeos\MShop\Price\Manager;
 
class Custompricefields extends Standard
{
    private $searchConfig = array(
        'price.minimumadvertisedprice' => array(
            'code' => 'price.minimumadvertisedprice',
            'internalcode' => 'mpri."minimumadvertisedprice"',
            'label' => 'Minimum Advertised Price',
            'type' => 'float', // integer, string, etc.
            'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT, // _INT, _STR, etc.
        )
    );
 
    public function saveItem(\Aimeos\MShop\Common\Item\Iface $item, $fetch = true)
    {
        $iface = '\\Aimeos\\MShop\\Price\\Item\\Iface';
        if( !( $item instanceof $iface ) ) {
            throw new \Aimeos\MShop\Price\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/price/manager/standard/insert';
            } else {
                $path = 'mshop/price/manager/standard/update';
            }
            $stmt = $this->getCachedStatement($conn, $path);

            $stmt->bind(1, $item->getMinimumAdvertisedPrice());
            $stmt->bind(2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(3, $item->getCurrencyId());
            $stmt->bind(4, $item->getDomain());
            $stmt->bind(5, $item->getLabel());
            $stmt->bind(6, $item->getQuantity(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(7, $item->getValue());
            $stmt->bind(8, $item->getCosts());
            $stmt->bind(9, $item->getRebate());
            $stmt->bind(10, $item->getTaxRate());
            $stmt->bind(11, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(12, $date); //mtime
            $stmt->bind(13, $context->getEditor());
            $stmt->bind(14, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            if ($id !== null) {
                $stmt->bind(15, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT);
                $item->setId($id);
            } else {
                $stmt->bind(15, $date); //ctime
            }
         $stmt->execute()->finish();
            if ($id === null && $fetch === true) {
                $path = 'mshop/price/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 = [])
    {
        return new \Aimeos\MShop\Price\Item\Custompricefields($values, $listitems, $refItems);
    }
}



./ext/myextension/lib/custom/config/mshop.php
Code: Select allreturn [
    'product' => [
        'manager' => [
            'name' => 'Abc',
            'standard' => [
            'insert' => array(
               'ansi' => '
                  INSERT INTO "mshop_product" (
                     "countryoforigin", "oldcode", "typeid", "code", "label", "status", "start", "end",
                     "config", "mtime", "editor", "target", "siteid", "ctime"
                  ) VALUES (
                     ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                  )
               '
            ),
            'update' => array(
               'ansi' => '
                  UPDATE "mshop_product"
                  SET "countryoforigin" = ?, "oldcode" = ?, "typeid" = ?, "code" = ?, "label" = ?, "status" = ?,
                     "start" = ?, "end" = ?, "config" = ?, "mtime" = ?, "editor" = ?, "target" = ?
                  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",
                     mpro."countryoforigin" AS "product.countryoforigin"
                  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", mpro."countryoforigin"
                     /*-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',
            ),
            ],
        ],
    ],
    'price' => [
        'manager' => [
            'name' => 'Custompricefields',
            'standard' => [
            'delete' => array(
               'ansi' => '
                  DELETE FROM "mshop_price"
                  WHERE :cond AND siteid = ?
               '
            ),
            'insert' => array(
               'ansi' => '
                  INSERT INTO "mshop_price" (
                     "minimumadvertisedprice", "typeid", "currencyid", "domain", "label",
                     "quantity", "value", "costs", "rebate", "taxrate",
                     "status", "mtime", "editor", "siteid", "ctime"
                  ) VALUES (
                     ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                  )
               '
            ),
            'update' => array(
               'ansi' => '
                  UPDATE "mshop_price"
                  SET "minimumadvertisedprice" = ?, "typeid" = ?, "currencyid" = ?, "domain" = ?, "label" = ?,
                     "quantity" = ?, "value" = ?, "costs" = ?, "rebate" = ?,
                     "taxrate" = ?, "status" = ?, "mtime" = ?, "editor" = ?
                  WHERE "siteid" = ? AND "id" = ?
               '
            ),
            'search' => array(
               'ansi' => '
                  SELECT mpri."id" AS "price.id", mpri."siteid" AS "price.siteid",
                     mpri."typeid" AS "price.typeid", mpri."currencyid" AS "price.currencyid",
                     mpri."domain" AS "price.domain", mpri."label" AS "price.label",
                     mpri."quantity" AS "price.quantity", mpri."value" AS "price.value",
                     mpri."costs" AS "price.costs", mpri."rebate" AS "price.rebate",
                     mpri."taxrate" AS "price.taxrate", mpri."status" AS "price.status",
                     mpri."mtime" AS "price.mtime", mpri."editor" AS "price.editor",
                     mpri."ctime" AS "price.ctime",
                     mpri."minimumadvertisedprice" AS "price.minimumadvertisedprice"
                  FROM "mshop_price" AS mpri
                  :joins
                  WHERE :cond
                  GROUP BY mpri."id", mpri."siteid", mpri."typeid", mpri."currencyid",
                     mpri."domain", mpri."label", mpri."quantity", mpri."value",
                     mpri."costs", mpri."rebate", mpri."taxrate", mpri."status",
                     mpri."mtime", mpri."editor", mpri."ctime", mpri."minimumadvertisedprice"
                     /*-columns*/ , :columns /*columns-*/
                  /*-orderby*/ ORDER BY :order /*orderby-*/
                  LIMIT :size OFFSET :start
               '
            ),
            'count' => array(
               'ansi' => '
                  SELECT COUNT(*) AS "count"
                  FROM (
                     SELECT DISTINCT mpri."id"
                     FROM "mshop_price" AS mpri
                     :joins
                     WHERE :cond
                     LIMIT 10000 OFFSET 0
                  ) AS list
               '
            ),
            'newid' => array(
               'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
               'mysql' => 'SELECT LAST_INSERT_ID()',
               'oracle' => 'SELECT mshop_price_seq.CURRVAL FROM DUAL',
               'pgsql' => 'SELECT lastval()',
               'sqlite' => 'SELECT last_insert_rowid()',
               'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
               'sqlanywhere' => 'SELECT @@IDENTITY',
            ),
            ],
        ],
    ],
];


Can you please again check out what is wrong in my code? SELECT query is workin' fine but INSERT and UPDATE queries are not working. I had the same issue when I was working on extending Product Manager but at that time it was Item class's __construct() method's parameter issue but this time I have rechecked and __construct() parameter are same as parent class.

Please, reply ASAP!

Thanks!
#5998 by aimeos
10 Apr 2018, 07:06
If saving doensn't work, please check:
- Is the new valule available in saveItem() of the manager
- Is the new value set in fromArray() of the item
- Is the new value available in fromArray() of the admin client
- Is the new value passed correctly in the template
#5999 by mohal_04
10 Apr 2018, 09:14
aimeos wrote:If saving doensn't work, please check:
- Is the new valule available in saveItem() of the manager
- Is the new value set in fromArray() of the item
- Is the new value available in fromArray() of the admin client
- Is the new value passed correctly in the template


Hi,

aimeos wrote:- Is the new valule available in saveItem() of the manager

Yes, new value "price.minimumadvertisedprice" is available in saveItem() method of "Custompricefields" manager. See below.
./ext/myextension/lib/custom/src/MShop/Price/Manager/Custompricefields.php
Code: Select allpublic function saveItem(\Aimeos\MShop\Common\Item\Iface $item, $fetch = true)
    {
        $iface = '\\Aimeos\\MShop\\Price\\Item\\Iface';
        if( !( $item instanceof $iface ) ) {
            throw new \Aimeos\MShop\Price\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/price/manager/standard/insert';
            } else {
                $path = 'mshop/price/manager/standard/update';
            }
            $stmt = $this->getCachedStatement($conn, $path);

            $stmt->bind(1, $item->getMinimumAdvertisedPrice());
            $stmt->bind(2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(3, $item->getCurrencyId());
            $stmt->bind(4, $item->getDomain());
            $stmt->bind(5, $item->getLabel());
            $stmt->bind(6, $item->getQuantity(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(7, $item->getValue());
            $stmt->bind(8, $item->getCosts());
            $stmt->bind(9, $item->getRebate());
            $stmt->bind(10, $item->getTaxRate());
            $stmt->bind(11, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(12, $date); //mtime
            $stmt->bind(13, $context->getEditor());
            $stmt->bind(14, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            if ($id !== null) {
                $stmt->bind(15, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT);
                $item->setId($id);
            } else {
                $stmt->bind(15, $date); //ctime
            }
         $stmt->execute()->finish();
            if ($id === null && $fetch === true) {
                $path = 'mshop/price/manager/standard/newid';
                $item->setId($this->newId($conn, $path));
            }
            $dbm->release($conn, $dbname);
        } catch(\Exception $e) {
            $dbm->release($conn, $dbname);
            throw $e;
        }
        return $item;
    }


aimeos wrote:- Is the new value set in fromArray() of the item

Yes, new value "price.minimumadvertisedprice" is set in fromArray() method of "Custompricefields" Item. See below:
./ext/myextension/lib/custom/src/MShop/Price/Item/Custompricefields.php
Code: Select allpublic function fromArray(array $list)
    {
        $unknown = [];
        $list = parent::fromArray($list);

        foreach ($list as $key => $value) {
            switch ($key) {
                case 'price.minimumadvertisedprice':
                    $this->setMinimumAdvertisedPrice($value);
                    break;
                default:
                    $unknown[$key] = $value;
            }
        }
        return $unknown;
    }


But this method is not being called. I don't know why. Maybe you could help!

aimeos wrote:- Is the new value available in fromArray() of the admin client

No idea about this. Which one is this file? The documentation https://aimeos.org/docs/Developers/Library/Extend_managers_items says nothing about it. Kindly, guide me, which file is it?

aimeos wrote:- Is the new value passed correctly in the template

Yes, I think so. You can check template code below.
./ext/myextension/admin/jqadm/templates/product/item-price-default.php
Code: Select all<div class="form-group row">
                     <label class="col-sm-4 form-control-label help"><?= $enc->html( $this->translate( 'admin', 'Minimum Advertised Price' ) ); ?></label>
                     <div class="col-sm-8">
                        <input class="form-control item-value" type="number" step="0.01" tabindex="<?= $this->get( 'tabindex' ); ?>"
                           name="<?= $enc->attr( $this->formparam( array( 'price', 'price.minimumadvertisedprice', '' ) ) ); ?>"
                           placeholder="<?= $enc->attr( $this->translate( 'admin', 'Minimum Advertised Price' ) ); ?>"
                           value="<?= $enc->attr( $this->get( 'priceData/price.minimumadvertisedprice/' . $idx, '0.00' ) ); ?>"
                           <?= $this->site()->readonly( $this->get( 'priceData/product.lists.siteid/' . $idx ) ); ?> />
                     </div>
                     <div class="col-sm-12 form-text text-muted help-text">
                        <?= $enc->html( $this->translate( 'admin', 'Minimum Advertised Price for the article' ) ); ?>
                     </div>
                  </div>


Can you please review all the code provided above? fromArray() method in Custompricefields Item class is not being invoked.

Thanks!
#6005 by mohal_04
11 Apr 2018, 07:56
aimeos wrote:Your new value isn't set in the item there:
https://github.com/aimeos/ai-admin-jqadm/blob/2017.10/admin/jqadm/src/Admin/JQAdm/Product/Price/Standard.php#L357


Hi,

Thanks for your guidance! I thought all changes must be in my extension. Anyhow, I have moved to Aimeos 2018.04 and now I am facing a different issue. I want to add Old SKU field on the product detail page (front-end) but product detail page is not showing latest changes.

According to the documentation (https://aimeos.org/docs/Developers/Html_frontend/Overwrite_existing_templates) I have copied the exact directory structure in <myextension>.

./ext/myextension/client/html/templates/catalog/detail/body-standard.php

BUT nothing changes on the front-end. I have cleared Laravel cache also but front-end view is not updating. May you help me with this?

Now my setup consists of:
Laravel: 5.6
Aimeos: 2018.04
Environment: Linux

Thanks!
#6006 by mohal_04
11 Apr 2018, 08:01
aimeos wrote:Your new value isn't set in the item there:
https://github.com/aimeos/ai-admin-jqadm/blob/2017.10/admin/jqadm/src/Admin/JQAdm/Product/Price/Standard.php#L357


Hi,

One more thing... Is the official documentation applicable on latest Aimeos version? Because on the documentation page it says "2016.xx version."

doc_aimeos_ver.jpg
doc_aimeos_ver.jpg (167,86 KiB) Viewed 147 times


Thanks!
#6007 by tenkraD
11 Apr 2018, 10:28
Hi moval,

dont forget, if you update the aimeos you have to rebuild your extension with the extensionbuilder that it is working right.
because they have changed the directory structur and some other stuff, i made this mistake too.

bye
#6009 by mohal_04
11 Apr 2018, 11:31
tenkraD wrote:Hi moval,

dont forget, if you update the aimeos you have to rebuild your extension with the extensionbuilder that it is working right.
because they have changed the directory structur and some other stuff, i made this mistake too.

bye


Thanks Buddy!!! Already did that :) ...