Merge branch 'master' of github.com:akaunting/akaunting
This commit is contained in:
		| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| namespace App\Abstracts; | ||||
|  | ||||
| use App\Abstracts\Http\FormRequest; | ||||
| use App\Traits\Import as ImportHelper; | ||||
| use App\Traits\Sources; | ||||
| use App\Utilities\Date; | ||||
| @@ -11,6 +12,7 @@ use Illuminate\Contracts\Translation\HasLocalePreference; | ||||
| use Illuminate\Support\Arr; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Support\Facades\Validator; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Maatwebsite\Excel\Concerns\Importable; | ||||
| use Maatwebsite\Excel\Concerns\SkipsEmptyRows; | ||||
| use Maatwebsite\Excel\Concerns\ToModel; | ||||
| @@ -27,6 +29,8 @@ abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRow | ||||
|  | ||||
|     public $user; | ||||
|  | ||||
|     public $request_class = null; | ||||
|  | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->user = user(); | ||||
| @@ -70,6 +74,49 @@ abstract class Import implements HasLocalePreference, ShouldQueue, SkipsEmptyRow | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * You can override this method to add custom rules for each row. | ||||
|      */ | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Validate each row data. | ||||
|      * | ||||
|      * @param \Illuminate\Validation\Validator $validator | ||||
|      * @throws ValidationException | ||||
|      */ | ||||
|     public function withValidator($validator) | ||||
|     { | ||||
|         $condition = class_exists($this->request_class) | ||||
|                     ? ! ($request = new $this->request_class) instanceof FormRequest | ||||
|                     : true; | ||||
|  | ||||
|         if ($condition) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         foreach ($validator->getData() as $row => $data) { | ||||
|             $request->initialize(request: $data); | ||||
|  | ||||
|             $rules = $this->prepareRules($request->rules()); | ||||
|  | ||||
|             try { | ||||
|                 Validator::make($data, $rules)->validate(); | ||||
|             } catch (ValidationException $e) { | ||||
|                 foreach ($e->validator->failed() as $attribute => $value) { | ||||
|                     foreach ($value as $rule => $params) { | ||||
|                         $validator->addFailure($row . '.' . $attribute, $rule, $params); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 throw new ValidationException($validator); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function chunkSize(): int | ||||
|     { | ||||
|         return config('excel.imports.chunk_size'); | ||||
|   | ||||
| @@ -31,7 +31,7 @@ class Bills extends BulkAction | ||||
|         ], | ||||
|         'cancelled' => [ | ||||
|             'icon'          => 'cancel', | ||||
|             'name'          => 'general.cancel', | ||||
|             'name'          => 'documents.actions.cancel', | ||||
|             'message'       => 'bulk_actions.message.cancelled', | ||||
|             'permission'    => 'update-purchases-bills', | ||||
|         ], | ||||
|   | ||||
| @@ -31,7 +31,7 @@ class Invoices extends BulkAction | ||||
|         ], | ||||
|         'cancelled' => [ | ||||
|             'icon'          => 'cancel', | ||||
|             'name'          => 'general.cancel', | ||||
|             'name'          => 'documents.actions.cancel', | ||||
|             'message'       => 'bulk_actions.message.cancelled', | ||||
|             'permission'    => 'update-sales-invoices', | ||||
|         ], | ||||
|   | ||||
							
								
								
									
										20
									
								
								app/Events/Document/DocumentSending.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Events/Document/DocumentSending.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Events\Document; | ||||
|  | ||||
| use App\Abstracts\Event; | ||||
|  | ||||
| class DocumentSending extends Event | ||||
| { | ||||
|     public $document; | ||||
|  | ||||
|     /** | ||||
|      * Create a new event instance. | ||||
|      * | ||||
|      * @param $document | ||||
|      */ | ||||
|     public function __construct($document) | ||||
|     { | ||||
|         $this->document = $document; | ||||
|     } | ||||
| } | ||||
| @@ -22,6 +22,7 @@ class BillItems extends Export | ||||
|  | ||||
|         $model->bill_number = $document->document_number; | ||||
|         $model->item_name = $model->item->name; | ||||
|         $model->item_type = $model->item->type; | ||||
|  | ||||
|         return parent::map($model); | ||||
|     } | ||||
| @@ -31,6 +32,7 @@ class BillItems extends Export | ||||
|         return [ | ||||
|             'bill_number', | ||||
|             'item_name', | ||||
|             'item_type', | ||||
|             'quantity', | ||||
|             'price', | ||||
|             'total', | ||||
|   | ||||
| @@ -22,6 +22,7 @@ class InvoiceItems extends Export | ||||
|  | ||||
|         $model->invoice_number = $document->document_number; | ||||
|         $model->item_name = $model->item->name; | ||||
|         $model->item_type = $model->item->type; | ||||
|  | ||||
|         return parent::map($model); | ||||
|     } | ||||
| @@ -31,6 +32,7 @@ class InvoiceItems extends Export | ||||
|         return [ | ||||
|             'invoice_number', | ||||
|             'item_name', | ||||
|             'item_type', | ||||
|             'quantity', | ||||
|             'price', | ||||
|             'total', | ||||
|   | ||||
| @@ -10,6 +10,7 @@ use App\Imports\Sales\Invoices as Import; | ||||
| use App\Jobs\Document\CreateDocument; | ||||
| use App\Jobs\Document\DeleteDocument; | ||||
| use App\Jobs\Document\DuplicateDocument; | ||||
| use App\Jobs\Document\SendDocument; | ||||
| use App\Jobs\Document\UpdateDocument; | ||||
| use App\Models\Document\Document; | ||||
| use App\Notifications\Sale\Invoice as Notification; | ||||
| @@ -260,12 +261,17 @@ class Invoices extends Controller | ||||
|             return redirect()->back(); | ||||
|         } | ||||
|  | ||||
|         // Notify the customer | ||||
|         $invoice->contact->notify(new Notification($invoice, 'invoice_new_customer', true)); | ||||
|         $response = $this->ajaxDispatch(new SendDocument($invoice)); | ||||
|  | ||||
|         event(new \App\Events\Document\DocumentSent($invoice)); | ||||
|         if ($response['success']) { | ||||
|             $message = trans('documents.messages.email_sent', ['type' => trans_choice('general.invoices', 1)]); | ||||
|  | ||||
|         flash(trans('documents.messages.email_sent', ['type' => trans_choice('general.invoices', 1)]))->success(); | ||||
|             flash($message)->success(); | ||||
|         } else { | ||||
|             $message = $response['message']; | ||||
|  | ||||
|             flash($message)->error()->important(); | ||||
|         } | ||||
|  | ||||
|         return redirect()->back(); | ||||
|     } | ||||
|   | ||||
| @@ -29,7 +29,7 @@ class Transaction extends FormRequest | ||||
|         } | ||||
|  | ||||
|         // Get company id | ||||
|         $company_id = (int) $this->request->get('company_id'); | ||||
|         $company_id = (int) $this->request->get('company_id', company_id()); | ||||
|  | ||||
|         $attachment = 'nullable'; | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,7 @@ class Item extends FormRequest | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'type'              => 'required|string', | ||||
|             'type'              => 'required|string|in:product,service', | ||||
|             'name'              => 'required|string', | ||||
|             'sale_price'        => $sale_price . '|regex:/^(?=.*?[0-9])[0-9.,]+$/', | ||||
|             'purchase_price'    => $purchase_price . '|regex:/^(?=.*?[0-9])[0-9.,]+$/', | ||||
|   | ||||
| @@ -48,7 +48,7 @@ class Document extends FormRequest | ||||
|         $rules = [ | ||||
|             'type'                  => 'required|string', | ||||
|             'document_number'       => 'required|string|unique:documents,NULL,' . $id . ',id,type,' . $type . ',company_id,' . $company_id . ',deleted_at,NULL', | ||||
|             'status'                => 'required|string', | ||||
|             'status'                => 'required|string|in:draft,paid,partial,sent,received,viewed,cancelled', | ||||
|             'issued_at'             => 'required|date_format:Y-m-d H:i:s|before_or_equal:due_at', | ||||
|             'due_at'                => 'required|date_format:Y-m-d H:i:s|after_or_equal:issued_at', | ||||
|             'amount'                => 'required', | ||||
|   | ||||
| @@ -22,9 +22,9 @@ class Tax extends FormRequest | ||||
|             $enabled = 'nullable'; | ||||
|         } | ||||
|  | ||||
|         $company_id = (int) $this->request->get('company_id'); | ||||
|         $company_id = (int) $this->request->get('company_id', company_id()); | ||||
|  | ||||
|         $type = 'required|string'; | ||||
|         $type = 'required|string|in:fixed,normal,inclusive,withholding,compound'; | ||||
|  | ||||
|         if (!empty($this->request->get('type')) && $this->request->get('type') == 'compound') { | ||||
|             $type .= '|unique:taxes,NULL,' . $id . ',id,company_id,' . $company_id . ',type,compound,deleted_at,NULL'; | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Banking\Transaction as Model; | ||||
|  | ||||
| class Transactions extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -25,9 +27,4 @@ class Transactions extends Import | ||||
|  | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return (new Request())->rules(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -26,10 +26,10 @@ class Transfers extends Import | ||||
|         $row = parent::map($row); | ||||
|  | ||||
|         $row['transferred_at'] = Date::parse($row['transferred_at'])->format('Y-m-d'); | ||||
|         $row['from_account_id'] = $this->getFromAccountId($row); | ||||
|         $row['to_account_id'] = $this->getToAccountId($row); | ||||
|         $row['from_currency_code'] = $this->getFromCurrencyCode($row); | ||||
|         $row['to_currency_code'] = $this->getToCurrencyCode($row); | ||||
|         $row['from_account_id'] = $this->getFromAccountId($row); | ||||
|         $row['to_account_id'] = $this->getToAccountId($row); | ||||
|         $row['expense_transaction_id'] = $this->getExpenseTransactionId($row); | ||||
|         $row['income_transaction_id'] = $this->getIncomeTransactionId($row); | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Common\ItemTax as Model; | ||||
|  | ||||
| class ItemTaxes extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -27,9 +29,4 @@ class ItemTaxes extends Import | ||||
|  | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return (new Request())->rules(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Common\Item as Model; | ||||
|  | ||||
| class Items extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -25,9 +27,4 @@ class Items extends Import | ||||
|  | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return (new Request())->rules(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use App\Models\Document\DocumentHistory as Model; | ||||
|  | ||||
| class BillHistories extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -33,10 +35,8 @@ class BillHistories extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['bill_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['bill_id']); | ||||
|   | ||||
| @@ -11,6 +11,8 @@ use App\Models\Document\DocumentItemTax as Model; | ||||
|  | ||||
| class BillItemTaxes extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -46,10 +48,8 @@ class BillItemTaxes extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['bill_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['bill_id']); | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use App\Models\Document\DocumentItem as Model; | ||||
|  | ||||
| class BillItems extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -39,10 +41,8 @@ class BillItems extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['bill_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['bill_id']); | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use App\Models\Document\DocumentTotal as Model; | ||||
|  | ||||
| class BillTotals extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -30,10 +32,8 @@ class BillTotals extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['bill_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['bill_id']); | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Banking\Transaction as Model; | ||||
|  | ||||
| class BillTransactions extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -34,10 +36,8 @@ class BillTransactions extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['bill_number'] = 'required|string'; | ||||
|  | ||||
|         return $rules; | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use Illuminate\Support\Str; | ||||
|  | ||||
| class Bills extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -37,16 +39,14 @@ class Bills extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['bill_number'] = Str::replaceFirst('unique:documents,NULL', 'unique:documents,document_number', $rules['document_number']); | ||||
|         $rules['billed_at'] = $rules['issued_at']; | ||||
|         $rules['currency_rate'] = 'required'; | ||||
|  | ||||
|         unset($rules['document_number'], $rules['issued_at'], $rules['type']); | ||||
|  | ||||
|         return $this->replaceForBatchRules($rules); | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Common\Contact as Model; | ||||
|  | ||||
| class Vendors extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -26,9 +28,4 @@ class Vendors extends Import | ||||
|  | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return (new Request())->rules(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Common\Contact as Model; | ||||
|  | ||||
| class Customers extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -26,9 +28,4 @@ class Customers extends Import | ||||
|  | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return (new Request())->rules(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use App\Models\Document\DocumentHistory as Model; | ||||
|  | ||||
| class InvoiceHistories extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -33,10 +35,8 @@ class InvoiceHistories extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['invoice_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['invoice_id']); | ||||
|   | ||||
| @@ -11,6 +11,8 @@ use App\Models\Document\DocumentItemTax as Model; | ||||
|  | ||||
| class InvoiceItemTaxes extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -46,10 +48,8 @@ class InvoiceItemTaxes extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['invoice_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['invoice_id']); | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use App\Models\Document\DocumentItem as Model; | ||||
|  | ||||
| class InvoiceItems extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -39,10 +41,8 @@ class InvoiceItems extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['invoice_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['invoice_id']); | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use App\Models\Document\DocumentTotal as Model; | ||||
|  | ||||
| class InvoiceTotals extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -30,10 +32,8 @@ class InvoiceTotals extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['invoice_number'] = 'required|string'; | ||||
|  | ||||
|         unset($rules['invoice_id']); | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Banking\Transaction as Model; | ||||
|  | ||||
| class InvoiceTransactions extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -24,20 +26,18 @@ class InvoiceTransactions extends Import | ||||
|         $row = parent::map($row); | ||||
|  | ||||
|         $row['type'] = 'income'; | ||||
|         $row['currency_code'] = $this->getCurrencyCode($row); | ||||
|         $row['account_id'] = $this->getAccountId($row); | ||||
|         $row['category_id'] = $this->getCategoryId($row, 'income'); | ||||
|         $row['contact_id'] = $this->getContactId($row, 'customer'); | ||||
|         $row['currency_code'] = $this->getCurrencyCode($row); | ||||
|         $row['document_id'] = $this->getDocumentId($row); | ||||
|         $row['number'] = $row['transaction_number']; | ||||
|  | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['invoice_number'] = 'required|string'; | ||||
|  | ||||
|         return $rules; | ||||
|   | ||||
| @@ -9,6 +9,8 @@ use Illuminate\Support\Str; | ||||
|  | ||||
| class Invoices extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -37,16 +39,14 @@ class Invoices extends Import | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     public function prepareRules(array $rules): array | ||||
|     { | ||||
|         $rules = (new Request())->rules(); | ||||
|  | ||||
|         $rules['invoice_number'] = Str::replaceFirst('unique:documents,NULL', 'unique:documents,document_number', $rules['document_number']); | ||||
|         $rules['invoiced_at'] = $rules['issued_at']; | ||||
|         $rules['currency_rate'] = 'required'; | ||||
|  | ||||
|         unset($rules['document_number'], $rules['issued_at'], $rules['type']); | ||||
|  | ||||
|         return $this->replaceForBatchRules($rules); | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use App\Models\Setting\Category as Model; | ||||
|  | ||||
| class Categories extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
| @@ -21,9 +23,4 @@ class Categories extends Import | ||||
|  | ||||
|         return $row; | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return (new Request())->rules(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,13 +8,10 @@ use App\Models\Setting\Tax as Model; | ||||
|  | ||||
| class Taxes extends Import | ||||
| { | ||||
|     public $request_class = Request::class; | ||||
|  | ||||
|     public function model(array $row) | ||||
|     { | ||||
|         return new Model($row); | ||||
|     } | ||||
|  | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return (new Request())->rules(); | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										26
									
								
								app/Jobs/Document/SendDocument.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Jobs/Document/SendDocument.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Jobs\Document; | ||||
|  | ||||
| use App\Abstracts\Job; | ||||
| use App\Events\Document\DocumentSending; | ||||
| use App\Events\Document\DocumentSent; | ||||
| use App\Models\Document\Document; | ||||
|  | ||||
| class SendDocument extends Job | ||||
| { | ||||
|     public function __construct(Document $document) | ||||
|     { | ||||
|         $this->document = $document; | ||||
|     } | ||||
|  | ||||
|     public function handle(): void | ||||
|     { | ||||
|         event(new DocumentSending($document)); | ||||
|  | ||||
|         // Notify the customer | ||||
|         $invoice->contact->notify(new Notification($invoice, 'invoice_new_customer', true)); | ||||
|  | ||||
|         event(new DocumentSent($document)); | ||||
|     } | ||||
| } | ||||
| @@ -3,6 +3,7 @@ | ||||
| namespace App\Jobs\Document; | ||||
|  | ||||
| use App\Abstracts\Job; | ||||
| use App\Events\Document\DocumentSending; | ||||
| use App\Events\Document\DocumentSent; | ||||
| use App\Models\Document\Document; | ||||
|  | ||||
| @@ -18,6 +19,8 @@ class SendDocumentAsCustomMail extends Job | ||||
|     { | ||||
|         $document = Document::find($this->request->get('document_id')); | ||||
|  | ||||
|         event(new DocumentSending($document)); | ||||
|  | ||||
|         $custom_mail = $this->request->only(['to', 'subject', 'body']); | ||||
|  | ||||
|         if ($this->request->get('user_email', false)) { | ||||
|   | ||||
							
								
								
									
										71
									
								
								app/Listeners/Update/V30/Version3013.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								app/Listeners/Update/V30/Version3013.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Listeners\Update\V30; | ||||
|  | ||||
| use App\Abstracts\Listeners\Update as Listener; | ||||
| use App\Events\Install\UpdateFinished as Event; | ||||
| use App\Traits\Categories; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
|  | ||||
| class Version3013 extends Listener | ||||
| { | ||||
|     use Categories; | ||||
|  | ||||
|     const ALIAS = 'core'; | ||||
|  | ||||
|     const VERSION = '3.0.13'; | ||||
|  | ||||
|     /** | ||||
|      * Handle the event. | ||||
|      * | ||||
|      * @param  $event | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(Event $event) | ||||
|     { | ||||
|         if ($this->skipThisUpdate($event)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         Log::channel('stdout')->info('Updating to 3.0.13 version...'); | ||||
|  | ||||
|         DB::transaction(function () { | ||||
|             $types = $this->getTypesByAllowedTranslations(); | ||||
|  | ||||
|             foreach ($types as $type => $translations) { | ||||
|                 DB::table('categories')->whereIn('type', $translations)->update(['type' => $type]); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         Log::channel('stdout')->info('Done!'); | ||||
|     } | ||||
|  | ||||
|     protected function getTypesByAllowedTranslations(): array | ||||
|     { | ||||
|         $types = $this->getCategoryTypes(false); | ||||
|         $lang_codes = array_keys(language()->allowed()); | ||||
|  | ||||
|         foreach ($types as $type => $trans_name) { | ||||
|             $translations_for_type = []; | ||||
|  | ||||
|             foreach ($lang_codes as $lang_code) { | ||||
|                 $translation = trans_choice($trans_name, 1, locale: $lang_code); | ||||
|  | ||||
|                 if ($translation === $trans_name) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 $translations_for_type[] = $translation; | ||||
|             } | ||||
|  | ||||
|             $types[$type] = $translations_for_type; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Example:     en-GB      es-ES | ||||
|          * 'income' => ['Income', 'Ingresos'] | ||||
|          */ | ||||
|         return $types; | ||||
|     } | ||||
| } | ||||
| @@ -614,7 +614,7 @@ class Document extends Model | ||||
|             if (! in_array($this->status, ['cancelled', 'draft'])) { | ||||
|                 try { | ||||
|                     $actions[] = [ | ||||
|                         'title' => trans('general.cancel'), | ||||
|                         'title' => trans('documents.actions.cancel'), | ||||
|                         'icon' => 'cancel', | ||||
|                         'url' => route($prefix . '.cancelled', $this->id), | ||||
|                         'permission' => 'update-' . $group . '-' . $permission_prefix, | ||||
|   | ||||
| @@ -21,6 +21,7 @@ class Event extends Provider | ||||
|             'App\Listeners\Update\V30\Version305', | ||||
|             'App\Listeners\Update\V30\Version307', | ||||
|             'App\Listeners\Update\V30\Version309', | ||||
|             'App\Listeners\Update\V30\Version3013', | ||||
|         ], | ||||
|         'Illuminate\Auth\Events\Login' => [ | ||||
|             'App\Listeners\Auth\Login', | ||||
|   | ||||
| @@ -7,7 +7,7 @@ use Illuminate\Support\Str; | ||||
|  | ||||
| trait Categories | ||||
| { | ||||
|     public function getCategoryTypes(): array | ||||
|     public function getCategoryTypes(bool $translate = true): array | ||||
|     { | ||||
|         $types = []; | ||||
|         $configs = config('type.category'); | ||||
| @@ -21,7 +21,7 @@ trait Categories | ||||
|                 $name = $attr['alias'] . '::' . $name; | ||||
|             } | ||||
|  | ||||
|             $types[$type] = trans_choice($name, 1); | ||||
|             $types[$type] = $translate ? trans_choice($name, 1) : $name; | ||||
|         } | ||||
|  | ||||
|         return $types; | ||||
|   | ||||
| @@ -172,6 +172,7 @@ trait Import | ||||
|  | ||||
|         $data = [ | ||||
|             'company_id'        => company_id(), | ||||
|             'type'              => !empty($row['account_type']) ? $row['account_type'] : 'bank', | ||||
|             'currency_code'     => $row['currency_code'], | ||||
|             'name'              => !empty($row['account_name']) ? $row['account_name'] : $row['currency_code'], | ||||
|             'number'            => !empty($row['account_number']) ? $row['account_number'] : (string) rand(1, 10000), | ||||
| @@ -198,6 +199,7 @@ trait Import | ||||
|  | ||||
|         $data = [ | ||||
|             'company_id'        => company_id(), | ||||
|             'type'              => !empty($row['account_type']) ? $row['account_type'] : 'bank', | ||||
|             'name'              => $row['account_name'], | ||||
|             'number'            => !empty($row['account_number']) ? $row['account_number'] : (string) rand(1, 10000), | ||||
|             'currency_code'     => !empty($row['currency_code']) ? $row['currency_code'] : default_currency(), | ||||
| @@ -224,6 +226,7 @@ trait Import | ||||
|  | ||||
|         $data = [ | ||||
|             'company_id'        => company_id(), | ||||
|             'type'              => !empty($row['account_type']) ? $row['account_type'] : 'bank', | ||||
|             'number'            => $row['account_number'], | ||||
|             'name'              => !empty($row['account_name']) ? $row['account_name'] : $row['account_number'], | ||||
|             'currency_code'     => !empty($row['currency_code']) ? $row['currency_code'] : default_currency(), | ||||
|   | ||||
| @@ -2,8 +2,11 @@ | ||||
|  | ||||
| namespace App\Utilities; | ||||
|  | ||||
| use App\Abstracts\Import as AbstractsImport; | ||||
| use App\Abstracts\ImportMultipleSheets; | ||||
| use App\Jobs\Auth\NotifyUser; | ||||
| use App\Notifications\Common\ImportCompleted; | ||||
| use Illuminate\Http\Request; | ||||
| use Maatwebsite\Excel\Validators\ValidationException; | ||||
| use Throwable; | ||||
|  | ||||
| @@ -12,69 +15,83 @@ class Import | ||||
|     /** | ||||
|      * Import the excel file or catch errors | ||||
|      * | ||||
|      * @param $class | ||||
|      * @param $request | ||||
|      * @param $translation | ||||
|      * @param AbstractsImport|ImportMultipleSheets $class | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public static function fromExcel($class, $request, $translation) | ||||
|     public static function fromExcel($class, Request $request, string $translation): array | ||||
|     { | ||||
|         $success = true; | ||||
|  | ||||
|         try { | ||||
|             $should_queue = should_queue(); | ||||
|  | ||||
|             $file = $request->file('import'); | ||||
|  | ||||
|             if (should_queue()) { | ||||
|                 $rows = $class->toArray($file); | ||||
|  | ||||
|                 $total_rows = 0; | ||||
|                 if (!empty($rows[0])) { | ||||
|                     $total_rows = count($rows[0]); | ||||
|                 } else if (!empty($sheets = $class->sheets())) { | ||||
|                     $total_rows = count($rows[array_keys($sheets)[0]]); | ||||
|                 } | ||||
|  | ||||
|                 $class->queue($file)->onQueue('imports')->chain([ | ||||
|                     new NotifyUser(user(), new ImportCompleted($translation, $total_rows)), | ||||
|                 ]); | ||||
|  | ||||
|                 $message = trans('messages.success.import_queued', ['type' => $translation]); | ||||
|             if ($should_queue) { | ||||
|                 self::importQueue($class, $file, $translation); | ||||
|             } else { | ||||
|                 $class->import($file); | ||||
|  | ||||
|                 $message = trans('messages.success.imported', ['type' => $translation]); | ||||
|             } | ||||
|  | ||||
|             $response = [ | ||||
|                 'success'   => true, | ||||
|                 'error'     => false, | ||||
|                 'data'      => null, | ||||
|                 'message'   => $message, | ||||
|             ]; | ||||
|             $message = trans( | ||||
|                 'messages.success.' . ($should_queue ? 'import_queued' : 'imported'), | ||||
|                 ['type' => $translation] | ||||
|             ); | ||||
|         } catch (Throwable $e) { | ||||
|             if ($e instanceof ValidationException) { | ||||
|                 foreach ($e->failures() as $failure) { | ||||
|                     $message = trans('messages.error.import_column', [ | ||||
|                         'message'   => collect($failure->errors())->first(), | ||||
|                         'column'    => $failure->attribute(), | ||||
|                         'line'      => $failure->row(), | ||||
|                     ]); | ||||
|             report($e); | ||||
|  | ||||
|                     flash($message)->error()->important(); | ||||
|                 } | ||||
|             $message = self::flashFailures($e); | ||||
|  | ||||
|                 $message = ''; | ||||
|             } else { | ||||
|                 $message = $e->getMessage(); | ||||
|             } | ||||
|  | ||||
|             $response = [ | ||||
|                 'success'   => false, | ||||
|                 'error'     => true, | ||||
|                 'data'      => null, | ||||
|                 'message'   => $message, | ||||
|             ]; | ||||
|             $success = false; | ||||
|         } | ||||
|  | ||||
|         return $response; | ||||
|         return [ | ||||
|             'success'   => $success, | ||||
|             'error'     => ! $success, | ||||
|             'data'      => null, | ||||
|             'message'   => $message, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Import the excel file | ||||
|      * | ||||
|      * @param AbstractsImport|ImportMultipleSheets $class | ||||
|      */ | ||||
|     protected static function importQueue($class, $file, string $translation): void | ||||
|     { | ||||
|         $rows = $class->toArray($file); | ||||
|  | ||||
|         $total_rows = 0; | ||||
|  | ||||
|         if (! empty($rows[0])) { | ||||
|             $total_rows = count($rows[0]); | ||||
|         } else if (! empty($sheets = $class->sheets())) { | ||||
|             $total_rows = count($rows[array_keys($sheets)[0]]); | ||||
|         } | ||||
|  | ||||
|         $class->queue($file)->onQueue('imports')->chain([ | ||||
|             new NotifyUser(user(), new ImportCompleted($translation, $total_rows)) | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     protected static function flashFailures(Throwable $e): string | ||||
|     { | ||||
|         if (! $e instanceof ValidationException) { | ||||
|             return $e->getMessage(); | ||||
|         } | ||||
|  | ||||
|         foreach ($e->failures() as $failure) { | ||||
|             $message = trans('messages.error.import_column', [ | ||||
|                 'message'   => collect($failure->errors())->first(), | ||||
|                 'column'    => $failure->attribute(), | ||||
|                 'line'      => $failure->row(), | ||||
|             ]); | ||||
|  | ||||
|             flash($message)->error()->important(); | ||||
|         } | ||||
|  | ||||
|         return ''; | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user