diff --git a/app/Exports/CarsExport.php b/app/Exports/CarsExport.php
new file mode 100644
index 0000000..e303b5c
--- /dev/null
+++ b/app/Exports/CarsExport.php
@@ -0,0 +1,51 @@
+car = $car;
+ $this->headings = $headings;
+ }
+
+ public function headings(): array
+ {
+ return $this->headings;
+ }
+
+ // public function map($car): array
+ // {
+ // $contract = $car->latestBuyContract();
+
+ // return [
+ // $car->name,
+ // $car->stammnummer,
+ // $car->initial_date_formatted,
+ // $contract ? $contract->date_formatted : null,
+ // $contract ? $contract->price : null,
+ // ];
+ // }
+
+ public function collection()
+ {
+ return $this->car;
+ }
+
+ public function styles(Worksheet $sheet)
+ {
+ return [
+ 1 => ['font' => ['bold' => true]],
+ ];
+ }
+}
diff --git a/app/Exports/ContractsExport.php b/app/Exports/ContractsExport.php
index 1e63051..99ae48f 100644
--- a/app/Exports/ContractsExport.php
+++ b/app/Exports/ContractsExport.php
@@ -24,9 +24,4 @@ class ContractsExport implements WithMultipleSheets
return $sheets;
}
-
- public function collection()
- {
- return Contract::whereYear('date', '=', $this->year)->orderBy('date', 'asc')->get();
- }
}
diff --git a/app/Exports/UnsoldCarsExport.php b/app/Exports/UnsoldCarsExport.php
new file mode 100644
index 0000000..e915737
--- /dev/null
+++ b/app/Exports/UnsoldCarsExport.php
@@ -0,0 +1,32 @@
+latestBuyContract();
+
+ return [
+ $car->name,
+ $car->stammnummer,
+ $car->initial_date_formatted,
+ $contract ? $contract->date_formatted : null,
+ $contract ? $contract->price : null,
+ ];
+ }
+}
diff --git a/app/Http/Controllers/CarController.php b/app/Http/Controllers/CarController.php
index 63c0249..0c57263 100644
--- a/app/Http/Controllers/CarController.php
+++ b/app/Http/Controllers/CarController.php
@@ -8,10 +8,12 @@ use Inertia\Inertia;
use App\Models\Brand;
use App\Models\Contract;
use App\Enums\ContractType;
+use App\Exports\CarsExport;
use App\Enums\InsuranceType;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\DB;
+use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Redirect;
class CarController extends Controller
@@ -32,6 +34,103 @@ class CarController extends Controller
return $this->renderCarsList($request, Car::soldOnly(), 'Cars/Sold', 'sell_contract.date');
}
+ public function print(Request $request)
+ {
+ $headings = [
+ 'Name',
+ 'Stammnummer',
+ 'Einkaufsdatum',
+ 'Einkaufspreis',
+ 'Verkaufsdatum',
+ 'Verkaufspreis',
+ 'Profit',
+ ];
+
+ $direction = $this->getDirection($request, 'desc');
+ $sortBy = $this->getSortBy($request, 'buy_contract.date');
+ $cars = $this->getWithCustomSort(Car::query(), $sortBy, $direction)
+ ->filter($request->only('search', 'trashed'))
+ ->get()
+ ->map(function ($car) {
+ $bcontract = $car->latestBuyContract();
+ $scontract = $car->latestSellContract();
+ return [
+ 'name' => $car->name,
+ 'stammnummer' => $car->stammnummer,
+ 'buy_date' => $bcontract ? $bcontract->date_formatted : null,
+ 'buy_price' => $bcontract ? $bcontract->price : null,
+ 'sell_date' => $scontract ? $scontract->date_formatted : null,
+ 'sell_price' => $scontract ? $scontract->price : null,
+ 'profit' => $car->latestProfit(),
+ ];
+ });
+
+ return Excel::download(new CarsExport($cars, $headings), date('Y-m-d') . '-Alle-Autos.xlsx');
+ }
+
+ public function unsoldPrint(Request $request)
+ {
+ $headings = [
+ 'Name',
+ 'Stammnummer',
+ 'Inverkehrssetzung',
+ 'Einkaufsdatum',
+ 'Einkaufspreis',
+ ];
+
+ $direction = $this->getDirection($request, 'desc');
+ $sortBy = $this->getSortBy($request, 'buy_contract.date');
+ $cars = $this->getWithCustomSort(Car::unsoldOnly(), $sortBy, $direction)
+ ->filter($request->only('search', 'trashed'))
+ ->get()
+ ->map(function ($car) {
+ $contract = $car->latestBuyContract();
+ return [
+ 'name' => $car->name,
+ 'stammnummer' => $car->stammnummer,
+ 'initial_date' => $car->initial_date_formatted,
+ 'buy_date' => $contract ? $contract->date_formatted : null,
+ 'price' => $contract ? $contract->price : null,
+ ];
+ });
+
+ return Excel::download(new CarsExport($cars, $headings), date('Y-m-d') . '-Meine-Autos.xlsx');
+ }
+
+ public function soldPrint(Request $request)
+ {
+ $headings = [
+ 'Name',
+ 'Stammnummer',
+ 'Einkaufsdatum',
+ 'Einkaufspreis',
+ 'Verkaufsdatum',
+ 'Verkaufspreis',
+ 'Profit',
+ ];
+
+ $direction = $this->getDirection($request, 'desc');
+ $sortBy = $this->getSortBy($request, 'buy_contract.date');
+ $cars = $this->getWithCustomSort(Car::soldOnly(), $sortBy, $direction)
+ ->filter($request->only('search', 'trashed'))
+ ->get()
+ ->map(function ($car) {
+ $bcontract = $car->latestBuyContract();
+ $scontract = $car->latestSellContract();
+ return [
+ 'name' => $car->name,
+ 'stammnummer' => $car->stammnummer,
+ 'buy_date' => $bcontract ? $bcontract->date_formatted : null,
+ 'buy_price' => $bcontract ? $bcontract->price : null,
+ 'sell_date' => $scontract ? $scontract->date_formatted : null,
+ 'sell_price' => $scontract ? $scontract->price : null,
+ 'profit' => $car->latestProfit(),
+ ];
+ });
+
+ return Excel::download(new CarsExport($cars, $headings), date('Y-m-d') . '-Verkaufte-Autos.xlsx');
+ }
+
private function renderCarsList(Request $request, $cars, string $renderPage, string $defaultSort = 'buy_contract.date') {
$direction = $this->getDirection($request, 'desc');
$sortBy = $this->getSortBy($request, $defaultSort);
diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php
index 4fda089..d3cac25 100644
--- a/app/Http/Controllers/ReportController.php
+++ b/app/Http/Controllers/ReportController.php
@@ -16,17 +16,6 @@ class ReportController extends Controller
return Inertia::render('Reports/Index', ['year' => (int)date('Y'), 'years' => array_reverse(range((int)date('Y') - 20, (int)date('Y')))]);
}
- private function getYearsArray($start)
- {
- $currentYear = (int)date('Y');
- $years = [$currentYear];
- if ($start < $currentYear) {
- for ($y = $start; $y < $currentYear; $y++) {
- $years[] = $y;
- }
- }
- }
-
public function print(Request $request)
{
$year = (int)$request->get('year');
diff --git a/public/js/app.js b/public/js/app.js
index fb3eb17..965dd04 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -18597,13 +18597,16 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _Components_Paginator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @/Components/Paginator */ "./resources/js/Components/Paginator.vue");
-/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lodash */ "./node_modules/lodash/lodash.js");
-/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(lodash__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _Components_Buttons_StandardButton_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @/Components/Buttons/StandardButton.vue */ "./resources/js/Components/Buttons/StandardButton.vue");
+/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! lodash */ "./node_modules/lodash/lodash.js");
+/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(lodash__WEBPACK_IMPORTED_MODULE_2__);
+
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
components: {
- Paginator: _Components_Paginator__WEBPACK_IMPORTED_MODULE_0__.default
+ Paginator: _Components_Paginator__WEBPACK_IMPORTED_MODULE_0__.default,
+ StandardButton: _Components_Buttons_StandardButton_vue__WEBPACK_IMPORTED_MODULE_1__.default
},
props: {
data: Object,
@@ -18611,7 +18614,8 @@ __webpack_require__.r(__webpack_exports__);
title: String,
currentRoute: String,
defaultSort: Object,
- filters: Object
+ filters: Object,
+ print: Boolean
},
data: function data() {
return {
@@ -18622,7 +18626,7 @@ __webpack_require__.r(__webpack_exports__);
watch: {
form: {
deep: true,
- handler: (0,lodash__WEBPACK_IMPORTED_MODULE_1__.throttle)(function () {
+ handler: (0,lodash__WEBPACK_IMPORTED_MODULE_2__.throttle)(function () {
this.refreshTable();
}, 300)
}
@@ -18651,13 +18655,13 @@ __webpack_require__.r(__webpack_exports__);
});
},
reset: function reset() {
- this.form = (0,lodash__WEBPACK_IMPORTED_MODULE_1__.mapValues)(this.form, function () {
+ this.form = (0,lodash__WEBPACK_IMPORTED_MODULE_2__.mapValues)(this.form, function () {
return null;
});
},
refreshTable: function refreshTable() {
if (this.currentRoute) {
- this.$inertia.get(this.route(this.currentRoute), (0,lodash__WEBPACK_IMPORTED_MODULE_1__.pickBy)(this.form), {
+ this.$inertia.get(this.route(this.currentRoute), (0,lodash__WEBPACK_IMPORTED_MODULE_2__.pickBy)(this.form), {
preserveState: true
});
}
@@ -24047,39 +24051,42 @@ var _hoisted_5 = {
var _hoisted_6 = {
"class": "flex w-full bg-white shadow rounded"
};
-var _hoisted_7 = {
+
+var _hoisted_7 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Excel-Export ");
+
+var _hoisted_8 = {
key: 2,
"class": "bg-white rounded-md shadow overflow-x-auto"
};
-var _hoisted_8 = {
+var _hoisted_9 = {
"class": "w-full whitespace-nowrap"
};
-var _hoisted_9 = {
+var _hoisted_10 = {
"class": "text-left font-bold"
};
-var _hoisted_10 = {
+var _hoisted_11 = {
key: 1,
"class": "flex items-center"
};
-var _hoisted_11 = {
+var _hoisted_12 = {
key: 2,
"class": "px-6 py-4 flex items-center"
};
-var _hoisted_12 = {
+var _hoisted_13 = {
key: 0,
"class": "border-t w-px"
};
-var _hoisted_13 = {
+var _hoisted_14 = {
key: 0
};
-var _hoisted_14 = {
+var _hoisted_15 = {
key: 3
};
-var _hoisted_15 = {
+var _hoisted_16 = {
"class": "inline-flex font-medium text-gray-500 ml-3"
};
-var _hoisted_16 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Keine Einträge gefunden ");
+var _hoisted_17 = /*#__PURE__*/(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(" Keine Einträge gefunden ");
function render(_ctx, _cache, $props, $setup, $data, $options) {
var _this = this;
@@ -24111,7 +24118,23 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
}),
type: "button",
"class": "ml-3 text-sm text-gray-500 hover:text-gray-700 focus:text-blue-200"
- }, "Reset")])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.data.total > 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("div", _hoisted_7, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("table", _hoisted_8, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("tr", _hoisted_9, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.columns, function (col, index) {
+ }, "Reset")]), $props.print ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("a", {
+ key: 0,
+ href: _ctx.route($props.currentRoute + '.print', {
+ search: $data.form.search,
+ sortBy: $data.sort.by,
+ direction: $data.sort.direction
+ }),
+ "class": "justify-center inline-flex items-center px-4 py-2 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest focus:outline-none focus:ring disabled:opacity-25 transition bg-green-800 hover:bg-green-700 active:bg-green-900 focus:border-green-900 focus:ring-green-300 py-3"
+ }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_unicon, {
+ fill: "white",
+ "class": "mr-2",
+ height: "24",
+ width: "24",
+ name: "chart"
+ }), _hoisted_7], 8
+ /* PROPS */
+ , ["href"])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.data.total > 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("div", _hoisted_8, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("table", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("tr", _hoisted_10, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.columns, function (col, index) {
return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("th", {
key: col.key,
"class": "px-6 pt-4 pb-4",
@@ -24139,7 +24162,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
name: "arrow-down"
})) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 8
/* PROPS */
- , ["onClick"])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("span", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(col.value), 1
+ , ["onClick"])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("span", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(col.value), 1
/* TEXT */
))], 8
/* PROPS */
@@ -24182,12 +24205,12 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
name: "trash-alt"
})], 8
/* PROPS */
- , ["onClick"])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("span", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.resolve(col.key, row)), 1
+ , ["onClick"])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("span", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($options.resolve(col.key, row)), 1
/* TEXT */
))]);
}), 128
/* KEYED_FRAGMENT */
- )), row.link ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("td", _hoisted_12, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_inertia_link, {
+ )), row.link ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("td", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_inertia_link, {
"class": "px-4 flex items-center",
href: row.link,
tabindex: "-1"
@@ -24208,18 +24231,18 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
, ["href"])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)]);
}), 128
/* KEYED_FRAGMENT */
- )), $props.data.total === 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("tr", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("td", {
+ )), $props.data.total === 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("tr", _hoisted_14, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("td", {
"class": "border-t px-6 py-4",
colspan: $props.columns.length
}, "Keine Einträge gefunden", 8
/* PROPS */
- , ["colspan"])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)])])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("div", _hoisted_14, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("span", _hoisted_15, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_unicon, {
+ , ["colspan"])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)])])) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)("div", _hoisted_15, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)("span", _hoisted_16, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_unicon, {
fill: "#7e8491",
"class": "mr-2",
height: "24",
width: "24",
name: "meh"
- }), _hoisted_16])]))]), $props.data.links ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(_component_Paginator, {
+ }), _hoisted_17])]))]), $props.data.links ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(_component_Paginator, {
key: 0,
"class": "mt-6",
links: $props.data.links
@@ -27936,7 +27959,8 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
columns: $data.columns,
defaultSort: $props.sort,
filters: $props.filters,
- currentRoute: $data.currentRoute
+ currentRoute: $data.currentRoute,
+ print: true
}, null, 8
/* PROPS */
, ["title", "data", "columns", "defaultSort", "filters", "currentRoute"])])];
@@ -28173,7 +28197,8 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
columns: $data.columns,
defaultSort: $props.sort,
filters: $props.filters,
- currentRoute: $data.currentRoute
+ currentRoute: $data.currentRoute,
+ print: true
}, null, 8
/* PROPS */
, ["title", "data", "columns", "defaultSort", "filters", "currentRoute"])])];
@@ -28231,7 +28256,8 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
columns: $data.columns,
defaultSort: $props.sort,
filters: $props.filters,
- currentRoute: $data.currentRoute
+ currentRoute: $data.currentRoute,
+ print: true
}, null, 8
/* PROPS */
, ["title", "data", "columns", "defaultSort", "filters", "currentRoute"])])];
diff --git a/resources/js/Components/SimpleTable.vue b/resources/js/Components/SimpleTable.vue
index 34e46f1..5039187 100644
--- a/resources/js/Components/SimpleTable.vue
+++ b/resources/js/Components/SimpleTable.vue
@@ -11,6 +11,10 @@
+
+