diff --git a/database/migrations/2024_07_28_082248_create_bazar_discount_rates_table.php b/database/migrations/2024_07_28_082248_create_bazar_discount_rates_table.php index 8f8b0c59..1ddc1dda 100644 --- a/database/migrations/2024_07_28_082248_create_bazar_discount_rates_table.php +++ b/database/migrations/2024_07_28_082248_create_bazar_discount_rates_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('bazar_discount_rates', function (Blueprint $table) { + Schema::create('bazar_discount_rates', static function (Blueprint $table): void { $table->id(); $table->string('name'); $table->string('type'); diff --git a/database/migrations/2024_07_28_082257_create_bazar_discounts_table.php b/database/migrations/2024_07_28_082257_create_bazar_discounts_table.php index 663324b2..70a656db 100644 --- a/database/migrations/2024_07_28_082257_create_bazar_discounts_table.php +++ b/database/migrations/2024_07_28_082257_create_bazar_discounts_table.php @@ -11,9 +11,9 @@ */ public function up(): void { - Schema::create('bazar_discounts', function (Blueprint $table) { + Schema::create('bazar_discounts', static function (Blueprint $table): void { $table->id(); - $table->foreignId('discount_rate_id')->constrained('bazar_discount_rates')->nullOnDelete(); + $table->foreignId('discount_rate_id')->nullable()->constrained('bazar_discount_rates')->nullOnDelete(); $table->morphs('discountable'); $table->float('value')->unsigned(); $table->timestamps(); diff --git a/database/migrations/2024_07_28_082300_create_bazar_buyable_tax_rate_table.php b/database/migrations/2024_07_28_082300_create_bazar_buyable_tax_rate_table.php new file mode 100644 index 00000000..4f776f00 --- /dev/null +++ b/database/migrations/2024_07_28_082300_create_bazar_buyable_tax_rate_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('tax_rate_id')->constrained('bazar_tax_rates')->cascadeOnDelete(); + $table->morphs('buyable'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('bazar_buyable_tax_rate'); + } +}; diff --git a/database/migrations/2024_07_28_082302_create_bazar_taxes_table.php b/database/migrations/2024_07_28_082302_create_bazar_taxes_table.php index a640ae48..774fe323 100644 --- a/database/migrations/2024_07_28_082302_create_bazar_taxes_table.php +++ b/database/migrations/2024_07_28_082302_create_bazar_taxes_table.php @@ -11,10 +11,10 @@ */ public function up(): void { - Schema::create('bazar_taxes', function (Blueprint $table) { + Schema::create('bazar_taxes', static function (Blueprint $table): void { $table->id(); - $table->foreignId('tax_rate_id')->constrained('bazar_tax_rates')->nullOnDelete(); - $table->foreignId('item_id')->constrained('bazar_items')->nullOnDelete(); + $table->foreignId('tax_rate_id')->nullable()->constrained('bazar_tax_rates')->nullOnDelete(); + $table->foreignId('item_id')->nullable()->constrained('bazar_items')->nullOnDelete(); $table->float('value')->unsigned(); $table->timestamps(); }); diff --git a/src/Interfaces/Models/DiscountRate.php b/src/Interfaces/Models/DiscountRate.php index f77ba074..d9d0501e 100644 --- a/src/Interfaces/Models/DiscountRate.php +++ b/src/Interfaces/Models/DiscountRate.php @@ -12,6 +12,11 @@ interface DiscountRate */ public function applicable(Discountable $model): bool; + /** + * Calculate the discount for the given model. + */ + public function calculate(Discountable $model): float; + /** * Apply the discount rate on the model. */ diff --git a/src/Interfaces/Models/Product.php b/src/Interfaces/Models/Product.php index 1014220b..249ba844 100644 --- a/src/Interfaces/Models/Product.php +++ b/src/Interfaces/Models/Product.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\Relations\MorphMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; interface Product extends Buyable, Stockable { @@ -37,6 +38,11 @@ public function categories(): BelongsToMany; */ public function variants(): HasMany; + /** + * Get the tax rates for the product. + */ + public function taxRates(): MorphToMany; + /** * Get the variant of the given option. */ diff --git a/src/Interfaces/Models/TaxRate.php b/src/Interfaces/Models/TaxRate.php index 2772f043..a2423d7c 100644 --- a/src/Interfaces/Models/TaxRate.php +++ b/src/Interfaces/Models/TaxRate.php @@ -2,7 +2,23 @@ namespace Cone\Bazar\Interfaces\Models; +use Cone\Bazar\Interfaces\Taxable; +use Cone\Bazar\Models\Tax; + interface TaxRate { - // + /** + * Determine wheter the discount rate is applicable on the model. + */ + public function applicable(Taxable $model): bool; + + /** + * Calculate the discount for the given model. + */ + public function calculate(Taxable $model): float; + + /** + * Apply the discount rate on the model. + */ + public function apply(Taxable $model): ?Tax; } diff --git a/src/Models/Product.php b/src/Models/Product.php index 7bb1d5ed..74fce3f6 100644 --- a/src/Models/Product.php +++ b/src/Models/Product.php @@ -18,6 +18,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Query\Builder as QueryBuilder; @@ -91,6 +92,14 @@ public function variants(): HasMany return $this->hasMany(Variant::getProxiedClass()); } + /** + * Get the tax rates for the product. + */ + public function taxRates(): MorphToMany + { + return $this->morphToMany(TaxRate::getProxiedClass(), 'buyable', 'bazar_buyable_tax_rate'); + } + /** * Determine whether the buyable object is available for the checkoutable instance. */ diff --git a/src/Models/TaxRate.php b/src/Models/TaxRate.php index 5faeccb1..d0262642 100644 --- a/src/Models/TaxRate.php +++ b/src/Models/TaxRate.php @@ -4,6 +4,7 @@ use Cone\Bazar\Database\Factories\TaxRateFactory; use Cone\Bazar\Interfaces\Models\TaxRate as Contract; +use Cone\Bazar\Interfaces\Taxable; use Cone\Root\Traits\InteractsWithProxy; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -43,4 +44,35 @@ protected static function newFactory(): Factory { return TaxRateFactory::new(); } + + /** + * Determine wheter the discount rate is applicable on the model. + */ + public function applicable(Taxable $model): bool + { + return true; + } + + /** + * Calculate the discount for the given model. + */ + public function calculate(Taxable $model): float + { + return 0; + } + + /** + * Apply the discount rate on the model. + */ + public function apply(Taxable $model): ?Tax + { + if (! $this->applicable($model)) { + return null; + } + + return $model->taxes()->updateOrCreate( + ['discount_rate_id' => $this->getKey()], + ['value' => $this->calculate($model)] + ); + } }