From da8b60b506249f7bbaee6ee7665ddf21886fd927 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 13 Jun 2023 18:55:51 +0000 Subject: [PATCH] Quick backup before crash --- Admin/Install/Media/bill.pdf.php | 8 ++-- Admin/Installer.php | 10 ++--- Controller/ApiBillController.php | 56 +++++++++++++++++++++++----- Controller/ApiPurchaseController.php | 1 + Controller/BackendController.php | 4 +- Controller/CliController.php | 2 +- Models/BillElement.php | 14 ++++--- Models/Price/Price.php | 5 +++ Models/Price/PriceMapper.php | 7 ++++ 9 files changed, 80 insertions(+), 27 deletions(-) diff --git a/Admin/Install/Media/bill.pdf.php b/Admin/Install/Media/bill.pdf.php index 152a02c..4d08bba 100755 --- a/Admin/Install/Media/bill.pdf.php +++ b/Admin/Install/Media/bill.pdf.php @@ -136,11 +136,11 @@ $pdf->setXY($rightPos + 26 + 2, $tempY, true); $pdf->MultiCell( 25, 30, $bill->number . "\n" - . $bill->billDate->format('Y-m-d') . "\n" - . $bill->performanceDate->format('Y-m-d') . "\n" + . ($bill->billDate?->format('Y-m-d') ?? '0') . "\n" + . ($bill->performanceDate?->format('Y-m-d') ?? '0') . "\n" . $bill->accountNumber . "\n" . '' . "\n" /* @todo: implement customer / supplier reference as string */ - . $bill->billDate->format('Y-m-d'), /* Consider to add dueDate in addition */ + . ($bill->billDate?->format('Y-m-d') ?? '0'), /* Consider to add dueDate in addition */ 0, 'L' ); $pdf->Ln(); @@ -308,6 +308,6 @@ $pdf->Ln(); //Close and output PDF document $pdf->Output( - $this->data['path'] ?? ($bill->billDate->format('Y-m-d') . '_' . $bill->number . '.pdf'), + $this->data['path'] ?? (($bill->billDate?->format('Y-m-d') ?? '0') . '_' . $bill->number . '.pdf'), 'I' ); diff --git a/Admin/Installer.php b/Admin/Installer.php index 66c0966..8fb388d 100755 --- a/Admin/Installer.php +++ b/Admin/Installer.php @@ -104,16 +104,16 @@ final class Installer extends InstallerAbstract /** * Install default attribute types * - * @param ApplicationAbstract $app Application - * @param array, is_required?:bool, is_custom_allowed?:bool, validation_pattern?:string, value_type?:string, values?:array}> $attributes Attribute definition + * @param ApplicationAbstract $app Application + * @param array $attributes Attribute definition * - * @return array + * @return array * * @since 1.0.0 */ private static function createBillAttributeTypes(ApplicationAbstract $app, array $attributes) : array { - /** @var array $billAttrType */ + /** @var array $billAttrType */ $billAttrType = []; /** @var \Modules\Billing\Controller\ApiController $module */ @@ -258,7 +258,7 @@ final class Installer extends InstallerAbstract /** @var \Modules\Billing\Controller\ApiController $module */ $module = $app->moduleManager->getModuleInstance('Billing'); - /** @var \Modules\Attribute\Models\ItemAttributeTypeMapper $itemAttributeSales */ + /** @var \Modules\Attribute\Models\AttributeType $itemAttributeSales */ $itemAttributeSales = ItemAttributeTypeMapper::get() ->with('defaults') ->where('name', 'sales_tax_code') diff --git a/Controller/ApiBillController.php b/Controller/ApiBillController.php index 15b8587..86bf9c3 100755 --- a/Controller/ApiBillController.php +++ b/Controller/ApiBillController.php @@ -24,6 +24,7 @@ use Modules\Billing\Models\BillElementMapper; use Modules\Billing\Models\BillMapper; use Modules\Billing\Models\BillStatus; use Modules\Billing\Models\BillTypeMapper; +use Modules\Billing\Models\NullBillElement; use Modules\Billing\Models\SettingsEnum; use Modules\ClientManagement\Models\Client; use Modules\ClientManagement\Models\ClientMapper; @@ -187,7 +188,7 @@ final class ApiBillController extends Controller /** * Create a base Bill object with default values * - * @param Client $client The client object for whom the bill is being created + * @param Client|Supplier $account The client or supplier object for whom the bill is being created * @param RequestAbstract $request The request object that contains the header account * * @return Bill The new Bill object with default values @@ -251,7 +252,9 @@ final class ApiBillController extends Controller $validLanguages = []; if (!empty($settings) && !empty($settings->content)) { $validLanguages = \json_decode($settings->content, true); - } else { + } + + if (empty($validLanguages) || !\is_array($validLanguages)) { $validLanguages = [ ISO639x1Enum::_EN, ]; @@ -441,6 +444,7 @@ final class ApiBillController extends Controller } if ($collection === null) { + /** @var \Modules\Media\Models\Collection $collection */ $collection = MediaMapper::getParentCollection($path) ->limit(1) ->execute(); @@ -591,6 +595,10 @@ final class ApiBillController extends Controller ->where('l11n/language', $bill->language) ->execute(); + if ($bill->client === null) { + return new NullBillElement(); + } + $element = $this->createBaseBillElement($bill->client, $item, $bill, $request); $element->bill = $bill->id; @@ -621,6 +629,19 @@ final class ApiBillController extends Controller return []; } + /** + * Render bill media + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param mixed $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ public function apiMediaRender(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void { // @todo: check if has permission @@ -727,7 +748,7 @@ final class ApiBillController extends Controller $pdfDir = __DIR__ . '/../../../Modules/Media/Files' . $path; $view->data['bill'] = $bill; - $view->data['path'] = $pdfDir . '/' .$bill->billDate->format('Y-m-d') . '_' . $bill->number . '.pdf'; + $view->data['path'] = $pdfDir . '/' . ($bill->billDate?->format('Y-m-d') ?? '0') . '_' . $bill->number . '.pdf'; $view->data['bill_creator'] = $request->getDataString('bill_creator'); $view->data['bill_title'] = $request->getDataString('bill_title'); @@ -878,7 +899,7 @@ final class ApiBillController extends Controller // @codeCoverageIgnoreEnd } - $billFileName = $bill->billDate->format('Y-m-d') . '_' . $bill->number . '.pdf'; + $billFileName = ($bill->billDate?->format('Y-m-d') ?? '0') . '_' . $bill->number . '.pdf'; \file_put_contents($pdfDir . '/' . $billFileName, $pdf); if (!\is_file($pdfDir . '/' . $billFileName)) { @@ -911,7 +932,7 @@ final class ApiBillController extends Controller ->with('attributes') ->with('attributes/type') ->with('attributes/value') - ->where('id', $bill->client->id) + ->where('id', $bill->client?->id ?? 0) ->where('attributes/type/name', ['bill_emails', 'bill_email_address'], 'IN') ->execute(); @@ -924,6 +945,7 @@ final class ApiBillController extends Controller } // Add type to media + /** @var \Model\Setting $originalType */ $originalType = $this->app->appSettings->get( names: SettingsEnum::ORIGINAL_MEDIA_TYPE, module: self::NAME @@ -953,28 +975,41 @@ final class ApiBillController extends Controller $this->createStandardCreateResponse($request, $response, $media); } + /** + * Send bill as email + * + * @param Media $media Media to send + * @param string $email Email address + * @param string $language Message language + * + * @return void + * + * @since 1.0.0 + */ public function sendBillEmail(Media $media, string $email, string $language = 'en') : void { - $handler = $this->app->moduleMaanger->get('Admin', 'Api')->setUpServerMailHandler(); + $handler = $this->app->moduleManager->get('Admin', 'Api')->setUpServerMailHandler(); - $emailSettings = $this->app->appSettings->get( + /** @var \Model\Setting $emailFrom */ + $emailFrom = $this->app->appSettings->get( names: AdminSettingsEnum::MAIL_SERVER_ADDR, module: 'Admin' ); - $emailSettings = $this->app->appSettings->get( + /** @var \Model\Setting $billingTemplate */ + $billingTemplate = $this->app->appSettings->get( names: SettingsEnum::BILLING_CUSTOMER_EMAIL_TEMPLATE, module: 'Billing' ); $mail = EmailMapper::get() ->with('l11n') - ->where('id', (int) $emailSettings->content) + ->where('id', (int) $billingTemplate->content) ->where('l11n/language', $language) ->execute(); $mail = new Email(); - $mail->setFrom($emailSettings->content); + $mail->setFrom($emailFrom->content); $mail->addTo($email); $mail->addAttachment($media->getAbsolutePath(), $media->name); @@ -1015,6 +1050,7 @@ final class ApiBillController extends Controller return; } + /** @var \Modules\Editor\Models\EditorDoc $model */ $model = $response->get($request->uri->__toString())['response']; $this->createModelRelation($request->header->account, $request->getDataInt('id'), $model->id, BillMapper::class, 'bill_note', '', $request->getOrigin()); } diff --git a/Controller/ApiPurchaseController.php b/Controller/ApiPurchaseController.php index 2a6dc22..3e06225 100755 --- a/Controller/ApiPurchaseController.php +++ b/Controller/ApiPurchaseController.php @@ -96,6 +96,7 @@ final class ApiPurchaseController extends Controller $mediaRequest->setData('parse_content', true, true); $this->app->moduleManager->get('Billing', 'Api')->apiMediaAddToBill($mediaRequest, $mediaResponse, $data); + /** @var \Modules\Media\Models\Media[] $uploaded */ $uploaded = $mediaResponse->get('')['response']['upload']; $in = \reset($uploaded)->getAbsolutePath(); // pdf is parsed in $in->content diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 17a6eed..6941ae4 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -120,7 +120,7 @@ final class BackendController extends Controller $view->data['bill'] = $bill; - /** @var \Modules\Auditor\Models\Auditor[] $logsBill */ + /** @var \Modules\Auditor\Models\Audit[] $logsBill */ $logsBill = AuditMapper::getAll() ->with('createdBy') ->where('module', 'Billing') @@ -128,7 +128,7 @@ final class BackendController extends Controller ->where('ref', $bill->id) ->execute(); - /** @var \Modules\Auditor\Models\Auditor[] $logsElements */ + /** @var \Modules\Auditor\Models\Audit[] $logsElements */ $logsElements = AuditMapper::getAll() ->with('createdBy') ->where('module', 'Billing') diff --git a/Controller/CliController.php b/Controller/CliController.php index 0599726..793b527 100755 --- a/Controller/CliController.php +++ b/Controller/CliController.php @@ -407,7 +407,7 @@ final class CliController extends Controller return \DateTime::createFromFormat( $supplier->getAttribute('bill_date_format')->value->valueStr ?? '', $date - ); + ) ?? new \DateTime('1970-01-01'); } foreach ($formats as $format) { diff --git a/Models/BillElement.php b/Models/BillElement.php index 5d0862a..73e9445 100755 --- a/Models/BillElement.php +++ b/Models/BillElement.php @@ -17,6 +17,7 @@ namespace Modules\Billing\Models; use Modules\Finance\Models\TaxCode; use Modules\ItemManagement\Models\Item; use phpOMS\Stdlib\Base\FloatInt; +use phpOMS\Stdlib\Base\SmartDateTime; /** * Bill class. @@ -272,12 +273,15 @@ class BillElement implements \JsonSerializable if (!empty($element->bill) && $item->getAttribute('subscription')->value->getValue() === 1 + && $element->item !== null ) { - $element->subscription = new Subscription(); - $element->subscription->bill = $element->bill; - $element->subscription->item = $element->item; - $element->subscription->start = $element->quantity; - $element->subscription->end = $element->quantity; + $element->subscription = new Subscription(); + $element->subscription->bill = $element->bill; + $element->subscription->item = $element->item; + $element->subscription->start = new \DateTime('now'); // @todo: change to bill performanceDate + $element->subscription->end = new SmartDateTime('now'); // @todo: depends on subscription type + $element->subscription->end->smartModify(m: 1); + $element->subscription->quantity = $element->quantity; $element->subscription->autoRenew = $item->getAttribute('subscription_renewal_type')->value->getValue() === 1; } diff --git a/Models/Price/Price.php b/Models/Price/Price.php index 3aee495..b8716d5 100755 --- a/Models/Price/Price.php +++ b/Models/Price/Price.php @@ -95,6 +95,11 @@ class Price implements \JsonSerializable public ?\DateTime $end = null; + /** + * Constructor. + * + * @since 1.0.0 + */ public function __construct() { $this->item = new NullItem(); diff --git a/Models/Price/PriceMapper.php b/Models/Price/PriceMapper.php index 47f66b7..935a386 100755 --- a/Models/Price/PriceMapper.php +++ b/Models/Price/PriceMapper.php @@ -155,6 +155,13 @@ final class PriceMapper extends DataMapperFactory */ public const PRIMARYFIELD = 'billing_price_id'; + /** + * Find price for a client + * + * @return Price[] + * + * @since 1.0.0 + */ public static function findClientPrice() : array { /*