diff --git a/app/Helpers/GenerateUrl.php b/app/Helpers/GenerateUrl.php deleted file mode 100644 index a88c855b7d..0000000000 --- a/app/Helpers/GenerateUrl.php +++ /dev/null @@ -1,35 +0,0 @@ -disk)->url($document->path); - - if ($url && $absolute) { - return url($url); - } - - if ($url) { - return $url; - } - - return null; -} diff --git a/app/Http/Controllers/EmailController.php b/app/Http/Controllers/EmailController.php index b731a92b0c..c2df5d3470 100644 --- a/app/Http/Controllers/EmailController.php +++ b/app/Http/Controllers/EmailController.php @@ -113,6 +113,17 @@ class EmailController extends BaseController $body = $request->input('body'); $entity_string = strtolower(class_basename($entity_obj)); +$company = $entity_obj->company; +$settings = $company->settings; + +$settings->reply_to_email = "Reply@example.com"; +$settings->bcc_email = "BCC@example.com"; +$settings->pdf_email_attachment = true; +$settings->ubl_email_attachment = true; + +$company->settings = $settings; +$company->save(); + $entity_obj->invitations->each(function ($invitation) use ($subject, $body, $entity_string, $entity_obj) { if ($invitation->contact->send_email && $invitation->contact->email) { $when = now()->addSeconds(1); diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index ea20eb2cdc..3627e4cfd1 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -212,8 +212,6 @@ class InvoiceController extends BaseController $invoice = $this->invoice_repo->save($request->all(), InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id)); - $invoice = StoreInvoice::dispatchNow($invoice, $request->all(), $invoice->company); //todo potentially this may return mixed ie PDF/$invoice... need to revisit when we implement UI - event(new InvoiceWasCreated($invoice, $invoice->company)); return $this->itemResponse($invoice); diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php index 14d8de6657..892b41d3ca 100644 --- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php +++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php @@ -35,9 +35,24 @@ class StoreInvoiceRequest extends Request public function rules() { - return [ - 'client_id' => 'required|exists:clients,id,company_id,'.auth()->user()->company()->id, - ]; + + $rules = []; + + if($this->input('documents') && is_array($this->input('documents'))) { + $documents = count($this->input('documents')); + + foreach(range(0, $documents) as $index) { + $rules['documents.' . $index] = 'file|mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'; + } + } + elseif($this->input('documents')){ + $rules['documents'] = 'file|mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'; + } + + $rules['client_id'] = 'required|exists:clients,id,company_id,'.auth()->user()->company()->id; + + return $rules; + } protected function prepareForValidation() diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php index 8278d9934a..c697a4d1ee 100644 --- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php @@ -38,11 +38,22 @@ class UpdateInvoiceRequest extends Request public function rules() { - return [ - 'documents' => 'mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx', - //'client_id' => 'required|integer', - //'invoice_type_id' => 'integer', - ]; + \Log::error(print_r($this->all(),1)); + + $rules = []; + + if($this->input('documents') && is_array($this->input('documents'))) { + $documents = count($this->input('documents')); + + foreach(range(0, $documents) as $index) { + $rules['documents.' . $index] = 'file|mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'; + } + } + elseif($this->input('documents')){ + $rules['documents'] = 'file|mimes:png,ai,svg,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'; + } + + return $rules; } protected function prepareForValidation() diff --git a/app/Jobs/Invoice/CreateInvoicePdf.php b/app/Jobs/Invoice/CreateInvoicePdf.php index 2b43fa683e..44f1360280 100644 --- a/app/Jobs/Invoice/CreateInvoicePdf.php +++ b/app/Jobs/Invoice/CreateInvoicePdf.php @@ -74,21 +74,19 @@ class CreateInvoicePdf implements ShouldQueue $file_path = $path . $this->invoice->number . '.pdf'; - $design = Design::find($this->decodePrimaryKey($this->invoice->client->getSetting('invoice_design_id'))); + $design = Design::find($this->decodePrimaryKey($this->invoice->client->getSetting('invoice_design_id'))); - $designer = new Designer($this->invoice, $design, $this->invoice->client->getSetting('pdf_variables'), 'invoice'); + $designer = new Designer($this->invoice, $design, $this->invoice->client->getSetting('pdf_variables'), 'invoice'); //get invoice design - //$html = $this->generateInvoiceHtml($designer->build()->getHtml(), $this->invoice, $this->contact); - $html = $this->generateEntityHtml($designer, $this->invoice, $this->contact); - + $html = $this->generateEntityHtml($designer, $this->invoice, $this->contact); //todo - move this to the client creation stage so we don't keep hitting this unnecessarily Storage::makeDirectory($path, 0755); - $pdf = $this->makePdf(null, null, $html); + $pdf = $this->makePdf(null, null, $html); - $instance = Storage::disk($this->disk)->put($file_path, $pdf); + $instance = Storage::disk($this->disk)->put($file_path, $pdf); return $file_path; } diff --git a/app/Jobs/Invoice/CreateUbl.php b/app/Jobs/Invoice/CreateUbl.php new file mode 100644 index 0000000000..e525521586 --- /dev/null +++ b/app/Jobs/Invoice/CreateUbl.php @@ -0,0 +1,318 @@ +invoice = $invoice; + } + + /** + * Execute the job. + * + * + * @return void + */ + + public function handle() + { + $invoice = $this->invoice; + $company = $invoice->company; + $client = $invoice->client; + $ubl_invoice = new UBLInvoice(); + + // invoice + $ubl_invoice->setId($invoice->number); + $ubl_invoice->setIssueDate(date_create($invoice->date)); + $ubl_invoice->setInvoiceTypeCode($invoice->amount < 0 ? self::INVOICE_TYPE_CREDIT : self::INVOICE_TYPE_STANDARD); + + $supplier_party = $this->createParty($company, $invoice->user); + $ubl_invoice->setAccountingSupplierParty($supplier_party); + + $customer_party = $this->createParty($client, $client->contacts[0]); + $ubl_invoice->setAccountingCustomerParty($customer_party); + + // line items + $invoice_lines = []; + $taxable = $this->getTaxable(); + + foreach ($invoice->line_items as $index => $item) { + $itemTaxable = $this->getItemTaxable($item, $taxable); + $invoice_lines[] = $this->createInvoiceLine($index, $item, $itemTaxable); + } + + $ubl_invoice->setInvoiceLines($invoice_lines); + + $taxtotal = new TaxTotal(); + $taxAmount1 = $taxAmount2 = 0; + + $taxAmount1 = $this->createTaxRate($taxtotal, $taxable, $invoice->tax_rate1, $invoice->tax_name1); + if ($invoice->tax_name2 || floatval($invoice->tax_rate2)) { + $taxAmount2 = $this->createTaxRate($taxtotal, $taxable, $invoice->tax_rate2, $invoice->tax_name2); + } + + $taxtotal->setTaxAmount($taxAmount1 + $taxAmount2); + $ubl_invoice->setTaxTotal($taxtotal); + + $ubl_invoice->setLegalMonetaryTotal((new LegalMonetaryTotal()) + //->setLineExtensionAmount() + ->setTaxExclusiveAmount($taxable) + ->setPayableAmount($invoice->balance)); + + try { + return Generator::invoice($ubl_invoice, $invoice->client->getCurrencyCode()); + } catch (\Exception $exception) { + info(print_r($exception,1)); + return false; + } + } + + private function createParty($company, $user) + { + $party = new Party(); + $party->setName($company->present()->name); + $address = (new Address()) + ->setCityName($company->city) + ->setStreetName($company->address1) + ->setBuildingNumber($company->address2) + ->setPostalZone($company->postal_code); + + if ($company->country_id) { + $country = new Country(); + $country->setIdentificationCode($company->country->iso_3166_2); + $address->setCountry($country); + } + + $party->setPostalAddress($address); + $party->setPhysicalLocation($address); + + $contact = new Contact(); + $contact->setElectronicMail($user->email); + $party->setContact($contact); + + return $party; + } + + private function createInvoiceLine($index, $item, $taxable) + { + $invoiceLine = (new InvoiceLine()) + ->setId($index + 1) + ->setInvoicedQuantity($item->quantity) + ->setLineExtensionAmount($this->costWithDiscount($item)) + ->setItem((new Item()) + ->setName($item->product_key) + ->setDescription($item->notes)); + //->setSellersItemIdentification("1ABCD")); + + $taxtotal = new TaxTotal(); + $itemTaxAmount1 = $itemTaxAmount2 = $itemTaxAmount3 = 0; + + $itemTaxAmount1 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate1, $item->tax_name1); + + if ($item->tax_name2 || floatval($item->tax_rate2)) { + $itemTaxAmount2 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate2, $item->tax_name2); + } + + if($item->tax_name3 || floatval($item->tax_rate3)){ + $itemTaxAmount3 = $this->createTaxRate($taxtotal, $taxable, $item->tax_rate3, $item->tax_name3); + } + + $taxtotal->setTaxAmount($itemTaxAmount1 + $itemTaxAmount2 + $itemTaxAmount3); + $invoiceLine->setTaxTotal($taxtotal); + + return $invoiceLine; + } + + private function createTaxRate(&$taxtotal, $taxable, $taxRate, $taxName) + { + $invoice = $this->invoice; + $taxAmount = $this->taxAmount($taxable, $taxRate); + $taxScheme = ((new TaxScheme()))->setId($taxName); + + $taxtotal->addTaxSubTotal((new TaxSubTotal()) + ->setTaxAmount($taxAmount) + ->setTaxableAmount($taxable) + ->setTaxCategory((new TaxCategory()) + ->setId($taxName) + ->setName($taxName) + ->setTaxScheme($taxScheme) + ->setPercent($taxRate))); + + return $taxAmount; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /** + * @param $invoiceItem + * @param $invoiceTotal + * + * @return float|int + */ + private function getItemTaxable($item, $invoice_total) + { + $total = $item->quantity * $item->cost; + + if ($this->invoice->discount != 0) { + if ($this->invoice->is_amount_discount) { + if ($invoice_total + $this->invoice->discount != 0) { + $total -= $invoice_total ? ($total / ($invoice_total + $this->invoice->discount) * $this->invoice->discount) : 0; + } + } else { + $total *= (100 - $this->invoice->discount) / 100; + } + } + + if ($item->discount != 0) { + if ($this->invoice->is_amount_discount) { + $total -= $item->discount; + } else { + $total -= $total * $item->discount / 100; + } + } + + return round($total, 2); + } + + /** + * @return float|int|mixed + */ + private function getTaxable() + { + $total = 0; + + foreach ($this->invoice->line_items as $item) { + $line_total = $item->quantity * $item->cost; + + if ($item->discount != 0) { + if ($this->invoice->is_amount_discount) { + $line_total -= $item->discount; + } else { + $line_total -= $line_total * $item->discount / 100; + } + } + + $total += $line_total; + } + + if ($this->invoice->discount > 0) { + if ($this->invoice->is_amount_discount) { + $total -= $this->invoice->discount; + } else { + $total *= (100 - $this->invoice->discount) / 100; + $total = round($total, 2); + } + } + + if ($this->invoice->custom_surcharge1 && $this->invoice->custom_surcharge_tax1) + $total += $this->invoice->custom_surcharge1; + + + if ($this->invoice->custom_surcharge2 && $this->invoice->custom_surcharge_tax2) + $total += $this->invoice->custom_surcharge2; + + + if ($this->invoice->custom_surcharge3 && $this->invoice->custom_surcharge_tax3) + $total += $this->invoice->custom_surcharge3; + + + if ($this->invoice->custom_surcharge4 && $this->invoice->custom_surcharge_tax4) + $total += $this->invoice->custom_surcharge4; + + + return $total; + } + + public function costWithDiscount($item) + { + $cost = $item->cost; + + if ($item->discount != 0) { + if ($this->invoice->is_amount_discount) { + $cost -= $item->discount / $item->quantity; + } else { + $cost -= $cost * $item->discount / 100; + } + } + + return $cost; + } + + public function taxAmount($taxable, $rate) + { + if ($this->invoice->uses_inclusive_taxes) { + return round($taxable - ($taxable / (1 + ($rate / 100))), 2); + } else { + return round($taxable * ($rate / 100), 2); + } + } + + + + + + +} \ No newline at end of file diff --git a/app/Jobs/Invoice/InvoiceNotification.php b/app/Jobs/Invoice/InvoiceNotification.php deleted file mode 100644 index 7a6bad80ed..0000000000 --- a/app/Jobs/Invoice/InvoiceNotification.php +++ /dev/null @@ -1,51 +0,0 @@ -invoice = $invoice; - } - - /** - * Execute the job. - * - * - * @return void - */ - public function handle() - { - - //notification for the invoice. - // - //could mean a email, sms, slack, push - } -} diff --git a/app/Jobs/Invoice/StoreInvoice.php b/app/Jobs/Invoice/StoreInvoice.php deleted file mode 100644 index 2f8c351cd2..0000000000 --- a/app/Jobs/Invoice/StoreInvoice.php +++ /dev/null @@ -1,107 +0,0 @@ -invoice = $invoice; - - $this->data = $data; - - $this->company = $company; - } - - /** - * Execute the job. - * - * We expect the Invoice object along with - * the request in array form - * - * Embedded in the request may be additional - * attributes which require additional work to be - * done in this job, these include - but are not limited to: - * - * 1. email_invoice - Email the Invoice - * 2. mark_paid - Mark the invoice as paid (Generates a payment against the invoice) - * 3. ...... - * - * @return NULL|Invoice - */ - public function handle(InvoiceRepository $invoice_repo) : ?Invoice - { - $payment = false; - - // /* Test if we should auto-bill the invoice */ - // if(property_exists($this->invoice->client->getSetting('auto_bill')) && (bool)$this->invoice->client->getSetting('auto_bill')) - // { - - // $this->invoice = $invoice_repo->markSent($this->invoice); - - // //fire autobill - todo - the PAYMENT class will update the INVOICE status. - // // $payment = - - // } - - if (isset($this->data['email_invoice']) && (bool)$this->data['email_invoice']) { - $this->invoice = $invoice_repo->markSent($this->invoice); - - //fire invoice job (the job performs the filtering logic of the email recipients... if any.) - InvoiceNotification::dispatch($invoice, $invoice->company); - } - - if (isset($this->data['mark_paid']) && (bool)$this->data['mark_paid']) { - $this->invoice = $invoice_repo->markSent($this->invoice); - - // generate a manual payment against the invoice - // the PAYMENT class will update the INVOICE status. - //$payment = - } - - /* Payment Notifications */ - if ($payment) { - //fire payment notifications here - PaymentNotification::dispatch($payment, $payment->company); - } - - if (isset($data['download_invoice']) && (bool)$this->data['download_invoice']) { - //fire invoice download and return PDF response from here - } - - return $this->invoice; - } -} diff --git a/app/Jobs/Util/UploadFile.php b/app/Jobs/Util/UploadFile.php index 1b7b923c52..536dd94cab 100644 --- a/app/Jobs/Util/UploadFile.php +++ b/app/Jobs/Util/UploadFile.php @@ -56,7 +56,7 @@ class UploadFile implements ShouldQueue $this->entity = $entity; $this->disk = $disk ?? config('filesystems.default'); - MultiDB::setDB($this->company->db); + //MultiDB::setDB($this->company->db); } /** diff --git a/app/Models/Account.php b/app/Models/Account.php index 2336c281f1..575843e43e 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -168,12 +168,12 @@ class Account extends BaseModel $planDetails = $this->getPlanDetails(false, false); } - return $selfHost || ! empty($planDetails) && ($planDetails['plan'] == self::PLAN_ENTERPRISE); + return $self_host || ! empty($planDetails) && ($planDetails['plan'] == self::PLAN_ENTERPRISE); // Enterprise; No Trial allowed case self::FEATURE_DOCUMENTS: case self::FEATURE_USER_PERMISSIONS: - return $selfHost || ! empty($planDetails) && $planDetails['plan'] == self::PLAN_ENTERPRISE && ! $planDetails['trial']; + return $self_host || ! empty($planDetails) && $planDetails['plan'] == self::PLAN_ENTERPRISE && ! $planDetails['trial']; default: return false; diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index bbca7eb38c..927eaad692 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -173,4 +173,12 @@ class BaseModel extends Model return new Designer($this, $design, $this->client->getSetting('pdf_variables'), $entity); } + + /** + * @return string + */ + public function getFileName($extension = 'pdf') + { + return $this->number . '.' . $extension; + } } diff --git a/app/Models/Client.php b/app/Models/Client.php index 12e02734bf..93c87c222c 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -436,10 +436,6 @@ class Client extends BaseModel implements HasLocalePreference return $languages->filter(function ($item) { return $item->id == $this->getSetting('language_id'); })->first()->locale; - - //$lang = Language::find($this->client->getSetting('language_id')); - - //return $lang->locale; } public function invoice_filepath() @@ -462,6 +458,11 @@ class Client extends BaseModel implements HasLocalePreference return $this->company->company_key . '/'; } + public function document_filepath() + { + return $this->company->company_key . '/documents/'; + } + public function setCompanyDefaults($data, $entity_name) :array { $defaults = []; diff --git a/app/Models/Document.php b/app/Models/Document.php index 097352e736..8a06b73f5c 100644 --- a/app/Models/Document.php +++ b/app/Models/Document.php @@ -13,6 +13,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Facades\Storage; class Document extends BaseModel { @@ -92,4 +93,21 @@ class Document extends BaseModel { return $this->morphTo(); } + + function generateUrl($absolute = false) + { + $url = Storage::disk($this->disk)->url($this->path); + + if ($url && $absolute) { + return url($url); + } + + if ($url) { + return $url; + } + + return null; + } + + } diff --git a/app/Notifications/Admin/EntitySentNotification.php b/app/Notifications/Admin/EntitySentNotification.php index b9afa0c564..7f8f3a8df2 100644 --- a/app/Notifications/Admin/EntitySentNotification.php +++ b/app/Notifications/Admin/EntitySentNotification.php @@ -118,18 +118,6 @@ class EntitySentNotification extends Notification implements ShouldQueue $logo = $this->invitation->company->present()->logo(); $amount = Number::formatMoney($this->entity->amount, $this->entity->client); - // return (new SlackMessage) - // ->success() - // ->from(ctrans('texts.notification_bot')) - // ->image($logo) - // ->content(ctrans('texts.notification_invoice_sent', - // [ - // 'amount' => $amount, - // 'client' => $this->contact->present()->name(), - // 'invoice' => $this->invoice->number - // ])); - - return (new SlackMessage) ->from(ctrans('texts.notification_bot')) ->success() diff --git a/app/Notifications/Admin/InvoiceSentNotification.php b/app/Notifications/Admin/InvoiceSentNotification.php index ff6bebedd3..102d092255 100644 --- a/app/Notifications/Admin/InvoiceSentNotification.php +++ b/app/Notifications/Admin/InvoiceSentNotification.php @@ -112,18 +112,6 @@ class InvoiceSentNotification extends Notification implements ShouldQueue $logo = $this->company->present()->logo(); $amount = Number::formatMoney($this->invoice->amount, $this->invoice->client); - // return (new SlackMessage) - // ->success() - // ->from(ctrans('texts.notification_bot')) - // ->image($logo) - // ->content(ctrans('texts.notification_invoice_sent', - // [ - // 'amount' => $amount, - // 'client' => $this->contact->present()->name(), - // 'invoice' => $this->invoice->number - // ])); - - return (new SlackMessage) ->from(ctrans('texts.notification_bot')) ->success() diff --git a/app/Notifications/Admin/InvoiceViewedNotification.php b/app/Notifications/Admin/InvoiceViewedNotification.php index a99dddc5fc..a5634e5dc9 100644 --- a/app/Notifications/Admin/InvoiceViewedNotification.php +++ b/app/Notifications/Admin/InvoiceViewedNotification.php @@ -87,15 +87,6 @@ class InvoiceViewedNotification extends Notification implements ShouldQueue 'logo' => $this->company->present()->logo(), ]; - // if($this->settings->email_style == 'custom'){ - - // $subject = - - // return (new MailMessage) - // ->subject($subject) - // ->view('email.template.custom', ['body' => ]); - // } - return (new MailMessage) ->subject($subject) ->markdown('email.admin.generic', $data); diff --git a/app/Notifications/Admin/NewPaymentNotification.php b/app/Notifications/Admin/NewPaymentNotification.php index e0828f73ef..c42536b2e4 100644 --- a/app/Notifications/Admin/NewPaymentNotification.php +++ b/app/Notifications/Admin/NewPaymentNotification.php @@ -48,10 +48,6 @@ class NewPaymentNotification extends Notification implements ShouldQueue * @param mixed $notifiable * @return array */ - // public function via($notifiable) - // { - // return $this->is_system ? ['slack'] : ['mail']; - //} public function via($notifiable) { diff --git a/app/Notifications/SendGenericNotification.php b/app/Notifications/SendGenericNotification.php index e35a40a30d..b7ded38872 100644 --- a/app/Notifications/SendGenericNotification.php +++ b/app/Notifications/SendGenericNotification.php @@ -2,6 +2,8 @@ namespace App\Notifications; +use App\Jobs\Invoice\CreateUbl; +use App\Models\Invoice; use App\Utils\Number; use App\Utils\Traits\MakesInvoiceHtml; use Illuminate\Bus\Queueable; @@ -36,7 +38,7 @@ class SendGenericNotification extends Notification implements ShouldQueue protected $settings; - public $is_system; + public $is_system; protected $body; @@ -92,9 +94,30 @@ class SendGenericNotification extends Notification implements ShouldQueue ]; - return (new MailMessage) + $mail_message = (new MailMessage) ->subject($subject) ->markdown('email.admin.generic_email', $data); + + if(strlen($this->settings->reply_to_email) > 1) + $mail_message->replyTo($this->settings->reply_to_email); + + if(strlen($this->settings->bcc_email) > 1) + $mail_message->bcc($this->settings->bcc_email); + + if($this->settings->pdf_email_attachment) + $mail_message->attach(public_path($this->entity->pdf_file_path())); + + foreach($this->entity->documents as $document){ + $mail_message->attach($document->generateUrl(), ['as' => $document->name]); + } + + if($this->entity instanceof Invoice && $this->settings->ubl_email_attachment){ + $ubl_string = CreateUbl::dispatchNow($this->entity); + $mail_message->attachData($ubl_string, $this->entity->getFileName('xml')); + } + + return $mail_message; + } /** diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php index cf43c56a31..8b44890eb0 100644 --- a/app/Repositories/BaseRepository.php +++ b/app/Repositories/BaseRepository.php @@ -21,6 +21,7 @@ use App\Models\Invoice; use App\Models\InvoiceInvitation; use App\Models\Quote; use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; use ReflectionClass; /** @@ -29,6 +30,8 @@ use ReflectionClass; class BaseRepository { use MakesHash; + use SavesDocuments; + /** * @return null */ @@ -221,10 +224,12 @@ class BaseRepository unset($tmp_data['client_contacts']); } - $model->fill($tmp_data); $model->save(); + if(array_key_exists('documents', $data)) + $this->saveDocuments($data['documents'], $model); + $invitation_factory_class = sprintf("App\\Factory\\%sInvitationFactory", $resource); if (isset($data['client_contacts'])) { diff --git a/app/Transformers/InvoiceTransformer.php b/app/Transformers/InvoiceTransformer.php index 8ac568fa29..eed103abfe 100644 --- a/app/Transformers/InvoiceTransformer.php +++ b/app/Transformers/InvoiceTransformer.php @@ -11,8 +11,10 @@ namespace App\Transformers; +use App\Models\Document; use App\Models\Invoice; use App\Models\InvoiceInvitation; +use App\Transformers\DocumentTransformer; use App\Transformers\InvoiceInvitationTransformer; use App\Utils\Traits\MakesHash; @@ -21,7 +23,8 @@ class InvoiceTransformer extends EntityTransformer use MakesHash; protected $defaultIncludes = [ - 'invitations' + 'invitations', + 'documents', ]; protected $availableIncludes = [ @@ -67,18 +70,18 @@ class InvoiceTransformer extends EntityTransformer return $this->includeCollection($invoice->expenses, $transformer, ENTITY_EXPENSE); } - - public function includeDocuments(Invoice $invoice) - { - $transformer = new DocumentTransformer($this->account, $this->serializer); - - $invoice->documents->each(function ($document) use ($invoice) { - $document->setRelation('invoice', $invoice); - }); - - return $this->includeCollection($invoice->documents, $transformer, ENTITY_DOCUMENT); - } */ + public function includeDocuments(Invoice $invoice) + { + $transformer = new DocumentTransformer($this->serializer); + + // $invoice->documents->each(function ($document) use ($invoice) { + // $document->setRelation('invoice', $invoice); + // }); + + return $this->includeCollection($invoice->documents, $transformer, Document::class); + } + public function transform(Invoice $invoice) { return [ diff --git a/app/Utils/Traits/SavesDocuments.php b/app/Utils/Traits/SavesDocuments.php new file mode 100644 index 0000000000..5ac71032b0 --- /dev/null +++ b/app/Utils/Traits/SavesDocuments.php @@ -0,0 +1,49 @@ +account; + $company = $entity; + } + else{ + $account = $entity->company->account; + $company = $entity->company; + } + + if(!$account->hasFeature(Account::FEATURE_DOCUMENTS)) + return false; + + foreach($document_array as $document) { + + $document = UploadFile::dispatchNow( + $document, + UploadFile::DOCUMENT, + $entity->user, + $entity->company, + $entity + ); + + } + + } +} diff --git a/composer.json b/composer.json index a7fdbcb712..37e2f47db4 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ "php": ">=7.3", "ext-json": "*", "asgrim/ofxparser": "^1.2", + "cleverit/ubl_invoice": "^1.3", "codedge/laravel-selfupdater": "2.5.1", "composer/composer": "^1.10", "dacastro4/laravel-gmail": "^3.2", diff --git a/tests/Unit/UBLInvoiceTest.php b/tests/Unit/UBLInvoiceTest.php new file mode 100644 index 0000000000..ab7b507a48 --- /dev/null +++ b/tests/Unit/UBLInvoiceTest.php @@ -0,0 +1,42 @@ +withoutMiddleware( + ThrottleRequests::class + ); + $this->makeTestData(); + + } + + public function testUblGenerates() + { + $ubl = CreateUbl::dispatchNow($this->invoice); + + $this->assertNotNull($ubl); + } + +} \ No newline at end of file