ultimatepos/Modules/Manufacturing/Utils/ManufacturingUtil.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;
}
}