mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 01:54:32 -04:00
commit
76e4832f6c
@ -1 +1 @@
|
||||
5.3.56
|
||||
5.3.57
|
@ -37,6 +37,8 @@ class CreditFactory
|
||||
$credit->tax_rate1 = 0;
|
||||
$credit->tax_name2 = '';
|
||||
$credit->tax_rate2 = 0;
|
||||
$credit->tax_name3 = '';
|
||||
$credit->tax_rate3 = 0;
|
||||
$credit->custom_value1 = '';
|
||||
$credit->custom_value2 = '';
|
||||
$credit->custom_value3 = '';
|
||||
|
@ -30,9 +30,12 @@ class CreditController extends Controller
|
||||
{
|
||||
set_time_limit(0);
|
||||
|
||||
$data = ['credit' => $credit];
|
||||
$invitation = $credit->invitations()->where('client_contact_id', auth()->user()->id)->first();
|
||||
|
||||
$invitation = $credit->invitations()->where('client_contact_id', auth()->user()->id)->first();
|
||||
$data = [
|
||||
'credit' => $credit,
|
||||
'key' => $invitation->key
|
||||
];
|
||||
|
||||
if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) {
|
||||
|
||||
|
@ -2,12 +2,19 @@
|
||||
|
||||
namespace App\Http\Controllers\ClientPortal;
|
||||
|
||||
use App\Events\Credit\CreditWasViewed;
|
||||
use App\Events\Invoice\InvoiceWasViewed;
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Events\Quote\QuoteWasViewed;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class EntityViewController extends Controller
|
||||
@ -19,7 +26,7 @@ class EntityViewController extends Controller
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $entity_types = ['invoice', 'quote'];
|
||||
private $entity_types = ['invoice', 'quote', 'credit', 'recurring_invoice'];
|
||||
|
||||
/**
|
||||
* Show the entity outside client portal.
|
||||
@ -118,4 +125,54 @@ class EntityViewController extends Controller
|
||||
|
||||
return back();
|
||||
}
|
||||
|
||||
public function handlePasswordSet(Request $request)
|
||||
{
|
||||
$entity_obj = 'App\Models\\'.ucfirst(Str::camel($request->entity_type)).'Invitation';
|
||||
$key = $request->entity_type.'_id';
|
||||
|
||||
$invitation = $entity_obj::where('key', $request->invitation_key)
|
||||
->whereHas($request->entity_type, function ($query) {
|
||||
$query->where('is_deleted',0);
|
||||
})
|
||||
->with('contact.client')
|
||||
->first();
|
||||
|
||||
$contact = $invitation->contact;
|
||||
$contact->password = Hash::make($request->password);
|
||||
$contact->save();
|
||||
|
||||
$request->session()->invalidate();
|
||||
auth()->guard('contact')->loginUsingId($contact->id, true);
|
||||
|
||||
if (! $invitation->viewed_date) {
|
||||
$invitation->markViewed();
|
||||
|
||||
event(new InvitationWasViewed($invitation->{$request->entity_type}, $invitation, $invitation->{$request->entity_type}->company, Ninja::eventVars()));
|
||||
|
||||
$this->fireEntityViewedEvent($invitation, $request->entity_type);
|
||||
}
|
||||
|
||||
return redirect()->route('client.'.$request->entity_type.'.show', [$request->entity_type => $this->encodePrimaryKey($invitation->{$key})]);
|
||||
|
||||
}
|
||||
|
||||
private function fireEntityViewedEvent($invitation, $entity_string)
|
||||
{
|
||||
switch ($entity_string) {
|
||||
case 'invoice':
|
||||
event(new InvoiceWasViewed($invitation, $invitation->company, Ninja::eventVars()));
|
||||
break;
|
||||
case 'quote':
|
||||
event(new QuoteWasViewed($invitation, $invitation->company, Ninja::eventVars()));
|
||||
break;
|
||||
case 'credit':
|
||||
event(new CreditWasViewed($invitation, $invitation->company, Ninja::eventVars()));
|
||||
break;
|
||||
default:
|
||||
// code...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -102,6 +102,17 @@ class InvitationController extends Controller
|
||||
auth()->guard('contact')->loginUsingId($client_contact->id, true);
|
||||
|
||||
} elseif ((bool) $invitation->contact->client->getSetting('enable_client_portal_password') !== false) {
|
||||
|
||||
//if no contact password has been set - allow user to set password - then continue to view entity
|
||||
if(empty($invitation->contact->password)){
|
||||
|
||||
return $this->render('view_entity.set_password', [
|
||||
'root' => 'themes',
|
||||
'entity_type' => $entity,
|
||||
'invitation_key' => $invitation_key
|
||||
]);
|
||||
}
|
||||
|
||||
$this->middleware('auth:contact');
|
||||
return redirect()->route('client.login');
|
||||
|
||||
|
@ -74,12 +74,12 @@ class InvoiceController extends Controller
|
||||
|
||||
$data = [
|
||||
'invoice' => $invoice,
|
||||
'key' => $invitation->key
|
||||
];
|
||||
|
||||
if ($request->query('mode') === 'fullscreen') {
|
||||
return render('invoices.show-fullscreen', $data);
|
||||
}
|
||||
// $request->fullUrlWithQuery(['q' => null]);
|
||||
return $this->render('invoices.show', $data);
|
||||
}
|
||||
|
||||
|
@ -58,12 +58,14 @@ class QuoteController extends Controller
|
||||
{
|
||||
/* If the quote is expired, convert the status here */
|
||||
|
||||
$data = [
|
||||
'quote' => $quote,
|
||||
];
|
||||
|
||||
$invitation = $quote->invitations()->where('client_contact_id', auth()->user()->id)->first();
|
||||
|
||||
$data = [
|
||||
'quote' => $quote,
|
||||
'key' => $invitation->key,
|
||||
];
|
||||
|
||||
if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) {
|
||||
|
||||
$invitation->markViewed();
|
||||
@ -160,7 +162,7 @@ class QuoteController extends Controller
|
||||
$quotes = Quote::whereIn('id', $ids)
|
||||
->where('client_id', auth('contact')->user()->client->id)
|
||||
->where('company_id', auth('contact')->user()->client->company_id)
|
||||
->where('status_id', Quote::STATUS_SENT)
|
||||
->whereIn('status_id', [Quote::STATUS_DRAFT, Quote::STATUS_SENT])
|
||||
->withTrashed()
|
||||
->get();
|
||||
|
||||
|
@ -385,7 +385,7 @@ class CompanyGatewayController extends BaseController
|
||||
|
||||
$company_gateway->save();
|
||||
|
||||
ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
|
||||
// ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db);
|
||||
|
||||
return $this->itemResponse($company_gateway);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class PayNowDropdown extends Component
|
||||
|
||||
$this->total = $total;
|
||||
|
||||
$this->methods = auth()->user()->client->service()->getPaymentMethods($total);
|
||||
$this->methods = auth()->guard('contact')->user()->client->service()->getPaymentMethods($total);
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
@ -61,6 +61,9 @@ class UpdateCompanyGatewayRequest extends Request
|
||||
$input['fees_and_limits'] = $this->cleanFeesAndLimits($input['fees_and_limits']);
|
||||
}
|
||||
|
||||
if (isset($input['token_billing']) && $input['token_billing'] == 'disabled')
|
||||
$input['token_billing'] = 'off';
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +76,10 @@ class StoreRecurringInvoiceRequest extends Request
|
||||
$input['assigned_user_id'] = $this->decodePrimaryKey($input['assigned_user_id']);
|
||||
}
|
||||
|
||||
if (array_key_exists('vendor_id', $input) && is_string($input['vendor_id'])) {
|
||||
$input['vendor_id'] = $this->decodePrimaryKey($input['vendor_id']);
|
||||
}
|
||||
|
||||
if (isset($input['client_contacts'])) {
|
||||
foreach ($input['client_contacts'] as $key => $contact) {
|
||||
if (! array_key_exists('send_email', $contact) || ! array_key_exists('id', $contact)) {
|
||||
|
137
app/Import/Definitions/QuoteMap.php
Normal file
137
app/Import/Definitions/QuoteMap.php
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://quoteninja.com).
|
||||
*
|
||||
* @link https://github.com/quoteninja/quoteninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://quoteninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Definitions;
|
||||
|
||||
class QuoteMap
|
||||
{
|
||||
public static function importable()
|
||||
{
|
||||
return [
|
||||
0 => 'quote.number',
|
||||
1 => 'quote.user_id',
|
||||
2 => 'quote.amount',
|
||||
3 => 'quote.balance',
|
||||
4 => 'client.name',
|
||||
5 => 'quote.discount',
|
||||
6 => 'quote.po_number',
|
||||
7 => 'quote.date',
|
||||
8 => 'quote.due_date',
|
||||
9 => 'quote.terms',
|
||||
10 => 'quote.status',
|
||||
11 => 'quote.public_notes',
|
||||
12 => 'quote.is_sent',
|
||||
13 => 'quote.private_notes',
|
||||
14 => 'quote.uses_inclusive_taxes',
|
||||
15 => 'quote.tax_name1',
|
||||
16 => 'quote.tax_rate1',
|
||||
17 => 'quote.tax_name2',
|
||||
18 => 'quote.tax_rate2',
|
||||
19 => 'quote.tax_name3',
|
||||
20 => 'quote.tax_rate3',
|
||||
21 => 'quote.is_amount_discount',
|
||||
22 => 'quote.footer',
|
||||
23 => 'quote.partial',
|
||||
24 => 'quote.partial_due_date',
|
||||
25 => 'quote.custom_value1',
|
||||
26 => 'quote.custom_value2',
|
||||
27 => 'quote.custom_value3',
|
||||
28 => 'quote.custom_value4',
|
||||
29 => 'quote.custom_surcharge1',
|
||||
30 => 'quote.custom_surcharge2',
|
||||
31 => 'quote.custom_surcharge3',
|
||||
32 => 'quote.custom_surcharge4',
|
||||
33 => 'quote.exchange_rate',
|
||||
34 => 'payment.date',
|
||||
35 => 'payment.amount',
|
||||
36 => 'payment.transaction_reference',
|
||||
37 => 'item.quantity',
|
||||
38 => 'item.cost',
|
||||
39 => 'item.product_key',
|
||||
40 => 'item.notes',
|
||||
41 => 'item.discount',
|
||||
42 => 'item.is_amount_discount',
|
||||
43 => 'item.tax_name1',
|
||||
44 => 'item.tax_rate1',
|
||||
45 => 'item.tax_name2',
|
||||
46 => 'item.tax_rate2',
|
||||
47 => 'item.tax_name3',
|
||||
48 => 'item.tax_rate3',
|
||||
49 => 'item.custom_value1',
|
||||
50 => 'item.custom_value2',
|
||||
51 => 'item.custom_value3',
|
||||
52 => 'item.custom_value4',
|
||||
53 => 'item.type_id',
|
||||
54 => 'client.email',
|
||||
];
|
||||
}
|
||||
|
||||
public static function import_keys()
|
||||
{
|
||||
return [
|
||||
0 => 'texts.quote_number',
|
||||
1 => 'texts.user',
|
||||
2 => 'texts.amount',
|
||||
3 => 'texts.balance',
|
||||
4 => 'texts.client',
|
||||
5 => 'texts.discount',
|
||||
6 => 'texts.po_number',
|
||||
7 => 'texts.date',
|
||||
8 => 'texts.due_date',
|
||||
9 => 'texts.terms',
|
||||
10 => 'texts.status',
|
||||
11 => 'texts.public_notes',
|
||||
12 => 'texts.sent',
|
||||
13 => 'texts.private_notes',
|
||||
14 => 'texts.uses_inclusive_taxes',
|
||||
15 => 'texts.tax_name',
|
||||
16 => 'texts.tax_rate',
|
||||
17 => 'texts.tax_name',
|
||||
18 => 'texts.tax_rate',
|
||||
19 => 'texts.tax_name',
|
||||
20 => 'texts.tax_rate',
|
||||
21 => 'texts.is_amount_discount',
|
||||
22 => 'texts.footer',
|
||||
23 => 'texts.partial',
|
||||
24 => 'texts.partial_due_date',
|
||||
25 => 'texts.custom_value1',
|
||||
26 => 'texts.custom_value2',
|
||||
27 => 'texts.custom_value3',
|
||||
28 => 'texts.custom_value4',
|
||||
29 => 'texts.surcharge',
|
||||
30 => 'texts.surcharge',
|
||||
31 => 'texts.surcharge',
|
||||
32 => 'texts.surcharge',
|
||||
33 => 'texts.exchange_rate',
|
||||
34 => 'texts.payment_date',
|
||||
35 => 'texts.payment_amount',
|
||||
36 => 'texts.transaction_reference',
|
||||
37 => 'texts.quantity',
|
||||
38 => 'texts.cost',
|
||||
39 => 'texts.product_key',
|
||||
40 => 'texts.notes',
|
||||
41 => 'texts.discount',
|
||||
42 => 'texts.is_amount_discount',
|
||||
43 => 'texts.tax_name',
|
||||
44 => 'texts.tax_rate',
|
||||
45 => 'texts.tax_name',
|
||||
46 => 'texts.tax_rate',
|
||||
47 => 'texts.tax_name',
|
||||
48 => 'texts.tax_rate',
|
||||
49 => 'texts.custom_value',
|
||||
50 => 'texts.custom_value',
|
||||
51 => 'texts.custom_value',
|
||||
52 => 'texts.custom_value',
|
||||
53 => 'texts.type',
|
||||
54 => 'texts.email',
|
||||
];
|
||||
}
|
||||
}
|
@ -13,14 +13,21 @@ namespace App\Import\Providers;
|
||||
use App\Factory\ClientFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Factory\QuoteFactory;
|
||||
use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
||||
use App\Http\Requests\Quote\StoreQuoteRequest;
|
||||
use App\Import\ImportException;
|
||||
use App\Jobs\Mail\NinjaMailerJob;
|
||||
use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Mail\Import\ImportCompleted;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Quote;
|
||||
use App\Models\User;
|
||||
use App\Repositories\ClientRepository;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Repositories\PaymentRepository;
|
||||
use App\Repositories\QuoteRepository;
|
||||
use App\Utils\Traits\CleanLineItems;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@ -71,7 +78,7 @@ class BaseImport
|
||||
->setCompany($this->company);
|
||||
}
|
||||
|
||||
protected function getCsvData($entity_type)
|
||||
public function getCsvData($entity_type)
|
||||
{
|
||||
$base64_encoded_csv = Cache::pull($this->hash . '-' . $entity_type);
|
||||
if (empty($base64_encoded_csv)) {
|
||||
@ -143,10 +150,10 @@ class BaseImport
|
||||
$count = 0;
|
||||
|
||||
foreach ($data as $key => $record) {
|
||||
|
||||
try {
|
||||
|
||||
$entity = $this->transformer->transform($record);
|
||||
|
||||
/** @var \App\Http\Requests\Request $request */
|
||||
$request = new $this->request_name();
|
||||
|
||||
@ -172,6 +179,7 @@ class BaseImport
|
||||
$count++;
|
||||
|
||||
}
|
||||
|
||||
} catch (\Exception $ex) {
|
||||
|
||||
if ($ex instanceof ImportException) {
|
||||
@ -187,8 +195,9 @@ class BaseImport
|
||||
];
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
public function ingestInvoices($invoices, $invoice_number_key)
|
||||
@ -209,8 +218,10 @@ class BaseImport
|
||||
$invoices = $this->groupInvoices($invoices, $invoice_number_key);
|
||||
|
||||
foreach ($invoices as $raw_invoice) {
|
||||
|
||||
try {
|
||||
$invoice_data = $invoice_transformer->transform($raw_invoice);
|
||||
nlog($invoice_data);
|
||||
$invoice_data['line_items'] = $this->cleanItems(
|
||||
$invoice_data['line_items'] ?? []
|
||||
);
|
||||
@ -354,6 +365,116 @@ class BaseImport
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
private function actionQuoteStatus(
|
||||
$quote,
|
||||
$quote_data,
|
||||
$quote_repository
|
||||
) {
|
||||
if (!empty($invoice_data['archived'])) {
|
||||
$quote_repository->archive($quote);
|
||||
$quote->fresh();
|
||||
}
|
||||
|
||||
if (!empty($invoice_data['viewed'])) {
|
||||
$quote = $quote
|
||||
->service()
|
||||
->markViewed()
|
||||
->save();
|
||||
}
|
||||
|
||||
if ($quote->status_id === Quote::STATUS_DRAFT) {
|
||||
} elseif ($quote->status_id === Quote::STATUS_SENT) {
|
||||
$quote = $quote
|
||||
->service()
|
||||
->markSent()
|
||||
->save();
|
||||
}
|
||||
|
||||
return $quote;
|
||||
}
|
||||
|
||||
public function ingestQuotes($quotes, $quote_number_key)
|
||||
{
|
||||
$quote_transformer = $this->transformer;
|
||||
|
||||
/** @var ClientRepository $client_repository */
|
||||
$client_repository = app()->make(ClientRepository::class);
|
||||
$client_repository->import_mode = true;
|
||||
|
||||
$quote_repository = new QuoteRepository();
|
||||
$quote_repository->import_mode = true;
|
||||
|
||||
$quotes = $this->groupInvoices($quotes, $quote_number_key);
|
||||
|
||||
foreach ($quotes as $raw_quote) {
|
||||
try {
|
||||
$quote_data = $quote_transformer->transform($raw_quote);
|
||||
$quote_data['line_items'] = $this->cleanItems(
|
||||
$quote_data['line_items'] ?? []
|
||||
);
|
||||
|
||||
// If we don't have a client ID, but we do have client data, go ahead and create the client.
|
||||
if (
|
||||
empty($quote_data['client_id']) &&
|
||||
!empty($quote_data['client'])
|
||||
) {
|
||||
$client_data = $quote_data['client'];
|
||||
$client_data['user_id'] = $this->getUserIDForRecord(
|
||||
$quote_data
|
||||
);
|
||||
|
||||
$client_repository->save(
|
||||
$client_data,
|
||||
$client = ClientFactory::create(
|
||||
$this->company->id,
|
||||
$client_data['user_id']
|
||||
)
|
||||
);
|
||||
$quote_data['client_id'] = $client->id;
|
||||
unset($quote_data['client']);
|
||||
}
|
||||
|
||||
$validator = Validator::make(
|
||||
$quote_data,
|
||||
(new StoreQuoteRequest())->rules()
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
$this->error_array['invoice'][] = [
|
||||
'quote' => $quote_data,
|
||||
'error' => $validator->errors()->all(),
|
||||
];
|
||||
} else {
|
||||
$quote = QuoteFactory::create(
|
||||
$this->company->id,
|
||||
$this->getUserIDForRecord($quote_data)
|
||||
);
|
||||
if (!empty($quote_data['status_id'])) {
|
||||
$quote->status_id = $quote_data['status_id'];
|
||||
}
|
||||
$quote_repository->save($quote_data, $quote);
|
||||
|
||||
$this->actionQuoteStatus(
|
||||
$quote,
|
||||
$quote_data,
|
||||
$quote_repository
|
||||
);
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
if ($ex instanceof ImportException) {
|
||||
$message = $ex->getMessage();
|
||||
} else {
|
||||
report($ex);
|
||||
$message = 'Unknown error';
|
||||
}
|
||||
|
||||
$this->error_array['quote'][] = [
|
||||
'invoice' => $raw_quote,
|
||||
'error' => $message,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUserIDForRecord($record)
|
||||
{
|
||||
if (!empty($record['user_id'])) {
|
||||
@ -379,4 +500,41 @@ class BaseImport
|
||||
return $this->company->owner()->id;
|
||||
}
|
||||
}
|
||||
|
||||
protected function finalizeImport()
|
||||
{
|
||||
$data = [
|
||||
'errors' => $this->error_array,
|
||||
'company' => $this->company,
|
||||
];
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new ImportCompleted($this->company, $data);
|
||||
$nmo->company = $this->company;
|
||||
$nmo->settings = $this->company->settings;
|
||||
$nmo->to_user = $this->company->owner();
|
||||
|
||||
NinjaMailerJob::dispatch($nmo);
|
||||
}
|
||||
|
||||
public function preTransform(array $data, $entity_type)
|
||||
{
|
||||
if (empty($this->column_map[$entity_type])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->skip_header) {
|
||||
array_shift($data);
|
||||
}
|
||||
|
||||
//sort the array by key
|
||||
$keys = $this->column_map[$entity_type];
|
||||
ksort($keys);
|
||||
|
||||
$data = array_map(function ($row) use ($keys) {
|
||||
return array_combine($keys, array_intersect_key($row, $keys));
|
||||
}, $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -61,9 +61,11 @@ class Csv extends BaseImport implements ImportInterface
|
||||
}
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
}
|
||||
|
||||
private function client()
|
||||
public function client()
|
||||
{
|
||||
$entity_type = 'client';
|
||||
|
||||
@ -90,7 +92,7 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->entity_count['clients'] = $client_count;
|
||||
}
|
||||
|
||||
private function product()
|
||||
public function product()
|
||||
{
|
||||
$entity_type = 'product';
|
||||
|
||||
@ -117,7 +119,7 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->entity_count['products'] = $product_count;
|
||||
}
|
||||
|
||||
private function invoice()
|
||||
public function invoice()
|
||||
{
|
||||
$entity_type = 'invoice';
|
||||
|
||||
@ -144,7 +146,7 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->entity_count['invoices'] = $invoice_count;
|
||||
}
|
||||
|
||||
private function payment()
|
||||
public function payment()
|
||||
{
|
||||
$entity_type = 'payment';
|
||||
|
||||
@ -171,7 +173,7 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->entity_count['payments'] = $payment_count;
|
||||
}
|
||||
|
||||
private function vendor()
|
||||
public function vendor()
|
||||
{
|
||||
$entity_type = 'vendor';
|
||||
|
||||
@ -198,7 +200,7 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->entity_count['vendors'] = $vendor_count;
|
||||
}
|
||||
|
||||
private function expense()
|
||||
public function expense()
|
||||
{
|
||||
$entity_type = 'expense';
|
||||
|
||||
@ -225,33 +227,14 @@ class Csv extends BaseImport implements ImportInterface
|
||||
$this->entity_count['expenses'] = $expense_count;
|
||||
}
|
||||
|
||||
private function quote()
|
||||
public function quote()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private function task()
|
||||
public function task()
|
||||
{
|
||||
}
|
||||
|
||||
public function preTransform(array $data, $entity_type)
|
||||
{
|
||||
if (empty($this->column_map[$entity_type])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->skip_header) {
|
||||
array_shift($data);
|
||||
}
|
||||
|
||||
//sort the array by key
|
||||
$keys = $this->column_map[$entity_type];
|
||||
ksort($keys);
|
||||
|
||||
$data = array_map(function ($row) use ($keys) {
|
||||
return array_combine($keys, array_intersect_key($row, $keys));
|
||||
}, $data);
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
public function transform(array $data)
|
||||
|
@ -15,7 +15,18 @@ interface ImportInterface
|
||||
|
||||
public function import(string $entity);
|
||||
|
||||
public function preTransform(array $data, string $entity_type);
|
||||
|
||||
public function transform(array $data);
|
||||
|
||||
public function client();
|
||||
|
||||
public function product();
|
||||
|
||||
public function invoice();
|
||||
|
||||
public function payment();
|
||||
|
||||
public function vendor();
|
||||
|
||||
public function expense();
|
||||
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
@ -8,9 +9,269 @@
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Providers;
|
||||
|
||||
class Wave extends BaseImport
|
||||
use App\Factory\ClientFactory;
|
||||
use App\Factory\ExpenseFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\VendorFactory;
|
||||
use App\Http\Requests\Client\StoreClientRequest;
|
||||
use App\Http\Requests\Expense\StoreExpenseRequest;
|
||||
use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
||||
use App\Http\Requests\Vendor\StoreVendorRequest;
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformer\Wave\ClientTransformer;
|
||||
use App\Import\Transformer\Wave\ExpenseTransformer;
|
||||
use App\Import\Transformer\Wave\InvoiceTransformer;
|
||||
use App\Import\Transformer\Wave\VendorTransformer;
|
||||
use App\Models\Client;
|
||||
use App\Repositories\ClientRepository;
|
||||
use App\Repositories\ExpenseRepository;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Repositories\VendorRepository;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class Wave extends BaseImport implements ImportInterface
|
||||
{
|
||||
|
||||
public array $entity_count = [];
|
||||
|
||||
public function import(string $entity)
|
||||
{
|
||||
if (
|
||||
in_array($entity, [
|
||||
'client',
|
||||
'invoice',
|
||||
// 'product',
|
||||
// 'payment',
|
||||
'vendor',
|
||||
'expense',
|
||||
])
|
||||
) {
|
||||
$this->{$entity}();
|
||||
}
|
||||
|
||||
//collate any errors
|
||||
|
||||
$this->finalizeImport();
|
||||
}
|
||||
|
||||
public function client()
|
||||
{
|
||||
$entity_type = 'client';
|
||||
|
||||
$data = $this->getCsvData($entity_type);
|
||||
|
||||
$data = $this->preTransform($data, $entity_type);
|
||||
|
||||
if (empty($data)) {
|
||||
$this->entity_count['clients'] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->request_name = StoreClientRequest::class;
|
||||
$this->repository_name = ClientRepository::class;
|
||||
$this->factory_name = ClientFactory::class;
|
||||
|
||||
$this->repository = app()->make($this->repository_name);
|
||||
$this->repository->import_mode = true;
|
||||
|
||||
$this->transformer = new ClientTransformer($this->company);
|
||||
|
||||
$client_count = $this->ingest($data, $entity_type);
|
||||
|
||||
$this->entity_count['clients'] = $client_count;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function product() {
|
||||
|
||||
//done automatically inside the invoice() method as we need to harvest the products from the line items
|
||||
|
||||
}
|
||||
|
||||
public function invoice() {
|
||||
|
||||
//make sure we update and create products with wave
|
||||
$initial_update_products_value = $this->company->update_products;
|
||||
$this->company->update_products = true;
|
||||
|
||||
$this->company->save();
|
||||
|
||||
$entity_type = 'invoice';
|
||||
|
||||
$data = $this->getCsvData($entity_type);
|
||||
|
||||
$data = $this->preTransform($data, $entity_type);
|
||||
|
||||
if (empty($data)) {
|
||||
$this->entity_count['invoices'] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->request_name = StoreInvoiceRequest::class;
|
||||
$this->repository_name = InvoiceRepository::class;
|
||||
$this->factory_name = InvoiceFactory::class;
|
||||
|
||||
$this->repository = app()->make($this->repository_name);
|
||||
$this->repository->import_mode = true;
|
||||
|
||||
$this->transformer = new InvoiceTransformer($this->company);
|
||||
|
||||
$invoice_count = $this->ingestInvoices($data, 'Invoice Number');
|
||||
|
||||
$this->entity_count['invoices'] = $invoice_count;
|
||||
|
||||
$this->company->update_products = $initial_update_products_value;
|
||||
$this->company->save();
|
||||
|
||||
}
|
||||
|
||||
public function payment()
|
||||
{
|
||||
//these are pulled in when processing invoices
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
|
||||
$entity_type = 'vendor';
|
||||
|
||||
$data = $this->getCsvData($entity_type);
|
||||
$data = $this->preTransform($data, $entity_type);
|
||||
|
||||
if (empty($data)) {
|
||||
$this->entity_count['vendors'] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->request_name = StoreVendorRequest::class;
|
||||
$this->repository_name = VendorRepository::class;
|
||||
$this->factory_name = VendorFactory::class;
|
||||
|
||||
$this->repository = app()->make($this->repository_name);
|
||||
$this->repository->import_mode = true;
|
||||
|
||||
$this->transformer = new VendorTransformer($this->company);
|
||||
|
||||
$vendor_count = $this->ingest($data, $entity_type);
|
||||
|
||||
$this->entity_count['vendors'] = $vendor_count;
|
||||
|
||||
}
|
||||
|
||||
public function expense()
|
||||
{
|
||||
$entity_type = 'expense';
|
||||
|
||||
$data = $this->getCsvData($entity_type);
|
||||
$data = $this->preTransform($data, $entity_type);
|
||||
|
||||
if (empty($data)) {
|
||||
$this->entity_count['expense'] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->request_name = StoreExpenseRequest::class;
|
||||
$this->repository_name = ExpenseRepository::class;
|
||||
$this->factory_name = ExpenseFactory::class;
|
||||
|
||||
$this->repository = app()->make($this->repository_name);
|
||||
$this->repository->import_mode = true;
|
||||
|
||||
$this->transformer = new ExpenseTransformer($this->company);
|
||||
|
||||
$expense_count = $this->ingestExpenses($data, $entity_type);
|
||||
|
||||
$this->entity_count['expenses'] = $expense_count;
|
||||
|
||||
}
|
||||
|
||||
public function transform(array $data){}
|
||||
|
||||
|
||||
private function groupExpenses($csvData)
|
||||
{
|
||||
|
||||
$grouped_expense = [];
|
||||
$key = 'Transaction ID';
|
||||
|
||||
foreach($csvData as $expense)
|
||||
{
|
||||
if($expense['Account Group'] == 'Expense')
|
||||
$grouped[$expense[$key]][] = $expense;
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
public function ingestExpenses($data)
|
||||
{
|
||||
$key = 'Transaction ID';
|
||||
|
||||
$expense_transformer = $this->transformer;
|
||||
|
||||
$vendor_repository = app()->make(VendorRepository::class);
|
||||
$expense_repository = app()->make(ExpenseRepository::class);
|
||||
|
||||
$expenses = $this->groupExpenses($data);
|
||||
|
||||
// nlog($expenses);
|
||||
// exit;
|
||||
foreach ($expenses as $raw_expense) {
|
||||
|
||||
try {
|
||||
|
||||
$expense_data = $expense_transformer->transform($raw_expense);
|
||||
|
||||
// If we don't have a client ID, but we do have client data, go ahead and create the client.
|
||||
if (empty($expense_data['vendor_id']) ) {
|
||||
$vendor_data['user_id'] = $this->getUserIDForRecord($expense_data);
|
||||
|
||||
$vendor_repository->save(
|
||||
['name' => $raw_expense['Vendor Name']],
|
||||
$vendor = VendorFactory::create(
|
||||
$this->company->id,
|
||||
$vendor_data['user_id']
|
||||
)
|
||||
);
|
||||
$expense_data['vendor_id'] = $vendor->id;
|
||||
}
|
||||
|
||||
$validator = Validator::make(
|
||||
$expense_data,
|
||||
(new StoreExpenseRequest())->rules()
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
$this->error_array['expense'][] = [
|
||||
'expense' => $expense_data,
|
||||
'error' => $validator->errors()->all(),
|
||||
];
|
||||
} else {
|
||||
$expense = ExpenseFactory::create(
|
||||
$this->company->id,
|
||||
$this->getUserIDForRecord($expense_data)
|
||||
);
|
||||
|
||||
$expense_repository->save($expense_data, $expense);
|
||||
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
if ($ex instanceof ImportException) {
|
||||
$message = $ex->getMessage();
|
||||
} else {
|
||||
report($ex);
|
||||
$message = 'Unknown error';
|
||||
}
|
||||
|
||||
$this->error_array['expense'][] = [
|
||||
'expense' => $raw_expense,
|
||||
'error' => $message,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,12 @@
|
||||
|
||||
namespace App\Import\Transformer;
|
||||
|
||||
use App\Factory\ExpenseCategoryFactory;
|
||||
use App\Factory\ProjectFactory;
|
||||
use App\Factory\VendorFactory;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Country;
|
||||
use App\Models\ExpenseCategory;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\User;
|
||||
use App\Utils\Number;
|
||||
@ -35,7 +38,12 @@ class BaseTransformer
|
||||
|
||||
public function getString($data, $field)
|
||||
{
|
||||
return isset($data[$field]) && $data[$field] ? $data[$field] : '';
|
||||
return isset($data[$field]) && $data[$field] ? trim($data[$field]) : '';
|
||||
}
|
||||
|
||||
public function getValueOrNull($data, $field)
|
||||
{
|
||||
return isset($data[$field]) && $data[$field] ? $data[$field] : null;
|
||||
}
|
||||
|
||||
public function getCurrencyByCode($data, $key = 'client.currency_id')
|
||||
@ -363,6 +371,34 @@ class BaseTransformer
|
||||
->exists();
|
||||
}
|
||||
|
||||
/** *
|
||||
* @return bool
|
||||
*/
|
||||
public function hasExpense($expense_number)
|
||||
{
|
||||
return $this->company
|
||||
->expenses()
|
||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $expense_number)),
|
||||
])
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $quote_number
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasQuote($quote_number)
|
||||
{
|
||||
return $this->company
|
||||
->quotes()
|
||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||
strtolower(str_replace(' ', '', $quote_number)),
|
||||
])
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $invoice_number
|
||||
*
|
||||
@ -397,6 +433,23 @@ class BaseTransformer
|
||||
return $vendor ? $vendor->id : null;
|
||||
}
|
||||
|
||||
public function getVendorIdOrCreate($name)
|
||||
{
|
||||
if(empty($name))
|
||||
return null;
|
||||
|
||||
$vendor = $this->getVendorId($name);
|
||||
|
||||
if($vendor)
|
||||
return $vendor;
|
||||
|
||||
$vendor = VendorFactory::create($this->company->id, $this->company->owner()->id);
|
||||
$vendor->name = $name;
|
||||
$vendor->save();
|
||||
|
||||
return $vendor->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
@ -414,6 +467,23 @@ class BaseTransformer
|
||||
return $ec ? $ec->id : null;
|
||||
}
|
||||
|
||||
public function getOrCreateExpenseCategry($name)
|
||||
{
|
||||
if(empty($name))
|
||||
return null;
|
||||
|
||||
$ec = $this->getExpenseCategoryId($name);
|
||||
|
||||
if($ec)
|
||||
return $ec;
|
||||
|
||||
$expense_category = ExpenseCategoryFactory::create($this->company->id, $this->company->owner()->id);
|
||||
$expense_category->name = $name;
|
||||
$expense_category->save();
|
||||
|
||||
return $expense_category->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
@ -458,4 +528,6 @@ class BaseTransformer
|
||||
|
||||
return $pt ? $pt->id : null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class ClientTransformer extends BaseTransformer
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data->name) && $this->hasClient($data->name)) {
|
||||
if (isset($data->name) && $this->getString($data, 'client.name')) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
|
243
app/Import/Transformer/Csv/QuoteTransformer.php
Normal file
243
app/Import/Transformer/Csv/QuoteTransformer.php
Normal file
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformer\Csv;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
use App\Import\Transformer\Csv\ClientTransformer;
|
||||
use App\Models\Quote;
|
||||
|
||||
/**
|
||||
* Class QuoteTransformer.
|
||||
*/
|
||||
class QuoteTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform($line_items_data)
|
||||
{
|
||||
$quote_data = reset($line_items_data);
|
||||
|
||||
if ($this->hasQuote($quote_data['quote.number'])) {
|
||||
throw new ImportException('Quote number already exists');
|
||||
}
|
||||
|
||||
$quoteStatusMap = [
|
||||
'sent' => Quote::STATUS_SENT,
|
||||
'draft' => Quote::STATUS_DRAFT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->company->id,
|
||||
'number' => $this->getString($quote_data, 'quote.number'),
|
||||
'user_id' => $this->getString($quote_data, 'quote.user_id'),
|
||||
'amount' => ($amount = $this->getFloat(
|
||||
$quote_data,
|
||||
'quote.amount'
|
||||
)),
|
||||
'balance' => isset($quote_data['quote.balance'])
|
||||
? $this->getFloat($quote_data, 'quote.balance')
|
||||
: $amount,
|
||||
'client_id' => $this->getClient(
|
||||
$this->getString($quote_data, 'client.name'),
|
||||
$this->getString($quote_data, 'client.email')
|
||||
),
|
||||
'discount' => $this->getFloat($quote_data, 'quote.discount'),
|
||||
'po_number' => $this->getString($quote_data, 'quote.po_number'),
|
||||
'date' => isset($quote_data['quote.date'])
|
||||
? date('Y-m-d', strtotime($quote_data['quote.date']))
|
||||
: now()->format('Y-m-d'),
|
||||
'due_date' => isset($quote_data['quote.due_date'])
|
||||
? date('Y-m-d', strtotime($quote_data['quote.due_date']))
|
||||
: null,
|
||||
'terms' => $this->getString($quote_data, 'quote.terms'),
|
||||
'public_notes' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.public_notes'
|
||||
),
|
||||
'private_notes' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.private_notes'
|
||||
),
|
||||
'tax_name1' => $this->getString($quote_data, 'quote.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($quote_data, 'quote.tax_rate1'),
|
||||
'tax_name2' => $this->getString($quote_data, 'quote.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($quote_data, 'quote.tax_rate2'),
|
||||
'tax_name3' => $this->getString($quote_data, 'quote.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($quote_data, 'quote.tax_rate3'),
|
||||
'custom_value1' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_value1'
|
||||
),
|
||||
'custom_value2' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_value2'
|
||||
),
|
||||
'custom_value3' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_value3'
|
||||
),
|
||||
'custom_value4' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_value4'
|
||||
),
|
||||
'footer' => $this->getString($quote_data, 'quote.footer'),
|
||||
'partial' => $this->getFloat($quote_data, 'quote.partial'),
|
||||
'partial_due_date' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.partial_due_date'
|
||||
),
|
||||
'custom_surcharge1' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_surcharge1'
|
||||
),
|
||||
'custom_surcharge2' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_surcharge2'
|
||||
),
|
||||
'custom_surcharge3' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_surcharge3'
|
||||
),
|
||||
'custom_surcharge4' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_surcharge4'
|
||||
),
|
||||
'exchange_rate' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.exchange_rate'
|
||||
),
|
||||
'status_id' =>
|
||||
$quoteStatusMap[
|
||||
($status = strtolower(
|
||||
$this->getString($quote_data, 'quote.status')
|
||||
))
|
||||
] ?? Quote::STATUS_SENT,
|
||||
'archived' => $status === 'archived',
|
||||
];
|
||||
|
||||
/* If we can't find the client, then lets try and create a client */
|
||||
if (!$transformed['client_id']) {
|
||||
$client_transformer = new ClientTransformer($this->company);
|
||||
|
||||
$transformed['client'] = $client_transformer->transform(
|
||||
$quote_data
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($quote_data['payment.amount'])) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($quote_data['payment.date'])
|
||||
? date(
|
||||
'Y-m-d',
|
||||
strtotime($quote_data['payment.date'])
|
||||
)
|
||||
: date('y-m-d'),
|
||||
'transaction_reference' => $this->getString(
|
||||
$quote_data,
|
||||
'payment.transaction_reference'
|
||||
),
|
||||
'amount' => $this->getFloat(
|
||||
$quote_data,
|
||||
'payment.amount'
|
||||
),
|
||||
],
|
||||
];
|
||||
} elseif ($status === 'paid') {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($quote_data['payment.date'])
|
||||
? date(
|
||||
'Y-m-d',
|
||||
strtotime($quote_data['payment.date'])
|
||||
)
|
||||
: date('y-m-d'),
|
||||
'transaction_reference' => $this->getString(
|
||||
$quote_data,
|
||||
'payment.transaction_reference'
|
||||
),
|
||||
'amount' => $this->getFloat(
|
||||
$quote_data,
|
||||
'quote.amount'
|
||||
),
|
||||
],
|
||||
];
|
||||
} elseif (
|
||||
isset($transformed['amount']) &&
|
||||
isset($transformed['balance']) &&
|
||||
$transformed['amount'] != $transformed['balance']
|
||||
) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($quote_data['payment.date'])
|
||||
? date(
|
||||
'Y-m-d',
|
||||
strtotime($quote_data['payment.date'])
|
||||
)
|
||||
: date('y-m-d'),
|
||||
'transaction_reference' => $this->getString(
|
||||
$quote_data,
|
||||
'payment.transaction_reference'
|
||||
),
|
||||
'amount' =>
|
||||
$transformed['amount'] - $transformed['balance'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$line_items = [];
|
||||
foreach ($line_items_data as $record) {
|
||||
$line_items[] = [
|
||||
'quantity' => $this->getFloat($record, 'item.quantity'),
|
||||
'cost' => $this->getFloat($record, 'item.cost'),
|
||||
'product_key' => $this->getString($record, 'item.product_key'),
|
||||
'notes' => $this->getString($record, 'item.notes'),
|
||||
'discount' => $this->getFloat($record, 'item.discount'),
|
||||
'is_amount_discount' => filter_var(
|
||||
$this->getString($record, 'item.is_amount_discount'),
|
||||
FILTER_VALIDATE_BOOLEAN,
|
||||
FILTER_NULL_ON_FAILURE
|
||||
),
|
||||
'tax_name1' => $this->getString($record, 'item.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($record, 'item.tax_rate1'),
|
||||
'tax_name2' => $this->getString($record, 'item.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($record, 'item.tax_rate2'),
|
||||
'tax_name3' => $this->getString($record, 'item.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($record, 'item.tax_rate3'),
|
||||
'custom_value1' => $this->getString(
|
||||
$record,
|
||||
'item.custom_value1'
|
||||
),
|
||||
'custom_value2' => $this->getString(
|
||||
$record,
|
||||
'item.custom_value2'
|
||||
),
|
||||
'custom_value3' => $this->getString(
|
||||
$record,
|
||||
'item.custom_value3'
|
||||
),
|
||||
'custom_value4' => $this->getString(
|
||||
$record,
|
||||
'item.custom_value4'
|
||||
),
|
||||
'type_id' => '1', //$this->getQuoteTypeId( $record, 'item.type_id' ),
|
||||
];
|
||||
}
|
||||
$transformed['line_items'] = $line_items;
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
74
app/Import/Transformer/Wave/ClientTransformer.php
Normal file
74
app/Import/Transformer/Wave/ClientTransformer.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformer\Wave;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
if ( isset( $data['customer_name'] ) && $this->hasClient( $data['customer_name'] ) ) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
$settings = new \stdClass;
|
||||
$settings->currency_id = (string) $this->getCurrencyByCode( $data, 'customer_currency' );
|
||||
|
||||
if ( strval( $data['Payment Terms'] ?? '' ) > 0 ) {
|
||||
$settings->payment_terms = $data['Payment Terms'];
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->company->id,
|
||||
'name' => $this->getString( $data, 'customer_name' ),
|
||||
'number' => $this->getValueOrNull( $data, 'account_number' ),
|
||||
'work_phone' => $this->getString( $data, 'phone' ),
|
||||
'website' => $this->getString( $data, 'website' ),
|
||||
'country_id' => !empty( $data['country'] ) ? $this->getCountryId( $data['country'] ) : null,
|
||||
'state' => $this->getString( $data, 'province/state' ),
|
||||
'address1' => $this->getString( $data, 'address_line_1' ),
|
||||
'address2' => $this->getString( $data, 'address_line_2' ),
|
||||
'city' => $this->getString( $data, 'city' ),
|
||||
'postal_code' => $this->getString( $data, 'postal_code/zip_code' ),
|
||||
|
||||
|
||||
'shipping_country_id' => !empty( $data['ship-to_country'] ) ? $this->getCountryId( $data['country'] ) : null,
|
||||
'shipping_state' => $this->getString( $data, 'ship-to_province/state' ),
|
||||
'shipping_address1' => $this->getString( $data, 'ship-to_address_line_1' ),
|
||||
'shipping_address2' => $this->getString( $data, 'ship-to_address_line_2' ),
|
||||
'shipping_city' => $this->getString( $data, 'ship-to_city' ),
|
||||
'shipping_postal_code' => $this->getString( $data, 'ship-to_postal_code/zip_code' ),
|
||||
'public_notes' => $this->getString( $data, 'delivery_instructions' ),
|
||||
|
||||
'credit_balance' => 0,
|
||||
'settings' =>$settings,
|
||||
'client_hash' => Str::random( 40 ),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString( $data, 'contact_first_name' ),
|
||||
'last_name' => $this->getString( $data, 'contact_last_name' ),
|
||||
'email' => $this->getString( $data, 'email' ),
|
||||
'phone' => $this->getString( $data, 'phone' ),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
66
app/Import/Transformer/Wave/ExpenseTransformer.php
Normal file
66
app/Import/Transformer/Wave/ExpenseTransformer.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* client Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformer\Wave;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
|
||||
|
||||
/**
|
||||
* Class ExpenseTransformer.
|
||||
*/
|
||||
class ExpenseTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $line_items_data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform( $line_items_data )
|
||||
{
|
||||
|
||||
$data = $line_items_data[0];
|
||||
|
||||
$amount = 0;
|
||||
$total_tax = 0;
|
||||
$tax_rate = 0;
|
||||
|
||||
|
||||
foreach ( $line_items_data as $record )
|
||||
{
|
||||
|
||||
$amount += floatval($record['Amount (One column)']);
|
||||
$total_tax += floatval($record['Sales Tax Amount']);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$tax_rate = round(($total_tax/$amount)*100,3);
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->company->id,
|
||||
'vendor_id' => $this->getVendorIdOrCreate($this->getString($data, 'Vendor')),
|
||||
'number' => $this->getString($data, 'Bill Number'),
|
||||
'public_notes'=> $this->getString($data, 'Notes / Memo'),
|
||||
'date' => date( 'Y-m-d', strtotime( $data['Transaction Date Added'] ) ) ?: now()->format('Y-m-d'), //27-01-2022
|
||||
'currency_id' => $this->company->settings->currency_id,
|
||||
'category_id' => $this->getOrCreateExpenseCategry($data['Account Name']),
|
||||
'amount' => $amount,
|
||||
'tax_name1' => $data['Sales Tax Name'],
|
||||
'tax_rate1' => $tax_rate,
|
||||
];
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
||||
|
||||
|
80
app/Import/Transformer/Wave/InvoiceTransformer.php
Normal file
80
app/Import/Transformer/Wave/InvoiceTransformer.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformer\Wave;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $line_items_data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform( $line_items_data ) {
|
||||
$invoice_data = reset( $line_items_data );
|
||||
|
||||
if ( $this->hasInvoice( $invoice_data['Invoice Number'] ) ) {
|
||||
throw new ImportException( 'Invoice number already exists' );
|
||||
}
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->company->id,
|
||||
'client_id' => $this->getClient( $customer_name = $this->getString( $invoice_data, 'Customer' ), null ),
|
||||
'number' => $invoice_number = $this->getString( $invoice_data, 'Invoice Number' ),
|
||||
'date' => date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ) ?: now()->format('Y-m-d'), //27-01-2022
|
||||
'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
];
|
||||
|
||||
$line_items = [];
|
||||
$payments = [];
|
||||
foreach ( $line_items_data as $record ) {
|
||||
if ( $record['Account Type'] === 'Income' ) {
|
||||
$description = $this->getString( $record, 'Transaction Line Description' );
|
||||
|
||||
// Remove duplicate data from description
|
||||
if ( substr( $description, 0, strlen( $customer_name ) + 3 ) === $customer_name . ' - ' ) {
|
||||
$description = substr( $description, strlen( $customer_name ) + 3 );
|
||||
}
|
||||
|
||||
if ( substr( $description, 0, strlen( $invoice_number ) + 3 ) === $invoice_number . ' - ' ) {
|
||||
$description = substr( $description, strlen( $invoice_number ) + 3 );
|
||||
}
|
||||
|
||||
$line_items[] = [
|
||||
'notes' => $description,
|
||||
'cost' => $this->getFloat( $record, 'Amount Before Sales Tax' ),
|
||||
'tax_name1' => $this->getString( $record, 'Sales Tax Name' ),
|
||||
'tax_rate1' => $this->getFloat( $record, 'Sales Tax Amount' ),
|
||||
|
||||
'quantity' => 1,
|
||||
];
|
||||
} elseif ( $record['Account Type'] === 'System Receivable Invoice' ) {
|
||||
// This is a payment
|
||||
$payments[] = [
|
||||
'date' => date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ),
|
||||
'amount' => $this->getFloat( $record, 'Amount (One column)' ),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$transformed['line_items'] = $line_items;
|
||||
$transformed['payments'] = $payments;
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
56
app/Import/Transformer/Wave/VendorTransformer.php
Normal file
56
app/Import/Transformer/Wave/VendorTransformer.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://clientninja.com).
|
||||
*
|
||||
* @link https://github.com/clientninja/clientninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. client Ninja LLC (https://clientninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformer\Wave;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class VendorTransformer.
|
||||
*/
|
||||
class VendorTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
if ( isset( $data['vendor_name'] ) && $this->hasVendor( $data['vendor_name'] ) ) {
|
||||
throw new ImportException('Vendor already exists');
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->company->id,
|
||||
'name' => $this->getString( $data, 'vendor_name' ),
|
||||
'number' => $this->getValueOrNull( $data, 'account_number' ),
|
||||
'phone' => $this->getString( $data, 'phone' ),
|
||||
'website' => $this->getString( $data, 'website' ),
|
||||
'country_id' => !empty( $data['country'] ) ? $this->getCountryId( $data['country'] ) : null,
|
||||
'state' => $this->getString( $data, 'province/state' ),
|
||||
'address1' => $this->getString( $data, 'address_line_1' ),
|
||||
'address2' => $this->getString( $data, 'address_line_2' ),
|
||||
'city' => $this->getString( $data, 'city' ),
|
||||
'postal_code' => $this->getString( $data, 'postal_code/zip_code' ),
|
||||
'currency_id' => $this->getCurrencyByCode( $data, 'vendor_currency' ),
|
||||
'client_hash' => Str::random( 40 ),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString( $data, 'contact_first_name' ),
|
||||
'last_name' => $this->getString( $data, 'contact_last_name' ),
|
||||
'email' => $this->getString( $data, 'email' ),
|
||||
'phone' => $this->getString( $data, 'phone' ),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -78,6 +78,7 @@ class Credit extends BaseModel
|
||||
'assigned_user_id',
|
||||
'exchange_rate',
|
||||
'subscription_id',
|
||||
'vendor_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
@ -123,6 +124,11 @@ class Credit extends BaseModel
|
||||
return $this->belongsTo(User::class, 'assigned_user_id', 'id')->withTrashed();
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo(Vendor::class);
|
||||
}
|
||||
|
||||
public function history()
|
||||
{
|
||||
return $this->hasManyThrough(Backup::class, Activity::class);
|
||||
|
@ -96,7 +96,7 @@ class GatewayType extends StaticModel
|
||||
case self::FPX:
|
||||
return ctrans('texts.fpx');
|
||||
default:
|
||||
return 'Undefined.';
|
||||
return ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +152,11 @@ class Invoice extends BaseModel
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo(Vendor::class);
|
||||
}
|
||||
|
||||
public function design()
|
||||
{
|
||||
return $this->belongsTo(Design::class);
|
||||
|
@ -76,6 +76,7 @@ class Quote extends BaseModel
|
||||
'exchange_rate',
|
||||
'subscription_id',
|
||||
'uses_inclusive_taxes',
|
||||
'vendor_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
@ -133,6 +134,11 @@ class Quote extends BaseModel
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo(Vendor::class);
|
||||
}
|
||||
|
||||
public function history()
|
||||
{
|
||||
return $this->hasManyThrough(Backup::class, Activity::class);
|
||||
|
@ -107,6 +107,7 @@ class RecurringInvoice extends BaseModel
|
||||
'design_id',
|
||||
'assigned_user_id',
|
||||
'exchange_rate',
|
||||
'vendor_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
@ -157,6 +158,11 @@ class RecurringInvoice extends BaseModel
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function vendor()
|
||||
{
|
||||
return $this->belongsTo(Vendor::class);
|
||||
}
|
||||
|
||||
public function activities()
|
||||
{
|
||||
return $this->hasMany(Activity::class)->orderBy('id', 'DESC')->take(50);
|
||||
|
@ -119,4 +119,30 @@ class AuthorizeCreateCustomer
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is how we can harvest client profiles and attach them within Invoice Ninja
|
||||
// $request = new net\authorize\api\contract\v1\GetCustomerProfileRequest();
|
||||
// $request->setMerchantAuthentication($driver->merchant_authentication);
|
||||
// $request->setCustomerProfileId($gateway_customer_reference);
|
||||
// $controller = new net\authorize\api\controller\GetCustomerProfileController($request);
|
||||
// $response = $controller->executeWithApiResponse($driver->mode());
|
||||
|
||||
// if (($response != null) && ($response->getMessages()->getResultCode() == "Ok") )
|
||||
// {
|
||||
// echo "GetCustomerProfile SUCCESS : " . "\n";
|
||||
// $profileSelected = $response->getProfile();
|
||||
// $paymentProfilesSelected = $profileSelected->getPaymentProfiles();
|
||||
// echo "Profile Has " . count($paymentProfilesSelected). " Payment Profiles" . "\n";
|
||||
|
||||
// foreach ($profileSelected->getPaymentProfiles() as $paymentProfile) {
|
||||
// echo "\nCustomer Profile ID: " . $paymentProfile->getCustomerProfileId() . "\n";
|
||||
// echo "Payment profile ID: " . $paymentProfile->getCustomerPaymentProfileId() . "\n";
|
||||
// echo "Credit Card Number: " . $paymentProfile->getPayment()->getCreditCard()->getCardNumber() . "\n";
|
||||
// if ($paymentProfile->getBillTo() != null) {
|
||||
// echo "First Name in Billing Address: " . $paymentProfile->getBillTo()->getFirstName() . "\n";
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -170,6 +170,7 @@ class CreditCard implements MethodInterface
|
||||
|
||||
private function completePayment($method, PaymentResponseRequest $request)
|
||||
{
|
||||
|
||||
$payment = new Payment($method, $this->checkout->payment_hash->data->currency);
|
||||
$payment->amount = $this->checkout->payment_hash->data->value;
|
||||
$payment->reference = $this->checkout->getDescription();
|
||||
@ -178,6 +179,10 @@ class CreditCard implements MethodInterface
|
||||
'email' => $this->checkout->client->present()->email(),
|
||||
];
|
||||
|
||||
$payment->metadata = [
|
||||
'udf1' => "Invoice Ninja",
|
||||
];
|
||||
|
||||
$this->checkout->payment_hash->data = array_merge((array)$this->checkout->payment_hash->data, ['checkout_payment_ref' => $payment]);
|
||||
$this->checkout->payment_hash->save();
|
||||
|
||||
|
@ -202,6 +202,9 @@ class PaymentMigrationRepository extends BaseRepository
|
||||
*/
|
||||
private function processExchangeRates($data, $payment)
|
||||
{
|
||||
if($payment->exchange_rate != 1)
|
||||
return $payment;
|
||||
|
||||
$client = Client::where('id', $data['client_id'])->withTrashed()->first();
|
||||
|
||||
$client_currency = $client->getSetting('currency_id');
|
||||
|
@ -210,6 +210,7 @@ class PaymentRepository extends BaseRepository {
|
||||
$payment->exchange_currency_id = $company_currency;
|
||||
$payment->currency_id = $client_currency;
|
||||
|
||||
return $payment;
|
||||
}
|
||||
|
||||
$payment->currency_id = $company_currency;
|
||||
|
@ -111,6 +111,9 @@ class ApplyPaymentAmount extends AbstractService
|
||||
private function setExchangeRate(Payment $payment)
|
||||
{
|
||||
|
||||
if($payment->exchange_rate != 1)
|
||||
return;
|
||||
|
||||
$client_currency = $payment->client->getSetting('currency_id');
|
||||
$company_currency = $payment->client->company->settings->currency_id;
|
||||
|
||||
|
@ -79,6 +79,9 @@ class InvoiceService
|
||||
public function setExchangeRate()
|
||||
{
|
||||
|
||||
if($this->invoice->exchange_rate != 1)
|
||||
return $this;
|
||||
|
||||
$client_currency = $this->invoice->client->getSetting('currency_id');
|
||||
$company_currency = $this->invoice->company->settings->currency_id;
|
||||
|
||||
|
@ -116,6 +116,9 @@ class MarkPaid extends AbstractService
|
||||
private function setExchangeRate(Payment $payment)
|
||||
{
|
||||
|
||||
if($payment->exchange_rate != 1)
|
||||
return;
|
||||
|
||||
$client_currency = $payment->client->getSetting('currency_id');
|
||||
$company_currency = $payment->client->company->settings->currency_id;
|
||||
|
||||
|
@ -89,6 +89,7 @@ class CreditTransformer extends EntityTransformer
|
||||
'user_id' => $this->encodePrimaryKey($credit->user_id),
|
||||
'project_id' => $this->encodePrimaryKey($credit->project_id),
|
||||
'assigned_user_id' => $this->encodePrimaryKey($credit->assigned_user_id),
|
||||
'vendor_id' => (string) $this->encodePrimaryKey($credit->vendor_id),
|
||||
'amount' => (float) $credit->amount,
|
||||
'balance' => (float) $credit->balance,
|
||||
'client_id' => (string) $this->encodePrimaryKey($credit->client_id),
|
||||
|
@ -95,6 +95,7 @@ class QuoteTransformer extends EntityTransformer
|
||||
'status_id' => (string) $quote->status_id,
|
||||
'design_id' => (string) $this->encodePrimaryKey($quote->design_id),
|
||||
'invoice_id' => (string) $this->encodePrimaryKey($quote->invoice_id),
|
||||
'vendor_id' => (string) $this->encodePrimaryKey($quote->vendor_id),
|
||||
'updated_at' => (int) $quote->updated_at,
|
||||
'archived_at' => (int) $quote->deleted_at,
|
||||
'created_at' => (int) $quote->created_at,
|
||||
|
@ -14,11 +14,13 @@ namespace App\Utils;
|
||||
|
||||
use App\Models\Country;
|
||||
use App\Models\CreditInvitation;
|
||||
use App\Models\GatewayType;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Models\QuoteInvitation;
|
||||
use App\Models\RecurringInvoiceInvitation;
|
||||
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Number;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\transformTranslations;
|
||||
use Exception;
|
||||
@ -153,6 +155,10 @@ class HtmlEngine
|
||||
$data['$project.name'] = ['value' => $this->entity->project->name, 'label' => ctrans('texts.project_name')];
|
||||
$data['$invoice.project'] = &$data['$project.name'];
|
||||
}
|
||||
|
||||
if($this->entity->vendor) {
|
||||
$data['$invoice.vendor'] = ['value' => $this->entity->vendor->present()->name(), 'label' => ctrans('texts.vendor_name')];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->entity_string == 'quote') {
|
||||
@ -508,6 +514,20 @@ class HtmlEngine
|
||||
|
||||
$data['$entity_images'] = ['value' => $this->generateEntityImagesMarkup(), 'label' => ''];
|
||||
|
||||
$data['$payments'] = ['value' => '', 'label' => ctrans('texts.payments')];
|
||||
|
||||
if ($this->entity_string == 'invoice' && $this->entity->payments()->exists()) {
|
||||
|
||||
$payment_list = '<br><br>';
|
||||
|
||||
foreach ($this->entity->payments as $payment) {
|
||||
$payment_list .= ctrans('texts.payment_subject') . ": " . $this->formatDate($payment->date, $this->client->date_format()) . " :: " . Number::formatMoney($payment->amount, $this->client) ." :: ". GatewayType::getAlias($payment->gateway_type_id) . "<br>";
|
||||
}
|
||||
|
||||
$data['$payments'] = ['value' => $payment_list, 'label' => ctrans('texts.payments')];
|
||||
}
|
||||
|
||||
|
||||
$arrKeysLength = array_map('strlen', array_keys($data));
|
||||
array_multisort($arrKeysLength, SORT_DESC, $data);
|
||||
|
||||
|
@ -302,12 +302,13 @@ trait MakesInvoiceValues
|
||||
$data[$key][$table_type . ".{$_table_type}3"] = $helpers->formatCustomFieldValue($this->client->company->custom_fields, "{$_table_type}3", $item->custom_value3, $this->client);
|
||||
$data[$key][$table_type . ".{$_table_type}4"] = $helpers->formatCustomFieldValue($this->client->company->custom_fields, "{$_table_type}4", $item->custom_value4, $this->client);
|
||||
|
||||
//$data[$key][$table_type.'.quantity'] = Number::formatValue($item->quantity, $this->client->currency());
|
||||
// 08-02-2022 - fix for regression below
|
||||
$data[$key][$table_type.'.quantity'] = Number::formatValue($item->quantity, $this->client->currency());
|
||||
|
||||
//change quantity from localized number, to decimal format with no trailing zeroes 06/09/21
|
||||
|
||||
//30-01-2022 - improve rounding display for Unit quantity
|
||||
$data[$key][$table_type.'.quantity'] = $item->quantity >=1 ? rtrim(number_format($item->quantity, $this->client->currency()->precision), $locale_info['decimal_point']) : rtrim(number_format($item->quantity,15), 0);
|
||||
// $data[$key][$table_type.'.quantity'] = $item->quantity >=1 ? rtrim(number_format($item->quantity, $this->client->currency()->precision), $locale_info['decimal_point']) : rtrim(number_format($item->quantity,15), 0);
|
||||
// $data[$key][$table_type.'.quantity'] = rtrim($item->quantity, $locale_info['decimal_point']);
|
||||
|
||||
//30-01-2022 - improve rounding display for Unit Cost
|
||||
|
@ -54,8 +54,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
//'asset_url' => null,
|
||||
'asset_url' => env('ASSET_URL', null),
|
||||
'asset_url' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -14,8 +14,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => '5.3.56',
|
||||
'app_tag' => '5.3.56',
|
||||
'app_version' => '5.3.57',
|
||||
'app_tag' => '5.3.57',
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', ''),
|
||||
|
67
package-lock.json
generated
67
package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"axios": "^0.24.0",
|
||||
"card-js": "^1.0.13",
|
||||
"card-validator": "^8.1.1",
|
||||
"clipboard": "^2.0.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"jsignature": "^2.1.3",
|
||||
"json-formatter-js": "^2.3.4",
|
||||
@ -3240,6 +3241,16 @@
|
||||
"colors": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/clipboard": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.10.tgz",
|
||||
"integrity": "sha512-cz3m2YVwFz95qSEbCDi2fzLN/epEN9zXBvfgAoGkvGOJZATMl9gtTDVOtBYkx2ODUJl2kvmud7n32sV2BpYR4g==",
|
||||
"dependencies": {
|
||||
"good-listener": "^1.2.2",
|
||||
"select": "^1.1.2",
|
||||
"tiny-emitter": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
@ -4040,6 +4051,11 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/delegate": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
|
||||
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@ -4908,6 +4924,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/good-listener": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
|
||||
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
|
||||
"dependencies": {
|
||||
"delegate": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
@ -8591,6 +8615,11 @@
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/select": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
|
||||
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
|
||||
},
|
||||
"node_modules/select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
@ -9488,6 +9517,11 @@
|
||||
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||
},
|
||||
"node_modules/tiny-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||
@ -12779,6 +12813,16 @@
|
||||
"string-width": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"clipboard": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.10.tgz",
|
||||
"integrity": "sha512-cz3m2YVwFz95qSEbCDi2fzLN/epEN9zXBvfgAoGkvGOJZATMl9gtTDVOtBYkx2ODUJl2kvmud7n32sV2BpYR4g==",
|
||||
"requires": {
|
||||
"good-listener": "^1.2.2",
|
||||
"select": "^1.1.2",
|
||||
"tiny-emitter": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
@ -13399,6 +13443,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"delegate": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
|
||||
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@ -14062,6 +14111,14 @@
|
||||
"slash": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"good-listener": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
|
||||
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
|
||||
"requires": {
|
||||
"delegate": "^3.1.2"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
@ -16685,6 +16742,11 @@
|
||||
"ajv-keywords": "^3.5.2"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
|
||||
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
|
||||
},
|
||||
"select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
@ -17381,6 +17443,11 @@
|
||||
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||
},
|
||||
"tiny-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||
|
@ -20,6 +20,7 @@
|
||||
"axios": "^0.24.0",
|
||||
"card-js": "^1.0.13",
|
||||
"card-validator": "^8.1.1",
|
||||
"clipboard": "^2.0.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"jsignature": "^2.1.3",
|
||||
"json-formatter-js": "^2.3.4",
|
||||
|
@ -18027,6 +18027,37 @@ offers a blessing:
|
||||
May you do good and not evil
|
||||
May you find forgiveness for yourself and forgive others
|
||||
May you share freely, never taking more than you give.
|
||||
--------------------------------------------------------------------------------
|
||||
states_rebuilder
|
||||
|
||||
// Copyright 2019 The MELLATI Meftah. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
super_editor
|
||||
|
||||
|
3
public/assets/clippy.svg
Normal file
3
public/assets/clippy.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg height="1024" width="896" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M128 768h256v64H128v-64z m320-384H128v64h320v-64z m128 192V448L384 640l192 192V704h320V576H576z m-288-64H128v64h160v-64zM128 704h160v-64H128v64z m576 64h64v128c-1 18-7 33-19 45s-27 18-45 19H64c-35 0-64-29-64-64V192c0-35 29-64 64-64h192C256 57 313 0 384 0s128 57 128 128h192c35 0 64 29 64 64v320h-64V320H64v576h640V768zM128 256h512c0-35-29-64-64-64h-64c-35 0-64-29-64-64s-29-64-64-64-64 29-64 64-29 64-64 64h-64c-35 0-64 29-64 64z" />
|
||||
</svg>
|
After Width: | Height: | Size: 519 B |
6
public/flutter_service_worker.js
vendored
6
public/flutter_service_worker.js
vendored
@ -25,14 +25,14 @@ const RESOURCES = {
|
||||
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
|
||||
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "015400679694f1f51047e46da0e1dc98",
|
||||
"assets/AssetManifest.json": "38d9aea341601f3a5c6fa7b5a1216ea5",
|
||||
"assets/NOTICES": "224588855e3a5da7f1c34f0db1837839",
|
||||
"assets/NOTICES": "9a4bf0423a5e265f38c4df37f7a0a913",
|
||||
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
|
||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||
"/": "085942208d4abcfcbd9e14bccdbc445c",
|
||||
"/": "9a6d03b86fbbbe937744bd4e18e8f03a",
|
||||
"version.json": "a00481850d5c63ba5df4e22636643438",
|
||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
||||
"main.dart.js": "1b02a5309c32514f339260abc3d5cb02",
|
||||
"main.dart.js": "299333488d94a781eef76d041cb91148",
|
||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||
"canvaskit/profiling/canvaskit.js": "3783918f48ef691e230156c251169480",
|
||||
|
2
public/js/clients/linkify-urls.js
vendored
2
public/js/clients/linkify-urls.js
vendored
@ -1 +1 @@
|
||||
(()=>{var e,t={2623:(e,t,r)=>{"use strict";e.exports=r(4666)},1886:(e,t)=>{"use strict";const r=e=>e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">"),n=e=>e.replace(/>/g,">").replace(/</g,"<").replace(/�?39;/g,"'").replace(/"/g,'"').replace(/&/g,"&");t.T=(e,...t)=>{if("string"==typeof e)return r(e);let n=e[0];for(const[o,a]of t.entries())n=n+r(String(a))+e[o+1];return n}},7636:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});var n=r(1886);var o=r(2623);const a=e=>e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">");const i=new Set(o);function c({name:e="div",attributes:t={},html:r="",text:o}={}){if(r&&o)throw new Error("The `html` and `text` options are mutually exclusive");const c=o?function(e,...t){if("string"==typeof e)return a(e);let r=e[0];for(const[n,o]of t.entries())r=r+a(String(o))+e[n+1];return r}(o):r;let l=`<${e}${function(e){const t=[];for(let[r,o]of Object.entries(e)){if(!1===o)continue;Array.isArray(o)&&(o=o.join(" "));let e=(0,n.T)(r);!0!==o&&(e+=`="${(0,n.T)(String(o))}"`),t.push(e)}return t.length>0?" "+t.join(" "):""}(t)}>`;return i.has(e)||(l+=`${c}</${e}>`),l}const l=(e,t)=>c({name:"a",attributes:{href:"",...t.attributes,href:e},text:void 0===t.value?e:void 0,html:void 0===t.value?void 0:"function"==typeof t.value?t.value(e):t.value});function s(e,t){if("string"===(t={attributes:{},type:"string",...t}).type)return((e,t)=>e.replace(/((?<!\+)https?:\/\/(?:www\.)?(?:[-\w.]+?[.@][a-zA-Z\d]{2,}|localhost)(?:[-\w.:%+~#*$!?&/=@]*?(?:,(?!\s))*?)*)/g,(e=>l(e,t))))(e,t);if("dom"===t.type)return((e,t)=>{const r=document.createDocumentFragment();for(const[o,a]of Object.entries(e.split(/((?<!\+)https?:\/\/(?:www\.)?(?:[-\w.]+?[.@][a-zA-Z\d]{2,}|localhost)(?:[-\w.:%+~#*$!?&/=@]*?(?:,(?!\s))*?)*)/g)))o%2?r.append((n=l(a,t),document.createRange().createContextualFragment(n))):a.length>0&&r.append(a);var n;return r})(e,t);throw new TypeError("The type option must be either `dom` or `string`")}},4666:e=>{"use strict";e.exports=JSON.parse('["area","base","br","col","embed","hr","img","input","link","menuitem","meta","param","source","track","wbr"]')}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},e=n(7636),document.querySelectorAll("[data-ref=entity-terms]").forEach((function(t){t.innerHTML=e(t.innerText,{attributes:{target:"_blank",class:"text-primary"}})}))})();
|
||||
(()=>{var e,t={2623:(e,t,r)=>{"use strict";e.exports=r(4666)},1886:(e,t)=>{"use strict";const r=e=>e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">"),n=e=>e.replace(/>/g,">").replace(/</g,"<").replace(/�?39;/g,"'").replace(/"/g,'"').replace(/&/g,"&");t.T=(e,...t)=>{if("string"==typeof e)return r(e);let n=e[0];for(const[o,a]of t.entries())n=n+r(String(a))+e[o+1];return n}},7636:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});var n=r(1886);var o=r(2623);const a=e=>e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">");const i=new Set(o);function c({name:e="div",attributes:t={},html:r="",text:o}={}){if(r&&o)throw new Error("The `html` and `text` options are mutually exclusive");const c=o?function(e,...t){if("string"==typeof e)return a(e);let r=e[0];for(const[n,o]of t.entries())r=r+a(String(o))+e[n+1];return r}(o):r;let l=`<${e}${function(e){const t=[];for(let[r,o]of Object.entries(e)){if(!1===o)continue;Array.isArray(o)&&(o=o.join(" "));let e=(0,n.T)(r);!0!==o&&(e+=`="${(0,n.T)(String(o))}"`),t.push(e)}return t.length>0?" "+t.join(" "):""}(t)}>`;return i.has(e)||(l+=`${c}</${e}>`),l}const l=(e,t)=>c({name:"a",attributes:{href:"",...t.attributes,href:e},text:void 0===t.value?e:void 0,html:void 0===t.value?void 0:"function"==typeof t.value?t.value(e):t.value});function s(e,t){if("string"===(t={attributes:{},type:"string",...t}).type)return((e,t)=>e.replace(/((?<!\+)https?:\/\/(?:www\.)?(?:[-\w.]+?[.@][a-zA-Z\d]{2,}|localhost)(?:[-\w.:%+~#*$!?&/=@]*?(?:,(?!\s))*?)*)/g,(e=>l(e,t))))(e,t);if("dom"===t.type)return((e,t)=>{const r=document.createDocumentFragment();for(const[o,a]of Object.entries(e.split(/((?<!\+)https?:\/\/(?:www\.)?(?:[-\w.]+?[.@][a-zA-Z\d]{2,}|localhost)(?:[-\w.:%+~#*$!?&/=@]*?(?:,(?!\s))*?)*)/g)))o%2?r.append((n=l(a,t),document.createRange().createContextualFragment(n))):a.length>0&&r.append(a);var n;return r})(e,t);throw new TypeError("The type option must be either `dom` or `string`")}},4666:e=>{"use strict";e.exports=JSON.parse('["area","base","br","col","embed","hr","img","input","link","menuitem","meta","param","source","track","wbr"]')}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},e=n(7636),document.querySelectorAll("[data-ref=entity-terms]").forEach((function(t){"function"===e&&(t.innerHTML=e(t.innerText,{attributes:{target:"_blank",class:"text-primary"}}))}))})();
|
265385
public/main.dart.js
vendored
265385
public/main.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
262833
public/main.foss.dart.js
vendored
262833
public/main.foss.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
262044
public/main.html.dart.js
vendored
262044
public/main.html.dart.js
vendored
File diff suppressed because one or more lines are too long
216414
public/main.next.dart.js
vendored
216414
public/main.next.dart.js
vendored
File diff suppressed because one or more lines are too long
21850
public/main.profile.dart.js
vendored
21850
public/main.profile.dart.js
vendored
File diff suppressed because one or more lines are too long
@ -15,7 +15,7 @@
|
||||
"/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=8ce33c3deae058ad314f",
|
||||
"/js/clients/shared/pdf.js": "/js/clients/shared/pdf.js?id=73a0d914ad3577f257f4",
|
||||
"/js/clients/shared/multiple-downloads.js": "/js/clients/shared/multiple-downloads.js?id=c2caa29f753ad1f3a12c",
|
||||
"/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=44c51b4838d1f135bbe3",
|
||||
"/js/clients/linkify-urls.js": "/js/clients/linkify-urls.js?id=dd6a49267dfe156c3bc9",
|
||||
"/js/clients/payments/braintree-credit-card.js": "/js/clients/payments/braintree-credit-card.js?id=a334dd9257dd510a1feb",
|
||||
"/js/clients/payments/braintree-paypal.js": "/js/clients/payments/braintree-paypal.js?id=37950e8a39281d2f596a",
|
||||
"/js/clients/payments/wepay-credit-card.js": "/js/clients/payments/wepay-credit-card.js?id=ba4d5b7175117ababdb2",
|
||||
@ -39,5 +39,6 @@
|
||||
"/js/clients/payments/stripe-browserpay.js": "/js/clients/payments/stripe-browserpay.js?id=71e49866d66a6d85b88a",
|
||||
"/js/clients/payments/stripe-fpx.js": "/js/clients/payments/stripe-fpx.js?id=3a1cac8fb671c2e4337f",
|
||||
"/css/app.css": "/css/app.css?id=cab8a6526b0f9f71842d",
|
||||
"/css/card-js.min.css": "/css/card-js.min.css?id=62afeb675235451543ad"
|
||||
"/css/card-js.min.css": "/css/card-js.min.css?id=62afeb675235451543ad",
|
||||
"/vendor/clipboard.min.js": "/vendor/clipboard.min.js?id=ad98572d415d2f245284"
|
||||
}
|
||||
|
1
public/vendor/clipboard.min.js
vendored
Normal file
1
public/vendor/clipboard.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/livewire.js
vendored
2
public/vendor/livewire/livewire.js
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/livewire.js.map
vendored
2
public/vendor/livewire/livewire.js.map
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/manifest.json
vendored
2
public/vendor/livewire/manifest.json
vendored
@ -1 +1 @@
|
||||
{"/livewire.js":"/livewire.js?id=f092ba91a90e56843ffc"}
|
||||
{"/livewire.js":"/livewire.js?id=ece4c4ab4b746f6f1739"}
|
12
resources/js/clients/linkify-urls.js
vendored
12
resources/js/clients/linkify-urls.js
vendored
@ -13,7 +13,13 @@ const linkifyUrls = require('linkify-urls');
|
||||
document
|
||||
.querySelectorAll('[data-ref=entity-terms]')
|
||||
.forEach((text) => {
|
||||
text.innerHTML = linkifyUrls(text.innerText, {
|
||||
attributes: {target: '_blank', class: 'text-primary'}
|
||||
});
|
||||
|
||||
if (linkifyUrls === 'function') {
|
||||
|
||||
text.innerHTML = linkifyUrls(text.innerText, {
|
||||
attributes: {target: '_blank', class: 'text-primary'}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -4544,7 +4544,7 @@ $LANG = array(
|
||||
'activity_123' => ':user deleted recurring expense :recurring_expense',
|
||||
'activity_124' => ':user restored recurring expense :recurring_expense',
|
||||
'fpx' => "FPX",
|
||||
|
||||
'to_view_entity_set_password' => 'To view the :entity you need to set password.',
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -1,5 +1,5 @@
|
||||
@extends('portal.ninja2020.layout.app')
|
||||
@section('meta_title', ctrans('texts.entity_number_placeholder', ['entity' => ctrans('texts.credit'), 'entity_number' => $credit->number]))
|
||||
@section('meta_title', ctrans('texts.view_credit'))
|
||||
|
||||
@push('head')
|
||||
<meta name="pdf-url" content="{{ $credit->pdf_file_path(null, 'url', true) }}">
|
||||
@ -9,15 +9,52 @@
|
||||
@endpush
|
||||
|
||||
@section('body')
|
||||
<div class="bg-white shadow sm:rounded-lg mb-4" translate>
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="sm:flex sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
{{ ctrans('texts.entity_number_placeholder', ['entity' => ctrans('texts.credit'), 'entity_number' => $credit->number]) }}
|
||||
</h3>
|
||||
|
||||
<div class="btn" data-clipboard-text="{{url("client/credit/{$key}")}}" aria-label="Copied!">
|
||||
<div class="flex text-sm leading-6 font-medium text-gray-500">
|
||||
<p class="mr-2">{{url("client/credit/{$key}")}}</p>
|
||||
<p><img class="h-5 w-5" src="{{ asset('assets/clippy.svg') }}" alt="Copy to clipboard"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('portal.ninja2020.components.entity-documents', ['entity' => $credit])
|
||||
|
||||
@include('portal.ninja2020.components.pdf-viewer', ['entity' => $credit])
|
||||
|
||||
<div class="flex justify-center">
|
||||
<canvas id="pdf-placeholder" class="shadow rounded-lg bg-white lg:hidden mt-4 p-4"></canvas>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('footer')
|
||||
<script src="{{ asset('js/clients/shared/pdf.js') }}"></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var clipboard = new ClipboardJS('.btn');
|
||||
|
||||
// clipboard.on('success', function(e) {
|
||||
// console.info('Action:', e.action);
|
||||
// console.info('Text:', e.text);
|
||||
// console.info('Trigger:', e.trigger);
|
||||
|
||||
// e.clearSelection();
|
||||
// });
|
||||
|
||||
// clipboard.on('error', function(e) {
|
||||
// console.error('Action:', e.action);
|
||||
// console.error('Trigger:', e.trigger);
|
||||
// });
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
|
@ -1,7 +1,22 @@
|
||||
@php
|
||||
$token_billing = $gateway instanceof \App\Models\CompanyGateway
|
||||
? $gateway->token_billing !== 'always'
|
||||
: $gateway->company_gateway->token_billing !== 'always';
|
||||
// $token_billing = $gateway instanceof \App\Models\CompanyGateway
|
||||
// ? $gateway->token_billing !== 'always'
|
||||
// : $gateway->company_gateway->token_billing !== 'always';
|
||||
|
||||
$gateway_instance = $gateway instanceof \App\Models\CompanyGateway ? $gateway : $gateway->company_gateway;
|
||||
$token_billing = true;
|
||||
$checked_on = '';
|
||||
$checked_off = 'checked';
|
||||
|
||||
if($gateway_instance->token_billing == 'off' || $gateway_instance->token_billing == 'always'){
|
||||
$token_billing = false;
|
||||
}
|
||||
|
||||
if($gateway_instance->token_billing == 'optout' || $gateway_instance->token_billing == 'always'){
|
||||
$checked_on = 'checked';
|
||||
$checked_off = '';
|
||||
}
|
||||
|
||||
@endphp
|
||||
|
||||
@if($token_billing)
|
||||
@ -13,13 +28,13 @@
|
||||
<label class="mr-4">
|
||||
<input type="radio" class="form-radio cursor-pointer" name="token-billing-checkbox"
|
||||
id="proxy_is_default"
|
||||
value="true"/>
|
||||
value="true" {{ $checked_on }}/>
|
||||
<span class="ml-1 cursor-pointer">{{ ctrans('texts.yes') }}</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" class="form-radio cursor-pointer" name="token-billing-checkbox"
|
||||
id="proxy_is_default"
|
||||
value="false" checked />
|
||||
value="false" {{ $checked_off }} />
|
||||
<span class="ml-1 cursor-pointer">{{ ctrans('texts.no') }}</span>
|
||||
</label>
|
||||
</dd>
|
||||
|
@ -7,6 +7,7 @@
|
||||
@include('portal.ninja2020.components.no-cache')
|
||||
|
||||
<script src="{{ asset('vendor/signature_pad@2.3.2/signature_pad.min.js') }}"></script>
|
||||
|
||||
@endpush
|
||||
|
||||
@section('body')
|
||||
@ -38,6 +39,14 @@
|
||||
{{ ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice->number])}}
|
||||
- {{ ctrans('texts.unpaid') }}
|
||||
</h3>
|
||||
|
||||
<div class="btn" data-clipboard-text="{{url("client/invoice/{$key}")}}" aria-label="Copied!">
|
||||
<div class="flex text-sm leading-6 font-medium text-gray-500">
|
||||
<p class="mr-2">{{url("client/invoice/{$key}")}}</p>
|
||||
<p><img class="h-5 w-5" src="{{ asset('assets/clippy.svg') }}" alt="Copy to clipboard"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="mt-5 sm:mt-0 sm:ml-6 flex justify-end">
|
||||
<div class="inline-flex rounded-md shadow-sm">
|
||||
@ -64,6 +73,13 @@
|
||||
{{ ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice->number])}}
|
||||
- {{ \App\Models\Invoice::stringStatus($invoice->status_id) }}
|
||||
</h3>
|
||||
|
||||
<div class="btn" data-clipboard-text="{{url("client/invoice/{$key}")}}" aria-label="Copied!">
|
||||
<div class="flex text-sm leading-6 font-medium text-gray-500">
|
||||
<p class="pr-10">{{url("client/invoice/{$key}")}}</p>
|
||||
<p><img class="h-5 w-5" src="{{ asset('assets/clippy.svg') }}" alt="Copy to clipboard"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -78,4 +94,24 @@
|
||||
|
||||
@section('footer')
|
||||
<script src="{{ asset('js/clients/invoices/payment.js') }}"></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var clipboard = new ClipboardJS('.btn');
|
||||
|
||||
// clipboard.on('success', function(e) {
|
||||
// console.info('Action:', e.action);
|
||||
// console.info('Text:', e.text);
|
||||
// console.info('Trigger:', e.trigger);
|
||||
|
||||
// e.clearSelection();
|
||||
// });
|
||||
|
||||
// clipboard.on('error', function(e) {
|
||||
// console.error('Action:', e.action);
|
||||
// console.error('Trigger:', e.trigger);
|
||||
// });
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
|
@ -9,9 +9,20 @@
|
||||
<div class="bg-white shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="sm:flex sm:items-start sm:justify-between">
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
{{ ctrans('texts.approve') }}
|
||||
</h3>
|
||||
<div>
|
||||
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
{{ ctrans('texts.approve') }}
|
||||
</h3>
|
||||
|
||||
<div class="btn" data-clipboard-text="{{url("client/quote/{$key}")}}" aria-label="Copied!">
|
||||
<div class="flex text-sm leading-6 font-medium text-gray-500">
|
||||
<p class="mr-2">{{url("client/quote/{$key}")}}</p>
|
||||
<p><img class="h-5 w-5" src="{{ asset('assets/clippy.svg') }}" alt="Copy to clipboard"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center">
|
||||
@yield('quote-not-approved-right-side')
|
||||
|
@ -21,14 +21,71 @@
|
||||
@endcomponent
|
||||
@endif
|
||||
|
||||
@if($quote->status_id === \App\Models\Quote::STATUS_SENT)
|
||||
@if(in_array($quote->status_id, [\App\Models\Quote::STATUS_SENT, \App\Models\Quote::STATUS_DRAFT]))
|
||||
<div class="mb-4">
|
||||
@include('portal.ninja2020.quotes.includes.actions', ['quote' => $quote])
|
||||
</div>
|
||||
@elseif($quote->status_id === \App\Models\Quote::STATUS_CONVERTED)
|
||||
|
||||
<div class="bg-white shadow sm:rounded-lg mb-4">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="sm:flex sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
{{ ctrans('texts.approved') }}
|
||||
</h3>
|
||||
|
||||
<div class="btn" data-clipboard-text="{{url("client/quote/{$key}")}}" aria-label="Copied!">
|
||||
<div class="flex text-sm leading-6 font-medium text-gray-500">
|
||||
<p class="mr-2">{{url("client/quote/{$key}")}}</p>
|
||||
<p><img class="h-5 w-5" src="{{ asset('assets/clippy.svg') }}" alt="Copy to clipboard"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@elseif($quote->status_id === \App\Models\Quote::STATUS_APPROVED)
|
||||
<p class="text-right text-gray-900 text-sm mb-4">{{ ctrans('texts.approved') }}</p>
|
||||
|
||||
<div class="bg-white shadow sm:rounded-lg mb-4">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="sm:flex sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
{{ ctrans('texts.approved') }}
|
||||
</h3>
|
||||
|
||||
<div class="btn" data-clipboard-text="{{url("client/quote/{$key}")}}" aria-label="Copied!">
|
||||
<div class="flex text-sm leading-6 font-medium text-gray-500">
|
||||
<p class="mr-2">{{url("client/quote/{$key}")}}</p>
|
||||
<p><img class="h-5 w-5" src="{{ asset('assets/clippy.svg') }}" alt="Copy to clipboard"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<p class="text-right text-gray-900 text-sm mb-4">{{ ctrans('texts.quotes_with_status_sent_can_be_approved') }}</p>
|
||||
|
||||
<div class="bg-white shadow sm:rounded-lg mb-4">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="sm:flex sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
{{ ctrans('texts.expired') }}
|
||||
</h3>
|
||||
|
||||
<div class="btn" data-clipboard-text="{{url("client/quote/{$key}")}}" aria-label="Copied!">
|
||||
<div class="flex text-sm leading-6 font-medium text-gray-500">
|
||||
<p class="mr-2">{{url("client/quote/{$key}")}}</p>
|
||||
<p><img class="h-5 w-5" src="{{ asset('assets/clippy.svg') }}" alt="Copy to clipboard"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@include('portal.ninja2020.components.entity-documents', ['entity' => $quote])
|
||||
@ -39,4 +96,24 @@
|
||||
|
||||
@section('footer')
|
||||
<script src="{{ asset('js/clients/quotes/approve.js') }}"></script>
|
||||
<script src="{{ asset('vendor/clipboard.min.js') }}"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var clipboard = new ClipboardJS('.btn');
|
||||
|
||||
// clipboard.on('success', function(e) {
|
||||
// console.info('Action:', e.action);
|
||||
// console.info('Text:', e.text);
|
||||
// console.info('Trigger:', e.trigger);
|
||||
|
||||
// e.clearSelection();
|
||||
// });
|
||||
|
||||
// clipboard.on('error', function(e) {
|
||||
// console.error('Action:', e.action);
|
||||
// console.error('Trigger:', e.trigger);
|
||||
// });
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
|
@ -0,0 +1,25 @@
|
||||
@extends('portal.ninja2020.layout.clean')
|
||||
|
||||
@section('body')
|
||||
<div class="flex h-screen">
|
||||
<div class="m-auto md:w-1/3 lg:w-1/5">
|
||||
<div class="flex flex-col">
|
||||
<h1 class="text-center text-3xl">{{ ctrans('texts.password') }}</h1>
|
||||
<p class="text-sm text-center text-gray-700">{{ ctrans('texts.to_view_entity_set_password', ['entity' => $entity_type]) }}</p>
|
||||
<form action="{{ route('client.set_password') }}" method="post" >
|
||||
<input type="hidden" name="entity_type" value="{{ $entity_type }}">
|
||||
<input type="hidden" name="invitation_key" value="{{ $invitation_key }}">
|
||||
@csrf
|
||||
<div class="flex flex-col">
|
||||
<div class="flex justify-between items-center">
|
||||
</div>
|
||||
<input type="password" name="password" id="password" class="input" minlength="7" autofocus>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<button class="button button-primary button-block bg-blue-600">{{ ctrans('texts.continue') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
@ -8,28 +8,16 @@
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
@if(method_exists($paginator,'getCursorName'))
|
||||
<li class="page-item">
|
||||
<button dusk="previousPage{{ $paginator->getCursorName() == 'page' ? '' : '.' . $paginator->getPageName() }}" type="button" class="page-link" wire:click="setPage('{{$paginator->previousCursor()->encode()}}','{{ $paginator->getCursorName() }}')" wire:loading.attr="disabled" rel="prev">@lang('pagination.previous')</button>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<button type="button" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="previousPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" rel="prev">@lang('pagination.previous')</button>
|
||||
</li>
|
||||
@endif
|
||||
<li class="page-item">
|
||||
<button type="button" class="page-link" wire:click="previousPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" rel="prev">@lang('pagination.previous')</button>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
@if(method_exists($paginator,'getCursorName'))
|
||||
<li class="page-item">
|
||||
<button dusk="nextPage{{ $paginator->getCursorName() == 'page' ? '' : '.' . $paginator->getPageName() }}" type="button" class="page-link" wire:click="setPage('{{$paginator->nextCursor()->encode()}}','{{ $paginator->getCursorName() }}')" wire:loading.attr="disabled" rel="next">@lang('pagination.next')</button>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<button type="button" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}" class="page-link" wire:click="nextPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" rel="next">@lang('pagination.next')</button>
|
||||
</li>
|
||||
@endif
|
||||
<li class="page-item">
|
||||
<button type="button" class="page-link" wire:click="nextPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" rel="next">@lang('pagination.next')</button>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
|
@ -18,6 +18,7 @@ Route::post('client/password/reset', 'Auth\ContactResetPasswordController@reset'
|
||||
Route::get('view/{entity_type}/{invitation_key}', 'ClientPortal\EntityViewController@index')->name('client.entity_view');
|
||||
Route::get('view/{entity_type}/{invitation_key}/password', 'ClientPortal\EntityViewController@password')->name('client.entity_view.password');
|
||||
Route::post('view/{entity_type}/{invitation_key}/password', 'ClientPortal\EntityViewController@handlePassword');
|
||||
Route::post('set_password', 'ClientPortal\EntityViewController@handlePasswordSet')->name('client.set_password');
|
||||
|
||||
Route::get('tmp_pdf/{hash}', 'ClientPortal\TempRouteController@index')->name('tmp_pdf');
|
||||
|
||||
|
@ -188,7 +188,8 @@ class CsvImportTest extends TestCase
|
||||
$base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
$this->assertTrue($base_transformer->hasClient('Ludwig Krajcik DVM'));
|
||||
|
||||
$this->assertTrue($base_transformer->hasClient('Bradly Jaskolski Sr.'));
|
||||
|
||||
$client_id = $base_transformer->getClient('Ludwig Krajcik DVM', null);
|
||||
|
||||
$c = Client::find($client_id);
|
||||
|
645
tests/Feature/Import/Wave/WaveTest.php
Normal file
645
tests/Feature/Import/Wave/WaveTest.php
Normal file
@ -0,0 +1,645 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace Tests\Feature\Import\CSV;
|
||||
|
||||
use App\Import\Providers\BaseImport;
|
||||
use App\Import\Providers\Wave;
|
||||
use App\Import\Transformer\BaseTransformer;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use App\Models\Vendor;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers App\Import\Providers\Wave
|
||||
*/
|
||||
class WaveTest extends TestCase
|
||||
{
|
||||
use MakesHash;
|
||||
use MockAccountData;
|
||||
use DatabaseTransactions;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(ThrottleRequests::class);
|
||||
|
||||
config(['database.default' => config('ninja.db.default')]);
|
||||
|
||||
$this->makeTestData();
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
}
|
||||
|
||||
// public function testExpenseImport()
|
||||
// {
|
||||
|
||||
// $csv = file_get_contents(
|
||||
// base_path() . '/tests/Feature/Import/wave_expenses.csv'
|
||||
// );
|
||||
// $hash = Str::random(32);
|
||||
|
||||
// $column_map = [
|
||||
// 0 => 'Transaction ID',
|
||||
// 1 => 'Transaction Date',
|
||||
// 2 => 'Account Name',
|
||||
// 3 => 'Transaction Description',
|
||||
// 4 => 'Transaction Line Description',
|
||||
// 5 => 'Amount (One column)',
|
||||
// 6 => ' ',
|
||||
// 7 => 'Debit Amount (Two Column Approach)',
|
||||
// 8 => 'Credit Amount (Two Column Approach)',
|
||||
// 9 => 'Other Accounts for this Transaction',
|
||||
// 10 => 'Customer',
|
||||
// 11 => 'Vendor',
|
||||
// 12 => 'Invoice Number',
|
||||
// 13 => 'Bill Number',
|
||||
// 14 => 'Notes / Memo',
|
||||
// 15 => 'Amount Before Sales Tax',
|
||||
// 16 => 'Sales Tax Amount',
|
||||
// 17 => 'Sales Tax Name',
|
||||
// 18 => 'Transaction Date Added',
|
||||
// 19 => 'Transaction Date Last Modified',
|
||||
// 20 => 'Account Group',
|
||||
// 21 => 'Account Type',
|
||||
// 22 => 'Account ID',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => ['expense' => ['mapping' => $column_map]],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'waveaccounting',
|
||||
// ];
|
||||
|
||||
// Cache::put($hash . '-expense', base64_encode($csv), 360);
|
||||
|
||||
// $csv_importer = new Wave($data, $this->company);
|
||||
|
||||
// $count = $csv_importer->import('expense');
|
||||
|
||||
|
||||
// }
|
||||
|
||||
public function testVendorAndExpenseWaveImport()
|
||||
{
|
||||
$csv = file_get_contents(
|
||||
base_path() . '/tests/Feature/Import/wave_vendors.csv'
|
||||
);
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
0 => 'vendor_name',
|
||||
1 => 'email',
|
||||
2 => 'contact_first_name',
|
||||
3 => 'contact_last_name',
|
||||
4 => 'vendor_currency',
|
||||
5 => 'account_number',
|
||||
6 => 'phone',
|
||||
7 => 'fax',
|
||||
8 => 'mobile',
|
||||
9 => 'toll_free',
|
||||
10 => 'website',
|
||||
11 => 'country',
|
||||
12 => 'province/state',
|
||||
13 => 'address_line_1',
|
||||
14 => 'address_line_2',
|
||||
15 => 'city',
|
||||
16 => 'postal_code/zip_code',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['vendor' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'waveaccounting',
|
||||
];
|
||||
|
||||
Cache::put($hash . '-vendor', base64_encode($csv), 360);
|
||||
|
||||
$csv_importer = new Wave($data, $this->company);
|
||||
|
||||
$count = $csv_importer->import('vendor');
|
||||
|
||||
$base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
$this->assertTrue($base_transformer->hasVendor('Vendor Name'));
|
||||
|
||||
$vendor_id = $base_transformer->getVendorId('Vendor Name');
|
||||
|
||||
$vendor = Vendor::find($vendor_id);
|
||||
|
||||
$this->assertInstanceOf(Vendor::class, $vendor);
|
||||
|
||||
$this->assertEquals(12, $vendor->currency_id);
|
||||
$this->assertEquals('Australian Capital Territory', $vendor->state);
|
||||
$this->assertEquals('city', $vendor->city);
|
||||
$this->assertEquals('postal_cod', $vendor->postal_code);
|
||||
|
||||
$this->assertEquals('firstname', $vendor->contacts->first()->first_name);
|
||||
$this->assertEquals('lastname', $vendor->contacts->first()->last_name);
|
||||
$this->assertEquals('vendor@gmail.com', $vendor->contacts->first()->email);
|
||||
$this->assertEquals('phone', $vendor->contacts->first()->phone);
|
||||
|
||||
|
||||
// now lets try importing expenses / bills
|
||||
$csv = file_get_contents(
|
||||
base_path() . '/tests/Feature/Import/wave_expenses.csv'
|
||||
);
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
0 => 'Transaction ID',
|
||||
1 => 'Transaction Date',
|
||||
2 => 'Account Name',
|
||||
3 => 'Transaction Description',
|
||||
4 => 'Transaction Line Description',
|
||||
5 => 'Amount (One column)',
|
||||
6 => ' ',
|
||||
7 => 'Debit Amount (Two Column Approach)',
|
||||
8 => 'Credit Amount (Two Column Approach)',
|
||||
9 => 'Other Accounts for this Transaction',
|
||||
10 => 'Customer',
|
||||
11 => 'Vendor',
|
||||
12 => 'Invoice Number',
|
||||
13 => 'Bill Number',
|
||||
14 => 'Notes / Memo',
|
||||
15 => 'Amount Before Sales Tax',
|
||||
16 => 'Sales Tax Amount',
|
||||
17 => 'Sales Tax Name',
|
||||
18 => 'Transaction Date Added',
|
||||
19 => 'Transaction Date Last Modified',
|
||||
20 => 'Account Group',
|
||||
21 => 'Account Type',
|
||||
22 => 'Account ID',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['expense' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'waveaccounting',
|
||||
];
|
||||
|
||||
Cache::put($hash . '-expense', base64_encode($csv), 360);
|
||||
|
||||
$csv_importer = new Wave($data, $this->company);
|
||||
|
||||
$count = $csv_importer->import('expense');
|
||||
|
||||
$base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
$this->assertTrue($base_transformer->hasExpense("66"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testClientWaveImport()
|
||||
{
|
||||
$csv = file_get_contents(
|
||||
base_path() . '/tests/Feature/Import/wave_clients.csv'
|
||||
);
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
0 => 'customer_name',
|
||||
1 => 'email',
|
||||
2 => 'contact_first_name',
|
||||
3 => 'contact_last_name',
|
||||
4 => 'customer_currency',
|
||||
5 => 'account_number',
|
||||
6 => 'phone',
|
||||
7 => 'fax',
|
||||
8 => 'mobile',
|
||||
9 => 'toll_free',
|
||||
10 => 'website',
|
||||
11 => 'country',
|
||||
12 => 'province/state',
|
||||
13 => 'address_line_1',
|
||||
14 => 'address_line_2',
|
||||
15 => 'city',
|
||||
16 => 'postal_code/zip_code',
|
||||
17 => 'shipping_address',
|
||||
18 => 'ship-to_contact',
|
||||
19 => 'ship-to_country',
|
||||
20 => 'ship-to_province/state',
|
||||
21 => 'ship-to_address_line_1',
|
||||
22 => 'ship-to_address_line_2',
|
||||
23 => 'ship-to_city',
|
||||
24 => 'ship-to_postal_code/zip_code',
|
||||
25 => 'ship-to_phone',
|
||||
26 => 'delivery_instructions',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['client' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'waveaccounting',
|
||||
];
|
||||
|
||||
Cache::put($hash . '-client', base64_encode($csv), 360);
|
||||
|
||||
$csv_importer = new Wave($data, $this->company);
|
||||
|
||||
$count = $csv_importer->import('client');
|
||||
|
||||
$base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
$this->assertTrue($base_transformer->hasClient('Homer Simpson'));
|
||||
$this->assertTrue($base_transformer->hasClient('Jessica Jones'));
|
||||
$this->assertTrue($base_transformer->hasClient('Lucas Cage'));
|
||||
$this->assertTrue($base_transformer->hasClient('Mark Walberg'));
|
||||
|
||||
$client_id = $base_transformer->getClient('Jessica Jones', 'jessica@jones.com');
|
||||
|
||||
$client = Client::find($client_id);
|
||||
|
||||
$this->assertInstanceOf(Client::class, $client);
|
||||
|
||||
$this->assertEquals('12', $client->settings->currency_id);
|
||||
$this->assertEquals('Queensland', $client->state);
|
||||
$this->assertEquals('NYC', $client->city);
|
||||
$this->assertEquals('11213', $client->postal_code);
|
||||
|
||||
$this->assertEquals('Jessica Jones', $client->contacts->first()->first_name);
|
||||
$this->assertEquals('', $client->contacts->first()->last_name);
|
||||
$this->assertEquals('jessica@jones.com', $client->contacts->first()->email);
|
||||
$this->assertEquals('555-867-5309', $client->contacts->first()->phone);
|
||||
|
||||
}
|
||||
|
||||
public function testInvoiceWaveImport()
|
||||
{
|
||||
//first import all the clients
|
||||
|
||||
$csv = file_get_contents(
|
||||
base_path() . '/tests/Feature/Import/wave_clients.csv'
|
||||
);
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
0 => 'customer_name',
|
||||
1 => 'email',
|
||||
2 => 'contact_first_name',
|
||||
3 => 'contact_last_name',
|
||||
4 => 'customer_currency',
|
||||
5 => 'account_number',
|
||||
6 => 'phone',
|
||||
7 => 'fax',
|
||||
8 => 'mobile',
|
||||
9 => 'toll_free',
|
||||
10 => 'website',
|
||||
11 => 'country',
|
||||
12 => 'province/state',
|
||||
13 => 'address_line_1',
|
||||
14 => 'address_line_2',
|
||||
15 => 'city',
|
||||
16 => 'postal_code/zip_code',
|
||||
17 => 'shipping_address',
|
||||
18 => 'ship-to_contact',
|
||||
19 => 'ship-to_country',
|
||||
20 => 'ship-to_province/state',
|
||||
21 => 'ship-to_address_line_1',
|
||||
22 => 'ship-to_address_line_2',
|
||||
23 => 'ship-to_city',
|
||||
24 => 'ship-to_postal_code/zip_code',
|
||||
25 => 'ship-to_phone',
|
||||
26 => 'delivery_instructions',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['client' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'waveaccounting',
|
||||
];
|
||||
|
||||
Cache::put($hash . '-client', base64_encode($csv), 360);
|
||||
|
||||
$csv_importer = new Wave($data, $this->company);
|
||||
|
||||
$count = $csv_importer->import('client');
|
||||
|
||||
//now import the invoices
|
||||
|
||||
$csv = file_get_contents(
|
||||
base_path() . '/tests/Feature/Import/wave_invoices.csv'
|
||||
);
|
||||
$hash = Str::random(32);
|
||||
|
||||
$column_map = [
|
||||
0 => 'Transaction ID',
|
||||
1 => 'Transaction Date',
|
||||
2 => 'Account Name',
|
||||
3 => 'Transaction Description',
|
||||
4 => 'Transaction Line Description',
|
||||
5 => 'Amount (One column)',
|
||||
6 => ' ',
|
||||
7 => 'Debit Amount (Two Column Approach)',
|
||||
8 => 'Credit Amount (Two Column Approach)',
|
||||
9 => 'Other Accounts for this Transaction',
|
||||
10 => 'Customer',
|
||||
11 => 'Vendor',
|
||||
12 => 'Invoice Number',
|
||||
13 => 'Bill Number',
|
||||
14 => 'Notes / Memo',
|
||||
15 => 'Amount Before Sales Tax',
|
||||
16 => 'Sales Tax Amount',
|
||||
17 => 'Sales Tax Name',
|
||||
18 => 'Transaction Date Added',
|
||||
19 => 'Transaction Date Last Modified',
|
||||
20 => 'Account Group',
|
||||
21 => 'Account Type',
|
||||
22 => 'Account ID',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'hash' => $hash,
|
||||
'column_map' => ['invoice' => ['mapping' => $column_map]],
|
||||
'skip_header' => true,
|
||||
'import_type' => 'waveaccounting',
|
||||
];
|
||||
|
||||
Cache::put($hash . '-invoice', base64_encode($csv), 360);
|
||||
|
||||
$csv_importer = new Wave($data, $this->company);
|
||||
|
||||
$count = $csv_importer->import('invoice');
|
||||
|
||||
$base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
$this->assertTrue($base_transformer->hasInvoice("2"));
|
||||
$this->assertTrue($base_transformer->hasInvoice("3"));
|
||||
$this->assertTrue($base_transformer->hasInvoice("4"));
|
||||
|
||||
$invoice_id = $base_transformer->getInvoiceId("4");
|
||||
$invoice = Invoice::find($invoice_id);
|
||||
|
||||
$this->assertEquals(3500.41 , $invoice->amount);
|
||||
$this->assertEquals(0 , $invoice->balance);
|
||||
$this->assertEquals(2 , count($invoice->line_items));
|
||||
|
||||
$this->assertTrue($invoice->payments()->exists());
|
||||
$this->assertEquals(3500.41, $invoice->payments->first()->amount);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// public function testVendorCsvImport()
|
||||
// {
|
||||
// $csv = file_get_contents(
|
||||
// base_path() . '/tests/Feature/Import/vendors.csv'
|
||||
// );
|
||||
// $hash = Str::random(32);
|
||||
// $column_map = [
|
||||
// 0 => 'vendor.name',
|
||||
// 19 => 'vendor.currency_id',
|
||||
// 20 => 'vendor.public_notes',
|
||||
// 21 => 'vendor.private_notes',
|
||||
// 22 => 'vendor.first_name',
|
||||
// 23 => 'vendor.last_name',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => ['vendor' => ['mapping' => $column_map]],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// $pre_import = Vendor::count();
|
||||
|
||||
// Cache::put($hash . '-vendor', base64_encode($csv), 360);
|
||||
|
||||
// $csv_importer = new Csv($data, $this->company);
|
||||
|
||||
// $csv_importer->import('vendor');
|
||||
|
||||
// $base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
// $this->assertTrue($base_transformer->hasVendor('Ludwig Krajcik DVM'));
|
||||
// }
|
||||
|
||||
// public function testProductImport()
|
||||
// {
|
||||
// $csv = file_get_contents(
|
||||
// base_path() . '/tests/Feature/Import/products.csv'
|
||||
// );
|
||||
// $hash = Str::random(32);
|
||||
// Cache::put($hash . '-product', base64_encode($csv), 360);
|
||||
|
||||
// $column_map = [
|
||||
// 1 => 'product.product_key',
|
||||
// 2 => 'product.notes',
|
||||
// 3 => 'product.cost',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => ['product' => ['mapping' => $column_map]],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// $csv_importer = new Csv($data, $this->company);
|
||||
|
||||
// $this->assertInstanceOf(Csv::class, $csv_importer);
|
||||
|
||||
// $csv_importer->import('product');
|
||||
|
||||
// $base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
// $this->assertTrue($base_transformer->hasProduct('officiis'));
|
||||
// // $this->assertTrue($base_transformer->hasProduct('maxime'));
|
||||
// }
|
||||
|
||||
// public function testClientImport()
|
||||
// {
|
||||
// $csv = file_get_contents(
|
||||
// base_path() . '/tests/Feature/Import/clients.csv'
|
||||
// );
|
||||
// $hash = Str::random(32);
|
||||
// $column_map = [
|
||||
// 1 => 'client.balance',
|
||||
// 2 => 'client.paid_to_date',
|
||||
// 0 => 'client.name',
|
||||
// 19 => 'client.currency_id',
|
||||
// 20 => 'client.public_notes',
|
||||
// 21 => 'client.private_notes',
|
||||
// 22 => 'contact.first_name',
|
||||
// 23 => 'contact.last_name',
|
||||
// 24 => 'contact.email',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => ['client' => ['mapping' => $column_map]],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// Cache::put($hash . '-client', base64_encode($csv), 360);
|
||||
|
||||
// $csv_importer = new Csv($data, $this->company);
|
||||
|
||||
// $this->assertInstanceOf(Csv::class, $csv_importer);
|
||||
|
||||
// $csv_importer->import('client');
|
||||
|
||||
// $base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
// $this->assertTrue($base_transformer->hasClient('Ludwig Krajcik DVM'));
|
||||
|
||||
// $client_id = $base_transformer->getClient('Ludwig Krajcik DVM', null);
|
||||
|
||||
// $c = Client::find($client_id);
|
||||
|
||||
// $this->assertEquals($client_id, $c->id);
|
||||
|
||||
// $client_id = $base_transformer->getClient(
|
||||
// 'a non existent clent',
|
||||
// 'brook59@example.org'
|
||||
// );
|
||||
|
||||
// $this->assertEquals($client_id, $c->id);
|
||||
// }
|
||||
|
||||
// public function testInvoiceImport()
|
||||
// {
|
||||
// /*Need to import clients first*/
|
||||
// $csv = file_get_contents(
|
||||
// base_path() . '/tests/Feature/Import/clients.csv'
|
||||
// );
|
||||
// $hash = Str::random(32);
|
||||
// $column_map = [
|
||||
// 1 => 'client.balance',
|
||||
// 2 => 'client.paid_to_date',
|
||||
// 0 => 'client.name',
|
||||
// 19 => 'client.currency_id',
|
||||
// 20 => 'client.public_notes',
|
||||
// 21 => 'client.private_notes',
|
||||
// 22 => 'contact.first_name',
|
||||
// 23 => 'contact.last_name',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => ['client' => ['mapping' => $column_map]],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// Cache::put($hash . '-client', base64_encode($csv), 360);
|
||||
|
||||
// $csv_importer = new Csv($data, $this->company);
|
||||
|
||||
// $this->assertInstanceOf(Csv::class, $csv_importer);
|
||||
|
||||
// $csv_importer->import('client');
|
||||
|
||||
// $base_transformer = new BaseTransformer($this->company);
|
||||
|
||||
// $this->assertTrue($base_transformer->hasClient('Ludwig Krajcik DVM'));
|
||||
|
||||
// /* client import verified*/
|
||||
|
||||
// /*Now import invoices*/
|
||||
// $csv = file_get_contents(
|
||||
// base_path() . '/tests/Feature/Import/invoice.csv'
|
||||
// );
|
||||
// $hash = Str::random(32);
|
||||
|
||||
// $column_map = [
|
||||
// 1 => 'client.email',
|
||||
// 3 => 'payment.amount',
|
||||
// 5 => 'invoice.po_number',
|
||||
// 8 => 'invoice.due_date',
|
||||
// 9 => 'item.discount',
|
||||
// 11 => 'invoice.partial_due_date',
|
||||
// 12 => 'invoice.public_notes',
|
||||
// 13 => 'invoice.private_notes',
|
||||
// 0 => 'client.name',
|
||||
// 2 => 'invoice.number',
|
||||
// 7 => 'invoice.date',
|
||||
// 14 => 'item.product_key',
|
||||
// 15 => 'item.notes',
|
||||
// 16 => 'item.cost',
|
||||
// 17 => 'item.quantity',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => ['invoice' => ['mapping' => $column_map]],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// Cache::put($hash . '-invoice', base64_encode($csv), 360);
|
||||
|
||||
// $csv_importer = new Csv($data, $this->company);
|
||||
|
||||
// $csv_importer->import('invoice');
|
||||
|
||||
// $this->assertTrue($base_transformer->hasInvoice('801'));
|
||||
|
||||
// /* Lets piggy back payments tests here to save rebuilding the test multiple times*/
|
||||
|
||||
// $csv = file_get_contents(
|
||||
// base_path() . '/tests/Feature/Import/payments.csv'
|
||||
// );
|
||||
// $hash = Str::random(32);
|
||||
|
||||
// $column_map = [
|
||||
// 0 => 'payment.client_id',
|
||||
// 1 => 'payment.invoice_number',
|
||||
// 2 => 'payment.amount',
|
||||
// 3 => 'payment.date',
|
||||
// ];
|
||||
|
||||
// $data = [
|
||||
// 'hash' => $hash,
|
||||
// 'column_map' => ['payment' => ['mapping' => $column_map]],
|
||||
// 'skip_header' => true,
|
||||
// 'import_type' => 'csv',
|
||||
// ];
|
||||
|
||||
// Cache::put($hash . '-payment', base64_encode($csv), 360);
|
||||
|
||||
// $csv_importer = new Csv($data, $this->company);
|
||||
|
||||
// $csv_importer->import('payment');
|
||||
|
||||
// $this->assertTrue($base_transformer->hasInvoice('801'));
|
||||
|
||||
// $invoice_id = $base_transformer->getInvoiceId('801');
|
||||
|
||||
// $invoice = Invoice::find($invoice_id);
|
||||
|
||||
// $this->assertTrue($invoice->payments()->exists());
|
||||
// $this->assertEquals(1, $invoice->payments()->count());
|
||||
// $this->assertEquals(400, $invoice->payments()->sum('payments.amount'));
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
3
tests/Feature/Import/freshbooks_clients.csv
Normal file
3
tests/Feature/Import/freshbooks_clients.csv
Normal file
@ -0,0 +1,3 @@
|
||||
Organization,First Name,Last Name,Email,Phone,Street,City,Province/State,Country,Postal Code,Notes
|
||||
Marge Simpson,Marge,Simpson,marge@simpsons.com,867-5309,2587 Sesame Street,Springfield,Illinois,United States,,
|
||||
X-Men,Scott,Summer,ssummers@xavierscool.edu,987654321,,,,United States,,
|
|
4
tests/Feature/Import/freshbooks_invoices.csv
Normal file
4
tests/Feature/Import/freshbooks_invoices.csv
Normal file
@ -0,0 +1,4 @@
|
||||
Client Name,Invoice #,Date Issued,Invoice Status,Date Paid,Item Name,Item Description,Rate,Quantity,Discount Percentage,Line Subtotal,Tax 1 Type,Tax 1 Amount,Tax 2 Type,Tax 2 Amount,Line Total,Currency
|
||||
X-Men,0000001,2021-01-28,sent,,General Car Repair,Bumper paint touch up,65.00,10.00000000,0.0000,650.00,,0.00,,0.00,650.00,USD
|
||||
X-Men,0000001,2021-01-28,sent,,Painting Service,25 hours painting,98.00,5.00000000,0.0000,490.00,,0.00,,0.00,490.00,USD
|
||||
X-Men,0000001,2021-01-28,sent,,Product Delivery,Trucking Logistics,150.00,45.00000000,0.0000,6750.00,,0.00,,0.00,6750.00,USD
|
|
3
tests/Feature/Import/i2g_clients.csv
Normal file
3
tests/Feature/Import/i2g_clients.csv
Normal file
@ -0,0 +1,3 @@
|
||||
"Client Name","Email","Phone","Country"
|
||||
"Alexander Hamilton","alexander@iamhamllton.com","5558675309","US"
|
||||
"Bruce Wayne","batman@gotham.gov","","US"
|
|
5
tests/Feature/Import/i2g_invoices.csv
Normal file
5
tests/Feature/Import/i2g_invoices.csv
Normal file
@ -0,0 +1,5 @@
|
||||
Id,AccountId,State,LastUpdated,CreatedDate,DocumentDate,DocumentNumber,Comment,Name,EmailRecipient,DocumentStatus,OutputStatus,PartPayment,DocumentRecipientAddress,ShipDate,ShipAddress,ShipAmount,ShipTrackingNumber,ShipVia,ShipFob,StyleName,DatePaid,CustomField,DiscountType,Discount,DiscountValue,Taxes,WithholdingTaxName,WithholdingTaxRate,TermsOld,Payments,Items,CurrencyCode,TotalAmount,BalanceDueAmount,AmountPaidAmount,DiscountAmount,SubtotalAmount,TotalTaxAmount,WithholdingTaxAmount
|
||||
a693ce35-78ed-49d8-a1be-968b4b18d689,24379237,synced,2021-01-28T11:04:09+00:00,2021-01-28T07:57:37+00:00,2021-01-28,1,,Barry Gordon,barry@capitalcity.gov,unsent,unsent,false,,,,0,,,,invoice,,,no_discount,0,0,"name,auto_apply,inclusive,id,rates,accumulative_of;Ma'am,true,false,d4037c01-b719-4e89-a1f4-91c0daf3ee34,""is_default,value;true,17"",",Withholding Tax,0,0,,"code,description,qty,unit_type,withholding_tax_applies,applied_taxes,unit_price,discount_percentage,discount_type,discount_amount;,Bumper paint touch up,4,parts,false,""rate,tax_id;17,d4037c01-b719-4e89-a1f4-91c0daf3ee34"",35,0,no_discount,0;,Wood Hammer Mallets,10,parts,false,""rate,tax_id;17,d4037c01-b719-4e89-a1f4-91c0daf3ee34"",2.5,0,no_discount,0;,Monthly Lawn Service 2 Hours Weekly,4,parts,false,""rate,tax_id;17,d4037c01-b719-4e89-a1f4-91c0daf3ee34"",65,0,no_discount,0;,Internal Hardware Repair,6,parts,false,""rate,tax_id;17,d4037c01-b719-4e89-a1f4-91c0daf3ee34"",65,0,no_discount,0",ILS,953.55,953.55,0,0,815,"sub_total,total,rate,tax_id;815,138.55,17,d4037c01-b719-4e89-a1f4-91c0daf3ee34",0
|
||||
a8acb5bc-c855-42b7-b56e-6fab01d14899,24379237,synced,2021-01-28T11:07:43+00:00,2021-01-28T11:07:05+00:00,2021-01-28,2,,James Gordon,commissionon@gotham.gov,unsent,unsent,false,,,,0,,,,invoice,,,no_discount,0,0,"name,auto_apply,inclusive,id,rates,accumulative_of;TAX,true,false,115e965e-eed8-4ea1-b1ca-cd1b36b8798a,""is_default,value;true,8"",",Withholding Tax,0,0,,"code,description,qty,unit_type,withholding_tax_applies,applied_taxes,unit_price,discount_percentage,discount_type,discount_amount;,Internal Hardware Repair,1,parts,false,""rate,tax_id;8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a"",65,0,no_discount,0",USD,70.2,70.2,0,0,65,"sub_total,total,rate,tax_id;65,5.2,8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a",0
|
||||
55152bdc-76b3-46eb-9420-cca8c9e7a081,24379237,synced,2021-01-28T11:08:08+00:00,2021-01-28T11:07:52+00:00,2021-01-28,4,,Deadpool Inc,wade@projectx.net,unsent,unsent,false,2584 Sesame Street,,2584 Sesame Street,0,,,,invoice,,,no_discount,0,0,"name,auto_apply,inclusive,id,rates,accumulative_of;TAX,true,false,115e965e-eed8-4ea1-b1ca-cd1b36b8798a,""is_default,value;true,8"",",Withholding Tax,0,30,,"code,description,qty,unit_type,withholding_tax_applies,applied_taxes,unit_price,discount_percentage,discount_type,discount_amount;,Internal Hardware Repair,1,parts,false,""rate,tax_id;8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a"",65,0,no_discount,0;,Monthly Lawn Service 2 Hours Weekly,1,parts,false,""rate,tax_id;8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a"",0,0,no_discount,0;,Wood Hammer Mallets,1,parts,false,""rate,tax_id;8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a"",2.5,0,no_discount,0",USD,72.9,72.9,0,0,67.5,"sub_total,total,rate,tax_id;67.5,5.4,8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a",0
|
||||
73c9c7be-abea-4154-92eb-ebf674b13748,24379237,synced,2021-01-28T11:08:51+00:00,2021-01-28T11:07:21+00:00,2021-01-28,3,,Daily Planet,louislane@dailyplanet.com,unsent,unsent,false,"2587 Super Plaza, Floor 25, Metropolis",,"2587 Super Plaza, Floor 25, Metropolis",0,,,,invoice,,,no_discount,0,0,"name,auto_apply,inclusive,id,rates,accumulative_of;TAX,true,false,115e965e-eed8-4ea1-b1ca-cd1b36b8798a,""is_default,value;true,8"",",Withholding Tax,0,14,,"code,description,qty,unit_type,withholding_tax_applies,applied_taxes,unit_price,discount_percentage,discount_type,discount_amount;,Monthly Lawn Service 2 Hours Weekly,4,labor_hours,false,""rate,tax_id;8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a"",85,0,no_discount,0",USD,367.2,367.2,0,0,340,"sub_total,total,rate,tax_id;340,27.2,8,115e965e-eed8-4ea1-b1ca-cd1b36b8798a",0
|
|
3
tests/Feature/Import/invoicely_clients.csv
Normal file
3
tests/Feature/Import/invoicely_clients.csv
Normal file
@ -0,0 +1,3 @@
|
||||
"Client Name","Email","Phone","Country"
|
||||
"Alexander Hamilton","alexander@iamhamllton.com","5558675309","US"
|
||||
"Bruce Wayne","batman@gotham.gov","","US"
|
|
2
tests/Feature/Import/invoicely_invoices.csv
Normal file
2
tests/Feature/Import/invoicely_invoices.csv
Normal file
@ -0,0 +1,2 @@
|
||||
"Date","Due","Details","Client","Status","Total"
|
||||
"Jan 28 2021","Jan 28 2021","INV-1","Bruce Wayne","Due","1,020.00"
|
|
106
tests/Feature/Import/quotes.csv
Normal file
106
tests/Feature/Import/quotes.csv
Normal file
@ -0,0 +1,106 @@
|
||||
"Invoice Ninja v4.5.49 - February 7, 2022 9:33 pm","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"QUOTES","","","","","","","","","","","","","","","","","","","","","","","","",""
|
||||
"Client","Email","Quote Number","Amount","Paid","PO Number","Status","Quote Date","Due Date","Discount","Public Notes","Private Notes","invoice surch 1","invoice surch 2","invoice 1","invoice 2","Item Product","Item Notes","product field","product field2","Item Cost","Item Quantity","Item Tax Name","Item Tax Rate","Item Tax Name","Item Tax Rate"
|
||||
"Jody Cartwright Jr.","julian50@example.com","0002","$5.55","$0.00","","Sent","2021-08-09","2021-09-20","","","","0","0","","","quod","Iusto quibusdam praesentium vel nobis explicabo. Eius ipsa et in iusto. Aut voluptas sit occaecati aperiam eos. Qui dolores ut illo odit eos sed sint.","","","5.55","1","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0013","$23.73","$0.00","","Sent","2021-09-02","2021-06-23","","","","0","0","","","ratione","Labore repudiandae ipsum nihil in pariatur dolores. Cupiditate voluptates autem non labore id aut consequatur. Mollitia rerum rerum quidem provident voluptas. Qui aliquid omnis consequatur et est voluptatem. Sit rerum aut molestiae qui.","","","3.39","7","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0014","$6.69","$0.00","","Sent","2021-06-11","2021-07-20","","","","0","0","","","dolor","Similique enim iure omnis voluptas laboriosam assumenda. Fugit nam amet eveniet sunt. Similique totam dignissimos ut quia voluptatibus tempore maxime laborum.","","","2.23","3","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0015","$45.71","$0.00","","Sent","2021-07-28","2021-04-21","","","","0","0","","","sed","Sint error quae corporis quas dolore qui deleniti minima. Aut dolorem facere nobis molestiae aut nemo. Veritatis sed omnis ut omnis. Quia explicabo possimus impedit iste.","","","6.53","7","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0016","$26.22","$0.00","","Sent","2021-04-01","2021-07-28","","","","0","0","","","omnis","Perspiciatis totam voluptatem nostrum dolorem impedit dolor. Sint quia necessitatibus labore officia necessitatibus. Ex delectus eaque sit inventore. A dolore ullam optio. Autem quod ut sed. Molestiae rerum sed quo et qui adipisci sed qui.","","","4.37","6","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0017","$45.50","$0.00","","Sent","2021-04-23","2021-08-23","","","","0","0","","","eum","Qui rerum minima quo earum. Quos facilis alias perferendis nam natus praesentium molestiae.","","","9.1","5","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0018","$7.53","$0.00","","Sent","2021-05-29","2021-07-29","","","","0","0","","","unde","Voluptates vel et molestiae pariatur aliquam commodi quia. Dolores dolor illum qui nulla.","","","7.53","1","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0019","$6.21","$0.00","","Sent","2021-06-27","2021-06-30","","","","0","0","","","maxime","Sunt fugiat deleniti qui. Voluptatem voluptates ut est et similique. Natus in et consequatur sed repudiandae.","","","6.21","1","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0020","$22.08","$0.00","","Sent","2021-03-24","2021-07-12","","","","0","0","","","esse","Nostrum blanditiis perspiciatis sunt tenetur fugiat praesentium. Reiciendis autem possimus nulla occaecati itaque placeat. Est quo voluptatibus architecto doloribus id sapiente.","","","2.76","8","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0021","$6.44","$0.00","","Sent","2021-06-06","2021-04-25","","","","0","0","","","mollitia","Et et consequatur voluptatum qui. Sed sed numquam omnis fugit ut. Et quaerat dicta quia minus.","","","6.44","1","","","","0"
|
||||
"Keyshawn Hahn","lewis.harris@example.com","0022","$7.36","$0.00","","Sent","2021-07-02","2021-06-15","","","","0","0","","","dolore","Sed velit voluptatem et ipsam quis libero. Vero perferendis minima earum nesciunt. Facilis in labore laboriosam inventore hic voluptatem ipsa.","","","1.84","4","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0033","$43.74","$0.00","","Sent","2021-06-27","2021-05-01","","","","0","0","","","incidunt","Harum repellat ut sed vitae eveniet delectus. Et qui repellat eius laboriosam. Praesentium corporis optio non doloremque qui aperiam temporibus.","","","4.86","9","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0034","$31.22","$0.00","","Sent","2021-07-19","2021-04-12","","","","0","0","","","accusantium","Eius voluptas velit omnis. Corporis voluptates soluta hic nobis et eum dicta. Molestiae possimus et totam dolores. Iure nostrum dolor enim saepe enim. Saepe quia nobis quas ipsum. Ut odit voluptas et error.","","","4.46","7","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0035","$35.37","$0.00","","Sent","2021-03-23","2021-09-22","","","","0","0","","","consequatur","Aut nesciunt velit totam iusto consectetur eius.","","","3.93","9","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0036","$7.95","$0.00","","Sent","2021-08-28","2021-09-17","","","","0","0","","","quis","Numquam harum pariatur pariatur totam. Voluptatem quis corporis sit aut commodi molestiae. Odio sit distinctio hic voluptatem qui expedita nihil.","","","2.65","3","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0037","$23.85","$0.00","","Sent","2021-06-21","2021-06-15","","","","0","0","","","perspiciatis","Eum labore veritatis inventore atque. Voluptatem nesciunt sed voluptatibus et rem necessitatibus hic voluptatum. Reiciendis dolorum architecto dolorum. Velit distinctio eligendi fugiat error est.","","","2.65","9","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0038","$7.32","$0.00","","Sent","2021-08-05","2021-07-07","","","","0","0","","","omnis","Ut dolor necessitatibus delectus quia velit ad sed. Eum non soluta numquam. Voluptatem enim quod similique cupiditate.","","","3.66","2","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0039","$31.45","$0.00","","Sent","2021-08-05","2021-09-12","","","","0","0","","","occaecati","Aut et ut eos. Hic minus adipisci non eum blanditiis et nihil.","","","6.29","5","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0040","$24.30","$0.00","","Sent","2021-05-09","2021-08-14","","","","0","0","","","placeat","Accusamus cumque est velit enim nam in totam. Distinctio vel quibusdam fugit a. Non consectetur et dolorem veniam.","","","4.86","5","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0041","$6.04","$0.00","","Sent","2021-03-18","2021-05-10","","","","0","0","","","quia","Aut et unde et aut voluptatem atque. Explicabo quo itaque tempora non.","","","6.04","1","","","","0"
|
||||
"Leonie Bergnaum","qhamill@example.com","0042","$26.15","$0.00","","Sent","2021-09-16","2021-10-01","","","","0","0","","","exercitationem","Nihil et aut occaecati voluptas et. Nemo rerum debitis aperiam fuga qui. Officiis eos vel sit quos illo hic.","","","5.23","5","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0053","$97.00","$0.00","","Sent","2021-06-04","2021-07-31","","","","0","0","","","vero","Ut quia perspiciatis numquam. Esse at totam aut eos nulla et modi sed. Voluptatibus ut autem labore culpa accusantium sed suscipit. Quidem nihil assumenda eos aliquid.","","","9.7","10","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0054","$4.02","$0.00","","Sent","2021-05-19","2021-08-11","","","","0","0","","","id","Aut doloremque temporibus est voluptatum et nesciunt occaecati. Debitis magnam sapiente officiis.","","","1.34","3","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0055","$38.40","$0.00","","Sent","2021-05-12","2021-07-14","","","","0","0","","","eaque","Laborum impedit ea excepturi vel recusandae voluptatum quo. Doloribus hic et ut laudantium eius nesciunt. Quis saepe earum aliquid nulla ut.","","","4.8","8","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0056","$56.94","$0.00","","Sent","2021-06-14","2021-07-07","","","","0","0","","","perferendis","Fugit asperiores consectetur voluptates. Accusantium ullam quibusdam tempore ab.","","","9.49","6","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0057","$57.92","$0.00","","Sent","2021-08-12","2021-05-18","","","","0","0","","","dolorum","Qui maxime ut exercitationem cum quia sapiente. Qui officia corrupti nam eum enim suscipit qui. Magnam consequatur nulla dolorum optio nostrum.","","","7.24","8","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0058","$46.56","$0.00","","Sent","2021-04-20","2021-09-20","","","","0","0","","","nihil","Nihil molestias possimus sint autem praesentium. Facere cupiditate officiis nihil sed veniam facere sit. Tempora quis error ut dolor esse vel quia. Est vel aut tempore et similique qui animi.","","","7.76","6","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0059","$9.40","$0.00","","Sent","2021-06-14","2021-03-25","","","","0","0","","","consequuntur","Facilis tempora soluta est similique. Hic sed quod ipsum eaque incidunt et laborum. Quia ut cum molestiae. Corrupti provident in ipsam.","","","1.88","5","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0060","$4.32","$0.00","","Sent","2021-05-20","2021-07-29","","","","0","0","","","sed","Est voluptate hic quod qui molestiae ad. Aspernatur id magnam et occaecati eum. Numquam voluptatem porro totam itaque.","","","4.32","1","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0061","$20.10","$0.00","","Sent","2021-07-27","2021-07-20","","","","0","0","","","a","Atque est animi ipsum porro. Quia fugiat expedita et sed accusantium voluptatem.","","","3.35","6","","","","0"
|
||||
"Sophia Kshlerin","shaniya90@example.org","0062","$86.90","$0.00","","Sent","2021-04-07","2021-08-06","","","","0","0","","","et","Harum ut dolore consequatur quis. Nobis expedita et numquam a vel beatae molestias. Sit ut non omnis minima id voluptatum. Repellendus non in qui natus atque.","","","8.69","10","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0073","$22.64","$0.00","","Sent","2021-04-28","2021-04-21","","","","0","0","","","sapiente","Amet ipsum consequatur et repellat porro quisquam dolor. Numquam quia incidunt et qui dignissimos. Vitae repellat quisquam animi velit natus quia. Quia vel laudantium voluptates recusandae sunt id cumque.","","","5.66","4","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0074","$8.76","$0.00","","Sent","2021-08-11","2021-06-09","","","","0","0","","","accusamus","Est accusamus quam quia est aut eaque architecto.","","","4.38","2","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0075","$57.19","$0.00","","Sent","2021-08-05","2021-09-15","","","","0","0","","","corrupti","Aut eveniet et sit voluptas.","","","8.17","7","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0076","$66.60","$0.00","","Sent","2021-04-21","2021-03-24","","","","0","0","","","qui","Sunt voluptas dolores iusto et culpa. Voluptas nostrum molestiae nisi dolores quidem sapiente.","","","6.66","10","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0077","$3.39","$0.00","","Sent","2021-08-17","2021-04-26","","","","0","0","","","similique","Labore autem dolores alias ab sunt veniam. Repellendus culpa eos voluptas nemo autem unde ratione. Voluptatem quibusdam corporis sed sunt iure repellat rerum.","","","1.13","3","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0078","$17.70","$0.00","","Sent","2021-05-30","2021-06-18","","","","0","0","","","voluptas","Non eum laborum vitae ea et aut. Dolor ab dolores molestiae pariatur. Minus est quo aut eligendi dolorem harum aut.","","","1.77","10","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0079","$34.90","$0.00","","Sent","2021-07-29","2021-09-16","","","","0","0","","","vitae","Earum id ad sunt ea facere amet. Nesciunt est error aut soluta. Omnis et autem et qui dolores molestias.","","","6.98","5","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0080","$30.12","$0.00","","Sent","2021-08-07","2021-06-07","","","","0","0","","","ut","Voluptate quos eaque suscipit aliquam quisquam dolores dolorem et. Sit et esse corporis quis. Nobis ut quidem ad quo eum.","","","5.02","6","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0081","$20.70","$0.00","","Sent","2021-04-28","2021-09-28","","","","0","0","","","similique","Ea illum asperiores eos qui. Quo quas reprehenderit natus ea dolor aperiam nihil. Debitis officia sit dolores quia sequi. Aliquam omnis et consequatur consequuntur. Velit blanditiis eum architecto dolor beatae. Ratione omnis quia quisquam.","","","4.14","5","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0082","$44.25","$0.00","","Sent","2021-03-25","2021-03-23","","","","0","0","","","reiciendis","Quis voluptatum laudantium ipsa. Sunt ut sed aut sequi nihil qui atque. Ducimus dolor nam et doloribus ullam est et.","","","8.85","5","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0093","$76.88","$0.00","","Sent","2021-06-15","2021-05-29","","","","0","0","","","molestiae","Perspiciatis maxime rem consequuntur nostrum minima dolore. Cum facilis saepe culpa sunt at rem. Id quis dolore deleniti voluptates quam laudantium eos.","","","9.61","8","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0094","$16.08","$0.00","","Sent","2021-07-12","2021-09-04","","","","0","0","","","minima","Quia nihil sunt quasi sint omnis maiores dicta ea. Autem exercitationem et et nisi. Animi doloremque nulla facilis nesciunt deserunt ut ipsam. Id dolores omnis temporibus in. Possimus in magni est placeat.","","","2.68","6","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0095","$8.98","$0.00","","Sent","2021-07-20","2021-03-19","","","","0","0","","","soluta","Assumenda aut inventore ad exercitationem vel nesciunt. Est sit magni veniam doloremque repudiandae eligendi eligendi. Assumenda aut dolorem eius minus et qui sapiente sed.","","","4.49","2","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0096","$41.58","$0.00","","Sent","2021-06-28","2021-04-13","","","","0","0","","","sunt","Exercitationem cupiditate pariatur neque debitis et perferendis enim. Quibusdam voluptas aut voluptatem architecto quae. Magnam blanditiis architecto quia aliquam rerum nulla doloremque. Dolores molestiae voluptas nemo aut.","","","4.62","9","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0097","$43.02","$0.00","","Sent","2021-06-09","2021-09-21","","","","0","0","","","provident","Vel libero debitis sint similique ducimus veritatis. Fuga fugit blanditiis sunt omnis consequatur distinctio dolores natus. Est ducimus mollitia accusamus sit dignissimos qui necessitatibus. Cupiditate est ratione aperiam ratione repellendus et non.","","","4.78","9","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0098","$52.60","$0.00","","Sent","2021-07-19","2021-09-30","","","","0","0","","","voluptatem","Nemo et nihil modi voluptatum ea hic.","","","5.26","10","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0099","$5.10","$0.00","","Sent","2021-09-30","2021-07-11","","","","0","0","","","qui","Et eaque inventore unde minima atque qui quia asperiores.","","","2.55","2","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0100","$6.52","$0.00","","Sent","2021-04-02","2021-05-28","","","","0","0","","","officiis","Fugit at illo voluptatem culpa dolore provident. Quo quod fuga omnis commodi. Sit a officia illo et sapiente nemo.","","","1.63","4","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0101","$18.00","$0.00","","Sent","2021-05-03","2021-09-14","","","","0","0","","","culpa","Quibusdam quo velit reprehenderit sit iusto.","","","9","2","","","","0"
|
||||
"Ms. Ivory Erdman III","nolson@example.org","0102","$9.28","$0.00","","Sent","2021-09-26","2021-04-13","","","","0","0","","","nihil","Nesciunt iusto maxime dolor necessitatibus. Eligendi dolorem placeat voluptas magni ducimus est officia. Ex delectus dolorem magnam hic. Velit soluta veritatis asperiores debitis.","","","1.16","8","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0113","$93.60","$0.00","","Sent","2021-04-05","2021-10-01","","","","0","0","","","distinctio","Optio quas quia animi dolores dolores quia optio. Excepturi ad ut nobis consectetur quia.","","","9.36","10","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0114","$31.20","$0.00","","Sent","2021-05-01","2021-06-19","","","","0","0","","","dolor","Quia optio temporibus eos sit. Aut iure velit nihil et. Aut dolores tempore dolor nisi.","","","5.2","6","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0115","$10.92","$0.00","","Sent","2021-05-29","2021-05-19","","","","0","0","","","est","Qui laudantium iure sit voluptates dolor optio. Incidunt mollitia officiis ut et qui non odio quisquam. Ut qui consequatur cum officiis maxime in. Enim assumenda vel fugit nesciunt enim ipsam consequatur.","","","1.82","6","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0116","$6.72","$0.00","","Sent","2021-04-09","2021-05-12","","","","0","0","","","eum","Quam sed dolor suscipit et consectetur nostrum. Quisquam id beatae deserunt tempore et. Laborum dolorem aut ut sed explicabo in. Et labore quia ex illo molestiae.","","","3.36","2","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0117","$23.43","$0.00","","Sent","2021-08-19","2021-07-24","","","","0","0","","","sunt","Vel ut sit qui doloribus nostrum. Eum vel sed nostrum in dolore.","","","7.81","3","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0118","$37.17","$0.00","","Sent","2021-09-08","2021-09-24","","","","0","0","","","quo","Rerum quaerat quia modi ut cum est amet.","","","5.31","7","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0119","$58.45","$0.00","","Sent","2021-07-01","2021-07-07","","","","0","0","","","deserunt","Natus accusantium excepturi omnis officiis itaque. Laborum assumenda nemo inventore minima. Et vel est qui. Alias repudiandae omnis corporis id.","","","8.35","7","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0120","$26.97","$0.00","","Sent","2021-03-31","2021-08-10","","","","0","0","","","omnis","Labore eligendi voluptate asperiores maxime aspernatur. Nam omnis quam nam ut. Voluptate quia ad incidunt sequi eos.","","","8.99","3","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0121","$21.72","$0.00","","Sent","2021-06-21","2021-04-24","","","","0","0","","","tempora","Eaque ipsa adipisci nam ea dolorem qui. Veritatis accusantium repellendus commodi vitae ut. Ut et temporibus aperiam sunt dolorem minus. Placeat perspiciatis quisquam quos assumenda unde. Accusantium adipisci et sunt iure hic.","","","7.24","3","","","","0"
|
||||
"Dr. Bella Schaefer DVM","mclaughlin.mack@example.org","0122","$24.90","$0.00","","Sent","2021-05-28","2021-09-19","","","","0","0","","","consequatur","Exercitationem minus blanditiis voluptas maxime consectetur repudiandae. Esse at sunt sequi. Vel sed officia aut et debitis libero corrupti. Eius minima voluptate corrupti quibusdam et impedit dolor.","","","4.98","5","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0133","$3.94","$0.00","","Sent","2021-08-02","2021-03-18","","","","0","0","","","nostrum","Aliquid doloremque ut doloribus neque accusamus aut.","","","1.97","2","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0134","$42.98","$0.00","","Sent","2021-03-30","2021-03-30","","","","0","0","","","at","Eos eum qui quaerat aperiam deleniti est excepturi. Et aspernatur pariatur ab id. Quia ipsam ut ut.","","","6.14","7","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0135","$22.68","$0.00","","Sent","2021-06-10","2021-03-23","","","","0","0","","","voluptatum","Nihil quaerat sed qui impedit. Tempora quo a dicta est excepturi excepturi harum. Deleniti dolor aut harum sit impedit ut.","","","3.24","7","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0136","$62.37","$0.00","","Sent","2021-04-24","2021-09-21","","","","0","0","","","et","Officiis eaque maxime rerum saepe. Rerum sit maiores ea et. Corrupti eos et soluta nobis ad quasi veritatis ut.","","","8.91","7","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0137","$85.23","$0.00","","Sent","2021-03-19","2021-08-03","","","","0","0","","","illum","Suscipit libero doloremque ut. Saepe optio dolorem amet qui reiciendis asperiores. Et iste dolorem ut et in iste. Facilis officia accusamus perferendis quo blanditiis nihil consequatur.","","","9.47","9","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0138","$2.44","$0.00","","Sent","2021-05-12","2021-04-18","","","","0","0","","","soluta","Ipsa quae impedit quisquam magnam. Quo et et ut nesciunt.","","","1.22","2","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0139","$41.60","$0.00","","Sent","2021-08-02","2021-05-01","","","","0","0","","","pariatur","Et aut a omnis quia qui esse. Impedit officiis itaque cupiditate facilis provident rem qui.","","","4.16","10","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0140","$16.95","$0.00","","Sent","2021-06-26","2021-05-10","","","","0","0","","","itaque","Aut molestiae dolor consequatur accusamus non earum hic et. Aspernatur ut nostrum aut animi ut rerum. Quis ipsum ut eveniet sequi nisi quia. Alias ut blanditiis consequuntur ut. Molestiae velit ullam iusto quia veniam aut modi.","","","5.65","3","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0141","$8.68","$0.00","","Sent","2021-09-23","2021-08-10","","","","0","0","","","aliquam","Aut sint illum fugit quos tenetur aut. Aut ea consequatur accusamus officiis error cum. Quod qui soluta fuga aut nisi. Facere ipsam eos veniam cupiditate quis tempore.","","","8.68","1","","","","0"
|
||||
"Jeramie Anderson","uhaag@example.com","0142","$1.98","$0.00","","Sent","2021-04-30","2021-05-16","","","","0","0","","","et","Delectus laudantium eius fugit tempore itaque ullam.","","","1.98","1","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0153","$23.34","$0.00","","Sent","2021-05-13","2021-03-25","","","","0","0","","","vel","Sed aut dolores earum impedit.","","","7.78","3","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0154","$19.50","$0.00","","Sent","2021-08-28","2021-07-30","","","","0","0","","","possimus","Blanditiis itaque quae atque ut tenetur quam. Eaque quis inventore dolores dolore expedita provident. Consequatur voluptatem libero voluptates qui et qui.","","","3.9","5","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0155","$41.92","$0.00","","Sent","2021-05-17","2021-07-05","","","","0","0","","","maxime","Saepe rem ad in veritatis vitae in perferendis. Explicabo ut omnis id quia iste.","","","5.24","8","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0156","$9.73","$0.00","","Sent","2021-08-31","2021-05-12","","","","0","0","","","voluptatem","Magnam nostrum quia exercitationem mollitia ipsam ipsam. Optio ad libero ullam dicta.","","","9.73","1","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0157","$16.24","$0.00","","Sent","2021-04-27","2021-04-02","","","","0","0","","","sunt","Est cupiditate recusandae voluptatum eaque reiciendis dolores ut. Minus provident molestiae veritatis nulla. Veniam perspiciatis velit sed laudantium. Sint aut quaerat vel eveniet iure neque corporis at. Animi nostrum incidunt est.","","","2.03","8","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0158","$26.13","$0.00","","Sent","2021-05-27","2021-07-31","","","","0","0","","","ea","Nihil molestias eum pariatur quas molestiae nemo ut. Hic aliquam corporis dolore praesentium incidunt impedit.","","","8.71","3","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0159","$9.61","$0.00","","Sent","2021-08-21","2021-07-12","","","","0","0","","","eveniet","Et sed et nemo non.","","","9.61","1","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0160","$14.12","$0.00","","Sent","2021-07-02","2021-05-02","","","","0","0","","","expedita","Sequi non ab aut ducimus. Quos deserunt vitae id illum. Facere non quis possimus.","","","3.53","4","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0161","$65.17","$0.00","","Sent","2021-05-02","2021-06-12","","","","0","0","","","numquam","Officiis est quisquam neque qui a odit quasi tempora.","","","9.31","7","","","","0"
|
||||
"Mr. Armand Reinger","stefan17@example.net","0162","$44.28","$0.00","","Sent","2021-04-11","2021-05-02","","","","0","0","","","natus","Doloremque reprehenderit officiis rem rerum dignissimos. Nulla quibusdam laborum omnis sunt et totam. Ab aperiam harum qui soluta.","","","7.38","6","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0173","$80.60","$0.00","","Sent","2021-04-25","2021-04-08","","","","0","0","","","ut","Alias id rem rerum dolores odit et similique.","","","8.06","10","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0174","$15.62","$0.00","","Sent","2021-07-08","2021-05-24","","","","0","0","","","voluptas","Hic recusandae libero voluptas rerum nam fuga ut. Consequatur nihil nihil aliquid ut. Doloribus itaque enim alias dolores. Optio inventore iste molestiae autem sequi. Itaque dolorum eaque qui dolorum error rerum quia.","","","7.81","2","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0175","$68.20","$0.00","","Sent","2021-08-31","2021-05-26","","","","0","0","","","sunt","Asperiores nobis eius delectus repellendus non ea esse.","","","6.82","10","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0176","$28.86","$0.00","","Sent","2021-08-23","2021-03-17","","","","0","0","","","quisquam","Rerum iste esse aperiam distinctio ut et. Suscipit voluptatem commodi eos corporis voluptates est. Error repellat vitae dolor omnis ducimus.","","","9.62","3","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0177","$69.52","$0.00","","Sent","2021-06-05","2021-05-17","","","","0","0","","","consectetur","Sit corrupti cumque quasi dolor debitis.","","","8.69","8","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0178","$61.11","$0.00","","Sent","2021-08-13","2021-05-18","","","","0","0","","","quo","Omnis facere qui praesentium. Recusandae quae omnis ut doloremque et. Ipsam eos doloribus impedit qui nemo dolorem. Esse autem distinctio esse voluptatum est dolor qui.","","","6.79","9","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0179","$47.94","$0.00","","Sent","2021-08-21","2021-07-08","","","","0","0","","","distinctio","Similique sit odio sequi nesciunt molestias earum. Sunt autem nulla et error quod nisi.","","","7.99","6","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0180","$51.18","$0.00","","Sent","2021-08-01","2021-09-11","","","","0","0","","","est","Non quia rem aut ipsa porro sed. Sapiente velit quod maxime culpa est aperiam sint. Recusandae et aut impedit necessitatibus.","","","8.53","6","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0181","$26.34","$0.00","","Sent","2021-06-22","2021-04-14","","","","0","0","","","nesciunt","Neque hic nostrum dolor quod aut quia. Impedit enim dolores et magni voluptatem nulla. Veritatis voluptates quae dolorem laudantium perferendis hic impedit.","","","8.78","3","","","","0"
|
||||
"Deja Larson","spinka.elinore@example.net","0182","$2.72","$0.00","","Sent","2021-08-29","2021-04-03","","","","0","0","","","aperiam","Qui sit id omnis quia. Culpa dolorem non voluptas possimus unde. Inventore fugit ut non officia ad vitae. A expedita autem veniam sed exercitationem.","","","1.36","2","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0193","$25.35","$0.00","","Sent","2021-09-13","2021-09-16","","","","0","0","","","sunt","Quisquam optio eum aperiam sit. Sequi sit id facilis quaerat quia. Officiis vero sunt nostrum corrupti. Molestiae omnis at vero.","","","5.07","5","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0194","$83.30","$0.00","","Sent","2021-05-18","2021-05-07","","","","0","0","","","tempore","Totam officia a molestias saepe. Sed et et facilis fuga provident sunt. Sit nemo repellendus quasi harum.","","","8.33","10","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0195","$13.20","$0.00","","Sent","2021-05-26","2021-04-18","","","","0","0","","","architecto","Quisquam vel voluptate fugiat sequi asperiores in. Nihil consequatur deleniti quaerat saepe qui veritatis omnis.","","","6.6","2","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0196","$41.58","$0.00","","Sent","2021-09-11","2021-06-17","","","","0","0","","","neque","Tempora aut ad a. Quasi nobis fugiat harum molestiae qui ipsam facilis.","","","6.93","6","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0197","$14.24","$0.00","","Sent","2021-07-17","2021-08-17","","","","0","0","","","omnis","Error rem quos exercitationem perspiciatis. Architecto unde excepturi dolorem unde architecto.","","","3.56","4","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0198","$39.12","$0.00","","Sent","2021-06-08","2021-06-07","","","","0","0","","","et","Dolores quo sed et facilis vitae. Corporis vitae placeat voluptatum nihil. Quidem error ipsum eius non temporibus enim corrupti.","","","4.89","8","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0199","$21.72","$0.00","","Sent","2021-05-11","2021-08-15","","","","0","0","","","rerum","Quod sint rerum praesentium magni. Eum quis aut quos sint illum quisquam. Fugiat fugiat dolores est.","","","5.43","4","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0200","$8.37","$0.00","","Sent","2021-03-20","2021-08-31","","","","0","0","","","rerum","Aut voluptatem reprehenderit aut cumque iure omnis. Repudiandae aut asperiores minus culpa tempore libero. Aut illo aliquam doloremque non fugit.","","","2.79","3","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0201","$31.20","$0.00","","Sent","2021-05-13","2021-09-28","","","","0","0","","","sapiente","Unde dolorem repellat esse quaerat. Qui ut ratione maiores at error nemo. Rerum rerum hic id quam consequatur voluptate in explicabo.","","","3.12","10","","","","0"
|
||||
"Tommie Prohaska","toney29@example.net","0202","$19.68","$0.00","","Sent","2021-03-22","2021-04-17","","","","0","0","","","ut","Earum voluptas veniam eum exercitationem et vel. Error distinctio ab dolor harum. Et ratione nam delectus impedit veniam.","","","9.84","2","","","","0"
|
||||
"Adam Walter","zcrooks@example.net","0206","$0.00","$0.00","","Sent","2021-09-24","","","","","0","0","","","1","11","pro field value 1","pro field val 2","0","1","","0","","0"
|
|
5
tests/Feature/Import/wave_clients.csv
Normal file
5
tests/Feature/Import/wave_clients.csv
Normal file
@ -0,0 +1,5 @@
|
||||
customer_name,email,contact_first_name,contact_last_name,customer_currency,account_number,phone,fax,mobile,toll_free,website,country,province/state,address_line_1,address_line_2,city,postal_code/zip_code,shipping_address,ship-to_contact,ship-to_country,ship-to_province/state,ship-to_address_line_1,ship-to_address_line_2,ship-to_city,ship-to_postal_code/zip_code,ship-to_phone,delivery_instructions
|
||||
Homer Simpson,homer@simpsons.com,Homer,Connery,USD,,555-875-5245,,,,http://simpsons.com/,,,1234 Tullis Street,,"Glasgow, Scotland",G1 2FF,False,,,,,,,,,
|
||||
Jessica Jones,jessica@jones.com,Jessica Jones,,AUD,,555-867-5309,,,,,Australia,Queensland,6548 Sesame Street,Apt 4,NYC,11213,False,,,,,,,,,
|
||||
Lucas Cage,luke@powerman.com,Luke Cage,Martha Stewart,BSD,,555-867-5309 x89,,,,,Bahamas,High Rock,965 Main Street,,Monroe,654123,False,,,,,,,,,
|
||||
Mark Walberg,markymark@walburger.com,Marcus,Connery,USD,,321654987,,,,,,,1234 Tullis Street,,"Glasgow, Scotland",G1 2FF,False,,,,,,,,,
|
|
26
tests/Feature/Import/wave_expenses.csv
Normal file
26
tests/Feature/Import/wave_expenses.csv
Normal file
@ -0,0 +1,26 @@
|
||||
Transaction ID,Transaction Date,Account Name,Transaction Description,Transaction Line Description,Amount (One column), ,Debit Amount (Two Column Approach),Credit Amount (Two Column Approach),Other Accounts for this Transaction,Customer,Vendor,Invoice Number,Bill Number,Notes / Memo,Amount Before Sales Tax,Sales Tax Amount,Sales Tax Name,Transaction Date Added,Transaction Date Last Modified,Account Group,Account Type,Account ID
|
||||
537537669383611013,2015-12-30,Owner Investment / Drawings,-hjj,-hjj,96.00,,,96.00,Computer – Hardware,,,,,,96.00,,,2015-12-30,2022-02-10,Equity,Business Owner Contribution and Drawing,
|
||||
537537669383611013,2015-12-30,Computer – Hardware,-hjj,-hjj,96.00,,96.00,,Owner Investment / Drawings,,,,,,96.00,,,2015-12-30,2022-02-10,Expense,Operating Expense,
|
||||
537537671069721225,2016-02-20,Cash on Hand,-,-,-20.00,,,20.00,Business Licenses & Permits,,,,,,-20.00,,,2016-02-21,2022-02-10,Asset,Cash and Bank,
|
||||
537537671069721225,2016-02-20,Business Licenses & Permits,-,-,20.00,,20.00,,Cash on Hand,,,,,,20.00,,,2016-02-21,2022-02-10,Expense,Operating Expense,
|
||||
1405423775985459539,2022-02-10,Sales,asa - 2,asa - 2 - bananas,10.00,,,10.00,"Accounts Receivable, Capitation Fees, GST",asa,,2,,,10.00,,,2022-02-10,2022-02-10,Income,Income,
|
||||
1405423775985459539,2022-02-10,Sales,asa - 2,asa - 2 - bananas,10.00,,,10.00,"Accounts Receivable, Capitation Fees, GST",asa,,2,,,10.00,,,2022-02-10,2022-02-10,Income,Income,
|
||||
1405423775985459539,2022-02-10,Capitation Fees,asa - 2,asa - 2 - Best Product Name,10.00,,,10.00,"Accounts Receivable, GST, Sales",asa,,2,,,10.00,1.00,GST,2022-02-10,2022-02-10,Income,Income,
|
||||
1405423775985459539,2022-02-10,GST,asa - 2,asa - 2 - Best Production Description,1.00,,,1.00,"Accounts Receivable, Capitation Fees, Sales",asa,,2,,,1.00,,,2022-02-10,2022-02-10,Liability,Sales Tax on Sales and Purchases,
|
||||
1405423775985459539,2022-02-10,Capitation Fees,asa - 2,asa - 2 - Best Product Name,10.00,,,10.00,"Accounts Receivable, GST, Sales",asa,,2,,,10.00,1.00,GST,2022-02-10,2022-02-10,Income,Income,
|
||||
1405423775985459539,2022-02-10,GST,asa - 2,asa - 2 - Best Production Description,1.00,,,1.00,"Accounts Receivable, Capitation Fees, Sales",asa,,2,,,1.00,,,2022-02-10,2022-02-10,Liability,Sales Tax on Sales and Purchases,
|
||||
1405423775985459539,2022-02-10,Accounts Receivable,asa - 2,asa - 2,42.00,,42.00,,"Capitation Fees, GST, Sales",asa,,2,,,42.00,,,2022-02-10,2022-02-10,Asset,System Receivable Invoice,
|
||||
1405429262361584366,2022-02-10,Computer – Hosting,Vendor Name - Bill ,Vendor Name - Bill - Best Product Name,10.00,,10.00,,"Accounts Payable, GST",,Vendor Name,,,,10.00,1.00,GST,2022-02-10,2022-02-10,Expense,Operating Expense,
|
||||
1405429262361584366,2022-02-10,GST,Vendor Name - Bill ,Vendor Name - Bill - Best Product Name,-1.00,,1.00,,"Accounts Payable, Computer – Hosting",,Vendor Name,,,,1.00,,,2022-02-10,2022-02-10,Liability,Sales Tax on Sales and Purchases,
|
||||
1405429262361584366,2022-02-10,Accounts Payable,Vendor Name - Bill ,Vendor Name - Bill ,11.00,,,11.00,"Computer – Hosting, GST",,Vendor Name,,,,11.00,,,2022-02-10,2022-02-10,Liability,System Payable Bill,
|
||||
1405437089897538538,2022-02-10,Computer – Hosting,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,200.00,,200.00,,"Accounts Payable, GST",,Vendor Name,,66,,200.00,20.00,GST,2022-02-10,2022-02-10,Expense,Operating Expense,
|
||||
1405437089897538538,2022-02-10,GST,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,-20.00,,20.00,,"Accounts Payable, Computer – Hosting",,Vendor Name,,66,,20.00,,,2022-02-10,2022-02-10,Liability,Sales Tax on Sales and Purchases,
|
||||
1405437089897538538,2022-02-10,Computer – Hosting,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,10.00,,10.00,,"Accounts Payable, GST",,Vendor Name,,66,,10.00,1.00,GST,2022-02-10,2022-02-10,Expense,Operating Expense,
|
||||
1405437089897538538,2022-02-10,GST,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,-1.00,,1.00,,"Accounts Payable, Computer – Hosting",,Vendor Name,,66,,1.00,,,2022-02-10,2022-02-10,Liability,Sales Tax on Sales and Purchases,
|
||||
1405437089897538538,2022-02-10,Computer – Hosting,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,10.00,,10.00,,"Accounts Payable, GST",,Vendor Name,,66,,10.00,1.00,GST,2022-02-10,2022-02-10,Expense,Operating Expense,
|
||||
1405437089897538538,2022-02-10,GST,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,-1.00,,1.00,,"Accounts Payable, Computer – Hosting",,Vendor Name,,66,,1.00,,,2022-02-10,2022-02-10,Liability,Sales Tax on Sales and Purchases,
|
||||
1405437089897538538,2022-02-10,Computer – Hosting,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,10.00,,10.00,,"Accounts Payable, GST",,Vendor Name,,66,,10.00,1.00,GST,2022-02-10,2022-02-10,Expense,Operating Expense,
|
||||
1405437089897538538,2022-02-10,GST,Vendor Name - Bill 66,Vendor Name - Bill 66 - Best Product Name,-1.00,,1.00,,"Accounts Payable, Computer – Hosting",,Vendor Name,,66,,1.00,,,2022-02-10,2022-02-10,Liability,Sales Tax on Sales and Purchases,
|
||||
1405437089897538538,2022-02-10,Accounts Payable,Vendor Name - Bill 66,Vendor Name - Bill 66,253.00,,,253.00,"Computer – Hosting, GST",,Vendor Name,,66,,253.00,,,2022-02-10,2022-02-10,Liability,System Payable Bill,
|
||||
1405441958066807314,2022-02-10,Accounts Payable,Bill Payment,Bill Payment,-253.00,,253.00,,Cash on Hand,,Vendor Name,,66,,-253.00,,,2022-02-10,2022-02-10,Liability,System Payable Bill,
|
||||
1405441958066807314,2022-02-10,Cash on Hand,Bill Payment,Bill Payment,-253.00,,,253.00,Accounts Payable,,,,,,-253.00,,,2022-02-10,2022-02-10,Asset,Cash and Bank,
|
|
16
tests/Feature/Import/wave_invoices.csv
Normal file
16
tests/Feature/Import/wave_invoices.csv
Normal file
@ -0,0 +1,16 @@
|
||||
Transaction ID,Transaction Date,Account Name,Transaction Description,Transaction Line Description,Amount (One column), ,Debit Amount (Two Column Approach),Credit Amount (Two Column Approach),Other Accounts for this Transaction,Customer,Vendor,Invoice Number,Bill Number,Notes / Memo,Amount Before Sales Tax,Sales Tax Amount,Sales Tax Name,Transaction Date Added,Transaction Date Last Modified,Account Group,Account Type,Account ID
|
||||
1131801267438479900,2021-01-28,Sales,Mark Walberg - 2,Mark Walberg - 2 - General Car Repair,294.00,,,294.00,"Accounts Receivable, Services",Mark Walberg,,2,,,294.00,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801267438479900,2021-01-28,Sales,Mark Walberg - 2,Mark Walberg - 2 - Hardware Supply,20.00,,,20.00,"Accounts Receivable, Services",Mark Walberg,,2,,,20.00,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801267438479900,2021-01-28,Services,Mark Walberg - 2,Mark Walberg - 2 - Lawn Service,160.00,,,160.00,"Accounts Receivable, Sales",Mark Walberg,,2,,,160.00,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801267438479900,2021-01-28,Services,Mark Walberg - 2,Mark Walberg - 2 - Product Delivery,4500.00,,,4500.00,"Accounts Receivable, Sales",Mark Walberg,,2,,,4500.00,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801267438479900,2021-01-28,Accounts Receivable,Mark Walberg - 2,Mark Walberg - 2,4974.00,,4974.00,,"Sales, Services",Mark Walberg,,2,,,4974.00,,,2021-01-28,2021-01-28,Asset,System Receivable Invoice,
|
||||
1131801934970350312,2021-01-28,Sales,Lucas Cage - 3,Lucas Cage - 3 - General Car Repair,98.00,,,98.00,"Accounts Receivable, Services",Lucas Cage,,3,,,98.00,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801934970350312,2021-01-28,Sales,Lucas Cage - 3,Lucas Cage - 3 - Hardware Supply,2.50,,,2.50,"Accounts Receivable, Services",Lucas Cage,,3,,,2.50,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801934970350312,2021-01-28,Services,Lucas Cage - 3,Lucas Cage - 3 - Lawn Service,40.00,,,40.00,"Accounts Receivable, Sales",Lucas Cage,,3,,,40.00,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801934970350312,2021-01-28,Services,Lucas Cage - 3,Lucas Cage - 3 - Product Delivery,450.00,,,450.00,"Accounts Receivable, Sales",Lucas Cage,,3,,,450.00,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131801934970350312,2021-01-28,Accounts Receivable,Lucas Cage - 3,Lucas Cage - 3,590.50,,590.50,,"Sales, Services",Lucas Cage,,3,,,590.50,,,2021-01-28,2021-01-28,Asset,System Receivable Invoice,
|
||||
1131802355113782011,2021-01-28,Accounts Receivable,Invoice Payment,Invoice Payment,-590.50,,,590.50,Cash on Hand,Lucas Cage,,3,,,-590.50,,,2021-01-28,2021-01-28,Asset,System Receivable Invoice,
|
||||
1131802355113782011,2021-01-28,Cash on Hand,Invoice Payment,Invoice Payment,590.50,,590.50,,Accounts Receivable,,,,,,590.50,,,2021-01-28,2021-01-28,Asset,Cash and Bank,
|
||||
1131802918996011960,2021-01-28,Services,Jessica Jones - 4,Jessica Jones - 4 - Lawn Service,30.84,,,30.84,"Accounts Receivable, Sales",Jessica Jones,,4,,,30.84,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131802918996011960,2021-01-28,Sales,Jessica Jones - 4,Jessica Jones - 4 - Painting Service,3469.57,,,3469.57,"Accounts Receivable, Services",Jessica Jones,,4,,,3469.57,,,2021-01-28,2021-01-28,Income,Income,
|
||||
1131802918996011960,2021-01-28,Accounts Receivable,Jessica Jones - 4,Jessica Jones - 4,3500.41,,3500.41,,"Sales, Services",Jessica Jones,,4,,,3500.41,,,2021-01-28,2021-01-28,Asset,System Receivable Invoice,
|
|
2
tests/Feature/Import/wave_vendors.csv
Normal file
2
tests/Feature/Import/wave_vendors.csv
Normal file
@ -0,0 +1,2 @@
|
||||
vendor_name,email,contact_first_name,contact_last_name,vendor_currency,account_number,phone,fax,mobile,toll_free,website,country,province/state,address_line_1,address_line_2,city,postal_code/zip_code
|
||||
Vendor Name,vendor@gmail.com,firstname,lastname,AUD,,phone,fax,mob,,,Australia,Australian Capital Territory,address1,address2,city ,postal_cod
|
|
6
tests/Feature/Import/zoho_contacts.csv
Normal file
6
tests/Feature/Import/zoho_contacts.csv
Normal file
@ -0,0 +1,6 @@
|
||||
Created Time,Last Modified Time,Display Name,Company Name,Salutation,First Name,Last Name,Phone,Currency Code,Notes,Website,Status,Credit Limit,Customer Sub Type,Billing Attention,Billing Address,Billing Street2,Billing City,Billing State,Billing Country,Billing Code,Billing Phone,Billing Fax,Shipping Attention,Shipping Address,Shipping Street2,Shipping City,Shipping State,Shipping Country,Shipping Code,Shipping Phone,Shipping Fax,Skype Identity,Facebook,Twitter,Department,Designation,Price List,Payment Terms,Payment Terms Label,Last Sync Time,Owner Name,EmailID,MobilePhone,Customer ID,Customer Name,Contact Type,Customer Address ID,Source,Reference ID,Payment Reminder
|
||||
2021-01-28 05:14:15,2021-01-28 05:16:02,Avengers,Avengers,,Thor,Odensohn,,USD,,thorodensohn.net,Active,0.000,business,,,,,,,,,,,,,,,,,,,,avengershq,avengershq,,,,0,Due on Receipt,,,thor@midgaurd.org,,2520018000000073005,Avengers,customer,2520018000000073005,1,,true
|
||||
2021-01-28 05:21:04,2021-01-28 05:21:04,Jessica Jones,Defenders,,,,888-867-5309,USD,,jesssicajonesdetective.com,Active,0.000,business,,,,,,,,,,,,,,,,,,,,jesssicajonesdetective,jesssicajonesdetective,,,,0,Due on Receipt,,,jessica@jones.net,,2520018000000073022,Jessica Jones,customer,2520018000000073022,1,,true
|
||||
2021-01-28 05:22:15,2021-01-28 05:22:15,Highlander,Highlander,Mr.,Sean,Connory,,USD,,highlander.com,Active,0.000,business,,,,,,,,,,,,,,,,,,,,highlander,highlander,,,,0,Due on Receipt,,,connory@highlander.com,,2520018000000073035,Highlander,customer,2520018000000073035,1,,true
|
||||
2021-01-28 05:23:44,2021-01-28 05:23:45,Simpsons Baking Co,Simpsons Baking Co,Mrs.,Margery,Simpson,888-567-5309,USD,,simpsonsbaking.com,Active,0.000,business,,,,,,,,,,,,,,,,,,,,simpsonsbaking,simpsonsbaking,,,,30,Net 30,,,marge@simpsonsbaking.com,,2520018000000073048,Simpsons Baking Co,customer,2520018000000073048,1,,true
|
||||
2021-01-28 05:24:53,2021-01-28 05:24:54,Defenders,Defenders,Mr.,Lucas,Cage,888-867-5309,USD,,cagepowerman.net,Active,0.000,individual,,,,,,,,,,,,,,,,,,,,cagepowerman,cagepowerman,,,,15,Net 15,,,lucas@powerman.com,98754321,2520018000000073061,Defenders,customer,2520018000000073061,1,,true
|
|
14
tests/Feature/Import/zoho_invoices.csv
Normal file
14
tests/Feature/Import/zoho_invoices.csv
Normal file
@ -0,0 +1,14 @@
|
||||
Invoice Date,Invoice ID,Invoice Number,Estimate Number,Invoice Status,Customer Name,Company Name,Customer ID,Branch ID,Branch Name,Due Date,Expected Payment Date,PurchaseOrder,Template Name,Currency Code,Exchange Rate,Discount Type,Is Discount Before Tax,Entity Discount Percent,Entity Discount Amount,Item Name,Item Desc,Quantity,Usage unit,Item Price,Discount,Discount Amount,Expense Reference ID,Project ID,Project Name,Item Total,SubTotal,Total,Balance,Shipping Charge,Adjustment,Adjustment Description,Round Off,Sales person,Payment Terms,Payment Terms Label,Last Payment Date,Notes,Terms & Conditions,Subject,LateFee Name,LateFee Type,LateFee Rate,LateFee Amount,LateFee Frequency,WriteOff Date,WriteOff Exchange Rate,WriteOff Amount,Recurrence Name,PayPal,Authorize.Net,Google Checkout,Payflow Pro,Stripe,2Checkout,Braintree,Forte,WorldPay,Payments Pro,Square,WePay,Razorpay,GoCardless,Partial Payments,Billing Address,Billing City,Billing State,Billing Country,Billing Code,Billing Fax,Billing Phone,Shipping Address,Shipping City,Shipping State,Shipping Country,Shipping Code,Shipping Fax,Shipping Phone Number
|
||||
2021-01-28,2520018000000073144,INV-000001,,Draft,Highlander,Highlander,2520018000000073035,,,2021-01-28,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,Hardware Supply,Wood Hammer Mallets,6.00,,4.25,0.00,0.000,,,,25.50,489.75,489.75,489.75,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073144,INV-000001,,Draft,Highlander,Highlander,2520018000000073035,,,2021-01-28,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,Hardware Supply,Wood Hammer Mallets,1.00,,4.25,0.00,0.000,,,,4.25,489.75,489.75,489.75,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073144,INV-000001,,Draft,Highlander,Highlander,2520018000000073035,,,2021-01-28,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,General Car Repair,Bumper paint touch up,4.00,,45.00,0.00,0.000,,,,180.00,489.75,489.75,489.75,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073144,INV-000001,,Draft,Highlander,Highlander,2520018000000073035,,,2021-01-28,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,Website Analysis,Routine SEO site monitoring,2.00,,140.00,0.00,0.000,,,,280.00,489.75,489.75,489.75,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073164,INV-000002,,Draft,Jessica Jones,Defenders,2520018000000073022,,,2021-01-28,,654,Standard Template,USD,1.00,item_level,true,0.00,0.0,Hardware Supply,Wood Hammer Mallets,5.00,,4.25,0.00,0.000,,,,21.25,460.00,460.00,460.00,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,Lawn Service,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073164,INV-000002,,Draft,Jessica Jones,Defenders,2520018000000073022,,,2021-01-28,,654,Standard Template,USD,1.00,item_level,true,0.00,0.0,Hardware Supply,Wood Hammer Mallets,6.00,,4.25,0.00,0.000,,,,25.50,460.00,460.00,460.00,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,Lawn Service,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073164,INV-000002,,Draft,Jessica Jones,Defenders,2520018000000073022,,,2021-01-28,,654,Standard Template,USD,1.00,item_level,true,0.00,0.0,Product Delivery,Trucking Logistics,7.00,,25.00,0.00,0.000,,,,175.00,460.00,460.00,460.00,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,Lawn Service,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073164,INV-000002,,Draft,Jessica Jones,Defenders,2520018000000073022,,,2021-01-28,,654,Standard Template,USD,1.00,item_level,true,0.00,0.0,Hardware Supply,Wood Hammer Mallets,9.00,,4.25,0.00,0.000,,,,38.25,460.00,460.00,460.00,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,Lawn Service,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073164,INV-000002,,Draft,Jessica Jones,Defenders,2520018000000073022,,,2021-01-28,,654,Standard Template,USD,1.00,item_level,true,0.00,0.0,Product Delivery,Trucking Logistics,8.00,,25.00,0.00,0.000,,,,200.00,460.00,460.00,460.00,0.00,0.00,Adjustment,0.00,,0,Due on Receipt,,Thanks for your business.,,Lawn Service,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073182,INV-000003,,Draft,Simpsons Baking Co,Simpsons Baking Co,2520018000000073048,,,2021-02-27,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,General Car Repair,Bumper paint touch up,1.00,,45.00,0.00,0.000,,,,45.00,390.00,390.00,390.00,0.00,0.00,Adjustment,0.00,,30,Net 30,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073182,INV-000003,,Draft,Simpsons Baking Co,Simpsons Baking Co,2520018000000073048,,,2021-02-27,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,Painting Service,25 hours painting,1.00,,25.00,0.00,0.000,,,,25.00,390.00,390.00,390.00,0.00,0.00,Adjustment,0.00,,30,Net 30,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073182,INV-000003,,Draft,Simpsons Baking Co,Simpsons Baking Co,2520018000000073048,,,2021-02-27,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,Website Analysis,Routine SEO site monitoring,1.00,,140.00,0.00,0.000,,,,140.00,390.00,390.00,390.00,0.00,0.00,Adjustment,0.00,,30,Net 30,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
||||
2021-01-28,2520018000000073182,INV-000003,,Draft,Simpsons Baking Co,Simpsons Baking Co,2520018000000073048,,,2021-02-27,,,Standard Template,USD,1.00,item_level,true,0.00,0.0,Website Design,New page design,1.00,,180.00,0.00,0.000,,,,180.00,390.00,390.00,390.00,0.00,0.00,Adjustment,0.00,,30,Net 30,,Thanks for your business.,,,,% of Invoice,0.00,0.00,Every Month,,1.00,0.00,,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,,,,,,,,,,,,,,
|
|
@ -41,6 +41,147 @@ class VendorApiTest extends TestCase
|
||||
Model::reguard();
|
||||
}
|
||||
|
||||
public function testAddVendorToInvoice()
|
||||
{
|
||||
$data = [
|
||||
'name' => $this->faker->firstName,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/vendors', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
$vendor_id =$arr['data']['id'];
|
||||
|
||||
$data = [
|
||||
'vendor_id' => $vendor_id,
|
||||
'client_id' => $this->client->hashed_id
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/invoices', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals($arr['data']['vendor_id'], $vendor_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function testAddVendorToRecurringInvoice()
|
||||
{
|
||||
$data = [
|
||||
'name' => $this->faker->firstName,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/vendors', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
$vendor_id = $arr['data']['id'];
|
||||
|
||||
$data = [
|
||||
'vendor_id' => $vendor_id,
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'frequency_id' => 1,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/recurring_invoices', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals($arr['data']['vendor_id'], $vendor_id);
|
||||
|
||||
}
|
||||
|
||||
public function testAddVendorToQuote()
|
||||
{
|
||||
$data = [
|
||||
'name' => $this->faker->firstName,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/vendors', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
$vendor_id =$arr['data']['id'];
|
||||
|
||||
$data = [
|
||||
'vendor_id' => $vendor_id,
|
||||
'client_id' => $this->client->hashed_id
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/quotes', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals($arr['data']['vendor_id'], $vendor_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function testAddVendorToCredit()
|
||||
{
|
||||
$data = [
|
||||
'name' => $this->faker->firstName,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/vendors', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
$vendor_id =$arr['data']['id'];
|
||||
|
||||
$data = [
|
||||
'vendor_id' => $vendor_id,
|
||||
'client_id' => $this->client->hashed_id
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/credits', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals($arr['data']['vendor_id'], $vendor_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testVendorPost()
|
||||
{
|
||||
$data = [
|
||||
|
@ -233,6 +233,8 @@ trait MockAccountData
|
||||
$user_id = $user->id;
|
||||
$this->user = $user;
|
||||
|
||||
// auth()->login($user);
|
||||
|
||||
CreateCompanyTaskStatuses::dispatchNow($this->company, $this->user);
|
||||
|
||||
$this->cu = CompanyUserFactory::create($user->id, $this->company->id, $this->account->id);
|
||||
|
1
webpack.mix.js
vendored
1
webpack.mix.js
vendored
@ -154,6 +154,7 @@ mix.js("resources/js/app.js", "public/js")
|
||||
"public/js/clients/payments/stripe-fpx.js")
|
||||
|
||||
mix.copyDirectory('node_modules/card-js/card-js.min.css', 'public/css/card-js.min.css');
|
||||
mix.copyDirectory('node_modules/clipboard/dist/clipboard.min.js', 'public/vendor/clipboard.min.js');
|
||||
|
||||
mix.sass("resources/sass/app.scss", "public/css")
|
||||
.options({
|
||||
|
Loading…
x
Reference in New Issue
Block a user