diff --git a/app/Console/Commands/BillReminder.php b/app/Console/Commands/BillReminder.php index e06564896..02ddda567 100644 --- a/app/Console/Commands/BillReminder.php +++ b/app/Console/Commands/BillReminder.php @@ -78,5 +78,4 @@ class BillReminder extends Command } } } - } diff --git a/app/Console/Commands/InvoiceReminder.php b/app/Console/Commands/InvoiceReminder.php index e3fcb75d9..f24fe0dc9 100644 --- a/app/Console/Commands/InvoiceReminder.php +++ b/app/Console/Commands/InvoiceReminder.php @@ -69,7 +69,7 @@ class InvoiceReminder extends Command foreach ($invoices as $invoice) { // Notify the customer - if ($invoice->customer) { + if ($invoice->customer && !empty($invoice->customer_email)) { $invoice->customer->notify(new Notification($invoice)); } @@ -83,5 +83,4 @@ class InvoiceReminder extends Command } } } - } diff --git a/app/Http/Controllers/Auth/Users.php b/app/Http/Controllers/Auth/Users.php index 57e75bec8..75933b591 100644 --- a/app/Http/Controllers/Auth/Users.php +++ b/app/Http/Controllers/Auth/Users.php @@ -243,6 +243,7 @@ class Users extends Controller public function autocomplete(ARequest $request) { $user = false; + $data = false; $column = $request['column']; $value = $request['value']; @@ -250,7 +251,7 @@ class Users extends Controller if (!empty($column) && !empty($value)) { switch ($column) { case 'id': - $user = User::find(); + $user = User::find((int) $value); break; case 'email': $user = User::where('email', $value)->first(); @@ -258,12 +259,16 @@ class Users extends Controller default: $user = User::where($column, $value)->first(); } + + $data = $user; + } elseif (!empty($column) && empty($value)) { + $data = trans('validation.required', ['attribute' => $column]); } return response()->json([ - 'errors' => ($user) ? false: true, - 'success' => ($user) ? true: false, - 'data' => $user + 'errors' => ($user) ? false : true, + 'success' => ($user) ? true : false, + 'data' => $data ]); } } diff --git a/app/Http/Controllers/Customers/Profile.php b/app/Http/Controllers/Customers/Profile.php new file mode 100644 index 000000000..b75ad6d17 --- /dev/null +++ b/app/Http/Controllers/Customers/Profile.php @@ -0,0 +1,92 @@ +edit(); + } + + public function show() + { + return $this->edit(); + } + + /** + * Show the form for editing the specified resource. + * + * @return Response + */ + public function edit() + { + $user = auth()->user(); + + return view('customers.profile.edit', compact('user')); + } + + /** + * Update the specified resource in storage. + * + * @param Request $request + * + * @return Response + */ + public function update(Request $request) + { + $user = auth()->user(); + + // Upload picture + $picture = $request->file('picture'); + if ($picture && $picture->isValid()) { + $request['picture'] = $picture->store('users'); + } + + // Do not reset password if not entered/changed + if (empty($request['password'])) { + unset($request['password']); + unset($request['password_confirmation']); + } + + // Update user + $user->update($request->input()); + + // Update customer + $user->customer->update($request->input()); + + $message = trans('messages.success.updated', ['type' => trans('auth.profile')]); + + flash($message)->success(); + + return redirect('customers/profile/edit'); + } + + /** + * Mark overdue invoices notifications are read and redirect to invoices page. + * + * @return Response + */ + public function readOverdueInvoices() + { + $user = auth()->user(); + + // Mark invoice notifications as read + foreach ($user->unreadNotifications as $notification) { + // Not an invoice notification + if ($notification->getAttribute('type') != 'App\Notifications\Income\Invoice') { + continue; + } + + $notification->markAsRead(); + } + + // Redirect to invoices + return redirect('customers/invoices'); + } +} diff --git a/app/Http/Controllers/Expenses/Vendors.php b/app/Http/Controllers/Expenses/Vendors.php index 6b06d28be..90c3f8377 100644 --- a/app/Http/Controllers/Expenses/Vendors.php +++ b/app/Http/Controllers/Expenses/Vendors.php @@ -44,6 +44,10 @@ class Vendors extends Controller */ public function store(Request $request) { + if (empty($request['email'])) { + $request['email'] = ''; + } + Vendor::create($request->all()); $message = trans('messages.success.added', ['type' => trans_choice('general.vendors', 1)]); @@ -120,6 +124,10 @@ class Vendors extends Controller */ public function update(Vendor $vendor, Request $request) { + if (empty($request['email'])) { + $request['email'] = ''; + } + $vendor->update($request->all()); $message = trans('messages.success.updated', ['type' => trans_choice('general.vendors', 1)]); @@ -169,6 +177,10 @@ class Vendors extends Controller public function vendor(Request $request) { + if (empty($request['email'])) { + $request['email'] = ''; + } + $vendor = Vendor::create($request->all()); return response()->json($vendor); diff --git a/app/Http/Controllers/Incomes/Customers.php b/app/Http/Controllers/Incomes/Customers.php index 17d9f1abd..ebf317aef 100644 --- a/app/Http/Controllers/Incomes/Customers.php +++ b/app/Http/Controllers/Incomes/Customers.php @@ -46,6 +46,10 @@ class Customers extends Controller public function store(Request $request) { if (empty($request->input('create_user'))) { + if (empty($request['email'])) { + $request['email'] = ''; + } + Customer::create($request->all()); } else { // Check if user exist @@ -112,6 +116,11 @@ class Customers extends Controller foreach ($rows as $row) { $data = $row->toArray(); + + if (empty($data['email'])) { + $data['email'] = ''; + } + $data['company_id'] = session('company_id'); Customer::create($data); @@ -149,6 +158,10 @@ class Customers extends Controller public function update(Customer $customer, Request $request) { if (empty($request->input('create_user'))) { + if (empty($request['email'])) { + $request['email'] = ''; + } + $customer->update($request->all()); } else { // Check if user exist @@ -220,6 +233,10 @@ class Customers extends Controller public function customer(Request $request) { + if (empty($request['email'])) { + $request['email'] = ''; + } + $customer = Customer::create($request->all()); return response()->json($customer); diff --git a/app/Http/Controllers/Incomes/Invoices.php b/app/Http/Controllers/Incomes/Invoices.php index 4535a2c17..ff44addec 100644 --- a/app/Http/Controllers/Incomes/Invoices.php +++ b/app/Http/Controllers/Incomes/Invoices.php @@ -489,6 +489,10 @@ class Invoices extends Controller */ public function emailInvoice(Invoice $invoice) { + if (empty($invoice->customer_email)) { + return redirect()->back(); + } + $invoice = $this->prepareInvoice($invoice); $logo = $this->getLogo(); @@ -584,18 +588,23 @@ class Invoices extends Controller $amount = $invoice->amount - $paid; - $request = new PaymentRequest(); + if (!empty($amount)) { + $request = new PaymentRequest(); - $request['company_id'] = $invoice->company_id; - $request['invoice_id'] = $invoice->id; - $request['account_id'] = setting('general.default_account'); - $request['payment_method'] = setting('general.default_payment_method', 'offlinepayment.cash.1'); - $request['currency_code'] = $invoice->currency_code; - $request['amount'] = $amount; - $request['paid_at'] = Date::now(); - $request['_token'] = csrf_token(); + $request['company_id'] = $invoice->company_id; + $request['invoice_id'] = $invoice->id; + $request['account_id'] = setting('general.default_account'); + $request['payment_method'] = setting('general.default_payment_method', 'offlinepayment.cash.1'); + $request['currency_code'] = $invoice->currency_code; + $request['amount'] = $amount; + $request['paid_at'] = Date::now(); + $request['_token'] = csrf_token(); - $this->payment($request); + $this->payment($request); + } else { + $invoice->invoice_status_code = 'paid'; + $invoice->save(); + } return redirect()->back(); } @@ -689,7 +698,9 @@ class Invoices extends Controller { $invoice = Invoice::find($payment->invoice_id); - if ($invoice->payments()->count() > 1) { + if ($invoice->payments()->paid() == $invoice->amount) { + $invoice->invoice_status_code = 'paid'; + } elseif ($invoice->payments()->count() > 1) { $invoice->invoice_status_code = 'partial'; } else { $invoice->invoice_status_code = 'draft'; diff --git a/app/Http/Requests/Customer/Profile.php b/app/Http/Requests/Customer/Profile.php new file mode 100644 index 000000000..45b729745 --- /dev/null +++ b/app/Http/Requests/Customer/Profile.php @@ -0,0 +1,35 @@ +user()->getAttribute('id'); + + return [ + 'name' => 'required|string', + 'email' => 'required|email|unique:users,email,' . $id . ',id,deleted_at,NULL', + 'password' => 'confirmed', + 'picture' => 'mimes:' . setting('general.file_types') . '|between:0,' . setting('general.file_size') * 1024, + ]; + } +} diff --git a/app/Http/Requests/Expense/Vendor.php b/app/Http/Requests/Expense/Vendor.php index b40613165..9f5e76629 100644 --- a/app/Http/Requests/Expense/Vendor.php +++ b/app/Http/Requests/Expense/Vendor.php @@ -23,6 +23,11 @@ class Vendor extends Request */ public function rules() { + $email = ''; + + // Get company id + $company_id = $this->request->get('company_id'); + // Check if store or update if ($this->getMethod() == 'PATCH') { $id = $this->vendor->getAttribute('id'); @@ -30,12 +35,13 @@ class Vendor extends Request $id = null; } - // Get company id - $company_id = $this->request->get('company_id'); + if (!empty($this->request->get('email'))) { + $email = 'email|unique:vendors,NULL,' . $id . ',id,company_id,' . $company_id . ',deleted_at,NULL'; + } return [ 'name' => 'required|string', - 'email' => 'required|email|unique:vendors,NULL,' . $id . ',id,company_id,' . $company_id . ',deleted_at,NULL', + 'email' => $email, 'currency_code' => 'required|string', ]; } diff --git a/app/Http/Requests/Income/Customer.php b/app/Http/Requests/Income/Customer.php index 861524f9c..4d2e97622 100644 --- a/app/Http/Requests/Income/Customer.php +++ b/app/Http/Requests/Income/Customer.php @@ -23,8 +23,12 @@ class Customer extends Request */ public function rules() { + $email = ''; $required = ''; + // Get company id + $company_id = $this->request->get('company_id'); + // Check if store or update if ($this->getMethod() == 'PATCH') { $id = $this->customer->getAttribute('id'); @@ -36,12 +40,13 @@ class Customer extends Request $required = 'required|'; } - // Get company id - $company_id = $this->request->get('company_id'); + if (!empty($this->request->get('email'))) { + $email = 'email|unique:customers,NULL,' . $id . ',id,company_id,' . $company_id . ',deleted_at,NULL'; + } return [ 'name' => 'required|string', - 'email' => 'required|email|unique:customers,NULL,' . $id . ',id,company_id,' . $company_id . ',deleted_at,NULL', + 'email' => $email, 'currency_code' => 'required|string', 'password' => $required . 'confirmed', ]; diff --git a/app/Traits/Currencies.php b/app/Traits/Currencies.php index 45a3f05e7..22a54ab17 100644 --- a/app/Traits/Currencies.php +++ b/app/Traits/Currencies.php @@ -13,9 +13,9 @@ trait Currencies $default = new Currency(setting('general.default_currency', 'USD')); if ($format) { - $money = Money::$code($amount, true)->convert($default, $rate)->format(); + $money = Money::$code($amount, true)->convert($default, (double) $rate)->format(); } else { - $money = Money::$code($amount)->convert($default, $rate)->getAmount(); + $money = Money::$code($amount)->convert($default, (double) $rate)->getAmount(); } return $money; @@ -28,9 +28,9 @@ trait Currencies $code = new Currency($code); if ($format) { - $money = Money::$default($amount, true)->convert($code, $rate)->format(); + $money = Money::$default($amount, true)->convert($code, (double) $rate)->format(); } else { - $money = Money::$default($amount)->convert($code, $rate)->getAmount(); + $money = Money::$default($amount)->convert($code, (double) $rate)->getAmount(); } return $money; @@ -41,9 +41,9 @@ trait Currencies $code = new Currency($code); if ($format) { - $money = Money::$default($amount, true)->convert($code, $rate)->format(); + $money = Money::$default($amount, true)->convert($code, (double) $rate)->format(); } else { - $money = Money::$default($amount)->convert($code, $rate)->getAmount(); + $money = Money::$default($amount)->convert($code, (double) $rate)->getAmount(); } return $money; diff --git a/public/css/app.css b/public/css/app.css index 78f922c22..cb55b99af 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -498,6 +498,18 @@ ul.add-new.nav.navbar-nav.pull-left { background-color: #ffffff; } } + +.text-disabled { + opacity: 0.4; +} + +.tooltip > .tooltip-inner { + background-color: #6da252; +} + +.tooltip.right .tooltip-arrow { + border-right-color: #6da252 !important; +} /* .content-wrapper { overflow: inherit; diff --git a/resources/lang/en-GB/invoices.php b/resources/lang/en-GB/invoices.php index 7f52a170f..d1a62106d 100644 --- a/resources/lang/en-GB/invoices.php +++ b/resources/lang/en-GB/invoices.php @@ -37,8 +37,9 @@ return [ ], 'messages' => [ - 'email_sent' => 'Invoice email has been sent successfully!', - 'marked_sent' => 'Invoice marked as sent successfully!', + 'email_sent' => 'Invoice email has been sent successfully!', + 'marked_sent' => 'Invoice marked as sent successfully!', + 'email_required' => 'No email address for this customer!', ], 'notification' => [ diff --git a/resources/views/customers/profile/edit.blade.php b/resources/views/customers/profile/edit.blade.php new file mode 100644 index 000000000..aaf544b35 --- /dev/null +++ b/resources/views/customers/profile/edit.blade.php @@ -0,0 +1,69 @@ +@extends('layouts.customer') + +@section('title', trans('general.title.edit', ['type' => trans('auth.profile')])) + +@section('content') + +