diff --git a/app/Http/Controllers/Api/InvoiceController.php b/app/Http/Controllers/Api/InvoiceController.php index 6aa401e..11dd1c2 100644 --- a/app/Http/Controllers/Api/InvoiceController.php +++ b/app/Http/Controllers/Api/InvoiceController.php @@ -19,6 +19,11 @@ class InvoiceController extends Controller return response()->json(Invoice::whereBetween('created_at', [$from, $end])->with('address')->orderBy('created_at', 'desc')->get()); } + public function open(): JsonResponse + { + return response()->json(Invoice::where('status', '=', 'sent')->orderBy('created_at', 'desc')->with(['customer', 'address', 'payments'])->get()); + } + /** * Store a newly created resource in storage. */ diff --git a/app/Http/Controllers/Api/PaymentController.php b/app/Http/Controllers/Api/PaymentController.php new file mode 100644 index 0000000..1f1928a --- /dev/null +++ b/app/Http/Controllers/Api/PaymentController.php @@ -0,0 +1,82 @@ +json(Payment::whereBetween('payment_date', [$from, $end])->with(['invoice'])->orderBy('payment_date', 'desc')->get()); + } + + public function index(Invoice $invoice): JsonResponse + { + return response()->json($invoice->payments); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request, Invoice $invoice): JsonResponse + { + $paymentData = $request->validate([ + 'invoice_id' => 'required|integer|exists:invoices,id', + 'paid_amount' => 'required|numeric', + 'payment_date' => 'required|date', + 'payment_method' => 'nullable|string', + 'status' => 'required|string|in:full,partial', + ]); + + if ($paymentData['status'] == 'full') { + $invoice->update(['status' => 'paid']); + } + + return response()->json($invoice->payments()->create($request->all())); + } + + /** + * Display the specified resource. + */ + public function show(Payment $payment) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, Payment $payment): JsonResponse + { + $paymentData = $request->validate([ + 'invoice_id' => 'required|integer|exists:invoices,id', + 'paid_amount' => 'required|numeric', + 'payment_date' => 'required|date', + 'payment_method' => 'nullable|string', + 'status' => 'required|string|in:full,partial', + ]); + + $payment->update($paymentData); + if ($payment->invoice->payments->where('status', 'full')->count() === 0) { + $payment->invoice->update(['status' => 'sent']); + } + + return response()->json($payment); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Payment $payment) + { + // + } +} diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php new file mode 100644 index 0000000..f6bfa6c --- /dev/null +++ b/app/Http/Controllers/PaymentController.php @@ -0,0 +1,35 @@ + $payment->load('invoice')]); + } + +} diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 2d21443..9d0cde4 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -38,8 +38,6 @@ class Invoice extends Model /** * Get the invoice state as translated string. - * - * @return string */ public function getLocalizedStateAttribute(): string { @@ -56,35 +54,57 @@ class Invoice extends Model /** * Get the created_at attribute in local time format. - * - * @return string */ public function getCreatedAttribute(): string { return $this->created_at->format('d.m.Y'); } + + /** + * Get the user, that has created the invoice. + */ public function user(): BelongsTo { return $this->belongsTo(User::class); } + /** + * Get the invoice's customer. + */ public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } + /** + * Get the invoice's address. + */ public function address(): BelongsTo { return $this->belongsTo(Address::class)->withTrashed(); } + /** + * Get the invoice's delivery address. + */ public function delivery(): BelongsTo { return $this->belongsTo(Address::class)->withTrashed(); } + /** + * Get the items (invoice positions) of this invoice. + */ public function items(): HasMany { return $this->hasMany(Invoiceitem::class); } + + /** + * Get the payments for the invoice + */ + public function payments(): HasMany + { + return $this->hasMany(Payment::class); + } } diff --git a/app/Models/Payment.php b/app/Models/Payment.php index cc5879a..69c61e4 100644 --- a/app/Models/Payment.php +++ b/app/Models/Payment.php @@ -3,9 +3,58 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Support\Facades\Date; class Payment extends Model { - use SoftDeletes; + public $timestamps = false; + + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = [ + 'invoice_id', + 'paid_amount', + 'status', + 'payment_method', + 'payment_date', + ]; + + /** + * The attributes that are appended with attribute getters. + * + * @var string[] + */ + protected $appends = [ + 'date', + 'localized_state' + ]; + + /** + * Get the payment state as translated string. + */ + public function getLocalizedStateAttribute(): string + { + return __('invoice.Payment state ' . $this->status); + } + + /** + * Get the payment date as localized string. + */ + public function getDateAttribute(): string + { + return Date::createFromFormat('Y-m-d', $this->payment_date)->format('d.m.Y'); + } + + /** + * Get the invoice the payment belongs to. + */ + public function invoice(): BelongsTo + { + return $this->belongsTo(Invoice::class); + } + } diff --git a/database/migrations/2024_11_25_164059_create_payments_table.php b/database/migrations/2024_11_25_164059_create_payments_table.php index 2072a47..9b82237 100644 --- a/database/migrations/2024_11_25_164059_create_payments_table.php +++ b/database/migrations/2024_11_25_164059_create_payments_table.php @@ -18,9 +18,8 @@ return new class extends Migration $table->decimal('paid_amount', 15, 2); $table->string('status'); $table->string('payment_method')->nullable(); + $table->date('payment_date'); - $table->timestamps(); - $table->softDeletes(); }); } diff --git a/lang/de/dashboard.php b/lang/de/dashboard.php index c909d09..4432df6 100644 --- a/lang/de/dashboard.php +++ b/lang/de/dashboard.php @@ -15,5 +15,6 @@ return [ 'Dashboard' => 'Dashboard', 'Customers without address' => 'Kunden ohne Rechnungsadresse', 'Invoices not sent' => 'Nicht versendete Rechnungen', + 'Invoices not paid' => 'Nicht bezahlte Rechnungen', ]; diff --git a/lang/de/invoice.php b/lang/de/invoice.php index bb9373a..a20fdfb 100644 --- a/lang/de/invoice.php +++ b/lang/de/invoice.php @@ -51,6 +51,7 @@ return [ 'Final sentence' => 'Bitte überweisen Sie den fälligen Rechnungsbetrag in Höhe von :sum bis spätestens :date auf das unten genannte Konto.', 'state_created' => 'Erstellt', 'state_sent' => 'Gesendet', + 'state_paid' => 'Bezahlt', 'Mail' => 'E-Mail', 'Send email to your customer with attachments.' => 'E-Mail mit Anlagen an den Kunden versenden.', 'Invoice body' => 'Sehr geehrte Kundin, sehr geehrter Kunde\n\nim Anhang erhalten Sie die Rechnung :invoice_number.\n\nMit freundlichen Grüßen', @@ -59,5 +60,22 @@ return [ 'Manual Mail' => 'Manueller E-Mail Versand', 'Send email to your customer with attachments manually.' => 'E-Mail mit Anlagen über ein externes Programm versenden.', 'Sent menually' => 'Manuell versendet', + 'Payment' => 'Zahlung', + 'Payment for invoice' => 'Zahlung zur Rechnung', + 'Payments' => 'Zahlungen', + 'Existing payments' => 'Bestehende Zahlungseingänge', + 'Add new payment' => 'Neuen Zahlungseingang erstellen', + 'Add new payment by clicking add' => 'Durch Klick auf "Anlegen" neuen Zahlungseingang erstellen', + 'Create new payment' => 'Neuen Zahlungseingang erstellen', + 'Select invoice' => 'Rechnung wählen', + 'Select your invoice for payment' => 'Wähle die Rechnung für den Zahlungseingang aus', + 'Enter your payment data' => 'Gib die Daten für den Zahlungseingang ein', + 'Payment state full' => 'Vollständiger Zahlungseingang', + 'Payment state partial' => 'Teilzahlung', + 'Payment status?' => 'Wurde der verbleibende Rechnungsbetrag vollständig bezahlt?', + 'Payment date' => 'Zahlungsdatum', + 'Payment amount' => 'Zahlungsbetrag', + 'Existing payments for invoice' => 'Bestehende Teilzahlungen für Rechnung', + 'Paid at' => 'Bezahlt am', ]; diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index e0711c6..67a6288 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -1,6 +1,7 @@ @php $customers = \App\Models\Customer::doesntHave('address')->get(); - $invoices = \App\Models\Invoice::where('status', '=', 'created')->orderBy('created_at')->get(); + $created_invoices = \App\Models\Invoice::where('status', '=', 'created')->orderBy('created_at')->get(); + $sent_invoices = \App\Models\Invoice::where('status', '=', 'sent')->orderBy('created_at')->get(); @endphp @@ -12,10 +13,40 @@
-
+
+ + +
+
+

{{ __('dashboard.Invoices not paid') }}

+ @foreach($sent_invoices as $invoice) + +
{{ $invoice->number }}
+
{{ $invoice->address->name }}
+
{{ $invoice->sum }}
+
{{ $invoice->created }}
+
+ @endforeach +
+
+ + +
+
+

{{ __('dashboard.Invoices not sent') }}

+ @foreach($created_invoices as $invoice) + +
{{ $invoice->number }}
+
{{ $invoice->address->name }}
+
+ @endforeach +
+
-
+

{{ __('dashboard.Customers without address') }}

@foreach($customers as $customer) @@ -28,20 +59,6 @@
- -
-
-

{{ __('dashboard.Invoices not sent') }}

- @foreach($invoices as $invoice) - -
{{ $invoice->number }}
-
{{ $invoice->address->name }}
-
- @endforeach -
-
- -
+
diff --git a/resources/views/invoice/index.blade.php b/resources/views/invoice/index.blade.php index a59c4d3..fb4219a 100644 --- a/resources/views/invoice/index.blade.php +++ b/resources/views/invoice/index.blade.php @@ -97,7 +97,7 @@ fetchInvoices() { let vm = this; - axios.get('/invoice/' + this.from + '/' + this.end) + axios.get('/invoice-filter/' + this.from + '/' + this.end) .then(function (response) { vm.invoices = response.data; vm.calculateSum(); diff --git a/resources/views/layouts/navigation.blade.php b/resources/views/layouts/navigation.blade.php index caa4c41..d67feaf 100644 --- a/resources/views/layouts/navigation.blade.php +++ b/resources/views/layouts/navigation.blade.php @@ -23,6 +23,10 @@ :active="\Illuminate\Support\Str::startsWith(request()->route()->getName(), 'invoice.')"> {{ __('invoice.Invoices') }} + + {{ __('invoice.Payments') }} + {{ __('configuration.Taxrates') }} @@ -93,7 +97,7 @@