mivita/app/Http/Controllers/Admin/PaymentSalesController.php
Kevin d01b9bca3a Absatzmengen: nach Warenausgang (Versanddatum) oder nach Rechnung auswertbar
- shopping_orders.shipped_at (+ Herkunft live/dhl/geschaetzt): gesetzt im
  Model, sobald der Versandstatus auf versendet wechselt, egal an welcher
  Stelle der Status gesetzt wird. sales:backfill-shipped-at traegt
  Altbestellungen aus dem DHL-Label nach oder schaetzt.
- SalesVolumeService rechnet Absatzmengen je Produkt wahlweise nach
  Versand (inkl. externer/API-Bestellungen, Stornos im Monat des
  Stornobelegs) oder nach Rechnung. Sets werden fuer die zweite Liste in
  Einzelartikel aufgeloest.
- Admin-Seite: Umschalter Versand/Rechnung, Datenqualitaet (Anteil
  geschaetzter Versanddaten), Export Produkte und Einzelartikel.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:42:39 +00:00

188 lines
6.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers\Admin;
use App\Exports\UserTeamExport;
use App\Exports\xExport;
use App\Http\Controllers\Controller;
use App\Services\HTMLHelper;
use App\Services\SalesVolumeService;
use Maatwebsite\Excel\Facades\Excel;
use Request;
/**
* Absatzmengen je Produkt – wahlweise nach Versand (Warenausgang) oder nach
* Rechnungseingang (Zahlung). Die eigentliche Ermittlung liegt in
* {@see SalesVolumeService}, hier stehen nur Filter, Datatables und Exporte.
*/
class PaymentSalesController extends Controller
{
/** Zweite Liste der Seite: Sets/Kits in ihre Anlagen aufgeloest. */
private const LIST_ARTICLES = 'articles';
public function __construct()
{
$this->middleware('admin');
}
public function index()
{
$service = $this->makeService();
$data = [
'filter_months' => HTMLHelper::getTransMonths(),
'filter_years' => HTMLHelper::getYearRange(2022),
'filter_basis' => SalesVolumeService::basisOptions(),
'basis' => $service->getBasis(),
'basis_label' => $service->getBasisLabel(),
'quality' => $service->getQualityStats(),
];
return view('admin.payment.salesvolume', $data);
}
public function datatable()
{
$service = $this->makeService();
$objects = Request::get('list') === self::LIST_ARTICLES
? $service->getArticleVolumes()
: $service->getProductVolumes();
$collection = collect();
foreach ($objects as $key => $obj) {
$collection->push([
'id' => $obj['product_id'] ?: $key,
'name' => $obj['name'],
'number' => $obj['number'],
'value' => $obj['value'],
]);
}
return \DataTables::of($collection)->toJson();
}
public function download()
{
if (Request::get('action') === 'exportfull_paid_invoice') {
return $this->exportFullList();
}
if (Request::get('action') === 'export_articles') {
return $this->exportKompaktList(self::LIST_ARTICLES);
}
if (Request::get('action') === 'export') {
return $this->exportKompaktList();
}
}
private function exportKompaktList(?string $list = null)
{
$service = $this->makeService();
$objects = $list === self::LIST_ARTICLES
? $service->getArticleVolumes()
: $service->getProductVolumes();
$columns = [];
$headers = ['#', 'Produkt', 'Artikelnummer', 'Menge'];
foreach ($objects as $key => $obj) {
$columns[] = [
'id' => $obj['product_id'] ?: $key,
'name' => $obj['name'],
'number' => $obj['number'],
'value' => $obj['value'],
];
}
$filename = 'mivita-absatzmengen-'.$this->getBasisSlug().'-'
.($list === self::LIST_ARTICLES ? 'einzelartikel' : 'kompakt').'-'
.session('payment_sales_vol_filter_month').'_'.session('payment_sales_vol_filter_year').'-export';
return Excel::download(new UserTeamExport($columns, $headers), $filename.'.xls');
}
private function exportFullList()
{
$service = $this->makeService();
$isShipping = $service->getBasis() === SalesVolumeService::BASIS_SHIPPING;
$headers = [
$isShipping ? 'Bestellung' : 'Rechnungsnummer',
$isShipping ? 'Versanddatum' : 'Rechnungsdatum',
'EMail',
'Zahlung',
'ProduktNummer',
'ProduktName',
'Anzahl',
'Summe',
'Hinweis',
];
$columns = [];
$total = [];
foreach ($service->getRows() as $row) {
$key = $row['product_id'] ?: $row['number'];
$total[$key] = ($total[$key] ?? 0) + $row['qty'];
$columns[] = [
'ref' => $row['ref'],
'date' => $row['date'],
'email' => $row['email'],
'payment' => $row['payment_type'],
'number' => $row['number'],
'name' => $row['name'],
'qty' => $row['qty'],
'sum' => $total[$key],
'note' => $row['note'],
];
}
$filename = 'mivita-absatzmengen-'.$this->getBasisSlug().'-voll-'
.session('payment_sales_vol_filter_month').'_'.session('payment_sales_vol_filter_year').'-export';
return Excel::download(new xExport($columns, $headers), $filename.'.xls');
}
private function makeService(): SalesVolumeService
{
$this->setFilterVars();
return new SalesVolumeService(
(int) session('payment_sales_vol_filter_month'),
(int) session('payment_sales_vol_filter_year'),
(string) session('payment_sales_vol_filter_basis'),
);
}
private function getBasisSlug(): string
{
return session('payment_sales_vol_filter_basis') === SalesVolumeService::BASIS_INVOICE
? 'rechnung'
: 'versand';
}
private function setFilterVars(): void
{
if (! session('payment_sales_vol_filter_month')) {
session(['payment_sales_vol_filter_month' => intval(date('m'))]);
}
if (! session('payment_sales_vol_filter_year')) {
session(['payment_sales_vol_filter_year' => intval(date('Y'))]);
}
if (! session('payment_sales_vol_filter_basis')) {
session(['payment_sales_vol_filter_basis' => SalesVolumeService::BASIS_SHIPPING]);
}
if (Request::get('payment_sales_vol_filter_month')) {
session(['payment_sales_vol_filter_month' => Request::get('payment_sales_vol_filter_month')]);
}
if (Request::get('payment_sales_vol_filter_year')) {
session(['payment_sales_vol_filter_year' => Request::get('payment_sales_vol_filter_year')]);
}
if (Request::get('payment_sales_vol_filter_basis')) {
session(['payment_sales_vol_filter_basis' => Request::get('payment_sales_vol_filter_basis')]);
}
}
}