diff --git a/app/Http/Controllers/Api/InvoiceController.php b/app/Http/Controllers/Api/InvoiceController.php new file mode 100644 index 0000000..18dac0c --- /dev/null +++ b/app/Http/Controllers/Api/InvoiceController.php @@ -0,0 +1,70 @@ +json(Invoice::whereBetween('created_at', [$from, $end])->with('address')->orderBy('created_at', 'desc')->get()); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request): JsonResponse + { + $invoiceData = $request->validate([ + 'customer_id' => 'required|integer|exists:customers,id', + 'address_id' => 'required|integer|exists:addresses,id', + 'delivery_id' => 'nullable|integer|exists:addresses,id', + 'tax' => 'required|numeric', + 'sum' => 'required|numeric', + ]); + $invoiceData['user_id'] = auth()->id(); + $invoiceData['type'] = '380'; + $invoiceData['status'] = 'created'; + $invoiceData['invoice_number'] = Invoice::whereYear('created_at', now()->year)->count() + 1; + + + + $invoice = new Invoice($invoiceData); + $invoice->save(); + + return response()->json($invoice); + } + + /** + * Display the specified resource. + */ + public function show(Invoice $invoice) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, Invoice $invoice) + { + // + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Invoice $invoice) + { + // + } +} diff --git a/app/Http/Controllers/Api/InvoiceitemController.php b/app/Http/Controllers/Api/InvoiceitemController.php new file mode 100644 index 0000000..2bca81c --- /dev/null +++ b/app/Http/Controllers/Api/InvoiceitemController.php @@ -0,0 +1,64 @@ +json($invoice->items); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request, Invoice $invoice): JsonResponse + { + $itemData = $request->validate([ + 'amount' => 'required|numeric|min:0', + 'discount' => 'numeric|nullable', + 'tax' => 'required|numeric|min:0', + 'price' => 'required|numeric|min:0', + 'total' => 'required|numeric|min:0', + 'name' => 'required|string', + 'description' => 'nullable|string', + + ]); + + $item = $invoice->items()->create($itemData); + return response()->json($item); + } + + /** + * Display the specified resource. + */ + public function show(Invoiceitem $invoiceitem) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, Invoiceitem $invoiceitem) + { + // + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Invoiceitem $invoiceitem) + { + // + } +} diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php new file mode 100644 index 0000000..2081732 --- /dev/null +++ b/app/Http/Controllers/InvoiceController.php @@ -0,0 +1,41 @@ + $invoice]); + } + + /** + * Show the form for editing the specified resource. + */ + public function edit(Invoice $invoice) + { + // + } +} diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index cbc8919..35f3435 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -3,8 +3,77 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; class Invoice extends Model { - // + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'user_id', + 'customer_id', + 'address_id', + 'delivery_id', + 'invoice_number', + 'type', + 'status', + 'sum', + 'tax', + ]; + + /** + * The attributes that are appended with attribute getters. + * + * @var string[] + */ + protected $appends = [ + 'created', + 'number' + ]; + + /** + * Get the invoice number formatted + */ + public function getNumberAttribute(): string + { + return $this->created_at->format('Y') . '-' . str_pad($this->invoice_number, 5, '0', STR_PAD_LEFT); + } + + /** + * Get the created_at attribute in local time format. + * + * @return string + */ + public function getCreatedAttribute(): string + { + return $this->created_at->format('d.m.Y'); + } + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } + + public function customer(): BelongsTo + { + return $this->belongsTo(Customer::class); + } + + public function address(): BelongsTo + { + return $this->belongsTo(Address::class)->withTrashed(); + } + + public function delivery(): BelongsTo + { + return $this->belongsTo(Address::class)->withTrashed(); + } + + public function items(): HasMany + { + return $this->hasMany(Invoiceitem::class); + } } diff --git a/app/Models/Invoiceitem.php b/app/Models/Invoiceitem.php index ba5c845..bd126a3 100644 --- a/app/Models/Invoiceitem.php +++ b/app/Models/Invoiceitem.php @@ -7,5 +7,20 @@ use Illuminate\Database\Eloquent\SoftDeletes; class Invoiceitem extends Model { - use SoftDeletes; + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'invoice_id', + 'amount', + 'discount', + 'tax', + 'price', + 'total', + 'name', + 'description', + ]; + } diff --git a/lang/de/invoice.php b/lang/de/invoice.php new file mode 100644 index 0000000..a2c4d5e --- /dev/null +++ b/lang/de/invoice.php @@ -0,0 +1,37 @@ + 'Rechnungen', + 'Invoice' => 'Rechnung', + 'Add new invoice' => 'Neue Rechnung erstellen', + 'Add new invoice by clicking add' => 'Durch Klick auf "Anlegen" neue Rechnung erstellen', + 'Existing invoices' => 'Bestehende Rechnungen', + 'Create new invoice' => 'Neue Rechnung anlegen', + 'Select customer' => 'Kunde auswählen', + 'Select your customer and address' => 'Wähle einen Kunden und seine Adresse aus', + 'Invoice item' => 'Rechnungsposition', + 'Invoice items' => 'Rechnungspositionen', + 'Amount' => 'Menge', + 'Name' => 'Bezeichnung', + 'Price' => 'Preis', + 'Tax' => 'MwSt.', + 'Description' => 'Beschreibung', + 'State' => 'Status', + 'Invoice Number' => 'Rechnungsnummer', + 'Sum' => 'Summe', + 'Net' => 'Nettobetrag', + 'From' => 'Von', + 'End' => 'Bis', + 'Enter your invoice items. Click add for an additional invoice item.' => 'Gib Deine Rechnungspositionen ein. Klicke auf "Hinzufügen" für weitere Rechnungspositionen.', +]; diff --git a/resources/views/components/delivery-card.blade.php b/resources/views/components/delivery-card.blade.php new file mode 100644 index 0000000..a46f0bf --- /dev/null +++ b/resources/views/components/delivery-card.blade.php @@ -0,0 +1,10 @@ +
{{ __('customer.Delivery Address') }}
+
+
+
+
+
+
+
+
diff --git a/resources/views/components/invoice-item.blade.php b/resources/views/components/invoice-item.blade.php new file mode 100644 index 0000000..366db80 --- /dev/null +++ b/resources/views/components/invoice-item.blade.php @@ -0,0 +1,15 @@ +
+
{{ $item->amount }}
+
{{ $item->name }}
+
{{ \Illuminate\Support\Number::currency($item->price) }}
+
{{ \Illuminate\Support\Number::percentage($item->tax) }}
+
{{ \Illuminate\Support\Number::currency($item->total) }}
+
+
+
+
{!! nl2br($item->description) !!}
+
+
+
+
+ diff --git a/resources/views/components/php-card.blade.php b/resources/views/components/php-card.blade.php new file mode 100644 index 0000000..b3ee24c --- /dev/null +++ b/resources/views/components/php-card.blade.php @@ -0,0 +1,11 @@ +@props(['address' => []]) + +
{{ $address->name }}
+
{{ $address->address }}
+
+
{{ $address->zip }}
+
{{ $address->city }}
+
+
{{ $address->phone }}
+
{{ $address->email }}
+ diff --git a/resources/views/invoice/create.blade.php b/resources/views/invoice/create.blade.php new file mode 100644 index 0000000..c0c2121 --- /dev/null +++ b/resources/views/invoice/create.blade.php @@ -0,0 +1,391 @@ + + +

+ {{ __('invoice.Create new invoice') }} +

+
+ +
+
+ + +
+
+
+
+

+ {{ __('invoice.Select customer') }} +

+

+ {{ __("invoice.Select your customer and address") }} +

+
+ +
+ + +
+ +
+ +
+ +
+ +
+
+ + +
+
+
+
+

+ {{ __('invoice.Select address') }} +

+

+ {{ __("invoice.Select your customer and address") }} +

+
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+ + +
+
+
+
+

+ {{ __('invoice.Invoice items') }} +

+

+ {{ __("invoice.Enter your invoice items. Click add for an additional invoice item.") }} +

+
+ + +
+ + + + +
+
+
+ + + + + + + + +
+ + +
+
+
+
+ +
+
+
+ +
+ + +
+ +
+ +
+ + Sprrelkfdsiodsaich + +
+
+ +
+
+ +
+ + diff --git a/resources/views/invoice/index.blade.php b/resources/views/invoice/index.blade.php new file mode 100644 index 0000000..a9776a9 --- /dev/null +++ b/resources/views/invoice/index.blade.php @@ -0,0 +1,119 @@ + + +

+ {{ __('invoice.Invoices') }} +

+
+ +
+
+
+
+
+
+

+ {{ __('invoice.Add new invoice') }} +

+ +

+ {{ __("invoice.Add new invoice by clicking add") }} +

+ +
+ {{ __('form.Add') }} +
+
+
+ +
+
+
+
+

+ {{ __('invoice.Existing invoices') }} +

+
+ + + + +
+
+ + +
{{ __('invoice.Invoice Number') }}
+
{{ __('common.Name') }}
+
{{ __('common.Email') }}
+
{{ __('invoice.State') }}
+
{{ __('invoice.Sum') }}
+
{{ __('common.Created at') }}
+
+ + + +
+
{{ __('invoice.Sum') }}
+
+
{{ __('invoice.Tax') }}
+
+
+ +
+
+
+ +
+
+ +
+ + diff --git a/resources/views/invoice/show.blade.php b/resources/views/invoice/show.blade.php new file mode 100644 index 0000000..8b0587e --- /dev/null +++ b/resources/views/invoice/show.blade.php @@ -0,0 +1,88 @@ + + +

+ {{ __('invoice.Invoice') }} {{ $invoice->number }} +

+
+ +
+
+ + +
+
+
+
+

+ {{ __('customer.Customer') }}: {{ $invoice->customer->name }} ({{ $invoice->customer->email }}) +

+
+
{{ __("customer.Invoice Address") }}
+
{{ __("customer.Delivery Address") }}
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + +
+
+
+
+

+ {{ __('invoice.Invoice items') }} +

+
+ + + + + +
+
+ +
+ @foreach($invoice->items as $item) + + @endforeach + +
+
+
+
+ + +
+
+
+
+
{{ __('invoice.Net') }}
+
{{ \Illuminate\Support\Number::currency($invoice->sum - $invoice->tax) }}
+
+
+
+
{{ __('invoice.Tax') }}
+
{{ \Illuminate\Support\Number::currency($invoice->tax) }}
+
+
+
+
{{ __('invoice.Sum') }}
+
{{ \Illuminate\Support\Number::currency($invoice->sum) }}
+
+
+
+ +
+
+ +
diff --git a/resources/views/layouts/navigation.blade.php b/resources/views/layouts/navigation.blade.php index 0178406..d6cee55 100644 --- a/resources/views/layouts/navigation.blade.php +++ b/resources/views/layouts/navigation.blade.php @@ -19,6 +19,10 @@ :active="\Illuminate\Support\Str::startsWith(request()->route()->getName(), 'customer.')"> {{ __('customer.Customers') }} + + {{ __('invoice.Invoices') }} + {{ __('configuration.Taxrates') }} diff --git a/routes/api.php b/routes/api.php index a410803..6c52e18 100644 --- a/routes/api.php +++ b/routes/api.php @@ -3,6 +3,8 @@ use App\Http\Controllers\Api\AddressController; use App\Http\Controllers\Api\AuthController; use App\Http\Controllers\Api\CustomerController; +use App\Http\Controllers\Api\InvoiceController; +use App\Http\Controllers\Api\InvoiceitemController; use App\Http\Controllers\Api\TaxrateController; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; @@ -22,6 +24,8 @@ Route::group(['as' => 'api.'], function () { Route::apiResource('/customer', CustomerController::class); Route::apiResource('/customer.address', AddressController::class)->shallow()->except(['update']); Route::apiResource('/taxrate', TaxRateController::class)->except(['show']); + Route::get('/invoice/{start?}/{end?}', [InvoiceController::class, 'index'])->name('invoice.index'); + Route::apiResource('/invoice.item', InvoiceItemController::class)->shallow(); }); }); diff --git a/routes/web.php b/routes/web.php index cb3a41f..dcacbca 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,7 @@ group(function () { Route::resource('/customer', CustomerController::class)->only(['index', 'create', 'edit']); Route::resource('/taxrate', TaxrateController::class)->only(['index', 'create', 'edit']); + Route::resource('/invoice', InvoiceController::class)->only(['index', 'create', 'show', 'edit']); }); require __DIR__.'/auth.php';