Improvements for reports

This commit is contained in:
David Bomba 2023-03-01 22:18:27 +11:00
parent 212f5920e0
commit 61c84e08d8
3 changed files with 149 additions and 14 deletions

View File

@ -11,14 +11,14 @@
namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Document;
use App\Models\Invoice;
use App\Utils\Ninja;
use League\Csv\Writer;
use App\Models\Company;
use App\Models\Invoice;
use App\Models\Product;
use App\Libraries\MultiDB;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App;
use League\Csv\Writer;
class ProductSalesExport extends BaseExport
{
@ -28,6 +28,13 @@ class ProductSalesExport extends BaseExport
protected $date_key = 'created_at';
protected $products;
public Writer $csv;
private $sales;
//translations => keys
protected array $entity_keys = [
'custom_value1' => 'custom_value1',
'custom_value2' => 'custom_value2',
@ -35,23 +42,30 @@ class ProductSalesExport extends BaseExport
'custom_value4' => 'custom_value4',
'product_key' => 'product_key',
'notes' => 'notes',
'cost' => 'cost',
'price' => 'price',
'quantity' => 'quantity',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'cost' => 'price',
'price' => 'cost',
'markup' => 'markup',
'discount' => 'discount',
'net_total' => 'net_total',
'profit' => 'profit',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
'tax_name3' => 'tax_name3',
'tax_rate1' => 'tax_rate1',
'tax_rate2' => 'tax_rate2',
'tax_rate3' => 'tax_rate3',
'tax_amount1' => 'tax_amount1',
'tax_amount2' => 'tax_amount2',
'tax_amount3' => 'tax_amount3',
'is_amount_discount' => 'is_amount_discount',
'discount' => 'discount',
'line_total' => 'line_total',
'gross_line_total' => 'gross_line_total',
'status' => 'status',
'date' => 'date',
'currency' => 'currency',
'client' => 'client',
];
private array $decorate_keys = [
@ -64,6 +78,7 @@ class ProductSalesExport extends BaseExport
{
$this->company = $company;
$this->input = $input;
$this->sales = collect();
}
public function run()
@ -74,6 +89,8 @@ class ProductSalesExport extends BaseExport
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
$this->products = Product::where('company_id', $this->company->id)->withTrashed()->get();
//load the CSV document from a string
$this->csv = Writer::createFromString();
@ -99,6 +116,31 @@ class ProductSalesExport extends BaseExport
}
});
$grouped = $this->sales->groupBy('product_key')->map(function ($key, $value){
$data = [
'product' => $value,
'quantity' => $key->sum('quantity'),
'markup' => $key->sum('markup'),
'profit' => $key->sum('profit'),
'net_total' => $key->sum('net_total'),
'discount' => $key->sum('discount'),
'line_total' => $key->sum('line_total'),
'tax_name1' => $key->whereNotNull('tax_name1')->where('tax_name1', '!=', '')->first() ? $key->whereNotNull('tax_name1')->where('tax_name1', '!=', '')->first()['tax_name1'] : '',
'tax_name2' => $key->whereNotNull('tax_name2')->where('tax_name2', '!=', '')->first() ? $key->whereNotNull('tax_name2')->where('tax_name2', '!=', '')->first()['tax_name2'] : '',
'tax_name3' => $key->whereNotNull('tax_name3')->where('tax_name3', '!=', '')->first() ? $key->whereNotNull('tax_name3')->where('tax_name3', '!=', '')->first()['tax_name3'] : '',
'tax_amount1' => $key->sum('tax_amount1'),
'tax_amount2' => $key->sum('tax_amount2'),
'tax_amount3' => $key->sum('tax_amount3'),
];
return $data;
});
nlog($grouped);
return $this->csv->toString();
}
@ -117,17 +159,109 @@ class ProductSalesExport extends BaseExport
$entity[$keyval] = '';
}
}
$entity = $this->decorateAdvancedFields($invoice, $entity);
$this->sales->push($entity);
return $entity;
return $this->decorateAdvancedFields($invoice, $entity);
}
private function decorateAdvancedFields(Invoice $invoice, $entity) :array
{
{
$product = $this->getProduct($entity['product_key']);
$entity['cost'] = $product->cost ?? 0;
$unit_cost = $entity['cost'] == 0 ? 1 : $entity['cost'];
$entity['client'] = $invoice->client->present()->name();
$entity['currency'] = $invoice->client->currency()->code;
$entity['status'] = $invoice->stringStatus($invoice->status_id);
$entity['date'] = Carbon::parse($invoice->date)->format($this->company->date_format());
$entity['discount'] = $this->calculateDiscount($invoice, $entity);
$entity['markup'] = round(((($entity['price'] - $entity['discount'] - $entity['cost']) / $unit_cost) * 100),2);
$entity['net_total'] = $entity['price'] - $entity['discount'];
$entity['profit'] = $entity['price'] - $entity['discount'] - $entity['cost'];
if(strlen($entity['tax_name1']) > 1) {
$entity['tax_name1'] = $entity['tax_name1'] . ' [' . $entity['tax_rate1'] . '%]';
$entity['tax_amount1'] = $this->calculateTax($invoice, $entity['line_total'], $entity['tax_rate1']);
}
else
$entity['tax_amount1'] = 0;
if(strlen($entity['tax_name2']) > 1) {
$entity['tax_name2'] = $entity['tax_name2'] . ' [' . $entity['tax_rate2'] . '%]';
$entity['tax_amount2'] = $this->calculateTax($invoice, $entity['line_total'], $entity['tax_rate2']);
}
else
$entity['tax_amount2'] = 0;
if(strlen($entity['tax_name3']) > 1) {
$entity['tax_name3'] = $entity['tax_name3'] . ' [' . $entity['tax_rate3'] . '%]';
$entity['tax_amount3'] = $this->calculateTax($invoice, $entity['line_total'], $entity['tax_rate3']);
}
else
$entity['tax_amount3'] = 0;
return $entity;
}
/**
* calculateTax
*
* @param mixed $invoice
* @param float $amount
* @param float $tax_rate
* @return float
*/
private function calculateTax(Invoice $invoice, float $amount, float $tax_rate): float
{
$amount = $amount - ($amount * ($invoice->discount / 100));
if($invoice->uses_inclusive_taxes) {
return round($amount - ($amount / (1 + ($tax_rate / 100))), 2);
}
else {
return round(($amount * $tax_rate / 100), 2);
}
}
/**
* calculateDiscount
*
* @param mixed $invoice
* @param mixed $entity
* @return float
*/
private function calculateDiscount(Invoice $invoice , $entity) :float
{
if($entity['discount'] == 0)
return 0;
if($invoice->is_amount_discount && $entity['discount'] != 0) {
return $entity['discount'];
}
elseif(!$invoice->is_amount_discount && $entity['discount'] != 0) {
return round($entity['line_total'] * ($entity['discount'] / 100), 2);
}
return 0;
}
/**
* getProduct
*
* @param string $product_key
* @return Product
*/
private function getProduct(string $product_key) :?Product
{
return $this->products->firstWhere('product_key', $product_key);
}
}

View File

@ -36,7 +36,7 @@ class ProductSalesReportRequest extends Request
'start_date' => 'bail|required_if:date_range,custom|nullable|date',
'report_keys' => 'bail|present|array',
'send_email' => 'bail|required|bool',
'client_id' => 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id.',is_deleted,0',
'client_id' => 'bail|nullable|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id.',is_deleted,0',
];
}

View File

@ -5011,6 +5011,7 @@ $LANG = array(
'add_company_logo' => 'Add Logo',
'add_stripe' => 'Add Stripe',
'invalid_coupon' => 'Invalid Coupon',
'product_sales' => 'Product Sales',
);