code fixes

This commit is contained in:
Dennis Eichhorn 2024-03-15 20:24:37 +00:00
parent 20a23ae678
commit 05d1e46ef7
14 changed files with 1837 additions and 1648 deletions

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,22 @@
"foreignTable": "account",
"foreignKey": "account_id"
},
"accounting_account_tax1_account": {
"name": "accounting_account_tax1_account",
"type": "INT",
"default": null,
"null": true,
"foreignTable": "accounting_account",
"foreignKey": "accounting_account_id"
},
"accounting_account_tax2_account": {
"name": "accounting_account_tax2_account",
"type": "INT",
"default": null,
"null": true,
"foreignTable": "accounting_account",
"foreignKey": "accounting_account_id"
},
"accounting_account_unit": {
"name": "accounting_account_unit",
"type": "INT",

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Modules\Accounting\Admin;
use Modules\Accounting\Models\AccountAbstractMapper;
use Modules\Accounting\Models\AccountType;
use phpOMS\Application\ApplicationAbstract;
use phpOMS\Config\SettingsInterface;
@ -79,7 +80,7 @@ final class Installer extends InstallerAbstract
if ($c === 2) {
$definitions = $line;
$languages = \count($definitions) - 19;
$languages = \count($definitions) - 21;
}
if ($c < 3) {
@ -91,8 +92,25 @@ final class Installer extends InstallerAbstract
$request->header->account = 1;
$request->setData('code', $line[0]);
$request->setData('content', \trim($line[19]));
$request->setData('language', $definitions[19]);
$request->setData('content', \trim($line[21]));
$request->setData('language', $definitions[21]);
$tax1 = AccountAbstractMapper::get()
->where('code', (string) $line[14])
->execute();
if ($tax1->id !== 0) {
$request->setData('tax1', $tax1->id);
}
$tax2 = AccountAbstractMapper::get()
->where('code', (string) $line[15])
->execute();
if ($tax2->id !== 0) {
$request->setData('tax2', $tax2->id);
}
$module->apiAccountCreate($request, $response);
$responseData = $response->getData('');
@ -112,8 +130,8 @@ final class Installer extends InstallerAbstract
$request->header->account = 1;
$request->setData('ref', $accountId);
$request->setData('content', \trim($line[19 + $i]));
$request->setData('language', $definitions[19 + $i]);
$request->setData('content', \trim($line[21 + $i]));
$request->setData('language', $definitions[21 + $i]);
$module->apiAccountL11nCreate($request, $response);
}
}

View File

@ -24,6 +24,7 @@ use Modules\Accounting\Models\CostCenterMapper;
use Modules\Accounting\Models\CostObject;
use Modules\Accounting\Models\CostObjectL11nMapper;
use Modules\Accounting\Models\CostObjectMapper;
use Modules\Accounting\Models\NullAccountAbstract;
use Modules\Accounting\Models\Posting;
use Modules\Accounting\Models\PostingElement;
use Modules\Accounting\Models\PostingMapper;
@ -31,6 +32,7 @@ use Modules\Accounting\Models\PostingSide;
use Modules\Admin\Models\AccountMapper;
use Modules\Admin\Models\NullAccount;
use Modules\Billing\Models\BillStatus;
use Modules\Finance\Models\TaxCodeMapper;
use Modules\ItemManagement\Models\Attribute\ItemAttributeTypeMapper;
use Modules\ItemManagement\Models\Attribute\ItemAttributeValueMapper;
use phpOMS\Localization\BaseStringL11n;
@ -146,7 +148,7 @@ final class ApiController extends Controller
$firstElement->createdBy = new NullAccount($account);
$firstElement->unit = $posting->unit;
$firstElement->account = $finAcc;
$firstElement->value = $new->grossSales->getInt();
$firstElement->value = \abs($new->grossSales->getInt());
if ($type === 'client') {
$firstElement->type = $new->grossSales->getInt() > 0
@ -165,17 +167,132 @@ final class ApiController extends Controller
// https://github.com/Karaka-Management/oms-Accounting/issues/10
foreach ($new->elements as $element) {
// handle pl account from bill
// handle taxes
$postingElement = new PostingElement();
$postingElement->createdBy = new NullAccount($account);
$postingElement->unit = $posting->unit;
$postingElement->account = $finAcc;
$postingElement->value = $element->totalSalesPriceGross->getInt();
$postingElement->type = $firstElement->type === PostingSide::DEBIT
? PostingSide::CREDIT
: PostingSide::DEBIT;
$elementAcc = AccountAbstractMapper::get()
->where('code', $element->fiAccount)
->execute();
$costCenter = CostCenterMapper::get()
->where('code', $element->costcenter)
->execute();
$costObject = CostObjectMapper::get()
->where('code', $element->costobject)
->execute();
$postingElement = new PostingElement();
$postingElement->createdBy = new NullAccount($account);
$postingElement->unit = $posting->unit;
$postingElement->account = $elementAcc;
$postingElement->value = \abs($element->totalListPriceNet->getInt());
$postingElement->costcenter = $costCenter;
$postingElement->costobject = $costObject;
if ($element->totalSalesPriceNet->getInt() > 0) {
$postingElement->type = $firstElement->type === PostingSide::DEBIT
? PostingSide::CREDIT
: PostingSide::DEBIT;
} else {
$postingElement->type = $firstElement->type;
}
$posting->elements[] = $postingElement;
// @todo Since this is an automatic posting we should be able to combine net+tax posting,
// at least visually into one posting line. e.g. EUR 119 M19 instead of 2.
// Maybe there needs to be a ref to another posting line so that the frontend knows that this tax posting
// should not be shown in the default view
// handle taxes
// Tax accounts can be defined in:
// 1. Account
// 2. Tax code
// 3. Tax combination
$taxAcc1 = null;
$taxAcc2 = null;
if ($elementAcc->taxAccount1 !== null || $elementAcc->taxAccount2 === null) {
// Try finding tax accounts by checking primary account
if ($elementAcc->taxAccount1 !== null) {
$taxAcc1 = new NullAccountAbstract($elementAcc->taxAccount1);
}
if ($elementAcc->taxAccount2 !== null) {
$taxAcc2 = new NullAccountAbstract($elementAcc->taxAccount2);
}
} else {
// Try finding tax accounts by checking tax code
$taxCode = TaxCodeMapper::get()
->where('abbr', $element->taxCode)
->execute();
if ($taxCode->taxAccount1 !== null) {
$taxAcc1 = AccountAbstractMapper::get()
->where('code', $taxCode->taxAccount1)
->execute();
}
if ($taxCode->taxAccount2 !== null) {
$taxAcc2 = AccountAbstractMapper::get()
->where('code', $taxCode->taxAccount2)
->execute();
}
// Still no tax account found
if ($taxAcc1 === null && $taxAcc2 === null) {
// Try finding tax accounts by checking tax combination
$taxAcc1 = AccountAbstractMapper::get()
->where('code', $element->taxCombination->taxAccount1)
->execute();
$taxAcc2 = AccountAbstractMapper::get()
->where('code', $element->taxCombination->taxAccount2)
->execute();
}
}
// Swap taxAcc1 and taxAcc2 if credit note
if ($element->totalSalesPriceNet->getInt() < 0) {
$tmp = $taxAcc1;
$taxAcc1 = $taxAcc2;
$taxAcc2 = $tmp;
}
if ($taxAcc1 !== null) {
$taxElement1 = new PostingElement();
$taxElement1->createdBy = new NullAccount($account);
$taxElement1->unit = $postingElement->unit;
$taxElement1->account = $taxAcc1;
$taxElement1->value = \abs($element->taxP->getInt());
$taxElement1->type = PostingSide::CREDIT;
$posting->elements[] = $taxElement1;
}
if ($taxAcc2 !== null) {
$taxElement2 = new PostingElement();
$taxElement2->createdBy = new NullAccount($account);
$taxElement2->unit = $postingElement->unit;
$taxElement2->account = $taxAcc2;
$taxElement2->value = \abs($element->taxP->getInt());
$taxElement2->type = PostingSide::DEBIT;
$posting->elements[] = $taxElement2;
}
// Handle discount
if ($element->totalListPriceNet->value !== $element->totalSalesPriceNet->value) {
$discountElement = new PostingElement();
$discountElement->createdBy = new NullAccount($account);
$discountElement->unit = $posting->unit;
$discountElement->account = empty($element->taxCombination->discountAccount)
? $elementAcc
: $element->taxCombination->discountAccount;
$discountElement->value = \abs($element->totalListPriceNet->value - $element->totalSalesPriceNet->value);
$discountElement->costcenter = $costCenter;
$discountElement->costobject = $costObject;
$discountElement->type = $firstElement->type;
$posting->elements[] = $discountElement;
}
}
// check debit === credit
@ -186,6 +303,25 @@ final class ApiController extends Controller
$this->createModel($account, $posting, PostingMapper::class, 'posting-bill', $ip);
}
/**
* A hook which creates a personal account.
*
* Usually called by ClientManagement or SupplierManagement (maybe even HR)
*
* @param int $account Account who created the model
* @param mixed $old Old value
* @param mixed $new New value (unused, should be null)
* @param int $type Module model type
* @param string $trigger What triggered this log?
* @param string $module Module name
* @param string $ref Reference to other model
* @param string $content Message
* @param string $ip Ip
*
* @return void
*
* @since 1.0.0
*/
public function hookPersonalAccountCreate(
int $account,
mixed $old,
@ -279,9 +415,11 @@ final class ApiController extends Controller
*/
private function createAccountFromRequest(RequestAbstract $request) : AccountAbstract
{
$account = new AccountAbstract();
$account->code = $request->getDataString('code') ?? '';
$account->account = $request->getDataInt('account');
$account = new AccountAbstract();
$account->code = $request->getDataString('code') ?? '';
$account->account = $request->getDataInt('account');
$account->taxAccount1 = $request->getDataInt('tax1');
$account->taxAccount2 = $request->getDataInt('tax2');
if ($request->hasData('content')) {
$account->setL11n(

View File

@ -401,8 +401,6 @@ final class BackendController extends Controller
$view->data['l11nValues'] = $l11nValues;
return $view;
return $view;
}
/**

View File

@ -64,15 +64,21 @@ class AccountAbstract
public ?int $taxAccount2 = null;
public int $taxCodeRequirement = RequirementType::ALLOWED;
public ?int $defaultTaxCode = null;
public ?int $mandatoryTaxCode = null;
public int $costCenterRequirement = RequirementType::ALLOWED;
public ?int $defaultCostCenter = null;
public ?int $mandatoryCostCenter = null;
public int $costObjectRequirement = RequirementType::ALLOWED;
public ?int $defaultCostObject = null;
public ?int $mandatoryCostObject = null;
// Indicators and report position for different reports (e.g. EÜR, ZM, UVA, OSS)

View File

@ -36,12 +36,14 @@ class AccountAbstractMapper extends DataMapperFactory
* @since 1.0.0
*/
public const COLUMNS = [
'accounting_account_id' => ['name' => 'accounting_account_id', 'type' => 'int', 'internal' => 'id'],
'accounting_account_code' => ['name' => 'accounting_account_code', 'type' => 'string', 'internal' => 'code', 'autocomplete' => true],
'accounting_account_type' => ['name' => 'accounting_account_type', 'type' => 'int', 'internal' => 'type'],
'accounting_account_parent' => ['name' => 'accounting_account_parent', 'type' => 'int', 'internal' => 'parent'],
'accounting_account_account' => ['name' => 'accounting_account_account', 'type' => 'int', 'internal' => 'account'],
'accounting_account_unit' => ['name' => 'accounting_account_unit', 'type' => 'int', 'internal' => 'unit'],
'accounting_account_id' => ['name' => 'accounting_account_id', 'type' => 'int', 'internal' => 'id'],
'accounting_account_code' => ['name' => 'accounting_account_code', 'type' => 'string', 'internal' => 'code', 'autocomplete' => true],
'accounting_account_type' => ['name' => 'accounting_account_type', 'type' => 'int', 'internal' => 'type'],
'accounting_account_parent' => ['name' => 'accounting_account_parent', 'type' => 'int', 'internal' => 'parent'],
'accounting_account_account' => ['name' => 'accounting_account_account', 'type' => 'int', 'internal' => 'account'],
'accounting_account_unit' => ['name' => 'accounting_account_unit', 'type' => 'int', 'internal' => 'unit'],
'accounting_account_tax1_account' => ['name' => 'accounting_account_tax1_account', 'type' => 'int', 'internal' => 'taxAccount1'],
'accounting_account_tax2_account' => ['name' => 'accounting_account_tax2_account', 'type' => 'int', 'internal' => 'taxAccount2'],
];
/**

View File

@ -59,6 +59,11 @@ class Posting
public array $elements = [];
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct()
{
$this->createdAt = new \DateTimeImmutable('now');

View File

@ -57,6 +57,13 @@ class PostingElement
public int $posting = 0;
// @todo Create some hard values similar to bill and bill element for taxCode, customer/supplier taxId, ...
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct()
{
$this->createdAt = new \DateTimeImmutable('now');

View File

@ -24,6 +24,6 @@ return ['Navigation' => [
'Entries' => 'Einträge',
'Postings' => 'Buchungen',
'Predefined' => 'Vordefiniert',
'Suppliers' => 'Lieferanten',
'Clients' => 'Kunden',
'Suppliers' => 'Lieferanten',
'Clients' => 'Kunden',
]];

View File

@ -24,6 +24,6 @@ return ['Navigation' => [
'Entries' => 'Entries',
'Postings' => 'Postings',
'Predefined' => 'Predefined',
'Suppliers' => 'Suppliers',
'Clients' => 'Clients',
'Suppliers' => 'Suppliers',
'Clients' => 'Clients',
]];

View File

@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use phpOMS\Uri\UriFactory;

View File

@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use phpOMS\Uri\UriFactory;
@ -6,7 +6,6 @@ $costcenter = $this->data['costcenter'];
$isNew = $costcenter->id === 0;
/** @var \phpOMS\Views\View $this */
echo $this->data['nav']->render(); ?>
<div class="row">

View File

@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
use phpOMS\Uri\UriFactory;