How can I build a query scope in Laravel that takes data if sum of relative table column is between requested range? - sql

I have two tables loads and stops. The Stops table has a price column. Loads' price is equal to the sum of stops' price related to the load. I want to build a scope that builds a query to get all loads where it's the price is in the requested range.
My scope:
public function scopeBetweenPrice($query, $from, $to) {
if ($from !== null || $to !== null) {
return $query;
}
return $query;
}

Related

getProduct()->getTag() return null, when it should return tags associated to the Product

In my project, we have products that has tag called serviceItem. Those item with that tag when ordered should be separated by the quantity into individuals order.
It issue is that getTags() returns null, and getTagIds gets "Call to a member function getTagIds() on null" when it gets to the next loop.
Is there a reason for why getTags() returns null?
private function transformOrderLines(OrderEntity $order): array
{
/**
* TODO: If we need to send advanced prices,
* the price value of the the lines array should be changed to caldulate the advanced price,
* with the built in quantity calculator
*/
$lines = [];
foreach ($order->getLineItems() as $orderLine) {
$hasDsmServiceItemTag = $orderLine->getProduct()->getTags();
$lines[] = [
'name' => $orderLine->getLabel(),
'sku' => substr($orderLine->getProduct()->getProductNumber(), 0, 19),
'price' => (string) ($orderLine->getProduct()->getPrice()->first()->getNet()
* $order->getCurrencyFactor()), //gets original price, calculates factor
'quantity' => (string) $orderLine->getQuantity()
];
}
$shipping = $this->transformShipping($order);
if ($shipping) {
$lines = array_merge($lines, $shipping);
}
return $lines;
}`
I also tried $orderLine->getProduct()->getTags()->getName() it also return "Call to a member function getTags() on null"
The problem is wherever the $order is fetched from the DB the orderLineItem.product.tag association is not included in the criteria.
For performance reasons shopware does not lazily load all association when you access them on entities, but you have to exactly define which associations should be included when you fetch the entities from the database.
For the full explanation take a look at the docs.

Getting sum complete (without pagination) of particular columns in backpack for laravel

I followed the recommendations I found here
jQuery(document).ready(function($) {
jQuery.fn.dataTable.Api.register( 'sum()', function ( ) {
return this.flatten().reduce( function ( a, b ) {
if ( typeof a === 'string' ) {
a = a.replace(/[^\d.-]/g, '') * 1;
}
if ( typeof b === 'string' ) {
b = b.replace(/[^\d.-]/g, '') * 1;
}
return a + b;
}, 0 );
} );
$("#crudTable tfoot").css("display", "table-footer-group");
crud.table.on("draw.dt", function ( row, data, start, end, display ) {
total = crud.table.rows( function ( idx, data, node ) {
return data[11].includes('Cancelado') ? false : true;} ).data().pluck(10).sum();
total = "$" + total.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
$("#crudTable tfoot tr th").html(
" <br> "
);
$("#crudTable tfoot tr").children().eq(10).html(
"Total <br>"+ total
);
});
});
And I added some modifications to get the total of the column by skipping the items that have canceled status, but I have not been able to get the total of the records but without paging. With Datatable I get the records that are being drawn, but I can't find how to intercept the ajax query or modify it to get the full total on that column including filter modifications.
Currently if in the pagination I request "show all records" obviously I get the value I need. But the requirement is that this value is displayed even if the table is visually paginated.
one way to achieve that would be to overwrite the search() function of the ListOperation (it's the table ajax endpoint).
You would need do do the full query without the pagination part to get the full data, and then pass the calculation along with the paginated response for display.
Cheers

Laravel Eloquent - where relationship field does not equal

I thought this would be fairly simple but it's not playing ball currently.
I have 2 tables for this question, 'applications' & 'application_call_logs'.
This query needs to return all from the applications table where the latest call log doesn't have a status of X.
Here's the current query:
$query = Application::query();
$query->where(function($query) {
$query->whereDoesntHave('call_logs');
$query->orWhereHas('latest_call_log', function($q) {
$q->where('status', '!=', 'not interested');
});
});
return $query->get();
This should return all rows that either have no call logs, or where the latest call log doesn't have the status field equaling a specific string.
This here:
$q->where('status', '!=', 'not interested');
Seems to have no affect if the call_logs has more than 1 row, even though I'm querying the latest relationship. I've also verified the latest is returning the correct latest record.
The two relationships in the Application model are:
public function call_logs()
{
return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id');
}
public function latest_call_log()
{
return $this->hasOne('App\ApplicationCallLog', 'lead_id', 'id')->latest();
}
Checked the SQL generated:
select * from `applications` where (not exists (select * from `lead_call_logs` where `applications`.`id` = `lead_call_logs`.`lead_id`) or exists (select * from `lead_call_logs` where `applications`.`id` = `lead_call_logs`.`lead_id` and `status` != ?))
there is a solution around should be good for this situation:
i think that this line has the week point of the code:
return $this->hasOne('App\ApplicationCallLog', 'lead_id', 'id')->latest();
this should be hasMany, but you use hasOne to limit the result to one.
and if you tried:
return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id')->latest()->limit(1);
it simply won't work, because the result will be limited to ApplicationCallLog for all of the results ....
will, there is a package staudenmeir/eloquent-eager-limit that is made especially for this situations:
composer require staudenmeir/eloquent-eager-limit:"^1.0"
class Application extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
public function latest_call_log()
{
return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id')->latest()
->limit(1);
}
}
class ApplicationCallLog extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
}
using this package will limit ApplicationCallLog for every result in your query not one for all of the result, and that will have the same effect for hasOne ....
with this minor enhancement, i think:
$q->where('status', '!=', 'not interested');
will work ...
more about eloquent-eager-limit package in:
https://github.com/staudenmeir/eloquent-eager-limit

How to set a maximum stock level for total WooCommerce variations sold, disregarding individual variation stock levels

I'm wondering if we are able to hook into WooCommerce to set a maximum amount of stock that can be purchased for a variable product. Disregarding the individual variation stock levels once this maximum amount is reached.
For example, I have a variable product selling workshop groups. There are 4 variations, each with a stock level set at 100. This is because no group can have more than 100 people in. However, only 250 tickets are available for sale (not 400 that we might expect because of the 4x100 quantity).
So this works as far as the max 100 places per workshop group. We just need to somehow be able to limit the total stock level of all 4 variations to 250.
I had hoped enabling the parent product "Manage stock" option and setting this to 250 would work. But obviously, variations must override this. If we can hook into that and turn that back on even when variation stock management is in use that might be a nice way of solving this.
Thanks for any help.
I came up with a solution to my problem by doing the following:
Add 2 custom fields to the WooCommerce product page, which will store the max quantity of the total variations we can sell and also the max quantity of an individual variation. The code for this is:
// Modify WooCommerce Product Settings
add_action('woocommerce_product_options_inventory_product_data', 'wc_add_custom_field' );
function wc_add_custom_field() {
$fields = array('Total quantity' => 'total_quantity','Variation quantity' => 'variation_quantity');
$field_description = array('total_quantity' ='description','variation_quantity' ='description');
$field_placeholder = array('total_quantity' =>'e.g. 300','variation_quantity' =>'e.g. 100');
foreach ($fields as $key => $value) {
woocommerce_wp_text_input( array(
'id' => $value,
'label' => $key,
'description' => $field_description[$value],
'desc_tip' => 'true',
'placeholder' => $field_placeholder[$value]
) );
}
}
// Save Fields
add_action( 'save_post_product', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields_save( $post_id ){
update_post_meta( $post_id, 'total_quantity', $_POST['total_quantity'] );
update_post_meta( $post_id, 'variation_quantity', $_POST['variation_quantity'] );
}
Add cart/basket validation rules to stop customers being able to purchase products that exceed the value of the custom "total_quantity" field added above:
add_action( "woocommerce_add_to_cart_validation","sc_woocommerce_add_to_cart_validation", 1, 5 );
function sc_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id, $variations ) {
// Iterate through each variation and get the total stock remaining
$product_variable = new WC_Product_Variable($product_id);
$product_variations = $product_variable->get_available_variations();
settype($variation_stock_availability, "integer");
foreach ($product_variations as $variation) {
$variation_stock_availability = +(int)$variation['max_qty'];
}
$count_variations = count($product_variations);
$total_quantity = get_post_meta( $product_id, 'total_quantity', true );
$variation_quantity = get_post_meta( $product_id, 'variation_quantity', true );
// formula to test if any stock remaining based on sold variations
$formula = $count_variations * $variation_quantity;
$formula1 = (int)$formula + (int)$quantity;
$formula1 = $formula1 - $variation_stock_availability;
// Iterating through each cart item and use the current running quantity in the cart in the forumula
foreach (WC()->cart->get_cart() as $cart_item_key=>$cart_item ){
// count(selected category) quantity
$running_qty += (int) $cart_item['quantity'];
$formula2 = (int)$formula + (int)$running_qty;
$formula2 = $formula2 - $variation_stock_availability;
// More than allowed products in the cart is not allowed
if ($formula2 >= $total_places) {
wc_add_notice( sprintf( __( "Unfortunately there is no availability based on your selection", "donaheys" )), 'error' );
$passed = false;
return $passed;
}
}
// More than allowed products in the cart is not allowed
if ($formula1 >= $total_places) {
// Add the error
wc_add_notice( sprintf( __( "Unfortunately there is no availability based on your selection", "donaheys" )), 'error' );
$passed = false;
return $passed;
} else {
$passed = true;
return $passed;
}
$running_qty = 0;
}
The result of the above code ensures we are can set a maximum amount of stock that can be purchased for a variable product, disregarding the individual variation stock levels once this maximum amount is reached.

How to select data from table that not inserted on other table in codeigniter

I've two tables products, stock I want to select all rows from table products that not inserted on stock and i've 2 conditions
1: column products.s_compnay_id = users.u_company_id
2: cloumn stock.s_company_id =users.u_company_id
that's my model
<?php
Class UserProducts_m extends CI_Model{
function index(){
$session_data = $this->session->userdata('logged_in');
$name = $session_data['username'];
$this->db->select('u_company_id');
$this->db->from('users');
$this->db->where('u_username', $name);
$user_data = $query = $this->db->get();
if ($user_data->num_rows() > 0) {
foreach ($query->result_array() as $row_userdata) {
$usercompanyid[] = $row_userdata;
}
$usercompany=$usercompanyid[0]['u_company_id'];
}
$query="select products.* from products where !FIND_IN_SET(products.p_id,select stock.s_p_id from stock and stock.s_company_id=$usercompany and p_company_id=$usercompany)";
$this->db->query($query);
$result= $this->db->get();
if ($result->num_rows() > 0) {
foreach ($result->result_array() as $row_result) {
$product_data[] = $row_result;
}
}
//return $result=$query->result();
}
}
?>
And that's my controller
<?php
Class UserProducts extends CI_Controller {
function index(){
$this->load->model("UserProducts_m");
$this->load->model("user");
$this->load->view("userproducts_v",array(
'userdata'=>$this->user->userdata(),
'userproducts'=>$this->UserProducts_m->index()
));
}
}
?>
that's my errors
Error Number: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select stock.s_p_id from stock and stock.s_company_id=1 and p_company_id=1)' at line 1
select products.* from products where !FIND_IN_SET(products.p_id,select stock.s_p_id from stock and stock.s_company_id=1 and p_company_id=1)
Filename: C:/xampp/htdocs/Elvan/system/database/DB_driver.php
Line Number: 691
I suggest you try putting curly braces around the vars in your query statement. Then it should resolve to array values properly.
$query="select products.* from products where
!find_in_set(products.p_id,select stock.s_p_id from stock and
stock.s_company_id = {$usercompanyid[0]['u_company_id']} and
p_company_id = {$usercompanyid[0]['u_company_id']})";
I see a couple other problems.
The line
$result= $this->db->get();
is not needed because $this->db->query($query); already returned a database result object. Do this
$result = $this->db->query($query);
if ($result->num_rows() > 0)
{ ...
Then you have this useless block of code (Pardon me for being blunt)
foreach ($result->result_array() as $row_result)
{
$product_data[] = $row_result;
}
This is useless because your code just copies array values from one array to another. You'll save a lot of code execution with the following which produces the same thing your foreach loop does.
$product_data = $result->result_array();
result->array() returns an array where each item is an array representing a table row.
You did the same thing earlier adding items to the $usercompanyid array. Do this.
if ($user_data->num_rows() > 0)
{
$usercompanyid = $query->result_array();
}
One last problem. It appears that UserProducts_m::index() does not return anything.
You can use the NOT IN sql query for this.
SELECT *
FROM products
WHERE product_id NOT IN (select field name form stock where clause);