snapshot of https://github.com/krayin/laravel-crm.git (2.2, 2026-09-18; blobs > 131072B omitted)
Some checks failed
Admin | Playwright Tests / Admin | Playwright Tests | Shard 1 Of 6 (push) Failing after 37s
Admin | Playwright Tests / Admin | Playwright Tests | Shard 2 Of 6 (push) Failing after 7s
Admin | Playwright Tests / Admin | Playwright Tests | Shard 4 Of 6 (push) Failing after 7s
Admin | Playwright Tests / Admin | Playwright Tests | Shard 6 Of 6 (push) Failing after 6s
Linting Tests / PHP 8.3 test on ubuntu-latest (push) Failing after 5s
CI / PHP 8.3 test on ubuntu-latest (push) Failing after 6s
Skills Consistency / validate-skills (push) Successful in 10s
Admin | Playwright Tests / Admin | Playwright Tests | Shard 3 Of 6 (push) Failing after 7s
Admin | Playwright Tests / Admin | Playwright Tests | Shard 5 Of 6 (push) Failing after 6s

This commit is contained in:
upstream-mirror
2026-09-18 04:37:41 +05:00
commit 135ffdb085
1274 changed files with 144880 additions and 0 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
open_collective: bagisto

36
.github/ISSUE_TEMPLATE/1_Bug_report.md vendored Normal file
View File

@@ -0,0 +1,36 @@
---
name: "🐛 Bug Report"
about: 'Report a general library issue.'
---
# Bug report
### Title
**Just a quick sentence to brief your trouble with Krayin CRM or something associated with it.**
**Please be calm, short and emphasize on points.**
### Issue Description
**Description helps the developers to understand the bug. It describes the problem encountered or some after effect of some kind.**
### Preconditions
**Please provide as detailed information about your environment as possible.**
1. framework Version.
2. Commit id.
### Steps to reproduce
**It is important to provide a set of clear steps to reproduce this bug.If relevant please include code samples.**
1. step1
2. step2
### Expected result
**Tell us what should happen.**
* [Screenshots, logs or description]
### Actual result
> **Tell us what happens instead.**
* [points....]

View File

@@ -0,0 +1,17 @@
---
name: "💡 Feature Request"
about: 'For ideas or feature requests, please make a pull request, or open an issue'
---
This repository is only for reporting bugs or issues. If you need support, please use
other channels:
1. Write an email - mailto:support@krayincrm.com
2. Create support ticket on https://krayincrm.uvdesk.com
3. Visit forums to get support from our community (https://forums.krayincrm.com)
Alternatively, you may use Facebook (https://www.facebook.com/groups/krayincrm/).
We promise that more channels are coming soon!!!

View File

@@ -0,0 +1,11 @@
---
name: "❔ Support Question"
about: 'This repository is only for reporting bugs or problems. If you need help, see:
https://github.com/krayin/laravel-crm#documentation'
---
This repository is only for reporting bugs or issues. If you need support, please use:
1. Create support ticket on https://krayincrm.uvdesk.com
Thanks!

View File

@@ -0,0 +1,9 @@
---
name: "🔒 Security Vulnerabilities"
about: 'For reporting security-related issues, see: https://github.com/krayin/laravel-crm#security-vulnerabilities'
---
PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
If you have security vulnerability to address related to Krayin then please write a mail to us:
**support@krayincrm.com**

19
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,19 @@
## Issue Reference
<!--- Please mention issue #id or use a comma if your pull request solves multiple issues. -->
## Description
<!--- Please describe your changes in detail. -->
## How To Test This?
<!--- Please describe in detail how to test the changes made in this pull request. -->
## Documentation
- [ ] My pull request requires an update on the documentation repository.
<!--- Please describe in detail what needs to be changed. --->
## Branch Selection
<!--- Please specify the target branch for this pull request. -->
- [ ] Target Branch: master
## Tailwind Reordering
<!--- Please make sure all the Tailwind classes are reordered. -->

51
.github/skills/README.md vendored Normal file
View File

@@ -0,0 +1,51 @@
# Skills Standard
## Canonical Source
All workspace skills are maintained in:
- `.github/skills/<skill-name>/SKILL.md`
This is the single source of truth for every AI coding agent in this repository.
## Agent Runtime Links
The following paths are **symlinks** to `.github/skills` so each agent runtime
auto-discovers the same skills:
| Path | Agent |
|------|-------|
| `.ai/skills` | Generic / `.ai` convention |
| `.claude/skills` | Claude Code |
| `.codex/skills` | OpenAI Codex |
| `.cursor/skills` | Cursor |
| `.kilocode/skills` | Kilo Code |
> Symlinks are committed to git (mode `120000`). On a Windows checkout without
> symlink support they may materialize as plain files — clone with symlink
> support enabled (`git config core.symlinks true`).
## Available Skills
| Skill | Use when |
|-------|----------|
| `crm-package-development` | Creating a new Krayin CRM package/module or extending CRM functionality without touching core files. |
| `pest-testing` | Writing or debugging Krayin CRM unit/feature tests with Pest. |
## Authoring Rules
- Add or update skills **only** in `.github/skills` (never edit through a symlink target name as if it were a separate copy).
- Keep `name` and `description` in the YAML frontmatter of every `SKILL.md`.
- `name` must be lowercase, hyphen-separated, and **match the skill's directory name**.
- Use explicit "Use when..." trigger language in descriptions so agents match them reliably.
- Do not maintain duplicate `SKILL.md` files in agent-specific folders.
## Validation
Validate frontmatter and naming with the Agent Skills reference tool:
```bash
skills-ref validate .github/skills/<skill-name>
```
See the [Agent Skills specification](https://agentskills.io/specification) for the full format.

View File

@@ -0,0 +1,222 @@
---
name: crm-package-development
description: Use when creating a new Krayin CRM package or module, extending CRM functionality via a package, or adding custom business logic without modifying core files. Also use for any translation work — adding or moving lang files, adding a locale, or deciding whether a package gets its own Resources/lang directory — and whenever a fix or feature needs a CHANGELOG.md entry. Covers Laravel package structure, service providers, migrations, models, repositories, routes, controllers, views, localization, changelog entries, config, ACL, and menus.
---
# Skill: CRM Package Development (Krayin CRM)
## Purpose
This skill guides the AI agent to design and develop a new CRM package
(module) for Krayin CRM in a clean, upgrade-safe, and maintainable way.
---
## When to Activate
Activate this skill when the user wants to:
- Create a new CRM package/module
- Extend CRM functionality via a package
- Add custom business logic without modifying core files
- Add, move, or delete translation (lang) files, or add a new locale
- Fix a bug or ship a feature — the change needs a `CHANGELOG.md` entry
---
## Project Context
- Framework: Laravel
- Product: Krayin CRM
- Krayin CRM is already installed and running
- The package must integrate seamlessly with existing CRM modules
---
## Development Rules
- Follow Krayin CRM architecture and conventions
- Do NOT modify core Krayin files unless explicitly required
- Use Laravel package-based structure
- All database changes must be done using migrations
- Ensure backward compatibility and safe upgrades
---
## Package Structure Guidelines
A CRM package should follow this structure:
```text
packages/
└── Webkul/
└── PackageName/
├── src/
│ ├── Providers/
│ │ └── PackageServiceProvider.php
│ ├── Models/
│ ├── Contracts/
│ ├── Repositories/
│ ├── Http/
│ │ ├── Controllers/
│ │ └── Requests/
│ ├── Routes/
│ │ ├── admin.php
│ │ └── api.php
│ ├── Database/
│ │ └── Migrations/
│ ├── Resources/
│ │ ├── views/ # only if the package renders its own Blade
│ │ └── lang/ # ONLY if views/ exists — see Localization
│ └── Config/
│ ├── package.php
│ ├── menu.php
│ ├── core_config.php
│ └── acl.php
└── composer.json
```
---
## Localization (Translations)
### The rule
A package owns a `Resources/lang/` directory **only if it also owns
`Resources/views/`** — that is, only if it renders its own Blade templates.
Every other package ships **zero** translation files; its strings live in the
**Admin** package under `admin::app.*`.
Before creating any lang file, ask:
> Does this package have `src/Resources/views/` with Blade templates?
- **Yes** → give it `Resources/lang/<locale>/app.php` and register its own
namespace with `loadTranslationsFrom()` in the service provider.
- **No** → do **not** create a lang directory and do **not** call
`loadTranslationsFrom()`. Put the keys in the Admin package and reference them
as `admin::app.…`.
Current state of the repo — preserve this invariant:
| Owns views | Packages | Translations live in |
|---|---|---|
| Yes | `Admin`, `Installer`, `WebForm` | the package itself (`admin::`, `installer::`, `web_form::`) |
| No | everything else (`Core`, `DataTransfer`, `Lead`, `Contact`, `Quote`, `User`, …) | `Admin` (`admin::app.*`) |
"Backend-only" strings are still translations and follow the same rule —
validation-rule messages, importer error maps, and `title` values referenced
from `Config/*.php` all belong in Admin when the package has no views.
### Where keys go for a view-less package
Nest them under the Admin key that already owns that domain so one feature's
strings stay together. Established precedent:
| Before | After |
|---|---|
| `core::app.validations.code` | `admin::app.validations.message.code` |
| `data_transfer::app.importers.persons.title` | `admin::app.settings.data-transfer.importers.persons.title` |
| `data_transfer::app.validation.errors.system` | `admin::app.settings.data-transfer.validation.errors.system` |
When you move keys out of a package, finish the job: rewrite every reference,
delete the package's `Resources/lang/`, and remove its `loadTranslationsFrom()`
call so the provider does not point at a path that no longer exists.
### Working with Admin lang files
- Admin ships one `app.php` per locale: `ar`, `en`, `es`, `fa`, `ko`, `pt_BR`,
`tr`, `vi`, `zh_CN`. **Add every new key to all of them in the same change** —
a key present only in `en` renders as the raw key string in other locales.
- If a real translation is unavailable, use the English text as the value. Never
omit the key, and never leave the key name as its own value.
- Preserve placeholders exactly: `:attribute`, `:days`, `:count` (Laravel) and
`%s` (importer messages formatted with `sprintf`).
- Pint enforces a **single space** around `=>` (`pint.json` →
`binary_operator_spaces`). Do not align `=>` into columns.
- Name the file `app.php` in every locale directory. A misnamed file (e.g.
`ar/ar.php`) is never loaded and the locale silently falls back to English.
### Adding a new locale
1. Create `<locale>/app.php` in each package that owns a lang directory
(`Admin`, `Installer`, `WebForm`), mirroring the `en` key structure exactly.
2. Register it in `config/app.php` → `available_locales`. This drives both the
admin locale dropdown (via `Core@locales`) and the web installer.
3. Add it to `$locales` in
`packages/Webkul/Installer/src/Console/Commands/Installer.php` so the CLI
installer offers it.
4. If the script is right-to-left, add it to the `['fa', 'ar']` checks in the
Admin layout Blade files.
### Verifying
Confirm parity with `en` — same key set, same placeholders — then check that
keys actually resolve:
```bash
php artisan tinker --execute='app()->setLocale("<locale>"); echo trans("admin::app.<your.key>");'
./vendor/bin/pint --test packages/Webkul/<Package>
```
A key that resolves to its own name (`admin::app.foo.bar`) is missing.
---
## Changelog
### The rule
**Every bug fix and every feature gets a `CHANGELOG.md` entry, in the same
change.** Do not leave it for someone else and do not treat it as optional
follow-up work — a fix that is not in the changelog is invisible to the release
notes.
Add an entry when the change is user-visible or operator-visible: a bug fix, a
new feature, an enhancement, a security fix, a configuration option, or a
convention that affects how the product is built. Skip it only for changes with
no observable effect at all — a typo in a code comment, a pure test refactor.
### Format
Entries live at the top of [CHANGELOG.md](../../../CHANGELOG.md), newest version
first, and use exactly this shape:
```markdown
## **v2.2.5 (Upcoming)**
* #2601[fixed] Fixed lead value not saved when the currency is changed.
* #2604[feature] Added Chinese (Simplified) translation.
```
- One blank line between every entry — the file is read as rendered markdown.
- No space between the issue number and the tag: `#2601[fixed]`, not `#2601 [fixed]`.
- Write the description as a complete sentence ending in a period, phrased from
the user's point of view, not the implementation's.
Valid tags, and when each applies:
| Tag | Use for |
|---|---|
| `[fixed]` | Something was broken and now works. |
| `[feature]` | New capability that did not exist before. |
| `[enhancement]` | Existing behaviour improved, refactored, or made faster. |
| `[security]` | Vulnerability fix. Reference the CVE when one exists. |
### Which version section
Add to the topmost section if it is still unreleased. If the top section is
already tagged `*Release*`, open a new one above it:
```markdown
## **v<next patch version> (Upcoming)**
```
Replace `(Upcoming)` with the real date in the release commit — the existing
released headings show the expected style: `## **v2.2.4 (20th of July 2026)** *Release*`.
### Two things not to do
- **Never invent an issue or PR number.** They point at real GitHub PRs, so a
guessed number creates a false reference. If the PR does not exist yet, omit
the `#NNNN` prefix and leave the tag, then fill the number in once it is
opened.
- **Do not bump the version constant as part of a feature or fix.**
`KRAYIN_VERSION` in `packages/Webkul/Core/src/Core.php` is incremented in the
release commit, together with dating the changelog heading — not per change.

144
.github/skills/pest-testing/SKILL.md vendored Normal file
View File

@@ -0,0 +1,144 @@
---
name: pest-testing
description: Use when writing or updating Krayin CRM tests (unit or feature), debugging test failures, using datasets, mocks or custom expectations, writing architecture tests, or when the user mentions test, spec, TDD, expects, assertion, or coverage. Uses the Pest PHP framework (v3) with Laravel 12.
license: MIT
metadata:
author: webkul
---
# Pest Testing in Krayin CRM
## When to Apply
Activate this skill when:
- Creating or updating tests (unit or feature)
- Debugging test failures
- Using datasets, mocks, or custom expectations
- Writing architecture or convention tests
- The user mentions test, spec, TDD, expects, assertion, coverage, or verifying behavior
## Krayin Testing Structure
### Test Locations
Krayin tests are stored in the root `tests/` directory:
```
/tests
├── Feature/
├── Unit/
├── Pest.php
├── TestCase.php
└── CreatesApplication.php
```
### Available Test Suites
Defined in `phpunit.xml`:
| Test Suite | Location | Command |
|------------|----------|---------|
| Unit | `tests/Unit` | `php artisan test --testsuite="Unit"` |
| Feature | `tests/Feature` | `php artisan test --testsuite="Feature"` |
## Pest.php Configuration
`tests/Pest.php` binds the base test case for feature tests:
```php
uses(\Tests\TestCase::class)->in('Feature');
```
It also defines helper functions you can reuse, such as:
- `getDefaultAdmin()`
- `actingAsSanctumAuthenticatedAdmin()`
- `getFirstName($fullName)`
## Running Tests
### Run All Tests
```bash
php artisan test --compact
```
### Run a Specific Test Suite
```bash
php artisan test --testsuite="Feature"
php artisan test --testsuite="Unit"
```
### Run a Specific Test File
```bash
php artisan test --compact tests/Feature/ExampleTest.php
```
### Run with Filter
```bash
php artisan test --compact --filter=testName
```
## Creating New Tests
### Create Feature Test
```bash
php artisan make:test --pest ExampleFeatureTest
```
### Create Unit Test
```bash
php artisan make:test --pest --unit ExampleUnitTest
```
## Basic Test Structure
```php
it('passes basic assertion', function () {
expect(true)->toBeTrue();
});
it('returns successful response', function () {
$response = $this->get('/');
$response->assertSuccessful();
});
```
## Assertions
Prefer specific response helpers:
| Use | Instead of |
|-----|------------|
| `assertSuccessful()` | `assertStatus(200)` |
| `assertNotFound()` | `assertStatus(404)` |
| `assertForbidden()` | `assertStatus(403)` |
## Datasets
```php
it('has valid emails', function (string $email) {
expect($email)->toContain('@');
})->with([
'james' => 'james@krayin.com',
'john' => 'john@krayin.com',
]);
```
## Common Pitfalls
- Forgetting to use `assertSuccessful()` and other specific helpers
- Skipping `--pest` when creating tests
- Ignoring helper utilities already available in `tests/Pest.php`
## Testing Best Practices
- Cover happy paths, failure paths, and edge cases
- Keep tests isolated and focused
- Use factories where available
- Follow existing test patterns in the repository

View File

@@ -0,0 +1,122 @@
name: Admin | Playwright Tests
on: [push, pull_request]
permissions:
contents: read
env:
FORCE_COLOR: 1
jobs:
admin_playwright_test:
runs-on: ${{ matrix.operating-systems }}
strategy:
fail-fast: false
matrix:
operating-systems: [ubuntu-latest]
php-versions: ['8.3']
node-version: ['22.13.1']
shard-index: [1,2,3,4,5,6]
shard-total: [6]
name: Admin | Playwright Tests | Shard ${{ matrix.shard-index }} Of ${{ matrix.shard-total }}
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: krayin
ports:
- 3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: curl, fileinfo, gd, intl, mbstring, openssl, pdo, pdo_mysql, tokenizer, zip
ini-values: error_reporting=E_ALL
tools: composer:v2
- name: Set Up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install Node.js Dependencies
run: npm install
working-directory: packages/Webkul/Admin
- name: Install Playwright Browsers
run: npx playwright install --with-deps
working-directory: packages/Webkul/Admin
- name: Setting Environment
run: |
cp .env.example .env
sed -i "s|^\(DB_HOST=\s*\).*$|\1127.0.0.1|" .env
sed -i "s|^\(DB_PORT=\s*\).*$|\1${{ job.services.mysql.ports['3306'] }}|" .env
sed -i "s|^\(DB_DATABASE=\s*\).*$|\1krayin|" .env
sed -i "s|^\(DB_USERNAME=\s*\).*$|\1root|" .env
sed -i "s|^\(DB_PASSWORD=\s*\).*$|\1root|" .env
sed -i "s|^\(APP_DEBUG=\s*\).*$|\1true|" .env
sed -i "s|^\(APP_URL=\s*\).*$|\1http://127.0.0.1:8000|" .env
cat .env
- name: Install Composer Dependencies
run: composer install
- name: Running Krayin Installer
run: php artisan krayin-crm:install --skip-env-check --skip-admin-creation
- name: Clear Laravel Caches
run: php artisan optimize:clear
- name: Verify Activity Binding
run: |
php artisan tinker --execute="
// 1) Laravel container binding (needed by repositories)
if (! app()->bound(Webkul\\Activity\\Contracts\\Activity::class)) {
throw new RuntimeException('Activity contract is NOT bound in Laravel container');
}
// 2) Concord model-proxy registry (needed by ActivityProxy::modelClass())
\$concord = app('concord');
if (! \$concord->model(Webkul\\Activity\\Contracts\\Activity::class)) {
throw new RuntimeException('Activity contract is NOT registered in Concord model registry');
}
dump(app()->make(Webkul\\Activity\\Contracts\\Activity::class)::class);
dump(\$concord->model(Webkul\\Activity\\Contracts\\Activity::class));
"
# - name: Seed Product Table
# run: php artisan db:seed --class="Webkul\\Installer\\Database\\Seeders\\ProductTableSeeder"
- name: Start Laravel server
run: |
php artisan serve --host=0.0.0.0 --port=8000 > server.log 2>&1 &
echo "Waiting for server to start..."
timeout 30 bash -c 'until curl -s http://127.0.0.1:8000 > /dev/null; do sleep 1; done'
- name: Run All Playwright Tests
env:
BASE_URL: 'http://127.0.0.1:8000'
run: |
npx playwright test --reporter=list --config=tests/e2e-pw/playwright.config.ts --shard=${{ matrix.shard-index }}/${{ matrix.shard-total }}
working-directory: packages/Webkul/Admin
- name: Upload Test Results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.shard-index }}-${{ github.run_id }}-${{ github.run_number }}
path: packages/Webkul/Admin/tests/e2e-pw/test-results
retention-days: 1

40
.github/workflows/auto_commits.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: Linting Tests
on: [push, pull_request]
permissions:
contents: write
jobs:
linting_tests:
runs-on: ${{ matrix.operating-systems }}
strategy:
matrix:
operating-systems: [ubuntu-latest]
php-versions: ['8.3']
name: PHP ${{ matrix.php-versions }} test on ${{ matrix.operating-systems }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: composer:v2
- name: Install Pint
run: composer global require laravel/pint
env:
COMPOSER_HOME: ${{ runner.temp }}/composer
- name: Run Pint
run: ${{ runner.temp }}/composer/vendor/bin/pint
- name: Commit Linted Files
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore: applied pint changes"

55
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: CI
on: [push, pull_request]
jobs:
tests:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: [ubuntu-latest]
php-versions: ["8.3"]
name: PHP ${{ matrix.php-versions }} test on ${{ matrix.operating-system }}
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: krayin
ports:
- 3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: curl, gd, intl, mbstring, openssl, pdo, pdo_mysql, tokenizer, zip
ini-values: error_reporting=E_ALL
tools: composer:v2
- name: Running Composer Install
run: composer install --no-interaction --prefer-dist --no-progress
- name: Set Testing Environment
run: |
cp .env.example .env
sed -i "s|^\(APP_ENV=\s*\).*$|\1testing|" .env
sed -i "s|^\(DB_HOST=\s*\).*$|\1127.0.0.1|" .env
sed -i "s|^\(DB_PORT=\s*\).*$|\1${{ job.services.mysql.ports['3306'] }}|" .env
sed -i "s|^\(DB_DATABASE=\s*\).*$|\1krayin|" .env
sed -i "s|^\(DB_USERNAME=\s*\).*$|\1root|" .env
sed -i "s|^\(DB_PASSWORD=\s*\).*$|\1root|" .env
- name: Running Krayin Installer
run: php artisan krayin-crm:install --skip-env-check --skip-admin-creation
- name: Running Pest Test
run: vendor/bin/pest --parallel --colors=always

View File

@@ -0,0 +1,41 @@
name: Skills Consistency
permissions:
contents: read
on:
pull_request:
paths:
- '.github/skills/**'
- '.ai/**'
- '.claude/**'
- '.codex/**'
- '.cursor/**'
- '.kilocode/**'
- 'bin/validate-skills.sh'
- '.github/workflows/skills-consistency.yml'
push:
branches:
- '2.*'
- master
- main
paths:
- '.github/skills/**'
- '.ai/**'
- '.claude/**'
- '.codex/**'
- '.cursor/**'
- '.kilocode/**'
- 'bin/validate-skills.sh'
- '.github/workflows/skills-consistency.yml'
jobs:
validate-skills:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Validate skill source-of-truth
run: bash bin/validate-skills.sh