mirror of
https://github.com/Karaka-Management/oms-ClientManagement.git
synced 2026-01-25 22:28:41 +00:00
bump
This commit is contained in:
parent
c717069fa9
commit
55794345ab
35
.github/dev_bug_report.md
vendored
35
.github/dev_bug_report.md
vendored
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
name: Dev Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: stat_backlog, type_bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Bug Description
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
# How to Reproduce
|
||||
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
## Minimal Code Example
|
||||
|
||||
```
|
||||
// your code ...
|
||||
```
|
||||
|
||||
# Expected Behavior
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
# Screenshots
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
# Additional Information
|
||||
Add any other context about the problem here.
|
||||
18
.github/dev_feature_request.md
vendored
18
.github/dev_feature_request.md
vendored
|
|
@ -1,18 +0,0 @@
|
|||
---
|
||||
name: Dev Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: stat_backlog, type_feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# What is the feature you request
|
||||
* A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
* A clear and concise description of what you want to happen.
|
||||
|
||||
# Alternatives
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
# Additional Information
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
[
|
||||
{
|
||||
"description": "Default client segmentation (segment, section, sales group, product group)",
|
||||
"type": "setting",
|
||||
"name": "1003100001",
|
||||
"content": "{\"segment\":1, \"section\":1, \"client_group\":1}",
|
||||
"pattern": "",
|
||||
"module": "ClientManagement"
|
||||
}
|
||||
]
|
||||
27
Admin/Install/Admin.install.php
Normal file
27
Admin/Install/Admin.install.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* Jingga
|
||||
*
|
||||
* PHP Version 8.1
|
||||
*
|
||||
* @package Modules\ClientManagement\Admin
|
||||
* @copyright Dennis Eichhorn
|
||||
* @license OMS License 2.0
|
||||
* @version 1.0.0
|
||||
* @link https://jingga.app
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use Modules\ClientManagement\Controller\ApiController;
|
||||
use Modules\ClientManagement\Models\SettingsEnum;
|
||||
|
||||
return [
|
||||
[
|
||||
"description" => "Default item segmentation (segment, section, sales group, product group)",
|
||||
'type' => 'setting',
|
||||
'name' => SettingsEnum::DEFAULT_SEGMENTATION,
|
||||
'content' => '{"segment":1, "section":1, "client_group":1}',
|
||||
'pattern' => '',
|
||||
'module' => ApiController::NAME,
|
||||
],
|
||||
];
|
||||
|
|
@ -38,6 +38,10 @@ class Admin
|
|||
*/
|
||||
public static function install(ApplicationAbstract $app, string $path) : void
|
||||
{
|
||||
// \Modules\Admin\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/Admin.install.json']);
|
||||
// We are creating default items in the ClientManagement installer.
|
||||
// This requires that these settings are already available
|
||||
// However, this install script runs AFTER the primary installer runs.
|
||||
// This causes problems for the item installation and is therefore moved to the "Installer".
|
||||
// \Modules\Admin\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/Admin.install.php']);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"type": 2,
|
||||
"subtype": 1,
|
||||
"name": "Clients",
|
||||
"uri": "{/base}/sales/client/list",
|
||||
"uri": "{/base}/sales/client/list?{?}",
|
||||
"target": "self",
|
||||
"icon": null,
|
||||
"order": 1,
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
"type": 3,
|
||||
"subtype": 1,
|
||||
"name": "List",
|
||||
"uri": "{/base}/sales/client/list",
|
||||
"uri": "{/base}/sales/client/list?{?}",
|
||||
"target": "self",
|
||||
"icon": null,
|
||||
"order": 1,
|
||||
|
|
|
|||
|
|
@ -331,19 +331,6 @@
|
|||
"default_value": "",
|
||||
"values": []
|
||||
},
|
||||
{
|
||||
"name": "order_limit",
|
||||
"l11n": {
|
||||
"en": "Order limit",
|
||||
"de": "Bestelllimit"
|
||||
},
|
||||
"value_type": 1,
|
||||
"is_custom_allowed": true,
|
||||
"validation_pattern": "",
|
||||
"is_required": false,
|
||||
"default_value": "",
|
||||
"values": []
|
||||
},
|
||||
{
|
||||
"name": "minimum_order",
|
||||
"l11n": {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
[
|
||||
|
||||
{
|
||||
"name": "internal_matchcodes",
|
||||
"is_required": false
|
||||
}
|
||||
]
|
||||
|
|
@ -61,7 +61,7 @@ final class Installer extends InstallerAbstract
|
|||
$attrTypes = self::createClientAttributeTypes($app, $attributes);
|
||||
$attrValues = self::createClientAttributeValues($app, $attrTypes, $attributes);
|
||||
|
||||
$data = \json_decode(\file_get_contents(__DIR__ . '/Install/Admin.install.json'), true);
|
||||
$data = include __DIR__ . '/Install/Admin.install.php';
|
||||
$content = \json_decode($data[0]['content'], true);
|
||||
|
||||
foreach ($content as $type => $_) {
|
||||
|
|
@ -102,7 +102,7 @@ final class Installer extends InstallerAbstract
|
|||
$l11nTypes = [];
|
||||
|
||||
/** @var \Modules\ClientManagement\Controller\ApiController $module */
|
||||
$module = $app->moduleManager->getModuleInstance('ClientManagement');
|
||||
$module = $app->moduleManager->get('ClientManagement');
|
||||
|
||||
foreach ($l11ns as $l11n) {
|
||||
$response = new HttpResponse();
|
||||
|
|
@ -143,7 +143,7 @@ final class Installer extends InstallerAbstract
|
|||
$clientAttrType = [];
|
||||
|
||||
/** @var \Modules\ClientManagement\Controller\ApiAttributeController $module */
|
||||
$module = $app->moduleManager->getModuleInstance('ClientManagement', 'ApiAttribute');
|
||||
$module = $app->moduleManager->get('ClientManagement', 'ApiAttribute');
|
||||
|
||||
/** @var array $attribute */
|
||||
foreach ($attributes as $attribute) {
|
||||
|
|
@ -211,7 +211,7 @@ final class Installer extends InstallerAbstract
|
|||
$clientAttrValue = [];
|
||||
|
||||
/** @var \Modules\ClientManagement\Controller\ApiAttributeController $module */
|
||||
$module = $app->moduleManager->getModuleInstance('ClientManagement', 'ApiAttribute');
|
||||
$module = $app->moduleManager->get('ClientManagement', 'ApiAttribute');
|
||||
|
||||
foreach ($attributes as $attribute) {
|
||||
$clientAttrValue[$attribute['name']] = [];
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ use phpOMS\Message\RequestAbstract;
|
|||
use phpOMS\Message\ResponseAbstract;
|
||||
use phpOMS\Model\Message\FormValidation;
|
||||
use phpOMS\Utils\StringUtils;
|
||||
use phpOMS\Validation\Finance\EUVat;
|
||||
|
||||
/**
|
||||
* ClientManagement class.
|
||||
|
|
@ -53,6 +54,12 @@ use phpOMS\Utils\StringUtils;
|
|||
* @license OMS License 2.0
|
||||
* @link https://jingga.app
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @todo Import client prices from csv/excel sheet
|
||||
* https://github.com/Karaka-Management/oms-ClientManagement/issues/17
|
||||
*
|
||||
* @todo Perform inflation increase on all client prices
|
||||
* https://github.com/Karaka-Management/oms-ClientManagement/issues/18
|
||||
*/
|
||||
final class ApiController extends Controller
|
||||
{
|
||||
|
|
@ -108,7 +115,10 @@ final class ApiController extends Controller
|
|||
|
||||
$validate = ['status' => -1];
|
||||
|
||||
if (\in_array($client->mainAddress->country, ISO3166CharEnum::getRegion('eu'))) {
|
||||
// Has to be in EU and match VAT pattern before we perform external API request
|
||||
if (\in_array($client->mainAddress->country, ISO3166CharEnum::getRegion('eu'))
|
||||
&& EUVat::isValid($request->getDataString('vat_id') ?? '')
|
||||
) {
|
||||
$validate = EUVATVies::validateQualified(
|
||||
$request->getDataString('vat_id') ?? '',
|
||||
$unit->getAttribute('vat_id')->value->valueStr ?? '',
|
||||
|
|
@ -289,7 +299,7 @@ final class ApiController extends Controller
|
|||
$client = new Client();
|
||||
$client->number = $request->getDataString('number') ?? '';
|
||||
$client->account = $account;
|
||||
$client->unit = $request->getDataInt('unit') ?? 1;
|
||||
$client->unit = $request->getDataInt('unit') ?? $this->app->unitId;
|
||||
|
||||
$request->setData('name', null, true);
|
||||
$client->mainAddress = $this->app->moduleManager->get('Admin', 'Api')->createAddressFromRequest($request);
|
||||
|
|
|
|||
|
|
@ -20,11 +20,13 @@ use Modules\ClientManagement\Models\Attribute\ClientAttributeTypeMapper;
|
|||
use Modules\ClientManagement\Models\Attribute\ClientAttributeValueL11nMapper;
|
||||
use Modules\ClientManagement\Models\Attribute\ClientAttributeValueMapper;
|
||||
use Modules\ClientManagement\Models\ClientMapper;
|
||||
use Modules\ClientManagement\Models\PermissionCategory;
|
||||
use Modules\ItemManagement\Models\Attribute\ItemAttributeTypeMapper;
|
||||
use Modules\ItemManagement\Models\Attribute\ItemAttributeValueL11nMapper;
|
||||
use Modules\Media\Models\MediaMapper;
|
||||
use Modules\Media\Models\MediaTypeMapper;
|
||||
use Modules\Organization\Models\Attribute\UnitAttributeMapper;
|
||||
use phpOMS\Account\PermissionType;
|
||||
use phpOMS\Asset\AssetType;
|
||||
use phpOMS\Contract\RenderableInterface;
|
||||
use phpOMS\DataStorage\Database\Query\Builder;
|
||||
|
|
@ -161,6 +163,7 @@ final class BackendController extends Controller
|
|||
$client = ClientMapper::getAll()
|
||||
->with('account')
|
||||
->with('mainAddress')
|
||||
->where('unit', $this->app->unitId)
|
||||
->limit(25)
|
||||
->execute();
|
||||
|
||||
|
|
@ -207,10 +210,10 @@ final class BackendController extends Controller
|
|||
$head = $response->data['Content']->head;
|
||||
$nonce = $this->app->appSettings->getOption('script-nonce');
|
||||
|
||||
$head->addAsset(AssetType::CSS, 'Resources/chartjs/chart.css');
|
||||
$head->addAsset(AssetType::JSLATE, 'Resources/chartjs/chart.js', ['nonce' => $nonce]);
|
||||
$head->addAsset(AssetType::JSLATE, 'Resources/OpenLayers/OpenLayers.js', ['nonce' => $nonce]);
|
||||
$head->addAsset(AssetType::JSLATE, 'Modules/ClientManagement/Controller.js', ['nonce' => $nonce, 'type' => 'module']);
|
||||
$head->addAsset(AssetType::CSS, 'Resources/chartjs/chart.css?v=' . $this->app->version);
|
||||
$head->addAsset(AssetType::JSLATE, 'Resources/chartjs/chart.js?v=' . $this->app->version, ['nonce' => $nonce]);
|
||||
$head->addAsset(AssetType::JSLATE, 'Resources/OpenLayers/OpenLayers.js?v=' . $this->app->version, ['nonce' => $nonce]);
|
||||
$head->addAsset(AssetType::JSLATE, 'Modules/ClientManagement/Controller.js?v=' . self::VERSION, ['nonce' => $nonce, 'type' => 'module']);
|
||||
|
||||
$view = new View($this->app->l11nManager, $request, $response);
|
||||
$view->setTemplate('/Modules/ClientManagement/Theme/Backend/client-view');
|
||||
|
|
@ -335,12 +338,24 @@ final class BackendController extends Controller
|
|||
|
||||
$view->data['clientSegmentationTypes'] = $clientSegmentationTypes;
|
||||
|
||||
/** @var \Modules\Auditor\Models\Audit[] */
|
||||
$view->data['audits'] = AuditMapper::getAll()
|
||||
->where('type', StringUtils::intHash(ClientMapper::class))
|
||||
->where('module', 'ClientManagement')
|
||||
->where('ref', (string) $view->data['client']->id)
|
||||
->execute();
|
||||
$logs = [];
|
||||
if ($this->app->accountManager->get($request->header->account)->hasPermission(
|
||||
PermissionType::READ,
|
||||
$this->app->unitId,
|
||||
null,
|
||||
self::NAME,
|
||||
PermissionCategory::CLIENT_LOG,
|
||||
)
|
||||
) {
|
||||
/** @var \Modules\Auditor\Models\Audit[] */
|
||||
$logs = AuditMapper::getAll()
|
||||
->where('type', StringUtils::intHash(ClientMapper::class))
|
||||
->where('module', 'ClientManagement')
|
||||
->where('ref', (string) $view->data['client']->id)
|
||||
->execute();
|
||||
}
|
||||
|
||||
$view->data['logs'] = $logs;
|
||||
|
||||
// @todo join audit with files, attributes, localization, prices, notes, ...
|
||||
|
||||
|
|
|
|||
3
Docs/Help/de/SUMMARY.md
Normal file
3
Docs/Help/de/SUMMARY.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# User Content
|
||||
|
||||
* [Attributes]({%}&page=Help/attributes)
|
||||
0
Docs/Help/de/accounting.md
Normal file
0
Docs/Help/de/accounting.md
Normal file
59
Docs/Help/de/attributes.md
Normal file
59
Docs/Help/de/attributes.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Attributes
|
||||
|
||||
## Default
|
||||
|
||||
The module automatically installs the following default attributes which can be set in the attribute tab in the respective client.
|
||||
|
||||
### General
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| abc_class | Custom client rating | |
|
||||
| support_emails | Send email for support ticket changes | yes |
|
||||
| support_email_address | Email address for support tickets | Account email |
|
||||
| legal_form | Client legal form | |
|
||||
|
||||
### Categories
|
||||
|
||||
Clients can be put in categories for horizontal and vertical grouping. By default the system uses segment->section->client_group as categories as well as client_type. These categories also get used by other modules. Additional groups can be defined but are not used by other modules by default.
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| segment | Level 1 | 1 |
|
||||
| section | Level 2 | 1 |
|
||||
| client_group | Level 3 | 1 |
|
||||
| client_type | **NOT** hierarchically. | 1 |
|
||||
| client_area | **NOT** hierarchically. Area a client belongs to. Useful for grouping customers based on location or sales rep. | |
|
||||
|
||||
| Level | > | > | > | > | > | > | Sample |
|
||||
| :---: | :-----------------: | :-: | :-----------------: | :-: | :-----------------: | :-----------------: | :----------------: |
|
||||
| 1 | > | > | > | > | Segment 1 | > | Segment 2 |
|
||||
| 2 | > | > | Section 1.1 | > | Section 1.2 | > | Section 2.1 |
|
||||
| 3 | Client Group 1.1.1 | > | Client Group 1.1.2 | > | Client Group 1.2.1 | Client Group 2.1.1 | Client Group 2.1.2 |
|
||||
|
||||
> You could consider the client (number) itself `Level 4`.
|
||||
|
||||
### Billing
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| bill_emails | Should bills get emailed to the customer | yes |
|
||||
| bill_email_address | Email address used for sending bill via email | account email |
|
||||
| bill_language | Language of the bill | Account language -> default bill language |
|
||||
| bill_currency | Currency of the bill. Coming soon. | |
|
||||
|
||||
### Purchase & Stock
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| minimum_order | Minimum order amount required from customer | |
|
||||
|
||||
### Accounting
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| sales_tax_code | Tax code for sales | |
|
||||
| vat_id | VAT id for european customers | |
|
||||
| tax_id | Tax id for local tax id | |
|
||||
| line_of_credit | Maximum amount allowed to be purchased taking unpaid invoices into account | |
|
||||
| credit_rating | Credit rating | |
|
||||
54
Docs/Help/de/introduction.md
Normal file
54
Docs/Help/de/introduction.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Introduction
|
||||
|
||||
The **Item Management** module is an essential module for any ERP application. This module handles basic item management and is deeply integrated into **Billing** and **Warehouse Management**.
|
||||
|
||||
## Target Group
|
||||
|
||||
The target group for this module is anyone who wants to manage their tangible and non-tangible products.
|
||||
|
||||
# Setup
|
||||
|
||||
This module doesn't have any additional setup requirements and can be simply installed through the module interface.
|
||||
|
||||
# Features
|
||||
|
||||
## Item master file
|
||||
|
||||
The module provides basic item data management
|
||||
|
||||
* Attach documents to items
|
||||
* Write notes for items
|
||||
* Overview of most recent notes, documents, invoices and sales statistics (requires **Billing**)
|
||||
|
||||
## Localization
|
||||
|
||||
Localizations allow you to define item names and descriptions in multiple languages. You can also define custom text elements for external use (e.g. descriptions to be exported to other systems such as your own shop system).
|
||||
|
||||
## Attributes
|
||||
|
||||
Attributes allow you to define various item characteristics such as color, medical device class, segmentation, hazardous good, brand, model and many more.
|
||||
|
||||
## Pricing
|
||||
|
||||
By installing the **Billing** module you are can define multiple purchase and sales prices. Prices and discounts can be defined for individual items, customers and suppliers and for customer groups. You may also define quantity based prices.
|
||||
|
||||
## Procurement
|
||||
|
||||
Together with the **Purchase** module you can define stock levels, order conditions and delivery times for automated order suggestion calculations making it a breeze to ensure sufficient stocks.
|
||||
|
||||
## Accounting
|
||||
|
||||
Together with the **Accounting** module you can define cost center, cost object and taxes for every item.
|
||||
|
||||
## Stock
|
||||
|
||||
Together with the **Warehouse Management** module you can also track your stocks and
|
||||
|
||||
# Recommendation
|
||||
|
||||
Other modules that work great with this one together are:
|
||||
|
||||
* [Warehouse Management](WarehouseManagement)
|
||||
* [Supplier Management](SupplierManagement)
|
||||
* [Purchase](Purchase)
|
||||
* [Accounting](Accounting)
|
||||
14
Docs/Help/de/localization.md
Normal file
14
Docs/Help/de/localization.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Localization
|
||||
|
||||
## Default
|
||||
|
||||
The module automatically installs the following default localizations which can be set in the localization tab in the respective item.
|
||||
|
||||
* name1 - Primary item name
|
||||
* name2 - Secondary item name
|
||||
* info - Internal item info
|
||||
* internal_matchcodes - Match code for finding item based on a specific name or short description
|
||||
* description_short - Short item description
|
||||
* description_long - Long item description
|
||||
* shop_name1 - Primary item name for a shop system
|
||||
* shop_name2 - Secondary item name for a shop system
|
||||
0
Docs/Help/de/pricing.md
Normal file
0
Docs/Help/de/pricing.md
Normal file
3
Docs/Help/en/SUMMARY.md
Normal file
3
Docs/Help/en/SUMMARY.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# User Content
|
||||
|
||||
* [Attributes]({%}&page=Help/attributes)
|
||||
0
Docs/Help/en/accounting.md
Normal file
0
Docs/Help/en/accounting.md
Normal file
59
Docs/Help/en/attributes.md
Normal file
59
Docs/Help/en/attributes.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Attributes
|
||||
|
||||
## Default
|
||||
|
||||
The module automatically installs the following default attributes which can be set in the attribute tab in the respective client.
|
||||
|
||||
### General
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| abc_class | Custom client rating | |
|
||||
| support_emails | Send email for support ticket changes | yes |
|
||||
| support_email_address | Email address for support tickets | Account email |
|
||||
| legal_form | Client legal form | |
|
||||
|
||||
### Categories
|
||||
|
||||
Clients can be put in categories for horizontal and vertical grouping. By default the system uses segment->section->client_group as categories as well as client_type. These categories also get used by other modules. Additional groups can be defined but are not used by other modules by default.
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| segment | Level 1 | 1 |
|
||||
| section | Level 2 | 1 |
|
||||
| client_group | Level 3 | 1 |
|
||||
| client_type | **NOT** hierarchically. | 1 |
|
||||
| client_area | **NOT** hierarchically. Area a client belongs to. Useful for grouping customers based on location or sales rep. | |
|
||||
|
||||
| Level | > | > | > | > | > | > | Sample |
|
||||
| :---: | :-----------------: | :-: | :-----------------: | :-: | :-----------------: | :-----------------: | :----------------: |
|
||||
| 1 | > | > | > | > | Segment 1 | > | Segment 2 |
|
||||
| 2 | > | > | Section 1.1 | > | Section 1.2 | > | Section 2.1 |
|
||||
| 3 | Client Group 1.1.1 | > | Client Group 1.1.2 | > | Client Group 1.2.1 | Client Group 2.1.1 | Client Group 2.1.2 |
|
||||
|
||||
> You could consider the client (number) itself `Level 4`.
|
||||
|
||||
### Billing
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| bill_emails | Should bills get emailed to the customer | yes |
|
||||
| bill_email_address | Email address used for sending bill via email | account email |
|
||||
| bill_language | Language of the bill | Account language -> default bill language |
|
||||
| bill_currency | Currency of the bill. Coming soon. | |
|
||||
|
||||
### Purchase & Stock
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| minimum_order | Minimum order amount required from customer | |
|
||||
|
||||
### Accounting
|
||||
|
||||
| Attribute | Description | Internal default value |
|
||||
| --------- | ----------- | ---------------------- |
|
||||
| sales_tax_code | Tax code for sales | |
|
||||
| vat_id | VAT id for european customers | |
|
||||
| tax_id | Tax id for local tax id | |
|
||||
| line_of_credit | Maximum amount allowed to be purchased taking unpaid invoices into account | |
|
||||
| credit_rating | Credit rating | |
|
||||
54
Docs/Help/en/introduction.md
Normal file
54
Docs/Help/en/introduction.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Introduction
|
||||
|
||||
The **Item Management** module is an essential module for any ERP application. This module handles basic item management and is deeply integrated into **Billing** and **Warehouse Management**.
|
||||
|
||||
## Target Group
|
||||
|
||||
The target group for this module is anyone who wants to manage their tangible and non-tangible products.
|
||||
|
||||
# Setup
|
||||
|
||||
This module doesn't have any additional setup requirements and can be simply installed through the module interface.
|
||||
|
||||
# Features
|
||||
|
||||
## Item master file
|
||||
|
||||
The module provides basic item data management
|
||||
|
||||
* Attach documents to items
|
||||
* Write notes for items
|
||||
* Overview of most recent notes, documents, invoices and sales statistics (requires **Billing**)
|
||||
|
||||
## Localization
|
||||
|
||||
Localizations allow you to define item names and descriptions in multiple languages. You can also define custom text elements for external use (e.g. descriptions to be exported to other systems such as your own shop system).
|
||||
|
||||
## Attributes
|
||||
|
||||
Attributes allow you to define various item characteristics such as color, medical device class, segmentation, hazardous good, brand, model and many more.
|
||||
|
||||
## Pricing
|
||||
|
||||
By installing the **Billing** module you are can define multiple purchase and sales prices. Prices and discounts can be defined for individual items, customers and suppliers and for customer groups. You may also define quantity based prices.
|
||||
|
||||
## Procurement
|
||||
|
||||
Together with the **Purchase** module you can define stock levels, order conditions and delivery times for automated order suggestion calculations making it a breeze to ensure sufficient stocks.
|
||||
|
||||
## Accounting
|
||||
|
||||
Together with the **Accounting** module you can define cost center, cost object and taxes for every item.
|
||||
|
||||
## Stock
|
||||
|
||||
Together with the **Warehouse Management** module you can also track your stocks and
|
||||
|
||||
# Recommendation
|
||||
|
||||
Other modules that work great with this one together are:
|
||||
|
||||
* [Warehouse Management](WarehouseManagement)
|
||||
* [Supplier Management](SupplierManagement)
|
||||
* [Purchase](Purchase)
|
||||
* [Accounting](Accounting)
|
||||
14
Docs/Help/en/localization.md
Normal file
14
Docs/Help/en/localization.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Localization
|
||||
|
||||
## Default
|
||||
|
||||
The module automatically installs the following default localizations which can be set in the localization tab in the respective item.
|
||||
|
||||
* name1 - Primary item name
|
||||
* name2 - Secondary item name
|
||||
* info - Internal item info
|
||||
* internal_matchcodes - Match code for finding item based on a specific name or short description
|
||||
* description_short - Short item description
|
||||
* description_long - Long item description
|
||||
* shop_name1 - Primary item name for a shop system
|
||||
* shop_name2 - Secondary item name for a shop system
|
||||
0
Docs/Help/en/pricing.md
Normal file
0
Docs/Help/en/pricing.md
Normal file
|
|
@ -31,4 +31,6 @@ abstract class PermissionCategory extends Enum
|
|||
public const ANALYSIS = 2;
|
||||
|
||||
public const CLIENT_NOTE = 3;
|
||||
|
||||
public const CLIENT_LOG = 101;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,6 +125,6 @@ return ['ClientManagement' => [
|
|||
'ClientType' => 'Kundenart',
|
||||
'ItemType' => 'Artikeltyp',
|
||||
'Item' => 'Item',
|
||||
'EarningIndicator' => 'Erlöskennzeichen',
|
||||
'CostIndicator' => 'Kostenkennzeichen',
|
||||
'EarningIndicator' => 'Verkaufssteuerkennzeichen',
|
||||
'CostIndicator' => 'Einkaufssteuerkennzeichen',
|
||||
]];
|
||||
|
|
|
|||
|
|
@ -127,6 +127,6 @@ return ['ClientManagement' => [
|
|||
'ClientType' => 'Client Type',
|
||||
'ItemType' => 'Item Type',
|
||||
'Item' => 'Item',
|
||||
'EarningIndicator' => 'Earning Indicator',
|
||||
'CostIndicator' => 'Cost Indicator',
|
||||
'EarningIndicator' => 'Sales tax code',
|
||||
'CostIndicator' => 'Purchase tax code',
|
||||
]];
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ $languages = ISO639Enum::getConstants();
|
|||
$client = $this->data['client'];
|
||||
$clientImage = $this->data['clientImage'] ?? new NullMedia();
|
||||
|
||||
$logs = $this->data['logs'] ?? [];
|
||||
|
||||
/**
|
||||
* @var \phpOMS\Views\View $this
|
||||
*/
|
||||
|
|
@ -58,7 +60,7 @@ echo $this->data['nav']->render();
|
|||
<li><label for="c-tab-8"><?= $this->getHtml('Files'); ?></label>
|
||||
<li><label for="c-tab-9"><?= $this->getHtml('Bills'); ?></label>
|
||||
<li><label for="c-tab-10"><?= $this->getHtml('Items'); ?></label>
|
||||
<li><label for="c-tab-17"><?= $this->getHtml('Logs'); ?></label>
|
||||
<?php if (!empty($logs)) : ?><li><label for="c-tab-17"><?= $this->getHtml('Logs'); ?></label><?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
|
|
@ -206,7 +208,7 @@ echo $this->data['nav']->render();
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<section class="portlet highlight-4">
|
||||
<section class="portlet hl-4">
|
||||
<div class="portlet-body">
|
||||
<textarea class="undecorated"><?= $this->printHtml($client->info); ?></textarea>
|
||||
</div>
|
||||
|
|
@ -217,7 +219,7 @@ echo $this->data['nav']->render();
|
|||
<!-- If note warning exists -->
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<section class="portlet highlight-1">
|
||||
<section class="portlet hl-1">
|
||||
<div class="portlet-body"><?= $this->printHtml($warning->plain); ?></div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -227,22 +229,22 @@ echo $this->data['nav']->render();
|
|||
<?php if ($this->data['hasBilling']) : ?>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-lg-4">
|
||||
<section class="portlet highlight-7">
|
||||
<section class="portlet hl-7">
|
||||
<div class="portlet-body">
|
||||
<table class="wf-100">
|
||||
<tr><td><?= $this->getHtml('YTDSales'); ?>:
|
||||
<td><?= $this->getCurrency(SalesBillMapper::getClientNetSales($client->id, SmartDateTime::startOfYear($this->data['business_start']), new \DateTime('now')), format: 'medium'); ?>
|
||||
<td><?= SalesBillMapper::getClientNetSales($client->id, SmartDateTime::startOfYear($this->data['business_start']), new \DateTime('now'))->getAmount(); ?>
|
||||
<tr><td><?= $this->getHtml('MTDSales'); ?>:
|
||||
<td><?= $this->getCurrency(SalesBillMapper::getClientNetSales($client->id, SmartDateTime::startOfMonth(), new \DateTime('now')), format: 'medium'); ?>
|
||||
<td><?= SalesBillMapper::getClientNetSales($client->id, SmartDateTime::startOfMonth(), new \DateTime('now'))->getAmount(); ?>
|
||||
<tr><td><?= $this->getHtml('CLV'); ?>:
|
||||
<td><?= $this->getCurrency(SalesBillMapper::getCLVHistoric($client->id), format: 'medium'); ?>
|
||||
<td><?= SalesBillMapper::getCLVHistoric($client->id)->getAmount(); ?>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-lg-4">
|
||||
<section class="portlet highlight-2">
|
||||
<section class="portlet hl-2">
|
||||
<div class="portlet-body">
|
||||
<table class="wf-100">
|
||||
<tr><td><?= $this->getHtml('LastContact'); ?>:
|
||||
|
|
@ -257,7 +259,7 @@ echo $this->data['nav']->render();
|
|||
</div>
|
||||
|
||||
<div class="col-xs-12 col-lg-4">
|
||||
<section class="portlet highlight-3">
|
||||
<section class="portlet hl-3">
|
||||
<div class="portlet-body">
|
||||
<table class="wf-100">
|
||||
<tr><td><?= $this->getHtml('DSO'); ?>:
|
||||
|
|
@ -553,9 +555,9 @@ echo $this->data['nav']->render();
|
|||
data-add-tpl="#clientSalesPriceTable tbody .oms-add-tpl-clientSalesPrice">
|
||||
<div class="portlet-head"><?= $this->getHtml('Pricing'); ?></div>
|
||||
<div class="portlet-body">
|
||||
<input id="iPriceId" class="hidden" name="id" type="number" data-tpl-text="/id" data-tpl-value="/id">
|
||||
<input id="iPriceClientId" class="hidden" name="client" type="text" value="<?= $client->id; ?>">
|
||||
<input id="iPriceItemType" class="hidden" name="type" type="text" value="<?= PriceType::SALES; ?>">
|
||||
<input id="iPriceId" class="vh" name="id" type="number" data-tpl-text="/id" data-tpl-value="/id">
|
||||
<input id="iPriceClientId" class="vh" name="client" type="text" value="<?= $client->id; ?>">
|
||||
<input id="iPriceItemType" class="vh" name="type" type="text" value="<?= PriceType::SALES; ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="iPriceName"><?= $this->getHtml('Name'); ?></label>
|
||||
|
|
@ -600,8 +602,8 @@ echo $this->data['nav']->render();
|
|||
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<label for="iPriceDiscountP"><?= $this->getHtml('DiscountP'); ?></label>
|
||||
<input id="iPriceDiscountP" name="discountPercentage" type="number" data-tpl-text="/discountp" data-tpl-value="/discountp">
|
||||
<label for="iPriceDiscountR"><?= $this->getHtml('DiscountP'); ?></label>
|
||||
<input id="iPriceDiscountR" name="discountPercentage" type="number" data-tpl-text="/discountr" data-tpl-value="/discountr">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -767,8 +769,8 @@ echo $this->data['nav']->render();
|
|||
</div>
|
||||
<div class="portlet-foot">
|
||||
<input id="bPriceItemAdd" formmethod="put" type="submit" class="add-form" value="<?= $this->getHtml('Add', '0', '0'); ?>">
|
||||
<input id="bPriceItemSave" formmethod="post" type="submit" class="save-form hidden button save" value="<?= $this->getHtml('Update', '0', '0'); ?>">
|
||||
<input id="bPriceItemCancel" type="submit" class="cancel-form hidden button close" value="<?= $this->getHtml('Cancel', '0', '0'); ?>">
|
||||
<input id="bPriceItemSave" formmethod="post" type="submit" class="save-form vh button save" value="<?= $this->getHtml('Update', '0', '0'); ?>">
|
||||
<input id="bPriceItemCancel" type="submit" class="cancel-form vh button close" value="<?= $this->getHtml('Cancel', '0', '0'); ?>">
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
|
@ -813,7 +815,7 @@ echo $this->data['nav']->render();
|
|||
<tr class="animated medium-duration greenCircleFade" data-id="" draggable="false">
|
||||
<td>
|
||||
<i class="g-icon btn update-form">settings</i>
|
||||
<input id="clientSalesPriceTable-remove-0" type="checkbox" class="hidden">
|
||||
<input id="clientSalesPriceTable-remove-0" type="checkbox" class="vh">
|
||||
<label for="clientSalesPriceTable-remove-0" class="checked-visibility-alt"><i class="g-icon btn form-action">close</i></label>
|
||||
<span class="checked-visibility">
|
||||
<label for="clientSalesPriceTable-remove-0" class="link default"><?= $this->getHtml('Cancel', '0', '0'); ?></label>
|
||||
|
|
@ -826,7 +828,7 @@ echo $this->data['nav']->render();
|
|||
<td data-tpl-text="/currency" data-tpl-value="/currency"></td>
|
||||
<td data-tpl-text="/quantity" data-tpl-value="/quantity"></td>
|
||||
<td data-tpl-text="/discount" data-tpl-value="/discount"></td>
|
||||
<td data-tpl-text="/discountp" data-tpl-value="/discountp"></td>
|
||||
<td data-tpl-text="/discountr" data-tpl-value="/discountr"></td>
|
||||
<td data-tpl-text="/bonus" data-tpl-value="/bonus"></td>
|
||||
<td data-tpl-text="/item_item" data-tpl-value="/item_item"></td>
|
||||
<td data-tpl-text="/item_segment" data-tpl-value="/item_segment"></td>
|
||||
|
|
@ -852,7 +854,7 @@ echo $this->data['nav']->render();
|
|||
<td>
|
||||
<i class="g-icon btn update-form">settings</i>
|
||||
<?php if ($value->name !== 'default') : ?>
|
||||
<input id="clientSalesPriceTable-remove-<?= $value->id; ?>" type="checkbox" class="hidden">
|
||||
<input id="clientSalesPriceTable-remove-<?= $value->id; ?>" type="checkbox" class="vh">
|
||||
<label for="clientSalesPriceTable-remove-<?= $value->id; ?>" class="checked-visibility-alt"><i class="g-icon btn form-action">close</i></label>
|
||||
<span class="checked-visibility">
|
||||
<label for="clientSalesPriceTable-remove-<?= $value->id; ?>" class="link default"><?= $this->getHtml('Cancel', '0', '0'); ?></label>
|
||||
|
|
@ -866,7 +868,7 @@ echo $this->data['nav']->render();
|
|||
<td data-tpl-text="/currency" data-tpl-value="/currency"><?= $this->printHtml($value->currency); ?>
|
||||
<td data-tpl-text="/quantity" data-tpl-value="/quantity"><?= $value->quantity->getAmount(); ?>
|
||||
<td data-tpl-text="/discount" data-tpl-value="/discount"><?= $value->discount->getAmount(); ?>
|
||||
<td data-tpl-text="/discountp" data-tpl-value="/discountp"><?= $this->getPercentage($value->discountPercentage->value / 10000 / 100); ?>
|
||||
<td data-tpl-text="/discountr" data-tpl-value="/discountr"><?= $this->getPercentage($value->discountPercentage); ?>
|
||||
<td data-tpl-text="/bonus" data-tpl-value="/bonus"><?= $value->bonus->getAmount(); ?>
|
||||
<td data-tpl-text="/item_item" data-tpl-value="/item_item"><?= $this->printHtml((string) $value->item); ?>
|
||||
<td data-tpl-text="/item_segment" data-tpl-value="/item_segment"><?= $this->printHtml((string) $value->itemsegment->getL11n()); ?>
|
||||
|
|
@ -1153,8 +1155,8 @@ echo $this->data['nav']->render();
|
|||
<td><a href="<?= $url; ?>"><?= $this->printHtml((string) $value->quantity->getAmount()); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $this->getCurrency($value->singleSalesPriceNet, symbol: ''); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $this->getCurrency($value->singleDiscountP, symbol: ''); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $this->getPercentage($value->singleDiscountR?->value ?? 0); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $this->getNumeric($value->discountQ?->value ?? 0); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $this->getPercentage($value->singleDiscountR); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $this->getNumeric($value->discountQ?->value); ?></a>
|
||||
<td><a href="<?= $url; ?>"><?= $this->getCurrency($value->totalSalesPriceNet, symbol: ''); ?></a>
|
||||
<?php endforeach; ?>
|
||||
<?php if ($count === 0) : ?>
|
||||
|
|
@ -1172,6 +1174,7 @@ echo $this->data['nav']->render();
|
|||
<?= $this->data['note']->render('client-note', 'notes', $client->notes); ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($logs)) : ?>
|
||||
<input type="radio" id="c-tab-17" name="tabular-2" checked>
|
||||
<div class="tab">
|
||||
<div class="row">
|
||||
|
|
@ -1203,11 +1206,10 @@ echo $this->data['nav']->render();
|
|||
<tbody>
|
||||
<?php
|
||||
$count = 0;
|
||||
$audits = $this->data['audits'] ?? [];
|
||||
$previous = empty($audits) ? HttpHeader::getAllHeaders()['Referer'] ?? 'admin/module/settings?id={?id}#{\#}' : 'admin/module/settings?{?}&audit=' . \reset($audits)->id . '&ptype=p#{\#}';
|
||||
$next = empty($audits) ? HttpHeader::getAllHeaders()['Referer'] ?? 'admin/module/settings?id={?id}#{\#}' : 'admin/module/settings?{?}&audit=' . \end($audits)->id . '&ptype=n#{\#}';
|
||||
$previous = empty($logs) ? HttpHeader::getAllHeaders()['Referer'] ?? 'admin/module/settings?id={?id}#{\#}' : 'admin/module/settings?{?}&audit=' . \reset($logs)->id . '&ptype=p#{\#}';
|
||||
$next = empty($logs) ? HttpHeader::getAllHeaders()['Referer'] ?? 'admin/module/settings?id={?id}#{\#}' : 'admin/module/settings?{?}&audit=' . \end($logs)->id . '&ptype=n#{\#}';
|
||||
|
||||
foreach ($audits as $key => $audit) : ++$count;
|
||||
foreach ($logs as $key => $audit) : ++$count;
|
||||
$url = UriFactory::build('{/base}/admin/audit/view?{?}&id=' . $audit->id); ?>
|
||||
<tr tabindex="0" data-href="<?= $url; ?>">
|
||||
<td><?= $audit->id; ?>
|
||||
|
|
@ -1232,5 +1234,6 @@ echo $this->data['nav']->render();
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user