bug fixes and permission tests

This commit is contained in:
Dennis Eichhorn 2022-01-22 21:56:00 +01:00
parent 71107e6c7a
commit 56a369d54d
12 changed files with 215 additions and 55 deletions

View File

@ -21,15 +21,17 @@
"user": 1
},
{
"type": "upload",
"create_collection": true,
"name": "Default",
"virtualPath": "/Modules/Billing/Templates",
"path": "/Modules/Media/Files/Modules/Billing/Templates/Default",
"fixed_names": true,
"files": [
"/Modules/Billing/Admin/Install/Media"
],
"user": 1
"type": "type",
"name": "preview",
"l11n": [
{
"title": "Preview",
"lang": "en"
},
{
"title": "Vorschau",
"lang": "de"
}
]
}
]

View File

@ -43,9 +43,18 @@ class Media
{
$media = \Modules\Media\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/Media.install.json']);
$defaultTemplate = \reset($media['upload'][0]);
$preivewType = (int) \reset($media['type'][0]);
$setting = new Setting();
SettingMapper::create()->execute($setting->with(0, SettingsEnum::DEFAULT_SALES_INVOICE_TEMPLATE, (string) $defaultTemplate->getId(), '\\d+', null, 'Billing'));
SettingMapper::create()->execute(
$setting->with(
0,
SettingsEnum::PREVIEW_MEDIA_TYPE,
(string) $preivewType,
'\\d+',
null,
'Billing'
)
);
}
}

View File

@ -0,0 +1,14 @@
[
{
"type": "upload",
"create_collection": true,
"name": "Default",
"virtualPath": "/Modules/Billing/Templates",
"path": "/Modules/Media/Files/Modules/Billing/Templates/Default",
"fixed_names": true,
"files": [
"/Modules/Billing/Admin/Install/Media"
],
"user": 1
}
]

View File

@ -9,6 +9,18 @@
"primary": true,
"autoincrement": true
},
"billing_type_number_format": {
"name": "billing_type_number_format",
"type": "VARCHAR(254)",
"null": false
},
"billing_type_template": {
"name": "billing_type_template",
"type": "INT",
"null": false,
"foreignTable": "media",
"foreignKey": "media_id"
},
"billing_type_transfer_type": {
"description": "What kind of bill is it?",
"name": "billing_type_transfer_type",

View File

@ -19,6 +19,8 @@ use Modules\Billing\Models\BillType;
use Modules\Billing\Models\BillTypeL11n;
use Modules\Billing\Models\BillTypeL11nMapper;
use Modules\Billing\Models\BillTypeMapper;
use Modules\Media\Models\NullCollection;
use phpOMS\Application\ApplicationAbstract;
use phpOMS\Config\SettingsInterface;
use phpOMS\DataStorage\Database\DatabasePool;
use phpOMS\Localization\ISO639x1Enum;
@ -50,9 +52,18 @@ final class Installer extends InstallerAbstract
{
parent::install($dbPool, $info, $cfgHandler);
self::createOutgoingBillTypes();
self::createIncomingBillTypes();
self::createTransferBillTypes();
// Install bill type templates
$app = new class() extends ApplicationAbstract {};
$app->dbPool = $dbPool;
$media = \Modules\Media\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/Install/Media2.install.json']);
/** @var int $defaultTemplate */
$defaultTemplate = (int) \reset($media['upload'][0])->getId();
self::createOutgoingBillTypes($defaultTemplate);
self::createIncomingBillTypes($defaultTemplate);
self::createTransferBillTypes($defaultTemplate);
}
/**
@ -62,45 +73,56 @@ final class Installer extends InstallerAbstract
*
* @since 1.0.0
*/
private static function createOutgoingBillTypes() : array
private static function createOutgoingBillTypes(int $template) : array
{
$billType = [];
// @todo: assign bill template here and not in the settings!!!
// @todo: allow multiple alternative bill templates
// @todo: implement ordering of templates
$billType['offer'] = new BillType('Offer');
$billType['offer']->numberFormat = '{y}-{id}';
$billType['offer']->template = new NullCollection($template);
$billType['offer']->transferType = BillTransferType::SALES;
$billType['offer']->transferStock = false;
BillTypeMapper::create()->execute($billType['offer']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['offer']->getId(), 'Angebot', ISO639x1Enum::_DE));
$billType['order_confirmation'] = new BillType('Order Confirmation');
$billType['order_confirmation']->numberFormat = '{y}-{id}';
$billType['order_confirmation']->template = new NullCollection($template);
$billType['order_confirmation']->transferType = BillTransferType::SALES;
$billType['order_confirmation']->transferStock = false;
BillTypeMapper::create()->execute($billType['order_confirmation']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['order_confirmation']->getId(), 'Auftragsbestaetigung', ISO639x1Enum::_DE));
$billType['delivery_note'] = new BillType('Delivery Note');
$billType['delivery_note']->numberFormat = '{y}-{id}';
$billType['delivery_note']->template = new NullCollection($template);
$billType['delivery_note']->transferType = BillTransferType::SALES;
$billType['delivery_note']->transferStock = true;
BillTypeMapper::create()->execute($billType['delivery_note']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['delivery_note']->getId(), 'Lieferschein', ISO639x1Enum::_DE));
$billType['invoice'] = new BillType('Invoice');
$billType['invoice']->numberFormat = '{y}-{id}';
$billType['invoice']->template = new NullCollection($template);
$billType['invoice']->transferType = BillTransferType::SALES;
$billType['invoice']->transferStock = false;
BillTypeMapper::create()->execute($billType['invoice']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['invoice']->getId(), 'Rechnung', ISO639x1Enum::_DE));
$billType['credit_note'] = new BillType('Credit Note');
$billType['credit_note']->numberFormat = '{y}-{id}';
$billType['credit_note']->template = new NullCollection($template);
$billType['credit_note']->transferType = BillTransferType::SALES;
$billType['credit_note']->transferStock = false;
BillTypeMapper::create()->execute($billType['credit_note']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['credit_note']->getId(), 'Rechnungskorrektur', ISO639x1Enum::_DE));
$billType['reverse_invoice'] = new BillType('Credit Note');
$billType['reverse_invoice']->numberFormat = '{y}-{id}';
$billType['reverse_invoice']->template = new NullCollection($template);
$billType['reverse_invoice']->transferType = BillTransferType::SALES;
$billType['reverse_invoice']->transferStock = false;
BillTypeMapper::create()->execute($billType['reverse_invoice']);
@ -116,41 +138,53 @@ final class Installer extends InstallerAbstract
*
* @since 1.0.0
*/
private static function createIncomingBillTypes() : array
private static function createIncomingBillTypes(int $template) : array
{
$billType = [];
$billType['offer'] = new BillType('Offer');
$billType['offer']->numberFormat = '{y}-{id}';
$billType['offer']->template = new NullCollection($template);
$billType['offer']->transferType = BillTransferType::PURCHASE;
$billType['offer']->transferStock = false;
BillTypeMapper::create()->execute($billType['offer']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['offer']->getId(), 'Angebot', ISO639x1Enum::_DE));
$billType['order_confirmation'] = new BillType('Order Confirmation');
$billType['order_confirmation']->numberFormat = '{y}-{id}';
$billType['order_confirmation']->template = new NullCollection($template);
$billType['order_confirmation']->transferType = BillTransferType::PURCHASE;
$billType['order_confirmation']->transferStock = false;
BillTypeMapper::create()->execute($billType['order_confirmation']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['order_confirmation']->getId(), 'Auftragsbestaetigung', ISO639x1Enum::_DE));
$billType['delivery_note'] = new BillType('Delivery Note');
$billType['delivery_note']->numberFormat = '{y}-{id}';
$billType['delivery_note']->template = new NullCollection($template);
$billType['delivery_note']->transferType = BillTransferType::PURCHASE;
$billType['delivery_note']->transferStock = true;
BillTypeMapper::create()->execute($billType['delivery_note']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['delivery_note']->getId(), 'Lieferschein', ISO639x1Enum::_DE));
$billType['invoice'] = new BillType('Invoice');
$billType['invoice']->numberFormat = '{y}-{id}';
$billType['invoice']->template = new NullCollection($template);
$billType['invoice']->transferType = BillTransferType::PURCHASE;
$billType['invoice']->transferStock = false;
BillTypeMapper::create()->execute($billType['invoice']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['invoice']->getId(), 'Rechnung', ISO639x1Enum::_DE));
$billType['credit_note'] = new BillType('Credit Note');
$billType['credit_note']->numberFormat = '{y}-{id}';
$billType['credit_note']->template = new NullCollection($template);
$billType['credit_note']->transferType = BillTransferType::PURCHASE;
$billType['credit_note']->transferStock = false;
BillTypeMapper::create()->execute($billType['credit_note']);
BillTypeL11nMapper::create()->execute(new BillTypeL11n($billType['credit_note']->getId(), 'Rechnungskorrektur', ISO639x1Enum::_DE));
$billType['reverse_invoice'] = new BillType('Credit Note');
$billType['reverse_invoice']->numberFormat = '{y}-{id}';
$billType['reverse_invoice']->template = new NullCollection($template);
$billType['reverse_invoice']->transferType = BillTransferType::PURCHASE;
$billType['reverse_invoice']->transferStock = false;
BillTypeMapper::create()->execute($billType['reverse_invoice']);
@ -166,7 +200,7 @@ final class Installer extends InstallerAbstract
*
* @since 1.0.0
*/
private static function createTransferBillTypes() : array
private static function createTransferBillTypes(int $template) : array
{
return [];
}

View File

@ -19,11 +19,10 @@ use Modules\Billing\Models\Bill;
use Modules\Billing\Models\BillElement;
use Modules\Billing\Models\BillElementMapper;
use Modules\Billing\Models\BillMapper;
use Modules\Billing\Models\NullBillType;
use Modules\Billing\Models\BillTypeMapper;
use Modules\Billing\Models\SettingsEnum;
use Modules\ClientManagement\Models\ClientMapper;
use Modules\ItemManagement\Models\ItemMapper;
use Modules\Media\Models\CollectionMapper;
use Modules\Media\Models\UploadStatus;
use Modules\SupplierManagement\Models\SupplierMapper;
use phpOMS\Autoloader;
@ -107,17 +106,20 @@ final class ApiController extends Controller
->execute();
}
/** @var \Modules\Billing\Models\BillType $billType */
$billType = BillTypeMapper::get()->where('id', (int) ($request->getData('type') ?? 1))->execute();
/* @var \Modules\Account\Models\Account $account */
$bill = new Bill();
$bill->createdBy = new NullAccount($request->header->account);
$bill->numberFormat = '{y}-{id}'; // @todo: use admin defined format
$bill->type = $billType;
$bill->numberFormat = $billType->numberFormat;
$bill->billTo = $request->getData('billto')
?? ($account->profile->account->name1 . (!empty($account->profile->account->name2) ? ', ' . $account->profile->account->name2 : '')); // @todo: use defaultInvoiceAddress or mainAddress. also consider to use billto1, billto2, billto3 (for multiple lines e.g. name2, fao etc.)
$bill->billAddress = $request->getData('billaddress') ?? $account->mainAddress->address;
$bill->billZip = $request->getData('billtopostal') ?? $account->mainAddress->postal;
$bill->billCity = $request->getData('billtocity') ?? $account->mainAddress->city;
$bill->billCountry = $request->getData('billtocountry') ?? $account->mainAddress->getCountry();
$bill->type = new NullBillType((int) $request->getData('type'));
$bill->client = $request->getData('client') === null ? null : $account;
$bill->supplier = $request->getData('supplier') === null ? null : $account;
$bill->performanceDate = new \DateTime($request->getData('performancedate') ?? 'now');
@ -360,14 +362,19 @@ final class ApiController extends Controller
{
Autoloader::addPath(__DIR__ . '/../../../Resources/');
$bill = BillMapper::get()->where('id', $request->getData('bill'))->execute();
$bill = BillMapper::get()
->with('type')
->with('type/template')
->with('type/template/sources')
->where('id', $request->getData('bill') ?? 0)
->execute();
// @todo: change once bill types have media files/templates assigned
$defaultTemplate = $this->app->appSettings->get(
names: SettingsEnum::DEFAULT_SALES_INVOICE_TEMPLATE,
$previewType = (int) $this->app->appSettings->get(
names: SettingsEnum::PREVIEW_MEDIA_TYPE,
module: self::NAME
);
$template = CollectionMapper::get()->where('id', (int) $defaultTemplate->content)->execute();
)->content;
$template = $bill->type->template;
$pdfDir = __DIR__ . '/../../../Modules/Media/Files/Modules/Billing/Bills/'
. $bill->createdAt->format('Y') . '/'
@ -411,7 +418,7 @@ final class ApiController extends Controller
. $bill->createdAt->format('Y') . '/'
. $bill->createdAt->format('m') . '/'
. $bill->createdAt->format('d'),
null // @todo: get bill MediaType
$previewType
);
$this->createModelRelation(

View File

@ -16,6 +16,7 @@ namespace Modules\Billing\Controller;
use Modules\Billing\Models\PurchaseBillMapper;
use Modules\Billing\Models\SalesBillMapper;
use Modules\Billing\Models\SettingsEnum;
use Modules\Billing\Models\StockBillMapper;
use phpOMS\Asset\AssetType;
use phpOMS\Contract\RenderableInterface;
@ -107,10 +108,22 @@ final class BackendController extends Controller
$view->setTemplate('/Modules/Billing/Theme/Backend/sales-bill');
$view->addData('nav', $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response));
$bill = SalesBillMapper::get()->with('elements')->where('id', (int) $request->getData('id'))->execute();
$bill = SalesBillMapper::get()
->with('elements')
->with('media')
->with('notes')
->where('id', (int) $request->getData('id'))
->execute();
$view->setData('bill', $bill);
$previewType = (int) $this->app->appSettings->get(
names: SettingsEnum::PREVIEW_MEDIA_TYPE,
module: self::NAME
)->content;
$view->setData('previewType', $previewType);
return $view;
}
@ -234,6 +247,13 @@ final class BackendController extends Controller
$view->setData('bill', $bill);
$previewType = (int) $this->app->appSettings->get(
names: SettingsEnum::PREVIEW_MEDIA_TYPE,
module: self::NAME
)->content;
$view->setData('previewType', $previewType);
return $view;
}

View File

@ -707,7 +707,7 @@ class Bill implements \JsonSerializable
{
$files = [];
foreach ($this->media as $file) {
if ($file->type === $type) {
if ($file->type->getId() === $type) {
$files[] = $file;
}
}
@ -726,9 +726,8 @@ class Bill implements \JsonSerializable
*/
public function getFileByType(int $type = null) : Media
{
$files = [];
foreach ($this->media as $file) {
if ($file->type === $type) {
if ($file->type->getId() === $type) {
return $file;
}
}
@ -742,22 +741,22 @@ class Bill implements \JsonSerializable
public function toArray() : array
{
return [
'id' => $this->id,
'number' => $this->number,
'numberFormat' => $this->numberFormat,
'type' => $this->type,
'shipTo' => $this->shipTo,
'shipFAO' => $this->shipFAO,
'shipAddress' => $this->shipAddress,
'shipCity' => $this->shipCity,
'shipZip' => $this->shipZip,
'shipCountry' => $this->shipCountry,
'billTo' => $this->billTo,
'billFAO' => $this->billFAO,
'billAddress' => $this->billAddress,
'billCity' => $this->billCity,
'billZip' => $this->billZip,
'billCountry' => $this->billCountry,
'id' => $this->id,
'number' => $this->number,
'numberFormat' => $this->numberFormat,
'type' => $this->type,
'shipTo' => $this->shipTo,
'shipFAO' => $this->shipFAO,
'shipAddress' => $this->shipAddress,
'shipCity' => $this->shipCity,
'shipZip' => $this->shipZip,
'shipCountry' => $this->shipCountry,
'billTo' => $this->billTo,
'billFAO' => $this->billFAO,
'billAddress' => $this->billAddress,
'billCity' => $this->billCity,
'billZip' => $this->billZip,
'billCountry' => $this->billCountry,
];
}

View File

@ -14,6 +14,8 @@ declare(strict_types=1);
namespace Modules\Billing\Models;
use Modules\Media\Models\Collection;
use Modules\Media\Models\NullCollection;
use phpOMS\Localization\ISO639x1Enum;
/**
@ -34,6 +36,10 @@ class BillType
*/
protected int $id = 0;
public Collection $template;
public string $numberFormat = '';
public int $transferType = BillTransferType::SALES;
public bool $transferStock = true;
@ -54,6 +60,7 @@ class BillType
*/
public function __construct(string $name = '')
{
$this->media = new NullCollection();
$this->setL11n($name);
}

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Modules\Billing\Models;
use Modules\Media\Models\CollectionMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/**
@ -33,9 +34,24 @@ final class BillTypeMapper extends DataMapperFactory
* @since 1.0.0
*/
public const COLUMNS = [
'billing_type_id' => ['name' => 'billing_type_id', 'type' => 'int', 'internal' => 'id'],
'billing_type_transfer_type' => ['name' => 'billing_type_transfer_type', 'type' => 'int', 'internal' => 'transferType'],
'billing_type_transfer_stock' => ['name' => 'billing_type_transfer_stock', 'type' => 'bool', 'internal' => 'transferStock'],
'billing_type_id' => ['name' => 'billing_type_id', 'type' => 'int', 'internal' => 'id'],
'billing_type_number_format' => ['name' => 'billing_type_number_format', 'type' => 'string', 'internal' => 'numberFormat'],
'billing_type_template' => ['name' => 'billing_type_template', 'type' => 'int', 'internal' => 'template'],
'billing_type_transfer_type' => ['name' => 'billing_type_transfer_type', 'type' => 'int', 'internal' => 'transferType'],
'billing_type_transfer_stock' => ['name' => 'billing_type_transfer_stock', 'type' => 'bool', 'internal' => 'transferStock'],
];
/**
* Belongs to.
*
* @var array<string, array{mapper:string, external:string}>
* @since 1.0.0
*/
public const OWNS_ONE = [
'template' => [
'mapper' => CollectionMapper::class,
'external' => 'billing_type_template',
],
];
/**

View File

@ -26,5 +26,5 @@ use phpOMS\Stdlib\Base\Enum;
*/
abstract class SettingsEnum extends Enum
{
public const DEFAULT_SALES_INVOICE_TEMPLATE = '1005100001_1';
public const PREVIEW_MEDIA_TYPE = '1005100001_1';
}

View File

@ -12,16 +12,22 @@
*/
declare(strict_types=1);
use phpOMS\System\File\FileUtils;
use phpOMS\Uri\UriFactory;
// Media helper functions (e.g. file icon generator)
include __DIR__ . '/../../../Media/Theme/Backend/template-functions.php';
/**
* @var \phpOMS\Views\View $this
*/
/** @var Modules\Billing\Models\Bill $bill */
$bill = $this->getData('bill');
$elements = $bill->getElements();
$media = $bill->getMedia();
$billPdf = $bill->getFileByType(0);
$previewType = $this->getData('previewType');
$billPdf = $bill->getFileByType($previewType);
echo $this->getData('nav')->render(); ?>
@ -258,6 +264,40 @@ echo $this->getData('nav')->render(); ?>
</div>
</section>
</div>
<div class="col-xs-12 col-md-6 col-lg-8">
<div class="portlet">
<div class="portlet-head"><?= $this->getHtml('Media'); ?><i class="fa fa-download floatRight download btn"></i></div>
<table class="default" id="invoice-item-list">
<thead>
<tr>
<td>
<td>
<td class="wf-100"><?= $this->getHtml('Name'); ?>
<td><?= $this->getHtml('Type'); ?>
<tbody>
<?php foreach ($media as $file) :
$url = $file->extension === 'collection'
? UriFactory::build('{/prefix}media/list?path=' . \rtrim($file->getVirtualPath(), '/') . '/' . $file->name)
: UriFactory::build('{/prefix}media/single?id=' . $file->getId()
. '&path={?path}' . (
$file->getId() === 0
? '/' . $file->name
: ''
)
);
$icon = $fileIconFunction(FileUtils::getExtensionType($file->extension));
?>
<tr data-href="<?= $url; ?>">
<td>
<td data-label="<?= $this->getHtml('Type'); ?>"><a href="<?= $url; ?>"><i class="fa fa-<?= $this->printHtml($icon); ?>"></i></a>
<td><a href="<?= $url; ?>"><?= $file->name; ?></a>
<td><a href="<?= $url; ?>"><?= $file->extension; ?></a>
<?php endforeach; ?>
</table>
</div>
</div>
</div>
</div>
<input type="radio" id="c-tab-6" name="tabular-2">