Refactor for adding additional locations for clients

This commit is contained in:
David Bomba 2025-02-25 09:42:45 +11:00
parent 8f6eb0ffa4
commit a2a37a8f60
12 changed files with 651 additions and 232 deletions

View File

@ -39,6 +39,7 @@ class StoreLocationRequest extends Request
$rules = [];
$rules['name'] = 'required|unique:expense_categories,name,null,null,company_id,'.$user->companyId();
$rules['country_id'] = 'integer|exists:countries,id';
return $this->globalRules($rules);
}
@ -53,6 +54,7 @@ class StoreLocationRequest extends Request
$input['color'] = '';
}
$this->replace($input);
}
}

View File

@ -45,6 +45,8 @@ class UpdateLocationRequest extends Request
$rules['name'] = Rule::unique('locations')->where('company_id', $user->company()->id)->ignore($this->location->id);
}
$rules['country_id'] = 'integer|exists:countries,id';
return $rules;
}

View File

@ -49,6 +49,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property string|null $custom_value3
* @property string|null $custom_value4
* @property bool $is_deleted
* @property bool $is_shipping_location
* @property int|null $created_at
* @property int|null $updated_at
* @property int|null $deleted_at
@ -87,6 +88,7 @@ class Location extends BaseModel
'custom_value3',
'custom_value4',
'is_deleted',
'is_shipping_location',
];

View File

@ -158,29 +158,6 @@ class ClientPresenter extends EntityPresenter
return $str;
}
// public function getCityState()
// {
// $settings = $this->entity->getMergedSettings();
// $country = false;
// if ($settings->country_id) {
// $country = Country::find($settings->country_id);
// }
// $swap = $country && $country->swap_postal_code;
// $city = e($settings->city ?: '');
// $state = e($settings->state ?: '');
// $postalCode = e($settings->postal_code ?: '');
// if ($city || $state || $postalCode) {
// return $this->cityStateZip($city, $state, $postalCode, $swap);
// } else {
// return false;
// }
// }
public function getCityState()
{
$client = $this->entity;

View File

@ -11,15 +11,16 @@
namespace App\Services\Credit;
use App\Factory\PaymentFactory;
use App\Jobs\EDocument\CreateEDocument;
use App\Utils\Ninja;
use App\Models\Credit;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Repositories\CreditRepository;
use App\Repositories\PaymentRepository;
use App\Utils\Ninja;
use App\Factory\PaymentFactory;
use App\Utils\Traits\MakesHash;
use App\Repositories\CreditRepository;
use App\Services\Invoice\LocationData;
use App\Jobs\EDocument\CreateEDocument;
use App\Repositories\PaymentRepository;
use Illuminate\Support\Facades\Storage;
class CreditService
@ -33,6 +34,11 @@ class CreditService
$this->credit = $credit;
}
public function location(): array
{
return (new LocationData($this->credit))->run();
}
public function getCreditPdf($invitation)
{
return (new GetCreditPdf($invitation))->run();

View File

@ -11,21 +11,22 @@
namespace App\Services\Invoice;
use App\Events\Invoice\InvoiceWasArchived;
use App\Jobs\EDocument\CreateEDocument;
use App\Jobs\Entity\CreateRawPdf;
use App\Jobs\Inventory\AdjustProductInventory;
use App\Libraries\Currency\Conversion\CurrencyApi;
use App\Models\CompanyGateway;
use App\Models\Task;
use App\Utils\Ninja;
use App\Models\Expense;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\Subscription;
use App\Models\Task;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
use App\Models\CompanyGateway;
use Illuminate\Support\Carbon;
use App\Utils\Traits\MakesHash;
use App\Jobs\Entity\CreateRawPdf;
use App\Services\Invoice\LocationData;
use App\Jobs\EDocument\CreateEDocument;
use Illuminate\Support\Facades\Storage;
use App\Events\Invoice\InvoiceWasArchived;
use App\Jobs\Inventory\AdjustProductInventory;
use App\Libraries\Currency\Conversion\CurrencyApi;
class InvoiceService
{
@ -617,6 +618,11 @@ class InvoiceService
return $this;
}
public function location(): array
{
return (new LocationData($this->invoice))->run();
}
public function workFlow()
{
if ($this->invoice->status_id == Invoice::STATUS_PAID && $this->invoice->client->getSetting('auto_archive_invoice')) {

View File

@ -0,0 +1,302 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Services\Invoice;
use App\Models\Quote;
use App\Models\Credit;
use App\Models\Country;
use App\Models\Invoice;
use App\Models\Location;
use App\Models\RecurringInvoice;
use App\Services\AbstractService;
class LocationData extends AbstractService
{
private ?Location $businessLocation;
private ?Location $shippingLocation;
public function __construct(private Invoice | Quote | Credit | RecurringInvoice $entity)
{
$this->setLocations();
}
private function setLocations(): self
{
if (!$this->entity->location) {
$this->businessLocation = null;
$this->shippingLocation = null;
}
elseif($this->entity->location->is_shipping_location) {
$this->shippingLocation = $this->entity->location;
$this->businessLocation = null;
} else {
$this->businessLocation = $this->entity->location;
$this->shippingLocation = null;
}
return $this;
}
public function run(): array
{
return [
// Business Address (from business location or client default)
'address' => $this->getBusinessAddress(),
'address1' => $this->getBusinessAddress1(),
'address2' => $this->getBusinessAddress2(),
'city' => $this->getBusinessCity(),
'state' => $this->getBusinessState(),
'postal_code' => $this->getBusinessPostalCode(),
'country' => $this->getBusinessCountry(),
'country_name' => $this->getBusinessCountryName(),
'country_code' => $this->getBusinessCountryCode(),
// Shipping Address (from shipping location or client default)
'shipping_address' => $this->getShippingAddress(),
'shipping_address1' => $this->getShippingAddress1(),
'shipping_address2' => $this->getShippingAddress2(),
'shipping_city' => $this->getShippingCity(),
'shipping_state' => $this->getShippingState(),
'shipping_postal_code' => $this->getShippingPostalCode(),
'shipping_country' => $this->getShippingCountry(),
'shipping_country_name' => $this->getShippingCountryName(),
'shipping_country_code' => $this->getShippingCountryCode(),
'shipping_exists' => strlen($this->getShippingAddress1()) > 0,
];
}
private function getBusinessCountry(): ?Country
{
if ($this->businessLocation) {
return $this->businessLocation->country ?? $this->entity->company->country();
}
return $this->entity->client->country ?? $this->entity->company->country();
}
private function getShippingCountry(): ?Country
{
if ($this->shippingLocation) {
return $this->shippingLocation->country ?? $this->entity->company->country();
}
return $this->entity->client->shipping_country ?? $this->entity->company->country();
}
public function getCityState()
{
$country = $this->getBusinessCountry();
$swap = $country && $country->swap_postal_code;
$city = e($this->getBusinessCity() ?: '');
$state = e($this->getBusinessState() ?: '');
$postalCode = e($this->getBusinessPostalCode() ?: '');
if ($city || $state || $postalCode) {
return $this->entity->present()->cityStateZip($city, $state, $postalCode, $swap);
} else {
return false;
}
}
private function getBusinessAddress(): ?string
{
$str = ' ';
if ($address1 = $this->getBusinessAddress1()) {
$str .= e($address1).'<br/>';
}
if ($address2 = $this->getBusinessAddress2()) {
$str .= e($address2).'<br/>';
}
if ($cityState = $this->getCityState()) {
$str .= e($cityState).'<br/>';
}
if ($country = $this->getBusinessCountryName()) {
$str .= e($country).'<br/>';
}
return $str;
}
private function getShippingCityState(): ?string
{
$country = $this->getShippingCountry();
$swap = $country && $country->swap_postal_code;
$city = e($this->getShippingCity() ?: '');
$state = e($this->getShippingState() ?: '');
$postalCode = e($this->getShippingPostalCode() ?: '');
if ($city || $state || $postalCode) {
return $this->entity->present()->cityStateZip($city, $state, $postalCode, $swap);
} else {
return false;
}
}
private function getShippingAddress(): ?string
{
$str = ' ';
if ($address1 = $this->getShippingAddress1()) {
$str .= e($address1).'<br/>';
}
if ($address2 = $this->getShippingAddress2()) {
$str .= e($address2).'<br/>';
}
if ($cityState = $this->getShippingCityState()) {
$str .= e($cityState).'<br/>';
}
if ($country = $this->getShippingCountryName()) {
$str .= e($country).'<br/>';
}
return $str;
}
private function getBusinessAddress1(): ?string
{
if ($this->businessLocation) {
return $this->businessLocation->address1 ?? '';
}
return $this->entity->client->address1 ?? '';
}
private function getBusinessAddress2(): ?string
{
if ($this->businessLocation) {
return $this->businessLocation->address2 ?? '';
}
return $this->entity->client->address2 ?? '';
}
private function getBusinessCity(): ?string
{
if ($this->businessLocation) {
return $this->businessLocation->city ?? '';
}
return $this->entity->client->city ?? '';
}
private function getBusinessState(): ?string
{
if ($this->businessLocation) {
return $this->businessLocation->state ?? '';
}
return $this->entity->client->state ?? '';
}
private function getBusinessPostalCode(): ?string
{
if ($this->businessLocation) {
return $this->businessLocation->postal_code ?? '';
}
return $this->entity->client->postal_code ?? '';
}
private function getBusinessCountryName(): ?string
{
if ($this->businessLocation) {
return $this->businessLocation->country->name;
}
return $this->entity->client->country->name;
}
private function getBusinessCountryCode(): ?string
{
if ($this->businessLocation) {
return $this->businessLocation->country->iso_3166_2;
}
return $this->entity->client->country->iso_3166_2;
}
private function getShippingAddress1(): ?string
{
if ($this->shippingLocation) {
return $this->shippingLocation->address1 ?? '';
}
return $this->entity->client->shipping_address1 ?? '';
}
private function getShippingAddress2(): ?string
{
if ($this->shippingLocation) {
return $this->shippingLocation->address2 ?? '';
}
return $this->entity->client->shipping_address2 ?? '';
}
private function getShippingCity(): ?string
{
if ($this->shippingLocation) {
return $this->shippingLocation->city ?? '';
}
return $this->entity->client->shipping_city ?? '';
}
private function getShippingState(): ?string
{
if ($this->shippingLocation) {
return $this->shippingLocation->state ?? '';
}
return $this->entity->client->shipping_state ?? '';
}
private function getShippingPostalCode(): ?string
{
if ($this->shippingLocation) {
return $this->shippingLocation->postal_code ?? '';
}
return $this->entity->client->shipping_postal_code ?? '';
}
private function getShippingCountryName(): ?string
{
if ($this->shippingLocation && $this->shippingLocation->country) {
return $this->shippingLocation->country->name;
}
return $this->entity->client->shipping_country->name ?? $this->entity->company->country()->name;
}
private function getShippingCountryCode(): ?string
{
if ($this->shippingLocation && $this->shippingLocation->country) {
return $this->shippingLocation->country->iso_3166_2;
}
return $this->entity->client->shipping_country->iso_3166_2 ?? $this->entity->company->country()->iso_3166_2;
}
}

View File

@ -11,15 +11,16 @@
namespace App\Services\Quote;
use App\Events\Quote\QuoteWasApproved;
use App\Exceptions\QuoteConversion;
use App\Jobs\EDocument\CreateEDocument;
use App\Models\Project;
use App\Models\Quote;
use App\Repositories\QuoteRepository;
use App\Services\Quote\UpdateReminder;
use App\Utils\Ninja;
use App\Models\Quote;
use App\Models\Project;
use App\Utils\Traits\MakesHash;
use App\Exceptions\QuoteConversion;
use App\Repositories\QuoteRepository;
use App\Events\Quote\QuoteWasApproved;
use App\Services\Invoice\LocationData;
use App\Services\Quote\UpdateReminder;
use App\Jobs\EDocument\CreateEDocument;
use Illuminate\Support\Facades\Storage;
class QuoteService
@ -35,6 +36,11 @@ class QuoteService
$this->quote = $quote;
}
public function location(): array
{
return (new LocationData($this->quote))->run();
}
public function createInvitations()
{
$this->quote = (new CreateInvitations($this->quote))->run();

View File

@ -18,6 +18,7 @@ use Illuminate\Support\Carbon;
use App\Utils\Traits\MakesHash;
use App\Models\RecurringExpense;
use App\Models\RecurringInvoice;
use App\Services\Invoice\LocationData;
use Illuminate\Support\Facades\Storage;
use App\Jobs\RecurringInvoice\SendRecurring;
@ -178,6 +179,11 @@ class RecurringService
}
public function location(): array
{
return (new LocationData($this->recurring_entity))->run();
}
public function save()
{
$this->recurring_entity->saveQuietly();

View File

@ -128,16 +128,17 @@ class HtmlEngine
App::setLocale($this->contact->preferredLocale());
$t->replace(Ninja::transformTranslations($this->settings));
$locationData = $this->entity->service()->location();
$data = [];
$data['$date_client_now'] = ['value' => now()->setTimezone($this->client->timezone()->name)->addSeconds($this->client->utc_offset())->format($this->client->date_format()), 'label' => ''];
$data['$date_company_now'] = ['value' => now()->setTimezone($this->company->timezone()->name)->addSeconds($this->company->utc_offset())->format($this->company->date_format()), 'label' => ''];
$data['$global_margin'] = ['value' => '6.35mm', 'label' => ''];
$data['$company_logo_size'] = ['value' => $this->resolveCompanyLogoSize(), 'label' => ''];
$data['$show_shipping_address'] = ['value' => strlen($this->client->shipping_address1 ?? '') > 0 && $this->settings->show_shipping_address ? 'flex' : 'none', 'label' => ''];
$data['$show_shipping_address_block'] = ['value' => strlen($this->client->shipping_address1 ?? '') > 0 && $this->settings->show_shipping_address ? 'block' : 'none', 'label' => ''];
// $data['$show_shipping_address_visibility'] = ['value' => $this->settings?->show_shipping_address ? 'visible' : 'hidden', 'label' => ''];
$data['$show_shipping_address_visibility'] = ['value' => strlen($this->client->shipping_address1 ?? '') > 0 && $this->settings->show_shipping_address ? 1 : 0, 'label' => ''];
$data['$show_shipping_address'] = ['value' => $locationData['shipping_exists'] && $this->settings->show_shipping_address ? 'flex' : 'none', 'label' => ''];
$data['$show_shipping_address_block'] = ['value' => $locationData['shipping_exists'] && $this->settings->show_shipping_address ? 'block' : 'none', 'label' => ''];
$data['$show_shipping_address_visibility'] = ['value' => $locationData['shipping_exists'] && $this->settings->show_shipping_address ? 1 : 0, 'label' => ''];
$data['$order_number'] = ['value' => '', 'label' => ctrans('texts.order_number')];
$data['$tax'] = ['value' => '', 'label' => ctrans('texts.tax')];
@ -457,15 +458,15 @@ class HtmlEngine
$data['$client.custom2'] = &$data['$client2'];
$data['$client.custom3'] = &$data['$client3'];
$data['$client.custom4'] = &$data['$client4'];
$data['$address1'] = ['value' => $this->client->address1 ?: ' ', 'label' => ctrans('texts.address1')];
$data['$address2'] = ['value' => $this->client->address2 ?: ' ', 'label' => ctrans('texts.address2')];
$data['$address1'] = ['value' => $locationData['address1'] ?: ' ', 'label' => ctrans('texts.address1')];
$data['$address2'] = ['value' => $locationData['address2'] ?: ' ', 'label' => ctrans('texts.address2')];
$data['$id_number'] = ['value' => $this->client->id_number ?: ' ', 'label' => ctrans('texts.id_number')];
$data['$client.number'] = ['value' => $this->client->number ?: ' ', 'label' => ctrans('texts.number')];
$data['$vat_number'] = ['value' => $this->client->vat_number ?: ' ', 'label' => ctrans('texts.vat_number')];
$data['$website'] = ['value' => $this->client->present()->website() ?: ' ', 'label' => ctrans('texts.website')];
$data['$phone'] = ['value' => $this->client->present()->phone() ?: ' ', 'label' => ctrans('texts.phone')];
$data['$country'] = ['value' => isset($this->client->country->name) ? ctrans('texts.country_' . $this->client->country->name) : '', 'label' => ctrans('texts.country')];
$data['$country_2'] = ['value' => isset($this->client->country) ? $this->client->country->iso_3166_2 : '', 'label' => ctrans('texts.country')];
$data['$country'] = ['value' => ctrans('texts.country_' . $locationData['country_name']) , 'label' => ctrans('texts.country')];
$data['$country_2'] = ['value' => $locationData['country_code'] , 'label' => ctrans('texts.country')];
$data['$email'] = ['value' => isset($this->contact) ? $this->contact->email : 'no contact email on record', 'label' => ctrans('texts.email')];
if (str_contains($data['$email']['value'], 'example.com')) {
@ -478,21 +479,21 @@ class HtmlEngine
$data['$client.address1'] = &$data['$address1'];
$data['$client.address2'] = &$data['$address2'];
$data['$client_address'] = ['value' => $this->client->present()->address() ?: ' ', 'label' => ctrans('texts.address')];
$data['$client_address'] = ['value' => $locationData['address'], 'label' => ctrans('texts.address')];
$data['$client.address'] = &$data['$client_address'];
$data['$client.postal_code'] = ['value' => $this->client->postal_code ?: ' ', 'label' => ctrans('texts.postal_code')];
$data['$client.postal_code'] = ['value' => $locationData['postal_code'] ?: ' ', 'label' => ctrans('texts.postal_code')];
$data['$client.public_notes'] = ['value' => $this->client->public_notes ?: ' ', 'label' => ctrans('texts.notes')];
$data['$client.city'] = ['value' => $this->client->city ?: ' ', 'label' => ctrans('texts.city')];
$data['$client.state'] = ['value' => $this->client->state ?: ' ', 'label' => ctrans('texts.state')];
$data['$client.city'] = ['value' => $locationData['city'] ?: ' ', 'label' => ctrans('texts.city')];
$data['$client.state'] = ['value' => $locationData['state'] ?: ' ', 'label' => ctrans('texts.state')];
$data['$client.id_number'] = &$data['$id_number'];
$data['$client.vat_number'] = &$data['$vat_number'];
$data['$client.website'] = &$data['$website'];
$data['$client.phone'] = &$data['$phone'];
$data['$city_state_postal'] = ['value' => $this->entity->present()->cityStateZip($this->client->city, $this->client->state, $this->client->postal_code, false) ?: ' ', 'label' => ctrans('texts.city_state_postal')];
$data['$city_state_postal'] = ['value' => $this->entity->present()->cityStateZip($locationData['city'], $locationData['state'], $locationData['postal_code'], false) ?: ' ', 'label' => ctrans('texts.city_state_postal')];
$data['$client.city_state_postal'] = &$data['$city_state_postal'];
$data['$postal_city_state'] = ['value' => $this->entity->present()->cityStateZip($this->client->city, $this->client->state, $this->client->postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city_state')];
$data['$postal_city_state'] = ['value' => $this->entity->present()->cityStateZip($locationData['city'], $locationData['state'], $locationData['postal_code'], true) ?: ' ', 'label' => ctrans('texts.postal_city_state')];
$data['$client.postal_city_state'] = &$data['$postal_city_state'];
$data['$postal_city'] = ['value' => $this->entity->present()->cityStateZip($this->client->city, null, $this->client->postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city')];
$data['$postal_city'] = ['value' => $this->entity->present()->cityStateZip($locationData['city'], null, $locationData['postal_code'], true) ?: ' ', 'label' => ctrans('texts.postal_city')];
$data['$client.postal_city'] = &$data['$postal_city'];
$data['$client.country'] = &$data['$country'];
$data['$client.email'] = &$data['$email'];
@ -505,25 +506,24 @@ class HtmlEngine
$data['$client.billing_postal_code'] = &$data['$client.postal_code'];
$data['$client.billing_country'] = &$data['$client.country'];
$data['$client.shipping_address'] = ['value' => $this->client->present()->shipping_address() ?: ' ', 'label' => ctrans('texts.shipping_address')];
$data['$client.shipping_address1'] = ['value' => $this->client->shipping_address1 ?: ' ', 'label' => ctrans('texts.shipping_address1')];
$data['$client.shipping_address2'] = ['value' => $this->client->shipping_address2 ?: ' ', 'label' => ctrans('texts.shipping_address2')];
$data['$client.shipping_city'] = ['value' => $this->client->shipping_city ?: ' ', 'label' => ctrans('texts.shipping_city')];
$data['$client.shipping_state'] = ['value' => $this->client->shipping_state ?: ' ', 'label' => ctrans('texts.shipping_state')];
$data['$client.shipping_postal_code'] = ['value' => $this->client->shipping_postal_code ?: ' ', 'label' => ctrans('texts.shipping_postal_code')];
$data['$client.shipping_country'] = ['value' => isset($this->client->shipping_country->name) ? ctrans('texts.country_' . $this->client->shipping_country->name) : '', 'label' => ctrans('texts.shipping_country')];
$data['$shipping_postal_city_state'] = ['value' => $this->entity->present()->cityStateZip($this->client->shipping_city, $this->client->shipping_state, $this->client->shipping_postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city_state')];
$data['$client.shipping_address'] = ['value' => $locationData['shipping_address'], 'label' => ctrans('texts.shipping_address')];
$data['$client.shipping_address1'] = ['value' => $locationData['shipping_address1'], 'label' => ctrans('texts.shipping_address1')];
$data['$client.shipping_address2'] = ['value' => $locationData['shipping_address2'], 'label' => ctrans('texts.shipping_address2')];
$data['$client.shipping_city'] = ['value' => $locationData['shipping_city'], 'label' => ctrans('texts.shipping_city')];
$data['$client.shipping_state'] = ['value' => $locationData['shipping_state'], 'label' => ctrans('texts.shipping_state')];
$data['$client.shipping_postal_code'] = ['value' => $locationData['shipping_postal_code'], 'label' => ctrans('texts.shipping_postal_code')];
$data['$client.shipping_country'] = ['value' => ctrans('texts.country_' . $locationData['shipping_country_name']), 'label' => ctrans('texts.shipping_country')];
$data['$shipping_postal_city_state'] = ['value' => $this->entity->present()->cityStateZip($locationData['shipping_city'], $locationData['shipping_state'], $locationData['shipping_postal_code'], true) ?: ' ', 'label' => ctrans('texts.postal_city_state')];
$data['$client.shipping_postal_city_state'] = &$data['$shipping_postal_city_state'];
$data['$shipping_postal_city'] = ['value' => $this->entity->present()->cityStateZip($this->client->shipping_city, null, $this->client->shipping_postal_code, true) ?: ' ', 'label' => ctrans('texts.postal_city')];
$data['$shipping_postal_city'] = ['value' => $this->entity->present()->cityStateZip($locationData['shipping_city'], null, $locationData['shipping_postal_code'], true) ?: ' ', 'label' => ctrans('texts.postal_city')];
$data['$client.shipping_postal_city'] = &$data['$shipping_postal_city'];
$data['$shipping_city_state_postal'] = ['value' => $this->entity->present()->cityStateZip($this->client->shipping_city, $this->client->shipping_state, $this->client->shipping_postal_code, false) ?: ' ', 'label' => ctrans('texts.city_state_postal')];
$data['$shipping_city_state_postal'] = ['value' => $this->entity->present()->cityStateZip($locationData['shipping_city'], $locationData['shipping_state'], $locationData['shipping_postal_code'], false) ?: ' ', 'label' => ctrans('texts.city_state_postal')];
$data['$client.shipping_city_state_postal'] = &$data['$shipping_city_state_postal'];
$data['$client.currency'] = ['value' => $this->client->currency()->code, 'label' => ''];
$data['$client.lang_2'] = ['value' => optional($this->client->language())->locale, 'label' => ''];
$data['$client.balance'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
$data['$client.payment_balance'] = ['value' => Number::formatMoney($this->client->payment_balance, $this->client), 'label' => ctrans('texts.payment_balance_on_file')];
$data['$client_balance'] = ['value' => Number::formatMoney($this->client->balance, $this->client), 'label' => ctrans('texts.account_balance')];
@ -970,29 +970,6 @@ class HtmlEngine
return $country ? $country->iso_3166_2 : ' ';
}
/**
* Due to the way we are compiling the blade template we
* have no ability to iterate, so in the case
* of line taxes where there are multiple rows,
* we use this function to format a section of rows.
*
* @return string a collection of <tr> rows with line item
* aggregate data
*/
// private function makeLineTaxes(): string
// {
// $tax_map = $this->entity_calc->getTaxMap();
// $data = '';
// foreach ($tax_map as $tax) {
// $data .= '<tr class="line_taxes">';
// $data .= '<td>'.$tax['name'].'</td>';
// $data .= '<td>'.Number::formatMoney($tax['total'], $this->client).'</td></tr>';
// }
// return $data;
// }
private function lineTaxValues(): string
{
@ -1007,31 +984,6 @@ class HtmlEngine
return $data;
}
// private function makeTotalTaxes(): string
// {
// $data = '';
// if (! $this->entity_calc->getTotalTaxMap()) {
// return $data;
// }
// foreach ($this->entity_calc->getTotalTaxMap() as $tax) {
// $data .= '<tr>';
// $data .= '<td colspan="{ count($this->entity->company->settings->pdf_variables->total_columns) - 2 }"></td>';
// $data .= '<td>'.$tax['name'].'</td>';
// $data .= '<td>'.Number::formatMoney($tax['total'], $this->client).'</td></tr>';
// }
// return $data;
// }
// private function parseLabelsAndValues($labels, $values, $section): string
// {
// $section = strtr($section, $labels);
// return strtr($section, $values);
// }
/*
| Ensures the URL doesn't have duplicated trailing slash
*/
@ -1041,104 +993,6 @@ class HtmlEngine
return config('ninja.app_url');
}
/**
* Builds CSS to assist with the generation
* of Repeating headers and footers on the PDF.
* @return string The css string
*/
// private function generateCustomCSS(): string
// {
// $header_and_footer = '
// .header, .header-space {
// height: 160px;
// }
// .footer, .footer-space {
// height: 160px;
// }
// .footer {
// position: fixed;
// bottom: 0;
// width: 100%;
// }
// .header {
// position: fixed;
// top: 0mm;
// width: 100%;
// }
// @media print {
// thead {display: table-header-group;}
// tfoot {display: table-footer-group;}
// button {display: none;}
// body {margin: 0;}
// }';
// $header = '
// .header, .header-space {
// height: 160px;
// }
// .header {
// position: fixed;
// top: 0mm;
// width: 100%;
// }
// @media print {
// thead {display: table-header-group;}
// button {display: none;}
// body {margin: 0;}
// }';
// $footer = '
// .footer, .footer-space {
// height: 160px;
// }
// .footer {
// position: fixed;
// bottom: 0;
// width: 100%;
// }
// @media print {
// tfoot {display: table-footer-group;}
// button {display: none;}
// body {margin: 0;}
// }';
// $css = '';
// if ($this->settings->all_pages_header && $this->settings->all_pages_footer) {
// $css .= $header_and_footer;
// } elseif ($this->settings->all_pages_header && ! $this->settings->all_pages_footer) {
// $css .= $header;
// } elseif (! $this->settings->all_pages_header && $this->settings->all_pages_footer) {
// $css .= $footer;
// }
// $css .= '
// .page {
// page-break-after: always;
// }
// @page {
// margin: 0mm
// }
// html {
// ';
// $css .= 'font-size:'.$this->settings->font_size.'px;';
// $css .= '}';
// return $css;
// }
/**
* Generate markup for HTML images on entity.
*
@ -1216,15 +1070,5 @@ class HtmlEngine
</div>
';
// return '
// <table border="0" cellspacing="0" cellpadding="0" align="center">
// <tr style="border: 0 !important; ">
// <td class="new_button" style="padding: 12px 18px 12px 18px; border-radius:5px;" align="center">
// <a href="'. $link .'" target="_blank" style="border: 0 !important;font-size: 18px; font-family: Helvetica, Arial, sans-serif; color: #ffffff; text-decoration: none; display: inline-block;">'. $text .'</a>
// </td>
// </tr>
// </table>
// ';
}
}

View File

@ -25,6 +25,7 @@ return new class extends Migration
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->string('postal_code')->nullable();
$table->boolean('is_shipping_location')->default(false);
$table->boolean('is_deleted')->default(false);
$table->unsignedInteger('country_id')->nullable();

View File

@ -2,11 +2,15 @@
namespace Tests\Feature;
use App\Models\Location;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Session;
use Tests\MockAccountData;
use Tests\TestCase;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\Location;
use App\Utils\HtmlEngine;
use Tests\MockAccountData;
use App\Models\ClientContact;
use Illuminate\Support\Facades\Session;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class LocationApiTest extends TestCase
{
@ -21,6 +25,267 @@ class LocationApiTest extends TestCase
Session::start();
}
public function testResolvingNormalShippingLocationData()
{
$client = Client::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'address1' => '123 Test St',
'address2' => 'Suite 100',
'city' => 'Test City',
'state' => 'TS',
'postal_code' => '12345',
'country_id' => '840', // USA
'shipping_address1' => 'Shipping Address 1',
'shipping_address2' => 'Shipping Address 2',
'shipping_city' => 'Shipping City',
'shipping_state' => 'Shipping State',
'shipping_postal_code' => 'Shipping Postal Code',
'shipping_country_id' => '4',
]);
$contact = ClientContact::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'first_name' => 'Test',
'last_name' => 'Contact',
'email' => 'test@test.com',
'send_email' => true,
]);
$location = Location::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'address1' => 'Location Address 1',
'address2' => 'Location Address 2',
'city' => 'Location City',
'state' => 'Location State',
'postal_code' => 'Location Postal Code',
'country_id' => '4',
'is_shipping_location' => false,
]);
$invoice = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'location_id' => $location->id,
]);
$invoice->service()->createInvitations()->markSent()->save();
$invitation = $invoice->invitations()->first();
$html_engine = new HtmlEngine($invitation);
$html_engine->buildEntityDataArray();
$data = $html_engine->makeValues();
$this->assertEquals('Location Address 1', $data['$client.address1']);
$this->assertEquals('Location Address 2', $data['$client.address2']);
$this->assertEquals('Location City', $data['$client.city']);
$this->assertEquals('Location State', $data['$client.state']);
$this->assertEquals('Location Postal Code', $data['$client.postal_code']);
$this->assertEquals('Afghanistan', $data['$client.country']);
$this->assertEquals('Shipping Address 1', $data['$client.shipping_address1']);
$this->assertEquals('Shipping Address 2', $data['$client.shipping_address2']);
$this->assertEquals('Shipping City', $data['$client.shipping_city']);
$this->assertEquals('Shipping State', $data['$client.shipping_state']);
$this->assertEquals('Shipping Postal Code', $data['$client.shipping_postal_code']);
$this->assertEquals('Afghanistan', $data['$client.shipping_country']);
}
public function testResolvingNormalLocationData()
{
$client = Client::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'address1' => '123 Test St',
'address2' => 'Suite 100',
'city' => 'Test City',
'state' => 'TS',
'postal_code' => '12345',
'country_id' => '840', // USA
]);
$contact = ClientContact::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'first_name' => 'Test',
'last_name' => 'Contact',
'email' => 'test@test.com',
'send_email' => true,
]);
$location = Location::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'address1' => 'Location Address 1',
'address2' => 'Location Address 2',
'city' => 'Location City',
'state' => 'Location State',
'postal_code' => 'Location Postal Code',
'country_id' => '4',
'is_shipping_location' => true,
]);
$invoice = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'location_id' => $location->id,
]);
$invoice->service()->createInvitations()->markSent()->save();
$invitation = $invoice->invitations()->first();
$html_engine = new HtmlEngine($invitation);
$html_engine->buildEntityDataArray();
$data = $html_engine->makeValues();
$this->assertEquals('123 Test St', $data['$client.address1']);
$this->assertEquals('Suite 100', $data['$client.address2']);
$this->assertEquals('Test City', $data['$client.city']);
$this->assertEquals('TS', $data['$client.state']);
$this->assertEquals('12345', $data['$client.postal_code']);
$this->assertEquals('United States', $data['$client.country']);
$this->assertEquals('Location Address 1', $data['$client.shipping_address1']);
$this->assertEquals('Location Address 2', $data['$client.shipping_address2']);
$this->assertEquals('Location City', $data['$client.shipping_city']);
$this->assertEquals('Location State', $data['$client.shipping_state']);
$this->assertEquals('Location Postal Code', $data['$client.shipping_postal_code']);
$this->assertEquals('Afghanistan', $data['$client.shipping_country']);
}
public function testResolvingShippingLocationData()
{
$client = Client::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'address1' => '123 Test St',
'address2' => 'Suite 100',
'city' => 'Test City',
'state' => 'TS',
'postal_code' => '12345',
'country_id' => '840', // USA
]);
$contact = ClientContact::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'first_name' => 'Test',
'last_name' => 'Contact',
'email' => 'test@test.com',
'send_email' => true,
]);
$location = Location::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'address1' => 'Location Address 1',
'address2' => 'Location Address 2',
'city' => 'Location City',
'state' => 'Location State',
'postal_code' => 'Location Postal Code',
'country_id' => '4',
'is_shipping_location' => true,
]);
$invoice = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'location_id' => $location->id,
]);
$invoice->service()->createInvitations()->markSent()->save();
$invitation = $invoice->invitations()->first();
$html_engine = new HtmlEngine($invitation);
$html_engine->buildEntityDataArray();
$data = $html_engine->makeValues();
$this->assertEquals('Location Address 1', $data['$client.shipping_address1']);
$this->assertEquals('Location Address 2', $data['$client.shipping_address2']);
$this->assertEquals('Location City', $data['$client.shipping_city']);
$this->assertEquals('Location State', $data['$client.shipping_state']);
$this->assertEquals('Location Postal Code', $data['$client.shipping_postal_code']);
$this->assertEquals('Afghanistan', $data['$client.shipping_country']);
}
public function testResolvingBusinessLocationData()
{
$client = Client::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'address1' => '123 Test St',
'address2' => 'Suite 100',
'city' => 'Test City',
'state' => 'TS',
'postal_code' => '12345',
'country_id' => '840', // USA
]);
$contact = ClientContact::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'first_name' => 'Test',
'last_name' => 'Contact',
'email' => 'test@test.com',
'send_email' => true,
]);
$location = Location::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'address1' => 'Location Address 1',
'address2' => 'Location Address 2',
'city' => 'Location City',
'state' => 'Location State',
'postal_code' => 'Location Postal Code',
'country_id' => '4',
]);
$invoice = Invoice::factory()->create([
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'client_id' => $client->id,
'location_id' => $location->id,
]);
$invoice->service()->createInvitations()->markSent()->save();
$invitation = $invoice->invitations()->first();
$html_engine = new HtmlEngine($invitation);
$html_engine->buildEntityDataArray();
$data = $html_engine->makeValues();
$this->assertEquals('Location Address 1', $data['$client.address1']);
$this->assertEquals('Location Address 2', $data['$client.address2']);
$this->assertEquals('Location City', $data['$client.city']);
$this->assertEquals('Location State', $data['$client.state']);
$this->assertEquals('Location Postal Code', $data['$client.postal_code']);
$this->assertEquals('Afghanistan', $data['$client.country']);
}
public function testLocationPost()
{
$data = [