Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
David Bomba 2016-05-05 07:44:54 +10:00
commit dd4ea2ac17
50 changed files with 1950 additions and 270 deletions

138
.htaccess
View File

@ -6,3 +6,141 @@
# https://coderwall.com/p/erbaig/laravel-s-htaccess-to-remove-public-from-url
# RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
# https://github.com/h5bp/server-configs-apache/blob/master/dist/.htaccess
# ######################################################################
# # INTERNET EXPLORER #
# ######################################################################
# ----------------------------------------------------------------------
# | Iframes cookies |
# ----------------------------------------------------------------------
# Allow cookies to be set from iframes in Internet Explorer.
#
# https://msdn.microsoft.com/en-us/library/ms537343.aspx
# http://www.w3.org/TR/2000/CR-P3P-20001215/
<IfModule mod_headers.c>
Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
</IfModule>
# ######################################################################
# # MEDIA TYPES AND CHARACTER ENCODINGS #
# ######################################################################
# ----------------------------------------------------------------------
# | Character encodings |
# ----------------------------------------------------------------------
# Serve all resources labeled as `text/html` or `text/plain`
# with the media type `charset` parameter set to `UTF-8`.
#
# https://httpd.apache.org/docs/current/mod/core.html#adddefaultcharset
AddDefaultCharset utf-8
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Serve the following file types with the media type `charset`
# parameter set to `UTF-8`.
#
# https://httpd.apache.org/docs/current/mod/mod_mime.html#addcharset
<IfModule mod_mime.c>
AddCharset utf-8 .atom \
.bbaw \
.css \
.geojson \
.js \
.json \
.jsonld \
.manifest \
.rdf \
.rss \
.topojson \
.vtt \
.webapp \
.webmanifest \
.xloc \
.xml
</IfModule>
# ######################################################################
# # WEB PERFORMANCE #
# ######################################################################
# ----------------------------------------------------------------------
# | Compression |
# ----------------------------------------------------------------------
<IfModule mod_deflate.c>
# Force compression for mangled headers.
# https://developer.yahoo.com/blogs/ydn/pushing-beyond-gzipping-25601.html
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Map certain file types to the specified encoding type in order to
# make Apache serve them with the appropriate `Content-Encoding` HTTP
# response header (this will NOT make Apache compress them!).
# If the following file types wouldn't be served without the appropriate
# `Content-Enable` HTTP response header, client applications (e.g.:
# browsers) wouldn't know that they first need to uncompress the response,
# and thus, wouldn't be able to understand the content.
# http://httpd.apache.org/docs/current/mod/mod_mime.html#addencoding
<IfModule mod_mime.c>
AddEncoding gzip svgz
</IfModule>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Compress all output labeled with one of the following media types.
# IMPORTANT: For Apache versions below 2.3.7 you don't need to enable
# `mod_filter` and can remove the `<IfModule mod_filter.c>` & `</IfModule>`
# lines as `AddOutputFilterByType` is still in the core directives.
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font-ttf" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/opentype" \
"image/svg+xml" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vtt" \
"text/x-component" \
"text/xml"
</IfModule>
</IfModule>

View File

@ -45,7 +45,8 @@ before_script:
- php artisan key:generate --no-interaction
- sed -i 's/APP_ENV=production/APP_ENV=development/g' .env
- sed -i 's/APP_DEBUG=false/APP_DEBUG=true/g' .env
- sed -i 's/REQUIRE_HTTPS=false/NINJA_DEV=true/g' .env
- sed -i '$a NINJA_DEV=true' .env
- sed -i '$a TRAVIS=true' .env
# create the database and user
- mysql -u root -e "create database IF NOT EXISTS ninja;"
- mysql -u root -e "GRANT ALL PRIVILEGES ON ninja.* To 'ninja'@'localhost' IDENTIFIED BY 'ninja'; FLUSH PRIVILEGES;"

View File

@ -0,0 +1,172 @@
<?php namespace App\Console\Commands;
use stdClass;
use Auth;
use DB;
use Utils;
use Artisan;
use Illuminate\Console\Command;
use Faker\Factory;
use App\Models\User;
use App\Ninja\Repositories\ClientRepository;
use App\Ninja\Repositories\InvoiceRepository;
use App\Ninja\Repositories\PaymentRepository;
use App\Ninja\Repositories\VendorRepository;
use App\Ninja\Repositories\ExpenseRepository;
class CreateTestData extends Command
{
//protected $name = 'ninja:create-test-data';
protected $description = 'Create Test Data';
protected $signature = 'ninja:create-test-data {count=1}';
protected $token;
public function __construct(
ClientRepository $clientRepo,
InvoiceRepository $invoiceRepo,
PaymentRepository $paymentRepo,
VendorRepository $vendorRepo,
ExpenseRepository $expenseRepo)
{
parent::__construct();
$this->faker = Factory::create();
$this->clientRepo = $clientRepo;
$this->invoiceRepo = $invoiceRepo;
$this->paymentRepo = $paymentRepo;
$this->vendorRepo = $vendorRepo;
$this->expenseRepo = $expenseRepo;
}
public function fire()
{
if (Utils::isNinjaProd()) {
return false;
}
$this->info(date('Y-m-d').' Running CreateTestData...');
Auth::loginUsingId(1);
$this->count = $this->argument('count');
$this->createClients();
$this->createVendors();
$this->info('Done');
}
private function createClients()
{
for ($i=0; $i<$this->count; $i++) {
$data = [
'name' => $this->faker->name,
'address1' => $this->faker->streetAddress,
'address2' => $this->faker->secondaryAddress,
'city' => $this->faker->city,
'state' => $this->faker->state,
'postal_code' => $this->faker->postcode,
'contacts' => [[
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
'email' => $this->faker->safeEmail,
'phone' => $this->faker->phoneNumber,
]]
];
$client = $this->clientRepo->save($data);
$this->info('Client: ' . $client->name);
$this->createInvoices($client);
}
}
private function createInvoices($client)
{
for ($i=0; $i<$this->count; $i++) {
$data = [
'client_id' => $client->id,
'invoice_items' => [[
'product_key' => $this->faker->word,
'qty' => $this->faker->randomDigit + 1,
'cost' => $this->faker->randomFloat(2, 1, 10),
'notes' => $this->faker->text($this->faker->numberBetween(50, 300))
]]
];
$invoice = $this->invoiceRepo->save($data);
$this->info('Invoice: ' . $invoice->invoice_number);
$this->createPayment($client, $invoice);
}
}
private function createPayment($client, $invoice)
{
$data = [
'invoice_id' => $invoice->id,
'client_id' => $client->id,
'amount' => $this->faker->randomFloat(2, 0, $invoice->amount)
];
$payment = $this->paymentRepo->save($data);
$this->info('Payment: ' . $payment->amount);
}
private function createVendors()
{
for ($i=0; $i<$this->count; $i++) {
$data = [
'name' => $this->faker->name,
'address1' => $this->faker->streetAddress,
'address2' => $this->faker->secondaryAddress,
'city' => $this->faker->city,
'state' => $this->faker->state,
'postal_code' => $this->faker->postcode,
'vendor_contacts' => [[
'first_name' => $this->faker->firstName,
'last_name' => $this->faker->lastName,
'email' => $this->faker->safeEmail,
'phone' => $this->faker->phoneNumber,
]]
];
$vendor = $this->vendorRepo->save($data);
$this->info('Vendor: ' . $vendor->name);
$this->createExpense($vendor);
}
}
private function createExpense($vendor)
{
for ($i=0; $i<$this->count; $i++) {
$data = [
'vendor_id' => $vendor->id,
'amount' => $this->faker->randomFloat(2, 1, 10),
'expense_date' => null,
'public_notes' => null,
];
$expense = $this->expenseRepo->save($data);
$this->info('Expense: ' . $expense->amount);
}
}
protected function getArguments()
{
return array(
//array('example', InputArgument::REQUIRED, 'An example argument.'),
);
}
protected function getOptions()
{
return array(
//array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
);
}
}

View File

@ -17,6 +17,7 @@ class Kernel extends ConsoleKernel
'App\Console\Commands\ResetData',
'App\Console\Commands\CheckData',
'App\Console\Commands\PruneData',
'App\Console\Commands\CreateTestData',
'App\Console\Commands\SendRenewalInvoices',
'App\Console\Commands\ChargeRenewalInvoices',
'App\Console\Commands\SendReminders',

View File

@ -39,7 +39,7 @@ class Handler extends ExceptionHandler {
return false;
}
if (Utils::isNinja()) {
if (Utils::isNinja() && ! Utils::isTravis()) {
Utils::logError(Utils::getErrorString($e));
return false;
} else {

View File

@ -90,9 +90,22 @@ class BaseAPIController extends Controller
$transformerClass = EntityModel::getTransformerName($this->entityType);
$transformer = new $transformerClass(Auth::user()->account, Input::get('serializer'));
$include = $transformer->getDefaultIncludes();
$include = $this->getRequestIncludes($include);
$query->with($include);
$includes = $transformer->getDefaultIncludes();
$includes = $this->getRequestIncludes($includes);
$query->with($includes);
if ($updatedAt = Input::get('updated_at')) {
$updatedAt = date('Y-m-d H:i:s', $updatedAt);
$query->where(function($query) use ($includes, $updatedAt) {
$query->where('updated_at', '>=', $updatedAt);
foreach ($includes as $include) {
$query->orWhereHas($include, function($query) use ($updatedAt) {
$query->where('updated_at', '>=', $updatedAt);
});
}
});
}
if ($clientPublicId = Input::get('client_id')) {
$filter = function($query) use ($clientPublicId) {
@ -156,7 +169,7 @@ class BaseAPIController extends Controller
if (Utils::isNinjaDev()) {
$count = count(\DB::getQueryLog());
Log::info(Request::method() . ' - ' . Request::url() . ": $count queries");
//Log::info(print_r(\DB::getQueryLog(), true));
Log::info(json_encode(\DB::getQueryLog()));
}
$index = Request::get('index') ?: 'data';
@ -193,23 +206,19 @@ class BaseAPIController extends Controller
protected function getRequestIncludes($data)
{
$data[] = 'user';
$included = Request::get('include');
$included = explode(',', $included);
foreach ($included as $include) {
if ($include == 'invoices') {
$data[] = 'invoices.invoice_items';
$data[] = 'invoices.user';
} elseif ($include == 'client') {
$data[] = 'client.contacts';
} elseif ($include == 'clients') {
$data[] = 'clients.contacts';
$data[] = 'clients.user';
} elseif ($include == 'vendors') {
$data[] = 'vendors.vendorcontacts';
$data[] = 'vendors.user';
}
elseif ($include) {
$data[] = 'vendors.vendor_contacts';
} elseif ($include) {
$data[] = $include;
}
}

View File

@ -143,20 +143,13 @@ class ClientApiController extends BaseAPIController
* )
*/
public function destroy($publicId)
public function destroy(UpdateClientRequest $request)
{
$client = Client::scope($publicId)->withTrashed()->first();
$client = $request->entity();
$this->clientRepo->delete($client);
$client = Client::scope($publicId)
->with('country', 'contacts', 'industry', 'size', 'currency')
->withTrashed()
->first();
$transformer = new ClientTransformer(Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($client, $transformer, ENTITY_CLIENT);
return $this->response($data);
return $this->itemResponse($client);
}
}

View File

@ -30,6 +30,7 @@ class ExpenseApiController extends BaseAPIController
{
$expenses = Expense::scope()
->withTrashed()
->with('client', 'invoice', 'vendor')
->orderBy('created_at','desc');
return $this->listResponse($expenses);

View File

@ -74,7 +74,7 @@ class ExpenseController extends BaseController
public function create(ExpenseRequest $request)
{
if ($request->vendor_id != 0) {
$vendor = Vendor::scope($request->vendor_id)->with('vendorcontacts')->firstOrFail();
$vendor = Vendor::scope($request->vendor_id)->with('vendor_contacts')->firstOrFail();
} else {
$vendor = null;
}
@ -85,7 +85,7 @@ class ExpenseController extends BaseController
'method' => 'POST',
'url' => 'expenses',
'title' => trans('texts.new_expense'),
'vendors' => Vendor::scope()->with('vendorcontacts')->orderBy('name')->get(),
'vendors' => Vendor::scope()->with('vendor_contacts')->orderBy('name')->get(),
'vendor' => $vendor,
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
'clientPublicId' => $request->client_id,
@ -124,7 +124,7 @@ class ExpenseController extends BaseController
'url' => 'expenses/'.$expense->public_id,
'title' => 'Edit Expense',
'actions' => $actions,
'vendors' => Vendor::scope()->with('vendorcontacts')->orderBy('name')->get(),
'vendors' => Vendor::scope()->with('vendor_contacts')->orderBy('name')->get(),
'vendorPublicId' => $expense->vendor ? $expense->vendor->public_id : null,
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
'clientPublicId' => $expense->client ? $expense->client->public_id : null,

View File

@ -164,12 +164,12 @@ class ExportController extends BaseController
if ($request->input(ENTITY_VENDOR)) {
$data['clients'] = Vendor::scope()
->with('user', 'vendorcontacts', 'country')
->with('user', 'vendor_contacts', 'country')
->withArchived()
->get();
$data['vendor_contacts'] = VendorContact::scope()
->with('user', 'vendor.contacts')
->with('user', 'vendor.vendor_contacts')
->withTrashed()
->get();

View File

@ -61,7 +61,7 @@ class InvoiceApiController extends BaseAPIController
{
$invoices = Invoice::scope()
->withTrashed()
->with('invoice_items')
->with('invoice_items', 'client')
->orderBy('created_at', 'desc');
return $this->listResponse($invoices);
@ -359,18 +359,13 @@ class InvoiceApiController extends BaseAPIController
* )
*/
public function destroy($publicId)
public function destroy(UpdateInvoiceAPIRequest $request)
{
$data['public_id'] = $publicId;
$invoice = Invoice::scope($publicId)->firstOrFail();
$invoice = $request->entity();
$this->invoiceRepo->delete($invoice);
$transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($invoice, $transformer, 'invoice');
return $this->response($data);
return $this->itemResponse($invoice);
}
}

View File

@ -49,7 +49,7 @@ class PaymentApiController extends BaseAPIController
{
$payments = Payment::scope()
->withTrashed()
->with(['client.contacts', 'invitation', 'user', 'invoice'])
->with(['invoice'])
->orderBy('created_at', 'desc');
return $this->listResponse($payments);
@ -145,17 +145,13 @@ class PaymentApiController extends BaseAPIController
* )
*/
public function destroy($publicId)
public function destroy(UpdatePaymentRequest $request)
{
$payment = $request->entity();
$payment = Payment::scope($publicId)->withTrashed()->first();
$invoiceId = $payment->invoice->public_id;
$this->clientRepo->delete($payment);
$this->paymentRepo->delete($payment);
$transformer = new PaymentTransformer(\Auth::user()->account, Input::get('serializer'));
$data = $this->createItem($payment, $transformer, 'invoice');
return $this->response($data);
return $this->itemResponse($payment);
}
}

View File

@ -551,7 +551,8 @@ class PaymentController extends BaseController
$payment = $this->paymentService->createPayment($invitation, $accountGateway, $token, $payerId);
Session::flash('message', trans('texts.applied_payment'));
} else {
Session::flash('error', Input::get('message'));
$message = Input::get('message') . ': ' . Input::get('invalid_fields');
Session::flash('error', $message);
}
return Redirect::to($invitation->getLink());
} elseif (method_exists($gateway, 'completePurchase')

View File

@ -81,7 +81,7 @@ class VendorApiController extends BaseAPIController
$vendor = $this->vendorRepo->save($request->input());
$vendor = Vendor::scope($vendor->public_id)
->with('country', 'vendorcontacts', 'industry', 'size', 'currency')
->with('country', 'vendor_contacts', 'industry', 'size', 'currency')
->first();
return $this->itemResponse($vendor);

View File

@ -1,30 +0,0 @@
<?php namespace App\Http\Requests;
use App\Http\Requests\Request;
use Illuminate\Validation\Factory;
class CreatePaymentTermRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'num_days' => 'required',
'name' => 'required',
];
}
}

View File

@ -1,30 +0,0 @@
<?php namespace App\Http\Requests;
use App\Http\Requests\Request;
use Illuminate\Validation\Factory;
class UpdateExpenseRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'amount' => 'required|positive',
];
}
}

View File

@ -9,8 +9,8 @@ class VendorRequest extends EntityRequest {
$vendor = parent::entity();
// eager load the contacts
if ($vendor && ! count($vendor->vendorcontacts)) {
$vendor->load('vendorcontacts');
if ($vendor && ! count($vendor->vendor_contacts)) {
$vendor->load('vendor_contacts');
}
return $vendor;

View File

@ -2,6 +2,8 @@
// https://github.com/denvertimothy/OFX
use Utils;
use Log;
use SimpleXMLElement;
class OFX
@ -21,13 +23,19 @@ class OFX
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $this->bank->url);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/x-ofx'));
// User-Agent: http://www.ofxhome.com/ofxforum/viewtopic.php?pid=108091#p108091
curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/x-ofx', 'User-Agent: httpclient'));
curl_setopt($c, CURLOPT_POSTFIELDS, $this->request);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$this->response = curl_exec($c);
//print_r($this->response);
//\Log::info(print_r($this->response, true));
if (Utils::isNinjaDev()) {
Log::info(print_r($this->response, true));
}
curl_close($c);
$tmp = explode('<OFX>', $this->response);
$this->responseHeader = $tmp[0];
$this->responseBody = '<OFX>'.$tmp[1];
@ -35,14 +43,15 @@ class OFX
public function xml()
{
$xml = $this->responseBody;
self::closeTags($xml);
$xml = self::closeTags($xml);
$x = new SimpleXMLElement($xml);
return $x;
}
public static function closeTags(&$x)
public static function closeTags($x)
{
$x = preg_replace('/(<([^<\/]+)>)(?!.*?<\/\2>)([^<]+)/', '\1\3</\2>', $x);
$x = preg_replace('/\s+/', '', $x);
return preg_replace('/(<([^<\/]+)>)(?!.*?<\/\2>)([^<]+)/', '\1\3</\2>', $x);
}
}
@ -224,3 +233,4 @@ class Account
}
}
}

View File

@ -51,6 +51,11 @@ class Utils
return php_sapi_name() == 'cli';
}
public static function isTravis()
{
return env('TRAVIS') == 'true';
}
public static function isNinja()
{
return self::isNinjaProd() || self::isNinjaDev();

View File

@ -19,6 +19,11 @@ class InvoiceItem extends EntityModel
return $this->belongsTo('App\Models\Invoice');
}
public function user()
{
return $this->belongsTo('App\Models\User')->withTrashed();
}
public function product()
{
return $this->belongsTo('App\Models\Product');

View File

@ -26,6 +26,11 @@ class Product extends EntityModel
return Product::scope()->where('product_key', '=', $key)->first();
}
public function user()
{
return $this->belongsTo('App\Models\User')->withTrashed();
}
public function default_tax_rate()
{
return $this->belongsTo('App\Models\TaxRate');

View File

@ -17,4 +17,9 @@ class TaxRate extends EntityModel
{
return ENTITY_TAX_RATE;
}
public function user()
{
return $this->belongsTo('App\Models\User')->withTrashed();
}
}

View File

@ -95,7 +95,7 @@ class Vendor extends EntityModel
return $this->hasMany('App\Models\Payment');
}
public function vendorContacts()
public function vendor_contacts()
{
return $this->hasMany('App\Models\VendorContact');
}
@ -143,7 +143,7 @@ class Vendor extends EntityModel
$contact->fill($data);
$contact->is_primary = $isPrimary;
return $this->vendorContacts()->save($contact);
return $this->vendor_contacts()->save($contact);
}
public function getRoute()

View File

@ -16,7 +16,7 @@ class VendorRepository extends BaseRepository
public function all()
{
return Vendor::scope()
->with('user', 'vendorcontacts', 'country')
->with('user', 'vendor_contacts', 'country')
->withTrashed()
->where('is_deleted', '=', false)
->get();
@ -71,7 +71,7 @@ class VendorRepository extends BaseRepository
} elseif (!$publicId || $publicId == '-1') {
$vendor = Vendor::createNew();
} else {
$vendor = Vendor::scope($publicId)->with('vendorcontacts')->firstOrFail();
$vendor = Vendor::scope($publicId)->with('vendor_contacts')->firstOrFail();
\Log::warning('Entity not set in vendor repo save');
}
@ -79,7 +79,7 @@ class VendorRepository extends BaseRepository
$vendor->save();
$first = true;
$vendorcontacts = isset($data['vendorcontact']) ? [$data['vendorcontact']] : $data['vendorcontacts'];
$vendorcontacts = isset($data['vendor_contact']) ? [$data['vendor_contact']] : $data['vendor_contacts'];
foreach ($vendorcontacts as $vendorcontact) {
$vendorcontact = $vendor->addVendorContact($vendorcontact, $first);

View File

@ -14,12 +14,12 @@ class AccountTransformer extends EntityTransformer
'users',
'products',
'taxRates',
'payments'
];
protected $availableIncludes = [
'clients',
'invoices',
'payments',
];
public function includeUsers(Account $account)

View File

@ -47,7 +47,7 @@ class ClientTransformer extends EntityTransformer
protected $availableIncludes = [
'invoices',
'credits',
'expenses',
//'expenses',
];
public function includeContacts(Client $client)
@ -77,13 +77,11 @@ class ClientTransformer extends EntityTransformer
public function transform(Client $client)
{
return [
return array_merge($this->getDefaults($client), [
'id' => (int) $client->public_id,
'name' => $client->name,
'balance' => (float) $client->balance,
'paid_to_date' => (float) $client->paid_to_date,
'user_id' => (int) $client->user->public_id + 1,
'account_key' => $this->account->account_key,
'updated_at' => $this->getTimestamp($client->updated_at),
'archived_at' => $this->getTimestamp($client->deleted_at),
'address1' => $client->address1,
@ -106,6 +104,6 @@ class ClientTransformer extends EntityTransformer
'currency_id' => (int) $client->currency_id,
'custom_value1' => $client->custom_value1,
'custom_value2' => $client->custom_value2,
];
]);
}
}

View File

@ -8,7 +8,7 @@ class ContactTransformer extends EntityTransformer
{
public function transform(Contact $contact)
{
return [
return array_merge($this->getDefaults($contact), [
'id' => (int) $contact->public_id,
'first_name' => $contact->first_name,
'last_name' => $contact->last_name,
@ -18,8 +18,7 @@ class ContactTransformer extends EntityTransformer
'is_primary' => (bool) $contact->is_primary,
'phone' => $contact->phone,
'last_login' => $contact->last_login,
'account_key' => $this->account->account_key,
'send_invoice' => (bool) $contact->send_invoice,
];
]);
}
}

View File

@ -8,17 +8,16 @@ class CreditTransformer extends EntityTransformer
{
public function transform(Credit $credit)
{
return [
return array_merge($this->getDefaults($credit), [
'id' => (int) $credit->public_id,
'amount' => (float) $credit->amount,
'balance' => (float) $credit->balance,
'updated_at' => $this->getTimestamp($credit->updated_at),
'archived_at' => $this->getTimestamp($credit->deleted_at),
'is_deleted' => (bool) $credit->is_deleted,
'account_key' => $this->account->account_key,
'credit_date' => $credit->credit_date,
'credit_number' => $credit->credit_number,
'private_notes' => $credit->private_notes,
];
]);
}
}

View File

@ -8,14 +8,12 @@ class DocumentTransformer extends EntityTransformer
{
public function transform(Document $document)
{
return [
return array_merge($this->getDefaults($document), [
'id' => (int) $document->public_id,
'name' => $document->name,
'account_key' => $this->account->account_key,
'type' => $document->type,
'invoice_id' => isset($document->invoice->public_id) ? (int) $document->invoice->public_id : null,
'expense_id' => isset($document->expense->public_id) ? (int) $document->expense->public_id : null,
];
]);
}
}

View File

@ -1,5 +1,6 @@
<?php namespace App\Ninja\Transformers;
use Auth;
use App\Models\Account;
use App\Models\Client;
use League\Fractal\TransformerAbstract;
@ -42,4 +43,18 @@ class EntityTransformer extends TransformerAbstract
{
return $this->defaultIncludes;
}
protected function getDefaults($entity)
{
$data = [
'account_key' => $this->account->account_key,
'is_owner' => (bool) Auth::user()->owns($entity),
];
if ($entity->relationLoaded('user')) {
$data['user_id'] = (int) $entity->user->public_id + 1;
}
return $data;
}
}

View File

@ -15,7 +15,7 @@ class ExpenseTransformer extends EntityTransformer
public function transform(Expense $expense)
{
return [
return array_merge($this->getDefaults($expense), [
'id' => (int) $expense->public_id,
'private_notes' => $expense->private_notes,
'public_notes' => $expense->public_notes,
@ -25,7 +25,6 @@ class ExpenseTransformer extends EntityTransformer
'transaction_id' => $expense->transaction_id,
'bank_id' => $expense->bank_id,
'expense_currency_id' => (int) $expense->expense_currency_id,
'account_key' => $this->account->account_key,
'amount' => (float) $expense->amount,
'expense_date' => $expense->expense_date,
'exchange_rate' => (float) $expense->exchange_rate,
@ -34,6 +33,6 @@ class ExpenseTransformer extends EntityTransformer
'client_id' => $this->client ? $this->client->public_id : (isset($expense->client->public_id) ? (int) $expense->client->public_id : null),
'invoice_id' => isset($expense->invoice->public_id) ? (int) $expense->invoice->public_id : null,
'vendor_id' => isset($expense->vendor->public_id) ? (int) $expense->vendor->public_id : null,
];
]);
}
}

View File

@ -8,11 +8,9 @@ class InvoiceItemTransformer extends EntityTransformer
{
public function transform(InvoiceItem $item)
{
return [
return array_merge($this->getDefaults($item), [
'id' => (int) $item->public_id,
'product_key' => $item->product_key,
'account_key' => $this->account->account_key,
'user_id' => (int) $item->user_id,
'updated_at' => $this->getTimestamp($item->updated_at),
'archived_at' => $this->getTimestamp($item->deleted_at),
'product_key' => $item->product_key,
@ -23,6 +21,6 @@ class InvoiceItemTransformer extends EntityTransformer
'tax_rate1' => (float) $item->tax_rate1,
'tax_name2' => $item->tax_name2 ? $item->tax_name1 : '',
'tax_rate2' => (float) $item->tax_rate2,
];
]);
}
}

View File

@ -28,7 +28,7 @@ class InvoiceTransformer extends EntityTransformer
'invitations',
'payments',
'client',
'expenses',
//'expenses',
];
public function __construct($account = null, $serializer = null, $client = null)
@ -71,7 +71,7 @@ class InvoiceTransformer extends EntityTransformer
public function transform(Invoice $invoice)
{
return [
return array_merge($this->getDefaults($invoice), [
'id' => (int) $invoice->public_id,
'amount' => (float) $invoice->amount,
'balance' => (float) $invoice->balance,
@ -105,8 +105,6 @@ class InvoiceTransformer extends EntityTransformer
'partial' => (float) $invoice->partial,
'has_tasks' => (bool) $invoice->has_tasks,
'auto_bill' => (bool) $invoice->auto_bill,
'account_key' => $this->account->account_key,
'user_id' => (int) $invoice->user->public_id + 1,
'custom_value1' => (float) $invoice->custom_value1,
'custom_value2' => (float) $invoice->custom_value2,
'custom_taxes1' => (bool) $invoice->custom_taxes1,
@ -115,6 +113,6 @@ class InvoiceTransformer extends EntityTransformer
'quote_invoice_id' => (int) $invoice->quote_invoice_id,
'custom_text_value1' => $invoice->custom_text_value1,
'custom_text_value2' => $invoice->custom_text_value2,
];
]);
}
}

View File

@ -47,11 +47,9 @@ class PaymentTransformer extends EntityTransformer
public function transform(Payment $payment)
{
return [
return array_merge($this->getDefaults($payment), [
'id' => (int) $payment->public_id,
'amount' => (float) $payment->amount,
'account_key' => $this->account->account_key,
'user_id' => (int) $payment->user->public_id + 1,
'transaction_reference' => $payment->transaction_reference,
'payment_date' => $payment->payment_date,
'updated_at' => $this->getTimestamp($payment->updated_at),
@ -59,6 +57,6 @@ class PaymentTransformer extends EntityTransformer
'is_deleted' => (bool) $payment->is_deleted,
'payment_type_id' => (int) $payment->payment_type_id,
'invoice_id' => (int) ($this->invoice ? $this->invoice->public_id : $payment->invoice->public_id),
];
]);
}
}

View File

@ -7,16 +7,15 @@ class ProductTransformer extends EntityTransformer
{
public function transform(Product $product)
{
return [
return array_merge($this->getDefaults($product), [
'id' => (int) $product->public_id,
'product_key' => $product->product_key,
'notes' => $product->notes,
'cost' => $product->cost,
'qty' => $product->qty,
'account_key' =>$this->account->account_key,
'default_tax_rate_id' =>$product->default_tax_rate_id,
'updated_at' =>$this->getTimestamp($product->updated_at),
'archived_at' => $this->getTimestamp($product->deleted_at),
];
]);
}
}

View File

@ -39,12 +39,10 @@ class TaskTransformer extends EntityTransformer
public function transform(Task $task)
{
return [
return array_merge($this->getDefaults($task), [
'id' => (int) $task->public_id,
'account_key' => $this->account->account_key,
'user_id' => (int) $task->user->public_id + 1,
'description' => $task->description,
'duration' => $task->getDuration()
];
]);
}
}

View File

@ -21,13 +21,12 @@ class TaxRateTransformer extends EntityTransformer
public function transform(TaxRate $taxRate)
{
return [
return array_merge($this->getDefaults($taxRate), [
'id' => (int) $taxRate->public_id,
'name' => $taxRate->name,
'rate' => (float) $taxRate->rate,
'updated_at' => $this->getTimestamp($taxRate->updated_at),
'archived_at' => $this->getTimestamp($taxRate->deleted_at),
'account_key' => $this->account->account_key,
];
]);
}
}

View File

@ -8,7 +8,7 @@ class VendorContactTransformer extends EntityTransformer
{
public function transform(VendorContact $contact)
{
return [
return array_merge($this->getDefaults($contact), [
'id' => (int) $contact->public_id,
'first_name' => $contact->first_name,
'last_name' => $contact->last_name,
@ -17,7 +17,6 @@ class VendorContactTransformer extends EntityTransformer
'archived_at' => $this->getTimestamp($contact->deleted_at),
'is_primary' => (bool) $contact->is_primary,
'phone' => $contact->phone,
'account_key' => $this->account->account_key,
];
]);
}
}

View File

@ -35,16 +35,19 @@ class VendorTransformer extends EntityTransformer
* @SWG\Property(property="id_number", type="string", example="123456")
*/
protected $defaultIncludes = [
'vendor_contacts',
];
protected $availableIncludes = [
'vendorContacts',
'invoices',
'expenses',
//'expenses',
];
public function includeVendorContacts(Vendor $vendor)
{
$transformer = new VendorContactTransformer($this->account, $this->serializer);
return $this->includeCollection($vendor->vendorContacts, $transformer, ENTITY_CONTACT);
return $this->includeCollection($vendor->vendor_contacts, $transformer, ENTITY_CONTACT);
}
public function includeInvoices(Vendor $vendor)
@ -61,13 +64,11 @@ class VendorTransformer extends EntityTransformer
public function transform(Vendor $vendor)
{
return [
return array_merge($this->getDefaults($vendor), [
'id' => (int) $vendor->public_id,
'name' => $vendor->name,
'balance' => (float) $vendor->balance,
'paid_to_date' => (float) $vendor->paid_to_date,
'user_id' => (int) $vendor->user->public_id + 1,
'account_key' => $this->account->account_key,
'updated_at' => $this->getTimestamp($vendor->updated_at),
'archived_at' => $this->getTimestamp($vendor->deleted_at),
'address1' => $vendor->address1,
@ -84,6 +85,6 @@ class VendorTransformer extends EntityTransformer
'vat_number' => $vendor->vat_number,
'id_number' => $vendor->id_number,
'currency_id' => (int) $vendor->currency_id
];
]);
}
}

View File

@ -0,0 +1,48 @@
<?php
use App\Models\Client;
use App\Models\Contact;
use App\Models\Country;
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/
$factory->define(Contact::class, function (Faker\Generator $faker) {
return [
'client_id' => function() {
return factory(Client::class)->create()->id;
},
'user_id' => 1,
'account_id' => 1,
'public_id' => Contact::count() + 1,
'is_primary' => true,
'send_invoice' => true,
'first_name' => $faker->firstName,
'last_name' => $faker->lastName,
'email' => $faker->safeEmail,
'phone' => $faker->phoneNumber,
];
});
$factory->define(Client::class, function (Faker\Generator $faker) {
return [
'user_id' => 1,
'account_id' => 1,
'public_id' => Client::count() + 1,
'name' => $faker->name,
'address1' => $faker->streetAddress,
'address2' => $faker->secondaryAddress,
'city' => $faker->city,
'state' => $faker->state,
'postal_code' => $faker->postcode,
'country_id' => Country::all()->random()->id,
];
});

View File

@ -382,11 +382,11 @@ return array(
'converted_to_invoice' => 'Il preventivo è stato convertito a fattura con successo',
'quote_subject' => 'Nuovo preventivo da :account',
'quote_message' => 'Per visualizzare il vostro preventivo per :amount, cliccare il collegamento sotto.',
'quote_link_message' => 'Per visualizzare il preventivo del vostro cliante cliccate il collegamento sotto:',
'quote_message' => 'Per visualizzare il vostro preventivo di :amount, cliccate il collegamento sotto.',
'quote_link_message' => 'Per visualizzare il preventivo del vostro cliente cliccate il collegamento sotto:',
'notification_quote_sent_subject' => 'Il preventivo :invoice è stato inviato a :client',
'notification_quote_viewed_subject' => 'Il preventivo :invoice è stato visualizzato da :client',
'notification_quote_sent' => 'Al seguente cliente :client è stata inviata la fattura :invoice per :amount.',
'notification_quote_sent' => 'Al seguente cliente :client è stata inviato il preventivo :invoice per un importo di :amount.',
'notification_quote_viewed' => 'Il seguente cliente :client ha visualizzato il preventivo :invoice di :amount.',
'session_expired' => 'La vostra sessione è scaduta.',
@ -728,12 +728,12 @@ return array(
'header' => 'Header',
'footer' => 'Footer',
'custom' => 'Custom',
'invoice_to' => 'Invoice to',
'invoice_no' => 'Invoice No.',
'recent_payments' => 'Recent Payments',
'outstanding' => 'Outstanding',
'manage_companies' => 'Manage Companies',
'total_revenue' => 'Total Revenue',
'invoice_to' => 'Fattura a',
'invoice_no' => 'Fattura N.',
'recent_payments' => 'Pagamenti recenti',
'outstanding' => 'Inevaso',
'manage_companies' => 'Gestisci aziende',
'total_revenue' => 'Ricavo totale',
'current_user' => 'Current User',
'new_recurring_invoice' => 'Nuova Fattura Ricorrente',
@ -784,7 +784,7 @@ return array(
'last_sent_on' => 'Last sent on :date',
'page_expire' => 'This page will expire soon, :click_here to keep working',
'upcoming_quotes' => 'Upcoming Quotes',
'upcoming_quotes' => 'Preventivi in scadenza',
'expired_quotes' => 'Preventivi Scaduti',
'sign_up_using' => 'Sign up using',
@ -842,19 +842,19 @@ return array(
'quote_counter' => 'Quote Counter',
'type' => 'Type',
'activity_1' => ':user created client :client',
'activity_2' => ':user archived client :client',
'activity_1' => ':user ha creato il cliente :client',
'activity_2' => ':user ha archiviato il cliente :client',
'activity_3' => ':user deleted client :client',
'activity_4' => ':user ha creato la fattura :invoice',
'activity_5' => ':user ha aggiornato la fattura :invoice',
'activity_6' => ':user emailed invoice :invoice to :contact',
'activity_7' => ':contact viewed invoice :invoice',
'activity_8' => ':user archived invoice :invoice',
'activity_9' => ':user deleted invoice :invoice',
'activity_10' => ':contact entered payment :payment for :invoice',
'activity_11' => ':user updated payment :payment',
'activity_12' => ':user archived payment :payment',
'activity_13' => ':user deleted payment :payment',
'activity_6' => ':user ha inviato per email la fattura :invoice a :contact',
'activity_7' => ':contact ha visto la fattura :invoice',
'activity_8' => ':user ha archiviato la fattura :invoice',
'activity_9' => ':user ha cancellato la fattura :invoice',
'activity_10' => ':contact ha inserito il pagamento :payment per :invoice',
'activity_11' => ':user ha aggiornato il pagamento :payment',
'activity_12' => ':user ha archiviato il pagamento :payment',
'activity_13' => ':user ha cancellato il pagamento :payment',
'activity_14' => ':user entered :credit credit',
'activity_15' => ':user updated :credit credit',
'activity_16' => ':user archived :credit credit',
@ -862,7 +862,7 @@ return array(
'activity_18' => ':user created quote :quote',
'activity_19' => ':user updated quote :quote',
'activity_20' => ':user emailed quote :quote to :contact',
'activity_21' => ':contact viewed quote :quote',
'activity_21' => ':contact ha visto il preventivo :quote',
'activity_22' => ':user archived quote :quote',
'activity_23' => ':user deleted quote :quote',
'activity_24' => ':user restored quote :quote',
@ -870,7 +870,7 @@ return array(
'activity_26' => ':user restored client :client',
'activity_27' => ':user restored payment :payment',
'activity_28' => ':user restored :credit credit',
'activity_29' => ':contact approved quote :quote',
'activity_29' => ':contact ha approvato la fattura :quote',
'payment' => 'Payment',
'system' => 'System',
@ -1004,33 +1004,33 @@ return array(
'archived_expenses' => 'Successfully archived expenses',
// Expenses
'expense_amount' => 'Expense Amount',
'expense_balance' => 'Expense Balance',
'expense_date' => 'Expense Date',
'expense_should_be_invoiced' => 'Should this expense be invoiced?',
'public_notes' => 'Public Notes',
'invoice_amount' => 'Invoice Amount',
'exchange_rate' => 'Exchange Rate',
'yes' => 'Yes',
'expense_amount' => 'Importo Spesa',
'expense_balance' => 'Bilancio Spesa',
'expense_date' => 'Data Spesa',
'expense_should_be_invoiced' => 'Questa spesa deve essere fatturata?',
'public_notes' => 'Note Pubbliche (Descrizione in fattura)',
'invoice_amount' => 'Importo Fattura',
'exchange_rate' => 'Tasso di Cambio',
'yes' => 'Si',
'no' => 'No',
'should_be_invoiced' => 'Should be invoiced',
'view_expense' => 'View expense # :expense',
'edit_expense' => 'Edit Expense',
'archive_expense' => 'Archive Expense',
'delete_expense' => 'Delete Expense',
'view_expense_num' => 'Expense # :expense',
'updated_expense' => 'Successfully updated expense',
'created_expense' => 'Successfully created expense',
'enter_expense' => 'Enter Expense',
'view' => 'View',
'restore_expense' => 'Restore Expense',
'invoice_expense' => 'Invoice Expense',
'expense_error_multiple_clients' =>'The expenses can\'t belong to different clients',
'expense_error_invoiced' => 'Expense has already been invoiced',
'convert_currency' => 'Convert currency',
'should_be_invoiced' => 'Deve essere fatturata',
'view_expense' => 'Vedi spesa # :expense',
'edit_expense' => 'Modifica Spesa',
'archive_expense' => 'Archivia Spesa',
'delete_expense' => 'Cancella Spesa',
'view_expense_num' => 'Spesa # :expense',
'updated_expense' => 'Spesa aggiornata con successo',
'created_expense' => 'Spesa creata con successo',
'enter_expense' => 'Inserisci Spesa',
'view' => 'Vedi',
'restore_expense' => 'Ripristina Spesa',
'invoice_expense' => 'Fattura Spesa',
'expense_error_multiple_clients' =>'Le spese non possono appartenere a clienti differenti',
'expense_error_invoiced' => 'La spesa è stata già fatturata',
'convert_currency' => 'Converti valuta',
// Payment terms
'num_days' => 'Number of days',
'num_days' => 'Numero di giorni',
'create_payment_term' => 'Create Payment Term',
'edit_payment_terms' => 'Edit Payment Term',
'edit_payment_term' => 'Edit Payment Term',
@ -1053,17 +1053,17 @@ return array(
</ul>',
'due' => 'Due',
'next_due_on' => 'Due Next: :date',
'use_client_terms' => 'Use client terms',
'day_of_month' => ':ordinal day of month',
'last_day_of_month' => 'Last day of month',
'day_of_week_after' => ':ordinal :day after',
'sunday' => 'Sunday',
'monday' => 'Monday',
'tuesday' => 'Tuesday',
'wednesday' => 'Wednesday',
'thursday' => 'Thursday',
'friday' => 'Friday',
'saturday' => 'Saturday',
'use_client_terms' => 'Usa i termini del cliente',
'day_of_month' => ':ordinal giorno del mese',
'last_day_of_month' => 'L\'ultimo giorno del mese',
'day_of_week_after' => ':ordinal :day dopo',
'sunday' => 'Domenica',
'monday' => 'Lunedì',
'tuesday' => 'Martedì',
'wednesday' => 'Mercoledì',
'thursday' => 'Giovedì',
'friday' => 'Venerdì',
'saturday' => 'Sabato',
// Fonts
'header_font_id' => 'Header Font',
@ -1182,17 +1182,17 @@ return array(
'edit_all_help' => 'Allow user to modify records they didn\'t create',
'view_payment' => 'View Payment',
'january' => 'January',
'february' => 'February',
'march' => 'March',
'april' => 'April',
'may' => 'May',
'june' => 'June',
'july' => 'July',
'august' => 'August',
'september' => 'September',
'october' => 'October',
'november' => 'November',
'december' => 'December',
'january' => 'Gennaio',
'february' => 'Febbraio',
'march' => 'Marzo',
'april' => 'Aprile',
'may' => 'Maggio',
'june' => 'Giugno',
'july' => 'Luglio',
'august' => 'Agosto',
'september' => 'Settembre',
'october' => 'Ottobre',
'november' => 'Novembre',
'december' => 'Dicembre',
);

View File

@ -0,0 +1,20 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Poprzedni',
'next' => 'Następny &raquo;',
);

View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
"password" => "Hasło musi mieć conajmniej sześć znaków i być takie samo jak potwierdzające.",
"user" => "Użytkownik o podanym adresie e-mail nie istnieje.",
"token" => "Wprowadzony token jest nieprawidłowy.",
"sent" => "Link do resetowania hasła został wysłany.",
"reset" => "Twoje hasło zostało zresetowane!",
];

View File

@ -0,0 +1,24 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
"password" => "Hasło musi mieć conajmniej sześć znaków i być takie samo jak potwierdzające.",
"user" => "Użytkownik o podanym adresie e-mail nie istnieje.",
"token" => "Wprowadzony token jest nieprawidłowy.",
"sent" => "Przypomnienie hasła zostało wysłane!",
);

1184
resources/lang/pl/texts.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,106 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| such as the size rules. Feel free to tweak each of these messages.
|
*/
"accepted" => ":attribute musi być zaakceptowany.",
"active_url" => ":attribute nie jest poprawnym URL-em.",
"after" => ":attribute musi być datą za :date.",
"alpha" => ":attribute może zawierać tylko litery.",
"alpha_dash" => ":attribute może zawierać tylko litery, liczby i myślniki.",
"alpha_num" => ":attribute może zawierać tylko litery i liczby.",
"array" => ":attribute musi być tablicą.",
"before" => ":attribute musi być datą przed :date.",
"between" => array(
"numeric" => ":attribute musi być pomiędzy :min - :max.",
"file" => ":attribute musi mieć rozmiar pomiędzy :min - :max kilobajtów.",
"string" => ":attribute musi mieć pomiędzy :min - :max znaków.",
"array" => ":attribute musi zawierać :min - :max pozycji.",
),
"confirmed" => ":attribute potwierdzenie nie jest zgodne.",
"date" => ":attribute nie jest prawidłową datą.",
"date_format" => ":attribute nie jest zgodne z formatem :format.",
"different" => ":attribute i :other muszą być różne.",
"digits" => ":attribute musi mieć :digits cyfr.",
"digits_between" => ":attribute musi być w przedziale od :min do :max cyfr.",
"email" => ":attribute format jest nieprawidłowy.",
"exists" => "Zaznaczony :attribute jest niepoprawny.",
"image" => ":attribute musi być zdjęciem.",
"in" => "Zaznaczony :attribute jest niepoprawny.",
"integer" => ":attribute musi być liczbą całkowitą.",
"ip" => ":attribute musi być poprawnym adresem IP.",
"max" => array(
"numeric" => ":attribute nie może być większy niż :max.",
"file" => ":attribute nie może być większy niż :max kilobajtów.",
"string" => ":attribute nie może być dłuższy niż :max znaków.",
"array" => ":attribute nie może zawierać więcej niż :max pozycji.",
),
"mimes" => ":attribute musi być plikiem o typie: :values.",
"min" => array(
"numeric" => ":attribute musi być przynajmniej :min.",
"file" => ":attribute musi mieć przynajmniej :min kilobajtów.",
"string" => ":attribute musi mieć przynajmniej :min znaków.",
"array" => ":attribute musi zawierać przynajmniej :min pozycji.",
),
"not_in" => "Zaznaczony :attribute jest niepoprawny.",
"numeric" => ":attribute musi być cyfrą.",
"regex" => ":attribute format jest niepoprawny.",
"required" => ":attribute pole jest wymagane.",
"required_if" => ":attribute pole jest wymagane jeśli :other ma :value.",
"required_with" => ":attribute pole jest wymagane kiedy :values jest obecne.",
"required_without" => ":attribute pole jest wymagane kiedy :values nie występuje.",
"same" => ":attribute i :other muszą być takie same.",
"size" => array(
"numeric" => ":attribute musi mieć :size.",
"file" => ":attribute musi mieć :size kilobajtów.",
"string" => ":attribute musi mieć :size znaków.",
"array" => ":attribute musi zawierać :size pozycji.",
),
"unique" => ":attribute już istnieje.",
"url" => ":attribute format jest nieprawidłowy.",
"positive" => ":attribute musi być większe niż zero.",
"has_credit" => "Klient ma niewystarczająco kredytu.",
"notmasked" => "Wartości są maskowane",
"less_than" => ":attribute musi być mniejsze od :value",
"has_counter" => "Wartość musi zawierać {\$counter}",
"valid_contacts" => "Kontakt musi posiadać e-mail lub nazwę",
"valid_invoice_items" => "Faktura przekracza maksymalną kwotę",
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => array(),
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => array(),
);

View File

@ -7,8 +7,8 @@
@section('content')
@if ($errors->first('vendorcontacts'))
<div class="alert alert-danger">{{ trans($errors->first('vendorcontacts')) }}</div>
@if ($errors->first('vendor_contacts'))
<div class="alert alert-danger">{{ trans($errors->first('vendor_contacts')) }}</div>
@endif
<div class="row">
@ -73,26 +73,26 @@
</div>
<div class="panel-body">
<div data-bind='template: { foreach: vendorcontacts,
<div data-bind='template: { foreach: vendor_contacts,
beforeRemove: hideContact,
afterAdd: showContact }'>
{!! Former::hidden('public_id')->data_bind("value: public_id, valueUpdate: 'afterkeydown',
attr: {name: 'vendorcontacts[' + \$index() + '][public_id]'}") !!}
attr: {name: 'vendor_contacts[' + \$index() + '][public_id]'}") !!}
{!! Former::text('first_name')->data_bind("value: first_name, valueUpdate: 'afterkeydown',
attr: {name: 'vendorcontacts[' + \$index() + '][first_name]'}") !!}
attr: {name: 'vendor_contacts[' + \$index() + '][first_name]'}") !!}
{!! Former::text('last_name')->data_bind("value: last_name, valueUpdate: 'afterkeydown',
attr: {name: 'vendorcontacts[' + \$index() + '][last_name]'}") !!}
attr: {name: 'vendor_contacts[' + \$index() + '][last_name]'}") !!}
{!! Former::text('email')->data_bind("value: email, valueUpdate: 'afterkeydown',
attr: {name: 'vendorcontacts[' + \$index() + '][email]', id:'email'+\$index()}") !!}
attr: {name: 'vendor_contacts[' + \$index() + '][email]', id:'email'+\$index()}") !!}
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
attr: {name: 'vendorcontacts[' + \$index() + '][phone]'}") !!}
attr: {name: 'vendor_contacts[' + \$index() + '][phone]'}") !!}
<div class="form-group">
<div class="col-lg-8 col-lg-offset-4 bold">
<span class="redlink bold" data-bind="visible: $parent.vendorcontacts().length > 1">
<span class="redlink bold" data-bind="visible: $parent.vendor_contacts().length > 1">
{!! link_to('#', trans('texts.remove_contact').' -', array('data-bind'=>'click: $parent.removeContact')) !!}
</span>
<span data-bind="visible: $index() === ($parent.vendorcontacts().length - 1)" class="pull-right greenlink bold">
<span data-bind="visible: $index() === ($parent.vendor_contacts().length - 1)" class="pull-right greenlink bold">
{!! link_to('#', trans('texts.add_contact').' +', array('onclick'=>'return addContact()')) !!}
</span>
</div>
@ -186,10 +186,10 @@
function VendorModel(data) {
var self = this;
self.vendorcontacts = ko.observableArray();
self.vendor_contacts = ko.observableArray();
self.mapping = {
'vendorcontacts': {
'vendor_contacts': {
create: function(options) {
return new VendorContactModel(options.data);
}
@ -199,12 +199,12 @@
if (data) {
ko.mapping.fromJS(data, self.mapping, this);
} else {
self.vendorcontacts.push(new VendorContactModel());
self.vendor_contacts.push(new VendorContactModel());
}
self.placeholderName = ko.computed(function() {
if (self.vendorcontacts().length == 0) return '';
var contact = self.vendorcontacts()[0];
if (self.vendor_contacts().length == 0) return '';
var contact = self.vendor_contacts()[0];
if (contact.first_name() || contact.last_name()) {
return contact.first_name() + ' ' + contact.last_name();
} else {
@ -226,12 +226,12 @@
ko.applyBindings(model);
function addContact() {
model.vendorcontacts.push(new VendorContactModel());
model.vendor_contacts.push(new VendorContactModel());
return false;
}
model.removeContact = function() {
model.vendorcontacts.remove(this);
model.vendor_contacts.remove(this);
}

View File

@ -109,7 +109,7 @@
<div class="col-md-3">
<h3>{{ trans('texts.contacts') }}</h3>
@foreach ($vendor->vendorcontacts as $contact)
@foreach ($vendor->vendor_contacts as $contact)
@if ($contact->first_name || $contact->last_name)
<b>{{ $contact->first_name.' '.$contact->last_name }}</b><br/>
@endif

View File

@ -78,7 +78,7 @@ class APICest
$data = new stdClass;
$data->name = $this->faker->word;
$data->vendorcontacts = [];
$data->vendor_contacts = [];
$this->createEntity('vendor', $data);
$this->listEntities('vendor');

View File

@ -44,13 +44,14 @@ class ExpenseCest
$I->selectDropdown($I, $vendorName, '.vendor-select .dropdown-toggle');
$I->selectDropdown($I, $clientEmail, '.client-select .dropdown-toggle');
$I->click('Save');
$I->wait(2);
$I->seeInDatabase('expenses', ['vendor_id' => $vendorId]);
// invoice expense
$I->executeJS('submitAction(\'invoice\')');
$I->wait(3);
$I->wait(2);
$I->click('Save');
$I->wait(3);
$I->wait(2);
$I->see($clientEmail);
$I->see($amount);
}