This commit is contained in:
Dennis Eichhorn 2024-03-10 02:24:56 +00:00
parent e320b48d38
commit 3cd6a79222
8 changed files with 201 additions and 32 deletions

View File

@ -355,6 +355,18 @@
"null": false, "null": false,
"default": null "default": null
}, },
"billing_tax_tax1_account": {
"name": "billing_tax_tax1_account",
"type": "VARCHAR(10)",
"null": false,
"default": null
},
"billing_tax_tax2_account": {
"name": "billing_tax_tax2_account",
"type": "VARCHAR(10)",
"null": false,
"default": null
},
"billing_tax_refund_account": { "billing_tax_refund_account": {
"name": "billing_tax_refund_account", "name": "billing_tax_refund_account",
"type": "VARCHAR(10)", "type": "VARCHAR(10)",
@ -367,6 +379,24 @@
"null": false, "null": false,
"default": null "default": null
}, },
"billing_tax_cashback_account": {
"name": "billing_tax_cashback_account",
"type": "VARCHAR(10)",
"null": false,
"default": null
},
"billing_tax_overpayment_account": {
"name": "billing_tax_overpayment_account",
"type": "VARCHAR(10)",
"null": false,
"default": null
},
"billing_tax_underpayment_account": {
"name": "billing_tax_underpayment_account",
"type": "VARCHAR(10)",
"null": false,
"default": null
},
"billing_tax_min_price": { "billing_tax_min_price": {
"name": "billing_tax_min_price", "name": "billing_tax_min_price",
"type": "BIGINT", "type": "BIGINT",

View File

@ -40,6 +40,17 @@ return [
], ],
], ],
], ],
'^.*/sales/bill/archive(\?.*$|$)' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingSalesArchive',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::SALES_INVOICE,
],
],
],
'^.*/sales/bill(\?.*$|$)' => [ '^.*/sales/bill(\?.*$|$)' => [
[ [
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingSalesInvoice', 'dest' => '\Modules\Billing\Controller\BackendController:viewBillingSalesInvoice',
@ -74,6 +85,17 @@ return [
], ],
], ],
], ],
'^.*/purchase/bill/archive(\?.*$|$)' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingPurchaseArchive',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::PURCHASE_INVOICE,
],
],
],
'^.*/purchase/bill(\?.*$|$)' => [ '^.*/purchase/bill(\?.*$|$)' => [
[ [
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingPurchaseInvoice', 'dest' => '\Modules\Billing\Controller\BackendController:viewBillingPurchaseInvoice',
@ -119,6 +141,17 @@ return [
], ],
], ],
], ],
'^.*/warehouse/bill/archive(\?.*$|$)' => [
[
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingStockArchive',
'verb' => RouteVerb::GET,
'permission' => [
'module' => BackendController::NAME,
'type' => PermissionType::READ,
'state' => PermissionCategory::PURCHASE_INVOICE,
],
],
],
'^.*/warehouse/bill(\?.*$|$)' => [ '^.*/warehouse/bill(\?.*$|$)' => [
[ [
'dest' => '\Modules\Billing\Controller\BackendController:viewBillingStockInvoice', 'dest' => '\Modules\Billing\Controller\BackendController:viewBillingStockInvoice',

View File

@ -170,6 +170,27 @@ final class ApiBillController extends Controller
public function apiBillFinalize(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void public function apiBillFinalize(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
{ {
if (!$this->app->accountManager->get($request->header->account)->hasPermission(
PermissionType::READ,
$this->app->unitId,
null,
self::NAME,
PermissionCategory::SALES_INVOICE
)
&& !$this->app->accountManager->get($request->header->account)->hasPermission(
PermissionType::READ,
$this->app->unitId,
null,
self::NAME,
PermissionCategory::PURCHASE_INVOICE
)
) {
$this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []);
$response->header->status = RequestStatusCode::R_403;
return;
}
// Archive bill // Archive bill
/** @var \Modules\Billing\Models\Bill $bill */ /** @var \Modules\Billing\Models\Bill $bill */
$old = BillMapper::get() $old = BillMapper::get()
@ -182,22 +203,22 @@ final class ApiBillController extends Controller
$this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill', $request->getOrigin()); $this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill', $request->getOrigin());
$this->app->eventManager->triggerSimilar('PRE:Module:' . self::NAME . '-bill-finalize', '', [
$request->header->account,
null, $bill,
null, self::NAME . '-bill-finalize',
self::NAME,
(string) $bill->id,
null,
$request->getOrigin(),
]);
// Create final pdf // Create final pdf
$this->apiBillPdfArchiveCreate($request, $response, $data); $this->apiBillPdfArchiveCreate($request, $response, $data);
$media = $response->getDataArray($request->uri->__toString())['response']; $media = $response->getDataArray($request->uri->__toString())['response'];
$this->app->eventManager->triggerSimilar('PRE:Module:' . self::NAME . '-bill-finalize', '', [
$request->header->account,
null, $new,
null, self::NAME . '-bill-finalize',
self::NAME,
(string) $new->id,
null,
$request->getOrigin(),
]);
// Send bill via email // Send bill via email
$this->apiBillEmail($request, $response, ['bill' => $old, 'media' => $media]); $this->apiBillEmail($request, $response, ['bill' => $new, 'media' => $media]);
$this->createStandardUpdateResponse($request, $response, $new); $this->createStandardUpdateResponse($request, $response, $new);
} }
@ -1334,6 +1355,14 @@ final class ApiBillController extends Controller
$response->set($request->uri->__toString(), new FormValidation(['status' => $status])); $response->set($request->uri->__toString(), new FormValidation(['status' => $status]));
$response->header->status = RequestStatusCode::R_400; $response->header->status = RequestStatusCode::R_400;
\phpOMS\Log\FileLogger::getInstance()->error(
\phpOMS\Log\FileLogger::MSG_FULL, [
'message' => 'Couldn\'t create bill path: ' . $bill->id,
'line' => __LINE__,
'file' => self::class,
]
);
return; return;
// @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd
} }
@ -1352,12 +1381,22 @@ final class ApiBillController extends Controller
\file_put_contents($pdfDir . '/' . $billFileName, $pdf); \file_put_contents($pdfDir . '/' . $billFileName, $pdf);
if (!\is_file($pdfDir . '/' . $billFileName)) { if (!\is_file($pdfDir . '/' . $billFileName)) {
$response->header->status = RequestStatusCode::R_400; $response->header->status = RequestStatusCode::R_400;
$response->set($request->uri->__toString(), []);
\phpOMS\Log\FileLogger::getInstance()->error(
\phpOMS\Log\FileLogger::MSG_FULL, [
'message' => 'Couldn\'t render bill pdf: ' . $bill->id,
'line' => __LINE__,
'file' => self::class,
]
);
return; return;
} }
$media = null; $media = null;
if ($oldFile->id === 0) { if ($oldFile->id === 0) {
// Creating new bill archive pdf
$media = $this->app->moduleManager->get('Media', 'Api')->createDbEntry( $media = $this->app->moduleManager->get('Media', 'Api')->createDbEntry(
status: [ status: [
'status' => UploadStatus::OK, 'status' => UploadStatus::OK,
@ -1397,12 +1436,12 @@ final class ApiBillController extends Controller
$request->getOrigin() $request->getOrigin()
); );
} else { } else {
// Updating existing bill archive pdf
$media = clone $oldFile; $media = clone $oldFile;
if (\realpath($pdfDir . '/' . $billFileName) !== \realpath($oldFile->getAbsolutePath())) { if (\realpath($pdfDir . '/' . $billFileName) !== \realpath($oldFile->getAbsolutePath())) {
\unlink($oldFile->getAbsolutePath()); \unlink($oldFile->getAbsolutePath());
} }
$media->setPath(\Modules\Media\Controller\ApiController::normalizeDbPath($pdfDir . '/' . $billFileName)); $media->setPath(\Modules\Media\Controller\ApiController::normalizeDbPath($pdfDir . '/' . $billFileName));
$media->setVirtualPath($path); $media->setVirtualPath($path);
$media->size = \filesize($media->getAbsolutePath()); $media->size = \filesize($media->getAbsolutePath());

View File

@ -70,6 +70,54 @@ final class BackendController extends Controller
->with('type') ->with('type')
->with('type/l11n') ->with('type/l11n')
->with('client') ->with('client')
->where('status', BillStatus::DRAFT)
->where('type/transferType', BillTransferType::SALES)
->where('type/l11n/language', $response->header->l11n->language)
->sort('id', OrderType::DESC)
->where('unit', $this->app->unitId)
->limit(25);
if ($request->getData('ptype') === 'p') {
$view->data['bills'] = $mapperQuery
->where('id', $request->getDataInt('id') ?? 0, '<')
->where('client', null, '!=')
->execute();
} elseif ($request->getData('ptype') === 'n') {
$view->data['bills'] = $mapperQuery->where('id', $request->getDataInt('id') ?? 0, '>')
->where('client', null, '!=')
->execute();
} else {
$view->data['bills'] = $mapperQuery->where('id', 0, '>')
->where('client', null, '!=')
->execute();
}
return $view;
}
/**
* Routing end-point for application behavior.
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param array $data Generic data
*
* @return RenderableInterface
*
* @since 1.0.0
* @codeCoverageIgnore
*/
public function viewBillingSalesArchive(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface
{
$view = new View($this->app->l11nManager, $request, $response);
$view->setTemplate('/Modules/Billing/Theme/Backend/sales-bill-list');
$view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1005104001, $request, $response);
$mapperQuery = SalesBillMapper::getAll()
->with('type')
->with('type/l11n')
->with('client')
->where('status', BillStatus::DRAFT, '!=')
->where('type/transferType', BillTransferType::SALES) ->where('type/transferType', BillTransferType::SALES)
->where('type/l11n/language', $response->header->l11n->language) ->where('type/l11n/language', $response->header->l11n->language)
->sort('id', OrderType::DESC) ->sort('id', OrderType::DESC)

View File

@ -49,10 +49,24 @@ class TaxCombination implements \JsonSerializable
public string $account = ''; public string $account = '';
// Tax accounts can be defined in:
// 1. Account (gross postings are automatically split)
// 2. Tax code
// 3. Tax combination
public string $taxAccount1 = '';
public string $taxAccount2 = '';
public string $refundAccount = ''; public string $refundAccount = '';
public string $discountAccount = ''; public string $discountAccount = '';
public string $cashbackAccount = '';
public string $overpaymentAccount = '';
public string $underpaymentAccount = '';
public ?int $minPrice = null; public ?int $minPrice = null;
public ?int $maxPrice = null; public ?int $maxPrice = null;

View File

@ -47,8 +47,13 @@ final class TaxCombinationMapper extends DataMapperFactory
'billing_tax_code' => ['name' => 'billing_tax_code', 'type' => 'string', 'internal' => 'taxCode'], 'billing_tax_code' => ['name' => 'billing_tax_code', 'type' => 'string', 'internal' => 'taxCode'],
'billing_tax_type' => ['name' => 'billing_tax_type', 'type' => 'int', 'internal' => 'taxType'], 'billing_tax_type' => ['name' => 'billing_tax_type', 'type' => 'int', 'internal' => 'taxType'],
'billing_tax_account' => ['name' => 'billing_tax_account', 'type' => 'string', 'internal' => 'account'], 'billing_tax_account' => ['name' => 'billing_tax_account', 'type' => 'string', 'internal' => 'account'],
'billing_tax_tax1_account' => ['name' => 'billing_tax_tax1_account', 'type' => 'string', 'internal' => 'taxAccount1'],
'billing_tax_tax2_account' => ['name' => 'billing_tax_tax2_account', 'type' => 'string', 'internal' => 'taxAccount2'],
'billing_tax_refund_account' => ['name' => 'billing_tax_refund_account', 'type' => 'string', 'internal' => 'refundAccount'], 'billing_tax_refund_account' => ['name' => 'billing_tax_refund_account', 'type' => 'string', 'internal' => 'refundAccount'],
'billing_tax_discount_account' => ['name' => 'billing_tax_discount_account', 'type' => 'string', 'internal' => 'discountAccount'], 'billing_tax_discount_account' => ['name' => 'billing_tax_discount_account', 'type' => 'string', 'internal' => 'discountAccount'],
'billing_tax_cashback_account' => ['name' => 'billing_tax_cashback_account', 'type' => 'string', 'internal' => 'cashbackAccount'],
'billing_tax_overpayment_account' => ['name' => 'billing_tax_overpayment_account', 'type' => 'string', 'internal' => 'overpaymentAccount'],
'billing_tax_underpayment_account' => ['name' => 'billing_tax_underpayment_account', 'type' => 'string', 'internal' => 'underpaymentAccount'],
'billing_tax_min_price' => ['name' => 'billing_tax_min_price', 'type' => 'int', 'internal' => 'minPrice'], 'billing_tax_min_price' => ['name' => 'billing_tax_min_price', 'type' => 'int', 'internal' => 'minPrice'],
'billing_tax_max_price' => ['name' => 'billing_tax_max_price', 'type' => 'int', 'internal' => 'maxPrice'], 'billing_tax_max_price' => ['name' => 'billing_tax_max_price', 'type' => 'int', 'internal' => 'maxPrice'],
'billing_tax_start' => ['name' => 'billing_tax_start', 'type' => 'DateTime', 'internal' => 'start'], 'billing_tax_start' => ['name' => 'billing_tax_start', 'type' => 'DateTime', 'internal' => 'start'],

View File

@ -333,11 +333,11 @@ echo $this->data['nav']->render(); ?>
</button><input name="item_number" type="text" autocomplete="off"></span> </button><input name="item_number" type="text" autocomplete="off"></span>
<td><textarea name="item_description" autocomplete="off"></textarea> <td><textarea name="item_description" autocomplete="off"></textarea>
<td><input name="item_quantity" type="number" step="any" value="" autocomplete="off"> <td><input name="item_quantity" type="number" step="any" value="" autocomplete="off">
<td><input name="item_discountp" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_discountp" type="number" step="any" value="" autocomplete="off">
<td><input name="item_discountr" type="number" min="-100" max="100" step="0.01" value="" autocomplete="off"> <td><input name="item_discountr" type="number" min="-100" max="100" step="0.01" value="" autocomplete="off">
<td><input name="item_bonus" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_bonus" type="number" step="any" value="" autocomplete="off">
<td><input name="item_price" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_price" type="number" step="any" value="" autocomplete="off">
<td><input name="item_taxr" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_taxr" type="number" step="any" value="" autocomplete="off">
<td> <td>
<td> <td>
</tr> </tr>
@ -356,11 +356,11 @@ echo $this->data['nav']->render(); ?>
</button><input name="item_number" autocomplete="off" type="text" value="<?= $element->itemNumber; ?>"<?= $disabled; ?>></span> </button><input name="item_number" autocomplete="off" type="text" value="<?= $element->itemNumber; ?>"<?= $disabled; ?>></span>
<td><textarea name="item_description" autocomplete="off"<?= $disabled; ?>><?= $element->itemName; ?></textarea> <td><textarea name="item_description" autocomplete="off"<?= $disabled; ?>><?= $element->itemName; ?></textarea>
<td><input name="item_quantity" autocomplete="off" type="number" step="any" value="<?= $element->quantity->sub($element->discountQ)->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>> <td><input name="item_quantity" autocomplete="off" type="number" step="any" value="<?= $element->quantity->sub($element->discountQ)->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>>
<td><input name="item_discountp" autocomplete="off" type="number" step="0.01" value="<?= $element->singleDiscountP->getAmount(); ?>"<?= $disabled; ?>> <td><input name="item_discountp" autocomplete="off" type="number" step="any" value="<?= $element->singleDiscountP->getAmount(); ?>"<?= $disabled; ?>>
<td><input name="item_discountr" autocomplete="off" type="number" step="0.01" value="<?= $element->singleDiscountR->getAmount(); ?>"<?= $disabled; ?>> <td><input name="item_discountr" autocomplete="off" type="number" step="any" value="<?= $element->singleDiscountR->getAmount(); ?>"<?= $disabled; ?>>
<td><input name="item_bonus" autocomplete="off" type="number" min="-100" max="100" step="0.01" value="<?= $element->discountQ->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>> <td><input name="item_bonus" autocomplete="off" type="number" min="-100" max="100" step="0.01" value="<?= $element->discountQ->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>>
<td><input name="item_price" autocomplete="off" type="number" step="0.01" value="<?= $element->singleSalesPriceNet->getFloat(); ?>"<?= $disabled; ?>> <td><input name="item_price" autocomplete="off" type="number" step="any" value="<?= $element->singleSalesPriceNet->getFloat(); ?>"<?= $disabled; ?>>
<td><input name="item_taxr" autocomplete="off" type="number" step="0.01" value="<?= $element->taxR->getAmount(); ?>"<?= $disabled; ?>> <td><input name="item_taxr" autocomplete="off" type="number" step="any" value="<?= $element->taxR->getAmount(); ?>"<?= $disabled; ?>>
<td><?= $this->getCurrency($element->totalSalesPriceNet, symbol: ''); ?> <td><?= $this->getCurrency($element->totalSalesPriceNet, symbol: ''); ?>
<td><?= \number_format($element->totalSalesPriceNet->value === 0 ? 0 : (1 - $element->totalPurchasePriceNet->value / $element->totalSalesPriceNet->value) * 100, 2); ?>% <td><?= \number_format($element->totalSalesPriceNet->value === 0 ? 0 : (1 - $element->totalPurchasePriceNet->value / $element->totalSalesPriceNet->value) * 100, 2); ?>%
<?php endforeach; ?> <?php endforeach; ?>

View File

@ -331,11 +331,11 @@ echo $this->data['nav']->render(); ?>
</button><input name="item_number" type="text" autocomplete="off"></span> </button><input name="item_number" type="text" autocomplete="off"></span>
<td><textarea name="item_description" autocomplete="off"></textarea> <td><textarea name="item_description" autocomplete="off"></textarea>
<td><input name="item_quantity" type="number" step="any" value="" autocomplete="off"> <td><input name="item_quantity" type="number" step="any" value="" autocomplete="off">
<td><input name="item_discountp" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_discountp" type="number" step="any" value="" autocomplete="off">
<td><input name="item_discountr" type="number" min="-100" max="100" step="0.01" value="" autocomplete="off"> <td><input name="item_discountr" type="number" min="-100" max="100" step="0.01" value="" autocomplete="off">
<td><input name="item_bonus" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_bonus" type="number" step="any" value="" autocomplete="off">
<td><input name="item_price" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_price" type="number" step="any" value="" autocomplete="off">
<td><input name="item_taxr" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_taxr" type="number" step="any" value="" autocomplete="off">
<td> <td>
<td> <td>
</tr> </tr>
@ -354,11 +354,11 @@ echo $this->data['nav']->render(); ?>
</button><input name="item_number" autocomplete="off" type="text" value="<?= $element->itemNumber; ?>"<?= $disabled; ?>></span> </button><input name="item_number" autocomplete="off" type="text" value="<?= $element->itemNumber; ?>"<?= $disabled; ?>></span>
<td><textarea name="item_description" autocomplete="off"<?= $disabled; ?>><?= $element->itemName; ?></textarea> <td><textarea name="item_description" autocomplete="off"<?= $disabled; ?>><?= $element->itemName; ?></textarea>
<td><input name="item_quantity" autocomplete="off" type="number" step="any" value="<?= $element->quantity->sub($element->discountQ)->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>> <td><input name="item_quantity" autocomplete="off" type="number" step="any" value="<?= $element->quantity->sub($element->discountQ)->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>>
<td><input name="item_discountp" autocomplete="off" type="number" step="0.01" value="<?= $element->singleDiscountP->getAmount(); ?>"<?= $disabled; ?>> <td><input name="item_discountp" autocomplete="off" type="number" step="any" value="<?= $element->singleDiscountP->getAmount(); ?>"<?= $disabled; ?>>
<td><input name="item_discountr" autocomplete="off" type="number" step="0.01" value="<?= $element->singleDiscountR->getAmount(); ?>"<?= $disabled; ?>> <td><input name="item_discountr" autocomplete="off" type="number" step="any" value="<?= $element->singleDiscountR->getAmount(); ?>"<?= $disabled; ?>>
<td><input name="item_bonus" autocomplete="off" type="number" min="-100" max="100" step="0.01" value="<?= $element->discountQ->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>> <td><input name="item_bonus" autocomplete="off" type="number" min="-100" max="100" step="0.01" value="<?= $element->discountQ->getAmount($element->container->quantityDecimals); ?>"<?= $disabled; ?>>
<td><input name="item_price" autocomplete="off" type="number" step="0.01" value="<?= $element->singleSalesPriceNet->getFloat(); ?>"<?= $disabled; ?>> <td><input name="item_price" autocomplete="off" type="number" step="any" value="<?= $element->singleSalesPriceNet->getFloat(); ?>"<?= $disabled; ?>>
<td><input name="item_taxr" autocomplete="off" type="number" step="0.01" value="<?= $element->taxR->getAmount(); ?>"<?= $disabled; ?>> <td><input name="item_taxr" autocomplete="off" type="number" step="any" value="<?= $element->taxR->getAmount(); ?>"<?= $disabled; ?>>
<td><?= $this->getCurrency($element->totalSalesPriceNet, symbol: ''); ?> <td><?= $this->getCurrency($element->totalSalesPriceNet, symbol: ''); ?>
<td><?= \number_format($element->totalSalesPriceNet->value === 0 ? 0 : (1 - $element->totalPurchasePriceNet->value / $element->totalSalesPriceNet->value) * 100, 2); ?>% <td><?= \number_format($element->totalSalesPriceNet->value === 0 ? 0 : (1 - $element->totalPurchasePriceNet->value / $element->totalSalesPriceNet->value) * 100, 2); ?>%
<?php endforeach; ?> <?php endforeach; ?>
@ -372,11 +372,11 @@ echo $this->data['nav']->render(); ?>
<i class="g-icon">book</i></button><input name="item_number" type="text" autocomplete="off"></span> <i class="g-icon">book</i></button><input name="item_number" type="text" autocomplete="off"></span>
<td><textarea name="item_description" autocomplete="off"></textarea> <td><textarea name="item_description" autocomplete="off"></textarea>
<td><input name="item_quantity" type="number" step="any" value="" autocomplete="off"> <td><input name="item_quantity" type="number" step="any" value="" autocomplete="off">
<td><input name="item_discountp" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_discountp" type="number" step="any" value="" autocomplete="off">
<td><input name="item_discountr" type="number" min="-100" max="100" step="0.01" value="" autocomplete="off"> <td><input name="item_discountr" type="number" min="-100" max="100" step="0.01" value="" autocomplete="off">
<td><input name="item_bonus" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_bonus" type="number" step="any" value="" autocomplete="off">
<td><input name="item_price" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_price" type="number" step="any" value="" autocomplete="off">
<td><input name="item_taxr" type="number" step="0.01" value="" autocomplete="off"> <td><input name="item_taxr" type="number" step="any" value="" autocomplete="off">
<td> <td>
<td> <td>
<?php endif; ?> <?php endif; ?>