mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-05 18:52:44 +01:00
Bug fixes; add support for other platform imports
This commit is contained in:
parent
ac99b0039d
commit
ff27f351c7
@ -30,7 +30,7 @@ class ImportRequest extends Request
|
||||
return [
|
||||
'import_type' => 'required',
|
||||
'files' => 'required_without:hash|array|min:1|max:6',
|
||||
'hash' => 'required|string',
|
||||
'hash' => 'nullable|string',
|
||||
'column_map' => 'required_with:hash|array',
|
||||
'skip_header' => 'required_with:hash|boolean',
|
||||
'files.*' => 'file|mimes:csv,txt',
|
||||
|
51
app/Import/Definitions/ExpenseMap.php
Normal file
51
app/Import/Definitions/ExpenseMap.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Definitions;
|
||||
|
||||
class ExpenseMap
|
||||
{
|
||||
public static function importable()
|
||||
{
|
||||
return [
|
||||
0 => 'expense.vendor',
|
||||
1 => 'expense.client',
|
||||
2 => 'expense.project',
|
||||
3 => 'expense.category',
|
||||
4 => 'expense.amount',
|
||||
5 => 'expense.currency',
|
||||
6 => 'expense.date',
|
||||
7 => 'expense.payment_type',
|
||||
8 => 'expense.payment_date',
|
||||
9 => 'expense.transaction_reference',
|
||||
10 => 'expense.public_notes',
|
||||
11 => 'expense.private_notes',
|
||||
];
|
||||
}
|
||||
|
||||
public static function import_keys()
|
||||
{
|
||||
return [
|
||||
0 => 'texts.vendor',
|
||||
1 => 'texts.client',
|
||||
2 => 'texts.project',
|
||||
3 => 'texts.category',
|
||||
4 => 'texts.amount',
|
||||
5 => 'texts.currency',
|
||||
6 => 'texts.date',
|
||||
7 => 'texts.payment_type',
|
||||
8 => 'texts.payment_date',
|
||||
9 => 'texts.transaction_reference',
|
||||
10 => 'texts.public_notes',
|
||||
11 => 'texts.private_notes',
|
||||
];
|
||||
}
|
||||
}
|
61
app/Import/Definitions/VendorMap.php
Normal file
61
app/Import/Definitions/VendorMap.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Definitions;
|
||||
|
||||
class VendorMap
|
||||
{
|
||||
public static function importable()
|
||||
{
|
||||
return [
|
||||
0 => 'vendor.name',
|
||||
1 => 'vendor.phone',
|
||||
2 => 'vendor.id_number',
|
||||
3 => 'vendor.vat_number',
|
||||
4 => 'vendor.website',
|
||||
5 => 'vendor.first_name',
|
||||
6 => 'vendor.last_name',
|
||||
7 => 'vendor.email',
|
||||
8 => 'vendor.currency_id',
|
||||
9 => 'vendor.public_notes',
|
||||
10 => 'vendor.private_notes',
|
||||
11 => 'vendor.address1',
|
||||
12 => 'vendor.address2',
|
||||
13 => 'vendor.city',
|
||||
14 => 'vendor.state',
|
||||
15 => 'vendor.postal_code',
|
||||
16 => 'vendor.country_id',
|
||||
];
|
||||
}
|
||||
|
||||
public static function import_keys()
|
||||
{
|
||||
return [
|
||||
0 => 'texts.name',
|
||||
1 => 'texts.phone',
|
||||
2 => 'texts.id_number',
|
||||
3 => 'texts.vat_number',
|
||||
4 => 'texts.website',
|
||||
5 => 'texts.first_name',
|
||||
6 => 'texts.last_name',
|
||||
7 => 'texts.email',
|
||||
8 => 'texts.currency',
|
||||
9 => 'texts.public_notes',
|
||||
10 => 'texts.private_notes',
|
||||
11 => 'texts.address1',
|
||||
12 => 'texts.address2',
|
||||
13 => 'texts.city',
|
||||
14 => 'texts.state',
|
||||
15 => 'texts.postal_code',
|
||||
16 => 'texts.country',
|
||||
];
|
||||
}
|
||||
}
|
6
app/Import/ImportException.php
Normal file
6
app/Import/ImportException.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace App\Import;
|
||||
|
||||
class ImportException extends \Exception{
|
||||
|
||||
}
|
@ -53,41 +53,32 @@ class BaseTransformer
|
||||
return (isset($data[$field]) && $data[$field]) ? $data[$field] : '1';
|
||||
}
|
||||
|
||||
public function getCurrencyByCode($data)
|
||||
{
|
||||
$code = array_key_exists('client.currency_id', $data) ? $data['client.currency_id'] : false;
|
||||
public function getCurrencyByCode( $data, $key = 'client.currency_id' ) {
|
||||
$code = array_key_exists( $key, $data ) ? $data[ $key ] : false;
|
||||
|
||||
if ($code) {
|
||||
$currency = $this->maps['currencies']->where('code', $code)->first();
|
||||
return $this->maps['currencies'][ $code ] ?? $this->maps['company']->settings->currency_id;
|
||||
}
|
||||
|
||||
if ($currency) {
|
||||
return $currency->id;
|
||||
}
|
||||
}
|
||||
public function getClient($client_name, $client_email) {
|
||||
$clients = $this->maps['company']->clients;
|
||||
|
||||
return $this->maps['company']->settings->currency_id;
|
||||
}
|
||||
$clients = $clients->where( 'name', $client_name );
|
||||
|
||||
public function getClient($client_name, $client_email)
|
||||
{
|
||||
$clients = $this->maps['company']->clients;
|
||||
if ( $clients->count() >= 1 ) {
|
||||
return $clients->first()->id;
|
||||
}
|
||||
|
||||
$clients = $clients->where('name', $client_name);
|
||||
if ( ! empty( $client_email ) ) {
|
||||
$contacts = ClientContact::where( 'company_id', $this->maps['company']->id )
|
||||
->where( 'email', $client_email );
|
||||
|
||||
if ($clients->count() >= 1) {
|
||||
return $clients->first()->id;
|
||||
}
|
||||
if ( $contacts->count() >= 1 ) {
|
||||
return $contacts->first()->client_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$contacts = ClientContact::where('company_id', $this->maps['company']->id)
|
||||
->where('email', $client_email);
|
||||
|
||||
if ($contacts->count() >=1) {
|
||||
return $contacts->first()->client_id;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -101,7 +92,7 @@ class BaseTransformer
|
||||
{
|
||||
$name = trim(strtolower($name));
|
||||
|
||||
return isset($this->maps[ENTITY_CLIENT][$name]);
|
||||
return isset( $this->maps['client'][ $name ] );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,7 +104,7 @@ class BaseTransformer
|
||||
{
|
||||
$name = trim(strtolower($name));
|
||||
|
||||
return isset($this->maps[ENTITY_VENDOR][$name]);
|
||||
return isset( $this->maps['vendor'][ $name ] );
|
||||
}
|
||||
|
||||
|
||||
@ -126,7 +117,7 @@ class BaseTransformer
|
||||
{
|
||||
$key = trim(strtolower($key));
|
||||
|
||||
return isset($this->maps[ENTITY_PRODUCT][$key]);
|
||||
return isset( $this->maps['product'][ $key ] );
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +158,7 @@ class BaseTransformer
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return isset($this->maps[ENTITY_CLIENT][$name]) ? $this->maps[ENTITY_CLIENT][$name] : null;
|
||||
return isset( $this->maps['client'][ $name ] ) ? $this->maps['client'][ $name ] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,7 +313,7 @@ class BaseTransformer
|
||||
*/
|
||||
public function getInvoiceNumber($number)
|
||||
{
|
||||
return $number ? str_pad(trim($number), 4, '0', STR_PAD_LEFT) : null;
|
||||
return $number ? ltrim( trim( $number ), '0' ) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -334,7 +325,8 @@ class BaseTransformer
|
||||
{
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
return isset($this->maps[ENTITY_INVOICE][$invoiceNumber]) ? $this->maps[ENTITY_INVOICE][$invoiceNumber] : null;
|
||||
|
||||
return isset( $this->maps['invoice'][ $invoiceNumber ] ) ? $this->maps['invoice'][ $invoiceNumber ] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,7 +338,8 @@ class BaseTransformer
|
||||
{
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
return isset($this->maps['invoices'][$invoiceNumber]) ? $this->maps['invoices'][$invoiceNumber]->public_id : null;
|
||||
|
||||
return isset( $this->maps['invoice'][ $invoiceNumber ] ) ? $this->maps['invoices'][ $invoiceNumber ]->public_id : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -359,7 +352,7 @@ class BaseTransformer
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
|
||||
return isset($this->maps[ENTITY_INVOICE][$invoiceNumber]);
|
||||
return $this->maps['invoice'][ $invoiceNumber ] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -372,7 +365,7 @@ class BaseTransformer
|
||||
$invoiceNumber = $this->getInvoiceNumber($invoiceNumber);
|
||||
$invoiceNumber = strtolower($invoiceNumber);
|
||||
|
||||
return isset($this->maps[ENTITY_INVOICE.'_'.ENTITY_CLIENT][$invoiceNumber]) ? $this->maps[ENTITY_INVOICE.'_'.ENTITY_CLIENT][$invoiceNumber] : null;
|
||||
return $this->maps['invoice_client'][ $invoiceNumber ] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -384,18 +377,39 @@ class BaseTransformer
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
|
||||
return isset($this->maps[ENTITY_VENDOR][$name]) ? $this->maps[ENTITY_VENDOR][$name] : null;
|
||||
return $this->maps['vendor'][ $name ] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getExpenseCategoryId($name)
|
||||
{
|
||||
$name = strtolower(trim($name));
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getExpenseCategoryId( $name ) {
|
||||
$name = strtolower( trim( $name ) );
|
||||
|
||||
return isset($this->maps[ENTITY_EXPENSE_CATEGORY][$name]) ? $this->maps[ENTITY_EXPENSE_CATEGORY][$name] : null;
|
||||
}
|
||||
return $this->maps['expense_category'][ $name ] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getProjectId( $name ) {
|
||||
$name = strtolower( trim( $name ) );
|
||||
|
||||
return $this->maps['project'][ $name ] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getPaymentTypeId( $name ) {
|
||||
$name = strtolower( trim( $name ) );
|
||||
|
||||
return $this->maps['payment_type'][ $name ] ?? null;
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,9 @@
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
@ -21,18 +22,18 @@ class ClientTransformer extends BaseTransformer
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
if (isset($data->name) && $this->hasClient($data->name)) {
|
||||
return false;
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
$settings = new \stdClass;
|
||||
$settings->currency_id = (string)$this->getCurrencyByCode($data);
|
||||
$settings->currency_id = (string)$this->getCurrencyByCode($data);
|
||||
|
||||
return [
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString( $data, 'client.name' ),
|
||||
'work_phone' => $this->getString( $data, 'client.phone' ),
|
||||
@ -71,8 +72,8 @@ class ClientTransformer extends BaseTransformer
|
||||
'custom_value4' => $this->getString( $data, 'contact.custom4' ),
|
||||
],
|
||||
],
|
||||
'country_id' => isset( $data->country_id ) ? $this->getCountryId( $data->country_id ) : null,
|
||||
'shipping_country_id' => isset( $data->shipping_country_id ) ? $this->getCountryId( $data->shipping_country_id ) : null,
|
||||
'country_id' => isset( $data['client.country'] ) ? $this->getCountryId( $data['client.country']) : null,
|
||||
'shipping_country_id' => isset($data['client.shipping_country'] ) ? $this->getCountryId( $data['client.shipping_country'] ) : null,
|
||||
];
|
||||
}
|
||||
}
|
36
app/Import/Transformers/Csv/ExpenseTransformer.php
Normal file
36
app/Import/Transformers/Csv/ExpenseTransformer.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class ExpenseTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
$clientId = isset( $data['expense.client'] ) ? $this->getClientId( $data['expense.client'] ) : null;
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'amount' => $this->getFloat( $data, 'expense.amount' ),
|
||||
'currency_id' => $this->getCurrencyByCode( $data, 'expense.currency_id' ),
|
||||
'vendor_id' => isset( $data['expense.vendor'] ) ? $this->getVendorId( $data['expense.vendor'] ) : null,
|
||||
'client_id' => isset( $data['expense.client'] ) ? $this->getClientId( $data['expense.client'] ) : null,
|
||||
'expense_date' => isset( $data['expense.date'] ) ? date( 'Y-m-d', strtotime( $data['expense.date'] ) ) : null,
|
||||
'public_notes' => $this->getString( $data, 'expense.public_notes' ),
|
||||
'private_notes' => $this->getString( $data, 'expense.private_notes' ),
|
||||
'expense_category_id' => isset( $data['expense.category'] ) ? $this->getExpenseCategoryId( $data['expense.category'] ) : null,
|
||||
'project_id' => isset( $data['expense.project'] ) ? $this->getProjectId( $data['expense.project'] ) : null,
|
||||
'payment_type_id' => isset( $data['expense.payment_type'] ) ? $this->getPaymentTypeId( $data['expense.payment_type'] ) : null,
|
||||
'payment_date' => isset( $data['expense.payment_date'] ) ? date( 'Y-m-d', strtotime( $data['expense.payment_date'] ) ) : null,
|
||||
'transaction_reference' => $this->getString( $data, 'expense.transaction_reference' ),
|
||||
'should_be_invoiced' => $clientId ? true : false,
|
||||
];
|
||||
}
|
||||
}
|
131
app/Import/Transformers/Csv/InvoiceTransformer.php
Normal file
131
app/Import/Transformers/Csv/InvoiceTransformer.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $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' );
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
'draft' => Invoice::STATUS_DRAFT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString( $invoice_data, 'invoice.number' ),
|
||||
'user_id' => $this->getString( $invoice_data, 'invoice.user_id' ),
|
||||
'amount' => $amount = $this->getFloat( $invoice_data, 'invoice.amount' ),
|
||||
'balance' => isset( $invoice_data['invoice.balance'] ) ? $this->getFloat( $invoice_data, 'invoice.balance' ) : $amount,
|
||||
'client_id' => $this->getClient( $this->getString( $invoice_data, 'client.name' ), $this->getString( $invoice_data, 'client.email' ) ),
|
||||
'discount' => $this->getFloat( $invoice_data, 'invoice.discount' ),
|
||||
'po_number' => $this->getString( $invoice_data, 'invoice.po_number' ),
|
||||
'date' => isset( $invoice_data['invoice.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['invoice.date'] ) ) : null,
|
||||
'due_date' => isset( $invoice_data['invoice.due_date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['invoice.due_date'] ) ) : null,
|
||||
'terms' => $this->getString( $invoice_data, 'invoice.terms' ),
|
||||
'public_notes' => $this->getString( $invoice_data, 'invoice.public_notes' ),
|
||||
'is_sent' => $this->getString( $invoice_data, 'invoice.is_sent' ),
|
||||
'private_notes' => $this->getString( $invoice_data, 'invoice.private_notes' ),
|
||||
'tax_name1' => $this->getString( $invoice_data, 'invoice.tax_name1' ),
|
||||
'tax_rate1' => $this->getFloat( $invoice_data, 'invoice.tax_rate1' ),
|
||||
'tax_name2' => $this->getString( $invoice_data, 'invoice.tax_name2' ),
|
||||
'tax_rate2' => $this->getFloat( $invoice_data, 'invoice.tax_rate2' ),
|
||||
'tax_name3' => $this->getString( $invoice_data, 'invoice.tax_name3' ),
|
||||
'tax_rate3' => $this->getFloat( $invoice_data, 'invoice.tax_rate3' ),
|
||||
'custom_value1' => $this->getString( $invoice_data, 'invoice.custom_value1' ),
|
||||
'custom_value2' => $this->getString( $invoice_data, 'invoice.custom_value2' ),
|
||||
'custom_value3' => $this->getString( $invoice_data, 'invoice.custom_value3' ),
|
||||
'custom_value4' => $this->getString( $invoice_data, 'invoice.custom_value4' ),
|
||||
'footer' => $this->getString( $invoice_data, 'invoice.footer' ),
|
||||
'partial' => $this->getFloat( $invoice_data, 'invoice.partial' ),
|
||||
'partial_due_date' => $this->getString( $invoice_data, 'invoice.partial_due_date' ),
|
||||
'custom_surcharge1' => $this->getString( $invoice_data, 'invoice.custom_surcharge1' ),
|
||||
'custom_surcharge2' => $this->getString( $invoice_data, 'invoice.custom_surcharge2' ),
|
||||
'custom_surcharge3' => $this->getString( $invoice_data, 'invoice.custom_surcharge3' ),
|
||||
'custom_surcharge4' => $this->getString( $invoice_data, 'invoice.custom_surcharge4' ),
|
||||
'exchange_rate' => $this->getString( $invoice_data, 'invoice.exchange_rate' ),
|
||||
'status_id' => $invoiceStatusMap[ $status =
|
||||
strtolower( $this->getString( $invoice_data, 'invoice.status' ) ) ] ??
|
||||
Invoice::STATUS_SENT,
|
||||
'viewed' => $status === 'viewed',
|
||||
'archived' => $status === 'archived',
|
||||
];
|
||||
|
||||
if ( isset( $invoice_data['payment.amount'] ) ) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset( $invoice_data['payment.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['payment.date'] ) ) : date( 'y-m-d' ),
|
||||
'transaction_reference' => $this->getString( $invoice_data, 'payment.transaction_reference' ),
|
||||
'amount' => $this->getFloat( $invoice_data, 'payment.amount' ),
|
||||
],
|
||||
];
|
||||
} elseif ( $status === 'paid' ) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset( $invoice_data['payment.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['payment.date'] ) ) : date( 'y-m-d' ),
|
||||
'transaction_reference' => $this->getString( $invoice_data, 'payment.transaction_reference' ),
|
||||
'amount' => $this->getFloat( $invoice_data, 'invoice.amount' ),
|
||||
],
|
||||
];
|
||||
} elseif ( isset( $transformed['amount'] ) && isset( $transformed['balance'] ) ) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset( $invoice_data['payment.date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['payment.date'] ) ) : date( 'y-m-d' ),
|
||||
'transaction_reference' => $this->getString( $invoice_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' => $this->getInvoiceTypeId( $record, 'item.type_id' ),
|
||||
];
|
||||
}
|
||||
$transformed['line_items'] = $line_items;
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
64
app/Import/Transformers/Csv/PaymentTransformer.php
Normal file
64
app/Import/Transformers/Csv/PaymentTransformer.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
|
||||
/**
|
||||
* Class PaymentTransformer.
|
||||
*/
|
||||
class PaymentTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
$client_id =
|
||||
$this->getClient( $this->getString( $data, 'payment.client_id' ), $this->getString( $data, 'payment.client_id' ) );
|
||||
|
||||
if ( empty( $client_id ) ) {
|
||||
throw new ImportException( 'Could not find client.' );
|
||||
}
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString( $data, 'payment.number' ),
|
||||
'user_id' => $this->getString( $data, 'payment.user_id' ),
|
||||
'amount' => $this->getFloat( $data, 'payment.amount' ),
|
||||
'refunded' => $this->getFloat( $data, 'payment.refunded' ),
|
||||
'applied' => $this->getFloat( $data, 'payment.applied' ),
|
||||
'transaction_reference' => $this->getString( $data, 'payment.transaction_reference ' ),
|
||||
'date' => $this->getString( $data, 'payment.date' ),
|
||||
'private_notes' => $this->getString( $data, 'payment.private_notes' ),
|
||||
'custom_value1' => $this->getString( $data, 'payment.custom_value1' ),
|
||||
'custom_value2' => $this->getString( $data, 'payment.custom_value2' ),
|
||||
'custom_value3' => $this->getString( $data, 'payment.custom_value3' ),
|
||||
'custom_value4' => $this->getString( $data, 'payment.custom_value4' ),
|
||||
'client_id' => $client_id,
|
||||
];
|
||||
|
||||
|
||||
if ( isset( $data['payment.invoice_number'] ) &&
|
||||
$invoice_id = $this->getInvoiceId( $data['payment.invoice_number'] ) ) {
|
||||
$transformed['invoices'] = [
|
||||
[
|
||||
'invoice_id' => $invoice_id,
|
||||
'amount' => $transformed['amount'] ?? null,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -9,8 +9,8 @@
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
/**
|
||||
* Class ProductTransformer.
|
||||
*/
|
||||
@ -19,7 +19,7 @@ class ProductTransformer extends BaseTransformer
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|Item
|
||||
* @return array
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
47
app/Import/Transformers/Csv/VendorTransformer.php
Normal file
47
app/Import/Transformers/Csv/VendorTransformer.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Import\Transformers\Csv;
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
|
||||
/**
|
||||
* Class VendorTransformer.
|
||||
*/
|
||||
class VendorTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
if ( isset( $data->name ) && $this->hasVendor( $data->name ) ) {
|
||||
throw new ImportException('Vendor already exists');
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString( $data, 'vendor.name' ),
|
||||
'phone' => $this->getString( $data, 'vendor.phone' ),
|
||||
'id_number' => $this->getString( $data, 'vendor.id_number' ),
|
||||
'vat_number' => $this->getString( $data, 'vendor.vat_number' ),
|
||||
'website' => $this->getString( $data, 'vendor.website' ),
|
||||
'currency_id' => $this->getCurrencyByCode( $data, 'vendor.currency_id' ),
|
||||
'public_notes' => $this->getString( $data, 'vendor.public_notes' ),
|
||||
'private_notes' => $this->getString( $data, 'vendor.private_notes' ),
|
||||
'address1' => $this->getString( $data, 'vendor.address1' ),
|
||||
'address2' => $this->getString( $data, 'vendor.address2' ),
|
||||
'city' => $this->getString( $data, 'vendor.city' ),
|
||||
'state' => $this->getString( $data, 'vendor.state' ),
|
||||
'postal_code' => $this->getString( $data, 'vendor.postal_code' ),
|
||||
'vendor_contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString( $data, 'vendor.first_name' ),
|
||||
'last_name' => $this->getString( $data, 'vendor.last_name' ),
|
||||
'email' => $this->getString( $data, 'vendor.email' ),
|
||||
'phone' => $this->getString( $data, 'vendor.phone' ),
|
||||
],
|
||||
],
|
||||
'country_id' => isset( $data['vendor.country_id'] ) ? $this->getCountryId( $data['vendor.country_id'] ) : null,
|
||||
];
|
||||
}
|
||||
}
|
55
app/Import/Transformers/Freshbooks/ClientTransformer.php
Normal file
55
app/Import/Transformers/Freshbooks/ClientTransformer.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Freshbooks;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
if ( isset( $data['Organization'] ) && $this->hasClient( $data['Organization'] ) ) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString( $data, 'Organization' ),
|
||||
'work_phone' => $this->getString( $data, 'Phone' ),
|
||||
'address1' => $this->getString( $data, 'Street' ),
|
||||
'city' => $this->getString( $data, 'City' ),
|
||||
'state' => $this->getString( $data, 'Province/State' ),
|
||||
'postal_code' => $this->getString( $data, 'Postal Code' ),
|
||||
'country_id' => isset( $data['Country'] ) ? $this->getCountryId( $data['Country'] ) : null,
|
||||
'private_notes' => $this->getString( $data, 'Notes' ),
|
||||
'credit_balance' => 0,
|
||||
'settings' => new \stdClass,
|
||||
'client_hash' => Str::random( 40 ),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString( $data, 'First Name' ),
|
||||
'last_name' => $this->getString( $data, 'Last Name' ),
|
||||
'email' => $this->getString( $data, 'Email' ),
|
||||
'phone' => $this->getString( $data, 'Phone' ),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
78
app/Import/Transformers/Freshbooks/InvoiceTransformer.php
Normal file
78
app/Import/Transformers/Freshbooks/InvoiceTransformer.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Freshbooks;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\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 #'] ) ) {
|
||||
throw new ImportException( 'Invoice number already exists' );
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
'draft' => Invoice::STATUS_DRAFT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient( $this->getString( $invoice_data, 'Client Name' ), null ),
|
||||
'number' => $this->getString( $invoice_data, 'Invoice #' ),
|
||||
'date' => isset( $invoice_data['Date Issued'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Date Issued'] ) ) : null,
|
||||
'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
|
||||
'amount' => 0,
|
||||
'status_id' => $invoiceStatusMap[ $status =
|
||||
strtolower( $this->getString( $invoice_data, 'Invoice Status' ) ) ] ?? Invoice::STATUS_SENT,
|
||||
'viewed' => $status === 'viewed',
|
||||
];
|
||||
|
||||
$line_items = [];
|
||||
foreach ( $line_items_data as $record ) {
|
||||
$line_items[] = [
|
||||
'product_key' => $this->getString( $record, 'Item Name' ),
|
||||
'notes' => $this->getString( $record, 'Item Description' ),
|
||||
'cost' => $this->getFloat( $record, 'Rate' ),
|
||||
'quantity' => $this->getFloat( $record, 'Quantity' ),
|
||||
'discount' => $this->getFloat( $record, 'Discount Percentage' ),
|
||||
'is_amount_discount' => false,
|
||||
'tax_name1' => $this->getString( $record, 'Tax 1 Type' ),
|
||||
'tax_rate1' => $this->getFloat( $record, 'Tax 1 Amount' ),
|
||||
'tax_name2' => $this->getString( $record, 'Tax 2 Type' ),
|
||||
'tax_rate2' => $this->getFloat( $record, 'Tax 2 Amount' ),
|
||||
];
|
||||
$transformed['amount'] += $this->getFloat( $record, 'Line Total' );
|
||||
}
|
||||
$transformed['line_items'] = $line_items;
|
||||
|
||||
if ( ! empty( $invoice_data['Date Paid'] ) ) {
|
||||
$transformed['payments'] = [[
|
||||
'date' => date( 'Y-m-d', strtotime( $invoice_data['Date Paid'] ) ),
|
||||
'amount' => $transformed['amount'],
|
||||
]];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
89
app/Import/Transformers/Invoice2Go/InvoiceTransformer.php
Normal file
89
app/Import/Transformers/Invoice2Go/InvoiceTransformer.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Invoice2Go;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $line_items_data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform( $invoice_data ) {
|
||||
if ( $this->hasInvoice( $invoice_data['DocumentNumber'] ) ) {
|
||||
throw new ImportException( 'Invoice number already exists' );
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'unsent' => Invoice::STATUS_DRAFT,
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString( $invoice_data, 'DocumentNumber' ),
|
||||
'notes' => $this->getString( $invoice_data, 'Comment' ),
|
||||
'date' => isset( $invoice_data['DocumentDate'] ) ? date( 'Y-m-d', strtotime( $invoice_data['DocumentDate'] ) ) : null,
|
||||
'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
|
||||
'amount' => 0,
|
||||
'status_id' => $invoiceStatusMap[ $status =
|
||||
strtolower( $this->getString( $invoice_data, 'DocumentStatus' ) ) ] ?? Invoice::STATUS_SENT,
|
||||
'viewed' => $status === 'viewed',
|
||||
'line_items' => [
|
||||
[
|
||||
'amount' => $amount = $this->getFloat( $invoice_data, 'TotalAmount' ),
|
||||
'quantity' => 1,
|
||||
'discount' => $this->getFloat( $invoice_data, 'DiscountValue' ),
|
||||
'is_amount_discount' => false,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$client_id =
|
||||
$this->getClient( $this->getString( $invoice_data, 'Name' ), $this->getString( $invoice_data, 'EmailRecipient' ) );
|
||||
|
||||
if ( $client_id ) {
|
||||
$transformed['client_id'] = $client_id;
|
||||
} else {
|
||||
$transformed['client'] = [
|
||||
'name' => $this->getString( $invoice_data, 'Name' ),
|
||||
'address1' => $this->getString( $invoice_data, 'DocumentRecipientAddress' ),
|
||||
'shipping_address1' => $this->getString( $invoice_data, 'ShipAddress' ),
|
||||
'credit_balance' => 0,
|
||||
'settings' => new \stdClass,
|
||||
'client_hash' => Str::random( 40 ),
|
||||
'contacts' => [
|
||||
[
|
||||
'email' => $this->getString( $invoice_data, 'Email' ),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
if ( ! empty( $invoice_data['Date Paid'] ) ) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => date( 'Y-m-d', strtotime( $invoice_data['DatePaid'] ) ),
|
||||
'amount' => $this->getFloat( $invoice_data, 'Payments' ),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
/**
|
||||
* Class InvoiceItemTransformer.
|
||||
*/
|
||||
class InvoiceItemTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|Item
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
return [
|
||||
'quantity' => $this->getFloat($data, 'item.quantity'),
|
||||
'cost' => $this->getFloat($data, 'item.cost'),
|
||||
'product_key' => $this->getString($data, 'item.product_key'),
|
||||
'notes' => $this->getString($data, 'item.notes'),
|
||||
'discount' => $this->getFloat($data, 'item.discount'),
|
||||
'is_amount_discount' => $this->getString($data, 'item.is_amount_discount'),
|
||||
'tax_name1' => $this->getString($data, 'item.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($data, 'item.tax_rate1'),
|
||||
'tax_name2' => $this->getString($data, 'item.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($data, 'item.tax_rate2'),
|
||||
'tax_name3' => $this->getString($data, 'item.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($data, 'item.tax_rate3'),
|
||||
'custom_value1' => $this->getString($data, 'item.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'item.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'item.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'item.custom_value4'),
|
||||
'type_id' => $this->getInvoiceTypeId($data, 'item.type_id'),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString($data, 'invoice.number'),
|
||||
'user_id' => $this->getString($data, 'invoice.user_id'),
|
||||
'amount' => $amount = $this->getFloat($data, 'invoice.amount'),
|
||||
'balance' => isset( $data['invoice.balance'] ) ? $this->getFloat( $data, 'invoice.balance' ) : $amount,
|
||||
'client_id' => $this->getClient($this->getString($data, 'client.name'), $this->getString($data, 'client.email')),
|
||||
'discount' => $this->getFloat($data, 'invoice.discount'),
|
||||
'po_number' => $this->getString($data, 'invoice.po_number'),
|
||||
'date' => $this->getString($data, 'invoice.date'),
|
||||
'due_date' => $this->getString($data, 'invoice.due_date'),
|
||||
'terms' => $this->getString($data, 'invoice.terms'),
|
||||
'public_notes' => $this->getString($data, 'invoice.public_notes'),
|
||||
'is_sent' => $this->getString($data, 'invoice.is_sent'),
|
||||
'private_notes' => $this->getString($data, 'invoice.private_notes'),
|
||||
'tax_name1' => $this->getString($data, 'invoice.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($data, 'invoice.tax_rate1'),
|
||||
'tax_name2' => $this->getString($data, 'invoice.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($data, 'invoice.tax_rate2'),
|
||||
'tax_name3' => $this->getString($data, 'invoice.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($data, 'invoice.tax_rate3'),
|
||||
'custom_value1' => $this->getString($data, 'invoice.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'invoice.custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'invoice.custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'invoice.custom_value4'),
|
||||
'footer' => $this->getString($data, 'invoice.footer'),
|
||||
'partial' => $this->getFloat($data, 'invoice.partial'),
|
||||
'partial_due_date' => $this->getString($data, 'invoice.partial_due_date'),
|
||||
'custom_surcharge1' => $this->getString($data, 'invoice.custom_surcharge1'),
|
||||
'custom_surcharge2' => $this->getString($data, 'invoice.custom_surcharge2'),
|
||||
'custom_surcharge3' => $this->getString($data, 'invoice.custom_surcharge3'),
|
||||
'custom_surcharge4' => $this->getString($data, 'invoice.custom_surcharge4'),
|
||||
'exchange_rate' => $this->getString($data, 'invoice.exchange_rate'),
|
||||
];
|
||||
}
|
||||
}
|
48
app/Import/Transformers/Invoicely/ClientTransformer.php
Normal file
48
app/Import/Transformers/Invoicely/ClientTransformer.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Invoicely;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
if ( isset( $data['Client Name'] ) && $this->hasClient( $data['Client Name'] ) ) {
|
||||
throw new ImportException('Client already exists');
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString( $data, 'Client Name' ),
|
||||
'work_phone' => $this->getString( $data, 'Phone' ),
|
||||
'country_id' => isset( $data['Country'] ) ? $this->getCountryIdBy2( $data['Country'] ) : null,
|
||||
'credit_balance' => 0,
|
||||
'settings' => new \stdClass,
|
||||
'client_hash' => Str::random( 40 ),
|
||||
'contacts' => [
|
||||
[
|
||||
'email' => $this->getString( $data, 'Email' ),
|
||||
'phone' => $this->getString( $data, 'Phone' ),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
58
app/Import/Transformers/Invoicely/InvoiceTransformer.php
Normal file
58
app/Import/Transformers/Invoicely/InvoiceTransformer.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Invoicely;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Models\Invoice;
|
||||
|
||||
/**
|
||||
* Class InvoiceTransformer.
|
||||
*/
|
||||
class InvoiceTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
if ( $this->hasInvoice( $data['Details'] ) ) {
|
||||
throw new ImportException( 'Invoice number already exists' );
|
||||
}
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient( $this->getString( $data, 'Client' ), null ),
|
||||
'number' => $this->getString( $data, 'Details' ),
|
||||
'date' => isset( $data['Date'] ) ? date( 'Y-m-d', strtotime( $data['Date'] ) ) : null,
|
||||
'due_date' => isset( $data['Due'] ) ? date( 'Y-m-d', strtotime( $data['Due'] ) ) : null,
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
'line_items' => [
|
||||
[
|
||||
'cost' => $amount = $this->getFloat( $data, 'Total' ),
|
||||
'quantity' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if ( strtolower( $data['Status'] ) === 'paid' ) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => date( 'Y-m-d' ),
|
||||
'amount' => $amount,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers;
|
||||
|
||||
/**
|
||||
* Class PaymentTransformer.
|
||||
*/
|
||||
class PaymentTransformer extends BaseTransformer
|
||||
{
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return bool|Item
|
||||
*/
|
||||
public function transform($data)
|
||||
{
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'number' => $this->getString($data, 'payment.number'),
|
||||
'user_id' => $this->getString($data, 'payment.user_id'),
|
||||
'amount' => $this->getFloat($data, 'payment.amount'),
|
||||
'refunded' => $this->getFloat($data, 'payment.refunded'),
|
||||
'applied' => $this->getFloat($data, 'payment.applied'),
|
||||
'transaction_reference' => $this->getString($data, 'payment.transaction_reference '),
|
||||
'date' => $this->getString($data, 'payment.date'),
|
||||
'private_notes' => $this->getString($data, 'payment.private_notes'),
|
||||
'number' => $this->getString($data, 'number'),
|
||||
'custom_value1' => $this->getString($data, 'custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'custom_value2'),
|
||||
'custom_value3' => $this->getString($data, 'custom_value3'),
|
||||
'custom_value4' => $this->getString($data, 'custom_value4'),
|
||||
'client_id' => $this->getString($data, 'client_id'),
|
||||
'invoice_number' => $this->getString($data, 'payment.invoice_number'),
|
||||
'method' => $this
|
||||
];
|
||||
}
|
||||
}
|
74
app/Import/Transformers/Waveaccounting/ClientTransformer.php
Normal file
74
app/Import/Transformers/Waveaccounting/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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Waveaccounting;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\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->maps['company']->id,
|
||||
'name' => $this->getString( $data, 'customer_name' ),
|
||||
'number' => $this->getString( $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' ),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Waveaccounting;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\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->maps['company']->id,
|
||||
'client_id' => $this->getClient( $customer_name = $this->getString( $invoice_data, 'Customer' ), null ),
|
||||
'number' => $invoice_number = $this->getString( $invoice_data, 'Invoice Number' ),
|
||||
'date' => isset( $invoice_data['Invoice Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Transaction Date'] ) ) : null,
|
||||
'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;
|
||||
}
|
||||
}
|
72
app/Import/Transformers/Zoho/ClientTransformer.php
Normal file
72
app/Import/Transformers/Zoho/ClientTransformer.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Zoho;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Class ClientTransformer.
|
||||
*/
|
||||
class ClientTransformer extends BaseTransformer {
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function transform( $data ) {
|
||||
if ( isset( $data['Company Name'] ) && $this->hasClient( $data['Company Name'] ) ) {
|
||||
throw new ImportException( 'Client already exists' );
|
||||
}
|
||||
|
||||
$settings = new \stdClass;
|
||||
$settings->currency_id = (string) $this->getCurrencyByCode( $data, 'Currency' );
|
||||
|
||||
if ( strval( $data['Payment Terms'] ?? '' ) > 0 ) {
|
||||
$settings->payment_terms = $data['Payment Terms'];
|
||||
}
|
||||
|
||||
return [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'name' => $this->getString( $data, 'Company Name' ),
|
||||
'work_phone' => $this->getString( $data, 'Phone' ),
|
||||
'private_notes' => $this->getString( $data, 'Notes' ),
|
||||
'website' => $this->getString( $data, 'Website' ),
|
||||
|
||||
'address1' => $this->getString( $data, 'Billing Address' ),
|
||||
'address2' => $this->getString( $data, 'Billing Street2' ),
|
||||
'city' => $this->getString( $data, 'Billing City' ),
|
||||
'state' => $this->getString( $data, 'Billing State' ),
|
||||
'postal_code' => $this->getString( $data, 'Billing Code' ),
|
||||
'country_id' => isset( $data['Billing Country'] ) ? $this->getCountryId( $data['Billing Country'] ) : null,
|
||||
|
||||
'shipping_address1' => $this->getString( $data, 'Shipping Address' ),
|
||||
'shipping_address2' => $this->getString( $data, 'Shipping Street2' ),
|
||||
'shipping_city' => $this->getString( $data, 'Shipping City' ),
|
||||
'shipping_state' => $this->getString( $data, 'Shipping State' ),
|
||||
'shipping_postal_code' => $this->getString( $data, 'Shipping Code' ),
|
||||
'shipping_country_id' => isset( $data['Shipping Country'] ) ? $this->getCountryId( $data['Shipping Country'] ) : null,
|
||||
'credit_balance' => 0,
|
||||
'settings' => $settings,
|
||||
'client_hash' => Str::random( 40 ),
|
||||
'contacts' => [
|
||||
[
|
||||
'first_name' => $this->getString( $data, 'First Name' ),
|
||||
'last_name' => $this->getString( $data, 'Last Name' ),
|
||||
'email' => $this->getString( $data, 'Email' ),
|
||||
'phone' => $this->getString( $data, 'Phone' ),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
77
app/Import/Transformers/Zoho/InvoiceTransformer.php
Normal file
77
app/Import/Transformers/Zoho/InvoiceTransformer.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?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://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Import\Transformers\Zoho;
|
||||
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\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' );
|
||||
}
|
||||
|
||||
$invoiceStatusMap = [
|
||||
'sent' => Invoice::STATUS_SENT,
|
||||
'draft' => Invoice::STATUS_DRAFT,
|
||||
];
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient( $this->getString( $invoice_data, 'Company Name' ), null ),
|
||||
'number' => $this->getString( $invoice_data, 'Invoice Number' ),
|
||||
'date' => isset( $invoice_data['Invoice Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Invoice Date'] ) ) : null,
|
||||
'due_date' => isset( $invoice_data['Due Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Due Date'] ) ) : null,
|
||||
'po_number' => $this->getString( $invoice_data, 'PurchaseOrder' ),
|
||||
'public_notes' => $this->getString( $invoice_data, 'Notes' ),
|
||||
'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
|
||||
'amount' => $this->getFloat( $invoice_data, 'Total' ),
|
||||
'balance' => $this->getFloat( $invoice_data, 'Balance' ),
|
||||
'status_id' => $invoiceStatusMap[ $status =
|
||||
strtolower( $this->getString( $invoice_data, 'Invoice Status' ) ) ] ?? Invoice::STATUS_SENT,
|
||||
'viewed' => $status === 'viewed',
|
||||
];
|
||||
|
||||
$line_items = [];
|
||||
foreach ( $line_items_data as $record ) {
|
||||
$line_items[] = [
|
||||
'product_key' => $this->getString( $record, 'Item Name' ),
|
||||
'notes' => $this->getString( $record, 'Item Description' ),
|
||||
'cost' => $this->getFloat( $record, 'Item Price' ),
|
||||
'quantity' => $this->getFloat( $record, 'Quantity' ),
|
||||
'discount' => $this->getFloat( $record, 'Discount Amount' ),
|
||||
'is_amount_discount' => true,
|
||||
];
|
||||
}
|
||||
$transformed['line_items'] = $line_items;
|
||||
|
||||
if ( $transformed['balance'] < $transformed['amount'] ) {
|
||||
$transformed['payments'] = [[
|
||||
'date' => date( 'Y-m-d' ),
|
||||
'amount' => $transformed['amount'] - $transformed['balance'],
|
||||
]];
|
||||
}
|
||||
|
||||
return $transformed;
|
||||
}
|
||||
}
|
@ -14,16 +14,9 @@ namespace App\Jobs\Import;
|
||||
use App\Factory\ClientFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\PaymentFactory;
|
||||
use App\Factory\ProductFactory;
|
||||
use App\Http\Requests\Client\StoreClientRequest;
|
||||
use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
||||
use App\Http\Requests\Product\StoreProductRequest;
|
||||
use App\Import\ImportException;
|
||||
use App\Import\Transformers\BaseTransformer;
|
||||
use App\Import\Transformers\ClientTransformer;
|
||||
use App\Import\Transformers\InvoiceItemTransformer;
|
||||
use App\Import\Transformers\InvoiceTransformer;
|
||||
use App\Import\Transformers\PaymentTransformer;
|
||||
use App\Import\Transformers\ProductTransformer;
|
||||
use App\Jobs\Mail\MailRouter;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\Import\ImportCompleted;
|
||||
@ -32,14 +25,15 @@ use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
use App\Models\Country;
|
||||
use App\Models\Currency;
|
||||
use App\Models\Expense;
|
||||
use App\Models\ExpenseCategory;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\Product;
|
||||
use App\Models\Project;
|
||||
use App\Models\TaxRate;
|
||||
use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
use App\Repositories\ClientRepository;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Repositories\PaymentRepository;
|
||||
use App\Utils\Traits\CleanLineItems;
|
||||
@ -54,6 +48,8 @@ use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use League\Csv\Reader;
|
||||
use League\Csv\Statement;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class CSVImport implements ShouldQueue {
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, CleanLineItems;
|
||||
@ -77,15 +73,11 @@ class CSVImport implements ShouldQueue {
|
||||
public $maps;
|
||||
|
||||
public function __construct( array $request, Company $company ) {
|
||||
$this->company = $company;
|
||||
|
||||
$this->hash = $request['hash'];
|
||||
|
||||
$this->company = $company;
|
||||
$this->hash = $request['hash'];
|
||||
$this->import_type = $request['import_type'];
|
||||
|
||||
$this->skip_header = $request['skip_header'] ?? null;
|
||||
|
||||
$this->column_map = $request['column_map'] ?? null;
|
||||
$this->column_map = $request['column_map'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,35 +95,21 @@ class CSVImport implements ShouldQueue {
|
||||
|
||||
$this->buildMaps();
|
||||
|
||||
//sort the array by key
|
||||
foreach ( $this->column_map as $entityType => &$map ) {
|
||||
ksort( $map );
|
||||
}
|
||||
|
||||
nlog( "import" . ucfirst( $this->import_type ) );
|
||||
$this->{"import" . ucfirst( $this->import_type )}();
|
||||
|
||||
$data = [
|
||||
'errors' => $this->error_array,
|
||||
'company'=>$this->company,
|
||||
];
|
||||
|
||||
|
||||
MailRouter::dispatchNow( new ImportCompleted( $data ), $this->company, auth()->user() );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private function importCsv() {
|
||||
nlog( "import " . $this->import_type );
|
||||
foreach ( [ 'client', 'product', 'invoice', 'payment', 'vendor', 'expense' ] as $entityType ) {
|
||||
if ( empty( $this->column_map[ $entityType ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$csvData = $this->getCsvData( $entityType );
|
||||
|
||||
if ( ! empty( $csvData ) ) {
|
||||
$importFunction = "import" . Str::plural( Str::title( $entityType ) );
|
||||
$importFunction = "import" . Str::plural( Str::title( $entityType ) );
|
||||
$preTransformFunction = "preTransform" . Str::title( $this->import_type );
|
||||
|
||||
if ( method_exists( $this, $preTransformFunction ) ) {
|
||||
$csvData = $this->$preTransformFunction( $csvData, $entityType );
|
||||
}
|
||||
|
||||
if ( empty( $csvData ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( method_exists( $this, $importFunction ) ) {
|
||||
// If there's an entity-specific import function, use that.
|
||||
@ -142,113 +120,204 @@ class CSVImport implements ShouldQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
'errors' => $this->error_array,
|
||||
'company' => $this->company,
|
||||
];
|
||||
|
||||
MailRouter::dispatchNow( new ImportCompleted( $data ), $this->company, auth()->user() );
|
||||
}
|
||||
|
||||
private function importInvoices( $records ) {
|
||||
$invoice_transformer = new InvoiceTransformer( $this->maps );
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private function preTransformCsv( $csvData, $entityType ) {
|
||||
if ( empty( $this->column_map[ $entityType ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->skip_header ) {
|
||||
array_shift( $records );
|
||||
array_shift( $csvData );
|
||||
}
|
||||
|
||||
$keys = $this->column_map['invoice'];
|
||||
$invoice_number_key = array_search( 'invoice.number', $keys );
|
||||
if ( $invoice_number_key === false ) {
|
||||
nlog( "no invoice number to use as key - returning" );
|
||||
//sort the array by key
|
||||
$keys = $this->column_map[ $entityType ];
|
||||
ksort( $keys );
|
||||
|
||||
return;
|
||||
$csvData = array_map( function ( $row ) use ( $keys ) {
|
||||
return array_combine( $keys, array_intersect_key( $row, $keys ) );
|
||||
}, $csvData );
|
||||
|
||||
if ( $entityType === 'invoice' ) {
|
||||
$csvData = $this->groupInvoices( $csvData, 'invoice.number' );
|
||||
}
|
||||
|
||||
$items_by_invoice = [];
|
||||
|
||||
// Group line items by invoice and map columns to keys.
|
||||
foreach ( $records as $key => $value ) {
|
||||
$items_by_invoice[ $value[ $invoice_number_key ] ][] = array_combine( $keys,array_intersect_key( $value , $keys ));
|
||||
}
|
||||
|
||||
foreach ( $items_by_invoice as $invoice_number => $line_items ) {
|
||||
$invoice_data = array_combine( $keys, reset( $line_items ) );
|
||||
|
||||
$invoice = $invoice_transformer->transform( $invoice_data );
|
||||
|
||||
$this->processInvoice( $line_items, $invoice );
|
||||
}
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function processInvoice( $line_items, $invoice ) {
|
||||
$invoice_repository = new InvoiceRepository();
|
||||
$item_transformer = new InvoiceItemTransformer( $this->maps );
|
||||
$items = [];
|
||||
private function preTransformFreshbooks( $csvData, $entityType ) {
|
||||
$csvData = $this->mapCSVHeaderToKeys( $csvData );
|
||||
|
||||
foreach ( $line_items as $record ) {
|
||||
$items[] = $item_transformer->transform( $record );
|
||||
if ( $entityType === 'invoice' ) {
|
||||
$csvData = $this->groupInvoices( $csvData, 'Invoice #' );
|
||||
}
|
||||
|
||||
$invoice['line_items'] = $this->cleanItems( $items );
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
$validator = Validator::make( $invoice, ( new StoreInvoiceRequest() )->rules() );
|
||||
private function preTransformInvoicely( $csvData, $entityType ) {
|
||||
$csvData = $this->mapCSVHeaderToKeys( $csvData );
|
||||
|
||||
if ( $validator->fails() ) {
|
||||
$this->error_array['invoice'][] = [ 'invoice' => $invoice, 'error' => $validator->errors()->all() ];
|
||||
} else {
|
||||
$invoice =
|
||||
$invoice_repository->save( $invoice, InvoiceFactory::create( $this->company->id, $this->getUserIDForRecord( $record ) ) );
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
$this->addInvoiceToMaps( $invoice );
|
||||
private function preTransformInvoice2go( $csvData, $entityType ) {
|
||||
$csvData = $this->mapCSVHeaderToKeys( $csvData );
|
||||
|
||||
// If there's no payment import, try importing payment data from the invoices CSV.
|
||||
if ( empty( $this->column_map['payment'] ) ) {
|
||||
$payment_data = reset( $line_items );
|
||||
// Check for payment columns
|
||||
if ( ! empty( $payment_data['payment.amount'] ) ) {
|
||||
// Transform the payment to be saved
|
||||
$payment_transformer = new PaymentTransformer( $this->maps );
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
/** @var PaymentRepository $payment_repository */
|
||||
$payment_repository = app()->make( PaymentRepository::class );
|
||||
$transformed_payment = $payment_transformer->transform( $payment_data );
|
||||
$transformed_payment['user_id'] = $invoice->user_id;
|
||||
$transformed_payment['client_id'] = $invoice->client_id;
|
||||
$transformed_payment['invoices'] = [
|
||||
[
|
||||
'invoice_id' => $invoice->id,
|
||||
'amount' => $transformed_payment['amount'],
|
||||
],
|
||||
];
|
||||
private function preTransformZoho( $csvData, $entityType ) {
|
||||
$csvData = $this->mapCSVHeaderToKeys( $csvData );
|
||||
|
||||
$payment_repository->save(
|
||||
$transformed_payment,
|
||||
PaymentFactory::create( $this->company->id, $invoice->user_id, $invoice->client_id )
|
||||
);
|
||||
}
|
||||
if ( $entityType === 'invoice' ) {
|
||||
$csvData = $this->groupInvoices( $csvData, 'Invoice Number' );
|
||||
}
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function preTransformWaveaccounting( $csvData, $entityType ) {
|
||||
$csvData = $this->mapCSVHeaderToKeys( $csvData );
|
||||
|
||||
if ( $entityType === 'invoice' ) {
|
||||
$csvData = $this->groupInvoices( $csvData, 'Invoice Number' );
|
||||
}
|
||||
|
||||
return $csvData;
|
||||
}
|
||||
|
||||
private function groupInvoices( $csvData, $key ) {
|
||||
// Group by invoice.
|
||||
$grouped = [];
|
||||
|
||||
foreach ( $csvData as $line_item ) {
|
||||
if ( empty( $line_item[ $key ] ) ) {
|
||||
$this->error_array['invoice'][] = [ 'invoice' => $line_item, 'error' => 'No invoice number' ];
|
||||
} else {
|
||||
$grouped[ $line_item[ $key ] ][] = $line_item;
|
||||
}
|
||||
}
|
||||
|
||||
$this->actionInvoiceStatus( $invoice, $record['invoice.status']??null, $invoice_repository );
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
private function mapCSVHeaderToKeys( $csvData ) {
|
||||
$keys = array_shift( $csvData );
|
||||
|
||||
return array_map( function ( $values ) use ( $keys ) {
|
||||
return array_combine( $keys, $values );
|
||||
}, $csvData );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private function importInvoices( $invoices ) {
|
||||
$invoice_transformer = $this->getTransformer( 'invoice' );
|
||||
|
||||
/** @var PaymentRepository $payment_repository */
|
||||
$payment_repository = app()->make( PaymentRepository::class );
|
||||
/** @var ClientRepository $client_repository */
|
||||
$client_repository = app()->make( ClientRepository::class );
|
||||
|
||||
foreach ( $invoices as $raw_invoice ) {
|
||||
try {
|
||||
$invoice_data = $invoice_transformer->transform( $raw_invoice );
|
||||
$invoice_repository = new InvoiceRepository();
|
||||
|
||||
$invoice_data['line_items'] = $this->cleanItems( $invoice_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( $invoice_data['client_id'] ) && ! empty( $invoice_data['client'] ) ) {
|
||||
$client_data = $invoice_data['client'];
|
||||
$client_data['user_id'] = $this->getUserIDForRecord( $invoice_data );
|
||||
|
||||
$client_repository->save(
|
||||
$client_data,
|
||||
$client = ClientFactory::create( $this->company->id, $client_data['user_id'] )
|
||||
);
|
||||
$invoice_data['client_id'] = $client->id;
|
||||
unset( $invoice_data['client'] );
|
||||
}
|
||||
|
||||
$validator = Validator::make( $invoice_data, ( new StoreInvoiceRequest() )->rules() );
|
||||
if ( $validator->fails() ) {
|
||||
$this->error_array['invoice'][] =
|
||||
[ 'invoice' => $invoice_data, 'error' => $validator->errors()->all() ];
|
||||
} else {
|
||||
$invoice = InvoiceFactory::create( $this->company->id, $this->getUserIDForRecord( $invoice_data ) );
|
||||
if ( ! empty( $invoice_data['status_id'] ) ) {
|
||||
$invoice->status_id = $invoice_data['status_id'];
|
||||
}
|
||||
$invoice_repository->save( $invoice_data, $invoice );
|
||||
$this->addInvoiceToMaps( $invoice );
|
||||
|
||||
// If we're doing a generic CSV import, only import payment data if we're not importing a payment CSV.
|
||||
// If we're doing a platform-specific import, trust the platform to only return payment info if there's not a separate payment CSV.
|
||||
if ( $this->import_type !== 'csv' || empty( $this->column_map['payment'] ) ) {
|
||||
// Check for payment columns
|
||||
if ( ! empty( $invoice_data['payments'] ) ) {
|
||||
foreach ( $invoice_data['payments'] as $payment_data ) {
|
||||
$payment_data['user_id'] = $invoice->user_id;
|
||||
$payment_data['client_id'] = $invoice->client_id;
|
||||
$payment_data['invoices'] = [
|
||||
[
|
||||
'invoice_id' => $invoice->id,
|
||||
'amount' => $payment_data['amount'] ?? null,
|
||||
],
|
||||
];
|
||||
|
||||
$payment_repository->save(
|
||||
$payment_data,
|
||||
PaymentFactory::create( $this->company->id, $invoice->user_id, $invoice->client_id )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->actionInvoiceStatus( $invoice, $invoice_data, $invoice_repository );
|
||||
}
|
||||
} catch ( \Exception $ex ) {
|
||||
if ( $ex instanceof ImportException ) {
|
||||
$message = $ex->getMessage();
|
||||
} else {
|
||||
report( $ex );
|
||||
$message = 'Unknown error';
|
||||
}
|
||||
|
||||
$this->error_array['invoice'][] = [ 'invoice' => $raw_invoice, 'error' => $message ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function actionInvoiceStatus( $invoice, $status, $invoice_repository ) {
|
||||
switch ( $status ) {
|
||||
case 'Archived':
|
||||
$invoice_repository->archive( $invoice );
|
||||
$invoice->fresh();
|
||||
break;
|
||||
case 'Sent':
|
||||
$invoice = $invoice->service()->markSent()->save();
|
||||
break;
|
||||
case 'Viewed':
|
||||
$invoice = $invoice->service()->markSent()->save();
|
||||
break;
|
||||
default:
|
||||
# code...
|
||||
break;
|
||||
private function actionInvoiceStatus( $invoice, $invoice_data, $invoice_repository ) {
|
||||
if ( ! empty( $invoice_data['archived'] ) ) {
|
||||
$invoice_repository->archive( $invoice );
|
||||
$invoice->fresh();
|
||||
}
|
||||
|
||||
if($invoice->status_id <= Invoice::STATUS_SENT){
|
||||
if ( $invoice->balance < $invoice->amount) {
|
||||
if ( ! empty( $invoice_data['viewed'] ) ) {
|
||||
$invoice = $invoice->service()->markViewed()->save();
|
||||
}
|
||||
|
||||
if ( $invoice->status_id === Invoice::STATUS_SENT ) {
|
||||
$invoice = $invoice->service()->markSent()->save();
|
||||
}
|
||||
|
||||
if ( $invoice->status_id <= Invoice::STATUS_SENT && $invoice->amount > 0 ) {
|
||||
if ( $invoice->balance < $invoice->amount ) {
|
||||
$invoice->status_id = Invoice::STATUS_PARTIAL;
|
||||
$invoice->save();
|
||||
} elseif($invoice->balance <=0){
|
||||
} elseif ( $invoice->balance <= 0 ) {
|
||||
$invoice->status_id = Invoice::STATUS_PAID;
|
||||
$invoice->save();
|
||||
}
|
||||
@ -262,41 +331,65 @@ class CSVImport implements ShouldQueue {
|
||||
$entity_type = Str::slug( $entity_type, '_' );
|
||||
$formatted_entity_type = Str::title( $entity_type );
|
||||
|
||||
$request = "\\App\\Http\\Requests\\${formatted_entity_type}\\Store${formatted_entity_type}Request";
|
||||
$repository_name = '\\App\\Repositories\\'.$formatted_entity_type . 'Repository';
|
||||
$transformer_name = '\\App\\Import\\Transformers\\'.$formatted_entity_type . 'Transformer';
|
||||
$factoryName = '\\App\\Factory\\'.$formatted_entity_type . 'Factory';
|
||||
$request_name = "\\App\\Http\\Requests\\${formatted_entity_type}\\Store${formatted_entity_type}Request";
|
||||
$repository_name = '\\App\\Repositories\\' . $formatted_entity_type . 'Repository';
|
||||
$factoryName = '\\App\\Factory\\' . $formatted_entity_type . 'Factory';
|
||||
|
||||
$repository = app()->make($repository_name);
|
||||
$transformer = new $transformer_name( $this->maps );
|
||||
|
||||
if ( $this->skip_header ) {
|
||||
array_shift( $records );
|
||||
}
|
||||
$repository = app()->make( $repository_name );
|
||||
$transformer = $this->getTransformer( $entity_type );
|
||||
|
||||
foreach ( $records as $record ) {
|
||||
$keys = $this->column_map[ $entity_type ];
|
||||
$values = array_intersect_key( $record, $keys );
|
||||
try {
|
||||
$entity = $transformer->transform( $record );
|
||||
|
||||
$data = array_combine( $keys, $values );
|
||||
/** @var \App\Http\Requests\Request $request */
|
||||
$request = new $request_name();
|
||||
|
||||
$entity = $transformer->transform( $data );
|
||||
// Pass entity data to request so it can be validated
|
||||
$request->query = $request->request = new ParameterBag( $entity );
|
||||
$validator = Validator::make( $entity, $request->rules() );
|
||||
|
||||
$validator = Validator::make( $entity, ( new $request() )->rules() );
|
||||
if ( $validator->fails() ) {
|
||||
$this->error_array[ $entity_type ][] =
|
||||
[ $entity_type => $record, 'error' => $validator->errors()->all() ];
|
||||
} else {
|
||||
$entity =
|
||||
$repository->save(
|
||||
array_diff_key( $entity, [ 'user_id' => false ] ),
|
||||
$factoryName::create( $this->company->id, $this->getUserIDForRecord( $entity ) ) );
|
||||
|
||||
if ( $validator->fails() ) {
|
||||
$this->error_array[ $entity_type ][] =
|
||||
[ $entity_type => $entity, 'error' => $validator->errors()->all() ];
|
||||
} else {
|
||||
$entity =
|
||||
$repository->save( $entity, $factoryName::create( $this->company->id, $this->getUserIDForRecord( $data) ) );
|
||||
$entity->save();
|
||||
if ( method_exists( $this, 'add' . $formatted_entity_type . 'ToMaps' ) ) {
|
||||
$this->{'add' . $formatted_entity_type . 'ToMaps'}( $entity );
|
||||
}
|
||||
}
|
||||
} catch ( \Exception $ex ) {
|
||||
if ( $ex instanceof ImportException ) {
|
||||
$message = $ex->getMessage();
|
||||
} else {
|
||||
report( $ex );
|
||||
$message = 'Unknown error';
|
||||
}
|
||||
|
||||
$entity->save();
|
||||
$this->{'add' . $formatted_entity_type . 'ToMaps'}( $entity );
|
||||
$this->error_array[ $entity_type ][] = [ $entity_type => $record, 'error' => $message ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $entity_type
|
||||
*
|
||||
* @return BaseTransformer
|
||||
*/
|
||||
private function getTransformer( $entity_type ) {
|
||||
$formatted_entity_type = Str::title( $entity_type );
|
||||
$formatted_import_type = Str::title( $this->import_type );
|
||||
$transformer_name =
|
||||
'\\App\\Import\\Transformers\\' . $formatted_import_type . '\\' . $formatted_entity_type . 'Transformer';
|
||||
|
||||
return new $transformer_name( $this->maps );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private function buildMaps() {
|
||||
$this->maps = [
|
||||
@ -313,6 +406,7 @@ class CSVImport implements ShouldQueue {
|
||||
'invoice_ids' => [],
|
||||
'vendors' => [],
|
||||
'expense_categories' => [],
|
||||
'payment_types' => [],
|
||||
'tax_rates' => [],
|
||||
'tax_names' => [],
|
||||
];
|
||||
@ -337,6 +431,11 @@ class CSVImport implements ShouldQueue {
|
||||
$this->addProductToMaps( $product );
|
||||
}
|
||||
|
||||
$projects = Project::scope()->get();
|
||||
foreach ( $projects as $project ) {
|
||||
$this->addProjectToMaps( $projects );
|
||||
}
|
||||
|
||||
$countries = Country::all();
|
||||
foreach ( $countries as $country ) {
|
||||
$this->maps['countries'][ strtolower( $country->name ) ] = $country->id;
|
||||
@ -348,6 +447,11 @@ class CSVImport implements ShouldQueue {
|
||||
$this->maps['currencies'][ strtolower( $currency->code ) ] = $currency->id;
|
||||
}
|
||||
|
||||
$payment_types = PaymentType::all();
|
||||
foreach ( $payment_types as $payment_type ) {
|
||||
$this->maps['payment_types'][ strtolower( $payment_type->name ) ] = $payment_type->id;
|
||||
}
|
||||
|
||||
$vendors = Vendor::scope()->get();
|
||||
foreach ( $vendors as $vendor ) {
|
||||
$this->addVendorToMaps( $vendor );
|
||||
@ -370,7 +474,7 @@ class CSVImport implements ShouldQueue {
|
||||
* @param Invoice $invoice
|
||||
*/
|
||||
private function addInvoiceToMaps( Invoice $invoice ) {
|
||||
if ( $number = strtolower( trim( $invoice->invoice_number ) ) ) {
|
||||
if ( $number = strtolower( trim( $invoice->number ) ) ) {
|
||||
$this->maps['invoices'][ $number ] = $invoice;
|
||||
$this->maps['invoice'][ $number ] = $invoice->id;
|
||||
$this->maps['invoice_client'][ $number ] = $invoice->client_id;
|
||||
@ -391,7 +495,7 @@ class CSVImport implements ShouldQueue {
|
||||
if ( $email = strtolower( trim( $contact->email ) ) ) {
|
||||
$this->maps['client'][ $email ] = $client->id;
|
||||
}
|
||||
if ( $name = strtolower( trim($contact->first_name.' '.$contact->last_name) ) ) {
|
||||
if ( $name = strtolower( trim( $contact->first_name . ' ' . $contact->last_name ) ) ) {
|
||||
$this->maps['client'][ $name ] = $client->id;
|
||||
}
|
||||
$this->maps['client_ids'][ $client->public_id ] = $client->id;
|
||||
@ -416,6 +520,15 @@ class CSVImport implements ShouldQueue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Project $project
|
||||
*/
|
||||
private function addProjectToMaps( Project $project ) {
|
||||
if ( $key = strtolower( trim( $project->name ) ) ) {
|
||||
$this->maps['project'][ $key ] = $project;
|
||||
}
|
||||
}
|
||||
|
||||
private function addVendorToMaps( Vendor $vendor ) {
|
||||
$this->maps['vendor'][ strtolower( $vendor->name ) ] = $vendor->id;
|
||||
}
|
||||
@ -428,8 +541,8 @@ class CSVImport implements ShouldQueue {
|
||||
|
||||
|
||||
private function getUserIDForRecord( $record ) {
|
||||
if ( !empty($record['client.user_id']) ) {
|
||||
return $this->findUser( $record[ 'client.user_id' ] );
|
||||
if ( ! empty( $record['user_id'] ) ) {
|
||||
return $this->findUser( $record['user_id'] );
|
||||
} else {
|
||||
return $this->company->owner()->id;
|
||||
}
|
||||
@ -473,6 +586,6 @@ class CSVImport implements ShouldQueue {
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user