<?php class ModuleContract extends Module { public int $DirectoryId; function __construct(System $System) { parent::__construct($System); $this->Name = 'Contract'; $this->Version = '1.0'; $this->Creator = 'Chronos'; $this->License = 'GNU/GPLv3'; $this->Description = 'Contract documents management'; $this->Dependencies = array(ModuleDocument::GetName(), ModuleSubject::GetName(), ModuleFile::GetName(), ModuleFinance::GetName()); $this->Models = array(Contract::GetClassName()); $this->DirectoryId = 0; } function DoStart(): void { $this->DirectoryId = Core::Cast($this->System)->Config['Contract']['DirectoryId']; $this->System->RegisterPage(['smlouvy', 'generovat'], 'PageContractGenerate'); Core::Cast($this->System)->FormManager->RegisterClass('Contract', array( 'Title' => 'Smlouvy', 'Table' => 'Contract', 'Items' => array( 'DocumentLine' => array('Type' => 'TDocumentLine', 'Caption' => 'Dokladová Å™ada', 'Default' => ''), 'BillCode' => array('Type' => 'TDocumentLineCode', 'Caption' => 'Kód', 'Default' => '', 'Null' => true), 'Subject' => array('Type' => 'TSubject', 'Caption' => 'Subjekt', 'Default' => ''), 'ValidFrom' => array('Type' => 'Date', 'Caption' => 'Platnost od', 'Default' => ''), 'ValidTo' => array('Type' => 'Date', 'Caption' => 'Platnost do', 'Default' => '', 'Null' => true), 'File' => array('Type' => 'TFile', 'Caption' => 'Soubor', 'Default' => '', 'Null' => true), 'Generate' => array('Type' => 'Boolean', 'Caption' => 'Generovat', 'Default' => ''), 'EmployeeSalaries' => array('Type' => 'TEmployeeSalaryListContract', 'Caption' => 'Výplaty zamÄ›stnanců', 'Default' => ''), 'Customers' => array('Type' => 'TCustomerListContract', 'Caption' => 'ZákaznÃci', 'Default' => ''), ), 'BeforeInsert' => array($this, 'BeforeInsertContract'), 'ItemActions' => array( array('Caption' => 'Generovat', 'URL' => '/smlouvy/generovat/?i=#RowId'), ) )); Core::Cast($this->System)->FormManager->RegisterFormType('TContract', array( 'Type' => 'Reference', 'Table' => 'Contract', 'Id' => 'Id', 'Name' => '(SELECT `DocumentLineCode`.`Name` FROM `DocumentLineCode` WHERE `Id`=`Contract`.`BillCode`)', 'Filter' => '1', )); } function BeforeInsertContract(Form $Form): array { if (array_key_exists('Time', $Form->Values)) $Year = date("Y", $Form->Values['Time']); else $Year = date("Y", $Form->Values['ValidFrom']); $Form->Values['BillCode'] = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($Form->Values['DocumentLine'], $Year); return $Form->Values; } static function Cast(Module $Module): ModuleContract { if ($Module instanceof ModuleContract) { return $Module; } throw new Exception('Expected ModuleContract type but '.gettype($Module)); } } class PageContractGenerate extends Page { function __construct(System $System) { parent::__construct($System); $this->Title = 'Generovánà smlouvy'; $this->ParentClass = 'PagePortal'; } function GenerateContract($Where = '') { $DirectoryId = ModuleContract::Cast($this->System->GetModule('Contract'))->DirectoryId; $Output = ''; $DbResult = $this->Database->query('SELECT * FROM `Contract` WHERE (`BillCode` <> "") '. 'AND (`ValidFrom` IS NOT NULL) AND (`Generate` = 1)'.$Where); while ($Row = $DbResult->fetch_assoc()) { if ($Row['File'] == null) { $this->Database->insert('File', array('Name' => '', 'Size' => 0, 'Directory' => $DirectoryId, 'Time' => 'NOW()', 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))')); $FileId = $this->Database->insert_id; } else $FileId = $Row['File']; $FileName = 'smlouva-'.$FileId.'.pdf'; $Bill = new BillContract($this->System); $Bill->ContractId = $Row['Id']; $FullFileName = ModuleFile::Cast($this->System->GetModule('File'))->File->GetDir($DirectoryId).$FileName; $Bill->SaveToFile($FullFileName); if (file_exists($FullFileName)) { $this->Database->update('File', 'Id='.$FileId, array('Name' => $FileName, 'Size' => filesize($FullFileName), 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))')); $this->Database->update('Contract', 'Id='.$Row['Id'], array('File' => $FileId)); $Output .= 'Smlouva '.$Row['Id'].' vygenerována do souboru '.$FileName.'<br/>'."\n"; } else $Output .= 'Soubor "'.$FullFileName.'" se nepodaÅ™ilo uložit.'; } return $Output; } function Show(): string { if (array_key_exists('i', $_GET) and is_numeric($_GET['i'])) { $Output = $this->GenerateContract(' AND (Id='.($_GET['i'] * 1).')'); } else $Output = 'Missing contract id.'; return $Output; } } class BillContract extends Pdf { public string $ContractId; function GenerateHTML(): string { $this->BorderTop = '0cm'; $this->BorderLeft = '1cm'; $this->BorderRight = '1cm'; $this->BorderBottom = '0cm'; $this->FontSize = 10; $DbResult = $this->Database->select('Subject', '*', '`Id`='.Core::Cast($this->System)->Config['Finance']['MainSubjectId']); if ($DbResult->num_rows > 0) { $Supplier = $DbResult->fetch_assoc(); } else die('MainSubjectId not found in Subjects.'); $DbResult = $this->Database->query('SELECT * FROM `Contract` WHERE `Id`='.$this->ContractId); if ($DbResult->num_rows > 0) { $Contract = $DbResult->fetch_array(); $DbResult = $this->Database->query('SELECT * FROM `Subject` WHERE `Id`='.$Contract['Subject']); if ($DbResult->num_rows > 0) { $Subject = $DbResult->fetch_assoc(); } else die('Customer Subject not found.'); } else die('Contract not found.'); $DbResult = $this->Database->select('DocumentLineCode', '*', '`Id`='.$Contract['BillCode']); if ($DbResult->num_rows > 0) { $SupplierBillCode = $DbResult->fetch_assoc(); } else die('BillCode not found.'); $ContractCode = $SupplierBillCode['Name']; $DbResult = $this->Database->select('Member', '*', '`Subject`='.$Contract['Subject']); if ($DbResult->num_rows > 0) { $Customer = $DbResult->fetch_assoc(); } else die('Customer not found.'); $PrefixMultiplier = new PrefixMultiplier(); $ServiceType = ''; $Price = 0; $MaxSpeed = ''; $MinSpeed = ''; $DbResult = $this->Database->query('SELECT * FROM ServiceCustomerRel '. 'LEFT JOIN Service ON Service.Id=ServiceCustomerRel.Service '. 'WHERE `ServiceCustomerRel`.`Customer`='.$Customer['Id'].' '); if ($DbResult->num_rows > 0) { while ($Service = $DbResult->fetch_assoc()) { if ($ServiceType != '') $ServiceType .= ', '; $ServiceType .= $Service['Name']; $Price += $Service['Price']; if ($Service['InternetSpeedMax'] != 0) $MaxSpeed = $PrefixMultiplier->Add($Service['InternetSpeedMax'], 'bit/s'); if ($Service['InternetSpeedMin'] != 0) $MinSpeed = $PrefixMultiplier->Add($Service['InternetSpeedMin'], 'bit/s'); } } $DbResult = $this->Database->query('SELECT NetworkInterface.LocalIP, NetworkInterface.MAC FROM NetworkDevice '. 'LEFT JOIN NetworkInterface ON NetworkInterface.Device=NetworkDevice.Id '. 'WHERE `NetworkDevice`.`Member`='.$Customer['Id'].' '); if ($DbResult->num_rows > 0) { $NetworkInterface = $DbResult->fetch_assoc(); $IpAddress = $NetworkInterface['LocalIP']; $MacAddress = $NetworkInterface['MAC']; $DbResult = $this->Database->query('SELECT * FROM NetworkSubnet '. 'WHERE CompareNetworkPrefix(INET_ATON("'.$IpAddress.'"), INET_ATON(`AddressRange`), `Mask`)'); if ($DbResult->num_rows > 0) { $Subnet = $DbResult->fetch_assoc(); $DefaultGateway = $Subnet['Gateway']; $NetworkAddressIPv4 = new NetworkAddressIPv4(); $NetworkAddressIPv4->Prefix = $Subnet['Mask']; $NetworkAddressIPv4->Address = $NetworkAddressIPv4->GetNetMask(); $NetMask = $NetworkAddressIPv4->AddressToString(); } else die('Subnet not found.'); $Interface = 'Ethernet'; $PrimaryDNS = '10.145.64.8'; } else { $IpAddress = ''; $MacAddress = ''; $DefaultGateway = ''; $NetMask = ''; $Interface = ''; $PrimaryDNS = ''; } $VarSymbol = $Subject['Id']; $DbResult = $this->Database->query('SELECT FinanceBankAccount.*, CONCAT(FinanceBankAccount.Number, "/", FinanceBank.Code) AS NumberFull FROM FinanceBankAccount '. 'JOIN FinanceBank ON FinanceBank.Id=FinanceBankAccount.Bank '. 'WHERE (FinanceBankAccount.`Subject`='.Core::Cast($this->System)->Config['Finance']['MainSubjectId'].') AND (FinanceBankAccount.`Use`=1)'); if ($DbResult->num_rows > 0) { $SupplierBankAccount = $DbResult->fetch_assoc(); } else die('Bank account not found.'); $DbResult = $this->Database->select('FinanceBillingPeriod', '*', 'Id='.$Customer['BillingPeriod']); if ($DbResult->num_rows > 0) { $BillingPeriod = $DbResult->fetch_assoc(); } else die('BillingPeriod not found.'); $PaymentPeriod = $BillingPeriod['Name']; $BankAccount = $SupplierBankAccount['NumberFull']; $DbResult = $this->Database->select('Member', '*', '`Subject`='.Core::Cast($this->System)->Config['Finance']['MainSubjectId']); if ($DbResult->num_rows > 0) { $SupplierMember = $DbResult->fetch_assoc(); } else die('Customer not found.'); $DbResult = $this->Database->query('SELECT Contact.Value AS Phone FROM User '. 'LEFT JOIN Contact ON Contact.User=User.ID AND Contact.Category=1 '. 'WHERE User.Id='.$SupplierMember['ResponsibleUser'].' ORDER BY `Contact`.`Receive` DESC'); if ($DbResult->num_rows > 0) { $SupplierUser = $DbResult->fetch_assoc(); $SupplierPhone = $SupplierUser['Phone']; } else $SupplierPhone = ''; $DbResult = $this->Database->query('SELECT Contact.Value AS Phone FROM User '. 'LEFT JOIN Contact ON Contact.User=User.ID AND Contact.Category=1 '. 'WHERE User.Id='.$Customer['ResponsibleUser'].' ORDER BY `Contact`.`Receive` DESC'); if ($DbResult->num_rows > 0) { $CustomerUser = $DbResult->fetch_assoc(); $CustomerPhone = $CustomerUser['Phone']; if ($CustomerPhone == null) $CustomerPhone = ''; } else $CustomerPhone = ''; $DbResult = $this->Database->query('SELECT Email, Contact.Value AS ContactEmail FROM User '. 'LEFT JOIN Contact ON Contact.User=User.ID AND Contact.Category=4 '. 'WHERE User.Id='.$Customer['ResponsibleUser'].' ORDER BY `Contact`.`Receive` DESC'); if ($DbResult->num_rows > 0) { $CustomerUser = $DbResult->fetch_assoc(); $CustomerEmail = $CustomerUser['Email']; if ($CustomerEmail == null) { $CustomerEmail = $CustomerUser['ContactEmail']; if ($CustomerEmail == null) $CustomerEmail = ''; } } else $CustomerEmail = ''; $SupplierName = $Supplier['Name']; $SupplierStreet = $Supplier['AddressStreet']; $SupplierTown = $Supplier['AddressTown']; $SupplierPsc = $Supplier['AddressPSC']; $SupplierIC = $Supplier['IC']; if ($Supplier['PayVAT'] == 1) $SupplierDIC = 'plátce DPH'; else $SupplierDIC = 'neplátce DPH'; $Web = '<a href="'.$Supplier['WWW'].'">'.$this->SimplifiedLink($Supplier['WWW']).'</a>'; $CustomerName = $Subject['Name']; $CustomerStreet = $Subject['AddressStreet']; $CustomerTown = $Subject['AddressTown']; $CustomerPsc = $Subject['AddressPSC']; $CustomerIC = $Subject['IC']; $CustomerDIC = $Subject['DIC']; $CustomerPhone = $CustomerPhone; $CustomerEmail = $CustomerEmail; $SignDate = HumanDate($Contract['ValidFrom']); $Output = '<html> <head></head> <body><table width="100%"><tr><td colspan="2">'. '<font size="6"><div align="center">Smlova o pÅ™ipojenà k internetu a poskytovánà datových služeb</font></div>'. '<font size="3"><div align="center">ÄŒÃslo: '.$ContractCode.'</font></div>'. '</td></tr>'. '</table>'. '<br>'. '<table width="100%">'. '<tr><th width="25%">Poskytovatel:</td><td width="25%"></td><th width="25%">OdbÄ›ratel:</th><td width="25%"></td></tr>'. '<tr><td>'.NotBlank($SupplierName).'</td><td></td><td>'.NotBlank($CustomerName).'</td><td></td></tr>'. '<tr><td>'.NotBlank($SupplierStreet).'</td><td></td><td>'.NotBlank($CustomerStreet).'</td><td></td></tr>'. '<tr><td>'.NotBlank($SupplierTown).'</td><td></td><td>'.NotBlank($CustomerTown).'</td><td></td></tr>'. '<tr><td>'.NotBlank($SupplierPsc).'</td><td></td><td>'.NotBlank($CustomerPsc).'</td><td></td></tr>'. '<tr><td colspan="4"> </td></tr>'. '<tr><td>IÄŒ:</td><td>'.NotBlank($SupplierIC).'</td><td>Telefon:</td><td>'.NotBlank($CustomerPhone).'</td></tr>'. '<tr><td>DIÄŒ:</td><td>'.NotBlank($SupplierDIC).'</td><td>E-mail:</td><td>'.NotBlank($CustomerEmail).'</td></tr>'. '<tr><td>Telefon:</td><td>'.NotBlank($SupplierPhone).'</td><td>RÄŒ/IÄŒ:</td><td>'.NotBlank($CustomerIC).'</td></tr>'. '<tr><td>Web:</td><td>'.NotBlank($Web).'</td><td>OP/DIÄŒ:</td><td>'.NotBlank($CustomerDIC).'</td></tr>'. '<tr><td>Bank. spojenÃ:</td><td>'.NotBlank($BankAccount).'</td><td>PÅ™Ãpojné mÃsto:</td><td></td></tr>'. '</table>'. '<br/>'. '<strong>I. PÅ™edmÄ›t smlouvy:</strong><br/>'. 'Smlouva se uzavÃrá mezi Poskytovatelem a OdbÄ›ratelem a pÅ™edmÄ›tem smlouvy je poskytovánà datových služeb a pÅ™ipojenà k sÃti internet, umožňujÃcà OdbÄ›rateli odebÃrat v koncovém bodÄ› za úplatu internetovou konektivitu prostÅ™ednictvÃm telekomunikaÄnà sÃtÄ› Poskytovatele. OdbÄ›ratel se zavazuje za tyto služby Poskytovateli platit cenu ve výši a pravidelných intervalech uvedených v této smlouvÄ›. Smlouva se sjednává na dobu neurÄitou.<br/>'. '<br/>'. '<strong>II. Poskytované služby:</strong><br/>'. '<table width="100%" border="1">'. '<tr><td width="50%">Zvolené služby:</td><td>'.NotBlank($ServiceType).'</td></tr>'. '</table>'. '<br/>'. '<table width="100%" border="1">'. '<tr><th colspan="4" align="center">Technické specifikace služby</th></tr>'. '<tr><td width="25%">Max. rychlost:</td><td width="25%">'.NotBlank($MaxSpeed).'</td><td width="25%">IP adresa:</td><td width="25%">'.NotBlank($IpAddress).'</td></tr>'. '<tr><td>Min. rychlost:</td><td>'.NotBlank($MinSpeed).'</td><td>Maska podsÃtÄ›:</td><td>'.NotBlank($NetMask).'</td></tr>'. '<tr><td>MAC adresa:</td><td>'.NotBlank($MacAddress).'</td><td>Výchozà brána:</td><td>'.NotBlank($DefaultGateway).'</td></tr>'. '<tr><td>PÅ™edávacà rozhranÃ:</td><td>'.NotBlank($Interface).'</td><td>Primárnà DNS:</td><td>'.NotBlank($PrimaryDNS).'</td></tr>'. '</table>'. '<br/>'. '<strong>III. Cena a platebnà podmÃnky:</strong><br/>'. 'Poplatky a pravidelné platby budou na základÄ› této smlouvy hrazeny OdbÄ›ratelem na bankovnà úÄet Poskytovatele bankovnÃm pÅ™evodem, nebo složenkou, v uvedené výši a s uvedenou frekvencÃ. Jako VS bude uvedeno pÅ™idÄ›lené ÄÃslo. V pÅ™ÃpadÄ› prodlenà s platbou mohou být uplatnÄ›ny sankce, Äi služba pozastavena, nebo zruÅ¡ena (dle CenÃku a VÅ¡eobecných smluvnÃch podmÃnek).<br/>'. '<table width="100%">'. '<tr><td width="25%">Cena služeb:</td><td width="25%">'.NotBlank($Price).' KÄ</td><td width="25%">ÄŒÃslo úÄtu:</td><td width="25%">'.NotBlank($BankAccount).'</td></tr>'. '<tr><td>Pronájem zaÅ™ÃzenÃ:</td><td>0 KÄ</td><td>Variabilnà symbol:</td><td>'.NotBlank($VarSymbol).'</td></tr>'. '<tr><td>Frekvence platby:</td><td>'.NotBlank($PaymentPeriod).'</td><td></td><td></td></tr>'. '<tr><td>Prvnà platba:</td><td></td><td></td><td></td></tr>'. '<tr><td>Splatnost:</td><td>do 21. dne uvedeného mÄ›sÃce</td><td></td><td></td></tr>'. '</table>'. '<br/>'. '<strong>IV. ZávÄ›reÄná ustanovenÃ:</strong><br/>'. 'OdbÄ›ratel svým podpisem stvrzuje, že se seznámil a souhlasà se VÅ¡eobecnými smluvnÃmi podmÃnkami, aktuálnÃm CenÃkem Poskytovatele a výše uvedenými skuteÄnostmi, které tvořà souÄást této Smlouvy. Dále stvrzuje, že souhlasà s provedenÃm instalace a umÃstÄ›nÃm pÅ™ijÃmacÃho zaÅ™Ãzenà a kabeláže a nemá proti nim námitky, pÅ™Ãp., že vlastnà veÅ¡kerá pÅ™ÃsluÅ¡ná povolenà a souhlas s jejich umÃstÄ›nÃm. Smlouva je vyhotovena ve dvou provedenÃch, kdy OdbÄ›ratel i Poskytovatel obdržà po jedné. Aktivace služby zaÄÃná dnem podpisu této Smlouvy. VýpovÄ›dnà lhůta je 30 dnů. PÅ™Ãpadné zmÄ›ny této Smlouvy vyžadujà formy vzájemnÄ› obÄ›ma stranami podepsaného dodatku.<br/>'. '<br/>'. '<table width="100%">'. '<tr><td width="20%" aling="left">Ve ZdÄ›chovÄ›</td><td width="20%">dne '.NotBlank($SignDate).'</td></tr>'. '</table>'. '<br/><br/><br/><br/>'. '<table width="100%">'. '<tr><td width="50%" align="center">odbÄ›ratel</td><td width="50%" align="center">dodavatel</td></tr>'. '</table>'. '</td></tr>'. '</table>'. '</body></html>'; return $Output; } function SimplifiedLink(string $Link): string { if (substr($Link, 0, 8) == 'https://') $Link = substr($Link, 8); if (substr($Link, 0, 7) == 'http://') $Link = substr($Link, 7); return $Link; } } class Contract extends Model { static function GetModelDesc(): ModelDesc { $Desc = new ModelDesc(self::GetClassName()); $Desc->AddReference('DocumentLine', DocumentLine::GetClassName()); $Desc->AddReference('BillCode', DocumentLineCode::GetClassName()); $Desc->AddReference('Subject', Subject::GetClassName()); $Desc->AddDate('ValidFrom'); $Desc->AddDate('ValidTo'); $Desc->AddReference('File', File::GetClassName()); return $Desc; } }