273 lines
11 KiB
PHP
273 lines
11 KiB
PHP
<?php
|
|
|
|
namespace Modules\Manufacturing\Utils;
|
|
|
|
use App\Business;
|
|
use App\Transaction;
|
|
use App\TransactionSellLinesPurchaseLines;
|
|
use App\Utils\Util;
|
|
use App\Variation;
|
|
use DB;
|
|
use Modules\Manufacturing\Entities\MfgRecipeIngredient;
|
|
|
|
class ManufacturingUtil extends Util
|
|
{
|
|
/**
|
|
* Retrives ingredients details.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getIngredientDetails($recipe, $business_id, $location_id = null)
|
|
{
|
|
$ingredients_array = [];
|
|
$with = ['variation', 'variation.product', 'variation.product_variation', 'variation.product.unit'];
|
|
|
|
//If location given retrieve variation location details
|
|
if (! empty($location_id)) {
|
|
$with = ['variation', 'variation.product', 'variation.product_variation', 'ingredient_group', 'variation.product.unit',
|
|
'variation.variation_location_details' => function ($q) use ($location_id) {
|
|
$q->where('location_id', $location_id);
|
|
}, ];
|
|
}
|
|
|
|
$ingredient_variations = MfgRecipeIngredient::where('mfg_recipe_id', $recipe->id)
|
|
->with($with)
|
|
->orderBy('sort_order', 'asc')
|
|
->get();
|
|
|
|
//Format variation data
|
|
foreach ($ingredient_variations as $ingredient_variation) {
|
|
$variation = $ingredient_variation->variation;
|
|
//If base unit has sub_units get details
|
|
$sub_units = $this->getSubUnits($business_id, $variation->product->unit->id);
|
|
$unit_name = $variation->product->unit->short_name;
|
|
$is_sub_unit = false;
|
|
$sub_unit_id = null;
|
|
$multiplier = 1;
|
|
if (! empty($sub_units)) {
|
|
foreach ($sub_units as $key => $value) {
|
|
if (! empty($ingredient_variation->sub_unit_id) && $ingredient_variation->sub_unit_id == $key) {
|
|
$unit_name = $value['name'];
|
|
$sub_unit_id = $ingredient_variation->sub_unit_id;
|
|
$multiplier = $value['multiplier'];
|
|
}
|
|
}
|
|
$is_sub_unit = true;
|
|
}
|
|
|
|
$line_total_quantity = $ingredient_variation->quantity;
|
|
$unit_qty = $line_total_quantity * $multiplier;
|
|
|
|
if (! empty($recipe)) {
|
|
$recipe_base_unit_multiplier = ! empty($recipe->sub_unit) ? $recipe->sub_unit->base_unit_multiplier : 1;
|
|
$total_recipe_qty = ! empty($recipe_base_unit_multiplier) ? $recipe->total_quantity * $recipe_base_unit_multiplier : $recipe->total_quantity;
|
|
$unit_qty = $total_recipe_qty > 0 ? $unit_qty / $total_recipe_qty : 0;
|
|
}
|
|
$total_price = $variation->dpp_inc_tax * $line_total_quantity * $multiplier;
|
|
$waste_percent = ! empty($ingredient_variation->waste_percent) ? $ingredient_variation->waste_percent : 0;
|
|
|
|
$wasted_qty = $this->calc_percentage($line_total_quantity, $waste_percent);
|
|
$final_quantity = $line_total_quantity - $wasted_qty;
|
|
$ingredients[] = [
|
|
'dpp_inc_tax' => $variation->dpp_inc_tax,
|
|
'quantity' => $line_total_quantity,
|
|
'full_name' => $variation->full_name,
|
|
'variation_id' => $variation->id,
|
|
'id' => $ingredient_variation->id,
|
|
'unit' => $unit_name,
|
|
'allow_decimal' => $variation->product->unit->allow_decimal,
|
|
'variation' => $variation,
|
|
'enable_stock' => $variation->product->enable_stock,
|
|
'is_sub_unit' => $is_sub_unit,
|
|
'sub_units' => $sub_units,
|
|
'sub_unit_id' => $sub_unit_id,
|
|
'multiplier' => $multiplier,
|
|
'unit_quantity' => $unit_qty,
|
|
'total_price' => $total_price,
|
|
'waste_percent' => $waste_percent,
|
|
'final_quantity' => $final_quantity,
|
|
'mfg_ingredient_group_id' => $ingredient_variation->mfg_ingredient_group_id,
|
|
'ingredient_group_name' => ! empty($ingredient_variation->ingredient_group->name) ? $ingredient_variation->ingredient_group->name : '',
|
|
'ig_description' => ! empty($ingredient_variation->ingredient_group->description) ? $ingredient_variation->ingredient_group->description : '',
|
|
];
|
|
}
|
|
|
|
return $ingredients;
|
|
}
|
|
|
|
/**
|
|
* Retrives manufacturing settings.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getSettings($business_id)
|
|
{
|
|
$business = Business::findOrFail($business_id);
|
|
|
|
$settings = ! empty($business->manufacturing_settings) ? json_decode($business->manufacturing_settings, true) : [];
|
|
|
|
return $settings;
|
|
}
|
|
|
|
/**
|
|
* Calculates production totals.
|
|
*
|
|
* @param int $business_id
|
|
* @param int location_id = null
|
|
* @param string $start_date = null
|
|
* @param string $end_date = null
|
|
*/
|
|
public function getProductionTotals(
|
|
$business_id,
|
|
$location_id = null,
|
|
$start_date = null,
|
|
$end_date = null,
|
|
$user_id = null
|
|
) {
|
|
$query = Transaction::where('business_id', $business_id)
|
|
->where('type', 'production_purchase')
|
|
->where('mfg_is_final', 1)
|
|
->leftJoin('purchase_lines as pl', 'transactions.id', '=', 'pl.transaction_id')
|
|
->select(
|
|
DB::raw('SUM(final_total) as total_production'),
|
|
DB::raw("SUM(
|
|
IF(
|
|
mfg_production_cost_type='percentage',
|
|
final_total - ((final_total * 100) / (mfg_production_cost + 100) ),
|
|
IF(
|
|
mfg_production_cost_type='per_unit',
|
|
mfg_production_cost*pl.quantity,
|
|
mfg_production_cost
|
|
)
|
|
)
|
|
) as total_production_cost")
|
|
)
|
|
->groupBy('transactions.id');
|
|
|
|
//Check for permitted locations of a user
|
|
$permitted_locations = auth()->user()->permitted_locations();
|
|
if ($permitted_locations != 'all') {
|
|
$query->whereIn('transactions.location_id', $permitted_locations);
|
|
}
|
|
|
|
if (! empty($start_date) && ! empty($end_date)) {
|
|
$query->whereBetween(DB::raw('date(transaction_date)'), [$start_date, $end_date]);
|
|
}
|
|
|
|
if (empty($start_date) && ! empty($end_date)) {
|
|
$query->whereDate('transaction_date', '<=', $end_date);
|
|
}
|
|
|
|
//Filter by the location
|
|
if (! empty($location_id)) {
|
|
$query->where('transactions.location_id', $location_id);
|
|
}
|
|
|
|
if (! empty($user_id)) {
|
|
$query->where('transactions.created_by', $user_id);
|
|
}
|
|
|
|
$production_details = $query->get();
|
|
|
|
$output = [
|
|
'total_production' => $production_details->SUM('total_production'),
|
|
'total_production_cost' => $production_details->SUM('total_production_cost'),
|
|
];
|
|
|
|
return $output;
|
|
}
|
|
|
|
/**
|
|
* Calculates sum of total production sells.
|
|
*
|
|
* @param int $business_id
|
|
* @param int location_id = null
|
|
* @param string $start_date = null
|
|
* @param string $end_date = null
|
|
*/
|
|
public function getTotalSold(
|
|
$business_id,
|
|
$location_id = null,
|
|
$start_date = null,
|
|
$end_date = null
|
|
) {
|
|
$query = TransactionSellLinesPurchaseLines::join('purchase_lines as pl', 'pl.id', '=', 'transaction_sell_lines_purchase_lines.purchase_line_id')
|
|
->join('transaction_sell_lines as tsl', 'tsl.id', '=', 'transaction_sell_lines_purchase_lines.sell_line_id')
|
|
->join('transactions as t', 'pl.transaction_id', '=', 't.id')
|
|
->where('t.business_id', $business_id)
|
|
->where('t.type', 'production_purchase')
|
|
->select(DB::raw('SUM((tsl.quantity - tsl.quantity_returned) * tsl.unit_price_inc_tax) as total_sold'));
|
|
|
|
//Check for permitted locations of a user
|
|
$permitted_locations = auth()->user()->permitted_locations();
|
|
if ($permitted_locations != 'all') {
|
|
$query->whereIn('t.location_id', $permitted_locations);
|
|
}
|
|
|
|
if (! empty($start_date) && ! empty($end_date)) {
|
|
$query->whereBetween(DB::raw('date(transaction_date)'), [$start_date, $end_date]);
|
|
}
|
|
|
|
if (empty($start_date) && ! empty($end_date)) {
|
|
$query->whereDate('transaction_date', '<=', $end_date);
|
|
}
|
|
|
|
//Filter by the location
|
|
if (! empty($location_id)) {
|
|
$query->where('t.location_id', $location_id);
|
|
}
|
|
|
|
$sell_details = $query->get();
|
|
|
|
$total_sold = $sell_details->sum('total_sold');
|
|
|
|
return $total_sold;
|
|
}
|
|
|
|
/**
|
|
* Function to calculate recipe total dynamically for each row on
|
|
* Recipe list
|
|
*
|
|
* @return decimal
|
|
*/
|
|
public function getRecipeTotal($row)
|
|
{
|
|
$price = 0;
|
|
foreach ($row->ingredients as $ingredient) {
|
|
if (! empty($ingredient->variation)) {
|
|
$ingredient_total = $ingredient->variation->dpp_inc_tax * $ingredient->quantity;
|
|
if (! empty($ingredient->sub_unit)) {
|
|
$multiplier = ! empty($ingredient->sub_unit->base_unit_multiplier) ? $ingredient->sub_unit->base_unit_multiplier : 1;
|
|
$ingredient_total = $ingredient_total * $multiplier;
|
|
}
|
|
$price += $ingredient_total;
|
|
}
|
|
}
|
|
|
|
$production_cost = $row->extra_cost;
|
|
if ($row->production_cost_type == 'percentage') {
|
|
$production_cost = ($price * $row->extra_cost) / 100;
|
|
} elseif ($row->production_cost_type == 'per_unit') {
|
|
$production_cost = $row->extra_cost * $row->total_quantity;
|
|
}
|
|
$price = $price + $production_cost;
|
|
|
|
return $price;
|
|
}
|
|
|
|
public function getProductionCost($recipe)
|
|
{
|
|
$total_production_cost = 0;
|
|
if (! empty($recipe->extra_cost)) {
|
|
$total_production_cost = $recipe->extra_cost;
|
|
if ($recipe->production_cost_type == 'percentage') {
|
|
$total_production_cost = $this->calc_percentage($recipe->ingredients_cost, $recipe->extra_cost);
|
|
} elseif ($recipe->production_cost_type == 'per_unit') {
|
|
$total_production_cost = $recipe->extra_cost * $recipe->total_quantity;
|
|
}
|
|
}
|
|
|
|
return $total_production_cost;
|
|
}
|
|
}
|