Custom shipping calculator which takes destination into account - calculator

I am trying to create a custom calculator which calculates shipping costs based of a deleivery address. For now, I will be hardcoding different fees according to a postcode prefix... e.g.
SK1 = 4
SK2 = 4
SK3 = 4
SK4 = 4
M1 = 6
M2 = 6
M3 = 6
M4 = 6
Everything else = 10
I am following the tutorial here.
The code stub I have is as follows:
<?php
/**
* Created by IntelliJ IDEA.
* User: camerona
* Date: 03/03/2017
* Time: 08:09
*/
namespace AppBundle\Shipping;
use Sylius\Component\Shipping\Calculator\CalculatorInterface;
use Sylius\Component\Shipping\Model\ShippingSubjectInterface;
class PostCodeCalculator implements CalculatorInterface
{
public function calculate(ShippingSubjectInterface $subject, array $configuration)
{
return $this->postCodeService->getShippingCostForPostCode($subject->getShippingAddress());
}
public function getType()
{
// TODO: Implement getType() method.
}
}
Is there a way in sylius where I can get access to the shipping address of an order? The ShippingSubjectInterface only allows access to volume, weight, items, and shippables.

/** #var $subject Shipment */
$postCode = $subject->getOrder()->getShippingAddress()->getPostCode();
Allowed me get address from subject.

Related

Contentsliding is not stopping at sysfolder since TYPO3 v10 - How to solve?

The TSref entry for slide explains:
Up to Version 9 of TYPO3 the sliding stopped when reaching a folder.
Beginning with TYPO3 10 this is not longer the case. See
$cObj->checkPid_badDoktypeList.
Ok, this variable is still 255 (formerly directly, now via constant PageRepository::DOKTYPE_RECYCLER).
What exactly should I see there that will help me? Or better, how to get content sliding still working like before?
You have to extend the ContentObjectRenderer class and overwrite the getSlidePids method with your own extension.
In the boot function of ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class] = [
'className' => \YourVendor\YourExtensionKey\ContentObject\ContentObjectRenderer::class
];
Then you have to create your own "Classes/ContentObject/ContentObjectRenderer.php" with:
<?php
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace YourVendor\YourExtension\ContentObject;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class ContentObjectRenderer extends \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
{
/**
* Returns all parents of the given PID (Page UID) list
*
* #param string $pidList A list of page Content-Element PIDs (Page UIDs) / stdWrap
* #param array $pidConf stdWrap array for the list
* #return string A list of PIDs
* #internal
*/
public function getSlidePids($pidList, $pidConf)
{
// todo: phpstan states that $pidConf always exists and is not nullable. At the moment, this is a false positive
// as null can be passed into this method via $pidConf. As soon as more strict types are used, this isset
// check must be replaced with a more appropriate check like empty or count.
$pidList = isset($pidConf) ? trim($this->stdWrap($pidList, $pidConf)) : trim($pidList);
if ($pidList === '') {
$pidList = 'this';
}
$tsfe = $this->getTypoScriptFrontendController();
$listArr = null;
if (trim($pidList)) {
$listArr = GeneralUtility::intExplode(',', str_replace('this', (string)$tsfe->contentPid, $pidList));
$listArr = $this->checkPidArray($listArr);
}
$pidList = [];
if (is_array($listArr) && !empty($listArr)) {
foreach ($listArr as $uid) {
$page = $tsfe->sys_page->getPage($uid);
if($page['doktype'] == PageRepository::DOKTYPE_SYSFOLDER)
break;
if (!$page['is_siteroot']) {
$pidList[] = $page['pid'];
}
}
}
return implode(',', $pidList);
}
}

How to add notice on magento 2 checkout, on street address field for billing and shipping

I want to add notice on street address field, on magento 2 checkout page. I tried adding it in: using layout process
<?php
namespace Pawan\Notice\Model\Checkout;
class LayoutProcessorPlugin
{
/**
* #param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
* #param array $jsLayout
* #return array
*/
public function afterProcess(
\Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
array $jsLayout
) {
$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
['shippingAddress']['children']['shipping-address-fieldset']['children']['street']['children'][1]
['notice'] = __('This is my custom notice.');
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
['billingAddress']['children']['billing-address-fieldset']['children']['street']['children'][1]
['notice'] = __('This is my custom notice.');
return $jsLayout;
}
}
it added only for shipping address but not billing can any one tell me how to add my billing address section under payment method
If need find exact place of tags just print layout process and add notice to particular tag
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/extranotice.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Simple Text Log'); // Simple Text Log
$logger->info('Array Log $jsLayout'.print_r($jsLayout, true)); // Array Log
checked on log file based on that I added for street
$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
['shippingAddress']['children']['shipping-address-fieldset']['children']['street']['children'][0]
['notice'] = __('No PO Box');

How can I determine which security manager is active on z/OS using Java?

I am writing Java code on z/OS and I need to find out which security manager (RACF, ACF2 or TopSecret) is active on the system. How can I do this?
You can use the IBM JZOS package to peek at memory as follows. For production code, I would create an enumeration for the security managers and rather than pass strings around and have to deal with string comparisons.
import com.ibm.jzos.ZUtil;
/**
* This is a sample program that uses IBM JZOS to determine
* the Enterprise Security Manager that is active on a z/OS
* system.
* <p>
* #see com.ibm.jzos.ZUtil#peekOSMemory(long, int)
* #see com.ibm.jzos.ZUtil#peekOSMemory(long, byte[])
*/
public class peek {
public static void main(String[] args) throws Exception {
byte[] rcvtIdBytes = new byte[4];
long pPSA = 0L;
int psaOffsetCVT = 16;
long pCVT = ZUtil.peekOSMemory(pPSA + psaOffsetCVT, 4); // Get address of CVT from PSA+16
int cvtOffsetCVTRAC = 0x3e0; // Offset of CVTRAC (#RCVT) in the CVT
long pCVTRAC =
ZUtil.peekOSMemory(pCVT + cvtOffsetCVTRAC, 4); // Get the address of CVTRAC (Mapped by ICHPRCVT)
// Now we can retrieve the 4 byte ID (in IBM-1047) of the active ESM.
int cvtracOffsetRCVTID = 0x45; // Offset of RCVTID in the RCVT
ZUtil.peekOSMemory(pCVTRAC + cvtracOffsetRCVTID, rcvtIdBytes); // Get the RCVTID
String rcvtId = new String(rcvtIdBytes, "IBM-1047");
System.out.println("The Security Manager is: "+rcvtId);
}
}

Lumen Database Queue first job always failing Allowed memory exhausted

I have a very odd situation where I set up a job to run in my Lumen database queue and all but the first job is processed. I do keep getting this particular error:
[2017-12-12 22:07:10] lumen.ERROR: Symfony\Component\Debug\Exception\FatalErrorException: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 702558208 bytes) in /var/www/vhosts/XXXXXXXXX$
Stack trace:
#0 /var/www/vhosts/XXXXXXXX/vendor/laravel/lumen-framework/src/Concerns/RegistersExceptionHandlers.php(54): Laravel\Lumen\Application->handleShutdown()
#1 [internal function]: Laravel\Lumen\Application->Laravel\Lumen\Concerns\{closure}()
#2 {main}
I have tried allowing the memory limit to go up but I keep getting the same error with differing values for the exhausted memory.
I find it very odd that it is always the first job and all of the rest of the jobs run perfectly fine. Should I be looking for bad data in the first job?
My code basically looks like this:
This is my Command file
namespace App\Console\Commands;
use App\Jobs\UpdateNNNAppListJob;
use Illuminate\Console\Command;
use App\Services\MiddlewareApi;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Mockery\Exception;
use Illuminate\Support\Facades\Queue;
class AddEmailsToAppList extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'addemails:nnnmobileapp';
/**
* The console command description.
*
* #var string
*/
protected $description = 'This will add all mobile app users in the database to the nnn mobile app list.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
public function handle()
{
$chunkSize = 500; //this is the most middleware can handle with its bulk signup call
$emailChunks = $this->getEmailsToAdd($chunkSize);
$jobDelay = 120; //time between queued jobs
$jobDelayTimeKeeper = 60; //This will be the actual time delay that will be put into the later method
foreach ($emailChunks as $emailChunk) {
Queue::later($jobDelayTimeKeeper, new UpdateMmpAppListJob($emailChunk));
$jobDelayTimeKeeper = $jobDelayTimeKeeper + $jobDelay;
}
}
public function getEmailsToAdd($chunkSize)
{
$emails = DB::table('app_users')
->join('app_datas', 'app_datas.customer_number', '=', 'app_users.customer_number')
->select('app_users.email')
->get()
->chunk($chunkSize);
return $emails;
}
}
Here is my Job File
<?php
namespace App\Jobs;
use App\Services\MiddlewareApi;
use Illuminate\Support\Facades\Log;
use Mockery\Exception;
class UpdateMmpAppListJob extends Job
{
/**
* Array of emails to update list with
* #var array
*/
protected $emailArray;
/**
* The number of times the job may be attempted.
*
* #var int
*/
public $tries = 2;
public function __construct($emailArray)
{
$this->emailArray = $emailArray;
}
public function handle()
{
$listCodeToAddTo = 'NNNAPP';
$sourceId = 'NNNNNNN';
$middlewareApi = new MiddlewareApi();
try {
$middlewareApi->post_add_customer_signup_bulk($listCodeToAddTo, $this->emailArray, $sourceId);
} catch (\Exception $e) {
Log::error('An error occurred with theUpdateMmpAppListJob: ' . $e);
mail('djarrin#NNN.com', 'UpdateNnnAppListJob Failure', 'A failure in the UpdateNnnAppListJob, here is the exception: ' . $e);
}
}
public function failed(\Exception $exception)
{
mail('djarrin#moneymappress.com', 'Push Processor Que Failure', 'A failure in the UpdateMmpAppListJob, here is the exception: ' . $exception);
}
}
Any help/suggestions on this issue would be appreciate.
Your code calls ->get() which will load the entire result into memory. This causes the huge memory allocation that you're seeing. Remove it and let ->chunk(...) work with the database builder instead of the in-memory Collection that get() has returned. You would also have to provide a callback to chunk that processes every chunk.
public function handle() {
$chunkSize = 500; //this is the most middleware can handle with its bulk signup call
$jobDelay = 120; //time between queued jobs
$jobDelayTimeKeeper = 60; //This will be the actual time delay that will be put into the later method
DB::table('app_users')
->join('app_datas', 'app_datas.customer_number', '=', 'app_users.customer_number')
->select('app_users.email')
->chunk($chunkSize, function($emailChunk) use (&$jobDelayTimeKeeper, $jobDelay) {
Queue::later($jobDelayTimeKeeper, new UpdateMmpAppListJob($emailChunk));
$jobDelayTimeKeeper = $jobDelayTimeKeeper + $jobDelay;
});
}
The above concept is correct but this syntax was required to get past the
[2017-12-14 22:08:26] lumen.ERROR: RuntimeException: You must specify an orderBy clause when using this function. in /home/vagrant/sites/nnn/vendor/illuminate/database/Query/Builder.php:1877
This is for Lumen 5.5:
public function handle()
{
$chunkSize = 500; //this is the most middleware can handle with its bulk signup call
$jobDelay = 120; //time between queued jobs
$jobDelayTimeKeeper = 60; //This will be the actual time delay that will be put into the later method
$emails = DB::table('app_users')
->join('app_datas', 'app_datas.customer_number', '=', 'app_users.customer_number')
->select('app_users.email')->orderBy('app_users.id', 'desc');
$emails->chunk($chunkSize, function($emailChunk) use (&$jobDelayTimeKeeper, $jobDelay) {
Queue::later($jobDelayTimeKeeper, new UpdateMmpAppListJob($emailChunk));
$jobDelayTimeKeeper = $jobDelayTimeKeeper + $jobDelay;
});
}

custom discount applied twice in magento 2

I have applied custom discount in magento 2.1 using this. Everything is working on local system but when I deploy the changes on server, discount get subtracted twice from the total.
Can any one any idea about this?
Sales.xml
<?xml version="1.0"?><config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Sales:etc/sales.xsd">
<section name="quote">
<group name="totals">
<item name="test_discount" instance="Namespace\Modulename\Model\Quote\Discount" sort_order="500"/>
</group>
</section>
To remove the custom discount applying twice in your summary .Just add below Lines
$items = $shippingAssignment->getItems();
if (!count($items)) {
return $this;
}
in the collect method. Once done, it will look like below.
public function collect(
\Magento\Quote\Model\Quote $quote,
\Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
\Magento\Quote\Model\Quote\Address\Total $total
) {
$items = $shippingAssignment->getItems();
if (!count($items)) {
return $this;
}
parent::collect($quote, $shippingAssignment, $total);
This could be because of multishipping.
Magento collects totals per address. In the default scenario a quote has two addresses: A billing address and a shipping address.
I have not tried the example you linked, but afaiks the fee will be applied twice. For some reason this does not show up on the frontend, but I also had problems where a fee was applied twice, but somehow still showed up correctly on the frontend.
I assume when having a multiple shipping order, there is still only one billing address. Therefore the following snippet should fix the issue of having custom fees/discounts applied twice:
$address = $shippingAssignment->getShipping()->getAddress();
if($address->getAddressType() != 'billing'){
return $this;
}
Or, if you only want to apply the fee/charge for shipments with items:
$allBaseTotals = $total->getAllBaseTotalAmounts();
if(!isset($allBaseTotals['subtotal']) || $allBaseTotals['subtotal'] <= 0){
return $this;
}
This means the example file in the tutorial you linked would turn out like this:
app/code/Magestore/Webpos/Model/Total/Quote/Custom.php
/**
* #param \Magento\Quote\Model\Quote $quote
* #param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment
* #param \Magento\Quote\Model\Quote\Address\Total $total
* #return $this|bool
*/
public function collect(
\Magento\Quote\Model\Quote $quote,
\Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
\Magento\Quote\Model\Quote\Address\Total $total
)
{
parent::collect($quote, $shippingAssignment, $total);
$address = $shippingAssignment->getShipping()->getAddress();
if($address->getAddressType() != 'billing'){
return $this;
}
$baseDiscount = 10;
$discount = $this->_priceCurrency->convert($baseDiscount);
$total->addTotalAmount('customdiscount', -$discount);
$total->addBaseTotalAmount('customdiscount', -$baseDiscount);
$total->setBaseGrandTotal($total->getBaseGrandTotal() - $baseDiscount);
$quote->setCustomDiscount(-$discount);
return $this;
}
Edit:
It seems if($address->getAddressType() != 'billing'){ does not work as I thought it would.
I'm using if($address->getAddressType() == 'billing'){ for now as I'm not using multishipping.
Discount is calculated by address in quote, since there are two address billing and shipping that why is calculated twice.
you can set condition on either billing or shipping that only calculate for shipping address or billing address.
here just put this simple if statement (from nbjohan answer) at the start.
$address = $shippingAssignment->getShipping()->getAddress();
if($address->getAddressType() != 'billing'){
return $this;
}
now it will calculate only for one time.