Skip to content

Commit 0f0d6e7

Browse files
authored
Merge branch 'discount-rules' into copilot/sub-pr-236
2 parents 9c01aa1 + 3b69d90 commit 0f0d6e7

32 files changed

+834
-201
lines changed

.github/workflows/back-end.yml

Lines changed: 180 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,184 @@
1-
name: Back-end
1+
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow
2+
3+
name: "Back-end"
24

35
on:
4-
push:
5-
branches:
6-
- master
7-
pull_request: null
6+
pull_request: null
7+
push:
8+
branches:
9+
- "master"
10+
# Add [skip ci] to commit message to skip CI.
11+
12+
permissions:
13+
contents: "read"
14+
15+
concurrency:
16+
group: "${{ github.workflow }}-${{ github.ref }}"
17+
cancel-in-progress: true
818

919
jobs:
10-
unit_tests:
11-
12-
strategy:
13-
fail-fast: true
14-
matrix:
15-
os: ["ubuntu-24.04"]
16-
php: ["8.3", "8.4"]
17-
laravel: ["^12.0"]
18-
dependency-version: ["highest"]
19-
20-
name: "Unit - PHP ${{ matrix.php }} - L ${{ matrix.laravel }} - ${{ matrix.dependency-version }}"
21-
22-
runs-on: "${{ matrix.os }}"
23-
24-
steps:
25-
- name: Checkout repository
26-
uses: actions/checkout@v4
27-
28-
- name: Setup PHP
29-
uses: shivammathur/setup-php@v2
30-
with:
31-
php-version: ${{ matrix.php }}
32-
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, fileinfo, exif
33-
tools: composer:v2
34-
coverage: xdebug3
35-
36-
- name: Check Composer configuration
37-
run: composer validate --no-interaction # @dev --strict
38-
39-
- name: Install dependencies
40-
if: ${{ matrix.dependency-version == 'highest' }}
41-
run: composer update --no-interaction --no-progress --prefer-dist --with="laravel/framework:${{ matrix.laravel }}"
42-
43-
- name: Install locked dependencies
44-
if: ${{ matrix.dependency-version == 'locked' }}
45-
run: composer install --prefer-dist --no-interaction --no-progress
46-
47-
- name: Check for PSR-4 mapping errors
48-
run: composer dump-autoload --optimize --strict-psr
49-
50-
- name: Execute tests
51-
run: composer exec -- phpunit
52-
53-
- name: Send coverage to Coveralls
54-
if: ${{ matrix.os == 'ubuntu-24.04' && matrix.php == '8.3' && matrix.laravel == '^12.0' }}
55-
env:
56-
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57-
run: |
58-
wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.7.0/php-coveralls.phar"
59-
php ./php-coveralls.phar -v
20+
syntax_errors:
21+
name: "1️⃣ Syntax errors"
22+
runs-on: "ubuntu-24.04"
23+
timeout-minutes: 5
24+
steps:
25+
-
26+
name: "Set up PHP"
27+
uses: "shivammathur/setup-php@v2"
28+
with:
29+
php-version: "8.4"
30+
extensions: "dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, fileinfo, exif"
31+
coverage: "none"
32+
tools: "parallel-lint"
33+
-
34+
name: "Checkout repository"
35+
uses: "actions/checkout@v4"
36+
-
37+
name: "Search for invalid complex curly syntax 🐌"
38+
run: |
39+
! git grep -e '\${[A-Z_a-z]' -- '*.php' '*.scss'
40+
-
41+
name: "Check source code for syntax errors"
42+
run: "composer exec --no-interaction -- parallel-lint src/ tests/"
43+
44+
unit_tests:
45+
name: "2️⃣ Unit and functional tests"
46+
needs:
47+
- "syntax_errors"
48+
strategy:
49+
fail-fast: false
50+
matrix:
51+
php-version:
52+
- "8.4"
53+
- "8.5"
54+
dependencies:
55+
- "lowest"
56+
- "locked"
57+
- "highest"
58+
include:
59+
-
60+
php-version: "8.4"
61+
dependencies: "locked"
62+
coverage: true
63+
runs-on: "ubuntu-24.04"
64+
timeout-minutes: 5
65+
steps:
66+
-
67+
name: "Set up PHP"
68+
uses: "shivammathur/setup-php@v2"
69+
with:
70+
php-version: "${{ matrix.php-version }}"
71+
extensions: "dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, fileinfo, exif"
72+
-
73+
name: "Setup problem matcher for PHPUnit"
74+
run: |
75+
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
76+
-
77+
name: "Checkout repository"
78+
uses: "actions/checkout@v4"
79+
-
80+
name: "Install dependencies"
81+
uses: "ramsey/composer-install@v3"
82+
with:
83+
dependency-versions: "${{ matrix.dependencies }}"
84+
-
85+
name: "Execute unit tests"
86+
run: "composer exec -- phpunit"
87+
-
88+
name: "Tests have failed: upload logs"
89+
if: "${{ failure() }}"
90+
uses: "actions/upload-artifact@v4"
91+
with:
92+
path: "storage/logs/"
93+
name: "laravel-logs-${{ matrix.php-version }}-${{ matrix.dependencies }}"
94+
-
95+
name: "Send coverage to Coveralls"
96+
env:
97+
COVERALLS_REPO_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
98+
if: "${{ env.COVERALLS_REPO_TOKEN && matrix.coverage }}"
99+
uses: "coverallsapp/github-action@v2"
100+
with:
101+
github-token: "${{ env.COVERALLS_REPO_TOKEN }}"
102+
flag-name: "Unit"
103+
allow-empty: false
104+
105+
static_analysis:
106+
name: "3️⃣ Static Analysis"
107+
needs:
108+
- "syntax_errors"
109+
runs-on: "ubuntu-24.04"
110+
timeout-minutes: 5
111+
steps:
112+
-
113+
name: "Set up PHP"
114+
uses: "shivammathur/setup-php@v2"
115+
with:
116+
php-version: "8.4"
117+
extensions: "dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, fileinfo, exif"
118+
coverage: "none"
119+
-
120+
name: "Checkout repository"
121+
uses: "actions/checkout@v4"
122+
-
123+
name: "Check JSON files"
124+
run: |
125+
git ls-files --cached -z -- '*.json' \
126+
| xargs -t --null -L 1 -- \
127+
php -r 'json_decode(file_get_contents($argv[1]), null, 512, JSON_THROW_ON_ERROR);'
128+
-
129+
name: "Validate Composer configuration"
130+
run: "composer validate --no-interaction --strict"
131+
-
132+
name: "Install dependencies"
133+
uses: "ramsey/composer-install@v3"
134+
with:
135+
dependency-versions: "locked"
136+
-
137+
name: "Check PSR-4 mapping 🐌"
138+
run: "composer dump-autoload --dev --optimize --strict-psr"
139+
-
140+
# https://github.com/phpstan/phpstan/issues/9475
141+
name: "Search for $this->$this typo 🐌"
142+
run: |
143+
! git grep --line-number -e '\$this\s*->\s*\$this' -- ':!:*/back-end\.yml'
144+
-
145+
name: "Install orchestra/testbench"
146+
run: "composer require --dev --update-with-all-dependencies orchestra/testbench"
147+
-
148+
name: "Perform static analysis"
149+
run: "composer exec -- phpstan || true 'Annotate only'"
150+
151+
coding_standards:
152+
name: "4️⃣ Coding Standards"
153+
needs:
154+
- "syntax_errors"
155+
runs-on: "ubuntu-24.04"
156+
timeout-minutes: 5
157+
steps:
158+
-
159+
name: "Set up PHP"
160+
uses: "shivammathur/setup-php@v2"
161+
with:
162+
php-version: "8.4"
163+
extensions: "dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, fileinfo, exif"
164+
coverage: "none"
165+
tools: "phpcs,cs2pr"
166+
-
167+
name: "Checkout repository"
168+
uses: "actions/checkout@v4"
169+
-
170+
name: "Install dependencies"
171+
uses: "ramsey/composer-install@v3"
172+
with:
173+
dependency-versions: "locked"
174+
#-
175+
# name: "Detect coding standards violations"
176+
# run: "composer exec -- phpcs -q --report=checkstyle --standard=PSR12 src/ | cs2pr"
177+
-
178+
name: "Detect coding standards violations"
179+
id: "pint"
180+
run: "composer exec -- pint --verbose --test"
181+
-
182+
name: "Annotate Pint results"
183+
if: "${{ failure() && steps.pint.outcome == 'failure' }}"
184+
run: "composer exec -- pint --test --format=checkstyle | cs2pr"

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
}
2323
},
2424
"require": {
25-
"php": "^8.3.0 || ^8.4.0",
26-
"conedevelopment/root": "^2.8.0"
25+
"php": "^8.4.0 || ^8.5.0",
26+
"conedevelopment/root": "^2.8.1"
2727
},
2828
"require-dev": {
2929
"fakerphp/faker": "^1.9.1",

database/factories/CouponFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Cone\Bazar\Database\Factories;
66

7-
use Cone\Bazar\Enums\CouponType;
7+
use Cone\Bazar\Enums\DiscountType;
88
use Cone\Bazar\Models\Coupon;
99
use Illuminate\Database\Eloquent\Factories\Factory;
1010
use Illuminate\Support\Str;
@@ -38,7 +38,7 @@ public function definition(): array
3838
'expires_at' => null,
3939
'rules' => [],
4040
'stackable' => false,
41-
'type' => CouponType::FIX,
41+
'type' => DiscountType::FIX,
4242
'value' => mt_rand(5, 50),
4343
'code' => Str::upper(Str::random(8)),
4444
];

database/migrations/2025_12_14_211655_create_bazar_coupons_table.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
use Cone\Bazar\Enums\CouponType;
5+
use Cone\Bazar\Enums\DiscountType;
66
use Illuminate\Database\Migrations\Migration;
77
use Illuminate\Database\Schema\Blueprint;
88
use Illuminate\Support\Facades\Schema;
@@ -18,7 +18,7 @@ public function up(): void
1818
$table->id();
1919
$table->string('code')->unique();
2020
$table->float('value', 10, 2)->unsigned();
21-
$table->enum('type', CouponType::cases())->default(CouponType::FIX->value);
21+
$table->string('type')->default(DiscountType::FIX->value);
2222
$table->json('rules')->nullable();
2323
$table->boolean('active')->default(true);
2424
$table->boolean('stackable')->default(false);

database/migrations/2025_12_31_224555_create_bazar_discount_rules_table.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
declare(strict_types=1);
44

5-
use Cone\Bazar\Enums\DiscountRuleType;
5+
use Cone\Bazar\Enums\DiscountRuleValueType;
6+
use Cone\Bazar\Models\Cart;
67
use Illuminate\Database\Migrations\Migration;
78
use Illuminate\Database\Schema\Blueprint;
89
use Illuminate\Support\Facades\Schema;
@@ -18,7 +19,8 @@ public function up(): void
1819
$table->id();
1920
$table->string('name');
2021
$table->boolean('active')->default(true);
21-
$table->string('type')->default(DiscountRuleType::CART->value);
22+
$table->string('discountable_type')->default(Cart::getProxiedClass());
23+
$table->string('value_type')->default(DiscountRuleValueType::TOTAL->value);
2224
$table->boolean('stackable')->default(false);
2325
$table->json('rules')->nullable();
2426
$table->timestamps();

database/migrations/2026_01_01_131520_create_bazar_discounts_table.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function up(): void
1616
Schema::create('bazar_discounts', static function (Blueprint $table): void {
1717
$table->id();
1818
$table->foreignId('discount_rule_id')->constrained('bazar_discount_rules')->cascadeOnDelete();
19-
$table->morphs('discountable');
19+
$table->uuidMorphs('discountable');
2020
$table->decimal('value', 10, 2);
2121
$table->timestamps();
2222
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Illuminate\Database\Migrations\Migration;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Support\Facades\Schema;
8+
9+
return new class extends Migration
10+
{
11+
/**
12+
* Run the migrations.
13+
*/
14+
public function up(): void
15+
{
16+
Schema::create('bazar_discountables', static function (Blueprint $table): void {
17+
$table->id();
18+
$table->foreignId('discount_rule_id')->constrained('bazar_discount_rules')->cascadeOnDelete();
19+
$table->uuidMorphs('discountable');
20+
$table->timestamps();
21+
});
22+
}
23+
24+
/**
25+
* Reverse the migrations.
26+
*/
27+
public function down(): void
28+
{
29+
Schema::dropIfExists('bazar_discountables');
30+
}
31+
};

src/BazarServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class BazarServiceProvider extends ServiceProvider
2020
Interfaces\Models\Category::class => Models\Category::class,
2121
Interfaces\Models\Coupon::class => Models\Coupon::class,
2222
Interfaces\Models\Discount::class => Models\Discount::class,
23+
Interfaces\Models\Discountable::class => Models\Discountable::class,
2324
Interfaces\Models\DiscountRule::class => Models\DiscountRule::class,
2425
Interfaces\Models\Item::class => Models\Item::class,
2526
Interfaces\Models\Order::class => Models\Order::class,
@@ -103,6 +104,7 @@ protected function registerPublishes(): void
103104
__DIR__.'/../stubs/BazarServiceProvider.stub' => $this->app->basePath('app/Providers/BazarServiceProvider.php'),
104105
__DIR__.'/../stubs/CategoryResource.stub' => $this->app->basePath('app/Root/Resources/CategoryResource.php'),
105106
__DIR__.'/../stubs/CouponResource.stub' => $this->app->basePath('app/Root/Resources/CouponResource.php'),
107+
__DIR__.'/../stubs/DiscountRuleResource.stub' => $this->app->basePath('app/Root/Resources/DiscountRuleResource.php'),
106108
__DIR__.'/../stubs/OrderResource.stub' => $this->app->basePath('app/Root/Resources/OrderResource.php'),
107109
__DIR__.'/../stubs/ProductResource.stub' => $this->app->basePath('app/Root/Resources/ProductResource.php'),
108110
__DIR__.'/../stubs/PropertyResource.stub' => $this->app->basePath('app/Root/Resources/PropertyResource.php'),

src/Cart/Driver.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,18 @@ protected function resolved(Request $request, Cart $cart): void
5252
$cart->user()->associate($request->user())->save();
5353
}
5454

55-
$cart->loadMissing(['items', 'items.buyable', 'coupons']);
55+
$cart->loadMissing([
56+
'coupons',
57+
'discounts',
58+
'items.buyable',
59+
'items.discounts',
60+
'items',
61+
'shipping',
62+
'shipping.discounts',
63+
]);
64+
65+
$cart->items->each->setRelation('checkoutable', $cart);
66+
$cart->shipping->setRelation('shippable', $cart);
5667
}
5768

5869
/**

0 commit comments

Comments
 (0)