diff --git a/app/Http/Controllers/PaymentApiController.php b/app/Http/Controllers/PaymentApiController.php index b271d4c99996..2d4d45fa788c 100644 --- a/app/Http/Controllers/PaymentApiController.php +++ b/app/Http/Controllers/PaymentApiController.php @@ -90,8 +90,8 @@ class PaymentApiController extends BaseAPIController $invoice = Invoice::scope($data['invoice_id'])->with('client')->first(); if ($invoice) { - $data['invoice'] = $invoice->public_id; - $data['client'] = $invoice->client->public_id; + $data['invoice_id'] = $invoice->id; + $data['client_id'] = $invoice->client->id; } else { $error = trans('validation.not_in', ['attribute' => 'invoice_id']); } diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 61e8487f53c5..989a4649174e 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -542,6 +542,8 @@ class PaymentController extends BaseController public function store(CreatePaymentRequest $request) { $input = $request->input(); + $input['invoice_id'] = Invoice::getPrivateId($input['invoice']); + $input['client_id'] = Client::getPrivateId($input['client']); $payment = $this->paymentRepo->save($input); if (Input::get('email_receipt')) { diff --git a/app/Http/Middleware/StartupCheck.php b/app/Http/Middleware/StartupCheck.php index 5bc4d543204a..efb40004b89b 100644 --- a/app/Http/Middleware/StartupCheck.php +++ b/app/Http/Middleware/StartupCheck.php @@ -75,11 +75,11 @@ class StartupCheck 'releases_link' => link_to(RELEASES_URL, 'Invoice Ninja', ['target' => '_blank']), ]; Session::put('news_feed_id', NEW_VERSION_AVAILABLE); - Session::put('news_feed_message', trans('texts.new_version_available', $params)); + Session::flash('news_feed_message', trans('texts.new_version_available', $params)); } else { Session::put('news_feed_id', $data->id); if ($data->message && $data->id > Auth::user()->news_feed_id) { - Session::put('news_feed_message', $data->message); + Session::flash('news_feed_message', $data->message); } } } else { diff --git a/app/Ninja/Import/Harvest/ClientTransformer.php b/app/Ninja/Import/Harvest/ClientTransformer.php new file mode 100644 index 000000000000..44b66f227e8c --- /dev/null +++ b/app/Ninja/Import/Harvest/ClientTransformer.php @@ -0,0 +1,21 @@ +client_name])) { + return false; + } + + return new Item($data, function ($data) use ($maps) { + return [ + 'name' => $data->client_name, + ]; + }); + } +} diff --git a/app/Ninja/Import/Harvest/ContactTransformer.php b/app/Ninja/Import/Harvest/ContactTransformer.php new file mode 100644 index 000000000000..5e5dd68909d7 --- /dev/null +++ b/app/Ninja/Import/Harvest/ContactTransformer.php @@ -0,0 +1,27 @@ +client])) { + $data->client_id = $maps[ENTITY_CLIENT][$data->client]; + } else { + return false; + } + + return new Item($data, function ($data) use ($maps) { + return [ + 'client_id' => $data->client_id, + 'first_name' => $data->first_name, + 'last_name' => $data->last_name, + 'email' => $data->email, + 'phone' => $data->office_phone ?: $data->mobile_phone, + ]; + }); + } +} diff --git a/app/Ninja/Import/Harvest/InvoiceTransformer.php b/app/Ninja/Import/Harvest/InvoiceTransformer.php new file mode 100644 index 000000000000..cc9ece282f1b --- /dev/null +++ b/app/Ninja/Import/Harvest/InvoiceTransformer.php @@ -0,0 +1,44 @@ +id])) { + return false; + } + + if (isset($maps[ENTITY_CLIENT][$data->client])) { + $data->client_id = $maps[ENTITY_CLIENT][$data->client]; + } else { + return false; + } + + return new Item($data, function ($data) use ($maps) { + + $invoiceDate = DateTime::createFromFormat('m/d/Y', $data->issue_date); + + return [ + 'invoice_number' => $data->id, + 'paid' => (float) $data->paid_amount, + 'client_id' => (int) $data->client_id, + 'po_number' => $data->po_number, + 'invoice_date_sql' => $invoiceDate->format('Y-m-d'), + 'tax_rate' => $data->tax ?: null, + 'tax_name' => $data->tax ? trans('texts.tax') : null, + 'invoice_items' => [ + [ + 'notes' => $data->subject, + 'cost' => (float) $data->invoice_amount, + 'qty' => 1, + ] + ], + ]; + }); + } +} \ No newline at end of file diff --git a/app/Ninja/Import/Harvest/PaymentTransformer.php b/app/Ninja/Import/Harvest/PaymentTransformer.php new file mode 100644 index 000000000000..78cca42a54a1 --- /dev/null +++ b/app/Ninja/Import/Harvest/PaymentTransformer.php @@ -0,0 +1,23 @@ +last_payment_date); + + return [ + 'amount' => $data->paid_amount, + 'payment_date_sql' => $paymentDate ? $paymentDate->format('Y-m-d') : null, + 'client_id' => $data->client_id, + 'invoice_id' => $data->invoice_id, + ]; + }); + } +} \ No newline at end of file diff --git a/app/Ninja/Repositories/ClientRepository.php b/app/Ninja/Repositories/ClientRepository.php index 446aec8a6f05..58b4bc09b37b 100644 --- a/app/Ninja/Repositories/ClientRepository.php +++ b/app/Ninja/Repositories/ClientRepository.php @@ -75,6 +75,10 @@ class ClientRepository extends BaseRepository $client->fill($data); $client->save(); + if ( ! isset($data['contact']) && ! isset($data['contacts'])) { + return $client; + } + $first = true; $contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts']; $contactIds = []; diff --git a/app/Ninja/Repositories/ContactRepository.php b/app/Ninja/Repositories/ContactRepository.php new file mode 100644 index 000000000000..49b73e91a664 --- /dev/null +++ b/app/Ninja/Repositories/ContactRepository.php @@ -0,0 +1,26 @@ +send_invoice = true; + $contact->client_id = $data['client_id']; + $contact->is_primary = Contact::scope()->where('client_id', '=', $contact->client_id)->count() == 0; + } else { + $contact = Contact::scope($publicId)->firstOrFail(); + } + + $contact->fill($data); + $contact->save(); + + return $contact; + } +} \ No newline at end of file diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index a6eb69a43036..99597dd24634 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -253,9 +253,9 @@ class InvoiceRepository extends BaseRepository $invoice->end_date = null; } - $invoice->terms = trim($data['terms']) ? trim($data['terms']) : (!$publicId && $account->invoice_terms ? $account->invoice_terms : ''); + $invoice->terms = (isset($data['terms']) && trim($data['terms'])) ? trim($data['terms']) : (!$publicId && $account->invoice_terms ? $account->invoice_terms : ''); $invoice->invoice_footer = (isset($data['invoice_footer']) && trim($data['invoice_footer'])) ? trim($data['invoice_footer']) : (!$publicId && $account->invoice_footer ? $account->invoice_footer : ''); - $invoice->public_notes = trim($data['public_notes']); + $invoice->public_notes = isset($data['public_notes']) ? trim($data['public_notes']) : null; // process date variables $invoice->terms = Utils::processVariables($invoice->terms); diff --git a/app/Ninja/Repositories/PaymentRepository.php b/app/Ninja/Repositories/PaymentRepository.php index e0f4ba10ef58..a080dd89c3d9 100644 --- a/app/Ninja/Repositories/PaymentRepository.php +++ b/app/Ninja/Repositories/PaymentRepository.php @@ -142,7 +142,7 @@ class PaymentRepository extends BaseRepository } if (!$publicId) { - $clientId = Client::getPrivateId(isset($input['client_id']) ? $input['client_id'] : $input['client']); + $clientId = $input['client_id']; $amount = Utils::parseFloat($input['amount']); if ($paymentTypeId == PAYMENT_TYPE_CREDIT) { @@ -159,11 +159,9 @@ class PaymentRepository extends BaseRepository } } + $payment->invoice_id = $input['invoice_id']; $payment->client_id = $clientId; $payment->amount = $amount; - - $invoicePublicId = isset($input['invoice_id']) ? $input['invoice_id'] : $input['invoice']; - $payment->invoice_id = Invoice::getPrivateId($invoicePublicId); } $payment->save(); diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php index 796c9815debe..49b80ad32e16 100644 --- a/app/Services/ImportService.php +++ b/app/Services/ImportService.php @@ -9,6 +9,7 @@ use parsecsv; use Session; use Validator; use League\Fractal\Manager; +use App\Ninja\Repositories\ContactRepository; use App\Ninja\Repositories\ClientRepository; use App\Ninja\Repositories\InvoiceRepository; use App\Ninja\Repositories\PaymentRepository; @@ -21,9 +22,11 @@ class ImportService protected $transformer; protected $invoiceRepo; protected $clientRepo; + protected $contactRepo; public static $entityTypes = [ ENTITY_CLIENT, + ENTITY_CONTACT, ENTITY_INVOICE, ENTITY_TASK, ]; @@ -31,7 +34,7 @@ class ImportService public static $sources = [ IMPORT_CSV, IMPORT_FRESHBOOKS, - //IMPORT_HARVEST, + IMPORT_HARVEST, //IMPORT_HIVEAGE, //IMPORT_INVOICEABLE, //IMPORT_NUTCACHE, @@ -40,7 +43,7 @@ class ImportService //IMPORT_ZOHO, ]; - public function __construct(Manager $manager, ClientRepository $clientRepo, InvoiceRepository $invoiceRepo, PaymentRepository $paymentRepo) + public function __construct(Manager $manager, ClientRepository $clientRepo, InvoiceRepository $invoiceRepo, PaymentRepository $paymentRepo, ContactRepository $contactRepo) { $this->fractal = $manager; $this->fractal->setSerializer(new ArraySerializer()); @@ -48,6 +51,7 @@ class ImportService $this->clientRepo = $clientRepo; $this->invoiceRepo = $invoiceRepo; $this->paymentRepo = $paymentRepo; + $this->contactRepo = $contactRepo; } public function import($source, $files) @@ -97,16 +101,18 @@ class ImportService $data['invoice_number'] = $account->getNextInvoiceNumber($invoice); } - if ($this->validate($data, $entityType) !== true) { + if ($this->validate($source, $data, $entityType) !== true) { return; } $entity = $this->{"{$entityType}Repo"}->save($data); // if the invoice is paid we'll also create a payment record - if ($entityType === ENTITY_INVOICE && isset($row->paid) && $row->paid) { - $this->createPayment($source, $row, $maps, $data['client_id'], $entity->public_id); + if ($entityType === ENTITY_INVOICE && isset($data['paid']) && $data['paid']) { + $this->createPayment($source, $row, $maps, $data['client_id'], $entity->id); } + + return $entity; } private function checkData($entityType, $count) @@ -149,9 +155,10 @@ class ImportService } } - private function validate($data, $entityType) + private function validate($source, $data, $entityType) { - if ($entityType === ENTITY_CLIENT) { + // Harvest's contacts are listed separately + if ($entityType === ENTITY_CLIENT && $source != IMPORT_HARVEST) { $rules = [ 'contacts' => 'valid_contacts', ]; @@ -183,13 +190,13 @@ class ImportService $clientMap = []; $clients = $this->clientRepo->all(); foreach ($clients as $client) { - $clientMap[$client->name] = $client->public_id; + $clientMap[$client->name] = $client->id; } $invoiceMap = []; $invoices = $this->invoiceRepo->all(); foreach ($invoices as $invoice) { - $invoiceMap[$invoice->invoice_number] = $invoice->public_id; + $invoiceMap[$invoice->invoice_number] = $invoice->id; } $countryMap = []; diff --git a/resources/views/accounts/import_export.blade.php b/resources/views/accounts/import_export.blade.php index 92f3c231508f..edb9ee60234b 100644 --- a/resources/views/accounts/import_export.blade.php +++ b/resources/views/accounts/import_export.blade.php @@ -4,6 +4,7 @@ @parent