public function edit($publicId)
 {
     $payment = Payment::scope($publicId)->firstOrFail();
     $payment->payment_date = Utils::fromSqlDate($payment->payment_date);
     $data = array('client' => null, 'invoice' => null, 'invoices' => Invoice::scope()->where('is_recurring', '=', false)->where('is_quote', '=', false)->with('client', 'invoice_status')->orderBy('invoice_number')->get(), 'payment' => $payment, 'method' => 'PUT', 'url' => 'payments/' . $publicId, 'title' => trans('texts.edit_payment'), 'paymentTypes' => Cache::get('paymentTypes'), 'clients' => Client::scope()->with('contacts')->orderBy('name')->get());
     return View::make('payments.edit', $data);
 }
 private function getData($request)
 {
     $account = Auth::user()->account;
     $data = ['account' => $account, 'title' => 'Invoice Ninja v' . NINJA_VERSION . ' - ' . $account->formatDateTime($account->getDateTime()), 'multiUser' => $account->users->count() > 1];
     if ($request->input(ENTITY_CLIENT)) {
         $data['clients'] = Client::scope()->with('user', 'contacts', 'country')->withArchived()->get();
         $data['contacts'] = Contact::scope()->with('user', 'client.contacts')->withTrashed()->get();
         $data['credits'] = Credit::scope()->with('user', 'client.contacts')->get();
     }
     if ($request->input(ENTITY_TASK)) {
         $data['tasks'] = Task::scope()->with('user', 'client.contacts')->withArchived()->get();
     }
     if ($request->input(ENTITY_INVOICE)) {
         $data['invoices'] = Invoice::scope()->with('user', 'client.contacts', 'invoice_status')->withArchived()->where('is_quote', '=', false)->where('is_recurring', '=', false)->get();
         $data['quotes'] = Invoice::scope()->with('user', 'client.contacts', 'invoice_status')->withArchived()->where('is_quote', '=', true)->where('is_recurring', '=', false)->get();
         $data['recurringInvoices'] = Invoice::scope()->with('user', 'client.contacts', 'invoice_status', 'frequency')->withArchived()->where('is_quote', '=', false)->where('is_recurring', '=', true)->get();
     }
     if ($request->input(ENTITY_PAYMENT)) {
         $data['payments'] = Payment::scope()->withArchived()->with('user', 'client.contacts', 'payment_type', 'invoice', 'account_gateway.gateway')->get();
     }
     if ($request->input(ENTITY_VENDOR)) {
         $data['clients'] = Vendor::scope()->with('user', 'vendorcontacts', 'country')->withArchived()->get();
         $data['vendor_contacts'] = VendorContact::scope()->with('user', 'vendor.contacts')->withTrashed()->get();
         /*
         $data['expenses'] = Credit::scope()
             ->with('user', 'client.contacts')
             ->get();
         */
     }
     return $data;
 }
 public function edit($publicId)
 {
     $credit = Credit::scope($publicId)->firstOrFail();
     $credit->credit_date = Utils::fromSqlDate($credit->credit_date);
     $data = array('client' => null, 'credit' => $credit, 'method' => 'PUT', 'url' => 'credits/' . $publicId, 'title' => 'Edit Credit', 'clients' => Client::scope()->with('contacts')->orderBy('name')->get());
     return View::make('credit.edit', $data);
 }
 public function save($data)
 {
     $publicId = isset($data['public_id']) ? $data['public_id'] : false;
     if (!$publicId || $publicId == '-1') {
         $client = Client::createNew();
     } else {
         $client = Client::scope($publicId)->with('contacts')->firstOrFail();
     }
     $client->fill($data);
     $client->save();
     /*
     if ( ! isset($data['contact']) && ! isset($data['contacts'])) {
         return $client;
     }
     */
     $first = true;
     $contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts'];
     $contactIds = [];
     foreach ($contacts as $contact) {
         $contact = $client->addContact($contact, $first);
         $contactIds[] = $contact->public_id;
         $first = false;
     }
     foreach ($client->contacts as $contact) {
         if (!in_array($contact->public_id, $contactIds)) {
             $contact->delete();
         }
     }
     return $client;
 }
 /**
  * @SWG\Post(
  *   path="/clients",
  *   tags={"client"},
  *   summary="Create a client",
  *   @SWG\Parameter(
  *     in="body",
  *     name="body",
  *     @SWG\Schema(ref="#/definitions/Client")
  *   ),
  *   @SWG\Response(
  *     response=200,
  *     description="New client",
  *      @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Client"))
  *   ),
  *   @SWG\Response(
  *     response="default",
  *     description="an ""unexpected"" error"
  *   )
  * )
  */
 public function store(CreateClientRequest $request)
 {
     $client = $this->clientRepo->save($request->input());
     $client = Client::scope($client->public_id)->with('country', 'contacts', 'industry', 'size', 'currency')->first();
     $transformer = new ClientTransformer(Auth::user()->account, Input::get('serializer'));
     $data = $this->createItem($client, $transformer, ENTITY_CLIENT);
     return $this->response($data);
 }
 public function index()
 {
     $clients = Client::scope()->with('contacts')->orderBy('created_at', 'desc')->get();
     $clients = Utils::remapPublicIds($clients->toArray());
     $response = json_encode($clients, JSON_PRETTY_PRINT);
     $headers = Utils::getApiHeaders(count($clients));
     return Response::make($response, 200, $headers);
 }
 /**
  * Handle an incoming request.
  *
  * @param  \Illuminate\Http\Request  $request
  * @param  \Closure  $next
  * @return mixed
  */
 public function handle($request, Closure $next)
 {
     if ($this->auth->check() && Client::scope()->count() > 0) {
         Session::reflash();
         return new RedirectResponse(url('/dashboard'));
     }
     return $next($request);
 }
 /**
  * @SWG\Post(
  *   path="/clients",
  *   tags={"client"},
  *   summary="Create a client",
  *   @SWG\Parameter(
  *     in="body",
  *     name="body",
  *     @SWG\Schema(ref="#/definitions/Client")
  *   ),
  *   @SWG\Response(
  *     response=200,
  *     description="New client",
  *      @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Client"))
  *   ),
  *   @SWG\Response(
  *     response="default",
  *     description="an ""unexpected"" error"
  *   )
  * )
  */
 public function store(CreateClientRequest $request)
 {
     $client = $this->clientRepo->save($request->input());
     $client = Client::scope($client->public_id)->with('country', 'contacts', 'industry', 'size', 'currency')->first();
     $client = Utils::remapPublicIds([$client]);
     $response = json_encode($client, JSON_PRETTY_PRINT);
     $headers = Utils::getApiHeaders();
     return Response::make($response, 200, $headers);
 }
 /**
  * @SWG\Get(
  *   path="/clients",
  *   summary="List of clients",
  *   tags={"client"},
  *   @SWG\Response(
  *     response=200,
  *     description="A list with clients",
  *      @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Client"))
  *   ),
  *   @SWG\Response(
  *     response="default",
  *     description="an ""unexpected"" error"
  *   )
  * )
  */
 public function index()
 {
     $clients = Client::scope()->orderBy('created_at', 'desc')->withTrashed();
     // Filter by email
     if ($email = Input::get('email')) {
         $clients = $clients->whereHas('contacts', function ($query) use($email) {
             $query->where('email', $email);
         });
     }
     return $this->listResponse($clients);
 }
 public function save($data, $client = null)
 {
     $publicId = isset($data['public_id']) ? $data['public_id'] : false;
     if ($client) {
         // do nothing
     } elseif (!$publicId || $publicId == '-1') {
         $client = Client::createNew();
     } else {
         $client = Client::scope($publicId)->with('contacts')->firstOrFail();
         \Log::warning('Entity not set in client repo save');
     }
     // convert currency code to id
     if (isset($data['currency_code'])) {
         $currencyCode = strtolower($data['currency_code']);
         $currency = Cache::get('currencies')->filter(function ($item) use($currencyCode) {
             return strtolower($item->code) == $currencyCode;
         })->first();
         if ($currency) {
             $data['currency_id'] = $currency->id;
         }
     }
     $client->fill($data);
     $client->save();
     /*
     if ( ! isset($data['contact']) && ! isset($data['contacts'])) {
         return $client;
     }
     */
     $first = true;
     $contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts'];
     $contactIds = [];
     // If the primary is set ensure it's listed first
     usort($contacts, function ($left, $right) {
         return (isset($right['is_primary']) ? $right['is_primary'] : 1) - (isset($left['is_primary']) ? $left['is_primary'] : 0);
     });
     foreach ($contacts as $contact) {
         $contact = $client->addContact($contact, $first);
         $contactIds[] = $contact->public_id;
         $first = false;
     }
     foreach ($client->contacts as $contact) {
         if (!in_array($contact->public_id, $contactIds)) {
             $contact->delete();
         }
     }
     if (!$publicId || $publicId == '-1') {
         event(new ClientWasCreated($client));
     } else {
         event(new ClientWasUpdated($client));
     }
     return $client;
 }
 private static function getViewModel()
 {
     // Tax rate $options
     $account = Auth::user()->account;
     $rates = TaxRate::scope()->orderBy('name')->get();
     $options = [];
     $defaultTax = false;
     foreach ($rates as $rate) {
         $options[$rate->rate . ' ' . $rate->name] = $rate->name . ' ' . ($rate->rate + 0) . '%';
         // load default invoice tax
         if ($rate->id == $account->default_tax_rate_id) {
             $defaultTax = $rate;
         }
     }
     return ['entityType' => ENTITY_QUOTE, 'account' => Auth::user()->account, 'products' => Product::scope()->orderBy('id')->get(['product_key', 'notes', 'cost', 'qty']), 'taxRateOptions' => $options, 'defaultTax' => $defaultTax, 'countries' => Cache::get('countries'), 'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->orderBy('name')->get(), 'currencies' => Cache::get('currencies'), 'sizes' => Cache::get('sizes'), 'paymentTerms' => Cache::get('paymentTerms'), 'languages' => Cache::get('languages'), 'industries' => Cache::get('industries'), 'invoiceDesigns' => InvoiceDesign::getDesigns(), 'invoiceFonts' => Cache::get('fonts'), 'invoiceLabels' => Auth::user()->account->getInvoiceLabels(), 'isRecurring' => false];
 }
 public function store()
 {
     $data = Input::all();
     $error = $this->clientRepo->getErrors($data);
     if ($error) {
         $headers = Utils::getApiHeaders();
         return Response::make($error, 500, $headers);
     } else {
         $client = $this->clientRepo->save(isset($data['id']) ? $data['id'] : false, $data, false);
         $client = Client::scope($client->public_id)->with('country', 'contacts', 'industry', 'size', 'currency')->first();
         $client = Utils::remapPublicIds([$client]);
         $response = json_encode($client, JSON_PRETTY_PRINT);
         $headers = Utils::getApiHeaders();
         return Response::make($response, 200, $headers);
     }
 }
 /**
  * @param array $data
  * @param Invoice|null $invoice
  * @return \App\Models\Invoice|Invoice|mixed
  */
 public function save(array $data, Invoice $invoice = null)
 {
     if (isset($data['client'])) {
         $canSaveClient = false;
         $canViewClient = false;
         $clientPublicId = array_get($data, 'client.public_id') ?: array_get($data, 'client.id');
         if (empty($clientPublicId) || $clientPublicId == '-1') {
             $canSaveClient = Auth::user()->can('create', ENTITY_CLIENT);
         } else {
             $client = Client::scope($clientPublicId)->first();
             $canSaveClient = Auth::user()->can('edit', $client);
             $canViewClient = Auth::user()->can('view', $client);
         }
         if ($canSaveClient) {
             $client = $this->clientRepo->save($data['client']);
         }
         if ($canSaveClient || $canViewClient) {
             $data['client_id'] = $client->id;
         }
     }
     $invoice = $this->invoiceRepo->save($data, $invoice);
     $client = $invoice->client;
     $client->load('contacts');
     $sendInvoiceIds = [];
     foreach ($client->contacts as $contact) {
         if ($contact->send_invoice) {
             $sendInvoiceIds[] = $contact->id;
         }
     }
     // if no contacts are selected auto-select the first to enusre there's an invitation
     if (!count($sendInvoiceIds)) {
         $sendInvoiceIds[] = $client->contacts[0]->id;
     }
     foreach ($client->contacts as $contact) {
         $invitation = Invitation::scope()->whereContactId($contact->id)->whereInvoiceId($invoice->id)->first();
         if (in_array($contact->id, $sendInvoiceIds) && !$invitation) {
             $invitation = Invitation::createNew();
             $invitation->invoice_id = $invoice->id;
             $invitation->contact_id = $contact->id;
             $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH);
             $invitation->save();
         } elseif (!in_array($contact->id, $sendInvoiceIds) && $invitation) {
             $invitation->delete();
         }
     }
     return $invoice;
 }
 public function save($data)
 {
     $publicId = isset($data['public_id']) ? $data['public_id'] : false;
     if (!$publicId || $publicId == '-1') {
         $client = Client::createNew();
     } else {
         $client = Client::scope($publicId)->with('contacts')->firstOrFail();
     }
     // convert currency code to id
     if (isset($data['currency_code'])) {
         $currencyCode = strtolower($data['currency_code']);
         $currency = Cache::get('currencies')->filter(function ($item) use($currencyCode) {
             return strtolower($item->code) == $currencyCode;
         })->first();
         if ($currency) {
             $data['currency_id'] = $currency->id;
         }
     }
     $client->fill($data);
     $client->save();
     /*
     if ( ! isset($data['contact']) && ! isset($data['contacts'])) {
         return $client;
     }
     */
     $first = true;
     $contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts'];
     $contactIds = [];
     foreach ($contacts as $contact) {
         $contact = $client->addContact($contact, $first);
         $contactIds[] = $contact->public_id;
         $first = false;
     }
     foreach ($client->contacts as $contact) {
         if (!in_array($contact->public_id, $contactIds)) {
             $contact->delete();
         }
     }
     if (!$publicId || $publicId == '-1') {
         event(new ClientWasCreated($client));
     } else {
         event(new ClientWasUpdated($client));
     }
     return $client;
 }
 /**
  * @return \Illuminate\Contracts\View\View
  */
 public function index()
 {
     $user = Auth::user();
     $viewAll = $user->hasPermission('view_all');
     $userId = $user->id;
     $account = $user->account;
     $accountId = $account->id;
     $dashboardRepo = $this->dashboardRepo;
     $metrics = $dashboardRepo->totals($accountId, $userId, $viewAll);
     $paidToDate = $dashboardRepo->paidToDate($accountId, $userId, $viewAll);
     $averageInvoice = $dashboardRepo->averages($accountId, $userId, $viewAll);
     $balances = $dashboardRepo->balances($accountId, $userId, $viewAll);
     $activities = $dashboardRepo->activities($accountId, $userId, $viewAll);
     $pastDue = $dashboardRepo->pastDue($accountId, $userId, $viewAll);
     $upcoming = $dashboardRepo->upcoming($accountId, $userId, $viewAll);
     $payments = $dashboardRepo->payments($accountId, $userId, $viewAll);
     $expenses = $dashboardRepo->expenses($accountId, $userId, $viewAll);
     $tasks = $dashboardRepo->tasks($accountId, $userId, $viewAll);
     // check if the account has quotes
     $hasQuotes = false;
     foreach ([$upcoming, $pastDue] as $data) {
         foreach ($data as $invoice) {
             if ($invoice->invoice_type_id == INVOICE_TYPE_QUOTE) {
                 $hasQuotes = true;
             }
         }
     }
     // check if the account has multiple curencies
     $currencyIds = $account->currency_id ? [$account->currency_id] : [DEFAULT_CURRENCY];
     $data = Client::scope()->withArchived()->distinct()->get(['currency_id'])->toArray();
     array_map(function ($item) use(&$currencyIds) {
         $currencyId = intval($item['currency_id']);
         if ($currencyId && !in_array($currencyId, $currencyIds)) {
             $currencyIds[] = $currencyId;
         }
     }, $data);
     $currencies = [];
     foreach ($currencyIds as $currencyId) {
         $currencies[$currencyId] = Utils::getFromCache($currencyId, 'currencies')->code;
     }
     $data = ['account' => $user->account, 'paidToDate' => $paidToDate, 'balances' => $balances, 'averageInvoice' => $averageInvoice, 'invoicesSent' => $metrics ? $metrics->invoices_sent : 0, 'activeClients' => $metrics ? $metrics->active_clients : 0, 'activities' => $activities, 'pastDue' => $pastDue, 'upcoming' => $upcoming, 'payments' => $payments, 'title' => trans('texts.dashboard'), 'hasQuotes' => $hasQuotes, 'showBreadcrumbs' => false, 'currencies' => $currencies, 'expenses' => $expenses, 'tasks' => $tasks];
     return View::make('dashboard', $data);
 }
 public function edit(ExpenseRequest $request)
 {
     $expense = $request->entity();
     $expense->expense_date = Utils::fromSqlDate($expense->expense_date);
     $actions = [];
     if ($expense->invoice) {
         $actions[] = ['url' => URL::to("invoices/{$expense->invoice->public_id}/edit"), 'label' => trans("texts.view_invoice")];
     } else {
         $actions[] = ['url' => 'javascript:submitAction("invoice")', 'label' => trans("texts.invoice_expense")];
     }
     $actions[] = \DropdownButton::DIVIDER;
     if (!$expense->trashed()) {
         $actions[] = ['url' => 'javascript:submitAction("archive")', 'label' => trans('texts.archive_expense')];
         $actions[] = ['url' => 'javascript:onDeleteClick()', 'label' => trans('texts.delete_expense')];
     } else {
         $actions[] = ['url' => 'javascript:submitAction("restore")', 'label' => trans('texts.restore_expense')];
     }
     $data = array('vendor' => null, 'expense' => $expense, 'method' => 'PUT', 'url' => 'expenses/' . $expense->public_id, 'title' => 'Edit Expense', 'actions' => $actions, '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);
     $data = array_merge($data, self::getViewModel());
     return View::make('expenses.edit', $data);
 }
 private function getAccountSearchData($account)
 {
     $data = ['clients' => [], 'contacts' => [], 'invoices' => [], 'quotes' => []];
     // include custom client fields in search
     if ($account->custom_client_label1) {
         $data[$account->custom_client_label1] = [];
     }
     if ($account->custom_client_label2) {
         $data[$account->custom_client_label2] = [];
     }
     $clients = Client::scope()->with('contacts', 'invoices')->get();
     foreach ($clients as $client) {
         if ($client->name) {
             $data['clients'][] = ['value' => $client->name, 'tokens' => $client->name, 'url' => $client->present()->url];
         }
         if ($client->custom_value1) {
             $data[$account->custom_client_label1][] = ['value' => "{$client->custom_value1}: " . $client->getDisplayName(), 'tokens' => $client->custom_value1, 'url' => $client->present()->url];
         }
         if ($client->custom_value2) {
             $data[$account->custom_client_label2][] = ['value' => "{$client->custom_value2}: " . $client->getDisplayName(), 'tokens' => $client->custom_value2, 'url' => $client->present()->url];
         }
         foreach ($client->contacts as $contact) {
             if ($contact->getFullName()) {
                 $data['contacts'][] = ['value' => $contact->getDisplayName(), 'tokens' => $contact->getDisplayName(), 'url' => $client->present()->url];
             }
             if ($contact->email) {
                 $data['contacts'][] = ['value' => $contact->email, 'tokens' => $contact->email, 'url' => $client->present()->url];
             }
         }
         foreach ($client->invoices as $invoice) {
             $entityType = $invoice->getEntityType();
             $data["{$entityType}s"][] = ['value' => $invoice->getDisplayName() . ': ' . $client->getDisplayName(), 'tokens' => $invoice->getDisplayName() . ': ' . $client->getDisplayName(), 'url' => $invoice->present()->url];
         }
     }
     return $data;
 }
 public function store()
 {
     $data = Input::all();
     $error = null;
     if (isset($data['id']) || isset($data['public_id'])) {
         die("We don't yet support updating invoices");
     }
     if (isset($data['email'])) {
         $client = Client::scope()->whereHas('contacts', function ($query) use($data) {
             $query->where('email', '=', $data['email']);
         })->first();
         if (!$client) {
             $clientData = ['contact' => ['email' => $data['email']]];
             foreach (['name', 'private_notes'] as $field) {
                 if (isset($data[$field])) {
                     $clientData[$field] = $data[$field];
                 }
             }
             foreach (['first_name', 'last_name'] as $field) {
                 if (isset($data[$field])) {
                     $clientData[$field] = $data[$field];
                 }
             }
             $error = $this->clientRepo->getErrors($clientData);
             if (!$error) {
                 $client = $this->clientRepo->save($clientData);
             }
         }
     } else {
         if (isset($data['client_id'])) {
             $client = Client::scope($data['client_id'])->first();
         }
     }
     // check if the invoice number is set and unique
     if (!isset($data['invoice_number']) && !isset($data['id'])) {
         // do nothing... invoice number will be set automatically
     } else {
         if (isset($data['invoice_number'])) {
             $invoice = Invoice::scope()->where('invoice_number', '=', $data['invoice_number'])->first();
             if ($invoice) {
                 $error = trans('validation.unique', ['attribute' => 'texts.invoice_number']);
             }
         }
     }
     if (!$error) {
         if (!isset($data['client_id']) && !isset($data['email'])) {
             $error = trans('validation.', ['attribute' => 'client_id or email']);
         } else {
             if (!$client) {
                 $error = trans('validation.not_in', ['attribute' => 'client_id']);
             }
         }
     }
     if ($error) {
         $response = json_encode($error, JSON_PRETTY_PRINT);
     } else {
         $data = self::prepareData($data, $client);
         $data['client_id'] = $client->id;
         $invoice = $this->invoiceRepo->save($data);
         if (!isset($data['id'])) {
             $invitation = Invitation::createNew();
             $invitation->invoice_id = $invoice->id;
             $invitation->contact_id = $client->contacts[0]->id;
             $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH);
             $invitation->save();
         }
         if (isset($data['email_invoice']) && $data['email_invoice']) {
             $this->mailer->sendInvoice($invoice);
         }
         // prepare the return data
         $invoice = Invoice::scope($invoice->public_id)->with('client', 'invoice_items', 'invitations')->first();
         $invoice = Utils::remapPublicIds([$invoice]);
         $response = json_encode($invoice, JSON_PRETTY_PRINT);
     }
     $headers = Utils::getApiHeaders();
     return Response::make($response, $error ? 400 : 200, $headers);
 }
 /**
  * @SWG\Post(
  *   path="/invoices",
  *   tags={"invoice"},
  *   summary="Create an invoice",
  *   @SWG\Parameter(
  *     in="body",
  *     name="body",
  *     @SWG\Schema(ref="#/definitions/Invoice")
  *   ),
  *   @SWG\Response(
  *     response=200,
  *     description="New invoice",
  *      @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Invoice"))
  *   ),
  *   @SWG\Response(
  *     response="default",
  *     description="an ""unexpected"" error"
  *   )
  * )
  */
 public function store(CreateInvoiceAPIRequest $request)
 {
     $data = Input::all();
     $error = null;
     if (isset($data['email'])) {
         $email = $data['email'];
         $client = Client::scope()->whereHas('contacts', function ($query) use($email) {
             $query->where('email', '=', $email);
         })->first();
         if (!$client) {
             $validator = Validator::make(['email' => $email], ['email' => 'email']);
             if ($validator->fails()) {
                 $messages = $validator->messages();
                 return $messages->first();
             }
             $clientData = ['contact' => ['email' => $email]];
             foreach (['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'country_id', 'private_notes', 'currency_code'] as $field) {
                 if (isset($data[$field])) {
                     $clientData[$field] = $data[$field];
                 }
             }
             foreach (['first_name', 'last_name', 'phone'] as $field) {
                 if (isset($data[$field])) {
                     $clientData['contact'][$field] = $data[$field];
                 }
             }
             $client = $this->clientRepo->save($clientData);
         }
     } else {
         if (isset($data['client_id'])) {
             $client = Client::scope($data['client_id'])->firstOrFail();
         }
     }
     $data = self::prepareData($data, $client);
     $data['client_id'] = $client->id;
     $invoice = $this->invoiceService->save($data);
     $payment = false;
     if ($invoice->isInvoice()) {
         if (isset($data['auto_bill']) && boolval($data['auto_bill'])) {
             $payment = $this->paymentService->autoBillInvoice($invoice);
         } else {
             if (isset($data['paid']) && $data['paid']) {
                 $payment = $this->paymentRepo->save(['invoice_id' => $invoice->id, 'client_id' => $client->id, 'amount' => $data['paid']]);
             }
         }
     }
     if (isset($data['email_invoice']) && $data['email_invoice']) {
         if ($payment) {
             $this->mailer->sendPaymentConfirmation($payment);
         } else {
             $this->mailer->sendInvoice($invoice);
         }
     }
     $invoice = Invoice::scope($invoice->public_id)->with('client', 'invoice_items', 'invitations')->first();
     if (isset($data['download_invoice']) && boolval($data['download_invoice'])) {
         return $this->fileReponse($invoice->getFileName(), $invoice->getPDFString());
     }
     return $this->itemResponse($invoice);
 }
 public function create(CreditRequest $request)
 {
     $data = array('clientPublicId' => Input::old('client') ? Input::old('client') : ($request->client_id ?: 0), 'credit' => null, 'method' => 'POST', 'url' => 'credits', 'title' => trans('texts.new_credit'), 'clients' => Client::scope()->with('contacts')->orderBy('name')->get());
     return View::make('credits.edit', $data);
 }
Example #21
0
 /**
  * Show the form for editing the specified resource.
  *
  * @param  int      $id
  * @return Response
  */
 public function edit($publicId)
 {
     $client = Client::scope($publicId)->with('contacts')->firstOrFail();
     $data = ['client' => $client, 'method' => 'PUT', 'url' => 'clients/' . $publicId, 'title' => trans('texts.edit_client')];
     $data = array_merge($data, self::getViewModel());
     if (Auth::user()->account->isNinjaAccount()) {
         if ($account = Account::whereId($client->public_id)->first()) {
             $data['proPlanPaid'] = $account['pro_plan_paid'];
         }
     }
     return View::make('clients.edit', $data);
 }
 /**
  * @return array
  */
 private static function getViewModel()
 {
     return ['clients' => Client::scope()->with('contacts')->orderBy('name')->get(), 'account' => Auth::user()->account];
 }
 public function create($clientPublicId = 0, $isRecurring = false)
 {
     $account = Auth::user()->account;
     $entityType = $isRecurring ? ENTITY_RECURRING_INVOICE : ENTITY_INVOICE;
     $clientId = null;
     if ($clientPublicId) {
         $clientId = Client::getPrivateId($clientPublicId);
     }
     $invoice = $account->createInvoice($entityType, $clientId);
     $invoice->public_id = 0;
     $data = ['clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(), 'entityType' => $invoice->getEntityType(), 'invoice' => $invoice, 'method' => 'POST', 'url' => 'invoices', 'title' => trans('texts.new_invoice')];
     $data = array_merge($data, self::getViewModel());
     return View::make('invoices.edit', $data);
 }
 private function mapFile()
 {
     $file = Input::file('file');
     if ($file == null) {
         Session::flash('error', trans('texts.select_file'));
         return Redirect::to('settings/' . ACCOUNT_IMPORT_EXPORT);
     }
     $name = $file->getRealPath();
     require_once app_path() . '/Includes/parsecsv.lib.php';
     $csv = new parseCSV();
     $csv->heading = false;
     $csv->auto($name);
     if (count($csv->data) + Client::scope()->count() > Auth::user()->getMaxNumClients()) {
         $message = trans('texts.limit_clients', ['count' => Auth::user()->getMaxNumClients()]);
         Session::flash('error', $message);
         return Redirect::to('settings/' . ACCOUNT_IMPORT_EXPORT);
     }
     Session::put('data', $csv->data);
     $headers = false;
     $hasHeaders = false;
     $mapped = array();
     $columns = array('', Client::$fieldName, Client::$fieldPhone, Client::$fieldAddress1, Client::$fieldAddress2, Client::$fieldCity, Client::$fieldState, Client::$fieldPostalCode, Client::$fieldCountry, Client::$fieldNotes, Contact::$fieldFirstName, Contact::$fieldLastName, Contact::$fieldPhone, Contact::$fieldEmail);
     if (count($csv->data) > 0) {
         $headers = $csv->data[0];
         foreach ($headers as $title) {
             if (strpos(strtolower($title), 'name') > 0) {
                 $hasHeaders = true;
                 break;
             }
         }
         for ($i = 0; $i < count($headers); $i++) {
             $title = strtolower($headers[$i]);
             $mapped[$i] = '';
             if ($hasHeaders) {
                 $map = array('first' => Contact::$fieldFirstName, 'last' => Contact::$fieldLastName, 'email' => Contact::$fieldEmail, 'mobile' => Contact::$fieldPhone, 'phone' => Client::$fieldPhone, 'name|organization' => Client::$fieldName, 'street|address|address1' => Client::$fieldAddress1, 'street2|address2' => Client::$fieldAddress2, 'city' => Client::$fieldCity, 'state|province' => Client::$fieldState, 'zip|postal|code' => Client::$fieldPostalCode, 'country' => Client::$fieldCountry, 'note' => Client::$fieldNotes);
                 foreach ($map as $search => $column) {
                     foreach (explode("|", $search) as $string) {
                         if (strpos($title, 'sec') === 0) {
                             continue;
                         }
                         if (strpos($title, $string) !== false) {
                             $mapped[$i] = $column;
                             break 2;
                         }
                     }
                 }
             }
         }
     }
     $data = array('data' => $csv->data, 'headers' => $headers, 'hasHeaders' => $hasHeaders, 'columns' => $columns, 'mapped' => $mapped);
     return View::make('accounts.import_map', $data);
 }
 /**
  * Bootstrap any application services.
  *
  * @return void
  */
 public function boot()
 {
     HTML::macro('nav_link', function ($url, $text, $url2 = '', $extra = '') {
         $class = Request::is($url) || Request::is($url . '/*') || Request::is($url2 . '/*') ? ' class="active"' : '';
         $title = ucwords(trans("texts.{$text}")) . Utils::getProLabel($text);
         return '<li' . $class . '><a href="' . URL::to($url) . '" ' . $extra . '>' . $title . '</a></li>';
     });
     HTML::macro('tab_link', function ($url, $text, $active = false) {
         $class = $active ? ' class="active"' : '';
         return '<li' . $class . '><a href="' . URL::to($url) . '" data-toggle="tab">' . $text . '</a></li>';
     });
     HTML::macro('menu_link', function ($type) {
         $types = $type . 's';
         $Type = ucfirst($type);
         $Types = ucfirst($types);
         $class = (Request::is($types) || Request::is('*' . $type . '*')) && !Request::is('*settings*') ? ' active' : '';
         $str = '<li class="dropdown ' . $class . '">
                <a href="' . URL::to($types) . '" class="dropdown-toggle">' . trans("texts.{$types}") . '</a>
                <ul class="dropdown-menu" id="menu1">
                <li><a href="' . URL::to($types . '/create') . '">' . trans("texts.new_{$type}") . '</a></li>';
         if ($type == ENTITY_INVOICE) {
             $str .= '<li class="divider"></li>
                      <li><a href="' . URL::to('recurring_invoices') . '">' . trans("texts.recurring_invoices") . '</a></li>
                      <li><a href="' . URL::to('recurring_invoices/create') . '">' . trans("texts.new_recurring_invoice") . '</a></li>';
             if (Auth::user()->isPro()) {
                 $str .= '<li class="divider"></li>
                         <li><a href="' . URL::to('quotes') . '">' . trans("texts.quotes") . '</a></li>
                         <li><a href="' . URL::to('quotes/create') . '">' . trans("texts.new_quote") . '</a></li>';
             }
         } else {
             if ($type == ENTITY_CLIENT) {
                 $str .= '<li class="divider"></li>
                     <li><a href="' . URL::to('credits') . '">' . trans("texts.credits") . '</a></li>
                     <li><a href="' . URL::to('credits/create') . '">' . trans("texts.new_credit") . '</a></li>';
             } else {
                 if ($type == ENTITY_EXPENSE) {
                     $str .= '<li class="divider"></li>
                     <li><a href="' . URL::to('vendors') . '">' . trans("texts.vendors") . '</a></li>
                     <li><a href="' . URL::to('vendors/create') . '">' . trans("texts.new_vendor") . '</a></li>';
                 }
             }
         }
         $str .= '</ul>
               </li>';
         return $str;
     });
     HTML::macro('image_data', function ($imagePath) {
         return 'data:image/jpeg;base64,' . base64_encode(file_get_contents($imagePath));
     });
     HTML::macro('flatButton', function ($label, $color) {
         return '<input type="button" value="' . trans("texts.{$label}") . '" style="background-color:' . $color . ';border:0 none;border-radius:5px;padding:12px 40px;margin:0 6px;cursor:hand;display:inline-block;font-size:14px;color:#fff;text-transform:none;font-weight:bold;"/>';
     });
     HTML::macro('emailViewButton', function ($link = '#', $entityType = ENTITY_INVOICE) {
         return view('partials.email_button')->with(['link' => $link, 'field' => "view_{$entityType}", 'color' => '#0b4d78'])->render();
     });
     HTML::macro('emailPaymentButton', function ($link = '#') {
         return view('partials.email_button')->with(['link' => $link, 'field' => 'pay_now', 'color' => '#36c157'])->render();
     });
     HTML::macro('breadcrumbs', function () {
         $str = '<ol class="breadcrumb">';
         // Get the breadcrumbs by exploding the current path.
         $basePath = Utils::basePath();
         $parts = explode('?', isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '');
         $path = $parts[0];
         if ($basePath != '/') {
             $path = str_replace($basePath, '', $path);
         }
         $crumbs = explode('/', $path);
         foreach ($crumbs as $key => $val) {
             if (is_numeric($val)) {
                 unset($crumbs[$key]);
             }
         }
         $crumbs = array_values($crumbs);
         for ($i = 0; $i < count($crumbs); $i++) {
             $crumb = trim($crumbs[$i]);
             if (!$crumb) {
                 continue;
             }
             if ($crumb == 'company') {
                 return '';
             }
             $name = trans("texts.{$crumb}");
             if ($i == count($crumbs) - 1) {
                 $str .= "<li class='active'>{$name}</li>";
             } else {
                 $str .= '<li>' . link_to($crumb, $name) . '</li>';
             }
         }
         return $str . '</ol>';
     });
     Validator::extend('positive', function ($attribute, $value, $parameters) {
         return Utils::parseFloat($value) >= 0;
     });
     Validator::extend('has_credit', function ($attribute, $value, $parameters) {
         $publicClientId = $parameters[0];
         $amount = $parameters[1];
         $client = \App\Models\Client::scope($publicClientId)->firstOrFail();
         $credit = $client->getTotalCredit();
         return $credit >= $amount;
     });
     // check that the time log elements don't overlap
     Validator::extend('time_log', function ($attribute, $value, $parameters) {
         $lastTime = 0;
         $value = json_decode($value);
         array_multisort($value);
         foreach ($value as $timeLog) {
             list($startTime, $endTime) = $timeLog;
             if (!$endTime) {
                 continue;
             }
             if ($startTime < $lastTime || $startTime > $endTime) {
                 return false;
             }
             if ($endTime < min($startTime, $lastTime)) {
                 return false;
             }
             $lastTime = max($lastTime, $endTime);
         }
         return true;
     });
     Validator::extend('less_than', function ($attribute, $value, $parameters) {
         return floatval($value) <= floatval($parameters[0]);
     });
     Validator::replacer('less_than', function ($message, $attribute, $rule, $parameters) {
         return str_replace(':value', $parameters[0], $message);
     });
     Validator::extend('has_counter', function ($attribute, $value, $parameters) {
         return !$value || strstr($value, '{$counter}');
     });
     Validator::extend('valid_contacts', function ($attribute, $value, $parameters) {
         foreach ($value as $contact) {
             $validator = Validator::make($contact, ['email' => 'email|required_without:first_name', 'first_name' => 'required_without:email']);
             if ($validator->fails()) {
                 return false;
             }
         }
         return true;
     });
     Validator::extend('valid_invoice_items', function ($attribute, $value, $parameters) {
         $total = 0;
         foreach ($value as $item) {
             $total += $item['qty'] * $item['cost'];
         }
         return $total <= MAX_INVOICE_AMOUNT;
     });
 }
 /**
  * @SWG\Post(
  *   path="/invoices",
  *   tags={"invoice"},
  *   summary="Create an invoice",
  *   @SWG\Parameter(
  *     in="body",
  *     name="body",
  *     @SWG\Schema(ref="#/definitions/Invoice")
  *   ),
  *   @SWG\Response(
  *     response=200,
  *     description="New invoice",
  *      @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Invoice"))
  *   ),
  *   @SWG\Response(
  *     response="default",
  *     description="an ""unexpected"" error"
  *   )
  * )
  */
 public function store(CreateInvoiceRequest $request)
 {
     $data = Input::all();
     $error = null;
     if (isset($data['email'])) {
         $email = $data['email'];
         $client = Client::scope()->whereHas('contacts', function ($query) use($email) {
             $query->where('email', '=', $email);
         })->first();
         if (!$client) {
             $validator = Validator::make(['email' => $email], ['email' => 'email']);
             if ($validator->fails()) {
                 $messages = $validator->messages();
                 return $messages->first();
             }
             $clientData = ['contact' => ['email' => $email]];
             foreach (['name', 'private_notes'] as $field) {
                 if (isset($data[$field])) {
                     $clientData[$field] = $data[$field];
                 }
             }
             foreach (['first_name', 'last_name'] as $field) {
                 if (isset($data[$field])) {
                     $clientData[$field] = $data[$field];
                 }
             }
             $client = $this->clientRepo->save($clientData);
         }
     } else {
         if (isset($data['client_id'])) {
             $client = Client::scope($data['client_id'])->firstOrFail();
         }
     }
     $data = self::prepareData($data, $client);
     $data['client_id'] = $client->id;
     $invoice = $this->invoiceRepo->save($data);
     if (!isset($data['id'])) {
         $invitation = Invitation::createNew();
         $invitation->invoice_id = $invoice->id;
         $invitation->contact_id = $client->contacts[0]->id;
         $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH);
         $invitation->save();
     }
     if (isset($data['email_invoice']) && $data['email_invoice']) {
         $this->mailer->sendInvoice($invoice);
     }
     $invoice = Invoice::scope($invoice->public_id)->with('client', 'invoice_items', 'invitations')->first();
     $transformer = new InvoiceTransformer(\Auth::user()->account, Input::get('serializer'));
     $data = $this->createItem($invoice, $transformer, 'invoice');
     return $this->response($data);
 }
 /**
  * Show the form for editing the specified resource.
  *
  * @param  int      $id
  * @return Response
  */
 public function edit($publicId)
 {
     $client = Client::scope($publicId)->with('contacts')->firstOrFail();
     $data = ['client' => $client, 'method' => 'PUT', 'url' => 'clients/' . $publicId, 'title' => trans('texts.edit_client')];
     $data = array_merge($data, self::getViewModel());
     return View::make('clients.edit', $data);
 }
 private static function getViewModel()
 {
     $recurringHelp = '';
     foreach (preg_split("/((\r?\n)|(\r\n?))/", trans('texts.recurring_help')) as $line) {
         $parts = explode("=>", $line);
         if (count($parts) > 1) {
             $line = $parts[0] . ' => ' . Utils::processVariables($parts[0]);
             $recurringHelp .= '<li>' . strip_tags($line) . '</li>';
         } else {
             $recurringHelp .= $line;
         }
     }
     return ['account' => Auth::user()->account->load('country'), 'products' => Product::scope()->orderBy('id')->get(array('product_key', 'notes', 'cost', 'qty')), 'countries' => Cache::get('countries'), 'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(), 'taxRates' => TaxRate::scope()->orderBy('name')->get(), 'currencies' => Cache::get('currencies'), 'languages' => Cache::get('languages'), 'sizes' => Cache::get('sizes'), 'paymentTerms' => Cache::get('paymentTerms'), 'industries' => Cache::get('industries'), 'invoiceDesigns' => InvoiceDesign::getDesigns(), 'frequencies' => array(1 => 'Weekly', 2 => 'Two weeks', 3 => 'Four weeks', 4 => 'Monthly', 5 => 'Three months', 6 => 'Six months', 7 => 'Annually'), 'recurringHelp' => $recurringHelp, 'invoiceLabels' => Auth::user()->account->getInvoiceLabels(), 'tasks' => Session::get('tasks') ? json_encode(Session::get('tasks')) : null];
 }
 public function edit($publicId)
 {
     $expense = Expense::scope($publicId)->firstOrFail();
     $expense->expense_date = Utils::fromSqlDate($expense->expense_date);
     $actions = [];
     if ($expense->invoice) {
         $actions[] = ['url' => URL::to("invoices/{$expense->invoice->public_id}/edit"), 'label' => trans("texts.view_invoice")];
     } else {
         $actions[] = ['url' => 'javascript:submitAction("invoice")', 'label' => trans("texts.invoice_expense")];
         /*
         // check for any open invoices
         $invoices = $task->client_id ? $this->invoiceRepo->findOpenInvoices($task->client_id) : [];
         
         foreach ($invoices as $invoice) {
             $actions[] = ['url' => 'javascript:submitAction("add_to_invoice", '.$invoice->public_id.')', 'label' => trans("texts.add_to_invoice", ["invoice" => $invoice->invoice_number])];
         }
         */
     }
     $actions[] = \DropdownButton::DIVIDER;
     if (!$expense->trashed()) {
         $actions[] = ['url' => 'javascript:submitAction("archive")', 'label' => trans('texts.archive_expense')];
         $actions[] = ['url' => 'javascript:onDeleteClick()', 'label' => trans('texts.delete_expense')];
     } else {
         $actions[] = ['url' => 'javascript:submitAction("restore")', 'label' => trans('texts.restore_expense')];
     }
     $data = array('vendor' => null, 'expense' => $expense, 'method' => 'PUT', 'url' => 'expenses/' . $publicId, 'title' => 'Edit Expense', 'actions' => $actions, 'vendors' => Vendor::scope()->with('vendorcontacts')->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);
     $data = array_merge($data, self::getViewModel());
     if (Auth::user()->account->isNinjaAccount()) {
         if ($account = Account::whereId($client->public_id)->first()) {
             $data['proPlanPaid'] = $account['pro_plan_paid'];
         }
     }
     return View::make('expenses.edit', $data);
 }
 /**
  * Bootstrap any application services.
  *
  * @return void
  */
 public function boot()
 {
     Form::macro('image_data', function ($image, $contents = false) {
         if (!$contents) {
             $contents = file_get_contents($image);
         } else {
             $contents = $image;
         }
         return 'data:image/jpeg;base64,' . base64_encode($contents);
     });
     Form::macro('nav_link', function ($url, $text) {
         //$class = ( Request::is($url) || Request::is($url.'/*') || Request::is($url2.'/*') ) ? ' class="active"' : '';
         $class = Request::is($url) || Request::is($url . '/*') ? ' class="active"' : '';
         $title = trans("texts.{$text}") . Utils::getProLabel($text);
         return '<li' . $class . '><a href="' . URL::to($url) . '">' . $title . '</a></li>';
     });
     Form::macro('tab_link', function ($url, $text, $active = false) {
         $class = $active ? ' class="active"' : '';
         return '<li' . $class . '><a href="' . URL::to($url) . '" data-toggle="tab">' . $text . '</a></li>';
     });
     Form::macro('menu_link', function ($type) {
         $types = $type . 's';
         $Type = ucfirst($type);
         $Types = ucfirst($types);
         $class = (Request::is($types) || Request::is('*' . $type . '*')) && !Request::is('*settings*') ? ' active' : '';
         return '<li class="dropdown ' . $class . '">
                 <a href="' . URL::to($types) . '" class="dropdown-toggle">' . trans("texts.{$types}") . '</a>
                </li>';
     });
     Form::macro('flatButton', function ($label, $color) {
         return '<input type="button" value="' . trans("texts.{$label}") . '" style="background-color:' . $color . ';border:0 none;border-radius:5px;padding:12px 40px;margin:0 6px;cursor:hand;display:inline-block;font-size:14px;color:#fff;text-transform:none;font-weight:bold;"/>';
     });
     Form::macro('emailViewButton', function ($link = '#', $entityType = ENTITY_INVOICE) {
         return view('partials.email_button')->with(['link' => $link, 'field' => "view_{$entityType}", 'color' => '#0b4d78'])->render();
     });
     Form::macro('emailPaymentButton', function ($link = '#') {
         return view('partials.email_button')->with(['link' => $link, 'field' => 'pay_now', 'color' => '#36c157'])->render();
     });
     Form::macro('breadcrumbs', function ($status = false) {
         $str = '<ol class="breadcrumb">';
         // Get the breadcrumbs by exploding the current path.
         $basePath = Utils::basePath();
         $parts = explode('?', isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '');
         $path = $parts[0];
         if ($basePath != '/') {
             $path = str_replace($basePath, '', $path);
         }
         $crumbs = explode('/', $path);
         foreach ($crumbs as $key => $val) {
             if (is_numeric($val)) {
                 unset($crumbs[$key]);
             }
         }
         $crumbs = array_values($crumbs);
         for ($i = 0; $i < count($crumbs); $i++) {
             $crumb = trim($crumbs[$i]);
             if (!$crumb) {
                 continue;
             }
             if ($crumb == 'company') {
                 return '';
             }
             $name = trans("texts.{$crumb}");
             if ($i == count($crumbs) - 1) {
                 $str .= "<li class='active'>{$name}</li>";
             } else {
                 $str .= '<li>' . link_to($crumb, $name) . '</li>';
             }
         }
         if ($status) {
             $str .= $status;
         }
         return $str . '</ol>';
     });
     Form::macro('human_filesize', function ($bytes, $decimals = 1) {
         $size = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
         $factor = floor((strlen($bytes) - 1) / 3);
         if ($factor == 0) {
             $decimals = 0;
         }
         // There aren't fractional bytes
         return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor];
     });
     Validator::extend('positive', function ($attribute, $value, $parameters) {
         return Utils::parseFloat($value) >= 0;
     });
     Validator::extend('has_credit', function ($attribute, $value, $parameters) {
         $publicClientId = $parameters[0];
         $amount = $parameters[1];
         $client = \App\Models\Client::scope($publicClientId)->firstOrFail();
         $credit = $client->getTotalCredit();
         return $credit >= $amount;
     });
     // check that the time log elements don't overlap
     Validator::extend('time_log', function ($attribute, $value, $parameters) {
         $lastTime = 0;
         $value = json_decode($value);
         array_multisort($value);
         foreach ($value as $timeLog) {
             list($startTime, $endTime) = $timeLog;
             if (!$endTime) {
                 continue;
             }
             if ($startTime < $lastTime || $startTime > $endTime) {
                 return false;
             }
             if ($endTime < min($startTime, $lastTime)) {
                 return false;
             }
             $lastTime = max($lastTime, $endTime);
         }
         return true;
     });
     Validator::extend('has_counter', function ($attribute, $value, $parameters) {
         return !$value || strstr($value, '{$counter}');
     });
     Validator::extend('valid_contacts', function ($attribute, $value, $parameters) {
         foreach ($value as $contact) {
             $validator = Validator::make($contact, ['email' => 'email|required_without:first_name', 'first_name' => 'required_without:email']);
             if ($validator->fails()) {
                 return false;
             }
         }
         return true;
     });
     Validator::extend('valid_invoice_items', function ($attribute, $value, $parameters) {
         $total = 0;
         foreach ($value as $item) {
             $qty = isset($item['qty']) ? $item['qty'] : 1;
             $cost = isset($item['cost']) ? $item['cost'] : 1;
             $total += $qty * $cost;
         }
         return $total <= MAX_INVOICE_AMOUNT;
     });
 }