how to calculate bundle product price from array of custom selection through parameter(post data)? - arrays

the data got from post is.
[productid] => 3
[product_type] => bundle
[bundle_option] => Array
(
[1] => Array
(
[0] => 1
[1] => 2
)
[2] => Array
(
[0] => 3
[1] => 4
)
)
[qty] => 1
how to calculate the bundle price for my selections. The magento core funtions are more preferable.

Please use below code:
public function getDisplayPrice($product) {
if($product->getFinalPrice()) {
return $product->getFormatedPrice();
} else if ($product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
$optionCol= $product->getTypeInstance(true)
->getOptionsCollection($product);
$selectionCol= $product->getTypeInstance(true)
->getSelectionsCollection(
$product->getTypeInstance(true)->getOptionsIds($product),
$product
);
$optionCol->appendSelections($selectionCol);
$price = $product->getPrice();
foreach ($optionCol as $option) {
if($option->required) {
$selections = $option->getSelections();
$minPrice = min(array_map(function ($s) {
return $s->price;
}, $selections));
if($product->getSpecialPrice() > 0) {
$minPrice *= $product->getSpecialPrice()/100;
}
$price += round($minPrice,2);
}
}
return Mage::app()->getStore()->formatPrice($price);
} else {
return "";
}
}

I solved it by own method, not sure its acceptable or not.
$bundle_option = Mage::app ()->getRequest ()->getParam('bundle_option');
$bundle_option_array = call_user_func_array('array_merge', $bundle_option);
$price = Mage::Helper('airhotels/bundle')->getBundlePrice($productid,$bundle_option_array);
my helper file is
public function getBundlePrice($productId,$bundle_option_array) {
$product = new Mage_Catalog_Model_Product();
$product->load($productId);
$price=0;
$selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection($product->getTypeInstance(true)->getOptionsIds($product), $product);
foreach($selectionCollection as $option)
{
if (in_array($option->getSelectionId(), $bundle_option_array)){
$price += $option->price;
}
}
return $price;
}

Related

How make second validation in request class

i make form and this request go to controller store:
public function store(StoreTermRequest $request): RedirectResponse
{
$this->authorize('terms.create');
$request->addTerms();
return redirect(route('terms'));
}
rules of request:
public function rules()
{
return [
'start_date' => ['required', 'date'],
'end_date' => ['required', 'after_or_equal:start_date', 'date'],
'start_day' => ['required', 'date_format:H:i'],
'end_day' => ['required', 'after_or_equal:start_day', 'date_format:H:i'],
'start_break' => ['required', 'date_format:H:i'],
'end_break' => ['required', 'after_or_equal:start_break', 'date_format:H:i'],
'time_one_visit' => ['required', 'integer', 'min:1'],
'work_days' => ['present', 'required'],
'work_days.*' => ['present', 'required', new Enum(Days::class)],
'doctor' => [
'required', 'exists:doctors,id', 'integer',
],
];
}
then i make buisness logic, from generate date to single visits terms then i want check whether the given dates are free. that's why i want make second validation
public function addTerms()
{
$startDayInMonth = strtotime($this->start_date);
$endDayInMonth = strtotime($this->end_date);
$startDayOfHour = strtotime($this->start_day);
$endDayOfHour = strtotime($this->end_day);
$startBreak = strtotime($this->start_break);
$endBreak = strtotime($this->end_break);
$workingDays = $this->work_days;
$timeOneVisit = $this->time_one_visit * 60;
$doctor = $this->doctor;
$doctorBefore = [];
$dateVisitBefore = [];
$startVisitBefore = [];
$endVisitBefore = [];
$j = $startDayInMonth;
while ($endDayInMonth >= $j) {
if (!in_array(date('N', $j), $workingDays)) {
$j += 86400;
continue;
}
$j += 86400;
$i = $startDayOfHour;
while ($endDayOfHour > $i) {
if ($startBreak <= $i && $endBreak > $i) {
$i = $endBreak;
}
$validator = Validator::make(
[
'start_visit' => date('H:i', $i),
'end_visit' => date('H:i', $i + $timeOneVisit)
],
[
'start_visit' => [new FreeTerm()],
'end_visit' => [new FreeTerm()],
]
);
if ($validator->fails()) {
//
}
array_push($doctorBefore, $doctor);
array_push($dateVisitBefore, date('Y-m-d', $j));
array_push($startVisitBefore, date('H:i', $i));
array_push($endVisitBefore, date('H:i', $i + $timeOneVisit));
$i += $timeOneVisit;
}
}
for ($i = 0; $i < count($doctorBefore); $i++) {
DB::table('terms')->insert([
'doctor_id' => $doctorBefore[$i],
'date_visit' => $dateVisitBefore[$i],
'start_visit' => $startVisitBefore[$i],
'end_visit' => $endVisitBefore[$i]
]);
}
}
and its successful validation but what write here to return to form after fail with error message
if ($validator->fails()) {
//
}
i tried
return redirect()->to(route('terms.create'));
return back()->withErrors($validate->errors()->withinput();
and a lot of combinations around this in controller in request class, but i'm done.
i want to see clear answer because my english is not perfect :P

save the record of bulk sms sent into db laravel

i have taken the id and mobile_num from users table.i have to insert that id name in this table as user_id,mobile_num,and status(0,1) into another table(wc_sms_status).sendSMSFunction is working fine.
public function SendBulkSms()
{
$usersNumber = User::select('id','mobile_num')->whereIn('id', [5,6,7,8])->get();
foreach($usersNumber as $userNumber)
{
if (!$userNumber->mobile_num)
{
$this->sendSmsFunction($userNumber->mobile_num);
DB::table('wc_sms_status')->insert([
['user_id' => 'id'],
['mobile_num' => 'mobile_num'] // set the status=1 // how query can be changed?
]);
}
elseif($userNumber->mobile_num == exist && status == 0)
{
$this->sendSmsFunction($userNumber->mobile_num);
$this->save();
}
else{
}
}
}
Do this :
public function SendBulkSms()
{
//assuming there is a relationship between your model users and wc_sms_status called wcSmsStatus
$usersNumber = User::with('wcSmsStatus')->select('id','mobile_num')->whereIn('id', [5,6,7,8])->get();
foreach($usersNumber as $userNumber)
{
if (!$userNumber->mobile_num)
{
$this->sendSmsFunction($userNumber->mobile_num);
DB::table('wc_sms_status')->insert([
'user_id' => $userNumber->id,
'mobile_num' => $userNumber->mobile_num,
'status' => 1,
]);
} elseif ($userNumber->mobile_num && $userNumber['wcSmsStatus']->status === 0)
{
$this->sendSmsFunction($userNumber->mobile_num);
$this->save();
} else {
}
}
}
public function SendBulkSms()
{
$users = User::select('id','mobile_num')
->whereIn('id', [5,6,7,8])
->whereNotNull('mobile_num')
->get();
$bulkData = [];
foreach ($users as $user)
{
$this->sendSmsFunction($userNumber->mobile_num);
DB::table('wc_sms_status')->insert([
['user_id' => 'id'],
['mobile_num' => 'mobile_num'] // set the status=1 // how query can be changed?
]);
$bulkData[] = [
'user_id' => $user->id,
'mobile_num' => $user->mobile_num,
];
}
if (!empty($bulkData)) {
WcSmsStatus::insert($education); // change to your model name
unset($bulkData);
}
}
try to use in this way, it will insert bulk data, dont fergot to mention protected $fillable[] in model

How can i set default values to array before results is added

i have standings method, where is all data from league matches.
For exmpl.
League one has 10 teams. And standings is calculated when results is added. But if some of teams doesn't have added results, they are not added to standings.
Main goal is to get all teams in standings, nvm if team hasn't any matches.
Before results is added, all results in standings should be 0 (points,matches,wins,loses and others)
here is my standings method:
public function standings(League $league, Team $team)
{
$standings = [];
$blank = [
'points' => 0,
'scoredGoals' => 0,
'goalsConceded' => 0,
'wins' => 0,
'loses' => 0,
'draws' => 0,
];
$matches = Match::with('score', 'homeTeam', 'awayTeam')
->whereHas('score', function($query){
$query->whereNotNull('home_team_score')
->whereNotNull('away_team_score');
})
->where('league_id', '=', $league->id)
->get();
foreach ($matches as $match) {
$homeTeamScore = $match->score->home_team_score;
$awayTeamScore = $match->score->away_team_score;
if (! isset($standings[$match->homeTeam->name])) {
$standings[$match->homeTeam->name] = $blank;
}
if (! isset($standings[$match->awayTeam->name])) {
$standings[$match->awayTeam->name] = $blank;
}
$home = &$standings[$match->homeTeam->name];
$away = &$standings[$match->awayTeam->name];
$away['scoredGoals'] += $awayTeamScore;
$home['scoredGoals'] += $homeTeamScore;
$away['goalsConceded'] += $homeTeamScore;
$home['goalsConceded'] += $awayTeamScore;
switch ($homeTeamScore <=> $awayTeamScore) {
case -1:
// home lost
// swap home and away and let it fall through
$tmpHome = &$home;
$home = &$away;
$away = &$tmpHome;
case 1:
// home won
$home['points'] += 3;
$home['wins']++;
$away['loses']++;
break;
default:
// draw
$home['points']++;
$away['points']++;
$home['draws']++;
$away['draws']++;
}
}
$standings = collect($standings)->sort(function ($one, $other) {
if ($one['points'] !== $other['points']) {
return $other['points'] - $one['points']; // similar to desc
}
$oneDelta = $one['scoredGoals'] - $one['goalsConceded'];
$otherDelta = $other['scoredGoals'] - $other['goalsConceded'];
return $otherDelta - $oneDelta; // similar to desc
});
return view('admin.leagues.standings')->with([
'standings' => $standings,
]);
}
I guess you can first fill your $standings collection with $blank item for all teams
$standings = [];
$blank = [
'points' => 0,
'scoredGoals' => 0,
'goalsConceded' => 0,
'wins' => 0,
'loses' => 0,
'draws' => 0,
];
$teams = Team::all();
foreach ($teams as $team) {
$standings[$team->name] = $blank;
}
And now you can omit following checks and initialization from the loop
if (! isset($standings[$match->homeTeam->name])) {
$standings[$match->homeTeam->name] = $blank;
}
if (! isset($standings[$match->awayTeam->name])) {
$standings[$match->awayTeam->name] = $blank;
}
This way you will have all the teams in $standings irrespective of their matches, later on your next loop will fill the related information for the teams who have played matches

how to custom sort an array based on its status followed by another field?

So I have an array, I need to sort it based on status in the following order i.e. failure->warn->completed.
Normally, I use lodash for sorting but its a bit of complex order here. It also needs to sort according to run after sorting with run. Im not sure how to start on this.
var arr = [{"status":"failure","name":"one","run":1},
{"status":"failure","name":"two","run":2},
{"status":"warn","name":"three","run":1},
{"status":"warn","name":"four","run":2},
{"status":"completed","name":"five","run":1}]
something like this?
Add a extra property for your sort key.
var arrnew = arr.map(function(item){
switch(item.status){
case "failure":
item.statusId=1;
break;
case "warn":
item.statusId=2;}
//...
return item} );
Sort by using that
_.sortBy(arrnew, 'statusId');
Sorts based on "status", and then the sub-slices by "run" 1 or 2:
let status_vals = [ "failure", "warn", "completed" ];
let arr = [
{"status":"failure","name":"one","run":1},
{"status":"failure","name":"two","run":2},
{"status":"warn","name":"three","run":1},
{"status":"warn","name":"four","run":2},
{"status":"completed","name":"five","run":1}
];
function sortIt ( status_arr, sort_arr ) {
let sorted_arr = [];
status_arr.forEach ( d => {
let temp = arr.filter ( obj => {
return obj.status === d;
} );
var length = temp.length;
for ( var i = 0; i < length; i++ ) {
if ( temp [ 0 ].run > temp [ i ].run ) {
temp.push ( temp.shift ( ) );
}
}
sorted_arr = [ ...sorted_arr, ...temp ];
} );
return sorted_arr;
}
sortIt ( status_vals, arr );

Yii2 Save multiple data in the db using foreach loop in actionCreate

In my project I want to insert multiple rows of data at a single time using the foreach loop. I have a variable which has array of elements.
For instance if my array has say 3 different elements. I want to save all these 3 elements in the 3 different db table rows. I also have other columns which are same for all the 3 array elements.
I have put them inside foreach statement but only the 1st elements gets saved. Is there any method I can achieve this?
My code
public function actionCreate($prodID)
{
$model = new ProductlinesStorage();
if ($model->load(Yii::$app->request->post())) {
$productlineID = Productlines::find()->where(['area_id' => $model->productline_id, 'product_id' => $prodID])->all();
foreach ($productlineID as $singleProductlineID) {
$model->productline_id = $singleProductlineID->productline_id;
$model->user_id = Yii::$app->user->identity->user_id;
$model->isNewRecord = true;
$model->save();
}
return $this->redirect(['/product/storage?id='.$prodID]);
} else {
return $this->renderAjax('create', [
'model' => $model,
'prodID' => $prodID,
]);
}
}
Only the productline_id is different other columns will have same data for all the prdouctline_id.
Thank You!!!
You have only one model object, and you are saving only to it.
Try this:
public function actionCreate($prodID)
{
$model = new ProductlinesStorage();
if ($model->load(Yii::$app->request->post())) {
$productlineID = Productlines::find()->where(['area_id' => $model->productline_id, 'product_id' => $prodID])->all();
foreach ($productlineID as $singleProductlineID) {
$model = new ProductlinesStorage();
$model->productline_id = $singleProductlineID->productline_id;
$model->user_id = Yii::$app->user->identity->user_id;
$model->isNewRecord = true;
$model->save();
}
return $this->redirect(['/product/storage?id='.$prodID]);
} else {
return $this->renderAjax('create', [
'model' => $model,
'prodID' => $prodID,
]);
}
}
maybe you can modify my code
public function actionCreate()
{
$model = new SemesterPendek();
$model->user_id = \Yii::$app->user->identity->id;
$model->npm = \Yii::$app->user->identity->username;
$modelsNilai = [new Nilai];
if ($model->load(Yii::$app->request->post())){
$model->waktu_daftar = date('Y-m-d h:m:s');
$model->save();
$modelsNilai = Tabular::createMultiple(Nilai::classname());
Tabular::loadMultiple($modelsNilai, Yii::$app->request->post());
// validate all models
$valid = $model->validate();
$valid = Tabular::validateMultiple($modelsNilai) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
foreach ($modelsNilai as $indexTools =>$modelNilai) {
$modelNilai->id_sp = $model->id;
// $modelNilai->user_id = \Yii::$app->user->identity->id;
if (! ($flag = $modelNilai->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
}
} catch (Exception $e) {
$transaction->rollBack(); \Yii::$app->session->setFlash('error','gagal');
}
}
} else {
return $this->render('create', [
'model' => $model,
'modelsNilai' => (empty($modelsNilai)) ? [new Nilai] : $modelsNilai,
]);
}
}
You need to create a different object to save in different rows. For loop executes 3 times but every time same object is being updated. You can define new object and save each time. Below code will work
public function actionCreate($prodID)
{
$model = new ProductlinesStorage();
if ($model->load(Yii::$app->request->post())) {
$productlineID = Productlines::find()->where(['area_id' => $model->productline_id, 'product_id' => $prodID])->all();
foreach ($productlineID as $singleProductlineID) {
$model = new ProductlinesStorage();
$model->productline_id = $singleProductlineID->productline_id;
$model->user_id = Yii::$app->user->identity->user_id;
$model->isNewRecord = true;
$model->save();
}
return $this->redirect(['/product/storage?id='.$prodID]);
} else {
return $this->renderAjax('create', [
'model' => $model,
'prodID' => $prodID,
]);
}
}

Resources