diff --git a/app/Exports/Banking/Transactions.php b/app/Exports/Banking/Transactions.php index aee773b3b..b4a3ad611 100644 --- a/app/Exports/Banking/Transactions.php +++ b/app/Exports/Banking/Transactions.php @@ -20,6 +20,7 @@ class Transactions extends Export implements WithColumnFormatting $model->contact_email = $model->contact->email; $model->category_name = $model->category->name; $model->invoice_bill_number = $model->document->document_number ?? 0; + $model->parent_number = Model::isRecurring()->find($model->parent_id)?->number; return parent::map($model); } @@ -41,6 +42,7 @@ class Transactions extends Export implements WithColumnFormatting 'payment_method', 'reference', 'reconciled', + 'parent_number', ]; } diff --git a/app/Exports/Purchases/Sheets/Bills.php b/app/Exports/Purchases/Sheets/Bills.php index 6f3bf5e0e..c266ea374 100644 --- a/app/Exports/Purchases/Sheets/Bills.php +++ b/app/Exports/Purchases/Sheets/Bills.php @@ -26,6 +26,7 @@ class Bills extends Export implements WithColumnFormatting $model->bill_number = $model->document_number; $model->billed_at = $model->issued_at; $model->contact_country = $country; + $model->parent_number = Model::billRecurring()->find($model->parent_id)?->document_number ?? null; return parent::map($model); } @@ -52,6 +53,7 @@ class Bills extends Export implements WithColumnFormatting 'contact_zip_code', 'contact_city', 'notes', + 'parent_number', ]; } diff --git a/app/Exports/Sales/Sheets/Invoices.php b/app/Exports/Sales/Sheets/Invoices.php index 39a7d3410..857874536 100644 --- a/app/Exports/Sales/Sheets/Invoices.php +++ b/app/Exports/Sales/Sheets/Invoices.php @@ -26,6 +26,7 @@ class Invoices extends Export implements WithColumnFormatting $model->invoice_number = $model->document_number; $model->invoiced_at = $model->issued_at; $model->contact_country = $country; + $model->parent_number = Model::invoiceRecurring()->find($model->parent_id)?->document_number; return parent::map($model); } @@ -53,6 +54,7 @@ class Invoices extends Export implements WithColumnFormatting 'contact_city', 'notes', 'footer', + 'parent_number', ]; } diff --git a/app/Imports/Banking/Transactions.php b/app/Imports/Banking/Transactions.php index eae60c77c..a7a41680d 100644 --- a/app/Imports/Banking/Transactions.php +++ b/app/Imports/Banking/Transactions.php @@ -24,6 +24,7 @@ class Transactions extends Import $row['category_id'] = $this->getCategoryId($row); $row['contact_id'] = $this->getContactId($row); $row['document_id'] = $this->getDocumentId($row); + $row['parent_id'] = $this->getParentId($row); return $row; } diff --git a/app/Imports/Purchases/Sheets/Bills.php b/app/Imports/Purchases/Sheets/Bills.php index 8a6c7206b..508284784 100644 --- a/app/Imports/Purchases/Sheets/Bills.php +++ b/app/Imports/Purchases/Sheets/Bills.php @@ -35,6 +35,7 @@ class Bills extends Import $row['currency_code'] = $this->getCurrencyCode($row); $row['type'] = Model::BILL_TYPE; $row['contact_country'] = !empty($country) ? $country : null; + $row['parent_id'] = $this->getParentId($row); return $row; } diff --git a/app/Imports/Sales/Sheets/Invoices.php b/app/Imports/Sales/Sheets/Invoices.php index aeb831de8..1ebf7dbe5 100644 --- a/app/Imports/Sales/Sheets/Invoices.php +++ b/app/Imports/Sales/Sheets/Invoices.php @@ -35,6 +35,7 @@ class Invoices extends Import $row['currency_code'] = $this->getCurrencyCode($row); $row['type'] = Model::INVOICE_TYPE; $row['contact_country'] = !empty($country) ? $country : null; + $row['parent_id'] = $this->getParentId($row); return $row; } diff --git a/app/Models/Banking/Transaction.php b/app/Models/Banking/Transaction.php index b13f16881..c17fb7334 100644 --- a/app/Models/Banking/Transaction.php +++ b/app/Models/Banking/Transaction.php @@ -165,6 +165,11 @@ class Transaction extends Model return $this->belongsTo('App\Models\Auth\User', 'contact_id', 'id'); } + public function scopeNumber(Builder $query, string $number): Builder + { + return $query->where('number', '=', $number); + } + public function scopeType(Builder $query, $types): Builder { if (empty($types)) { diff --git a/app/Models/Common/Recurring.php b/app/Models/Common/Recurring.php index 98cbe9441..41b851edd 100644 --- a/app/Models/Common/Recurring.php +++ b/app/Models/Common/Recurring.php @@ -13,6 +13,10 @@ class Recurring extends Model public const ACTIVE_STATUS = 'active'; public const END_STATUS = 'ended'; public const COMPLETE_STATUS = 'completed'; + public const INVOICE_RECURRING_TYPE = 'invoice-recurring'; + public const BILL_RECURRING_TYPE = 'bill-recurring'; + public const INCOME_RECURRING_TYPE = 'income-recurring'; + public const EXPENSE_RECURRING_TYPE = 'expense-recurring'; protected $table = 'recurring'; @@ -55,6 +59,21 @@ class Recurring extends Model return $this->morphTo()->isRecurring(); } + public function documents() + { + return $this->morphedByMany('App\Models\Document\Document', 'recurable'); + } + + public function invoices() + { + return $this->documents()->where('type', self::INVOICE_RECURRING_TYPE); + } + + public function bills() + { + return $this->documents()->where('type', self::BILL_RECURRING_TYPE); + } + public function scopeActive(Builder $query): Builder { return $query->where($this->qualifyColumn('status'), '=', static::ACTIVE_STATUS); @@ -69,4 +88,49 @@ class Recurring extends Model { return $query->where($this->qualifyColumn('status'), '=', static::COMPLETE_STATUS); } + + public function scopeDocument(Builder $query, $type): Builder + { + return $query->where($this->qualifyColumn('recurable_type'), '=', 'App\\Models\\Document\\Document') + ->whereHas('recurable', function (Builder $query) use ($type) { + $query->where('type', $type); + }); + } + + public function scopeInvoice(Builder $query): Builder + { + return $query->where($this->qualifyColumn('recurable_type'), '=', 'App\\Models\\Document\\Document') + ->whereHas('recurable', function (Builder $query) { + $query->where('type', self::INVOICE_RECURRING_TYPE); + }); + } + + public function scopeBill(Builder $query): Builder + { + return $query->where($this->qualifyColumn('recurable_type'), '=', 'App\\Models\\Document\\Document') + ->whereHas('recurable', function (Builder $query) { + $query->where('type', self::BILL_RECURRING_TYPE); + }); + } + + public function scopeTransaction(Builder $query): Builder + { + return $query->where($this->qualifyColumn('recurable_type'), '=', 'App\\Models\\Banking\\Transaction'); + } + + public function scopeExpenseTransaction(Builder $query): Builder + { + return $query->where($this->qualifyColumn('recurable_type'), '=', 'App\\Models\\Banking\\Transaction') + ->whereHas('recurable', function (Builder $query) { + $query->where('type', self::EXPENSE_RECURRING_TYPE); + }); + } + + public function scopeIncomeTransaction(Builder $query): Builder + { + return $query->where($this->qualifyColumn('recurable_type'), '=', 'App\\Models\\Banking\\Transaction') + ->whereHas('recurable', function (Builder $query) { + $query->where('type', self::INCOME_RECURRING_TYPE); + }); + } } diff --git a/app/Models/Document/DocumentHistory.php b/app/Models/Document/DocumentHistory.php index ea9ac38c1..e00292e2b 100644 --- a/app/Models/Document/DocumentHistory.php +++ b/app/Models/Document/DocumentHistory.php @@ -30,8 +30,24 @@ class DocumentHistory extends Model return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_TYPE); } + public function scopeInvoiceRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } + public function scopeBill(Builder $query) { return $query->where($this->qualifyColumn('type'), '=', Document::BILL_TYPE); } + + public function scopeBillRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::BILL_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } } diff --git a/app/Models/Document/DocumentItem.php b/app/Models/Document/DocumentItem.php index ffaa3c7da..547247664 100644 --- a/app/Models/Document/DocumentItem.php +++ b/app/Models/Document/DocumentItem.php @@ -100,11 +100,27 @@ class DocumentItem extends Model return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_TYPE); } + public function scopeInvoiceRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } + public function scopeBill(Builder $query) { return $query->where($this->qualifyColumn('type'), '=', Document::BILL_TYPE); } + public function scopeBillRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::BILL_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } + public function getDiscountAttribute(): string { if (setting('localisation.percent_position', 'after') === 'after') { diff --git a/app/Models/Document/DocumentItemTax.php b/app/Models/Document/DocumentItemTax.php index 0594b087c..5e7b40e31 100644 --- a/app/Models/Document/DocumentItemTax.php +++ b/app/Models/Document/DocumentItemTax.php @@ -41,11 +41,27 @@ class DocumentItemTax extends Model return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_TYPE); } + public function scopeInvoiceRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } + public function scopeBill(Builder $query) { return $query->where($this->qualifyColumn('type'), '=', Document::BILL_TYPE); } + public function scopeBillRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::BILL_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } + public function onCloned($src) { $document_item = DocumentItem::find($this->document_item_id); diff --git a/app/Models/Document/DocumentTotal.php b/app/Models/Document/DocumentTotal.php index ea0f3e89d..ae3a8590b 100644 --- a/app/Models/Document/DocumentTotal.php +++ b/app/Models/Document/DocumentTotal.php @@ -33,11 +33,27 @@ class DocumentTotal extends Model return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_TYPE); } + public function scopeInvoiceRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::INVOICE_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } + public function scopeBill(Builder $query) { return $query->where($this->qualifyColumn('type'), '=', Document::BILL_TYPE); } + public function scopeBillRecurring(Builder $query): Builder + { + return $query->where($this->qualifyColumn('type'), '=', Document::BILL_RECURRING_TYPE) + ->whereHas('document.recurring', function (Builder $query) { + $query->whereNull('deleted_at'); + }); + } + public function scopeCode($query, $code) { return $query->where('code', '=', $code); diff --git a/app/Traits/Import.php b/app/Traits/Import.php index 64a6dc57c..abb8f17dc 100644 --- a/app/Traits/Import.php +++ b/app/Traits/Import.php @@ -16,6 +16,7 @@ use App\Jobs\Setting\CreateCurrency; use App\Jobs\Setting\CreateTax; use App\Models\Auth\User; use App\Models\Banking\Account; +use App\Models\Banking\Transaction; use App\Models\Common\Contact; use App\Models\Common\Item; use App\Models\Document\Document; @@ -149,6 +150,21 @@ trait Import return is_null($id) ? $id : (int) $id; } + public function getParentId($row) + { + $id = isset($row['parent_id']) ? $row['parent_id'] : null; + + if (empty($id) && isset($row['document_number']) && !empty($row['parent_number'])) { + $id = Document::number($row['parent_number'])->pluck('id')->first(); + } + + if (empty($id) && isset($row['number']) && !empty($row['parent_number'])) { + $id = Transaction::number($row['parent_number'])->pluck('id')->first(); + } + + return is_null($id) ? $id : (int) $id; + } + public function getItemId($row, $type = null) { $id = isset($row['item_id']) ? $row['item_id'] : null;