Changeset 901


Ignore:
Timestamp:
Feb 17, 2021, 9:27:32 PM (3 years ago)
Author:
chronos
Message:
  • Added: Documents section accessible from users panel.
  • Added: Contract model moved to separate module Contract.
  • Added: New action to generate PDF from Contract.
  • Fixed: Allow users to download files only by hash instead of direct id.
  • Added: Support for SHA1 as allowed mysql function.
Location:
trunk
Files:
3 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/Application/DefaultConfig.php

    r897 r901  
    5353        array('Name' => 'MainRouter/ConnectTimeout', 'Type' => 'Integer', 'Default' => '5', 'Title' => 'Vypršení času'),
    5454        array('Name' => 'MainRouter/MangleRuleSubgroupMinPrefix', 'Type' => 'Integer', 'Default' => '28', 'Title' => 'Nejmenší prefix podsítě pro mangle pravidla'),
     55        array('Name' => 'Contract/DirectoryId', 'Type' => 'Integer', 'Default' => '19', 'Title' => 'Id adresáře souborů smluv'),
    5556    );
    5657  }
  • trunk/Application/UpdateTrace.php

    r890 r901  
    21342134  $Manager->Execute('ALTER TABLE `FinanceOperation` CHANGE `Value` `Value` FLOAT NOT NULL DEFAULT "0";');
    21352135  $Manager->Execute('ALTER TABLE `NetworkInterface` CHANGE `OnlineNotify` `OnlineNotify` INT(11) NOT NULL DEFAULT "0";');
     2136}
     2137
     2138function UpdateTo901(UpdateManager $Manager): void
     2139{
     2140  $Manager->Execute('ALTER TABLE `Member` ADD `Contract` INT NULL DEFAULT NULL AFTER `ChangeReplaceId`;');
     2141  $Manager->Execute('ALTER TABLE `Member` ADD FOREIGN KEY (`Contract`) REFERENCES `Contract`(`Id`) ON DELETE RESTRICT ON UPDATE RESTRICT;');
     2142  $Manager->Execute("INSERT INTO `Module` (`Id`, `Name`, `Title`, `Version`, `Creator`, `License`, `Installed`, `HomePage`, `Description`) VALUES (NULL, 'Contract', '', '', '', '', '0', '', '');");
     2143  $Manager->Execute("INSERT INTO `Module` (`Id`, `Name`, `Title`, `Version`, `Creator`, `License`, `Installed`, `HomePage`, `Description`) VALUES (NULL, 'Document', '', '', '', '', '0', '', '');");
     2144  $Manager->Execute("INSERT INTO `PermissionOperation` (`Id`, `Module`, `Operation`, `Item`, `ItemId`) VALUES (NULL, '1', 'DisplayCustomerDocuments', '', '0');");
     2145  $Manager->Execute("INSERT INTO `PermissionGroupAssignment` (`Id`, `Group`, `AssignedGroup`, `AssignedOperation`) VALUES (NULL, '3', NULL, '52');");
     2146  $Manager->Execute('ALTER TABLE `File` ADD `Hash` VARCHAR(255) NOT NULL AFTER `Time`;');
     2147  $Manager->Execute("UPDATE `File` SET `Hash` = SHA1(CONCAT(Id,Name,Size,Time))");
     2148  $Manager->Execute("ALTER TABLE `Contract` ADD `Generate` INT NOT NULL DEFAULT '0' AFTER `File`;");
     2149  $Manager->Execute("ALTER TABLE `Contract` DROP `BillCodeText`;");
     2150  $Manager->Execute("INSERT INTO `FileDirectory` (`Id`, `Name`, `Parent`) VALUES (NULL, 'smlouvy', NULL);");
     2151  $Manager->Execute("ALTER TABLE `Log` CHANGE `Value` `Value` MEDIUMTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;");
     2152  $Manager->Execute("INSERT INTO `PermissionOperation` (`Id`, `Module`, `Operation`, `Item`, `ItemId`) VALUES (NULL, '4', 'DownloadById', '', '0');");
     2153  $Manager->Execute("INSERT INTO `PermissionGroupAssignment` (`Id`, `Group`, `AssignedGroup`, `AssignedOperation`) VALUES (NULL, '4', NULL, '53');");
    21362154}
    21372155
     
    22402258      880 => array('Revision' => 882, 'Function' => 'UpdateTo882'),
    22412259      882 => array('Revision' => 885, 'Function' => 'UpdateTo885'),
     2260      885 => array('Revision' => 901, 'Function' => 'UpdateTo901'),
    22422261    );
    22432262  }
  • trunk/Application/Version.php

    r899 r901  
    11<?php
    22
    3 $Revision = 899; // Subversion revision
    4 $DatabaseRevision = 885; // SQL structure revision
     3$Revision = 901; // Subversion revision
     4$DatabaseRevision = 901; // SQL structure revision
    55$ReleaseTime = strtotime('2021-02-17');
  • trunk/Modules/Customer/Customer.php

    r899 r901  
    3737        'SupportActivity' => array('Type' => 'TSupportActivityListCustomer', 'Caption' => 'Zákaznická podpora', 'Default' => ''),
    3838        'Consumption' => array('Type' => 'TCustomerStockSerialNumber', 'Caption' => 'Spotřeba zařízení', 'Default' => ''),
     39        'Contract' => array('Type' => 'TContract', 'Caption' => 'Smlouva', 'Default' => '', 'Null' => true),
    3940        'ChangeAction' => array('Type' => 'TActionEnum', 'Caption' => 'Změna - akce', 'Default' => '', 'Null' => true),
    4041        'ChangeTime' => array('Type' => 'DateTime', 'Caption' => 'Změna - čas', 'Default' => '', 'Null' => true, 'NotInList' => true),
     
    196197      ),
    197198    ));
     199    $this->System->FormManager->RegisterFormType('TCustomerListContract', array(
     200      'Type' => 'ManyToOne',
     201      'Table' => 'Member',
     202      'Id' => 'Id',
     203      'Ref' => 'Contract',
     204      'Filter' => '1',
     205    ));
     206
     207    $this->System->RegisterPage(['user', 'dokumenty'], 'PageCustomerDocuments');
    198208
    199209    ModuleIS::Cast(Core::Cast($this->System)->GetModule('IS'))->RegisterDashboardItem('Customer',
     
    211221    $Output .= ' platících:'.$DbRow['0'].'<br/>';
    212222
     223    return $Output;
     224  }
     225}
     226
     227class PageCustomerDocuments extends Page
     228{
     229  function __construct(System $System)
     230  {
     231    parent::__construct($System);
     232    $this->FullTitle = 'Dokumenty klienta';
     233    $this->ShortTitle = 'Dokumenty';
     234    $this->ParentClass = 'PageUser';
     235  }
     236
     237  function Show(): string
     238  {
     239    $Output = '<br/><div><strong>Dostupné dokumenty:</strong></div><br/>';
     240
     241    $User = &ModuleUser::Cast($this->System->GetModule('User'))->User;
     242
     243    // Determine which customer should be displayed
     244    if (array_key_exists('i', $_GET))
     245    {
     246      if (!$User->CheckPermission('Finance', 'Manage')) return 'Nemáte oprávnění';
     247      $CustomerId = $_GET['i'];
     248    } else
     249    {
     250      if (!$User->CheckPermission('Customer', 'DisplayCustomerDocuments')) return 'Nemáte oprávnění';
     251      $UserId = ModuleUser::Cast($this->System->GetModule('User'))->User->User['Id'];
     252      $DbResult = $this->Database->query('SELECT `Customer` FROM `UserCustomerRel` WHERE `User`='.$UserId.' LIMIT 1');
     253      if ($DbResult->num_rows > 0)
     254      {
     255        $CustomerUserRel = $DbResult->fetch_assoc();
     256        $CustomerId = $CustomerUserRel['Customer'];
     257      } else return $this->SystemMessage('Chyba', 'Nejste zákazníkem');
     258    }
     259
     260    // Load customer info
     261    $DbResult = $this->Database->query('SELECT * FROM `Member` WHERE `Id`='.$CustomerId);
     262    if ($DbResult->num_rows == 1)
     263    {
     264      $Customer = $DbResult->fetch_assoc();
     265    } else return $this->SystemMessage('Položka nenalezena', 'Zákazník nenalezen');
     266
     267    if ($Customer['Contract'] != '')
     268    {
     269      $DbResult = $this->Database->query('SELECT Contract.*, File.Hash AS FileHash, DocumentLineCode.Name AS BillCodeText FROM Contract '.
     270        'LEFT JOIN File ON File.Id=Contract.File '.
     271        'LEFT JOIN DocumentLineCode ON DocumentLineCode.Id=Contract.BillCode '.
     272        'WHERE (Contract.Id='.$Customer['Contract'].')');
     273      if ($DbResult->num_rows > 0)
     274      {
     275        $Contract = $DbResult->fetch_assoc();
     276        if ($Contract['File'] > 0) $Output .= 'Smlouva: <a href="'.$this->System->Link('/file?h='.$Contract['FileHash']).'">'.$Contract['BillCodeText'].'</a><br/>';
     277          else $Output .= 'Smlouva: '.$Contract['BillCodeText'].'<br/>';
     278        $Output .= 'Všeobecné smluvní podmínky: <a href="http://www.zdechov.net/docs/V%C5%A1eobecn%C3%A9%20smluvn%C3%AD%20podm%C3%ADnky.pdf">PDF</a><br/>';
     279      }
     280    }
    213281    return $Output;
    214282  }
  • trunk/Modules/Document/Document.php

    r899 r901  
    8080    ));
    8181  }
     82
     83  static function Cast(Module $Module): ModuleDocument
     84  {
     85    if ($Module instanceof ModuleDocument)
     86    {
     87      return $Module;
     88    }
     89    throw new Exception('Expected ModuleDocument type but '.gettype($Module));
     90  }
     91
     92  function GetFinanceYear(int $Year): array
     93  {
     94    if ($Year == 0)
     95    {
     96      // Get latest year
     97      $DbResult = $this->Database->select('FinanceYear', '*', '1 ORDER BY `Year` DESC LIMIT 1');
     98    } else $DbResult = $this->Database->select('FinanceYear', '*', '`Year`='.$Year);
     99    if ($DbResult->num_rows == 0)
     100    {
     101            if ($Year == date('Y'))
     102            {
     103                    $this->CreateFinanceYear($Year);
     104        $DbResult = $this->Database->select('FinanceYear', '*', '`Year`='.$Year);
     105            } else throw new Exception('Rok '.$Year.' nenalezen');
     106          }
     107    $FinanceYear = $DbResult->fetch_assoc();
     108    if ($FinanceYear['Closed'] == 1)
     109      throw new Exception('Rok '.$FinanceYear['Year'].' je již uzavřen. Nelze do něj přidávat položky.');
     110    return $FinanceYear;
     111  }
     112
     113  function GetNextDocumentLineNumber(string $Id, int $FinanceYear = 0): string
     114  {
     115          $FinanceYear = $this->GetFinanceYear($FinanceYear);
     116
     117    $DbResult = $this->Database->query('SELECT `Shortcut`, `Id` FROM `DocumentLine` WHERE `Id`='.$Id);
     118    $DocumentLine = $DbResult->fetch_assoc();
     119
     120    $DbResult = $this->Database->query('SELECT * FROM `DocumentLineSequence` WHERE '.
     121      '`DocumentLine`='.$Id.' AND `FinanceYear`='.$FinanceYear['Id']);
     122    $Sequence = $DbResult->fetch_assoc();
     123
     124    if ($Sequence['YearPrefix'] == 1)
     125    {
     126      $Result = $DocumentLine['Shortcut'].$Sequence['NextNumber'].'/'.$FinanceYear['Year'];
     127    } else $Result = $DocumentLine['Shortcut'].$Sequence['NextNumber'];
     128
     129    $this->Database->query('UPDATE `DocumentLineSequence` SET `NextNumber` = `NextNumber` + 1 '.
     130      'WHERE (`DocumentLine`='.$Id.') AND (`FinanceYear`='.$FinanceYear['Id'].')');
     131    return $Result;
     132  }
     133
     134  function GetNextDocumentLineNumberId(string $Id, int $FinanceYear = 0): int
     135  {
     136    $Code = $this->GetNextDocumentLineNumber($Id, $FinanceYear);
     137    $this->Database->insert('DocumentLineCode', array('DocumentLine' => $Id, 'Name' => $Code));
     138    return $this->Database->insert_id;
     139  }
     140
     141  function CreateFinanceYear(int $Year)
     142  {
     143    $StartTime = mktime(0, 0, 0, 1, 1, $Year);
     144    $EndTime = mktime(0, 0, 0, 12, 31, $Year);
     145    $this->Database->insert('FinanceYear', array('Year' => $Year,
     146            'DateStart' => TimeToMysqlDate($StartTime), 'DateEnd' => TimeToMysqlDate($EndTime), 'Closed' => 0));
     147          $YearId = $this->Database->insert_id;
     148
     149    // Create DocumentLineSequence from previous
     150    $DbResult = $this->Database->select('DocumentLine', 'Id', '`Yearly` = 1');
     151    while ($DbRow = $DbResult->fetch_assoc())
     152    {
     153            $this->Database->insert('DocumentLineSequence', array('FinanceYear' => $YearId,
     154              'NextNumber' => 1, 'YearPrefix' => 1, 'DocumentLine' => $DbRow['Id']));
     155          }
     156  }
    82157}
    83158
  • trunk/Modules/Employee/Employee.php

    r899 r901  
    8383      'Filter' => '1',
    8484    ));
     85    $this->System->FormManager->RegisterFormType('TEmployeeSalaryListContract', array(
     86      'Type' => 'ManyToOne',
     87      'Table' => 'EmployeeSalary',
     88      'Id' => 'Id',
     89      'Ref' => 'Contract',
     90      'Filter' => '1',
     91    ));
    8592  }
    8693}
  • trunk/Modules/File/File.php

    r899 r901  
    2020    $Desc->AddReference('Directory', FileDirectory::GetClassName(), true);
    2121    $Desc->AddDateTime('Time');
     22    $Desc->AddString('Hash');
     23    $Desc->AddBoolean('Generate');
    2224    return $Desc;
    2325  }
     
    5961  }
    6062
    61   function Download(string $Id): void
    62   {
    63     $DbResult = $this->Database->select('File', '*', 'Id='.addslashes($Id));
     63  function DownloadHash(string $Hash): void
     64  {
     65    $this->Download('Hash="'.addslashes($Hash).'"');
     66  }
     67
     68  function DownloadId(string $Id): void
     69  {
     70    if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('File', 'DownloadById'))
     71      echo('Nemáte oprávnění');
     72    $this->Download('Id='.addslashes($Id));
     73  }
     74
     75  function Download(string $Where): void
     76  {
     77    $DbResult = $this->Database->select('File', '*', $Where);
    6478    if ($DbResult->num_rows > 0)
    6579    {
     
    105119  function Show(): string
    106120  {
    107     if (array_key_exists('id', $_GET)) $Id = $_GET['id'];
    108     else if (array_key_exists('i', $_GET)) $Id = $_GET['i'];
     121    if (array_key_exists('h', $_GET))
     122    {
     123      $Hash = $_GET['h'];
     124      $this->ClearPage = true;
     125      ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadHash($Hash);
     126      return '';
     127    }
     128    else if (array_key_exists('i', $_GET))
     129    {
     130      $Id = $_GET['i'] * 1;
     131      $this->ClearPage = true;
     132      ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadId($Id);
     133    }
    109134    else return $this->SystemMessage('Chyba', 'Nezadáno id souboru');
    110     $this->ClearPage = true;
    111     $Output = ModuleFile::Cast($this->System->GetModule('File'))->File->Download($Id);
    112     return $Output;
     135    return '';
    113136  }
    114137}
     
    208231        'Size' => array('Type' => 'Integer', 'Caption' => 'Velikost', 'Default' => ''),
    209232        'Time' => array('Type' => 'DateTime', 'Caption' => 'Čas vytvoření', 'Default' => ''),
     233        'Hash' => array('Type' => 'String', 'Caption' => 'Haš', 'Default' => ''),
    210234        'Invoices' => array('Type' => 'TFinanceInvoiceListFile', 'Caption' => 'Faktury', 'Default' => ''),
    211235        'Operations' => array('Type' => 'TFinanceOperationListFile', 'Caption' => 'Operace', 'Default' => ''),
  • trunk/Modules/Finance/Bill.php

    r888 r901  
    11<?php
    22
    3 class Bill extends Model
     3class Bill extends Pdf
    44{
    55  public int $SpecificSymbol = 1; // computer network number
    6   public bool $Checked = false;
    7 
    8   function GenerateHTML(): string
    9   {
    10     return '';
    11   }
    12 
    13   function SaveToFile(string $FileName): void
    14   {
    15     $PdfData = $this->HtmlToPdf($this->GenerateHTML());
    16     file_put_contents($FileName, $PdfData);
    17   }
    18 
    19   function HtmlToPdf(string $HtmlCode): string
    20   {
    21     $Encoding = new Encoding();
    22     if ($this->Checked == false) {
    23       if (CommandExist('htmldoc')) {
    24         $this->Checked = true;
    25       } else throw new Exception('htmldoc is not installed.');
    26     }
    27     $Output = shell_exec('echo "'.addslashes($Encoding->FromUTF8($HtmlCode)).
    28       '"|htmldoc --no-numbered --webpage --no-embedfonts --charset 8859-2 -t pdf -');
    29     return $Output;
    30   }
    316}
    327
  • trunk/Modules/Finance/Finance.php

    r900 r901  
    2121    $this->License = 'GNU/GPLv3';
    2222    $this->Description = 'Base module for finance management';
    23     $this->Dependencies = array(ModuleFile::GetName(), ModuleEmailQueue::GetName(), ModuleSubject::GetName(), ModuleDocument::GetName());
     23    $this->Dependencies = array(ModuleFile::GetName(), ModuleEmailQueue::GetName(), ModuleSubject::GetName(),
     24      ModuleDocument::GetName());
    2425    $this->Models = array(FinanceBillingPeriod::GetClassName(), FinanceVatType::GetClassName(), FinanceVat::GetClassName(),
    2526      FinanceGroup::GetClassName(), FinanceOperationGroup::GetClassName(), FinanceOperation::GetClassName(),
     
    2728      Company::GetClassName(), FinanceTreasury::GetClassName(), FinanceTreasuryCheck::GetClassName(),
    2829      Currency::GetClassName(), FinanceBank::GetClassName(), FinanceBankAccount::GetClassName(), FinanceCharge::GetClassName(),
    29       Contract::GetClassName(), FinanceInvoiceOperationRel::GetClassName());
     30      FinanceInvoiceOperationRel::GetClassName());
    3031
    3132    $this->Bill = new Bill($this->System);
     
    423424        'Name' => array('Type' => 'String', 'Caption' => 'Název', 'Default' => ''),
    424425      ),
    425     ));
    426     $this->System->FormManager->RegisterClass('Contract', array(
    427       'Title' => 'Smlouvy',
    428       'Table' => 'Contract',
    429       'Items' => array(
    430         'DocumentLine' => array('Type' => 'TDocumentLine', 'Caption' => 'Dokladová řada', 'Default' => ''),
    431         'BillCode' => array('Type' => 'TDocumentLineCode', 'Caption' => 'Kód', 'Default' => '', 'Null' => true),
    432         'Subject' => array('Type' => 'TSubject', 'Caption' => 'Subjekt', 'Default' => ''),
    433         'ValidFrom' => array('Type' => 'Date', 'Caption' => 'Platnost od', 'Default' => ''),
    434         'ValidTo' => array('Type' => 'Date', 'Caption' => 'Platnost do', 'Default' => '', 'Null' => true),
    435         'File' => array('Type' => 'TFile', 'Caption' => 'Soubor', 'Default' => '', 'Null' => true),
    436       ),
    437       'BeforeInsert' => array($this, 'BeforeInsertContract'),
    438     ));
    439     $this->System->FormManager->RegisterFormType('TContract', array(
    440       'Type' => 'Reference',
    441       'Table' => 'Contract',
    442       'Id' => 'Id',
    443       'Name' => 'BillCode',
    444       'Filter' => '1',
    445426    ));
    446427    $this->System->FormManager->RegisterFormType('TFinanceVAT', array(
     
    541522  }
    542523
    543   function DoStop(): void
    544   {
    545   }
    546 
    547524  function BeforeInsertFinanceOperation(Form $Form): array
    548525  {
     
    550527      else $Year = date("Y", $Form->Values['ValidFrom']);
    551528    $FinanceGroup = $this->Finance->GetFinanceGroupById($Form->Values['Group'], 'FinanceOperationGroup');
    552     $Form->Values['BillCode'] = $this->Finance->GetNextDocumentLineNumberId($FinanceGroup['DocumentLine'], $Year);
     529    $Form->Values['BillCode'] = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($FinanceGroup['DocumentLine'], $Year);
    553530    return $Form->Values;
    554531  }
     
    576553      else $Year = date("Y", $Form->Values['ValidFrom']);
    577554    $Group = $this->Finance->GetFinanceGroupById($Form->Values['Group'], 'FinanceInvoiceGroup');
    578     $Form->Values['BillCode'] = $this->Finance->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
     555    $Form->Values['BillCode'] = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
    579556    return $Form->Values;
    580557  }
     
    621598  }
    622599
    623   function BeforeInsertContract(Form $Form): array
    624   {
    625     if (array_key_exists('Time', $Form->Values)) $Year = date("Y", $Form->Values['Time']);
    626       else $Year = date("Y", $Form->Values['ValidFrom']);
    627     $Form->Values['BillCode'] = $this->Finance->GetNextDocumentLineNumberId($Form->Values['DocumentLine'], $Year);
    628     return $Form->Values;
    629   }
    630 
    631600  static function Cast(Module $Module): ModuleFinance
    632601  {
  • trunk/Modules/Finance/FinanceModels.php

    r899 r901  
    7777  }
    7878
    79   function CreateFinanceYear(int $Year)
    80   {
    81     $StartTime = mktime(0, 0, 0, 1, 1, $Year);
    82     $EndTime = mktime(0, 0, 0, 12, 31, $Year);
    83     $this->Database->insert('FinanceYear', array('Year' => $Year,
    84             'DateStart' => TimeToMysqlDate($StartTime), 'DateEnd' => TimeToMysqlDate($EndTime), 'Closed' => 0));
    85           $YearId = $this->Database->insert_id;
    86 
    87     // Create DocumentLineSequence from previous
    88     $DbResult = $this->Database->select('DocumentLine', 'Id', '`Yearly` = 1');
    89     while ($DbRow = $DbResult->fetch_assoc())
     79  function GetFinanceGroupById(string $Id, string $Table): ?array
     80  {
     81    $DbResult = $this->Database->query('SELECT * FROM `'.$Table.'` WHERE `Id`= '.$Id);
     82    if ($DbResult->num_rows == 1)
    9083    {
    91             $this->Database->insert('DocumentLineSequence', array('FinanceYear' => $YearId,
    92               'NextNumber' => 1, 'YearPrefix' => 1, 'DocumentLine' => $DbRow['Id']));
    93           }
    94   }
    95 
    96   function GetFinanceYear(int $Year): array
    97   {
    98     if ($Year == 0)
    99     {
    100       // Get latest year
    101       $DbResult = $this->Database->select('FinanceYear', '*', '1 ORDER BY `Year` DESC LIMIT 1');
    102     } else $DbResult = $this->Database->select('FinanceYear', '*', '`Year`='.$Year);
    103     if ($DbResult->num_rows == 0)
    104     {
    105             if ($Year == date('Y'))
    106             {
    107                     $this->CreateFinanceYear($Year);
    108         $DbResult = $this->Database->select('FinanceYear', '*', '`Year`='.$Year);
    109             } else throw new Exception('Rok '.$Year.' nenalezen');
    110           }
    111     $FinanceYear = $DbResult->fetch_assoc();
    112     if ($FinanceYear['Closed'] == 1)
    113       throw new Exception('Rok '.$FinanceYear['Year'].' je již uzavřen. Nelze do něj přidávat položky.');
    114     return $FinanceYear;
    115   }
    116 
    117   function GetNextDocumentLineNumber(string $Id, int $FinanceYear = 0): string
    118   {
    119           $FinanceYear = $this->GetFinanceYear($FinanceYear);
    120 
    121     $DbResult = $this->Database->query('SELECT `Shortcut`, `Id` FROM `DocumentLine` WHERE `Id`='.$Id);
    122     $DocumentLine = $DbResult->fetch_assoc();
    123 
    124     $DbResult = $this->Database->query('SELECT * FROM `DocumentLineSequence` WHERE '.
    125       '`DocumentLine`='.$Id.' AND `FinanceYear`='.$FinanceYear['Id']);
    126     $Sequence = $DbResult->fetch_assoc();
    127 
    128     if ($Sequence['YearPrefix'] == 1)
    129     {
    130       $Result = $DocumentLine['Shortcut'].$Sequence['NextNumber'].'/'.$FinanceYear['Year'];
    131     } else $Result = $DocumentLine['Shortcut'].$Sequence['NextNumber'];
    132 
    133     $this->Database->query('UPDATE `DocumentLineSequence` SET `NextNumber` = `NextNumber` + 1 '.
    134       'WHERE (`DocumentLine`='.$Id.') AND (`FinanceYear`='.$FinanceYear['Id'].')');
    135     return $Result;
    136   }
    137 
    138   function GetNextDocumentLineNumberId(string $Id, int $FinanceYear = 0): int
    139   {
    140     $Code = $this->GetNextDocumentLineNumber($Id, $FinanceYear);
    141     $this->Database->insert('DocumentLineCode', array('DocumentLine' => $Id, 'Name' => $Code));
    142     return $this->Database->insert_id;
    143   }
    144 
    145   function GetFinanceGroupById(string $Id, string $Table): ?array
    146   {
    147     $DbResult = $this->Database->query('SELECT * FROM `'.$Table.'` WHERE `Id`= '.$Id);
    148     if ($DbResult->num_rows == 1) {
    14984      $Group = $DbResult->fetch_assoc();
    15085      return $Group;
     
    443378}
    444379
    445 class Contract extends Model
    446 {
    447   static function GetModelDesc(): ModelDesc
    448   {
    449     $Desc = new ModelDesc(self::GetClassName());
    450     $Desc->AddReference('DocumentLine', DocumentLine::GetClassName());
    451     $Desc->AddReference('BillCode', DocumentLineCode::GetClassName());
    452     $Desc->AddReference('Subject', Subject::GetClassName());
    453     $Desc->AddDate('ValidFrom');
    454     $Desc->AddDate('ValidTo');
    455     $Desc->AddReference('File', File::GetClassName());
    456     return $Desc;
    457   }
    458 }
    459 
    460380class FinanceBillingPeriod extends Model
    461381{
  • trunk/Modules/Finance/Import.php

    r888 r901  
    131131  {
    132132    $Year = date('Y', $Time);
    133     $BillCode = ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
     133    $BillCode = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
    134134    // TODO: Fixed BankAccount=1, allow to select bank account for import
    135135    $this->Database->insert('FinanceOperation', array('Text' => $Text,
  • trunk/Modules/Finance/Manage.php

    r887 r901  
    135135
    136136    $Year = date('Y', $TimeCreation);
    137     $BillCode = $Finance->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
     137    $BillCode = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
    138138    $SumValue = 0;
    139139    foreach ($Items as $Item) {
     
    377377      $Title = 'Pravidelné vyúčtování služeb';
    378378      $Content = 'Vyúčtovaní zákazníka <strong>'.$Subject['Name'].'</strong> zastoupeného uživatelem <strong>'.
    379         $User['Name'].'</strong> ke dni <strong>'.$this->System->HumanDate(time()).'</strong>.<br/><br/>'."\n".
     379        $User['Name'].'</strong> ke dni <strong>'.Core::Cast($this->System)->HumanDate(time()).'</strong>.<br/><br/>'."\n".
    380380        'Vaše aktuální služby: ';
    381381      $DbResult = $this->Database->query('SELECT GROUP_CONCAT(`Service`.`Name`) AS `Name` FROM `ServiceCustomerRel` LEFT JOIN `Service` '.
     
    441441      if (file_exists($FullFileName))
    442442      {
    443         $this->Database->update('File', 'Id='.$FileId, array('Name' => $FileName, 'Size' => filesize($FullFileName)));
     443        $this->Database->update('File', 'Id='.$FileId, array('Name' => $FileName, 'Size' => filesize($FullFileName), 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))'));
    444444        $this->Database->update('FinanceInvoice', 'Id='.$Row['Id'], array('File' => $FileId));
    445445        $Output .= 'Faktura '.$Row['Id'].' vygenerována do souboru '.$FileName.'<br/>'."\n";
     
    472472      if (file_exists($FullFileName))
    473473      {
    474         $this->Database->update('File', 'Id='.$FileId, array('Name' => $FileName, 'Size' => filesize($FullFileName)));
     474        $this->Database->update('File', 'Id='.$FileId, array('Name' => $FileName, 'Size' => filesize($FullFileName), 'Hash' => 'SHA1(CONCAT(Id,Name,Size,Time))'));
    475475        $this->Database->update('FinanceOperation', 'Id='.$Row['Id'], array('File' => $FileId));
    476476        $Output .= 'Doklad pro platbu '.$Row['Id'].' vygenerován do souboru '.$FileName.'<br/>'."\n";
  • trunk/Modules/Finance/UserState.php

    r888 r901  
    1111  }
    1212
    13   function ShowFinanceOperation(int $Subject): string
     13  function ShowFinanceOperation(int $SubjectId): string
    1414  {
    15     $UserOperationTableQuery = '((SELECT `Text`, `Time`, `Value`, `File`, `BillCode`, NULL AS `PeriodFrom`, NULL AS `PeriodTo`, `DocumentLineCode`.`Name` AS `BillName` '.
     15    $UserOperationTableQuery = '((SELECT `Text`, `FinanceOperation`.`Time`, `Value`, `File`.`Hash` AS `FileHash`, `BillCode`, NULL AS `PeriodFrom`, NULL AS `PeriodTo`, `DocumentLineCode`.`Name` AS `BillName` '.
    1616      'FROM `FinanceOperation` '.
    1717      'LEFT JOIN `DocumentLineCode` ON `DocumentLineCode`.`Id`=`FinanceOperation`.`BillCode` '.
    18       'WHERE (`Subject`='.$Subject['Id'].') '.
     18      'LEFT JOIN `File` ON `File`.`Id`=`FinanceOperation`.`File` '.
     19      'WHERE (`Subject`='.$SubjectId.') '.
    1920      ') UNION ALL '.
    2021      '(SELECT (SELECT GROUP_CONCAT(`Description` SEPARATOR ",") FROM `FinanceInvoiceItem` WHERE `FinanceInvoice`=`FinanceInvoice`.`Id`) AS `Text`, '.
    21       '`Time`, -`Value`, `File`, `BillCode`, `PeriodFrom`, `PeriodTo`, `DocumentLineCode`.`Name` AS `BillName` FROM `FinanceInvoice` '.
     22      '`FinanceInvoice`.`Time`, -`Value`, `File`.`Hash` AS `FileHash`, `BillCode`, `PeriodFrom`, `PeriodTo`, `DocumentLineCode`.`Name` AS `BillName` '.
     23      'FROM `FinanceInvoice` '.
    2224      'LEFT JOIN `DocumentLineCode` ON `DocumentLineCode`.`Id`=`FinanceInvoice`.`BillCode` '.
    23       'WHERE (`Subject`='.$Subject['Id'].') AND (`VisibleToUser` = 1)))';
     25      'LEFT JOIN `File` ON `File`.`Id`=`FinanceInvoice`.`File` '.
     26      'WHERE (`Subject`='.$SubjectId.') AND (`VisibleToUser` = 1)))';
    2427
    2528    $Output = '<div style="text-align:center">Výpis finančních operací</div>';
     
    5659      if ($Row['Value'] > 0) $Row['Value'] = '+'.$Row['Value'];
    5760      if ($Row['BillName'] == '') $Row['BillName'] = 'PDF';
    58       if ($Row['File'] > 0) $Invoice = '<a href="'.$this->System->Link('/file?id='.$Row['File']).'">'.$Row['BillName'].'</a>';
     61      if ($Row['FileHash'] != '') $Invoice = '<a href="'.$this->System->Link('/file?h='.$Row['FileHash']).'">'.$Row['BillName'].'</a>';
    5962        else $Invoice = NotBlank($Row['BillName']);
    6063      if ($Row['PeriodFrom'] != '') $Period = HumanDate($Row['PeriodFrom']).' - '.HumanDate($Row['PeriodTo']);
     
    102105    } else return $this->SystemMessage('Položka nenalezena', 'Zákazník nenalezen');
    103106
    104 
    105107    // Load subject info
    106108    $DbResult = $this->Database->query('SELECT * FROM `Subject` WHERE `Id`='.$Customer['Subject']);
     
    109111      $Subject = $DbResult->fetch_assoc();
    110112    } else return $this->SystemMessage('Položka nenalezena', 'Subjekt nenalezen');
    111 
    112113
    113114    $Output = '<table width="100%" border="0" cellspacing="0" cellpadding="3"><tr><td valign="top">';
     
    124125
    125126    // Tabulka operaci
    126     $Output .= $this->ShowFinanceOperation($Subject);
     127    $Output .= $this->ShowFinanceOperation($Subject['Id']);
    127128
    128129    $Output .= '</td><td valign="top">';
  • trunk/Modules/FinanceBankAPI/FileImport.php

    r899 r901  
    4444          }
    4545          $Year = date('Y', MysqlDateToTime($DbRow['Time']));
    46           $BillCode = $Finance->GetNextDocumentLineNumberId($FinanceGroup['DocumentLine'], $Year);
     46          $BillCode = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($FinanceGroup['DocumentLine'], $Year);
    4747          $this->Database->insert('FinanceOperation', array('Subject' => $DbRow2['Id'], 'Cash' => 0,
    4848            'ValueUser' => Abs($DbRow['Value']), 'Value' => 0, 'Taxable' => 1, 'BankAccount' => $DbRow['BankAccount'], 'Network' => 1,
     
    171171  {
    172172    $Year = date('Y', $Time);
    173     $BillCode = ModuleFinance::Cast($this->System->GetModule('Finance'))->Finance->GetNextDocumentLineNumberId(
     173    $BillCode = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId(
    174174      $Group['DocumentLine'], $Year);
    175175    $this->Database->insert('FinanceOperation', array('Text' => $Text,
  • trunk/Modules/FinanceBankAPI/FinanceBankAPI.php

    r899 r901  
    3737    $this->License = 'GNU/GPLv3';
    3838    $this->Description = 'Communication through API to various banks, manual file import';
    39     $this->Dependencies = array(ModuleFinance::GetName(), ModuleScheduler::GetName(), ModuleIS::GetName());
     39    $this->Dependencies = array(ModuleFinance::GetName(), ModuleScheduler::GetName(), ModuleIS::GetName(),
     40      ModuleDocument::GetName());
    4041    $this->Models = array(FinanceBankImport::GetClassName());
    4142  }
  • trunk/Modules/OpeningHours/OpeningHours.php

    r899 r901  
    4343    if (ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('OpeningHours', 'Edit'))
    4444    {
    45       $Output = '<div class="Centred">';
     45      $Output = '<div class="Centered">';
    4646      $DbResult = $this->Database->select('Subject', 'Name', 'Id='.$Id);
    4747      $DbRow = $DbResult->fetch_assoc();
     
    119119  function ShowAll(): string
    120120  {
    121     $Output = '<div class="Centred">';
    122     $DbResult = $this->Database->query('SELECT SubjectOpenTime.*, DATE_FORMAT(SubjectOpenTime.UpdateTime, "%e.%c.%Y") as UpdateTime, Subject.Id, Subject.Name as Name FROM SubjectOpenTime JOIN Subject ON Subject.Id = SubjectOpenTime.Subject ORDER BY Name');
     121    $Output = '<div class="Centered">';
     122    $DbResult = $this->Database->query('SELECT SubjectOpenTime.*, DATE_FORMAT(SubjectOpenTime.UpdateTime, "%e.%c.%Y") as UpdateTime, '.
     123      'Subject.Id, Subject.Name as Name FROM SubjectOpenTime '.
     124      'JOIN Subject ON Subject.Id = SubjectOpenTime.Subject ORDER BY Name');
    123125    while ($Subject = $DbResult->fetch_assoc())
    124126    {
     
    190192      if ($Subject['Notice'] != '') $Output .= 'Poznámka: '.$Subject['Notice'].'<br />';
    191193
    192       if ($Subject['Photo'] != 0) $Output .= '<a href="file?id='.$Subject['Photo'].'">Fotka</a> ';
     194      if ($Subject['Photo'] != 0) $Output .= '<a href="file?i='.$Subject['Photo'].'">Fotka</a> ';
    193195
    194196      if (ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('SubjectOpenTime', 'Edit'))
  • trunk/Modules/Portal/Portal.php

    r900 r901  
    165165    if ($User->CheckPermission('Finance', 'DisplaySubjectState'))
    166166      $Output .= '<a href="'.$this->System->Link('/finance/platby/').'">Finance</a><br />';
     167    if ($User->CheckPermission('Customer', 'DisplayCustomerDocuments'))
     168      $Output .= '<a href="'.$this->System->Link('/user/dokumenty/').'">Dokumenty</a><br />';
    167169    if ($User->CheckPermission('Network', 'RegistredHostList'))
    168170      $Output .= '<a href="'.$this->System->Link('/network/user-hosts/').'">Počítače</a><br />';
  • trunk/Modules/Stock/Stock.php

    r899 r901  
    1111    $this->License = 'GNU/GPLv3';
    1212    $this->Description = 'Stock and products';
    13     $this->Dependencies = array(ModuleUser::GetName(), ModuleCustomer::GetName(), ModuleNetwork::GetName());
     13    $this->Dependencies = array(ModuleUser::GetName(), ModuleCustomer::GetName(), ModuleNetwork::GetName(),
     14      ModuleDocument::GetName());
    1415    $this->Models = array(Product::GetClassName(), StockSerialNumber::GetClassName(), Stock::GetClassName(),
    1516      StockMoveGroup::GetClassName(), StockMove::GetClassName(), StockMoveItem::GetClassName(),
     
    255256      else $Year = date("Y", $Form->Values['ValidFrom']);
    256257    $Group = $Finance->GetFinanceGroupById($Form->Values['Group'], 'StockMoveGroup');
    257     $Form->Values['BillCode'] = $Finance->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
     258    $Form->Values['BillCode'] = ModuleDocument::Cast($this->System->GetModule('Document'))->GetNextDocumentLineNumberId($Group['DocumentLine'], $Year);
    258259    return $Form->Values;
    259260  }
  • trunk/Modules/Subject/Subject.php

    r899 r901  
    4343          'WHERE `FinanceInvoice`.`Subject`=#Id), 0))'),
    4444        'BankAccounts' => array('Type' => 'TFinanceBankAccountListSubject', 'Caption' => 'Bankovní účty', 'Default' => ''),
     45        'Contracts' => array('Type' => 'TContractListSubject', 'Caption' => 'Smlouvy', 'Default' => ''),
    4546      ),
    4647    ));
     
    4849      'Type' => 'ManyToOne',
    4950      'Table' => 'FinanceBankAccount',
     51      'Id' => 'Id',
     52      'Ref' => 'Subject',
     53      'Filter' => '1',
     54    ));
     55    $this->System->FormManager->RegisterFormType('TContractListSubject', array(
     56      'Type' => 'ManyToOne',
     57      'Table' => 'Contract',
    5058      'Id' => 'Id',
    5159      'Ref' => 'Subject',
  • trunk/Modules/User/UserPage.php

    r895 r901  
    7373        } else $Actions .= call_user_func($Action).'<br/>';
    7474      }
    75       $Output .= '<div class="Centred"><table id="MainTable"><tr><td style="vertical-align:top;">';
     75      $Output .= '<div class="Centered"><table id="MainTable"><tr><td style="vertical-align:top;">';
    7676      $Output .= $this->Panel('Nabídka uživatele', $Actions);
    7777      $Output .= '</td><td style="vertical-align:top;">';
     
    106106        $Form->OnSubmit = '?Action=Login';
    107107        $Output .= $Form->ShowEditForm();
    108         $Output .= '<div class="Centred"><a href="?Action=UserRegister">Registrovat se</a> '.
     108        $Output .= '<div class="Centered"><a href="?Action=UserRegister">Registrovat se</a> '.
    109109        '<a href="?Action=PasswordRecovery">Obnova zapomenutého hesla</a></div>';
    110110      } else
     
    125125            $Form->Values['Password'] = '';
    126126            $Output .= $Form->ShowEditForm();
    127             $Output .= '<div class="Centred"><a href="?Action=UserRegister">Registrovat se</a> '.
     127            $Output .= '<div class="Centered"><a href="?Action=UserRegister">Registrovat se</a> '.
    128128              '<a href="?Action=PasswordRecovery">Obnova zapomenutého hesla</a></div>';
    129129          } else {
    130             //$Output .= '<div class="Centred">Za 5 sekund budete přesměrováni na <a href="?Action=UserMenu">nabídku uživatele</a></div>';
     130            //$Output .= '<div class="Centered">Za 5 sekund budete přesměrováni na <a href="?Action=UserMenu">nabídku uživatele</a></div>';
    131131            //Header('refresh:5;url=?Action=UserMenu');
    132132            Header('Location: ?Action=UserMenu');
  • trunk/Packages/Common/Common.php

    r899 r901  
    2727include_once(dirname(__FILE__).'/BigInt.php');
    2828include_once(dirname(__FILE__).'/Int128.php');
     29include_once(dirname(__FILE__).'/Pdf.php');
    2930include_once(dirname(__FILE__).'/Modules/Setup.php');
    3031include_once(dirname(__FILE__).'/Modules/ModuleManager.php');
  • trunk/Packages/Common/Database.php

    r900 r901  
    4949  {
    5050    $this->Prefix = '';
    51     $this->Functions = array('NOW()', 'CURDATE()', 'CURTIME()', 'UUID()');
     51    $this->Functions = array('NOW(', 'CURDATE(', 'CURTIME(', 'UUID(', 'SHA1(');
    5252    $this->Type = 'mysql';  // mysql, pgsql
    5353    $this->Error = '';
     
    141141  }
    142142
     143  function IsFunction(string $Text): bool
     144  {
     145    $Pos = strpos($Text, '(');
     146    return ($Pos !== false) && in_array(substr($Text, 0, $Pos + 1), $this->Functions);
     147  }
     148
    143149  function GetInsert(string $Table, array $Data): string
    144150  {
     
    148154    {
    149155      $Name .= ',`'.$Key.'`';
    150       if (!in_array($Value, $this->Functions))
     156      if (is_null($Value)) $Value = 'NULL';
     157      else if (!$this->IsFunction($Value))
    151158      {
    152         if (is_null($Value)) $Value = 'NULL';
    153         else $Value = $this->PDO->quote($Value);
     159        $Value = $this->PDO->quote($Value);
    154160      }
    155161      $Values .= ','.$Value;
     
    170176    foreach ($Data as $Key => $Value)
    171177    {
    172       if (!in_array($Value, $this->Functions))
     178      if (is_null($Value)) $Value = 'NULL';
     179      else if (!$this->IsFunction($Value))
    173180      {
    174         if (is_null($Value)) $Value = 'NULL';
    175         else $Value = $this->PDO->quote($Value);
     181        $Value = $this->PDO->quote($Value);
    176182      }
    177183      $Values .= ', `'.$Key.'`='.$Value;
     
    187193    foreach ($Data as $Key => $Value)
    188194    {
    189       if (!in_array($Value, $this->Functions))
     195      if (is_null($Value)) $Value = 'NULL';
     196      else if (!$this->IsFunction($Value))
    190197      {
    191         if (is_null($Value)) $Value = 'NULL';
    192         else $Value = $this->PDO->quote($Value);
     198        $Value = $this->PDO->quote($Value);
    193199      }
    194200      $Name .= ',`'.$Key.'`';
  • trunk/Packages/Common/Modules/Setup.php

    r900 r901  
    194194        {
    195195          $Output .= '<h3>Odinstalace vše</h3>';
    196           $this->System->ModuleManager->UninstallAll(array(ModuleCondition::System));
     196          $this->System->ModuleManager->UninstallAll(array(ModuleCondition::All));
    197197          $this->Database->query('DROP TABLE IF EXISTS `'.$this->UpdateManager->VersionTable.'`');
    198198          $Output .= $this->ControlPanel();
  • trunk/style/new/style.css

    r843 r901  
    77.ActionMenu
    88{
    9   text-align: center; 
    10   list-style: none; 
     9  text-align: center;
     10  list-style: none;
    1111  margin: 0px 0px 0px 0px;
    1212  padding: 0px 0px 0px 0px;
     
    1414
    1515.ActionMenu li
    16 {   
    17   display: inline;   
     16{
     17  display: inline;
    1818  padding-left: 4px;
    1919  padding-right: 4px;
     
    5757#Footer
    5858{
    59   border-style: solid; 
    60   border-top-color: gray; 
    61   border-width: 1px 0 0 0; 
    62   margin-top: 7px; 
     59  border-style: solid;
     60  border-top-color: gray;
     61  border-width: 1px 0 0 0;
     62  margin-top: 7px;
    6363  padding-top: 2px;
    6464  font-size: 10px;
     
    6868.Navigation
    6969{
    70   border-style: solid; 
    71   border-bottom-color: gray; 
    72   border-width: 0 0 1px 0; 
    73   margin-bottom: 3px; 
     70  border-style: solid;
     71  border-bottom-color: gray;
     72  border-width: 0 0 1px 0;
     73  margin-bottom: 3px;
    7474  padding-bottom: 2px;
    7575}
     
    8585.MainTitle
    8686{
    87   padding: 3px; 
    88   font-size: 20px; 
    89   border-style: solid; 
    90   border-color: blue; 
    91   border-width: 1px; 
    92   background-color: #F0F0FF; 
     87  padding: 3px;
     88  font-size: 20px;
     89  border-style: solid;
     90  border-color: blue;
     91  border-width: 1px;
     92  background-color: #F0F0FF;
    9393  margin-bottom: 4px;
    9494}
     
    9797{
    9898  margin: 2px 0px 2px 0px;
    99   padding: 2px 2px 2px 2px; 
    100   font-size: small; 
    101   border-style: solid; 
    102   border-color: red; 
     99  padding: 2px 2px 2px 2px;
     100  font-size: small;
     101  border-style: solid;
     102  border-color: red;
    103103  border-width: 0px;
    104104  background-color: #FFF0F0;
    105105  width: 100%;
    106   border-collapse: collapse; 
     106  border-collapse: collapse;
    107107}
    108108
     
    122122{
    123123  margin: 2px 2px 2px 2px;
    124   display: none; 
    125   border-width: 1px; 
    126   border-style: solid; 
    127   border-color: silver; 
     124  display: none;
     125  border-width: 1px;
     126  border-style: solid;
     127  border-color: silver;
    128128  background-color: white;
    129   padding: 3px; 
     129  padding: 3px;
    130130  font-size: 9pt;
    131131}
     
    135135  width: 100%;
    136136  border-width: 0px;
    137   font-size: small; 
     137  font-size: small;
    138138  padding-bottom: 5px;
    139139  margin-bottom: 5px;
     
    147147}
    148148
    149 .NewsItemFrame 
     149.NewsItemFrame
    150150{
    151151  border-collapse: collapse;
    152   padding: 0px; 
    153   margin: 2px 2px 2px 2px; 
    154   font-size: small; 
     152  padding: 0px;
     153  margin: 2px 2px 2px 2px;
     154  font-size: small;
    155155  color: red;
    156156  width: 100%;
     
    159159.RSSIcon
    160160{
    161   margin: 0px 0px 0px 0px; 
     161  margin: 0px 0px 0px 0px;
    162162  border-width: 0px;
    163163}
     
    188188  border-left: 0;
    189189  border-right: 0;
    190   color: white; 
     190  color: white;
    191191  font-size: small;
    192   font-weight: bold; 
     192  font-weight: bold;
    193193  margin: 0;
    194194  padding: 5px;
    195195}
    196196
    197 .SystemMessage div 
     197.SystemMessage div
    198198{
    199199  background: transparent;
     
    204204}
    205205
    206 .Centred
     206.Centered
    207207{
    208208  text-align: center;
     
    241241.ChatHistory .Year
    242242{
    243   border-style: solid; 
    244   border-bottom-color: gray; 
    245   border-width: 0px 0px 1px 0px; 
    246   margin-bottom: 3px; 
     243  border-style: solid;
     244  border-bottom-color: gray;
     245  border-width: 0px 0px 1px 0px;
     246  margin-bottom: 3px;
    247247  padding-bottom: 2px;
    248248}
     
    250250.ChatHistory .Year .YearContent
    251251{
    252   margin-left: 15px; 
     252  margin-left: 15px;
    253253  margin-right: 15px;
    254254}
     
    256256.ChatHistory .Year .YearContent .Months
    257257{
    258   border-style: solid; 
    259   border-bottom-color: gray; 
    260   border-width: 0px 0px 1px 0px; 
    261   margin-bottom: 3px; 
     258  border-style: solid;
     259  border-bottom-color: gray;
     260  border-width: 0px 0px 1px 0px;
     261  margin-bottom: 3px;
    262262  padding-bottom: 2px;
    263263}
     
    265265.ChatHistory .Year .YearContent .Months span
    266266{
    267   position: absolute; 
     267  position: absolute;
    268268  left: 100px;
    269269}
     
    271271.ChatHistory .YearContent .Months span strong
    272272{
    273   border-style: solid; 
    274   border-width: 1px; 
    275   border-color: black; 
     273  border-style: solid;
     274  border-width: 1px;
     275  border-color: black;
    276276  padding-left: 3px;
    277277}
     
    291291  text-align: center;
    292292  margin-left: auto;
    293   margin-right: auto; 
     293  margin-right: auto;
    294294}
    295295
     
    322322  background-color: #fff;
    323323}
    324  
     324
    325325.Panel .Title
    326326{
     
    331331  color: #666;
    332332  text-align: left;
    333   text-transform: uppercase; 
     333  text-transform: uppercase;
    334334  border-bottom: 1px solid #CCC;
    335335}
    336  
     336
    337337.Panel .Content
    338338{
     
    343343  padding: 7px;
    344344}
    345  
     345
    346346.Panel .Title .Action
    347347{
     
    366366  background-color: #FFF;
    367367}
    368  
     368
    369369.NewsPanel .Title
    370370{
     
    375375  color: #a44;
    376376  text-align: left;
    377   text-transform: uppercase; 
     377  text-transform: uppercase;
    378378  border-bottom: 1px solid #d99;
    379379}
    380  
     380
    381381.NewsPanel .Content
    382382{
     
    387387  padding: 0px;
    388388}
    389  
     389
    390390.NewsPanel .Title .Action
    391391{
     
    403403.NewsPanel .Title .Action A:link
    404404{
    405   color: #c00; 
     405  color: #c00;
    406406}
    407407
    408408.NewsPanel .Title .Action A:visited
    409409{
    410   color: #600; 
     410  color: #600;
    411411}
    412412
     
    473473}
    474474
    475 .Tab ul 
     475.Tab ul
    476476{
    477477  list-style: none;
     
    479479  margin: 0;
    480480}
    481    
    482 .Tab li 
     481
     482.Tab li
    483483{
    484484  float: left;
     
    487487  margin: 0;
    488488}
    489    
    490 .Tab a 
     489
     490.Tab a
    491491{
    492492  text-decoration: none;
     
    496496  text-align: center;
    497497}
    498  
    499 .Tab a:hover 
     498
     499.Tab a:hover
    500500{
    501501  background: #fdd;
    502502}
    503  
    504 .Tab #selected 
     503
     504.Tab #selected
    505505{
    506506  border-color: black;
    507507}
    508  
    509 .Tab #selected a 
     508
     509.Tab #selected a
    510510{
    511511  position: relative;
  • trunk/style/simple/style.css

    r251 r901  
    7171#Footer
    7272{
    73   border-style: solid; 
    74   border-top-color: gray; 
    75   border-width: 1px 0 0 0; 
    76   margin-top: 7px; 
     73  border-style: solid;
     74  border-top-color: gray;
     75  border-width: 1px 0 0 0;
     76  margin-top: 7px;
    7777  padding-top: 2px;
    7878  font-size: 10px;
     
    8282.Navigation
    8383{
    84   border-style: solid; 
    85   border-bottom-color: gray; 
    86   border-width: 0 0 1px 0; 
    87   margin-bottom: 3px; 
     84  border-style: solid;
     85  border-bottom-color: gray;
     86  border-width: 0 0 1px 0;
     87  margin-bottom: 3px;
    8888  padding-bottom: 2px;
    8989}
     
    9999#Title
    100100{
    101   padding: 3px; 
    102   font-size: 20px; 
    103   border-style: solid; 
    104   border-color: blue; 
    105   border-width: 1px; 
    106   background-color: #F0F0FF; 
     101  padding: 3px;
     102  font-size: 20px;
     103  border-style: solid;
     104  border-color: blue;
     105  border-width: 1px;
     106  background-color: #F0F0FF;
    107107  margin-bottom: 4px;
    108108}
     
    111111{
    112112  margin: 2px 0px 2px 0px;
    113   padding: 2px 2px 2px 2px; 
    114   font-size: small; 
    115   border-style: solid; 
    116   border-color: red; 
     113  padding: 2px 2px 2px 2px;
     114  font-size: small;
     115  border-style: solid;
     116  border-color: red;
    117117  border-width: 1px;
    118118  background-color: #FFF0F0;
    119119  width: 100%;
    120   border-collapse: collapse; 
     120  border-collapse: collapse;
    121121}
    122122
     
    136136{
    137137  margin: 2px 2px 2px 2px;
    138   display: none; 
    139   border-width: 1px; 
    140   border-style: solid; 
    141   border-color: blue; 
    142   padding: 3px; 
     138  display: none;
     139  border-width: 1px;
     140  border-style: solid;
     141  border-color: blue;
     142  padding: 3px;
    143143  font-size: 9pt;
    144144}
     
    153153  width: 100%;
    154154  border-width: 0px;
    155   font-size: small; 
     155  font-size: small;
    156156  padding-bottom: 5px;
    157157  margin-bottom: 5px;
     
    165165}
    166166
    167 .NewsItemFrame 
     167.NewsItemFrame
    168168{
    169169  border-collapse: collapse;
    170   padding: 0px; 
    171   margin: 2px 2px 2px 2px; 
    172   font-size: small; 
     170  padding: 0px;
     171  margin: 2px 2px 2px 2px;
     172  font-size: small;
    173173  color: red;
    174174  width: 100%;
     
    177177.RSSIcon
    178178{
    179   margin: 0px 0px 0px 0px; 
     179  margin: 0px 0px 0px 0px;
    180180  border-width: 0px;
    181181}
     
    206206  border-left: 0;
    207207  border-right: 0;
    208   color: white; 
    209   font-size: small;
    210   font-weight: bold; 
     208  color: white;
     209  font-size: small;
     210  font-weight: bold;
    211211  margin: 0;
    212212  padding: 5px;
    213213}
    214214
    215 .SystemMessage div 
     215.SystemMessage div
    216216{
    217217  background: transparent;
     
    222222}
    223223
    224 .Centred
     224.Centered
    225225{
    226226  text-align: center;
     
    259259.ChatHistory .Year
    260260{
    261   border-style: solid; 
    262   border-bottom-color: gray; 
    263   border-width: 0px 0px 1px 0px; 
    264   margin-bottom: 3px; 
     261  border-style: solid;
     262  border-bottom-color: gray;
     263  border-width: 0px 0px 1px 0px;
     264  margin-bottom: 3px;
    265265  padding-bottom: 2px;
    266266}
     
    268268.ChatHistory .Year .YearContent
    269269{
    270   margin-left: 15px; 
     270  margin-left: 15px;
    271271  margin-right: 15px;
    272272}
     
    274274.ChatHistory .Year .YearContent .Months
    275275{
    276   border-style: solid; 
    277   border-bottom-color: gray; 
    278   border-width: 0px 0px 1px 0px; 
    279   margin-bottom: 3px; 
     276  border-style: solid;
     277  border-bottom-color: gray;
     278  border-width: 0px 0px 1px 0px;
     279  margin-bottom: 3px;
    280280  padding-bottom: 2px;
    281281}
     
    283283.ChatHistory .Year .YearContent .Months span
    284284{
    285   position: absolute; 
     285  position: absolute;
    286286  left: 100px;
    287287}
     
    289289.ChatHistory .YearContent .Months span strong
    290290{
    291   border-style: solid; 
    292   border-width: 1px; 
    293   border-color: black; 
     291  border-style: solid;
     292  border-width: 1px;
     293  border-color: black;
    294294  padding-left: 3px;
    295295}
     
    309309  text-align: center;
    310310  margin-left: auto;
    311   margin-right: auto; 
     311  margin-right: auto;
    312312}
    313313
Note: See TracChangeset for help on using the changeset viewer.