improve billing

This commit is contained in:
Dennis Eichhorn 2021-02-20 21:19:43 +01:00
parent 15923d8a3e
commit 24c7d7d7a5
11 changed files with 1089 additions and 337 deletions

View File

@ -5,7 +5,7 @@
"type": 2,
"subtype": 1,
"name": "Billing",
"uri": "{/prefix}sales/invoice/list",
"uri": "{/prefix}sales/bill/list",
"target": "self",
"icon": null,
"order": 5,
@ -15,11 +15,11 @@
"children": [
{
"id": 1005104101,
"pid": "/sales/invoice",
"pid": "/sales/bill",
"type": 3,
"subtype": 1,
"name": "List",
"uri": "{/prefix}sales/invoice/list",
"uri": "{/prefix}sales/bill/list",
"target": "self",
"icon": null,
"order": 1,
@ -30,11 +30,11 @@
},
{
"id": 1005104301,
"pid": "/sales/invoice",
"pid": "/sales/bill",
"type": 3,
"subtype": 1,
"name": "Create",
"uri": "{/prefix}sales/invoice/create?{?}",
"uri": "{/prefix}sales/bill/create?{?}",
"target": "self",
"icon": null,
"order": 5,
@ -50,22 +50,22 @@
"pid": "/",
"type": 2,
"subtype": 1,
"name": "Invoice",
"uri": "{/prefix}purchase/invoice/list",
"name": "Billing",
"uri": "{/prefix}purchase/bill/list",
"target": "self",
"icon": null,
"order": 5,
"from": "Invoice",
"from": "Billing",
"permission": { "permission": 2, "type": null, "element": null },
"parent": 1002101001,
"children": [
{
"id": 1005105101,
"pid": "/purchase/invoice",
"pid": "/purchase/bill",
"type": 3,
"subtype": 1,
"name": "List",
"uri": "{/prefix}purchase/invoice/list",
"uri": "{/prefix}purchase/bill/list",
"target": "self",
"icon": null,
"order": 1,
@ -76,11 +76,11 @@
},
{
"id": 1005105301,
"pid": "/purchase/invoice",
"pid": "/purchase/bill",
"type": 3,
"subtype": 1,
"name": "Create",
"uri": "{/prefix}purchase/invoice/create?{?}",
"uri": "{/prefix}purchase/bill/create?{?}",
"target": "self",
"icon": null,
"order": 5,

View File

@ -6,9 +6,9 @@ use phpOMS\Account\PermissionType;
use phpOMS\Router\RouteVerb;
return [
'^.*/sales/invoice/create.*$' => [
'^.*/sales/bill/create.*$' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingInvoiceCreate',
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingSalesInvoiceCreate',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
@ -17,9 +17,9 @@ return [
],
],
],
'^.*/sales/invoice/list.*$' => [
'^.*/sales/bill/list.*$' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingInvoiceList',
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingSalesList',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
@ -28,9 +28,9 @@ return [
],
],
],
'^.*/sales/invoice\?.*$' => [
'^.*/sales/bill\?.*$' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingInvoice',
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingSalesInvoice',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
@ -39,7 +39,7 @@ return [
],
],
],
'^.*/purchase/invoice/create.*$' => [
'^.*/purchase/bill/create.*$' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingPurchaseInvoiceCreate',
'verb' => RouteVerb::GET,
@ -50,9 +50,9 @@ return [
],
],
],
'^.*/purchase/invoice/list.*$' => [
'^.*/purchase/bill/list.*$' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingPurchaInvoiceList',
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingPurchaseList',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
@ -61,4 +61,15 @@ return [
],
],
],
'^.*/purchase/bill\?.*$' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingPurchaseInvoice',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::MODULE_NAME,
'type' => PermissionType::READ,
'state' => PermissionState::SALES_INVOICE,
],
],
],
];

View File

@ -14,7 +14,8 @@ declare(strict_types=1);
namespace Modules\Billing\Controller;
use Modules\Billing\Models\BillMapper;
use Modules\Billing\Models\SalesBillMapper;
use Modules\Billing\Models\PurchaseBillMapper;
use Modules\Billing\Models\BillTypeL11n;
use phpOMS\Contract\RenderableInterface;
use phpOMS\Message\RequestAbstract;
@ -43,7 +44,7 @@ final class BackendController extends Controller
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewBillingInvoiceList(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
public function viewBillingSalesList(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Billing/Theme/Backend/sales-bill-list');
@ -51,18 +52,18 @@ final class BackendController extends Controller
if ($request->getData('ptype') === 'p') {
$view->setData('bills',
BillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getBeforePivot((int) ($request->getData('id') ?? 0), limit: 25, depth: 3)
SalesBillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getSalesBeforePivot((int) ($request->getData('id') ?? 0), limit: 25, depth: 3)
);
} elseif ($request->getData('ptype') === 'n') {
$view->setData('bills',
BillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getAfterPivot((int) ($request->getData('id') ?? 0), limit: 25, depth: 3)
SalesBillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getSalesAfterPivot((int) ($request->getData('id') ?? 0), limit: 25, depth: 3)
);
} else {
$view->setData('bills',
BillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getAfterPivot(0, limit: 25, depth: 3)
SalesBillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getSalesAfterPivot(0, limit: 25, depth: 3)
);
}
@ -81,13 +82,13 @@ final class BackendController extends Controller
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewBillingInvoice(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
public function viewBillingSalesInvoice(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Billing/Theme/Backend/sales-bill');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response));
$bill = BillMapper::get((int) $request->getData('id'));
$bill = SalesBillMapper::get((int) $request->getData('id'));
$view->setData('bill', $bill);
@ -106,7 +107,7 @@ final class BackendController extends Controller
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewBillingInvoiceCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
public function viewBillingSalesInvoiceCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Billing/Theme/Backend/invoice-create');
@ -127,11 +128,53 @@ final class BackendController extends Controller
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewBillingPurchaInvoiceList(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
public function viewBillingPurchaseList(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Billing/Theme/Backend/purchase-invoice-list');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005105001, $request, $response));
$view->setTemplate('/Modules/Billing/Theme/Backend/purchase-bill-list');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response));
if ($request->getData('ptype') === 'p') {
$view->setData('bills',
PurchaseBillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getPurchaseBeforePivot((int) ($request->getData('id') ?? 0), limit: 25, depth: 3)
);
} elseif ($request->getData('ptype') === 'n') {
$view->setData('bills',
PurchaseBillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getPurchaseAfterPivot((int) ($request->getData('id') ?? 0), limit: 25, depth: 3)
);
} else {
$view->setData('bills',
PurchaseBillMapper::withConditional('language', $response->getLanguage(), [BillTypeL11n::class])
::getPurchaseAfterPivot(0, limit: 25, depth: 3)
);
}
return $view;
}
/**
* Routing end-point for application behaviour.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param mixed $data Generic data
*
* @return RenderableInterface
*
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewBillingPurchaseInvoice(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Billing/Theme/Backend/purchase-bill');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response));
$bill = PurchaseBillMapper::get((int) $request->getData('id'));
$view->setData('bill', $bill);
return $view;
}

View File

@ -32,7 +32,7 @@ use phpOMS\Localization\Money;
* @link https://orange-management.org
* @since 1.0.0
*/
final class BillMapper extends DataMapperAbstract
class BillMapper extends DataMapperAbstract
{
/**
* Columns.
@ -153,235 +153,4 @@ final class BillMapper extends DataMapperAbstract
* @since 1.0.0
*/
protected static string $table = 'billing_bill';
public static function getSalesByItemId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_element_total_salesprice_net)')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) $result[0]);
}
public static function getSalesByClientId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_net)')
->from(self::$table)
->where(self::$table . '.billing_bill_client', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) $result[0]);
}
public static function getAvgSalesPriceByItemId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_element_single_salesprice_net)', 'COUNT(billing_bill_element_total_salesprice_net)')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) (((int) $result[0]) / ((int) $result[1])));
}
public static function getLastOrderDateByItemId(int $id) : \DateTimeImmutable
{
// @todo: only delivers/invoice/production (no offers ...)
$query = new Builder(self::$db);
$result = $query->select('billing_bill_performance_date')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->orderBy('billing_bill_id', 'DESC')
->limit(1)
->execute()
->fetch();
return new \DateTimeImmutable($result[0]);
}
public static function getLastOrderDateByClientId(int $id) : \DateTimeImmutable
{
// @todo: only delivers/invoice/production (no offers ...)
$query = new Builder(self::$db);
$result = $query->select('billing_bill_performance_date')
->from(self::$table)
->where(self::$table . '.billing_bill_client', '=', $id)
->orderBy('billing_bill_id', 'DESC')
->limit(1)
->execute()
->fetch();
return new \DateTimeImmutable($result[0]);
}
public static function getItemRetentionRate(int $id, \DateTime $start, \DateTime $end) : float
{
}
public static function getItemLivetimeValue(int $id, \DateTime $start, \DateTime $end) : Money
{
}
public static function getNewestItemInvoices(int $id, int $limit = 10) : array
{
$depth = 3;
// @todo: limit is not working correctly... only returns / 2 or something like that?. Maybe because bills arent unique?
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
$query->leftJoin(BillElementMapper::getTable(), BillElementMapper::getTable() . '_' . $depth)
->on(self::$table . '_' . $depth . '.billing_bill_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_item', '=', $id)
->limit($limit);
if (!empty(self::$createdAt)) {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$createdAt]['name'], 'DESC');
} else {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$primaryField]['name'], 'DESC');
}
return self::getAllByQuery($query, RelationType::ALL, $depth);
}
public static function getNewestClientInvoices(int $id, int $limit = 10) : array
{
$depth = 3;
// @todo: limit is not working correctly... only returns / 2 or something like that?. Maybe because bills arent unique?
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
$query->where(self::$table . '_' . $depth . '.billing_bill_client', '=', $id)
->limit($limit);
if (!empty(self::$createdAt)) {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$createdAt]['name'], 'DESC');
} else {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$primaryField]['name'], 'DESC');
}
return self::getAllByQuery($query, RelationType::ALL, $depth);
}
public static function getItemTopCustomers(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
{
$depth = 3;
$query ??= ClientMapper::getQuery(null, [], RelationType::ALL, $depth);
$query->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->leftJoin(self::$table, self::$table . '_' . $depth)
->on(ClientMapper::getTable() . '_' . $depth . '.clientmgmt_client_id', '=', self::$table . '_' . $depth . '.billing_bill_client')
->leftJoin(BillElementMapper::getTable(), BillElementMapper::getTable() . '_' . $depth)
->on(self::$table . '_' . $depth . '.billing_bill_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '_' . $depth . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '_' . $depth . '.billing_bill_performance_date', '<=', $end)
->orderBy('net_sales', 'DESC')
->limit($limit)
->groupBy(ClientMapper::getTable() . '_' . $depth . '.clientmgmt_client_id');
$clients = ClientMapper::getAllByQuery($query, RelationType::ALL, $depth);
$data = ClientMapper::getDataLastQuery();
return [$clients, $data];
}
public static function getItemRegionSales(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->select(CountryMapper::getTable() . '.country_region')
->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->leftJoin(CountryMapper::getTable())
->on(self::$table . '.billing_bill_billCountry', '=', CountryMapper::getTable() . '.country_code2')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy(CountryMapper::getTable() . '.country_region')
->execute()
->fetchAll(\PDO::FETCH_KEY_PAIR);
return $result;
}
public static function getItemCountrySales(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
{
$query = new Builder(self::$db);
$result = $query->select(CountryMapper::getTable() . '.country_code2')
->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->leftJoin(CountryMapper::getTable())
->on(self::$table . '.billing_bill_billCountry', '=', CountryMapper::getTable() . '.country_code2')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy(CountryMapper::getTable() . '.country_code2')
->orderBy('net_sales', 'DESC')
->limit($limit)
->execute()
->fetchAll(\PDO::FETCH_KEY_PAIR);
return $result;
}
public static function getItemMonthlySalesCosts(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->selectAs('SUM(billing_bill_element_total_purchaseprice_net)', 'net_costs')
->selectAs('YEAR(billing_bill_performance_date)', 'year')
->selectAs('MONTH(billing_bill_performance_date)', 'month')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy('year', 'month')
->orderBy(['year', 'month'], ['ASC', 'ASC'])
->execute()
->fetchAll();
return $result;
}
public static function getClientMonthlySalesCosts(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->selectAs('SUM(billing_bill_net)', 'net_sales')
->selectAs('SUM(billing_bill_costs)', 'net_costs')
->selectAs('YEAR(billing_bill_performance_date)', 'year')
->selectAs('MONTH(billing_bill_performance_date)', 'month')
->from(self::$table)
->where(self::$table . '.billing_bill_client', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy('year', 'month')
->orderBy(['year', 'month'], ['ASC', 'ASC'])
->execute()
->fetchAll();
return $result;
}
}

View File

@ -0,0 +1,335 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package Modules\Billing\Models
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
namespace Modules\Billing\Models;
use Modules\SupplierManagement\Models\SupplierMapper;
use phpOMS\DataStorage\Database\Query\Builder;
use phpOMS\DataStorage\Database\RelationType;
use phpOMS\Localization\Defaults\CountryMapper;
use phpOMS\Localization\Money;
/**
* Mapper class.
*
* @package Modules\Billing\Models
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
final class PurchaseBillMapper extends BillMapper
{
/**
* Model to use by the mapper.
*
* @var string
* @since 1.0.0
*/
protected static string $model = Bill::class;
public static function getPurchaseBeforePivot(
mixed $pivot,
string $column = null,
int $limit = 50,
string $order = 'ASC',
int $relations = RelationType::ALL,
int $depth = 3,
Builder $query = null
) : array
{
$query = self::getQuery(null, [], $relations, $depth);
$query->where(BillTypeMapper::getTable() . '_' . ($depth - 1) . '.billing_type_transfer_type', '=', BillTransferType::PURCHASE);
return self::getBeforePivot($pivot, $column, $limit, $order, $relations, $depth, $query);
}
public static function getStockBeforePivot(
mixed $pivot,
string $column = null,
int $limit = 50,
string $order = 'ASC',
int $relations = RelationType::ALL,
int $depth = 3,
Builder $query = null
) : array
{
$query = self::getQuery(null, [], $relations, $depth);
$query->where(BillTypeMapper::getTable() . '_' . ($depth - 1) . '.billing_type_transfer_type', '=', BillTransferType::STOCK);
return self::getBeforePivot($pivot, $column, $limit, $order, $relations, $depth, $query);
}
public static function getPurchaseAfterPivot(
mixed $pivot,
string $column = null,
int $limit = 50,
string $order = 'ASC',
int $relations = RelationType::ALL,
int $depth = 3,
Builder $query = null
) : array
{
$query = self::getQuery(null, [], $relations, $depth);
$query->where(BillTypeMapper::getTable() . '_' . ($depth - 1) . '.billing_type_transfer_type', '=', BillTransferType::PURCHASE);
return self::getAfterPivot($pivot, $column, $limit, $order, $relations, $depth, $query);
}
public static function getStockAfterPivot(
mixed $pivot,
string $column = null,
int $limit = 50,
string $order = 'ASC',
int $relations = RelationType::ALL,
int $depth = 3,
Builder $query = null
) : array
{
$query = self::getQuery(null, [], $relations, $depth);
$query->where(BillTypeMapper::getTable() . '_' . ($depth - 1) . '.billing_type_transfer_type', '=', BillTransferType::STOCK);
return self::getAfterPivot($pivot, $column, $limit, $order, $relations, $depth, $query);
}
public static function getPurchaseByItemId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_element_total_purchaseprice_net)')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) $result[0]);
}
public static function getPurchaseBySupplierId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_net)')
->from(self::$table)
->where(self::$table . '.billing_bill_supplier', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) $result[0]);
}
public static function getAvgPurchasePriceByItemId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_element_single_purchaseprice_net)', 'COUNT(billing_bill_element_total_purchaseprice_net)')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) (((int) $result[0]) / ((int) $result[1])));
}
public static function getLastOrderDateByItemId(int $id) : \DateTimeImmutable
{
// @todo: only delivers/invoice/production (no offers ...)
$query = new Builder(self::$db);
$result = $query->select('billing_bill_performance_date')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->orderBy('billing_bill_id', 'DESC')
->limit(1)
->execute()
->fetch();
return new \DateTimeImmutable($result[0]);
}
public static function getLastOrderDateBySupplierId(int $id) : \DateTimeImmutable
{
// @todo: only delivers/invoice/production (no offers ...)
$query = new Builder(self::$db);
$result = $query->select('billing_bill_performance_date')
->from(self::$table)
->where(self::$table . '.billing_bill_supplier', '=', $id)
->orderBy('billing_bill_id', 'DESC')
->limit(1)
->execute()
->fetch();
return new \DateTimeImmutable($result[0]);
}
public static function getItemRetentionRate(int $id, \DateTime $start, \DateTime $end) : float
{
}
public static function getItemLivetimeValue(int $id, \DateTime $start, \DateTime $end) : Money
{
}
public static function getNewestItemInvoices(int $id, int $limit = 10) : array
{
$depth = 3;
// @todo: limit is not working correctly... only returns / 2 or something like that?. Maybe because bills arent unique?
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
$query->leftJoin(BillElementMapper::getTable(), BillElementMapper::getTable() . '_' . $depth)
->on(self::$table . '_' . $depth . '.billing_bill_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_item', '=', $id)
->limit($limit);
if (!empty(self::$createdAt)) {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$createdAt]['name'], 'DESC');
} else {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$primaryField]['name'], 'DESC');
}
return self::getAllByQuery($query, RelationType::ALL, $depth);
}
public static function getNewestSupplierInvoices(int $id, int $limit = 10) : array
{
$depth = 3;
// @todo: limit is not working correctly... only returns / 2 or something like that?. Maybe because bills arent unique?
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
$query->where(self::$table . '_' . $depth . '.billing_bill_supplier', '=', $id)
->limit($limit);
if (!empty(self::$createdAt)) {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$createdAt]['name'], 'DESC');
} else {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$primaryField]['name'], 'DESC');
}
return self::getAllByQuery($query, RelationType::ALL, $depth);
}
public static function getItemTopSuppliers(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
{
$depth = 3;
$query ??= SupplierMapper::getQuery(null, [], RelationType::ALL, $depth);
$query->selectAs('SUM(billing_bill_element_total_purchaseprice_net)', 'net_purchase')
->leftJoin(self::$table, self::$table . '_' . $depth)
->on(SupplierMapper::getTable() . '_' . $depth . '.suppliermgmt_supplier_id', '=', self::$table . '_' . $depth . '.billing_bill_supplier')
->leftJoin(BillElementMapper::getTable(), BillElementMapper::getTable() . '_' . $depth)
->on(self::$table . '_' . $depth . '.billing_bill_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '_' . $depth . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '_' . $depth . '.billing_bill_performance_date', '<=', $end)
->orderBy('net_purchase', 'DESC')
->limit($limit)
->groupBy(SupplierMapper::getTable() . '_' . $depth . '.suppliermgmt_supplier_id');
$suppliers = SupplierMapper::getAllByQuery($query, RelationType::ALL, $depth);
$data = SupplierMapper::getDataLastQuery();
return [$suppliers, $data];
}
public static function getItemRegionPurchase(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->select(CountryMapper::getTable() . '.country_region')
->selectAs('SUM(billing_bill_element_total_purchaseprice_net)', 'net_purchase')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->leftJoin(CountryMapper::getTable())
->on(self::$table . '.billing_bill_billCountry', '=', CountryMapper::getTable() . '.country_code2')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy(CountryMapper::getTable() . '.country_region')
->execute()
->fetchAll(\PDO::FETCH_KEY_PAIR);
return $result;
}
public static function getItemCountryPurchase(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
{
$query = new Builder(self::$db);
$result = $query->select(CountryMapper::getTable() . '.country_code2')
->selectAs('SUM(billing_bill_element_total_purchaseprice_net)', 'net_purchase')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->leftJoin(CountryMapper::getTable())
->on(self::$table . '.billing_bill_billCountry', '=', CountryMapper::getTable() . '.country_code2')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy(CountryMapper::getTable() . '.country_code2')
->orderBy('net_purchase', 'DESC')
->limit($limit)
->execute()
->fetchAll(\PDO::FETCH_KEY_PAIR);
return $result;
}
public static function getItemMonthlyPurchaseCosts(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->selectAs('SUM(billing_bill_element_total_purchaseprice_net)', 'net_purchase')
->selectAs('SUM(billing_bill_element_total_purchaseprice_net)', 'net_costs')
->selectAs('YEAR(billing_bill_performance_date)', 'year')
->selectAs('MONTH(billing_bill_performance_date)', 'month')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy('year', 'month')
->orderBy(['year', 'month'], ['ASC', 'ASC'])
->execute()
->fetchAll();
return $result;
}
public static function getSupplierMonthlyPurchaseCosts(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->selectAs('SUM(billing_bill_net)', 'net_purchase')
->selectAs('SUM(billing_bill_costs)', 'net_costs')
->selectAs('YEAR(billing_bill_performance_date)', 'year')
->selectAs('MONTH(billing_bill_performance_date)', 'month')
->from(self::$table)
->where(self::$table . '.billing_bill_supplier', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy('year', 'month')
->orderBy(['year', 'month'], ['ASC', 'ASC'])
->execute()
->fetchAll();
return $result;
}
}

303
Models/SalesBillMapper.php Normal file
View File

@ -0,0 +1,303 @@
<?php
/**
* Orange Management
*
* PHP Version 7.4
*
* @package Modules\Billing\Models
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
namespace Modules\Billing\Models;
use Modules\ClientManagement\Models\ClientMapper;
use phpOMS\DataStorage\Database\Query\Builder;
use phpOMS\DataStorage\Database\RelationType;
use phpOMS\Localization\Defaults\CountryMapper;
use phpOMS\Localization\Money;
/**
* Mapper class.
*
* @package Modules\Billing\Models
* @license OMS License 1.0
* @link https://orange-management.org
* @since 1.0.0
*/
final class SalesBillMapper extends BillMapper
{
/**
* Model to use by the mapper.
*
* @var string
* @since 1.0.0
*/
protected static string $model = Bill::class;
public static function getSalesBeforePivot(
mixed $pivot,
string $column = null,
int $limit = 50,
string $order = 'ASC',
int $relations = RelationType::ALL,
int $depth = 3,
Builder $query = null
) : array
{
$query = self::getQuery(null, [], $relations, $depth);
$query->where(BillTypeMapper::getTable() . '_' . ($depth - 1) . '.billing_type_transfer_type', '=', BillTransferType::SALES);
return self::getBeforePivot($pivot, $column, $limit, $order, $relations, $depth, $query);
}
public static function getSalesAfterPivot(
mixed $pivot,
string $column = null,
int $limit = 50,
string $order = 'ASC',
int $relations = RelationType::ALL,
int $depth = 3,
Builder $query = null
) : array
{
$query = self::getQuery(null, [], $relations, $depth);
$query->where(BillTypeMapper::getTable() . '_' . ($depth - 1) . '.billing_type_transfer_type', '=', BillTransferType::SALES);
return self::getAfterPivot($pivot, $column, $limit, $order, $relations, $depth, $query);
}
public static function getSalesByItemId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_element_total_salesprice_net)')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) $result[0]);
}
public static function getSalesByClientId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_net)')
->from(self::$table)
->where(self::$table . '.billing_bill_client', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) $result[0]);
}
public static function getAvgSalesPriceByItemId(int $id, \DateTime $start, \DateTime $end) : Money
{
$query = new Builder(self::$db);
$result = $query->select('SUM(billing_bill_element_single_salesprice_net)', 'COUNT(billing_bill_element_total_salesprice_net)')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->execute()
->fetch();
return new Money((int) (((int) $result[0]) / ((int) $result[1])));
}
public static function getLastOrderDateByItemId(int $id) : \DateTimeImmutable
{
// @todo: only delivers/invoice/production (no offers ...)
$query = new Builder(self::$db);
$result = $query->select('billing_bill_performance_date')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->orderBy('billing_bill_id', 'DESC')
->limit(1)
->execute()
->fetch();
return new \DateTimeImmutable($result[0]);
}
public static function getLastOrderDateByClientId(int $id) : \DateTimeImmutable
{
// @todo: only delivers/invoice/production (no offers ...)
$query = new Builder(self::$db);
$result = $query->select('billing_bill_performance_date')
->from(self::$table)
->where(self::$table . '.billing_bill_client', '=', $id)
->orderBy('billing_bill_id', 'DESC')
->limit(1)
->execute()
->fetch();
return new \DateTimeImmutable($result[0]);
}
public static function getItemRetentionRate(int $id, \DateTime $start, \DateTime $end) : float
{
}
public static function getItemLivetimeValue(int $id, \DateTime $start, \DateTime $end) : Money
{
}
public static function getNewestItemInvoices(int $id, int $limit = 10) : array
{
$depth = 3;
// @todo: limit is not working correctly... only returns / 2 or something like that?. Maybe because bills arent unique?
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
$query->leftJoin(BillElementMapper::getTable(), BillElementMapper::getTable() . '_' . $depth)
->on(self::$table . '_' . $depth . '.billing_bill_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_item', '=', $id)
->limit($limit);
if (!empty(self::$createdAt)) {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$createdAt]['name'], 'DESC');
} else {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$primaryField]['name'], 'DESC');
}
return self::getAllByQuery($query, RelationType::ALL, $depth);
}
public static function getNewestClientInvoices(int $id, int $limit = 10) : array
{
$depth = 3;
// @todo: limit is not working correctly... only returns / 2 or something like that?. Maybe because bills arent unique?
$query ??= self::getQuery(null, [], RelationType::ALL, $depth);
$query->where(self::$table . '_' . $depth . '.billing_bill_client', '=', $id)
->limit($limit);
if (!empty(self::$createdAt)) {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$createdAt]['name'], 'DESC');
} else {
$query->orderBy(self::$table . '_' . $depth . '.' . self::$columns[self::$primaryField]['name'], 'DESC');
}
return self::getAllByQuery($query, RelationType::ALL, $depth);
}
public static function getItemTopCustomers(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
{
$depth = 3;
$query ??= ClientMapper::getQuery(null, [], RelationType::ALL, $depth);
$query->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->leftJoin(self::$table, self::$table . '_' . $depth)
->on(ClientMapper::getTable() . '_' . $depth . '.clientmgmt_client_id', '=', self::$table . '_' . $depth . '.billing_bill_client')
->leftJoin(BillElementMapper::getTable(), BillElementMapper::getTable() . '_' . $depth)
->on(self::$table . '_' . $depth . '.billing_bill_id', '=', BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '_' . $depth . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '_' . $depth . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '_' . $depth . '.billing_bill_performance_date', '<=', $end)
->orderBy('net_sales', 'DESC')
->limit($limit)
->groupBy(ClientMapper::getTable() . '_' . $depth . '.clientmgmt_client_id');
$clients = ClientMapper::getAllByQuery($query, RelationType::ALL, $depth);
$data = ClientMapper::getDataLastQuery();
return [$clients, $data];
}
public static function getItemRegionSales(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->select(CountryMapper::getTable() . '.country_region')
->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->leftJoin(CountryMapper::getTable())
->on(self::$table . '.billing_bill_billCountry', '=', CountryMapper::getTable() . '.country_code2')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy(CountryMapper::getTable() . '.country_region')
->execute()
->fetchAll(\PDO::FETCH_KEY_PAIR);
return $result;
}
public static function getItemCountrySales(int $id, \DateTime $start, \DateTime $end, int $limit = 10) : array
{
$query = new Builder(self::$db);
$result = $query->select(CountryMapper::getTable() . '.country_code2')
->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->leftJoin(CountryMapper::getTable())
->on(self::$table . '.billing_bill_billCountry', '=', CountryMapper::getTable() . '.country_code2')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy(CountryMapper::getTable() . '.country_code2')
->orderBy('net_sales', 'DESC')
->limit($limit)
->execute()
->fetchAll(\PDO::FETCH_KEY_PAIR);
return $result;
}
public static function getItemMonthlySalesCosts(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->selectAs('SUM(billing_bill_element_total_salesprice_net)', 'net_sales')
->selectAs('SUM(billing_bill_element_total_purchaseprice_net)', 'net_costs')
->selectAs('YEAR(billing_bill_performance_date)', 'year')
->selectAs('MONTH(billing_bill_performance_date)', 'month')
->from(self::$table)
->leftJoin(BillElementMapper::getTable())
->on(self::$table . '.billing_bill_id', '=', BillElementMapper::getTable() . '.billing_bill_element_bill')
->where(BillElementMapper::getTable() . '.billing_bill_element_item', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy('year', 'month')
->orderBy(['year', 'month'], ['ASC', 'ASC'])
->execute()
->fetchAll();
return $result;
}
public static function getClientMonthlySalesCosts(int $id, \DateTime $start, \DateTime $end) : array
{
$query = new Builder(self::$db);
$result = $query->selectAs('SUM(billing_bill_net)', 'net_sales')
->selectAs('SUM(billing_bill_costs)', 'net_costs')
->selectAs('YEAR(billing_bill_performance_date)', 'year')
->selectAs('MONTH(billing_bill_performance_date)', 'month')
->from(self::$table)
->where(self::$table . '.billing_bill_client', '=', $id)
->andWhere(self::$table . '.billing_bill_performance_date', '>=', $start)
->andWhere(self::$table . '.billing_bill_performance_date', '<=', $end)
->groupBy('year', 'month')
->orderBy(['year', 'month'], ['ASC', 'ASC'])
->execute()
->fetchAll();
return $result;
}
}

View File

@ -1,18 +0,0 @@
<?php
/**
* Orange Management
*
* PHP Version 8.0
*
* @package Modules\Billing
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
/**
* @var \phpOMS\Views\View $this
*/
echo $this->getData('nav')->render();

View File

@ -0,0 +1,65 @@
<?php
/**
* Orange Management
*
* PHP Version 8.0
*
* @package Modules\Billing
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
use phpOMS\Uri\UriFactory;
$bills = $this->getData('bills') ?? [];
echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('Bills'); ?><i class="fa fa-download floatRight download btn"></i></div>
<table id="billList" class="default">
<thead>
<tr>
<td><?= $this->getHtml('ID', '0', '0'); ?>
<td><?= $this->getHtml('Type'); ?>
<td><?= $this->getHtml('ClientID'); ?>
<td class="wf-100"><?= $this->getHtml('Client'); ?>
<td class="wf-100"><?= $this->getHtml('Address'); ?>
<td class="wf-100"><?= $this->getHtml('Postal'); ?>
<td class="wf-100"><?= $this->getHtml('City'); ?>
<td class="wf-100"><?= $this->getHtml('Country'); ?>
<td><?= $this->getHtml('Net'); ?>
<td><?= $this->getHtml('Gross'); ?>
<td><?= $this->getHtml('Profit'); ?>
<td><?= $this->getHtml('Created'); ?>
<tbody>
<?php $count = 0; foreach ($bills as $key => $value) :
++$count;
$url = UriFactory::build('{/prefix}purchase/bill?{?}&id=' . $value->getId());
?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>"><?= $value->getNumber(); ?></a>
<td><a href="<?= $url; ?>"><?= $value->type->getL11n(); ?></a>
<td><a href="<?= $url; ?>"><?= $value->client->number; ?></a>
<td><a href="<?= $url; ?>"><?= $this->printHtml($value->billTo); ?></a>
<td><a href="<?= $url; ?>"><?= $value->billAddress; ?></a>
<td><a href="<?= $url; ?>"><?= $value->billZip; ?></a>
<td><a href="<?= $url; ?>"><?= $value->billCity; ?></a>
<td><a href="<?= $url; ?>"><?= $value->billCountry; ?></a>
<td><a href="<?= $url; ?>"><?= $value->net->getCurrency(); ?></a>
<td><a href="<?= $url; ?>"><?= $value->gross->getCurrency(); ?></a>
<td><a href="<?= $url; ?>"><?= $value->profit->getCurrency(); ?></a>
<td><a href="<?= $url; ?>"><?= $value->createdAt->format('Y-m-d'); ?></a>
<?php endforeach; ?>
<?php if ($count === 0) : ?>
<tr><td colspan="9" class="empty"><?= $this->getHtml('Empty', '0', '0'); ?>
<?php endif; ?>
</table>
</div>
</div>
</div>

View File

@ -0,0 +1,294 @@
<?php
/**
* Orange Management
*
* PHP Version 8.0
*
* @package Modules\Billing
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
use phpOMS\Uri\UriFactory;
/**
* @var \phpOMS\Views\View $this
*/
$bill = $this->getData('bill');
$elements = $bill->getElements();
$billPdf = $bill->getMediaByType('bill');
echo $this->getData('nav')->render(); ?>
<div class="tabview tab-2">
<div class="box">
<ul class="tab-links">
<li><label for="c-tab-1"><?= $this->getHtml('Invoice'); ?></label></li>
<li><label for="c-tab-2"><?= $this->getHtml('Items'); ?></label></li>
<li><label for="c-tab-3"><?= $this->getHtml('Preview'); ?></label></li>
<li><label for="c-tab-4"><?= $this->getHtml('Payment'); ?></label></li>
<li><label for="c-tab-5"><?= $this->getHtml('Media'); ?></label></li>
<li><label for="c-tab-6"><?= $this->getHtml('Logs'); ?></label></li>
</ul>
</div>
<div class="tab-content">
<input type="radio" id="c-tab-1" name="tabular-2" checked>
<div class="tab">
<div class="row">
<div class="col-xs-12 col-md-6 col-lg-4">
<section class="portlet">
<form>
<div class="portlet-head"><?= $this->getHtml('Invoice'); ?></div>
<div class="portlet-body">
<table class="layout wf-100">
<tr><td><label for="iSource"><?= $this->getHtml('Source'); ?></label>
<tr><td><span class="input"><button type="button" formaction=""><i class="fa fa-book"></i></button><input type="text" id="iSource" name="source"></span>
<tr><td><label for="iType"><?= $this->getHtml('Type'); ?></label>
<tr><td><select id="iType" name="type">
<option><?= $this->getHtml('Invoice'); ?>
<option><?= $this->getHtml('Offer'); ?>
<option><?= $this->getHtml('Confirmation'); ?>
<option><?= $this->getHtml('DeliveryNote'); ?>
<option><?= $this->getHtml('CreditNote'); ?>
</select>
<tr><td><label for="iClient"><?= $this->getHtml('Client'); ?></label>
<tr><td><span class="input"><button type="button" formaction=""><i class="fa fa-book"></i></button><input type="text" id="iClient" name="client"></span>
<tr><td><label for="iDelivery"><?= $this->getHtml('Delivery'); ?></label>
<tr><td><input type="datetime-local" id="iDelivery" name="delivery">
<tr><td><label for="iDue"><?= $this->getHtml('Due'); ?></label>
<tr><td><input type="datetime-local" id="iDue" name="due">
<tr><td><label for="iFreightage"><?= $this->getHtml('Freightage'); ?></label>
<tr><td><input type="number" id="iFreightage" name="freightage">
<tr><td><label for="iShipment"><?= $this->getHtml('Shipment'); ?></label>
<tr><td><select id="iShipment" name="shipment">
<option>
</select>
<tr><td><label for="iTermsOfDelivery"><?= $this->getHtml('TermsOfDelivery'); ?></label>
<tr><td><select id="iTermsOfDelivery" name="termsofdelivery">
<option>
</select>
</table>
</div>
<div class="portlet-foot"><input type="submit" value="<?= $this->getHtml('Create', '0', '0'); ?>"></div>
</form>
</section>
</div>
<div class="col-xs-12 col-md-6 col-lg-4">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Invoice'); ?></div>
<div class="portlet-body">
<form>
<table class="layout wf-100">
<tr><td><label for="iAddressS"><?= $this->getHtml('Addresses'); ?></label>
<tr><td><select id="iAddressS" name="addressS">
<option>
</select>
<tr><td><label for="iIRecipient"><?= $this->getHtml('Recipient'); ?></label>
<tr><td><input type="text" id="iIRecipient" name="irecipient">
<tr><td><label for="iAddress"><?= $this->getHtml('Address'); ?></label>
<tr><td><input type="text" id="iAddress" name="address">
<tr><td><label for="iZip"><?= $this->getHtml('Zip'); ?></label>
<tr><td><input type="text" id="iZip" name="zip">
<tr><td><label for="iCity"><?= $this->getHtml('City'); ?></label>
<tr><td><input type="text" id="iCity" name="city">
<tr><td><label for="iCountry"><?= $this->getHtml('Country'); ?></label>
<tr><td><input type="text" id="iCountry" name="country">
</table>
</form>
</div>
</section>
</div>
<div class="col-xs-12 col-md-6 col-lg-4">
<section class="portlet">
<div class="portlet-head"><?= $this->getHtml('Delivery'); ?></div>
<div class="portlet-body">
<form>
<table class="layout wf-100">
<tr><td><label for="iAddressS"><?= $this->getHtml('Addresses'); ?></label>
<tr><td><select id="iAddressS" name="addressS">
<option>
</select>
<tr><td><label for="iDRecipient"><?= $this->getHtml('Recipient'); ?></label>
<tr><td><input type="text" id="iDRecipient" name="drecipient">
<tr><td><label for="iAddress"><?= $this->getHtml('Address'); ?></label>
<tr><td><input type="text" id="iAddress" name="address">
<tr><td><label for="iZip"><?= $this->getHtml('Zip'); ?></label>
<tr><td><input type="text" id="iZip" name="zip">
<tr><td><label for="iCity"><?= $this->getHtml('City'); ?></label>
<tr><td><input type="text" id="iCity" name="city">
<tr><td><label for="iCountry"><?= $this->getHtml('Country'); ?></label>
<tr><td><input type="text" id="iCountry" name="country">
</table>
</form>
</div>
</section>
</div>
</div>
</div>
<input type="radio" id="c-tab-2" name="tabular-2">
<div class="tab">
<div class="row">
<div class="col-xs-12">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('Invoice'); ?><i class="fa fa-download floatRight download btn"></i></div>
<table class="default" id="invoice-item-list">
<thead>
<tr>
<td>
<td><?= $this->getHtml('Item'); ?>
<td class="wf-100"><?= $this->getHtml('Name'); ?>
<td><?= $this->getHtml('Quantity'); ?>
<td><?= $this->getHtml('Price'); ?>
<td><?= $this->getHtml('Discount'); ?>
<td><?= $this->getHtml('DiscountP'); ?>
<td><?= $this->getHtml('Bonus'); ?>
<td><?= $this->getHtml('Tax'); ?>
<td><?= $this->getHtml('Net'); ?>
<tbody>
<?php foreach ($elements as $element) : ?>
<tr>
<td><i class="fa fa-plus add"></i> <i class="fa fa-chevron-up order-up"></i> <i class="fa fa-chevron-down order-down"></i>
<td><span class="input"><button type="button" formaction=""><i class="fa fa-book"></i></button><input type="text" value="<?= $element->itemNumber; ?>" required></span>
<td><textarea required><?= $element->itemName; ?></textarea>
<td><input type="number" min="0" value="<?= $element->quantity; ?>" required>
<td><input type="text" value="<?= $element->singleSalesPriceNet->getCurrency(); ?>">
<td><input type="number" min="0">
<td><input type="number" min="0" max="100" step="any">
<td><input type="number" min="0" step="any">
<td><input type="number" min="0" step="any">
<td><?= $element->totalSalesPriceNet->getCurrency(); ?>
<?php endforeach; ?>
<tr>
<td><i class="fa fa-plus"></i> <i class="fa fa-chevron-up order-up"></i> <i class="fa fa-chevron-down order-down"></i>
<td><span class="input"><button type="button" formaction=""><i class="fa fa-book"></i></button><input type="text" required></span>
<td><textarea required></textarea>
<td><input type="number" min="0" value="0" required>
<td><input type="text">
<td><input type="number" min="0">
<td><input type="number" min="0" max="100" step="any">
<td><input type="number" min="0" step="any">
<td><input type="number" min="0" step="any">
<td>
</table>
<div class="portlet-foot">
<?= $this->getHtml('Freightage'); ?>: 0.00 -
<?= $this->getHtml('Net'); ?>: <?= $bill->net->getCurrency(); ?> -
<?= $this->getHtml('Tax'); ?>: 0.00 -
<?= $this->getHtml('Total'); ?>: <?= $bill->gross->getCurrency(); ?>
</div>
</div>
</div>
</div>
</div>
<input type="radio" id="c-tab-3" name="tabular-2">
<div class="tab">
<div class="row">
<div class="col-xs-12">
<section id="mediaFile" class="portlet">
<div class="portlet-body">
<iframe style="min-height: 600px;" data-form="iUiSettings" data-name="iframeHelper" id="iHelperFrame" src="<?= UriFactory::build('{/backend}Resources/mozilla/Pdf/web/viewer.html?{?}&file=' . ($billPdf->isAbsolute ? '' : '/../../../../') . $billPdf->getPath()); ?>" allowfullscreen></iframe>
</div>
</section>
</div>
</div>
</div>
<input type="radio" id="c-tab-4" name="tabular-2">
<div class="tab">
<div class="row">
<div class="col-xs-12 col-md-6 col-lg-4">
<section class="box wf-100">
<header><h1><?= $this->getHtml('Payment'); ?></h1></header>
<div class="inner">
<form>
<table class="layout wf-100">
<tr><td><label for="iType"><?= $this->getHtml('Type'); ?></label>
<tr><td><select id="iType" name="type">
<option>
</select>
<tr><td><label for="iType"><?= $this->getHtml('Type'); ?></label>
<tr><td><select id="iType" name="type">
<option><?= $this->getHtml('MoneyTransfer'); ?>
<option><?= $this->getHtml('Prepaid'); ?>
<option><?= $this->getHtml('AlreadyPaid'); ?>
<option><?= $this->getHtml('CreditCard'); ?>
<option><?= $this->getHtml('DirectDebit'); ?>
</select>
<tr><td><label for="iDue"><?= $this->getHtml('Due'); ?></label>
<tr><td><input type="datetime-local" id="iDue" name="due">
<tr><td><label for="iDue"><?= $this->getHtml('Due'); ?> - <?= $this->getHtml('Cashback'); ?></label>
<tr><td><input type="datetime-local" id="iDue" name="due">
<tr><td><label for="iCashBack"><?= $this->getHtml('Cashback'); ?></label>
<tr><td><input type="number" id="iCashBack" name="cashback">
<tr><td><label for="iDue"><?= $this->getHtml('Due'); ?> - <?= $this->getHtml('Cashback'); ?> 2</label>
<tr><td><input type="datetime-local" id="iDue" name="due">
<tr><td><label for="iCashBack2"><?= $this->getHtml('Cashback'); ?> 2</label>
<tr><td><input type="number" id="iCashBack2" name="cashback2">
<tr><td><input type="submit" value="<?= $this->getHtml('Create', '0', '0'); ?>">
</table>
</form>
</div>
</section>
</div>
</div>
</div>
<input type="radio" id="c-tab-5" name="tabular-2">
<div class="tab">
<div class="row">
<div class="col-xs-12 col-md-6 col-lg-4">
<section class="box wf-100">
<header><h1><?= $this->getHtml('Media'); ?></h1></header>
<div class="inner">
<form>
<table class="layout wf-100">
<tbody>
<tr><td colspan="2"><label for="iMedia"><?= $this->getHtml('Media'); ?></label>
<tr><td><input type="text" id="iMedia" placeholder="&#xf15b; File"><td><button><?= $this->getHtml('Select'); ?></button>
<tr><td colspan="2"><label for="iUpload"><?= $this->getHtml('Upload'); ?></label>
<tr><td><input type="file" id="iUpload" form="fTask"><input form="fTask" type="hidden" name="type"><td>
</table>
</form>
</div>
</section>
</div>
</div>
</div>
<input type="radio" id="c-tab-6" name="tabular-2">
<div class="tab">
<div class="row">
<div class="col-xs-12">
<div class="box wf-100">
<table class="default">
<caption><?= $this->getHtml('Logs'); ?><i class="fa fa-download floatRight download btn"></i></caption>
<thead>
<tr>
<td>IP
<td><?= $this->getHtml('ID', '0', '0'); ?>
<td><?= $this->getHtml('Name'); ?>
<td class="wf-100"><?= $this->getHtml('Log'); ?>
<td><?= $this->getHtml('Date'); ?>
<tfoot>
<tr>
<td colspan="6">
<tbody>
<tr>
<td><?= $this->printHtml($this->request->getOrigin()); ?>
<td><?= $this->printHtml((string) $this->request->header->account); ?>
<td><?= $this->printHtml((string) $this->request->header->account); ?>
<td>Create Invoice
<td><?= $this->printHtml((new \DateTime('now'))->format('Y-m-d H:i:s')); ?>
</table>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,49 +0,0 @@
<?php
/**
* Orange Management
*
* PHP Version 8.0
*
* @package Modules\Billing
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link https://orange-management.org
*/
declare(strict_types=1);
$footerView = new \phpOMS\Views\PaginationView($this->l11nManager, $this->request, $this->response);
$footerView->setTemplate('/Web/Templates/Lists/Footer/PaginationBig');
$footerView->setPages(20);
$footerView->setPage(1);
echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<div class="box wf-100">
<table class="default">
<caption><?= $this->getHtml('Invoices'); ?><i class="fa fa-download floatRight download btn"></i></caption>
<thead>
<tr>
<td><?= $this->getHtml('ID', '0', '0'); ?>
<td><?= $this->getHtml('Type'); ?>
<td><?= $this->getHtml('SupplierID'); ?>
<td class="wf-100"><?= $this->getHtml('Supplier'); ?>
<td><?= $this->getHtml('Net'); ?>
<td><?= $this->getHtml('Gross'); ?>
<td><?= $this->getHtml('Created'); ?>
<td><?= $this->getHtml('Due'); ?>
<tfoot>
<tr>
<td colspan="8">
<tbody>
<?php $count = 0; foreach ([] as $key => $value) : ++$count; ?>
<?php endforeach; ?>
<?php if ($count === 0) : ?>
<tr><td colspan="8" class="empty"><?= $this->getHtml('Empty', '0', '0'); ?>
<?php endif; ?>
</table>
</div>
</div>
</div>

View File

@ -21,7 +21,7 @@ echo $this->getData('nav')->render(); ?>
<div class="row">
<div class="col-xs-12">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('Invoices'); ?><i class="fa fa-download floatRight download btn"></i></div>
<div class="portlet-head"><?= $this->getHtml('Bills'); ?><i class="fa fa-download floatRight download btn"></i></div>
<table id="billList" class="default">
<thead>
<tr>
@ -40,7 +40,7 @@ echo $this->getData('nav')->render(); ?>
<tbody>
<?php $count = 0; foreach ($bills as $key => $value) :
++$count;
$url = UriFactory::build('{/prefix}sales/invoice?{?}&id=' . $value->getId());
$url = UriFactory::build('{/prefix}sales/bill?{?}&id=' . $value->getId());
?>
<tr data-href="<?= $url; ?>">
<td><a href="<?= $url; ?>"><?= $value->getNumber(); ?></a>
@ -63,4 +63,3 @@ echo $this->getData('nav')->render(); ?>
</div>
</div>
</div>