mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Improvements for reports
This commit is contained in:
parent
212f5920e0
commit
61c84e08d8
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -5011,6 +5011,7 @@ $LANG = array(
|
||||
'add_company_logo' => 'Add Logo',
|
||||
'add_stripe' => 'Add Stripe',
|
||||
'invalid_coupon' => 'Invalid Coupon',
|
||||
'product_sales' => 'Product Sales',
|
||||
);
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user