diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index 88a4800987..0675437752 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -524,6 +524,11 @@ class CreditController extends BaseController { /*If we are using bulk actions, we don't want to return anything */ switch ($action) { + case 'mark_paid': + $credit->service()->markPaid()->save(); + return $this->itemResponse($credit); + break; + case 'clone_to_credit': $credit = CloneCreditFactory::create($credit, auth()->user()->id); diff --git a/app/Http/Middleware/ContactAccount.php b/app/Http/Middleware/ContactAccount.php index e1ac296fc8..79faf0a9c7 100644 --- a/app/Http/Middleware/ContactAccount.php +++ b/app/Http/Middleware/ContactAccount.php @@ -32,8 +32,8 @@ class ContactAccount if(!Ninja::isHosted()) { $account_id = Account::first()->id; - $request->attributes->add(['account_id' => $account_id]); - + $request->request->add(['account_id' => $account_id]); + } return $next($request); diff --git a/app/Http/Middleware/SetDomainNameDb.php b/app/Http/Middleware/SetDomainNameDb.php index 728f14fcbf..ab49e9ef15 100644 --- a/app/Http/Middleware/SetDomainNameDb.php +++ b/app/Http/Middleware/SetDomainNameDb.php @@ -49,7 +49,7 @@ class SetDomainNameDb ]; if($company = MultiDB::findAndSetDbByDomain($query)){ - $request->attributes->add(['account_id' => $company->account_id]); + $request->request->add(['account_id' => $company->account_id]); } else { @@ -71,7 +71,7 @@ class SetDomainNameDb ]; if($company = MultiDB::findAndSetDbByDomain($query)){ - $request->attributes->add(['account_id' => $company->account_id]); + $request->request->add(['account_id' => $company->account_id]); } else { diff --git a/app/Http/Requests/Credit/StoreCreditRequest.php b/app/Http/Requests/Credit/StoreCreditRequest.php index e4fc2f23ad..5b0cd808ee 100644 --- a/app/Http/Requests/Credit/StoreCreditRequest.php +++ b/app/Http/Requests/Credit/StoreCreditRequest.php @@ -56,6 +56,7 @@ class StoreCreditRequest extends Request // $rules['number'] = new UniqueCreditNumberRule($this->all()); $rules['number'] = ['nullable', Rule::unique('credits')->where('company_id', auth()->user()->company()->id)]; + $rules['discount'] = 'sometimes|numeric'; diff --git a/app/Http/Requests/Credit/UpdateCreditRequest.php b/app/Http/Requests/Credit/UpdateCreditRequest.php index 28cbfe2b4b..d7abee626b 100644 --- a/app/Http/Requests/Credit/UpdateCreditRequest.php +++ b/app/Http/Requests/Credit/UpdateCreditRequest.php @@ -57,6 +57,7 @@ class UpdateCreditRequest extends Request $rules['number'] = Rule::unique('credits')->where('company_id', auth()->user()->company()->id)->ignore($this->credit->id); $rules['line_items'] = 'array'; + $rules['discount'] = 'sometimes|numeric'; return $rules; } diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php index efb4e93106..06b0bf1b1c 100644 --- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php +++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php @@ -56,6 +56,7 @@ class StoreInvoiceRequest extends Request $rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())]; $rules['line_items'] = 'array'; + $rules['discount'] = 'sometimes|numeric'; return $rules; } diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index d90688ef7b..d008d7a36b 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -56,6 +56,7 @@ class UpdateInvoiceRequest extends Request $rules['number'] = Rule::unique('invoices')->where('company_id', auth()->user()->company()->id)->ignore($this->invoice->id); $rules['line_items'] = 'array'; + $rules['discount'] = 'sometimes|numeric'; if($this->input('status_id') != Invoice::STATUS_DRAFT) $rules['balance'] = new InvoiceBalanceSanity($this->invoice, $this->all()); diff --git a/app/Http/Requests/Quote/StoreQuoteRequest.php b/app/Http/Requests/Quote/StoreQuoteRequest.php index 01145f5475..30f5587f59 100644 --- a/app/Http/Requests/Quote/StoreQuoteRequest.php +++ b/app/Http/Requests/Quote/StoreQuoteRequest.php @@ -50,6 +50,7 @@ class StoreQuoteRequest extends Request } $rules['number'] = ['nullable',Rule::unique('quotes')->where('company_id', auth()->user()->company()->id)]; + $rules['discount'] = 'sometimes|numeric'; // $rules['number'] = new UniqueQuoteNumberRule($this->all()); $rules['line_items'] = 'array'; diff --git a/app/Http/Requests/Quote/UpdateQuoteRequest.php b/app/Http/Requests/Quote/UpdateQuoteRequest.php index d67ce3dc1f..0fa9e56f78 100644 --- a/app/Http/Requests/Quote/UpdateQuoteRequest.php +++ b/app/Http/Requests/Quote/UpdateQuoteRequest.php @@ -51,6 +51,7 @@ class UpdateQuoteRequest extends Request $rules['number'] = Rule::unique('quotes')->where('company_id', auth()->user()->company()->id)->ignore($this->quote->id); $rules['line_items'] = 'array'; + $rules['discount'] = 'sometimes|numeric'; return $rules; } diff --git a/app/PaymentDrivers/MolliePaymentDriver.php b/app/PaymentDrivers/MolliePaymentDriver.php index 1aac3ee606..e05fe49729 100644 --- a/app/PaymentDrivers/MolliePaymentDriver.php +++ b/app/PaymentDrivers/MolliePaymentDriver.php @@ -176,7 +176,7 @@ class MolliePaymentDriver extends BaseDriver SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_MOLLIE, $this->client, - $this->client->companyk + $this->client->company ); nlog($e->getMessage()); @@ -239,7 +239,8 @@ class MolliePaymentDriver extends BaseDriver SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_MOLLIE, - $this->client + $this->client, + $this->client->company ); return $payment; @@ -259,7 +260,8 @@ class MolliePaymentDriver extends BaseDriver SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_CHECKOUT, - $this->client + $this->client, + $this->client->company ); return false; @@ -310,7 +312,7 @@ class MolliePaymentDriver extends BaseDriver $client = $record->client; } else{ - $client = Client::withTrashed()->find($this->decodePrimaryKey($payment['metadata']->client_id)); + $client = Client::withTrashed()->find($this->decodePrimaryKey($payment->metadata->client_id)); } $message = [ @@ -331,7 +333,8 @@ class MolliePaymentDriver extends BaseDriver SystemLog::CATEGORY_GATEWAY_RESPONSE, $response, SystemLog::TYPE_MOLLIE, - $client + $client, + $client->company ); return response()->json([], 200); diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index c7ae018be8..4ea1e65340 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -185,13 +185,13 @@ class PaymentRepository extends BaseRepository { * @param $payment * @return */ - private function processExchangeRates($data, $payment) + public function processExchangeRates($data, $payment) { if(array_key_exists('exchange_rate', $data) && isset($data['exchange_rate'])) return $payment; - $client = Client::find($data['client_id']); + $client = Client::withTrashed()->find($data['client_id']); $client_currency = $client->getSetting('currency_id'); $company_currency = $client->company->settings->currency_id; diff --git a/app/Services/Credit/CreditService.php b/app/Services/Credit/CreditService.php index c6b41fb3ee..22bd94a564 100644 --- a/app/Services/Credit/CreditService.php +++ b/app/Services/Credit/CreditService.php @@ -11,8 +11,13 @@ namespace App\Services\Credit; +use App\Factory\PaymentFactory; use App\Jobs\Util\UnlinkFile; use App\Models\Credit; +use App\Models\Payment; +use App\Models\PaymentType; +use App\Repositories\CreditRepository; +use App\Repositories\PaymentRepository; use App\Services\Credit\CreateInvitations; use App\Services\Credit\TriggeredActions; use App\Utils\Traits\MakesHash; @@ -79,6 +84,61 @@ class CreditService return $this; } + /* + For euro users - we mark a credit as paid when + we need to document a refund of sorts. + + Criteria: Credit must be a negative value + A negative payment for the balance will be generated + This amount will be reduced from the clients paid to date. + + */ + public function markPaid() + { + if($this->credit->balance > 0) + return $this; + + $payment_repo = new PaymentRepository(new CreditRepository()); + + //set credit balance to zero + $adjustment = $this->credit->balance; + + $this->updateBalance($adjustment) + ->updatePaidToDate($adjustment) + ->save(); + + //create a negative payment of total $this->credit->balance + $payment = PaymentFactory::create($this->credit->company_id, $this->credit->user_id); + $payment->client_id = $this->credit->client_id; + $payment->amount = $adjustment; + $payment->applied = $adjustment; + $payment->refunded = 0; + $payment->status_id = Payment::STATUS_COMPLETED; + $payment->type_id = PaymentType::CREDIT; + $payment->is_manual = true; + $payment->date = now(); + + $payment->saveQuietly(); + $payment->number = $payment->client->getNextPaymentNumber($payment->client, $payment); + $payment = $payment_repo->processExchangeRates(['client_id' => $this->credit->client_id], $payment); + $payment->saveQuietly(); + + $payment + ->credits() + ->attach($this->credit->id, ['amount' => $adjustment]); + + //reduce client paid_to_date by $this->credit->balance amount + $this->credit + ->client + ->service() + ->updatePaidToDate($adjustment) + ->save(); + + event('eloquent.created: App\Models\Payment', $payment); + + return $this; + } + public function markSent() { $this->credit = (new MarkSent($this->credit->client, $this->credit))->run(); diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index ae84ea1646..f1ea59aefc 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -130,7 +130,7 @@ class AutoBillInvoice extends AbstractService info("Auto Bill payment captured for ".$this->invoice->number); } - return $this->invoice; + return $this->invoice->fresh(); } /** diff --git a/app/Services/Invoice/CreateInvitations.php b/app/Services/Invoice/CreateInvitations.php index 07734ab643..fb5e26a82b 100644 --- a/app/Services/Invoice/CreateInvitations.php +++ b/app/Services/Invoice/CreateInvitations.php @@ -33,7 +33,7 @@ class CreateInvitations extends AbstractService public function run() { - $contacts = $this->invoice->client->contacts; + $contacts = $this->invoice->client->contacts()->where('send_email', true)->get(); if($contacts->count() == 0){ $this->createBlankContact(); diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index 626327f803..58222c6e75 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -139,8 +139,13 @@ class DeletePayment if ($this->payment->credits()->exists()) { $this->payment->credits()->each(function ($paymentable_credit) { + $multiplier = 1; + + if($paymentable_credit->pivot->amount < 0) + $multiplier = -1; + $paymentable_credit->service() - ->updateBalance($paymentable_credit->pivot->amount) + ->updateBalance($paymentable_credit->pivot->amount*$multiplier) ->updatePaidToDate($paymentable_credit->pivot->amount*-1) ->setStatus(Credit::STATUS_SENT) ->save(); diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index a1984fb7a2..ba7da5f286 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -717,8 +717,9 @@ class SubscriptionService */ public function convertInvoiceToRecurring($client_id) :RecurringInvoice { - - $client = Client::find($client_id); + MultiDB::setDb($this->subscription->company->db); + + $client = Client::withTrashed()->find($client_id); $subscription_repo = new SubscriptionRepository();