diff --git a/Controller.js b/Controller.js index 48ca412..dcee1de 100755 --- a/Controller.js +++ b/Controller.js @@ -1,10 +1,8 @@ import { Autoloader } from '../../jsOMS/Autoloader.js'; -import { NotificationMessage } from '../../jsOMS/Message/Notification/NotificationMessage.js'; -import { NotificationType } from '../../jsOMS/Message/Notification/NotificationType.js'; Autoloader.defineNamespace('jsOMS.Modules'); -jsOMS.Modules.SupplierManager = class { +jsOMS.Modules.SupplierManagement = class { /** * @constructor * @@ -17,24 +15,31 @@ jsOMS.Modules.SupplierManager = class { bind (id) { - const e = typeof id === 'undefined' ? document.getElementsByTagName('canvas') : [document.getElementById(id)], - length = e.length; + const charts = typeof id === 'undefined' ? document.getElementsByTagName('canvas') : [document.getElementById(id)]; + let length = charts.length; for (let i = 0; i < length; ++i) { - if (e[i].getAttribute('data-chart') === null - && e[i].getAttribute('data-chart') !== 'undefined' + if (charts[i].getAttribute('data-chart') === null + && charts[i].getAttribute('data-chart') !== 'undefined' ) { continue; } - this.bindElement(e[i]); + this.bindChart(charts[i]); + } + + const maps = typeof id === 'undefined' ? document.getElementsByClassName('map') : [document.getElementById(id)]; + length = maps.length; + + for (let i = 0; i < length; ++i) { + this.bindMap(maps[i]); } }; - bindElement (chart) + bindChart (chart) { if (typeof chart === 'undefined' || !chart) { - jsOMS.Log.Logger.instance.error('Invalid chart: ' + chart, 'SupplierManagementController'); + jsOMS.Log.Logger.instance.error('Invalid chart: ' + chart, 'SupplierManagement'); return; } @@ -44,6 +49,42 @@ jsOMS.Modules.SupplierManager = class { const myChart = new Chart(chart.getContext('2d'), data); }; + + bindMap (map) + { + if (typeof map === 'undefined' || !map) { + jsOMS.Log.Logger.instance.error('Invalid map: ' + map, 'SupplierManagement'); + + return; + } + + const mapObj = new OpenLayers.Map(map.getAttribute('id'), { + controls: [ + new OpenLayers.Control.Navigation( + { + zoomBoxEnabled: true, + zoomWheelEnabled: false + } + ), + new OpenLayers.Control.Zoom(), + new OpenLayers.Control.Attribution() + ] + }); + + mapObj.addLayer(new OpenLayers.Layer.OSM()); + + const fromProjection = new OpenLayers.Projection("EPSG:4326"); // Transform from WGS 1984 + const toProjection = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection + const position = new OpenLayers.LonLat(map.getAttribute('data-lon'), map.getAttribute('data-lat')).transform(fromProjection, toProjection); + const zoom = 12; + + const markers = new OpenLayers.Layer.Markers("Markers"); + mapObj.addLayer(markers); + + markers.addMarker(new OpenLayers.Marker(position)); + + mapObj.setCenter(position, zoom); + }; }; -window.omsApp.moduleManager.get('SupplierManager').bind(); +window.omsApp.moduleManager.get('SupplierManagement').bind(); diff --git a/Controller/BackendController.php b/Controller/BackendController.php index c3e8462..72f9466 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -15,12 +15,15 @@ declare(strict_types=1); namespace Modules\SupplierManagement\Controller; use Modules\Billing\Models\PurchaseBillMapper; +use Modules\Media\Models\MediaMapper; +use Modules\Media\Models\MediaTypeMapper; use Modules\SupplierManagement\Models\SupplierAttributeTypeL11nMapper; use Modules\SupplierManagement\Models\SupplierAttributeTypeMapper; use Modules\SupplierManagement\Models\SupplierAttributeValueMapper; use Modules\SupplierManagement\Models\SupplierMapper; use phpOMS\Asset\AssetType; use phpOMS\Contract\RenderableInterface; +use phpOMS\DataStorage\Database\Query\Builder; use phpOMS\DataStorage\Database\Query\OrderType; use phpOMS\Localization\Money; use phpOMS\Message\RequestAbstract; @@ -196,11 +199,11 @@ final class BackendController extends Controller */ public function viewSupplierManagementSupplierProfile(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : RenderableInterface { - /** @var \phpOMS\Model\Html\Head $head */ - $head = $response->get('Content')->head; + $head = $response->data['Content']->head; $head->addAsset(AssetType::CSS, 'Resources/chartjs/Chartjs/chart.css'); $head->addAsset(AssetType::JSLATE, 'Resources/chartjs/Chartjs/chart.js'); - $head->addAsset(AssetType::JSLATE, 'Modules/SupplierManagement/Controller.js', ['type' => 'module']); + $head->addAsset(AssetType::JSLATE, 'Resources/OpenLayers/OpenLayers.js'); + $head->addAsset(AssetType::JSLATE, 'Modules/ClientManagement/Controller.js', ['type' => 'module']); $view = new View($this->app->l11nManager, $request, $response); $view->setTemplate('/Modules/SupplierManagement/Theme/Backend/supplier-profile'); @@ -218,6 +221,34 @@ final class BackendController extends Controller $view->data['supplier'] = $supplier; + // Get item profile image + // It might not be part of the 5 newest item files from above + // @todo: It would be nice to have something like this as a default method in the model e.g. + // ItemManagement::getRelations()->with('types')->where(...); + // This should return the relations and NOT the model itself + $query = new Builder($this->app->dbPool->get()); + $results = $query->selectAs(SupplierMapper::HAS_MANY['files']['external'], 'file') + ->from(SupplierMapper::TABLE) + ->leftJoin(SupplierMapper::HAS_MANY['files']['table']) + ->on(SupplierMapper::HAS_MANY['files']['table'] . '.' . SupplierMapper::HAS_MANY['files']['self'], '=', SupplierMapper::TABLE . '.' . SupplierMapper::PRIMARYFIELD) + ->leftJoin(MediaMapper::TABLE) + ->on(SupplierMapper::HAS_MANY['files']['table'] . '.' . SupplierMapper::HAS_MANY['files']['external'], '=', MediaMapper::TABLE . '.' . MediaMapper::PRIMARYFIELD) + ->leftJoin(MediaMapper::HAS_MANY['types']['table']) + ->on(MediaMapper::TABLE . '.' . MediaMapper::PRIMARYFIELD, '=', MediaMapper::HAS_MANY['types']['table'] . '.' . MediaMapper::HAS_MANY['types']['self']) + ->leftJoin(MediaTypeMapper::TABLE) + ->on(MediaMapper::HAS_MANY['types']['table'] . '.' . MediaMapper::HAS_MANY['types']['external'], '=', MediaTypeMapper::TABLE . '.' . MediaTypeMapper::PRIMARYFIELD) + ->where(SupplierMapper::HAS_MANY['files']['self'], '=', $supplier->id) + ->where(MediaTypeMapper::TABLE . '.' . MediaTypeMapper::getColumnByMember('name'), '=', 'supplier_profile_image'); + + + $clientImage = MediaMapper::get() + ->with('types') + ->where('id', $results) + ->limit(1) + ->execute(); + + $view->data['clientImage'] = $clientImage; + // stats if ($this->app->moduleManager->isActive('Billing')) { $ytd = PurchaseBillMapper::getPurchaseBySupplierId($supplier->id, new SmartDateTime('Y-01-01'), new SmartDateTime('now')); diff --git a/Theme/Backend/supplier-list.tpl.php b/Theme/Backend/supplier-list.tpl.php index 8897a63..86b5e03 100755 --- a/Theme/Backend/supplier-list.tpl.php +++ b/Theme/Backend/supplier-list.tpl.php @@ -27,7 +27,6 @@ echo $this->data['nav']->render(); ?> - $value) : ++$count; - $url = UriFactory::build('{/base}/purchase/supplier/profile?{?}&id=' . $value->id); - $image = $value->getFileByTypeName('supplier_profile_image'); ?> + $url = UriFactory::build('{/base}/purchase/supplier/profile?{?}&id=' . $value->id); + ?> -
getHtml('ID', '0', '0'); ?>
<?= $this->getHtml('IMG_alt_supplier'); ?> printHtml($value->number); ?> - printHtml($value->profile->account->name1); ?> printHtml($value->profile->account->name2); ?> + printHtml($value->account->name1); ?> printHtml($value->account->name2); ?> printHtml($value->mainAddress->city); ?> printHtml($value->mainAddress->postal); ?> printHtml($value->mainAddress->address); ?> diff --git a/Theme/Backend/supplier-profile-bills.tpl.php b/Theme/Backend/supplier-profile-bills.tpl.php new file mode 100644 index 0000000..9e9792f --- /dev/null +++ b/Theme/Backend/supplier-profile-bills.tpl.php @@ -0,0 +1,194 @@ +data['newestInvoices'] ?? []; + +?> + +
+
+
+
getHtml('Bills'); ?>
+ + + + + $value) : + ++$count; + $url = UriFactory::build('{/base}/purchase/bill?{?}&id=' . $value->id); + ?> + +
+ getHtml('ID', '0', '0'); ?> + + + + getHtml('Type'); ?> + + + + getHtml('ClientID'); ?> + + + + getHtml('Client'); ?> + + + + getHtml('Address'); ?> + + + + getHtml('Postal'); ?> + + + + getHtml('City'); ?> + + + + getHtml('Country'); ?> + + + + getHtml('Net'); ?> + + + + getHtml('Profit'); ?> + + + + getHtml('Created'); ?> + + + +
+ getNumber(); ?> + type->getL11n(); ?> + client->number; ?> + printHtml($value->billTo); ?> + billAddress; ?> + billZip; ?> + billCity; ?> + billCountry; ?> + getCurrency($value->netSales); ?> + getCurrency($value->netProfit); ?> + createdAt->format('Y-m-d'); ?> + + +
getHtml('Empty', '0', '0'); ?> + +
+
+
+
diff --git a/Theme/Backend/supplier-profile-items.tpl.php b/Theme/Backend/supplier-profile-items.tpl.php new file mode 100644 index 0000000..2884062 --- /dev/null +++ b/Theme/Backend/supplier-profile-items.tpl.php @@ -0,0 +1,160 @@ +data['items'] ?? []; + +?> + +
+
+
+
getHtml('Items'); ?>
+ + + + + $value) : + if ($value->itemNumber === '') { + continue; + } + + ++$count; + $url = UriFactory::build('{/base}/purchase/item/profile?{?}&id=' . $value->id); + ?> + +
+ getHtml('ID', '0', '0'); ?> + + + + getHtml('Name'); ?> + + + + getHtml('Quantity'); ?> + + + + getHtml('UnitPrice'); ?> + + + + getHtml('Discount'); ?> + + + + getHtml('Discount%'); ?> + + + + getHtml('DiscountBonus'); ?> + + + + getHtml('TotalPrice'); ?> + + + +
+ printHtml($value->itemNumber); ?> + printHtml($value->itemName); ?> + printHtml((string) $value->getQuantity()); ?> + getcurrency($value->singlePurchasePriceNet); ?> + + + + getcurrency($value->totalPurchasePriceNet); ?> + + +
getHtml('Empty', '0', '0'); ?> + +
+
+
+
diff --git a/Theme/Backend/supplier-profile.tpl.php b/Theme/Backend/supplier-profile.tpl.php index da15cf6..36e089b 100755 --- a/Theme/Backend/supplier-profile.tpl.php +++ b/Theme/Backend/supplier-profile.tpl.php @@ -12,7 +12,8 @@ */ declare(strict_types=1); -use Modules\Profile\Models\ContactType; +use Modules\Admin\Models\ContactType; +use Modules\Media\Models\NullMedia; use phpOMS\Uri\UriFactory; $countryCodes = \phpOMS\Localization\ISO3166TwoEnum::getConstants(); @@ -22,11 +23,13 @@ $countries = \phpOMS\Localization\ISO3166NameEnum::getConstants(); * @var \Modules\SupplierManagement\Models\Supplier $supplier */ $supplier = $this->data['supplier']; -$notes = $supplier->getNotes(); -$files = $supplier->files; +$notes = $supplier->getNotes(); +$files = $supplier->files; -$newestInvoices = $this->data['newestInvoices'] ?? []; -$monthlyPurchaseCosts = $this->data['monthlyPurchaseCosts'] ?? []; +$supplierImage = $this->getData('supplierImage') ?? new NullMedia(); + +$newestInvoices = $this->data['newestInvoices'] ?? []; +$monthlySalesCosts = $this->data['monthlySalesCosts'] ?? []; /** * @var \phpOMS\Views\View $this @@ -37,24 +40,20 @@ echo $this->data['nav']->render();
@@ -62,7 +61,16 @@ echo $this->data['nav']->render();
-
+ + +
@@ -85,7 +93,7 @@ echo $this->data['nav']->render();
getHtml('Contact'); ?> - +
@@ -99,10 +107,10 @@ echo $this->data['nav']->render(); -
+
getHtml('Address'); ?> - +
-
-
+
-
- mainAddress->getCountry()) . '.svg')) : ?> - <?= $this->getHtml('IMG_alt_map'); ?> - + + +
+
+
+
+ <?= $this->printHtml($supplierImage->name); ?> +
+
+
- -
-
getHtml('Contact'); ?>
-
- -
getHtml('Main'); ?>: -
getHtml('Phone'); ?>: - -
getHtml('Email'); ?>: - -
getHtml('Accounting'); ?>: -
getHtml('Phone'); ?>: - -
getHtml('Email'); ?>: - -
-
-
@@ -279,7 +276,6 @@ echo $this->data['nav']->render();
getHtml('RecentInvoices'); ?>
-
@@ -315,17 +310,17 @@ echo $this->data['nav']->render();
-
+
-
getHtml('Purchase'); ?>
+
getHtml('Sales'); ?>
- @@ -338,61 +333,60 @@ echo $this->data['nav']->render(); "data": [ ], - "yAxisID": "axis-2", + "yAxisID": "axis2", "fill": false, "borderColor": "rgb(255, 99, 132)", "backgroundColor": "rgb(255, 99, 132)" }, { - "label": "getHtml('Purchase'); ?>", + "label": "getHtml('Sales'); ?>", "type": "bar", "data": [ ], - "yAxisID": "axis-1", + "yAxisID": "axis1", "backgroundColor": "rgb(54, 162, 235)" } ] }, "options": { + "responsive": true, "scales": { - "yAxes": [ - { - "id": "axis-1", + "axis1": { + "id": "axis1", + "display": true, + "position": "left" + }, + "axis2": { + "id": "axis2", + "display": true, + "position": "right", + "title": { "display": true, - "position": "left" + "text": "getHtml('Margin'); ?> %" }, - { - "id": "axis-2", - "display": true, - "position": "right", - "scaleLabel": { - "display": true, - "labelString": "getHtml('Margin'); ?> %" - }, - "gridLines": { - "display": false - }, - "beginAtZero": true, - "ticks": { - "min": 0, - "max": 100, - "stepSize": 10 - } + "grid": { + "display": false + }, + "beginAtZero": true, + "ticks": { + "min": 0, + "max": 100, + "stepSize": 10 } - ] + } } } }'> @@ -403,41 +397,6 @@ echo $this->data['nav']->render();
- request->uri->fragment === 'c-tab-2' ? ' checked' : ''; ?>> -
-
-
-
-

getHtml('Contact'); ?>

-
- - -
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
request->uri->fragment === 'c-tab-3' ? ' checked' : ''; ?>>
@@ -469,9 +428,62 @@ echo $this->data['nav']->render();
+ +
+
+
+

getHtml('Contact'); ?>

+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- request->uri->fragment === 'c-tab-4' ? ' checked' : ''; ?>> + request->uri->fragment === 'c-tab-5' ? ' checked' : ''; ?>>
+
+
+
+

getHtml('Payment'); ?>

+
+
+ +
+
+
+
+
+
+
+
+
+
@@ -502,28 +514,6 @@ echo $this->data['nav']->render();
- request->uri->fragment === 'c-tab-5' ? ' checked' : ''; ?>> -
-
-
-
-

getHtml('Payment'); ?>

-
-
- -
-
-
-
-
-
-
-
-
-
request->uri->fragment === 'c-tab-6' ? ' checked' : ''; ?>>
@@ -531,7 +521,7 @@ echo $this->data['nav']->render();

getHtml('Price'); ?>

-
+
@@ -573,7 +563,7 @@ echo $this->data['nav']->render();

getHtml('AreaManager'); ?>

- +
@@ -600,6 +590,14 @@ echo $this->data['nav']->render();
request->uri->fragment === 'c-tab-9' ? ' checked' : ''; ?>> +
+ +
+ request->uri->fragment === 'c-tab-9' ? ' checked' : ''; ?>> +
+ +
+ request->uri->fragment === 'c-tab-10' ? ' checked' : ''; ?>>