April 2026 waren Wirtschaft Feedback
This commit is contained in:
parent
02f2a4c23e
commit
9ce711d6b2
167 changed files with 25278 additions and 8518 deletions
27
.cursor/mcp.json
Normal file
27
.cursor/mcp.json
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"laravel-boost": {
|
||||||
|
"command": "php",
|
||||||
|
"args": [
|
||||||
|
"artisan",
|
||||||
|
"boost:mcp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"context7": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@upstash/context7-mcp",
|
||||||
|
"--api-key",
|
||||||
|
"ctx7sk-119cd4ab-8983-4229-8702-e84c59c34fc9"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sequential-thinking": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-sequential-thinking"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
248
.cursor/rules/laravel-boost.mdc
Normal file
248
.cursor/rules/laravel-boost.mdc
Normal file
|
|
@ -0,0 +1,248 @@
|
||||||
|
---
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
<laravel-boost-guidelines>
|
||||||
|
=== foundation rules ===
|
||||||
|
|
||||||
|
# Laravel Boost Guidelines
|
||||||
|
|
||||||
|
The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
|
||||||
|
|
||||||
|
## Foundational Context
|
||||||
|
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
||||||
|
|
||||||
|
- php - 8.4.1
|
||||||
|
- laravel/framework (LARAVEL) - v11
|
||||||
|
- laravel/prompts (PROMPTS) - v0
|
||||||
|
- laravel/pint (PINT) - v1
|
||||||
|
- pestphp/pest (PEST) - v2
|
||||||
|
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, naming.
|
||||||
|
- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
|
||||||
|
- Check for existing components to reuse before writing a new one.
|
||||||
|
|
||||||
|
## Verification Scripts
|
||||||
|
- Do not create verification scripts or tinker when tests cover that functionality and prove it works. Unit and feature tests are more important.
|
||||||
|
|
||||||
|
## Application Structure & Architecture
|
||||||
|
- Stick to existing directory structure - don't create new base folders without approval.
|
||||||
|
- Do not change the application's dependencies without approval.
|
||||||
|
|
||||||
|
## Frontend Bundling
|
||||||
|
- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them.
|
||||||
|
|
||||||
|
## Replies
|
||||||
|
- Be concise in your explanations - focus on what's important rather than explaining obvious details.
|
||||||
|
|
||||||
|
## Documentation Files
|
||||||
|
- You must only create documentation files if explicitly requested by the user.
|
||||||
|
|
||||||
|
|
||||||
|
=== boost rules ===
|
||||||
|
|
||||||
|
## Laravel Boost
|
||||||
|
- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
|
||||||
|
|
||||||
|
## Artisan
|
||||||
|
- Use the `list-artisan-commands` tool when you need to call an Artisan command to double check the available parameters.
|
||||||
|
|
||||||
|
## URLs
|
||||||
|
- Whenever you share a project URL with the user you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain / IP, and port.
|
||||||
|
|
||||||
|
## Tinker / Debugging
|
||||||
|
- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
|
||||||
|
- Use the `database-query` tool when you only need to read from the database.
|
||||||
|
|
||||||
|
## Reading Browser Logs With the `browser-logs` Tool
|
||||||
|
- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
|
||||||
|
- Only recent browser logs will be useful - ignore old logs.
|
||||||
|
|
||||||
|
## Searching Documentation (Critically Important)
|
||||||
|
- Boost comes with a powerful `search-docs` tool you should use before any other approaches. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation specific for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages.
|
||||||
|
- The 'search-docs' tool is perfect for all Laravel related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
|
||||||
|
- You must use this tool to search for Laravel-ecosystem documentation before falling back to other approaches.
|
||||||
|
- Search the documentation before making code changes to ensure we are taking the correct approach.
|
||||||
|
- Use multiple, broad, simple, topic based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
|
||||||
|
- Do not add package names to queries - package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`.
|
||||||
|
|
||||||
|
### Available Search Syntax
|
||||||
|
- You can and should pass multiple queries at once. The most relevant results will be returned first.
|
||||||
|
|
||||||
|
1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'
|
||||||
|
2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit"
|
||||||
|
3. Quoted Phrases (Exact Position) - query="infinite scroll" - Words must be adjacent and in that order
|
||||||
|
4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit"
|
||||||
|
5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms
|
||||||
|
|
||||||
|
|
||||||
|
=== php rules ===
|
||||||
|
|
||||||
|
## PHP
|
||||||
|
|
||||||
|
- Always use curly braces for control structures, even if it has one line.
|
||||||
|
|
||||||
|
### Constructors
|
||||||
|
- Use PHP 8 constructor property promotion in `__construct()`.
|
||||||
|
- <code-snippet>public function __construct(public GitHub $github) { }</code-snippet>
|
||||||
|
- Do not allow empty `__construct()` methods with zero parameters.
|
||||||
|
|
||||||
|
### Type Declarations
|
||||||
|
- Always use explicit return type declarations for methods and functions.
|
||||||
|
- Use appropriate PHP type hints for method parameters.
|
||||||
|
|
||||||
|
<code-snippet name="Explicit Return Types and Method Params" lang="php">
|
||||||
|
protected function isAccessible(User $user, ?string $path = null): bool
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
</code-snippet>
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
- Prefer PHPDoc blocks over comments. Never use comments within the code itself unless there is something _very_ complex going on.
|
||||||
|
|
||||||
|
## PHPDoc Blocks
|
||||||
|
- Add useful array shape type definitions for arrays when appropriate.
|
||||||
|
|
||||||
|
## Enums
|
||||||
|
- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`.
|
||||||
|
|
||||||
|
|
||||||
|
=== laravel/core rules ===
|
||||||
|
|
||||||
|
## Do Things the Laravel Way
|
||||||
|
|
||||||
|
- Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool.
|
||||||
|
- If you're creating a generic PHP class, use `artisan make:class`.
|
||||||
|
- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior.
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins.
|
||||||
|
- Use Eloquent models and relationships before suggesting raw database queries
|
||||||
|
- Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them.
|
||||||
|
- Generate code that prevents N+1 query problems by using eager loading.
|
||||||
|
- Use Laravel's query builder for very complex database operations.
|
||||||
|
|
||||||
|
### Model Creation
|
||||||
|
- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `php artisan make:model`.
|
||||||
|
|
||||||
|
### APIs & Eloquent Resources
|
||||||
|
- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
|
||||||
|
|
||||||
|
### Controllers & Validation
|
||||||
|
- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
|
||||||
|
- Check sibling Form Requests to see if the application uses array or string based validation rules.
|
||||||
|
|
||||||
|
### Queues
|
||||||
|
- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
|
||||||
|
|
||||||
|
### Authentication & Authorization
|
||||||
|
- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
|
||||||
|
|
||||||
|
### URL Generation
|
||||||
|
- When generating links to other pages, prefer named routes and the `route()` function.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
|
||||||
|
- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
|
||||||
|
- When creating tests, make use of `php artisan make:test [options] <name>` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.
|
||||||
|
|
||||||
|
### Vite Error
|
||||||
|
- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`.
|
||||||
|
|
||||||
|
|
||||||
|
=== laravel/v11 rules ===
|
||||||
|
|
||||||
|
## Laravel 11
|
||||||
|
|
||||||
|
- Use the `search-docs` tool to get version specific documentation.
|
||||||
|
- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel 11 file structure.
|
||||||
|
- This is **perfectly fine** and recommended by Laravel. Follow the existing structure from Laravel 10. We do not to need migrate to the Laravel 11 structure unless the user explicitly requests that.
|
||||||
|
|
||||||
|
### Laravel 10 Structure
|
||||||
|
- Middleware typically live in `app/Http/Middleware/` and service providers in `app/Providers/`.
|
||||||
|
- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure:
|
||||||
|
- Middleware registration is in `app/Http/Kernel.php`
|
||||||
|
- Exception handling is in `app/Exceptions/Handler.php`
|
||||||
|
- Console commands and schedule registration is in `app/Console/Kernel.php`
|
||||||
|
- Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php`
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
|
||||||
|
- Laravel 11 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
|
||||||
|
|
||||||
|
### Models
|
||||||
|
- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
|
||||||
|
|
||||||
|
### New Artisan Commands
|
||||||
|
- List Artisan commands using Boost's MCP tool, if available. New commands available in Laravel 11:
|
||||||
|
- `php artisan make:enum`
|
||||||
|
- `php artisan make:class`
|
||||||
|
- `php artisan make:interface`
|
||||||
|
|
||||||
|
|
||||||
|
=== pint/core rules ===
|
||||||
|
|
||||||
|
## Laravel Pint Code Formatter
|
||||||
|
|
||||||
|
- You must run `vendor/bin/pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
|
||||||
|
- Do not run `vendor/bin/pint --test`, simply run `vendor/bin/pint` to fix any formatting issues.
|
||||||
|
|
||||||
|
|
||||||
|
=== pest/core rules ===
|
||||||
|
|
||||||
|
## Pest
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- If you need to verify a feature is working, write or update a Unit / Feature test.
|
||||||
|
|
||||||
|
### Pest Tests
|
||||||
|
- All tests must be written using Pest. Use `php artisan make:test --pest <name>`.
|
||||||
|
- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files - these are core to the application.
|
||||||
|
- Tests should test all of the happy paths, failure paths, and weird paths.
|
||||||
|
- Tests live in the `tests/Feature` and `tests/Unit` directories.
|
||||||
|
- Pest tests look and behave like this:
|
||||||
|
<code-snippet name="Basic Pest Test Example" lang="php">
|
||||||
|
it('is true', function () {
|
||||||
|
expect(true)->toBeTrue();
|
||||||
|
});
|
||||||
|
</code-snippet>
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
- Run the minimal number of tests using an appropriate filter before finalizing code edits.
|
||||||
|
- To run all tests: `php artisan test`.
|
||||||
|
- To run all tests in a file: `php artisan test tests/Feature/ExampleTest.php`.
|
||||||
|
- To filter on a particular test name: `php artisan test --filter=testName` (recommended after making a change to a related file).
|
||||||
|
- When the tests relating to your changes are passing, ask the user if they would like to run the entire test suite to ensure everything is still passing.
|
||||||
|
|
||||||
|
### Pest Assertions
|
||||||
|
- When asserting status codes on a response, use the specific method like `assertForbidden` and `assertNotFound` instead of using `assertStatus(403)` or similar, e.g.:
|
||||||
|
<code-snippet name="Pest Example Asserting postJson Response" lang="php">
|
||||||
|
it('returns all', function () {
|
||||||
|
$response = $this->postJson('/api/docs', []);
|
||||||
|
|
||||||
|
$response->assertSuccessful();
|
||||||
|
});
|
||||||
|
</code-snippet>
|
||||||
|
|
||||||
|
### Mocking
|
||||||
|
- Mocking can be very helpful when appropriate.
|
||||||
|
- When mocking, you can use the `Pest\Laravel\mock` Pest function, but always import it via `use function Pest\Laravel\mock;` before using it. Alternatively, you can use `$this->mock()` if existing tests do.
|
||||||
|
- You can also create partial mocks using the same import or self method.
|
||||||
|
|
||||||
|
### Datasets
|
||||||
|
- Use datasets in Pest to simplify tests which have a lot of duplicated data. This is often the case when testing validation rules, so consider going with this solution when writing tests for validation rules.
|
||||||
|
|
||||||
|
<code-snippet name="Pest Dataset Example" lang="php">
|
||||||
|
it('has emails', function (string $email) {
|
||||||
|
expect($email)->not->toBeEmpty();
|
||||||
|
})->with([
|
||||||
|
'james' => 'james@laravel.com',
|
||||||
|
'taylor' => 'taylor@laravel.com',
|
||||||
|
]);
|
||||||
|
</code-snippet>
|
||||||
|
</laravel-boost-guidelines>
|
||||||
44
.devcontainer/devcontainer.json
Normal file
44
.devcontainer/devcontainer.json
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"name": "Partner Grüne Seele (Dev Container)",
|
||||||
|
"dockerComposeFile": [
|
||||||
|
"../docker-compose.yml"
|
||||||
|
],
|
||||||
|
"service": "laravel.test",
|
||||||
|
"workspaceFolder": "/var/www/html",
|
||||||
|
"remoteUser": "sail",
|
||||||
|
"features": {},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"bmewburn.vscode-intelephense-client",
|
||||||
|
"onecentlin.laravel-blade",
|
||||||
|
"shufo.vscode-blade-formatter",
|
||||||
|
"bradlc.vscode-tailwindcss",
|
||||||
|
"Anthropic.claude-code",
|
||||||
|
"onecentlin.laravel-extension-pack"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// WICHTIG: Nur noch den Haupt-Container starten!
|
||||||
|
"runServices": [
|
||||||
|
"laravel.test"
|
||||||
|
],
|
||||||
|
"containerEnv": {
|
||||||
|
"WWWUSER": "501",
|
||||||
|
"WWWGROUP": "20",
|
||||||
|
"LARAVEL_SAIL": "1"
|
||||||
|
},
|
||||||
|
"mounts": [
|
||||||
|
"source=${localWorkspaceFolder},target=/var/www/html,type=bind,consistency=cached"
|
||||||
|
],
|
||||||
|
// WICHTIG: Nur noch den Vite-Port weiterleiten
|
||||||
|
"forwardPorts": [
|
||||||
|
5179
|
||||||
|
],
|
||||||
|
"portsAttributes": {
|
||||||
|
"5179": {
|
||||||
|
"label": "Vite Dev Server",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
.env
31
.env
|
|
@ -27,15 +27,15 @@ LOG_CHANNEL=stack
|
||||||
LOG_LEVEL=debug
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=192.168.1.8
|
DB_HOST=mysql
|
||||||
DB_PORT=3306
|
DB_PORT=3306
|
||||||
DB_DATABASE=grueneseele
|
DB_DATABASE=partner_gruene_seele
|
||||||
DB_USERNAME=kadmin
|
DB_USERNAME=root
|
||||||
DB_PASSWORD=KT32vQ7ix
|
DB_PASSWORD=password
|
||||||
|
|
||||||
|
|
||||||
#DB_CONNECTION=mysql
|
#DB_CONNECTION=mysql
|
||||||
#DB_HOST=localhost
|
#DB_HOST=mysql
|
||||||
#DB_PORT=3306
|
#DB_PORT=3306
|
||||||
#DB_DATABASE=web28_db4
|
#DB_DATABASE=web28_db4
|
||||||
#DB_USERNAME=web28_4
|
#DB_USERNAME=web28_4
|
||||||
|
|
@ -51,16 +51,21 @@ MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
REDIS_HOST=127.0.0.1
|
REDIS_HOST=127.0.0.1
|
||||||
REDIS_PASSWORD=null
|
REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6384
|
||||||
|
#REDIS_PORT=6379
|
||||||
|
|
||||||
MAIL_DRIVER=smtp
|
MAIL_DRIVER=smtp
|
||||||
MAIL_HOST=w017e534.kasserver.com
|
MAIL_HOST=mailpit
|
||||||
MAIL_PORT=587
|
MAIL_PORT=1029
|
||||||
MAIL_USERNAME=m0496c96
|
|
||||||
MAIL_PASSWORD=mZtVp7WQcs6DC3hf
|
#MAIL_DRIVER=smtp
|
||||||
MAIL_ENCRYPTION=null
|
#MAIL_HOST=w017e534.kasserver.com
|
||||||
MAIL_FROM_ADDRESS=dev@adametz.media
|
#MAIL_PORT=587
|
||||||
MAIL_FROM_NAME="DEV Grüne Seele"
|
#MAIL_USERNAME=m0496c96
|
||||||
|
#MAIL_PASSWORD=mZtVp7WQcs6DC3hf
|
||||||
|
#MAIL_ENCRYPTION=null
|
||||||
|
#MAIL_FROM_ADDRESS=dev@adametz.media
|
||||||
|
#MAIL_FROM_NAME="DEV Grüne Seele"
|
||||||
|
|
||||||
#MAIL_MAILER=smtp
|
#MAIL_MAILER=smtp
|
||||||
#MAIL_HOST=s182.goserver.host
|
#MAIL_HOST=s182.goserver.host
|
||||||
|
|
|
||||||
27
.mcp.json
Normal file
27
.mcp.json
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"laravel-boost": {
|
||||||
|
"command": "php",
|
||||||
|
"args": [
|
||||||
|
"artisan",
|
||||||
|
"boost:mcp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"context7": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@upstash/context7-mcp",
|
||||||
|
"--api-key",
|
||||||
|
"ctx7sk-119cd4ab-8983-4229-8702-e84c59c34fc9"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sequential-thinking": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-sequential-thinking"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load diff
85
CLAUDE.md
Normal file
85
CLAUDE.md
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
German-language MLM/direct-sales e-commerce platform for organic/natural products ("Gruene Seele" / Green Soul). Partners/distributors get personal whitelabel shops, earn commissions through a multi-level hierarchy, and manage orders, invoices, and promotions.
|
||||||
|
|
||||||
|
**Stack:** PHP 8.4, Laravel 11 (using Laravel 10 directory structure), Bootstrap 4, jQuery, Laravel Mix (webpack), MySQL, Laravel Passport (API auth).
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Tests (Pest v2, uses SQLite in-memory)
|
||||||
|
php artisan test # run all tests
|
||||||
|
php artisan test tests/Feature/ExampleTest.php # run single file
|
||||||
|
php artisan test --filter=testName # filter by name
|
||||||
|
|
||||||
|
# Code formatting (Laravel Pint)
|
||||||
|
vendor/bin/pint --dirty # format changed files only
|
||||||
|
vendor/bin/pint # format all files
|
||||||
|
composer format # alias for pint
|
||||||
|
|
||||||
|
# Frontend (Laravel Mix, NOT Vite)
|
||||||
|
npm run dev # development build
|
||||||
|
npm run prod # production build
|
||||||
|
npm run watch # watch mode
|
||||||
|
|
||||||
|
# Artisan - always pass --no-interaction
|
||||||
|
php artisan make:model Name --no-interaction
|
||||||
|
php artisan make:test --pest Name --no-interaction
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Multi-Domain Routing (`routes/web.php`)
|
||||||
|
Three separate domain groups, each with distinct middleware:
|
||||||
|
- **Main domain** (`config('app.domain')`) - admin panel + user dashboard
|
||||||
|
- **Promo domain** (`config('app.promo_domain')`) - public promotion/microsite pages
|
||||||
|
- **Shop domain** (`config('app.shop_domain')`) - public whitelabel shop
|
||||||
|
|
||||||
|
### Admin Access Levels (middleware in `app/Http/Middleware/`)
|
||||||
|
- `CopyReader` - admin >= 1 (product/content management)
|
||||||
|
- `Admin` - admin >= 7 (sales, customers, promotions)
|
||||||
|
- `SuperAdmin` - admin >= 8 (users, shipping, settings)
|
||||||
|
- `SysAdmin` - admin >= 9 (system tools, imports)
|
||||||
|
|
||||||
|
### Key Service Layer
|
||||||
|
- **`app/Services/Yard.php`** + `app/Services/Yard/` - Custom shopping cart (extends forked Gloudemans Cart in `packages/digital-bird/shoppingcart/`). Handles shipping, tax, margins, commissions.
|
||||||
|
- **`app/Services/Invoice.php`** - Invoice and cancellation invoice PDF generation (uses DomPDF)
|
||||||
|
- **`app/Services/PaymentReminderService.php`** - Payment reminder logic with status progression
|
||||||
|
- **`app/Services/Credit.php`** - User credit/balance management
|
||||||
|
- **`app/Services/Stats/`** - Sales statistics
|
||||||
|
|
||||||
|
### Repository Pattern
|
||||||
|
Business logic uses repositories in `app/Repositories/` (e.g., `CheckoutRepository`, `InvoiceRepository`, `CustomerRepository`). Controllers delegate to repositories and services.
|
||||||
|
|
||||||
|
### Local Packages
|
||||||
|
`packages/digital-bird/shoppingcart/` - Forked `gloudemans/shoppingcart`, autoloaded via composer PSR-4 as `Gloudemans\Shoppingcart\`.
|
||||||
|
|
||||||
|
### Cron Jobs (`app/Console/Kernel.php`)
|
||||||
|
- `payments:accounts` - Checks user account expiry, sends reminders (statuses 31/33/34/35), deactivates expired accounts
|
||||||
|
- `payments:reminders` - Sends payment reminders for open invoices
|
||||||
|
|
||||||
|
### API (`routes/api.php`)
|
||||||
|
No versioning. Passport-authenticated endpoints for WordPress integration (`/api/wp/*`) and auth (`/api/auth/*`).
|
||||||
|
|
||||||
|
### Global Helpers
|
||||||
|
`app/helpers.php` (autoloaded) - URL helpers, formatting delegates to `App\Services\Util`.
|
||||||
|
|
||||||
|
### PDF Generation
|
||||||
|
- `app/Libraries/InvoicePDF.php`, `ContractPDF.php` - FPDF/FPDI based
|
||||||
|
- `app/Services/Invoice.php` - DomPDF based (Blade templates in `resources/views/pdf/`)
|
||||||
|
|
||||||
|
## Important Conventions
|
||||||
|
|
||||||
|
- This project uses **Laravel 10 directory structure** on Laravel 11. Do NOT migrate to Laravel 11 structure.
|
||||||
|
- Middleware registration: `app/Http/Kernel.php`
|
||||||
|
- Exception handling: `app/Exceptions/Handler.php`
|
||||||
|
- Schedule: `app/Console/Kernel.php`
|
||||||
|
- Default auth guard is `user` (not `web`), configured in `config/auth.php`
|
||||||
|
- User model is `App\User` (not `App\Models\User`)
|
||||||
|
- Views are Blade templates with Bootstrap 4 + jQuery DataTables
|
||||||
|
- Always run `vendor/bin/pint --dirty` before finalizing changes
|
||||||
|
- Countries supported: DE, FR, CH, NL (with reverse charge VAT handling)
|
||||||
740
_ide_helper.php
740
_ide_helper.php
File diff suppressed because it is too large
Load diff
2267
_ide_helper_models.php
Normal file
2267
_ide_helper_models.php
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -33,16 +33,20 @@ class PaymentsReminders extends Command
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'payments:reminders';
|
protected $signature = 'payments:reminders';
|
||||||
|
|
||||||
protected $description = 'Run Payments Reminders';
|
protected $description = 'Run Payments Reminders';
|
||||||
|
|
||||||
private $timeStart;
|
private $timeStart;
|
||||||
|
|
||||||
private $dev = false;
|
private $dev = false;
|
||||||
|
|
||||||
private $paymentReminderService;
|
private $paymentReminderService;
|
||||||
|
|
||||||
private $stats = [
|
private $stats = [
|
||||||
'total_processed' => 0,
|
'total_processed' => 0,
|
||||||
'reminders_sent' => 0,
|
'reminders_sent' => 0,
|
||||||
'errors' => 0,
|
'errors' => 0,
|
||||||
'skipped' => 0
|
'skipped' => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(PaymentReminderService $paymentReminderService)
|
public function __construct(PaymentReminderService $paymentReminderService)
|
||||||
|
|
@ -68,7 +72,7 @@ class PaymentsReminders extends Command
|
||||||
$executionTime = round(microtime(true) - $this->timeStart, 2);
|
$executionTime = round(microtime(true) - $this->timeStart, 2);
|
||||||
$this->info("\n=== PAYMENT REMINDERS ABGESCHLOSSEN ===");
|
$this->info("\n=== PAYMENT REMINDERS ABGESCHLOSSEN ===");
|
||||||
$this->info("Ausführungszeit: {$executionTime} Sekunden");
|
$this->info("Ausführungszeit: {$executionTime} Sekunden");
|
||||||
$this->info("Statistiken:");
|
$this->info('Statistiken:');
|
||||||
$this->info(" - Gesamt verarbeitet: {$this->stats['total_processed']}");
|
$this->info(" - Gesamt verarbeitet: {$this->stats['total_processed']}");
|
||||||
$this->info(" - Erinnerungen gesendet: {$this->stats['reminders_sent']}");
|
$this->info(" - Erinnerungen gesendet: {$this->stats['reminders_sent']}");
|
||||||
$this->info(" - Fehler: {$this->stats['errors']}");
|
$this->info(" - Fehler: {$this->stats['errors']}");
|
||||||
|
|
@ -76,15 +80,17 @@ class PaymentsReminders extends Command
|
||||||
|
|
||||||
\Log::info('PaymentsReminders Command completed successfully', [
|
\Log::info('PaymentsReminders Command completed successfully', [
|
||||||
'execution_time' => $executionTime,
|
'execution_time' => $executionTime,
|
||||||
'stats' => $this->stats
|
'stats' => $this->stats,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::error('PaymentsReminders Command failed', [
|
\Log::error('PaymentsReminders Command failed', [
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
'trace' => $e->getTraceAsString()
|
'trace' => $e->getTraceAsString(),
|
||||||
]);
|
]);
|
||||||
$this->error('Command failed: ' . $e->getMessage());
|
$this->error('Command failed: '.$e->getMessage());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -98,40 +104,44 @@ class PaymentsReminders extends Command
|
||||||
|
|
||||||
// Hole alle aktiven PaymentReminder und gruppiere sie nach clearingtype
|
// Hole alle aktiven PaymentReminder und gruppiere sie nach clearingtype
|
||||||
$payment_reminders = PaymentReminder::where('active', true)->get();
|
$payment_reminders = PaymentReminder::where('active', true)->get();
|
||||||
$this->info("Gefundene aktive PaymentReminder: " . $payment_reminders->count());
|
$this->info('Gefundene aktive PaymentReminder: '.$payment_reminders->count());
|
||||||
|
|
||||||
if ($payment_reminders->isEmpty()) {
|
if ($payment_reminders->isEmpty()) {
|
||||||
$this->warn("Keine aktiven PaymentReminder gefunden!");
|
$this->warn('Keine aktiven PaymentReminder gefunden!');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finde für jeden clearingtype das kleinste Intervall (in Tagen)
|
// Finde für jeden clearingtype das kleinste Intervall (in Tagen)
|
||||||
$intervals = $this->paymentReminderService->getActiveIntervals();
|
$intervals = $this->paymentReminderService->getActiveIntervals();
|
||||||
|
|
||||||
$this->info("Gefundene clearingtypes mit kleinsten Intervallen:");
|
$this->info('Gefundene clearingtypes mit kleinsten Intervallen:');
|
||||||
foreach($intervals as $clearingtype => $interval){
|
foreach ($intervals as $clearingtype => $interval) {
|
||||||
$this->line(" - {$clearingtype}: {$interval} Tage");
|
$this->line(" - {$clearingtype}: {$interval} Tage");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verarbeite jeden clearingtype mit seinem kleinsten Intervall
|
// Verarbeite jeden clearingtype mit seinem kleinsten Intervall
|
||||||
foreach($intervals as $clearingtype => $interval){
|
foreach ($intervals as $clearingtype => $interval) {
|
||||||
$this->info("\n--- Verarbeite clearingtype: {$clearingtype} mit Intervall: {$interval} Tage ---");
|
$this->info("\n--- Verarbeite clearingtype: {$clearingtype} mit Intervall: {$interval} Tage ---");
|
||||||
|
|
||||||
$date = Carbon::now()->subDays($interval);
|
$date = Carbon::now()->subDays($interval);
|
||||||
$this->line("Suche Zahlungen vor: " . $date->format('d.m.Y H:i:s'));
|
$this->line('Suche Zahlungen vor: '.$date->format('d.m.Y H:i:s'));
|
||||||
|
|
||||||
// Hole nur die neueste ShoppingPayment pro shopping_order_id
|
// Hole nur die neueste ShoppingPayment pro shopping_order_id
|
||||||
$shopping_payments = $this->paymentReminderService->getOpenPaymentsForClearingType($clearingtype, $interval);
|
$shopping_payments = $this->paymentReminderService->getOpenPaymentsForClearingType($clearingtype, $interval);
|
||||||
|
|
||||||
$this->info("Gefundene offene Zahlungen für {$clearingtype}: " . $shopping_payments->count());
|
$this->info("Gefundene offene Zahlungen für {$clearingtype}: ".$shopping_payments->count());
|
||||||
|
|
||||||
if ($shopping_payments->isEmpty()) {
|
if ($shopping_payments->isEmpty()) {
|
||||||
$this->line(" Keine Zahlungen für {$clearingtype} gefunden.");
|
$this->line("Keine Zahlungen für {$clearingtype} gefunden.");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verarbeite jede Zahlung
|
// Verarbeite jede Zahlung
|
||||||
foreach($shopping_payments as $shopping_payment){
|
$this->line('--- START processPayment VERARBEITUNG');
|
||||||
|
|
||||||
|
foreach ($shopping_payments as $shopping_payment) {
|
||||||
$this->processPayment($shopping_payment, $clearingtype);
|
$this->processPayment($shopping_payment, $clearingtype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -145,24 +155,23 @@ class PaymentsReminders extends Command
|
||||||
$this->stats['total_processed']++;
|
$this->stats['total_processed']++;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->line(" Verarbeite Order ID: {$shopping_payment->shopping_order_id}, Created: {$shopping_payment->created_at->format('d.m.Y H:i:s')}, Amount: {$shopping_payment->amount}, Reminder: {$shopping_payment->reminder}");
|
$this->line("Verarbeite Order ID: {$shopping_payment->shopping_order_id}, Created: {$shopping_payment->created_at->format('d.m.Y H:i:s')}, Amount: {$shopping_payment->amount}, Reminder: {$shopping_payment->reminder}");
|
||||||
|
|
||||||
// Prüfe ob eine Erinnerung gesendet werden soll
|
// Prüfe ob eine Erinnerung gesendet werden soll
|
||||||
if ($this->shouldSendReminder($shopping_payment, $clearingtype)) {
|
if ($this->shouldSendReminder($shopping_payment, $clearingtype)) {
|
||||||
$this->sendReminderForPayment($shopping_payment);
|
$this->sendReminderForPayment($shopping_payment);
|
||||||
} else {
|
} else {
|
||||||
$this->line(" ⏭️ Übersprungen - Keine Erinnerung fällig");
|
$this->line('Übersprungen - Keine Erinnerung fällig');
|
||||||
$this->stats['skipped']++;
|
$this->stats['skipped']++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->error(" ❌ Fehler bei Order ID {$shopping_payment->shopping_order_id}: " . $e->getMessage());
|
$this->error("Fehler bei Order ID {$shopping_payment->shopping_order_id}: ".$e->getMessage());
|
||||||
$this->stats['errors']++;
|
$this->stats['errors']++;
|
||||||
|
|
||||||
\Log::error('Error processing payment reminder', [
|
\Log::error('Error processing payment reminder', [
|
||||||
'order_id' => $shopping_payment->shopping_order_id,
|
'order_id' => $shopping_payment->shopping_order_id,
|
||||||
'payment_id' => $shopping_payment->id,
|
'payment_id' => $shopping_payment->id,
|
||||||
'error' => $e->getMessage()
|
'error' => $e->getMessage(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,33 +188,52 @@ class PaymentsReminders extends Command
|
||||||
// Hole alle aktiven Erinnerungen für diesen Clearingtype
|
// Hole alle aktiven Erinnerungen für diesen Clearingtype
|
||||||
$payment_reminders = PaymentReminder::where('active', true)
|
$payment_reminders = PaymentReminder::where('active', true)
|
||||||
->where('clearingtype', $clearingtype)
|
->where('clearingtype', $clearingtype)
|
||||||
->orderBy('interval', 'asc')
|
->orderBy('interval', 'asc') // von kein nach gross
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
if ($payment_reminders->isEmpty()) {
|
if ($payment_reminders->isEmpty()) {
|
||||||
|
$this->line('shouldSendReminder - keine PaymentReminders');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wenn alle Erinnerungen bereits gesendet wurden
|
// Wenn alle Erinnerungen bereits gesendet wurden
|
||||||
if ($shopping_payment->reminder >= $payment_reminders->count()) {
|
if ($shopping_payment->reminder >= $payment_reminders->count()) {
|
||||||
|
$this->line('shouldSendReminder - alle Erinnerungen wurden bereits gesendet');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hole die nächste Erinnerung
|
$next_reminder = isset($payment_reminders[$shopping_payment->reminder]) ? $payment_reminders[$shopping_payment->reminder] : null;
|
||||||
$next_reminder = $payment_reminders[$shopping_payment->reminder];
|
if ($next_reminder == null) {
|
||||||
|
$next_reminder = isset($payment_reminders[0]) ? $payment_reminders[0] : null;
|
||||||
|
if ($next_reminder == null) {
|
||||||
|
$this->line('shouldSendReminder - keine Erinnerung gefunden');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->line("shouldSendReminder - nächste Erinnerung: {$next_reminder->interval} Tage");
|
||||||
|
|
||||||
// Wenn noch keine Erinnerung gesendet wurde, prüfe das erste Intervall
|
// Wenn noch keine Erinnerung gesendet wurde, prüfe das erste Intervall
|
||||||
if ($shopping_payment->reminder == 0) {
|
if ($shopping_payment->reminder == null || $shopping_payment->reminder == 0) {
|
||||||
$daysSinceOrder = $shopping_payment->created_at->diffInDays(now());
|
$daysSinceOrder = $shopping_payment->created_at->diffInDays(now());
|
||||||
|
$this->line("shouldSendReminder - no reminder send first intervall - Tage seit Bestellung: {$daysSinceOrder} : Next intervall: {$next_reminder->interval}");
|
||||||
|
|
||||||
return $daysSinceOrder >= $next_reminder->interval;
|
return $daysSinceOrder >= $next_reminder->interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hole die nächste Erinnerung
|
||||||
|
|
||||||
// Wenn bereits Erinnerungen gesendet wurden, prüfe das nächste Intervall
|
// Wenn bereits Erinnerungen gesendet wurden, prüfe das nächste Intervall
|
||||||
if ($shopping_payment->reminder_date) {
|
if ($shopping_payment->reminder_date) {
|
||||||
$current_reminder = $payment_reminders[$shopping_payment->reminder - 1];
|
$current_reminder = $payment_reminders[$shopping_payment->reminder - 1];
|
||||||
|
$this->line("shouldSendReminder - letzte Erinnerung: {$current_reminder->interval} Tage");
|
||||||
$interval_difference = $next_reminder->interval - $current_reminder->interval;
|
$interval_difference = $next_reminder->interval - $current_reminder->interval;
|
||||||
|
|
||||||
$next_reminder_date = Carbon::parse($shopping_payment->reminder_date)->addDays($interval_difference);
|
$next_reminder_date = Carbon::parse($shopping_payment->reminder_date)->addDays($interval_difference);
|
||||||
|
$this->line("shouldSendReminder - next reminder date: {$next_reminder_date->format('d.m.Y H:i:s')}");
|
||||||
|
|
||||||
return now()->gte($next_reminder_date);
|
return now()->gte($next_reminder_date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,12 +246,12 @@ class PaymentsReminders extends Command
|
||||||
private function sendReminderForPayment($shopping_payment)
|
private function sendReminderForPayment($shopping_payment)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->line(" 📧 Sende Erinnerung...");
|
$this->line('Sende Erinnerung...');
|
||||||
|
|
||||||
$result = $this->paymentReminderService->sendReminder($shopping_payment);
|
$result = $this->paymentReminderService->sendReminder($shopping_payment);
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$this->line(" ✅ Erinnerung erfolgreich gesendet");
|
$this->line('Erinnerung erfolgreich gesendet');
|
||||||
$this->stats['reminders_sent']++;
|
$this->stats['reminders_sent']++;
|
||||||
|
|
||||||
// Log für Cron-Job
|
// Log für Cron-Job
|
||||||
|
|
@ -231,21 +259,20 @@ class PaymentsReminders extends Command
|
||||||
'order_id' => $shopping_payment->shopping_order_id,
|
'order_id' => $shopping_payment->shopping_order_id,
|
||||||
'payment_id' => $shopping_payment->id,
|
'payment_id' => $shopping_payment->id,
|
||||||
'reminder_count' => $shopping_payment->reminder + 1,
|
'reminder_count' => $shopping_payment->reminder + 1,
|
||||||
'email' => $shopping_payment->shopping_order->shopping_user->billing_email ?? 'N/A'
|
'email' => $shopping_payment->shopping_order->shopping_user->billing_email ?? 'N/A',
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$this->line(" ⚠️ Keine Erinnerung gesendet (keine weitere Erinnerung verfügbar)");
|
$this->line('Keine Erinnerung gesendet (keine weitere Erinnerung verfügbar)');
|
||||||
$this->stats['skipped']++;
|
$this->stats['skipped']++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->error(" ❌ Fehler beim Senden der Erinnerung: " . $e->getMessage());
|
$this->error('Fehler beim Senden der Erinnerung: '.$e->getMessage());
|
||||||
$this->stats['errors']++;
|
$this->stats['errors']++;
|
||||||
|
|
||||||
\Log::error('Error sending payment reminder', [
|
\Log::error('Error sending payment reminder', [
|
||||||
'order_id' => $shopping_payment->shopping_order_id,
|
'order_id' => $shopping_payment->shopping_order_id,
|
||||||
'payment_id' => $shopping_payment->id,
|
'payment_id' => $shopping_payment->id,
|
||||||
'error' => $e->getMessage()
|
'error' => $e->getMessage(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,19 +19,19 @@ class Kernel extends ConsoleKernel
|
||||||
/**
|
/**
|
||||||
* Define the application's command schedule.
|
* Define the application's command schedule.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule)
|
protected function schedule(Schedule $schedule)
|
||||||
{
|
{
|
||||||
/*$schedule->command('payments:accounts')
|
if (config('app.debug') == false) {
|
||||||
|
$schedule->command('payments:accounts')
|
||||||
->sendOutputTo(storage_path('logs/cron.log'))
|
->sendOutputTo(storage_path('logs/cron.log'))
|
||||||
->appendOutputTo(storage_path('logs/cron-history.log'))
|
->appendOutputTo(storage_path('logs/cron-history.log'))
|
||||||
->emailOutputOnFailure(config('app.exception_mail'))
|
->emailOutputOnFailure(config('app.exception_mail'))
|
||||||
->onFailure(function () {
|
->onFailure(function () {
|
||||||
\Log::error('Payments:accounts command failed');
|
\Log::error('Payments:accounts command failed');
|
||||||
});
|
});
|
||||||
*/
|
}
|
||||||
|
|
||||||
$schedule->command('payments:reminders')
|
$schedule->command('payments:reminders')
|
||||||
->sendOutputTo(storage_path('logs/cron.log'))
|
->sendOutputTo(storage_path('logs/cron.log'))
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,17 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Cron;
|
namespace App\Cron;
|
||||||
|
|
||||||
use App\User;
|
|
||||||
use App\Models\UserBusiness;
|
|
||||||
use App\Services\HTMLHelper;
|
|
||||||
use App\Models\UserCreditItem;
|
|
||||||
use App\Repositories\CreditRepository;
|
|
||||||
use App\Mail\MailCustomMessage;
|
use App\Mail\MailCustomMessage;
|
||||||
use App\Mail\MailVerifyAccount;
|
use App\Mail\MailVerifyAccount;
|
||||||
use App\Models\UserHistory;
|
use App\Models\UserHistory;
|
||||||
use App\Models\UserMessage;
|
use App\Models\UserMessage;
|
||||||
|
use App\User;
|
||||||
use Carbon;
|
use Carbon;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
class UserCheckPaymentsAccounts
|
class UserCheckPaymentsAccounts
|
||||||
{
|
{
|
||||||
|
|
||||||
/*RULES
|
/*RULES
|
||||||
reminders
|
reminders
|
||||||
> 29 renewal_days > set next_m_level to m_level
|
> 29 renewal_days > set next_m_level to m_level
|
||||||
|
|
@ -27,28 +23,30 @@ class UserCheckPaymentsAccounts
|
||||||
> 0 deaktiv = reminder_deaktiv //status 35
|
> 0 deaktiv = reminder_deaktiv //status 35
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static function userReminderPayments(User $user, $dev){
|
public static function userReminderPayments(User $user, $dev)
|
||||||
//35 reminder_deaktiv
|
{
|
||||||
if(!$user->isActiveAccount()){ // payment_account gt now
|
// 35 reminder_deaktiv
|
||||||
|
if (! $user->isActiveAccount()) { // payment_account gt now
|
||||||
return self::checkIsReminderSend($user, 35, $dev);
|
return self::checkIsReminderSend($user, 35, $dev);
|
||||||
}
|
}
|
||||||
//34 reminder_last
|
// 34 reminder_last
|
||||||
if($user->daysActiveAccount() <= config('main.remind_last_days')){
|
if ($user->daysActiveAccount() <= config('main.remind_last_days')) {
|
||||||
return self::checkIsReminderSend($user, 34, $dev);
|
return self::checkIsReminderSend($user, 34, $dev);
|
||||||
}
|
}
|
||||||
//33 reminder_sec
|
// 33 reminder_sec
|
||||||
if($user->daysActiveAccount() <= config('main.remind_sec_days')){
|
if ($user->daysActiveAccount() <= config('main.remind_sec_days')) {
|
||||||
return self::checkIsReminderSend($user, 33, $dev);
|
return self::checkIsReminderSend($user, 33, $dev);
|
||||||
}
|
}
|
||||||
//31 reminder_first
|
// 31 reminder_first
|
||||||
if($user->daysActiveAccount() > config('main.remind_sec_days')){
|
if ($user->daysActiveAccount() > config('main.remind_sec_days')) {
|
||||||
return self::checkIsReminderSend($user, 31, $dev);
|
return self::checkIsReminderSend($user, 31, $dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function checkIsReminderSend(User $user, $status, $dev)
|
||||||
private static function checkIsReminderSend(User $user, $status, $dev){
|
{
|
||||||
|
|
||||||
$isSend = UserHistory::whereUserId($user->id)
|
$isSend = UserHistory::whereUserId($user->id)
|
||||||
->whereAction('reminder_payments')
|
->whereAction('reminder_payments')
|
||||||
|
|
@ -56,24 +54,25 @@ class UserCheckPaymentsAccounts
|
||||||
->whereStatus($status)
|
->whereStatus($status)
|
||||||
->get()->last();
|
->get()->last();
|
||||||
|
|
||||||
if($isSend){
|
if ($isSend) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if($dev){
|
if ($dev) {
|
||||||
$referenz = 0;
|
$referenz = 0;
|
||||||
}else{
|
} else {
|
||||||
$referenz = self::sendReminderMail($user, $status);
|
$referenz = self::sendReminderMail($user, $status);
|
||||||
}
|
}
|
||||||
UserHistory::create(['user_id' => $user->id, 'action'=>'reminder_payments', 'referenz'=>$referenz, 'identifier'=>$user->payment_account, 'status'=>$status]);
|
UserHistory::create(['user_id' => $user->id, 'action' => 'reminder_payments', 'referenz' => $referenz, 'identifier' => $user->payment_account, 'status' => $status]);
|
||||||
return $status;
|
|
||||||
|
|
||||||
|
return $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sendReminderMail(User $user, $status){
|
private static function sendReminderMail(User $user, $status)
|
||||||
|
{
|
||||||
|
|
||||||
$days = $user->daysActiveAccount();
|
$days = $user->daysActiveAccount();
|
||||||
if($days < 0){
|
if ($days < 0) {
|
||||||
$days = $days*-1;
|
$days = $days * -1;
|
||||||
}
|
}
|
||||||
$datetime = $user->getPaymentAccountDateFormat();
|
$datetime = $user->getPaymentAccountDateFormat();
|
||||||
|
|
||||||
|
|
@ -85,54 +84,53 @@ class UserCheckPaymentsAccounts
|
||||||
$price = 'von '.$user->payment_order_product->getFormattedPrice().' EUR';
|
$price = 'von '.$user->payment_order_product->getFormattedPrice().' EUR';
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
$message = __('reminder.copy_first_'.$status, ['days'=>$days, 'datetime'=>$datetime, 'price' =>$price, 'pay_date'=>$pay_date]);
|
$message = __('reminder.copy_first_'.$status, ['days' => $days, 'datetime' => $datetime, 'price' => $price, 'pay_date' => $pay_date]);
|
||||||
$message_last = __('reminder.copy_last_'.$status, ['days'=>$days, 'datetime'=>$datetime, 'price' =>$price, 'pay_date'=>$pay_date]);
|
$message_last = __('reminder.copy_last_'.$status, ['days' => $days, 'datetime' => $datetime, 'price' => $price, 'pay_date' => $pay_date]);
|
||||||
$button = __('reminder.button_'.$status);
|
$button = __('reminder.button_'.$status);
|
||||||
|
|
||||||
$message = preg_replace("/[\n\r]/","",$message);
|
$message = preg_replace("/[\n\r]/", '', $message);
|
||||||
$message_last = preg_replace("/[\n\r]/","",$message_last);
|
$message_last = preg_replace("/[\n\r]/", '', $message_last);
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'subject' => __('reminder.subject')." | ID: ".$status,
|
'subject' => __('reminder.subject').' | ID: '.$status,
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
'message_last' => $message_last,
|
'message_last' => $message_last,
|
||||||
'url' => route('user_membership'),
|
'url' => route('user_membership'),
|
||||||
'button' => $button,
|
'button' => $button,
|
||||||
];
|
];
|
||||||
//dump($data);
|
// dump($data);
|
||||||
$sender = User::find(1);
|
$sender = User::find(1);
|
||||||
$customer_mail = UserMessage::create([
|
$customer_mail = UserMessage::create([
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'send_user_id' => $sender->id,
|
'send_user_id' => $sender->id,
|
||||||
'email' => $user->email,
|
'email' => $user->email,
|
||||||
'subject' => $data['subject'],
|
'subject' => $data['subject'],
|
||||||
'message' => $data['message']." ".$data['message_last'],
|
'message' => $data['message'].' '.$data['message_last'],
|
||||||
]);
|
]);
|
||||||
try{
|
try {
|
||||||
if($status >= 34){
|
if ($status >= 34) {
|
||||||
//Mail::to($user->email)->bcc(config('app.info_mail'))->send(new MailCustomMessage($user, $data, $sender, false));
|
// Mail::to($user->email)->bcc(config('app.info_mail'))->send(new MailCustomMessage($user, $data, $sender, false));
|
||||||
}else{
|
} else {
|
||||||
//Mail::to($user->email)->send(new MailCustomMessage($user, $data, $sender, false));
|
// Mail::to($user->email)->send(new MailCustomMessage($user, $data, $sender, false));
|
||||||
}
|
}
|
||||||
}
|
} catch (\Exception $e) {
|
||||||
catch(\Exception $e){
|
|
||||||
\Log::channel('cron')->error('Mail Error: '.$e->getMessage());
|
\Log::channel('cron')->error('Mail Error: '.$e->getMessage());
|
||||||
// Never reached
|
// Never reached
|
||||||
$customer_mail->fail = true;
|
$customer_mail->fail = true;
|
||||||
$customer_mail->error = $e->getMessage();
|
$customer_mail->error = $e->getMessage();
|
||||||
$customer_mail->save();
|
$customer_mail->save();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
$customer_mail->send = true;
|
$customer_mail->send = true;
|
||||||
$customer_mail->sent_at = now();
|
$customer_mail->sent_at = now();
|
||||||
$customer_mail->save();
|
$customer_mail->save();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*public function checkConfirmation()
|
||||||
/*public function checkConfirmation()
|
|
||||||
{
|
{
|
||||||
User Register sind in der DB UserRegister, erst bei bestätigung wird es in die User DB übertragen
|
User Register sind in der DB UserRegister, erst bei bestätigung wird es in die User DB übertragen
|
||||||
|
|
||||||
|
|
@ -158,4 +156,3 @@ class UserCheckPaymentsAccounts
|
||||||
}
|
}
|
||||||
return "TOSK";
|
return "TOSK";
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
|
||||||
59
app/Http/Controllers/Admin/Inventory/LocationController.php
Normal file
59
app/Http/Controllers/Admin/Inventory/LocationController.php
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\StoreLocationRequest;
|
||||||
|
use App\Http\Requests\Inventory\UpdateLocationRequest;
|
||||||
|
use App\Models\Location;
|
||||||
|
|
||||||
|
class LocationController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.locations.index', [
|
||||||
|
'values' => Location::query()->orderBy('name')->get(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.locations.form', [
|
||||||
|
'model' => new Location(['active' => true]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreLocationRequest $request)
|
||||||
|
{
|
||||||
|
Location::create($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.locations.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Location $location)
|
||||||
|
{
|
||||||
|
return view('admin.inventory.locations.form', [
|
||||||
|
'model' => $location,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateLocationRequest $request, Location $location)
|
||||||
|
{
|
||||||
|
$location->update($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.locations.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Location $location)
|
||||||
|
{
|
||||||
|
$location->delete();
|
||||||
|
|
||||||
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.locations.index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\StoreMaterialQualityRequest;
|
||||||
|
use App\Http\Requests\Inventory\UpdateMaterialQualityRequest;
|
||||||
|
use App\Models\MaterialQuality;
|
||||||
|
|
||||||
|
class MaterialQualityController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.material-qualities.index', [
|
||||||
|
'values' => MaterialQuality::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.material-qualities.form', [
|
||||||
|
'model' => new MaterialQuality(['pos' => 0]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreMaterialQualityRequest $request)
|
||||||
|
{
|
||||||
|
MaterialQuality::create($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.material-qualities.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(MaterialQuality $materialQuality)
|
||||||
|
{
|
||||||
|
return view('admin.inventory.material-qualities.form', [
|
||||||
|
'model' => $materialQuality,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateMaterialQualityRequest $request, MaterialQuality $materialQuality)
|
||||||
|
{
|
||||||
|
$materialQuality->update($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.material-qualities.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(MaterialQuality $materialQuality)
|
||||||
|
{
|
||||||
|
$materialQuality->delete();
|
||||||
|
|
||||||
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.material-qualities.index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\StorePackagingItemRequest;
|
||||||
|
use App\Http\Requests\Inventory\UpdatePackagingItemRequest;
|
||||||
|
use App\Models\PackagingItem;
|
||||||
|
use App\Models\PackagingMaterial;
|
||||||
|
use App\Models\Supplier;
|
||||||
|
use App\Repositories\PackagingItemRepository;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PackagingItemController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected PackagingItemRepository $packagingItemRepository
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$category = $request->get('category', 'packaging');
|
||||||
|
$isShipping = $category === 'shipping';
|
||||||
|
|
||||||
|
$query = PackagingItem::query()
|
||||||
|
->with(['packagingMaterial', 'supplier'])
|
||||||
|
->orderBy('name');
|
||||||
|
|
||||||
|
if ($isShipping) {
|
||||||
|
$query->whereIn('category', ['shipping', 'label', 'shipping_office']);
|
||||||
|
} else {
|
||||||
|
$query->where('category', 'packaging');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('admin.inventory.packaging-items.index', [
|
||||||
|
'values' => $query->get(),
|
||||||
|
'category' => $category,
|
||||||
|
'pageTitle' => $isShipping ? __('Versandverpackung') : __('Produktverpackung'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
$category = $request->get('category', 'packaging');
|
||||||
|
|
||||||
|
return view('admin.inventory.packaging-items.form', [
|
||||||
|
'model' => new PackagingItem(['active' => true, 'category' => $category === 'shipping' ? 'shipping' : 'packaging', 'weight_grams' => 0]),
|
||||||
|
'packagingMaterials' => PackagingMaterial::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
'suppliers' => Supplier::query()->orderBy('name')->get(),
|
||||||
|
'category' => $category,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StorePackagingItemRequest $request)
|
||||||
|
{
|
||||||
|
$item = $this->packagingItemRepository->create($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
$category = in_array($item->category, ['shipping', 'label', 'shipping_office']) ? 'shipping' : 'packaging';
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.packaging-items.index', ['category' => $category]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(PackagingItem $packagingItem)
|
||||||
|
{
|
||||||
|
$category = in_array($packagingItem->category, ['shipping', 'label', 'shipping_office']) ? 'shipping' : 'packaging';
|
||||||
|
|
||||||
|
return view('admin.inventory.packaging-items.form', [
|
||||||
|
'model' => $packagingItem,
|
||||||
|
'packagingMaterials' => PackagingMaterial::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
'suppliers' => Supplier::query()->orderBy('name')->get(),
|
||||||
|
'category' => $category,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdatePackagingItemRequest $request, PackagingItem $packagingItem)
|
||||||
|
{
|
||||||
|
$this->packagingItemRepository->update($packagingItem, $request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
$category = in_array($packagingItem->category, ['shipping', 'label', 'shipping_office']) ? 'shipping' : 'packaging';
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.packaging-items.index', ['category' => $category]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(PackagingItem $packagingItem)
|
||||||
|
{
|
||||||
|
$category = in_array($packagingItem->category, ['shipping', 'label', 'shipping_office']) ? 'shipping' : 'packaging';
|
||||||
|
|
||||||
|
$packagingItem->delete();
|
||||||
|
|
||||||
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.packaging-items.index', ['category' => $category]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\StorePackagingMaterialRequest;
|
||||||
|
use App\Http\Requests\Inventory\UpdatePackagingMaterialRequest;
|
||||||
|
use App\Models\PackagingMaterial;
|
||||||
|
|
||||||
|
class PackagingMaterialController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.packaging-materials.index', [
|
||||||
|
'values' => PackagingMaterial::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.packaging-materials.form', [
|
||||||
|
'model' => new PackagingMaterial(['pos' => 0]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StorePackagingMaterialRequest $request)
|
||||||
|
{
|
||||||
|
PackagingMaterial::create($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.packaging-materials.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(PackagingMaterial $packagingMaterial)
|
||||||
|
{
|
||||||
|
return view('admin.inventory.packaging-materials.form', [
|
||||||
|
'model' => $packagingMaterial,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdatePackagingMaterialRequest $request, PackagingMaterial $packagingMaterial)
|
||||||
|
{
|
||||||
|
$packagingMaterial->update($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.packaging-materials.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(PackagingMaterial $packagingMaterial)
|
||||||
|
{
|
||||||
|
$packagingMaterial->delete();
|
||||||
|
|
||||||
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.packaging-materials.index');
|
||||||
|
}
|
||||||
|
}
|
||||||
169
app/Http/Controllers/Admin/Inventory/ProductionController.php
Normal file
169
app/Http/Controllers/Admin/Inventory/ProductionController.php
Normal file
|
|
@ -0,0 +1,169 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\StoreProductionRequest;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\Production;
|
||||||
|
use App\Repositories\ProductionRepository;
|
||||||
|
use App\Services\ProductionService;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class ProductionController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected ProductionRepository $productionRepository,
|
||||||
|
protected ProductionService $productionService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function index(): View
|
||||||
|
{
|
||||||
|
return view('admin.inventory.productions.index', [
|
||||||
|
'values' => $this->productionRepository->listForIndex(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): View
|
||||||
|
{
|
||||||
|
$defaultLocationId = Location::query()->where('name', 'like', '%öln%')->value('id')
|
||||||
|
?? Location::query()->where('active', true)->first()?->id;
|
||||||
|
|
||||||
|
return view('admin.inventory.productions.create', [
|
||||||
|
'products' => Product::query()->where('active', 1)->orderBy('name')->get(['id', 'name']),
|
||||||
|
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
|
||||||
|
'defaultLocationId' => $defaultLocationId,
|
||||||
|
'model' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreProductionRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
$payload = $request->validatedPayload();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$production = $this->productionService->store(
|
||||||
|
[
|
||||||
|
'product_id' => $payload['product_id'],
|
||||||
|
'location_id' => $payload['location_id'],
|
||||||
|
'produced_at' => $payload['produced_at'],
|
||||||
|
'quantity' => $payload['quantity'],
|
||||||
|
'notes' => $payload['notes'],
|
||||||
|
],
|
||||||
|
$payload['ingredient_lines'],
|
||||||
|
(int) $request->user()->id
|
||||||
|
);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
return redirect()->back()->withInput()->withErrors($e->errors());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($production->mhd_warning) {
|
||||||
|
\Session::flash('alert-warning', __('Hinweis: Mindestens eine Rohstoff-Charge hat ein kürzeres MHD als das geplante Produkt-MHD.'));
|
||||||
|
}
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.productions.show', $production);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Production $production): View
|
||||||
|
{
|
||||||
|
$production->load([
|
||||||
|
'product',
|
||||||
|
'location',
|
||||||
|
'producedByUser.account',
|
||||||
|
'productionIngredients.ingredient',
|
||||||
|
'productionIngredients.stockEntry',
|
||||||
|
'productionPackagings.packagingItem.packagingMaterial',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return view('admin.inventory.productions.show', [
|
||||||
|
'model' => $production,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Production $production): View
|
||||||
|
{
|
||||||
|
$production->load([
|
||||||
|
'product',
|
||||||
|
'location',
|
||||||
|
'productionIngredients.ingredient',
|
||||||
|
'productionIngredients.stockEntry',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$defaultLocationId = $production->location_id;
|
||||||
|
|
||||||
|
return view('admin.inventory.productions.edit', [
|
||||||
|
'model' => $production,
|
||||||
|
'products' => Product::query()->where('active', 1)
|
||||||
|
->orWhere('id', $production->product_id)
|
||||||
|
->orderBy('name')->get(['id', 'name']),
|
||||||
|
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
|
||||||
|
'defaultLocationId' => $defaultLocationId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(StoreProductionRequest $request, Production $production): RedirectResponse
|
||||||
|
{
|
||||||
|
$payload = $request->validatedPayload();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$production = $this->productionService->updateProduction(
|
||||||
|
$production,
|
||||||
|
[
|
||||||
|
'product_id' => $payload['product_id'],
|
||||||
|
'location_id' => $payload['location_id'],
|
||||||
|
'produced_at' => $payload['produced_at'],
|
||||||
|
'quantity' => $payload['quantity'],
|
||||||
|
'notes' => $payload['notes'],
|
||||||
|
],
|
||||||
|
$payload['ingredient_lines'],
|
||||||
|
(int) $request->user()->id
|
||||||
|
);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
return redirect()->back()->withInput()->withErrors($e->errors());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($production->mhd_warning) {
|
||||||
|
\Session::flash('alert-warning', __('Hinweis: Mindestens eine Rohstoff-Charge hat ein kürzeres MHD als das geplante Produkt-MHD.'));
|
||||||
|
}
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.productions.show', $production);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function copy(Production $production): View
|
||||||
|
{
|
||||||
|
$production->load([
|
||||||
|
'product',
|
||||||
|
'productionIngredients.ingredient',
|
||||||
|
'productionIngredients.stockEntry',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$defaultLocationId = $production->location_id;
|
||||||
|
|
||||||
|
return view('admin.inventory.productions.create', [
|
||||||
|
'model' => $production,
|
||||||
|
'products' => Product::query()->where('active', 1)->orderBy('name')->get(['id', 'name']),
|
||||||
|
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
|
||||||
|
'defaultLocationId' => $defaultLocationId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function recipeJson(Request $request, Product $product): JsonResponse
|
||||||
|
{
|
||||||
|
$locationId = (int) $request->query('location_id', 0);
|
||||||
|
$quantity = (int) $request->query('quantity', 1);
|
||||||
|
if ($locationId < 1) {
|
||||||
|
return response()->json(['message' => __('location_id erforderlich')], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(
|
||||||
|
$this->productionService->buildRecipePayload($product, $locationId, max(1, $quantity))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
234
app/Http/Controllers/Admin/Inventory/StockEntryController.php
Normal file
234
app/Http/Controllers/Admin/Inventory/StockEntryController.php
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\ReceiveStockEntryRequest;
|
||||||
|
use App\Http\Requests\Inventory\StoreStockEntryRequest;
|
||||||
|
use App\Http\Requests\Inventory\UpdateStockEntryRequest;
|
||||||
|
use App\Models\Ingredient;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\MaterialQuality;
|
||||||
|
use App\Models\PackagingItem;
|
||||||
|
use App\Models\StockEntry;
|
||||||
|
use App\Models\Supplier;
|
||||||
|
use App\Repositories\StockEntryRepository;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class StockEntryController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected StockEntryRepository $stockEntryRepository
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function index(): View
|
||||||
|
{
|
||||||
|
return view('admin.inventory.stock-entries.index', array_merge($this->formSharedData(), [
|
||||||
|
'values' => $this->stockEntryRepository->listForIndex(),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): View|RedirectResponse
|
||||||
|
{
|
||||||
|
if (! auth()->user()->isAdmin()) {
|
||||||
|
return redirect()->route('home');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('admin.inventory.stock-entries.create', array_merge($this->formSharedData(), [
|
||||||
|
'model' => new StockEntry([
|
||||||
|
'ordered_at' => now()->toDateString(),
|
||||||
|
'entry_type' => 'ingredient',
|
||||||
|
]),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreStockEntryRequest $request): RedirectResponse
|
||||||
|
{
|
||||||
|
if (! $request->user()->isAdmin()) {
|
||||||
|
return redirect()->route('home');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $request->validatedPayload();
|
||||||
|
$data['ordered_by'] = (int) auth()->id();
|
||||||
|
|
||||||
|
$this->stockEntryRepository->create($data);
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(StockEntry $stockEntry): View
|
||||||
|
{
|
||||||
|
$stockEntry->load([
|
||||||
|
'ingredient',
|
||||||
|
'packagingItem.packagingMaterial',
|
||||||
|
'supplier',
|
||||||
|
'location',
|
||||||
|
'quality',
|
||||||
|
'orderedByUser.account',
|
||||||
|
'receivedByUser.account',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return view('admin.inventory.stock-entries.show', array_merge($this->formSharedData(), [
|
||||||
|
'model' => $stockEntry,
|
||||||
|
'materialQualities' => MaterialQuality::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(StockEntry $stockEntry): View|RedirectResponse
|
||||||
|
{
|
||||||
|
if (! auth()->user()->isAdmin()) {
|
||||||
|
return redirect()->route('home');
|
||||||
|
}
|
||||||
|
if (! $stockEntry->isPending()) {
|
||||||
|
\Session::flash('alert-error', __('Nur offene Bestellungen können bearbeitet werden.'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stockEntry->load(['ingredient', 'packagingItem']);
|
||||||
|
|
||||||
|
return view('admin.inventory.stock-entries.edit', array_merge($this->formSharedData(), [
|
||||||
|
'model' => $stockEntry,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateStockEntryRequest $request, StockEntry $stockEntry): RedirectResponse
|
||||||
|
{
|
||||||
|
if (! $request->user()->isAdmin()) {
|
||||||
|
return redirect()->route('home');
|
||||||
|
}
|
||||||
|
if (! $stockEntry->isPending()) {
|
||||||
|
\Session::flash('alert-error', __('Nur offene Bestellungen können bearbeitet werden.'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stockEntryRepository->update($stockEntry, $request->validatedPayload());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(StockEntry $stockEntry): RedirectResponse
|
||||||
|
{
|
||||||
|
if (! auth()->user()->isAdmin()) {
|
||||||
|
return redirect()->route('home');
|
||||||
|
}
|
||||||
|
if (! $stockEntry->isPending()) {
|
||||||
|
\Session::flash('alert-error', __('Nur offene Bestellungen können gelöscht werden.'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
$stockEntry->delete();
|
||||||
|
|
||||||
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function receive(ReceiveStockEntryRequest $request, StockEntry $stockEntry): RedirectResponse
|
||||||
|
{
|
||||||
|
if (! $stockEntry->isPending()) {
|
||||||
|
\Session::flash('alert-error', __('Eintrag nicht mehr offen.'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $request->validated();
|
||||||
|
if ($stockEntry->entry_type !== 'ingredient') {
|
||||||
|
$data['quality_id'] = null;
|
||||||
|
$data['best_before'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stockEntryRepository->receive($stockEntry, $data);
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry->fresh());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function searchIngredients(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$term = trim((string) $request->query('q', ''));
|
||||||
|
if (mb_strlen($term) < 1) {
|
||||||
|
return response()->json(['results' => []]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = Ingredient::query()
|
||||||
|
->where('active', true)
|
||||||
|
->where(function ($query) use ($term) {
|
||||||
|
$query->where('name', 'like', '%'.$term.'%')
|
||||||
|
->orWhere('inci', 'like', '%'.$term.'%');
|
||||||
|
})
|
||||||
|
->orderBy('name')
|
||||||
|
->limit(30)
|
||||||
|
->get(['id', 'name', 'inci']);
|
||||||
|
|
||||||
|
$results = $rows->map(function (Ingredient $i) {
|
||||||
|
$text = $i->name;
|
||||||
|
if ($i->inci) {
|
||||||
|
$text .= ' ('.$i->inci.')';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['id' => $i->id, 'text' => $text];
|
||||||
|
})->values()->all();
|
||||||
|
|
||||||
|
return response()->json(['results' => $results]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function searchPackagingItems(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$term = trim((string) $request->query('q', ''));
|
||||||
|
$entryType = $request->query('entry_type');
|
||||||
|
|
||||||
|
$categoryMap = [
|
||||||
|
'packaging' => 'packaging',
|
||||||
|
'label' => 'label',
|
||||||
|
'shipping_office' => 'shipping_office',
|
||||||
|
];
|
||||||
|
|
||||||
|
$query = PackagingItem::query()
|
||||||
|
->where('active', true);
|
||||||
|
|
||||||
|
if ($entryType && isset($categoryMap[$entryType])) {
|
||||||
|
$query->where('category', $categoryMap[$entryType]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb_strlen($term) >= 1) {
|
||||||
|
$query->where('name', 'like', '%'.$term.'%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = $query->orderBy('name')->limit(30)->get(['id', 'name']);
|
||||||
|
|
||||||
|
$results = $rows->map(fn (PackagingItem $p) => [
|
||||||
|
'id' => $p->id,
|
||||||
|
'text' => $p->name,
|
||||||
|
])->values()->all();
|
||||||
|
|
||||||
|
return response()->json(['results' => $results]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
protected function formSharedData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'suppliers' => Supplier::query()->where('active', true)->orderBy('name')->get(),
|
||||||
|
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
|
||||||
|
'entryTypeLabels' => [
|
||||||
|
'ingredient' => __('Rohstoff'),
|
||||||
|
'packaging' => __('Verpackung'),
|
||||||
|
'label' => __('Etikett'),
|
||||||
|
'shipping_office' => __('Versand & Büro'),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\StoreSupplierCategoryRequest;
|
||||||
|
use App\Http\Requests\Inventory\UpdateSupplierCategoryRequest;
|
||||||
|
use App\Models\SupplierCategory;
|
||||||
|
|
||||||
|
class SupplierCategoryController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.supplier-categories.index', [
|
||||||
|
'values' => SupplierCategory::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.supplier-categories.form', [
|
||||||
|
'model' => new SupplierCategory(['pos' => 0]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreSupplierCategoryRequest $request)
|
||||||
|
{
|
||||||
|
SupplierCategory::create($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.supplier-categories.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(SupplierCategory $supplierCategory)
|
||||||
|
{
|
||||||
|
return view('admin.inventory.supplier-categories.form', [
|
||||||
|
'model' => $supplierCategory,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateSupplierCategoryRequest $request, SupplierCategory $supplierCategory)
|
||||||
|
{
|
||||||
|
$supplierCategory->update($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.supplier-categories.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(SupplierCategory $supplierCategory)
|
||||||
|
{
|
||||||
|
$supplierCategory->delete();
|
||||||
|
|
||||||
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.supplier-categories.index');
|
||||||
|
}
|
||||||
|
}
|
||||||
74
app/Http/Controllers/Admin/Inventory/SupplierController.php
Normal file
74
app/Http/Controllers/Admin/Inventory/SupplierController.php
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Inventory;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Inventory\StoreSupplierRequest;
|
||||||
|
use App\Http\Requests\Inventory\UpdateSupplierRequest;
|
||||||
|
use App\Models\Country;
|
||||||
|
use App\Models\Supplier;
|
||||||
|
use App\Models\SupplierCategory;
|
||||||
|
use App\Repositories\SupplierRepository;
|
||||||
|
|
||||||
|
class SupplierController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected SupplierRepository $supplierRepository
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('admin.inventory.suppliers.index', [
|
||||||
|
'values' => Supplier::query()->with(['country', 'supplierCategories'])->orderBy('name')->get(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$defaultCountryId = Country::where('code', 'DE')->value('id');
|
||||||
|
|
||||||
|
return view('admin.inventory.suppliers.form', [
|
||||||
|
'model' => new Supplier(['active' => true, 'country_id' => $defaultCountryId]),
|
||||||
|
'countries' => Country::query()->orderBy('de')->get(),
|
||||||
|
'supplierCategories' => SupplierCategory::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreSupplierRequest $request)
|
||||||
|
{
|
||||||
|
$this->supplierRepository->create($request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.suppliers.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Supplier $supplier)
|
||||||
|
{
|
||||||
|
$supplier->load('supplierCategories');
|
||||||
|
|
||||||
|
return view('admin.inventory.suppliers.form', [
|
||||||
|
'model' => $supplier,
|
||||||
|
'countries' => Country::query()->orderBy('de')->get(),
|
||||||
|
'supplierCategories' => SupplierCategory::query()->orderBy('pos')->orderBy('name')->get(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateSupplierRequest $request, Supplier $supplier)
|
||||||
|
{
|
||||||
|
$this->supplierRepository->update($supplier, $request->validated());
|
||||||
|
|
||||||
|
\Session::flash('alert-save', '1');
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.suppliers.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Supplier $supplier)
|
||||||
|
{
|
||||||
|
$supplier->delete();
|
||||||
|
|
||||||
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
||||||
|
|
||||||
|
return redirect()->route('admin.inventory.suppliers.index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,15 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Storage;
|
use App\Models\File;
|
||||||
use Response;
|
use App\Models\ShoppingOrder;
|
||||||
|
use App\Models\UserCredit;
|
||||||
use App\Services\Credit;
|
use App\Services\Credit;
|
||||||
use App\Services\Invoice;
|
use App\Services\Invoice;
|
||||||
|
use App\Services\PDFMerger;
|
||||||
use Auth;
|
use Auth;
|
||||||
|
use Response;
|
||||||
|
use Storage;
|
||||||
|
|
||||||
class FileController extends Controller
|
class FileController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -15,26 +19,25 @@ class FileController extends Controller
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
public function __construct() {}
|
||||||
|
|
||||||
|
private function isPermission($user_id)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
private function isPermission($user_id){
|
if (Auth::user()->isAdmin() || $user_id == Auth::user()->id) {
|
||||||
|
|
||||||
if(Auth::user()->isAdmin() || $user_id == Auth::user()->id){
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
abort(404);
|
abort(404);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($id = null, $disk = null, $do='file')
|
public function show($id = null, $disk = null, $do = 'file')
|
||||||
{
|
{
|
||||||
$path = "";
|
$path = '';
|
||||||
$filename = "";
|
$filename = '';
|
||||||
|
|
||||||
if($disk === 'user'){
|
if ($disk === 'user') {
|
||||||
$file = \App\Models\File::findOrFail($id);
|
$file = File::findOrFail($id);
|
||||||
$this->isPermission($file->user_id);
|
$this->isPermission($file->user_id);
|
||||||
$path = Storage::disk($disk)->path($file->dir.$file->filename);
|
$path = Storage::disk($disk)->path($file->dir.$file->filename);
|
||||||
if (file_exists($path)) {
|
if (file_exists($path)) {
|
||||||
|
|
@ -42,23 +45,29 @@ class FileController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($disk === 'invoice'){
|
if ($disk === 'invoice') {
|
||||||
$shopping_order = \App\Models\ShoppingOrder::findOrFail($id);
|
$shopping_order = ShoppingOrder::findOrFail($id);
|
||||||
$this->isPermission($shopping_order->auth_user_id);
|
$this->isPermission($shopping_order->auth_user_id);
|
||||||
$filename = Invoice::getFilename($shopping_order);
|
$filename = Invoice::getFilename($shopping_order);
|
||||||
$path = Invoice::getDownloadPath($shopping_order);
|
$path = Invoice::getDownloadPath($shopping_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($disk === 'delivery') {
|
||||||
if ($disk === 'delivery'){
|
$shopping_order = ShoppingOrder::findOrFail($id);
|
||||||
$shopping_order = \App\Models\ShoppingOrder::findOrFail($id);
|
|
||||||
$this->isPermission($shopping_order->auth_user_id);
|
$this->isPermission($shopping_order->auth_user_id);
|
||||||
$filename = Invoice::getDeliveryFilename($shopping_order);
|
$filename = Invoice::getDeliveryFilename($shopping_order);
|
||||||
$path = Invoice::getDownloadPathDelivery($shopping_order);
|
$path = Invoice::getDownloadPathDelivery($shopping_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($disk === 'invoice_delivery'){
|
if ($disk === 'cancellation') {
|
||||||
$shopping_order = \App\Models\ShoppingOrder::findOrFail($id);
|
$shopping_order = ShoppingOrder::findOrFail($id);
|
||||||
|
$this->isPermission($shopping_order->auth_user_id);
|
||||||
|
$filename = Invoice::getCancellationFilename($shopping_order);
|
||||||
|
$path = Invoice::getCancellationDownloadPath($shopping_order);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($disk === 'invoice_delivery') {
|
||||||
|
$shopping_order = ShoppingOrder::findOrFail($id);
|
||||||
$this->isPermission($shopping_order->auth_user_id);
|
$this->isPermission($shopping_order->auth_user_id);
|
||||||
|
|
||||||
$ifilename = Invoice::getFilename($shopping_order);
|
$ifilename = Invoice::getFilename($shopping_order);
|
||||||
|
|
@ -66,7 +75,7 @@ class FileController extends Controller
|
||||||
$dfilename = Invoice::getDeliveryFilename($shopping_order);
|
$dfilename = Invoice::getDeliveryFilename($shopping_order);
|
||||||
$dpath = Invoice::getDownloadPathDelivery($shopping_order, true);
|
$dpath = Invoice::getDownloadPathDelivery($shopping_order, true);
|
||||||
|
|
||||||
$oMerger = new \App\Services\PDFMerger();
|
$oMerger = new PDFMerger;
|
||||||
$oMerger->init();
|
$oMerger->init();
|
||||||
|
|
||||||
$oMerger->addPDF($ipath);
|
$oMerger->addPDF($ipath);
|
||||||
|
|
@ -75,28 +84,29 @@ class FileController extends Controller
|
||||||
$oMerger->setFileName($filename);
|
$oMerger->setFileName($filename);
|
||||||
$oMerger->merge();
|
$oMerger->merge();
|
||||||
$file = $oMerger->output();
|
$file = $oMerger->output();
|
||||||
|
|
||||||
return Response::make($file, 200)
|
return Response::make($file, 200)
|
||||||
->header("Content-Type", 'application/pdf')
|
->header('Content-Type', 'application/pdf')
|
||||||
->header('Content-disposition', 'attachment; filename="'.$filename.'"');
|
->header('Content-disposition', 'attachment; filename="'.$filename.'"');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($disk === 'credit'){
|
if ($disk === 'credit') {
|
||||||
$UserCredit = \App\Models\UserCredit::findOrFail($id);
|
$UserCredit = UserCredit::findOrFail($id);
|
||||||
$this->isPermission($UserCredit->auth_user_id);
|
$this->isPermission($UserCredit->auth_user_id);
|
||||||
$filename = Credit::getFilename($UserCredit);
|
$filename = Credit::getFilename($UserCredit);
|
||||||
$path = Credit::getDownloadPath($UserCredit);
|
$path = Credit::getDownloadPath($UserCredit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Storage::disk('public')->exists($path)) {
|
if (! Storage::disk('public')->exists($path)) {
|
||||||
return Response::make('File no found.', 404);
|
return Response::make('File no found.', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$file = Storage::disk('public')->get($path);
|
$file = Storage::disk('public')->get($path);
|
||||||
$mime = Storage::disk('public')->mimeType($path);
|
$mime = Storage::disk('public')->mimeType($path);
|
||||||
|
|
||||||
if($do === 'download'){
|
if ($do === 'download') {
|
||||||
return Response::make($file, 200)
|
return Response::make($file, 200)
|
||||||
->header("Content-Type", $mime)
|
->header('Content-Type', $mime)
|
||||||
->header('Content-disposition', 'attachment; filename="'.$filename.'"');
|
->header('Content-disposition', 'attachment; filename="'.$filename.'"');
|
||||||
/* $full_path = Invoice::getDownloadPath($shopping_order, true);
|
/* $full_path = Invoice::getDownloadPath($shopping_order, true);
|
||||||
$he
|
$he
|
||||||
|
|
@ -104,32 +114,31 @@ class FileController extends Controller
|
||||||
return Response::download($full_path, $filename);
|
return Response::download($full_path, $filename);
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
if($do === 'stream'){
|
if ($do === 'stream') {
|
||||||
return Response::make($file, 200)
|
return Response::make($file, 200)
|
||||||
->header("Content-Type", $mime)
|
->header('Content-Type', $mime)
|
||||||
->header('Content-disposition','filename="'.$filename.'"');
|
|
||||||
}
|
|
||||||
|
|
||||||
if($do === 'file'){
|
|
||||||
return Response::make($file, 200)
|
|
||||||
->header("Content-Type", $mime)
|
|
||||||
->header('Content-disposition', 'filename="'.$filename.'"');
|
->header('Content-disposition', 'filename="'.$filename.'"');
|
||||||
}
|
}
|
||||||
if($do === 'image'){
|
|
||||||
|
if ($do === 'file') {
|
||||||
return Response::make($file, 200)
|
return Response::make($file, 200)
|
||||||
->header("Content-Type", $mime);
|
->header('Content-Type', $mime)
|
||||||
|
->header('Content-disposition', 'filename="'.$filename.'"');
|
||||||
}
|
}
|
||||||
if($do === 'pdf'){
|
if ($do === 'image') {
|
||||||
$path = storage_path().'/app/public/' . $path;
|
return Response::make($file, 200)
|
||||||
$headers = array(
|
->header('Content-Type', $mime);
|
||||||
'Content-Type:'. $mime,
|
}
|
||||||
|
if ($do === 'pdf') {
|
||||||
|
$path = storage_path().'/app/public/'.$path;
|
||||||
|
$headers = [
|
||||||
|
'Content-Type:'.$mime,
|
||||||
// 'Content-Length: ' . $file->size
|
// 'Content-Length: ' . $file->size
|
||||||
// 'Content-Disposition: ' . $stream . '; filename=' . $file->original_name
|
// 'Content-Disposition: ' . $stream . '; filename=' . $file->original_name
|
||||||
);
|
];
|
||||||
|
|
||||||
return Response::download($path, $filename, $headers);
|
return Response::download($path, $filename, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,18 +2,12 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Category;
|
|
||||||
use App\Models\Ingredient;
|
use App\Models\Ingredient;
|
||||||
use App\Models\IqImage;
|
|
||||||
use App\Models\ProductCategory;
|
|
||||||
use App\Models\ProductIngredient;
|
use App\Models\ProductIngredient;
|
||||||
use Request;
|
use Request;
|
||||||
|
|
||||||
|
|
||||||
class IngredientController extends Controller
|
class IngredientController extends Controller
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('copyreader');
|
$this->middleware('copyreader');
|
||||||
|
|
@ -25,22 +19,24 @@ class IngredientController extends Controller
|
||||||
$data = [
|
$data = [
|
||||||
'values' => Ingredient::all(),
|
'values' => Ingredient::all(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return view('admin.ingredient.index', $data);
|
return view('admin.ingredient.index', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
if($id === "new"){
|
if ($id === 'new') {
|
||||||
$model = new Ingredient();
|
$model = new Ingredient;
|
||||||
$model->active = true;
|
$model->active = true;
|
||||||
}else{
|
} else {
|
||||||
$model = Ingredient::findOrFail($id);
|
$model = Ingredient::findOrFail($id);
|
||||||
}
|
}
|
||||||
$data = [
|
$data = [
|
||||||
'model' => $model,
|
'model' => $model,
|
||||||
//'trans' => array_keys(config('localization.supportedLocales')),
|
// 'trans' => array_keys(config('localization.supportedLocales')),
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return view('admin.ingredient.edit', $data);
|
return view('admin.ingredient.edit', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,30 +45,42 @@ class IngredientController extends Controller
|
||||||
|
|
||||||
$data = Request::all();
|
$data = Request::all();
|
||||||
$data['active'] = isset($data['active']) ? true : false;
|
$data['active'] = isset($data['active']) ? true : false;
|
||||||
if($data['id'] === "new"){
|
if (isset($data['default_factor']) && $data['default_factor'] !== '') {
|
||||||
|
$data['default_factor'] = reFormatNumber($data['default_factor']) ?: 1.10;
|
||||||
|
}
|
||||||
|
if (isset($data['min_stock_alert']) && $data['min_stock_alert'] === '') {
|
||||||
|
$data['min_stock_alert'] = null;
|
||||||
|
} elseif (isset($data['min_stock_alert']) && $data['min_stock_alert'] !== null) {
|
||||||
|
$data['min_stock_alert'] = reFormatNumber($data['min_stock_alert']);
|
||||||
|
}
|
||||||
|
if (empty($data['material_quality_id'])) {
|
||||||
|
$data['material_quality_id'] = null;
|
||||||
|
}
|
||||||
|
if ($data['id'] === 'new') {
|
||||||
$model = Ingredient::create($data);
|
$model = Ingredient::create($data);
|
||||||
}else{
|
} else {
|
||||||
$model = Ingredient::find($data['id']);
|
$model = Ingredient::find($data['id']);
|
||||||
$model->fill($data)->save();
|
$model->fill($data)->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
\Session()->flash('alert-save', '1');
|
\Session()->flash('alert-save', '1');
|
||||||
return redirect(route('admin_product_ingredients'));
|
|
||||||
|
|
||||||
|
return redirect(route('admin_product_ingredients'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($id){
|
public function delete($id)
|
||||||
|
{
|
||||||
|
|
||||||
if(ProductIngredient::where('ingredient_id', $id)->count()) {
|
if (ProductIngredient::where('ingredient_id', $id)->count()) {
|
||||||
\Session()->flash('alert-error', 'Eintrag wird als Produkt-Inhaltsstoff verwendet');
|
\Session()->flash('alert-error', 'Eintrag wird als Produkt-Inhaltsstoff verwendet');
|
||||||
|
|
||||||
return redirect(route('admin_product_ingredients'));
|
return redirect(route('admin_product_ingredients'));
|
||||||
}
|
}
|
||||||
$model = Ingredient::findOrFail($id);
|
$model = Ingredient::findOrFail($id);
|
||||||
$model->delete();
|
$model->delete();
|
||||||
\Session()->flash('alert-success', 'Eintrag gelöscht');
|
\Session()->flash('alert-success', 'Eintrag gelöscht');
|
||||||
|
|
||||||
return redirect(route('admin_product_ingredients'));
|
return redirect(route('admin_product_ingredients'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Country;
|
use App\Models\Country;
|
||||||
|
use App\Models\Ingredient;
|
||||||
|
use App\Models\PackagingItem;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\ProductImage;
|
use App\Models\ProductImage;
|
||||||
use App\Models\ProductIngredient;
|
use App\Models\ProductIngredient;
|
||||||
|
|
@ -10,8 +12,6 @@ use App\Repositories\ProductRepository;
|
||||||
use Request;
|
use Request;
|
||||||
use Validator;
|
use Validator;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ProductController extends Controller
|
class ProductController extends Controller
|
||||||
{
|
{
|
||||||
protected $productRepo;
|
protected $productRepo;
|
||||||
|
|
@ -24,35 +24,40 @@ class ProductController extends Controller
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
if(Request::get('show_active_products')){
|
if (Request::get('show_active_products')) {
|
||||||
set_user_attr('show_active_products', Request::get('show_active_products'));
|
set_user_attr('show_active_products', Request::get('show_active_products'));
|
||||||
}
|
}
|
||||||
if(get_user_attr('show_active_products') === "true"){
|
if (get_user_attr('show_active_products') === 'true') {
|
||||||
$values = Product::where('active', true)->orderBy('pos', 'DESC')->orderBy('id', 'DESC')->get();
|
$values = Product::where('active', true)->orderBy('pos', 'DESC')->orderBy('id', 'DESC')->get();
|
||||||
}else{
|
} else {
|
||||||
$values = Product::orderBy('pos', 'DESC')->orderBy('id', 'DESC')->get();
|
$values = Product::orderBy('pos', 'DESC')->orderBy('id', 'DESC')->get();
|
||||||
|
|
||||||
}
|
}
|
||||||
$data = [
|
$data = [
|
||||||
'values' => $values
|
'values' => $values,
|
||||||
];
|
];
|
||||||
|
|
||||||
return view('admin.product.index', $data);
|
return view('admin.product.index', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
if($id === "new"){
|
if ($id === 'new') {
|
||||||
$model = new Product();
|
$model = new Product;
|
||||||
$model->active = true;
|
$model->active = true;
|
||||||
}else{
|
} else {
|
||||||
$model = Product::findOrFail($id);
|
$model = Product::findOrFail($id);
|
||||||
|
$model->load(['packagings.packagingMaterial']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$country_for_prices = Country::where('own_eur', '=', true)->orWhere('currency', '=', true)->get();
|
$country_for_prices = Country::where('own_eur', '=', true)->orWhere('currency', '=', true)->get();
|
||||||
$data = [
|
$data = [
|
||||||
'product' => $model,
|
'product' => $model,
|
||||||
'country_for_prices' => $country_for_prices,
|
'country_for_prices' => $country_for_prices,
|
||||||
|
'ingredient_catalog' => Ingredient::query()->where('active', true)->with('materialQuality')->orderBy('name')->get(['id', 'name', 'inci', 'effect', 'default_factor', 'material_quality_id']),
|
||||||
|
'packaging_catalog' => PackagingItem::query()->where('active', true)->with('packagingMaterial')->orderBy('name')->get(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return view('admin.product.edit', $data);
|
return view('admin.product.edit', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,34 +66,36 @@ class ProductController extends Controller
|
||||||
|
|
||||||
$data = Request::all();
|
$data = Request::all();
|
||||||
|
|
||||||
$rules = array(
|
$rules = [
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
);
|
];
|
||||||
/*if(isset($data['number']) && $data['number'] != ""){
|
/*if(isset($data['number']) && $data['number'] != ""){
|
||||||
$rules['number'] = 'int';
|
$rules['number'] = 'int';
|
||||||
}*/
|
}*/
|
||||||
if(isset($data['wp_number'])){
|
if (isset($data['wp_number'])) {
|
||||||
if($data['id'] !== "new"){
|
if ($data['id'] !== 'new') {
|
||||||
$model = Product::findOrFail($data['id']);
|
$model = Product::findOrFail($data['id']);
|
||||||
$rules['wp_number'] = 'unique:products,wp_number,'.$model->id;
|
$rules['wp_number'] = 'unique:products,wp_number,'.$model->id;
|
||||||
}else{
|
} else {
|
||||||
$rules['wp_number'] = 'unique:products,wp_number';
|
$rules['wp_number'] = 'unique:products,wp_number';
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$validator = Validator::make(Request::all(), $rules);
|
$validator = Validator::make(Request::all(), $rules);
|
||||||
|
|
||||||
if($data['id'] === "new"){
|
if ($data['id'] === 'new') {
|
||||||
$model = new Product();
|
$model = new Product;
|
||||||
}else{
|
} else {
|
||||||
$model = Product::findOrFail($data['id']);
|
$model = Product::findOrFail($data['id']);
|
||||||
|
$model->load(['packagings.packagingMaterial']);
|
||||||
}
|
}
|
||||||
$country_for_prices = Country::where('own_eur', '=', true)->orWhere('currency', '=', true)->get();
|
$country_for_prices = Country::where('own_eur', '=', true)->orWhere('currency', '=', true)->get();
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'product' => $model,
|
'product' => $model,
|
||||||
'country_for_prices' => $country_for_prices,
|
'country_for_prices' => $country_for_prices,
|
||||||
|
'ingredient_catalog' => Ingredient::query()->where('active', true)->with('materialQuality')->orderBy('name')->get(['id', 'name', 'inci', 'effect', 'default_factor', 'material_quality_id']),
|
||||||
|
'packaging_catalog' => PackagingItem::query()->where('active', true)->with('packagingMaterial')->orderBy('name')->get(),
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
|
|
@ -98,34 +105,41 @@ class ProductController extends Controller
|
||||||
} else {
|
} else {
|
||||||
$product = $this->productRepo->update(Request::all());
|
$product = $this->productRepo->update(Request::all());
|
||||||
\Session()->flash('alert-save', true);
|
\Session()->flash('alert-save', true);
|
||||||
|
|
||||||
return redirect(route('admin_product_edit', [$product->id]));
|
return redirect(route('admin_product_edit', [$product->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
\Session()->flash('alert-save', '1');
|
\Session()->flash('alert-save', '1');
|
||||||
|
|
||||||
return redirect(route('admin_product_show'));
|
return redirect(route('admin_product_show'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function copy($id){
|
public function copy($id)
|
||||||
|
{
|
||||||
$model = Product::findOrFail($id);
|
$model = Product::findOrFail($id);
|
||||||
$product = $this->productRepo->copy($model);
|
$product = $this->productRepo->copy($model);
|
||||||
\Session()->flash('alert-success', 'Eintrag kopiert');
|
\Session()->flash('alert-success', 'Eintrag kopiert');
|
||||||
|
|
||||||
return redirect(route('admin_product_show'));
|
return redirect(route('admin_product_show'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($id, $do = 'product', $did = null){
|
public function delete($id, $do = 'product', $did = null)
|
||||||
if($do === 'product'){
|
{
|
||||||
|
if ($do === 'product') {
|
||||||
$model = Product::findOrFail($id);
|
$model = Product::findOrFail($id);
|
||||||
$model->delete();
|
$model->delete();
|
||||||
\Session()->flash('alert-success', 'Eintrag gelöscht');
|
\Session()->flash('alert-success', 'Eintrag gelöscht');
|
||||||
|
|
||||||
return redirect(route('admin_product_show'));
|
return redirect(route('admin_product_show'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($do === 'ingredient'){
|
if ($do === 'ingredient') {
|
||||||
$model = Product::findOrFail($id);
|
$model = Product::findOrFail($id);
|
||||||
$ProductIngredient = ProductIngredient::where('ingredient_id', $did)->where('product_id', $model->id)->first();
|
$ProductIngredient = ProductIngredient::where('ingredient_id', $did)->where('product_id', $model->id)->first();
|
||||||
if($ProductIngredient){
|
if ($ProductIngredient) {
|
||||||
$ProductIngredient->delete();
|
$ProductIngredient->delete();
|
||||||
\Session()->flash('alert-success', 'Eintrag gelöscht');
|
\Session()->flash('alert-success', 'Eintrag gelöscht');
|
||||||
|
|
||||||
return redirect(route('admin_product_edit', [$model->id]));
|
return redirect(route('admin_product_edit', [$model->id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,24 +148,29 @@ class ProductController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload FILE -----------------------------------------------------------------------------------------------------------------------
|
// Upload FILE -----------------------------------------------------------------------------------------------------------------------
|
||||||
public function imageUpload(){
|
public function imageUpload()
|
||||||
|
{
|
||||||
|
|
||||||
if(Request::has('product_id')){
|
if (Request::has('product_id')) {
|
||||||
$product = Product::findOrFail(Request::get('product_id'));
|
$product = Product::findOrFail(Request::get('product_id'));
|
||||||
|
|
||||||
return \App\Services\ProductImage::imageUpload('product', $product, Request::get('upload_type'));
|
return \App\Services\ProductImage::imageUpload('product', $product, Request::get('upload_type'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function imageDelete($product_image_id, $product_id){
|
public function imageDelete($product_image_id, $product_id)
|
||||||
|
{
|
||||||
$product = Product::findOrFail($product_id);
|
$product = Product::findOrFail($product_id);
|
||||||
|
|
||||||
return \App\Services\ProductImage::imageDelete('product', $product, $product_image_id);
|
return \App\Services\ProductImage::imageDelete('product', $product, $product_image_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function imageAttribute($product_id, $attr, $val = false){
|
public function imageAttribute($product_id, $attr, $val = false)
|
||||||
|
{
|
||||||
|
|
||||||
if(is_numeric($val) && $val < 0){
|
if (is_numeric($val) && $val < 0) {
|
||||||
$val = 0;
|
$val = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,9 +179,9 @@ class ProductController extends Controller
|
||||||
$product_image->{$attr} = $val;
|
$product_image->{$attr} = $val;
|
||||||
$product_image->save();
|
$product_image->save();
|
||||||
|
|
||||||
\Session()->flash('alert-success', "Wert gespeichert");
|
\Session()->flash('alert-success', 'Wert gespeichert');
|
||||||
|
|
||||||
return redirect()->back();
|
return redirect()->back();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,46 +2,48 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Request;
|
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Services\Payment;
|
|
||||||
use App\Models\ShoppingUser;
|
|
||||||
use App\Models\ShoppingOrder;
|
use App\Models\ShoppingOrder;
|
||||||
use App\Models\UserPayCredit;
|
use App\Models\ShoppingUser;
|
||||||
use App\Models\ShoppingPayment;
|
|
||||||
use App\Models\PaymentTransaction;
|
|
||||||
use App\Services\CustomerPriority;
|
|
||||||
use App\Repositories\InvoiceRepository;
|
use App\Repositories\InvoiceRepository;
|
||||||
|
use App\Services\CustomerPriority;
|
||||||
|
use App\Services\Invoice;
|
||||||
|
use App\Services\Payment;
|
||||||
use App\Services\PaymentService;
|
use App\Services\PaymentService;
|
||||||
|
use Request;
|
||||||
|
|
||||||
class SalesController extends Controller
|
class SalesController extends Controller
|
||||||
{
|
{
|
||||||
|
public function __construct()
|
||||||
public function __construct(){
|
{
|
||||||
$this->middleware('admin');
|
$this->middleware('admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index(){
|
public function index()
|
||||||
|
{
|
||||||
|
|
||||||
if(Request::get('reset') === 'filter'){
|
if (Request::get('reset') === 'filter') {
|
||||||
set_user_attr('filter_txaction', null);
|
set_user_attr('filter_txaction', null);
|
||||||
set_user_attr('filter_member_id', null);
|
set_user_attr('filter_member_id', null);
|
||||||
set_user_attr('filter_art', null);
|
set_user_attr('filter_art', null);
|
||||||
set_user_attr('filter_shipped', null);
|
set_user_attr('filter_shipped', null);
|
||||||
|
|
||||||
return redirect(route('admin_sales'));
|
return redirect(route('admin_sales'));
|
||||||
}
|
}
|
||||||
//set Filter!
|
// set Filter!
|
||||||
$filter_members = ShoppingOrder::join('users', 'member_id', '=', 'users.id')->groupBy('member_id')->join('user_accounts', 'account_id', '=', 'user_accounts.id')->select('users.id', 'users.email', 'user_accounts.first_name', 'user_accounts.last_name')->get();
|
$filter_members = ShoppingOrder::join('users', 'member_id', '=', 'users.id')->groupBy('member_id')->join('user_accounts', 'account_id', '=', 'user_accounts.id')->select('users.id', 'users.email', 'user_accounts.first_name', 'user_accounts.last_name')->get();
|
||||||
$data = [
|
$data = [
|
||||||
'filter_members' => $filter_members,
|
'filter_members' => $filter_members,
|
||||||
];
|
];
|
||||||
|
|
||||||
return view('admin.sales.index', $data);
|
return view('admin.sales.index', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function detail($id){
|
public function detail($id)
|
||||||
|
{
|
||||||
|
|
||||||
$ShoppingOrder = ShoppingOrder::find($id);
|
$ShoppingOrder = ShoppingOrder::find($id);
|
||||||
if($ShoppingOrder->shipped == 0){
|
if ($ShoppingOrder->shipped == 0) {
|
||||||
$ShoppingOrder->shipped = 1;
|
$ShoppingOrder->shipped = 1;
|
||||||
$ShoppingOrder->save();
|
$ShoppingOrder->save();
|
||||||
}
|
}
|
||||||
|
|
@ -54,37 +56,42 @@ class SalesController extends Controller
|
||||||
return view('admin.sales.detail', $data);
|
return view('admin.sales.detail', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function detailStore($id){
|
public function detailStore($id)
|
||||||
|
{
|
||||||
|
|
||||||
$data = Request::all();
|
$data = Request::all();
|
||||||
$change_member_error = false;
|
$change_member_error = false;
|
||||||
if($data['action']==='shopping-order-change-member'){
|
if ($data['action'] === 'shopping-order-change-member') {
|
||||||
if(!isset($data['change_member_key']) || $data['change_member_key'] !== config('main.edit_data_pass')){
|
if (! isset($data['change_member_key']) || $data['change_member_key'] !== config('main.edit_data_pass')) {
|
||||||
$change_member_error = "Das Passwort ist falsch.";
|
$change_member_error = 'Das Passwort ist falsch.';
|
||||||
}else{
|
} else {
|
||||||
//change
|
// change
|
||||||
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
||||||
CustomerPriority::newMemberForOrder($shopping_order, $data['change_member_id'], $data['customer_set_member_for']);
|
CustomerPriority::newMemberForOrder($shopping_order, $data['change_member_id'], $data['customer_set_member_for']);
|
||||||
\Session()->flash('alert-save', true);
|
\Session()->flash('alert-save', true);
|
||||||
|
|
||||||
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($data['action']==='shopping-user-is-like-member'){
|
if ($data['action'] === 'shopping-user-is-like-member') {
|
||||||
if(!isset($data['change_member_key']) || $data['change_member_key'] !== config('main.edit_data_pass')){
|
if (! isset($data['change_member_key']) || $data['change_member_key'] !== config('main.edit_data_pass')) {
|
||||||
\Session()->flash('alert-error', 'Das Passwort ist falsch.');
|
\Session()->flash('alert-error', 'Das Passwort ist falsch.');
|
||||||
|
|
||||||
return redirect($data['back']);
|
return redirect($data['back']);
|
||||||
}else{
|
} else {
|
||||||
if(!isset($data['is_like_shopping_user_id'])){
|
if (! isset($data['is_like_shopping_user_id'])) {
|
||||||
\Session()->flash('alert-error', 'Keine Änderung ausgewählt');
|
\Session()->flash('alert-error', 'Keine Änderung ausgewählt');
|
||||||
|
|
||||||
return redirect($data['back']);
|
return redirect($data['back']);
|
||||||
}
|
}
|
||||||
$shopping_user = ShoppingUser::findOrFail($data['id']);
|
$shopping_user = ShoppingUser::findOrFail($data['id']);
|
||||||
$set_like_shopping_user = ShoppingUser::findOrFail($data['is_like_shopping_user_id']);
|
$set_like_shopping_user = ShoppingUser::findOrFail($data['is_like_shopping_user_id']);
|
||||||
$send_member_mail = isset($data['send_member_mail']) ? true : false;
|
$send_member_mail = isset($data['send_member_mail']) ? true : false;
|
||||||
$change_shopping_user = isset($data['change_shopping_user']) ? true : false;
|
$change_shopping_user = isset($data['change_shopping_user']) ? true : false;
|
||||||
//Mail send in setIsLike
|
// Mail send in setIsLike
|
||||||
CustomerPriority::setIsLike($shopping_user, $set_like_shopping_user, $send_member_mail, $change_shopping_user);
|
CustomerPriority::setIsLike($shopping_user, $set_like_shopping_user, $send_member_mail, $change_shopping_user);
|
||||||
\Session()->flash('alert-save', true);
|
\Session()->flash('alert-save', true);
|
||||||
|
|
||||||
return redirect($data['back']);
|
return redirect($data['back']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -95,54 +102,57 @@ class SalesController extends Controller
|
||||||
'isAdmin' => true,
|
'isAdmin' => true,
|
||||||
'isView' => $ShoppingOrder->auth_user_id ? 'sales_user' : 'sales_customer',
|
'isView' => $ShoppingOrder->auth_user_id ? 'sales_user' : 'sales_customer',
|
||||||
];
|
];
|
||||||
|
|
||||||
return view('admin.sales.detail', $data);
|
return view('admin.sales.detail', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function datatable(){
|
public function datatable()
|
||||||
|
{
|
||||||
|
|
||||||
$query = ShoppingOrder::with('shopping_user', 'shopping_payments')->select('shopping_orders.*');
|
$query = ShoppingOrder::with('shopping_user', 'shopping_payments')->select('shopping_orders.*');
|
||||||
|
|
||||||
set_user_attr('filter_txaction', Request::get('filter_txaction'));
|
set_user_attr('filter_txaction', Request::get('filter_txaction'));
|
||||||
if(Request::get('filter_txaction') != ""){
|
if (Request::get('filter_txaction') != '') {
|
||||||
if(Request::get('filter_txaction') === 'NULL'){
|
if (Request::get('filter_txaction') === 'NULL') {
|
||||||
$query->where('txaction', '=', NULL);
|
$query->where('txaction', '=', null);
|
||||||
|
|
||||||
}else{
|
} else {
|
||||||
$query->where('txaction', '=', Request::get('filter_txaction'));
|
$query->where('txaction', '=', Request::get('filter_txaction'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_user_attr('filter_member_id', Request::get('filter_member_id'));
|
set_user_attr('filter_member_id', Request::get('filter_member_id'));
|
||||||
if(Request::get('filter_member_id') != ""){
|
if (Request::get('filter_member_id') != '') {
|
||||||
$query->where('member_id', '=', Request::get('filter_member_id'));
|
$query->where('member_id', '=', Request::get('filter_member_id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
set_user_attr('filter_art', Request::get('filter_art'));
|
set_user_attr('filter_art', Request::get('filter_art'));
|
||||||
if(Request::get('filter_art') != ""){
|
if (Request::get('filter_art') != '') {
|
||||||
if(Request::get('filter_art') === 'user_order'){
|
if (Request::get('filter_art') === 'user_order') {
|
||||||
$query->where('shopping_orders.auth_user_id', '!=', NULL)->where('payment_for', '!=', 6);
|
$query->where('shopping_orders.auth_user_id', '!=', null)->where('payment_for', '!=', 6);
|
||||||
}elseif(Request::get('filter_art') === 'customer_order'){
|
} elseif (Request::get('filter_art') === 'customer_order') {
|
||||||
$query->where('shopping_orders.auth_user_id', NULL);
|
$query->where('shopping_orders.auth_user_id', null);
|
||||||
}elseif(Request::get('filter_art') === 'user_for_customer'){
|
} elseif (Request::get('filter_art') === 'user_for_customer') {
|
||||||
$query->where('shopping_user_id', '!=', NULL)->where('payment_for', '=', 6);
|
$query->where('shopping_user_id', '!=', null)->where('payment_for', '=', 6);
|
||||||
}
|
}
|
||||||
// $query->where('payment_for', '=', Request::get('filter_art'));
|
// $query->where('payment_for', '=', Request::get('filter_art'));
|
||||||
}
|
}
|
||||||
set_user_attr('filter_shipped', Request::get('filter_shipped'));
|
set_user_attr('filter_shipped', Request::get('filter_shipped'));
|
||||||
if(Request::get('filter_shipped') != ""){
|
if (Request::get('filter_shipped') != '') {
|
||||||
$query->where('shipped', '=', Request::get('filter_shipped'));
|
$query->where('shipped', '=', Request::get('filter_shipped'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return \DataTables::eloquent($query)
|
return \DataTables::eloquent($query)
|
||||||
->addColumn('id', function (ShoppingOrder $ShoppingOrder) {
|
->addColumn('id', function (ShoppingOrder $ShoppingOrder) {
|
||||||
return '<a href="' . route('admin_sales_detail', [$ShoppingOrder->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
|
return '<a href="'.route('admin_sales_detail', [$ShoppingOrder->id]).'" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
|
||||||
})
|
})
|
||||||
->addColumn('created_at', function (ShoppingOrder $ShoppingOrder) {
|
->addColumn('created_at', function (ShoppingOrder $ShoppingOrder) {
|
||||||
return $ShoppingOrder->created_at->format("d.m.Y");
|
return $ShoppingOrder->created_at->format('d.m.Y');
|
||||||
})
|
})
|
||||||
->addColumn('txaction', function (ShoppingOrder $ShoppingOrder) {
|
->addColumn('txaction', function (ShoppingOrder $ShoppingOrder) {
|
||||||
return Payment::getShoppingOrderBadge($ShoppingOrder);
|
return Payment::getShoppingOrderBadge($ShoppingOrder);
|
||||||
})
|
})
|
||||||
->addColumn('total_shipping', function (ShoppingOrder $ShoppingOrder) {
|
->addColumn('total_shipping', function (ShoppingOrder $ShoppingOrder) {
|
||||||
return $ShoppingOrder->getFormattedTotalShipping()." €";
|
return $ShoppingOrder->getFormattedTotalShipping().' €';
|
||||||
})
|
})
|
||||||
->addColumn('payment', function (ShoppingOrder $ShoppingOrder) {
|
->addColumn('payment', function (ShoppingOrder $ShoppingOrder) {
|
||||||
return $ShoppingOrder->getLastShoppingPayment('getPaymentType');
|
return $ShoppingOrder->getLastShoppingPayment('getPaymentType');
|
||||||
|
|
@ -157,10 +167,10 @@ class SalesController extends Controller
|
||||||
return $ShoppingOrder->getLastShoppingPayment('reference');
|
return $ShoppingOrder->getLastShoppingPayment('reference');
|
||||||
})
|
})
|
||||||
->addColumn('member_id', function (ShoppingOrder $ShoppingOrder) {
|
->addColumn('member_id', function (ShoppingOrder $ShoppingOrder) {
|
||||||
if($ShoppingOrder->member_id) {
|
if ($ShoppingOrder->member_id) {
|
||||||
return $ShoppingOrder->member_id ? '<a href="' . route('admin_lead_edit', [$ShoppingOrder->member_id]) . '">' . $ShoppingOrder->member->getFullName() . '</a>' : '';
|
return $ShoppingOrder->member_id ? '<a href="'.route('admin_lead_edit', [$ShoppingOrder->member_id]).'">'.$ShoppingOrder->member->getFullName().'</a>' : '';
|
||||||
}
|
}
|
||||||
if($ShoppingOrder->shopping_user && $ShoppingOrder->shopping_user->is_like){
|
if ($ShoppingOrder->shopping_user && $ShoppingOrder->shopping_user->is_like) {
|
||||||
return '<button type="button" class="btn btn-xs btn-outline-info" data-toggle="modal" data-target="#modals-load-content"
|
return '<button type="button" class="btn btn-xs btn-outline-info" data-toggle="modal" data-target="#modals-load-content"
|
||||||
data-id="'.$ShoppingOrder->shopping_user->id.'"
|
data-id="'.$ShoppingOrder->shopping_user->id.'"
|
||||||
data-action="shopping-user-is-like-member"
|
data-action="shopping-user-is-like-member"
|
||||||
|
|
@ -168,6 +178,7 @@ class SalesController extends Controller
|
||||||
data-modal="modal-xl"
|
data-modal="modal-xl"
|
||||||
data-route="'.route('modal_load').'"><span class="fa fa-edit"></span> Vertriebspartner zuordnen</button>';
|
data-route="'.route('modal_load').'"><span class="fa fa-edit"></span> Vertriebspartner zuordnen</button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -400,34 +411,35 @@ class SalesController extends Controller
|
||||||
->make(true);
|
->make(true);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public function store(){
|
public function store()
|
||||||
|
{
|
||||||
$data = Request::all();
|
$data = Request::all();
|
||||||
if(!isset($data['id'])){
|
if (! isset($data['id'])) {
|
||||||
abort(404);
|
abort(404);
|
||||||
}
|
}
|
||||||
if(isset($data['action'])){
|
if (isset($data['action'])) {
|
||||||
if($data['action'] === 'store_shipped' && isset($data['shipped'])){
|
if ($data['action'] === 'store_shipped' && isset($data['shipped'])) {
|
||||||
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
||||||
$shopping_order->shipped = $data['shipped'];
|
$shopping_order->shipped = $data['shipped'];
|
||||||
$shopping_order->save();
|
$shopping_order->save();
|
||||||
//handel Promotion Product and credit by storno
|
// handel Promotion Product and credit by storno
|
||||||
Payment::handelUserPromotionOrder($shopping_order);
|
Payment::handelUserPromotionOrder($shopping_order);
|
||||||
Payment::handelUserShopOrder($shopping_order);
|
Payment::handelUserShopOrder($shopping_order);
|
||||||
|
|
||||||
if($shopping_order->getAPIShippedType() === 'sent' || $shopping_order->getAPIShippedType() === 'close'){
|
if ($shopping_order->getAPIShippedType() === 'sent' || $shopping_order->getAPIShippedType() === 'close') {
|
||||||
if(!$shopping_order->shipped_at){
|
if (! $shopping_order->shipped_at) {
|
||||||
$shopping_order->shipped_at = now();
|
$shopping_order->shipped_at = now();
|
||||||
$shopping_order->save();
|
$shopping_order->save();
|
||||||
//is shipped set pending_to
|
// is shipped set pending_to
|
||||||
if($shopping_order->shopping_order_margin){
|
if ($shopping_order->shopping_order_margin) {
|
||||||
if($shopping_order->shopping_order_margin->hasPartnerCommission()){
|
if ($shopping_order->shopping_order_margin->hasPartnerCommission()) {
|
||||||
$days = Setting::getContentBySlug('pending_partner_commissions_in_days');
|
$days = Setting::getContentBySlug('pending_partner_commissions_in_days');
|
||||||
$days = $days ? $days : 20;
|
$days = $days ? $days : 20;
|
||||||
$partner_commission_pending_to = $shopping_order->shipped_at;
|
$partner_commission_pending_to = $shopping_order->shipped_at;
|
||||||
$partner_commission_pending_to->addDays($days);
|
$partner_commission_pending_to->addDays($days);
|
||||||
$shopping_order->shopping_order_margin->partner_commission_pending_to = $partner_commission_pending_to;
|
$shopping_order->shopping_order_margin->partner_commission_pending_to = $partner_commission_pending_to;
|
||||||
$shopping_order->shopping_order_margin->save();
|
$shopping_order->shopping_order_margin->save();
|
||||||
}else{
|
} else {
|
||||||
$days = Setting::getContentBySlug('pending_order_margins_in_days');
|
$days = Setting::getContentBySlug('pending_order_margins_in_days');
|
||||||
$days = $days ? $days : 20;
|
$days = $days ? $days : 20;
|
||||||
$margin_pending_to = $shopping_order->shipped_at;
|
$margin_pending_to = $shopping_order->shipped_at;
|
||||||
|
|
@ -437,25 +449,25 @@ class SalesController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
$shopping_order->shipped_at = null;
|
$shopping_order->shipped_at = null;
|
||||||
$shopping_order->save();
|
$shopping_order->save();
|
||||||
if($shopping_order->shopping_order_margin){
|
if ($shopping_order->shopping_order_margin) {
|
||||||
//zurücksetzen der pending_to
|
// zurücksetzen der pending_to
|
||||||
$shopping_order->shopping_order_margin->partner_commission_pending_to = null;
|
$shopping_order->shopping_order_margin->partner_commission_pending_to = null;
|
||||||
$shopping_order->shopping_order_margin->margin_pending_to = null;
|
$shopping_order->shopping_order_margin->margin_pending_to = null;
|
||||||
$shopping_order->shopping_order_margin->save();
|
$shopping_order->shopping_order_margin->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($shopping_order->getAPIShippedType() === 'cancel'){
|
if ($shopping_order->getAPIShippedType() === 'cancel') {
|
||||||
if($shopping_order->shopping_order_margin){
|
if ($shopping_order->shopping_order_margin) {
|
||||||
$shopping_order->shopping_order_margin->cancellation = true;
|
$shopping_order->shopping_order_margin->cancellation = true;
|
||||||
$shopping_order->shopping_order_margin->partner_commission_pending_to = null;
|
$shopping_order->shopping_order_margin->partner_commission_pending_to = null;
|
||||||
$shopping_order->shopping_order_margin->margin_pending_to = null;
|
$shopping_order->shopping_order_margin->margin_pending_to = null;
|
||||||
$shopping_order->shopping_order_margin->save();
|
$shopping_order->shopping_order_margin->save();
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
if($shopping_order->shopping_order_margin && $shopping_order->shopping_order_margin->cancellation){
|
if ($shopping_order->shopping_order_margin && $shopping_order->shopping_order_margin->cancellation) {
|
||||||
$shopping_order->shopping_order_margin->cancellation = false;
|
$shopping_order->shopping_order_margin->cancellation = false;
|
||||||
$shopping_order->shopping_order_margin->partner_commission_pending_to = null;
|
$shopping_order->shopping_order_margin->partner_commission_pending_to = null;
|
||||||
$shopping_order->shopping_order_margin->margin_pending_to = null;
|
$shopping_order->shopping_order_margin->margin_pending_to = null;
|
||||||
|
|
@ -463,53 +475,94 @@ class SalesController extends Controller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* txaction ändern
|
/* txaction ändern
|
||||||
änderung der txaction von der Bestellung, Status Zahlung, offen, bezahlt, keine zahlung */
|
änderung der txaction von der Bestellung, Status Zahlung, offen, bezahlt, keine zahlung */
|
||||||
if($data['action'] === 'store_txaction' && isset($data['txaction']) && isset($data['payment_id'])){
|
if ($data['action'] === 'store_txaction' && isset($data['txaction']) && isset($data['payment_id'])) {
|
||||||
PaymentService::updateTransactionStatus($data['id'], $data['txaction'], $data['payment_id']);
|
PaymentService::updateTransactionStatus($data['id'], $data['txaction'], $data['payment_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if(isset($data['back'])){
|
if (isset($data['back'])) {
|
||||||
return redirect($data['back']);
|
return redirect($data['back']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return back();
|
return back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function invoice()
|
||||||
public function invoice(){
|
{
|
||||||
$data = Request::all();
|
$data = Request::all();
|
||||||
if(!isset($data['id'])){
|
if (! isset($data['id'])) {
|
||||||
abort(404);
|
abort(404);
|
||||||
}
|
}
|
||||||
if(isset($data['action'])){
|
if (isset($data['action'])) {
|
||||||
if($data['action'] === 'create_invoice'){
|
if ($data['action'] === 'create_invoice') {
|
||||||
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
||||||
$invoice_repo = new InvoiceRepository($shopping_order);
|
$invoice_repo = new InvoiceRepository($shopping_order);
|
||||||
if(\App\Services\Invoice::isInvoice($shopping_order)){
|
if (Invoice::isInvoice($shopping_order)) {
|
||||||
$user_invoice = $invoice_repo->update($data);
|
$user_invoice = $invoice_repo->update($data);
|
||||||
}else{
|
} else {
|
||||||
$user_invoice = $invoice_repo->create($data);
|
$user_invoice = $invoice_repo->create($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendLogisticMail($id){
|
public function invoiceCancellation()
|
||||||
|
{
|
||||||
|
$data = Request::all();
|
||||||
|
if (! isset($data['id'])) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
if (isset($data['action'])) {
|
||||||
|
if ($data['action'] === 'create_cancellation_invoice') {
|
||||||
|
$shopping_order = ShoppingOrder::findOrFail($data['id']);
|
||||||
|
|
||||||
|
// Prüfen ob bereits eine Rechnung existiert
|
||||||
|
if (! Invoice::isInvoice($shopping_order)) {
|
||||||
|
\Session()->flash('alert-error', 'Es existiert keine Rechnung, die storniert werden kann.');
|
||||||
|
|
||||||
|
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüfen ob bereits eine Stornorechnung existiert
|
||||||
|
if (Invoice::isCancellationInvoice($shopping_order)) {
|
||||||
|
\Session()->flash('alert-error', 'Es existiert bereits eine Stornorechnung für diese Bestellung.');
|
||||||
|
|
||||||
|
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoice_repo = new InvoiceRepository($shopping_order);
|
||||||
|
$cancellation_invoice = $invoice_repo->createCancellation($data);
|
||||||
|
|
||||||
|
if ($cancellation_invoice) {
|
||||||
|
\Session()->flash('alert-success', 'Stornorechnung wurde erfolgreich erstellt.');
|
||||||
|
} else {
|
||||||
|
\Session()->flash('alert-error', 'Fehler beim Erstellen der Stornorechnung.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect(route('admin_sales'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendLogisticMail($id)
|
||||||
|
{
|
||||||
$shopping_order = ShoppingOrder::findOrFail($id);
|
$shopping_order = ShoppingOrder::findOrFail($id);
|
||||||
|
|
||||||
if(\App\Services\Invoice::isInvoice($shopping_order)){
|
if (Invoice::isInvoice($shopping_order)) {
|
||||||
\App\Services\Invoice::sendLogisticMail($shopping_order);
|
Invoice::sendLogisticMail($shopping_order);
|
||||||
\Session()->flash('alert-success', "Rechnung / Lieferschein wurde an den Versand gesendet.");
|
\Session()->flash('alert-success', 'Rechnung / Lieferschein wurde an den Versand gesendet.');
|
||||||
}else{
|
} else {
|
||||||
\Session()->flash('alert-error', "Keine Rechnung vorhanden.");
|
\Session()->flash('alert-error', 'Keine Rechnung vorhanden.');
|
||||||
}
|
|
||||||
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return redirect(route('admin_sales_detail', [$shopping_order->id]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
34
app/Http/Requests/Inventory/ReceiveStockEntryRequest.php
Normal file
34
app/Http/Requests/Inventory/ReceiveStockEntryRequest.php
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ReceiveStockEntryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'received_at' => ['required', 'date'],
|
||||||
|
'received_quantity' => ['required', 'numeric', 'min:0.000001'],
|
||||||
|
'batch_number' => ['nullable', 'string', 'max:100'],
|
||||||
|
'best_before' => ['nullable', 'date'],
|
||||||
|
'quality_id' => ['nullable', 'integer', 'exists:material_qualities,id'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'received_quantity' => reFormatNumber($this->input('received_quantity')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Requests/Inventory/StoreLocationRequest.php
Normal file
31
app/Http/Requests/Inventory/StoreLocationRequest.php
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreLocationRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'active' => ['sometimes', 'boolean'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'active' => $this->boolean('active'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Requests/Inventory/StoreMaterialQualityRequest.php
Normal file
31
app/Http/Requests/Inventory/StoreMaterialQualityRequest.php
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreMaterialQualityRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'pos' => ['nullable', 'integer', 'min:0', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
if ($this->has('pos') && $this->input('pos') === '') {
|
||||||
|
$this->merge(['pos' => 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
app/Http/Requests/Inventory/StorePackagingItemRequest.php
Normal file
45
app/Http/Requests/Inventory/StorePackagingItemRequest.php
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class StorePackagingItemRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'packaging_material_id' => ['required', 'integer', 'exists:packaging_materials,id'],
|
||||||
|
'supplier_id' => ['nullable', 'integer', 'exists:suppliers,id'],
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'category' => ['required', Rule::in(['packaging', 'shipping', 'label', 'shipping_office'])],
|
||||||
|
'weight_grams' => ['nullable', 'numeric', 'min:0'],
|
||||||
|
'min_stock_alert' => ['nullable', 'integer', 'min:0'],
|
||||||
|
'url' => ['nullable', 'url', 'max:500'],
|
||||||
|
'product_id' => ['nullable', 'integer', 'exists:products,id'],
|
||||||
|
'active' => ['sometimes', 'boolean'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'active' => $this->boolean('active'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach (['supplier_id', 'product_id', 'min_stock_alert'] as $key) {
|
||||||
|
if ($this->input($key) === '' || $this->input($key) === null) {
|
||||||
|
$this->merge([$key => null]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StorePackagingMaterialRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'pos' => ['nullable', 'integer', 'min:0', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
if ($this->has('pos') && $this->input('pos') === '') {
|
||||||
|
$this->merge(['pos' => 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
app/Http/Requests/Inventory/StoreProductionRequest.php
Normal file
54
app/Http/Requests/Inventory/StoreProductionRequest.php
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreProductionRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed|string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'product_id' => ['required', 'integer', 'exists:products,id'],
|
||||||
|
'location_id' => ['required', 'integer', 'exists:locations,id'],
|
||||||
|
'produced_at' => ['required', 'date'],
|
||||||
|
'quantity' => ['required', 'integer', 'min:1'],
|
||||||
|
'notes' => ['nullable', 'string', 'max:2000'],
|
||||||
|
'ingredient_lines' => ['required', 'array', 'min:1'],
|
||||||
|
'ingredient_lines.*.ingredient_id' => ['required', 'integer', 'exists:ingredients,id'],
|
||||||
|
'ingredient_lines.*.stock_entry_id' => ['required', 'integer', 'exists:stock_entries,id'],
|
||||||
|
'ingredient_lines.*.quantity_used' => ['required', 'string'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function validatedPayload(): array
|
||||||
|
{
|
||||||
|
$data = $this->validated();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'product_id' => (int) $data['product_id'],
|
||||||
|
'location_id' => (int) $data['location_id'],
|
||||||
|
'produced_at' => $data['produced_at'],
|
||||||
|
'quantity' => (int) $data['quantity'],
|
||||||
|
'notes' => $data['notes'] ?? null,
|
||||||
|
'ingredient_lines' => array_map(function (array $line): array {
|
||||||
|
return [
|
||||||
|
'ingredient_id' => (int) $line['ingredient_id'],
|
||||||
|
'stock_entry_id' => (int) $line['stock_entry_id'],
|
||||||
|
'quantity_used' => $line['quantity_used'],
|
||||||
|
];
|
||||||
|
}, $data['ingredient_lines']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
73
app/Http/Requests/Inventory/StoreStockEntryRequest.php
Normal file
73
app/Http/Requests/Inventory/StoreStockEntryRequest.php
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
|
class StoreStockEntryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'entry_type' => ['required', Rule::in(['ingredient', 'packaging', 'label', 'shipping_office'])],
|
||||||
|
'ingredient_id' => ['nullable', 'integer', 'exists:ingredients,id'],
|
||||||
|
'packaging_item_id' => ['nullable', 'integer', 'exists:packaging_items,id'],
|
||||||
|
'supplier_id' => ['required', 'integer', 'exists:suppliers,id'],
|
||||||
|
'location_id' => ['required', 'integer', 'exists:locations,id'],
|
||||||
|
'ordered_at' => ['required', 'date'],
|
||||||
|
'ordered_quantity' => ['required', 'numeric', 'min:0.000001'],
|
||||||
|
'price_per_kg' => ['nullable', 'numeric', 'min:0'],
|
||||||
|
'price_total' => ['nullable', 'numeric', 'min:0'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'ordered_quantity' => reFormatNumber($this->input('ordered_quantity')),
|
||||||
|
'price_per_kg' => $this->filled('price_per_kg') ? reFormatNumber($this->input('price_per_kg')) : null,
|
||||||
|
'price_total' => $this->filled('price_total') ? reFormatNumber($this->input('price_total')) : null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(function (Validator $validator): void {
|
||||||
|
$type = $this->input('entry_type');
|
||||||
|
if ($type === 'ingredient') {
|
||||||
|
if (empty($this->input('ingredient_id'))) {
|
||||||
|
$validator->errors()->add('ingredient_id', __('Bitte einen Inhaltsstoff wählen.'));
|
||||||
|
}
|
||||||
|
} elseif (! empty($type)) {
|
||||||
|
if (empty($this->input('packaging_item_id'))) {
|
||||||
|
$validator->errors()->add('packaging_item_id', __('Bitte einen Verpackungsartikel wählen.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function validatedPayload(): array
|
||||||
|
{
|
||||||
|
$data = $this->validated();
|
||||||
|
if (($data['entry_type'] ?? '') === 'ingredient') {
|
||||||
|
$data['packaging_item_id'] = null;
|
||||||
|
} else {
|
||||||
|
$data['ingredient_id'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Requests/Inventory/StoreSupplierCategoryRequest.php
Normal file
31
app/Http/Requests/Inventory/StoreSupplierCategoryRequest.php
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreSupplierCategoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'pos' => ['nullable', 'integer', 'min:0', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
if ($this->has('pos') && $this->input('pos') === '') {
|
||||||
|
$this->merge(['pos' => 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
app/Http/Requests/Inventory/StoreSupplierRequest.php
Normal file
39
app/Http/Requests/Inventory/StoreSupplierRequest.php
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreSupplierRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'url' => ['nullable', 'string', 'max:2048'],
|
||||||
|
'contact_person' => ['nullable', 'string', 'max:255'],
|
||||||
|
'email' => ['nullable', 'email', 'max:255'],
|
||||||
|
'phone' => ['nullable', 'string', 'max:100'],
|
||||||
|
'country_id' => ['required', 'integer', 'exists:countries,id'],
|
||||||
|
'notes' => ['nullable', 'string'],
|
||||||
|
'active' => ['sometimes', 'boolean'],
|
||||||
|
'supplier_category_ids' => ['nullable', 'array'],
|
||||||
|
'supplier_category_ids.*' => ['integer', 'exists:supplier_categories,id'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'active' => $this->boolean('active'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Requests/Inventory/UpdateLocationRequest.php
Normal file
31
app/Http/Requests/Inventory/UpdateLocationRequest.php
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateLocationRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'active' => ['sometimes', 'boolean'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'active' => $this->boolean('active'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Http/Requests/Inventory/UpdateMaterialQualityRequest.php
Normal file
31
app/Http/Requests/Inventory/UpdateMaterialQualityRequest.php
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateMaterialQualityRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'pos' => ['nullable', 'integer', 'min:0', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
if ($this->has('pos') && $this->input('pos') === '') {
|
||||||
|
$this->merge(['pos' => 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
app/Http/Requests/Inventory/UpdatePackagingItemRequest.php
Normal file
45
app/Http/Requests/Inventory/UpdatePackagingItemRequest.php
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class UpdatePackagingItemRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'packaging_material_id' => ['required', 'integer', 'exists:packaging_materials,id'],
|
||||||
|
'supplier_id' => ['nullable', 'integer', 'exists:suppliers,id'],
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'category' => ['required', Rule::in(['packaging', 'shipping', 'label', 'shipping_office'])],
|
||||||
|
'weight_grams' => ['nullable', 'numeric', 'min:0'],
|
||||||
|
'min_stock_alert' => ['nullable', 'integer', 'min:0'],
|
||||||
|
'url' => ['nullable', 'url', 'max:500'],
|
||||||
|
'product_id' => ['nullable', 'integer', 'exists:products,id'],
|
||||||
|
'active' => ['sometimes', 'boolean'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'active' => $this->boolean('active'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach (['supplier_id', 'product_id', 'min_stock_alert'] as $key) {
|
||||||
|
if ($this->input($key) === '' || $this->input($key) === null) {
|
||||||
|
$this->merge([$key => null]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdatePackagingMaterialRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'pos' => ['nullable', 'integer', 'min:0', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
if ($this->has('pos') && $this->input('pos') === '') {
|
||||||
|
$this->merge(['pos' => 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
app/Http/Requests/Inventory/UpdateStockEntryRequest.php
Normal file
73
app/Http/Requests/Inventory/UpdateStockEntryRequest.php
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
|
class UpdateStockEntryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'entry_type' => ['required', Rule::in(['ingredient', 'packaging', 'label', 'shipping_office'])],
|
||||||
|
'ingredient_id' => ['nullable', 'integer', 'exists:ingredients,id'],
|
||||||
|
'packaging_item_id' => ['nullable', 'integer', 'exists:packaging_items,id'],
|
||||||
|
'supplier_id' => ['required', 'integer', 'exists:suppliers,id'],
|
||||||
|
'location_id' => ['required', 'integer', 'exists:locations,id'],
|
||||||
|
'ordered_at' => ['required', 'date'],
|
||||||
|
'ordered_quantity' => ['required', 'numeric', 'min:0.000001'],
|
||||||
|
'price_per_kg' => ['nullable', 'numeric', 'min:0'],
|
||||||
|
'price_total' => ['nullable', 'numeric', 'min:0'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'ordered_quantity' => reFormatNumber($this->input('ordered_quantity')),
|
||||||
|
'price_per_kg' => $this->filled('price_per_kg') ? reFormatNumber($this->input('price_per_kg')) : null,
|
||||||
|
'price_total' => $this->filled('price_total') ? reFormatNumber($this->input('price_total')) : null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(function (Validator $validator): void {
|
||||||
|
$type = $this->input('entry_type');
|
||||||
|
if ($type === 'ingredient') {
|
||||||
|
if (empty($this->input('ingredient_id'))) {
|
||||||
|
$validator->errors()->add('ingredient_id', __('Bitte einen Inhaltsstoff wählen.'));
|
||||||
|
}
|
||||||
|
} elseif (! empty($type)) {
|
||||||
|
if (empty($this->input('packaging_item_id'))) {
|
||||||
|
$validator->errors()->add('packaging_item_id', __('Bitte einen Verpackungsartikel wählen.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function validatedPayload(): array
|
||||||
|
{
|
||||||
|
$data = $this->validated();
|
||||||
|
if (($data['entry_type'] ?? '') === 'ingredient') {
|
||||||
|
$data['packaging_item_id'] = null;
|
||||||
|
} else {
|
||||||
|
$data['ingredient_id'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateSupplierCategoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, string>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'pos' => ['nullable', 'integer', 'min:0', 'max:255'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
if ($this->has('pos') && $this->input('pos') === '') {
|
||||||
|
$this->merge(['pos' => 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
app/Http/Requests/Inventory/UpdateSupplierRequest.php
Normal file
39
app/Http/Requests/Inventory/UpdateSupplierRequest.php
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Inventory;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateSupplierRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, array<int, mixed>>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'url' => ['nullable', 'string', 'max:2048'],
|
||||||
|
'contact_person' => ['nullable', 'string', 'max:255'],
|
||||||
|
'email' => ['nullable', 'email', 'max:255'],
|
||||||
|
'phone' => ['nullable', 'string', 'max:100'],
|
||||||
|
'country_id' => ['required', 'integer', 'exists:countries,id'],
|
||||||
|
'notes' => ['nullable', 'string'],
|
||||||
|
'active' => ['sometimes', 'boolean'],
|
||||||
|
'supplier_category_ids' => ['nullable', 'array'],
|
||||||
|
'supplier_category_ids.*' => ['integer', 'exists:supplier_categories,id'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
$this->merge([
|
||||||
|
'active' => $this->boolean('active'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Mail;
|
namespace App\Mail;
|
||||||
|
|
||||||
use App\User;
|
|
||||||
use App\Services\Invoice;
|
|
||||||
use App\Models\ShoppingOrder;
|
use App\Models\ShoppingOrder;
|
||||||
|
use App\Services\Invoice;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Mail\Mailable;
|
use Illuminate\Mail\Mailable;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Storage;
|
use Storage;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
|
|
||||||
class MailLogistic extends Mailable
|
class MailLogistic extends Mailable
|
||||||
{
|
{
|
||||||
|
|
@ -18,29 +17,30 @@ class MailLogistic extends Mailable
|
||||||
|
|
||||||
public $subject;
|
public $subject;
|
||||||
|
|
||||||
|
|
||||||
public function __construct(ShoppingOrder $shopping_order)
|
public function __construct(ShoppingOrder $shopping_order)
|
||||||
{
|
{
|
||||||
$this->shopping_order = $shopping_order;
|
$this->shopping_order = $shopping_order;
|
||||||
$name = $shopping_order->shopping_user->billing_firstname . ' ' . $shopping_order->shopping_user->billing_lastname;
|
$name = $shopping_order->shopping_user->billing_firstname.' '.$shopping_order->shopping_user->billing_lastname;
|
||||||
$company = $shopping_order->shopping_user->billing_company ?? '';
|
$company = $shopping_order->shopping_user->billing_company ?? '';
|
||||||
|
|
||||||
|
$hasWhiteLabel = $shopping_order->user_white_label || $shopping_order->hasWhitelabelProducts();
|
||||||
|
|
||||||
$this->subject = 'Partner';
|
$this->subject = 'Partner';
|
||||||
if($shopping_order->user_white_label){
|
if ($hasWhiteLabel) {
|
||||||
//Bei allen, die ein eigenes Logo haben
|
// Bei allen, die ein eigenes Logo haben
|
||||||
$this->subject .= ' (mit Logo)';
|
$this->subject .= ' (mit Logo)';
|
||||||
}else{
|
} else {
|
||||||
//Bei allen, die kein Tattoostudio sind
|
// Bei allen, die kein Tattoostudio sind
|
||||||
$this->subject = ' - ';
|
$this->subject = ' - ';
|
||||||
}
|
}
|
||||||
if($shopping_order->shopping_user->same_as_billing){
|
if ($shopping_order->shopping_user->same_as_billing) {
|
||||||
//Rechnungsadresse und Lieferadresse sind gleich
|
// Rechnungsadresse und Lieferadresse sind gleich
|
||||||
$this->subject = '';
|
$this->subject = '';
|
||||||
}else{
|
} else {
|
||||||
//hat eine andere Lieferadresse
|
// hat eine andere Lieferadresse
|
||||||
$this->subject = ' Lieferadresse';
|
$this->subject = ' Lieferadresse';
|
||||||
}
|
}
|
||||||
$this->subject .= ' '.$company.' (' . $name . ')';
|
$this->subject .= ' '.$company.' ('.$name.')';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,32 +51,32 @@ class MailLogistic extends Mailable
|
||||||
|
|
||||||
$filename = Invoice::getFilename($this->shopping_order);
|
$filename = Invoice::getFilename($this->shopping_order);
|
||||||
$path = Invoice::getDownloadPath($this->shopping_order);
|
$path = Invoice::getDownloadPath($this->shopping_order);
|
||||||
if (!Storage::disk('public')->exists($path)) {
|
if (! Storage::disk('public')->exists($path)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$file = Storage::disk('public')->path($path);
|
$file = Storage::disk('public')->path($path);
|
||||||
$mime = Storage::disk('public')->mimeType($path);
|
$mime = Storage::disk('public')->mimeType($path);
|
||||||
|
|
||||||
|
|
||||||
$mail = $this->view('emails.logistic')->with([
|
$mail = $this->view('emails.logistic')->with([
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'copy1line' => $copy1line,
|
'copy1line' => $copy1line,
|
||||||
])->attach($file,[
|
])->attach($file, [
|
||||||
'as' => $filename,
|
'as' => $filename,
|
||||||
'mime' => $mime,
|
'mime' => $mime,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
//Wenn das Logo gesetzt ist und die Rechnungsadresse und Lieferadresse unterschiedlich sind, dann wird der Lieferschein angehängt
|
// Wenn mindestens ein White-Label-Produkt enthalten ist, wird der Lieferschein (Etikett-Infos) mit angehängt
|
||||||
if($this->shopping_order->user_white_label && !$this->shopping_order->shopping_user->same_as_billing){
|
$hasWhiteLabel = $this->shopping_order->user_white_label || $this->shopping_order->hasWhitelabelProducts();
|
||||||
|
if ($hasWhiteLabel) {
|
||||||
$filenameDelivery = Invoice::getDeliveryFilename($this->shopping_order);
|
$filenameDelivery = Invoice::getDeliveryFilename($this->shopping_order);
|
||||||
$pathDelivery = Invoice::getDownloadPathDelivery($this->shopping_order);
|
$pathDelivery = Invoice::getDownloadPathDelivery($this->shopping_order);
|
||||||
if (!Storage::disk('public')->exists($pathDelivery)) {
|
if (! Storage::disk('public')->exists($pathDelivery)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$fileDelivery = Storage::disk('public')->path($pathDelivery);
|
$fileDelivery = Storage::disk('public')->path($pathDelivery);
|
||||||
$mimeDelivery = Storage::disk('public')->mimeType($pathDelivery);
|
$mimeDelivery = Storage::disk('public')->mimeType($pathDelivery);
|
||||||
|
|
||||||
$mail->attach($fileDelivery,[
|
$mail->attach($fileDelivery, [
|
||||||
'as' => $filenameDelivery,
|
'as' => $filenameDelivery,
|
||||||
'mime' => $mimeDelivery,
|
'mime' => $mimeDelivery,
|
||||||
]); // attach file;
|
]); // attach file;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ namespace App\Models;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Ingredient
|
* Class Ingredient
|
||||||
|
|
@ -25,10 +26,10 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @property Carbon $created_at
|
* @property Carbon $created_at
|
||||||
* @property Carbon $updated_at
|
* @property Carbon $updated_at
|
||||||
* @property Collection|Product[] $products
|
* @property Collection|Product[] $products
|
||||||
* @package App\Models
|
* @property-read Collection|ProductIngredient[] $product_ingredients
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductIngredient[] $product_ingredients
|
|
||||||
* @property-read int|null $product_ingredients_count
|
* @property-read int|null $product_ingredients_count
|
||||||
* @property-read int|null $products_count
|
* @property-read int|null $products_count
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient query()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient query()
|
||||||
|
|
@ -43,6 +44,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient whereTransInci($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient whereTransInci($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient whereTransName($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient whereTransName($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Ingredient whereUpdatedAt($value)
|
||||||
|
*
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class Ingredient extends Model
|
class Ingredient extends Model
|
||||||
|
|
@ -51,7 +53,9 @@ class Ingredient extends Model
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'active' => 'bool',
|
'active' => 'bool',
|
||||||
'pos' => 'int'
|
'pos' => 'int',
|
||||||
|
'default_factor' => 'decimal:2',
|
||||||
|
'min_stock_alert' => 'decimal:2',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|
@ -62,19 +66,30 @@ class Ingredient extends Model
|
||||||
'effect',
|
'effect',
|
||||||
'trans_effect',
|
'trans_effect',
|
||||||
'active',
|
'active',
|
||||||
'pos'
|
'pos',
|
||||||
|
'default_factor',
|
||||||
|
'min_stock_alert',
|
||||||
|
'material_quality_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<MaterialQuality, $this>
|
||||||
|
*/
|
||||||
|
public function materialQuality(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MaterialQuality::class);
|
||||||
|
}
|
||||||
|
|
||||||
public function products()
|
public function products()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Product::class, 'product_ingredients')
|
return $this->belongsToMany(Product::class, 'product_ingredients')
|
||||||
->withPivot('id')
|
->withPivot('id', 'pos', 'gram', 'factor')
|
||||||
->withTimestamps();
|
->withTimestamps()
|
||||||
|
->orderByPivot('pos');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function product_ingredients()
|
public function product_ingredients()
|
||||||
{
|
{
|
||||||
return $this->hasMany(ProductIngredient::class, 'product_ingredients', 'id');
|
return $this->hasMany(ProductIngredient::class, 'ingredient_id');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
app/Models/Location.php
Normal file
28
app/Models/Location.php
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Database\Factories\LocationFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Location extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<LocationFactory> */
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'active',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'active' => 'boolean',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
18
app/Models/MaterialQuality.php
Normal file
18
app/Models/MaterialQuality.php
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Database\Factories\MaterialQualityFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class MaterialQuality extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<MaterialQualityFactory> */
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'pos',
|
||||||
|
];
|
||||||
|
}
|
||||||
75
app/Models/PackagingItem.php
Normal file
75
app/Models/PackagingItem.php
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Database\Factories\PackagingItemFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class PackagingItem extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<PackagingItemFactory> */
|
||||||
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'packaging_material_id',
|
||||||
|
'supplier_id',
|
||||||
|
'name',
|
||||||
|
'category',
|
||||||
|
'weight_grams',
|
||||||
|
'min_stock_alert',
|
||||||
|
'url',
|
||||||
|
'product_id',
|
||||||
|
'active',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'active' => 'boolean',
|
||||||
|
'weight_grams' => 'decimal:2',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<PackagingMaterial, $this>
|
||||||
|
*/
|
||||||
|
public function packagingMaterial(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(PackagingMaterial::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Supplier, $this>
|
||||||
|
*/
|
||||||
|
public function supplier(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Supplier::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Product, $this>
|
||||||
|
*/
|
||||||
|
public function product(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Product::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produkte, die diesen Verpackungsartikel in der Stückliste führen (BOM).
|
||||||
|
*
|
||||||
|
* @return BelongsToMany<Product, $this>
|
||||||
|
*/
|
||||||
|
public function products(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Product::class, 'product_packagings')
|
||||||
|
->withPivot('quantity', 'pos')
|
||||||
|
->withTimestamps();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
app/Models/PackagingMaterial.php
Normal file
27
app/Models/PackagingMaterial.php
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Database\Factories\PackagingMaterialFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
class PackagingMaterial extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<PackagingMaterialFactory> */
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'pos',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return HasMany<PackagingItem, $this>
|
||||||
|
*/
|
||||||
|
public function packagingItems(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(PackagingItem::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,8 +20,24 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @property bool $active
|
* @property bool $active
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
|
* @property string|null $subject
|
||||||
|
* @property string|null $clearingtype
|
||||||
*
|
*
|
||||||
* @package App\Models
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereAction($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereActive($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereClearingtype($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereInterval($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereMessage($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereSubject($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereTitle($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PaymentReminder whereUpdatedAt($value)
|
||||||
|
*
|
||||||
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class PaymentReminder extends Model
|
class PaymentReminder extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -29,7 +45,7 @@ class PaymentReminder extends Model
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'interval' => 'int',
|
'interval' => 'int',
|
||||||
'active' => 'bool'
|
'active' => 'bool',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|
@ -39,7 +55,7 @@ class PaymentReminder extends Model
|
||||||
'message',
|
'message',
|
||||||
'action',
|
'action',
|
||||||
'clearingtype',
|
'clearingtype',
|
||||||
'active'
|
'active',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static $clearingtypes = [
|
protected static $clearingtypes = [
|
||||||
|
|
@ -47,11 +63,13 @@ class PaymentReminder extends Model
|
||||||
'vor' => 'Vorkasse',
|
'vor' => 'Vorkasse',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function getClearingtype(){
|
public function getClearingtype()
|
||||||
|
{
|
||||||
return isset(self::$clearingtypes[$this->clearingtype]) ? self::$clearingtypes[$this->clearingtype] : 'Kein Typ';
|
return isset(self::$clearingtypes[$this->clearingtype]) ? self::$clearingtypes[$this->clearingtype] : 'Kein Typ';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function returnClearingtypes(){
|
public static function returnClearingtypes()
|
||||||
|
{
|
||||||
return self::$clearingtypes;
|
return self::$clearingtypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,12 @@ namespace App\Models;
|
||||||
use App\Services\Type;
|
use App\Services\Type;
|
||||||
use App\Services\Util;
|
use App\Services\Util;
|
||||||
use Cviebrock\EloquentSluggable\Sluggable;
|
use Cviebrock\EloquentSluggable\Sluggable;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App\Models\Product
|
* App\Models\Product
|
||||||
|
|
@ -34,13 +38,14 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
* @property int|null $pos
|
* @property int|null $pos
|
||||||
* @property int $active
|
* @property int $active
|
||||||
* @property int|null $amount
|
* @property int|null $amount
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductAttribute[] $attributes
|
* @property-read Collection|ProductAttribute[] $attributes
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductCategory[] $categories
|
* @property-read Collection|ProductCategory[] $categories
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductImage[] $images
|
* @property-read Collection|ProductImage[] $images
|
||||||
* @property-write mixed $price_vk
|
* @property-write mixed $price_vk
|
||||||
|
*
|
||||||
* @method static bool|null forceDelete()
|
* @method static bool|null forceDelete()
|
||||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\Product onlyTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Product onlyTrashed()
|
||||||
* @method static bool|null restore()
|
* @method static bool|null restore()
|
||||||
|
|
@ -72,78 +77,102 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereUsage($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereUsage($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\Product withTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Product withTrashed()
|
||||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\Product withoutTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\Product withoutTrashed()
|
||||||
|
*
|
||||||
* @property string|null $slug
|
* @property string|null $slug
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product findSimilarSlugs($attribute, $config, $slug)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product findSimilarSlugs($attribute, $config, $slug)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereSlug($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereSlug($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product query()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product query()
|
||||||
|
*
|
||||||
* @property int|null $weight
|
* @property int|null $weight
|
||||||
* @property int|null $show_at
|
* @property int|null $show_at
|
||||||
* @property array|null $action
|
* @property array|null $action
|
||||||
* @property-read int|null $attributes_count
|
* @property-read int|null $attributes_count
|
||||||
* @property-read int|null $categories_count
|
* @property-read int|null $categories_count
|
||||||
* @property-read int|null $images_count
|
* @property-read int|null $images_count
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereAction($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereAction($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereShowAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereShowAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereWeight($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereWeight($value)
|
||||||
|
*
|
||||||
* @property int|null $points
|
* @property int|null $points
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductImage[] $imagesActive
|
* @property-read Collection|ProductImage[] $imagesActive
|
||||||
* @property-read int|null $images_active_count
|
* @property-read int|null $images_active_count
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product wherePoints($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product wherePoints($value)
|
||||||
|
*
|
||||||
* @property string|null $identifier
|
* @property string|null $identifier
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereIdentifier($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereIdentifier($value)
|
||||||
|
*
|
||||||
* @property int|null $upgrade_to_id
|
* @property int|null $upgrade_to_id
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereUpgradeToId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereUpgradeToId($value)
|
||||||
|
*
|
||||||
* @property int|null $contents_total
|
* @property int|null $contents_total
|
||||||
* @property int|null $unit
|
* @property int|null $unit
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereContentsTotal($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereContentsTotal($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereUnit($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereUnit($value)
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\CountryPrice[] $country_prices
|
*
|
||||||
|
* @property-read Collection|CountryPrice[] $country_prices
|
||||||
* @property-read int|null $country_prices_count
|
* @property-read int|null $country_prices_count
|
||||||
* @property int|null $wp_number
|
* @property int|null $wp_number
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereWpNumber($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereWpNumber($value)
|
||||||
|
*
|
||||||
* @property bool|null $single_commission
|
* @property bool|null $single_commission
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereShippingAddon($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Product whereShippingAddon($value)
|
||||||
|
*
|
||||||
* @property-read int|null $ingredients_count
|
* @property-read int|null $ingredients_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductIngredient[] $product_ingredients
|
* @property-read Collection|ProductIngredient[] $product_ingredients
|
||||||
* @property-read int|null $product_ingredients_count
|
* @property-read int|null $product_ingredients_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Ingredient[] $p_ingredients
|
* @property-read Collection|Ingredient[] $p_ingredients
|
||||||
* @property-read int|null $p_ingredients_count
|
* @property-read int|null $p_ingredients_count
|
||||||
* @property bool $amount_commission
|
* @property bool $amount_commission
|
||||||
* @property string|null $value_commission
|
* @property string|null $value_commission
|
||||||
* @property string|null $partner_commission
|
* @property string|null $partner_commission
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereAmountCommission($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereAmountCommission($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product wherePartnerCommission($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product wherePartnerCommission($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereSingleCommission($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereSingleCommission($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereValueCommission($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereValueCommission($value)
|
||||||
|
*
|
||||||
* @property bool|null $shipping_addon
|
* @property bool|null $shipping_addon
|
||||||
* @property bool|null $max_buy
|
* @property bool|null $max_buy
|
||||||
* @property int|null $max_buy_num
|
* @property int|null $max_buy_num
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ProductBuy[] $product_buys
|
* @property-read Collection|ProductBuy[] $product_buys
|
||||||
* @property-read int|null $product_buys_count
|
* @property-read int|null $product_buys_count
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereMaxBuy($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereMaxBuy($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereMaxBuyNum($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereMaxBuyNum($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product withUniqueSlugConstraints(\Illuminate\Database\Eloquent\Model $model, string $attribute, array $config, string $slug)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product withUniqueSlugConstraints(\Illuminate\Database\Eloquent\Model $model, string $attribute, array $config, string $slug)
|
||||||
|
*
|
||||||
* @property string|null $short_copy
|
* @property string|null $short_copy
|
||||||
* @property array|null $show_on
|
* @property array|null $show_on
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereShortCopy($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereShortCopy($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereShowOn($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereShowOn($value)
|
||||||
|
*
|
||||||
* @property bool $exclude_stats_sales
|
* @property bool $exclude_stats_sales
|
||||||
* @property bool|null $whitelabel
|
* @property bool|null $whitelabel
|
||||||
* @property string|null $whitelabel_name
|
* @property string|null $whitelabel_name
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ProductAttribute> $attribute_variants
|
* @property-read Collection<int, ProductAttribute> $attribute_variants
|
||||||
* @property-read int|null $attribute_variants_count
|
* @property-read int|null $attribute_variants_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ProductImage> $whitelabel_images
|
* @property-read Collection<int, ProductImage> $whitelabel_images
|
||||||
* @property-read int|null $whitelabel_images_count
|
* @property-read int|null $whitelabel_images_count
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereExcludeStatsSales($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereExcludeStatsSales($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereWhitelabel($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereWhitelabel($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereWhitelabelName($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|Product whereWhitelabelName($value)
|
||||||
|
*
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class Product extends Model
|
class Product extends Model
|
||||||
{
|
{
|
||||||
|
|
||||||
/*identifiers
|
/*identifiers
|
||||||
show_upgrade # in membership payment can upgrade this package to show order
|
show_upgrade # in membership payment can upgrade this package to show order
|
||||||
show_order # in membership payment show always
|
show_order # in membership payment show always
|
||||||
|
|
@ -172,8 +201,8 @@ class Product extends Model
|
||||||
'max_buy_num' => 'int',
|
'max_buy_num' => 'int',
|
||||||
'whitelabel' => 'bool',
|
'whitelabel' => 'bool',
|
||||||
];
|
];
|
||||||
use Sluggable;
|
|
||||||
|
|
||||||
|
use Sluggable;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
protected $dates = ['deleted_at'];
|
protected $dates = ['deleted_at'];
|
||||||
|
|
@ -215,7 +244,9 @@ class Product extends Model
|
||||||
'upgrade_to_id',
|
'upgrade_to_id',
|
||||||
'shipping_addon',
|
'shipping_addon',
|
||||||
'max_buy',
|
'max_buy',
|
||||||
'max_buy_num'
|
'max_buy_num',
|
||||||
|
'shelf_life_type',
|
||||||
|
'shelf_life_months',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -225,8 +256,9 @@ class Product extends Model
|
||||||
'show_order' => 'Wird immer als Option angezeigt',
|
'show_order' => 'Wird immer als Option angezeigt',
|
||||||
'upgrade' => 'Produktupgrade zur Produkt ID',
|
'upgrade' => 'Produktupgrade zur Produkt ID',
|
||||||
'upgrade_member' => 'Vertriebspartnerupgrade zur Karriere ID',
|
'upgrade_member' => 'Vertriebspartnerupgrade zur Karriere ID',
|
||||||
//'proportional_voucher' => 'Anteiliger Gutschein Vertriebspartner',
|
// 'proportional_voucher' => 'Anteiliger Gutschein Vertriebspartner',
|
||||||
];
|
];
|
||||||
|
|
||||||
public $unitTypes = [
|
public $unitTypes = [
|
||||||
0 => '',
|
0 => '',
|
||||||
1 => 'ml',
|
1 => 'ml',
|
||||||
|
|
@ -248,34 +280,39 @@ class Product extends Model
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'slug' => [
|
'slug' => [
|
||||||
'source' => 'name'
|
'source' => 'name',
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attributes(){
|
public function attributes()
|
||||||
return $this->hasMany(ProductAttribute::class, 'product_id', 'id')->where('type_id','!=', 1);
|
{
|
||||||
|
return $this->hasMany(ProductAttribute::class, 'product_id', 'id')->where('type_id', '!=', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attribute_variants(){
|
public function attribute_variants()
|
||||||
return $this->hasMany(ProductAttribute::class, 'product_id', 'id')->where('type_id','=', 1);
|
{
|
||||||
|
return $this->hasMany(ProductAttribute::class, 'product_id', 'id')->where('type_id', '=', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function categories()
|
||||||
public function categories(){
|
{
|
||||||
return $this->hasMany('App\Models\ProductCategory', 'product_id', 'id');
|
return $this->hasMany('App\Models\ProductCategory', 'product_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function images(){
|
public function images()
|
||||||
return $this->hasMany(ProductImage::class, 'product_id', 'id')->where('type','=', 'product')->orderBy('pos');
|
{
|
||||||
|
return $this->hasMany(ProductImage::class, 'product_id', 'id')->where('type', '=', 'product')->orderBy('pos');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function imagesActive(){
|
public function imagesActive()
|
||||||
return $this->hasMany(ProductImage::class, 'product_id', 'id')->where('type','=', 'product')->where('active', true)->orderBy('pos');
|
{
|
||||||
|
return $this->hasMany(ProductImage::class, 'product_id', 'id')->where('type', '=', 'product')->where('active', true)->orderBy('pos');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function whitelabel_images(){
|
public function whitelabel_images()
|
||||||
return $this->hasMany(ProductImage::class, 'product_id', 'id')->where('type','=', 'wllogo')->orderBy('pos');
|
{
|
||||||
|
return $this->hasMany(ProductImage::class, 'product_id', 'id')->where('type', '=', 'wllogo')->orderBy('pos');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function country_prices()
|
public function country_prices()
|
||||||
|
|
@ -291,81 +328,130 @@ class Product extends Model
|
||||||
public function p_ingredients()
|
public function p_ingredients()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Ingredient::class, 'product_ingredients')
|
return $this->belongsToMany(Ingredient::class, 'product_ingredients')
|
||||||
->withPivot('id')
|
->withPivot('id', 'pos', 'gram', 'factor', 'recipe_type')
|
||||||
->withTimestamps();
|
->withTimestamps()
|
||||||
|
->wherePivot('recipe_type', 'product')
|
||||||
|
->orderByPivot('pos');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function manufacturer_ingredients()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Ingredient::class, 'product_ingredients')
|
||||||
|
->withPivot('id', 'pos', 'gram', 'factor', 'recipe_type')
|
||||||
|
->withTimestamps()
|
||||||
|
->wherePivot('recipe_type', 'manufacturer')
|
||||||
|
->orderByPivot('pos');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function product_ingredients()
|
public function product_ingredients()
|
||||||
{
|
{
|
||||||
return $this->hasMany(ProductIngredient::class, 'product_ingredients', 'id');
|
return $this->hasMany(ProductIngredient::class, 'product_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShortCopy($clean = false, $len = false){
|
/**
|
||||||
|
* Verpackungs-Stückliste (BOM) am Produkt mit Menge und Reihenfolge.
|
||||||
|
*
|
||||||
|
* @return BelongsToMany<PackagingItem, $this>
|
||||||
|
*/
|
||||||
|
public function packagings()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(PackagingItem::class, 'product_packagings')
|
||||||
|
->withPivot('quantity', 'pos')
|
||||||
|
->withTimestamps()
|
||||||
|
->orderByPivot('pos');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return HasMany<Production, $this>
|
||||||
|
*/
|
||||||
|
public function productions(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(Production::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShortCopy($clean = false, $len = false)
|
||||||
|
{
|
||||||
$ret = $this->short_copy ? $this->short_copy : $this->description;
|
$ret = $this->short_copy ? $this->short_copy : $this->description;
|
||||||
if($len && $clean){
|
if ($len && $clean) {
|
||||||
return substr_ellipsis($ret, $len, $clean);
|
return substr_ellipsis($ret, $len, $clean);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
public function getActionName($id = 0){
|
|
||||||
if(isset($this->actions[$id])){
|
public function getActionName($id = 0)
|
||||||
|
{
|
||||||
|
if (isset($this->actions[$id])) {
|
||||||
return $this->actions[$id];
|
return $this->actions[$id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getWhiteLableName($id = 0){
|
public function getWhiteLableName($id = 0)
|
||||||
|
{
|
||||||
return $this->whitelabel_name ? $this->whitelabel_name : $this->name;
|
return $this->whitelabel_name ? $this->whitelabel_name : $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function _format_number($value){
|
public function _format_number($value)
|
||||||
return preg_replace("/[^0-9,]/", "", $value);
|
{
|
||||||
|
return preg_replace('/[^0-9,]/', '', $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPriceAttribute( $value ) {
|
public function setPriceAttribute($value)
|
||||||
|
{
|
||||||
|
|
||||||
$this->attributes['price'] = $value ? Util::reFormatNumber($value) : null;
|
$this->attributes['price'] = $value ? Util::reFormatNumber($value) : null;
|
||||||
}
|
}
|
||||||
public function setPriceEkAttribute( $value ) {
|
|
||||||
|
public function setPriceEkAttribute($value)
|
||||||
|
{
|
||||||
|
|
||||||
$this->attributes['price_ek'] = $value ? Util::reFormatNumber($value) : null;
|
$this->attributes['price_ek'] = $value ? Util::reFormatNumber($value) : null;
|
||||||
}
|
}
|
||||||
public function setTaxAttribute( $value ) {
|
|
||||||
|
|
||||||
$this->attributes['tax'] = $value != "" ? Util::reFormatNumber($value) : null;
|
public function setTaxAttribute($value)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->attributes['tax'] = $value != '' ? Util::reFormatNumber($value) : null;
|
||||||
}
|
}
|
||||||
public function setPriceOldAttribute( $value ) {
|
|
||||||
|
public function setPriceOldAttribute($value)
|
||||||
|
{
|
||||||
|
|
||||||
$this->attributes['price_old'] = $value ? Util::reFormatNumber($value) : null;
|
$this->attributes['price_old'] = $value ? Util::reFormatNumber($value) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setValueCommissionAttribute( $value ) {
|
public function setValueCommissionAttribute($value)
|
||||||
|
{
|
||||||
$this->attributes['value_commission'] = $value ? Util::reFormatNumber($value) : 0;
|
$this->attributes['value_commission'] = $value ? Util::reFormatNumber($value) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPartnerCommissionAttribute( $value ) {
|
public function setPartnerCommissionAttribute($value)
|
||||||
|
{
|
||||||
$this->attributes['partner_commission'] = $value ? Util::reFormatNumber($value) : 0;
|
$this->attributes['partner_commission'] = $value ? Util::reFormatNumber($value) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedPrice()
|
public function getFormattedPrice()
|
||||||
{
|
{
|
||||||
return isset($this->attributes['price']) ? Util::formatNumber($this->attributes['price']) : "";
|
return isset($this->attributes['price']) ? Util::formatNumber($this->attributes['price']) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedPriceEk()
|
public function getFormattedPriceEk()
|
||||||
{
|
{
|
||||||
return isset($this->attributes['price_ek']) ? Util::formatNumber($this->attributes['price_ek']) : "";
|
return isset($this->attributes['price_ek']) ? Util::formatNumber($this->attributes['price_ek']) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedTax($country = null)
|
public function getFormattedTax($country = null)
|
||||||
{
|
{
|
||||||
return isset($this->attributes['tax']) ? Util::formatNumber($this->getTaxWith($country), 0) : "";
|
return isset($this->attributes['tax']) ? Util::formatNumber($this->getTaxWith($country), 0) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedPriceOld()
|
public function getFormattedPriceOld()
|
||||||
{
|
{
|
||||||
return isset($this->attributes['price_old']) ? Util::formatNumber($this->attributes['price_old']) : "";
|
return isset($this->attributes['price_old']) ? Util::formatNumber($this->attributes['price_old']) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedValueCommission()
|
public function getFormattedValueCommission()
|
||||||
{
|
{
|
||||||
return isset($this->attributes['value_commission']) ? Util::formatNumber($this->attributes['value_commission']) : 0;
|
return isset($this->attributes['value_commission']) ? Util::formatNumber($this->attributes['value_commission']) : 0;
|
||||||
|
|
@ -376,9 +462,9 @@ class Product extends Model
|
||||||
return isset($this->attributes['partner_commission']) ? Util::formatNumber($this->attributes['partner_commission']) : 0;
|
return isset($this->attributes['partner_commission']) ? Util::formatNumber($this->attributes['partner_commission']) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* price by user Factor */
|
||||||
/*price by user Factor*/
|
private function calcPriceUserFactor($price)
|
||||||
private function calcPriceUserFactor($price){
|
{
|
||||||
/*
|
/*
|
||||||
Nicht in benutzung, die margin errechnet sich im Warenkorb, wegen der Staffelprovision
|
Nicht in benutzung, die margin errechnet sich im Warenkorb, wegen der Staffelprovision
|
||||||
if(\Auth::user() && \Auth::user()->user_level){
|
if(\Auth::user() && \Auth::user()->user_level){
|
||||||
|
|
@ -388,15 +474,19 @@ class Product extends Model
|
||||||
*/
|
*/
|
||||||
return $price;
|
return $price;
|
||||||
}
|
}
|
||||||
/*price net*/
|
|
||||||
private function calcPriceNet($price, $country=null){
|
/* price net */
|
||||||
|
private function calcPriceNet($price, $country = null)
|
||||||
|
{
|
||||||
$tax = $this->getTaxWith($country);
|
$tax = $this->getTaxWith($country);
|
||||||
$tax_rate = ($tax + 100) / 100;
|
$tax_rate = ($tax + 100) / 100;
|
||||||
|
|
||||||
return $price / $tax_rate;
|
return $price / $tax_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
//price calu with
|
// price calu with
|
||||||
public function getPriceWith(Bool $net = true, Bool $ufactor = true, $country = null, $commission=false){
|
public function getPriceWith(bool $net = true, bool $ufactor = true, $country = null, $commission = false)
|
||||||
|
{
|
||||||
$price = isset($this->attributes['price']) ? $this->attributes['price'] : null;
|
$price = isset($this->attributes['price']) ? $this->attributes['price'] : null;
|
||||||
|
|
||||||
/*$cprice = $country ? $this->getCPrice($country) : null; //eigener Preis für Land
|
/*$cprice = $country ? $this->getCPrice($country) : null; //eigener Preis für Land
|
||||||
|
|
@ -405,81 +495,95 @@ class Product extends Model
|
||||||
$price = $net ? $this->calcPriceNet($price, $country) : $price;
|
$price = $net ? $this->calcPriceNet($price, $country) : $price;
|
||||||
$price = $ufactor ? $this->calcPriceUserFactor($price) : $price;
|
$price = $ufactor ? $this->calcPriceUserFactor($price) : $price;
|
||||||
$price = $commission ? $this->calcPriceUserCommission($price) : $price;
|
$price = $commission ? $this->calcPriceUserCommission($price) : $price;
|
||||||
|
|
||||||
return round($price, 2);
|
return round($price, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*out*/
|
/* out */
|
||||||
public function getFormattedPriceWith(Bool $net = true, Bool $ufactor = true)
|
public function getFormattedPriceWith(bool $net = true, bool $ufactor = true)
|
||||||
{
|
{
|
||||||
return isset($this->attributes['price']) ? Util::formatNumber($this->getPriceWith($net, $ufactor)) : "";
|
return isset($this->attributes['price']) ? Util::formatNumber($this->getPriceWith($net, $ufactor)) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTaxWith($country = null){
|
public function getTaxWith($country = null)
|
||||||
|
{
|
||||||
$tax = isset($this->attributes['tax']) ? $this->attributes['tax'] : null;
|
$tax = isset($this->attributes['tax']) ? $this->attributes['tax'] : null;
|
||||||
$ctax = $country ? $this->getCTax($country) : null;
|
$ctax = $country ? $this->getCTax($country) : null;
|
||||||
|
|
||||||
return $ctax !== null ? $ctax : $tax;
|
return $ctax !== null ? $ctax : $tax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getBasePriceFormattedFull()
|
||||||
|
{
|
||||||
public function getBasePriceFormattedFull(){
|
if ($price = $this->getBasePrice()) {
|
||||||
if($price = $this->getBasePrice()){
|
|
||||||
$unit = $this->attributes['unit'];
|
$unit = $this->attributes['unit'];
|
||||||
//ml g
|
// ml g
|
||||||
if($unit === 1 || $unit === 2){
|
if ($unit === 1 || $unit === 2) {
|
||||||
return Util::formatNumber($price) . ' € / 100 '.$this->getUnitType();
|
return Util::formatNumber($price).' € / 100 '.$this->getUnitType();
|
||||||
}
|
}
|
||||||
//l kg
|
// l kg
|
||||||
if($unit === 3 || $unit === 4){
|
if ($unit === 3 || $unit === 4) {
|
||||||
return Util::formatNumber($price) . ' € / 1 '.$this->getUnitType();
|
return Util::formatNumber($price).' € / 1 '.$this->getUnitType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBasePriceFormatted(){
|
return '';
|
||||||
if($price = $this->getBasePrice()){
|
}
|
||||||
|
|
||||||
|
public function getBasePriceFormatted()
|
||||||
|
{
|
||||||
|
if ($price = $this->getBasePrice()) {
|
||||||
return Util::formatNumber($price);
|
return Util::formatNumber($price);
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBasePrice(){
|
public function getBasePrice()
|
||||||
if(isset($this->attributes['unit']) && isset($this->attributes['contents_total']) && $this->attributes['contents_total'] != 0){
|
{
|
||||||
|
if (isset($this->attributes['unit']) && isset($this->attributes['contents_total']) && $this->attributes['contents_total'] != 0) {
|
||||||
$unit = $this->attributes['unit'];
|
$unit = $this->attributes['unit'];
|
||||||
//ml g
|
// ml g
|
||||||
if($unit === 1 || $unit === 2){
|
if ($unit === 1 || $unit === 2) {
|
||||||
return $this->attributes['price'] * 100 / $this->attributes['contents_total'];
|
return $this->attributes['price'] * 100 / $this->attributes['contents_total'];
|
||||||
}
|
}
|
||||||
//l kg
|
// l kg
|
||||||
if($unit === 3 || $unit === 4){
|
if ($unit === 3 || $unit === 4) {
|
||||||
return $this->attributes['price'] * 1000 / $this->attributes['contents_total'];
|
return $this->attributes['price'] * 1000 / $this->attributes['contents_total'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
public function getUnitType(){
|
|
||||||
|
public function getUnitType()
|
||||||
|
{
|
||||||
return isset($this->unitTypes[$this->unit]) ? $this->unitTypes[$this->unit] : '-';
|
return isset($this->unitTypes[$this->unit]) ? $this->unitTypes[$this->unit] : '-';
|
||||||
}
|
}
|
||||||
public function getShowAtType(){
|
|
||||||
|
public function getShowAtType()
|
||||||
|
{
|
||||||
return isset(Type::$showATs[$this->show_at]) ? Type::$showATs[$this->show_at] : '-';
|
return isset(Type::$showATs[$this->show_at]) ? Type::$showATs[$this->show_at] : '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowOnTypes($seperator = false){
|
public function getShowOnTypes($seperator = false)
|
||||||
|
{
|
||||||
$ret = [];
|
$ret = [];
|
||||||
if($this->show_on && is_array($this->show_on)){
|
if ($this->show_on && is_array($this->show_on)) {
|
||||||
foreach($this->show_on as $show){
|
foreach ($this->show_on as $show) {
|
||||||
$ret[] = isset(Type::$showONs[$show]) ? Type::$showONs[$show] : '-';
|
$ret[] = isset(Type::$showONs[$show]) ? Type::$showONs[$show] : '-';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $seperator ? implode($seperator, $ret) : $ret;
|
return $seperator ? implode($seperator, $ret) : $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setPosAttribute($value)
|
||||||
public function setPosAttribute($value){
|
{
|
||||||
$this->attributes['pos'] = is_numeric($value) ? $value : null;
|
$this->attributes['pos'] = is_numeric($value) ? $value : null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLang($key)
|
public function getLang($key)
|
||||||
{
|
{
|
||||||
$lang = \App::getLocale();
|
$lang = \App::getLocale();
|
||||||
|
|
@ -487,62 +591,75 @@ class Product extends Model
|
||||||
return $this->{$key};
|
return $this->{$key};
|
||||||
}
|
}
|
||||||
$trans = $this->getTrans($key, $lang);
|
$trans = $this->getTrans($key, $lang);
|
||||||
if (!$trans || $trans == '') {
|
if (! $trans || $trans == '') {
|
||||||
return $this->{$key};
|
return $this->{$key};
|
||||||
}
|
}
|
||||||
|
|
||||||
return $trans;
|
return $trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTrans($key, $lang)
|
public function getTrans($key, $lang)
|
||||||
{
|
{
|
||||||
$key = 'trans_' . $key;
|
$key = 'trans_'.$key;
|
||||||
if (!empty($this->{$key}[$lang])) {
|
if (! empty($this->{$key}[$lang])) {
|
||||||
return $this->{$key}[$lang];
|
return $this->{$key}[$lang];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTranNames()
|
public function getTranNames()
|
||||||
{
|
{
|
||||||
$ret = "";
|
$ret = '';
|
||||||
foreach ((array) $this->trans_name as $value){
|
foreach ((array) $this->trans_name as $value) {
|
||||||
$ret .= $value.', ';
|
$ret .= $value.', ';
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtrim($ret, ', ');
|
return rtrim($ret, ', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCountryPrice($country_id){
|
public function getCountryPrice($country_id)
|
||||||
return $this->country_prices->where('country_id', '=', $country_id)->first() ?: new CountryPrice();
|
{
|
||||||
|
return $this->country_prices->where('country_id', '=', $country_id)->first() ?: new CountryPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCPrice($country_id){
|
public function getCPrice($country_id)
|
||||||
|
{
|
||||||
return $this->getCountryPrice($country_id)->c_price;
|
return $this->getCountryPrice($country_id)->c_price;
|
||||||
}
|
}
|
||||||
public function getCTax($country_id){
|
|
||||||
|
public function getCTax($country_id)
|
||||||
|
{
|
||||||
return $this->getCountryPrice($country_id)->c_tax;
|
return $this->getCountryPrice($country_id)->c_tax;
|
||||||
}
|
}
|
||||||
public function getCPriceOld($country_id){
|
|
||||||
|
public function getCPriceOld($country_id)
|
||||||
|
{
|
||||||
return $this->getCountryPrice($country_id)->c_price_old;
|
return $this->getCountryPrice($country_id)->c_price_old;
|
||||||
}
|
}
|
||||||
public function getCCurrency($country_id){
|
|
||||||
|
public function getCCurrency($country_id)
|
||||||
|
{
|
||||||
return $this->getCountryPrice($country_id)->c_currency;
|
return $this->getCountryPrice($country_id)->c_currency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRealPrice(Country $country){
|
public function getRealPrice(Country $country)
|
||||||
if($country->own_eur && $this->getCPrice($country->id)){
|
{
|
||||||
|
if ($country->own_eur && $this->getCPrice($country->id)) {
|
||||||
return $this->getCPrice($country->id);
|
return $this->getCPrice($country->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->price;
|
return $this->price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedPriceCurrencyWith(Bool $net = true, Bool $ufactor = true, Country $country = null, $commission = false){
|
public function getFormattedPriceCurrencyWith(bool $net = true, bool $ufactor = true, ?Country $country = null, $commission = false)
|
||||||
$ret = "";
|
{
|
||||||
if($country && isset($country->currency) && $country->currency){
|
$ret = '';
|
||||||
|
if ($country && isset($country->currency) && $country->currency) {
|
||||||
$price = $this->getPriceWith($net, $ufactor, $country, $commission);
|
$price = $this->getPriceWith($net, $ufactor, $country, $commission);
|
||||||
$ret = formatNumber($price * $country->currency_faktor)." ".$country->currency_unit;
|
$ret = formatNumber($price * $country->currency_faktor).' '.$country->currency_unit;
|
||||||
|
|
||||||
return '<br><span class="small">~'.$ret.'<span>';
|
return '<br><span class="small">~'.$ret.'<span>';
|
||||||
}
|
}
|
||||||
return "" ;
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @property Carbon $updated_at
|
* @property Carbon $updated_at
|
||||||
* @property Ingredient $ingredient
|
* @property Ingredient $ingredient
|
||||||
* @property Product $product
|
* @property Product $product
|
||||||
* @package App\Models
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient query()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient query()
|
||||||
|
|
@ -28,6 +28,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient whereIngredientId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient whereIngredientId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient whereProductId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient whereProductId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ProductIngredient whereUpdatedAt($value)
|
||||||
|
*
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class ProductIngredient extends Model
|
class ProductIngredient extends Model
|
||||||
|
|
@ -36,12 +37,19 @@ class ProductIngredient extends Model
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'product_id' => 'int',
|
'product_id' => 'int',
|
||||||
'ingredient_id' => 'int'
|
'ingredient_id' => 'int',
|
||||||
|
'pos' => 'int',
|
||||||
|
'gram' => 'decimal:3',
|
||||||
|
'factor' => 'decimal:2',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'product_id',
|
'product_id',
|
||||||
'ingredient_id'
|
'ingredient_id',
|
||||||
|
'pos',
|
||||||
|
'gram',
|
||||||
|
'factor',
|
||||||
|
'recipe_type',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function ingredient()
|
public function ingredient()
|
||||||
|
|
|
||||||
72
app/Models/Production.php
Normal file
72
app/Models/Production.php
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
class Production extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'product_id',
|
||||||
|
'location_id',
|
||||||
|
'produced_by',
|
||||||
|
'produced_at',
|
||||||
|
'quantity',
|
||||||
|
'notes',
|
||||||
|
'mhd_warning',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'produced_at' => 'date',
|
||||||
|
'mhd_warning' => 'boolean',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Product, $this>
|
||||||
|
*/
|
||||||
|
public function product(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Product::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Location, $this>
|
||||||
|
*/
|
||||||
|
public function location(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Location::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<User, $this>
|
||||||
|
*/
|
||||||
|
public function producedByUser(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'produced_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return HasMany<ProductionIngredient, $this>
|
||||||
|
*/
|
||||||
|
public function productionIngredients(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ProductionIngredient::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return HasMany<ProductionPackaging, $this>
|
||||||
|
*/
|
||||||
|
public function productionPackagings(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ProductionPackaging::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/Models/ProductionIngredient.php
Normal file
50
app/Models/ProductionIngredient.php
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class ProductionIngredient extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'production_id',
|
||||||
|
'ingredient_id',
|
||||||
|
'stock_entry_id',
|
||||||
|
'quantity_used',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'quantity_used' => 'decimal:2',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Production, $this>
|
||||||
|
*/
|
||||||
|
public function production(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Production::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Ingredient, $this>
|
||||||
|
*/
|
||||||
|
public function ingredient(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Ingredient::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<StockEntry, $this>
|
||||||
|
*/
|
||||||
|
public function stockEntry(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(StockEntry::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
app/Models/ProductionPackaging.php
Normal file
41
app/Models/ProductionPackaging.php
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class ProductionPackaging extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'production_id',
|
||||||
|
'packaging_item_id',
|
||||||
|
'quantity_used',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'quantity_used' => 'integer',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Production, $this>
|
||||||
|
*/
|
||||||
|
public function production(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Production::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<PackagingItem, $this>
|
||||||
|
*/
|
||||||
|
public function packagingItem(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(PackagingItem::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,11 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App\Models\ShoppingOrder
|
* App\Models\ShoppingOrder
|
||||||
|
|
@ -22,16 +25,17 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
* @property int|null $weight
|
* @property int|null $weight
|
||||||
* @property int|null $paid
|
* @property int|null $paid
|
||||||
* @property string|null $txaction
|
* @property string|null $txaction
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property-read \App\User|null $auth_user
|
* @property-read User|null $auth_user
|
||||||
* @property-read \App\Models\Country $country
|
* @property-read Country $country
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ShoppingOrderItem[] $shopping_order_items
|
* @property-read Collection|ShoppingOrderItem[] $shopping_order_items
|
||||||
* @property-read int|null $shopping_order_items_count
|
* @property-read int|null $shopping_order_items_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\ShoppingPayment[] $shopping_payments
|
* @property-read Collection|ShoppingPayment[] $shopping_payments
|
||||||
* @property-read int|null $shopping_payments_count
|
* @property-read int|null $shopping_payments_count
|
||||||
* @property-read \App\Models\ShoppingUser $shopping_user
|
* @property-read ShoppingUser $shopping_user
|
||||||
* @property-read \App\Models\UserShop $user_shop
|
* @property-read UserShop $user_shop
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder query()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder query()
|
||||||
|
|
@ -51,62 +55,93 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUpdatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUserShopId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUserShopId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereWeight($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereWeight($value)
|
||||||
|
*
|
||||||
* @property int|null $payment_for
|
* @property int|null $payment_for
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder wherePaymentFor($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder wherePaymentFor($value)
|
||||||
|
*
|
||||||
* @property int|null $member_id
|
* @property int|null $member_id
|
||||||
* @property string|null $mode
|
* @property string|null $mode
|
||||||
* @property-read \App\User|null $member
|
* @property-read User|null $member
|
||||||
* @property-read \App\Models\UserHistory|null $user_history
|
* @property-read UserHistory|null $user_history
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereMemberId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereMemberId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereMode($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereMode($value)
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
*
|
||||||
|
* @property Carbon|null $deleted_at
|
||||||
* @property string|null $user_deleted_at
|
* @property string|null $user_deleted_at
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder onlyTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder onlyTrashed()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereDeletedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereDeletedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUserDeletedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereUserDeletedAt($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder withTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder withTrashed()
|
||||||
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder withoutTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\App\Models\ShoppingOrder withoutTrashed()
|
||||||
* @property-read \App\Models\ShippingCountry $shipping_country
|
*
|
||||||
|
* @property-read ShippingCountry $shipping_country
|
||||||
* @property float|null $shipping_net
|
* @property float|null $shipping_net
|
||||||
* @property float|null $subtotal_shipping
|
* @property float|null $subtotal_shipping
|
||||||
* @property int|null $points
|
* @property int|null $points
|
||||||
* @property int|null $shipped
|
* @property int|null $shipped
|
||||||
* @property string|null $tracking
|
* @property string|null $tracking
|
||||||
* @property string|null $wp_invoice_path
|
* @property string|null $wp_invoice_path
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder wherePoints($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder wherePoints($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereShipped($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereShipped($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereShippingNet($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereShippingNet($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereSubtotalWs($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereSubtotalWs($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereTracking($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereTracking($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereWpInvoicePath($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrder whereWpInvoicePath($value)
|
||||||
|
*
|
||||||
* @property array|null $wp_notice
|
* @property array|null $wp_notice
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereWpNotice($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereWpNotice($value)
|
||||||
|
*
|
||||||
* @property string|null $subtotal_full
|
* @property string|null $subtotal_full
|
||||||
* @property-read \App\Models\ShoppingOrderMargin|null $shopping_order_margin
|
* @property-read ShoppingOrderMargin|null $shopping_order_margin
|
||||||
* @property-read \App\Models\ShoppingPayment|null $shopping_payment_last
|
* @property-read ShoppingPayment|null $shopping_payment_last
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereSubtotalFull($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereSubtotalFull($value)
|
||||||
|
*
|
||||||
* @property string|null $discount
|
* @property string|null $discount
|
||||||
* @property string|null $payment_credit
|
* @property string|null $payment_credit
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereDiscount($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereDiscount($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder wherePaymentCredit($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder wherePaymentCredit($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereSubtotalShipping($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereSubtotalShipping($value)
|
||||||
|
*
|
||||||
* @property string|null $total_without_credit
|
* @property string|null $total_without_credit
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereTotalWithoutCredit($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereTotalWithoutCredit($value)
|
||||||
|
*
|
||||||
* @property array|null $invoice
|
* @property array|null $invoice
|
||||||
* @property \Illuminate\Support\Carbon|null $shipped_at
|
* @property Carbon|null $shipped_at
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereInvoice($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereInvoice($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippedAt($value)
|
||||||
|
*
|
||||||
* @property string|null $invoice_number
|
* @property string|null $invoice_number
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereInvoiceNumber($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereInvoiceNumber($value)
|
||||||
|
*
|
||||||
* @property int|null $promotion_user_id
|
* @property int|null $promotion_user_id
|
||||||
* @property string|null $shipping_option
|
* @property string|null $shipping_option
|
||||||
* @property-read \App\Models\PromotionUser|null $promotion_user
|
* @property-read PromotionUser|null $promotion_user
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder wherePromotionUserId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder wherePromotionUserId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippingOption($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippingOption($value)
|
||||||
|
*
|
||||||
* @property array|null $delivery
|
* @property array|null $delivery
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereDelivery($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereDelivery($value)
|
||||||
|
*
|
||||||
* @property bool $user_white_label
|
* @property bool $user_white_label
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrder whereUserWhiteLabel($value)
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrder whereUserWhiteLabel($value)
|
||||||
|
*
|
||||||
|
* @property array<array-key, mixed>|null $cancellation_invoice
|
||||||
|
*
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingOrder whereCancellationInvoice($value)
|
||||||
|
*
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class ShoppingOrder extends Model
|
class ShoppingOrder extends Model
|
||||||
|
|
@ -114,6 +149,7 @@ class ShoppingOrder extends Model
|
||||||
protected $table = 'shopping_orders';
|
protected $table = 'shopping_orders';
|
||||||
|
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
protected $dates = ['deleted_at'];
|
protected $dates = ['deleted_at'];
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
|
@ -139,6 +175,7 @@ class ShoppingOrder extends Model
|
||||||
'weight',
|
'weight',
|
||||||
'paid',
|
'paid',
|
||||||
'invoice',
|
'invoice',
|
||||||
|
'cancellation_invoice',
|
||||||
'delivery',
|
'delivery',
|
||||||
'user_white_label',
|
'user_white_label',
|
||||||
'invoice_number',
|
'invoice_number',
|
||||||
|
|
@ -155,6 +192,7 @@ class ShoppingOrder extends Model
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'wp_notice' => 'array',
|
'wp_notice' => 'array',
|
||||||
'invoice' => 'array',
|
'invoice' => 'array',
|
||||||
|
'cancellation_invoice' => 'array',
|
||||||
'delivery' => 'array',
|
'delivery' => 'array',
|
||||||
'shipped_at' => 'datetime',
|
'shipped_at' => 'datetime',
|
||||||
'user_white_label' => 'boolean',
|
'user_white_label' => 'boolean',
|
||||||
|
|
@ -167,14 +205,14 @@ class ShoppingOrder extends Model
|
||||||
3 => 'abgeschlossen',
|
3 => 'abgeschlossen',
|
||||||
5 => 'Wartestellung',
|
5 => 'Wartestellung',
|
||||||
4 => 'Abholung',
|
4 => 'Abholung',
|
||||||
10 => 'storniert'
|
10 => 'storniert',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static $paymentForTypes = [
|
public static $paymentForTypes = [
|
||||||
0 => '',
|
0 => '',
|
||||||
1 => 'Registrierung',
|
1 => 'Registrierung',
|
||||||
2 => 'Mitgliedschaft',
|
2 => 'Mitgliedschaft',
|
||||||
3 => 'Guthabenaufladung', //guthaben
|
3 => 'Guthabenaufladung', // guthaben
|
||||||
4 => 'VP.Bestellung Abholung',
|
4 => 'VP.Bestellung Abholung',
|
||||||
5 => 'VP.Bestellung Lieferung',
|
5 => 'VP.Bestellung Lieferung',
|
||||||
6 => 'VP.Kundenbestellung',
|
6 => 'VP.Kundenbestellung',
|
||||||
|
|
@ -182,7 +220,7 @@ class ShoppingOrder extends Model
|
||||||
8 => 'Shop',
|
8 => 'Shop',
|
||||||
9 => '-',
|
9 => '-',
|
||||||
10 => 'extern',
|
10 => 'extern',
|
||||||
11 => ''
|
11 => '',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static $paymentForColors = [
|
public static $paymentForColors = [
|
||||||
|
|
@ -198,18 +236,17 @@ class ShoppingOrder extends Model
|
||||||
8 => 'info',
|
8 => 'info',
|
||||||
9 => 'default',
|
9 => 'default',
|
||||||
10 => 'info',
|
10 => 'info',
|
||||||
11 => 'default'
|
11 => 'default',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public static $apiShippedTypes = [
|
public static $apiShippedTypes = [
|
||||||
0 => 'open', //(Fullfilment durch Händler)',
|
0 => 'open', // (Fullfilment durch Händler)',
|
||||||
1 => 'process', //(Fullfilment: nicht Versand)
|
1 => 'process', // (Fullfilment: nicht Versand)
|
||||||
2 => 'sent', //(Fullfilment: Versand erfolgt)'
|
2 => 'sent', // (Fullfilment: Versand erfolgt)'
|
||||||
3 => 'close', //(Fullfilment: Versand erfolgt)',
|
3 => 'close', // (Fullfilment: Versand erfolgt)',
|
||||||
4 => 'pick_up', //(Fullfilment: Versand erfolgt)',
|
4 => 'pick_up', // (Fullfilment: Versand erfolgt)',
|
||||||
10 => 'cancel'
|
10 => 'cancel',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static $shippedColors = [
|
public static $shippedColors = [
|
||||||
|
|
@ -224,101 +261,126 @@ class ShoppingOrder extends Model
|
||||||
|
|
||||||
public function shopping_user()
|
public function shopping_user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Models\ShoppingUser','shopping_user_id');
|
return $this->belongsTo('App\Models\ShoppingUser', 'shopping_user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function country()
|
public function country()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Models\ShippingCountry','country_id');
|
return $this->belongsTo('App\Models\ShippingCountry', 'country_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shipping_country()
|
public function shipping_country()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Models\ShippingCountry','country_id');
|
return $this->belongsTo('App\Models\ShippingCountry', 'country_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function promotion_user()
|
public function promotion_user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Models\PromotionUser','promotion_user_id');
|
return $this->belongsTo('App\Models\PromotionUser', 'promotion_user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user_shop()
|
public function user_shop()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Models\UserShop','user_shop_id');
|
return $this->belongsTo('App\Models\UserShop', 'user_shop_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
//can null
|
// can null
|
||||||
public function member()
|
public function member()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\User','member_id');
|
return $this->belongsTo('App\User', 'member_id');
|
||||||
}
|
}
|
||||||
//can null
|
|
||||||
|
// can null
|
||||||
public function auth_user()
|
public function auth_user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\User','auth_user_id');
|
return $this->belongsTo('App\User', 'auth_user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user_history()
|
public function user_history()
|
||||||
{
|
{
|
||||||
return $this->hasOne('App\Models\UserHistory','shopping_order_id')->latest();
|
return $this->hasOne('App\Models\UserHistory', 'shopping_order_id')->latest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shopping_order_margin()
|
public function shopping_order_margin()
|
||||||
{
|
{
|
||||||
return $this->hasOne('App\Models\ShoppingOrderMargin','shopping_order_id')->latest();
|
return $this->hasOne('App\Models\ShoppingOrderMargin', 'shopping_order_id')->latest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shopping_order_items(){
|
public function shopping_order_items()
|
||||||
|
{
|
||||||
return $this->hasMany('App\Models\ShoppingOrderItem', 'shopping_order_id');
|
return $this->hasMany('App\Models\ShoppingOrderItem', 'shopping_order_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shopping_payments(){
|
/**
|
||||||
|
* Mindestens eine Bestellzeile mit White-Label-Produkt (Lieferschein mit Etikett-Infos).
|
||||||
|
*/
|
||||||
|
public function hasWhitelabelProducts(): bool
|
||||||
|
{
|
||||||
|
return $this->shopping_order_items()
|
||||||
|
->whereHas('product', function ($query): void {
|
||||||
|
$query->where('whitelabel', true);
|
||||||
|
})
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shopping_payments()
|
||||||
|
{
|
||||||
return $this->hasMany('App\Models\ShoppingPayment', 'shopping_order_id');
|
return $this->hasMany('App\Models\ShoppingPayment', 'shopping_order_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shopping_payment_last(){
|
public function shopping_payment_last()
|
||||||
|
{
|
||||||
return $this->hasOne('App\Models\ShoppingPayment', 'shopping_order_id')->latest();
|
return $this->hasOne('App\Models\ShoppingPayment', 'shopping_order_id')->latest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUserHistoryValue($values = []){
|
public function setUserHistoryValue($values = [])
|
||||||
if($user_history = $this->user_history){
|
{
|
||||||
foreach ($values as $key=>$val){
|
if ($user_history = $this->user_history) {
|
||||||
|
foreach ($values as $key => $val) {
|
||||||
$user_history->{$key} = $val;
|
$user_history->{$key} = $val;
|
||||||
}
|
}
|
||||||
$user_history->save();
|
$user_history->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLastShoppingPayment($key=false){
|
public function getLastShoppingPayment($key = false)
|
||||||
|
{
|
||||||
$shopping_payment = $this->shopping_payments->last();
|
$shopping_payment = $this->shopping_payments->last();
|
||||||
if($shopping_payment){
|
if ($shopping_payment) {
|
||||||
if($key === 'getPaymentType'){
|
if ($key === 'getPaymentType') {
|
||||||
return $shopping_payment->getPaymentType();
|
return $shopping_payment->getPaymentType();
|
||||||
}
|
}
|
||||||
if($key === 'reference'){
|
if ($key === 'reference') {
|
||||||
return $shopping_payment->reference;
|
return $shopping_payment->reference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShippedType(){
|
public function getShippedType()
|
||||||
return isset(self::$shippedTypes[$this->shipped]) ? self::$shippedTypes[$this->shipped] : "";
|
{
|
||||||
|
return isset(self::$shippedTypes[$this->shipped]) ? self::$shippedTypes[$this->shipped] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAPIShippedType(){
|
public function getAPIShippedType()
|
||||||
return isset(self::$apiShippedTypes[$this->shipped]) ? self::$apiShippedTypes[$this->shipped] : "free";
|
{
|
||||||
|
return isset(self::$apiShippedTypes[$this->shipped]) ? self::$apiShippedTypes[$this->shipped] : 'free';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShippedColor(){
|
public function getShippedColor()
|
||||||
return isset(self::$shippedColors[$this->shipped]) ? self::$shippedColors[$this->shipped] : "default";
|
{
|
||||||
|
return isset(self::$shippedColors[$this->shipped]) ? self::$shippedColors[$this->shipped] : 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentForType(){
|
public function getPaymentForType()
|
||||||
return isset(self::$paymentForTypes[$this->payment_for]) ? self::$paymentForTypes[$this->payment_for] : "";
|
{
|
||||||
|
return isset(self::$paymentForTypes[$this->payment_for]) ? self::$paymentForTypes[$this->payment_for] : '';
|
||||||
}
|
}
|
||||||
public function getPaymentForColor(){
|
|
||||||
return isset(self::$paymentForColors[$this->payment_for]) ? self::$paymentForColors[$this->payment_for] : "";
|
public function getPaymentForColor()
|
||||||
|
{
|
||||||
|
return isset(self::$paymentForColors[$this->payment_for]) ? self::$paymentForColors[$this->payment_for] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedTotal()
|
public function getFormattedTotal()
|
||||||
|
|
@ -360,39 +422,46 @@ class ShoppingOrder extends Model
|
||||||
{
|
{
|
||||||
return formatNumber($this->attributes['tax']);
|
return formatNumber($this->attributes['tax']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedTotalWithoutCredit()
|
public function getFormattedTotalWithoutCredit()
|
||||||
{
|
{
|
||||||
return formatNumber($this->attributes['total_without_credit']);
|
return formatNumber($this->attributes['total_without_credit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedPaymentCredit()
|
public function getFormattedPaymentCredit()
|
||||||
{
|
{
|
||||||
return formatNumber($this->attributes['payment_credit']);
|
return formatNumber($this->attributes['payment_credit']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedTotalShipping()
|
public function getFormattedTotalShipping()
|
||||||
{
|
{
|
||||||
return formatNumber($this->attributes['total_shipping']);
|
return formatNumber($this->attributes['total_shipping']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getItemsCount(){
|
public function getItemsCount()
|
||||||
|
{
|
||||||
$count = 0;
|
$count = 0;
|
||||||
if($this->shopping_order_items){
|
if ($this->shopping_order_items) {
|
||||||
foreach ($this->shopping_order_items as $shopping_order_item){
|
foreach ($this->shopping_order_items as $shopping_order_item) {
|
||||||
$count += $shopping_order_item->qty;
|
$count += $shopping_order_item->qty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $count;
|
return $count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isInvoice(){
|
public function isInvoice()
|
||||||
|
{
|
||||||
return $this->user_invoice ? true : false;
|
return $this->user_invoice ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isPickUp(){
|
public function isPickUp()
|
||||||
|
{
|
||||||
return $this->shipping_option === 'pick_up' ? true : false;
|
return $this->shipping_option === 'pick_up' ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isTax(){
|
public function isTax()
|
||||||
|
{
|
||||||
return $this->tax > 0 ? true : false;
|
return $this->tax > 0 ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Services\Util;
|
use App\Services\Util;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App\Models\ShoppingPayment
|
* App\Models\ShoppingPayment
|
||||||
|
|
@ -18,11 +20,12 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @property string $currency
|
* @property string $currency
|
||||||
* @property string|null $status
|
* @property string|null $status
|
||||||
* @property string|null $txaction
|
* @property string|null $txaction
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\PaymentTransaction[] $payment_transactions
|
* @property-read Collection|PaymentTransaction[] $payment_transactions
|
||||||
* @property-read int|null $payment_transactions_count
|
* @property-read int|null $payment_transactions_count
|
||||||
* @property-read \App\Models\ShoppingOrder $shopping_order
|
* @property-read ShoppingOrder $shopping_order
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment query()
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment query()
|
||||||
|
|
@ -38,8 +41,17 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereTxaction($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereTxaction($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereUpdatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereWallettype($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereWallettype($value)
|
||||||
|
*
|
||||||
* @property string|null $mode
|
* @property string|null $mode
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereMode($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingPayment whereMode($value)
|
||||||
|
*
|
||||||
|
* @property int|null $reminder
|
||||||
|
* @property Carbon|null $reminder_date
|
||||||
|
*
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingPayment whereReminder($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShoppingPayment whereReminderDate($value)
|
||||||
|
*
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class ShoppingPayment extends Model
|
class ShoppingPayment extends Model
|
||||||
|
|
@ -58,7 +70,7 @@ class ShoppingPayment extends Model
|
||||||
'reminder',
|
'reminder',
|
||||||
'reminder_date',
|
'reminder_date',
|
||||||
'txaction',
|
'txaction',
|
||||||
'mode'
|
'mode',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
|
@ -66,44 +78,46 @@ class ShoppingPayment extends Model
|
||||||
'reminder_date' => 'datetime',
|
'reminder_date' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public function shopping_order()
|
public function shopping_order()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('App\Models\ShoppingOrder','shopping_order_id');
|
return $this->belongsTo('App\Models\ShoppingOrder', 'shopping_order_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function payment_transactions()
|
public function payment_transactions()
|
||||||
{
|
{
|
||||||
return $this->hasMany('App\Models\PaymentTransaction','shopping_payment_id');
|
return $this->hasMany('App\Models\PaymentTransaction', 'shopping_payment_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentType(){
|
public function getPaymentType()
|
||||||
|
{
|
||||||
|
|
||||||
if($this->clearingtype === 'pp') {
|
if ($this->clearingtype === 'pp') {
|
||||||
return 'PayPal';
|
return 'PayPal';
|
||||||
}
|
}
|
||||||
if($this->clearingtype === 'cc') {
|
if ($this->clearingtype === 'cc') {
|
||||||
return 'Kreditkarte';
|
return 'Kreditkarte';
|
||||||
}
|
}
|
||||||
if($this->clearingtype === 'vor') {
|
if ($this->clearingtype === 'vor') {
|
||||||
return 'Vorkasse';
|
return 'Vorkasse';
|
||||||
}
|
}
|
||||||
if($this->clearingtype === 'elv') {
|
if ($this->clearingtype === 'elv') {
|
||||||
return 'SEPA Lastschrift';
|
return 'SEPA Lastschrift';
|
||||||
}
|
}
|
||||||
if($this->clearingtype === 'sb') {
|
if ($this->clearingtype === 'sb') {
|
||||||
return 'Sofort Überweisung';
|
return 'Sofort Überweisung';
|
||||||
}
|
}
|
||||||
if($this->clearingtype === 'fnc') {
|
if ($this->clearingtype === 'fnc') {
|
||||||
return 'Rechnung';
|
return 'Rechnung';
|
||||||
}
|
}
|
||||||
if($this->clearingtype === 'non') {
|
if ($this->clearingtype === 'non') {
|
||||||
return 'keine';
|
|
||||||
}
|
|
||||||
return 'keine';
|
return 'keine';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentAmount(){
|
return 'keine';
|
||||||
return Util::formatNumber($this->amount/100)." ".$this->currency;
|
}
|
||||||
|
|
||||||
|
public function getPaymentAmount()
|
||||||
|
{
|
||||||
|
return Util::formatNumber($this->amount / 100).' '.$this->currency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
118
app/Models/StockEntry.php
Normal file
118
app/Models/StockEntry.php
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use Database\Factories\StockEntryFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class StockEntry extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<StockEntryFactory> */
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'entry_type',
|
||||||
|
'ingredient_id',
|
||||||
|
'packaging_item_id',
|
||||||
|
'supplier_id',
|
||||||
|
'location_id',
|
||||||
|
'unit',
|
||||||
|
'ordered_by',
|
||||||
|
'ordered_at',
|
||||||
|
'ordered_quantity',
|
||||||
|
'price_per_kg',
|
||||||
|
'price_total',
|
||||||
|
'received_by',
|
||||||
|
'received_at',
|
||||||
|
'received_quantity',
|
||||||
|
'batch_number',
|
||||||
|
'best_before',
|
||||||
|
'quality_id',
|
||||||
|
'status',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'ordered_at' => 'date',
|
||||||
|
'received_at' => 'date',
|
||||||
|
'best_before' => 'date',
|
||||||
|
'ordered_quantity' => 'decimal:2',
|
||||||
|
'received_quantity' => 'decimal:2',
|
||||||
|
'price_per_kg' => 'decimal:4',
|
||||||
|
'price_total' => 'decimal:4',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Ingredient, $this>
|
||||||
|
*/
|
||||||
|
public function ingredient(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Ingredient::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<PackagingItem, $this>
|
||||||
|
*/
|
||||||
|
public function packagingItem(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(PackagingItem::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Supplier, $this>
|
||||||
|
*/
|
||||||
|
public function supplier(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Supplier::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Location, $this>
|
||||||
|
*/
|
||||||
|
public function location(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Location::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<MaterialQuality, $this>
|
||||||
|
*/
|
||||||
|
public function quality(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MaterialQuality::class, 'quality_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<User, $this>
|
||||||
|
*/
|
||||||
|
public function orderedByUser(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'ordered_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<User, $this>
|
||||||
|
*/
|
||||||
|
public function receivedByUser(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'received_by');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isPending(): bool
|
||||||
|
{
|
||||||
|
return $this->status === 'pending';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isReceived(): bool
|
||||||
|
{
|
||||||
|
return $this->status === 'received';
|
||||||
|
}
|
||||||
|
}
|
||||||
67
app/Models/Supplier.php
Normal file
67
app/Models/Supplier.php
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Database\Factories\SupplierFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class Supplier extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<SupplierFactory> */
|
||||||
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'url',
|
||||||
|
'contact_person',
|
||||||
|
'email',
|
||||||
|
'phone',
|
||||||
|
'country_id',
|
||||||
|
'notes',
|
||||||
|
'active',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'active' => 'boolean',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo<Country, $this>
|
||||||
|
*/
|
||||||
|
public function country(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Country::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsToMany<SupplierCategory, $this>
|
||||||
|
*/
|
||||||
|
public function supplierCategories(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(
|
||||||
|
SupplierCategory::class,
|
||||||
|
'supplier_supplier_category',
|
||||||
|
'supplier_id',
|
||||||
|
'supplier_category_id'
|
||||||
|
)->withTimestamps();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return HasMany<PackagingItem, $this>
|
||||||
|
*/
|
||||||
|
public function packagingItems(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(PackagingItem::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
app/Models/SupplierCategory.php
Normal file
32
app/Models/SupplierCategory.php
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Database\Factories\SupplierCategoryFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
|
||||||
|
class SupplierCategory extends Model
|
||||||
|
{
|
||||||
|
/** @use HasFactory<SupplierCategoryFactory> */
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'pos',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsToMany<Supplier, $this>
|
||||||
|
*/
|
||||||
|
public function suppliers(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(
|
||||||
|
Supplier::class,
|
||||||
|
'supplier_supplier_category',
|
||||||
|
'supplier_category_id',
|
||||||
|
'supplier_id'
|
||||||
|
)->withTimestamps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\URL;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
|
|
@ -15,6 +17,7 @@ class AppServiceProvider extends ServiceProvider
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
Schema::defaultStringLength(191);
|
Schema::defaultStringLength(191);
|
||||||
|
URL::forceScheme('https');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -26,7 +29,7 @@ class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
if ($this->app->environment() !== 'production') {
|
if ($this->app->environment() !== 'production') {
|
||||||
$this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
|
$this->app->register(IdeHelperServiceProvider::class);
|
||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
|
||||||
44
app/Repositories/PackagingItemRepository.php
Normal file
44
app/Repositories/PackagingItemRepository.php
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\PackagingItem;
|
||||||
|
|
||||||
|
class PackagingItemRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public function create(array $data): PackagingItem
|
||||||
|
{
|
||||||
|
return PackagingItem::create($this->extractAttributes($data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public function update(PackagingItem $packagingItem, array $data): PackagingItem
|
||||||
|
{
|
||||||
|
$packagingItem->update($this->extractAttributes($data));
|
||||||
|
|
||||||
|
return $packagingItem->fresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
protected function extractAttributes(array $data): array
|
||||||
|
{
|
||||||
|
return collect($data)->only([
|
||||||
|
'packaging_material_id',
|
||||||
|
'supplier_id',
|
||||||
|
'name',
|
||||||
|
'category',
|
||||||
|
'weight_grams',
|
||||||
|
'min_stock_alert',
|
||||||
|
'product_id',
|
||||||
|
'active',
|
||||||
|
])->all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,26 +2,23 @@
|
||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use App\Models\CountryPrice;
|
|
||||||
use App\Models\Attribute;
|
use App\Models\Attribute;
|
||||||
|
use App\Models\CountryPrice;
|
||||||
|
use App\Models\Ingredient;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\ProductAttribute;
|
use App\Models\ProductAttribute;
|
||||||
use App\Models\ProductCategory;
|
use App\Models\ProductCategory;
|
||||||
use App\Models\ProductImage;
|
use App\Models\ProductImage;
|
||||||
use App\Models\ProductIngredient;
|
use App\Models\ProductIngredient;
|
||||||
|
use App\Services\Slim;
|
||||||
|
|
||||||
|
class ProductRepository extends BaseRepository
|
||||||
class ProductRepository extends BaseRepository {
|
{
|
||||||
|
|
||||||
|
|
||||||
public function __construct(Product $model)
|
public function __construct(Product $model)
|
||||||
{
|
{
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh.
|
* refresh.
|
||||||
*/
|
*/
|
||||||
|
|
@ -37,59 +34,211 @@ class ProductRepository extends BaseRepository {
|
||||||
$data['max_buy'] = isset($data['max_buy']) ? 1 : 0;
|
$data['max_buy'] = isset($data['max_buy']) ? 1 : 0;
|
||||||
$data['show_on'] = isset($data['show_on']) ? $data['show_on'] : null;
|
$data['show_on'] = isset($data['show_on']) ? $data['show_on'] : null;
|
||||||
|
|
||||||
if($data['id'] === "new"){
|
if (array_key_exists('shelf_life_type', $data)) {
|
||||||
$this->model = Product::create($data);
|
if ($data['shelf_life_type'] === '' || $data['shelf_life_type'] === null) {
|
||||||
|
$data['shelf_life_type'] = null;
|
||||||
|
$data['shelf_life_months'] = null;
|
||||||
|
} elseif ($data['shelf_life_type'] === 'pao') {
|
||||||
|
$data['shelf_life_months'] = null;
|
||||||
|
} elseif ($data['shelf_life_type'] === 'fixed' && array_key_exists('shelf_life_months', $data) && $data['shelf_life_months'] !== '' && $data['shelf_life_months'] !== null) {
|
||||||
|
$data['shelf_life_months'] = (int) $data['shelf_life_months'];
|
||||||
}
|
}
|
||||||
else{
|
}
|
||||||
|
|
||||||
|
if ($data['id'] === 'new') {
|
||||||
|
$this->model = Product::create($data);
|
||||||
|
} else {
|
||||||
$this->model = $this->getById($data['id']);
|
$this->model = $this->getById($data['id']);
|
||||||
$this->model->fill($data);
|
$this->model->fill($data);
|
||||||
$this->model->save();
|
$this->model->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$this->updateCategories(isset($data['categories']) ? $data['categories'] : []);
|
$this->updateCategories(isset($data['categories']) ? $data['categories'] : []);
|
||||||
$this->updateAttributes(isset($data['attributes']) ? $data['attributes'] : []);
|
$this->updateAttributes(isset($data['attributes']) ? $data['attributes'] : []);
|
||||||
|
|
||||||
$this->updateWLVariants(isset($data['whitelabel_variants']) ? $data['whitelabel_variants'] : []);
|
$this->updateWLVariants(isset($data['whitelabel_variants']) ? $data['whitelabel_variants'] : []);
|
||||||
$this->updateWLImageAttributs(isset($data['image_wl_attributes']) ? $data['image_wl_attributes'] : [] , isset($data['whitelabel_variants']) ? $data['whitelabel_variants'] : []);
|
$this->updateWLImageAttributs(isset($data['image_wl_attributes']) ? $data['image_wl_attributes'] : [], isset($data['whitelabel_variants']) ? $data['whitelabel_variants'] : []);
|
||||||
|
|
||||||
$this->updateIngredients(isset($data['product_ingredients']) ? $data['product_ingredients'] : []);
|
$this->updateIngredients($data);
|
||||||
|
$this->updateManufacturerIngredients($data);
|
||||||
|
$this->updatePackagings($data);
|
||||||
$this->updateCountryPrices($data);
|
$this->updateCountryPrices($data);
|
||||||
|
|
||||||
|
|
||||||
return $this->model;
|
return $this->model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updatePackagings(array $data = []): bool
|
||||||
public function updateIngredients($data = array())
|
|
||||||
{
|
{
|
||||||
$ProductIngredient = $this->model->p_ingredients()->pluck('ingredient_id')->toArray();
|
if (! isset($data['pp_packaging_item_id']) || ! is_array($data['pp_packaging_item_id'])) {
|
||||||
//set attr
|
$this->model->packagings()->detach();
|
||||||
if(is_array($data)){
|
|
||||||
foreach ($data as $id) {
|
|
||||||
//not use
|
|
||||||
if(!in_array($id, $ProductIngredient)){
|
|
||||||
ProductIngredient::create([
|
|
||||||
'product_id' => $this->model->id,
|
|
||||||
'ingredient_id' => $id,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateCategories($data = array())
|
$ids = $data['pp_packaging_item_id'];
|
||||||
|
$quantities = $data['pp_quantity'] ?? [];
|
||||||
|
$syncData = [];
|
||||||
|
foreach ($ids as $index => $packagingItemId) {
|
||||||
|
$pid = (int) $packagingItemId;
|
||||||
|
if ($pid <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$qtyRaw = $quantities[$index] ?? null;
|
||||||
|
$qty = $this->parseNullableDecimal($qtyRaw);
|
||||||
|
if ($qty === null || $qty <= 0) {
|
||||||
|
$qty = 1.0;
|
||||||
|
}
|
||||||
|
$syncData[$pid] = [
|
||||||
|
'quantity' => $qty,
|
||||||
|
'pos' => (int) $index,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->model->packagings()->sync($syncData);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateIngredients(array $data = []): bool
|
||||||
|
{
|
||||||
|
if (! array_key_exists('product_inci_sync_sent', $data)) {
|
||||||
|
if (isset($data['product_ingredients']) && is_array($data['product_ingredients'])) {
|
||||||
|
$ids = array_values(array_unique(array_filter(array_map('intval', $data['product_ingredients']), fn (int $id) => $id > 0)));
|
||||||
|
$defaults = Ingredient::whereIn('id', $ids)->pluck('default_factor', 'id');
|
||||||
|
|
||||||
|
ProductIngredient::where('product_id', $this->model->id)
|
||||||
|
->where('recipe_type', 'product')
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
foreach ($ids as $index => $ingredientId) {
|
||||||
|
$factor = $defaults[$ingredientId] ?? 1.10;
|
||||||
|
ProductIngredient::create([
|
||||||
|
'product_id' => $this->model->id,
|
||||||
|
'ingredient_id' => $ingredientId,
|
||||||
|
'pos' => $index,
|
||||||
|
'gram' => null,
|
||||||
|
'factor' => $factor,
|
||||||
|
'recipe_type' => 'product',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['pi_ingredient_id']) && is_array($data['pi_ingredient_id'])) {
|
||||||
|
$ids = $data['pi_ingredient_id'];
|
||||||
|
$grams = $data['pi_gram'] ?? [];
|
||||||
|
$factors = $data['pi_factor'] ?? [];
|
||||||
|
|
||||||
|
ProductIngredient::where('product_id', $this->model->id)
|
||||||
|
->where('recipe_type', 'product')
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
foreach ($ids as $index => $ingredientId) {
|
||||||
|
$ingredientId = (int) $ingredientId;
|
||||||
|
if ($ingredientId <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ProductIngredient::create([
|
||||||
|
'product_id' => $this->model->id,
|
||||||
|
'ingredient_id' => $ingredientId,
|
||||||
|
'pos' => $index,
|
||||||
|
'gram' => $this->parseNullableDecimal($grams[$index] ?? null),
|
||||||
|
'factor' => $this->parseFactor($factors[$index] ?? null, $ingredientId),
|
||||||
|
'recipe_type' => 'product',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProductIngredient::where('product_id', $this->model->id)
|
||||||
|
->where('recipe_type', 'product')
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateManufacturerIngredients(array $data = []): bool
|
||||||
|
{
|
||||||
|
if (! array_key_exists('manufacturer_inci_sync_sent', $data)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['mfg_ingredient_id']) && is_array($data['mfg_ingredient_id'])) {
|
||||||
|
$ids = $data['mfg_ingredient_id'];
|
||||||
|
$grams = $data['mfg_gram'] ?? [];
|
||||||
|
$factors = $data['mfg_factor'] ?? [];
|
||||||
|
|
||||||
|
ProductIngredient::where('product_id', $this->model->id)
|
||||||
|
->where('recipe_type', 'manufacturer')
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
foreach ($ids as $index => $ingredientId) {
|
||||||
|
$ingredientId = (int) $ingredientId;
|
||||||
|
if ($ingredientId <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ProductIngredient::create([
|
||||||
|
'product_id' => $this->model->id,
|
||||||
|
'ingredient_id' => $ingredientId,
|
||||||
|
'pos' => $index,
|
||||||
|
'gram' => $this->parseNullableDecimal($grams[$index] ?? null),
|
||||||
|
'factor' => $this->parseFactor($factors[$index] ?? null, $ingredientId),
|
||||||
|
'recipe_type' => 'manufacturer',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProductIngredient::where('product_id', $this->model->id)
|
||||||
|
->where('recipe_type', 'manufacturer')
|
||||||
|
->delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseNullableDecimal(mixed $value): ?float
|
||||||
|
{
|
||||||
|
if ($value === null || $value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (is_numeric($value)) {
|
||||||
|
return (float) $value;
|
||||||
|
}
|
||||||
|
$normalized = reFormatNumber((string) $value);
|
||||||
|
|
||||||
|
return $normalized !== null && $normalized !== '' ? (float) $normalized : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseFactor(mixed $value, int $ingredientId): float
|
||||||
|
{
|
||||||
|
if ($value === null || $value === '') {
|
||||||
|
$default = Ingredient::whereKey($ingredientId)->value('default_factor');
|
||||||
|
|
||||||
|
return $default !== null ? (float) $default : 1.10;
|
||||||
|
}
|
||||||
|
if (is_numeric($value)) {
|
||||||
|
return (float) $value;
|
||||||
|
}
|
||||||
|
$normalized = reFormatNumber((string) $value);
|
||||||
|
|
||||||
|
return $normalized !== null && $normalized !== '' ? (float) $normalized : 1.10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateCategories($data = [])
|
||||||
{
|
{
|
||||||
foreach ($this->model->categories as $category) {
|
foreach ($this->model->categories as $category) {
|
||||||
if(($pos = array_search($category->category_id, $data)) !== FALSE){
|
if (($pos = array_search($category->category_id, $data)) !== false) {
|
||||||
unset($data[$pos]);
|
unset($data[$pos]);
|
||||||
}else{
|
} else {
|
||||||
$category->delete();
|
$category->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//set attr
|
// set attr
|
||||||
if(is_array($data)){
|
if (is_array($data)) {
|
||||||
foreach ($data as $id) {
|
foreach ($data as $id) {
|
||||||
ProductCategory::create([
|
ProductCategory::create([
|
||||||
'product_id' => $this->model->id,
|
'product_id' => $this->model->id,
|
||||||
|
|
@ -97,20 +246,21 @@ class ProductRepository extends BaseRepository {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateAttributes($data = array())
|
public function updateAttributes($data = [])
|
||||||
{
|
{
|
||||||
foreach ($this->model->attributes as $attribute) {
|
foreach ($this->model->attributes as $attribute) {
|
||||||
if(($pos = array_search($attribute->attribute_id, $data)) !== FALSE){
|
if (($pos = array_search($attribute->attribute_id, $data)) !== false) {
|
||||||
unset($data[$pos]);
|
unset($data[$pos]);
|
||||||
}else{
|
} else {
|
||||||
$attribute->delete();
|
$attribute->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//set attr
|
// set attr
|
||||||
if(is_array($data)){
|
if (is_array($data)) {
|
||||||
foreach ($data as $id) {
|
foreach ($data as $id) {
|
||||||
$attribute = Attribute::findOrFail($id);
|
$attribute = Attribute::findOrFail($id);
|
||||||
ProductAttribute::create([
|
ProductAttribute::create([
|
||||||
|
|
@ -120,20 +270,21 @@ class ProductRepository extends BaseRepository {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateWLVariants($data = array())
|
public function updateWLVariants($data = [])
|
||||||
{
|
{
|
||||||
foreach ($this->model->attribute_variants as $variant) {
|
foreach ($this->model->attribute_variants as $variant) {
|
||||||
if(($pos = array_search($variant->attribute_id, $data)) !== FALSE){
|
if (($pos = array_search($variant->attribute_id, $data)) !== false) {
|
||||||
unset($data[$pos]);
|
unset($data[$pos]);
|
||||||
}else{
|
} else {
|
||||||
$variant->delete();
|
$variant->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//set attr
|
// set attr
|
||||||
if(is_array($data)){
|
if (is_array($data)) {
|
||||||
foreach ($data as $id) {
|
foreach ($data as $id) {
|
||||||
$attribute = Attribute::findOrFail($id);
|
$attribute = Attribute::findOrFail($id);
|
||||||
ProductAttribute::create([
|
ProductAttribute::create([
|
||||||
|
|
@ -143,34 +294,32 @@ class ProductRepository extends BaseRepository {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateWLImageAttributs($attributes = [], $variants = [])
|
public function updateWLImageAttributs($attributes = [], $variants = [])
|
||||||
{
|
{
|
||||||
//abgleich der attributes gegen die variants
|
// abgleich der attributes gegen die variants
|
||||||
foreach ($attributes as $image => $value) {
|
foreach ($attributes as $image => $value) {
|
||||||
foreach ($value as $k => $val) {
|
foreach ($value as $k => $val) {
|
||||||
if(!is_array($variants) || !in_array($val, $variants)){
|
if (! is_array($variants) || ! in_array($val, $variants)) {
|
||||||
unset($attributes[$image][$k]);
|
unset($attributes[$image][$k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($this->model->whitelabel_images as $image) {
|
foreach ($this->model->whitelabel_images as $image) {
|
||||||
$image->update([
|
$image->update([
|
||||||
'attributes' => isset($attributes[$image->id]) ? $attributes[$image->id] : NULL,
|
'attributes' => isset($attributes[$image->id]) ? $attributes[$image->id] : null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function updateCountryPrices($data)
|
public function updateCountryPrices($data)
|
||||||
{
|
{
|
||||||
if(!isset($data['country_prices']) || !is_array($data['country_prices'])){
|
if (! isset($data['country_prices']) || ! is_array($data['country_prices'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
foreach ($data['country_prices'] as $k => $country_id) {
|
foreach ($data['country_prices'] as $k => $country_id) {
|
||||||
|
|
@ -186,53 +335,69 @@ class ProductRepository extends BaseRepository {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function copy($model)
|
public function copy($model)
|
||||||
{
|
{
|
||||||
$this->model = $model->replicate();
|
$this->model = $model->replicate();
|
||||||
$this->model->name = "Kopie: ".$this->model->name;
|
$this->model->name = 'Kopie: '.$this->model->name;
|
||||||
$this->model->wp_number = null;
|
$this->model->wp_number = null;
|
||||||
$this->model->save();
|
$this->model->save();
|
||||||
|
|
||||||
//categories
|
// categories
|
||||||
foreach ($model->categories as $category){
|
foreach ($model->categories as $category) {
|
||||||
ProductCategory::create([
|
ProductCategory::create([
|
||||||
'product_id' => $this->model->id,
|
'product_id' => $this->model->id,
|
||||||
'category_id' => $category->category_id,
|
'category_id' => $category->category_id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//attributes
|
// attributes
|
||||||
foreach ($model->attributes as $attribute){
|
foreach ($model->attributes as $attribute) {
|
||||||
ProductAttribute::create([
|
ProductAttribute::create([
|
||||||
'product_id' => $this->model->id,
|
'product_id' => $this->model->id,
|
||||||
'type_id' => $this->model->attribute_type_id,
|
'type_id' => $attribute->type_id,
|
||||||
'attribute_id' => $attribute->attribute_id,
|
'attribute_id' => $attribute->attribute_id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
//INCS
|
foreach ($model->p_ingredients()->orderByPivot('pos')->get() as $ing) {
|
||||||
$ingredients = $model->p_ingredients()->pluck('ingredient_id')->toArray();
|
|
||||||
if(is_array($ingredients)){
|
|
||||||
foreach ($ingredients as $incs_id){
|
|
||||||
ProductIngredient::create([
|
ProductIngredient::create([
|
||||||
'product_id' => $this->model->id,
|
'product_id' => $this->model->id,
|
||||||
'ingredient_id' => $incs_id,
|
'ingredient_id' => $ing->id,
|
||||||
|
'pos' => (int) ($ing->pivot->pos ?? 0),
|
||||||
|
'gram' => $ing->pivot->gram,
|
||||||
|
'factor' => $ing->pivot->factor !== null ? (float) $ing->pivot->factor : 1.10,
|
||||||
|
'recipe_type' => 'product',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($model->manufacturer_ingredients()->orderByPivot('pos')->get() as $ing) {
|
||||||
|
ProductIngredient::create([
|
||||||
|
'product_id' => $this->model->id,
|
||||||
|
'ingredient_id' => $ing->id,
|
||||||
|
'pos' => (int) ($ing->pivot->pos ?? 0),
|
||||||
|
'gram' => $ing->pivot->gram,
|
||||||
|
'factor' => $ing->pivot->factor !== null ? (float) $ing->pivot->factor : 1.10,
|
||||||
|
'recipe_type' => 'manufacturer',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$packSync = [];
|
||||||
|
foreach ($model->packagings()->orderByPivot('pos')->get() as $pack) {
|
||||||
|
$packSync[$pack->id] = [
|
||||||
|
'quantity' => $pack->pivot->quantity !== null ? (float) $pack->pivot->quantity : 1.0,
|
||||||
|
'pos' => (int) ($pack->pivot->pos ?? 0),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$this->model->packagings()->sync($packSync);
|
||||||
|
|
||||||
//images
|
// images
|
||||||
foreach ($model->images as $image){
|
foreach ($model->images as $image) {
|
||||||
$name = \App\Services\Slim::sanitizeFileName($image->original_name);
|
$name = Slim::sanitizeFileName($image->original_name);
|
||||||
$name = uniqid() . '_' . $name;
|
$name = uniqid().'_'.$name;
|
||||||
|
|
||||||
//copy
|
// copy
|
||||||
$data = \Storage::disk('public')->copy(
|
$data = \Storage::disk('public')->copy(
|
||||||
'images/product/'.$image->product_id.'/'.$image->filename,
|
'images/product/'.$image->product_id.'/'.$image->filename,
|
||||||
'images/product/'.$this->model->id.'/'.$name
|
'images/product/'.$this->model->id.'/'.$name
|
||||||
|
|
@ -246,7 +411,7 @@ class ProductRepository extends BaseRepository {
|
||||||
'ext' => $image->ext,
|
'ext' => $image->ext,
|
||||||
'mine' => $image->mine,
|
'mine' => $image->mine,
|
||||||
'size' => $image->size,
|
'size' => $image->size,
|
||||||
'attributes' => $image->attributes
|
'attributes' => $image->attributes,
|
||||||
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
@ -254,10 +419,5 @@ class ProductRepository extends BaseRepository {
|
||||||
return $this->model;
|
return $this->model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function delete() {}
|
||||||
public function delete()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
21
app/Repositories/ProductionRepository.php
Normal file
21
app/Repositories/ProductionRepository.php
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\Production;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
|
class ProductionRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return Collection<int, Production>
|
||||||
|
*/
|
||||||
|
public function listForIndex(): Collection
|
||||||
|
{
|
||||||
|
return Production::query()
|
||||||
|
->with(['product', 'location', 'producedByUser'])
|
||||||
|
->orderByDesc('produced_at')
|
||||||
|
->orderByDesc('id')
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
}
|
||||||
92
app/Repositories/StockEntryRepository.php
Normal file
92
app/Repositories/StockEntryRepository.php
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\StockEntry;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
|
class StockEntryRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public function create(array $data): StockEntry
|
||||||
|
{
|
||||||
|
$data['unit'] = ($data['entry_type'] ?? '') === 'ingredient' ? 'gram' : 'piece';
|
||||||
|
|
||||||
|
return StockEntry::query()->create($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public function update(StockEntry $stockEntry, array $data): StockEntry
|
||||||
|
{
|
||||||
|
if (array_key_exists('entry_type', $data)) {
|
||||||
|
$data['unit'] = ($data['entry_type'] ?? '') === 'ingredient' ? 'gram' : 'piece';
|
||||||
|
}
|
||||||
|
|
||||||
|
$stockEntry->update($data);
|
||||||
|
|
||||||
|
return $stockEntry->fresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public function receive(StockEntry $stockEntry, array $data): StockEntry
|
||||||
|
{
|
||||||
|
$data['status'] = 'received';
|
||||||
|
$data['received_by'] = auth()->id();
|
||||||
|
|
||||||
|
$stockEntry->update($data);
|
||||||
|
|
||||||
|
return $stockEntry->fresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection<int, StockEntry>
|
||||||
|
*/
|
||||||
|
public function getByStatus(string $status): Collection
|
||||||
|
{
|
||||||
|
return StockEntry::query()
|
||||||
|
->where('status', $status)
|
||||||
|
->orderByDesc('ordered_at')
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection<int, StockEntry>
|
||||||
|
*/
|
||||||
|
public function getForIngredient(int $ingredientId): Collection
|
||||||
|
{
|
||||||
|
return StockEntry::query()
|
||||||
|
->where('ingredient_id', $ingredientId)
|
||||||
|
->where('status', 'received')
|
||||||
|
->orderByDesc('received_at')
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liste: Pending zuerst (neuestes Bestelldatum), dann Received (neuester Eingang).
|
||||||
|
*
|
||||||
|
* @return Collection<int, StockEntry>
|
||||||
|
*/
|
||||||
|
public function listForIndex(): Collection
|
||||||
|
{
|
||||||
|
$with = [
|
||||||
|
'ingredient',
|
||||||
|
'packagingItem',
|
||||||
|
'supplier',
|
||||||
|
'location',
|
||||||
|
'quality',
|
||||||
|
'orderedByUser',
|
||||||
|
'receivedByUser',
|
||||||
|
];
|
||||||
|
|
||||||
|
$pending = StockEntry::query()->with($with)->where('status', 'pending')->orderByDesc('ordered_at')->get();
|
||||||
|
$received = StockEntry::query()->with($with)->where('status', 'received')->orderByDesc('received_at')->get();
|
||||||
|
|
||||||
|
return $pending->concat($received)->values();
|
||||||
|
}
|
||||||
|
}
|
||||||
58
app/Repositories/SupplierRepository.php
Normal file
58
app/Repositories/SupplierRepository.php
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\Supplier;
|
||||||
|
|
||||||
|
class SupplierRepository
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public function create(array $data): Supplier
|
||||||
|
{
|
||||||
|
$supplier = Supplier::create($this->extractSupplierAttributes($data));
|
||||||
|
$this->syncCategories($supplier, $data['supplier_category_ids'] ?? []);
|
||||||
|
|
||||||
|
return $supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public function update(Supplier $supplier, array $data): Supplier
|
||||||
|
{
|
||||||
|
$supplier->update($this->extractSupplierAttributes($data));
|
||||||
|
$this->syncCategories($supplier, $data['supplier_category_ids'] ?? []);
|
||||||
|
|
||||||
|
return $supplier->fresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int|string>|null $categoryIds
|
||||||
|
*/
|
||||||
|
public function syncCategories(Supplier $supplier, array $categoryIds): void
|
||||||
|
{
|
||||||
|
$ids = array_values(array_filter(array_map('intval', $categoryIds)));
|
||||||
|
|
||||||
|
$supplier->supplierCategories()->sync($ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
protected function extractSupplierAttributes(array $data): array
|
||||||
|
{
|
||||||
|
return collect($data)->only([
|
||||||
|
'name',
|
||||||
|
'url',
|
||||||
|
'contact_person',
|
||||||
|
'email',
|
||||||
|
'phone',
|
||||||
|
'country_id',
|
||||||
|
'notes',
|
||||||
|
'active',
|
||||||
|
])->all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,60 +2,54 @@
|
||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
use Str;
|
use App\Models\PaymentMethod;
|
||||||
use App\User;
|
|
||||||
use stdClass;
|
|
||||||
use Validator;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use App\Models\UserAccount;
|
use App\Models\UserAccount;
|
||||||
use App\Models\UserRegister;
|
use App\Models\UserRegister;
|
||||||
use App\Models\PaymentMethod;
|
|
||||||
use App\Services\UserService;
|
use App\Services\UserService;
|
||||||
|
use App\User;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use stdClass;
|
||||||
|
use Validator;
|
||||||
|
|
||||||
class UserRepository extends BaseRepository {
|
class UserRepository extends BaseRepository
|
||||||
|
{
|
||||||
|
|
||||||
public function __construct(User $model)
|
public function __construct(User $model)
|
||||||
{
|
{
|
||||||
$this->model = $model;
|
$this->model = $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function update($data)
|
public function update($data)
|
||||||
{
|
{
|
||||||
|
|
||||||
if($data['user_id'] === "new" || $data['user_id'] == 0){
|
if ($data['user_id'] === 'new' || $data['user_id'] == 0) {
|
||||||
|
|
||||||
$this->model = User::create([
|
$this->model = User::create([
|
||||||
'email' => $data['email'],
|
'email' => $data['email'],
|
||||||
'password' => env('APP_KEY'),
|
'password' => Hash::make(config('app.key')),
|
||||||
]);
|
]);
|
||||||
$this->model->payment_methods = PaymentMethod::getDefaultAsArray();
|
$this->model->payment_methods = PaymentMethod::getDefaultAsArray();
|
||||||
$this->model->save();
|
$this->model->save();
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
$this->model = $this->getById($data['user_id']);
|
$this->model = $this->getById($data['user_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$this->model->account_id){
|
if (! $this->model->account_id) {
|
||||||
$account = new UserAccount();
|
$account = new UserAccount;
|
||||||
}else{
|
} else {
|
||||||
$account = $this->model->account;
|
$account = $this->model->account;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['same_as_billing'] = !isset($data['same_as_billing']) ? 0 : 1;
|
$data['same_as_billing'] = ! isset($data['same_as_billing']) ? 0 : 1;
|
||||||
|
|
||||||
$data['birthday_day'] = isset($data['birthday_day']) ? $data['birthday_day'] : 1;
|
$data['birthday_day'] = isset($data['birthday_day']) ? $data['birthday_day'] : 1;
|
||||||
$data['birthday_month'] = isset($data['birthday_month']) ? $data['birthday_month'] : 1;
|
$data['birthday_month'] = isset($data['birthday_month']) ? $data['birthday_month'] : 1;
|
||||||
$data['birthday_year'] = isset($data['birthday_year']) ? $data['birthday_year'] : 1900;
|
$data['birthday_year'] = isset($data['birthday_year']) ? $data['birthday_year'] : 1900;
|
||||||
$data['birthday'] = $data['birthday_day'].".".$data['birthday_month'].".".$data['birthday_year'];
|
$data['birthday'] = $data['birthday_day'].'.'.$data['birthday_month'].'.'.$data['birthday_year'];
|
||||||
$data['birthday'] = $data['birthday'] == "1.1.1900" ? null : $data['birthday'];
|
$data['birthday'] = $data['birthday'] == '1.1.1900' ? null : $data['birthday'];
|
||||||
|
|
||||||
$account->fill($data)->save();
|
$account->fill($data)->save();
|
||||||
|
|
||||||
if(!$this->model->account_id){
|
if (! $this->model->account_id) {
|
||||||
$this->model->account_id = $account->id;
|
$this->model->account_id = $account->id;
|
||||||
$this->model->save();
|
$this->model->save();
|
||||||
}
|
}
|
||||||
|
|
@ -63,9 +57,10 @@ class UserRepository extends BaseRepository {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createUserRegister($data){
|
public function createUserRegister($data)
|
||||||
|
{
|
||||||
|
|
||||||
$obj = new stdClass();
|
$obj = new stdClass;
|
||||||
|
|
||||||
$obj->email = $data['email'];
|
$obj->email = $data['email'];
|
||||||
$obj->password = Hash::make($data['password']);
|
$obj->password = Hash::make($data['password']);
|
||||||
|
|
@ -80,7 +75,7 @@ class UserRepository extends BaseRepository {
|
||||||
$obj->confirmation_code_to = date('Y-m-d H:i:s', strtotime('+1 week'));
|
$obj->confirmation_code_to = date('Y-m-d H:i:s', strtotime('+1 week'));
|
||||||
$obj->confirmation_code_remider = 0;
|
$obj->confirmation_code_remider = 0;
|
||||||
$obj->m_sponsor = config('app.main_user_id');
|
$obj->m_sponsor = config('app.main_user_id');
|
||||||
if(isset($data['from_member_id'])){
|
if (isset($data['from_member_id'])) {
|
||||||
$obj->m_sponsor = (int) str_replace('gs', '', $data['from_member_id']) - config('main.add_number_id');
|
$obj->m_sponsor = (int) str_replace('gs', '', $data['from_member_id']) - config('main.add_number_id');
|
||||||
}
|
}
|
||||||
$confirmation_code = UserService::createConfirmationCode();
|
$confirmation_code = UserService::createConfirmationCode();
|
||||||
|
|
@ -88,24 +83,26 @@ class UserRepository extends BaseRepository {
|
||||||
UserRegister::create([
|
UserRegister::create([
|
||||||
'identifier' => $data['email'],
|
'identifier' => $data['email'],
|
||||||
'instance' => $confirmation_code,
|
'instance' => $confirmation_code,
|
||||||
'content' => $obj
|
'content' => $obj,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $obj;
|
return $obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearUserRegister(){
|
public function clearUserRegister()
|
||||||
$cleartime = date('Y-m-d H:i:s', strtotime('-1 day')); //gestern -24h
|
{
|
||||||
|
$cleartime = date('Y-m-d H:i:s', strtotime('-1 day')); // gestern -24h
|
||||||
UserRegister::where('created_at', '<', $cleartime)->delete();
|
UserRegister::where('created_at', '<', $cleartime)->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create($UserRegister){
|
public function create($UserRegister)
|
||||||
|
{
|
||||||
|
|
||||||
$userObj = $UserRegister->content;
|
$userObj = $UserRegister->content;
|
||||||
|
|
||||||
$user = User::create([
|
$user = User::create([
|
||||||
'email' => $userObj->email,
|
'email' => $userObj->email,
|
||||||
'password' =>$userObj->password,
|
'password' => $userObj->password,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$account = UserAccount::create([
|
$account = UserAccount::create([
|
||||||
|
|
@ -122,7 +119,7 @@ class UserRepository extends BaseRepository {
|
||||||
$user->confirmation_code_to = null;
|
$user->confirmation_code_to = null;
|
||||||
$user->confirmation_code_remider = 0;
|
$user->confirmation_code_remider = 0;
|
||||||
$user->confirmation_date = now();
|
$user->confirmation_date = now();
|
||||||
$user->lang = !empty(\App::getLocale()) ? \App::getLocale() : "de";
|
$user->lang = ! empty(\App::getLocale()) ? \App::getLocale() : 'de';
|
||||||
$user->m_sponsor = $userObj->m_sponsor;
|
$user->m_sponsor = $userObj->m_sponsor;
|
||||||
|
|
||||||
$user->account_id = $account->id;
|
$user->account_id = $account->id;
|
||||||
|
|
@ -132,7 +129,7 @@ class UserRepository extends BaseRepository {
|
||||||
|
|
||||||
$user = User::find($user->id);
|
$user = User::find($user->id);
|
||||||
|
|
||||||
//clear
|
// clear
|
||||||
$identifier = $UserRegister->identifier;
|
$identifier = $UserRegister->identifier;
|
||||||
UserRegister::where('identifier', $identifier)->delete();
|
UserRegister::where('identifier', $identifier)->delete();
|
||||||
|
|
||||||
|
|
@ -141,13 +138,13 @@ class UserRepository extends BaseRepository {
|
||||||
|
|
||||||
public function deleteUser(User $user)
|
public function deleteUser(User $user)
|
||||||
{
|
{
|
||||||
if($user->account){
|
if ($user->account) {
|
||||||
$user->account->delete();
|
$user->account->delete();
|
||||||
}
|
}
|
||||||
$user->email = "delete".time();
|
$user->email = 'delete'.time();
|
||||||
$user->password = "delete".time();
|
$user->password = 'delete'.time();
|
||||||
$user->confirmed = 0;
|
$user->confirmed = 0;
|
||||||
$user->confirmation_code = "delete".time();
|
$user->confirmation_code = 'delete'.time();
|
||||||
$user->confirmation_date = null;
|
$user->confirmation_date = null;
|
||||||
$user->confirmation_code_to = null;
|
$user->confirmation_code_to = null;
|
||||||
$user->confirmation_code_remider = 2;
|
$user->confirmation_code_remider = 2;
|
||||||
|
|
@ -162,31 +159,35 @@ class UserRepository extends BaseRepository {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reverse_charge_validate($data, $user, $route){
|
public function reverse_charge_validate($data, $user, $route)
|
||||||
|
{
|
||||||
|
|
||||||
if(isset($data['action']) && $data['action'] == 'reverse_charge_validate'){
|
if (isset($data['action']) && $data['action'] == 'reverse_charge_validate') {
|
||||||
$rules = array(
|
$rules = [
|
||||||
'tax_identification_number' => 'required',
|
'tax_identification_number' => 'required',
|
||||||
);
|
];
|
||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
$data = [
|
$data = [
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
];
|
];
|
||||||
|
|
||||||
return redirect($route)->withErrors($validator)->withInput($data);
|
return redirect($route)->withErrors($validator)->withInput($data);
|
||||||
}
|
}
|
||||||
$ret = $this->reverse_charge_activate($data, $user);
|
$ret = $this->reverse_charge_activate($data, $user);
|
||||||
if($ret === 'error'){
|
if ($ret === 'error') {
|
||||||
$validator = Validator::make($data, []);
|
$validator = Validator::make($data, []);
|
||||||
$validator->errors()->add('tax_identification_number_validated', __('msg.VATID_could_not_be_validated'));
|
$validator->errors()->add('tax_identification_number_validated', __('msg.VATID_could_not_be_validated'));
|
||||||
$data['reverse_charge'] = 0;
|
$data['reverse_charge'] = 0;
|
||||||
$data = [
|
$data = [
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
];
|
];
|
||||||
|
|
||||||
return redirect($route.'#user-vat-validation')->withErrors($validator)->withInput($data);
|
return redirect($route.'#user-vat-validation')->withErrors($validator)->withInput($data);
|
||||||
}
|
}
|
||||||
if($ret === 'valid'){
|
if ($ret === 'valid') {
|
||||||
\Session()->flash('alert-success', __('msg.VATID_successfully_entered'));
|
\Session()->flash('alert-success', __('msg.VATID_successfully_entered'));
|
||||||
|
|
||||||
return redirect($route.'#user-vat-validation')->withInput($data);
|
return redirect($route.'#user-vat-validation')->withInput($data);
|
||||||
|
|
||||||
return redirect($route.'#user-vat-validation')->withInput($data);
|
return redirect($route.'#user-vat-validation')->withInput($data);
|
||||||
|
|
@ -194,8 +195,9 @@ class UserRepository extends BaseRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reverse_charge_delete($data, $user, $route){
|
public function reverse_charge_delete($data, $user, $route)
|
||||||
if(isset($data['action']) && $data['action'] == 'reverse_charge_delete'){
|
{
|
||||||
|
if (isset($data['action']) && $data['action'] == 'reverse_charge_delete') {
|
||||||
$user->account->tax_identification_number = '';
|
$user->account->tax_identification_number = '';
|
||||||
$user->account->reverse_charge = 0;
|
$user->account->reverse_charge = 0;
|
||||||
$user->account->reverse_charge_code = null;
|
$user->account->reverse_charge_code = null;
|
||||||
|
|
@ -203,11 +205,13 @@ class UserRepository extends BaseRepository {
|
||||||
$user->account->save();
|
$user->account->save();
|
||||||
$data['tax_identification_number'] = '';
|
$data['tax_identification_number'] = '';
|
||||||
\Session()->flash('alert-success', __('msg.reverse_charge_procedure_and_VATID_deleted'));
|
\Session()->flash('alert-success', __('msg.reverse_charge_procedure_and_VATID_deleted'));
|
||||||
|
|
||||||
return redirect($route.'#user-vat-validation')->withInput($data);
|
return redirect($route.'#user-vat-validation')->withInput($data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reverse_charge_activate($data, $user){
|
public function reverse_charge_activate($data, $user)
|
||||||
|
{
|
||||||
|
|
||||||
/* 'AT' => 'AT-Oesterreich',
|
/* 'AT' => 'AT-Oesterreich',
|
||||||
'BE' => 'BE-Belgien',
|
'BE' => 'BE-Belgien',
|
||||||
|
|
@ -239,11 +243,11 @@ class UserRepository extends BaseRepository {
|
||||||
'XI' => 'XI-Nordirland', */
|
'XI' => 'XI-Nordirland', */
|
||||||
$countryCode = 'DE';
|
$countryCode = 'DE';
|
||||||
|
|
||||||
if($user->account->country_id){
|
if ($user->account->country_id) {
|
||||||
$countryCode = $user->account->country->code;
|
$countryCode = $user->account->country->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
$vatid = str_replace(array(' ', '.', '-', ',', ', '), '', trim($data['tax_identification_number']));
|
$vatid = str_replace([' ', '.', '-', ',', ', '], '', trim($data['tax_identification_number']));
|
||||||
$cc = substr($vatid, 0, 2);
|
$cc = substr($vatid, 0, 2);
|
||||||
$vatNo = substr($vatid, 2);
|
$vatNo = substr($vatid, 2);
|
||||||
|
|
||||||
|
|
@ -255,26 +259,25 @@ class UserRepository extends BaseRepository {
|
||||||
'ssl' => [
|
'ssl' => [
|
||||||
'verify_peer' => false,
|
'verify_peer' => false,
|
||||||
'verify_peer_name' => false,
|
'verify_peer_name' => false,
|
||||||
'allow_self_signed' => true
|
'allow_self_signed' => true,
|
||||||
|
],
|
||||||
]
|
]
|
||||||
]
|
),
|
||||||
)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$client = new \SoapClient("https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl", $options);
|
$client = new \SoapClient('https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', $options);
|
||||||
$result = $client->checkVat(['countryCode' => $countryCode, 'vatNumber' => $vatNo]);
|
$result = $client->checkVat(['countryCode' => $countryCode, 'vatNumber' => $vatNo]);
|
||||||
|
|
||||||
if($result->valid == true) {
|
if ($result->valid == true) {
|
||||||
$user->account->tax_identification_number = $data['tax_identification_number'];
|
$user->account->tax_identification_number = $data['tax_identification_number'];
|
||||||
$user->account->reverse_charge = 1;
|
$user->account->reverse_charge = 1;
|
||||||
$user->account->reverse_charge_code = $countryCode;
|
$user->account->reverse_charge_code = $countryCode;
|
||||||
$user->account->reverse_charge_valid = now();
|
$user->account->reverse_charge_valid = now();
|
||||||
$user->account->save();
|
$user->account->save();
|
||||||
|
|
||||||
return 'valid';
|
return 'valid';
|
||||||
} else {
|
} else {
|
||||||
return 'error';
|
return 'error';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,23 +1,21 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\User;
|
|
||||||
use App\Models\Country;
|
|
||||||
use App\Models\Product;
|
|
||||||
use App\Models\Category;
|
|
||||||
use App\Models\LeadType;
|
|
||||||
use App\Models\Attribute;
|
use App\Models\Attribute;
|
||||||
use App\Models\UserLevel;
|
|
||||||
use App\Models\Ingredient;
|
|
||||||
use App\Models\ShoppingUser;
|
|
||||||
use App\Models\AttributeType;
|
use App\Models\AttributeType;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\Country;
|
||||||
|
use App\Models\Ingredient;
|
||||||
|
use App\Models\LeadType;
|
||||||
|
use App\Models\Product;
|
||||||
use App\Models\ShippingCountry;
|
use App\Models\ShippingCountry;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use App\Models\ShoppingUser;
|
||||||
|
use App\Models\UserLevel;
|
||||||
|
use App\User;
|
||||||
|
|
||||||
class HTMLHelper
|
class HTMLHelper
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static $months = [
|
public static $months = [
|
||||||
1 => 'January',
|
1 => 'January',
|
||||||
2 => 'February',
|
2 => 'February',
|
||||||
|
|
@ -30,47 +28,50 @@ class HTMLHelper
|
||||||
9 => 'September',
|
9 => 'September',
|
||||||
10 => 'October',
|
10 => 'October',
|
||||||
11 => 'November',
|
11 => 'November',
|
||||||
12 => 'December'
|
12 => 'December',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static $roles = [
|
private static $roles = [
|
||||||
0 => 'Kunde',
|
0 => 'Kunde',
|
||||||
1 => 'Redakteur',
|
1 => 'Redakteur',
|
||||||
7 => 'Admin',
|
7 => 'Admin',
|
||||||
8 => 'SuperAdmin',
|
8 => 'SuperAdmin',
|
||||||
9 => 'SySAdmin',
|
9 => 'SySAdmin',
|
||||||
//10 => "API",
|
// 10 => "API",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public static function getMonth($i)
|
||||||
public static function getMonth($i){
|
{
|
||||||
return self::$months[intval($i)];
|
return self::$months[intval($i)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getTransMonths($full = false){
|
public static function getTransMonths($full = false)
|
||||||
|
{
|
||||||
$ret = [];
|
$ret = [];
|
||||||
foreach(self::$months as $key=>$val){
|
foreach (self::$months as $key => $val) {
|
||||||
$ret[$key] = trans('cal.months.'.$val);
|
$ret[$key] = trans('cal.months.'.$val);
|
||||||
}
|
}
|
||||||
if($full){ //ganzes Jahr
|
if ($full) { // ganzes Jahr
|
||||||
$ret[13] = trans('cal.months.full_year');
|
$ret[13] = trans('cal.months.full_year');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getYearRange($start = 2021)
|
public static function getYearRange($start = 2021)
|
||||||
{
|
{
|
||||||
$end = date("Y");
|
$end = date('Y');
|
||||||
|
|
||||||
return array_reverse(range($start, $end));
|
return array_reverse(range($start, $end));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getRoleLabel($role_id = 0){
|
public static function getRoleLabel($role_id = 0)
|
||||||
|
{
|
||||||
return '<span class="badge badge-pill '.self::getLabel($role_id).'">'.self::$roles[$role_id].'</span>';
|
return '<span class="badge badge-pill '.self::getLabel($role_id).'">'.self::$roles[$role_id].'</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getLabel($id){
|
public static function getLabel($id)
|
||||||
|
{
|
||||||
switch ($id) {
|
switch ($id) {
|
||||||
case 0:
|
case 0:
|
||||||
return 'badge-default';
|
return 'badge-default';
|
||||||
|
|
@ -94,31 +95,32 @@ class HTMLHelper
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCustomListOf($name, $select){
|
public static function getCustomListOf($name, $select)
|
||||||
$ret = "";
|
{
|
||||||
if($name === 'day'){
|
$ret = '';
|
||||||
|
if ($name === 'day') {
|
||||||
$start = 1;
|
$start = 1;
|
||||||
$end = 31;
|
$end = 31;
|
||||||
$values = range($start, $end);
|
$values = range($start, $end);
|
||||||
$ret = '<option value="">'.__('Tag').'</option>\n';
|
$ret = '<option value="">'.__('Tag').'</option>\n';
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value == $select) ? 'selected="selected"' : '';
|
$attr = ($value == $select) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($name === 'month'){
|
if ($name === 'month') {
|
||||||
$ret = '<option value="">'.__('Monat').'</option>\n';
|
$ret = '<option value="">'.__('Monat').'</option>\n';
|
||||||
foreach (self::$months as $key=>$value){
|
foreach (self::$months as $key => $value) {
|
||||||
$attr = ($key == $select) ? 'selected="selected"' : '';
|
$attr = ($key == $select) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($name === 'year'){
|
if ($name === 'year') {
|
||||||
$start = date("Y", strtotime("-5 years", time()));
|
$start = date('Y', strtotime('-5 years', time()));
|
||||||
$end = date("Y", strtotime("-90 years", time()));
|
$end = date('Y', strtotime('-90 years', time()));
|
||||||
$values = range($start, $end);
|
$values = range($start, $end);
|
||||||
$ret = '<option value="">'.__('Jahr').'</option>\n';
|
$ret = '<option value="">'.__('Jahr').'</option>\n';
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value == $select) ? 'selected="selected"' : '';
|
$attr = ($value == $select) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
@ -127,14 +129,16 @@ class HTMLHelper
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
public static function setContentReadMore($content){
|
|
||||||
|
public static function setContentReadMore($content)
|
||||||
|
{
|
||||||
|
|
||||||
$sep = '##mehr lesen##';
|
$sep = '##mehr lesen##';
|
||||||
if(strpos($content, $sep) !== false){
|
if (strpos($content, $sep) !== false) {
|
||||||
$name = 'collapse_'.random_int(1000, 10000);
|
$name = 'collapse_'.random_int(1000, 10000);
|
||||||
$split = explode($sep, $content);
|
$split = explode($sep, $content);
|
||||||
$first = isset($split[0]) ? $split[0] : "";
|
$first = isset($split[0]) ? $split[0] : '';
|
||||||
$text = isset($split[1]) ? $split[1] : "";
|
$text = isset($split[1]) ? $split[1] : '';
|
||||||
|
|
||||||
$content = $first;
|
$content = $first;
|
||||||
$content .= '<br><a class="btn btn-primary btn-sm mt-2 collapsed" data-toggle="collapse" href="#'.$name.'" role="button" aria-expanded="false" aria-controls="'.$name.'">
|
$content .= '<br><a class="btn btn-primary btn-sm mt-2 collapsed" data-toggle="collapse" href="#'.$name.'" role="button" aria-expanded="false" aria-controls="'.$name.'">
|
||||||
|
|
@ -147,381 +151,435 @@ class HTMLHelper
|
||||||
</div>
|
</div>
|
||||||
</div>';
|
</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getRolesOptions(){
|
public static function getRolesOptions()
|
||||||
$ret = "";
|
{
|
||||||
foreach (self::$roles as $role_id => $value){
|
$ret = '';
|
||||||
|
foreach (self::$roles as $role_id => $value) {
|
||||||
$ret .= '<option value="'.$role_id.'">'.$value.'</option>\n';
|
$ret .= '<option value="'.$role_id.'">'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getYearSelectOptions(){
|
public static function getYearSelectOptions()
|
||||||
$start = date("Y", strtotime("-5 years", time()));
|
{
|
||||||
$end = date("Y", strtotime("+1 years", time()));
|
$start = date('Y', strtotime('-5 years', time()));
|
||||||
|
$end = date('Y', strtotime('+1 years', time()));
|
||||||
$values = range($start, $end);
|
$values = range($start, $end);
|
||||||
$now = date("Y", time());
|
$now = date('Y', time());
|
||||||
$ret = "";
|
$ret = '';
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value == $now) ? 'selected="selected"' : '';
|
$attr = ($value == $now) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getAttributeTypes($id = false)
|
||||||
public static function getAttributeTypes($id = false){
|
{
|
||||||
$values = AttributeType::where('parent_id', null)->where('active', 1)->orderBy('pos', 'asc')->get();
|
$values = AttributeType::where('parent_id', null)->where('active', 1)->orderBy('pos', 'asc')->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($id === false){
|
if ($id === false) {
|
||||||
$val = $values->first();
|
$val = $values->first();
|
||||||
$id = $val->id;
|
$id = $val->id;
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
|
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getProductsWhiteLabelOptions($ids = [], $unsets = [], $type_id = false)
|
||||||
public static function getProductsWhiteLabelOptions($ids = [], $unsets = [], $type_id = false){
|
{
|
||||||
$values = Product::where('whitelabel', 1)->where('active', 1)->get();
|
$values = Product::where('whitelabel', 1)->where('active', 1)->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
if(is_array($unsets) && in_array($value->id, $unsets)){
|
if (is_array($unsets) && in_array($value->id, $unsets)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$attr = (is_array($ids) && in_array($value->id, $ids)) ? 'selected="selected"' : '';
|
$attr = (is_array($ids) && in_array($value->id, $ids)) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getAttributesOptions($ids = [], $all = true, $type_id = false)
|
||||||
public static function getAttributesOptions($ids = array(), $all = true, $type_id = false){
|
{
|
||||||
if($type_id){
|
if ($type_id) {
|
||||||
$values = Attribute::where('active', 1)->where('attribute_type_id', $type_id)->get();
|
$values = Attribute::where('active', 1)->where('attribute_type_id', $type_id)->get();
|
||||||
}else{
|
} else {
|
||||||
$values = Attribute::where('active', 1)->get();
|
$values = Attribute::where('active', 1)->get();
|
||||||
}
|
}
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('no').'</option>\n';
|
$ret .= '<option value="">'.__('no').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getProductAttributesOptions($product_attributes, $ids = [], $all = true, $type_id = false){
|
public static function getProductAttributesOptions($product_attributes, $ids = [], $all = true, $type_id = false)
|
||||||
$ret = "";
|
{
|
||||||
if($all){
|
$ret = '';
|
||||||
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('no').'</option>\n';
|
$ret .= '<option value="">'.__('no').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($product_attributes as $product_attribute){
|
foreach ($product_attributes as $product_attribute) {
|
||||||
if($product_attribute->attribute){
|
if ($product_attribute->attribute) {
|
||||||
$attr = (is_array($ids) && in_array($product_attribute->attribute_id, $ids)) ? 'selected="selected"' : '';
|
$attr = (is_array($ids) && in_array($product_attribute->attribute_id, $ids)) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$product_attribute->attribute_id.'" '.$attr.'>'.$product_attribute->attribute->name.'</option>\n';
|
$ret .= '<option value="'.$product_attribute->attribute_id.'" '.$attr.'>'.$product_attribute->attribute->name.'</option>\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCategoriesWithoutParents($id = false, $sameId = false, $all = true){
|
public static function getCategoriesWithoutParents($id = false, $sameId = false, $all = true)
|
||||||
|
{
|
||||||
$values = Category::where('parent_id', null)->get();
|
$values = Category::where('parent_id', null)->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('no').'</option>\n';
|
$ret .= '<option value="">'.__('no').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
if($sameId == $value->id){
|
if ($sameId == $value->id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getProductsOptions($ids = array(), $all = true){
|
public static function getProductsOptions($ids = [], $all = true)
|
||||||
if($ids == null){
|
{
|
||||||
$ids = array();
|
if ($ids == null) {
|
||||||
|
$ids = [];
|
||||||
}
|
}
|
||||||
$values = Product::where('active', 1)->get();
|
$values = Product::where('active', 1)->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('no').'</option>\n';
|
$ret .= '<option value="">'.__('no').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCategoriesOptions($ids = array(), $all = true){
|
public static function getCategoriesOptions($ids = [], $all = true)
|
||||||
|
{
|
||||||
$values = Category::where('active', 1)->get();
|
$values = Category::where('active', 1)->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('no').'</option>\n';
|
$ret .= '<option value="">'.__('no').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCategoriesByShowOn($show_on = []){
|
public static function getCategoriesByShowOn($show_on = [])
|
||||||
|
{
|
||||||
$values = Category::where('active', true)->whereJsonContains('show_on', $show_on)->orderBy('pos', 'ASC')->get();
|
$values = Category::where('active', true)->whereJsonContains('show_on', $show_on)->orderBy('pos', 'ASC')->get();
|
||||||
$ret = [];
|
$ret = [];
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$ret[$value->id] = ['name' => $value->name, 'count' => $value->getProductsCountOn($show_on)];
|
$ret[$value->id] = ['name' => $value->name, 'count' => $value->getProductsCountOn($show_on)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
public static function getCategoriesOptionsByShowOn($ids = array(), $all = false, $show_on = []){
|
|
||||||
|
public static function getCategoriesOptionsByShowOn($ids = [], $all = false, $show_on = [])
|
||||||
|
{
|
||||||
$values = Category::where('active', true)->whereJsonContains('show_on', $show_on)->orderBy('pos', 'ASC')->get();
|
$values = Category::where('active', true)->whereJsonContains('show_on', $show_on)->orderBy('pos', 'ASC')->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.$all.'</option>\n';
|
$ret .= '<option value="">'.$all.'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
$attr = in_array($value->id, $ids) ? 'selected="selected"' : '';
|
||||||
$count = $value->getProductsCountOn($show_on);
|
$count = $value->getProductsCountOn($show_on);
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.' ('.$count.')</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.' ('.$count.')</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getProductIngredientsOptions($has_ids = array(), $all = true){
|
public static function getProductIngredientsOptions($has_ids = [], $all = true)
|
||||||
$values = Ingredient::where('active', 1)->get();
|
{
|
||||||
$ret = "";
|
$values = Ingredient::where('active', 1)->orderBy('name')->get();
|
||||||
$attr = "";
|
$ret = '';
|
||||||
foreach ($values as $value){
|
$attr = '';
|
||||||
if(!in_array($value->id, $has_ids)){
|
foreach ($values as $value) {
|
||||||
|
if (! in_array($value->id, $has_ids)) {
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getLeadTypeOptions($id = false, $all = true){
|
public static function getLeadTypeOptions($id = false, $all = true)
|
||||||
|
{
|
||||||
$values = LeadType::where('active', 1)->get();
|
$values = LeadType::where('active', 1)->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('no').'</option>\n';
|
$ret .= '<option value="">'.__('no').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getUserLevelOptions($id = false, $all = true){
|
public static function getUserLevelOptions($id = false, $all = true)
|
||||||
|
{
|
||||||
$values = UserLevel::where('active', 1)->get();
|
$values = UserLevel::where('active', 1)->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('no').'</option>\n';
|
$ret .= '<option value="">'.__('no').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->name.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getCompanyOptions($company)
|
||||||
public static function getCompanyOptions($company){
|
{
|
||||||
$options = array(1 => __('business'), 0 => __('private'), );
|
$options = [1 => __('business'), 0 => __('private')];
|
||||||
$ret = "";
|
$ret = '';
|
||||||
foreach ($options as $id => $value){
|
foreach ($options as $id => $value) {
|
||||||
$attr = ($id == $company) ? 'selected="selected"' : '';
|
$attr = ($id == $company) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$id.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$id.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getContriesWithMore($id, $all=true){#
|
public static function getContriesWithMore($id, $all = true) //
|
||||||
|
{
|
||||||
$values = Country::all();
|
$values = Country::all();
|
||||||
$counter = 1;
|
$counter = 1;
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
|
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
if( $counter == 7){
|
if ($counter == 7) {
|
||||||
$ret .= '<optgroup label="'.__('further countrie').'">';
|
$ret .= '<optgroup label="'.__('further countrie').'">';
|
||||||
}
|
}
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->getLocated().'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->getLocated().'</option>\n';
|
||||||
|
|
||||||
$counter ++;
|
$counter++;
|
||||||
}
|
}
|
||||||
$ret .= '</optgroup>';
|
$ret .= '</optgroup>';
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getContriesCodes($id, $all=true){#
|
public static function getContriesCodes($id, $all = true) //
|
||||||
|
{
|
||||||
$values = Country::all();
|
$values = Country::all();
|
||||||
$counter = 1;
|
$counter = 1;
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
|
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
|
|
||||||
if(!$value->phone) continue;
|
if (! $value->phone) {
|
||||||
if( $counter == 7){
|
continue;
|
||||||
|
}
|
||||||
|
if ($counter == 7) {
|
||||||
$ret .= '<optgroup label="'.__('further countrie').'">';
|
$ret .= '<optgroup label="'.__('further countrie').'">';
|
||||||
}
|
}
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->phone.'('.$value->getLocated().')</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->phone.'('.$value->getLocated().')</option>\n';
|
||||||
|
|
||||||
$counter ++;
|
$counter++;
|
||||||
}
|
}
|
||||||
$ret .= '</optgroup>';
|
$ret .= '</optgroup>';
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCountriesWithoutUsedShippings($all=true){#
|
public static function getCountriesWithoutUsedShippings($all = true) //
|
||||||
|
{
|
||||||
$values = Country::all();
|
$values = Country::all();
|
||||||
$country_ids = ShippingCountry::all()->pluck('country_id')->toArray();
|
$country_ids = ShippingCountry::all()->pluck('country_id')->toArray();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
if(!in_array($value->id, $country_ids)){
|
if (! in_array($value->id, $country_ids)) {
|
||||||
$ret .= '<option value="'.$value->id.'">'.$value->getLocated().'</option>\n';
|
$ret .= '<option value="'.$value->id.'">'.$value->getLocated().'</option>\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCountryNameFormShipping($id){
|
public static function getCountryNameFormShipping($id)
|
||||||
|
{
|
||||||
$value = ShippingCountry::find($id);
|
$value = ShippingCountry::find($id);
|
||||||
if($value){
|
if ($value) {
|
||||||
return $value->country->getLocated();
|
return $value->country->getLocated();
|
||||||
}
|
}
|
||||||
return "not defined";
|
|
||||||
|
return 'not defined';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getCountriesForShipping($id, $all=false, $shipping_for = false){#
|
public static function getCountriesForShipping($id, $all = false, $shipping_for = false) //
|
||||||
|
{
|
||||||
$values = ShippingCountry::all();
|
$values = ShippingCountry::all();
|
||||||
|
|
||||||
if($shipping_for){
|
if ($shipping_for) {
|
||||||
$temp = [];
|
$temp = [];
|
||||||
foreach($values as $value){
|
foreach ($values as $value) {
|
||||||
if($shipping = $value->shipping){
|
if ($shipping = $value->shipping) {
|
||||||
if($shipping->getShippingPricesFirstBy($shipping_for)){
|
if ($shipping->getShippingPricesFirstBy($shipping_for)) {
|
||||||
$temp[] = $value;
|
$temp[] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$values = $temp;
|
$values = $temp;
|
||||||
}
|
}
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->country->getLocated().'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$value->country->getLocated().'</option>\n';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getSalutation($id){
|
public static function getSalutation($id)
|
||||||
$values = array('mr' => __('MR'), 'ms' => __('MS'));
|
{
|
||||||
$ret = "";
|
$values = ['mr' => __('MR'), 'ms' => __('MS')];
|
||||||
|
$ret = '';
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
foreach ($values as $key => $value){
|
foreach ($values as $key => $value) {
|
||||||
$attr = ($key == $id) ? 'selected="selected"' : '';
|
$attr = ($key == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getSalutationLang($id){
|
public static function getSalutationLang($id)
|
||||||
$values = array('mr' => __('MR'), 'ms' => __('MS'));
|
{
|
||||||
return (!empty($values[$id]) ? $values[$id] : '');
|
$values = ['mr' => __('MR'), 'ms' => __('MS')];
|
||||||
|
|
||||||
|
return ! empty($values[$id]) ? $values[$id] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getTaxSaleOptions($id){
|
public static function getTaxSaleOptions($id)
|
||||||
$values = array('1' => __('taxable_sales_1'), '2' => __('taxable_sales_2'));
|
{
|
||||||
$ret = "";
|
$values = ['1' => __('taxable_sales_1'), '2' => __('taxable_sales_2')];
|
||||||
|
$ret = '';
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
foreach ($values as $key => $value){
|
foreach ($values as $key => $value) {
|
||||||
$attr = ($key == $id) ? 'selected="selected"' : '';
|
$attr = ($key == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getMembersOptions($id, $all=false){
|
public static function getMembersOptions($id, $all = false)
|
||||||
|
{
|
||||||
$values = User::where('active', '=', true)->where('blocked', '=', false)->where('payment_account', '>=', now())->get();
|
$values = User::where('active', '=', true)->where('blocked', '=', false)->where('payment_account', '>=', now())->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$to="";
|
$to = '';
|
||||||
if($value->account){
|
if ($value->account) {
|
||||||
$to = $value->account->first_name." ".$value->account->last_name." | ";
|
$to = $value->account->first_name.' '.$value->account->last_name.' | ';
|
||||||
}
|
}
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$to.$value->email.' #'.$value->account->m_account.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$to.$value->email.' #'.$value->account->m_account.'</option>\n';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getUserCustomerOptions($id, $all=false){
|
public static function getUserCustomerOptions($id, $all = false)
|
||||||
|
{
|
||||||
$values = ShoppingUser::select(['id', 'billing_firstname', 'billing_lastname', 'billing_email', 'number'])
|
$values = ShoppingUser::select(['id', 'billing_firstname', 'billing_lastname', 'billing_email', 'number'])
|
||||||
->where('shopping_users.member_id', '=', \Auth::user()->id)->get();
|
->where('shopping_users.member_id', '=', \Auth::user()->id)->get();
|
||||||
$ret = "";
|
$ret = '';
|
||||||
if($all){
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
$attr = ($value->id == $id) ? 'selected="selected"' : '';
|
||||||
$to = $value->billing_firstname." ".$value->billing_lastname." | ".$value->billing_email;
|
$to = $value->billing_firstname.' '.$value->billing_lastname.' | '.$value->billing_email;
|
||||||
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$to.' #'.$value->account->m_account.'</option>\n';
|
$ret .= '<option value="'.$value->id.'" '.$attr.'>'.$to.' #'.$value->account->m_account.'</option>\n';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAnyOptions($id, $options = [], $all=true){#
|
public static function getAnyOptions($id, $options = [], $all = true) //
|
||||||
$ret = "";
|
{
|
||||||
if($all){
|
$ret = '';
|
||||||
|
if ($all) {
|
||||||
$ret .= '<option value="">'.__('please select').'</option>\n';
|
$ret .= '<option value="">'.__('please select').'</option>\n';
|
||||||
}
|
}
|
||||||
foreach ($options as $key=>$value){
|
foreach ($options as $key => $value) {
|
||||||
$attr = ($key == $id) ? 'selected="selected"' : '';
|
$attr = ($key == $id) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getOptionRange($select, $from=1, $to=50){
|
public static function getOptionRange($select, $from = 1, $to = 50)
|
||||||
|
{
|
||||||
$values = range($from, $to);
|
$values = range($from, $to);
|
||||||
$ret = "";
|
$ret = '';
|
||||||
foreach ($values as $value){
|
foreach ($values as $value) {
|
||||||
$attr = ($value == $select) ? 'selected="selected"' : '';
|
$attr = ($value == $select) ? 'selected="selected"' : '';
|
||||||
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,127 +1,199 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Mail\MailInvoice;
|
use App\Mail\MailInvoice;
|
||||||
use App\Mail\MailLogistic;
|
use App\Mail\MailLogistic;
|
||||||
use App\Services\Util;
|
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\ShoppingOrder;
|
use App\Models\ShoppingOrder;
|
||||||
use App\Models\UserCredit;
|
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
class Invoice
|
class Invoice
|
||||||
{
|
{
|
||||||
|
public static function getInvoiceNumber()
|
||||||
public static function getInvoiceNumber(){
|
{
|
||||||
return (int) Setting::getContentBySlug('invoice-number');
|
return (int) Setting::getContentBySlug('invoice-number');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function makeNextInvoiceNumber(){
|
public static function makeNextInvoiceNumber()
|
||||||
|
{
|
||||||
$invoice_number = self::getInvoiceNumber();
|
$invoice_number = self::getInvoiceNumber();
|
||||||
$invoice_number = $invoice_number+1;
|
$invoice_number = $invoice_number + 1;
|
||||||
Setting::setContentBySlug('invoice-number', $invoice_number, 'int');
|
Setting::setContentBySlug('invoice-number', $invoice_number, 'int');
|
||||||
|
|
||||||
return $invoice_number;
|
return $invoice_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createInvoiceNumber($invoice_number, $invoice_date){
|
public static function createInvoiceNumber($invoice_number, $invoice_date)
|
||||||
|
{
|
||||||
$prefix = \Carbon::parse($invoice_date)->format('Ym');
|
$prefix = \Carbon::parse($invoice_date)->format('Ym');
|
||||||
|
|
||||||
return $prefix.$invoice_number;
|
return $prefix.$invoice_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getInvoiceStorageDir($invoice_date){
|
public static function getInvoiceStorageDir($invoice_date)
|
||||||
return "/invoice/".\Carbon::parse($invoice_date)->format('Y/m/');
|
{
|
||||||
|
return '/invoice/'.\Carbon::parse($invoice_date)->format('Y/m/');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDeliveryStorageDir($invoice_date){
|
public static function getDeliveryStorageDir($invoice_date)
|
||||||
return "/delivery/".\Carbon::parse($invoice_date)->format('Y/m/');
|
{
|
||||||
|
return '/delivery/'.\Carbon::parse($invoice_date)->format('Y/m/');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function makeInvoiceFilename($invoice_number){
|
public static function makeInvoiceFilename($invoice_number)
|
||||||
return "Rechnung-".$invoice_number.".pdf";
|
{
|
||||||
|
return 'Rechnung-'.$invoice_number.'.pdf';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function makeDeliveryFilename($invoice_number){
|
public static function makeDeliveryFilename($invoice_number)
|
||||||
return "Lieferschein-".$invoice_number.".pdf";
|
{
|
||||||
|
return 'Lieferschein-'.$invoice_number.'.pdf';
|
||||||
}
|
}
|
||||||
//invoice
|
|
||||||
public static function isInvoice(ShoppingOrder $shopping_order){
|
public static function makeCancellationFilename($invoice_number)
|
||||||
|
{
|
||||||
|
return 'Stornorechnung-'.$invoice_number.'.pdf';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCancellationStorageDir($invoice_date)
|
||||||
|
{
|
||||||
|
return '/cancellation/'.\Carbon::parse($invoice_date)->format('Y/m/');
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoice
|
||||||
|
public static function isInvoice(ShoppingOrder $shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->invoice['filename']) ? true : false;
|
return isset($shopping_order->invoice['filename']) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getFilename($shopping_order){
|
public static function getFilename($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->invoice['filename']) ? $shopping_order->invoice['filename'] : false;
|
return isset($shopping_order->invoice['filename']) ? $shopping_order->invoice['filename'] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDir($shopping_order){
|
public static function getDir($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->invoice['dir']) ? $shopping_order->invoice['dir'] : false;
|
return isset($shopping_order->invoice['dir']) ? $shopping_order->invoice['dir'] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDate($shopping_order){
|
public static function getDate($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->invoice['invoice_date']) ? $shopping_order->invoice['invoice_date'] : false;
|
return isset($shopping_order->invoice['invoice_date']) ? $shopping_order->invoice['invoice_date'] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getNumber($shopping_order){
|
public static function getNumber($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->invoice['invoice_number']) ? $shopping_order->invoice['invoice_number'] : false;
|
return isset($shopping_order->invoice['invoice_number']) ? $shopping_order->invoice['invoice_number'] : false;
|
||||||
}
|
}
|
||||||
//delivery
|
|
||||||
public static function isDelivery(ShoppingOrder $shopping_order){
|
// cancellation
|
||||||
|
public static function isCancellationInvoice(ShoppingOrder $shopping_order)
|
||||||
|
{
|
||||||
|
return isset($shopping_order->cancellation_invoice['filename']) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCancellationFilename($shopping_order)
|
||||||
|
{
|
||||||
|
return isset($shopping_order->cancellation_invoice['filename']) ? $shopping_order->cancellation_invoice['filename'] : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCancellationDir($shopping_order)
|
||||||
|
{
|
||||||
|
return isset($shopping_order->cancellation_invoice['dir']) ? $shopping_order->cancellation_invoice['dir'] : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCancellationDate($shopping_order)
|
||||||
|
{
|
||||||
|
return isset($shopping_order->cancellation_invoice['cancellation_date']) ? $shopping_order->cancellation_invoice['cancellation_date'] : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCancellationNumber($shopping_order)
|
||||||
|
{
|
||||||
|
return isset($shopping_order->cancellation_invoice['cancellation_number']) ? $shopping_order->cancellation_invoice['cancellation_number'] : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getCancellationDownloadPath(ShoppingOrder $shopping_order, $full = false)
|
||||||
|
{
|
||||||
|
$dir = self::getCancellationDir($shopping_order);
|
||||||
|
$filename = self::getCancellationFilename($shopping_order);
|
||||||
|
if (! $full) {
|
||||||
|
return $dir.$filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \Storage::disk('public')->path($dir.$filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// delivery
|
||||||
|
public static function isDelivery(ShoppingOrder $shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->delivery['filename']) ? true : false;
|
return isset($shopping_order->delivery['filename']) ? true : false;
|
||||||
}
|
}
|
||||||
public static function getDeliveryFilename($shopping_order){
|
|
||||||
|
public static function getDeliveryFilename($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->delivery['filename']) ? $shopping_order->delivery['filename'] : self::makeDeliveryFilename(self::getDeliveryNumber($shopping_order));
|
return isset($shopping_order->delivery['filename']) ? $shopping_order->delivery['filename'] : self::makeDeliveryFilename(self::getDeliveryNumber($shopping_order));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDeliveryDir($shopping_order){
|
public static function getDeliveryDir($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->delivery['dir']) ? $shopping_order->delivery['dir'] : self::getDeliveryStorageDir(self::getDeliveryDate($shopping_order));
|
return isset($shopping_order->delivery['dir']) ? $shopping_order->delivery['dir'] : self::getDeliveryStorageDir(self::getDeliveryDate($shopping_order));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDeliveryDate($shopping_order){
|
public static function getDeliveryDate($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->delivery['date']) ? $shopping_order->delivery['date'] : self::getDate($shopping_order);
|
return isset($shopping_order->delivery['date']) ? $shopping_order->delivery['date'] : self::getDate($shopping_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDeliveryNumber($shopping_order){
|
public static function getDeliveryNumber($shopping_order)
|
||||||
|
{
|
||||||
return isset($shopping_order->delivery['number']) ? $shopping_order->delivery['number'] : self::getNumber($shopping_order);
|
return isset($shopping_order->delivery['number']) ? $shopping_order->delivery['number'] : self::getNumber($shopping_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getDownloadPath(ShoppingOrder $shopping_order, $full = false)
|
||||||
public static function getDownloadPath(ShoppingOrder $shopping_order, $full = false){
|
{
|
||||||
$dir = self::getDir($shopping_order);
|
$dir = self::getDir($shopping_order);
|
||||||
$filename = self::getFilename($shopping_order);
|
$filename = self::getFilename($shopping_order);
|
||||||
if(!$full){
|
if (! $full) {
|
||||||
return $dir.$filename;
|
return $dir.$filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
return \Storage::disk('public')->path($dir.$filename);
|
return \Storage::disk('public')->path($dir.$filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDownloadPathDelivery(ShoppingOrder $shopping_order, $full = false){
|
public static function getDownloadPathDelivery(ShoppingOrder $shopping_order, $full = false)
|
||||||
|
{
|
||||||
$dir = self::getDeliveryDir($shopping_order);
|
$dir = self::getDeliveryDir($shopping_order);
|
||||||
$filename = self::getDeliveryFilename($shopping_order);
|
$filename = self::getDeliveryFilename($shopping_order);
|
||||||
if(!$full){
|
if (! $full) {
|
||||||
return $dir.$filename;
|
return $dir.$filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
return \Storage::disk('public')->path($dir.$filename);
|
return \Storage::disk('public')->path($dir.$filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function sendInvoiceMail($shopping_order){
|
public static function sendInvoiceMail($shopping_order)
|
||||||
|
{
|
||||||
$bcc = [];
|
$bcc = [];
|
||||||
$billing_email = $shopping_order->shopping_user->billing_email;
|
$billing_email = $shopping_order->shopping_user->billing_email;
|
||||||
if(!$billing_email){
|
if (! $billing_email) {
|
||||||
if($shopping_order->mode === 'test'){
|
if ($shopping_order->mode === 'test') {
|
||||||
$billing_email = config('app.checkout_test_mail');
|
$billing_email = config('app.checkout_test_mail');
|
||||||
}else{
|
} else {
|
||||||
$billing_email = config('app.checkout_mail');
|
$billing_email = config('app.checkout_mail');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($shopping_order->mode === 'test'){
|
if ($shopping_order->mode === 'test') {
|
||||||
$bcc[] = config('app.checkout_test_mail');
|
$bcc[] = config('app.checkout_test_mail');
|
||||||
}else{
|
} else {
|
||||||
$bcc[] = config('app.checkout_mail');
|
$bcc[] = config('app.checkout_mail');
|
||||||
}
|
}
|
||||||
Mail::to($billing_email)->bcc($bcc)->send(new MailInvoice($shopping_order));
|
Mail::to($billing_email)->bcc($bcc)->send(new MailInvoice($shopping_order));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function sendLogisticMail(ShoppingOrder $shopping_order){
|
public static function sendLogisticMail(ShoppingOrder $shopping_order)
|
||||||
$to = [config('app.logistic_mail')]; //['versand@aloe-vera.bio'];
|
{
|
||||||
|
$to = [config('app.logistic_mail')]; // ['versand@aloe-vera.bio'];
|
||||||
Mail::to($to)->send(new MailLogistic($shopping_order));
|
Mail::to($to)->send(new MailLogistic($shopping_order));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
namespace App\Services;
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Mail\PaymentReminderEmail;
|
||||||
use App\Models\Logger;
|
use App\Models\Logger;
|
||||||
use App\Models\PaymentReminder;
|
use App\Models\PaymentReminder;
|
||||||
use App\Models\ShoppingPayment;
|
use App\Models\ShoppingPayment;
|
||||||
use App\Mail\PaymentReminderEmail;
|
|
||||||
use App\Services\Util;
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
|
|
@ -31,19 +30,23 @@ class PaymentReminderService
|
||||||
'action' => $action,
|
'action' => $action,
|
||||||
'channel' => 'payment_reminder',
|
'channel' => 'payment_reminder',
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
'level' => $level
|
'level' => $level,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hole alle aktiven Intervalle für Zahlungserinnerungen
|
* Hole alle aktiven Intervalle für Zahlungserinnerungen, immer mit dem kleinsten intervall
|
||||||
*/
|
*/
|
||||||
public function getActiveIntervals()
|
public function getActiveIntervals()
|
||||||
{
|
{
|
||||||
$intervals = [];
|
$intervals = [];
|
||||||
$payment_reminders = PaymentReminder::where('active', true)->get();
|
$payment_reminders = PaymentReminder::where('active', true)->orderBy('interval', 'asc')->get();
|
||||||
|
|
||||||
foreach($payment_reminders as $reminder) {
|
foreach ($payment_reminders as $reminder) {
|
||||||
|
|
||||||
|
if (isset($intervals[$reminder->clearingtype]) && $intervals[$reminder->clearingtype] < $reminder->interval) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$intervals[$reminder->clearingtype] = $reminder->interval;
|
$intervals[$reminder->clearingtype] = $reminder->interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,7 +67,7 @@ class PaymentReminderService
|
||||||
->where('shopping_payments.created_at', '<', $date)
|
->where('shopping_payments.created_at', '<', $date)
|
||||||
->where('shopping_payments.amount', '>', 0)
|
->where('shopping_payments.amount', '>', 0)
|
||||||
->whereNull('shopping_orders.deleted_at')
|
->whereNull('shopping_orders.deleted_at')
|
||||||
->whereIn('shopping_payments.id', function($query) use ($clearingtype, $date) {
|
->whereIn('shopping_payments.id', function ($query) use ($clearingtype, $date) {
|
||||||
$query->selectRaw('MAX(shopping_payments.id)')
|
$query->selectRaw('MAX(shopping_payments.id)')
|
||||||
->from('shopping_payments')
|
->from('shopping_payments')
|
||||||
->join('shopping_orders', 'shopping_payments.shopping_order_id', '=', 'shopping_orders.id')
|
->join('shopping_orders', 'shopping_payments.shopping_order_id', '=', 'shopping_orders.id')
|
||||||
|
|
@ -79,7 +82,6 @@ class PaymentReminderService
|
||||||
->select('shopping_payments.*')
|
->select('shopping_payments.*')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
|
||||||
return $payments;
|
return $payments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,7 +93,7 @@ class PaymentReminderService
|
||||||
$intervals = $this->getActiveIntervals();
|
$intervals = $this->getActiveIntervals();
|
||||||
$results = [];
|
$results = [];
|
||||||
|
|
||||||
foreach($intervals as $clearingtype => $interval){
|
foreach ($intervals as $clearingtype => $interval) {
|
||||||
$date = Carbon::now()->subDays($interval);
|
$date = Carbon::now()->subDays($interval);
|
||||||
$payments = $this->getOpenPaymentsForClearingType($clearingtype, $interval);
|
$payments = $this->getOpenPaymentsForClearingType($clearingtype, $interval);
|
||||||
|
|
||||||
|
|
@ -99,7 +101,7 @@ class PaymentReminderService
|
||||||
'interval' => $interval,
|
'interval' => $interval,
|
||||||
'date_limit' => $date,
|
'date_limit' => $date,
|
||||||
'payments' => $payments,
|
'payments' => $payments,
|
||||||
'count' => $payments->count()
|
'count' => $payments->count(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,13 +116,13 @@ class PaymentReminderService
|
||||||
$intervals = $this->getActiveIntervals();
|
$intervals = $this->getActiveIntervals();
|
||||||
$detailedData = [];
|
$detailedData = [];
|
||||||
|
|
||||||
foreach($intervals as $clearingtype => $interval){
|
foreach ($intervals as $clearingtype => $interval) {
|
||||||
$date = Carbon::now()->subDays($interval);
|
$date = Carbon::now()->subDays($interval);
|
||||||
$payments = $this->getOpenPaymentsForClearingType($clearingtype, $interval);
|
$payments = $this->getOpenPaymentsForClearingType($clearingtype, $interval);
|
||||||
|
|
||||||
foreach($payments as $payment){
|
foreach ($payments as $payment) {
|
||||||
$name = !isset($payment->shopping_order->shopping_user) ? 'Kein Name' : $payment->shopping_order->shopping_user->billing_firstname.' '.$payment->shopping_order->shopping_user->billing_lastname;
|
$name = ! isset($payment->shopping_order->shopping_user) ? 'Kein Name' : $payment->shopping_order->shopping_user->billing_firstname.' '.$payment->shopping_order->shopping_user->billing_lastname;
|
||||||
$email = !isset($payment->shopping_order->shopping_user) ? 'Keine Email' : $payment->shopping_order->shopping_user->billing_email;
|
$email = ! isset($payment->shopping_order->shopping_user) ? 'Keine Email' : $payment->shopping_order->shopping_user->billing_email;
|
||||||
$shipped = '<span class="badge badge-pill badge-'.$payment->shopping_order->getShippedColor().'">'.$payment->shopping_order->getShippedType().'</span>';
|
$shipped = '<span class="badge badge-pill badge-'.$payment->shopping_order->getShippedColor().'">'.$payment->shopping_order->getShippedType().'</span>';
|
||||||
|
|
||||||
// Countdown für nächste Erinnerung berechnen
|
// Countdown für nächste Erinnerung berechnen
|
||||||
|
|
@ -158,17 +160,16 @@ class PaymentReminderService
|
||||||
public function sendReminder($payment)
|
public function sendReminder($payment)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// holen der nächsten zahlungserinnerung
|
||||||
//holen der nächsten zahlungserinnerung
|
|
||||||
$payment_reminder = $this->getReminder((int) $payment->reminder, $payment->clearingtype);
|
$payment_reminder = $this->getReminder((int) $payment->reminder, $payment->clearingtype);
|
||||||
if(!$payment_reminder){
|
if (! $payment_reminder) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//zahlungserinnerung Platzhalter ersetzen.
|
// zahlungserinnerung Platzhalter ersetzen.
|
||||||
$payment_reminder = $this->replacePlaceholder($payment, $payment_reminder);
|
$payment_reminder = $this->replacePlaceholder($payment, $payment_reminder);
|
||||||
|
|
||||||
//zahlungserinnerung senden
|
// zahlungserinnerung senden
|
||||||
$emailSent = $this->sendReminderEmail($payment, $payment_reminder);
|
$emailSent = $this->sendReminderEmail($payment, $payment_reminder);
|
||||||
|
|
||||||
if ($emailSent) {
|
if ($emailSent) {
|
||||||
|
|
@ -181,8 +182,8 @@ class PaymentReminderService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//action ausführen
|
// action ausführen
|
||||||
if($payment_reminder->action === 'set_order_status_cancelled'){
|
if ($payment_reminder->action === 'set_order_status_cancelled') {
|
||||||
$this->setNoNPayment($payment);
|
$this->setNoNPayment($payment);
|
||||||
$payment->shopping_order->shipped = 10;
|
$payment->shopping_order->shipped = 10;
|
||||||
$payment->shopping_order->save();
|
$payment->shopping_order->save();
|
||||||
|
|
@ -195,9 +196,9 @@ class PaymentReminderService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//reminder setzen +1
|
// reminder setzen +1
|
||||||
$payment->reminder = (int) $payment->reminder + 1;
|
$payment->reminder = (int) $payment->reminder + 1; // anzahl der Reminder
|
||||||
$payment->reminder_date = Carbon::now();
|
$payment->reminder_date = Carbon::now(); // wann wurde der letzte reminder gesendet?
|
||||||
$payment->save();
|
$payment->save();
|
||||||
|
|
||||||
$this->createLog(
|
$this->createLog(
|
||||||
|
|
@ -235,13 +236,14 @@ class PaymentReminderService
|
||||||
->orderBy('interval', 'asc')
|
->orderBy('interval', 'asc')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
if($payment_reminders->isEmpty()) {
|
if ($payment_reminders->isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Wenn reminder größer ist als Anzahl der Erinnerungen
|
// Wenn reminder größer ist als Anzahl der Erinnerungen
|
||||||
if($reminder >= $payment_reminders->count()) {
|
if ($reminder >= $payment_reminders->count()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hole die Erinnerung an Position $reminder (0,1,2,3...)
|
// Hole die Erinnerung an Position $reminder (0,1,2,3...)
|
||||||
return $payment_reminders[$reminder];
|
return $payment_reminders[$reminder];
|
||||||
}
|
}
|
||||||
|
|
@ -256,7 +258,7 @@ class PaymentReminderService
|
||||||
'{billing_last_name}' => $shopping_user->billing_lastname,
|
'{billing_last_name}' => $shopping_user->billing_lastname,
|
||||||
'{order_number}' => '<b>'.$shopping_order->getLastShoppingPayment('reference').'</b>',
|
'{order_number}' => '<b>'.$shopping_order->getLastShoppingPayment('reference').'</b>',
|
||||||
'{order_date}' => '<b>'.$shopping_order->created_at->format('d.m.Y').'</b>',
|
'{order_date}' => '<b>'.$shopping_order->created_at->format('d.m.Y').'</b>',
|
||||||
'{order_total}' => '<b>'.$shopping_order->getFormattedTotalShipping().'</b>'
|
'{order_total}' => '<b>'.$shopping_order->getFormattedTotalShipping().'</b>',
|
||||||
];
|
];
|
||||||
|
|
||||||
$payment_reminder->subject = str_replace(
|
$payment_reminder->subject = str_replace(
|
||||||
|
|
@ -281,13 +283,13 @@ class PaymentReminderService
|
||||||
$subject = $payment_reminder->subject;
|
$subject = $payment_reminder->subject;
|
||||||
$message = $payment_reminder->message;
|
$message = $payment_reminder->message;
|
||||||
|
|
||||||
if(Util::isTestSystem()){
|
if (Util::isTestSystem()) {
|
||||||
$email = config('app.checkout_test_mail');
|
$email = config('app.checkout_test_mail');
|
||||||
}
|
}
|
||||||
|
|
||||||
if($payment->shopping_order->mode === 'test' || Util::isTestSystem()){
|
if ($payment->shopping_order->mode === 'test' || Util::isTestSystem()) {
|
||||||
$bcc[] = config('app.checkout_test_mail');
|
$bcc[] = config('app.checkout_test_mail');
|
||||||
}else{
|
} else {
|
||||||
$bcc[] = config('app.checkout_mail');
|
$bcc[] = config('app.checkout_mail');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,14 +297,15 @@ class PaymentReminderService
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::error('Fehler beim E-Mail-Versand: ' . $e->getMessage());
|
\Log::error('Fehler beim E-Mail-Versand: '.$e->getMessage());
|
||||||
$this->createLog(
|
$this->createLog(
|
||||||
'email_exception',
|
'email_exception',
|
||||||
"E-Mail Exception: " . $e->getMessage() . " für Payment ID: {$payment->id}",
|
'E-Mail Exception: '.$e->getMessage()." für Payment ID: {$payment->id}",
|
||||||
'ShoppingOrder',
|
'ShoppingOrder',
|
||||||
$payment->shopping_order_id,
|
$payment->shopping_order_id,
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -332,7 +335,7 @@ class PaymentReminderService
|
||||||
return [
|
return [
|
||||||
'type' => 'completed',
|
'type' => 'completed',
|
||||||
'message' => 'Alle Erinnerungen gesendet',
|
'message' => 'Alle Erinnerungen gesendet',
|
||||||
'days_left' => 0
|
'days_left' => 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,16 +358,16 @@ class PaymentReminderService
|
||||||
'type' => 'overdue',
|
'type' => 'overdue',
|
||||||
'message' => 'Nächste Erinnerung fällig',
|
'message' => 'Nächste Erinnerung fällig',
|
||||||
'days_left' => 0,
|
'days_left' => 0,
|
||||||
'next_reminder_date' => $next_reminder_date
|
'next_reminder_date' => $next_reminder_date,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'type' => 'countdown',
|
'type' => 'countdown',
|
||||||
'message' => 'Nächste Erinnerung in ' . $days_left . ' Tagen',
|
'message' => 'Nächste Erinnerung in '.$days_left.' Tagen',
|
||||||
'days_left' => $days_left,
|
'days_left' => $days_left,
|
||||||
'next_reminder_date' => $next_reminder_date,
|
'next_reminder_date' => $next_reminder_date,
|
||||||
'next_reminder_interval' => $interval_difference
|
'next_reminder_interval' => $interval_difference,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -446,8 +449,7 @@ class PaymentReminderService
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'summary' => $summary,
|
'summary' => $summary,
|
||||||
'detailed_stats' => $stats
|
'detailed_stats' => $stats,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
343
app/Services/ProductionService.php
Normal file
343
app/Services/ProductionService.php
Normal file
|
|
@ -0,0 +1,343 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\Production;
|
||||||
|
use App\Models\StockEntry;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
class ProductionService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
* @param array<int, array{ingredient_id: int, stock_entry_id: int, quantity_used: float|int|string}> $ingredientLines
|
||||||
|
*/
|
||||||
|
public function store(array $data, array $ingredientLines, int $userId): Production
|
||||||
|
{
|
||||||
|
return DB::transaction(function () use ($data, $ingredientLines, $userId) {
|
||||||
|
$product = Product::query()
|
||||||
|
->with(['p_ingredients', 'packagings'])
|
||||||
|
->findOrFail($data['product_id']);
|
||||||
|
|
||||||
|
$locationId = (int) $data['location_id'];
|
||||||
|
$producedQty = (int) $data['quantity'];
|
||||||
|
if ($producedQty < 1) {
|
||||||
|
throw ValidationException::withMessages(['quantity' => __('Die Stückzahl muss mindestens 1 sein.')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($product->p_ingredients->isEmpty()) {
|
||||||
|
throw ValidationException::withMessages(['product_id' => __('Das Produkt hat keine Rezeptur (Inhaltsstoffe).')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$requiredGrams = $this->requiredGramsByIngredient($product, $producedQty);
|
||||||
|
|
||||||
|
$sums = [];
|
||||||
|
foreach ($ingredientLines as $line) {
|
||||||
|
$iid = (int) $line['ingredient_id'];
|
||||||
|
$used = $this->parseQuantity($line['quantity_used'] ?? null);
|
||||||
|
$sums[$iid] = ($sums[$iid] ?? 0) + $used;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($requiredGrams as $iid => $req) {
|
||||||
|
$sum = $sums[$iid] ?? 0;
|
||||||
|
if (abs($sum - $req) > 0.02) {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'ingredient_lines' => __('Summe der Chargen-Mengen pro INCI muss dem Soll-Verbrauch entsprechen (INCI :id: Soll :req g, Ist :sum g).', [
|
||||||
|
'id' => $iid,
|
||||||
|
'req' => number_format($req, 2, ',', '.'),
|
||||||
|
'sum' => number_format($sum, 2, ',', '.'),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($sums as $iid => $_sum) {
|
||||||
|
if (! isset($requiredGrams[$iid])) {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'ingredient_lines' => __('Unerwarteter Inhaltsstoff in den Chargen-Zeilen.'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($ingredientLines as $line) {
|
||||||
|
$this->assertStockEntryMatchesLine($line, $locationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$mhdWarning = $this->computeMhdWarning($product, $data['produced_at'], $ingredientLines);
|
||||||
|
|
||||||
|
$production = Production::query()->create([
|
||||||
|
'product_id' => $product->id,
|
||||||
|
'location_id' => $locationId,
|
||||||
|
'produced_by' => $userId,
|
||||||
|
'produced_at' => $data['produced_at'],
|
||||||
|
'quantity' => $producedQty,
|
||||||
|
'notes' => $data['notes'] ?? null,
|
||||||
|
'mhd_warning' => $mhdWarning,
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($ingredientLines as $line) {
|
||||||
|
$production->productionIngredients()->create([
|
||||||
|
'ingredient_id' => (int) $line['ingredient_id'],
|
||||||
|
'stock_entry_id' => (int) $line['stock_entry_id'],
|
||||||
|
'quantity_used' => $this->parseQuantity($line['quantity_used'] ?? null),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($product->packagings as $bom) {
|
||||||
|
$perUnit = (float) ($bom->pivot->quantity ?? 1);
|
||||||
|
$pieces = (int) round($perUnit * $producedQty);
|
||||||
|
if ($pieces < 1) {
|
||||||
|
$pieces = 1;
|
||||||
|
}
|
||||||
|
$production->productionPackagings()->create([
|
||||||
|
'packaging_item_id' => $bom->id,
|
||||||
|
'quantity_used' => $pieces,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $production->fresh(['product', 'location', 'productionIngredients', 'productionPackagings']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
* @param array<int, array{ingredient_id: int, stock_entry_id: int, quantity_used: float|int|string}> $ingredientLines
|
||||||
|
*/
|
||||||
|
public function updateProduction(Production $production, array $data, array $ingredientLines, int $userId): Production
|
||||||
|
{
|
||||||
|
return DB::transaction(function () use ($production, $data, $ingredientLines) {
|
||||||
|
$product = Product::query()
|
||||||
|
->with(['p_ingredients', 'packagings'])
|
||||||
|
->findOrFail($data['product_id']);
|
||||||
|
|
||||||
|
$locationId = (int) $data['location_id'];
|
||||||
|
$producedQty = (int) $data['quantity'];
|
||||||
|
if ($producedQty < 1) {
|
||||||
|
throw ValidationException::withMessages(['quantity' => __('Die Stückzahl muss mindestens 1 sein.')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($product->p_ingredients->isEmpty()) {
|
||||||
|
throw ValidationException::withMessages(['product_id' => __('Das Produkt hat keine Rezeptur (Inhaltsstoffe).')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$requiredGrams = $this->requiredGramsByIngredient($product, $producedQty);
|
||||||
|
|
||||||
|
$sums = [];
|
||||||
|
foreach ($ingredientLines as $line) {
|
||||||
|
$iid = (int) $line['ingredient_id'];
|
||||||
|
$used = $this->parseQuantity($line['quantity_used'] ?? null);
|
||||||
|
$sums[$iid] = ($sums[$iid] ?? 0) + $used;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($requiredGrams as $iid => $req) {
|
||||||
|
$sum = $sums[$iid] ?? 0;
|
||||||
|
if (abs($sum - $req) > 0.02) {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'ingredient_lines' => __('Summe der Chargen-Mengen pro INCI muss dem Soll-Verbrauch entsprechen (INCI :id: Soll :req g, Ist :sum g).', [
|
||||||
|
'id' => $iid,
|
||||||
|
'req' => number_format($req, 2, ',', '.'),
|
||||||
|
'sum' => number_format($sum, 2, ',', '.'),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($ingredientLines as $line) {
|
||||||
|
$this->assertStockEntryMatchesLine($line, $locationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$mhdWarning = $this->computeMhdWarning($product, $data['produced_at'], $ingredientLines);
|
||||||
|
|
||||||
|
$production->update([
|
||||||
|
'product_id' => $product->id,
|
||||||
|
'location_id' => $locationId,
|
||||||
|
'produced_at' => $data['produced_at'],
|
||||||
|
'quantity' => $producedQty,
|
||||||
|
'notes' => $data['notes'] ?? null,
|
||||||
|
'mhd_warning' => $mhdWarning,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$production->productionIngredients()->delete();
|
||||||
|
foreach ($ingredientLines as $line) {
|
||||||
|
$production->productionIngredients()->create([
|
||||||
|
'ingredient_id' => (int) $line['ingredient_id'],
|
||||||
|
'stock_entry_id' => (int) $line['stock_entry_id'],
|
||||||
|
'quantity_used' => $this->parseQuantity($line['quantity_used'] ?? null),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$production->productionPackagings()->delete();
|
||||||
|
foreach ($product->packagings as $bom) {
|
||||||
|
$perUnit = (float) ($bom->pivot->quantity ?? 1);
|
||||||
|
$pieces = (int) round($perUnit * $producedQty);
|
||||||
|
if ($pieces < 1) {
|
||||||
|
$pieces = 1;
|
||||||
|
}
|
||||||
|
$production->productionPackagings()->create([
|
||||||
|
'packaging_item_id' => $bom->id,
|
||||||
|
'quantity_used' => $pieces,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $production->fresh(['product', 'location', 'productionIngredients', 'productionPackagings']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, float>
|
||||||
|
*/
|
||||||
|
public function requiredGramsByIngredient(Product $product, int $producedQuantity): array
|
||||||
|
{
|
||||||
|
$required = [];
|
||||||
|
foreach ($product->p_ingredients as $ing) {
|
||||||
|
$gram = $ing->pivot->gram;
|
||||||
|
if ($gram === null || $gram === '') {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'product_id' => __('Für „:name“ fehlt Gramm in der Rezeptur.', ['name' => $ing->name]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$factor = (float) ($ing->pivot->factor ?? 1.1);
|
||||||
|
$required[(int) $ing->id] = (float) $gram * $factor * $producedQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $required;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array{ingredient_id: int, stock_entry_id: int, quantity_used?: mixed} $line
|
||||||
|
*/
|
||||||
|
public function assertStockEntryMatchesLine(array $line, int $locationId): void
|
||||||
|
{
|
||||||
|
$entry = StockEntry::query()->findOrFail((int) $line['stock_entry_id']);
|
||||||
|
if ($entry->status !== 'received') {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'ingredient_lines' => __('Wareneingang :id ist nicht als eingegangen gebucht.', ['id' => $entry->id]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if ((int) $entry->ingredient_id !== (int) $line['ingredient_id']) {
|
||||||
|
throw ValidationException::withMessages(['ingredient_lines' => __('Charge passt nicht zum Inhaltsstoff.')]);
|
||||||
|
}
|
||||||
|
if ((int) $entry->location_id !== $locationId) {
|
||||||
|
throw ValidationException::withMessages(['ingredient_lines' => __('Charge gehört zu einem anderen Lagerort.')]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, array{ingredient_id: int, stock_entry_id: int, quantity_used?: mixed}> $ingredientLines
|
||||||
|
*/
|
||||||
|
public function computeMhdWarning(Product $product, string $producedAt, array $ingredientLines): bool
|
||||||
|
{
|
||||||
|
if ($product->shelf_life_type !== 'fixed' || ! $product->shelf_life_months) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$productEnd = Carbon::parse($producedAt)->addMonths((int) $product->shelf_life_months)->startOfDay();
|
||||||
|
|
||||||
|
foreach ($ingredientLines as $line) {
|
||||||
|
$entry = StockEntry::query()->find((int) $line['stock_entry_id']);
|
||||||
|
if (! $entry || ! $entry->best_before) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($entry->best_before->lt($productEnd)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Letzte empfangene Wareneingänge pro Inhaltsstoff am Standort (max. 3).
|
||||||
|
*
|
||||||
|
* @return Collection<int, StockEntry>
|
||||||
|
*/
|
||||||
|
public function latestStockEntriesForIngredient(int $ingredientId, int $locationId, int $limit = 3)
|
||||||
|
{
|
||||||
|
return StockEntry::query()
|
||||||
|
->where('status', 'received')
|
||||||
|
->where('entry_type', 'ingredient')
|
||||||
|
->where('ingredient_id', $ingredientId)
|
||||||
|
->where('location_id', $locationId)
|
||||||
|
->orderByDesc('received_at')
|
||||||
|
->orderByDesc('id')
|
||||||
|
->limit($limit)
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function buildRecipePayload(Product $product, int $locationId, int $productionQuantity): array
|
||||||
|
{
|
||||||
|
$product->loadMissing(['p_ingredients', 'packagings.packagingMaterial']);
|
||||||
|
|
||||||
|
$qty = max(1, $productionQuantity);
|
||||||
|
|
||||||
|
$ingredients = [];
|
||||||
|
foreach ($product->p_ingredients as $ing) {
|
||||||
|
$gram = $ing->pivot->gram;
|
||||||
|
$factor = (float) ($ing->pivot->factor ?? 1.1);
|
||||||
|
$req = ($gram !== null && $gram !== '') ? (float) $gram * $factor * $qty : null;
|
||||||
|
$ingredients[] = [
|
||||||
|
'id' => $ing->id,
|
||||||
|
'name' => $ing->name,
|
||||||
|
'gram' => $gram !== null && $gram !== '' ? (float) $gram : null,
|
||||||
|
'factor' => $factor,
|
||||||
|
'required_grams_total' => $req,
|
||||||
|
'stock_entries' => $this->latestStockEntriesForIngredient((int) $ing->id, $locationId)->map(function (StockEntry $se) {
|
||||||
|
return [
|
||||||
|
'id' => $se->id,
|
||||||
|
'batch_number' => $se->batch_number,
|
||||||
|
'best_before' => $se->best_before?->format('Y-m-d'),
|
||||||
|
'received_at' => $se->received_at?->format('Y-m-d'),
|
||||||
|
'received_quantity' => $se->received_quantity !== null ? (float) $se->received_quantity : null,
|
||||||
|
];
|
||||||
|
})->values()->all(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$packagings = [];
|
||||||
|
foreach ($product->packagings as $pk) {
|
||||||
|
$perUnit = (float) ($pk->pivot->quantity ?? 1);
|
||||||
|
$packagings[] = [
|
||||||
|
'id' => $pk->id,
|
||||||
|
'name' => $pk->name,
|
||||||
|
'quantity_per_product' => $perUnit,
|
||||||
|
'total_pieces' => (int) round($perUnit * max(1, $productionQuantity)),
|
||||||
|
'weight_grams' => $pk->weight_grams !== null ? (float) $pk->weight_grams : null,
|
||||||
|
'material_name' => $pk->packagingMaterial?->name,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'product' => [
|
||||||
|
'id' => $product->id,
|
||||||
|
'name' => $product->name,
|
||||||
|
'shelf_life_type' => $product->shelf_life_type,
|
||||||
|
'shelf_life_months' => $product->shelf_life_months,
|
||||||
|
],
|
||||||
|
'location_id' => $locationId,
|
||||||
|
'production_quantity' => $productionQuantity,
|
||||||
|
'ingredients' => $ingredients,
|
||||||
|
'packagings' => $packagings,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseQuantity(mixed $value): float
|
||||||
|
{
|
||||||
|
if ($value === null || $value === '') {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
if (is_numeric($value)) {
|
||||||
|
return (float) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$n = reFormatNumber((string) $value);
|
||||||
|
|
||||||
|
return $n !== null && $n !== '' ? (float) $n : 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
345
app/User.php
345
app/User.php
|
|
@ -3,23 +3,39 @@
|
||||||
namespace App;
|
namespace App;
|
||||||
|
|
||||||
use App\Mail\MailResetPassword;
|
use App\Mail\MailResetPassword;
|
||||||
|
use App\Models\File;
|
||||||
|
use App\Models\LeadType;
|
||||||
use App\Models\PaymentMethod;
|
use App\Models\PaymentMethod;
|
||||||
|
use App\Models\UserAccount;
|
||||||
|
use App\Models\UserHistory;
|
||||||
|
use App\Models\UserLevel;
|
||||||
|
use App\Models\UserPayCredit;
|
||||||
|
use App\Models\UserShop;
|
||||||
|
use App\Models\UserUpdateEmail;
|
||||||
|
use App\Models\UserWhitelabelProduct;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
|
use Illuminate\Notifications\DatabaseNotification;
|
||||||
|
use Illuminate\Notifications\DatabaseNotificationCollection;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Laravel\Passport\Client;
|
||||||
use Laravel\Passport\HasApiTokens;
|
use Laravel\Passport\HasApiTokens;
|
||||||
|
use Laravel\Passport\Token;
|
||||||
use Util;
|
use Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App\User
|
* App\User
|
||||||
*
|
*
|
||||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
|
* @property-read DatabaseNotificationCollection|DatabaseNotification[] $notifications
|
||||||
* @property-read int|null $notifications_count
|
* @property-read int|null $notifications_count
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User query()
|
* @method static \Illuminate\Database\Eloquent\Builder|User query()
|
||||||
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property string $email
|
* @property string $email
|
||||||
* @property \Illuminate\Support\Carbon|null $email_verified_at
|
* @property \Illuminate\Support\Carbon|null $email_verified_at
|
||||||
|
|
@ -52,6 +68,7 @@ use Util;
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @property string|null $deleted_at
|
* @property string|null $deleted_at
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAboOptions($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereAboOptions($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAccountId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereAccountId($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereAccountPayment($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereAccountPayment($value)
|
||||||
|
|
@ -84,37 +101,44 @@ use Util;
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereTestMode($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereTestMode($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereWizard($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereWizard($value)
|
||||||
* @property-read \App\Models\UserAccount|null $account
|
*
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\File[] $files
|
* @property-read UserAccount|null $account
|
||||||
|
* @property-read Collection|File[] $files
|
||||||
* @property-read int|null $files_count
|
* @property-read int|null $files_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserHistory[] $user_histories
|
* @property-read Collection|UserHistory[] $user_histories
|
||||||
* @property-read int|null $user_histories_count
|
* @property-read int|null $user_histories_count
|
||||||
* @property-read \App\Models\UserLevel|null $user_level
|
* @property-read UserLevel|null $user_level
|
||||||
* @property-read User|null $user_sponsor
|
* @property-read User|null $user_sponsor
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserUpdateEmail[] $user_update_email
|
* @property-read Collection|UserUpdateEmail[] $user_update_email
|
||||||
* @property-read int|null $user_update_email_count
|
* @property-read int|null $user_update_email_count
|
||||||
* @property string|null $payment_account
|
* @property string|null $payment_account
|
||||||
* @property-read \App\Models\UserLevel|null $next_user_level
|
* @property-read UserLevel|null $next_user_level
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User wherePaymentAccount($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User wherePaymentAccount($value)
|
||||||
|
*
|
||||||
* @property string|null $payment_credit
|
* @property string|null $payment_credit
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User wherePaymentCredit($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User wherePaymentCredit($value)
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\UserPayCredit[] $user_pay_credits
|
*
|
||||||
|
* @property-read Collection|UserPayCredit[] $user_pay_credits
|
||||||
* @property-read int|null $user_pay_credits_count
|
* @property-read int|null $user_pay_credits_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Passport\Client[] $clients
|
* @property-read Collection|Client[] $clients
|
||||||
* @property-read int|null $clients_count
|
* @property-read int|null $clients_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Passport\Token[] $tokens
|
* @property-read Collection|Token[] $tokens
|
||||||
* @property-read int|null $tokens_count
|
* @property-read int|null $tokens_count
|
||||||
* @property-read \App\Models\UserShop|null $shop
|
* @property-read UserShop|null $shop
|
||||||
* @property int|null $lead_type_id
|
* @property int|null $lead_type_id
|
||||||
* @property-read \App\Models\LeadType|null $lead_type
|
* @property-read LeadType|null $lead_type
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\UserWhitelabelProduct> $whitelabel_products
|
* @property-read Collection<int, UserWhitelabelProduct> $whitelabel_products
|
||||||
* @property-read int|null $whitelabel_products_count
|
* @property-read int|null $whitelabel_products_count
|
||||||
|
*
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|User whereLeadTypeId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|User whereLeadTypeId($value)
|
||||||
|
*
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
use Notifiable, HasApiTokens;
|
use HasApiTokens, Notifiable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
|
|
@ -142,13 +166,15 @@ class User extends Authenticatable
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
'settings' => 'array',
|
'settings' => 'array',
|
||||||
'payment_methods' => 'array'
|
'payment_methods' => 'array',
|
||||||
];
|
];
|
||||||
|
|
||||||
private $userImage = false;
|
private $userImage = false;
|
||||||
|
|
||||||
private $userImageLink = false;
|
private $userImageLink = false;
|
||||||
|
|
||||||
public function account(){
|
public function account()
|
||||||
|
{
|
||||||
return $this->belongsTo('App\Models\UserAccount', 'account_id');
|
return $this->belongsTo('App\Models\UserAccount', 'account_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,33 +183,42 @@ class User extends Authenticatable
|
||||||
return $this->hasOne('App\Models\UserShop', 'user_id', 'id');
|
return $this->hasOne('App\Models\UserShop', 'user_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user_level(){
|
public function user_level()
|
||||||
|
{
|
||||||
return $this->belongsTo('App\Models\UserLevel', 'm_level');
|
return $this->belongsTo('App\Models\UserLevel', 'm_level');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function next_user_level(){
|
public function next_user_level()
|
||||||
|
{
|
||||||
return $this->belongsTo('App\Models\UserLevel', 'next_m_level');
|
return $this->belongsTo('App\Models\UserLevel', 'next_m_level');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user_sponsor(){
|
public function user_sponsor()
|
||||||
|
{
|
||||||
return $this->belongsTo('App\User', 'm_sponsor');
|
return $this->belongsTo('App\User', 'm_sponsor');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function lead_type(){
|
public function lead_type()
|
||||||
|
{
|
||||||
return $this->belongsTo('App\Models\LeadType', 'lead_type_id');
|
return $this->belongsTo('App\Models\LeadType', 'lead_type_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sponsorHasCommisson(){
|
public function sponsorHasCommisson()
|
||||||
if($this->user_sponsor && $this->user_sponsor->user_level && $this->user_sponsor->user_level->partner_provision){
|
{
|
||||||
|
if ($this->user_sponsor && $this->user_sponsor->user_level && $this->user_sponsor->user_level->partner_provision) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public function files(){
|
|
||||||
|
public function files()
|
||||||
|
{
|
||||||
return $this->hasMany('App\Models\File', 'user_id', '');
|
return $this->hasMany('App\Models\File', 'user_id', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function user_histories(){
|
public function user_histories()
|
||||||
|
{
|
||||||
return $this->hasMany('App\Models\UserHistory', 'user_id', '');
|
return $this->hasMany('App\Models\UserHistory', 'user_id', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,38 +237,43 @@ class User extends Authenticatable
|
||||||
return $this->hasMany('App\Models\UserWhitelabelProduct', 'user_id', 'id');
|
return $this->hasMany('App\Models\UserWhitelabelProduct', 'user_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMUserSponsor(){
|
public function getMUserSponsor()
|
||||||
if($this->user_sponsor && $this->user_sponsor->account){
|
{
|
||||||
return $this->user_sponsor->account->first_name." ".$this->user_sponsor->account->last_name." | ".$this->user_sponsor->email;
|
if ($this->user_sponsor && $this->user_sponsor->account) {
|
||||||
|
return $this->user_sponsor->account->first_name.' '.$this->user_sponsor->account->last_name.' | '.$this->user_sponsor->email;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public function getFullName($email=true){
|
|
||||||
$ret = "";
|
public function getFullName($email = true)
|
||||||
if($this->account){
|
{
|
||||||
$ret = $this->account->first_name." ".$this->account->last_name;
|
$ret = '';
|
||||||
|
if ($this->account) {
|
||||||
|
$ret = $this->account->first_name.' '.$this->account->last_name;
|
||||||
|
|
||||||
}
|
}
|
||||||
if($email && $this->id > 1){
|
if ($email && $this->id > 1) {
|
||||||
$ret .= " | ".$this->email;
|
$ret .= ' | '.$this->email;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFullAddress($email=true){
|
public function getFullAddress($email = true)
|
||||||
$ret = "";
|
{
|
||||||
if($this->account){
|
$ret = '';
|
||||||
$ret .= $this->account->first_name." ".$this->account->last_name."\n";
|
if ($this->account) {
|
||||||
|
$ret .= $this->account->first_name.' '.$this->account->last_name."\n";
|
||||||
$ret .= $this->account->address."\n";
|
$ret .= $this->account->address."\n";
|
||||||
$ret .= $this->account->address_2 ? $this->account->address_2."\n" : "";
|
$ret .= $this->account->address_2 ? $this->account->address_2."\n" : '';
|
||||||
$ret .= $this->account->zipcode." ".$this->account->city."\n";
|
$ret .= $this->account->zipcode.' '.$this->account->city."\n";
|
||||||
$ret .= $email ? $this->email."\n" : "";
|
$ret .= $email ? $this->email."\n" : '';
|
||||||
|
|
||||||
$pre = $this->account->pre_phone_id != "" ? $this->account->pre_phone->phone." " : "";
|
$pre = $this->account->pre_phone_id != '' ? $this->account->pre_phone->phone.' ' : '';
|
||||||
$ret .= $this->account->phone ? $pre.$this->account->phone."\n" : "";
|
$ret .= $this->account->phone ? $pre.$this->account->phone."\n" : '';
|
||||||
|
|
||||||
$pre = $this->account->pre_mobil_id != "" ? $this->account->pre_mobil->phone." " : "";
|
$pre = $this->account->pre_mobil_id != '' ? $this->account->pre_mobil->phone.' ' : '';
|
||||||
$ret .= $this->account->mobil ? $pre.$this->account->mobil."\n" : "";
|
$ret .= $this->account->mobil ? $pre.$this->account->mobil."\n" : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
@ -244,19 +284,19 @@ class User extends Authenticatable
|
||||||
*/
|
*/
|
||||||
public function isCopyReader()
|
public function isCopyReader()
|
||||||
{
|
{
|
||||||
if($this->admin >= 1){
|
if ($this->admin >= 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function isPasswort(): bool
|
||||||
* @return bool
|
{
|
||||||
*/
|
if (Hash::check(config('app.key'), $this->password)) {
|
||||||
public function isPasswort(){
|
|
||||||
if($this->password == env('APP_KEY')){
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,9 +305,10 @@ class User extends Authenticatable
|
||||||
*/
|
*/
|
||||||
public function isAdmin()
|
public function isAdmin()
|
||||||
{
|
{
|
||||||
if($this->admin >= 7){
|
if ($this->admin >= 7) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,9 +317,10 @@ class User extends Authenticatable
|
||||||
*/
|
*/
|
||||||
public function isSuperAdmin()
|
public function isSuperAdmin()
|
||||||
{
|
{
|
||||||
if($this->admin >= 8){
|
if ($this->admin >= 8) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,9 +329,10 @@ class User extends Authenticatable
|
||||||
*/
|
*/
|
||||||
public function isSySAdmin()
|
public function isSySAdmin()
|
||||||
{
|
{
|
||||||
if($this->admin >= 9){
|
if ($this->admin >= 9) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,9 +341,10 @@ class User extends Authenticatable
|
||||||
*/
|
*/
|
||||||
public function isApiUser()
|
public function isApiUser()
|
||||||
{
|
{
|
||||||
if($this->admin >= 10){
|
if ($this->admin >= 10) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,195 +356,246 @@ class User extends Authenticatable
|
||||||
return $this->test_mode ? true : false;
|
return $this->test_mode ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function showSideNav()
|
public function showSideNav()
|
||||||
{
|
{
|
||||||
if($this->active == 1 && $this->blocked == 0 && $this->wizard >= 10){
|
if ($this->active == 1 && $this->blocked == 0 && $this->wizard >= 10) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isActive(){
|
public function isActive()
|
||||||
|
{
|
||||||
return ($this->active == 1 && $this->blocked == 0) ? true : false;
|
return ($this->active == 1 && $this->blocked == 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isActiveAccount(){
|
public function isActiveAccount()
|
||||||
if($this->isActive() && $this->payment_account){
|
{
|
||||||
|
if ($this->isActive() && $this->payment_account) {
|
||||||
return Carbon::parse($this->payment_account)->gt(Carbon::now());
|
return Carbon::parse($this->payment_account)->gt(Carbon::now());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isRenewalAccount()
|
||||||
public function isRenewalAccount(){
|
{
|
||||||
if ($this->payment_account) {
|
if ($this->payment_account) {
|
||||||
return Carbon::parse($this->payment_account)->modify('-'.(config('main.renewal_days')).' days')->lt(Carbon::now());
|
return Carbon::parse($this->payment_account)->modify('-'.(config('main.renewal_days')).' days')->lt(Carbon::now());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function nextRenewalAccount(){
|
public function nextRenewalAccount()
|
||||||
return $this->payment_account ? Carbon::parse($this->payment_account)->modify('-'.config('main.renewal_days').' days')->format(\Util::formatDateTimeDB()) : false ;
|
{
|
||||||
|
return $this->payment_account ? Carbon::parse($this->payment_account)->modify('-'.config('main.renewal_days').' days')->format(Util::formatDateTimeDB()) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function daysActiveAccount(){
|
public function daysActiveAccount()
|
||||||
|
{
|
||||||
return Carbon::now()->diffInDays(Carbon::parse($this->payment_account), false);
|
return Carbon::now()->diffInDays(Carbon::parse($this->payment_account), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function modifyActiveAccount($add = "1 year"){
|
public function modifyActiveAccount($add = '1 year')
|
||||||
return Carbon::parse($this->payment_account)->modify($add)->format(\Util::formatDateTimeDB());
|
{
|
||||||
|
return Carbon::parse($this->payment_account)->modify($add)->format(Util::formatDateTimeDB());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function daysHumansActiveAccount(){
|
public function daysHumansActiveAccount()
|
||||||
|
{
|
||||||
return Carbon::now()->diffForHumans(Carbon::parse($this->payment_account));
|
return Carbon::now()->diffForHumans(Carbon::parse($this->payment_account));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function daysActiveShop(){
|
public function daysActiveShop()
|
||||||
|
{
|
||||||
return Carbon::now()->diffInDays(Carbon::parse($this->payment_shop), false);
|
return Carbon::now()->diffInDays(Carbon::parse($this->payment_shop), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function modifyActiveShop($add = "1 year"){
|
public function modifyActiveShop($add = '1 year')
|
||||||
return Carbon::parse($this->payment_shop)->modify($add)->format(\Util::formatDateTimeDB());
|
{
|
||||||
|
return Carbon::parse($this->payment_shop)->modify($add)->format(Util::formatDateTimeDB());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function daysHumansActiveShop(){
|
public function daysHumansActiveShop()
|
||||||
|
{
|
||||||
return Carbon::now()->diffForHumans(Carbon::parse($this->payment_shop));
|
return Carbon::now()->diffForHumans(Carbon::parse($this->payment_shop));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAboOption(){
|
public function isAboOption()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getConfirmationDateFormat(){
|
public function getConfirmationDateFormat()
|
||||||
if(!$this->attributes['confirmation_date']){ return ""; }
|
{
|
||||||
return Carbon::parse($this->attributes['confirmation_date'])->format(\Util::formatDateTimeDB());
|
if (! $this->attributes['confirmation_date']) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return Carbon::parse($this->attributes['confirmation_date'])->format(Util::formatDateTimeDB());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getActiveDateFormat(){
|
public function getActiveDateFormat()
|
||||||
if(!$this->attributes['active_date']){ return ""; }
|
{
|
||||||
return Carbon::parse($this->attributes['active_date'])->format(\Util::formatDateTimeDB());
|
if (! $this->attributes['active_date']) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return Carbon::parse($this->attributes['active_date'])->format(Util::formatDateTimeDB());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getAgreementFormat(){
|
public function getAgreementFormat()
|
||||||
if(!$this->attributes['agreement']){ return ""; }
|
{
|
||||||
return Carbon::parse($this->attributes['agreement'])->format(\Util::formatDateTimeDB());
|
if (! $this->attributes['agreement']) {
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentAccountDateFormat($time = true){
|
return Carbon::parse($this->attributes['agreement'])->format(Util::formatDateTimeDB());
|
||||||
if(!$this->attributes['payment_account']){ return ""; }
|
|
||||||
if(!$time){
|
|
||||||
return Carbon::parse($this->attributes['payment_account'])->format(\Util::formatDateDB());
|
|
||||||
}
|
|
||||||
return Carbon::parse($this->attributes['payment_account'])->format(\Util::formatDateTimeDB());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentShopDateFormat($time = true){
|
public function getPaymentAccountDateFormat($time = true)
|
||||||
if(!$this->attributes['payment_shop']){ return ""; }
|
{
|
||||||
if(!$time){
|
if (! $this->attributes['payment_account']) {
|
||||||
return Carbon::parse($this->attributes['payment_shop'])->format(\Util::formatDateDB());
|
return '';
|
||||||
}
|
}
|
||||||
return Carbon::parse($this->attributes['payment_shop'])->format(\Util::formatDateTimeDB());
|
if (! $time) {
|
||||||
|
return Carbon::parse($this->attributes['payment_account'])->format(Util::formatDateDB());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getReleaseAccountFormat($time = true){
|
return Carbon::parse($this->attributes['payment_account'])->format(Util::formatDateTimeDB());
|
||||||
if(!$this->attributes['release_account']){ return ""; }
|
|
||||||
if(!$time){
|
|
||||||
return Carbon::parse($this->attributes['release_account'])->format(\Util::formatDateDB());
|
|
||||||
}
|
}
|
||||||
return Carbon::parse($this->attributes['release_account'])->format(\Util::formatDateTimeDB());
|
|
||||||
|
public function getPaymentShopDateFormat($time = true)
|
||||||
|
{
|
||||||
|
if (! $this->attributes['payment_shop']) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (! $time) {
|
||||||
|
return Carbon::parse($this->attributes['payment_shop'])->format(Util::formatDateDB());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Carbon::parse($this->attributes['payment_shop'])->format(Util::formatDateTimeDB());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getReleaseAccountFormat($time = true)
|
||||||
|
{
|
||||||
|
if (! $this->attributes['release_account']) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (! $time) {
|
||||||
|
return Carbon::parse($this->attributes['release_account'])->format(Util::formatDateDB());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Carbon::parse($this->attributes['release_account'])->format(Util::formatDateTimeDB());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedPaymentCredit()
|
public function getFormattedPaymentCredit()
|
||||||
{
|
{
|
||||||
return isset($this->attributes['payment_credit']) ? Util::formatNumber($this->attributes['payment_credit']) : "0";
|
return isset($this->attributes['payment_credit']) ? Util::formatNumber($this->attributes['payment_credit']) : '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setSetting(array $revisions, bool $save = true){
|
public function setSetting(array $revisions, bool $save = true)
|
||||||
if(!$this->settings){
|
{
|
||||||
|
if (! $this->settings) {
|
||||||
$this->settings = [];
|
$this->settings = [];
|
||||||
}
|
}
|
||||||
$this->settings = array_merge($this->settings, $revisions);
|
$this->settings = array_merge($this->settings, $revisions);
|
||||||
if ($save) {
|
if ($save) {
|
||||||
$this->save();
|
$this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSetting($key, $default = null){
|
public function getSetting($key, $default = null)
|
||||||
|
{
|
||||||
return isset($this->settings[$key]) ? $this->settings[$key] : $default;
|
return isset($this->settings[$key]) ? $this->settings[$key] : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentMethodsShort(){
|
public function getPaymentMethodsShort()
|
||||||
$ret = "";
|
{
|
||||||
if($this->payment_methods !== null){
|
$ret = '';
|
||||||
foreach ($this->payment_methods as $payment_method){
|
if ($this->payment_methods !== null) {
|
||||||
if($find = PaymentMethod::find($payment_method)){
|
foreach ($this->payment_methods as $payment_method) {
|
||||||
$ret .= $find->short." | ";
|
if ($find = PaymentMethod::find($payment_method)) {
|
||||||
|
$ret .= $find->short.' | ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$ret = rtrim($ret, " | ");
|
$ret = rtrim($ret, ' | ');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getLandByCountry(){
|
public function getLandByCountry()
|
||||||
if($this->account && $this->account->country_id){
|
{
|
||||||
|
if ($this->account && $this->account->country_id) {
|
||||||
$code = $this->account->country->code;
|
$code = $this->account->country->code;
|
||||||
if($code == "FR"){
|
if ($code == 'FR') {
|
||||||
return 'fr';
|
return 'fr';
|
||||||
}
|
}
|
||||||
if($code == "CH"){
|
if ($code == 'CH') {
|
||||||
return 'de';
|
return 'de';
|
||||||
}
|
}
|
||||||
if($code == "NL"){
|
if ($code == 'NL') {
|
||||||
return 'nl';
|
return 'nl';
|
||||||
}
|
}
|
||||||
if($code == "DE"){
|
if ($code == 'DE') {
|
||||||
return 'de';
|
return 'de';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "de";
|
|
||||||
|
return 'de';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBirthdayFormat($format = "d.m.Y"){
|
public function getBirthdayFormat($format = 'd.m.Y')
|
||||||
if($this->account && $this->account->getBirthdayRaw()){
|
{
|
||||||
|
if ($this->account && $this->account->getBirthdayRaw()) {
|
||||||
return (int) Carbon::parse($this->account->getBirthdayRaw())->format($format);
|
return (int) Carbon::parse($this->account->getBirthdayRaw())->format($format);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasProfileImage(){
|
public function hasProfileImage()
|
||||||
|
{
|
||||||
|
|
||||||
if($this->userImage){
|
if ($this->userImage) {
|
||||||
return $this->userImage;
|
return $this->userImage;
|
||||||
}
|
}
|
||||||
if(\Storage::disk('user')->has($this->id.'/avatar.jpg')){
|
if (\Storage::disk('user')->has($this->id.'/avatar.jpg')) {
|
||||||
$this->userImage = $this->id.'/avatar.jpg';
|
$this->userImage = $this->id.'/avatar.jpg';
|
||||||
}
|
}
|
||||||
if(\Storage::disk('user')->has($this->id.'/avatar.png')){
|
if (\Storage::disk('user')->has($this->id.'/avatar.png')) {
|
||||||
$this->userImage = $this->id.'/avatar.png';
|
$this->userImage = $this->id.'/avatar.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->userImage;
|
return $this->userImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProfileImage(){
|
public function getProfileImage()
|
||||||
if($this->hasProfileImage()){
|
{
|
||||||
|
if ($this->hasProfileImage()) {
|
||||||
return str_replace('/', '_', $this->userImage);
|
return str_replace('/', '_', $this->userImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,16 +32,17 @@
|
||||||
"srmklive/paypal": "~3.0"
|
"srmklive/paypal": "~3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"spatie/laravel-ignition": "^2.0",
|
"barryvdh/laravel-debugbar": "^3.13",
|
||||||
"nunomaduro/collision": "^8.1",
|
"barryvdh/laravel-ide-helper": "^3.0",
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
|
"laravel/boost": "^1.0",
|
||||||
"laravel/pint": "^1.0",
|
"laravel/pint": "^1.0",
|
||||||
"laravel/sail": "^1.26",
|
"laravel/sail": "^1.26",
|
||||||
"mockery/mockery": "^1.6.2",
|
"mockery/mockery": "^1.6.2",
|
||||||
|
"nunomaduro/collision": "^8.1",
|
||||||
"pestphp/pest": "^2.0",
|
"pestphp/pest": "^2.0",
|
||||||
"pestphp/pest-plugin-laravel": "^2.0",
|
"pestphp/pest-plugin-laravel": "^2.0",
|
||||||
"barryvdh/laravel-debugbar": "^3.13",
|
"spatie/laravel-ignition": "^2.0"
|
||||||
"barryvdh/laravel-ide-helper": "^3.0"
|
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
|
|
|
||||||
2514
composer.lock
generated
2514
composer.lock
generated
File diff suppressed because it is too large
Load diff
22
database/factories/LocationFactory.php
Normal file
22
database/factories/LocationFactory.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Location;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Location>
|
||||||
|
*/
|
||||||
|
class LocationFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Location::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->city(),
|
||||||
|
'active' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
22
database/factories/MaterialQualityFactory.php
Normal file
22
database/factories/MaterialQualityFactory.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\MaterialQuality;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<MaterialQuality>
|
||||||
|
*/
|
||||||
|
class MaterialQualityFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = MaterialQuality::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->unique()->words(2, true),
|
||||||
|
'pos' => $this->faker->numberBetween(0, 50),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
29
database/factories/PackagingItemFactory.php
Normal file
29
database/factories/PackagingItemFactory.php
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\PackagingItem;
|
||||||
|
use App\Models\PackagingMaterial;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<PackagingItem>
|
||||||
|
*/
|
||||||
|
class PackagingItemFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = PackagingItem::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'packaging_material_id' => PackagingMaterial::factory(),
|
||||||
|
'supplier_id' => null,
|
||||||
|
'name' => $this->faker->words(3, true),
|
||||||
|
'category' => 'packaging',
|
||||||
|
'weight_grams' => 0,
|
||||||
|
'min_stock_alert' => null,
|
||||||
|
'product_id' => null,
|
||||||
|
'active' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
22
database/factories/PackagingMaterialFactory.php
Normal file
22
database/factories/PackagingMaterialFactory.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\PackagingMaterial;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<PackagingMaterial>
|
||||||
|
*/
|
||||||
|
class PackagingMaterialFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = PackagingMaterial::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->unique()->word(),
|
||||||
|
'pos' => $this->faker->numberBetween(0, 50),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
208
database/factories/StockEntryFactory.php
Normal file
208
database/factories/StockEntryFactory.php
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Ingredient;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\MaterialQuality;
|
||||||
|
use App\Models\PackagingItem;
|
||||||
|
use App\Models\StockEntry;
|
||||||
|
use App\Models\Supplier;
|
||||||
|
use App\User;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<StockEntry>
|
||||||
|
*/
|
||||||
|
class StockEntryFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = StockEntry::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$orderedAt = Carbon::instance($this->faker->dateTimeBetween('-3 months', 'now'));
|
||||||
|
|
||||||
|
return [
|
||||||
|
'entry_type' => 'ingredient',
|
||||||
|
'ingredient_id' => fn () => $this->makeIngredient()->id,
|
||||||
|
'packaging_item_id' => null,
|
||||||
|
'supplier_id' => Supplier::factory(),
|
||||||
|
'location_id' => Location::factory(),
|
||||||
|
'unit' => 'gram',
|
||||||
|
'ordered_by' => fn () => $this->makeOrderUser()->id,
|
||||||
|
'ordered_at' => $orderedAt->format('Y-m-d'),
|
||||||
|
'ordered_quantity' => $this->faker->randomFloat(2, 250, 50_000),
|
||||||
|
'price_per_kg' => $this->faker->randomFloat(4, 2, 120),
|
||||||
|
'price_total' => null,
|
||||||
|
'received_by' => null,
|
||||||
|
'received_at' => null,
|
||||||
|
'received_quantity' => null,
|
||||||
|
'batch_number' => null,
|
||||||
|
'best_before' => null,
|
||||||
|
'quality_id' => null,
|
||||||
|
'status' => 'pending',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ingredient(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'entry_type' => 'ingredient',
|
||||||
|
'ingredient_id' => fn () => $this->makeIngredient()->id,
|
||||||
|
'packaging_item_id' => null,
|
||||||
|
'unit' => 'gram',
|
||||||
|
'price_per_kg' => $this->faker->randomFloat(4, 2, 120),
|
||||||
|
'price_total' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function packaging(): static
|
||||||
|
{
|
||||||
|
return $this->state(function () {
|
||||||
|
$supplier = Supplier::factory()->create();
|
||||||
|
$item = PackagingItem::factory()->create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'category' => 'packaging',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'entry_type' => 'packaging',
|
||||||
|
'ingredient_id' => null,
|
||||||
|
'packaging_item_id' => $item->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'unit' => 'piece',
|
||||||
|
'price_per_kg' => null,
|
||||||
|
'price_total' => $this->faker->randomFloat(4, 15, 2500),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function label(): static
|
||||||
|
{
|
||||||
|
return $this->state(function () {
|
||||||
|
$supplier = Supplier::factory()->create();
|
||||||
|
$item = PackagingItem::factory()->create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'category' => 'label',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'entry_type' => 'label',
|
||||||
|
'ingredient_id' => null,
|
||||||
|
'packaging_item_id' => $item->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'unit' => 'piece',
|
||||||
|
'price_per_kg' => null,
|
||||||
|
'price_total' => $this->faker->randomFloat(4, 5, 800),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shippingOffice(): static
|
||||||
|
{
|
||||||
|
return $this->state(function () {
|
||||||
|
$supplier = Supplier::factory()->create();
|
||||||
|
$item = PackagingItem::factory()->create([
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'category' => 'shipping_office',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'entry_type' => 'shipping_office',
|
||||||
|
'ingredient_id' => null,
|
||||||
|
'packaging_item_id' => $item->id,
|
||||||
|
'supplier_id' => $supplier->id,
|
||||||
|
'unit' => 'piece',
|
||||||
|
'price_per_kg' => null,
|
||||||
|
'price_total' => $this->faker->randomFloat(4, 8, 1500),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pending(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn () => [
|
||||||
|
'status' => 'pending',
|
||||||
|
'received_by' => null,
|
||||||
|
'received_at' => null,
|
||||||
|
'received_quantity' => null,
|
||||||
|
'batch_number' => null,
|
||||||
|
'best_before' => null,
|
||||||
|
'quality_id' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function received(): static
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
$receiver = $this->makeOrderUser();
|
||||||
|
$orderedAt = $attributes['ordered_at'] ?? now()->format('Y-m-d');
|
||||||
|
$orderedCarbon = Carbon::parse($orderedAt);
|
||||||
|
$receivedCarbon = (clone $orderedCarbon)->addDays($this->faker->numberBetween(1, 21));
|
||||||
|
if ($receivedCarbon->isFuture()) {
|
||||||
|
$receivedCarbon = Carbon::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
$qty = $attributes['ordered_quantity'] ?? 1000;
|
||||||
|
$entryType = $attributes['entry_type'] ?? 'ingredient';
|
||||||
|
|
||||||
|
$extra = [
|
||||||
|
'status' => 'received',
|
||||||
|
'received_by' => $receiver->id,
|
||||||
|
'received_at' => $receivedCarbon->format('Y-m-d'),
|
||||||
|
'received_quantity' => round((float) $qty, 2),
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($entryType === 'ingredient') {
|
||||||
|
$extra['batch_number'] = $this->faker->bothify('CH-####-??');
|
||||||
|
$extra['best_before'] = $this->faker->dateTimeBetween('+2 months', '+24 months')->format('Y-m-d');
|
||||||
|
$extra['quality_id'] = MaterialQuality::query()->inRandomOrder()->value('id');
|
||||||
|
} else {
|
||||||
|
$extra['batch_number'] = null;
|
||||||
|
$extra['best_before'] = null;
|
||||||
|
$extra['quality_id'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $extra;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function makeIngredient(): Ingredient
|
||||||
|
{
|
||||||
|
$name = $this->faker->randomElement([
|
||||||
|
'Shea Butter',
|
||||||
|
'Kokosöl raffiniert',
|
||||||
|
'Mandelöl süß',
|
||||||
|
'Jojobaöl',
|
||||||
|
'Distillat Rosenhydrolat',
|
||||||
|
]).' '.$this->faker->unique()->numerify('###');
|
||||||
|
|
||||||
|
return Ingredient::query()->create([
|
||||||
|
'name' => $name,
|
||||||
|
'trans_name' => '',
|
||||||
|
'inci' => $this->faker->optional(0.7)->words(3, true) ?? '',
|
||||||
|
'trans_inci' => '',
|
||||||
|
'effect' => '',
|
||||||
|
'trans_effect' => '',
|
||||||
|
'active' => true,
|
||||||
|
'pos' => 0,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function makeOrderUser(): User
|
||||||
|
{
|
||||||
|
return User::query()->create([
|
||||||
|
'email' => 'sf_u_'.str_replace('.', '', uniqid('', true)).'@factory.test',
|
||||||
|
'password' => bcrypt('password'),
|
||||||
|
'admin' => 7,
|
||||||
|
'confirmed' => true,
|
||||||
|
'active' => true,
|
||||||
|
'wizard' => 100,
|
||||||
|
'blocked' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
database/factories/SupplierCategoryFactory.php
Normal file
22
database/factories/SupplierCategoryFactory.php
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\SupplierCategory;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<SupplierCategory>
|
||||||
|
*/
|
||||||
|
class SupplierCategoryFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = SupplierCategory::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->unique()->words(2, true),
|
||||||
|
'pos' => $this->faker->numberBetween(0, 50),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
48
database/factories/SupplierFactory.php
Normal file
48
database/factories/SupplierFactory.php
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Country;
|
||||||
|
use App\Models\Supplier;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends Factory<Supplier>
|
||||||
|
*/
|
||||||
|
class SupplierFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Supplier::class;
|
||||||
|
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->company(),
|
||||||
|
'url' => $this->faker->optional()->url(),
|
||||||
|
'contact_person' => $this->faker->optional()->name(),
|
||||||
|
'email' => $this->faker->optional()->companyEmail(),
|
||||||
|
'phone' => $this->faker->optional()->phoneNumber(),
|
||||||
|
'country_id' => Country::query()->value('id') ?? $this->resolveCountryId(),
|
||||||
|
'notes' => null,
|
||||||
|
'active' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveCountryId(): int
|
||||||
|
{
|
||||||
|
$country = Country::query()->firstOrCreate(
|
||||||
|
['code' => 'TE'],
|
||||||
|
[
|
||||||
|
'phone' => '00',
|
||||||
|
'en' => 'Testland',
|
||||||
|
'de' => 'Testland',
|
||||||
|
'es' => 'Testland',
|
||||||
|
'fr' => 'Testland',
|
||||||
|
'it' => 'Testland',
|
||||||
|
'ru' => 'Testland',
|
||||||
|
'active' => true,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (int) $country->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
class CreateCountriesTable extends Migration
|
class CreateCountriesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|
@ -35,14 +35,11 @@ class CreateCountriesTable extends Migration
|
||||||
$table->boolean('currency_calc')->default(false);
|
$table->boolean('currency_calc')->default(false);
|
||||||
$table->decimal('currency_faktor', 4, 2)->nullable();
|
$table->decimal('currency_faktor', 4, 2)->nullable();
|
||||||
|
|
||||||
$table->boolean('active')->default(true);
|
|
||||||
$table->text('trans_name')->nullable();
|
$table->text('trans_name')->nullable();
|
||||||
$table->text('attr')->nullable();
|
$table->text('attr')->nullable();
|
||||||
|
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
class CreateAttributesTable extends Migration
|
class CreateAttributesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|
@ -25,16 +25,13 @@ class CreateAttributesTable extends Migration
|
||||||
|
|
||||||
$table->string('slug')->unique()->index();
|
$table->string('slug')->unique()->index();
|
||||||
|
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
$table->foreign('parent_id')
|
$table->foreign('parent_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('attributes');
|
->on('attributes');
|
||||||
|
|
||||||
$table->foreign('attribute_type_id')
|
// FK zu attribute_types wird in create_attribute_types_table Migration gesetzt (Reihenfolge-Problem)
|
||||||
->references('id')
|
|
||||||
->on('attribute_types');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
class CreateProductAttributesTable extends Migration
|
class CreateProductAttributesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|
@ -32,10 +32,7 @@ class CreateProductAttributesTable extends Migration
|
||||||
->on('attributes')
|
->on('attributes')
|
||||||
->onDelete('cascade');
|
->onDelete('cascade');
|
||||||
|
|
||||||
$table->foreign('type_id')
|
// FK zu attribute_types wird in create_attribute_types_table Migration gesetzt (Reihenfolge-Problem)
|
||||||
->references('id')
|
|
||||||
->on('attribute_types')
|
|
||||||
->onDelete('cascade');
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
class CreateProductImagesTable extends Migration
|
class CreateProductImagesTable extends Migration
|
||||||
{
|
{
|
||||||
|
|
@ -37,10 +37,7 @@ class CreateProductImagesTable extends Migration
|
||||||
->on('products')
|
->on('products')
|
||||||
->onDelete('cascade');
|
->onDelete('cascade');
|
||||||
|
|
||||||
$table->foreign('user_wl_product_id')
|
// FK zu user_whitelabel_products wird in create_user_whitelabel_products_table Migration gesetzt (Reihenfolge-Problem)
|
||||||
->references('id')
|
|
||||||
->on('user_whitelabel_products')
|
|
||||||
->onDelete('cascade');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class CreateProductBuysTable extends Migration
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('products');
|
->on('products');
|
||||||
|
|
||||||
$table->foreign('user_id')
|
$table->foreign('auth_user_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('users');
|
->on('users');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,24 @@ class CreateAttributeTypesTable extends Migration
|
||||||
|
|
||||||
$table->string('slug')->unique()->index();
|
$table->string('slug')->unique()->index();
|
||||||
|
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
$table->foreign('parent_id')
|
$table->foreign('parent_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('attributes');
|
->on('attributes');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('attributes', function (Blueprint $table) {
|
||||||
|
$table->foreign('attribute_type_id')
|
||||||
|
->references('id')
|
||||||
|
->on('attribute_types');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('product_attributes', function (Blueprint $table) {
|
||||||
|
$table->foreign('type_id')
|
||||||
|
->references('id')
|
||||||
|
->on('attribute_types')
|
||||||
|
->onDelete('cascade');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,6 +53,14 @@ class CreateAttributeTypesTable extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
|
Schema::table('product_attributes', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['type_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('attributes', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['attribute_type_id']);
|
||||||
|
});
|
||||||
|
|
||||||
Schema::dropIfExists('attribute_types');
|
Schema::dropIfExists('attribute_types');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,13 @@ class CreateUserWhitelabelProductsTable extends Migration
|
||||||
->on('products')
|
->on('products')
|
||||||
->onDelete('cascade');
|
->onDelete('cascade');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Schema::table('product_images', function (Blueprint $table) {
|
||||||
|
$table->foreign('user_wl_product_id')
|
||||||
|
->references('id')
|
||||||
|
->on('user_whitelabel_products')
|
||||||
|
->onDelete('cascade');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -45,6 +52,10 @@ class CreateUserWhitelabelProductsTable extends Migration
|
||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
|
Schema::table('product_images', function (Blueprint $table) {
|
||||||
|
$table->dropForeign(['user_wl_product_id']);
|
||||||
|
});
|
||||||
|
|
||||||
Schema::dropIfExists('user_whitelabel_products');
|
Schema::dropIfExists('user_whitelabel_products');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('shopping_orders', function (Blueprint $table) {
|
||||||
|
$table->text('cancellation_invoice')->nullable()->after('invoice');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('shopping_orders', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('cancellation_invoice');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('product_ingredients', function (Blueprint $table) {
|
||||||
|
$table->unsignedSmallInteger('pos')->default(0)->after('ingredient_id');
|
||||||
|
$table->decimal('gram', 12, 2)->nullable()->after('pos');
|
||||||
|
$table->decimal('factor', 4, 2)->default(1.10)->after('gram');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('product_ingredients', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['pos', 'gram', 'factor']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('products', function (Blueprint $table) {
|
||||||
|
$table->enum('shelf_life_type', ['pao', 'fixed'])->nullable()->after('max_buy_num');
|
||||||
|
$table->unsignedTinyInteger('shelf_life_months')->nullable()->after('shelf_life_type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('products', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['shelf_life_type', 'shelf_life_months']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('ingredients', function (Blueprint $table) {
|
||||||
|
$table->decimal('default_factor', 4, 2)->default(1.10)->after('pos');
|
||||||
|
$table->decimal('min_stock_alert', 12, 2)->nullable()->after('default_factor');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('ingredients', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['default_factor', 'min_stock_alert']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('locations', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('locations');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('supplier_categories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->unsignedTinyInteger('pos')->default(0);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('supplier_categories');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('suppliers', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('url')->nullable();
|
||||||
|
$table->string('contact_person')->nullable();
|
||||||
|
$table->string('email')->nullable();
|
||||||
|
$table->string('phone', 100)->nullable();
|
||||||
|
$table->unsignedInteger('country_id');
|
||||||
|
$table->text('notes')->nullable();
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
|
||||||
|
$table->foreign('country_id')->references('id')->on('countries');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('suppliers');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('supplier_supplier_category', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('supplier_id')->constrained('suppliers')->cascadeOnDelete();
|
||||||
|
$table->foreignId('supplier_category_id')->constrained('supplier_categories')->cascadeOnDelete();
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['supplier_id', 'supplier_category_id'], 'supplier_supplier_cat_unique');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('supplier_supplier_category');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('material_qualities', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->unsignedTinyInteger('pos')->default(0);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('material_qualities');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('packaging_materials', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->unsignedTinyInteger('pos')->default(0);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('packaging_materials');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('packaging_items', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('packaging_material_id')->constrained('packaging_materials');
|
||||||
|
$table->foreignId('supplier_id')->nullable()->constrained('suppliers')->nullOnDelete();
|
||||||
|
$table->string('name');
|
||||||
|
$table->enum('category', ['packaging', 'label', 'shipping_office']);
|
||||||
|
$table->decimal('weight_grams', 10, 2)->default(0);
|
||||||
|
$table->unsignedInteger('min_stock_alert')->nullable();
|
||||||
|
$table->unsignedInteger('product_id')->nullable();
|
||||||
|
$table->foreign('product_id')->references('id')->on('products')->nullOnDelete();
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('packaging_items');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('stock_entries', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->enum('entry_type', ['ingredient', 'packaging', 'label', 'shipping_office']);
|
||||||
|
$table->unsignedInteger('ingredient_id')->nullable();
|
||||||
|
$table->foreign('ingredient_id')->references('id')->on('ingredients')->nullOnDelete();
|
||||||
|
$table->foreignId('packaging_item_id')->nullable()->constrained('packaging_items')->nullOnDelete();
|
||||||
|
$table->foreignId('supplier_id')->constrained('suppliers');
|
||||||
|
$table->foreignId('location_id')->constrained('locations');
|
||||||
|
$table->enum('unit', ['gram', 'piece']);
|
||||||
|
|
||||||
|
$table->unsignedInteger('ordered_by');
|
||||||
|
$table->foreign('ordered_by')->references('id')->on('users');
|
||||||
|
$table->date('ordered_at');
|
||||||
|
$table->decimal('ordered_quantity', 12, 2);
|
||||||
|
$table->decimal('price_per_kg', 10, 4)->nullable();
|
||||||
|
$table->decimal('price_total', 10, 4)->nullable();
|
||||||
|
|
||||||
|
$table->unsignedInteger('received_by')->nullable();
|
||||||
|
$table->foreign('received_by')->references('id')->on('users')->nullOnDelete();
|
||||||
|
$table->date('received_at')->nullable();
|
||||||
|
$table->decimal('received_quantity', 12, 2)->nullable();
|
||||||
|
$table->string('batch_number', 100)->nullable();
|
||||||
|
$table->date('best_before')->nullable();
|
||||||
|
$table->foreignId('quality_id')->nullable()->constrained('material_qualities')->nullOnDelete();
|
||||||
|
|
||||||
|
$table->enum('status', ['pending', 'received'])->default('pending');
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(['status', 'ordered_at']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('stock_entries');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('product_packagings', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedInteger('product_id');
|
||||||
|
$table->foreign('product_id')->references('id')->on('products')->cascadeOnDelete();
|
||||||
|
$table->foreignId('packaging_item_id')->constrained('packaging_items')->cascadeOnDelete();
|
||||||
|
$table->decimal('quantity', 12, 2)->default(1);
|
||||||
|
$table->unsignedSmallInteger('pos')->default(0);
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['product_id', 'packaging_item_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Schema::hasTable('packaging_items')) {
|
||||||
|
$rows = DB::table('packaging_items')
|
||||||
|
->whereNotNull('product_id')
|
||||||
|
->orderBy('id')
|
||||||
|
->get(['id', 'product_id']);
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
DB::table('product_packagings')->insert([
|
||||||
|
'product_id' => $row->product_id,
|
||||||
|
'packaging_item_id' => $row->id,
|
||||||
|
'quantity' => 1,
|
||||||
|
'pos' => 0,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('product_packagings');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('productions', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedInteger('product_id');
|
||||||
|
$table->foreign('product_id')->references('id')->on('products')->cascadeOnDelete();
|
||||||
|
$table->foreignId('location_id')->constrained('locations');
|
||||||
|
$table->unsignedInteger('produced_by');
|
||||||
|
$table->foreign('produced_by')->references('id')->on('users');
|
||||||
|
$table->date('produced_at');
|
||||||
|
$table->unsignedInteger('quantity');
|
||||||
|
$table->text('notes')->nullable();
|
||||||
|
$table->boolean('mhd_warning')->default(false);
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(['produced_at', 'location_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('production_ingredients', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('production_id')->constrained('productions')->cascadeOnDelete();
|
||||||
|
$table->unsignedInteger('ingredient_id');
|
||||||
|
$table->foreign('ingredient_id')->references('id')->on('ingredients');
|
||||||
|
$table->foreignId('stock_entry_id')->constrained('stock_entries');
|
||||||
|
$table->decimal('quantity_used', 12, 2);
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(['production_id', 'ingredient_id']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::create('production_packagings', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('production_id')->constrained('productions')->cascadeOnDelete();
|
||||||
|
$table->foreignId('packaging_item_id')->constrained('packaging_items');
|
||||||
|
$table->unsignedInteger('quantity_used');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index('production_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('production_packagings');
|
||||||
|
Schema::dropIfExists('production_ingredients');
|
||||||
|
Schema::dropIfExists('productions');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('packaging_items', function (Blueprint $table) {
|
||||||
|
$table->string('url', 500)->nullable()->after('min_stock_alert');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('packaging_items', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('url');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue