Merge pull request #8840 from turbo124/v5-develop

v5.7.23
This commit is contained in:
David Bomba 2023-09-30 09:42:34 +10:00 committed by GitHub
commit 4f986df06c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 658 additions and 245 deletions

View File

@ -1 +1 @@
5.7.22 5.7.23

View File

@ -83,6 +83,7 @@ class BaseExport
'contact_custom_value4' => 'vendor_contact.custom_value4', 'contact_custom_value4' => 'vendor_contact.custom_value4',
'email' => 'vendor_contact.email', 'email' => 'vendor_contact.email',
'status' => 'vendor.status', 'status' => 'vendor.status',
'classification' => 'vendor.classification',
]; ];
protected array $client_report_keys = [ protected array $client_report_keys = [
@ -125,7 +126,9 @@ class BaseExport
"contact_custom_value2" => "contact.custom_value2", "contact_custom_value2" => "contact.custom_value2",
"contact_custom_value3" => "contact.custom_value3", "contact_custom_value3" => "contact.custom_value3",
"contact_custom_value4" => "contact.custom_value4", "contact_custom_value4" => "contact.custom_value4",
'payment_balance' => 'client.payment_balance',
'credit_balance' => 'client.credit_balance',
'classification' => 'client.classification',
]; ];
protected array $invoice_report_keys = [ protected array $invoice_report_keys = [

View File

@ -71,7 +71,11 @@ class ClientExport extends BaseExport
'contact_custom_value3' => 'contact.custom_value3', 'contact_custom_value3' => 'contact.custom_value3',
'contact_custom_value4' => 'contact.custom_value4', 'contact_custom_value4' => 'contact.custom_value4',
'email' => 'contact.email', 'email' => 'contact.email',
'status' => 'status' 'status' => 'status',
'payment_balance' => 'client.payment_balance',
'credit_balance' => 'client.credit_balance',
'classification' => 'client.classification',
]; ];
public function __construct(Company $company, array $input) public function __construct(Company $company, array $input)
@ -223,6 +227,10 @@ class ClientExport extends BaseExport
$entity['industry_id'] = $client->industry ? ctrans("texts.industry_{$client->industry->name}") : ''; $entity['industry_id'] = $client->industry ? ctrans("texts.industry_{$client->industry->name}") : '';
} }
if (in_array('client.classification', $this->input['report_keys']) && isset($client->classification)) {
$entity['client.classification'] = ctrans("texts.{$client->classification}") ?? '';
}
return $entity; return $entity;
} }

View File

@ -139,7 +139,11 @@ class VendorExport extends BaseExport
$entity['currency'] = $vendor->currency() ? $vendor->currency()->code : $vendor->company->currency()->code; $entity['currency'] = $vendor->currency() ? $vendor->currency()->code : $vendor->company->currency()->code;
} }
$entity['status'] = $this->calculateStatus($vendor); if (in_array('vendor.classification', $this->input['report_keys']) && isset($vendor->classification)) {
$entity['vendor.classification'] = ctrans("texts.{$vendor->classification}") ?? '';
}
// $entity['status'] = $this->calculateStatus($vendor);
return $entity; return $entity;
} }

View File

@ -123,11 +123,14 @@ class ClientController extends BaseController
return $request->disallowUpdate(); return $request->disallowUpdate();
} }
/** @var \App\Models\User $user */
$user = auth()->user();
$client = $this->client_repo->save($request->all(), $client); $client = $this->client_repo->save($request->all(), $client);
$this->uploadLogo($request->file('company_logo'), $client->company, $client); $this->uploadLogo($request->file('company_logo'), $client->company, $client);
event(new ClientWasUpdated($client, $client->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new ClientWasUpdated($client, $client->company, Ninja::eventVars($user ? $user->id : null)));
return $this->itemResponse($client->fresh()); return $this->itemResponse($client->fresh());
} }
@ -141,7 +144,10 @@ class ClientController extends BaseController
*/ */
public function create(CreateClientRequest $request) public function create(CreateClientRequest $request)
{ {
$client = ClientFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$client = ClientFactory::create($user->company()->id, $user->id);
return $this->itemResponse($client); return $this->itemResponse($client);
} }
@ -155,7 +161,10 @@ class ClientController extends BaseController
*/ */
public function store(StoreClientRequest $request) public function store(StoreClientRequest $request)
{ {
$client = $this->client_repo->save($request->all(), ClientFactory::create(auth()->user()->company()->id, auth()->user()->id)); /** @var \App\Models\User $user */
$user = auth()->user();
$client = $this->client_repo->save($request->all(), ClientFactory::create($user->company()->id, $user->id));
$client->load('contacts', 'primary_contact'); $client->load('contacts', 'primary_contact');
@ -166,7 +175,7 @@ class ClientController extends BaseController
$this->uploadLogo($request->file('company_logo'), $client->company, $client); $this->uploadLogo($request->file('company_logo'), $client->company, $client);
event(new ClientWasCreated($client, $client->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); event(new ClientWasCreated($client, $client->company, Ninja::eventVars(auth()->user() ? $user->id : null)));
return $this->itemResponse($client); return $this->itemResponse($client);
} }
@ -273,9 +282,12 @@ class ClientController extends BaseController
public function merge(PurgeClientRequest $request, Client $client, string $mergeable_client) public function merge(PurgeClientRequest $request, Client $client, string $mergeable_client)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$m_client = Client::withTrashed() $m_client = Client::withTrashed()
->where('id', $this->decodePrimaryKey($mergeable_client)) ->where('id', $this->decodePrimaryKey($mergeable_client))
->where('company_id', auth()->user()->company()->id) ->where('company_id', $user->company()->id)
->first(); ->first();
if (!$m_client) { if (!$m_client) {

View File

@ -73,7 +73,10 @@ class TaskStatusController extends BaseController
*/ */
public function create(CreateTaskStatusRequest $request) public function create(CreateTaskStatusRequest $request)
{ {
$task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$task_status = TaskStatusFactory::create($user->company()->id, auth()->user()->id);
return $this->itemResponse($task_status); return $this->itemResponse($task_status);
} }
@ -87,8 +90,10 @@ class TaskStatusController extends BaseController
*/ */
public function store(StoreTaskStatusRequest $request) public function store(StoreTaskStatusRequest $request)
{ {
/** @var \App\Models\User $user */
$user = auth()->user();
$task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); $task_status = TaskStatusFactory::create($user->company()->id, auth()->user()->id);
$task_status->fill($request->all()); $task_status->fill($request->all());
$task_status->save(); $task_status->save();

View File

@ -125,7 +125,10 @@ class TaxRateController extends BaseController
*/ */
public function create(CreateTaxRateRequest $request) public function create(CreateTaxRateRequest $request)
{ {
$tax_rate = TaxRateFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$tax_rate = TaxRateFactory::create($user->company()->id, auth()->user()->id);
return $this->itemResponse($tax_rate); return $this->itemResponse($tax_rate);
} }
@ -138,7 +141,10 @@ class TaxRateController extends BaseController
*/ */
public function store(StoreTaxRateRequest $request) public function store(StoreTaxRateRequest $request)
{ {
$tax_rate = TaxRateFactory::create(auth()->user()->company()->id, auth()->user()->id); /** @var \App\Models\User $user */
$user = auth()->user();
$tax_rate = TaxRateFactory::create($user->company()->id, $user->id);
$tax_rate->fill($request->all()); $tax_rate->fill($request->all());
$tax_rate->save(); $tax_rate->save();
@ -417,15 +423,33 @@ class TaxRateController extends BaseController
*/ */
public function bulk() public function bulk()
{ {
$action = request()->input('action'); /** @var \App\Models\User $user */
$user = auth()->user();
$action = request()->input('action');
$ids = request()->input('ids'); $ids = request()->input('ids');
$tax_rates = TaxRate::withTrashed()->find($this->transformKeys($ids)); $tax_rates = TaxRate::withTrashed()->find($this->transformKeys($ids));
$tax_rates->each(function ($tax_rate, $key) use ($action) { $tax_rates->each(function ($tax_rate, $key) use ($action, $user) {
if (auth()->user()->can('edit', $tax_rate)) { if ($user->can('edit', $tax_rate)) {
if(in_array($action, ['archive','delete'])) {
$settings = $user->company()->settings;
foreach(['tax_name1','tax_name2','tax_name3'] as $tax_name) {
if($settings->{$tax_name} == $tax_rate->name) {
$settings->{$tax_name} = '';
$settings->{str_replace("name", "rate", $tax_name)} = '';
}
}
$user->company()->saveSettings($settings, $user->company());
}
$this->base_repo->{$action}($tax_rate); $this->base_repo->{$action}($tax_rate);
} }
}); });

View File

@ -93,7 +93,7 @@ class StoreClientRequest extends Request
$rules['number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)]; $rules['number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)];
$rules['id_number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)]; $rules['id_number'] = ['bail', 'nullable', Rule::unique('clients')->where('company_id', $user->company()->id)];
$rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; $rules['classification'] = 'bail|sometimes|nullable|in:individual,business,partnership,trust,charity,government,other';
return $rules; return $rules;
} }

View File

@ -60,7 +60,7 @@ class UpdateClientRequest extends Request
$rules['size_id'] = 'integer|nullable'; $rules['size_id'] = 'integer|nullable';
$rules['country_id'] = 'integer|nullable'; $rules['country_id'] = 'integer|nullable';
$rules['shipping_country_id'] = 'integer|nullable'; $rules['shipping_country_id'] = 'integer|nullable';
$rules['classification'] = 'bail|sometimes|nullable|in:individual,company,partnership,trust,charity,government,other'; $rules['classification'] = 'bail|sometimes|nullable|in:individual,business,partnership,trust,charity,government,other';
if ($this->id_number) { if ($this->id_number) {
$rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id); $rules['id_number'] = Rule::unique('clients')->where('company_id', $user->company()->id)->ignore($this->client->id);

View File

@ -30,7 +30,10 @@ class StoreUserRequest extends Request
*/ */
public function authorize() : bool public function authorize() : bool
{ {
return auth()->user()->isAdmin(); /** @var \App\Models\User $user */
$user = auth()->user();
return $user->isAdmin();
} }
public function rules() public function rules()

View File

@ -330,7 +330,7 @@ class BaseDriver extends AbstractPaymentDriver
$payment->gateway_type_id = $data['gateway_type_id']; $payment->gateway_type_id = $data['gateway_type_id'];
$client_contact = $this->getContact(); $client_contact = $this->getContact();
$client_contact_id = $client_contact ? $client_contact->id : null; $client_contact_id = $client_contact ? $client_contact->id : $this->client->contacts()->first()->id;
$payment->amount = $data['amount']; $payment->amount = $data['amount'];
$payment->type_id = $data['payment_type']; $payment->type_id = $data['payment_type'];
@ -430,9 +430,9 @@ class BaseDriver extends AbstractPaymentDriver
public function getContact() public function getContact()
{ {
if ($this->invitation) { if ($this->invitation) {
return ClientContact::find($this->invitation->client_contact_id); return ClientContact::withTrashed()->find($this->invitation->client_contact_id);
} elseif (auth()->guard('contact')->user()) { } elseif (auth()->guard('contact')->user()) {
return auth()->user(); return auth()->guard('contact')->user();
} else { } else {
return false; return false;
} }

View File

@ -121,10 +121,11 @@ class CheckoutComPaymentDriver extends BaseDriver
$this->is_four_api = true; //was four api, now known as previous. $this->is_four_api = true; //was four api, now known as previous.
/** @phpstan-ignore-next-line **/
$builder = CheckoutSdk::builder() $builder = CheckoutSdk::builder()
->previous() ->previous()
->staticKeys() ->staticKeys()
->environment($this->company_gateway->getConfigField('testMode') ? Environment::sandbox() : Environment::production()) ->environment($this->company_gateway->getConfigField('testMode') ? Environment::sandbox() : Environment::production()) /** phpstan-ignore-line **/
->publicKey($this->company_gateway->getConfigField('publicApiKey')) ->publicKey($this->company_gateway->getConfigField('publicApiKey'))
->secretKey($this->company_gateway->getConfigField('secretApiKey')); ->secretKey($this->company_gateway->getConfigField('secretApiKey'));
@ -132,10 +133,12 @@ class CheckoutComPaymentDriver extends BaseDriver
} else { } else {
$builder = CheckoutSdk::builder()->staticKeys() /** @phpstan-ignore-next-line **/
$builder = CheckoutSdk::builder()
->staticKeys()
->environment($this->company_gateway->getConfigField('testMode') ? Environment::sandbox() : Environment::production()) /** phpstan-ignore-line **/
->publicKey($this->company_gateway->getConfigField('publicApiKey')) ->publicKey($this->company_gateway->getConfigField('publicApiKey'))
->secretKey($this->company_gateway->getConfigField('secretApiKey')) ->secretKey($this->company_gateway->getConfigField('secretApiKey'));
->environment($this->company_gateway->getConfigField('testMode') ? Environment::sandbox() : Environment::production());
$this->gateway = $builder->build(); $this->gateway = $builder->build();
@ -221,6 +224,16 @@ class CheckoutComPaymentDriver extends BaseDriver
$response = $this->gateway->getPaymentsClient()->refundPayment($payment->transaction_reference, $request); $response = $this->gateway->getPaymentsClient()->refundPayment($payment->transaction_reference, $request);
SystemLogger::dispatch(
array_merge(['message' => "Gateway Refund"], $response),
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_CHECKOUT,
$payment->client,
$payment->company,
);
return [ return [
'transaction_reference' => $response['action_id'], 'transaction_reference' => $response['action_id'],
'transaction_response' => json_encode($response), 'transaction_response' => json_encode($response),
@ -228,13 +241,21 @@ class CheckoutComPaymentDriver extends BaseDriver
'description' => $response['reference'], 'description' => $response['reference'],
'code' => 202, 'code' => 202,
]; ];
} catch (CheckoutApiException $e) { } catch (CheckoutApiException $e) {
// API error // API error
throw new PaymentFailed($e->getMessage(), $e->getCode()); throw new PaymentFailed($e->getMessage(), $e->getCode());
} catch (CheckoutArgumentException $e) { } catch (CheckoutArgumentException $e) {
// Bad arguments // Bad arguments
// throw new PaymentFailed($e->getMessage(), $e->getCode()); SystemLogger::dispatch(
$e->getMessage(),
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_CHECKOUT,
$payment->client,
$payment->company,
);
return [ return [
'transaction_reference' => null, 'transaction_reference' => null,
@ -243,9 +264,17 @@ class CheckoutComPaymentDriver extends BaseDriver
'description' => $e->getMessage(), 'description' => $e->getMessage(),
'code' => $e->getCode(), 'code' => $e->getCode(),
]; ];
} catch (CheckoutAuthorizationException $e) { } catch (CheckoutAuthorizationException $e) {
// throw new PaymentFailed("The was a problem with the Checkout Gateway Credentials.", $e->getCode()); SystemLogger::dispatch(
$e->getMessage(),
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_CHECKOUT,
$payment->client,
$payment->company,
);
return [ return [
'transaction_reference' => null, 'transaction_reference' => null,
@ -268,13 +297,14 @@ class CheckoutComPaymentDriver extends BaseDriver
$request = new CustomerRequest(); $request = new CustomerRequest();
$phone = new Phone(); $phone = new Phone();
// $phone->number = $this->client->present()->phone();
$phone->number = substr(str_pad($this->client->present()->phone(), 6, "0", STR_PAD_RIGHT), 0, 24); $phone->number = substr(str_pad($this->client->present()->phone(), 6, "0", STR_PAD_RIGHT), 0, 24);
$request->email = $this->client->present()->email(); $request->email = $this->client->present()->email();
$request->name = $this->client->present()->name(); $request->name = $this->client->present()->name();
$request->phone = $phone; $request->phone = $phone;
// if($this->company_gateway->update_details)
// $this->updateCustomer();
try { try {
$response = $this->gateway->getCustomersClient()->create($request); $response = $this->gateway->getCustomersClient()->create($request);
} catch (CheckoutApiException $e) { } catch (CheckoutApiException $e) {
@ -301,6 +331,27 @@ class CheckoutComPaymentDriver extends BaseDriver
} }
} }
public function updateCustomer()
{
$phone = new Phone();
$phone->number = substr(str_pad($this->client->present()->phone(), 6, "0", STR_PAD_RIGHT), 0, 24);
$request = new CustomerRequest();
$request->email = $this->client->present()->email();
$request->name = $this->client->present()->name();
$request->phone = $phone;
try {
$response = $this->gateway->getCustomersClient()->update("customer_id", $request);
} catch (CheckoutApiException $e) {
} catch (CheckoutAuthorizationException $e) {
}
}
/** /**
* Boots a request for a token payment * Boots a request for a token payment
* *

View File

@ -206,6 +206,7 @@ class PayPalExpressPaymentDriver extends BaseDriver
'transactionId' => $this->payment_hash->hash.'-'.time(), 'transactionId' => $this->payment_hash->hash.'-'.time(),
'ButtonSource' => 'InvoiceNinja_SP', 'ButtonSource' => 'InvoiceNinja_SP',
'solutionType' => 'Sole', 'solutionType' => 'Sole',
'no_shipping' => $this->company_gateway->require_shipping_address ? 0 : 1,
]; ];
} }

View File

@ -142,6 +142,11 @@ class CreditCard implements MethodInterface
return $this->processSuccessfulPayment($response); return $this->processSuccessfulPayment($response);
} }
if(is_array($response)) {
nlog("square");
nlog($response);
}
return $this->processUnsuccessfulPayment($response); return $this->processUnsuccessfulPayment($response);
} }
@ -293,7 +298,7 @@ class CreditCard implements MethodInterface
$body->setFamilyName(''); $body->setFamilyName('');
$body->setEmailAddress($this->square_driver->client->present()->email()); $body->setEmailAddress($this->square_driver->client->present()->email());
$body->setAddress($billing_address); $body->setAddress($billing_address);
$body->setPhoneNumber($this->square_driver->client->phone); // $body->setPhoneNumber($this->square_driver->client->phone);
$body->setReferenceId($this->square_driver->client->number); $body->setReferenceId($this->square_driver->client->number);
$body->setNote('Created by Invoice Ninja.'); $body->setNote('Created by Invoice Ninja.');
@ -309,8 +314,8 @@ class CreditCard implements MethodInterface
return $result->getCustomer()->getId(); return $result->getCustomer()->getId();
} else { } else {
$errors = $api_response->getErrors(); $errors = $api_response->getErrors();
nlog($errors);
return $this->processUnsuccessfulPayment($errors); return $this->processUnsuccessfulPayment($api_response);
} }
} }
} }

View File

@ -182,9 +182,9 @@ class FacturaEInvoice extends AbstractService
Storage::makeDirectory($this->invoice->client->e_invoice_filepath($this->invoice->invitations->first())); Storage::makeDirectory($this->invoice->client->e_invoice_filepath($this->invoice->invitations->first()));
} }
$this->fac->export(Storage::disk($disk)->path($this->invoice->client->e_invoice_filepath($this->invoice->invitations->first()) . $this->invoice->getFileName("xsig"))); // $this->fac->export(Storage::disk($disk)->path($this->invoice->client->e_invoice_filepath($this->invoice->invitations->first()) . $this->invoice->getFileName("xsig")));
return $this->fac->export();
return $this->invoice->client->e_invoice_filepath($this->invoice->invitations->first()) . $this->invoice->getFileName("xsig"); // return $this->invoice->client->e_invoice_filepath($this->invoice->invitations->first()) . $this->invoice->getFileName("xsig");
} }
@ -468,8 +468,11 @@ class FacturaEInvoice extends AbstractService
{ {
$company = $this->invoice->company; $company = $this->invoice->company;
if($company->getSetting('classification'))
return $this->setIndividualSeller();
$seller = new FacturaeParty([ $seller = new FacturaeParty([
"isLegalEntity" => $company->custom_value1, // Se asume true si se omite "isLegalEntity" => true,
"taxNumber" => $company->settings->vat_number, "taxNumber" => $company->settings->vat_number,
"name" => substr($company->present()->name(), 0, 40), "name" => substr($company->present()->name(), 0, 40),
"address" => substr($company->settings->address1, 0, 80), "address" => substr($company->settings->address1, 0, 80),
@ -500,11 +503,49 @@ class FacturaEInvoice extends AbstractService
return $this; return $this;
} }
private function setIndividualSeller(): self
{
$company = $this->invoice->company;
$seller = new FacturaeParty([
"isLegalEntity" => false,
"taxNumber" => $company->settings->vat_number,
"name" => $company->getSetting('classification') === 'individual' ? substr($company->owner()->present()->name(), 0, 40) : substr($company->present()->name(), 0, 40),
"address" => substr($company->settings->address1, 0, 80),
"postCode" => substr($this->invoice->client->postal_code, 0, 5),
"town" => substr($company->settings->city, 0, 50),
"province" => substr($company->settings->state, 0, 20),
"countryCode" => $company->country()->iso_3166_3, // Se asume España si se omite
// "book" => "0", // Libro
// "merchantRegister" => "RG", // Registro Mercantil
// "sheet" => "1", // Hoja
// "folio" => "2", // Folio
// "section" => "3", // Sección
// "volume" => "4", // Tomo
"email" => substr($company->settings->email, 0, 60),
"phone" => substr($company->settings->phone, 0, 15),
"fax" => "",
"website" => substr($company->settings->website, 0, 50),
// "contactPeople" => substr($company->owner()->present()->name(), 0, 40),
"firstSurname" => $company->owner()->present()->firstName(),
"lastSurname" => $company->owner()->present()->lastName(),
]);
$this->fac->setSeller($seller);
return $this;
}
private function buildBuyer(): self private function buildBuyer(): self
{ {
$buyer = new FacturaeParty([ $buyer = new FacturaeParty([
"isLegalEntity" => $this->invoice->client->has_valid_vat_number, "isLegalEntity" => $this->invoice->client->classification === 'individual' ? false : true,
"taxNumber" => $this->invoice->client->vat_number, "taxNumber" => $this->invoice->client->vat_number,
"name" => substr($this->invoice->client->present()->name(),0, 40), "name" => substr($this->invoice->client->present()->name(),0, 40),
"firstSurname" => substr($this->invoice->client->present()->first_name(),0, 40), "firstSurname" => substr($this->invoice->client->present()->first_name(),0, 40),

View File

@ -52,6 +52,7 @@ class MarkPaid extends AbstractService
$this->invoice $this->invoice
->service() ->service()
->setExchangeRate() ->setExchangeRate()
->clearPartial()
->updateBalance($this->payable_balance * -1) ->updateBalance($this->payable_balance * -1)
->updatePaidToDate($this->payable_balance) ->updatePaidToDate($this->payable_balance)
->setStatus(Invoice::STATUS_PAID) ->setStatus(Invoice::STATUS_PAID)

View File

@ -29,7 +29,9 @@ class RefundPayment
private $credit_note; private $credit_note;
private $total_refund; private float $total_refund = 0;
private float $credits_used = 0;
private $gateway_refund_status; private $gateway_refund_status;
@ -45,8 +47,6 @@ class RefundPayment
$this->refund_data = $refund_data; $this->refund_data = $refund_data;
$this->total_refund = 0;
$this->gateway_refund_status = false; $this->gateway_refund_status = false;
$this->activity_repository = new ActivityRepository(); $this->activity_repository = new ActivityRepository();
@ -56,9 +56,9 @@ class RefundPayment
{ {
$this->payment = $this $this->payment = $this
->calculateTotalRefund() //sets amount for the refund (needed if we are refunding multiple invoices in one payment) ->calculateTotalRefund() //sets amount for the refund (needed if we are refunding multiple invoices in one payment)
->updateCreditables() //return the credits first
->processGatewayRefund() //process the gateway refund if needed ->processGatewayRefund() //process the gateway refund if needed
->setStatus() //sets status of payment ->setStatus() //sets status of payment
->updateCreditables() //return the credits first
->updatePaymentables() //update the paymentable items ->updatePaymentables() //update the paymentable items
->adjustInvoices() ->adjustInvoices()
->finalize() ->finalize()
@ -104,12 +104,14 @@ class RefundPayment
*/ */
private function processGatewayRefund() private function processGatewayRefund()
{ {
if ($this->refund_data['gateway_refund'] !== false && $this->total_refund > 0) { $net_refund = ($this->total_refund - $this->credits_used);
if ($this->refund_data['gateway_refund'] !== false && $net_refund > 0) {
if ($this->payment->company_gateway) { if ($this->payment->company_gateway) {
$response = $this->payment->company_gateway->driver($this->payment->client)->refund($this->payment, $this->total_refund); $response = $this->payment->company_gateway->driver($this->payment->client)->refund($this->payment, $net_refund);
if($response['amount'] ?? false) if($response['amount'] ?? false)
$this->total_refund = $response['amount']; $net_refund = $response['amount'];
if($response['voided'] ?? false) if($response['voided'] ?? false)
{ {
@ -123,7 +125,7 @@ class RefundPayment
})->toArray(); })->toArray();
} }
$this->payment->refunded += $this->total_refund; $this->payment->refunded += $net_refund;
if ($response['success'] == false) { if ($response['success'] == false) {
$this->payment->save(); $this->payment->save();
@ -132,7 +134,7 @@ class RefundPayment
} }
} }
} else { } else {
$this->payment->refunded += $this->total_refund; $this->payment->refunded += $net_refund;
} }
return $this; return $this;
@ -227,23 +229,29 @@ class RefundPayment
*/ */
private function updateCreditables() private function updateCreditables()
{ {
if ($this->payment->credits()->exists()) { if ($this->payment->credits()->exists()) {
$amount_to_refund = $this->total_refund;
//Adjust credits first!!! //Adjust credits first!!!
foreach ($this->payment->credits as $paymentable_credit) { foreach ($this->payment->credits as $paymentable_credit) {
$available_credit = $paymentable_credit->pivot->amount - $paymentable_credit->pivot->refunded; $available_credit = $paymentable_credit->pivot->amount - $paymentable_credit->pivot->refunded;
if ($available_credit > $this->total_refund) { if ($available_credit > $amount_to_refund) {
$paymentable_credit->pivot->refunded += $this->total_refund; $paymentable_credit->pivot->refunded += $amount_to_refund;
$paymentable_credit->pivot->save(); $paymentable_credit->pivot->save();
$paymentable_credit->service() $paymentable_credit->service()
->setStatus(Credit::STATUS_SENT) ->setStatus(Credit::STATUS_SENT)
->updateBalance($this->total_refund) ->adjustBalance($amount_to_refund)
->updatePaidToDate($this->total_refund * -1) ->updatePaidToDate($amount_to_refund * -1)
->save(); ->save();
$this->total_refund = 0; $this->credits_used += $amount_to_refund;
$amount_to_refund = 0;
} else { } else {
$paymentable_credit->pivot->refunded += $available_credit; $paymentable_credit->pivot->refunded += $available_credit;
$paymentable_credit->pivot->save(); $paymentable_credit->pivot->save();
@ -254,10 +262,12 @@ class RefundPayment
->updatePaidToDate($available_credit * -1) ->updatePaidToDate($available_credit * -1)
->save(); ->save();
$this->total_refund -= $available_credit; $this->credits_used += $available_credit;
$amount_to_refund -= $available_credit;
} }
if ($this->total_refund == 0) { if ($amount_to_refund == 0) {
break; break;
} }
} }

172
composer.lock generated
View File

@ -485,16 +485,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.281.12", "version": "3.282.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "22a92f08758db2b152843ea0875eeee5a467d8ff" "reference": "79a3ed5bb573f592823f8b1cffe0dbac3132e6b4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/22a92f08758db2b152843ea0875eeee5a467d8ff", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/79a3ed5bb573f592823f8b1cffe0dbac3132e6b4",
"reference": "22a92f08758db2b152843ea0875eeee5a467d8ff", "reference": "79a3ed5bb573f592823f8b1cffe0dbac3132e6b4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -574,9 +574,9 @@
"support": { "support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.281.12" "source": "https://github.com/aws/aws-sdk-php/tree/3.282.0"
}, },
"time": "2023-09-22T18:12:27+00:00" "time": "2023-09-28T18:09:20+00:00"
}, },
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@ -1353,16 +1353,16 @@
}, },
{ {
"name": "doctrine/dbal", "name": "doctrine/dbal",
"version": "3.6.7", "version": "3.7.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/dbal.git", "url": "https://github.com/doctrine/dbal.git",
"reference": "8e0e268052b4a8974cb00215bb2892787021614f" "reference": "00d03067f07482f025d41ab55e4ba0db5eca2cdf"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/8e0e268052b4a8974cb00215bb2892787021614f", "url": "https://api.github.com/repos/doctrine/dbal/zipball/00d03067f07482f025d41ab55e4ba0db5eca2cdf",
"reference": "8e0e268052b4a8974cb00215bb2892787021614f", "reference": "00d03067f07482f025d41ab55e4ba0db5eca2cdf",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1378,9 +1378,9 @@
"doctrine/coding-standard": "12.0.0", "doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1", "fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.1", "jetbrains/phpstorm-stubs": "2023.1",
"phpstan/phpstan": "1.10.34", "phpstan/phpstan": "1.10.35",
"phpstan/phpstan-strict-rules": "^1.5", "phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "9.6.12", "phpunit/phpunit": "9.6.13",
"psalm/plugin-phpunit": "0.18.4", "psalm/plugin-phpunit": "0.18.4",
"slevomat/coding-standard": "8.13.1", "slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.7.2", "squizlabs/php_codesniffer": "3.7.2",
@ -1446,7 +1446,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/doctrine/dbal/issues", "issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/3.6.7" "source": "https://github.com/doctrine/dbal/tree/3.7.0"
}, },
"funding": [ "funding": [
{ {
@ -1462,20 +1462,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-09-19T20:15:41+00:00" "time": "2023-09-26T20:56:55+00:00"
}, },
{ {
"name": "doctrine/deprecations", "name": "doctrine/deprecations",
"version": "v1.1.1", "version": "1.1.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/deprecations.git", "url": "https://github.com/doctrine/deprecations.git",
"reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
"reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1507,9 +1507,9 @@
"homepage": "https://www.doctrine-project.org/", "homepage": "https://www.doctrine-project.org/",
"support": { "support": {
"issues": "https://github.com/doctrine/deprecations/issues", "issues": "https://github.com/doctrine/deprecations/issues",
"source": "https://github.com/doctrine/deprecations/tree/v1.1.1" "source": "https://github.com/doctrine/deprecations/tree/1.1.2"
}, },
"time": "2023-06-03T09:27:29+00:00" "time": "2023-09-27T20:04:15+00:00"
}, },
{ {
"name": "doctrine/event-manager", "name": "doctrine/event-manager",
@ -4287,16 +4287,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v10.24.0", "version": "v10.25.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "bcebd0a4c015d5c38aeec299d355a42451dd3726" "reference": "6014dd456b414b305fb0b408404efdcec18e64bc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/bcebd0a4c015d5c38aeec299d355a42451dd3726", "url": "https://api.github.com/repos/laravel/framework/zipball/6014dd456b414b305fb0b408404efdcec18e64bc",
"reference": "bcebd0a4c015d5c38aeec299d355a42451dd3726", "reference": "6014dd456b414b305fb0b408404efdcec18e64bc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4314,7 +4314,7 @@
"ext-tokenizer": "*", "ext-tokenizer": "*",
"fruitcake/php-cors": "^1.2", "fruitcake/php-cors": "^1.2",
"guzzlehttp/uri-template": "^1.0", "guzzlehttp/uri-template": "^1.0",
"laravel/prompts": "^0.1", "laravel/prompts": "^0.1.9",
"laravel/serializable-closure": "^1.3", "laravel/serializable-closure": "^1.3",
"league/commonmark": "^2.2.1", "league/commonmark": "^2.2.1",
"league/flysystem": "^3.8.0", "league/flysystem": "^3.8.0",
@ -4396,7 +4396,7 @@
"league/flysystem-read-only": "^3.3", "league/flysystem-read-only": "^3.3",
"league/flysystem-sftp-v3": "^3.0", "league/flysystem-sftp-v3": "^3.0",
"mockery/mockery": "^1.5.1", "mockery/mockery": "^1.5.1",
"orchestra/testbench-core": "^8.10", "orchestra/testbench-core": "^8.12",
"pda/pheanstalk": "^4.0", "pda/pheanstalk": "^4.0",
"phpstan/phpstan": "^1.4.7", "phpstan/phpstan": "^1.4.7",
"phpunit/phpunit": "^10.0.7", "phpunit/phpunit": "^10.0.7",
@ -4483,20 +4483,20 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2023-09-19T15:25:04+00:00" "time": "2023-09-28T14:08:59+00:00"
}, },
{ {
"name": "laravel/prompts", "name": "laravel/prompts",
"version": "v0.1.8", "version": "v0.1.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/prompts.git", "url": "https://github.com/laravel/prompts.git",
"reference": "68dcc65babf92e1fb43cba0b3f78fc3d8002709c" "reference": "37ed55f6950d921a87d5beeab16d03f8de26b060"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/prompts/zipball/68dcc65babf92e1fb43cba0b3f78fc3d8002709c", "url": "https://api.github.com/repos/laravel/prompts/zipball/37ed55f6950d921a87d5beeab16d03f8de26b060",
"reference": "68dcc65babf92e1fb43cba0b3f78fc3d8002709c", "reference": "37ed55f6950d921a87d5beeab16d03f8de26b060",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4505,6 +4505,10 @@
"php": "^8.1", "php": "^8.1",
"symfony/console": "^6.2" "symfony/console": "^6.2"
}, },
"conflict": {
"illuminate/console": ">=10.17.0 <10.25.0",
"laravel/framework": ">=10.17.0 <10.25.0"
},
"require-dev": { "require-dev": {
"mockery/mockery": "^1.5", "mockery/mockery": "^1.5",
"pestphp/pest": "^2.3", "pestphp/pest": "^2.3",
@ -4515,6 +4519,11 @@
"ext-pcntl": "Required for the spinner to be animated." "ext-pcntl": "Required for the spinner to be animated."
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-main": "0.1.x-dev"
}
},
"autoload": { "autoload": {
"files": [ "files": [
"src/helpers.php" "src/helpers.php"
@ -4529,9 +4538,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/laravel/prompts/issues", "issues": "https://github.com/laravel/prompts/issues",
"source": "https://github.com/laravel/prompts/tree/v0.1.8" "source": "https://github.com/laravel/prompts/tree/v0.1.10"
}, },
"time": "2023-09-19T15:33:56+00:00" "time": "2023-09-29T07:26:07+00:00"
}, },
{ {
"name": "laravel/serializable-closure", "name": "laravel/serializable-closure",
@ -5825,16 +5834,16 @@
}, },
{ {
"name": "microsoft/microsoft-graph", "name": "microsoft/microsoft-graph",
"version": "1.106.0", "version": "1.107.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/microsoftgraph/msgraph-sdk-php.git", "url": "https://github.com/microsoftgraph/msgraph-sdk-php.git",
"reference": "a9f43d74131bb13cb1b5a999101d486b26601b8f" "reference": "63fed05d4d9c348db094f8d8a1d44ff9ce6887c7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/microsoftgraph/msgraph-sdk-php/zipball/a9f43d74131bb13cb1b5a999101d486b26601b8f", "url": "https://api.github.com/repos/microsoftgraph/msgraph-sdk-php/zipball/63fed05d4d9c348db094f8d8a1d44ff9ce6887c7",
"reference": "a9f43d74131bb13cb1b5a999101d486b26601b8f", "reference": "63fed05d4d9c348db094f8d8a1d44ff9ce6887c7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5871,9 +5880,9 @@
"homepage": "https://developer.microsoft.com/en-us/graph", "homepage": "https://developer.microsoft.com/en-us/graph",
"support": { "support": {
"issues": "https://github.com/microsoftgraph/msgraph-sdk-php/issues", "issues": "https://github.com/microsoftgraph/msgraph-sdk-php/issues",
"source": "https://github.com/microsoftgraph/msgraph-sdk-php/tree/1.106.0" "source": "https://github.com/microsoftgraph/msgraph-sdk-php/tree/1.107.0"
}, },
"time": "2023-09-08T06:02:27+00:00" "time": "2023-09-27T06:43:40+00:00"
}, },
{ {
"name": "mollie/mollie-api-php", "name": "mollie/mollie-api-php",
@ -6361,16 +6370,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "2.70.0", "version": "2.71.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/briannesbitt/Carbon.git", "url": "https://github.com/briannesbitt/Carbon.git",
"reference": "d3298b38ea8612e5f77d38d1a99438e42f70341d" "reference": "98276233188583f2ff845a0f992a235472d9466a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d3298b38ea8612e5f77d38d1a99438e42f70341d", "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/98276233188583f2ff845a0f992a235472d9466a",
"reference": "d3298b38ea8612e5f77d38d1a99438e42f70341d", "reference": "98276233188583f2ff845a0f992a235472d9466a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6463,7 +6472,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-09-07T16:43:50+00:00" "time": "2023-09-25T11:31:05+00:00"
}, },
{ {
"name": "nette/schema", "name": "nette/schema",
@ -8127,16 +8136,16 @@
}, },
{ {
"name": "phpstan/phpdoc-parser", "name": "phpstan/phpdoc-parser",
"version": "1.24.1", "version": "1.24.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git", "url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01" "reference": "bcad8d995980440892759db0c32acae7c8e79442"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bcad8d995980440892759db0c32acae7c8e79442",
"reference": "9f854d275c2dbf84915a5c0ec9a2d17d2cd86b01", "reference": "bcad8d995980440892759db0c32acae7c8e79442",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8168,9 +8177,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types", "description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": { "support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues", "issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.1" "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.2"
}, },
"time": "2023-09-18T12:18:02+00:00" "time": "2023-09-26T12:28:12+00:00"
}, },
{ {
"name": "pragmarx/google2fa", "name": "pragmarx/google2fa",
@ -9689,16 +9698,16 @@
}, },
{ {
"name": "setasign/fpdi", "name": "setasign/fpdi",
"version": "v2.4.1", "version": "v2.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Setasign/FPDI.git", "url": "https://github.com/Setasign/FPDI.git",
"reference": "f4ba73e5bc053ccc90b81717c5df1cb2ea7bae7b" "reference": "ecf0459643ec963febfb9a5d529dcd93656006a4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Setasign/FPDI/zipball/f4ba73e5bc053ccc90b81717c5df1cb2ea7bae7b", "url": "https://api.github.com/repos/Setasign/FPDI/zipball/ecf0459643ec963febfb9a5d529dcd93656006a4",
"reference": "f4ba73e5bc053ccc90b81717c5df1cb2ea7bae7b", "reference": "ecf0459643ec963febfb9a5d529dcd93656006a4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9749,7 +9758,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/Setasign/FPDI/issues", "issues": "https://github.com/Setasign/FPDI/issues",
"source": "https://github.com/Setasign/FPDI/tree/v2.4.1" "source": "https://github.com/Setasign/FPDI/tree/v2.5.0"
}, },
"funding": [ "funding": [
{ {
@ -9757,7 +9766,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-07-27T08:12:09+00:00" "time": "2023-09-28T10:46:27+00:00"
}, },
{ {
"name": "shopify/shopify-api", "name": "shopify/shopify-api",
@ -10330,16 +10339,16 @@
}, },
{ {
"name": "stripe/stripe-php", "name": "stripe/stripe-php",
"version": "v12.4.0", "version": "v12.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/stripe/stripe-php.git", "url": "https://github.com/stripe/stripe-php.git",
"reference": "7d0a90772fc1c179e370971264318208533324b9" "reference": "a4249b4a90437844f6c35e8701f8c68acd206f56"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/7d0a90772fc1c179e370971264318208533324b9", "url": "https://api.github.com/repos/stripe/stripe-php/zipball/a4249b4a90437844f6c35e8701f8c68acd206f56",
"reference": "7d0a90772fc1c179e370971264318208533324b9", "reference": "a4249b4a90437844f6c35e8701f8c68acd206f56",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10384,9 +10393,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/stripe/stripe-php/issues", "issues": "https://github.com/stripe/stripe-php/issues",
"source": "https://github.com/stripe/stripe-php/tree/v12.4.0" "source": "https://github.com/stripe/stripe-php/tree/v12.5.0"
}, },
"time": "2023-09-21T22:55:47+00:00" "time": "2023-09-28T23:06:27+00:00"
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
@ -15037,16 +15046,16 @@
}, },
{ {
"name": "friendsofphp/php-cs-fixer", "name": "friendsofphp/php-cs-fixer",
"version": "v3.28.0", "version": "v3.34.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "113e09fea3d2306319ffaa2423fe3de768b28cff" "reference": "7c7a4ad2ed8fe50df3e25528218b13d383608f23"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/113e09fea3d2306319ffaa2423fe3de768b28cff", "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7c7a4ad2ed8fe50df3e25528218b13d383608f23",
"reference": "113e09fea3d2306319ffaa2423fe3de768b28cff", "reference": "7c7a4ad2ed8fe50df3e25528218b13d383608f23",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -15067,6 +15076,9 @@
"symfony/process": "^5.4 || ^6.0", "symfony/process": "^5.4 || ^6.0",
"symfony/stopwatch": "^5.4 || ^6.0" "symfony/stopwatch": "^5.4 || ^6.0"
}, },
"conflict": {
"stevebauman/unfinalize": "*"
},
"require-dev": { "require-dev": {
"facile-it/paraunit": "^1.3 || ^2.0", "facile-it/paraunit": "^1.3 || ^2.0",
"justinrainbow/json-schema": "^5.2", "justinrainbow/json-schema": "^5.2",
@ -15120,7 +15132,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.28.0" "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.34.0"
}, },
"funding": [ "funding": [
{ {
@ -15128,7 +15140,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-09-22T20:43:40+00:00" "time": "2023-09-29T15:34:26+00:00"
}, },
{ {
"name": "hamcrest/hamcrest-php", "name": "hamcrest/hamcrest-php",
@ -15839,16 +15851,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.10.35", "version": "1.10.36",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3" "reference": "ffa3089511121a672e62969404e4fddc753f9b15"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e730e5facb75ffe09dfb229795e8c01a459f26c3", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ffa3089511121a672e62969404e4fddc753f9b15",
"reference": "e730e5facb75ffe09dfb229795e8c01a459f26c3", "reference": "ffa3089511121a672e62969404e4fddc753f9b15",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -15897,7 +15909,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-09-19T15:27:56+00:00" "time": "2023-09-29T14:07:45+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
@ -16567,16 +16579,16 @@
}, },
{ {
"name": "sebastian/complexity", "name": "sebastian/complexity",
"version": "3.0.1", "version": "3.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git", "url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "c70b73893e10757af9c6a48929fa6a333b56a97a" "reference": "68cfb347a44871f01e33ab0ef8215966432f6957"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c70b73893e10757af9c6a48929fa6a333b56a97a", "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957",
"reference": "c70b73893e10757af9c6a48929fa6a333b56a97a", "reference": "68cfb347a44871f01e33ab0ef8215966432f6957",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -16589,7 +16601,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "3.0-dev" "dev-main": "3.1-dev"
} }
}, },
"autoload": { "autoload": {
@ -16613,7 +16625,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues", "issues": "https://github.com/sebastianbergmann/complexity/issues",
"security": "https://github.com/sebastianbergmann/complexity/security/policy", "security": "https://github.com/sebastianbergmann/complexity/security/policy",
"source": "https://github.com/sebastianbergmann/complexity/tree/3.0.1" "source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0"
}, },
"funding": [ "funding": [
{ {
@ -16621,7 +16633,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2023-08-31T09:55:53+00:00" "time": "2023-09-28T11:50:59+00:00"
}, },
{ {
"name": "sebastian/diff", "name": "sebastian/diff",

View File

@ -15,8 +15,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => env('APP_VERSION','5.7.22'), 'app_version' => env('APP_VERSION','5.7.23'),
'app_tag' => env('APP_TAG','5.7.22'), 'app_tag' => env('APP_TAG','5.7.23'),
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''), 'api_secret' => env('API_SECRET', ''),

View File

@ -5176,7 +5176,7 @@ $LANG = array(
'email_delivered' => 'Email Delivered', 'email_delivered' => 'Email Delivered',
'log' => 'Log', 'log' => 'Log',
'classification' => 'Classification', 'classification' => 'Classification',
'stock_quantity' => 'Stock :quantity', 'stock_quantity_number' => 'Stock :quantity',
); );
return $LANG; return $LANG;

View File

@ -16,6 +16,8 @@ trait CreatesApplication
{ {
$app = require __DIR__.'/../bootstrap/app.php'; $app = require __DIR__.'/../bootstrap/app.php';
define('STDIN', fopen("php://stdin", "r"));
$app->make(Kernel::class)->bootstrap(); $app->make(Kernel::class)->bootstrap();
Hash::setRounds(4); Hash::setRounds(4);

View File

@ -73,7 +73,7 @@ class ClassificationTest extends TestCase
public function testValidation2Classification() public function testValidation2Classification()
{ {
$this->client->classification = 'company'; $this->client->classification = 'business';
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),
@ -84,7 +84,7 @@ class ClassificationTest extends TestCase
$arr = $response->json(); $arr = $response->json();
$this->assertEquals('company', $arr['data']['classification']); $this->assertEquals('business', $arr['data']['classification']);
} }
public function testValidation3Classification() public function testValidation3Classification()

View File

@ -497,7 +497,7 @@ class PaymentTest extends TestCase
'is_primary' => 1, 'is_primary' => 1,
]); ]);
/** @var \App\Models\Invoice $invoice */
$invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id $invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
$invoice->client_id = $client->id; $invoice->client_id = $client->id;
@ -1310,15 +1310,14 @@ class PaymentTest extends TestCase
]; ];
try {
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token, 'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments?include=invoices', $data); ])->postJson('/api/v1/payments?include=invoices', $data);
} catch (ValidationException $e) {
$message = json_decode($e->validator->getMessageBag(), 1); $response->assertStatus(422);
$this->assertNotNull($message);
}
} }
public function testPaymentWithSameInvoiceMultipleTimes() public function testPaymentWithSameInvoiceMultipleTimes()

View File

@ -11,21 +11,22 @@
namespace Tests\Feature; namespace Tests\Feature;
use Tests\TestCase;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use Tests\MockAccountData;
use App\Models\ClientContact;
use App\Factory\ClientFactory; use App\Factory\ClientFactory;
use App\Factory\CreditFactory; use App\Factory\CreditFactory;
use App\Factory\InvoiceFactory; use App\Factory\InvoiceFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Models\ClientContact;
use App\Models\Invoice;
use App\Models\Payment;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Helpers\Invoice\InvoiceSum;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
use Tests\MockAccountData; use Illuminate\Routing\Middleware\ThrottleRequests;
use Tests\TestCase; use Illuminate\Foundation\Testing\DatabaseTransactions;
/** /**
* @test * @test
@ -37,6 +38,8 @@ class RefundTest extends TestCase
use DatabaseTransactions; use DatabaseTransactions;
use MockAccountData; use MockAccountData;
public $faker;
protected function setUp() :void protected function setUp() :void
{ {
parent::setUp(); parent::setUp();
@ -53,7 +56,7 @@ class RefundTest extends TestCase
$this->makeTestData(); $this->makeTestData();
$this->withoutExceptionHandling(); // $this->withoutExceptionHandling();
} }
/** /**
@ -82,10 +85,10 @@ class RefundTest extends TestCase
$this->invoice->save(); $this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice); $invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build(); $invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice(); $this->invoice = $invoice_calc->getInvoice();
$this->invoice->save(); $this->invoice->save();
$data = [ $data = [
@ -119,14 +122,12 @@ class RefundTest extends TestCase
$response = false; $response = false;
try {
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token, 'X-API-TOKEN' => $this->token,
])->post('/api/v1/payments/refund', $data); ])->postJson('/api/v1/payments/refund', $data);
} catch (ValidationException $e) {
$message = json_decode($e->validator->getMessageBag(), 1);
}
$arr = $response->json(); $arr = $response->json();
@ -165,10 +166,10 @@ class RefundTest extends TestCase
$this->invoice->save(); $this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice); $invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build(); $invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice(); $this->invoice = $invoice_calc->getInvoice();
$this->invoice->save(); $this->invoice->save();
$this->invoice->setRelation('client', $this->client); $this->invoice->setRelation('client', $this->client);
@ -217,23 +218,12 @@ class RefundTest extends TestCase
'date' => '2020/12/12', 'date' => '2020/12/12',
]; ];
$response = false;
try {
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token, 'X-API-TOKEN' => $this->token,
])->post('/api/v1/payments/refund', $data); ])->postJson('/api/v1/payments/refund', $data);
} catch (ValidationException $e) { $response->assertStatus(422);
$message = json_decode($e->validator->getMessageBag(), 1);
$this->assertNotNull($message);
\Log::error($message);
}
if ($response) {
$response->assertStatus(302);
}
} }
/** /**
@ -262,10 +252,10 @@ class RefundTest extends TestCase
$this->invoice->save(); $this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice); $invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build(); $invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice(); $this->invoice = $invoice_calc->getInvoice();
$this->invoice->save(); $this->invoice->save();
$data = [ $data = [
@ -346,10 +336,10 @@ class RefundTest extends TestCase
$this->invoice->save(); $this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice); $invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build(); $invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice(); $this->invoice = $invoice_calc->getInvoice();
$this->invoice->save(); $this->invoice->save();
$data = [ $data = [
@ -439,10 +429,10 @@ class RefundTest extends TestCase
$this->invoice->save(); $this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice); $invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build(); $invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice(); $this->invoice = $invoice_calc->getInvoice();
$this->invoice->save(); $this->invoice->save();
$data = [ $data = [
@ -485,10 +475,10 @@ class RefundTest extends TestCase
$this->invoice->save(); $this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice); $invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build(); $invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice(); $this->invoice = $invoice_calc->getInvoice();
$this->invoice->save(); $this->invoice->save();
$data = [ $data = [
@ -553,13 +543,13 @@ class RefundTest extends TestCase
$this->invoice->line_items = $this->buildLineItems(); $this->invoice->line_items = $this->buildLineItems();
$this->invoice->uses_inclusive_taxes = false; $this->invoice->uses_inclusive_taxes = false;
$this->invoice_client_id = $client->id; $this->invoice->client_id = $client->id;
$this->invoice->save(); $this->invoice->save();
$this->invoice_calc = new InvoiceSum($this->invoice); $invoice_calc = new InvoiceSum($this->invoice);
$this->invoice_calc->build(); $invoice_calc->build();
$this->invoice = $this->invoice_calc->getInvoice(); $this->invoice = $invoice_calc->getInvoice();
$this->invoice->save(); $this->invoice->save();
$this->credit = CreditFactory::create($this->company->id, $this->user->id); $this->credit = CreditFactory::create($this->company->id, $this->user->id);
@ -650,4 +640,172 @@ class RefundTest extends TestCase
} }
/*Additional scenarios*/ /*Additional scenarios*/
public function testRefundsWhenCreditsArePresent()
{
$i = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Invoice::STATUS_SENT,
'amount' => 1000,
'balance' => 1000,
]);
$c = Credit::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Invoice::STATUS_SENT,
'amount' => 100,
'balance' => 100,
]);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 1000,
],
],
'credits' => [
[
'credit_id' => $c->hashed_id,
'amount' => 100,
],
],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments', $data);
$arr = $response->json();
$response->assertStatus(200);
$this->assertEquals(0, $c->fresh()->balance);
$this->assertEquals(0, $i->fresh()->balance);
$payment_id = $arr['data']['id'];
$refund = [
'id' => $payment_id,
'client_id' => $this->client->hashed_id,
'amount' => 10,
'date' => now()->format('Y-m-d'),
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 10,
],
]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/refund', $refund);
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals(0, $arr['data']['refunded']);
$this->assertEquals(10, $c->fresh()->balance);
$this->assertEquals(10, $i->fresh()->balance);
}
public function testRefundsWithSplitCreditAndPaymentRefund()
{
$i = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Invoice::STATUS_SENT,
'amount' => 1000,
'balance' => 1000,
]);
$c = Credit::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $this->client->id,
'status_id' => Invoice::STATUS_SENT,
'amount' => 100,
'balance' => 100,
]);
$data = [
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 1000,
],
],
'credits' => [
[
'credit_id' => $c->hashed_id,
'amount' => 100,
],
],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments', $data);
$arr = $response->json();
$response->assertStatus(200);
$this->assertEquals(0, $c->fresh()->balance);
$this->assertEquals(0, $i->fresh()->balance);
$payment_id = $arr['data']['id'];
$payment = Payment::find($this->decodePrimaryKey($payment_id));
$this->assertEquals(900, $payment->amount);
$this->assertEquals(900, $payment->applied);
$this->assertEquals(0, $payment->refunded);
$refund = [
'id' => $payment_id,
'client_id' => $this->client->hashed_id,
'amount' => 200,
'date' => now()->format('Y-m-d'),
'invoices' => [
[
'invoice_id' => $i->hashed_id,
'amount' => 200,
],
]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/refund', $refund);
$response->assertStatus(200);
$arr = $response->json();
$this->assertEquals(100, $arr['data']['refunded']);
$this->assertEquals(100, $c->fresh()->balance);
$this->assertEquals(200, $i->fresh()->balance);
$this->assertEquals(900, $payment->fresh()->amount);
$this->assertEquals(900, $payment->fresh()->applied);
$this->assertEquals(100, $payment->fresh()->refunded);
}
} }

View File

@ -11,13 +11,15 @@
namespace Tests\Feature; namespace Tests\Feature;
use Tests\TestCase;
use App\Models\Company;
use App\Models\TaxRate;
use Tests\MockAccountData;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
use Tests\MockAccountData; use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
/** /**
* @test * @test
@ -44,6 +46,44 @@ class TaxRateApiTest extends TestCase
Model::reguard(); Model::reguard();
} }
public function testRemovingDefaultTaxes()
{
$t = TaxRate::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'name' => 'nastytax1',
'rate' => 10,
]);
$settings = $this->company->settings;
$settings->tax_rate1 = $t->rate;
$settings->tax_name1 = $t->name;
$this->company->saveSettings($settings, $this->company);
$this->company->fresh();
$this->assertEquals('nastytax1', $this->company->settings->tax_name1);
$this->assertEquals(10, $this->company->settings->tax_rate1);
$data = [
'ids' => [$this->encodePrimaryKey($t->id)],
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/tax_rates/bulk?action=archive', $data);
$response->assertStatus(200);
$this->company = $this->company->fresh();
$this->assertEquals('', $this->company->getSetting('tax_name1'));
$this->assertEquals(0, $this->company->getSetting('tax_rate1'));
}
public function testTaxRatesGetFilter() public function testTaxRatesGetFilter()
{ {
$response = $this->withHeaders([ $response = $this->withHeaders([

View File

@ -43,6 +43,8 @@ class CompanyLedgerTest extends TestCase
public $account; public $account;
public $faker;
protected function setUp() :void protected function setUp() :void
{ {
parent::setUp(); parent::setUp();

View File

@ -11,57 +11,58 @@
namespace Tests; namespace Tests;
use App\DataMapper\ClientRegistrationFields; use App\Models\Task;
use App\DataMapper\ClientSettings; use App\Models\User;
use App\DataMapper\CompanySettings; use App\Models\Quote;
use App\Factory\CompanyUserFactory;
use App\Factory\CreditFactory;
use App\Factory\InvoiceFactory;
use App\Factory\InvoiceInvitationFactory;
use App\Factory\InvoiceItemFactory;
use App\Factory\InvoiceToRecurringInvoiceFactory;
use App\Factory\PurchaseOrderFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Jobs\Company\CreateCompanyTaskStatuses;
use App\Models\Account;
use App\Models\BankIntegration;
use App\Models\BankTransaction;
use App\Models\BankTransactionRule;
use App\Models\Client; use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Company;
use App\Models\CompanyGateway;
use App\Models\CompanyToken;
use App\Models\Credit; use App\Models\Credit;
use App\Models\CreditInvitation; use App\Models\Vendor;
use App\Models\Account;
use App\Models\Company;
use App\Models\Expense; use App\Models\Expense;
use App\Models\ExpenseCategory;
use App\Models\GroupSetting;
use App\Models\InvoiceInvitation;
use App\Models\Payment; use App\Models\Payment;
use App\Models\Product; use App\Models\Product;
use App\Models\Project; use App\Models\Project;
use App\Models\PurchaseOrderInvitation; use App\Models\TaxRate;
use App\Models\Quote; use App\Models\Scheduler;
use App\Models\TaskStatus;
use App\Utils\TruthSource;
use App\Models\CompanyToken;
use App\Models\GroupSetting;
use App\Models\ClientContact;
use App\Models\VendorContact;
use App\Factory\CreditFactory;
use App\Models\CompanyGateway;
use App\Models\RecurringQuote;
use Illuminate\Support\Carbon;
use App\Factory\InvoiceFactory;
use App\Models\BankIntegration;
use App\Models\BankTransaction;
use App\Models\ExpenseCategory;
use App\Models\QuoteInvitation; use App\Models\QuoteInvitation;
use App\Utils\Traits\MakesHash;
use App\Models\CreditInvitation;
use App\Models\RecurringExpense; use App\Models\RecurringExpense;
use App\Models\RecurringInvoice; use App\Models\RecurringInvoice;
use App\Models\RecurringQuote; use App\Models\InvoiceInvitation;
use App\Models\Scheduler; use App\DataMapper\ClientSettings;
use App\Models\Task; use App\DataMapper\CompanySettings;
use App\Models\TaskStatus; use App\Factory\CompanyUserFactory;
use App\Models\TaxRate; use App\Factory\InvoiceItemFactory;
use App\Models\User; use App\Helpers\Invoice\InvoiceSum;
use App\Models\Vendor; use App\Models\BankTransactionRule;
use App\Models\VendorContact;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\MakesHash;
use App\Utils\TruthSource;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use App\Factory\PurchaseOrderFactory;
use Illuminate\Support\Facades\Cache;
use App\Utils\Traits\GeneratesCounter;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use App\Models\PurchaseOrderInvitation;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use App\Factory\InvoiceInvitationFactory;
use App\DataMapper\ClientRegistrationFields;
use App\Jobs\Company\CreateCompanyTaskStatuses;
use App\Factory\InvoiceToRecurringInvoiceFactory;
/** /**
* Class MockAccountData. * Class MockAccountData.
@ -200,7 +201,9 @@ trait MockAccountData
/* Warm up the cache !*/ /* Warm up the cache !*/
$cached_tables = config('ninja.cached_tables'); $cached_tables = config('ninja.cached_tables');
$this->artisan('db:seed --force'); Artisan::call('db:seed', [
'--force' => true
]);
foreach ($cached_tables as $name => $class) { foreach ($cached_tables as $name => $class) {
// check that the table exists in case the migration is pending // check that the table exists in case the migration is pending

View File

@ -49,7 +49,36 @@ class InvoiceTest extends TestCase
$this->invoice_calc = new InvoiceSum($this->invoice); $this->invoice_calc = new InvoiceSum($this->invoice);
} }
public function testGrossTaxAmountCalcuations() public function testMarkPaidWithPartial()
{
$item = InvoiceItemFactory::create();
$item->quantity = 1;
$item->cost = 50;
$line_items[] = $item;
$this->invoice->partial = 5;
$this->invoice->partial_due_date = now()->addDay();
$this->invoice->due_date = now()->addDays(10);
$this->invoice->line_items = $line_items;
$this->invoice->save();
$invoice_calc = new InvoiceSum($this->invoice);
$invoice = $invoice_calc->build()->getInvoice()->service()->markSent()->save();
$this->assertEquals(5, $invoice->partial);
$this->assertNotNull($invoice->partial_due_date);
$this->assertEquals(50, $invoice->amount);
$invoice = $invoice->service()->markPaid()->save();
$this->assertEquals(0, $invoice->partial);
$this->assertEquals(0, $invoice->balance);
$this->assertNull($invoice->partial_due_date);
}
public function testGrossTaxAmountCalcuations()
{ {
$invoice = InvoiceFactory::create($this->company->id, $this->user->id); $invoice = InvoiceFactory::create($this->company->id, $this->user->id);
$invoice->client_id = $this->client->id; $invoice->client_id = $this->client->id;